Version 1.1.0-dev.5.0

svn merge -r 31107:31316 https://dart.googlecode.com/svn/branches/bleeding_edge trunk

git-svn-id: http://dart.googlecode.com/svn/trunk@31329 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/pkg/analyzer/lib/src/services/formatter_impl.dart b/pkg/analyzer/lib/src/services/formatter_impl.dart
index f54675a..2bae3ec 100644
--- a/pkg/analyzer/lib/src/services/formatter_impl.dart
+++ b/pkg/analyzer/lib/src/services/formatter_impl.dart
@@ -352,6 +352,10 @@
   /// A flag to indicate that a newline should be emitted before the next token.
   bool needsNewline = false;
 
+  /// A flag to indicate that user introduced newlines should be emitted before
+  /// the next token.
+  bool preserveNewlines = false;
+
   /// A counter for spaces that should be emitted preceding the next token.
   int leadingSpaces = 0;
 
@@ -422,8 +426,10 @@
     visit(node.leftHandSide);
     space();
     token(node.operator);
-    space();
-    visit(node.rightHandSide);
+    allowContinuedLines((){
+      space();
+      visit(node.rightHandSide);
+    });
   }
 
   visitBinaryExpression(BinaryExpression node) {
@@ -460,7 +466,8 @@
   visitCascadeExpression(CascadeExpression node) {
     visit(node.target);
     indent(2);
-    visitNodes(node.cascadeSections);
+    newlines();
+    visitNodes(node.cascadeSections, separatedBy: newlines);
     unindent(2);
   }
 
@@ -488,15 +495,18 @@
   }
 
   visitClassDeclaration(ClassDeclaration node) {
+    preserveLeadingNewlines();
     modifier(node.abstractKeyword);
     token(node.classKeyword);
     space();
     visit(node.name);
-    visit(node.typeParameters);
-    visitNode(node.extendsClause, precededBy: space);
-    visitNode(node.withClause, precededBy: space);
-    visitNode(node.implementsClause, precededBy: space);
-    space();
+    allowContinuedLines((){
+      visit(node.typeParameters);
+      visitNode(node.extendsClause, precededBy: space);
+      visitNode(node.withClause, precededBy: space);
+      visitNode(node.implementsClause, precededBy: space);
+      space();
+    });
     token(node.leftBracket);
     indent();
     visitNodes(node.members, precededBy: newlines, separatedBy: newlines);
@@ -543,6 +553,8 @@
 
     visitNodes(node.declarations, separatedBy: newlines);
 
+    preserveLeadingNewlines();
+
     // Handle trailing whitespace
     token(node.endToken /* EOF */);
 
@@ -554,12 +566,14 @@
     visit(node.condition);
     space();
     token(node.question);
-    space();
-    visit(node.thenExpression);
-    space();
-    token(node.colon);
-    space();
-    visit(node.elseExpression);
+    allowContinuedLines((){
+      space();
+      visit(node.thenExpression);
+      space();
+      token(node.colon);
+      space();
+      visit(node.elseExpression);
+    });
   }
 
   visitConstructorDeclaration(ConstructorDeclaration node) {
@@ -663,8 +677,10 @@
     token(node.whileKeyword);
     space();
     token(node.leftParenthesis);
-    visit(node.condition);
-    token(node.rightParenthesis);
+    allowContinuedLines((){
+      visit(node.condition);
+      token(node.rightParenthesis);
+    });
     token(node.semicolon);
   }
 
@@ -684,7 +700,9 @@
     token(node.keyword);
     space();
     visit(node.uri);
-    visitNodes(node.combinators, precededBy: space, separatedBy: space);
+    allowContinuedLines((){
+      visitNodes(node.combinators, precededBy: space, separatedBy: space);
+    });
     token(node.semicolon);
   }
 
@@ -791,6 +809,7 @@
   }
 
   visitFunctionDeclaration(FunctionDeclaration node) {
+    preserveLeadingNewlines();
     visitNode(node.returnType, followedBy: space);
     token(node.propertyKeyword, followedBy: space);
     visit(node.name);
@@ -837,10 +856,12 @@
   visitIfStatement(IfStatement node) {
     var hasElse = node.elseStatement != null;
     token(node.ifKeyword);
-    space();
-    token(node.leftParenthesis);
-    visit(node.condition);
-    token(node.rightParenthesis);
+    allowContinuedLines((){
+      space();
+      token(node.leftParenthesis);
+      visit(node.condition);
+      token(node.rightParenthesis);
+    });
     space();
     if (hasElse) {
       printAsBlock(node.thenStatement);
@@ -864,8 +885,10 @@
     space();
     visit(node.uri);
     token(node.asToken, precededBy: space, followedBy: space);
-    visit(node.prefix);
-    visitNodes(node.combinators, precededBy: space, separatedBy: space);
+    allowContinuedLines((){
+      visit(node.prefix);
+      visitNodes(node.combinators, precededBy: space, separatedBy: space);
+    });
     token(node.semicolon);
   }
 
@@ -951,10 +974,12 @@
     modifier(node.constKeyword);
     visitNode(node.typeArguments, followedBy: space);
     token(node.leftBracket);
+    newlines();
     indent();
-    visitCommaSeparatedNodes(node.entries);
+    visitCommaSeparatedNodes(node.entries, followedBy: newlines);
     optionalTrailingComma(node.rightBracket);
     unindent();
+    newlines();
     token(node.rightBracket);
   }
 
@@ -1073,9 +1098,11 @@
       token(node.semicolon);
     } else {
       token(node.keyword);
-      space();
-      expression.accept(this);
-      token(node.semicolon);
+      allowContinuedLines((){
+        space();
+        expression.accept(this);
+        token(node.semicolon);
+      });
     }
   }
 
@@ -1209,8 +1236,16 @@
     if (node.initializer != null) {
       space();
       token(node.equals);
-      space();
-      visit(node.initializer);
+      var initializer = node.initializer;
+      if (initializer is! ListLiteral && initializer is! MapLiteral) {
+        allowContinuedLines((){
+          space();
+          visit(initializer);
+        });
+      } else {
+        space();
+        visit(initializer);
+      }
     }
   }
 
@@ -1229,8 +1264,10 @@
     token(node.keyword);
     space();
     token(node.leftParenthesis);
-    visit(node.condition);
-    token(node.rightParenthesis);
+    allowContinuedLines((){
+      visit(node.condition);
+      token(node.rightParenthesis);
+    });
     if (node.body is! EmptyStatement) {
       space();
     }
@@ -1283,7 +1320,11 @@
   }
 
   /// Visit a comma-separated list of [nodes] if not null.
-  visitCommaSeparatedNodes(NodeList<ASTNode> nodes) {
+  visitCommaSeparatedNodes(NodeList<ASTNode> nodes, {followedBy(): null}) {
+    //TODO(pquitslund): handle this more neatly
+    if (followedBy == null) {
+      followedBy = space;
+    }
     if (nodes != null) {
       var size = nodes.length;
       if (size > 0) {
@@ -1293,7 +1334,7 @@
           if (i > 0) {
             var comma = node.beginToken.previous;
             token(comma);
-            space();
+            followedBy();
           }
           node.accept(this);
         }
@@ -1316,6 +1357,12 @@
     }
   }
 
+  /// Allow [code] to be continued across lines.
+  allowContinuedLines(code()) {
+    //TODO(pquitslund): add before
+    code();
+    //TODO(pquitslund): add after
+  }
 
   /// Emit the given [modifier] if it's non null, followed by non-breaking
   /// whitespace.
@@ -1336,6 +1383,12 @@
     }
   }
 
+  /// Indicate that user introduced newlines should be emitted before the next
+  /// token.
+  preserveLeadingNewlines() {
+    preserveNewlines = true;
+  }
+
   token(Token token, {precededBy(), followedBy(), int minNewlines: 0}) {
     if (token != null) {
       if (needsNewline) {
@@ -1446,8 +1499,12 @@
       currentToken = comment != null ? comment : token;
     }
 
-    var lines = max(min, countNewlinesBetween(previousToken, currentToken));
-    writer.newlines(lines);
+    var lines = 0;
+    if (needsNewline || preserveNewlines) {
+      lines = max(min, countNewlinesBetween(previousToken, currentToken));
+      preserveNewlines = false;
+    }
+    emitNewlines(lines);
 
     previousToken =
         currentToken.previous != null ? currentToken.previous : token.previous;
@@ -1459,7 +1516,7 @@
       var nextToken = comment.next != null ? comment.next : token;
       var newlines = calculateNewlinesBetweenComments(comment, nextToken);
       if (newlines > 0) {
-        writer.newlines(newlines);
+        emitNewlines(newlines);
         lines += newlines;
       } else {
         var spaces = countSpacesBetween(comment, nextToken);
@@ -1476,6 +1533,10 @@
     return lines;
   }
 
+  void emitNewlines(lines) {
+    writer.newlines(lines);
+  }
+
   ensureTrailingNewline() {
     if (writer.lastToken is! NewlineToken) {
       writer.newline();
diff --git a/pkg/analyzer/test/services/data/cu_tests.data b/pkg/analyzer/test/services/data/cu_tests.data
new file mode 100644
index 0000000..6e1547a
--- /dev/null
+++ b/pkg/analyzer/test/services/data/cu_tests.data
@@ -0,0 +1,8 @@
+>>>
+class
+A
+{
+}
+<<<
+class A {
+}
\ No newline at end of file
diff --git a/pkg/analyzer/test/services/data/stmt_tests.data b/pkg/analyzer/test/services/data/stmt_tests.data
new file mode 100644
index 0000000..ca6096c
--- /dev/null
+++ b/pkg/analyzer/test/services/data/stmt_tests.data
@@ -0,0 +1,27 @@
+>>>
+if (x &&
+    y) {
+  print('!');
+}
+<<<
+if (x && y) {
+  print('!');
+}
+>>>
+for (var a=0; a<100; ++a) { print(a); }
+<<<
+for (var a = 0; a < 100; ++a) {
+  print(a);
+}
+>>>
+for(
+var a=0;
+a<100; 
+++a)
+{ 
+print(a);
+}
+<<<
+for (var a = 0; a < 100; ++a) {
+  print(a);
+}
\ No newline at end of file
diff --git a/pkg/analyzer/test/services/formatter_test.dart b/pkg/analyzer/test/services/formatter_test.dart
index 61e4356..3d26066 100644
--- a/pkg/analyzer/test/services/formatter_test.dart
+++ b/pkg/analyzer/test/services/formatter_test.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.
 
+//import 'dart:io';
+
 import 'package:unittest/unittest.dart';
 
 import 'package:analyzer/src/generated/java_core.dart' show CharSequence;
@@ -11,6 +13,22 @@
 
 main() {
 
+//TODO(pquitslund): disabled pending build investigation
+
+//  /// Data driven statement tests
+//  group('stmt_tests.data', () {
+//    runTests(new File('data/stmt_tests.data'), (input, expectedOutput) {
+//      expect(formatStatement(input) + '\n', equals(expectedOutput));
+//    });
+//  });
+//
+//  /// Data driven compilation unit tests
+//  group('cu_tests.data', () {
+//    runTests(new File('data/cu_tests.data'), (input, expectedOutput) {
+//      expectCUFormatsTo(input, expectedOutput);
+//    });
+//  });
+
   /// Formatter tests
   group('formatter', () {
 
@@ -566,7 +584,10 @@
     test('CU - comments (11)', () {
       expectCUFormatsTo(
           'var m = {1: 2 /* bang */, 3: 4};\n',
-          'var m = {1: 2 /* bang */, 3: 4};\n'
+          'var m = {\n'
+          '  1: 2 /* bang */,\n'
+          '  3: 4\n'
+          '};\n'
       );
     });
 
@@ -787,10 +808,7 @@
         '1,\n'
         '2,\n'
         '];',
-        'var l = [\n'
-        '  1,\n'
-        '  2,\n'
-        '];'
+        'var l = [1, 2,];'
       );
       //Dangling ','
       expectStmtFormatsTo(
@@ -802,24 +820,29 @@
     test('stmt (maps)', () {
       expectStmtFormatsTo(
         'var map = const {"foo": "bar", "fuz": null};',
-        'var map = const {"foo": "bar", "fuz": null};'
+        'var map = const {\n'
+        '  "foo": "bar",\n'
+        '  "fuz": null\n'
+        '};'
       );
 
       expectStmtFormatsTo(
           'var map = {\n'
           '"foo": "bar",\n'
-          '"bar": "baz"'
+          '"bar": "baz"\n'
           '};',
           'var map = {\n'
           '  "foo": "bar",\n'
-          '  "bar": "baz"'
+          '  "bar": "baz"\n'
           '};'
       );
 
       //Dangling ','
       expectStmtFormatsTo(
         'var map = {"foo": "bar",};',
-        'var map = {"foo": "bar",};'
+        'var map = {\n'
+        '  "foo": "bar",\n'
+        '};'
       );
     });
 
@@ -914,6 +937,135 @@
                           transforms: false);
     });
 
+    // smoketest to ensure we're enforcing the 'no gratuitous linebreaks'
+    // opinion
+    test('CU (eat newlines)', () {
+      expectCUFormatsTo(
+        'abstract\n'
+        'class\n'
+        'A{}',
+        'abstract class A {\n'
+        '}\n'
+      );
+    });
+
+//    test('line continuations - 1', () {
+//      expectStmtFormatsTo(
+//          'if (x &&\n'
+//          '    y) {\n'
+//          '  print("yes!");\n'
+//          '}',
+//          'if (x &&\n'
+//          '    y) {\n'
+//          '  print("yes!");\n'
+//          '}'
+//      );
+//      expectStmtFormatsTo(
+//          'var x =\n'
+//          '    1234567890;',
+//          'var x =\n'
+//          '    1234567890;'
+//      );
+//      expectStmtFormatsTo(
+//          'foo() {\n'
+//          '  var x = 0;\n'
+//          '  x =\n'
+//          '      1234567890;\n'
+//          '}',
+//          'foo() {\n'
+//          '  var x = 0;\n'
+//          '  x =\n'
+//          '      1234567890;\n'
+//          '}'
+//      );
+//      expectStmtFormatsTo(
+//          'foo() {\n'
+//          '  while (true &&\n'
+//          '      true) {\n'
+//          '    print("!");\n'
+//          '  }\n'
+//          '}',
+//          'foo() {\n'
+//          '  while (true &&\n'
+//          '      true) {\n'
+//          '    print("!");\n'
+//          '  }\n'
+//          '}'
+//      );
+//      expectStmtFormatsTo(
+//          'foo() {\n'
+//          '  do {\n'
+//          '    print("!");\n'
+//          '  } while (true &&\n'
+//          '      true);\n'
+//          '}',
+//          'foo() {\n'
+//          '  do {\n'
+//          '    print("!");\n'
+//          '  } while (true &&\n'
+//          '      true);\n'
+//          '}'
+//      );
+//      expectStmtFormatsTo(
+//          'int foo() {\n'
+//          '  return\n'
+//          '      foo();\n'
+//          '}',
+//          'int foo() {\n'
+//          '  return\n'
+//          '      foo();\n'
+//          '}'
+//      );
+//      expectStmtFormatsTo(
+//          'int foo() {\n'
+//          '  return\n'
+//          '      13;\n'
+//          '}',
+//          'int foo() {\n'
+//          '  return\n'
+//          '      13;\n'
+//          '}'
+//      );
+//      expectStmtFormatsTo(
+//          'foo(fn()) {\n'
+//          '  return foo(() {\n'
+//          '    return 1;\n'
+//          '});\n'
+//          '}',
+//          'foo(fn()) {\n'
+//          '  return foo(() {\n'
+//          '    return 1;\n'
+//          '});\n'
+//          '}'
+//      );
+//      expectStmtFormatsTo(
+//          'true ? foo() :\n'
+//          '    bar();',
+//          'true ? foo() :\n'
+//          '    bar();'
+//      );
+//      expectCUFormatsTo(
+//          'import "dart:core" as\n'
+//          '    core;\n',
+//          'import "dart:core" as\n'
+//          '    core;\n'
+//      );
+//      expectCUFormatsTo(
+//          'export "package:foo/foo.dart" show\n'
+//          '    Foo;\n',
+//          'export "package:foo/foo.dart" show\n'
+//          '    Foo;\n'
+//      );
+//      expectCUFormatsTo(
+//          'class Foo extends Bar implements\n'
+//          '    Baz {\n'
+//          '}\n',
+//          'class Foo extends Bar implements\n'
+//          '    Baz {\n'
+//          '}\n'
+//      );
+//    });
+
     test('initialIndent', () {
       var formatter = new CodeFormatter(
           new FormatterOptions(initialIndentationLevel: 2));
@@ -1155,3 +1307,22 @@
 expectStmtFormatsTo(src, expected, {transforms: true}) =>
     expect(formatStatement(src, options:
       new FormatterOptions(codeTransforms: transforms)), equals(expected));
+
+runTests(testFile, expectClause(input, output)) {
+
+  var testIndex = 1;
+  var lines = testFile.readAsLinesSync();
+
+  for (var i = 1; i < lines.length; ++i) {
+    var input = '', expectedOutput = '';
+    while(lines[i] != '<<<') {
+      input += lines[i++] + '\n';
+    }
+    while(++i < lines.length && lines[i] != '>>>') {
+      expectedOutput += lines[i] + '\n';
+    }
+    test('test - (${testIndex++})', () {
+      expectClause(input, expectedOutput);
+    });
+  }
+}
diff --git a/pkg/args/lib/args.dart b/pkg/args/lib/args.dart
index a76e726..4b9f857 100644
--- a/pkg/args/lib/args.dart
+++ b/pkg/args/lib/args.dart
@@ -261,7 +261,7 @@
  */
 library args;
 
-import 'package:collection_helpers/wrappers.dart';
+import 'package:collection/wrappers.dart';
 
 import 'src/parser.dart';
 import 'src/usage.dart';
diff --git a/pkg/args/lib/src/options.dart b/pkg/args/lib/src/options.dart
index 0b8b404..a4091df 100644
--- a/pkg/args/lib/src/options.dart
+++ b/pkg/args/lib/src/options.dart
@@ -1,6 +1,6 @@
 library options;
 
-import 'package:collection_helpers/wrappers.dart';
+import 'package:collection/wrappers.dart';
 
 /**
  * A command-line option. Includes both flags and options which take a value.
diff --git a/pkg/args/pubspec.yaml b/pkg/args/pubspec.yaml
index f907300..771fdb1 100644
--- a/pkg/args/pubspec.yaml
+++ b/pkg/args/pubspec.yaml
@@ -8,7 +8,7 @@
  a set of options and values using GNU and POSIX style options.
 
 dependencies:
-  collection_helpers: ">=0.9.1 <0.10.0"
+  collection: ">=0.9.0 <0.10.0"
 dev_dependencies:
   unittest: ">=0.9.0 <0.10.0"
 environment:
diff --git a/pkg/async/LICENSE b/pkg/async/LICENSE
new file mode 100644
index 0000000..ee99930
--- /dev/null
+++ b/pkg/async/LICENSE
@@ -0,0 +1,26 @@
+Copyright 2013, the Dart project authors. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+    * Neither the name of Google Inc. nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/pkg/async/README.md b/pkg/async/README.md
new file mode 100644
index 0000000..dc34553
--- /dev/null
+++ b/pkg/async/README.md
@@ -0,0 +1,11 @@
+The `async` package will contain tools to work with asynchronous computations.
+
+The package contains sub-libraries with different utilities.
+
+### Zipping streams
+
+The "stream_zip.dart" sub-library contains functionality to combine several streams
+of events into a single stream of tuples of events.
+
+### History.
+This package is unrelated to the discontinued `async` package with version 0.1.7.
diff --git a/runtime/bin/vmservice/service_request_router.dart b/pkg/async/lib/async.dart
similarity index 68%
copy from runtime/bin/vmservice/service_request_router.dart
copy to pkg/async/lib/async.dart
index c889c85..e9d6544 100644
--- a/runtime/bin/vmservice/service_request_router.dart
+++ b/pkg/async/lib/async.dart
@@ -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.
 
-part of vmservice;
+library dart.pkg.async;
 
-abstract class ServiceRequestRouter {
-  Future route(ServiceRequest request);
-}
+export "stream_zip.dart";
diff --git a/pkg/async/lib/stream_zip.dart b/pkg/async/lib/stream_zip.dart
new file mode 100644
index 0000000..055489d
--- /dev/null
+++ b/pkg/async/lib/stream_zip.dart
@@ -0,0 +1,119 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/**
+ * Help for combining multiple streams into a single stream.
+ */
+library dart.pkg.async.stream_zip;
+
+import "dart:async";
+
+/**
+ * A stream that combines the values of other streams.
+ */
+class StreamZip extends Stream<List> {
+  final Iterable<Stream> _streams;
+  StreamZip(Iterable<Stream> streams) : _streams = streams;
+
+  StreamSubscription<List> listen(void onData(List data), {
+                                  Function onError,
+                                  void onDone(),
+                                  bool cancelOnError}) {
+    cancelOnError = identical(true, cancelOnError);
+    List<StreamSubscription> subscriptions = <StreamSubscription>[];
+    StreamController controller;
+    List current;
+    int dataCount = 0;
+
+    /// Called for each data from a subscription in [subscriptions].
+    void handleData(int index, data) {
+      current[index] = data;
+      dataCount++;
+      if (dataCount == subscriptions.length) {
+        List data = current;
+        current = new List(subscriptions.length);
+        dataCount = 0;
+        for (int i = 0; i < subscriptions.length; i++) {
+          if (i != index) subscriptions[i].resume();
+        }
+        controller.add(data);
+      } else {
+        subscriptions[index].pause();
+      }
+    }
+
+    /// Called for each error from a subscription in [subscriptions].
+    /// Except if [cancelOnError] is true, in which case the function below
+    /// is used instead.
+    void handleError(Object error, StackTrace stackTrace) {
+      controller.addError(error, stackTrace);
+    }
+
+    /// Called when a subscription has an error and [cancelOnError] is true.
+    ///
+    /// Prematurely cancels all subscriptions since we know that we won't
+    /// be needing any more values.
+    void handleErrorCancel(Object error, StackTrace stackTrace) {
+      for (int i = 0; i < subscriptions.length; i++) {
+        subscriptions[i].cancel();
+      }
+      controller.addError(error, stackTrace);
+    }
+
+    void handleDone() {
+      for (int i = 0; i < subscriptions.length; i++) {
+        subscriptions[i].cancel();
+      }
+      controller.close();
+    }
+
+    try {
+      for (Stream stream in _streams) {
+        int index = subscriptions.length;
+        subscriptions.add(stream.listen(
+            (data) { handleData(index, data); },
+            onError: cancelOnError ? handleError : handleErrorCancel,
+            onDone: handleDone,
+            cancelOnError: cancelOnError));
+      }
+    } catch (e) {
+      for (int i = subscriptions.length - 1; i >= 0; i--) {
+        subscriptions[i].cancel();
+      }
+      rethrow;
+    }
+
+    current = new List(subscriptions.length);
+
+    controller = new StreamController<List>(
+      onPause: () {
+        for (int i = 0; i < subscriptions.length; i++) {
+          // This may pause some subscriptions more than once.
+          // These will not be resumed by onResume below, but must wait for the
+          // next round.
+          subscriptions[i].pause();
+        }
+      },
+      onResume: () {
+        for (int i = 0; i < subscriptions.length; i++) {
+          subscriptions[i].resume();
+        }
+      },
+      onCancel: () {
+        for (int i = 0; i < subscriptions.length; i++) {
+          // Canceling more than once is safe.
+          subscriptions[i].cancel();
+        }
+      }
+    );
+
+    if (subscriptions.isEmpty) {
+      controller.close();
+    }
+    return controller.stream.listen(onData,
+                                    onError: onError,
+                                    onDone: onDone,
+                                    cancelOnError: cancelOnError);
+  }
+}
diff --git a/pkg/async/pubspec.yaml b/pkg/async/pubspec.yaml
new file mode 100644
index 0000000..3603226
--- /dev/null
+++ b/pkg/async/pubspec.yaml
@@ -0,0 +1,9 @@
+name: async
+version: 0.9.0
+author: Dart Team <misc@dartlang.org>
+description: Utility functions and classes related to the 'dart:async' library.
+homepage: http://www.dartlang.org
+dev_dependencies:
+  unittest: ">=0.9.0 <0.10.0"
+environment:
+  sdk: ">=1.0.0 <2.0.0"
diff --git a/pkg/sequence_zip/test/stream_test.dart b/pkg/async/test/stream_zip_test.dart
similarity index 98%
rename from pkg/sequence_zip/test/stream_test.dart
rename to pkg/async/test/stream_zip_test.dart
index 2f0de8f..54083b9 100644
--- a/pkg/sequence_zip/test/stream_test.dart
+++ b/pkg/async/test/stream_zip_test.dart
@@ -3,7 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import "dart:async";
-import "package:sequence_zip/stream_zip.dart";
+import "package:async/stream_zip.dart";
 import "package:unittest/unittest.dart";
 
 /// Create an error with the same values as [base], except that it throwsA
diff --git a/pkg/async/test/stream_zip_zone_test.dart b/pkg/async/test/stream_zip_zone_test.dart
new file mode 100644
index 0000000..d39e3d7
--- /dev/null
+++ b/pkg/async/test/stream_zip_zone_test.dart
@@ -0,0 +1,59 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "dart:async";
+import "package:async/stream_zip.dart";
+import "package:unittest/unittest.dart";
+
+// Test that stream listener callbacks all happen in the zone where the
+// listen occurred.
+
+main() {
+ StreamController controller;
+ controller = new StreamController();
+ testStream("singlesub-async", controller, controller.stream);
+ controller = new StreamController.broadcast();
+ testStream("broadcast-async", controller, controller.stream);
+ controller = new StreamController();
+ testStream("asbroadcast-async", controller,
+                                 controller.stream.asBroadcastStream());
+
+ controller = new StreamController(sync: true);
+ testStream("singlesub-sync", controller, controller.stream);
+ controller = new StreamController.broadcast(sync: true);
+ testStream("broadcast-sync", controller, controller.stream);
+ controller = new StreamController(sync: true);
+ testStream("asbroadcast-sync", controller,
+                                controller.stream.asBroadcastStream());
+}
+
+void testStream(String name, StreamController controller, Stream stream) {
+  test(name, () {
+    Zone outer = Zone.current;
+    runZoned(() {
+      Zone newZone1 = Zone.current;
+      StreamSubscription sub;
+      sub = stream.listen(expectAsync1((v) {
+        expect(v, 42);
+        expect(Zone.current, newZone1);
+        outer.run(() {
+          sub.onData(expectAsync1((v) {
+            expect(v, 37);
+            expect(Zone.current, newZone1);
+            runZoned(() {
+              Zone newZone2 = Zone.current;
+              sub.onData(expectAsync1((v) {
+                expect(v, 87);
+                expect(Zone.current, newZone1);
+              }));
+            });
+            controller.add(87);
+          }));
+        });
+        controller.add(37);
+      }));
+    });
+    controller.add(42);
+  });
+}
diff --git a/pkg/barback/lib/src/package_graph.dart b/pkg/barback/lib/src/package_graph.dart
index 2ecf6b4..c2e1a8e 100644
--- a/pkg/barback/lib/src/package_graph.dart
+++ b/pkg/barback/lib/src/package_graph.dart
@@ -69,13 +69,6 @@
   /// The stack trace for [_lastUnexpectedError].
   StackTrace _lastUnexpectedErrorTrace;
 
-  // TODO(nweiz): Allow transformers to declare themselves as "lightweight" or
-  // "heavyweight" and adjust their restrictions appropriately. Simple
-  // transformers may be very efficient to run in parallel, whereas dart2js uses
-  // a lot of memory and should be run more sequentially.
-  /// A pool that controls how many transformers may be applied at once.
-  final Pool transformPool = new Pool(10);
-
   /// Creates a new [PackageGraph] that will transform assets in all packages
   /// made available by [provider].
   PackageGraph(this.provider) {
diff --git a/pkg/barback/lib/src/pool.dart b/pkg/barback/lib/src/pool.dart
index 24100ca..4653722 100644
--- a/pkg/barback/lib/src/pool.dart
+++ b/pkg/barback/lib/src/pool.dart
@@ -138,4 +138,4 @@
     _released = true;
     _pool._onResourceReleased();
   }
-}
\ No newline at end of file
+}
diff --git a/pkg/barback/lib/src/transform_node.dart b/pkg/barback/lib/src/transform_node.dart
index 2a99691..76b29bd 100644
--- a/pkg/barback/lib/src/transform_node.dart
+++ b/pkg/barback/lib/src/transform_node.dart
@@ -128,9 +128,7 @@
 
     _isDirty = false;
 
-    return phase.cascade.graph.transformPool
-        .withResource(() => transformer.apply(transform))
-        .catchError((error, stack) {
+    return transformer.apply(transform).catchError((error, stack) {
       // If the transform became dirty while processing, ignore any errors from
       // it.
       if (_isDirty) return;
diff --git a/pkg/barback/pubspec.yaml b/pkg/barback/pubspec.yaml
index 5a7b410..c7e59ce 100644
--- a/pkg/barback/pubspec.yaml
+++ b/pkg/barback/pubspec.yaml
@@ -8,7 +8,7 @@
 # When the minor version of this is upgraded, you *must* update that version
 # number in pub to stay in sync with this. New patch versions are considered
 # backwards compatible, and pub will allow later patch versions automatically.
-version: 0.11.0 # Minor version bumped
+version: 0.11.0
 
 author: "Dart Team <misc@dartlang.org>"
 homepage: http://www.dartlang.org
diff --git a/pkg/barback/test/package_graph/many_parallel_transformers_test.dart b/pkg/barback/test/package_graph/many_parallel_transformers_test.dart
index 72f19ac..8c47241 100644
--- a/pkg/barback/test/package_graph/many_parallel_transformers_test.dart
+++ b/pkg/barback/test/package_graph/many_parallel_transformers_test.dart
@@ -28,7 +28,5 @@
       expectAsset("app|$i.out", "$i.out");
     }
     buildShouldSucceed();
-
-    expect(rewrite.maxParallelRuns, completion(equals(10)));
   });
 }
diff --git a/pkg/barback/test/transformer/mock.dart b/pkg/barback/test/transformer/mock.dart
index cfbb21a..57d3f07 100644
--- a/pkg/barback/test/transformer/mock.dart
+++ b/pkg/barback/test/transformer/mock.dart
@@ -27,9 +27,6 @@
   Future<int> get numRuns => schedule(() => _numRuns);
   var _numRuns = 0;
 
-  Future<int> get maxParallelRuns => schedule(() => _maxParallelRuns);
-  var _maxParallelRuns = 0;
-
   /// The number of currently running transforms.
   int _runningTransforms = 0;
 
@@ -179,9 +176,6 @@
     _numRuns++;
     if (_runningTransforms == 0) _started.complete();
     _runningTransforms++;
-    if (_runningTransforms > _maxParallelRuns) {
-      _maxParallelRuns = _runningTransforms;
-    }
     return newFuture(() => doApply(transform)).then((_) {
       if (_apply != null) return _apply.future;
     }).whenComplete(() {
diff --git a/pkg/collection/LICENSE b/pkg/collection/LICENSE
new file mode 100644
index 0000000..ee99930
--- /dev/null
+++ b/pkg/collection/LICENSE
@@ -0,0 +1,26 @@
+Copyright 2013, the Dart project authors. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+    * Neither the name of Google Inc. nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/pkg/collection/README.md b/pkg/collection/README.md
new file mode 100644
index 0000000..bb392fd
--- /dev/null
+++ b/pkg/collection/README.md
@@ -0,0 +1,55 @@
+Helper libraries for working with collections.
+
+The `collection` package contains a number of separate libraries
+with utility functions and classes that makes working with collections easier.
+
+## Using
+
+The `collection` package can be imported as separate libraries, or
+in totality:
+
+    import 'package:collection/equality.dart';
+    import 'package:collection/algorithms.dart';
+    import 'package:collection/wrappers.dart';
+
+or
+
+    import 'package:collection/collection.dart';
+
+## Equality
+
+The equality library gives a way to specify equality of elements and
+collections.
+
+Collections in Dart have no inherent equality. Two sets are not equal, even
+if they contain exactly the same objects as elements.
+
+The equality library provides a way to say define such an equality. In this
+case, for example, `const SetEquality(const IdentityEquality())` is an equality
+that considers two sets equal exactly if they contain identical elements.
+
+The library provides ways to define equalities on `Iterable`s, `List`s, `Set`s, and
+`Map`s, as well as combinations of these, such as:
+
+    const MapEquality(const IdentityEquality(), const ListEquality());
+
+This equality considers maps equal if they have identical keys, and the corresponding values are lists with equal (`operator==`) values.
+
+## Algorithms
+
+The algorithms library contains functions that operate on lists.
+
+It contains ways to shuffle a `List`, do binary search on a sorted `List`, and
+some different sorting algorithms.
+
+
+## Wrappers
+
+The wrappers library contains classes that "wrap" a collection.
+
+A wrapper class contains an object of the same type, and it forwards all
+methods to the wrapped object.
+
+Wrapper classes can be used in various ways, for example to restrict the type
+of an object to that of a supertype, or to change the behavior of selected
+functions on an existing object.
diff --git a/pkg/collection/lib/algorithms.dart b/pkg/collection/lib/algorithms.dart
new file mode 100644
index 0000000..5ff0bb3
--- /dev/null
+++ b/pkg/collection/lib/algorithms.dart
@@ -0,0 +1,301 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/**
+ * Operations on collections.
+ */
+library dart.pkg.collection.algorithms;
+
+import "dart:math" show Random;
+
+/** Version of [binarySearch] optimized for comparable keys */
+int _comparableBinarySearch(List<Comparable> list, Comparable key) {
+  int min = 0;
+  int max = list.length;
+  while (min < max) {
+    int mid = min + ((max - min) >> 1);
+    var element = list[mid];
+    int comp = element.compareTo(key);
+    if (comp == 0) return mid;
+    if (comp < 0) {
+      min = mid + 1;
+    } else {
+      max = mid;
+    }
+  }
+  return -1;
+}
+
+/**
+ * Returns a position of the [key] in [sortedList], if it is there.
+ *
+ * If the list isn't sorted according to the [compare] function, the result
+ * is unpredictable.
+ *
+ * If [compare] is omitted, it defaults to calling [Comparable.compareTo] on
+ * the objects.
+ *
+ * Returns -1 if [key] is not in the list by default.
+ */
+int binarySearch(List sortedList, var key,
+                 { int compare(var a, var b) }) {
+  if (compare == null) {
+    return _comparableBinarySearch(sortedList, key);
+  }
+  int min = 0;
+  int max = sortedList.length;
+  while (min < max) {
+    int mid = min + ((max - min) >> 1);
+    var element = sortedList[mid];
+    int comp = compare(element, key);
+    if (comp == 0) return mid;
+    if (comp < 0) {
+      min = mid + 1;
+    } else {
+      max = mid;
+    }
+  }
+  return -1;
+}
+
+
+/**
+ * Shuffles a list randomly.
+ *
+ * A sub-range of a list can be shuffled by providing [start] and [end].
+ */
+void shuffle(List list, [int start = 0, int end = null]) {
+  Random random = new Random();
+  if (end == null) end = list.length;
+  int length = end - start;
+  while (length > 1) {
+    int pos = random.nextInt(length);
+    length--;
+    var tmp1 = list[start + pos];
+    list[start + pos] = list[start + length];
+    list[start + length] = tmp1;
+  }
+}
+
+
+/**
+ * Reverses a list, or a part of a list, in-place.
+ */
+void reverse(List list, [int start = 0, int end = null]) {
+  if (end == null) end = list.length;
+  _reverse(list, start, end);
+}
+
+// Internal helper function that assumes valid arguments.
+void _reverse(List list, int start, int end) {
+  for (int i = start, j = end - 1; i < j; i++, j--) {
+    var tmp = list[i];
+    list[i] = list[j];
+    list[j] = tmp;
+  }
+}
+
+/**
+ * Sort a list using insertion sort.
+ *
+ * Insertion sort is a simple sorting algorithm. For `n` elements it does on
+ * the order of `n * log(n)` comparisons but up to `n` squared moves. The
+ * sorting is performed in-place, without using extra memory.
+ *
+ * For short lists the many moves have less impact than the simple algorithm,
+ * and it is often the favored sorting algorithm for short lists.
+ *
+ * This insertion sort is stable: Equal elements end up in the same order
+ * as they started in.
+ */
+void insertionSort(List list,
+                   { int compare(a, b),
+                     int start: 0,
+                     int end: null }) {
+  // If the same method could have both positional and named optional
+  // parameters, this should be (list, [start, end], {compare}).
+  if (end == null) end = list.length;
+  if (compare == null) compare = Comparable.compare;
+  _insertionSort(list, compare, start, end, start + 1);
+}
+
+/**
+ * Internal helper function that assumes arguments correct.
+ *
+ * Assumes that the elements up to [sortedUntil] (not inclusive) are
+ * already sorted. The [sortedUntil] values should always be at least
+ * `start + 1`.
+ */
+void _insertionSort(List list, int compare(a, b), int start, int end,
+                    int sortedUntil) {
+  for (int pos = sortedUntil; pos < end; pos++) {
+    int min = start;
+    int max = pos;
+    var element = list[pos];
+    while (min < max) {
+      int mid = min + ((max - min) >> 1);
+      int comparison = compare(element, list[mid]);
+      if (comparison < 0) {
+        max = mid;
+      } else {
+        min = mid + 1;
+      }
+    }
+    list.setRange(min + 1, pos + 1, list, min);
+    list[min] = element;
+  }
+}
+
+/** Limit below which merge sort defaults to insertion sort. */
+const int _MERGE_SORT_LIMIT = 32;
+
+/**
+ * Sorts a list, or a range of a list, using the merge sort algorithm.
+ *
+ * Merge-sorting works by splitting the job into two parts, sorting each
+ * recursively, and then merging the two sorted parts.
+ *
+ * This takes on the order of `n * log(n)` comparisons and moves to sort
+ * `n` elements, but requires extra space of about the same size as the list
+ * being sorted.
+ *
+ * This merge sort is stable: Equal elements end up in the same order
+ * as they started in.
+ */
+void mergeSort(List list, {int start: 0, int end: null, int compare(a, b)}) {
+  if (end == null) end = list.length;
+  if (compare == null) compare = Comparable.compare;
+  int length = end - start;
+  if (length < 2) return;
+  if (length < _MERGE_SORT_LIMIT) {
+    _insertionSort(list, compare, start, end, start + 1);
+    return;
+  }
+  // Special case the first split instead of directly calling
+  // _mergeSort, because the _mergeSort requires its target to
+  // be different from its source, and it requires extra space
+  // of the same size as the list to sort.
+  // This split allows us to have only half as much extra space,
+  // and it ends up in the original place.
+  int middle = start + ((end - start) >> 1);
+  int firstLength = middle - start;
+  int secondLength = end - middle;
+  // secondLength is always the same as firstLength, or one greater.
+  List scratchSpace = new List(secondLength);
+  _mergeSort(list, compare, middle, end, scratchSpace, 0);
+  int firstTarget = end - firstLength;
+  _mergeSort(list, compare, start, middle, list, firstTarget);
+  _merge(compare,
+         list, firstTarget, end,
+         scratchSpace, 0, secondLength,
+         list, start);
+}
+
+/**
+ * Performs an insertion sort into a potentially different list than the
+ * one containing the original values.
+ *
+ * It will work in-place as well.
+ */
+void _movingInsertionSort(List list, int compare(a, b), int start, int end,
+                          List target, int targetOffset) {
+  int length = end - start;
+  if (length == 0) return;
+  target[targetOffset] = list[start];
+  for (int i = 1; i < length; i++) {
+    var element = list[start + i];
+    int min = targetOffset;
+    int max = targetOffset + i;
+    while (min < max) {
+      int mid = min + ((max - min) >> 1);
+      if (compare(element, target[mid]) < 0) {
+        max = mid;
+      } else {
+        min = mid + 1;
+      }
+    }
+    target.setRange(min + 1, targetOffset + i + 1,
+                    target, min);
+    target[min] = element;
+  }
+}
+
+/**
+ * Sorts [list] from [start] to [end] into [target] at [targetOffset].
+ *
+ * The `target` list must be able to contain the range from `start` to `end`
+ * after `targetOffset`.
+ *
+ * Allows target to be the same list as [list], as long as it's not
+ * overlapping the `start..end` range.
+ */
+void _mergeSort(List list, int compare(a, b), int start, int end,
+                List target, int targetOffset) {
+  int length = end - start;
+  if (length < _MERGE_SORT_LIMIT) {
+    _movingInsertionSort(list, compare, start, end, target, targetOffset);
+    return;
+  }
+  int middle = start + (length >> 1);
+  int firstLength = middle - start;
+  int secondLength = end - middle;
+  // Here secondLength >= firstLength (differs by at most one).
+  int targetMiddle = targetOffset + firstLength;
+  // Sort the second half into the end of the target area.
+  _mergeSort(list, compare, middle, end,
+             target, targetMiddle);
+  // Sort the first half into the end of the source area.
+  _mergeSort(list, compare, start, middle,
+             list, middle);
+  // Merge the two parts into the target area.
+  _merge(compare,
+         list, middle, middle + firstLength,
+         target, targetMiddle, targetMiddle + secondLength,
+         target, targetOffset);
+}
+
+/**
+ * Merges two lists into a target list.
+ *
+ * One of the input lists may be positioned at the end of the target
+ * list.
+ *
+ * For equal object, elements from [firstList] are always preferred.
+ * This allows the merge to be stable if the first list contains elements
+ * that started out earlier than the ones in [secondList]
+ */
+void _merge(int compare(a, b),
+            List firstList, int firstStart, int firstEnd,
+            List secondList, int secondStart, int secondEnd,
+            List target, int targetOffset) {
+  // No empty lists reaches here.
+  assert(firstStart < firstEnd);
+  assert(secondStart < secondEnd);
+  int cursor1 = firstStart;
+  int cursor2 = secondStart;
+  var firstElement = firstList[cursor1++];
+  var secondElement = secondList[cursor2++];
+  while (true) {
+    if (compare(firstElement, secondElement) <= 0) {
+      target[targetOffset++] = firstElement;
+      if (cursor1 == firstEnd) break;  // Flushing second list after loop.
+      firstElement = firstList[cursor1++];
+    } else {
+      target[targetOffset++] = secondElement;
+      if (cursor2 != secondEnd) {
+        secondElement = secondList[cursor2++];
+        continue;
+      }
+      // Second list empties first. Flushing first list here.
+      target[targetOffset++] = firstElement;
+      target.setRange(targetOffset, targetOffset + (firstEnd - cursor1),
+          firstList, cursor1);
+      return;
+    }
+  }
+  // First list empties first. Reached by break above.
+  target[targetOffset++] = secondElement;
+  target.setRange(targetOffset, targetOffset + (secondEnd - cursor2),
+      secondList, cursor2);
+}
diff --git a/pkg/collection/lib/collection.dart b/pkg/collection/lib/collection.dart
new file mode 100644
index 0000000..a6f192d
--- /dev/null
+++ b/pkg/collection/lib/collection.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/**
+ * Exports all the individual parts of the collection-helper library.
+ *
+ * The sub-libraries of this package are:
+ *
+ * - `algorithms.dart`: Algorithms that work on lists (shuffle, binary search
+ *                      and various sorting algorithms).
+ * - `equality.dart`: Different notions of equality of collections.
+ * - `iterable_zip.dart`: Combining multiple iterables into one.
+ * - `wrappers.dart`: Wrapper classes that delegate to a collection object.
+ *                    Includes unmodifiable views of collections.
+ */
+library dart.pkg.collection;
+
+export "algorithms.dart";
+export "equality.dart";
+export "iterable_zip.dart";
+export "wrappers.dart";
diff --git a/pkg/collection/lib/equality.dart b/pkg/collection/lib/equality.dart
new file mode 100644
index 0000000..c6fdafa
--- /dev/null
+++ b/pkg/collection/lib/equality.dart
@@ -0,0 +1,419 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/**
+ * Defines equality relations on collections.
+ */
+library dart.pkg.collection.equality;
+
+import "dart:collection";
+
+const int _HASH_MASK = 0x7fffffff;
+
+/**
+ * A generic equality relation on objects.
+ */
+abstract class Equality<E> {
+  const factory Equality() = DefaultEquality;
+
+  /**
+   * Compare two elements for being equal.
+   *
+   * This should be a proper equality relation.
+   */
+  bool equals(E e1, E e2);
+
+  /**
+   * Get a hashcode of an element.
+   *
+   * The hashcode should be compatible with [equals], so that if
+   * `equals(a, b)` then `hash(a) == hash(b)`.
+   */
+  int hash(E e);
+
+  /**
+   * Test whether an object is a valid argument to [equals] and [hash].
+   *
+   * Some implementations may be restricted to only work on specific types
+   * of objects.
+   */
+  bool isValidKey(Object o);
+}
+
+/**
+ * Equality of objects that compares only the natural equality of the objects.
+ *
+ * This equality uses the objects' own [Object.==] and [Object.hashCode] for
+ * the equality.
+ */
+class DefaultEquality implements Equality {
+  const DefaultEquality();
+  bool equals(Object e1, Object e2) => e1 == e2;
+  int hash(Object e) => e.hashCode;
+  bool isValidKey(Object o) => true;
+}
+
+/**
+ * Equality of objects that compares only the identity of the objects.
+ */
+class IdentityEquality implements Equality {
+  const IdentityEquality();
+  bool equals(Object e1, Object e2) => identical(e1, e2);
+  int hash(Object e) => identityHashCode(e);
+  bool isValidKey(Object o) => true;
+}
+
+/**
+ * Equality on iterables.
+ *
+ * Two iterables are equal if they have the same elements in the same order.
+ */
+class IterableEquality<E> implements Equality<Iterable<E>> {
+  final Equality<E> _elementEquality;
+  const IterableEquality([Equality<E> elementEquality =
+                              const DefaultEquality()])
+      : _elementEquality = elementEquality;
+
+  bool equals(Iterable<E> elements1, Iterable<E> elements2) {
+    if (identical(elements1, elements2)) return true;
+    if (elements1 == null || elements2 == null) return false;
+    Iterator it1 = elements1.iterator;
+    Iterator it2 = elements2.iterator;
+    while (true) {
+      bool hasNext = it1.moveNext();
+      if (hasNext != it2.moveNext()) return false;
+      if (!hasNext) return true;
+      if (!_elementEquality.equals(it1.current, it2.current)) return false;
+    }
+  }
+
+  int hash(Iterable<E> elements) {
+    // Jenkins's one-at-a-time hash function.
+    int hash = 0;
+    for (E element in elements) {
+      int c = _elementEquality.hash(element);
+      hash = (hash + c) & _HASH_MASK;
+      hash = (hash + (hash << 10)) & _HASH_MASK;
+      hash ^= (hash >> 6);
+    }
+    hash = (hash + (hash << 3)) & _HASH_MASK;
+    hash ^= (hash >> 11);
+    hash = (hash + (hash << 15)) & _HASH_MASK;
+    return hash;
+  }
+
+  bool isValidKey(Object o) => o is Iterable<E>;
+}
+
+/**
+ * Equality on lists.
+ *
+ * Two lists are equal if they have the same length and their elements
+ * at each index are equal.
+ *
+ * This is effectively the same as [IterableEquality] except that it
+ * accesses elements by index instead of through iteration.
+ */
+class ListEquality<E> implements Equality<List<E>> {
+  final Equality<E> _elementEquality;
+  const ListEquality([Equality<E> elementEquality = const DefaultEquality()])
+      : _elementEquality = elementEquality;
+
+  bool equals(List<E> e1, List<E> e2) {
+    if (identical(e1, e2)) return true;
+    if (e1 == null || e2 == null) return false;
+    int length = e1.length;
+    if (length != e2.length) return false;
+    for (int i = 0; i < length; i++) {
+      if (!_elementEquality.equals(e1[i], e2[i])) return false;
+    }
+    return true;
+  }
+
+  int hash(List<E> e) {
+    // Jenkins's one-at-a-time hash function.
+    // This code is almost identical to the one in IterableEquality, except
+    // that it uses indexing instead of iterating to get the elements.
+    int hash = 0;
+    for (int i = 0; i < e.length; i++) {
+      int c = _elementEquality.hash(e[i]);
+      hash = (hash + c) & _HASH_MASK;
+      hash = (hash + (hash << 10)) & _HASH_MASK;
+      hash ^= (hash >> 6);
+    }
+    hash = (hash + (hash << 3)) & _HASH_MASK;
+    hash ^= (hash >> 11);
+    hash = (hash + (hash << 15)) & _HASH_MASK;
+    return hash;
+  }
+
+  bool isValidKey(Object o) => o is List<E>;
+}
+
+abstract class _UnorderedEquality<E, T extends Iterable<E>>
+    implements Equality<T> {
+  final Equality<E> _elementEquality;
+
+  const _UnorderedEquality(this._elementEquality);
+
+  bool equals(T e1, T e2) {
+    if (identical(e1, e2)) return true;
+    if (e1 == null || e2 == null) return false;
+    HashMap<E, int> counts = new HashMap(
+        equals: _elementEquality.equals,
+        hashCode: _elementEquality.hash,
+        isValidKey: _elementEquality.isValidKey);
+    int length = 0;
+    for (var e in e1) {
+      int count = counts[e];
+      if (count == null) count = 0;
+      counts[e] = count + 1;
+      length++;
+    }
+    for (var e in e2) {
+      int count = counts[e];
+      if (count == null || count == 0) return false;
+      counts[e] = count - 1;
+      length--;
+    }
+    return length == 0;
+  }
+
+  int hash(T e) {
+    int hash = 0;
+    for (E element in e) {
+      int c = _elementEquality.hash(element);
+      hash = (hash + c) & _HASH_MASK;
+    }
+    hash = (hash + (hash << 3)) & _HASH_MASK;
+    hash ^= (hash >> 11);
+    hash = (hash + (hash << 15)) & _HASH_MASK;
+    return hash;
+  }
+}
+
+/**
+ * Equality of the elements of two iterables without considering order.
+ *
+ * Two iterables are considered equal if they have the same number of elements,
+ * and the elements of one set can be paired with the elements
+ * of the other iterable, so that each pair are equal.
+ */
+class UnorderedIterableEquality<E> extends _UnorderedEquality<E, Iterable<E>> {
+  const UnorderedIterableEquality(
+      [Equality<E> elementEquality = const DefaultEquality()])
+      : super(elementEquality);
+
+  bool isValidKey(Object o) => o is Iterable<E>;
+}
+
+/**
+ * Equality of sets.
+ *
+ * Two sets are considered equal if they have the same number of elements,
+ * and the elements of one set can be paired with the elements
+ * of the other set, so that each pair are equal.
+ *
+ * This equality behaves the same as [UnorderedIterableEquality] except that
+ * it expects sets instead of iterables as arguments.
+ */
+class SetEquality<E> extends _UnorderedEquality<E, Set<E>> {
+  const SetEquality(
+      [Equality<E> elementEquality = const DefaultEquality()])
+      : super(elementEquality);
+
+  bool isValidKey(Object o) => o is Set<E>;
+}
+
+/**
+ *  Internal class used by [MapEquality].
+ *
+ *  The class represents a map entry as a single object,
+ *  using a combined hashCode and equality of the key and value.
+ */
+class _MapEntry {
+  final MapEquality equality;
+  final key;
+  final value;
+  _MapEntry(this.equality, this.key, this.value);
+
+  int get hashCode =>
+      (3 * equality._keyEquality.hash(key) +
+       7 * equality._valueEquality.hash(value)) & _HASH_MASK;
+
+  bool operator==(Object other) {
+    if (other is! _MapEntry) return false;
+    _MapEntry otherEntry = other;
+    return equality._keyEquality.equals(key, otherEntry.key) &&
+           equality._valueEquality.equals(value, otherEntry.value);
+
+  }
+}
+
+/**
+ * Equality on maps.
+ *
+ * Two maps are equal if they have the same number of entries, and if the
+ * entries of the two maps are pairwise equal on both key and value.
+ */
+class MapEquality<K, V> implements Equality<Map<K, V>> {
+  final Equality<K> _keyEquality;
+  final Equality<V> _valueEquality;
+  const MapEquality({ Equality<K> keys : const DefaultEquality(),
+                      Equality<V> values : const DefaultEquality() })
+      : _keyEquality = keys, _valueEquality = values;
+
+  bool equals(Map<K, V> e1, Map<K, V> e2) {
+    if (identical(e1, e2)) return true;
+    if (e1 == null || e2 == null) return false;
+    int length = e1.length;
+    if (length != e2.length) return false;
+    Map<_MapEntry, int> equalElementCounts = new HashMap();
+    for (K key in e1.keys) {
+      _MapEntry entry = new _MapEntry(this, key, e1[key]);
+      int count = equalElementCounts[entry];
+      if (count == null) count = 0;
+      equalElementCounts[entry] = count + 1;
+    }
+    for (K key in e2.keys) {
+      _MapEntry entry = new _MapEntry(this, key, e2[key]);
+      int count = equalElementCounts[entry];
+      if (count == null || count == 0) return false;
+      equalElementCounts[entry] = count - 1;
+    }
+    return true;
+  }
+
+  int hash(Map<K, V> map) {
+    int hash = 0;
+    for (K key in map.keys) {
+      int keyHash = _keyEquality.hash(key);
+      int valueHash = _valueEquality.hash(map[key]);
+      hash = (hash + 3 * keyHash + 7 * valueHash) & _HASH_MASK;
+    }
+    hash = (hash + (hash << 3)) & _HASH_MASK;
+    hash ^= (hash >> 11);
+    hash = (hash + (hash << 15)) & _HASH_MASK;
+    return hash;
+  }
+
+  bool isValidKey(Object o) => o is Map<K, V>;
+}
+
+/**
+ * Combines several equalities into a single equality.
+ *
+ * Tries each equality in order, using [Equality.isValidKey], and returns
+ * the result of the first equality that applies to the argument or arguments.
+ *
+ * For `equals`, the first equality that matches the first argument is used,
+ * and if the second argument of `equals` is not valid for that equality,
+ * it returns false.
+ *
+ * Because the equalities are tried in order, they should generally work on
+ * disjoint types. Otherwise the multi-equality may give inconsistent results
+ * for `equals(e1, e2)` and `equals(e2, e1)`. This can happen if one equality
+ * considers only `e1` a valid key, and not `e2`, but an equality which is
+ * checked later, allows both.
+ */
+class MultiEquality<E> implements Equality<E> {
+  final Iterable<Equality<E>> _equalities;
+
+  const MultiEquality(Iterable<Equality<E>> equalities)
+      : _equalities = equalities;
+
+  bool equals(E e1, E e2) {
+    for (Equality<E> eq in _equalities) {
+      if (eq.isValidKey(e1)) return eq.isValidKey(e2) && eq.equals(e1, e2);
+    }
+    return false;
+  }
+
+  int hash(E e) {
+    for (Equality<E> eq in _equalities) {
+      if (eq.isValidKey(e)) return eq.hash(e);
+    }
+    return -1;
+  }
+
+  bool isValidKey(Object o) {
+    for (Equality<E> eq in _equalities) {
+      if (eq.isValidKey(o)) return true;
+    }
+    return false;
+  }
+}
+
+/**
+ * Deep equality on collections.
+ *
+ * Recognizes lists, sets, iterables and maps and compares their elements using
+ * deep equality as well.
+ *
+ * Non-iterable/map objects are compared using a configurable base equality.
+ *
+ * Works in one of two modes: ordered or unordered.
+ *
+ * In ordered mode, lists and iterables are required to have equal elements
+ * in the same order. In unordered mode, the order of elements in iterables
+ * and lists are not importan.
+ *
+ * A list is only equal to another list, likewise for sets and maps. All other
+ * iterables are compared as iterables only.
+ */
+class DeepCollectionEquality implements Equality {
+  final Equality _base;
+  final bool _unordered;
+  const DeepCollectionEquality([Equality base = const DefaultEquality()])
+      : _base = base, _unordered = false;
+
+  /**
+   * Creates a deep equality on collections where the order of lists and
+   * iterables are not considered important. That is, lists and iterables are
+   * treated as unordered iterables.
+   */
+  const DeepCollectionEquality.unordered(
+      [Equality base = const DefaultEquality()])
+      : _base = base, _unordered = true;
+
+  bool equals(e1, e2) {
+    if (e1 is Set) {
+      if (e2 is! Set) return false;
+      return new SetEquality(this).equals(e1, e2);
+    }
+    if (e1 is Map) {
+      if (e2 is! Map) return false;
+      return new MapEquality(keys: this, values: this).equals(e1, e2);
+    }
+    if (!_unordered) {
+      if (e1 is List) {
+        if (e2 is! List) return false;
+        return new ListEquality(this).equals(e1, e2);
+      }
+      if (e1 is Iterable) {
+        if (e2 is! Iterable) return false;
+        return new IterableEquality(this).equals(e1, e2);
+      }
+    } else if (e1 is Iterable) {
+      if (e2 is! Iterable) return false;
+      if (e1 is List != e2 is List) return false;
+      return new UnorderedIterableEquality(this).equals(e1, e2);
+    }
+    return _base.equals(e1, e2);
+  }
+
+  int hash(Object o) {
+    if (o is Set) return new SetEquality(this).hash(o);
+    if (o is Map) return new MapEquality(keys: this, values: this).hash(o);
+    if (!_unordered) {
+      if (o is List) return new ListEquality(this).hash(o);
+      if (o is Iterable) return new IterableEquality(this).hash(o);
+    } else if (o is Iterable) {
+      return new UnorderedIterableEquality(this).hash(o);
+    }
+    return _base.hash(o);
+  }
+
+  bool isValidKey(Object o) => o is Iterable || o is Map || _base.isValidKey(o);
+}
diff --git a/pkg/collection/lib/iterable_zip.dart b/pkg/collection/lib/iterable_zip.dart
new file mode 100644
index 0000000..772b07e
--- /dev/null
+++ b/pkg/collection/lib/iterable_zip.dart
@@ -0,0 +1,59 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/**
+ * Zipping multiple iterables into one iterable of tuples of values.
+ */
+library dart.pkg.collection.iterable_zip;
+
+import "dart:collection" show IterableBase;
+
+/**
+ * Iterable that iterates over lists of values from other iterables.
+ *
+ * When [iterator] is read, an [Iterator] is created for each [Iterable] in
+ * the [Iterable] passed to the constructor.
+ *
+ * As long as all these iterators have a next value, those next values are
+ * combined into a single list, which becomes the next value of this
+ * [Iterable]'s [Iterator]. As soon as any of the iterators run out,
+ * the zipped iterator also stops.
+ */
+class IterableZip extends IterableBase<List> {
+  final Iterable<Iterable> _iterables;
+  IterableZip(Iterable<Iterable> iterables)
+      : this._iterables = iterables;
+
+  /**
+   * Returns an iterator that combines values of the iterables' iterators
+   * as long as they all have values.
+   */
+  Iterator<List> get iterator {
+    List iterators = _iterables.map((x) => x.iterator).toList(growable: false);
+    // TODO(lrn): Return an empty iterator directly if iterators is empty?
+    return new _IteratorZip(iterators);
+  }
+}
+
+class _IteratorZip implements Iterator<List> {
+  final List<Iterator> _iterators;
+  List _current;
+  _IteratorZip(List iterators) : _iterators = iterators;
+  bool moveNext() {
+    if (_iterators.isEmpty) return false;
+    for (int i = 0; i < _iterators.length; i++) {
+      if (!_iterators[i].moveNext()) {
+        _current = null;
+        return false;
+      }
+    }
+    _current = new List(_iterators.length);
+    for (int i = 0; i < _iterators.length; i++) {
+      _current[i] = _iterators[i].current;
+    }
+    return true;
+  }
+
+  List get current => _current;
+}
diff --git a/pkg/collection_helpers/lib/unmodifiable_wrappers.dart b/pkg/collection/lib/src/unmodifiable_wrappers.dart
similarity index 99%
rename from pkg/collection_helpers/lib/unmodifiable_wrappers.dart
rename to pkg/collection/lib/src/unmodifiable_wrappers.dart
index b44337f..022bbfe 100644
--- a/pkg/collection_helpers/lib/unmodifiable_wrappers.dart
+++ b/pkg/collection/lib/src/unmodifiable_wrappers.dart
@@ -11,7 +11,7 @@
  * The [List] wrapper prevents changes to the length of the wrapped list,
  * but allows changes to the contents.
  */
-part of dart.collection_helpers.wrappers;
+part of dart.pkg.collection.wrappers;
 
 /**
  * A fixed-length list.
diff --git a/pkg/collection/lib/wrappers.dart b/pkg/collection/lib/wrappers.dart
new file mode 100644
index 0000000..ec78f5c
--- /dev/null
+++ b/pkg/collection/lib/wrappers.dart
@@ -0,0 +1,334 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/**
+ * Delegating wrappers for [Iterable], [List], [Set], [Queue] and [Map].
+ *
+ * Also adds unmodifiable views for `Set` and `Map`, and a fixed length
+ * view for `List`. The unmodifable list view from `dart:collection` is exported
+ * as well, just for completeness.
+ */
+library dart.pkg.collection.wrappers;
+
+import "dart:collection";
+import "dart:math" show Random;
+
+export "dart:collection" show UnmodifiableListView;
+
+part "src/unmodifiable_wrappers.dart";
+
+/**
+ * Creates an [Iterable] that delegates all operations to a base iterable.
+ *
+ * This class can be used hide non-`Iterable` methods of an iterable object,
+ * or it can be extended to add extra functionality on top of an existing
+ * iterable object.
+ */
+class DelegatingIterable<E> implements Iterable<E> {
+  Iterable<E> _base;
+
+  /**
+   * Create a wrapper that forwards operations to [base].
+   */
+  DelegatingIterable(Iterable<E> base) : _base = base;
+
+  bool any(bool test(E element)) => _base.any(test);
+
+  bool contains(Object element) => _base.contains(element);
+
+  E elementAt(int index) => _base.elementAt(index);
+
+  bool every(bool test(E element)) => _base.every(test);
+
+  Iterable expand(Iterable f(E element)) => _base.expand(f);
+
+  E get first => _base.first;
+
+  E firstWhere(bool test(E element), {E orElse()}) =>
+      _base.firstWhere(test, orElse: orElse);
+
+  fold(initialValue, combine(previousValue, E element)) =>
+      _base.fold(initialValue, combine);
+
+  void forEach(void f(E element)) => _base.forEach(f);
+
+  bool get isEmpty => _base.isEmpty;
+
+  bool get isNotEmpty => _base.isNotEmpty;
+
+  Iterator<E> get iterator => _base.iterator;
+
+  String join([String separator = ""]) => _base.join(separator);
+
+  E get last => _base.last;
+
+  E lastWhere(bool test(E element), {E orElse()}) =>
+      _base.lastWhere(test, orElse: orElse);
+
+  int get length => _base.length;
+
+  Iterable map(f(E element)) => _base.map(f);
+
+  E reduce(E combine(E value, E element)) => _base.reduce(combine);
+
+  E get single => _base.single;
+
+  E singleWhere(bool test(E element)) => _base.singleWhere(test);
+
+  Iterable<E> skip(int n) => _base.skip(n);
+
+  Iterable<E> skipWhile(bool test(E value)) => _base.skipWhile(test);
+
+  Iterable<E> take(int n) => _base.take(n);
+
+  Iterable<E> takeWhile(bool test(E value)) => _base.takeWhile(test);
+
+  List<E> toList({bool growable: true}) => _base.toList(growable: growable);
+
+  Set<E> toSet() => _base.toSet();
+
+  Iterable<E> where(bool test(E element)) => _base.where(test);
+}
+
+
+/**
+ * Creates a [List] that delegates all operations to a base list.
+ *
+ * This class can be used hide non-`List` methods of a list object,
+ * or it can be extended to add extra functionality on top of an existing
+ * list object.
+ */
+class DelegatingList<E> extends DelegatingIterable<E> implements List<E> {
+  DelegatingList(List<E> base) : super(base);
+
+  List<E> get _listBase => _base;
+
+  E operator [](int index) => _listBase[index];
+
+  void operator []=(int index, E value) {
+    _listBase[index] = value;
+  }
+
+  void add(E value) {
+    _listBase.add(value);
+  }
+
+  void addAll(Iterable<E> iterable) {
+    _listBase.addAll(iterable);
+  }
+
+  Map<int, E> asMap() => _listBase.asMap();
+
+  void clear() {
+    _listBase.clear();
+  }
+
+  void fillRange(int start, int end, [E fillValue]) {
+    _listBase.fillRange(start, end, fillValue);
+  }
+
+  Iterable<E> getRange(int start, int end) => _listBase.getRange(start, end);
+
+  int indexOf(E element, [int start = 0]) => _listBase.indexOf(element, start);
+
+  void insert(int index, E element) {
+    _listBase.insert(index, element);
+  }
+
+  void insertAll(int index, Iterable<E> iterable) {
+    _listBase.insertAll(index, iterable);
+  }
+
+  int lastIndexOf(E element, [int start]) =>
+      _listBase.lastIndexOf(element, start);
+
+  void set length(int newLength) {
+    _listBase.length = newLength;
+  }
+
+  bool remove(Object value) => _listBase.remove(value);
+
+  E removeAt(int index) => _listBase.removeAt(index);
+
+  E removeLast() => _listBase.removeLast();
+
+  void removeRange(int start, int end) {
+    _listBase.removeRange(start, end);
+  }
+
+  void removeWhere(bool test(E element)) {
+    _listBase.removeWhere(test);
+  }
+
+  void replaceRange(int start, int end, Iterable<E> iterable) {
+    _listBase.replaceRange(start, end, iterable);
+  }
+
+  void retainWhere(bool test(E element)) {
+    _listBase.retainWhere(test);
+  }
+
+  Iterable<E> get reversed => _listBase.reversed;
+
+  void setAll(int index, Iterable<E> iterable) {
+    _listBase.setAll(index, iterable);
+  }
+
+  void setRange(int start, int end, Iterable<E> iterable, [int skipCount = 0]) {
+    _listBase.setRange(start, end, iterable, skipCount);
+  }
+
+  void shuffle([Random random]) {
+    _listBase.shuffle(random);
+  }
+
+  void sort([int compare(E a, E b)]) {
+    _listBase.sort(compare);
+  }
+
+  List<E> sublist(int start, [int end]) => _listBase.sublist(start, end);
+}
+
+
+/**
+ * Creates a [Set] that delegates all operations to a base set.
+ *
+ * This class can be used hide non-`Set` methods of a set object,
+ * or it can be extended to add extra functionality on top of an existing
+ * set object.
+ */
+class DelegatingSet<E> extends DelegatingIterable<E> implements Set<E> {
+  DelegatingSet(Set<E> base) : super(base);
+
+  Set<E> get _setBase => _base;
+
+  bool add(E value) => _setBase.add(value);
+
+  void addAll(Iterable<E> elements) {
+    _setBase.addAll(elements);
+  }
+
+  void clear() {
+    _setBase.clear();
+  }
+
+  bool containsAll(Iterable<Object> other) => _setBase.containsAll(other);
+
+  Set<E> difference(Set<E> other) => _setBase.difference(other);
+
+  Set<E> intersection(Set<Object> other) => _setBase.intersection(other);
+
+  E lookup(E element) => _setBase.lookup(element);
+
+  bool remove(Object value) => _setBase.remove(value);
+
+  void removeAll(Iterable<Object> elements) {
+    _setBase.removeAll(elements);
+  }
+
+  void removeWhere(bool test(E element)) {
+    _setBase.removeWhere(test);
+  }
+
+  void retainAll(Iterable<Object> elements) {
+    _setBase.retainAll(elements);
+  }
+
+  void retainWhere(bool test(E element)) {
+    _setBase.retainWhere(test);
+  }
+
+  Set<E> union(Set<E> other) => _setBase.union(other);
+}
+
+/**
+ * Creates a [Queue] that delegates all operations to a base queue.
+ *
+ * This class can be used hide non-`Queue` methods of a queue object,
+ * or it can be extended to add extra functionality on top of an existing
+ * queue object.
+ */
+class DelegatingQueue<E> extends DelegatingIterable<E> implements Queue<E> {
+  DelegatingQueue(Queue<E> queue) : super(queue);
+
+  Queue<E> get _baseQueue => _base;
+
+  void add(E value) {
+    _baseQueue.add(value);
+  }
+
+  void addAll(Iterable<E> iterable) {
+    _baseQueue.addAll(iterable);
+  }
+
+  void addFirst(E value) {
+    _baseQueue.addFirst(value);
+  }
+
+  void addLast(E value) {
+    _baseQueue.addLast(value);
+  }
+
+  void clear() {
+    _baseQueue.clear();
+  }
+
+  bool remove(Object object) => _baseQueue.remove(object);
+
+  void removeWhere(bool test(E element)) { _baseQueue.removeWhere(test); }
+
+  void retainWhere(bool test(E element)) { _baseQueue.retainWhere(test); }
+
+  E removeFirst() => _baseQueue.removeFirst();
+
+  E removeLast() => _baseQueue.removeLast();
+}
+
+/**
+ * Creates a [Map] that delegates all operations to a base map.
+ *
+ * This class can be used hide non-`Map` methods of an object that extends
+ * `Map`, or it can be extended to add extra functionality on top of an existing
+ * map object.
+ */
+class DelegatingMap<K, V> implements Map<K, V> {
+  Map<K, V> _base;
+  DelegatingMap(Map<K, V> base) : _base = base;
+
+  V operator [](Object key) => _base[key];
+
+  void operator []=(K key, V value) {
+    _base[key] = value;
+  }
+
+  void addAll(Map<K, V> other) {
+    _base.addAll(other);
+  }
+
+  void clear() {
+    _base.clear();
+  }
+
+  bool containsKey(Object key) => _base.containsKey(key);
+
+  bool containsValue(Object value) => _base.containsValue(value);
+
+  void forEach(void f(K key, V value)) {
+    _base.forEach(f);
+  }
+
+  bool get isEmpty => _base.isEmpty;
+
+  bool get isNotEmpty => _base.isNotEmpty;
+
+  Iterable<K> get keys => _base.keys;
+
+  int get length => _base.length;
+
+  V putIfAbsent(K key, V ifAbsent()) => _base.putIfAbsent(key, ifAbsent);
+
+  V remove(Object key) => _base.remove(key);
+
+  Iterable<V> get values => _base.values;
+}
diff --git a/pkg/collection/pubspec.yaml b/pkg/collection/pubspec.yaml
new file mode 100644
index 0000000..0fec04b
--- /dev/null
+++ b/pkg/collection/pubspec.yaml
@@ -0,0 +1,9 @@
+name: collection
+version: 0.9.0
+author: Dart Team <misc@dartlang.org>
+description: Collections and utilities functions and classes related to collections.
+homepage: http://www.dartlang.org
+dev_dependencies:
+  unittest: ">=0.9.0 <0.10.0"
+environment:
+  sdk: ">=1.0.0 <2.0.0"
diff --git a/pkg/collection_helpers/test/algorithms_test.dart b/pkg/collection/test/algorithms_test.dart
similarity index 99%
rename from pkg/collection_helpers/test/algorithms_test.dart
rename to pkg/collection/test/algorithms_test.dart
index ff82fff..933e268 100644
--- a/pkg/collection_helpers/test/algorithms_test.dart
+++ b/pkg/collection/test/algorithms_test.dart
@@ -4,7 +4,7 @@
 
 /// Tests algorithm utilities.
 
-import "package:collection_helpers/all.dart";
+import "package:collection/collection.dart";
 import "package:unittest/unittest.dart";
 import 'dart:math';
 
@@ -268,4 +268,4 @@
   OC(this.id, this.order);
   int compareTo(OC other) => id - other.id;
   String toString() => "OC[$id,$order]";
-}
\ No newline at end of file
+}
diff --git a/pkg/collection_helpers/test/equality_test.dart b/pkg/collection/test/equality_test.dart
similarity index 98%
rename from pkg/collection_helpers/test/equality_test.dart
rename to pkg/collection/test/equality_test.dart
index 00a1505..edabfd5 100644
--- a/pkg/collection_helpers/test/equality_test.dart
+++ b/pkg/collection/test/equality_test.dart
@@ -5,7 +5,7 @@
 // Tests equality utilities.
 
 import "dart:collection";
-import "package:collection_helpers/all.dart";
+import "package:collection/collection.dart";
 import "package:unittest/unittest.dart";
 
 main() {
diff --git a/pkg/sequence_zip/test/iterable_test.dart b/pkg/collection/test/iterable_zip_test.dart
similarity index 98%
rename from pkg/sequence_zip/test/iterable_test.dart
rename to pkg/collection/test/iterable_zip_test.dart
index 978ee96..ec191fe 100644
--- a/pkg/sequence_zip/test/iterable_test.dart
+++ b/pkg/collection/test/iterable_zip_test.dart
@@ -3,7 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import "dart:collection";
-import "package:sequence_zip/iterable_zip.dart";
+import "package:collection/iterable_zip.dart";
 import "package:unittest/unittest.dart";
 
 /// Iterable like [base] except that it throws when value equals [errorValue].
diff --git a/pkg/collection_helpers/test/unmodifiable_collection_test.dart b/pkg/collection/test/unmodifiable_collection_test.dart
similarity index 99%
rename from pkg/collection_helpers/test/unmodifiable_collection_test.dart
rename to pkg/collection/test/unmodifiable_collection_test.dart
index ac5bb07..d810b75 100644
--- a/pkg/collection_helpers/test/unmodifiable_collection_test.dart
+++ b/pkg/collection/test/unmodifiable_collection_test.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 "package:collection_helpers/wrappers.dart";
+import "package:collection/wrappers.dart";
 import "package:unittest/unittest.dart";
 
 // Test unmodifiable collection views.
diff --git a/pkg/collection_helpers/test/wrapper_test.dart b/pkg/collection/test/wrapper_test.dart
similarity index 99%
rename from pkg/collection_helpers/test/wrapper_test.dart
rename to pkg/collection/test/wrapper_test.dart
index 3c3da3c..875a70a 100644
--- a/pkg/collection_helpers/test/wrapper_test.dart
+++ b/pkg/collection/test/wrapper_test.dart
@@ -5,7 +5,7 @@
 /// Tests wrapper utilities.
 
 import "dart:collection";
-import "package:collection_helpers/all.dart";
+import "package:collection/collection.dart";
 import "package:unittest/unittest.dart";
 
 // Test that any member access/call on the wrapper object is equal to
diff --git a/pkg/collection_helpers/LICENSE b/pkg/collection_helpers/LICENSE
new file mode 100644
index 0000000..ee99930
--- /dev/null
+++ b/pkg/collection_helpers/LICENSE
@@ -0,0 +1,26 @@
+Copyright 2013, the Dart project authors. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+    * Neither the name of Google Inc. nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/pkg/collection_helpers/README.md b/pkg/collection_helpers/README.md
index 742cc16..fd20bd2 100644
--- a/pkg/collection_helpers/README.md
+++ b/pkg/collection_helpers/README.md
@@ -1,55 +1,9 @@
-Helper libraries for working with collections.
+Deprecated helper libraries for working with collections.
 
-The `collection_helpers` package contains a number of separate libraries
-with utility functions and classes that makes working with collections easier.
+The `collection_helpers` package has been split into the
+`collection` package (for most of the library)
+and the `typed_data` package (for typed data buffers).
 
-## Using
+All further development will happen on those libraries.
 
-The `collection_helpers` library can be imported as separate libraries, or
-in totality:
-
-    import 'package:collection_helpers/equality.dart';
-    import 'package:collection_helpers/algorithms.dart';
-    import 'package:collection_helpers/wrappers.dart';
-
-or
-
-    import 'package:collection_helpers/all.dart';
-
-## Equality
-
-The equality library gives a way to specify equality of elements and
-collections.
-
-Collections in Dart have no inherent equality. Two sets are not equal, even
-if they contain exactly the same objects as elements.
-
-The equality library provides a way to say define such an equality. In this
-case, for example, `const SetEquality(const IdentityEquality())` is an equality
-that considers two sets equal exactly if they contain identical elements.
-
-The library provides ways to define equalities on `Iterable`s, `List`s, `Set`s, and
-`Map`s, as well as combinations of these, such as:
-
-    const MapEquality(const IdentityEquality(), const ListEquality());
-
-This equality considers maps equal if they have identical keys, and the corresponding values are lists with equal (`operator==`) values.
-
-## Algorithms
-
-The algorithms library contains functions that operate on lists.
-
-It contains ways to shuffle a `List`, do binary search on a sorted `List`, and
-some different sorting algorithms.
-
-
-## Wrappers
-
-The wrappers library contains classes that "wrap" a collection.
-
-A wrapper class contains an object of the same type, and it forwards all
-methods to the wrapped object.
-
-Wrapper classes can be used in various ways, for example to restrict the type
-of an object to that of a supertype, or to change the behavior of selected
-functions on an existing object.
+Please start using those libraries directly.
diff --git a/pkg/collection_helpers/lib/algorithms.dart b/pkg/collection_helpers/lib/algorithms.dart
index 057111a..85d15ba 100644
--- a/pkg/collection_helpers/lib/algorithms.dart
+++ b/pkg/collection_helpers/lib/algorithms.dart
@@ -2,300 +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.
 
-/**
- * Operations on collections.
- */
+@deprecated
 library dart.collection_helpers.algorithms;
 
-import "dart:math" show Random;
-
-/** Version of [binarySearch] optimized for comparable keys */
-int _comparableBinarySearch(List<Comparable> list, Comparable key) {
-  int min = 0;
-  int max = list.length;
-  while (min < max) {
-    int mid = min + ((max - min) >> 1);
-    var element = list[mid];
-    int comp = element.compareTo(key);
-    if (comp == 0) return mid;
-    if (comp < 0) {
-      min = mid + 1;
-    } else {
-      max = mid;
-    }
-  }
-  return -1;
-}
-
-/**
- * Returns a position of the [key] in [sortedList], if it is there.
- *
- * If the list isn't sorted according to the [compare] function, the result
- * is unpredictable.
- *
- * If [compare] is omitted, it defaults to calling [Comparable.compareTo] on
- * the objects.
- *
- * Returns -1 if [key] is not in the list by default.
- */
-int binarySearch(List sortedList, var key,
-                 { int compare(var a, var b) }) {
-  if (compare == null) {
-    return _comparableBinarySearch(sortedList, key);
-  }
-  int min = 0;
-  int max = sortedList.length;
-  while (min < max) {
-    int mid = min + ((max - min) >> 1);
-    var element = sortedList[mid];
-    int comp = compare(element, key);
-    if (comp == 0) return mid;
-    if (comp < 0) {
-      min = mid + 1;
-    } else {
-      max = mid;
-    }
-  }
-  return -1;
-}
-
-
-/**
- * Shuffles a list randomly.
- *
- * A sub-range of a list can be shuffled by providing [start] and [end].
- */
-void shuffle(List list, [int start = 0, int end = null]) {
-  Random random = new Random();
-  if (end == null) end = list.length;
-  int length = end - start;
-  while (length > 1) {
-    int pos = random.nextInt(length);
-    length--;
-    var tmp1 = list[start + pos];
-    list[start + pos] = list[start + length];
-    list[start + length] = tmp1;
-  }
-}
-
-
-/**
- * Reverses a list, or a part of a list, in-place.
- */
-void reverse(List list, [int start = 0, int end = null]) {
-  if (end == null) end = list.length;
-  _reverse(list, start, end);
-}
-
-// Internal helper function that assumes valid arguments.
-void _reverse(List list, int start, int end) {
-  for (int i = start, j = end - 1; i < j; i++, j--) {
-    var tmp = list[i];
-    list[i] = list[j];
-    list[j] = tmp;
-  }
-}
-
-/**
- * Sort a list using insertion sort.
- *
- * Insertion sort is a simple sorting algorithm. For `n` elements it does on
- * the order of `n * log(n)` comparisons but up to `n` squared moves. The
- * sorting is performed in-place, without using extra memory.
- *
- * For short lists the many moves have less impact than the simple algorithm,
- * and it is often the favored sorting algorithm for short lists.
- *
- * This insertion sort is stable: Equal elements end up in the same order
- * as they started in.
- */
-void insertionSort(List list,
-                   { int compare(a, b),
-                     int start: 0,
-                     int end: null }) {
-  // If the same method could have both positional and named optional
-  // parameters, this should be (list, [start, end], {compare}).
-  if (end == null) end = list.length;
-  if (compare == null) compare = Comparable.compare;
-  _insertionSort(list, compare, start, end, start + 1);
-}
-
-/**
- * Internal helper function that assumes arguments correct.
- *
- * Assumes that the elements up to [sortedUntil] (not inclusive) are
- * already sorted. The [sortedUntil] values should always be at least
- * `start + 1`.
- */
-void _insertionSort(List list, int compare(a, b), int start, int end,
-                    int sortedUntil) {
-  for (int pos = sortedUntil; pos < end; pos++) {
-    int min = start;
-    int max = pos;
-    var element = list[pos];
-    while (min < max) {
-      int mid = min + ((max - min) >> 1);
-      int comparison = compare(element, list[mid]);
-      if (comparison < 0) {
-        max = mid;
-      } else {
-        min = mid + 1;
-      }
-    }
-    list.setRange(min + 1, pos + 1, list, min);
-    list[min] = element;
-  }
-}
-
-/** Limit below which merge sort defaults to insertion sort. */
-const int _MERGE_SORT_LIMIT = 32;
-
-/**
- * Sorts a list, or a range of a list, using the merge sort algorithm.
- *
- * Merge-sorting works by splitting the job into two parts, sorting each
- * recursively, and then merging the two sorted parts.
- *
- * This takes on the order of `n * log(n)` comparisons and moves to sort
- * `n` elements, but requires extra space of about the same size as the list
- * being sorted.
- *
- * This merge sort is stable: Equal elements end up in the same order
- * as they started in.
- */
-void mergeSort(List list, {int start: 0, int end: null, int compare(a, b)}) {
-  if (end == null) end = list.length;
-  if (compare == null) compare = Comparable.compare;
-  int length = end - start;
-  if (length < 2) return;
-  if (length < _MERGE_SORT_LIMIT) {
-    _insertionSort(list, compare, start, end, start + 1);
-    return;
-  }
-  // Special case the first split instead of directly calling
-  // _mergeSort, because the _mergeSort requires its target to
-  // be different from its source, and it requires extra space
-  // of the same size as the list to sort.
-  // This split allows us to have only half as much extra space,
-  // and it ends up in the original place.
-  int middle = start + ((end - start) >> 1);
-  int firstLength = middle - start;
-  int secondLength = end - middle;
-  // secondLength is always the same as firstLength, or one greater.
-  List scratchSpace = new List(secondLength);
-  _mergeSort(list, compare, middle, end, scratchSpace, 0);
-  int firstTarget = end - firstLength;
-  _mergeSort(list, compare, start, middle, list, firstTarget);
-  _merge(compare,
-         list, firstTarget, end,
-         scratchSpace, 0, secondLength,
-         list, start);
-}
-
-/**
- * Performs an insertion sort into a potentially different list than the
- * one containing the original values.
- *
- * It will work in-place as well.
- */
-void _movingInsertionSort(List list, int compare(a, b), int start, int end,
-                          List target, int targetOffset) {
-  int length = end - start;
-  if (length == 0) return;
-  target[targetOffset] = list[start];
-  for (int i = 1; i < length; i++) {
-    var element = list[start + i];
-    int min = targetOffset;
-    int max = targetOffset + i;
-    while (min < max) {
-      int mid = min + ((max - min) >> 1);
-      if (compare(element, target[mid]) < 0) {
-        max = mid;
-      } else {
-        min = mid + 1;
-      }
-    }
-    target.setRange(min + 1, targetOffset + i + 1,
-                    target, min);
-    target[min] = element;
-  }
-}
-
-/**
- * Sorts [list] from [start] to [end] into [target] at [targetOffset].
- *
- * The `target` list must be able to contain the range from `start` to `end`
- * after `targetOffset`.
- *
- * Allows target to be the same list as [list], as long as it's not
- * overlapping the `start..end` range.
- */
-void _mergeSort(List list, int compare(a, b), int start, int end,
-                List target, int targetOffset) {
-  int length = end - start;
-  if (length < _MERGE_SORT_LIMIT) {
-    _movingInsertionSort(list, compare, start, end, target, targetOffset);
-    return;
-  }
-  int middle = start + (length >> 1);
-  int firstLength = middle - start;
-  int secondLength = end - middle;
-  // Here secondLength >= firstLength (differs by at most one).
-  int targetMiddle = targetOffset + firstLength;
-  // Sort the second half into the end of the target area.
-  _mergeSort(list, compare, middle, end,
-             target, targetMiddle);
-  // Sort the first half into the end of the source area.
-  _mergeSort(list, compare, start, middle,
-             list, middle);
-  // Merge the two parts into the target area.
-  _merge(compare,
-         list, middle, middle + firstLength,
-         target, targetMiddle, targetMiddle + secondLength,
-         target, targetOffset);
-}
-
-/**
- * Merges two lists into a target list.
- *
- * One of the input lists may be positioned at the end of the target
- * list.
- *
- * For equal object, elements from [firstList] are always preferred.
- * This allows the merge to be stable if the first list contains elements
- * that started out earlier than the ones in [secondList]
- */
-void _merge(int compare(a, b),
-            List firstList, int firstStart, int firstEnd,
-            List secondList, int secondStart, int secondEnd,
-            List target, int targetOffset) {
-  // No empty lists reaches here.
-  assert(firstStart < firstEnd);
-  assert(secondStart < secondEnd);
-  int cursor1 = firstStart;
-  int cursor2 = secondStart;
-  var firstElement = firstList[cursor1++];
-  var secondElement = secondList[cursor2++];
-  while (true) {
-    if (compare(firstElement, secondElement) <= 0) {
-      target[targetOffset++] = firstElement;
-      if (cursor1 == firstEnd) break;  // Flushing second list after loop.
-      firstElement = firstList[cursor1++];
-    } else {
-      target[targetOffset++] = secondElement;
-      if (cursor2 != secondEnd) {
-        secondElement = secondList[cursor2++];
-        continue;
-      }
-      // Second list empties first. Flushing first list here.
-      target[targetOffset++] = firstElement;
-      target.setRange(targetOffset, targetOffset + (firstEnd - cursor1),
-          firstList, cursor1);
-      return;
-    }
-  }
-  // First list empties first. Reached by break above.
-  target[targetOffset++] = secondElement;
-  target.setRange(targetOffset, targetOffset + (secondEnd - cursor2),
-      secondList, cursor2);
-}
+export "package:collection/algorithms.dart";
diff --git a/pkg/collection_helpers/lib/all.dart b/pkg/collection_helpers/lib/all.dart
index 3658cf1..a9f6b63 100644
--- a/pkg/collection_helpers/lib/all.dart
+++ b/pkg/collection_helpers/lib/all.dart
@@ -2,18 +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.
 
-/**
- * Exports all the individual parts of the collection-helper library.
- *
- * The sub-libraries of this package are:
- *
- * - `algorithms.dart`: Algorithms that work on lists (shuffle, binary search
- *                      and various sorting algorithms).
- * - `equality.dart`: Different notions of equality of collections.
- * - `typed_buffers.dart`: Growable typed data lists.
- * - `wrappers.dart`: Wrapper classes that delegate to a collection object.
- *                    Includes unmodifiable views of collections.
- */
+@deprecated
 library dart.collection_helper;
 
 export "algorithms.dart";
diff --git a/pkg/collection_helpers/lib/equality.dart b/pkg/collection_helpers/lib/equality.dart
index 2b46266..c47d635 100644
--- a/pkg/collection_helpers/lib/equality.dart
+++ b/pkg/collection_helpers/lib/equality.dart
@@ -2,418 +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.
 
-/**
- * Defines equality relations on collections.
- */
+@deprecated
 library dart.collection_helpers.equality;
 
-import "dart:collection";
-
-const int _HASH_MASK = 0x7fffffff;
-
-/**
- * A generic equality relation on objects.
- */
-abstract class Equality<E> {
-  const factory Equality() = DefaultEquality;
-
-  /**
-   * Compare two elements for being equal.
-   *
-   * This should be a proper equality relation.
-   */
-  bool equals(E e1, E e2);
-
-  /**
-   * Get a hashcode of an element.
-   *
-   * The hashcode should be compatible with [equals], so that if
-   * `equals(a, b)` then `hash(a) == hash(b)`.
-   */
-  int hash(E e);
-
-  /**
-   * Test whether an object is a valid argument to [equals] and [hash].
-   *
-   * Some implementations may be restricted to only work on specific types
-   * of objects.
-   */
-  bool isValidKey(Object o);
-}
-
-/**
- * Equality of objects that compares only the natural equality of the objects.
- *
- * This equality uses the objects' own [Object.==] and [Object.hashCode] for
- * the equality.
- */
-class DefaultEquality implements Equality {
-  const DefaultEquality();
-  bool equals(Object e1, Object e2) => e1 == e2;
-  int hash(Object e) => e.hashCode;
-  bool isValidKey(Object o) => true;
-}
-
-/**
- * Equality of objects that compares only the identity of the objects.
- */
-class IdentityEquality implements Equality {
-  const IdentityEquality();
-  bool equals(Object e1, Object e2) => identical(e1, e2);
-  int hash(Object e) => identityHashCode(e);
-  bool isValidKey(Object o) => true;
-}
-
-/**
- * Equality on iterables.
- *
- * Two iterables are equal if they have the same elements in the same order.
- */
-class IterableEquality<E> implements Equality<Iterable<E>> {
-  final Equality<E> _elementEquality;
-  const IterableEquality([Equality<E> elementEquality =
-                              const DefaultEquality()])
-      : _elementEquality = elementEquality;
-
-  bool equals(Iterable<E> elements1, Iterable<E> elements2) {
-    if (identical(elements1, elements2)) return true;
-    if (elements1 == null || elements2 == null) return false;
-    Iterator it1 = elements1.iterator;
-    Iterator it2 = elements2.iterator;
-    while (true) {
-      bool hasNext = it1.moveNext();
-      if (hasNext != it2.moveNext()) return false;
-      if (!hasNext) return true;
-      if (!_elementEquality.equals(it1.current, it2.current)) return false;
-    }
-  }
-
-  int hash(Iterable<E> elements) {
-    // Jenkins's one-at-a-time hash function.
-    int hash = 0;
-    for (E element in elements) {
-      int c = _elementEquality.hash(element);
-      hash = (hash + c) & _HASH_MASK;
-      hash = (hash + (hash << 10)) & _HASH_MASK;
-      hash ^= (hash >> 6);
-    }
-    hash = (hash + (hash << 3)) & _HASH_MASK;
-    hash ^= (hash >> 11);
-    hash = (hash + (hash << 15)) & _HASH_MASK;
-    return hash;
-  }
-
-  bool isValidKey(Object o) => o is Iterable<E>;
-}
-
-/**
- * Equality on lists.
- *
- * Two lists are equal if they have the same length and their elements
- * at each index are equal.
- *
- * This is effectively the same as [IterableEquality] except that it
- * accesses elements by index instead of through iteration.
- */
-class ListEquality<E> implements Equality<List<E>> {
-  final Equality<E> _elementEquality;
-  const ListEquality([Equality<E> elementEquality = const DefaultEquality()])
-      : _elementEquality = elementEquality;
-
-  bool equals(List<E> e1, List<E> e2) {
-    if (identical(e1, e2)) return true;
-    if (e1 == null || e2 == null) return false;
-    int length = e1.length;
-    if (length != e2.length) return false;
-    for (int i = 0; i < length; i++) {
-      if (!_elementEquality.equals(e1[i], e2[i])) return false;
-    }
-    return true;
-  }
-
-  int hash(List<E> e) {
-    // Jenkins's one-at-a-time hash function.
-    // This code is almost identical to the one in IterableEquality, except
-    // that it uses indexing instead of iterating to get the elements.
-    int hash = 0;
-    for (int i = 0; i < e.length; i++) {
-      int c = _elementEquality.hash(e[i]);
-      hash = (hash + c) & _HASH_MASK;
-      hash = (hash + (hash << 10)) & _HASH_MASK;
-      hash ^= (hash >> 6);
-    }
-    hash = (hash + (hash << 3)) & _HASH_MASK;
-    hash ^= (hash >> 11);
-    hash = (hash + (hash << 15)) & _HASH_MASK;
-    return hash;
-  }
-
-  bool isValidKey(Object o) => o is List<E>;
-}
-
-abstract class _UnorderedEquality<E, T extends Iterable<E>>
-    implements Equality<T> {
-  final Equality<E> _elementEquality;
-
-  const _UnorderedEquality(this._elementEquality);
-
-  bool equals(T e1, T e2) {
-    if (identical(e1, e2)) return true;
-    if (e1 == null || e2 == null) return false;
-    HashMap<E, int> counts = new HashMap(
-        equals: _elementEquality.equals,
-        hashCode: _elementEquality.hash,
-        isValidKey: _elementEquality.isValidKey);
-    int length = 0;
-    for (var e in e1) {
-      int count = counts[e];
-      if (count == null) count = 0;
-      counts[e] = count + 1;
-      length++;
-    }
-    for (var e in e2) {
-      int count = counts[e];
-      if (count == null || count == 0) return false;
-      counts[e] = count - 1;
-      length--;
-    }
-    return length == 0;
-  }
-
-  int hash(T e) {
-    int hash = 0;
-    for (E element in e) {
-      int c = _elementEquality.hash(element);
-      hash = (hash + c) & _HASH_MASK;
-    }
-    hash = (hash + (hash << 3)) & _HASH_MASK;
-    hash ^= (hash >> 11);
-    hash = (hash + (hash << 15)) & _HASH_MASK;
-    return hash;
-  }
-}
-
-/**
- * Equality of the elements of two iterables without considering order.
- *
- * Two iterables are considered equal if they have the same number of elements,
- * and the elements of one set can be paired with the elements
- * of the other iterable, so that each pair are equal.
- */
-class UnorderedIterableEquality<E> extends _UnorderedEquality<E, Iterable<E>> {
-  const UnorderedIterableEquality(
-      [Equality<E> elementEquality = const DefaultEquality()])
-      : super(elementEquality);
-
-  bool isValidKey(Object o) => o is Iterable<E>;
-}
-
-/**
- * Equality of sets.
- *
- * Two sets are considered equal if they have the same number of elements,
- * and the elements of one set can be paired with the elements
- * of the other set, so that each pair are equal.
- *
- * This equality behaves the same as [UnorderedIterableEquality] except that
- * it expects sets instead of iterables as arguments.
- */
-class SetEquality<E> extends _UnorderedEquality<E, Set<E>> {
-  const SetEquality(
-      [Equality<E> elementEquality = const DefaultEquality()])
-      : super(elementEquality);
-
-  bool isValidKey(Object o) => o is Set<E>;
-}
-
-/**
- *  Internal class used by [MapEquality].
- *
- *  The class represents a map entry as a single object,
- *  using a combined hashCode and equality of the key and value.
- */
-class _MapEntry {
-  final MapEquality equality;
-  final key;
-  final value;
-  _MapEntry(this.equality, this.key, this.value);
-
-  int get hashCode =>
-      (3 * equality._keyEquality.hash(key) +
-       7 * equality._valueEquality.hash(value)) & _HASH_MASK;
-
-  bool operator==(Object other) {
-    if (other is! _MapEntry) return false;
-    _MapEntry otherEntry = other;
-    return equality._keyEquality.equals(key, otherEntry.key) &&
-           equality._valueEquality.equals(value, otherEntry.value);
-
-  }
-}
-
-/**
- * Equality on maps.
- *
- * Two maps are equal if they have the same number of entries, and if the
- * entries of the two maps are pairwise equal on both key and value.
- */
-class MapEquality<K, V> implements Equality<Map<K, V>> {
-  final Equality<K> _keyEquality;
-  final Equality<V> _valueEquality;
-  const MapEquality({ Equality<K> keys : const DefaultEquality(),
-                      Equality<V> values : const DefaultEquality() })
-      : _keyEquality = keys, _valueEquality = values;
-
-  bool equals(Map<K, V> e1, Map<K, V> e2) {
-    if (identical(e1, e2)) return true;
-    if (e1 == null || e2 == null) return false;
-    int length = e1.length;
-    if (length != e2.length) return false;
-    Map<_MapEntry, int> equalElementCounts = new HashMap();
-    for (K key in e1.keys) {
-      _MapEntry entry = new _MapEntry(this, key, e1[key]);
-      int count = equalElementCounts[entry];
-      if (count == null) count = 0;
-      equalElementCounts[entry] = count + 1;
-    }
-    for (K key in e2.keys) {
-      _MapEntry entry = new _MapEntry(this, key, e2[key]);
-      int count = equalElementCounts[entry];
-      if (count == null || count == 0) return false;
-      equalElementCounts[entry] = count - 1;
-    }
-    return true;
-  }
-
-  int hash(Map<K, V> map) {
-    int hash = 0;
-    for (K key in map.keys) {
-      int keyHash = _keyEquality.hash(key);
-      int valueHash = _valueEquality.hash(map[key]);
-      hash = (hash + 3 * keyHash + 7 * valueHash) & _HASH_MASK;
-    }
-    hash = (hash + (hash << 3)) & _HASH_MASK;
-    hash ^= (hash >> 11);
-    hash = (hash + (hash << 15)) & _HASH_MASK;
-    return hash;
-  }
-
-  bool isValidKey(Object o) => o is Map<K, V>;
-}
-
-/**
- * Combines several equalities into a single equality.
- *
- * Tries each equality in order, using [Equality.isValidKey], and returns
- * the result of the first equality that applies to the argument or arguments.
- *
- * For `equals`, the first equality that matches the first argument is used,
- * and if the second argument of `equals` is not valid for that equality,
- * it returns false.
- *
- * Because the equalities are tried in order, they should generally work on
- * disjoint types. Otherwise the multi-equality may give inconsistent results
- * for `equals(e1, e2)` and `equals(e2, e1)`. This can happen if one equality
- * considers only `e1` a valid key, and not `e2`, but an equality which is
- * checked later, allows both.
- */
-class MultiEquality<E> implements Equality<E> {
-  final Iterable<Equality<E>> _equalities;
-
-  const MultiEquality(Iterable<Equality<E>> equalities)
-      : _equalities = equalities;
-
-  bool equals(E e1, E e2) {
-    for (Equality<E> eq in _equalities) {
-      if (eq.isValidKey(e1)) return eq.isValidKey(e2) && eq.equals(e1, e2);
-    }
-    return false;
-  }
-
-  int hash(E e) {
-    for (Equality<E> eq in _equalities) {
-      if (eq.isValidKey(e)) return eq.hash(e);
-    }
-    return -1;
-  }
-
-  bool isValidKey(Object o) {
-    for (Equality<E> eq in _equalities) {
-      if (eq.isValidKey(o)) return true;
-    }
-    return false;
-  }
-}
-
-/**
- * Deep equality on collections.
- *
- * Recognizes lists, sets, iterables and maps and compares their elements using
- * deep equality as well.
- *
- * Non-iterable/map objects are compared using a configurable base equality.
- *
- * Works in one of two modes: ordered or unordered.
- *
- * In ordered mode, lists and iterables are required to have equal elements
- * in the same order. In unordered mode, the order of elements in iterables
- * and lists are not importan.
- *
- * A list is only equal to another list, likewise for sets and maps. All other
- * iterables are compared as iterables only.
- */
-class DeepCollectionEquality implements Equality {
-  final Equality _base;
-  final bool _unordered;
-  const DeepCollectionEquality([Equality base = const DefaultEquality()])
-      : _base = base, _unordered = false;
-
-  /**
-   * Creates a deep equality on collections where the order of lists and
-   * iterables are not considered important. That is, lists and iterables are
-   * treated as unordered iterables.
-   */
-  const DeepCollectionEquality.unordered(
-      [Equality base = const DefaultEquality()])
-      : _base = base, _unordered = true;
-
-  bool equals(e1, e2) {
-    if (e1 is Set) {
-      if (e2 is! Set) return false;
-      return new SetEquality(this).equals(e1, e2);
-    }
-    if (e1 is Map) {
-      if (e2 is! Map) return false;
-      return new MapEquality(keys: this, values: this).equals(e1, e2);
-    }
-    if (!_unordered) {
-      if (e1 is List) {
-        if (e2 is! List) return false;
-        return new ListEquality(this).equals(e1, e2);
-      }
-      if (e1 is Iterable) {
-        if (e2 is! Iterable) return false;
-        return new IterableEquality(this).equals(e1, e2);
-      }
-    } else if (e1 is Iterable) {
-      if (e2 is! Iterable) return false;
-      if (e1 is List != e2 is List) return false;
-      return new UnorderedIterableEquality(this).equals(e1, e2);
-    }
-    return _base.equals(e1, e2);
-  }
-
-  int hash(Object o) {
-    if (o is Set) return new SetEquality(this).hash(o);
-    if (o is Map) return new MapEquality(keys: this, values: this).hash(o);
-    if (!_unordered) {
-      if (o is List) return new ListEquality(this).hash(o);
-      if (o is Iterable) return new IterableEquality(this).hash(o);
-    } else if (o is Iterable) {
-      return new UnorderedIterableEquality(this).hash(o);
-    }
-    return _base.hash(o);
-  }
-
-  bool isValidKey(Object o) => o is Iterable || o is Map || _base.isValidKey(o);
-}
+export "package:collection/equality.dart";
diff --git a/pkg/collection_helpers/lib/typed_buffers.dart b/pkg/collection_helpers/lib/typed_buffers.dart
index 2f331e7..612e3df 100644
--- a/pkg/collection_helpers/lib/typed_buffers.dart
+++ b/pkg/collection_helpers/lib/typed_buffers.dart
@@ -2,234 +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.
 
-/**
- * Growable typed-data lists.
- *
- * These lists works just as a typed-data list, except that they are growable.
- * They use an underlying buffer, and when that buffer becomes too small, it
- * is replaced by a new buffer.
- *
- * That means that using the [TypedDataView.buffer] getter is not guaranteed
- * to return the same result each time it is used, and that the buffer may
- * be larger than what the list is using.
- */
+@deprecated
 library dart.collection_helpers.typed_buffers;
 
-import "dart:collection" show ListBase;
-import "dart:typed_data";
-
-abstract class _TypedDataBuffer<E> extends ListBase<E> {
-  static const int INITIAL_LENGTH = 8;
-
-  /// This is a Uint8List for Uint8Buffer. It's both a List<E> and a TypedData,
-  /// which we don't have a type for here.
-  var _buffer;
-  /// The length of the list being built.
-  int _length;
-
-  _TypedDataBuffer(List<E> buffer)
-      : this._buffer = buffer, this._length = buffer.length;
-
-  int get length => _length;
-  E operator[](int index) {
-    if (index >= length) throw new RangeError.range(index, 0, length - 1);
-    return _buffer[index];
-  }
-
-  void operator[]=(int index, E value) {
-    if (index >= length) throw new RangeError.range(index, 0, length - 1);
-    _buffer[index] = value;
-  }
-
-  void set length(int newLength) {
-    if (newLength < _length) {
-      E defaultValue = _defaultValue;
-      for (int i = newLength; i < _length; i++) {
-        _buffer[i] = defaultValue;
-      }
-    } else if (newLength > _buffer.length) {
-      List<E> newBuffer;
-      if (_buffer.length == 0) {
-        newBuffer = _createBuffer(newLength);
-      } else {
-        newBuffer = _createBiggerBuffer(newLength);
-      }
-      newBuffer.setRange(0, _length, _buffer);
-      _buffer = newBuffer;
-    }
-    _length = newLength;
-  }
-
-  void _add(E value) {
-    if (_length == _buffer.length) _grow();
-    _buffer[_length++] = value;
-  }
-
-  // We override the default implementation of `add` and `addAll` because
-  // they grow by setting the length in increments of one. We want to grow
-  // by doubling capacity in most cases.
-  void add(E value) { _add(value); }
-
-  void addAll(Iterable<E> values) {
-    for (E value in values) _add(value);
-  }
-
-  void insert(int index, E element) {
-    if (index < 0 || index > _length) {
-      throw new RangeError.range(index, 0, _length);
-    }
-    if (_length < _buffer.length) {
-      _buffer.setRange(index + 1, _length + 1, _buffer, index);
-      _buffer[index] = element;
-      _length++;
-      return;
-    }
-    List<E> newBuffer = _createBiggerBuffer(null);
-    newBuffer.setRange(0, index, _buffer);
-    newBuffer.setRange(index + 1, _length + 1, _buffer, index);
-    newBuffer[index] = element;
-    _length++;
-    _buffer = newBuffer;
-  }
-
-  /**
-   * Create a bigger buffer.
-   *
-   * This method determines how much bigger a bigger buffer should
-   * be. If [requiredLength] is not null, it will be at least that
-   * size. It will always have at least have double the capacity of
-   * the current buffer.
-   */
-  List<E> _createBiggerBuffer(int requiredLength) {
-    int newLength = _buffer.length * 2;
-    if (requiredLength != null && newLength < requiredLength) {
-      newLength = requiredLength;
-    } else if (newLength < INITIAL_LENGTH) {
-      newLength = INITIAL_LENGTH;
-    }
-    return _createBuffer(newLength);
-  }
-
-  void _grow() {
-    _buffer = _createBiggerBuffer(null)..setRange(0, _length, _buffer);
-  }
-
-  void setRange(int start, int end, Iterable<E> source, [int skipCount = 0]) {
-    if (end > _length) throw new RangeError.range(end, 0, _length);
-    if (source is _TypedDataBuffer<E>) {
-      _buffer.setRange(start, end, source._buffer, skipCount);
-    } else {
-      _buffer.setRange(start, end, source, skipCount);
-    }
-  }
-
-  // TypedData.
-
-  int get elementSizeInBytes => _buffer.elementSizeInBytes;
-
-  int get lengthInBytes => _length * _buffer.elementSizeInBytes;
-
-  int get offsetInBytes => _buffer.offsetInBytes;
-
-  /**
-    * Returns the underlying [ByteBuffer].
-    *
-    * The returned buffer may be replaced by operations that change the [length]
-    * of this list.
-    *
-    * The buffer may be larger than [lengthInBytes] bytes, but never smaller.
-    */
-  ByteBuffer get buffer => _buffer.buffer;
-
-  // Specialization for the specific type.
-
-  // Return zero for integers, 0.0 for floats, etc.
-  // Used to fill buffer when changing length.
-  E get _defaultValue;
-
-  // Create a new typed list to use as buffer.
-  List<E> _createBuffer(int size);
-}
-
-abstract class _IntBuffer extends _TypedDataBuffer<int> {
-  _IntBuffer(buffer): super(buffer);
-  int get _defaultValue => 0;
-}
-
-abstract class _FloatBuffer extends _TypedDataBuffer<double> {
-  _FloatBuffer(buffer): super(buffer);
-  double get _defaultValue => 0.0;
-}
-
-class Uint8Buffer extends _IntBuffer {
-  Uint8Buffer([int initialLength = 0]) : super(new Uint8List(initialLength));
-  Uint8List _createBuffer(int size) => new Uint8List(size);
-}
-
-class Int8Buffer extends _IntBuffer {
-  Int8Buffer([int initialLength = 0]) : super(new Int8List(initialLength));
-  Int8List _createBuffer(int size) => new Int8List(size);
-}
-
-class Uint8ClampedBuffer extends _IntBuffer {
-  Uint8ClampedBuffer([int initialLength = 0])
-      : super(new Uint8ClampedList(initialLength));
-  Uint8ClampedList _createBuffer(int size) => new Uint8ClampedList(size);
-}
-
-class Uint16Buffer extends _IntBuffer {
-  Uint16Buffer([int initialLength = 0]) : super(new Uint16List(initialLength));
-  Uint16List _createBuffer(int size) => new Uint16List(size);
-}
-
-class Int16Buffer extends _IntBuffer {
-  Int16Buffer([int initialLength = 0]) : super(new Int16List(initialLength));
-  Int16List _createBuffer(int size) => new Int16List(size);
-}
-
-class Uint32Buffer extends _IntBuffer {
-  Uint32Buffer([int initialLength = 0]) : super(new Uint32List(initialLength));
-  Uint32List _createBuffer(int size) => new Uint32List(size);
-}
-
-class Int32Buffer extends _IntBuffer {
-  Int32Buffer([int initialLength = 0]) : super(new Int32List(initialLength));
-  Int32List _createBuffer(int size) => new Int32List(size);
-}
-
-class Uint64Buffer extends _IntBuffer {
-  Uint64Buffer([int initialLength = 0]) : super(new Uint64List(initialLength));
-  Uint64List _createBuffer(int size) => new Uint64List(size);
-}
-
-class Int64Buffer extends _IntBuffer {
-  Int64Buffer([int initialLength = 0]) : super(new Int64List(initialLength));
-  Int64List _createBuffer(int size) => new Int64List(size);
-}
-
-class Float32Buffer extends _FloatBuffer {
-  Float32Buffer([int initialLength = 0])
-      : super(new Float32List(initialLength));
-  Float32List _createBuffer(int size) => new Float32List(size);
-}
-
-class Float64Buffer extends _FloatBuffer {
-  Float64Buffer([int initialLength = 0])
-      : super(new Float64List(initialLength));
-  Float64List _createBuffer(int size) => new Float64List(size);
-}
-
-class Int32x4Buffer extends _TypedDataBuffer<Int32x4> {
-  static Int32x4 _zero = new Int32x4(0, 0, 0, 0);
-  Int32x4Buffer([int initialLength = 0])
-      : super(new Int32x4List(initialLength));
-  Int32x4 get _defaultValue => _zero;
-  Int32x4List _createBuffer(int size) => new Int32x4List(size);
-}
-
-class Float32x4Buffer extends _TypedDataBuffer<Float32x4> {
-  Float32x4Buffer([int initialLength = 0])
-      : super(new Float32x4List(initialLength));
-  Float32x4 get _defaultValue => new Float32x4.zero();
-  Float32x4List _createBuffer(int size) => new Float32x4List(size);
-}
+export "package:typed_data/typed_buffers.dart";
diff --git a/pkg/collection_helpers/lib/wrappers.dart b/pkg/collection_helpers/lib/wrappers.dart
index 3576cc0..d408151 100644
--- a/pkg/collection_helpers/lib/wrappers.dart
+++ b/pkg/collection_helpers/lib/wrappers.dart
@@ -2,333 +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.
 
-/**
- * Delegating wrappers for [Iterable], [List], [Set], [Queue] and [Map].
- *
- * Also adds unmodifiable views for `Set` and `Map`, and a fixed length
- * view for `List`. The unmodifable list view from `dart:collection` is exported
- * as well, just for completeness.
- */
+@deprecated
 library dart.collection_helpers.wrappers;
 
-import "dart:collection";
-import "dart:math" show Random;
-
-export "dart:collection" show UnmodifiableListView;
-
-part "unmodifiable_wrappers.dart";
-
-/**
- * Creates an [Iterable] that delegates all operations to a base iterable.
- *
- * This class can be used hide non-`Iterable` methods of an iterable object,
- * or it can be extended to add extra functionality on top of an existing
- * iterable object.
- */
-class DelegatingIterable<E> implements Iterable<E> {
-  Iterable<E> _base;
-
-  /**
-   * Create a wrapper that forwards operations to [base].
-   */
-  DelegatingIterable(Iterable<E> base) : _base = base;
-
-  bool any(bool test(E element)) => _base.any(test);
-
-  bool contains(Object element) => _base.contains(element);
-
-  E elementAt(int index) => _base.elementAt(index);
-
-  bool every(bool test(E element)) => _base.every(test);
-
-  Iterable expand(Iterable f(E element)) => _base.expand(f);
-
-  E get first => _base.first;
-
-  E firstWhere(bool test(E element), {E orElse()}) =>
-      _base.firstWhere(test, orElse: orElse);
-
-  fold(initialValue, combine(previousValue, E element)) =>
-      _base.fold(initialValue, combine);
-
-  void forEach(void f(E element)) => _base.forEach(f);
-
-  bool get isEmpty => _base.isEmpty;
-
-  bool get isNotEmpty => _base.isNotEmpty;
-
-  Iterator<E> get iterator => _base.iterator;
-
-  String join([String separator = ""]) => _base.join(separator);
-
-  E get last => _base.last;
-
-  E lastWhere(bool test(E element), {E orElse()}) =>
-      _base.lastWhere(test, orElse: orElse);
-
-  int get length => _base.length;
-
-  Iterable map(f(E element)) => _base.map(f);
-
-  E reduce(E combine(E value, E element)) => _base.reduce(combine);
-
-  E get single => _base.single;
-
-  E singleWhere(bool test(E element)) => _base.singleWhere(test);
-
-  Iterable<E> skip(int n) => _base.skip(n);
-
-  Iterable<E> skipWhile(bool test(E value)) => _base.skipWhile(test);
-
-  Iterable<E> take(int n) => _base.take(n);
-
-  Iterable<E> takeWhile(bool test(E value)) => _base.takeWhile(test);
-
-  List<E> toList({bool growable: true}) => _base.toList(growable: growable);
-
-  Set<E> toSet() => _base.toSet();
-
-  Iterable<E> where(bool test(E element)) => _base.where(test);
-}
-
-
-/**
- * Creates a [List] that delegates all operations to a base list.
- *
- * This class can be used hide non-`List` methods of a list object,
- * or it can be extended to add extra functionality on top of an existing
- * list object.
- */
-class DelegatingList<E> extends DelegatingIterable<E> implements List<E> {
-  DelegatingList(List<E> base) : super(base);
-
-  List<E> get _listBase => _base;
-
-  E operator [](int index) => _listBase[index];
-
-  void operator []=(int index, E value) {
-    _listBase[index] = value;
-  }
-
-  void add(E value) {
-    _listBase.add(value);
-  }
-
-  void addAll(Iterable<E> iterable) {
-    _listBase.addAll(iterable);
-  }
-
-  Map<int, E> asMap() => _listBase.asMap();
-
-  void clear() {
-    _listBase.clear();
-  }
-
-  void fillRange(int start, int end, [E fillValue]) {
-    _listBase.fillRange(start, end, fillValue);
-  }
-
-  Iterable<E> getRange(int start, int end) => _listBase.getRange(start, end);
-
-  int indexOf(E element, [int start = 0]) => _listBase.indexOf(element, start);
-
-  void insert(int index, E element) {
-    _listBase.insert(index, element);
-  }
-
-  void insertAll(int index, Iterable<E> iterable) {
-    _listBase.insertAll(index, iterable);
-  }
-
-  int lastIndexOf(E element, [int start]) =>
-      _listBase.lastIndexOf(element, start);
-
-  void set length(int newLength) {
-    _listBase.length = newLength;
-  }
-
-  bool remove(Object value) => _listBase.remove(value);
-
-  E removeAt(int index) => _listBase.removeAt(index);
-
-  E removeLast() => _listBase.removeLast();
-
-  void removeRange(int start, int end) {
-    _listBase.removeRange(start, end);
-  }
-
-  void removeWhere(bool test(E element)) {
-    _listBase.removeWhere(test);
-  }
-
-  void replaceRange(int start, int end, Iterable<E> iterable) {
-    _listBase.replaceRange(start, end, iterable);
-  }
-
-  void retainWhere(bool test(E element)) {
-    _listBase.retainWhere(test);
-  }
-
-  Iterable<E> get reversed => _listBase.reversed;
-
-  void setAll(int index, Iterable<E> iterable) {
-    _listBase.setAll(index, iterable);
-  }
-
-  void setRange(int start, int end, Iterable<E> iterable, [int skipCount = 0]) {
-    _listBase.setRange(start, end, iterable, skipCount);
-  }
-
-  void shuffle([Random random]) {
-    _listBase.shuffle(random);
-  }
-
-  void sort([int compare(E a, E b)]) {
-    _listBase.sort(compare);
-  }
-
-  List<E> sublist(int start, [int end]) => _listBase.sublist(start, end);
-}
-
-
-/**
- * Creates a [Set] that delegates all operations to a base set.
- *
- * This class can be used hide non-`Set` methods of a set object,
- * or it can be extended to add extra functionality on top of an existing
- * set object.
- */
-class DelegatingSet<E> extends DelegatingIterable<E> implements Set<E> {
-  DelegatingSet(Set<E> base) : super(base);
-
-  Set<E> get _setBase => _base;
-
-  bool add(E value) => _setBase.add(value);
-
-  void addAll(Iterable<E> elements) {
-    _setBase.addAll(elements);
-  }
-
-  void clear() {
-    _setBase.clear();
-  }
-
-  bool containsAll(Iterable<Object> other) => _setBase.containsAll(other);
-
-  Set<E> difference(Set<E> other) => _setBase.difference(other);
-
-  Set<E> intersection(Set<Object> other) => _setBase.intersection(other);
-
-  E lookup(E element) => _setBase.lookup(element);
-
-  bool remove(Object value) => _setBase.remove(value);
-
-  void removeAll(Iterable<Object> elements) {
-    _setBase.removeAll(elements);
-  }
-
-  void removeWhere(bool test(E element)) {
-    _setBase.removeWhere(test);
-  }
-
-  void retainAll(Iterable<Object> elements) {
-    _setBase.retainAll(elements);
-  }
-
-  void retainWhere(bool test(E element)) {
-    _setBase.retainWhere(test);
-  }
-
-  Set<E> union(Set<E> other) => _setBase.union(other);
-}
-
-/**
- * Creates a [Queue] that delegates all operations to a base queue.
- *
- * This class can be used hide non-`Queue` methods of a queue object,
- * or it can be extended to add extra functionality on top of an existing
- * queue object.
- */
-class DelegatingQueue<E> extends DelegatingIterable<E> implements Queue<E> {
-  DelegatingQueue(Queue<E> queue) : super(queue);
-
-  Queue<E> get _baseQueue => _base;
-
-  void add(E value) {
-    _baseQueue.add(value);
-  }
-
-  void addAll(Iterable<E> iterable) {
-    _baseQueue.addAll(iterable);
-  }
-
-  void addFirst(E value) {
-    _baseQueue.addFirst(value);
-  }
-
-  void addLast(E value) {
-    _baseQueue.addLast(value);
-  }
-
-  void clear() {
-    _baseQueue.clear();
-  }
-
-  bool remove(Object object) => _baseQueue.remove(object);
-
-  void removeWhere(bool test(E element)) { _baseQueue.removeWhere(test); }
-
-  void retainWhere(bool test(E element)) { _baseQueue.retainWhere(test); }
-
-  E removeFirst() => _baseQueue.removeFirst();
-
-  E removeLast() => _baseQueue.removeLast();
-}
-
-/**
- * Creates a [Map] that delegates all operations to a base map.
- *
- * This class can be used hide non-`Map` methods of an object that extends
- * `Map`, or it can be extended to add extra functionality on top of an existing
- * map object.
- */
-class DelegatingMap<K, V> implements Map<K, V> {
-  Map<K, V> _base;
-  DelegatingMap(Map<K, V> base) : _base = base;
-
-  V operator [](Object key) => _base[key];
-
-  void operator []=(K key, V value) {
-    _base[key] = value;
-  }
-
-  void addAll(Map<K, V> other) {
-    _base.addAll(other);
-  }
-
-  void clear() {
-    _base.clear();
-  }
-
-  bool containsKey(Object key) => _base.containsKey(key);
-
-  bool containsValue(Object value) => _base.containsValue(value);
-
-  void forEach(void f(K key, V value)) {
-    _base.forEach(f);
-  }
-
-  bool get isEmpty => _base.isEmpty;
-
-  bool get isNotEmpty => _base.isNotEmpty;
-
-  Iterable<K> get keys => _base.keys;
-
-  int get length => _base.length;
-
-  V putIfAbsent(K key, V ifAbsent()) => _base.putIfAbsent(key, ifAbsent);
-
-  V remove(Object key) => _base.remove(key);
-
-  Iterable<V> get values => _base.values;
-}
+export "package:collection/wrappers.dart";
diff --git a/pkg/collection_helpers/pubspec.yaml b/pkg/collection_helpers/pubspec.yaml
index 482ca1c..0002f71 100644
--- a/pkg/collection_helpers/pubspec.yaml
+++ b/pkg/collection_helpers/pubspec.yaml
@@ -1,9 +1,10 @@
 name: collection_helpers
-version: 0.9.1
-author: "Dart Team <misc@dartlang.org>"
-description: Utility functions and classes for working with collections.
+version: 0.9.2
+author: Dart Team <misc@dartlang.org>
+description: Discontinued. Use package:collection or package:typed_data.
 homepage: http://www.dartlang.org
-dev_dependencies:
-  unittest: ">=0.9.0 <0.10.0"
+dependencies:
+  collection: "0.9.0"
+  typed_data: "0.9.0"
 environment:
   sdk: ">=1.0.0 <2.0.0"
diff --git a/pkg/custom_element/lib/custom-elements.debug.js b/pkg/custom_element/lib/custom-elements.debug.js
index fff3b8a..3860932a 100644
--- a/pkg/custom_element/lib/custom-elements.debug.js
+++ b/pkg/custom_element/lib/custom-elements.debug.js
@@ -1151,6 +1151,11 @@
       // getPrototypeOf(Element), we cannot do so when
       // we use mixin, so we install a magic reference
       customMixin(element, definition.prototype, definition.native);
+
+      // Dart note: make sure we pick up the right constructor.
+      // dart2js depends on this for dart:mirrors caching to work.
+      // See tests/html/custom/mirrors_test.dart
+      element.constructor = definition.prototype.constructor;
       element.__proto__ = definition.prototype;
     }
   }
diff --git a/pkg/custom_element/lib/custom-elements.min.js b/pkg/custom_element/lib/custom-elements.min.js
index cb5746f..713ae84 100644
--- a/pkg/custom_element/lib/custom-elements.min.js
+++ b/pkg/custom_element/lib/custom-elements.min.js
@@ -25,4 +25,4 @@
 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-"undefined"==typeof WeakMap&&!function(){var a=Object.defineProperty,b=Date.now()%1e9,c=function(){this.name="__st"+(1e9*Math.random()>>>0)+(b++ +"__")};c.prototype={set:function(b,c){var d=b[this.name];d&&d[0]===b?d[1]=c:a(b,this.name,{value:[b,c],writable:!0})},get:function(a){var b;return(b=a[this.name])&&b[0]===a?b[1]:void 0},"delete":function(a){this.set(a,void 0)}},window.WeakMap=c}(),function(a){function b(a){u.push(a),t||(t=!0,q(d))}function c(a){return window.ShadowDOMPolyfill&&window.ShadowDOMPolyfill.wrapIfNeeded(a)||a}function d(){t=!1;var a=u;u=[],a.sort(function(a,b){return a.uid_-b.uid_});var b=!1;a.forEach(function(a){var c=a.takeRecords();e(a),c.length&&(a.callback_(c,a),b=!0)}),b&&d()}function e(a){a.nodes_.forEach(function(b){var c=p.get(b);c&&c.forEach(function(b){b.observer===a&&b.removeTransientObservers()})})}function f(a,b){for(var c=a;c;c=c.parentNode){var d=p.get(c);if(d)for(var e=0;e<d.length;e++){var f=d[e],g=f.options;if(c===a||g.subtree){var h=b(g);h&&f.enqueue(h)}}}}function g(a){this.callback_=a,this.nodes_=[],this.records_=[],this.uid_=++v}function h(a,b){this.type=a,this.target=b,this.addedNodes=[],this.removedNodes=[],this.previousSibling=null,this.nextSibling=null,this.attributeName=null,this.attributeNamespace=null,this.oldValue=null}function i(a){var b=new h(a.type,a.target);return b.addedNodes=a.addedNodes.slice(),b.removedNodes=a.removedNodes.slice(),b.previousSibling=a.previousSibling,b.nextSibling=a.nextSibling,b.attributeName=a.attributeName,b.attributeNamespace=a.attributeNamespace,b.oldValue=a.oldValue,b}function j(a,b){return w=new h(a,b)}function k(a){return x?x:(x=i(w),x.oldValue=a,x)}function l(){w=x=void 0}function m(a){return a===x||a===w}function n(a,b){return a===b?a:x&&m(a)?x:null}function o(a,b,c){this.observer=a,this.target=b,this.options=c,this.transientObservedNodes=[]}var p=new WeakMap,q=window.msSetImmediate;if(!q){var r=[],s=String(Math.random());window.addEventListener("message",function(a){if(a.data===s){var b=r;r=[],b.forEach(function(a){a()})}}),q=function(a){r.push(a),window.postMessage(s,"*")}}var t=!1,u=[],v=0;g.prototype={observe:function(a,b){if(a=c(a),!b.childList&&!b.attributes&&!b.characterData||b.attributeOldValue&&!b.attributes||b.attributeFilter&&b.attributeFilter.length&&!b.attributes||b.characterDataOldValue&&!b.characterData)throw new SyntaxError;var d=p.get(a);d||p.set(a,d=[]);for(var e,f=0;f<d.length;f++)if(d[f].observer===this){e=d[f],e.removeListeners(),e.options=b;break}e||(e=new o(this,a,b),d.push(e),this.nodes_.push(a)),e.addListeners()},disconnect:function(){this.nodes_.forEach(function(a){for(var b=p.get(a),c=0;c<b.length;c++){var d=b[c];if(d.observer===this){d.removeListeners(),b.splice(c,1);break}}},this),this.records_=[]},takeRecords:function(){var a=this.records_;return this.records_=[],a}};var w,x;o.prototype={enqueue:function(a){var c=this.observer.records_,d=c.length;if(c.length>0){var e=c[d-1],f=n(e,a);if(f)return c[d-1]=f,void 0}else b(this.observer);c[d]=a},addListeners:function(){this.addListeners_(this.target)},addListeners_:function(a){var b=this.options;b.attributes&&a.addEventListener("DOMAttrModified",this,!0),b.characterData&&a.addEventListener("DOMCharacterDataModified",this,!0),b.childList&&a.addEventListener("DOMNodeInserted",this,!0),(b.childList||b.subtree)&&a.addEventListener("DOMNodeRemoved",this,!0)},removeListeners:function(){this.removeListeners_(this.target)},removeListeners_:function(a){var b=this.options;b.attributes&&a.removeEventListener("DOMAttrModified",this,!0),b.characterData&&a.removeEventListener("DOMCharacterDataModified",this,!0),b.childList&&a.removeEventListener("DOMNodeInserted",this,!0),(b.childList||b.subtree)&&a.removeEventListener("DOMNodeRemoved",this,!0)},addTransientObserver:function(a){if(a!==this.target){this.addListeners_(a),this.transientObservedNodes.push(a);var b=p.get(a);b||p.set(a,b=[]),b.push(this)}},removeTransientObservers:function(){var a=this.transientObservedNodes;this.transientObservedNodes=[],a.forEach(function(a){this.removeListeners_(a);for(var b=p.get(a),c=0;c<b.length;c++)if(b[c]===this){b.splice(c,1);break}},this)},handleEvent:function(a){switch(a.stopImmediatePropagation(),a.type){case"DOMAttrModified":var b=a.attrName,c=a.relatedNode.namespaceURI,d=a.target,e=new j("attributes",d);e.attributeName=b,e.attributeNamespace=c;var g=a.attrChange===MutationEvent.ADDITION?null:a.prevValue;f(d,function(a){return!a.attributes||a.attributeFilter&&a.attributeFilter.length&&-1===a.attributeFilter.indexOf(b)&&-1===a.attributeFilter.indexOf(c)?void 0:a.attributeOldValue?k(g):e});break;case"DOMCharacterDataModified":var d=a.target,e=j("characterData",d),g=a.prevValue;f(d,function(a){return a.characterData?a.characterDataOldValue?k(g):e:void 0});break;case"DOMNodeRemoved":this.addTransientObserver(a.target);case"DOMNodeInserted":var h,i,d=a.relatedNode,m=a.target;"DOMNodeInserted"===a.type?(h=[m],i=[]):(h=[],i=[m]);var n=m.previousSibling,o=m.nextSibling,e=j("childList",d);e.addedNodes=h,e.removedNodes=i,e.previousSibling=n,e.nextSibling=o,f(d,function(a){return a.childList?e:void 0})}l()}},a.JsMutationObserver=g,!a.MutationObserver&&a.WebKitMutationObserver&&(a.MutationObserver=a.WebKitMutationObserver),a.MutationObserver||(a.MutationObserver=g)}(this),window.CustomElements=window.CustomElements||{flags:{}},function(a){function b(a,c,d){var e=a.firstElementChild;if(!e)for(e=a.firstChild;e&&e.nodeType!==Node.ELEMENT_NODE;)e=e.nextSibling;for(;e;)c(e,d)!==!0&&b(e,c,d),e=e.nextElementSibling;return null}function c(a,b){for(var c=a.shadowRoot;c;)d(c,b),c=c.olderShadowRoot}function d(a,d){b(a,function(a){return d(a)?!0:(c(a,d),void 0)}),c(a,d)}function e(a){return h(a)?(i(a),!0):(l(a),void 0)}function f(a){d(a,function(a){return e(a)?!0:void 0})}function g(a){return e(a)||f(a)}function h(b){if(!b.__upgraded__&&b.nodeType===Node.ELEMENT_NODE){var c=b.getAttribute("is")||b.localName,d=a.registry[c];if(d)return y.dom&&console.group("upgrade:",b.localName),a.upgrade(b),y.dom&&console.groupEnd(),!0}}function i(a){l(a),q(a)&&d(a,function(a){l(a)})}function j(a){if(B.push(a),!A){A=!0;var b=window.Platform&&window.Platform.endOfMicrotask||setTimeout;b(k)}}function k(){A=!1;for(var a,b=B,c=0,d=b.length;d>c&&(a=b[c]);c++)a();B=[]}function l(a){z?j(function(){m(a)}):m(a)}function m(a){(a.enteredViewCallback||a.__upgraded__&&y.dom)&&(y.dom&&console.group("inserted:",a.localName),q(a)&&(a.__inserted=(a.__inserted||0)+1,a.__inserted<1&&(a.__inserted=1),a.__inserted>1?y.dom&&console.warn("inserted:",a.localName,"insert/remove count:",a.__inserted):a.enteredViewCallback&&(y.dom&&console.log("inserted:",a.localName),a.enteredViewCallback())),y.dom&&console.groupEnd())}function n(a){o(a),d(a,function(a){o(a)})}function o(a){z?j(function(){p(a)}):p(a)}function p(a){(a.leftViewCallback||a.__upgraded__&&y.dom)&&(y.dom&&console.log("removed:",a.localName),q(a)||(a.__inserted=(a.__inserted||0)-1,a.__inserted>0&&(a.__inserted=0),a.__inserted<0?y.dom&&console.warn("removed:",a.localName,"insert/remove count:",a.__inserted):a.leftViewCallback&&a.leftViewCallback()))}function q(a){for(var b=a,c=window.ShadowDOMPolyfill&&window.ShadowDOMPolyfill.wrapIfNeeded(document)||document;b;){if(b==c)return!0;b=b.parentNode||b.host}}function r(a){if(a.shadowRoot&&!a.shadowRoot.__watched){y.dom&&console.log("watching shadow-root for: ",a.localName);for(var b=a.shadowRoot;b;)s(b),b=b.olderShadowRoot}}function s(a){a.__watched||(v(a),a.__watched=!0)}function t(a){if(y.dom){var b=a[0];if(b&&"childList"===b.type&&b.addedNodes&&b.addedNodes){for(var c=b.addedNodes[0];c&&c!==document&&!c.host;)c=c.parentNode;var d=c&&(c.URL||c._URL||c.host&&c.host.localName)||"";d=d.split("/?").shift().split("/").pop()}console.group("mutations (%d) [%s]",a.length,d||"")}a.forEach(function(a){"childList"===a.type&&(D(a.addedNodes,function(a){a.localName&&g(a)}),D(a.removedNodes,function(a){a.localName&&n(a)}))}),y.dom&&console.groupEnd()}function u(){t(C.takeRecords()),k()}function v(a){C.observe(a,{childList:!0,subtree:!0})}function w(a){v(a)}function x(a){y.dom&&console.group("upgradeDocument: ",(a.URL||a._URL||"").split("/").pop()),g(a),y.dom&&console.groupEnd()}var y=window.logFlags||{},z=!window.MutationObserver||window.MutationObserver===window.JsMutationObserver;a.hasPolyfillMutations=z;var A=!1,B=[],C=new MutationObserver(t),D=Array.prototype.forEach.call.bind(Array.prototype.forEach);a.watchShadow=r,a.upgradeAll=g,a.upgradeSubtree=f,a.observeDocument=w,a.upgradeDocument=x,a.takeRecords=u}(window.CustomElements),function(a){function b(b,f){var g=f||{};if(!b)throw new Error("document.register: first argument `name` must not be empty");if(b.indexOf("-")<0)throw new Error("document.register: first argument ('name') must contain a dash ('-'). Argument provided was '"+String(b)+"'.");if(m(b))throw new Error("DuplicateDefinitionError: a type with name '"+String(b)+"' is already registered");if(!g.prototype)throw new Error("Options missing required prototype property");return g.name=b.toLowerCase(),g.lifecycle=g.lifecycle||{},g.ancestry=c(g.extends),d(g),e(g),k(g.prototype),n(g.name,g),g.ctor=o(g),g.ctor.prototype=g.prototype,g.prototype.constructor=g.ctor,(a.ready||a.performedInitialDocumentUpgrade)&&a.upgradeAll(document),g.ctor}function c(a){var b=m(a);return b?c(b.extends).concat([b]):[]}function d(a){for(var b,c=a.extends,d=0;b=a.ancestry[d];d++)c=b.is&&b.tag;a.tag=c||a.name,c&&(a.is=a.name)}function e(a){if(!Object.__proto__){var b=HTMLElement.prototype;if(a.is){var c=document.createElement(a.tag);b=Object.getPrototypeOf(c)}for(var d,e=a.prototype;e&&e!==b;){var d=Object.getPrototypeOf(e);e.__proto__=d,e=d}}a.native=b}function f(a){return g(x(a.tag),a)}function g(b,c){return c.is&&b.setAttribute("is",c.is),b.removeAttribute("unresolved"),h(b,c),b.__upgraded__=!0,a.upgradeSubtree(b),j(b),b}function h(a,b){Object.__proto__?a.__proto__=b.prototype:(i(a,b.prototype,b.native),a.__proto__=b.prototype)}function i(a,b,c){for(var d={},e=b;e!==c&&e!==HTMLUnknownElement.prototype;){for(var f,g=Object.getOwnPropertyNames(e),h=0;f=g[h];h++)d[f]||(Object.defineProperty(a,f,Object.getOwnPropertyDescriptor(e,f)),d[f]=1);e=Object.getPrototypeOf(e)}}function j(a){a.createdCallback&&a.createdCallback()}function k(a){if(!a.setAttribute._polyfilled){var b=a.setAttribute;a.setAttribute=function(a,c){l.call(this,a,c,b)};var c=a.removeAttribute;a.removeAttribute=function(a){l.call(this,a,null,c)},a.setAttribute._polyfilled=!0}}function l(a,b,c){var d=this.getAttribute(a);c.apply(this,arguments);var e=this.getAttribute(a);this.attributeChangedCallback&&e!==d&&this.attributeChangedCallback(a,d,e)}function m(a){return a?w[a.toLowerCase()]:void 0}function n(a,b){if(w[a])throw new Error("a type with that name is already registered.");w[a]=b}function o(a){return function(){return f(a)}}function p(a,b){var c=m(b||a);if(c){if(a==c.tag&&b==c.is)return new c.ctor;if(!b&&!c.is)return new c.ctor}if(b){var d=p(a);return d.setAttribute("is",b),d}var d=x(a);return a.indexOf("-")>=0&&h(d,HTMLElement),d}function q(a){if(!a.__upgraded__&&a.nodeType===Node.ELEMENT_NODE){var b=a.getAttribute("is"),c=w[b||a.localName];if(c){if(b&&c.tag==a.localName)return g(a,c);if(!b&&!c.extends)return g(a,c)}}}function r(b){var c=y.call(this,b);return a.upgradeAll(c),c}a||(a=window.CustomElements={flags:{}});var s=a.flags,t=Boolean(document.register),u=!s.register&&t;if(u){var v=function(){};a.registry={},a.upgradeElement=v,a.watchShadow=v,a.upgrade=v,a.upgradeAll=v,a.upgradeSubtree=v,a.observeDocument=v,a.upgradeDocument=v,a.takeRecords=v}else{var w={},x=document.createElement.bind(document),y=Node.prototype.cloneNode;document.register=b,document.createElement=p,Node.prototype.cloneNode=r,a.registry=w,a.upgrade=q}a.hasNative=t,a.useNative=u}(window.CustomElements),function(){function a(a){return"link"===a.localName&&a.getAttribute("rel")===b}var b=window.HTMLImports?HTMLImports.IMPORT_LINK_TYPE:"none",c={selectors:["link[rel="+b+"]"],map:{link:"parseLink"},parse:function(a){if(!a.__parsed){a.__parsed=!0;var b=a.querySelectorAll(c.selectors);d(b,function(a){c[c.map[a.localName]](a)}),CustomElements.upgradeDocument(a),CustomElements.observeDocument(a)}},parseLink:function(b){a(b)&&this.parseImport(b)},parseImport:function(a){a.content&&c.parse(a.content)}},d=Array.prototype.forEach.call.bind(Array.prototype.forEach);CustomElements.parser=c}(),function(a){function b(){CustomElements.parser.parse(document),CustomElements.upgradeDocument(document),CustomElements.performedInitialDocumentUpgrade=!0;var a=window.Platform&&Platform.endOfMicrotask?Platform.endOfMicrotask:setTimeout;a(function(){CustomElements.ready=!0,CustomElements.readyTime=Date.now(),window.HTMLImports&&(CustomElements.elapsed=CustomElements.readyTime-HTMLImports.readyTime),document.body.dispatchEvent(new CustomEvent("WebComponentsReady",{bubbles:!0}))})}if("function"!=typeof window.CustomEvent&&(window.CustomEvent=function(a){var b=document.createEvent("HTMLEvents");return b.initEvent(a,!0,!0),b}),"complete"===document.readyState||a.flags.eager)b();else if("interactive"!==document.readyState||window.attachEvent||window.HTMLImports&&!window.HTMLImports.ready){var c=window.HTMLImports?"HTMLImportsLoaded":"loading"==document.readyState?"DOMContentLoaded":"load";window.addEventListener(c,b)}else b()}(window.CustomElements),function(){if(HTMLElement.prototype.createShadowRoot){var a=HTMLElement.prototype.createShadowRoot;HTMLElement.prototype.createShadowRoot=function(){var b=a.call(this);return b.host=this,CustomElements.watchShadow(this),b}}if(window.ShadowDOMPolyfill){var b=["upgradeAll","upgradeSubtree","observeDocument","upgradeDocument"],c={};b.forEach(function(a){c[a]=CustomElements[a]}),b.forEach(function(a){CustomElements[a]=function(b){return c[a](window.ShadowDOMPolyfill.wrapIfNeeded(b))}})}if(window.CustomElements&&!CustomElements.useNative){var d=Document.prototype.importNode;Document.prototype.importNode=function(a,b){var c=d.call(this,a,b);return CustomElements.upgradeAll(c),c}}}();
\ No newline at end of file
+"undefined"==typeof WeakMap&&!function(){var a=Object.defineProperty,b=Date.now()%1e9,c=function(){this.name="__st"+(1e9*Math.random()>>>0)+(b++ +"__")};c.prototype={set:function(b,c){var d=b[this.name];d&&d[0]===b?d[1]=c:a(b,this.name,{value:[b,c],writable:!0})},get:function(a){var b;return(b=a[this.name])&&b[0]===a?b[1]:void 0},"delete":function(a){this.set(a,void 0)}},window.WeakMap=c}(),function(a){function b(a){u.push(a),t||(t=!0,q(d))}function c(a){return window.ShadowDOMPolyfill&&window.ShadowDOMPolyfill.wrapIfNeeded(a)||a}function d(){t=!1;var a=u;u=[],a.sort(function(a,b){return a.uid_-b.uid_});var b=!1;a.forEach(function(a){var c=a.takeRecords();e(a),c.length&&(a.callback_(c,a),b=!0)}),b&&d()}function e(a){a.nodes_.forEach(function(b){var c=p.get(b);c&&c.forEach(function(b){b.observer===a&&b.removeTransientObservers()})})}function f(a,b){for(var c=a;c;c=c.parentNode){var d=p.get(c);if(d)for(var e=0;e<d.length;e++){var f=d[e],g=f.options;if(c===a||g.subtree){var h=b(g);h&&f.enqueue(h)}}}}function g(a){this.callback_=a,this.nodes_=[],this.records_=[],this.uid_=++v}function h(a,b){this.type=a,this.target=b,this.addedNodes=[],this.removedNodes=[],this.previousSibling=null,this.nextSibling=null,this.attributeName=null,this.attributeNamespace=null,this.oldValue=null}function i(a){var b=new h(a.type,a.target);return b.addedNodes=a.addedNodes.slice(),b.removedNodes=a.removedNodes.slice(),b.previousSibling=a.previousSibling,b.nextSibling=a.nextSibling,b.attributeName=a.attributeName,b.attributeNamespace=a.attributeNamespace,b.oldValue=a.oldValue,b}function j(a,b){return w=new h(a,b)}function k(a){return x?x:(x=i(w),x.oldValue=a,x)}function l(){w=x=void 0}function m(a){return a===x||a===w}function n(a,b){return a===b?a:x&&m(a)?x:null}function o(a,b,c){this.observer=a,this.target=b,this.options=c,this.transientObservedNodes=[]}var p=new WeakMap,q=window.msSetImmediate;if(!q){var r=[],s=String(Math.random());window.addEventListener("message",function(a){if(a.data===s){var b=r;r=[],b.forEach(function(a){a()})}}),q=function(a){r.push(a),window.postMessage(s,"*")}}var t=!1,u=[],v=0;g.prototype={observe:function(a,b){if(a=c(a),!b.childList&&!b.attributes&&!b.characterData||b.attributeOldValue&&!b.attributes||b.attributeFilter&&b.attributeFilter.length&&!b.attributes||b.characterDataOldValue&&!b.characterData)throw new SyntaxError;var d=p.get(a);d||p.set(a,d=[]);for(var e,f=0;f<d.length;f++)if(d[f].observer===this){e=d[f],e.removeListeners(),e.options=b;break}e||(e=new o(this,a,b),d.push(e),this.nodes_.push(a)),e.addListeners()},disconnect:function(){this.nodes_.forEach(function(a){for(var b=p.get(a),c=0;c<b.length;c++){var d=b[c];if(d.observer===this){d.removeListeners(),b.splice(c,1);break}}},this),this.records_=[]},takeRecords:function(){var a=this.records_;return this.records_=[],a}};var w,x;o.prototype={enqueue:function(a){var c=this.observer.records_,d=c.length;if(c.length>0){var e=c[d-1],f=n(e,a);if(f)return c[d-1]=f,void 0}else b(this.observer);c[d]=a},addListeners:function(){this.addListeners_(this.target)},addListeners_:function(a){var b=this.options;b.attributes&&a.addEventListener("DOMAttrModified",this,!0),b.characterData&&a.addEventListener("DOMCharacterDataModified",this,!0),b.childList&&a.addEventListener("DOMNodeInserted",this,!0),(b.childList||b.subtree)&&a.addEventListener("DOMNodeRemoved",this,!0)},removeListeners:function(){this.removeListeners_(this.target)},removeListeners_:function(a){var b=this.options;b.attributes&&a.removeEventListener("DOMAttrModified",this,!0),b.characterData&&a.removeEventListener("DOMCharacterDataModified",this,!0),b.childList&&a.removeEventListener("DOMNodeInserted",this,!0),(b.childList||b.subtree)&&a.removeEventListener("DOMNodeRemoved",this,!0)},addTransientObserver:function(a){if(a!==this.target){this.addListeners_(a),this.transientObservedNodes.push(a);var b=p.get(a);b||p.set(a,b=[]),b.push(this)}},removeTransientObservers:function(){var a=this.transientObservedNodes;this.transientObservedNodes=[],a.forEach(function(a){this.removeListeners_(a);for(var b=p.get(a),c=0;c<b.length;c++)if(b[c]===this){b.splice(c,1);break}},this)},handleEvent:function(a){switch(a.stopImmediatePropagation(),a.type){case"DOMAttrModified":var b=a.attrName,c=a.relatedNode.namespaceURI,d=a.target,e=new j("attributes",d);e.attributeName=b,e.attributeNamespace=c;var g=a.attrChange===MutationEvent.ADDITION?null:a.prevValue;f(d,function(a){return!a.attributes||a.attributeFilter&&a.attributeFilter.length&&-1===a.attributeFilter.indexOf(b)&&-1===a.attributeFilter.indexOf(c)?void 0:a.attributeOldValue?k(g):e});break;case"DOMCharacterDataModified":var d=a.target,e=j("characterData",d),g=a.prevValue;f(d,function(a){return a.characterData?a.characterDataOldValue?k(g):e:void 0});break;case"DOMNodeRemoved":this.addTransientObserver(a.target);case"DOMNodeInserted":var h,i,d=a.relatedNode,m=a.target;"DOMNodeInserted"===a.type?(h=[m],i=[]):(h=[],i=[m]);var n=m.previousSibling,o=m.nextSibling,e=j("childList",d);e.addedNodes=h,e.removedNodes=i,e.previousSibling=n,e.nextSibling=o,f(d,function(a){return a.childList?e:void 0})}l()}},a.JsMutationObserver=g,!a.MutationObserver&&a.WebKitMutationObserver&&(a.MutationObserver=a.WebKitMutationObserver),a.MutationObserver||(a.MutationObserver=g)}(this),window.CustomElements=window.CustomElements||{flags:{}},function(a){function b(a,c,d){var e=a.firstElementChild;if(!e)for(e=a.firstChild;e&&e.nodeType!==Node.ELEMENT_NODE;)e=e.nextSibling;for(;e;)c(e,d)!==!0&&b(e,c,d),e=e.nextElementSibling;return null}function c(a,b){for(var c=a.shadowRoot;c;)d(c,b),c=c.olderShadowRoot}function d(a,d){b(a,function(a){return d(a)?!0:(c(a,d),void 0)}),c(a,d)}function e(a){return h(a)?(i(a),!0):(l(a),void 0)}function f(a){d(a,function(a){return e(a)?!0:void 0})}function g(a){return e(a)||f(a)}function h(b){if(!b.__upgraded__&&b.nodeType===Node.ELEMENT_NODE){var c=b.getAttribute("is")||b.localName,d=a.registry[c];if(d)return y.dom&&console.group("upgrade:",b.localName),a.upgrade(b),y.dom&&console.groupEnd(),!0}}function i(a){l(a),q(a)&&d(a,function(a){l(a)})}function j(a){if(B.push(a),!A){A=!0;var b=window.Platform&&window.Platform.endOfMicrotask||setTimeout;b(k)}}function k(){A=!1;for(var a,b=B,c=0,d=b.length;d>c&&(a=b[c]);c++)a();B=[]}function l(a){z?j(function(){m(a)}):m(a)}function m(a){(a.enteredViewCallback||a.__upgraded__&&y.dom)&&(y.dom&&console.group("inserted:",a.localName),q(a)&&(a.__inserted=(a.__inserted||0)+1,a.__inserted<1&&(a.__inserted=1),a.__inserted>1?y.dom&&console.warn("inserted:",a.localName,"insert/remove count:",a.__inserted):a.enteredViewCallback&&(y.dom&&console.log("inserted:",a.localName),a.enteredViewCallback())),y.dom&&console.groupEnd())}function n(a){o(a),d(a,function(a){o(a)})}function o(a){z?j(function(){p(a)}):p(a)}function p(a){(a.leftViewCallback||a.__upgraded__&&y.dom)&&(y.dom&&console.log("removed:",a.localName),q(a)||(a.__inserted=(a.__inserted||0)-1,a.__inserted>0&&(a.__inserted=0),a.__inserted<0?y.dom&&console.warn("removed:",a.localName,"insert/remove count:",a.__inserted):a.leftViewCallback&&a.leftViewCallback()))}function q(a){for(var b=a,c=window.ShadowDOMPolyfill&&window.ShadowDOMPolyfill.wrapIfNeeded(document)||document;b;){if(b==c)return!0;b=b.parentNode||b.host}}function r(a){if(a.shadowRoot&&!a.shadowRoot.__watched){y.dom&&console.log("watching shadow-root for: ",a.localName);for(var b=a.shadowRoot;b;)s(b),b=b.olderShadowRoot}}function s(a){a.__watched||(v(a),a.__watched=!0)}function t(a){if(y.dom){var b=a[0];if(b&&"childList"===b.type&&b.addedNodes&&b.addedNodes){for(var c=b.addedNodes[0];c&&c!==document&&!c.host;)c=c.parentNode;var d=c&&(c.URL||c._URL||c.host&&c.host.localName)||"";d=d.split("/?").shift().split("/").pop()}console.group("mutations (%d) [%s]",a.length,d||"")}a.forEach(function(a){"childList"===a.type&&(D(a.addedNodes,function(a){a.localName&&g(a)}),D(a.removedNodes,function(a){a.localName&&n(a)}))}),y.dom&&console.groupEnd()}function u(){t(C.takeRecords()),k()}function v(a){C.observe(a,{childList:!0,subtree:!0})}function w(a){v(a)}function x(a){y.dom&&console.group("upgradeDocument: ",(a.URL||a._URL||"").split("/").pop()),g(a),y.dom&&console.groupEnd()}var y=window.logFlags||{},z=!window.MutationObserver||window.MutationObserver===window.JsMutationObserver;a.hasPolyfillMutations=z;var A=!1,B=[],C=new MutationObserver(t),D=Array.prototype.forEach.call.bind(Array.prototype.forEach);a.watchShadow=r,a.upgradeAll=g,a.upgradeSubtree=f,a.observeDocument=w,a.upgradeDocument=x,a.takeRecords=u}(window.CustomElements),function(a){function b(b,f){var g=f||{};if(!b)throw new Error("document.register: first argument `name` must not be empty");if(b.indexOf("-")<0)throw new Error("document.register: first argument ('name') must contain a dash ('-'). Argument provided was '"+String(b)+"'.");if(m(b))throw new Error("DuplicateDefinitionError: a type with name '"+String(b)+"' is already registered");if(!g.prototype)throw new Error("Options missing required prototype property");return g.name=b.toLowerCase(),g.lifecycle=g.lifecycle||{},g.ancestry=c(g.extends),d(g),e(g),k(g.prototype),n(g.name,g),g.ctor=o(g),g.ctor.prototype=g.prototype,g.prototype.constructor=g.ctor,(a.ready||a.performedInitialDocumentUpgrade)&&a.upgradeAll(document),g.ctor}function c(a){var b=m(a);return b?c(b.extends).concat([b]):[]}function d(a){for(var b,c=a.extends,d=0;b=a.ancestry[d];d++)c=b.is&&b.tag;a.tag=c||a.name,c&&(a.is=a.name)}function e(a){if(!Object.__proto__){var b=HTMLElement.prototype;if(a.is){var c=document.createElement(a.tag);b=Object.getPrototypeOf(c)}for(var d,e=a.prototype;e&&e!==b;){var d=Object.getPrototypeOf(e);e.__proto__=d,e=d}}a.native=b}function f(a){return g(x(a.tag),a)}function g(b,c){return c.is&&b.setAttribute("is",c.is),b.removeAttribute("unresolved"),h(b,c),b.__upgraded__=!0,a.upgradeSubtree(b),j(b),b}function h(a,b){Object.__proto__?a.__proto__=b.prototype:(i(a,b.prototype,b.native),a.constructor=b.prototype.constructor,a.__proto__=b.prototype)}function i(a,b,c){for(var d={},e=b;e!==c&&e!==HTMLUnknownElement.prototype;){for(var f,g=Object.getOwnPropertyNames(e),h=0;f=g[h];h++)d[f]||(Object.defineProperty(a,f,Object.getOwnPropertyDescriptor(e,f)),d[f]=1);e=Object.getPrototypeOf(e)}}function j(a){a.createdCallback&&a.createdCallback()}function k(a){if(!a.setAttribute._polyfilled){var b=a.setAttribute;a.setAttribute=function(a,c){l.call(this,a,c,b)};var c=a.removeAttribute;a.removeAttribute=function(a){l.call(this,a,null,c)},a.setAttribute._polyfilled=!0}}function l(a,b,c){var d=this.getAttribute(a);c.apply(this,arguments);var e=this.getAttribute(a);this.attributeChangedCallback&&e!==d&&this.attributeChangedCallback(a,d,e)}function m(a){return a?w[a.toLowerCase()]:void 0}function n(a,b){if(w[a])throw new Error("a type with that name is already registered.");w[a]=b}function o(a){return function(){return f(a)}}function p(a,b){var c=m(b||a);if(c){if(a==c.tag&&b==c.is)return new c.ctor;if(!b&&!c.is)return new c.ctor}if(b){var d=p(a);return d.setAttribute("is",b),d}var d=x(a);return a.indexOf("-")>=0&&h(d,HTMLElement),d}function q(a){if(!a.__upgraded__&&a.nodeType===Node.ELEMENT_NODE){var b=a.getAttribute("is"),c=w[b||a.localName];if(c){if(b&&c.tag==a.localName)return g(a,c);if(!b&&!c.extends)return g(a,c)}}}function r(b){var c=y.call(this,b);return a.upgradeAll(c),c}a||(a=window.CustomElements={flags:{}});var s=a.flags,t=Boolean(document.register),u=!s.register&&t;if(u){var v=function(){};a.registry={},a.upgradeElement=v,a.watchShadow=v,a.upgrade=v,a.upgradeAll=v,a.upgradeSubtree=v,a.observeDocument=v,a.upgradeDocument=v,a.takeRecords=v}else{var w={},x=document.createElement.bind(document),y=Node.prototype.cloneNode;document.register=b,document.createElement=p,Node.prototype.cloneNode=r,a.registry=w,a.upgrade=q}a.hasNative=t,a.useNative=u}(window.CustomElements),function(){function a(a){return"link"===a.localName&&a.getAttribute("rel")===b}var b=window.HTMLImports?HTMLImports.IMPORT_LINK_TYPE:"none",c={selectors:["link[rel="+b+"]"],map:{link:"parseLink"},parse:function(a){if(!a.__parsed){a.__parsed=!0;var b=a.querySelectorAll(c.selectors);d(b,function(a){c[c.map[a.localName]](a)}),CustomElements.upgradeDocument(a),CustomElements.observeDocument(a)}},parseLink:function(b){a(b)&&this.parseImport(b)},parseImport:function(a){a.content&&c.parse(a.content)}},d=Array.prototype.forEach.call.bind(Array.prototype.forEach);CustomElements.parser=c}(),function(a){function b(){CustomElements.parser.parse(document),CustomElements.upgradeDocument(document),CustomElements.performedInitialDocumentUpgrade=!0;var a=window.Platform&&Platform.endOfMicrotask?Platform.endOfMicrotask:setTimeout;a(function(){CustomElements.ready=!0,CustomElements.readyTime=Date.now(),window.HTMLImports&&(CustomElements.elapsed=CustomElements.readyTime-HTMLImports.readyTime),document.body.dispatchEvent(new CustomEvent("WebComponentsReady",{bubbles:!0}))})}if("function"!=typeof window.CustomEvent&&(window.CustomEvent=function(a){var b=document.createEvent("HTMLEvents");return b.initEvent(a,!0,!0),b}),"complete"===document.readyState||a.flags.eager)b();else if("interactive"!==document.readyState||window.attachEvent||window.HTMLImports&&!window.HTMLImports.ready){var c=window.HTMLImports?"HTMLImportsLoaded":"loading"==document.readyState?"DOMContentLoaded":"load";window.addEventListener(c,b)}else b()}(window.CustomElements),function(){if(HTMLElement.prototype.createShadowRoot){var a=HTMLElement.prototype.createShadowRoot;HTMLElement.prototype.createShadowRoot=function(){var b=a.call(this);return b.host=this,CustomElements.watchShadow(this),b}}if(window.ShadowDOMPolyfill){var b=["upgradeAll","upgradeSubtree","observeDocument","upgradeDocument"],c={};b.forEach(function(a){c[a]=CustomElements[a]}),b.forEach(function(a){CustomElements[a]=function(b){return c[a](window.ShadowDOMPolyfill.wrapIfNeeded(b))}})}if(window.CustomElements&&!CustomElements.useNative){var d=Document.prototype.importNode;Document.prototype.importNode=function(a,b){var c=d.call(this,a,b);return CustomElements.upgradeAll(c),c}}}();
\ No newline at end of file
diff --git a/pkg/custom_element/pubspec.yaml b/pkg/custom_element/pubspec.yaml
index 2ed1f29..39302d5 100644
--- a/pkg/custom_element/pubspec.yaml
+++ b/pkg/custom_element/pubspec.yaml
@@ -1,5 +1,5 @@
 name: custom_element
-version: 0.9.1+1
+version: 0.9.1+2
 author: "Polymer.dart Team <web-ui-dev@dartlang.org>"
 homepage: http://www.dartlang.org/
 description: >
diff --git a/pkg/intl/lib/intl.dart b/pkg/intl/lib/intl.dart
index d14cb12..7fff850 100644
--- a/pkg/intl/lib/intl.dart
+++ b/pkg/intl/lib/intl.dart
@@ -29,6 +29,7 @@
 import 'src/date_format_internal.dart';
 import "number_symbols.dart";
 import "number_symbols_data.dart";
+import "src/temporary_debugging.dart";
 
 part 'date_format.dart';
 part 'src/date_format_field.dart';
diff --git a/pkg/intl/lib/src/date_format_helpers.dart b/pkg/intl/lib/src/date_format_helpers.dart
index 253a4e6..5508586 100644
--- a/pkg/intl/lib/src/date_format_helpers.dart
+++ b/pkg/intl/lib/src/date_format_helpers.dart
@@ -39,8 +39,22 @@
   DateTime asDate() {
     // TODO(alanknight): Validate the date, especially for things which
     // can crash the VM, e.g. large month values.
+    if (debugLogDateCreation) {
+      debugDateCreationLog
+        ..write("  Creating Date from\n")
+        ..write("    UTC: $utc\n")
+        ..write("    year: $year\n")
+        ..write("    month: $month\n")
+        ..write("    day: $day\n")
+        ..write("    pm: $pm\n")
+        ..write("    hour: $hour\n")
+        ..write("    minute: $minute\n")
+        ..write("    second: $second\n")
+        ..write("    fractionalSecond: $fractionalSecond\n");
+    }
+    var result;
     if (utc) {
-      return new DateTime.utc(
+      result = new DateTime.utc(
           year,
           month,
           day,
@@ -49,7 +63,7 @@
           second,
           fractionalSecond);
     } else {
-      return new DateTime(
+      result = new DateTime(
           year,
           month,
           day,
@@ -58,6 +72,11 @@
           second,
           fractionalSecond);
     }
+    if (debugLogDateCreation) {
+      debugDateCreationLog
+        ..write("Created $result");
+    }
+    return result;
   }
 }
 
diff --git a/pkg/intl/lib/src/temporary_debugging.dart b/pkg/intl/lib/src/temporary_debugging.dart
new file mode 100644
index 0000000..f96b56d
--- /dev/null
+++ b/pkg/intl/lib/src/temporary_debugging.dart
@@ -0,0 +1,10 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// This library contains temporary debugging code that should be
+/// removed once its purpose is finished. You would be crazy to use it.
+
+bool debugLogDateCreation = false;
+
+StringBuffer debugDateCreationLog = new StringBuffer();
\ No newline at end of file
diff --git a/pkg/intl/test/date_time_format_test_core.dart b/pkg/intl/test/date_time_format_test_core.dart
index 65461e2..989b264 100644
--- a/pkg/intl/test/date_time_format_test_core.dart
+++ b/pkg/intl/test/date_time_format_test_core.dart
@@ -14,6 +14,7 @@
 import 'date_time_format_test_data.dart';
 import 'package:intl/intl.dart';
 import 'package:intl/src/date_format_internal.dart';
+import 'package:intl/src/temporary_debugging.dart';
 
 var formatsToTest = const [
   DateFormat.DAY,
@@ -164,6 +165,7 @@
     if (!badSkeletons.any((x) => x == skeleton)) {
       var format = new DateFormat(skeleton, localeName);
       var actualResult = format.format(date);
+      debugLogDateCreation = true;
       var parsed = format.parse(actualResult);
       var thenPrintAgain = format.format(parsed);
       // We've seen a case where this failed in a way that seemed like a time
@@ -172,11 +174,17 @@
       // as possible if it occurs again.
       if (thenPrintAgain != actualResult) {
         print("Date mismatch!");
+        print("Date creation log: $debugDateCreationLog");
+        debugDateCreationLog.clear();
         print("  Expected $actualResult");
         print("  Got $thenPrintAgain");
         print("  Original date = $date");
         print("  Original ms = ${date.millisecondsSinceEpoch}");
         print("  Parsed back to $parsed");
+        var parsed2 = format.parse(actualResult);
+        print("  Parsing again yields $parsed2");
+        print("  Logged as: $debugDateCreationLog");
+        debugDateCreationLog.clear();
         print("  Parsed ms = ${parsed.millisecondsSinceEpoch}");
         print("  Original tz = $originalTimeZoneOffset");
         print("  Current tz name = $originalTimeZoneName");
@@ -185,6 +193,7 @@
         print("  Start time = $originalTime");
         print("  Current time ${new DateTime.now()}");
       }
+      debugLogDateCreation = false;
       expect(thenPrintAgain, equals(actualResult));
     }
   }
diff --git a/pkg/logging/lib/logging.dart b/pkg/logging/lib/logging.dart
index 8bff36b..ba342f7 100644
--- a/pkg/logging/lib/logging.dart
+++ b/pkg/logging/lib/logging.dart
@@ -51,7 +51,7 @@
 library logging;
 
 import 'dart:async';
-import 'package:collection_helpers/wrappers.dart';
+import 'package:collection/wrappers.dart';
 
 /**
  * Whether to allow fine-grain logging and configuration of loggers in a
diff --git a/pkg/logging/pubspec.yaml b/pkg/logging/pubspec.yaml
index 098558c..ef3a4cc 100644
--- a/pkg/logging/pubspec.yaml
+++ b/pkg/logging/pubspec.yaml
@@ -10,6 +10,6 @@
 environment:
   sdk: '>=1.0.0 <2.0.0'
 dependencies:
-  collection_helpers: '>=0.9.1 <0.10.0'
+  collection: '>=0.9.0 <0.10.0'
 dev_dependencies:
   unittest: '>=0.9.0 <0.10.0'
diff --git a/pkg/math/LICENSE b/pkg/math/LICENSE
new file mode 100644
index 0000000..ee99930
--- /dev/null
+++ b/pkg/math/LICENSE
@@ -0,0 +1,26 @@
+Copyright 2013, the Dart project authors. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+    * Neither the name of Google Inc. nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/runtime/bin/vmservice/service_request_router.dart b/pkg/math/lib/math.dart
similarity index 68%
copy from runtime/bin/vmservice/service_request_router.dart
copy to pkg/math/lib/math.dart
index c889c85..9958bec 100644
--- a/runtime/bin/vmservice/service_request_router.dart
+++ b/pkg/math/lib/math.dart
@@ -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.
 
-part of vmservice;
+library dart.pkg.math;
 
-abstract class ServiceRequestRouter {
-  Future route(ServiceRequest request);
-}
+// Placeholder library, reserved for future extension.
diff --git a/pkg/math/pubspec.yaml b/pkg/math/pubspec.yaml
new file mode 100644
index 0000000..4a20312
--- /dev/null
+++ b/pkg/math/pubspec.yaml
@@ -0,0 +1,9 @@
+name: math
+version: 0.9.0
+author: Dart Team <misc@dartlang.org>
+description: Utility functions and classes related to the 'dart:math' library.
+homepage: http://www.dartlang.org
+dev_dependencies:
+  unittest: ">=0.9.0 <0.10.0"
+environment:
+  sdk: ">=1.0.0 <2.0.0"
diff --git a/pkg/observe/pubspec.yaml b/pkg/observe/pubspec.yaml
index 0bb50ce..87c8727 100644
--- a/pkg/observe/pubspec.yaml
+++ b/pkg/observe/pubspec.yaml
@@ -1,5 +1,5 @@
 name: observe
-version: 0.9.2
+version: 0.9.3
 author: Polymer.dart Authors <web-ui-dev@dartlang.org>
 description: >
   Observable properties and objects for use in Model-Driven-Views (MDV).
@@ -10,7 +10,7 @@
 homepage: https://www.dartlang.org/polymer-dart/
 dependencies:
   analyzer: ">=0.10.1 <0.11.0"
-  barback: ">=0.9.0 <0.11.0"
+  barback: ">=0.9.0 <0.12.0"
   logging: ">=0.9.0 <0.10.0"
   path: ">=0.9.0 <2.0.0"
   source_maps: ">=0.9.0 <0.10.0"
diff --git a/pkg/pkg.status b/pkg/pkg.status
index 9c4ab8b..36160f6 100644
--- a/pkg/pkg.status
+++ b/pkg/pkg.status
@@ -22,14 +22,16 @@
 third_party/html5lib/test/dom_compat_test: Skip
 third_party/html5lib/test/browser/browser_test: Skip
 
+http/test/http_test: Pass, RuntimeError # Issue 15652
+
 [ $compiler == dart2js ]
-collection_helpers/test/equality_test/01: Fail # Issue 1533
-collection_helpers/test/equality_test/02: Fail # Issue 1533
-collection_helpers/test/equality_test/03: Fail # Issue 1533
-collection_helpers/test/equality_test/04: Fail # Issue 1533
-collection_helpers/test/equality_test/05: Fail # Issue 1533
-collection_helpers/test/equality_test/none: Pass, Fail # Issue 14348
-collection_helpers/test/typed_buffers_test/01: Fail # Not supporting Int64List, Uint64List.
+collection/test/equality_test/01: Fail # Issue 1533
+collection/test/equality_test/02: Fail # Issue 1533
+collection/test/equality_test/03: Fail # Issue 1533
+collection/test/equality_test/04: Fail # Issue 1533
+collection/test/equality_test/05: Fail # Issue 1533
+collection/test/equality_test/none: Pass, Fail # Issue 14348
+typed_data/test/typed_buffers_test/01: Fail # Not supporting Int64List, Uint64List.
 
 [ $compiler == dart2js && $checked ]
 crypto/test/base64_test: Slow, Pass
@@ -42,7 +44,7 @@
 unittest/test/unittest_nested_groups_setup_teardown_test: RuntimeError # http://dartbug.com/10109
 stack_trace/test/vm_test: RuntimeError, OK # VM-specific traces
 stack_trace/test/chain_test: Fail # Issues 15171 and 15105
-sequence_zip/test/stream_test: RuntimeError, OK # Timers are not supported.
+async/test/stream_zip_test: RuntimeError, OK # Timers are not supported.
 unittest/test/missing_tick_test: Fail # Timer interface not supported: dartbug.com/7728.
 
 [ $runtime == vm || $runtime == d8 || $runtime == jsshell ]
@@ -81,7 +83,7 @@
 # Bug in Spidermonkey's Uint8ClampedArray on x64 (non-Win FF is x64, Win is x86)
 # See https://bugzilla.mozilla.org/show_bug.cgi?id=940972
 # Likely to get patched only on some versions of Firefox.
-collection_helpers/test/typed_buffers_test: RuntimeError
+typed_data/test/typed_buffers_test: RuntimeError
 
 [ $runtime == opera && $compiler == dart2js ]
 intl/test/find_default_locale_browser_test: Fail
@@ -90,38 +92,21 @@
 [ $runtime == ie9 ]
 intl/test/date_time_format_http_request_test: Fail # Issue 8983
 mime/test/mime_multipart_transformer_test: Skip # No typed_data on IE9.
-collection_helpers/test/typed_buffers_test: Fail, Crash # No typed_data on IE9.
+typed_data/test/typed_buffers_test: Fail, Crash # No typed_data on IE9.
 polymer/test/instance_attrs_test: Pass, Fail # Issue 14167
 
 [ $runtime == safari ]
 fixnum/test/int_64_test: Pass, Fail # Bug in JSC.
 
 # Unexplained errors only occuring on Safari.
-collection_helpers/test/typed_buffers_test: RuntimeError
+typed_data/test/typed_buffers_test: RuntimeError
 
 [ $runtime == ie9 || $runtime == ie10 ]
-polymer/example/canonicalization/test/canonicalization_deploy_test: Pass, Timeout
-polymer/example/canonicalization/test/canonicalization_test: Timeout, OK # tests development only behavior
-polymer/test/attr_deserialize_test: Pass, Timeout # Issue 13260
-polymer/test/attr_mustache_test: Pass, Timeout # Issue 13260
-polymer/test/bind_test: Timeout # Issue 13260
 polymer/test/bind_mdv_test: RuntimeError # Issue 14412, 13260
-polymer/test/custom_event_test: Timeout # Issue 13260
-polymer/test/entered_view_test: Timeout # Issue 13260
-polymer/test/event_handlers_test: Timeout # Issue 13260
-polymer/test/event_path_declarative_test: Timeout # Issue 13260
-polymer/test/event_path_test: Timeout # Issue 13260
-polymer/test/events_test: Timeout # Issue 13260
-polymer/test/nested_binding_test: Timeout # Issue 13260
-polymer/test/noscript_test: Timeout # Issue 13260
-polymer/test/property_change_test: Timeout # Issue 13260
-polymer/test/prop_attr_reflection_test: Timeout # Issue 13260
-polymer/test/prop_attr_bind_reflection_test: Timeout # Issue 13260
-polymer/test/publish_attributes_test: Timeout # Issue 13260
-polymer/test/publish_inherited_properties_test: Timeout # Issue 13260
-polymer/test/take_attributes_test: Timeout # Issue 13260
-polymer/test/template_distribute_dynamic_test: Pass, Timeout # Issue 13260
-polymer/test/unbind_test: Timeout # Issue 13260, 15259
+polymer/test/noscript_test: RuntimeError # Issue 13260
+
+[ ($runtime == ie9 || $runtime == ie10) && $checked ]
+polymer/test/take_attributes_test: RuntimeError # Issue 13260
 
 # Skip browser-specific tests on VM
 [ $runtime == vm ]
diff --git a/pkg/polymer/CHANGELOG.md b/pkg/polymer/CHANGELOG.md
index d2e3eba..3aad33a 100644
--- a/pkg/polymer/CHANGELOG.md
+++ b/pkg/polymer/CHANGELOG.md
@@ -5,6 +5,24 @@
 impact polymer: custom_element, html_import, observe, shadow_dom,
 and template_binding.
 
+#### Pub version 0.9.3+3
+  * Removes workaround now that mirrors implement a missing feature. Requires
+    SDK >= 1.1.0-dev.5.0.
+
+#### Pub version 0.9.3+2
+  * Fix rare canonicalization bug
+    [15694](https://code.google.com/p/dart/issues/detail?id=15694)
+
+#### Pub version 0.9.3+1
+  * Fix type error in runner.dart
+    [15649](https://code.google.com/p/dart/issues/detail?id=15649).
+
+#### Pub version 0.9.3
+  * pub-build now runs the linter automatically
+
+#### Pub version 0.9.2+4
+  * fix linter on SVG and MathML tags with XML namespaces
+
 #### Pub version 0.9.2+3
   * fix [15574](https://code.google.com/p/dart/issues/detail?id=15574),
     event bindings in dart2js, by working around issue
diff --git a/pkg/polymer/lib/builder.dart b/pkg/polymer/lib/builder.dart
index 440c2723..26813e7 100644
--- a/pkg/polymer/lib/builder.dart
+++ b/pkg/polymer/lib/builder.dart
@@ -39,25 +39,27 @@
  *     import 'package:polymer/builder.dart';
  *
  *     main() {
- *        lint().then((_) => deploy());
+ *        deploy(); // deploy also calls the linter internally.
  *     }
  *
- * **Example 3**: Runs the linter, but conditionally does the deploy step. See
- * [parseOptions] for a description of options parsed automatically by this
- * helper library.
+ * **Example 3**: Always run the linter, but conditionally build a deployable
+ * version. See [parseOptions] for a description of options parsed automatically
+ * by this helper library.
  *
  *     import 'dart:io';
  *     import 'package:polymer/builder.dart';
  *
  *     main(args) {
  *        var options = parseOptions(args);
- *        lint().then((_) {
- *          if (options.forceDeploy) deploy();
- *        });
+ *        if (options.forceDeploy) {
+ *          deploy();
+ *        } else {
+ *          lint();
+ *        }
  *     }
  *
- * **Example 4**: Same as above, but uses [build] (which internally calls [lint]
- * and optionally calls [deploy]).
+ * **Example 4**: Same as above, but uses [build] (which internally calls either
+ * [lint] or [deploy]).
  *
  *     import 'dart:io';
  *     import 'package:polymer/builder.dart';
@@ -118,13 +120,11 @@
         ' options to build(). Running as if no options were passed.');
     options = parseOptions([]);
   }
-  return lint(entryPoints: entryPoints, options: options,
-      currentPackage: currentPackage, packageDirs: packageDirs).then((res) {
-    if (options.forceDeploy) {
-      return deploy(entryPoints: entryPoints, options: options,
-          currentPackage: currentPackage, packageDirs: packageDirs);
-    }
-  });
+  return options.forceDeploy
+      ? deploy(entryPoints: entryPoints, options: options,
+            currentPackage: currentPackage, packageDirs: packageDirs)
+      : lint(entryPoints: entryPoints, options: options,
+            currentPackage: currentPackage, packageDirs: packageDirs);
 }
 
 
@@ -152,36 +152,10 @@
   }
   if (currentPackage == null) currentPackage = readCurrentPackageFromPubspec();
   var linterOptions = new TransformOptions(entryPoints: entryPoints);
-  var formatter = options.machineFormat ? jsonFormatter : consoleFormatter;
-  var linter = new Linter(linterOptions, formatter);
+  var linter = new Linter(linterOptions);
   return runBarback(new BarbackOptions([[linter]], null,
-      currentPackage: currentPackage, packageDirs: packageDirs)).then((assets) {
-    var messages = {};
-    var futures = [];
-    for (var asset in assets) {
-      var id = asset.id;
-      if (id.package == currentPackage && id.path.endsWith('.messages')) {
-        futures.add(asset.readAsString().then((content) {
-          if (content.isEmpty) return;
-          messages[id] = content;
-        }));
-      }
-    }
-
-    return Future.wait(futures).then((_) {
-      // Print messages sorting by package and filepath.
-      var orderedKeys = messages.keys.toList();
-      orderedKeys.sort((a, b) {
-        int packageCompare = a.package.compareTo(b.package);
-        if (packageCompare != 0) return packageCompare;
-        return a.path.compareTo(b.path);
-      });
-
-      for (var key in orderedKeys) {
-        print(messages[key]);
-      }
-    });
-  });
+      currentPackage: currentPackage, packageDirs: packageDirs,
+      machineFormat: options.machineFormat));
 }
 
 /**
@@ -220,7 +194,7 @@
   var barbackOptions = new BarbackOptions(
       new PolymerTransformerGroup(transformOptions).phases,
       options.outDir, currentPackage: currentPackage,
-      packageDirs: packageDirs);
+      packageDirs: packageDirs, machineFormat: options.machineFormat);
   return runBarback(barbackOptions)
       .then((_) => print('Done! All files written to "${options.outDir}"'));
 }
diff --git a/pkg/polymer/lib/polymer.dart b/pkg/polymer/lib/polymer.dart
index baf1a6c..ff80921 100644
--- a/pkg/polymer/lib/polymer.dart
+++ b/pkg/polymer/lib/polymer.dart
@@ -59,7 +59,6 @@
 import 'package:template_binding/template_binding.dart';
 
 import 'deserialize.dart' as deserialize;
-import 'src/reflected_type.dart';
 
 export 'package:observe/observe.dart';
 export 'package:observe/html.dart';
diff --git a/pkg/polymer/lib/src/build/common.dart b/pkg/polymer/lib/src/build/common.dart
index 655ccbf..ebedf23 100644
--- a/pkg/polymer/lib/src/build/common.dart
+++ b/pkg/polymer/lib/src/build/common.dart
@@ -112,6 +112,8 @@
 
   Future<bool> assetExists(AssetId id, Transform transform) =>
       transform.getInput(id).then((_) => true).catchError((_) => false);
+
+  String toString() => 'polymer ($runtimeType)';
 }
 
 /** Create an [AssetId] for a [url] seen in the [source] asset. */
diff --git a/pkg/polymer/lib/src/build/linter.dart b/pkg/polymer/lib/src/build/linter.dart
index 75374f5..07e0153 100644
--- a/pkg/polymer/lib/src/build/linter.dart
+++ b/pkg/polymer/lib/src/build/linter.dart
@@ -21,8 +21,6 @@
 import 'common.dart';
 import 'utils.dart';
 
-typedef String MessageFormatter(String kind, String message, Span span);
-
 /**
  * A linter that checks for common Polymer errors and produces warnings to
  * show on the editor or the command line. Leaves sources unchanged, but creates
@@ -34,24 +32,19 @@
   /** Only run on .html files. */
   final String allowedExtensions = '.html';
 
-  final MessageFormatter _formatter;
-
-  Linter(this.options, [this._formatter]);
+  Linter(this.options);
 
   Future apply(Transform transform) {
-    var wrapper = new _LoggerInterceptor(transform, _formatter);
     var seen = new Set<AssetId>();
     var primary = transform.primaryInput;
     var id = primary.id;
-    wrapper.addOutput(primary); // this phase is analysis only
+    transform.addOutput(primary); // this phase is analysis only
     seen.add(id);
-    return readPrimaryAsHtml(wrapper).then((document) {
-      return _collectElements(document, id, wrapper, seen).then((elements) {
+    return readPrimaryAsHtml(transform).then((document) {
+      return _collectElements(document, id, transform, seen).then((elements) {
         bool isEntrypoint = options.isHtmlEntryPoint(id);
-        new _LinterVisitor(wrapper, elements, isEntrypoint).run(document);
-        var messagesId = id.addExtension('.messages');
-        wrapper.addOutput(new Asset.fromString(messagesId,
-            wrapper._messages.join('\n')));
+        new _LinterVisitor(transform.logger, elements, isEntrypoint)
+            .run(document);
       });
     });
   }
@@ -129,70 +122,6 @@
   }
 }
 
-/** A proxy of [Transform] that returns a different logger. */
-// TODO(sigmund): get rid of this when barback supports a better way to log
-// messages without printing them.
-class _LoggerInterceptor implements Transform, TransformLogger {
-  final Transform _original;
-  final List<String> _messages = [];
-  final MessageFormatter _formatter;
-
-  _LoggerInterceptor(this._original, MessageFormatter formatter)
-      : _formatter = formatter == null ? consoleFormatter : formatter;
-
-  TransformLogger get logger => this;
-
-  noSuchMethod(Invocation m) => reflect(_original).delegate(m);
-
-  // form TransformLogger:
-  void warning(String message, {AssetId asset, Span span})
-      => _write('warning', message, span);
-
-  void error(String message, {AssetId asset, Span span})
-      => _write('error', message, span);
-
-  void _write(String kind, String message, Span span) {
-    _messages.add(_formatter(kind, message, span));
-  }
-}
-
-/**
- * Formatter that generates messages using a format that can be parsed
- * by tools, such as the Dart Editor, for reporting error messages.
- */
-String jsonFormatter(String kind, String message, Span span) {
-  return JSON.encode((span == null)
-      ? [{'method': 'warning', 'params': {'message': message}}]
-      : [{'method': kind,
-          'params': {
-            'file': span.sourceUrl,
-            'message': message,
-            'line': span.start.line + 1,
-            'charStart': span.start.offset,
-            'charEnd': span.end.offset,
-          }}]);
-}
-
-/**
- * Formatter that generates messages that are easy to read on the console (used
- * by default).
- */
-String consoleFormatter(String kind, String message, Span span) {
-  var useColors = stdioType(stdout) == StdioType.TERMINAL;
-  var levelColor = (kind == 'error') ? _RED_COLOR : _MAGENTA_COLOR;
-  var output = new StringBuffer();
-  if (useColors) output.write(levelColor);
-  output..write(kind)..write(' ');
-  if (useColors) output.write(_NO_COLOR);
-  if (span == null) {
-    output.write(message);
-  } else {
-    output.write(span.getLocationMessage(message,
-          useColors: useColors,
-          color: levelColor));
-  }
-  return output.toString();
-}
 
 /**
  * Information needed about other polymer-element tags in order to validate
@@ -395,7 +324,7 @@
   void _validateNormalElement(Element node) {
     // Event handlers only allowed inside polymer-elements
     node.attributes.forEach((name, value) {
-      if (name.startsWith('on')) {
+      if (name is String && name.startsWith('on')) {
         _validateEventHandler(node, name, value);
       }
     });
@@ -517,10 +446,6 @@
   return !_invalidTagNames.containsKey(name);
 }
 
-const String _RED_COLOR = '\u001b[31m';
-const String _MAGENTA_COLOR = '\u001b[35m';
-const String _NO_COLOR = '\u001b[0m';
-
 const String USE_INIT_DART =
     'To run a polymer application, you need to call "initPolymer". You can '
     'either include a generic script tag that does this for you:'
diff --git a/pkg/polymer/lib/src/build/runner.dart b/pkg/polymer/lib/src/build/runner.dart
index c7658de..87db2ae 100644
--- a/pkg/polymer/lib/src/build/runner.dart
+++ b/pkg/polymer/lib/src/build/runner.dart
@@ -12,7 +12,6 @@
 import 'dart:convert';
 import 'dart:io';
 
-import 'package:args/args.dart';
 import 'package:barback/barback.dart';
 import 'package:path/path.dart' as path;
 import 'package:stack_trace/stack_trace.dart';
@@ -42,8 +41,15 @@
   /** Directory where to generate code, if any. */
   final String outDir;
 
+  /**
+   * Whether to print error messages using a json-format that tools, such as the
+   * Dart Editor, can process.
+   */
+  final bool machineFormat;
+
   BarbackOptions(this.phases, this.outDir, {currentPackage, packageDirs,
-      this.transformTests: false, this.transformPolymerDependencies: false})
+      this.transformTests: false, this.transformPolymerDependencies: false,
+      this.machineFormat: false})
       : currentPackage = (currentPackage != null
           ? currentPackage : readCurrentPackageFromPubspec()),
         packageDirs = (packageDirs != null
@@ -59,7 +65,7 @@
 Future<AssetSet> runBarback(BarbackOptions options) {
   var barback = new Barback(new _PolymerPackageProvider(options.packageDirs));
   _initBarback(barback, options);
-  _attachListeners(barback);
+  _attachListeners(barback, options);
   if (options.outDir == null) return barback.getAllAssets();
   return _emitAllFiles(barback, options);
 }
@@ -80,7 +86,7 @@
  * Extract a mapping between package names and the path in the file system where
  * to find the sources of such package. This map will contain an entry for the
  * current package and everything it depends on (extracted via `pub
- * list-pacakge-dirs`).
+ * list-package-dirs`).
  */
 Map<String, String> _readPackageDirsFromPub(String currentPackage) {
   var dartExec = Platform.executable;
@@ -171,7 +177,7 @@
 }
 
 /** Attach error listeners on [barback] so we can report errors. */
-void _attachListeners(Barback barback) {
+void _attachListeners(Barback barback, BarbackOptions options) {
   // Listen for errors and results
   barback.errors.listen((e) {
     var trace = null;
@@ -189,6 +195,14 @@
       exit(1);
     }
   });
+
+  barback.log.listen((entry) {
+    if (options.machineFormat) {
+      print(_jsonFormatter(entry));
+    } else {
+      print(_consoleFormatter(entry));
+    }
+  });
 }
 
 /**
@@ -311,3 +325,54 @@
   _ensureDir(path.dirname(filepath));
   return asset.read().pipe(new File(filepath).openWrite());
 }
+
+String _kindFromEntry(LogEntry entry) {
+  var level = entry.level;
+  return level == LogLevel.ERROR ? 'error'
+      : (level == LogLevel.WARNING ? 'warning' : 'info');
+}
+
+/**
+ * Formatter that generates messages using a format that can be parsed
+ * by tools, such as the Dart Editor, for reporting error messages.
+ */
+String _jsonFormatter(LogEntry entry) {
+  var kind = _kindFromEntry(entry);
+  var span = entry.span;
+  return JSON.encode((span == null)
+      ? [{'method': kind, 'params': {'message': entry.message}}]
+      : [{'method': kind,
+          'params': {
+            'file': span.sourceUrl,
+            'message': entry.message,
+            'line': span.start.line + 1,
+            'charStart': span.start.offset,
+            'charEnd': span.end.offset,
+          }}]);
+}
+
+/**
+ * Formatter that generates messages that are easy to read on the console (used
+ * by default).
+ */
+String _consoleFormatter(LogEntry entry) {
+  var kind = _kindFromEntry(entry);
+  var useColors = stdioType(stdout) == StdioType.TERMINAL;
+  var levelColor = (kind == 'error') ? _RED_COLOR : _MAGENTA_COLOR;
+  var output = new StringBuffer();
+  if (useColors) output.write(levelColor);
+  output..write(kind)..write(' ');
+  if (useColors) output.write(_NO_COLOR);
+  if (entry.span == null) {
+    output.write(entry.message);
+  } else {
+    output.write(entry.span.getLocationMessage(entry.message,
+          useColors: useColors,
+          color: levelColor));
+  }
+  return output.toString();
+}
+
+const String _RED_COLOR = '\u001b[31m';
+const String _MAGENTA_COLOR = '\u001b[35m';
+const String _NO_COLOR = '\u001b[0m';
diff --git a/pkg/polymer/lib/src/loader.dart b/pkg/polymer/lib/src/loader.dart
index 5ee0915..48085e3 100644
--- a/pkg/polymer/lib/src/loader.dart
+++ b/pkg/polymer/lib/src/loader.dart
@@ -139,7 +139,8 @@
 final _rootUri = currentMirrorSystem().isolate.rootLibrary.uri;
 
 final String _packageRoot =
-    '${path.dirname(Uri.parse(window.location.href).path)}/packages/';
+    path.url.join(path.url.dirname(Uri.parse(window.location.href).path),
+        'packages') + '/';
 
 final Logger _loaderLog = new Logger('polymer.loader');
 
@@ -180,7 +181,7 @@
     for (var m in c.metadata) {
       var meta = m.reflectee;
       if (meta is CustomTag) {
-        Polymer.register(meta.tagName, getReflectedTypeWorkaround(c));
+        Polymer.register(meta.tagName, c.reflectedType);
       }
     }
 
diff --git a/pkg/polymer/lib/src/reflected_type.dart b/pkg/polymer/lib/src/reflected_type.dart
deleted file mode 100644
index 6486abc..0000000
--- a/pkg/polymer/lib/src/reflected_type.dart
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library polymer.src.reflected_type;
-
-// These are used by _getReflectedTypeWorkaround, see http://dartbug.com/12607
-@MirrorsUsed(targets:
-    const ['_js_helper.createRuntimeType', 'dart._js_mirrors.JsClassMirror'],
-    override: 'polymer.src.reflected_type')
-import 'dart:mirrors';
-
-// Horrible hack to work around: http://dartbug.com/12607
-Type getReflectedTypeWorkaround(ClassMirror cls) {
-  // On Dart VM, just return reflectedType.
-  if (1.0 is! int) return cls.reflectedType;
-
-  var mangledName = reflect(cls).getField(_mangledNameField).reflectee;
-  Type type = _jsHelper.invoke(#createRuntimeType, [mangledName]).reflectee;
-  return type;
-}
-
-final LibraryMirror _jsHelper =
-    currentMirrorSystem().libraries[Uri.parse('dart:_js_helper')];
-
-final Symbol _mangledNameField = () {
-  var jsClassMirrorMirror = reflect(reflectClass(ClassMirror)).type;
-  for (var name in jsClassMirrorMirror.declarations.keys) {
-    if (MirrorSystem.getName(name) == '_mangledName') return name;
-  }
-}();
diff --git a/pkg/polymer/lib/transformer.dart b/pkg/polymer/lib/transformer.dart
index 735fac3..960d9df 100644
--- a/pkg/polymer/lib/transformer.dart
+++ b/pkg/polymer/lib/transformer.dart
@@ -12,6 +12,7 @@
 import 'src/build/code_extractor.dart';
 import 'src/build/common.dart';
 import 'src/build/import_inliner.dart';
+import 'src/build/linter.dart';
 import 'src/build/polyfill_injector.dart';
 import 'src/build/script_compactor.dart';
 
@@ -69,6 +70,7 @@
 
 List<List<Transformer>> _createDeployPhases(TransformOptions options) {
   return [
+    [new Linter(options)],
     [new InlineCodeExtractor(options)],
     [new ObservableTransformer()],
     [new ImportInliner(options)],
diff --git a/pkg/polymer/pubspec.yaml b/pkg/polymer/pubspec.yaml
index db8f3ce..7a348ce 100644
--- a/pkg/polymer/pubspec.yaml
+++ b/pkg/polymer/pubspec.yaml
@@ -1,5 +1,5 @@
 name: polymer
-version: 0.9.2+3
+version: 0.9.3+3
 author: Polymer.dart Authors <web-ui-dev@dartlang.org>
 description: >
   Polymer.dart is a new type of library for the web, built on top of Web
@@ -9,7 +9,7 @@
 dependencies:
   analyzer: ">=0.10.1 <0.11.0"
   args: ">=0.9.0 <0.10.0"
-  barback: ">=0.9.0 <0.11.0"
+  barback: ">=0.9.0 <0.12.0"
   browser: ">=0.9.0 <0.10.0"
   csslib: ">=0.9.0 <0.10.0"
   custom_element: ">=0.9.1+1 <0.10.0"
@@ -29,4 +29,4 @@
 dev_dependencies:
   unittest: ">=0.9.0 <0.10.0"
 environment:
-  sdk: ">=1.0.0 <2.0.0"
+  sdk: ">=1.1.0-dev.5.0 <2.0.0"
diff --git a/pkg/polymer/test/build/common.dart b/pkg/polymer/test/build/common.dart
index 592f92f..d38fb3d 100644
--- a/pkg/polymer/test/build/common.dart
+++ b/pkg/polymer/test/build/common.dart
@@ -31,20 +31,27 @@
    */
   final Map<String, String> files;
   final Iterable<String> packages;
+  final List<String> messages;
+  int messagesSeen = 0;
+  bool errorSeen = false;
 
   Barback barback;
   var errorSubscription;
   var resultSubscription;
+  var logSubscription;
 
   Future<Asset> getAsset(AssetId id) =>
       new Future.value(new Asset.fromString(id, files[idToString(id)]));
-  TestHelper(List<List<Transformer>> transformers, Map<String, String> files)
+
+  TestHelper(List<List<Transformer>> transformers, Map<String, String> files,
+      this.messages)
       : files = files,
         packages = files.keys.map((s) => idFromString(s).package) {
     barback = new Barback(this);
     for (var p in packages) {
       barback.updateTransformers(p, transformers);
     }
+
     errorSubscription = barback.errors.listen((e) {
       var trace = null;
       if (e is Error) trace = e.stackTrace;
@@ -53,14 +60,30 @@
       }
       fail('error running barback: $e');
     });
+
     resultSubscription = barback.results.listen((result) {
-      expect(result.succeeded, isTrue, reason: "${result.errors}");
+      expect(result.succeeded, !errorSeen, reason: "${result.errors}");
+    });
+
+    logSubscription = barback.log.listen((entry) {
+      if (entry.level == LogLevel.ERROR) errorSeen = true;
+      // We only check messages when an expectation is provided.
+      if (messages == null) return;
+
+      var msg = '${entry.level.name.toLowerCase()}: ${entry.message}';
+      var span = entry.span;
+      var spanInfo = span == null ? '' :
+          ' (${span.sourceUrl} ${span.start.line} ${span.start.column})';
+      expect(messagesSeen, lessThan(messages.length),
+          reason: 'more messages than expected.\nMessage seen: $msg$spanInfo');
+      expect('$msg$spanInfo', messages[messagesSeen++]);
     });
   }
 
   void tearDown() {
     errorSubscription.cancel();
     resultSubscription.cancel();
+    logSubscription.cancel();
   }
 
   /**
@@ -90,14 +113,20 @@
     files.forEach((k, v) {
       futures.add(check(k, v));
     });
-    return Future.wait(futures);
+    return Future.wait(futures).then((_) {
+      // We only check messages when an expectation is provided.
+      if (messages == null) return;
+      expect(messages.length, messagesSeen,
+          reason: 'less messages than expected');
+    });
   }
 }
 
 testPhases(String testName, List<List<Transformer>> phases,
-    Map<String, String> inputFiles, Map<String, String> expectedFiles) {
+    Map<String, String> inputFiles, Map<String, String> expectedFiles,
+    [List<String> expectedMessages]) {
   test(testName, () {
-    var helper = new TestHelper(phases, inputFiles)..run();
+    var helper = new TestHelper(phases, inputFiles, expectedMessages)..run();
     return helper.checkAll(expectedFiles).then((_) => helper.tearDown());
   });
 }
diff --git a/pkg/polymer/test/build/linter_test.dart b/pkg/polymer/test/build/linter_test.dart
index 46964be..1641b64 100644
--- a/pkg/polymer/test/build/linter_test.dart
+++ b/pkg/polymer/test/build/linter_test.dart
@@ -16,9 +16,7 @@
   useCompactVMConfiguration();
   _testLinter('nothing to report', {
       'a|lib/test.html': '<!DOCTYPE html><html></html>',
-    }, {
-      'a|lib/test.html.messages': ''
-    });
+    }, []);
 
   group('must have Dart code to invoke initPolymer, dart.js, not boot.js', () {
     _testLinter('nothing to report', {
@@ -27,15 +25,13 @@
             '</script>'
             '<script src="packages/browser/dart.js"></script>'
             '</html>',
-      }, {
-        'a|web/test.html.messages': '',
-      });
+      }, []);
 
     _testLinter('missing Dart code and dart.js', {
         'a|web/test.html': '<!DOCTYPE html><html></html>',
-      }, {
-        'a|web/test.html.messages': 'error: $USE_INIT_DART',
-      });
+      }, [
+        'error: $USE_INIT_DART',
+      ]);
 
     _testLinter('using deprecated boot.js', {
         'a|web/test.html': '<!DOCTYPE html><html>\n'
@@ -44,10 +40,9 @@
             '</script>'
             '<script src="packages/browser/dart.js"></script>'
             '</html>',
-      }, {
-        'a|web/test.html.messages': 'warning: $BOOT_JS_DEPRECATED '
-                                    '(web/test.html 1 0)',
-      });
+      }, [
+        'warning: $BOOT_JS_DEPRECATED (web/test.html 1 0)',
+      ]);
   });
   group('single script tag per document', () {
     _testLinter('two top-level tags', {
@@ -57,11 +52,10 @@
             '<script type="application/dart" src="b.dart">'
             '</script>'
             '<script src="packages/browser/dart.js"></script>'
-      }, {
-        'a|web/test.html.messages':
-            'warning: Only one "application/dart" script tag per document is'
-            ' allowed. (web/test.html 1 0)',
-      });
+      }, [
+        'warning: Only one "application/dart" script tag per document is'
+        ' allowed. (web/test.html 1 0)',
+      ]);
 
     _testLinter('two top-level tags, non entrypoint', {
         'a|lib/test.html': '<!DOCTYPE html><html>'
@@ -70,11 +64,10 @@
             '<script type="application/dart" src="b.dart">'
             '</script>'
             '<script src="packages/browser/dart.js"></script>'
-      }, {
-        'a|lib/test.html.messages':
-            'warning: Only one "application/dart" script tag per document is'
-            ' allowed. (lib/test.html 1 0)',
-      });
+      }, [
+        'warning: Only one "application/dart" script tag per document is'
+        ' allowed. (lib/test.html 1 0)',
+      ]);
 
     _testLinter('tags inside elements', {
         'a|web/test.html': '<!DOCTYPE html><html>'
@@ -85,28 +78,24 @@
             '<script type="application/dart" src="b.dart">'
             '</script>'
             '<script src="packages/browser/dart.js"></script>'
-      }, {
-        'a|web/test.html.messages':
-            'warning: Only one "application/dart" script tag per document is'
-            ' allowed. (web/test.html 1 0)',
-      });
+      }, [
+        'warning: Only one "application/dart" script tag per document is'
+        ' allowed. (web/test.html 1 0)',
+      ]);
   });
 
   group('doctype warning', () {
     _testLinter('in web', {
         'a|web/test.html': '<html></html>',
-      }, {
-        'a|web/test.html.messages':
-            'warning: Unexpected start tag (html). Expected DOCTYPE. '
-            '(web/test.html 0 0)\n'
-            'error: $USE_INIT_DART',
-      });
+      }, [
+        'warning: Unexpected start tag (html). Expected DOCTYPE. '
+        '(web/test.html 0 0)',
+        'error: $USE_INIT_DART',
+      ]);
 
     _testLinter('in lib', {
         'a|lib/test.html': '<html></html>',
-      }, {
-        'a|lib/test.html.messages': '',
-      });
+      }, []);
   });
 
   group('duplicate polymer-elements,', () {
@@ -115,13 +104,12 @@
             <polymer-element name="x-a"></polymer-element>
             <polymer-element name="x-a"></polymer-element>
             </html>'''.replaceAll('            ', ''),
-      }, {
-        'a|lib/test.html.messages':
-            'warning: duplicate definition for custom tag "x-a". '
-            '(lib/test.html 1 0)\n'
-            'warning: duplicate definition for custom tag "x-a"  '
-            '(second definition). (lib/test.html 2 0)'
-      });
+      }, [
+        'warning: duplicate definition for custom tag "x-a". '
+        '(lib/test.html 1 0)',
+        'warning: duplicate definition for custom tag "x-a"  '
+        '(second definition). (lib/test.html 2 0)'
+      ]);
 
     _testLinter('other file', {
         'a|lib/b.html': '''<html>
@@ -131,24 +119,22 @@
             <link rel="import" href="b.html">
             <polymer-element name="x-a"></polymer-element>
             </html>'''.replaceAll('            ', ''),
-      }, {
-        'a|lib/test.html.messages':
-            'warning: duplicate definition for custom tag "x-a". '
-            '(lib/b.html 1 0)\n'
-            'warning: duplicate definition for custom tag "x-a"  '
-            '(second definition). (lib/test.html 2 0)'
-      });
+      }, [
+        'warning: duplicate definition for custom tag "x-a". '
+        '(lib/b.html 1 0)',
+        'warning: duplicate definition for custom tag "x-a"  '
+        '(second definition). (lib/test.html 2 0)'
+      ]);
 
     _testLinter('non existing file', {
         'a|lib/test.html': '''<html>
             <link rel="import" href="b.html">
             <polymer-element name="x-a"></polymer-element>
             </html>'''.replaceAll('            ', ''),
-      }, {
-        'a|lib/test.html.messages':
-            'error: couldn\'t find imported asset "lib/b.html" in package '
-            '"a". (lib/test.html 1 0)'
-      });
+      }, [
+        'error: couldn\'t find imported asset "lib/b.html" in package '
+        '"a". (lib/test.html 1 0)'
+      ]);
 
     _testLinter('other package', {
         'b|lib/b.html': '''<html>
@@ -158,13 +144,12 @@
             <link rel="import" href="../../packages/b/b.html">
             <polymer-element name="x-a"></polymer-element>
             </html>'''.replaceAll('            ', ''),
-      }, {
-        'a|lib/test.html.messages':
-            'warning: duplicate definition for custom tag "x-a". '
-            '(package:b/b.html 1 0)\n'
-            'warning: duplicate definition for custom tag "x-a"  '
-            '(second definition). (lib/test.html 2 0)'
-      });
+      }, [
+        'warning: duplicate definition for custom tag "x-a". '
+        '(package:b/b.html 1 0)',
+        'warning: duplicate definition for custom tag "x-a"  '
+        '(second definition). (lib/test.html 2 0)'
+      ]);
   });
 
   _testLinter('bad link-rel tag (href missing)', {
@@ -174,22 +159,20 @@
           <link rel="foo">
           <link rel="import" href="">
           </html>'''.replaceAll('          ', ''),
-    }, {
-      'a|lib/test.html.messages':
-          'warning: link rel="import" missing href. (lib/test.html 1 0)\n'
-          'warning: link rel="stylesheet" missing href. (lib/test.html 2 0)\n'
-          'warning: link rel="import" missing href. (lib/test.html 4 0)'
-    });
+    }, [
+      'warning: link rel="import" missing href. (lib/test.html 1 0)',
+      'warning: link rel="stylesheet" missing href. (lib/test.html 2 0)',
+      'warning: link rel="import" missing href. (lib/test.html 4 0)'
+    ]);
 
   _testLinter('<element> is not supported', {
       'a|lib/test.html': '''<html>
           <element name="x-a"></element>
           </html>'''.replaceAll('          ', ''),
-    }, {
-      'a|lib/test.html.messages':
-          'warning: <element> elements are not supported, use <polymer-element>'
-          ' instead (lib/test.html 1 0)'
-    });
+    }, [
+      'warning: <element> elements are not supported, use <polymer-element>'
+      ' instead (lib/test.html 1 0)'
+    ]);
 
   _testLinter('do not nest <polymer-element>', {
       'a|lib/test.html': '''<html>
@@ -199,51 +182,44 @@
             </div></template>
           </polymer-element>
           </html>'''.replaceAll('          ', ''),
-    }, {
-      'a|lib/test.html.messages':
-          'error: Nested polymer element definitions are not allowed.'
-          ' (lib/test.html 3 4)'
-    });
+    }, [
+      'error: Nested polymer element definitions are not allowed.'
+      ' (lib/test.html 3 4)'
+    ]);
 
   _testLinter('need a name for <polymer-element>', {
       'a|lib/test.html': '''<html>
           <polymer-element></polymer-element>
           </html>'''.replaceAll('          ', ''),
-    }, {
-      'a|lib/test.html.messages':
-          'error: Missing tag name of the custom element. Please include an '
-          'attribute like \'name="your-tag-name"\'. (lib/test.html 1 0)'
-    });
+    }, [
+      'error: Missing tag name of the custom element. Please include an '
+      'attribute like \'name="your-tag-name"\'. (lib/test.html 1 0)'
+    ]);
 
   _testLinter('name for <polymer-element> should have dashes', {
       'a|lib/test.html': '''<html>
           <polymer-element name="a"></polymer-element>
           </html>'''.replaceAll('          ', ''),
-    }, {
-      'a|lib/test.html.messages':
-          'error: Invalid name "a". Custom element names must have at least one'
-          ' dash and can\'t be any of the following names: annotation-xml, '
-          'color-profile, font-face, font-face-src, font-face-uri, '
-          'font-face-format, font-face-name, missing-glyph. (lib/test.html 1 0)'
-    });
+    }, [
+      'error: Invalid name "a". Custom element names must have at least one'
+      ' dash and can\'t be any of the following names: annotation-xml, '
+      'color-profile, font-face, font-face-src, font-face-uri, '
+      'font-face-format, font-face-name, missing-glyph. (lib/test.html 1 0)'
+    ]);
 
   _testLinter('extend is a valid element or existing tag', {
       'a|lib/test.html': '''<html>
           <polymer-element name="x-a" extends="li"></polymer-element>
           </html>'''.replaceAll('          ', ''),
-    }, {
-      'a|lib/test.html.messages': ''
-    });
+    }, []);
 
   _testLinter('extend is a valid element or existing tag', {
       'a|lib/test.html': '''<html>
           <polymer-element name="x-a" extends="x-b"></polymer-element>
           </html>'''.replaceAll('          ', ''),
-    }, {
-      'a|lib/test.html.messages': ''
-          'warning: custom element with name "x-b" not found. '
-          '(lib/test.html 1 0)'
-    });
+    }, [
+      'warning: custom element with name "x-b" not found. (lib/test.html 1 0)'
+    ]);
 
 
   group('script type matches code', () {
@@ -251,11 +227,10 @@
         'a|lib/test.html': '''<html>
             <script src="foo.dart"></script>
             </html>'''.replaceAll('            ', ''),
-      }, {
-        'a|lib/test.html.messages':
-            'warning: Wrong script type, expected type="application/dart".'
-            ' (lib/test.html 1 0)'
-      });
+      }, [
+        'warning: Wrong script type, expected type="application/dart".'
+        ' (lib/test.html 1 0)'
+      ]);
 
     _testLinter('in polymer-element, .dart url', {
         'a|lib/test.html': '''<html>
@@ -263,11 +238,10 @@
             <script src="foo.dart"></script>
             </polymer-element>
             </html>'''.replaceAll('            ', ''),
-      }, {
-        'a|lib/test.html.messages':
-            'warning: Wrong script type, expected type="application/dart".'
-            ' (lib/test.html 2 0)'
-      });
+      }, [
+        'warning: Wrong script type, expected type="application/dart".'
+        ' (lib/test.html 2 0)'
+      ]);
 
     _testLinter('in polymer-element, .js url', {
         'a|lib/test.html': '''<html>
@@ -275,9 +249,7 @@
             <script src="foo.js"></script>
             </polymer-element>
             </html>'''.replaceAll('            ', ''),
-      }, {
-        'a|lib/test.html.messages': ''
-      });
+      }, []);
 
     _testLinter('in polymer-element, inlined', {
         'a|lib/test.html': '''<html>
@@ -285,126 +257,113 @@
             <script>foo...</script>
             </polymer-element>
             </html>'''.replaceAll('            ', ''),
-      }, {
-        'a|lib/test.html.messages':
-            'warning: script tag in polymer element with no type will '
-            'be treated as JavaScript. Did you forget type="application/dart"?'
-            ' (lib/test.html 2 0)'
-      });
+      }, [
+        'warning: script tag in polymer element with no type will '
+        'be treated as JavaScript. Did you forget type="application/dart"?'
+        ' (lib/test.html 2 0)'
+      ]);
 
     _testLinter('top-level, dart type & .dart url', {
         'a|lib/test.html': '''<html>
             <script type="application/dart" src="foo.dart"></script>
             </html>'''.replaceAll('            ', ''),
-      }, {
-        'a|lib/test.html.messages': ''
-      });
+      }, []);
 
     _testLinter('top-level, dart type & .js url', {
         'a|lib/test.html': '''<html>
             <script type="application/dart" src="foo.js"></script>
             </html>'''.replaceAll('            ', ''),
-      }, {
-        'a|lib/test.html.messages':
-            'warning: "application/dart" scripts should use the .dart file '
-            'extension. (lib/test.html 1 0)'
-      });
+      }, [
+        'warning: "application/dart" scripts should use the .dart file '
+        'extension. (lib/test.html 1 0)'
+      ]);
   });
 
   _testLinter('script tags should have only src url or inline code', {
       'a|lib/test.html': '''<html>
           <script type="application/dart" src="foo.dart">more</script>
           </html>'''.replaceAll('          ', ''),
-    }, {
-      'a|lib/test.html.messages':
-          'warning: script tag has "src" attribute and also has script text. '
-          '(lib/test.html 1 0)'
-    });
+    }, [
+      'warning: script tag has "src" attribute and also has script text. '
+      '(lib/test.html 1 0)'
+    ]);
 
   group('event handlers', () {
     _testLinter('onfoo is not polymer', {
         'a|lib/test.html': '''<html><body>
             <div onfoo="something"></div>
             '''.replaceAll('            ', ''),
-      }, {
-        'a|lib/test.html.messages':
-            'warning: Event handler "onfoo" will be interpreted as an inline '
-            'JavaScript event handler. Use the form '
-            'on-event-name="handlerName" if you want a Dart handler '
-            'that will automatically update the UI based on model changes. '
-            '(lib/test.html 1 5)'
-      });
+      }, [
+        'warning: Event handler "onfoo" will be interpreted as an inline '
+        'JavaScript event handler. Use the form '
+        'on-event-name="handlerName" if you want a Dart handler '
+        'that will automatically update the UI based on model changes. '
+        '(lib/test.html 1 5)'
+      ]);
 
     _testLinter('on-foo is only supported in polymer elements', {
         'a|lib/test.html': '''<html><body>
             <div on-foo="something"></div>
             '''.replaceAll('            ', ''),
-      }, {
-        'a|lib/test.html.messages':
-            'warning: Inline event handlers are only supported inside '
-            'declarations of <polymer-element>. '
-            '(lib/test.html 1 5)'
-      });
+      }, [
+        'warning: Inline event handlers are only supported inside '
+        'declarations of <polymer-element>. '
+        '(lib/test.html 1 5)'
+      ]);
 
     _testLinter('on-foo is not an expression', {
         'a|lib/test.html': '''<html><body>
             <polymer-element name="x-a"><div on-foo="bar()"></div>
             </polymer-element>
             '''.replaceAll('            ', ''),
-      }, {
-        'a|lib/test.html.messages':
-            'warning: Invalid event handler body "bar()". Declare a method '
-            'in your custom element "void handlerName(event, detail, target)" '
-            'and use the form on-foo="handlerName". '
-            '(lib/test.html 1 33)'
-      });
+      }, [
+        'warning: Invalid event handler body "bar()". Declare a method '
+        'in your custom element "void handlerName(event, detail, target)" '
+        'and use the form on-foo="handlerName". '
+        '(lib/test.html 1 33)'
+      ]);
 
     _testLinter('on-foo-bar is supported as a custom event name', {
         'a|lib/test.html': '''<html><body>
             <polymer-element name="x-a"><div on-foo-bar="quux"></div>
             </polymer-element>
             '''.replaceAll('            ', ''),
-      }, {});
+      }, []);
   });
 
   group('using custom tags', () {
     _testLinter('tag exists (x-tag)', {
         'a|lib/test.html': '<x-foo></x-foo>',
-      }, {
-        'a|lib/test.html.messages':
-            'warning: definition for Polymer element with tag name "x-foo" not '
-            'found. (lib/test.html 0 0)'
-      });
+      }, [
+        'warning: definition for Polymer element with tag name "x-foo" not '
+        'found. (lib/test.html 0 0)'
+      ]);
 
     _testLinter('tag exists (type extension)', {
         'a|lib/test.html': '<div is="x-foo"></div>',
-      }, {
-        'a|lib/test.html.messages':
-            'warning: definition for Polymer element with tag name "x-foo" not '
-            'found. (lib/test.html 0 0)'
-      });
+      }, [
+        'warning: definition for Polymer element with tag name "x-foo" not '
+        'found. (lib/test.html 0 0)'
+      ]);
 
     _testLinter('used correctly (no base tag)', {
         'a|lib/test.html': '''
             <polymer-element name="x-a"></polymer-element>
             <x-a></x-a>
             '''.replaceAll('            ', ''),
-      }, {
-        'a|lib/test.html.messages': ''
-      });
+      }, []);
 
     _testLinter('used incorrectly (no base tag)', {
         'a|lib/test.html': '''
             <polymer-element name="x-a"></polymer-element>
             <div is="x-a"></div>
             '''.replaceAll('            ', ''),
-      }, {
-        'a|lib/test.html.messages':
-            'warning: custom element "x-a" doesn\'t declare any type '
-            'extensions. To fix this, either rewrite this tag as '
-            '<x-a> or add \'extends="div"\' to '
-            'the custom element declaration. (lib/test.html 1 0)'
-      });
+      }, [
+        'warning: custom element "x-a" doesn\'t declare any type '
+        'extensions. To fix this, either rewrite this tag as '
+        '<x-a> or add \'extends="div"\' to '
+        'the custom element declaration. (lib/test.html 1 0)'
+      ]);
 
     _testLinter('used incorrectly, imported def (no base tag)', {
         'a|lib/b.html': '<polymer-element name="x-a"></polymer-element>',
@@ -412,13 +371,12 @@
             <link rel="import" href="b.html">
             <div is="x-a"></div>
             '''.replaceAll('            ', ''),
-      }, {
-        'a|lib/test.html.messages':
-            'warning: custom element "x-a" doesn\'t declare any type '
-            'extensions. To fix this, either rewrite this tag as '
-            '<x-a> or add \'extends="div"\' to '
-            'the custom element declaration. (lib/test.html 1 0)'
-      });
+      }, [
+        'warning: custom element "x-a" doesn\'t declare any type '
+        'extensions. To fix this, either rewrite this tag as '
+        '<x-a> or add \'extends="div"\' to '
+        'the custom element declaration. (lib/test.html 1 0)'
+      ]);
 
     _testLinter('used correctly (base tag)', {
         'a|lib/b.html': '''
@@ -429,9 +387,7 @@
             <link rel="import" href="b.html">
             <div is="x-a"></div>
             '''.replaceAll('            ', ''),
-      }, {
-        'a|lib/test.html.messages': ''
-      });
+      }, []);
 
     _testLinter('used incorrectly (missing base tag)', {
         'a|lib/b.html': '''
@@ -442,13 +398,12 @@
             <link rel="import" href="b.html">
             <x-a></x-a>
             '''.replaceAll('            ', ''),
-      }, {
-        'a|lib/test.html.messages': ''
-            'warning: custom element "x-a" extends from "div", but this tag '
-            'will not include the default properties of "div". To fix this, '
-            'either write this tag as <div is="x-a"> or remove the "extends" '
-            'attribute from the custom element declaration. (lib/test.html 1 0)'
-      });
+      }, [
+        'warning: custom element "x-a" extends from "div", but this tag '
+        'will not include the default properties of "div". To fix this, '
+        'either write this tag as <div is="x-a"> or remove the "extends" '
+        'attribute from the custom element declaration. (lib/test.html 1 0)'
+      ]);
 
     _testLinter('used incorrectly (wrong base tag)', {
         'a|lib/b.html': '''
@@ -459,11 +414,10 @@
             <link rel="import" href="b.html">
             <span is="x-a"></span>
             '''.replaceAll('            ', ''),
-      }, {
-        'a|lib/test.html.messages': ''
-            'warning: custom element "x-a" extends from "div". Did you mean '
-            'to write <div is="x-a">? (lib/test.html 1 0)'
-      });
+      }, [
+        'warning: custom element "x-a" extends from "div". Did you mean '
+        'to write <div is="x-a">? (lib/test.html 1 0)'
+      ]);
 
     _testLinter('used incorrectly (wrong base tag, transitive)', {
         'a|lib/c.html': '''
@@ -481,11 +435,10 @@
             <link rel="import" href="b.html">
             <span is="x-a"></span>
             '''.replaceAll('            ', ''),
-      }, {
-        'a|lib/test.html.messages': ''
-            'warning: custom element "x-a" extends from "li". Did you mean '
-            'to write <li is="x-a">? (lib/test.html 1 0)'
-      });
+      }, [
+        'warning: custom element "x-a" extends from "li". Did you mean '
+        'to write <li is="x-a">? (lib/test.html 1 0)'
+      ]);
   });
 
   group('custom attributes', () {
@@ -494,32 +447,24 @@
             <polymer-element name="x-a" attributes="foo-bar">
             </polymer-element>
             '''.replaceAll('            ', ''),
-      }, {
-        'a|lib/test.html.messages':
-            'warning: PolymerElement no longer recognizes attribute names with '
-            'dashes such as "foo-bar". Use "fooBar" or "foobar" instead (both '
-            'forms are equivalent in HTML). (lib/test.html 1 28)'
-      });
+      }, [
+        'warning: PolymerElement no longer recognizes attribute names with '
+        'dashes such as "foo-bar". Use "fooBar" or "foobar" instead (both '
+        'forms are equivalent in HTML). (lib/test.html 1 28)'
+      ]);
   });
+
+  _testLinter("namespaced attributes don't cause an internal error", {
+      'a|lib/test.html': '''<html><body>
+          <svg xmlns="http://www.w3.org/2000/svg" width="520" height="350">
+          </svg>
+          '''.replaceAll('            ', ''),
+    }, []);
 }
 
-_testLinter(String name, Map inputFiles, Map outputMessages) {
-  var linter = new Linter(new TransformOptions(), _testFormatter);
+_testLinter(String name, Map inputFiles, List outputMessages) {
+  var linter = new Linter(new TransformOptions());
   var outputFiles = {};
   inputFiles.forEach((k, v) => outputFiles[k] = v);
-  outputMessages.forEach((k, v) => outputFiles[k] = v);
-  var keys = inputFiles.keys.toSet();
-  keys.retainAll(outputMessages.keys);
-  expect(keys, isEmpty);
-  testPhases(name, [[linter]], inputFiles, outputFiles);
-}
-
-
-_testFormatter(String kind, String message, Span span) {
-  var formattedMessage = '$kind: $message';
-  if (span != null) {
-    formattedMessage = '$formattedMessage '
-        '(${span.sourceUrl} ${span.start.line} ${span.start.column})';
-  }
-  return formattedMessage;
+  testPhases(name, [[linter]], inputFiles, outputFiles, outputMessages);
 }
diff --git a/pkg/polymer/test/build/static_clean_test.dart b/pkg/polymer/test/build/static_clean_test.dart
new file mode 100644
index 0000000..410fc51
--- /dev/null
+++ b/pkg/polymer/test/build/static_clean_test.dart
@@ -0,0 +1,11 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library polymer.test.build.static_clean_test;
+
+import 'package:polymer/builder.dart';
+
+void main() {
+  // Check that builder.dart is statically clean. Nothing to do.
+}
diff --git a/pkg/sequence_zip/LICENSE b/pkg/sequence_zip/LICENSE
new file mode 100644
index 0000000..ee99930
--- /dev/null
+++ b/pkg/sequence_zip/LICENSE
@@ -0,0 +1,26 @@
+Copyright 2013, the Dart project authors. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+    * Neither the name of Google Inc. nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/pkg/sequence_zip/lib/iterable_zip.dart b/pkg/sequence_zip/lib/iterable_zip.dart
index f21da73..dd4e5cb 100644
--- a/pkg/sequence_zip/lib/iterable_zip.dart
+++ b/pkg/sequence_zip/lib/iterable_zip.dart
@@ -2,61 +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.
 
-/**
- * Help for combining multiple Iterables into a single Iterable.
- *
- * This API is also available as part of the
- * [sequence_zip](#sequence_zip) library.
- */
+/** Please use `package:collection/iterable_zip.dart` instead. */
+@deprecated
 library iterable_zip;
 
-import "dart:collection";
-
-/**
- * Iterable that iterates over lists of values from other iterables.
- *
- * When [iterator] is read, an [Iterator] is created for each [Iterable] in
- * the [Iterable] passed to the constructor.
- *
- * As long as all these iterators have a next value, those next values are
- * combined into a single list, which becomes the next value of this
- * [Iterable]'s [Iterator]. As soon as any of the iterators run out,
- * the zipped iterator also stops.
- */
-class IterableZip extends IterableBase<List> {
-  final Iterable<Iterable> _iterables;
-  IterableZip(Iterable<Iterable> iterables)
-      : this._iterables = iterables;
-
-  /**
-   * Returns an iterator that combines values of the iterables' iterators
-   * as long as they all have values.
-   */
-  Iterator<List> get iterator {
-    List iterators = _iterables.map((x) => x.iterator).toList(growable: false);
-    // TODO(lrn): Return an empty iterator directly if iterators is empty?
-    return new _IteratorZip(iterators);
-  }
-}
-
-class _IteratorZip implements Iterator<List> {
-  final List<Iterator> _iterators;
-  List _current;
-  _IteratorZip(List iterators) : _iterators = iterators;
-  bool moveNext() {
-    if (_iterators.isEmpty) return false;
-    for (int i = 0; i < _iterators.length; i++) {
-      if (!_iterators[i].moveNext()) {
-        _current = null;
-        return false;
-      }
-    }
-    _current = new List(_iterators.length);
-    for (int i = 0; i < _iterators.length; i++) {
-      _current[i] = _iterators[i].current;
-    }
-    return true;
-  }
-
-  List get current => _current;
-}
+export "package:collection/iterable_zip.dart";
diff --git a/pkg/sequence_zip/lib/sequence_zip.dart b/pkg/sequence_zip/lib/sequence_zip.dart
index 2f0d7e6..8824e46 100644
--- a/pkg/sequence_zip/lib/sequence_zip.dart
+++ b/pkg/sequence_zip/lib/sequence_zip.dart
@@ -3,14 +3,10 @@
 // BSD-style license that can be found in the LICENSE file.
 
 /**
- * Utilities for combining multiple streams or Iterables
- * into a single stream or Iterable, respectively.
- *
- * This library defines no new APIs.
- * It's a convenience library for using the APIs in the
- * [iterable_zip](#iterable_zip) and
- * [stream_zip](#stream_zip) libraries.
+ * Please use the libraries `package:collection/iterable_zip.dart` for iterable zipping
+ * or `package:async/stream_zip.dart` for stream zipping.
  */
+@deprecated
 library sequence_zip;
 
 export "iterable_zip.dart";
diff --git a/pkg/sequence_zip/lib/stream_zip.dart b/pkg/sequence_zip/lib/stream_zip.dart
index b09cfdb..78b7a3a 100644
--- a/pkg/sequence_zip/lib/stream_zip.dart
+++ b/pkg/sequence_zip/lib/stream_zip.dart
@@ -2,121 +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.
 
-/**
- * Help for combining multiple streams into a single stream.
- *
- * This API is also available as part of the
- * [sequence_zip](#sequence_zip) library.
- */
+/** Please use `package:async/stream_zip.dart` instead. */
+@deprecated
 library stream_zip;
 
-import "dart:async";
-
-/**
- * A stream that combines the values of other streams.
- */
-class StreamZip extends Stream<List> {
-  final Iterable<Stream> _streams;
-  StreamZip(Iterable<Stream> streams) : _streams = streams;
-
-  StreamSubscription<List> listen(void onData(List data), {
-                                  Function onError,
-                                  void onDone(),
-                                  bool cancelOnError}) {
-    cancelOnError = identical(true, cancelOnError);
-    List<StreamSubscription> subscriptions = <StreamSubscription>[];
-    StreamController controller;
-    List current;
-    int dataCount = 0;
-
-    /// Called for each data from a subscription in [subscriptions].
-    void handleData(int index, data) {
-      current[index] = data;
-      dataCount++;
-      if (dataCount == subscriptions.length) {
-        List data = current;
-        current = new List(subscriptions.length);
-        dataCount = 0;
-        for (int i = 0; i < subscriptions.length; i++) {
-          if (i != index) subscriptions[i].resume();
-        }
-        controller.add(data);
-      } else {
-        subscriptions[index].pause();
-      }
-    }
-
-    /// Called for each error from a subscription in [subscriptions].
-    /// Except if [cancelOnError] is true, in which case the function below
-    /// is used instead.
-    void handleError(Object error, StackTrace stackTrace) {
-      controller.addError(error, stackTrace);
-    }
-
-    /// Called when a subscription has an error and [cancelOnError] is true.
-    ///
-    /// Prematurely cancels all subscriptions since we know that we won't
-    /// be needing any more values.
-    void handleErrorCancel(Object error, StackTrace stackTrace) {
-      for (int i = 0; i < subscriptions.length; i++) {
-        subscriptions[i].cancel();
-      }
-      controller.addError(error, stackTrace);
-    }
-
-    void handleDone() {
-      for (int i = 0; i < subscriptions.length; i++) {
-        subscriptions[i].cancel();
-      }
-      controller.close();
-    }
-
-    try {
-      for (Stream stream in _streams) {
-        int index = subscriptions.length;
-        subscriptions.add(stream.listen(
-            (data) { handleData(index, data); },
-            onError: cancelOnError ? handleError : handleErrorCancel,
-            onDone: handleDone,
-            cancelOnError: cancelOnError));
-      }
-    } catch (e) {
-      for (int i = subscriptions.length - 1; i >= 0; i--) {
-        subscriptions[i].cancel();
-      }
-      rethrow;
-    }
-
-    current = new List(subscriptions.length);
-
-    controller = new StreamController<List>(
-      onPause: () {
-        for (int i = 0; i < subscriptions.length; i++) {
-          // This may pause some subscriptions more than once.
-          // These will not be resumed by onResume below, but must wait for the
-          // next round.
-          subscriptions[i].pause();
-        }
-      },
-      onResume: () {
-        for (int i = 0; i < subscriptions.length; i++) {
-          subscriptions[i].resume();
-        }
-      },
-      onCancel: () {
-        for (int i = 0; i < subscriptions.length; i++) {
-          // Canceling more than once is safe.
-          subscriptions[i].cancel();
-        }
-      }
-    );
-
-    if (subscriptions.isEmpty) {
-      controller.close();
-    }
-    return controller.stream.listen(onData,
-                                    onError: onError,
-                                    onDone: onDone,
-                                    cancelOnError: cancelOnError);
-  }
-}
+export "package:async/stream_zip.dart";
\ No newline at end of file
diff --git a/pkg/sequence_zip/pubspec.yaml b/pkg/sequence_zip/pubspec.yaml
index fa4d22c..961e43a 100644
--- a/pkg/sequence_zip/pubspec.yaml
+++ b/pkg/sequence_zip/pubspec.yaml
@@ -1,12 +1,14 @@
 name: sequence_zip
-version: 0.9.0
-author: "Dart Team <misc@dartlang.org>"
+version: 0.9.1
+author: Dart Team <misc@dartlang.org>
 homepage: http://www.dartlang.org
 description: >
   "Zip" functionality on iterables and streams.
-  Combines multiple iterables into a single iterable of tuples of values,
-  and similar for Streams.
-dev_dependencies:
-  unittest: ">=0.9.0 <0.10.0"
+  This package has been discontinued.
+  The zip functionality for iterables is in `package:collection/iterable_zip.dart`
+  and the zip functionality for streams is in `package:async/stream_zip.dart`.
+dependencies:
+  collection: "0.9.0"
+  async: "0.9.0"
 environment:
   sdk: ">=0.8.10+6 <2.0.0"
diff --git a/pkg/serialization/LICENSE b/pkg/serialization/LICENSE
new file mode 100644
index 0000000..ee99930
--- /dev/null
+++ b/pkg/serialization/LICENSE
@@ -0,0 +1,26 @@
+Copyright 2013, the Dart project authors. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+    * Neither the name of Google Inc. nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/pkg/serialization/README.md b/pkg/serialization/README.md
new file mode 100644
index 0000000..d35ebc8
--- /dev/null
+++ b/pkg/serialization/README.md
@@ -0,0 +1,20 @@
+Serialization
+=============
+
+A general-purpose serialization facility for Dart Objects.
+
+This provides the ability to save and restore objects to pluggable
+Formats using pluggable Rules.
+These rules can use mirrors or be hard-coded. The main principle
+is using only public APIs on the serialized objects, so changes to the
+internal representation do not break previous serializations. It also handles
+cycles, different representations, filling in known objects on the 
+receiving side, and other issues. It is not as much intended for
+APIs using JSON to pass acyclic structures without class information,
+and is fairly heavweight and expensive for doing that compared to simpler
+approaches.
+ 
+For more detailed descriptions and examples of use, see the comment on
+the [serialization][serialization] library.
+
+[serialization]: https://api.dartlang.org/docs/channels/stable/latest/serialization.html
diff --git a/pkg/serialization/pubspec.yaml b/pkg/serialization/pubspec.yaml
index 3a5ea8a..2a8d9b2 100644
--- a/pkg/serialization/pubspec.yaml
+++ b/pkg/serialization/pubspec.yaml
@@ -1,5 +1,5 @@
 name: serialization
-version: 0.9.0
+version: 0.9.1
 author: "Dart Team <misc@dartlang.org>"
 homepage: http://www.dartlang.org
 documentation: http://api.dartlang.org/docs/pkg/serialization
@@ -8,4 +8,4 @@
 dev_dependencies:
   unittest: ">=0.9.0 <0.10.0"
 environment:
-  sdk: ">=0.8.10+6 <2.0.0"
+  sdk: ">=1.0.0 <2.0.0"
diff --git a/pkg/stack_trace/lib/src/chain.dart b/pkg/stack_trace/lib/src/chain.dart
index f6e2f3f..4055bc8 100644
--- a/pkg/stack_trace/lib/src/chain.dart
+++ b/pkg/stack_trace/lib/src/chain.dart
@@ -157,10 +157,19 @@
   /// This calls [Trace.terse] on every trace in [traces], and discards any
   /// trace that contain only internal frames.
   Chain get terse {
-    return new Chain(traces.map((trace) => trace.terse).where((trace) {
+    var terseTraces = traces.map((trace) => trace.terse);
+    var nonEmptyTraces = terseTraces.where((trace) {
       // Ignore traces that contain only internal processing.
       return trace.frames.length > 1;
-    }));
+    });
+
+    // If all the traces contain only internal processing, preserve the last
+    // (top-most) one so that the chain isn't empty.
+    if (nonEmptyTraces.isEmpty && terseTraces.isNotEmpty) {
+      return new Chain([terseTraces.last]);
+    }
+
+    return new Chain(nonEmptyTraces);
   }
 
   /// Converts [this] to a [Trace].
diff --git a/pkg/stack_trace/test/chain_test.dart b/pkg/stack_trace/test/chain_test.dart
index 4d31acb..9c16690 100644
--- a/pkg/stack_trace/test/chain_test.dart
+++ b/pkg/stack_trace/test/chain_test.dart
@@ -386,6 +386,21 @@
           '$userSlashCode 10:11  Foo.bar\n'
           'dart:core             Bar.baz\n'));
     });
+
+    test("doesn't return in an empty chain", () {
+      var chain = new Chain([
+        new Trace.parse(
+            'dart:core 10:11                             Foo.bar\n'
+            'package:stack_trace/stack_trace.dart 10:11  Bar.baz\n'
+            'dart:core 10:11                             Zip.zap'),
+        new Trace.parse(
+            'dart:core 10:11                             A.b\n'
+            'package:stack_trace/stack_trace.dart 10:11  C.d\n'
+            'dart:core 10:11                             E.f')
+      ]);
+
+      expect(chain.terse.toString(), equals('dart:core  E.f\n'));
+    });
   });
 
   test('Chain.toTrace eliminates asynchronous gaps', () {
diff --git a/pkg/typed_data/LICENSE b/pkg/typed_data/LICENSE
new file mode 100644
index 0000000..ee99930
--- /dev/null
+++ b/pkg/typed_data/LICENSE
@@ -0,0 +1,26 @@
+Copyright 2013, the Dart project authors. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+    * Neither the name of Google Inc. nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/pkg/typed_data/README.md b/pkg/typed_data/README.md
new file mode 100644
index 0000000..e1e7db5
--- /dev/null
+++ b/pkg/typed_data/README.md
@@ -0,0 +1,15 @@
+Helper libraries for working with typed data lists.
+
+The `typed_data` package contains utility functions and classes that makes working with typed data lists easier.
+
+## Using
+
+The `typed_data` package can be imported as
+
+    import 'package:typed_data/typed_data.dart';
+
+## Typed buffers: Growable typed data lists
+
+Typed buffers are contains growable lists backed by typed arrays.
+These are similar to the growable lists returned by `new List()`, 
+but stores typed data like a typed data list.
\ No newline at end of file
diff --git a/pkg/typed_data/lib/typed_buffers.dart b/pkg/typed_data/lib/typed_buffers.dart
new file mode 100644
index 0000000..b880338
--- /dev/null
+++ b/pkg/typed_data/lib/typed_buffers.dart
@@ -0,0 +1,235 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/**
+ * Growable typed-data lists.
+ *
+ * These lists works just as a typed-data list, except that they are growable.
+ * They use an underlying buffer, and when that buffer becomes too small, it
+ * is replaced by a new buffer.
+ *
+ * That means that using the [TypedDataView.buffer] getter is not guaranteed
+ * to return the same result each time it is used, and that the buffer may
+ * be larger than what the list is using.
+ */
+library dart.pkg.typed_data.typed_buffers;
+
+import "dart:collection" show ListBase;
+import "dart:typed_data";
+
+abstract class _TypedDataBuffer<E> extends ListBase<E> {
+  static const int INITIAL_LENGTH = 8;
+
+  /// This is a Uint8List for Uint8Buffer. It's both a List<E> and a TypedData,
+  /// which we don't have a type for here.
+  var _buffer;
+  /// The length of the list being built.
+  int _length;
+
+  _TypedDataBuffer(List<E> buffer)
+      : this._buffer = buffer, this._length = buffer.length;
+
+  int get length => _length;
+  E operator[](int index) {
+    if (index >= length) throw new RangeError.range(index, 0, length - 1);
+    return _buffer[index];
+  }
+
+  void operator[]=(int index, E value) {
+    if (index >= length) throw new RangeError.range(index, 0, length - 1);
+    _buffer[index] = value;
+  }
+
+  void set length(int newLength) {
+    if (newLength < _length) {
+      E defaultValue = _defaultValue;
+      for (int i = newLength; i < _length; i++) {
+        _buffer[i] = defaultValue;
+      }
+    } else if (newLength > _buffer.length) {
+      List<E> newBuffer;
+      if (_buffer.length == 0) {
+        newBuffer = _createBuffer(newLength);
+      } else {
+        newBuffer = _createBiggerBuffer(newLength);
+      }
+      newBuffer.setRange(0, _length, _buffer);
+      _buffer = newBuffer;
+    }
+    _length = newLength;
+  }
+
+  void _add(E value) {
+    if (_length == _buffer.length) _grow();
+    _buffer[_length++] = value;
+  }
+
+  // We override the default implementation of `add` and `addAll` because
+  // they grow by setting the length in increments of one. We want to grow
+  // by doubling capacity in most cases.
+  void add(E value) { _add(value); }
+
+  void addAll(Iterable<E> values) {
+    for (E value in values) _add(value);
+  }
+
+  void insert(int index, E element) {
+    if (index < 0 || index > _length) {
+      throw new RangeError.range(index, 0, _length);
+    }
+    if (_length < _buffer.length) {
+      _buffer.setRange(index + 1, _length + 1, _buffer, index);
+      _buffer[index] = element;
+      _length++;
+      return;
+    }
+    List<E> newBuffer = _createBiggerBuffer(null);
+    newBuffer.setRange(0, index, _buffer);
+    newBuffer.setRange(index + 1, _length + 1, _buffer, index);
+    newBuffer[index] = element;
+    _length++;
+    _buffer = newBuffer;
+  }
+
+  /**
+   * Create a bigger buffer.
+   *
+   * This method determines how much bigger a bigger buffer should
+   * be. If [requiredLength] is not null, it will be at least that
+   * size. It will always have at least have double the capacity of
+   * the current buffer.
+   */
+  List<E> _createBiggerBuffer(int requiredLength) {
+    int newLength = _buffer.length * 2;
+    if (requiredLength != null && newLength < requiredLength) {
+      newLength = requiredLength;
+    } else if (newLength < INITIAL_LENGTH) {
+      newLength = INITIAL_LENGTH;
+    }
+    return _createBuffer(newLength);
+  }
+
+  void _grow() {
+    _buffer = _createBiggerBuffer(null)..setRange(0, _length, _buffer);
+  }
+
+  void setRange(int start, int end, Iterable<E> source, [int skipCount = 0]) {
+    if (end > _length) throw new RangeError.range(end, 0, _length);
+    if (source is _TypedDataBuffer<E>) {
+      _buffer.setRange(start, end, source._buffer, skipCount);
+    } else {
+      _buffer.setRange(start, end, source, skipCount);
+    }
+  }
+
+  // TypedData.
+
+  int get elementSizeInBytes => _buffer.elementSizeInBytes;
+
+  int get lengthInBytes => _length * _buffer.elementSizeInBytes;
+
+  int get offsetInBytes => _buffer.offsetInBytes;
+
+  /**
+    * Returns the underlying [ByteBuffer].
+    *
+    * The returned buffer may be replaced by operations that change the [length]
+    * of this list.
+    *
+    * The buffer may be larger than [lengthInBytes] bytes, but never smaller.
+    */
+  ByteBuffer get buffer => _buffer.buffer;
+
+  // Specialization for the specific type.
+
+  // Return zero for integers, 0.0 for floats, etc.
+  // Used to fill buffer when changing length.
+  E get _defaultValue;
+
+  // Create a new typed list to use as buffer.
+  List<E> _createBuffer(int size);
+}
+
+abstract class _IntBuffer extends _TypedDataBuffer<int> {
+  _IntBuffer(buffer): super(buffer);
+  int get _defaultValue => 0;
+}
+
+abstract class _FloatBuffer extends _TypedDataBuffer<double> {
+  _FloatBuffer(buffer): super(buffer);
+  double get _defaultValue => 0.0;
+}
+
+class Uint8Buffer extends _IntBuffer {
+  Uint8Buffer([int initialLength = 0]) : super(new Uint8List(initialLength));
+  Uint8List _createBuffer(int size) => new Uint8List(size);
+}
+
+class Int8Buffer extends _IntBuffer {
+  Int8Buffer([int initialLength = 0]) : super(new Int8List(initialLength));
+  Int8List _createBuffer(int size) => new Int8List(size);
+}
+
+class Uint8ClampedBuffer extends _IntBuffer {
+  Uint8ClampedBuffer([int initialLength = 0])
+      : super(new Uint8ClampedList(initialLength));
+  Uint8ClampedList _createBuffer(int size) => new Uint8ClampedList(size);
+}
+
+class Uint16Buffer extends _IntBuffer {
+  Uint16Buffer([int initialLength = 0]) : super(new Uint16List(initialLength));
+  Uint16List _createBuffer(int size) => new Uint16List(size);
+}
+
+class Int16Buffer extends _IntBuffer {
+  Int16Buffer([int initialLength = 0]) : super(new Int16List(initialLength));
+  Int16List _createBuffer(int size) => new Int16List(size);
+}
+
+class Uint32Buffer extends _IntBuffer {
+  Uint32Buffer([int initialLength = 0]) : super(new Uint32List(initialLength));
+  Uint32List _createBuffer(int size) => new Uint32List(size);
+}
+
+class Int32Buffer extends _IntBuffer {
+  Int32Buffer([int initialLength = 0]) : super(new Int32List(initialLength));
+  Int32List _createBuffer(int size) => new Int32List(size);
+}
+
+class Uint64Buffer extends _IntBuffer {
+  Uint64Buffer([int initialLength = 0]) : super(new Uint64List(initialLength));
+  Uint64List _createBuffer(int size) => new Uint64List(size);
+}
+
+class Int64Buffer extends _IntBuffer {
+  Int64Buffer([int initialLength = 0]) : super(new Int64List(initialLength));
+  Int64List _createBuffer(int size) => new Int64List(size);
+}
+
+class Float32Buffer extends _FloatBuffer {
+  Float32Buffer([int initialLength = 0])
+      : super(new Float32List(initialLength));
+  Float32List _createBuffer(int size) => new Float32List(size);
+}
+
+class Float64Buffer extends _FloatBuffer {
+  Float64Buffer([int initialLength = 0])
+      : super(new Float64List(initialLength));
+  Float64List _createBuffer(int size) => new Float64List(size);
+}
+
+class Int32x4Buffer extends _TypedDataBuffer<Int32x4> {
+  static Int32x4 _zero = new Int32x4(0, 0, 0, 0);
+  Int32x4Buffer([int initialLength = 0])
+      : super(new Int32x4List(initialLength));
+  Int32x4 get _defaultValue => _zero;
+  Int32x4List _createBuffer(int size) => new Int32x4List(size);
+}
+
+class Float32x4Buffer extends _TypedDataBuffer<Float32x4> {
+  Float32x4Buffer([int initialLength = 0])
+      : super(new Float32x4List(initialLength));
+  Float32x4 get _defaultValue => new Float32x4.zero();
+  Float32x4List _createBuffer(int size) => new Float32x4List(size);
+}
diff --git a/pkg/typed_data/lib/typed_data.dart b/pkg/typed_data/lib/typed_data.dart
new file mode 100644
index 0000000..b6619ab
--- /dev/null
+++ b/pkg/typed_data/lib/typed_data.dart
@@ -0,0 +1,10 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/**
+ * Utilities and functionality related to the "dart:typed_data" library.
+ */
+library dart.pkg.typed_data;
+
+export "package:typed_data/typed_buffers.dart";
diff --git a/pkg/typed_data/pubspec.yaml b/pkg/typed_data/pubspec.yaml
new file mode 100644
index 0000000..af2e72a
--- /dev/null
+++ b/pkg/typed_data/pubspec.yaml
@@ -0,0 +1,9 @@
+name: typed_data
+version: 0.9.0
+author: Dart Team <misc@dartlang.org>
+description: Utility functions and classes related to the 'dart:typed_data' library.
+homepage: http://www.dartlang.org
+dev_dependencies:
+  unittest: ">=0.9.0 <0.10.0"
+environment:
+  sdk: ">=1.0.0 <2.0.0"
diff --git a/pkg/collection_helpers/test/typed_buffers_test.dart b/pkg/typed_data/test/typed_buffers_test.dart
similarity index 99%
rename from pkg/collection_helpers/test/typed_buffers_test.dart
rename to pkg/typed_data/test/typed_buffers_test.dart
index d8ba5d0..1cb37b0 100644
--- a/pkg/collection_helpers/test/typed_buffers_test.dart
+++ b/pkg/typed_data/test/typed_buffers_test.dart
@@ -4,7 +4,7 @@
 
 // Tests typed-data buffer classes.
 
-import "package:collection_helpers/all.dart";
+import "package:typed_data/typed_buffers.dart";
 import "package:unittest/unittest.dart";
 import "dart:typed_data";
 
diff --git a/pkg/unittest/lib/compact_vm_config.dart b/pkg/unittest/lib/compact_vm_config.dart
index 69560ac..c531d80 100644
--- a/pkg/unittest/lib/compact_vm_config.dart
+++ b/pkg/unittest/lib/compact_vm_config.dart
@@ -67,6 +67,20 @@
     }
   }
 
+  void onTestResultChanged(TestCase test) {
+    _pass--;
+    _fail++;
+    _progressLine(_start, _pass, _fail, test.description);
+    print('');
+    if (test.message != '') {
+      print(indent(test.message));
+    }
+
+    if (test.stackTrace != null) {
+      print(indent(test.stackTrace.toString()));
+    }
+  }
+
   void onDone(bool success) {
     // Override and don't call the superclass onDone() to avoid printing the
     // "unittest-suite-..." boilerplate.
diff --git a/pkg/unittest/lib/src/iterable_matchers.dart b/pkg/unittest/lib/src/iterable_matchers.dart
index ab7827f..2189286 100644
--- a/pkg/unittest/lib/src/iterable_matchers.dart
+++ b/pkg/unittest/lib/src/iterable_matchers.dart
@@ -108,69 +108,27 @@
     }
   }
 }
+
 /**
  * Returns a matcher which matches [Iterable]s that have the same
  * length and the same elements as [expected], but not necessarily in
  * the same order. Note that this is O(n^2) so should only be used on
  * small objects.
  */
-Matcher unorderedEquals(Iterable expected) =>
-    new _UnorderedEquals(expected);
+Matcher unorderedEquals(Iterable expected) => new _UnorderedEquals(expected);
 
-class _UnorderedEquals extends Matcher {
-  Iterable _expected;
+class _UnorderedEquals extends _UnorderedMatches {
+  final List _expectedValues;
 
-  _UnorderedEquals(Iterable this._expected);
-
-  String _test(item) {
-    if (item is !Iterable) {
-      return 'not iterable';
-    }
-    // Check the lengths are the same.
-    var expectedLength = _expected.length;
-    var actualLength = item.length;
-    if (expectedLength > actualLength) {
-      return 'has too few elements (${actualLength} < ${expectedLength})';
-    } else if (expectedLength < actualLength) {
-      return 'has too many elements (${actualLength} > ${expectedLength})';
-    }
-    List<bool> matched = new List<bool>(actualLength);
-    for (var i = 0; i < actualLength; i++) {
-      matched[i] = false;
-    }
-    var expectedPosition = 0;
-    for (var expectedElement in _expected) {
-      var actualPosition = 0;
-      var gotMatch = false;
-      for (var actualElement in item) {
-        if (!matched[actualPosition]) {
-          if (expectedElement == actualElement) {
-            matched[actualPosition] = gotMatch = true;
-            break;
-          }
-        }
-        ++actualPosition;
-      }
-      if (!gotMatch) {
-        Description reason = new StringDescription();
-        reason.add('has no match for element ').
-            addDescriptionOf(expectedElement).
-            add(' at index ${expectedPosition}');
-        return reason.toString();
-      }
-      ++expectedPosition;
-    }
-    return null;
-  }
-
-  bool matches(item, Map mismatchState) => (_test(item) == null);
+  _UnorderedEquals(Iterable expected)
+      : super(expected.map(equals)),
+        _expectedValues = expected.toList();
 
   Description describe(Description description) =>
-      description.add('equals ').addDescriptionOf(_expected).add(' unordered');
-
-  Description describeMismatch(item, Description mismatchDescription,
-                               Map matchState, bool verbose) =>
-      mismatchDescription.add(_test(item));
+    description
+        .add('equals ')
+        .addDescriptionOf(_expectedValues)
+        .add(' unordered');
 }
 
 /**
@@ -193,6 +151,73 @@
 }
 
 /**
+ * Returns a matcher which matches [Iterable]s whose elements match the matchers
+ * in [expected], but not necessarily in the same order.
+ *
+ *  Note that this is `O(n^2)` and so should only be used on small objects.
+ */
+Matcher unorderedMatches(Iterable expected) =>
+    new _UnorderedMatches(expected);
+
+class _UnorderedMatches extends Matcher {
+  final List<Matcher> _expected;
+
+  _UnorderedMatches(Iterable expected)
+      : _expected = expected.map(wrapMatcher).toList();
+
+  String _test(item) {
+    if (item is !Iterable) return 'not iterable';
+    item = item.toList();
+
+    // Check the lengths are the same.
+    if (_expected.length > item.length) {
+      return 'has too few elements (${item.length} < ${_expected.length})';
+    } else if (_expected.length < item.length) {
+      return 'has too many elements (${item.length} > ${_expected.length})';
+    }
+
+    var matched = new List<bool>.filled(item.length, false);
+    var expectedPosition = 0;
+    for (var expectedMatcher in _expected) {
+      var actualPosition = 0;
+      var gotMatch = false;
+      for (var actualElement in item) {
+        if (!matched[actualPosition]) {
+          if (expectedMatcher.matches(actualElement, {})) {
+            matched[actualPosition] = gotMatch = true;
+            break;
+          }
+        }
+        ++actualPosition;
+      }
+
+      if (!gotMatch) {
+        return new StringDescription()
+            .add('has no match for ')
+            .addDescriptionOf(expectedMatcher)
+            .add(' at index ${expectedPosition}')
+            .toString();
+      }
+
+      ++expectedPosition;
+    }
+    return null;
+  }
+
+  bool matches(item, Map mismatchState) => _test(item) == null;
+
+  Description describe(Description description) =>
+    description
+      .add('matches ')
+      .addAll('[', ', ', ']', _expected)
+      .add(' unordered');
+
+  Description describeMismatch(item, Description mismatchDescription,
+                               Map matchState, bool verbose) =>
+      mismatchDescription.add(_test(item));
+}
+
+/**
  * A pairwise matcher for iterable. You can pass an arbitrary [comparator]
  * function that takes an expected and actual argument which will be applied
  * to each pair in order. [description]  should be a meaningful name for
diff --git a/pkg/unittest/pubspec.yaml b/pkg/unittest/pubspec.yaml
index dd67528..f1c1d4a 100644
--- a/pkg/unittest/pubspec.yaml
+++ b/pkg/unittest/pubspec.yaml
@@ -1,5 +1,5 @@
 name: unittest
-version: 0.9.1
+version: 0.9.2+1
 author: Dart Team <misc@dartlang.org>
 description: A library for writing dart unit tests.
 homepage: http://www.dartlang.org
diff --git a/pkg/unittest/test/matchers_test.dart b/pkg/unittest/test/matchers_test.dart
index 1ec1e92..9f8e121 100644
--- a/pkg/unittest/test/matchers_test.dart
+++ b/pkg/unittest/test/matchers_test.dart
@@ -481,7 +481,30 @@
       shouldFail(d, unorderedEquals([3, 1]),
           "Expected: equals [3, 1] unordered "
           "Actual: [1, 2] "
-          "Which: has no match for element <3> at index 0");
+          "Which: has no match for <3> at index 0");
+    });
+
+    test('unorderedMatchess', () {
+      var d = [1, 2];
+      shouldPass(d, unorderedMatches([2, 1]));
+      shouldPass(d, unorderedMatches([greaterThan(1), greaterThan(0)]));
+      shouldFail(d, unorderedMatches([greaterThan(0)]),
+          "Expected: matches [a value greater than <0>] unordered "
+          "Actual: [1, 2] "
+          "Which: has too many elements (2 > 1)");
+      shouldFail(d, unorderedMatches([3, 2, 1]),
+          "Expected: matches [<3>, <2>, <1>] unordered "
+          "Actual: [1, 2] "
+          "Which: has too few elements (2 < 3)");
+      shouldFail(d, unorderedMatches([3, 1]),
+          "Expected: matches [<3>, <1>] unordered "
+          "Actual: [1, 2] "
+          "Which: has no match for <3> at index 0");
+      shouldFail(d, unorderedMatches([greaterThan(3), greaterThan(0)]),
+          "Expected: matches [a value greater than <3>, a value greater than "
+              "<0>] unordered "
+          "Actual: [1, 2] "
+          "Which: has no match for a value greater than <3> at index 0");
     });
 
     test('pairwise compare', () {
diff --git a/pkg/unmodifiable_collection/lib/unmodifiable_collection.dart b/pkg/unmodifiable_collection/lib/unmodifiable_collection.dart
index 17e24e5..428bb7d 100644
--- a/pkg/unmodifiable_collection/lib/unmodifiable_collection.dart
+++ b/pkg/unmodifiable_collection/lib/unmodifiable_collection.dart
@@ -5,18 +5,18 @@
 /**
  * This library used to introduce unmodifiable wrappers for collections.
  *
- * This functionality has been moved to the `collection_helpers` library.
+ * This functionality has been moved to the `collection` library.
  *
  * Please replace the import of this library with:
  *
- *     import "package:collection_helpers/wrappers.dart";
+ *     import "package:collection/wrappers.dart";
  *
  * and change dependencies to match.
  */
 @deprecated
 library unmodifiable_collection;
 
-export "package:collection_helpers/wrappers.dart"
+export "package:collection/wrappers.dart"
     show UnmodifiableListView,
          UnmodifiableSetView,
          UnmodifiableMapView,
diff --git a/pkg/unmodifiable_collection/pubspec.yaml b/pkg/unmodifiable_collection/pubspec.yaml
index b4ee459..2e59d7a 100644
--- a/pkg/unmodifiable_collection/pubspec.yaml
+++ b/pkg/unmodifiable_collection/pubspec.yaml
@@ -1,12 +1,12 @@
 name: unmodifiable_collection
-version: 0.9.1
+version: 0.9.2
 author: "Dart Team <misc@dartlang.org>"
 homepage: http://www.dartlang.org
 documentation: http://api.dartlang.org/docs/pkg/unmodifiable_collection
 description: >
- Discontinued library. Use package:collection_helpers/wrappers.dart instead.
+ Discontinued library. Use package:collection/wrappers.dart instead.
 
 dependencies:
-  collection_helpers: ">=0.9.0 <0.10.0"
+  collection: ">=0.9.0 <0.10.0"
 environment:
   sdk: ">=0.8.10+6 <2.0.0"
diff --git a/runtime/bin/builtin.h b/runtime/bin/builtin.h
index 90a121e..a4d8a13 100644
--- a/runtime/bin/builtin.h
+++ b/runtime/bin/builtin.h
@@ -54,7 +54,8 @@
 
   // Native method support.
   static Dart_NativeFunction NativeLookup(Dart_Handle name,
-                                          int argument_count);
+                                          int argument_count,
+                                          bool* auto_setup_scope);
 
   static const char* builtin_source_paths_[];
   static const char* io_source_paths_[];
diff --git a/runtime/bin/builtin_gen_snapshot.cc b/runtime/bin/builtin_gen_snapshot.cc
index 9a89adb..965a862 100644
--- a/runtime/bin/builtin_gen_snapshot.cc
+++ b/runtime/bin/builtin_gen_snapshot.cc
@@ -29,11 +29,14 @@
 
 
 Dart_NativeFunction Builtin::NativeLookup(Dart_Handle name,
-                                          int argument_count) {
+                                          int argument_count,
+                                          bool* auto_setup_scope) {
   const char* function_name = NULL;
   Dart_Handle result = Dart_StringToCString(name, &function_name);
   DART_CHECK_VALID(result);
   ASSERT(function_name != NULL);
+  ASSERT(auto_setup_scope != NULL);
+  *auto_setup_scope = true;
   int num_entries = sizeof(BuiltinEntries) / sizeof(struct NativeEntries);
   for (int i = 0; i < num_entries; i++) {
     struct NativeEntries* entry = &(BuiltinEntries[i]);
diff --git a/runtime/bin/builtin_natives.cc b/runtime/bin/builtin_natives.cc
index ca3d8a3..5681c0a 100644
--- a/runtime/bin/builtin_natives.cc
+++ b/runtime/bin/builtin_natives.cc
@@ -54,6 +54,7 @@
   V(File_Delete, 1)                                                            \
   V(File_DeleteLink, 1)                                                        \
   V(File_Rename, 2)                                                            \
+  V(File_Copy, 2)                                                              \
   V(File_RenameLink, 2)                                                        \
   V(File_ResolveSymbolicLinks, 1)                                              \
   V(File_OpenStdio, 1)                                                         \
@@ -84,11 +85,14 @@
  * Looks up native functions in both libdart_builtin and libdart_io.
  */
 Dart_NativeFunction Builtin::NativeLookup(Dart_Handle name,
-                                          int argument_count) {
+                                          int argument_count,
+                                          bool* auto_setup_scope) {
   const char* function_name = NULL;
   Dart_Handle result = Dart_StringToCString(name, &function_name);
   DART_CHECK_VALID(result);
   ASSERT(function_name != NULL);
+  ASSERT(auto_setup_scope != NULL);
+  *auto_setup_scope = true;
   int num_entries = sizeof(BuiltinEntries) / sizeof(struct NativeEntries);
   for (int i = 0; i < num_entries; i++) {
     struct NativeEntries* entry = &(BuiltinEntries[i]);
@@ -97,7 +101,7 @@
       return reinterpret_cast<Dart_NativeFunction>(entry->function_);
     }
   }
-  return IONativeLookup(name, argument_count);
+  return IONativeLookup(name, argument_count, auto_setup_scope);
 }
 
 
diff --git a/runtime/bin/dbg_message.cc b/runtime/bin/dbg_message.cc
index 5912c31..55f2db4 100644
--- a/runtime/bin/dbg_message.cc
+++ b/runtime/bin/dbg_message.cc
@@ -1017,27 +1017,54 @@
 }
 
 
-void DbgMsgQueue::HandleMessages() {
-  bool resume_requested = false;
+void DbgMsgQueue::Notify() {
   MonitorLocker ml(&msg_queue_lock_);
-  is_running_ = false;
-  while (!resume_requested) {
-    while (msglist_head_ == NULL) {
-      ASSERT(msglist_tail_ == NULL);
-      dart::Monitor::WaitResult res = ml.Wait();  // Wait for debugger commands.
-      ASSERT(res == dart::Monitor::kNotified);
-    }
-    while (msglist_head_ != NULL && !resume_requested) {
-      ASSERT(msglist_tail_ != NULL);
-      DbgMessage* msg = msglist_head_;
-      msglist_head_ = msglist_head_->next();
-      resume_requested = msg->HandleMessage();
-      delete msg;
-    }
+  ml.Notify();
+}
+
+
+bool DbgMsgQueue::HandlePendingMessages() {
+  // Handle all available debug messages, up to a resume request.
+  bool resume_requested = false;
+  while (msglist_head_ != NULL && !resume_requested) {
+    ASSERT(msglist_tail_ != NULL);
+    DbgMessage* msg = msglist_head_;
+    msglist_head_ = msglist_head_->next();
     if (msglist_head_ == NULL) {
       msglist_tail_ = NULL;
     }
+    resume_requested = msg->HandleMessage();
+    delete msg;
   }
+  return resume_requested;
+}
+
+
+void DbgMsgQueue::MessageLoop() {
+  MonitorLocker ml(&msg_queue_lock_);
+  is_running_ = false;
+
+  // Request notification on isolate messages.  This allows us to
+  // respond to vm service messages while at breakpoint.
+  Dart_SetMessageNotifyCallback(DbgMsgQueueList::NotifyIsolate);
+
+  while (true) {
+    // Handle all available vm service messages, up to a resume
+    // request.
+    if (Dart_HandleServiceMessages()) {
+      break;
+    }
+
+    // Handle all available debug messages, up to a resume request.
+    if (HandlePendingMessages()) {
+      break;
+    }
+
+    // Wait for more debug or vm service messages.
+    dart::Monitor::WaitResult res = ml.Wait();
+    ASSERT(res == dart::Monitor::kNotified);
+  }
+  Dart_SetMessageNotifyCallback(NULL);
   is_interrupted_ = false;
   is_running_ = true;
 }
@@ -1177,6 +1204,16 @@
 }
 
 
+void DbgMsgQueueList::NotifyIsolate(Dart_Isolate isolate) {
+  MutexLocker ml(msg_queue_list_lock_);
+  Dart_IsolateId isolate_id = Dart_GetIsolateId(isolate);
+  DbgMsgQueue* queue = DbgMsgQueueList::GetIsolateMsgQueueLocked(isolate_id);
+  if (queue != NULL) {
+    queue->Notify();
+  }
+}
+
+
 bool DbgMsgQueueList::InterruptIsolate(Dart_IsolateId isolate_id) {
   MutexLocker ml(msg_queue_list_lock_);
   DbgMsgQueue* queue = DbgMsgQueueList::GetIsolateMsgQueueLocked(isolate_id);
@@ -1293,7 +1330,7 @@
   ASSERT(msg_queue != NULL);
   msg_queue->SendQueuedMsgs();
   msg_queue->SendBreakpointEvent(bp_id, loc);
-  msg_queue->HandleMessages();
+  msg_queue->MessageLoop();
   Dart_ExitScope();
 }
 
@@ -1307,7 +1344,7 @@
   ASSERT(msg_queue != NULL);
   msg_queue->SendQueuedMsgs();
   msg_queue->SendExceptionEvent(exception, stack_trace);
-  msg_queue->HandleMessages();
+  msg_queue->MessageLoop();
   Dart_ExitScope();
 }
 
@@ -1325,7 +1362,7 @@
     msg_queue->SendQueuedMsgs();
     msg_queue->SendIsolateEvent(isolate_id, kind);
     if (kind == kInterrupted) {
-      msg_queue->HandleMessages();
+      msg_queue->MessageLoop();
     } else {
       ASSERT(kind == kShutdown);
       RemoveIsolateMsgQueue(isolate_id);
diff --git a/runtime/bin/dbg_message.h b/runtime/bin/dbg_message.h
index 79551ee..23c08fc 100644
--- a/runtime/bin/dbg_message.h
+++ b/runtime/bin/dbg_message.h
@@ -161,8 +161,16 @@
                   const char* end,
                   int debug_fd);
 
-  // Handle all debug command messages in the queue.
-  void HandleMessages();
+  // Notify an isolate of a pending vmservice message.
+  void Notify();
+
+  // Run a message loop which handles messages as they arrive until
+  // normal program execution resumes.
+  void MessageLoop();
+
+  // Handle any pending debug command messages in the queue.  Return
+  // value indicates whether a resume has been requested.
+  bool HandlePendingMessages();
 
   // Interrupt Isolate.
   void InterruptIsolate();
@@ -225,6 +233,9 @@
                                 const char* end,
                                 int debug_fd);
 
+  // Notify an isolate of a pending vmservice message.
+  static void NotifyIsolate(Dart_Isolate isolate);
+
   // Interrupt isolate.
   static bool InterruptIsolate(Dart_IsolateId isolate_id);
 
diff --git a/runtime/bin/eventhandler_linux.cc b/runtime/bin/eventhandler_linux.cc
index 335238c..0db1f53 100644
--- a/runtime/bin/eventhandler_linux.cc
+++ b/runtime/bin/eventhandler_linux.cc
@@ -134,8 +134,7 @@
   if (status == -1) {
     FATAL("Failed adding interrupt fd to epoll instance");
   }
-  timer_fd_ = TEMP_FAILURE_RETRY(timerfd_create(CLOCK_REALTIME,
-                                                TFD_NONBLOCK | TFD_CLOEXEC));
+  timer_fd_ = TEMP_FAILURE_RETRY(timerfd_create(CLOCK_REALTIME, TFD_CLOEXEC));
   if (epoll_fd_ == -1) {
     FATAL("Failed creating timerfd file descriptor");
   }
@@ -147,7 +146,8 @@
                                         timer_fd_,
                                         &event));
   if (status == -1) {
-    FATAL("Failed adding timerfd fd to epoll instance");
+    FATAL2(
+        "Failed adding timerfd fd(%i) to epoll instance: %i", timer_fd_, errno);
   }
 }
 
diff --git a/runtime/bin/eventhandler_win.cc b/runtime/bin/eventhandler_win.cc
index 7b5d66a..b6ac1ce 100644
--- a/runtime/bin/eventhandler_win.cc
+++ b/runtime/bin/eventhandler_win.cc
@@ -429,7 +429,6 @@
 
 bool ListenSocket::IssueAccept() {
   ScopedLock lock(this);
-
   // For AcceptEx there needs to be buffer storage for address
   // information for two addresses (local and remote address). The
   // AcceptEx documentation says: "This value must be at least 16
@@ -452,9 +451,10 @@
                  buffer->GetCleanOverlapped());
   if (!ok) {
     if (WSAGetLastError() != WSA_IO_PENDING) {
-      Log::PrintErr("AcceptEx failed: %d\n", WSAGetLastError());
+      int error = WSAGetLastError();
       closesocket(buffer->client());
       OverlappedBuffer::DisposeBuffer(buffer);
+      WSASetLastError(error);
       return false;
     }
   }
@@ -972,7 +972,11 @@
         }
         // Always keep 5 outstanding accepts going, to enhance performance.
         while (listen_socket->pending_accept_count() < 5) {
-          listen_socket->IssueAccept();
+          bool accept_success = listen_socket->IssueAccept();
+          if (!accept_success) {
+            HandleError(listen_socket);
+            break;
+          }
         }
       }
 
diff --git a/runtime/bin/file.cc b/runtime/bin/file.cc
index f0205fb..7f40f96 100644
--- a/runtime/bin/file.cc
+++ b/runtime/bin/file.cc
@@ -262,7 +262,6 @@
 
   // Write the data out into the file.
   int64_t bytes_written = file->Write(reinterpret_cast<void*>(buffer), length);
-
   // Release the direct pointer acquired above.
   result = Dart_TypedDataReleaseData(buffer_obj);
   if (Dart_IsError(result)) Dart_PropagateError(result);
@@ -503,6 +502,22 @@
 }
 
 
+void FUNCTION_NAME(File_Copy)(Dart_NativeArguments args) {
+  const char* old_path =
+      DartUtils::GetStringValue(Dart_GetNativeArgument(args, 0));
+  const char* new_path =
+      DartUtils::GetStringValue(Dart_GetNativeArgument(args, 1));
+  bool result = File::Copy(old_path, new_path);
+  if (result) {
+    Dart_SetReturnValue(args, Dart_NewBoolean(result));
+  } else {
+    Dart_Handle err = DartUtils::NewDartOSError();
+    if (Dart_IsError(err)) Dart_PropagateError(err);
+    Dart_SetReturnValue(args, err);
+  }
+}
+
+
 void FUNCTION_NAME(File_ResolveSymbolicLinks)(Dart_NativeArguments args) {
   const char* str =
       DartUtils::GetStringValue(Dart_GetNativeArgument(args, 0));
@@ -706,6 +721,20 @@
 }
 
 
+CObject* File::CopyRequest(const CObjectArray& request) {
+  if (request.Length() == 2 &&
+      request[0]->IsString() &&
+      request[1]->IsString()) {
+    CObjectString old_path(request[0]);
+    CObjectString new_path(request[1]);
+    bool completed = File::Copy(old_path.CString(), new_path.CString());
+    if (completed) return CObject::True();
+    return CObject::NewOSError();
+  }
+  return CObject::IllegalArgumentError();
+}
+
+
 CObject* File::ResolveSymbolicLinksRequest(const CObjectArray& request) {
   if (request.Length() == 1 && request[0]->IsString()) {
     CObjectString filename(request[0]);
diff --git a/runtime/bin/file.h b/runtime/bin/file.h
index 1f3eb11..ec1bac8 100644
--- a/runtime/bin/file.h
+++ b/runtime/bin/file.h
@@ -126,6 +126,7 @@
   static bool DeleteLink(const char* path);
   static bool Rename(const char* old_path, const char* new_path);
   static bool RenameLink(const char* old_path, const char* new_path);
+  static bool Copy(const char* old_path, const char* new_path);
   static off64_t LengthFromPath(const char* path);
   static void Stat(const char* path, int64_t* data);
   static time_t LastModified(const char* path);
@@ -144,6 +145,7 @@
   static CObject* CreateRequest(const CObjectArray& request);
   static CObject* DeleteRequest(const CObjectArray& request);
   static CObject* RenameRequest(const CObjectArray& request);
+  static CObject* CopyRequest(const CObjectArray& request);
   static CObject* OpenRequest(const CObjectArray& request);
   static CObject* ResolveSymbolicLinksRequest(const CObjectArray& request);
   static CObject* CloseRequest(const CObjectArray& request);
diff --git a/runtime/bin/file_android.cc b/runtime/bin/file_android.cc
index 917e83e..3851c32 100644
--- a/runtime/bin/file_android.cc
+++ b/runtime/bin/file_android.cc
@@ -11,11 +11,13 @@
 #include <fcntl.h>  // NOLINT
 #include <sys/stat.h>  // NOLINT
 #include <sys/types.h>  // NOLINT
+#include <sys/sendfile.h>  // NOLINT
 #include <unistd.h>  // NOLINT
 #include <libgen.h>  // NOLINT
 
 #include "bin/builtin.h"
 #include "bin/log.h"
+#include "bin/signal_blocker.h"
 
 
 namespace dart {
@@ -46,7 +48,7 @@
 
 void File::Close() {
   ASSERT(handle_->fd() >= 0);
-  int err = TEMP_FAILURE_RETRY(close(handle_->fd()));
+  int err = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(close(handle_->fd()));
   if (err != 0) {
     const int kBufferSize = 1024;
     char error_message[kBufferSize];
@@ -64,13 +66,15 @@
 
 int64_t File::Read(void* buffer, int64_t num_bytes) {
   ASSERT(handle_->fd() >= 0);
-  return TEMP_FAILURE_RETRY(read(handle_->fd(), buffer, num_bytes));
+  return TEMP_FAILURE_RETRY_BLOCK_SIGNALS(read(handle_->fd(), buffer,
+                                               num_bytes));
 }
 
 
 int64_t File::Write(const void* buffer, int64_t num_bytes) {
   ASSERT(handle_->fd() >= 0);
-  return TEMP_FAILURE_RETRY(write(handle_->fd(), buffer, num_bytes));
+  return TEMP_FAILURE_RETRY_BLOCK_SIGNALS(write(handle_->fd(), buffer,
+                                                num_bytes));
 }
 
 
@@ -88,20 +92,21 @@
 
 bool File::Truncate(off64_t length) {
   ASSERT(handle_->fd() >= 0);
-  return TEMP_FAILURE_RETRY(ftruncate(handle_->fd(), length) != -1);
+  return TEMP_FAILURE_RETRY_BLOCK_SIGNALS(
+      ftruncate(handle_->fd(), length) != -1);
 }
 
 
 bool File::Flush() {
   ASSERT(handle_->fd() >= 0);
-  return TEMP_FAILURE_RETRY(fsync(handle_->fd()) != -1);
+  return TEMP_FAILURE_RETRY_BLOCK_SIGNALS(fsync(handle_->fd()) != -1);
 }
 
 
 off64_t File::Length() {
   ASSERT(handle_->fd() >= 0);
   struct stat st;
-  if (TEMP_FAILURE_RETRY(fstat(handle_->fd(), &st)) == 0) {
+  if (TEMP_FAILURE_RETRY_BLOCK_SIGNALS(fstat(handle_->fd(), &st)) == 0) {
     return st.st_size;
   }
   return -1;
@@ -111,7 +116,7 @@
 File* File::Open(const char* name, FileOpenMode mode) {
   // Report errors for non-regular files.
   struct stat st;
-  if (TEMP_FAILURE_RETRY(stat(name, &st)) == 0) {
+  if (TEMP_FAILURE_RETRY_BLOCK_SIGNALS(stat(name, &st)) == 0) {
     if (!S_ISREG(st.st_mode)) {
       errno = (S_ISDIR(st.st_mode)) ? EISDIR : ENOENT;
       return NULL;
@@ -125,7 +130,7 @@
     flags = flags | O_TRUNC;
   }
   flags |= O_CLOEXEC;
-  int fd = TEMP_FAILURE_RETRY(open(name, flags, 0666));
+  int fd = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(open(name, flags, 0666));
   if (fd < 0) {
     return NULL;
   }
@@ -147,7 +152,7 @@
 
 bool File::Exists(const char* name) {
   struct stat st;
-  if (TEMP_FAILURE_RETRY(stat(name, &st)) == 0) {
+  if (TEMP_FAILURE_RETRY_BLOCK_SIGNALS(stat(name, &st)) == 0) {
     return S_ISREG(st.st_mode);
   } else {
     return false;
@@ -156,7 +161,9 @@
 
 
 bool File::Create(const char* name) {
-  int fd = TEMP_FAILURE_RETRY(open(name, O_RDONLY | O_CREAT | O_CLOEXEC, 0666));
+  int fd = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(open(name,
+                                                 O_RDONLY | O_CREAT | O_CLOEXEC,
+                                                 0666));
   if (fd < 0) {
     return false;
   }
@@ -165,7 +172,7 @@
 
 
 bool File::CreateLink(const char* name, const char* target) {
-  int status = TEMP_FAILURE_RETRY(symlink(target, name));
+  int status = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(symlink(target, name));
   return (status == 0);
 }
 
@@ -173,7 +180,7 @@
 bool File::Delete(const char* name) {
   File::Type type = File::GetType(name, true);
   if (type == kIsFile) {
-    return TEMP_FAILURE_RETRY(unlink(name)) == 0;
+    return TEMP_FAILURE_RETRY_BLOCK_SIGNALS(unlink(name)) == 0;
   } else if (type == kIsDirectory) {
     errno = EISDIR;
   } else {
@@ -186,7 +193,7 @@
 bool File::DeleteLink(const char* name) {
   File::Type type = File::GetType(name, false);
   if (type == kIsLink) {
-    return TEMP_FAILURE_RETRY(unlink(name)) == 0;
+    return TEMP_FAILURE_RETRY_BLOCK_SIGNALS(unlink(name)) == 0;
   }
   errno = EINVAL;
   return false;
@@ -196,7 +203,7 @@
 bool File::Rename(const char* old_path, const char* new_path) {
   File::Type type = File::GetType(old_path, true);
   if (type == kIsFile) {
-    return TEMP_FAILURE_RETRY(rename(old_path, new_path)) == 0;
+    return TEMP_FAILURE_RETRY_BLOCK_SIGNALS(rename(old_path, new_path)) == 0;
   } else if (type == kIsDirectory) {
     errno = EISDIR;
   } else {
@@ -209,7 +216,7 @@
 bool File::RenameLink(const char* old_path, const char* new_path) {
   File::Type type = File::GetType(old_path, false);
   if (type == kIsLink) {
-    return TEMP_FAILURE_RETRY(rename(old_path, new_path)) == 0;
+    return TEMP_FAILURE_RETRY_BLOCK_SIGNALS(rename(old_path, new_path)) == 0;
   } else if (type == kIsDirectory) {
     errno = EISDIR;
   } else {
@@ -219,9 +226,68 @@
 }
 
 
+bool File::Copy(const char* old_path, const char* new_path) {
+  File::Type type = File::GetType(old_path, true);
+  if (type == kIsFile) {
+    struct stat st;
+    if (TEMP_FAILURE_RETRY_BLOCK_SIGNALS(stat(old_path, &st)) != 0) {
+      return false;
+    }
+    int old_fd = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(open(old_path,
+                                                       O_RDONLY | O_CLOEXEC));
+    if (old_fd < 0) {
+      return false;
+    }
+    int new_fd = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(
+        open(new_path, O_WRONLY | O_TRUNC | O_CREAT | O_CLOEXEC, st.st_mode));
+    if (new_fd < 0) {
+      VOID_TEMP_FAILURE_RETRY_BLOCK_SIGNALS(close(old_fd));
+      return false;
+    }
+    off_t offset = 0;
+    int result = 1;
+    while (result > 0) {
+      // Loop to ensure we copy everything, and not only up to 2GB.
+      result = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(
+          sendfile(new_fd, old_fd, &offset, kMaxUint32));
+    }
+    // From sendfile man pages:
+    //   Applications may wish to fall back to read(2)/write(2) in the case
+    //   where sendfile() fails with EINVAL or ENOSYS.
+    if (result < 0 && (errno == EINVAL || errno == ENOSYS)) {
+      const intptr_t kBufferSize = 8 * KB;
+      uint8_t buffer[kBufferSize];
+      while ((result = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(
+          read(old_fd, buffer, kBufferSize))) > 0) {
+        int wrote = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(write(new_fd, buffer,
+                                                           result));
+        if (wrote != result) {
+          result = -1;
+          break;
+        }
+      }
+    }
+    if (result < 0) {
+      int e = errno;
+      VOID_TEMP_FAILURE_RETRY_BLOCK_SIGNALS(close(old_fd));
+      VOID_TEMP_FAILURE_RETRY_BLOCK_SIGNALS(close(new_fd));
+      VOID_TEMP_FAILURE_RETRY_BLOCK_SIGNALS(unlink(new_path));
+      errno = e;
+      return false;
+    }
+    return true;
+  } else if (type == kIsDirectory) {
+    errno = EISDIR;
+  } else {
+    errno = ENOENT;
+  }
+  return false;
+}
+
+
 off64_t File::LengthFromPath(const char* name) {
   struct stat st;
-  if (TEMP_FAILURE_RETRY(stat(name, &st)) == 0) {
+  if (TEMP_FAILURE_RETRY_BLOCK_SIGNALS(stat(name, &st)) == 0) {
     return st.st_size;
   }
   return -1;
@@ -230,7 +296,7 @@
 
 void File::Stat(const char* name, int64_t* data) {
   struct stat st;
-  if (TEMP_FAILURE_RETRY(stat(name, &st)) == 0) {
+  if (TEMP_FAILURE_RETRY_BLOCK_SIGNALS(stat(name, &st)) == 0) {
     if (S_ISREG(st.st_mode)) {
       data[kType] = kIsFile;
     } else if (S_ISDIR(st.st_mode)) {
@@ -253,7 +319,7 @@
 
 time_t File::LastModified(const char* name) {
   struct stat st;
-  if (TEMP_FAILURE_RETRY(stat(name, &st)) == 0) {
+  if (TEMP_FAILURE_RETRY_BLOCK_SIGNALS(stat(name, &st)) == 0) {
     return st.st_mtime;
   }
   return -1;
@@ -335,9 +401,11 @@
   struct stat entry_info;
   int stat_success;
   if (follow_links) {
-    stat_success = TEMP_FAILURE_RETRY(stat(pathname, &entry_info));
+    stat_success = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(stat(pathname,
+                                                         &entry_info));
   } else {
-    stat_success = TEMP_FAILURE_RETRY(lstat(pathname, &entry_info));
+    stat_success = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(lstat(pathname,
+                                                          &entry_info));
   }
   if (stat_success == -1) return File::kDoesNotExist;
   if (S_ISDIR(entry_info.st_mode)) return File::kIsDirectory;
@@ -350,8 +418,8 @@
 File::Identical File::AreIdentical(const char* file_1, const char* file_2) {
   struct stat file_1_info;
   struct stat file_2_info;
-  if (TEMP_FAILURE_RETRY(lstat(file_1, &file_1_info)) == -1 ||
-      TEMP_FAILURE_RETRY(lstat(file_2, &file_2_info)) == -1) {
+  if (TEMP_FAILURE_RETRY_BLOCK_SIGNALS(lstat(file_1, &file_1_info)) == -1 ||
+      TEMP_FAILURE_RETRY_BLOCK_SIGNALS(lstat(file_2, &file_2_info)) == -1) {
     return File::kError;
   }
   return (file_1_info.st_ino == file_2_info.st_ino &&
diff --git a/runtime/bin/file_linux.cc b/runtime/bin/file_linux.cc
index f5db4e5..b4c2b31 100644
--- a/runtime/bin/file_linux.cc
+++ b/runtime/bin/file_linux.cc
@@ -11,11 +11,13 @@
 #include <fcntl.h>  // NOLINT
 #include <sys/stat.h>  // NOLINT
 #include <sys/types.h>  // NOLINT
+#include <sys/sendfile.h>  // NOLINT
 #include <unistd.h>  // NOLINT
 #include <libgen.h>  // NOLINT
 
 #include "bin/builtin.h"
 #include "bin/log.h"
+#include "bin/signal_blocker.h"
 
 
 namespace dart {
@@ -46,7 +48,7 @@
 
 void File::Close() {
   ASSERT(handle_->fd() >= 0);
-  int err = TEMP_FAILURE_RETRY(close(handle_->fd()));
+  int err = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(close(handle_->fd()));
   if (err != 0) {
     const int kBufferSize = 1024;
     char error_buf[kBufferSize];
@@ -63,13 +65,15 @@
 
 int64_t File::Read(void* buffer, int64_t num_bytes) {
   ASSERT(handle_->fd() >= 0);
-  return TEMP_FAILURE_RETRY(read(handle_->fd(), buffer, num_bytes));
+  return TEMP_FAILURE_RETRY_BLOCK_SIGNALS(read(handle_->fd(), buffer,
+                                               num_bytes));
 }
 
 
 int64_t File::Write(const void* buffer, int64_t num_bytes) {
   ASSERT(handle_->fd() >= 0);
-  return TEMP_FAILURE_RETRY(write(handle_->fd(), buffer, num_bytes));
+  return TEMP_FAILURE_RETRY_BLOCK_SIGNALS(write(handle_->fd(), buffer,
+                                                num_bytes));
 }
 
 
@@ -87,20 +91,21 @@
 
 bool File::Truncate(off64_t length) {
   ASSERT(handle_->fd() >= 0);
-  return TEMP_FAILURE_RETRY(ftruncate64(handle_->fd(), length) != -1);
+  return TEMP_FAILURE_RETRY_BLOCK_SIGNALS(
+      ftruncate64(handle_->fd(), length) != -1);
 }
 
 
 bool File::Flush() {
   ASSERT(handle_->fd() >= 0);
-  return TEMP_FAILURE_RETRY(fsync(handle_->fd()) != -1);
+  return TEMP_FAILURE_RETRY_BLOCK_SIGNALS(fsync(handle_->fd()) != -1);
 }
 
 
 off64_t File::Length() {
   ASSERT(handle_->fd() >= 0);
   struct stat64 st;
-  if (TEMP_FAILURE_RETRY(fstat64(handle_->fd(), &st)) == 0) {
+  if (TEMP_FAILURE_RETRY_BLOCK_SIGNALS(fstat64(handle_->fd(), &st)) == 0) {
     return st.st_size;
   }
   return -1;
@@ -110,7 +115,7 @@
 File* File::Open(const char* name, FileOpenMode mode) {
   // Report errors for non-regular files.
   struct stat64 st;
-  if (TEMP_FAILURE_RETRY(stat64(name, &st)) == 0) {
+  if (TEMP_FAILURE_RETRY_BLOCK_SIGNALS(stat64(name, &st)) == 0) {
     // Only accept regular files and character devices.
     if (!S_ISREG(st.st_mode) && !S_ISCHR(st.st_mode)) {
       errno = (S_ISDIR(st.st_mode)) ? EISDIR : ENOENT;
@@ -125,7 +130,7 @@
     flags = flags | O_TRUNC;
   }
   flags |= O_CLOEXEC;
-  int fd = TEMP_FAILURE_RETRY(open64(name, flags, 0666));
+  int fd = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(open64(name, flags, 0666));
   if (fd < 0) {
     return NULL;
   }
@@ -147,7 +152,7 @@
 
 bool File::Exists(const char* name) {
   struct stat64 st;
-  if (TEMP_FAILURE_RETRY(stat64(name, &st)) == 0) {
+  if (TEMP_FAILURE_RETRY_BLOCK_SIGNALS(stat64(name, &st)) == 0) {
     return S_ISREG(st.st_mode);
   } else {
     return false;
@@ -156,7 +161,7 @@
 
 
 bool File::Create(const char* name) {
-  int fd = TEMP_FAILURE_RETRY(
+  int fd = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(
       open64(name, O_RDONLY | O_CREAT | O_CLOEXEC, 0666));
   if (fd < 0) {
     return false;
@@ -166,7 +171,7 @@
 
 
 bool File::CreateLink(const char* name, const char* target) {
-  int status = TEMP_FAILURE_RETRY(symlink(target, name));
+  int status = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(symlink(target, name));
   return (status == 0);
 }
 
@@ -174,7 +179,7 @@
 bool File::Delete(const char* name) {
   File::Type type = File::GetType(name, true);
   if (type == kIsFile) {
-    return TEMP_FAILURE_RETRY(unlink(name)) == 0;
+    return TEMP_FAILURE_RETRY_BLOCK_SIGNALS(unlink(name)) == 0;
   } else if (type == kIsDirectory) {
     errno = EISDIR;
   } else {
@@ -187,7 +192,7 @@
 bool File::DeleteLink(const char* name) {
   File::Type type = File::GetType(name, false);
   if (type == kIsLink) {
-    return TEMP_FAILURE_RETRY(unlink(name)) == 0;
+    return TEMP_FAILURE_RETRY_BLOCK_SIGNALS(unlink(name)) == 0;
   }
   errno = EINVAL;
   return false;
@@ -197,7 +202,7 @@
 bool File::Rename(const char* old_path, const char* new_path) {
   File::Type type = File::GetType(old_path, true);
   if (type == kIsFile) {
-    return TEMP_FAILURE_RETRY(rename(old_path, new_path)) == 0;
+    return TEMP_FAILURE_RETRY_BLOCK_SIGNALS(rename(old_path, new_path)) == 0;
   } else if (type == kIsDirectory) {
     errno = EISDIR;
   } else {
@@ -210,7 +215,7 @@
 bool File::RenameLink(const char* old_path, const char* new_path) {
   File::Type type = File::GetType(old_path, false);
   if (type == kIsLink) {
-    return TEMP_FAILURE_RETRY(rename(old_path, new_path)) == 0;
+    return TEMP_FAILURE_RETRY_BLOCK_SIGNALS(rename(old_path, new_path)) == 0;
   } else if (type == kIsDirectory) {
     errno = EISDIR;
   } else {
@@ -220,9 +225,68 @@
 }
 
 
+bool File::Copy(const char* old_path, const char* new_path) {
+  File::Type type = File::GetType(old_path, true);
+  if (type == kIsFile) {
+    struct stat64 st;
+    if (TEMP_FAILURE_RETRY_BLOCK_SIGNALS(stat64(old_path, &st)) != 0) {
+      return false;
+    }
+    int old_fd = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(open64(old_path,
+                                                         O_RDONLY | O_CLOEXEC));
+    if (old_fd < 0) {
+      return false;
+    }
+    int new_fd = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(
+        open64(new_path, O_WRONLY | O_TRUNC | O_CREAT | O_CLOEXEC, st.st_mode));
+    if (new_fd < 0) {
+      VOID_TEMP_FAILURE_RETRY_BLOCK_SIGNALS(close(old_fd));
+      return false;
+    }
+    off64_t offset = 0;
+    int result = 1;
+    while (result > 0) {
+      // Loop to ensure we copy everything, and not only up to 2GB.
+      result = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(
+          sendfile64(new_fd, old_fd, &offset, kMaxUint32));
+    }
+    // From sendfile man pages:
+    //   Applications may wish to fall back to read(2)/write(2) in the case
+    //   where sendfile() fails with EINVAL or ENOSYS.
+    if (result < 0 && (errno == EINVAL || errno == ENOSYS)) {
+      const intptr_t kBufferSize = 8 * KB;
+      uint8_t buffer[kBufferSize];
+      while ((result = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(
+          read(old_fd, buffer, kBufferSize))) > 0) {
+        int wrote = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(write(new_fd, buffer,
+                                                           result));
+        if (wrote != result) {
+          result = -1;
+          break;
+        }
+      }
+    }
+    if (result < 0) {
+      int e = errno;
+      VOID_TEMP_FAILURE_RETRY_BLOCK_SIGNALS(close(old_fd));
+      VOID_TEMP_FAILURE_RETRY_BLOCK_SIGNALS(close(new_fd));
+      VOID_TEMP_FAILURE_RETRY_BLOCK_SIGNALS(unlink(new_path));
+      errno = e;
+      return false;
+    }
+    return true;
+  } else if (type == kIsDirectory) {
+    errno = EISDIR;
+  } else {
+    errno = ENOENT;
+  }
+  return false;
+}
+
+
 off64_t File::LengthFromPath(const char* name) {
   struct stat64 st;
-  if (TEMP_FAILURE_RETRY(stat64(name, &st)) == 0) {
+  if (TEMP_FAILURE_RETRY_BLOCK_SIGNALS(stat64(name, &st)) == 0) {
     return st.st_size;
   }
   return -1;
@@ -231,7 +295,7 @@
 
 void File::Stat(const char* name, int64_t* data) {
   struct stat64 st;
-  if (TEMP_FAILURE_RETRY(stat64(name, &st)) == 0) {
+  if (TEMP_FAILURE_RETRY_BLOCK_SIGNALS(stat64(name, &st)) == 0) {
     if (S_ISREG(st.st_mode)) {
       data[kType] = kIsFile;
     } else if (S_ISDIR(st.st_mode)) {
@@ -254,7 +318,7 @@
 
 time_t File::LastModified(const char* name) {
   struct stat64 st;
-  if (TEMP_FAILURE_RETRY(stat64(name, &st)) == 0) {
+  if (TEMP_FAILURE_RETRY_BLOCK_SIGNALS(stat64(name, &st)) == 0) {
     return st.st_mtime;
   }
   return -1;
@@ -329,9 +393,11 @@
   struct stat64 entry_info;
   int stat_success;
   if (follow_links) {
-    stat_success = TEMP_FAILURE_RETRY(stat64(pathname, &entry_info));
+    stat_success = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(stat64(pathname,
+                                                           &entry_info));
   } else {
-    stat_success = TEMP_FAILURE_RETRY(lstat64(pathname, &entry_info));
+    stat_success = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(lstat64(pathname,
+                                                            &entry_info));
   }
   if (stat_success == -1) return File::kDoesNotExist;
   if (S_ISDIR(entry_info.st_mode)) return File::kIsDirectory;
@@ -344,8 +410,8 @@
 File::Identical File::AreIdentical(const char* file_1, const char* file_2) {
   struct stat64 file_1_info;
   struct stat64 file_2_info;
-  if (TEMP_FAILURE_RETRY(lstat64(file_1, &file_1_info)) == -1 ||
-      TEMP_FAILURE_RETRY(lstat64(file_2, &file_2_info)) == -1) {
+  if (TEMP_FAILURE_RETRY_BLOCK_SIGNALS(lstat64(file_1, &file_1_info)) == -1 ||
+      TEMP_FAILURE_RETRY_BLOCK_SIGNALS(lstat64(file_2, &file_2_info)) == -1) {
     return File::kError;
   }
   return (file_1_info.st_ino == file_2_info.st_ino &&
diff --git a/runtime/bin/file_macos.cc b/runtime/bin/file_macos.cc
index 46c77cb..d750af8 100644
--- a/runtime/bin/file_macos.cc
+++ b/runtime/bin/file_macos.cc
@@ -9,6 +9,7 @@
 
 #include <errno.h>  // NOLINT
 #include <fcntl.h>  // NOLINT
+#include <copyfile.h>  // NOLINT
 #include <sys/stat.h>  // NOLINT
 #include <unistd.h>  // NOLINT
 #include <libgen.h>  // NOLINT
@@ -17,7 +18,7 @@
 #include "bin/builtin.h"
 #include "bin/fdutils.h"
 #include "bin/log.h"
-
+#include "bin/signal_blocker.h"
 
 namespace dart {
 namespace bin {
@@ -47,7 +48,7 @@
 
 void File::Close() {
   ASSERT(handle_->fd() >= 0);
-  int err = TEMP_FAILURE_RETRY(close(handle_->fd()));
+  int err = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(close(handle_->fd()));
   if (err != 0) {
     const int kBufferSize = 1024;
     char error_message[kBufferSize];
@@ -65,13 +66,15 @@
 
 int64_t File::Read(void* buffer, int64_t num_bytes) {
   ASSERT(handle_->fd() >= 0);
-  return TEMP_FAILURE_RETRY(read(handle_->fd(), buffer, num_bytes));
+  return TEMP_FAILURE_RETRY_BLOCK_SIGNALS(read(handle_->fd(), buffer,
+                                               num_bytes));
 }
 
 
 int64_t File::Write(const void* buffer, int64_t num_bytes) {
   ASSERT(handle_->fd() >= 0);
-  return TEMP_FAILURE_RETRY(write(handle_->fd(), buffer, num_bytes));
+  return TEMP_FAILURE_RETRY_BLOCK_SIGNALS(write(handle_->fd(), buffer,
+                                                num_bytes));
 }
 
 
@@ -89,20 +92,21 @@
 
 bool File::Truncate(off64_t length) {
   ASSERT(handle_->fd() >= 0);
-  return TEMP_FAILURE_RETRY(ftruncate(handle_->fd(), length) != -1);
+  return TEMP_FAILURE_RETRY_BLOCK_SIGNALS(
+      ftruncate(handle_->fd(), length) != -1);
 }
 
 
 bool File::Flush() {
   ASSERT(handle_->fd() >= 0);
-  return TEMP_FAILURE_RETRY(fsync(handle_->fd()) != -1);
+  return TEMP_FAILURE_RETRY_BLOCK_SIGNALS(fsync(handle_->fd()) != -1);
 }
 
 
 off64_t File::Length() {
   ASSERT(handle_->fd() >= 0);
   struct stat st;
-  if (TEMP_FAILURE_RETRY(fstat(handle_->fd(), &st)) == 0) {
+  if (TEMP_FAILURE_RETRY_BLOCK_SIGNALS(fstat(handle_->fd(), &st)) == 0) {
     return st.st_size;
   }
   return -1;
@@ -112,7 +116,7 @@
 File* File::Open(const char* name, FileOpenMode mode) {
   // Report errors for non-regular files.
   struct stat st;
-  if (TEMP_FAILURE_RETRY(stat(name, &st)) == 0) {
+  if (TEMP_FAILURE_RETRY_BLOCK_SIGNALS(stat(name, &st)) == 0) {
     // Only accept regular files and character devices.
     if (!S_ISREG(st.st_mode) && !S_ISCHR(st.st_mode)) {
       errno = (S_ISDIR(st.st_mode)) ? EISDIR : ENOENT;
@@ -126,7 +130,7 @@
   if ((mode & kTruncate) != 0) {
     flags = flags | O_TRUNC;
   }
-  int fd = TEMP_FAILURE_RETRY(open(name, flags, 0666));
+  int fd = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(open(name, flags, 0666));
   if (fd < 0) {
     return NULL;
   }
@@ -149,7 +153,7 @@
 
 bool File::Exists(const char* name) {
   struct stat st;
-  if (TEMP_FAILURE_RETRY(stat(name, &st)) == 0) {
+  if (TEMP_FAILURE_RETRY_BLOCK_SIGNALS(stat(name, &st)) == 0) {
     return S_ISREG(st.st_mode);
   } else {
     return false;
@@ -158,7 +162,8 @@
 
 
 bool File::Create(const char* name) {
-  int fd = TEMP_FAILURE_RETRY(open(name, O_RDONLY | O_CREAT, 0666));
+  int fd = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(open(name, O_RDONLY | O_CREAT,
+                                                 0666));
   if (fd < 0) {
     return false;
   }
@@ -167,7 +172,7 @@
 
 
 bool File::CreateLink(const char* name, const char* target) {
-  int status = TEMP_FAILURE_RETRY(symlink(target, name));
+  int status = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(symlink(target, name));
   return (status == 0);
 }
 
@@ -175,7 +180,7 @@
 bool File::Delete(const char* name) {
   File::Type type = File::GetType(name, true);
   if (type == kIsFile) {
-    return TEMP_FAILURE_RETRY(unlink(name)) == 0;
+    return TEMP_FAILURE_RETRY_BLOCK_SIGNALS(unlink(name)) == 0;
   } else if (type == kIsDirectory) {
     errno = EISDIR;
   } else {
@@ -188,7 +193,7 @@
 bool File::DeleteLink(const char* name) {
   File::Type type = File::GetType(name, false);
   if (type == kIsLink) {
-    return TEMP_FAILURE_RETRY(unlink(name)) == 0;
+    return TEMP_FAILURE_RETRY_BLOCK_SIGNALS(unlink(name)) == 0;
   }
   errno = EINVAL;
   return false;
@@ -198,7 +203,7 @@
 bool File::Rename(const char* old_path, const char* new_path) {
   File::Type type = File::GetType(old_path, true);
   if (type == kIsFile) {
-    return TEMP_FAILURE_RETRY(rename(old_path, new_path)) == 0;
+    return TEMP_FAILURE_RETRY_BLOCK_SIGNALS(rename(old_path, new_path)) == 0;
   } else if (type == kIsDirectory) {
     errno = EISDIR;
   } else {
@@ -211,7 +216,7 @@
 bool File::RenameLink(const char* old_path, const char* new_path) {
   File::Type type = File::GetType(old_path, false);
   if (type == kIsLink) {
-    return TEMP_FAILURE_RETRY(rename(old_path, new_path)) == 0;
+    return TEMP_FAILURE_RETRY_BLOCK_SIGNALS(rename(old_path, new_path)) == 0;
   } else if (type == kIsDirectory) {
     errno = EISDIR;
   } else {
@@ -221,9 +226,22 @@
 }
 
 
+bool File::Copy(const char* old_path, const char* new_path) {
+  File::Type type = File::GetType(old_path, true);
+  if (type == kIsFile) {
+    return copyfile(old_path, new_path, NULL, COPYFILE_ALL) == 0;
+  } else if (type == kIsDirectory) {
+    errno = EISDIR;
+  } else {
+    errno = ENOENT;
+  }
+  return false;
+}
+
+
 off64_t File::LengthFromPath(const char* name) {
   struct stat st;
-  if (TEMP_FAILURE_RETRY(stat(name, &st)) == 0) {
+  if (TEMP_FAILURE_RETRY_BLOCK_SIGNALS(stat(name, &st)) == 0) {
     return st.st_size;
   }
   return -1;
@@ -232,7 +250,7 @@
 
 void File::Stat(const char* name, int64_t* data) {
   struct stat st;
-  if (TEMP_FAILURE_RETRY(stat(name, &st)) == 0) {
+  if (TEMP_FAILURE_RETRY_BLOCK_SIGNALS(stat(name, &st)) == 0) {
     if (S_ISREG(st.st_mode)) {
       data[kType] = kIsFile;
     } else if (S_ISDIR(st.st_mode)) {
@@ -255,7 +273,7 @@
 
 time_t File::LastModified(const char* name) {
   struct stat st;
-  if (TEMP_FAILURE_RETRY(stat(name, &st)) == 0) {
+  if (TEMP_FAILURE_RETRY_BLOCK_SIGNALS(stat(name, &st)) == 0) {
     return st.st_mtime;
   }
   return -1;
@@ -336,9 +354,11 @@
   struct stat entry_info;
   int stat_success;
   if (follow_links) {
-    stat_success = TEMP_FAILURE_RETRY(stat(pathname, &entry_info));
+    stat_success = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(stat(pathname,
+                                                         &entry_info));
   } else {
-    stat_success = TEMP_FAILURE_RETRY(lstat(pathname, &entry_info));
+    stat_success = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(lstat(pathname,
+                                                          &entry_info));
   }
   if (stat_success == -1) return File::kDoesNotExist;
   if (S_ISDIR(entry_info.st_mode)) return File::kIsDirectory;
@@ -351,8 +371,8 @@
 File::Identical File::AreIdentical(const char* file_1, const char* file_2) {
   struct stat file_1_info;
   struct stat file_2_info;
-  if (TEMP_FAILURE_RETRY(lstat(file_1, &file_1_info)) == -1 ||
-      TEMP_FAILURE_RETRY(lstat(file_2, &file_2_info)) == -1) {
+  if (TEMP_FAILURE_RETRY_BLOCK_SIGNALS(lstat(file_1, &file_1_info)) == -1 ||
+      TEMP_FAILURE_RETRY_BLOCK_SIGNALS(lstat(file_2, &file_2_info)) == -1) {
     return File::kError;
   }
   return (file_1_info.st_ino == file_2_info.st_ino &&
diff --git a/runtime/bin/file_patch.dart b/runtime/bin/file_patch.dart
index 68612a5..4ded719 100644
--- a/runtime/bin/file_patch.dart
+++ b/runtime/bin/file_patch.dart
@@ -14,6 +14,7 @@
       native "File_Rename";
   /* patch */ static _renameLink(String oldPath, String newPath)
       native "File_RenameLink";
+  /* patch */ static _copy(String oldPath, String newPath) native "File_Copy";
   /* patch */ static _lengthFromPath(String path) native "File_LengthFromPath";
   /* patch */ static _lastModified(String path) native "File_LastModified";
   /* patch */ static _open(String path, int mode) native "File_Open";
diff --git a/runtime/bin/file_win.cc b/runtime/bin/file_win.cc
index 4c3c853..1be41cb 100644
--- a/runtime/bin/file_win.cc
+++ b/runtime/bin/file_win.cc
@@ -322,6 +322,27 @@
 }
 
 
+bool File::Copy(const char* old_path, const char* new_path) {
+  File::Type type = GetType(old_path, false);
+  if (type == kIsFile) {
+    const wchar_t* system_old_path = StringUtils::Utf8ToWide(old_path);
+    const wchar_t* system_new_path = StringUtils::Utf8ToWide(new_path);
+    bool success = CopyFileExW(system_old_path,
+                               system_new_path,
+                               NULL,
+                               NULL,
+                               NULL,
+                               0) != 0;
+    free(const_cast<wchar_t*>(system_old_path));
+    free(const_cast<wchar_t*>(system_new_path));
+    return success;
+  } else {
+    SetLastError(ERROR_FILE_NOT_FOUND);
+  }
+  return false;
+}
+
+
 off64_t File::LengthFromPath(const char* name) {
   struct __stat64 st;
   const wchar_t* system_name = StringUtils::Utf8ToWide(name);
diff --git a/runtime/bin/io_impl_sources.gypi b/runtime/bin/io_impl_sources.gypi
index d026609..a720c7f 100644
--- a/runtime/bin/io_impl_sources.gypi
+++ b/runtime/bin/io_impl_sources.gypi
@@ -50,12 +50,12 @@
     'socket_linux.cc',
     'socket_macos.cc',
     'socket_win.cc',
-    'stdin.cc',
-    'stdin.h',
-    'stdin_android.cc',
-    'stdin_linux.cc',
-    'stdin_macos.cc',
-    'stdin_win.cc',
+    'stdio.cc',
+    'stdio.h',
+    'stdio_android.cc',
+    'stdio_linux.cc',
+    'stdio_macos.cc',
+    'stdio_win.cc',
   ],
   'conditions': [
     ['dart_io_support==1', {
diff --git a/runtime/bin/io_natives.cc b/runtime/bin/io_natives.cc
index 480ce68..6a860b7 100644
--- a/runtime/bin/io_natives.cc
+++ b/runtime/bin/io_natives.cc
@@ -27,8 +27,7 @@
   V(Filter_End, 1)                                                             \
   V(Filter_Process, 4)                                                         \
   V(Filter_Processed, 3)                                                       \
-  V(InternetAddress_Fixed, 1)                                                  \
-  V(InternetAddress_Parse, 2)                                                  \
+  V(InternetAddress_Parse, 1)                                                  \
   V(IOService_NewServicePort, 0)                                               \
   V(Platform_NumberOfProcessors, 0)                                            \
   V(Platform_OperatingSystem, 0)                                               \
@@ -46,6 +45,8 @@
   V(Process_Exit, 1)                                                           \
   V(Process_Sleep, 1)                                                          \
   V(Process_Pid, 1)                                                            \
+  V(Process_SetSignalHandler, 1)                                               \
+  V(Process_ClearSignalHandler, 1)                                             \
   V(SecureSocket_Connect, 9)                                                   \
   V(SecureSocket_Destroy, 1)                                                   \
   V(SecureSocket_Handshake, 1)                                                 \
@@ -80,6 +81,7 @@
   V(Stdin_SetEchoMode, 1)                                                      \
   V(Stdin_GetLineMode, 0)                                                      \
   V(Stdin_SetLineMode, 1)                                                      \
+  V(Stdout_GetTerminalSize, 0)                                                 \
   V(StringToSystemEncoding, 1)                                                 \
   V(SystemEncodingToString, 1)
 
@@ -96,11 +98,14 @@
 
 
 Dart_NativeFunction IONativeLookup(Dart_Handle name,
-                                   int argument_count) {
+                                   int argument_count,
+                                   bool* auto_setup_scope) {
   const char* function_name = NULL;
   Dart_Handle result = Dart_StringToCString(name, &function_name);
   DART_CHECK_VALID(result);
   ASSERT(function_name != NULL);
+  ASSERT(auto_setup_scope != NULL);
+  *auto_setup_scope = true;
   int num_entries = sizeof(IOEntries) / sizeof(struct NativeEntries);
   for (int i = 0; i < num_entries; i++) {
     struct NativeEntries* entry = &(IOEntries[i]);
diff --git a/runtime/bin/io_natives.h b/runtime/bin/io_natives.h
index dac7fce..7039234 100644
--- a/runtime/bin/io_natives.h
+++ b/runtime/bin/io_natives.h
@@ -12,7 +12,8 @@
 namespace bin {
 
 Dart_NativeFunction IONativeLookup(Dart_Handle name,
-                                   int argument_count);
+                                   int argument_count,
+                                   bool* auto_setup_scope);
 
 }  // namespace bin
 }  // namespace dart
diff --git a/runtime/bin/io_service.h b/runtime/bin/io_service.h
index d9e8c45..af829eb 100644
--- a/runtime/bin/io_service.h
+++ b/runtime/bin/io_service.h
@@ -18,40 +18,41 @@
   V(File, Create, 1)                                                           \
   V(File, Delete, 2)                                                           \
   V(File, Rename, 3)                                                           \
-  V(File, Open, 4)                                                             \
-  V(File, ResolveSymbolicLinks, 5)                                             \
-  V(File, Close, 6)                                                            \
-  V(File, Position, 7)                                                         \
-  V(File, SetPosition, 8)                                                      \
-  V(File, Truncate, 9)                                                         \
-  V(File, Length, 10)                                                          \
-  V(File, LengthFromPath, 11)                                                  \
-  V(File, LastModified, 12)                                                    \
-  V(File, Flush, 13)                                                           \
-  V(File, ReadByte, 14)                                                        \
-  V(File, WriteByte, 15)                                                       \
-  V(File, Read, 16)                                                            \
-  V(File, ReadInto, 17)                                                        \
-  V(File, WriteFrom, 18)                                                       \
-  V(File, CreateLink, 19)                                                      \
-  V(File, DeleteLink, 20)                                                      \
-  V(File, RenameLink, 21)                                                      \
-  V(File, LinkTarget, 22)                                                      \
-  V(File, Type, 23)                                                            \
-  V(File, Identical, 24)                                                       \
-  V(File, Stat, 25)                                                            \
-  V(Socket, Lookup, 26)                                                        \
-  V(Socket, ListInterfaces, 27)                                                \
-  V(Socket, ReverseLookup, 28)                                                 \
-  V(Directory, Create, 29)                                                     \
-  V(Directory, Delete, 30)                                                     \
-  V(Directory, Exists, 31)                                                     \
-  V(Directory, CreateTemp, 32)                                                 \
-  V(Directory, ListStart, 33)                                                  \
-  V(Directory, ListNext, 34)                                                   \
-  V(Directory, ListStop, 35)                                                   \
-  V(Directory, Rename, 36)                                                     \
-  V(SSLFilter, ProcessFilter, 37)
+  V(File, Copy, 4)                                                             \
+  V(File, Open, 5)                                                             \
+  V(File, ResolveSymbolicLinks, 6)                                             \
+  V(File, Close, 7)                                                            \
+  V(File, Position, 8)                                                         \
+  V(File, SetPosition, 9)                                                      \
+  V(File, Truncate, 10)                                                        \
+  V(File, Length, 11)                                                          \
+  V(File, LengthFromPath, 12)                                                  \
+  V(File, LastModified, 13)                                                    \
+  V(File, Flush, 14)                                                           \
+  V(File, ReadByte, 15)                                                        \
+  V(File, WriteByte, 16)                                                       \
+  V(File, Read, 17)                                                            \
+  V(File, ReadInto, 18)                                                        \
+  V(File, WriteFrom, 19)                                                       \
+  V(File, CreateLink, 20)                                                      \
+  V(File, DeleteLink, 21)                                                      \
+  V(File, RenameLink, 22)                                                      \
+  V(File, LinkTarget, 23)                                                      \
+  V(File, Type, 24)                                                            \
+  V(File, Identical, 25)                                                       \
+  V(File, Stat, 26)                                                            \
+  V(Socket, Lookup, 27)                                                        \
+  V(Socket, ListInterfaces, 28)                                                \
+  V(Socket, ReverseLookup, 29)                                                 \
+  V(Directory, Create, 30)                                                     \
+  V(Directory, Delete, 31)                                                     \
+  V(Directory, Exists, 32)                                                     \
+  V(Directory, CreateTemp, 33)                                                 \
+  V(Directory, ListStart, 34)                                                  \
+  V(Directory, ListNext, 35)                                                   \
+  V(Directory, ListStop, 36)                                                   \
+  V(Directory, Rename, 37)                                                     \
+  V(SSLFilter, ProcessFilter, 38)
 
 #define DECLARE_REQUEST(type, method, id)                                      \
   k##type##method##Request = id,
diff --git a/runtime/bin/process.cc b/runtime/bin/process.cc
index d7dd894..ebafedd 100644
--- a/runtime/bin/process.cc
+++ b/runtime/bin/process.cc
@@ -10,7 +10,6 @@
 
 #include "include/dart_api.h"
 
-
 namespace dart {
 namespace bin {
 
@@ -208,7 +207,8 @@
   int64_t status = 0;
   // Ignore result if passing invalid argument and just exit 0.
   DartUtils::GetInt64Value(Dart_GetNativeArgument(args, 0), &status);
-  // Be sure to do platform-specific cleanups.
+  Dart_ExitIsolate();
+  Dart_Cleanup();
   Platform::Cleanup();
   exit(static_cast<int>(status));
 }
@@ -243,6 +243,23 @@
 }
 
 
+void FUNCTION_NAME(Process_SetSignalHandler)(Dart_NativeArguments args) {
+  intptr_t signal = DartUtils::GetIntptrValue(Dart_GetNativeArgument(args, 0));
+  intptr_t id = Process::SetSignalHandler(signal);
+  if (id == -1) {
+    Dart_SetReturnValue(args, DartUtils::NewDartOSError());
+  } else {
+    Dart_SetReturnValue(args, Dart_NewInteger(id));
+  }
+}
+
+
+void FUNCTION_NAME(Process_ClearSignalHandler)(Dart_NativeArguments args) {
+  intptr_t signal = DartUtils::GetIntptrValue(Dart_GetNativeArgument(args, 0));
+  Process::ClearSignalHandler(signal);
+}
+
+
 Dart_Handle Process::GetProcessIdNativeField(Dart_Handle process,
                                              intptr_t* pid) {
   return Dart_GetNativeInstanceField(process, kProcessIdNativeField, pid);
diff --git a/runtime/bin/process.h b/runtime/bin/process.h
index 02a9ecc..adda36a 100644
--- a/runtime/bin/process.h
+++ b/runtime/bin/process.h
@@ -41,6 +41,41 @@
 };
 
 
+// To be kept in sync with ProcessSignal consts in sdk/lib/io/process.dart
+// Note that this map is as on Linux.
+enum ProcessSignals {
+  kSighup = 1,
+  kSigint = 2,
+  kSigquit = 3,
+  kSigill = 4,
+  kSigtrap = 5,
+  kSigabrt = 6,
+  kSigbus = 7,
+  kSigfpe = 8,
+  kSigkill = 9,
+  kSigusr1 = 10,
+  kSigsegv = 11,
+  kSigusr2 = 12,
+  kSigpipe = 13,
+  kSigalrm = 14,
+  kSigterm = 15,
+  kSigchld = 17,
+  kSigcont = 18,
+  kSigstop = 19,
+  kSigtstp = 20,
+  kSigttin = 21,
+  kSigttou = 22,
+  kSigurg = 23,
+  kSigxcpu = 24,
+  kSigxfsz = 25,
+  kSigvtalrm = 26,
+  kSigprof = 27,
+  kSigwinch = 28,
+  kSigpoll = 29,
+  kSigsys = 31
+};
+
+
 class Process {
  public:
   // Start a new process providing access to stdin, stdout, stderr and
@@ -84,6 +119,9 @@
 
   static intptr_t CurrentProcessId();
 
+  static intptr_t SetSignalHandler(intptr_t signal);
+  static void ClearSignalHandler(intptr_t signal);
+
   static Dart_Handle GetProcessIdNativeField(Dart_Handle process,
                                              intptr_t* pid);
   static Dart_Handle SetProcessIdNativeField(Dart_Handle process,
@@ -98,6 +136,46 @@
 };
 
 
+class SignalInfo {
+ public:
+  SignalInfo(int fd, int signal, SignalInfo* prev = NULL)
+      : fd_(fd),
+        signal_(signal),
+        // SignalInfo is expected to be created when in a isolate.
+        port_(Dart_GetMainPortId()),
+        next_(NULL),
+        prev_(prev) {
+    if (prev_ != NULL) {
+      prev_->next_ = this;
+    }
+  }
+
+  ~SignalInfo();
+
+  void Unlink() {
+    if (prev_ != NULL) {
+      prev_->next_ = next_;
+    }
+    if (next_ != NULL) {
+      next_->prev_ = prev_;
+    }
+  }
+
+  int fd() const { return fd_; }
+  int signal() const { return signal_; }
+  Dart_Port port() const { return port_; }
+  SignalInfo* next() const { return next_; }
+
+ private:
+  int fd_;
+  int signal_;
+  // The port_ is used to identify what isolate the signal-info belongs to.
+  Dart_Port port_;
+  SignalInfo* next_;
+  SignalInfo* prev_;
+};
+
+
 // Utility class for collecting the output when running a process
 // synchronously by using Process::Wait. This class is sub-classed in
 // the platform specific files to implement reading into the buffers
diff --git a/runtime/bin/process_android.cc b/runtime/bin/process_android.cc
index 378b9ba..2567cbe 100644
--- a/runtime/bin/process_android.cc
+++ b/runtime/bin/process_android.cc
@@ -18,6 +18,7 @@
 
 #include "bin/fdutils.h"
 #include "bin/log.h"
+#include "bin/signal_blocker.h"
 #include "bin/thread.h"
 
 
@@ -631,6 +632,115 @@
   return static_cast<intptr_t>(getpid());
 }
 
+
+static Mutex* signal_mutex = new Mutex();
+static SignalInfo* signal_handlers = NULL;
+static const int kSignalsCount = 5;
+static const int kSignals[kSignalsCount] = {
+  SIGINT,
+  SIGWINCH,
+  SIGTERM,
+  SIGUSR1,
+  SIGUSR2
+};
+
+
+SignalInfo::~SignalInfo() {
+  VOID_TEMP_FAILURE_RETRY(close(fd_));
+}
+
+
+static void SignalHandler(int signal) {
+  MutexLocker lock(signal_mutex);
+  const SignalInfo* handler = signal_handlers;
+  while (handler != NULL) {
+    if (handler->signal() == signal) {
+      int value = 0;
+      VOID_TEMP_FAILURE_RETRY(write(handler->fd(), &value, 1));
+    }
+    handler = handler->next();
+  }
+}
+
+
+intptr_t Process::SetSignalHandler(intptr_t signal) {
+  bool found = false;
+  for (int i = 0; i < kSignalsCount; i++) {
+    if (kSignals[i] == signal) {
+      found = true;
+      break;
+    }
+  }
+  if (!found) return -1;
+  int fds[2];
+  if (TEMP_FAILURE_RETRY_BLOCK_SIGNALS(pipe(fds)) != 0) {
+    return -1;
+  }
+  if (!FDUtils::SetNonBlocking(fds[0])) {
+    VOID_TEMP_FAILURE_RETRY_BLOCK_SIGNALS(close(fds[0]));
+    VOID_TEMP_FAILURE_RETRY_BLOCK_SIGNALS(close(fds[1]));
+    return -1;
+  }
+  ThreadSignalBlocker blocker(kSignalsCount, kSignals);
+  MutexLocker lock(signal_mutex);
+  SignalInfo* handler = signal_handlers;
+  bool listen = true;
+  while (handler != NULL) {
+    if (handler->signal() == signal) {
+      listen = false;
+      break;
+    }
+    handler = handler->next();
+  }
+  if (listen) {
+    struct sigaction act;
+    bzero(&act, sizeof(act));
+    act.sa_handler = SignalHandler;
+    int status = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(
+        sigaction(signal, &act, NULL));
+    if (status < 0) {
+      VOID_TEMP_FAILURE_RETRY_BLOCK_SIGNALS(close(fds[0]));
+      VOID_TEMP_FAILURE_RETRY_BLOCK_SIGNALS(close(fds[1]));
+      return -1;
+    }
+  }
+  if (signal_handlers == NULL) {
+    signal_handlers = new SignalInfo(fds[1], signal);
+  } else {
+    new SignalInfo(fds[1], signal, signal_handlers);
+  }
+  return fds[0];
+}
+
+
+void Process::ClearSignalHandler(intptr_t signal) {
+  ThreadSignalBlocker blocker(kSignalsCount, kSignals);
+  MutexLocker lock(signal_mutex);
+  SignalInfo* handler = signal_handlers;
+  bool unlisten = true;
+  while (handler != NULL) {
+    bool remove = false;
+    if (handler->signal() == signal) {
+      if (handler->port() == Dart_GetMainPortId()) {
+        if (signal_handlers == handler) signal_handlers = handler->next();
+        handler->Unlink();
+        remove = true;
+      } else {
+        unlisten = false;
+      }
+    }
+    SignalInfo* next = handler->next();
+    if (remove) delete handler;
+    handler = next;
+  }
+  if (unlisten) {
+    struct sigaction act;
+    bzero(&act, sizeof(act));
+    act.sa_handler = SIG_DFL;
+    VOID_TEMP_FAILURE_RETRY_BLOCK_SIGNALS(sigaction(signal, &act, NULL));
+  }
+}
+
 }  // namespace bin
 }  // namespace dart
 
diff --git a/runtime/bin/process_linux.cc b/runtime/bin/process_linux.cc
index 95d11cd..7479064 100644
--- a/runtime/bin/process_linux.cc
+++ b/runtime/bin/process_linux.cc
@@ -18,6 +18,7 @@
 
 #include "bin/fdutils.h"
 #include "bin/log.h"
+#include "bin/signal_blocker.h"
 #include "bin/thread.h"
 
 
@@ -630,6 +631,115 @@
   return static_cast<intptr_t>(getpid());
 }
 
+
+static Mutex* signal_mutex = new Mutex();
+static SignalInfo* signal_handlers = NULL;
+static const int kSignalsCount = 5;
+static const int kSignals[kSignalsCount] = {
+  SIGINT,
+  SIGWINCH,
+  SIGTERM,
+  SIGUSR1,
+  SIGUSR2
+};
+
+
+SignalInfo::~SignalInfo() {
+  VOID_TEMP_FAILURE_RETRY(close(fd_));
+}
+
+
+static void SignalHandler(int signal) {
+  MutexLocker lock(signal_mutex);
+  const SignalInfo* handler = signal_handlers;
+  while (handler != NULL) {
+    if (handler->signal() == signal) {
+      int value = 0;
+      VOID_TEMP_FAILURE_RETRY(write(handler->fd(), &value, 1));
+    }
+    handler = handler->next();
+  }
+}
+
+
+intptr_t Process::SetSignalHandler(intptr_t signal) {
+  bool found = false;
+  for (int i = 0; i < kSignalsCount; i++) {
+    if (kSignals[i] == signal) {
+      found = true;
+      break;
+    }
+  }
+  if (!found) return -1;
+  int fds[2];
+  if (TEMP_FAILURE_RETRY_BLOCK_SIGNALS(pipe(fds)) != 0) {
+    return -1;
+  }
+  if (!FDUtils::SetNonBlocking(fds[0])) {
+    VOID_TEMP_FAILURE_RETRY_BLOCK_SIGNALS(close(fds[0]));
+    VOID_TEMP_FAILURE_RETRY_BLOCK_SIGNALS(close(fds[1]));
+    return -1;
+  }
+  ThreadSignalBlocker blocker(kSignalsCount, kSignals);
+  MutexLocker lock(signal_mutex);
+  SignalInfo* handler = signal_handlers;
+  bool listen = true;
+  while (handler != NULL) {
+    if (handler->signal() == signal) {
+      listen = false;
+      break;
+    }
+    handler = handler->next();
+  }
+  if (listen) {
+    struct sigaction act;
+    bzero(&act, sizeof(act));
+    act.sa_handler = SignalHandler;
+    int status = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(
+        sigaction(signal, &act, NULL));
+    if (status < 0) {
+      VOID_TEMP_FAILURE_RETRY_BLOCK_SIGNALS(close(fds[0]));
+      VOID_TEMP_FAILURE_RETRY_BLOCK_SIGNALS(close(fds[1]));
+      return -1;
+    }
+  }
+  if (signal_handlers == NULL) {
+    signal_handlers = new SignalInfo(fds[1], signal);
+  } else {
+    new SignalInfo(fds[1], signal, signal_handlers);
+  }
+  return fds[0];
+}
+
+
+void Process::ClearSignalHandler(intptr_t signal) {
+  ThreadSignalBlocker blocker(kSignalsCount, kSignals);
+  MutexLocker lock(signal_mutex);
+  SignalInfo* handler = signal_handlers;
+  bool unlisten = true;
+  while (handler != NULL) {
+    bool remove = false;
+    if (handler->signal() == signal) {
+      if (handler->port() == Dart_GetMainPortId()) {
+        if (signal_handlers == handler) signal_handlers = handler->next();
+        handler->Unlink();
+        remove = true;
+      } else {
+        unlisten = false;
+      }
+    }
+    SignalInfo* next = handler->next();
+    if (remove) delete handler;
+    handler = next;
+  }
+  if (unlisten) {
+    struct sigaction act;
+    bzero(&act, sizeof(act));
+    act.sa_handler = SIG_DFL;
+    VOID_TEMP_FAILURE_RETRY_BLOCK_SIGNALS(sigaction(signal, &act, NULL));
+  }
+}
+
 }  // namespace bin
 }  // namespace dart
 
diff --git a/runtime/bin/process_macos.cc b/runtime/bin/process_macos.cc
index edb222a..ae0f37e 100644
--- a/runtime/bin/process_macos.cc
+++ b/runtime/bin/process_macos.cc
@@ -18,6 +18,7 @@
 
 #include "bin/fdutils.h"
 #include "bin/log.h"
+#include "bin/signal_blocker.h"
 #include "bin/thread.h"
 
 extern char **environ;
@@ -622,8 +623,44 @@
 }
 
 
+static int SignalMap(intptr_t id) {
+  switch (static_cast<ProcessSignals>(id)) {
+    case kSighup: return SIGHUP;
+    case kSigint: return SIGINT;
+    case kSigquit: return SIGQUIT;
+    case kSigill: return SIGILL;
+    case kSigtrap: return SIGTRAP;
+    case kSigabrt: return SIGABRT;
+    case kSigbus: return SIGBUS;
+    case kSigfpe: return SIGFPE;
+    case kSigkill: return SIGKILL;
+    case kSigusr1: return SIGUSR1;
+    case kSigsegv: return SIGSEGV;
+    case kSigusr2: return SIGUSR2;
+    case kSigpipe: return SIGPIPE;
+    case kSigalrm: return SIGALRM;
+    case kSigterm: return SIGTERM;
+    case kSigchld: return SIGCHLD;
+    case kSigcont: return SIGCONT;
+    case kSigstop: return SIGSTOP;
+    case kSigtstp: return SIGTSTP;
+    case kSigttin: return SIGTTIN;
+    case kSigttou: return SIGTTOU;
+    case kSigurg: return SIGURG;
+    case kSigxcpu: return SIGXCPU;
+    case kSigxfsz: return SIGXFSZ;
+    case kSigvtalrm: return SIGVTALRM;
+    case kSigprof: return SIGPROF;
+    case kSigwinch: return SIGWINCH;
+    case kSigpoll: return -1;
+    case kSigsys: return SIGSYS;
+  }
+  return -1;
+}
+
+
 bool Process::Kill(intptr_t id, int signal) {
-  return (TEMP_FAILURE_RETRY(kill(id, signal)) != -1);
+  return (TEMP_FAILURE_RETRY(kill(id, SignalMap(signal))) != -1);
 }
 
 
@@ -636,6 +673,119 @@
   return static_cast<intptr_t>(getpid());
 }
 
+
+static Mutex* signal_mutex = new Mutex();
+static SignalInfo* signal_handlers = NULL;
+static const int kSignalsCount = 5;
+static const int kSignals[kSignalsCount] = {
+  SIGINT,
+  SIGWINCH,
+  SIGTERM,
+  SIGUSR1,
+  SIGUSR2
+};
+
+
+SignalInfo::~SignalInfo() {
+  VOID_TEMP_FAILURE_RETRY(close(fd_));
+}
+
+
+static void SignalHandler(int signal) {
+  MutexLocker lock(signal_mutex);
+  const SignalInfo* handler = signal_handlers;
+  while (handler != NULL) {
+    if (handler->signal() == signal) {
+      int value = 0;
+      VOID_TEMP_FAILURE_RETRY(write(handler->fd(), &value, 1));
+    }
+    handler = handler->next();
+  }
+}
+
+
+intptr_t Process::SetSignalHandler(intptr_t signal) {
+  signal = SignalMap(signal);
+  if (signal == -1) return -1;
+  bool found = false;
+  for (int i = 0; i < kSignalsCount; i++) {
+    if (kSignals[i] == signal) {
+      found = true;
+      break;
+    }
+  }
+  if (!found) return -1;
+  int fds[2];
+  if (TEMP_FAILURE_RETRY_BLOCK_SIGNALS(pipe(fds)) != 0) {
+    return -1;
+  }
+  if (!FDUtils::SetNonBlocking(fds[0])) {
+    VOID_TEMP_FAILURE_RETRY_BLOCK_SIGNALS(close(fds[0]));
+    VOID_TEMP_FAILURE_RETRY_BLOCK_SIGNALS(close(fds[1]));
+    return -1;
+  }
+  ThreadSignalBlocker blocker(kSignalsCount, kSignals);
+  MutexLocker lock(signal_mutex);
+  SignalInfo* handler = signal_handlers;
+  bool listen = true;
+  while (handler != NULL) {
+    if (handler->signal() == signal) {
+      listen = false;
+      break;
+    }
+    handler = handler->next();
+  }
+  if (listen) {
+    struct sigaction act;
+    bzero(&act, sizeof(act));
+    act.sa_handler = SignalHandler;
+    int status = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(
+        sigaction(signal, &act, NULL));
+    if (status < 0) {
+      VOID_TEMP_FAILURE_RETRY_BLOCK_SIGNALS(close(fds[0]));
+      VOID_TEMP_FAILURE_RETRY_BLOCK_SIGNALS(close(fds[1]));
+      return -1;
+    }
+  }
+  if (signal_handlers == NULL) {
+    signal_handlers = new SignalInfo(fds[1], signal);
+  } else {
+    new SignalInfo(fds[1], signal, signal_handlers);
+  }
+  return fds[0];
+}
+
+
+void Process::ClearSignalHandler(intptr_t signal) {
+  signal = SignalMap(signal);
+  if (signal == -1) return;
+  ThreadSignalBlocker blocker(kSignalsCount, kSignals);
+  MutexLocker lock(signal_mutex);
+  SignalInfo* handler = signal_handlers;
+  bool unlisten = true;
+  while (handler != NULL) {
+    bool remove = false;
+    if (handler->signal() == signal) {
+      if (handler->port() == Dart_GetMainPortId()) {
+        if (signal_handlers == handler) signal_handlers = handler->next();
+        handler->Unlink();
+        remove = true;
+      } else {
+        unlisten = false;
+      }
+    }
+    SignalInfo* next = handler->next();
+    if (remove) delete handler;
+    handler = next;
+  }
+  if (unlisten) {
+    struct sigaction act;
+    bzero(&act, sizeof(act));
+    act.sa_handler = SIG_DFL;
+    VOID_TEMP_FAILURE_RETRY_BLOCK_SIGNALS(sigaction(signal, &act, NULL));
+  }
+}
+
 }  // namespace bin
 }  // namespace dart
 
diff --git a/runtime/bin/process_patch.dart b/runtime/bin/process_patch.dart
index e0e8fc6..b83ec1b 100644
--- a/runtime/bin/process_patch.dart
+++ b/runtime/bin/process_patch.dart
@@ -71,12 +71,77 @@
 }
 
 
+List<_SignalController> _signalControllers = new List(32);
+
+
+class _SignalController {
+  final ProcessSignal signal;
+
+  StreamController _controller;
+  var _id;
+
+  _SignalController(this.signal) {
+    _controller = new StreamController.broadcast(
+        onListen: _listen,
+        onCancel: _cancel);
+  }
+
+  Stream<ProcessSignal> get stream => _controller.stream;
+
+  void _listen() {
+    var id = _setSignalHandler(signal._signalNumber);
+    if (id is! int) {
+      _controller.addError(
+          new SignalException("Failed to listen for $signal", id));
+      return;
+    }
+    _id = id;
+    var socket = new _RawSocket(new _NativeSocket.watch(id));
+    socket.listen((event) {
+      if (event == RawSocketEvent.READ) {
+        var bytes = socket.read();
+        for (int i = 0; i < bytes.length; i++) {
+          _controller.add(signal);
+        }
+      }
+    });
+  }
+
+  void _cancel() {
+    if (_id != null) {
+      _clearSignalHandler(signal._signalNumber);
+      _id = null;
+    }
+  }
+
+  /* patch */ static int _setSignalHandler(int signal)
+      native "Process_SetSignalHandler";
+  /* patch */ static int _clearSignalHandler(int signal)
+      native "Process_ClearSignalHandler";
+}
+
+
 patch class _ProcessUtils {
   /* patch */ static void _exit(int status) native "Process_Exit";
   /* patch */ static void _setExitCode(int status)
       native "Process_SetExitCode";
   /* patch */ static void _sleep(int millis) native "Process_Sleep";
   /* patch */ static int _pid(Process process) native "Process_Pid";
+  /* patch */ static Stream<ProcessSignal> _watchSignal(ProcessSignal signal) {
+    if (signal != ProcessSignal.SIGHUP &&
+        signal != ProcessSignal.SIGINT &&
+        (Platform.isWindows ||
+         (signal != ProcessSignal.SIGUSR1 &&
+          signal != ProcessSignal.SIGUSR2 &&
+          signal != ProcessSignal.SIGWINCH))) {
+      throw new SignalException(
+          "Listening for signal $signal is not supported");
+    }
+    if (_signalControllers[signal._signalNumber] == null) {
+      _signalControllers[signal._signalNumber] = new _SignalController(signal);
+    }
+    return _signalControllers[signal._signalNumber].stream;
+  }
 }
 
 
diff --git a/runtime/bin/process_win.cc b/runtime/bin/process_win.cc
index 00514c7..3875b4f 100644
--- a/runtime/bin/process_win.cc
+++ b/runtime/bin/process_win.cc
@@ -11,6 +11,7 @@
 #include "bin/process.h"
 #include "bin/eventhandler.h"
 #include "bin/log.h"
+#include "bin/socket.h"
 #include "bin/thread.h"
 #include "bin/utils.h"
 #include "bin/utils_win.h"
@@ -350,6 +351,33 @@
 }
 
 
+const int kMaxPipeNameSize = 80;
+template<int Count>
+static int GenerateNames(wchar_t pipe_names[Count][kMaxPipeNameSize]) {
+  UUID uuid;
+  RPC_STATUS status = UuidCreateSequential(&uuid);
+  if (status != RPC_S_OK && status != RPC_S_UUID_LOCAL_ONLY) {
+    return status;
+  }
+  RPC_WSTR uuid_string;
+  status = UuidToStringW(&uuid, &uuid_string);
+  if (status != RPC_S_OK) {
+    return status;
+  }
+  for (int i = 0; i < Count; i++) {
+    static const wchar_t* prefix = L"\\\\.\\Pipe\\dart";
+    _snwprintf(pipe_names[i],
+               kMaxPipeNameSize,
+               L"%s_%s_%d", prefix, uuid_string, i + 1);
+  }
+  status = RpcStringFreeW(&uuid_string);
+  if (status != RPC_S_OK) {
+    return status;
+  }
+  return 0;
+}
+
+
 int Process::Start(const char* path,
                    char* arguments[],
                    intptr_t arguments_length,
@@ -368,34 +396,13 @@
   HANDLE exit_handles[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE };
 
   // Generate unique pipe names for the four named pipes needed.
-  static const int kMaxPipeNameSize = 80;
   wchar_t pipe_names[4][kMaxPipeNameSize];
-  UUID uuid;
-  RPC_STATUS status = UuidCreateSequential(&uuid);
-  if (status != RPC_S_OK && status != RPC_S_UUID_LOCAL_ONLY) {
+  int status = GenerateNames<4>(pipe_names);
+  if (status != 0) {
     SetOsErrorMessage(os_error_message);
     Log::PrintErr("UuidCreateSequential failed %d\n", status);
     return status;
   }
-  RPC_WSTR uuid_string;
-  status = UuidToStringW(&uuid, &uuid_string);
-  if (status != RPC_S_OK) {
-    SetOsErrorMessage(os_error_message);
-    Log::PrintErr("UuidToString failed %d\n", status);
-    return status;
-  }
-  for (int i = 0; i < 4; i++) {
-    static const wchar_t* prefix = L"\\\\.\\Pipe\\dart";
-    _snwprintf(pipe_names[i],
-               kMaxPipeNameSize,
-               L"%s_%s_%d", prefix, uuid_string, i + 1);
-  }
-  status = RpcStringFreeW(&uuid_string);
-  if (status != RPC_S_OK) {
-    SetOsErrorMessage(os_error_message);
-    Log::PrintErr("RpcStringFree failed %d\n", status);
-    return status;
-  }
 
   if (!CreateProcessPipe(stdin_handles, pipe_names[0], kInheritRead)) {
     int error_code = SetOsErrorMessage(os_error_message);
@@ -849,6 +856,102 @@
   return static_cast<intptr_t>(GetCurrentProcessId());
 }
 
+
+static SignalInfo* signal_handlers = NULL;
+static Mutex* signal_mutex = new Mutex();
+
+
+SignalInfo::~SignalInfo() {
+  reinterpret_cast<FileHandle*>(fd_)->Close();
+}
+
+
+BOOL WINAPI SignalHandler(DWORD signal) {
+  MutexLocker lock(signal_mutex);
+  const SignalInfo* handler = signal_handlers;
+  bool handled = false;
+  while (handler != NULL) {
+    if (handler->signal() == signal) {
+      int value = 0;
+      Socket::Write(handler->fd(), &value, 1);
+      handled = true;
+    }
+    handler = handler->next();
+  }
+  return handled;
+}
+
+
+intptr_t GetWinSignal(intptr_t signal) {
+  switch (signal) {
+    case kSighup: return CTRL_CLOSE_EVENT;
+    case kSigint: return CTRL_C_EVENT;
+    default:
+      return -1;
+  }
+}
+
+
+intptr_t Process::SetSignalHandler(intptr_t signal) {
+  signal = GetWinSignal(signal);
+  if (signal == -1) return -1;
+
+  // Generate a unique pipe name for the named pipe.
+  wchar_t pipe_name[kMaxPipeNameSize];
+  int status = GenerateNames<1>(&pipe_name);
+  if (status != 0) return status;
+
+  HANDLE fds[2];
+  if (!CreateProcessPipe(fds, pipe_name, kInheritNone)) {
+    int error_code = GetLastError();
+    CloseProcessPipe(fds);
+    SetLastError(error_code);
+    return -1;
+  }
+  MutexLocker lock(signal_mutex);
+  FileHandle* write_handle = new FileHandle(fds[kWriteHandle]);
+  write_handle->EnsureInitialized(EventHandler::delegate());
+  intptr_t write_fd = reinterpret_cast<intptr_t>(write_handle);
+  if (signal_handlers == NULL) {
+    if (SetConsoleCtrlHandler(SignalHandler, true) == 0) {
+      int error_code = GetLastError();
+      delete write_handle;
+      CloseProcessPipe(fds);
+      SetLastError(error_code);
+      return -1;
+    }
+    signal_handlers = new SignalInfo(write_fd, signal);
+  } else {
+    new SignalInfo(write_fd, signal, signal_handlers);
+  }
+  return reinterpret_cast<intptr_t>(new FileHandle(fds[kReadHandle]));
+}
+
+
+void Process::ClearSignalHandler(intptr_t signal) {
+  signal = GetWinSignal(signal);
+  if (signal == -1) return;
+  MutexLocker lock(signal_mutex);
+  SignalInfo* handler = signal_handlers;
+  while (handler != NULL) {
+    if (handler->port() == Dart_GetMainPortId() &&
+        handler->signal() == signal) {
+      handler->Unlink();
+      break;
+    }
+    handler = handler->next();
+  }
+  if (handler != NULL) {
+    if (signal_handlers == handler) {
+      signal_handlers = handler->next();
+    }
+    if (signal_handlers == NULL) {
+      USE(SetConsoleCtrlHandler(SignalHandler, false));
+    }
+  }
+  delete handler;
+}
+
 }  // namespace bin
 }  // namespace dart
 
diff --git a/runtime/bin/resources_sources.gypi b/runtime/bin/resources_sources.gypi
index 941f67d..c5f7885 100644
--- a/runtime/bin/resources_sources.gypi
+++ b/runtime/bin/resources_sources.gypi
@@ -5,13 +5,14 @@
 {
   'sources': [
 #  VM Service backend sources
+    'vmservice/client.dart',
     'vmservice/constants.dart',
     'vmservice/resources.dart',
     'vmservice/running_isolate.dart',
     'vmservice/running_isolates.dart',
     'vmservice/server.dart',
-    'vmservice/service_request.dart',
-    'vmservice/service_request_router.dart',
+    'vmservice/message.dart',
+    'vmservice/message_router.dart',
     'vmservice/vmservice.dart',
     'vmservice/vmservice_io.dart',
 # VM Service frontend sources
diff --git a/runtime/bin/secure_socket.cc b/runtime/bin/secure_socket.cc
index 6fa0a99..4bcaa73 100644
--- a/runtime/bin/secure_socket.cc
+++ b/runtime/bin/secure_socket.cc
@@ -126,16 +126,7 @@
   ThrowIfError(Dart_StringToCString(host_name_object, &host_name));
 
   RawAddr raw_addr;
-  Dart_TypedData_Type type;
-  uint8_t* buffer = NULL;
-  intptr_t len;
-  ThrowIfError(Dart_TypedDataAcquireData(host_sockaddr_storage_object,
-                                         &type,
-                                         reinterpret_cast<void**>(&buffer),
-                                         &len));
-  ASSERT(static_cast<size_t>(len) <= sizeof(raw_addr));
-  memmove(&raw_addr, buffer, len);
-  Dart_TypedDataReleaseData(host_sockaddr_storage_object);
+  SocketAddress::GetSockAddr(host_sockaddr_storage_object, &raw_addr);
 
   int64_t port;
   if (!DartUtils::GetInt64Value(port_object, &port)) {
diff --git a/runtime/bin/signal_blocker.h b/runtime/bin/signal_blocker.h
new file mode 100644
index 0000000..1ab816c
--- /dev/null
+++ b/runtime/bin/signal_blocker.h
@@ -0,0 +1,71 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#ifndef BIN_SIGNAL_BLOCKER_H_
+#define BIN_SIGNAL_BLOCKER_H_
+
+#include "platform/globals.h"
+
+#if defined(TARGET_OS_WINDOWS)
+#error Do not include this file on Windows.
+#endif
+
+#include <signal.h>  // NOLINT
+
+#include "platform/thread.h"
+
+namespace dart {
+namespace bin {
+
+class ThreadSignalBlocker {
+ public:
+  explicit ThreadSignalBlocker(int sig) {
+    sigset_t signal_mask;
+    sigemptyset(&signal_mask);
+    sigaddset(&signal_mask, sig);
+    // Add sig to signal mask.
+    int r = pthread_sigmask(SIG_BLOCK, &signal_mask, &old);
+    USE(r);
+    ASSERT(r == 0);
+  }
+
+  ThreadSignalBlocker(int sigs_count, const int sigs[]) {
+    sigset_t signal_mask;
+    sigemptyset(&signal_mask);
+    for (int i = 0; i < sigs_count; i++) {
+      sigaddset(&signal_mask, sigs[i]);
+    }
+    // Add sig to signal mask.
+    int r = pthread_sigmask(SIG_BLOCK, &signal_mask, &old);
+    USE(r);
+    ASSERT(r == 0);
+  }
+
+  ~ThreadSignalBlocker() {
+    // Restore signal mask.
+    int r = pthread_sigmask(SIG_SETMASK, &old, NULL);
+    USE(r);
+    ASSERT(r == 0);
+  }
+
+ private:
+  sigset_t old;
+};
+
+
+#define TEMP_FAILURE_RETRY_BLOCK_SIGNALS(expression)                           \
+    ({ ThreadSignalBlocker tsb(SIGPROF);                                       \
+       int64_t __result;                                                       \
+       do {                                                                    \
+         __result = static_cast<int64_t>(expression);                          \
+       } while (__result == -1L && errno == EINTR);                            \
+       __result; })
+
+#define VOID_TEMP_FAILURE_RETRY_BLOCK_SIGNALS(expression)                      \
+    (static_cast<void>(TEMP_FAILURE_RETRY_BLOCK_SIGNALS(expression)))
+
+}  // namespace bin
+}  // namespace dart
+
+#endif  // BIN_SIGNAL_BLOCKER_H_
diff --git a/runtime/bin/socket.cc b/runtime/bin/socket.cc
index 2d1b8bc..42fe373 100644
--- a/runtime/bin/socket.cc
+++ b/runtime/bin/socket.cc
@@ -15,7 +15,6 @@
 
 #include "include/dart_api.h"
 
-
 namespace dart {
 namespace bin {
 
@@ -27,75 +26,20 @@
 int Socket::service_ports_index_ = 0;
 
 
-static void GetSockAddr(Dart_Handle obj, RawAddr* addr) {
-  Dart_TypedData_Type data_type;
-  uint8_t* data = NULL;
-  intptr_t len;
-  Dart_Handle result = Dart_TypedDataAcquireData(
-      obj, &data_type, reinterpret_cast<void**>(&data), &len);
-  if (Dart_IsError(result)) Dart_PropagateError(result);
-  if (data_type != Dart_TypedData_kUint8) {
-    Dart_PropagateError(Dart_NewApiError("Unexpected type for socket address"));
-  }
-  memmove(reinterpret_cast<void *>(addr), data, len);
-  Dart_TypedDataReleaseData(obj);
-}
-
-
-void FUNCTION_NAME(InternetAddress_Fixed)(Dart_NativeArguments args) {
-  int64_t id = 0;
-  bool ok = DartUtils::GetInt64Value(Dart_GetNativeArgument(args, 0), &id);
-  ASSERT(ok);
-  USE(ok);
-  RawAddr raw;
-  memset(&raw, 0, sizeof(raw));
-  switch (id) {
-    case SocketAddress::ADDRESS_LOOPBACK_IP_V4: {
-      raw.in.sin_family = AF_INET;
-      raw.in.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
-      break;
-    }
-    case SocketAddress::ADDRESS_LOOPBACK_IP_V6: {
-      raw.in6.sin6_family = AF_INET6;
-      raw.in6.sin6_addr = in6addr_loopback;
-      break;
-    }
-    case SocketAddress::ADDRESS_ANY_IP_V4: {
-      raw.in.sin_family = AF_INET;
-      raw.in.sin_addr.s_addr = INADDR_ANY;
-      break;
-    }
-    case SocketAddress::ADDRESS_ANY_IP_V6: {
-      raw.in6.sin6_family = AF_INET6;
-      raw.in6.sin6_addr = in6addr_any;
-      break;
-    }
-    default:
-      Dart_Handle error = DartUtils::NewDartArgumentError("");
-      if (Dart_IsError(error)) Dart_PropagateError(error);
-      Dart_ThrowException(error);
-  }
-  Dart_SetReturnValue(args, SocketAddress::ToTypedData(&raw));
-}
-
-
 void FUNCTION_NAME(InternetAddress_Parse)(Dart_NativeArguments args) {
-  int64_t type = 0;
-  bool ok = DartUtils::GetInt64Value(Dart_GetNativeArgument(args, 0), &type);
-  ASSERT(ok);
-  USE(ok);
   const char* address =
-      DartUtils::GetStringValue(Dart_GetNativeArgument(args, 1));
+      DartUtils::GetStringValue(Dart_GetNativeArgument(args, 0));
   ASSERT(address != NULL);
   RawAddr raw;
   memset(&raw, 0, sizeof(raw));
+  int type = strchr(address, ':') == NULL ? SocketAddress::TYPE_IPV4
+                                          : SocketAddress::TYPE_IPV6;
   if (type == SocketAddress::TYPE_IPV4) {
     raw.addr.sa_family = AF_INET;
   } else {
-    ASSERT(type == SocketAddress::TYPE_IPV6);
     raw.addr.sa_family = AF_INET6;
   }
-  ok = Socket::ParseAddress(type, address, &raw);
+  bool ok = Socket::ParseAddress(type, address, &raw);
   if (!ok) {
     Dart_SetReturnValue(args, Dart_Null());
   } else {
@@ -106,7 +50,7 @@
 
 void FUNCTION_NAME(Socket_CreateConnect)(Dart_NativeArguments args) {
   RawAddr addr;
-  GetSockAddr(Dart_GetNativeArgument(args, 1), &addr);
+  SocketAddress::GetSockAddr(Dart_GetNativeArgument(args, 1), &addr);
   Dart_Handle port_arg = Dart_GetNativeArgument(args, 2);
   int64_t port = DartUtils::GetInt64ValueCheckRange(port_arg, 0, 65535);
   intptr_t socket = Socket::CreateConnect(addr, port);
@@ -122,7 +66,7 @@
 
 void FUNCTION_NAME(Socket_CreateBindDatagram)(Dart_NativeArguments args) {
   RawAddr addr;
-  GetSockAddr(Dart_GetNativeArgument(args, 1), &addr);
+  SocketAddress::GetSockAddr(Dart_GetNativeArgument(args, 1), &addr);
   Dart_Handle port_arg = Dart_GetNativeArgument(args, 2);
   int64_t port = DartUtils::GetInt64ValueCheckRange(port_arg, 0, 65535);
   bool reuse_addr = DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 3));
@@ -246,20 +190,14 @@
   Socket::FormatNumericAddress(&addr, numeric_address, INET6_ADDRSTRLEN);
 
   // Create a Datagram object with the data and sender address and port.
-  const int kNumArgs = 5;
+  const int kNumArgs = 4;
   Dart_Handle dart_args[kNumArgs];
   dart_args[0] = data;
-  dart_args[1] = Dart_NewBoolean(addr.addr.sa_family == AF_INET6);
-  dart_args[2] = Dart_NewStringFromCString(numeric_address);
-  if (Dart_IsError(dart_args[2])) Dart_PropagateError(dart_args[2]);
-  int len = SocketAddress::GetAddrLength(&addr);
-  dart_args[3] = Dart_NewTypedData(Dart_TypedData_kUint8, len);
+  dart_args[1] = Dart_NewStringFromCString(numeric_address);
+  if (Dart_IsError(dart_args[1])) Dart_PropagateError(dart_args[1]);
+  dart_args[2] = SocketAddress::ToTypedData(&addr);
+  dart_args[3] = Dart_NewInteger(port);
   if (Dart_IsError(dart_args[3])) Dart_PropagateError(dart_args[3]);
-  Dart_Handle err = Dart_ListSetAsBytes(
-      dart_args[3], 0, reinterpret_cast<uint8_t *>(&addr), len);
-  if (Dart_IsError(err)) Dart_PropagateError(err);
-  dart_args[4] = Dart_NewInteger(port);
-  if (Dart_IsError(dart_args[4])) Dart_PropagateError(dart_args[4]);
   // TODO(sgjesse): Cache the _makeDatagram function somewhere.
   Dart_Handle io_lib =
       Dart_LookupLibrary(DartUtils::NewString("dart:io"));
@@ -319,7 +257,7 @@
   Dart_Handle address_obj = Dart_GetNativeArgument(args, 4);
   ASSERT(Dart_IsList(address_obj));
   RawAddr addr;
-  GetSockAddr(address_obj, &addr);
+  SocketAddress::GetSockAddr(address_obj, &addr);
   int64_t port = DartUtils::GetInt64ValueCheckRange(
       Dart_GetNativeArgument(args, 5),
       0,
@@ -428,7 +366,7 @@
 
 void FUNCTION_NAME(ServerSocket_CreateBindListen)(Dart_NativeArguments args) {
   RawAddr addr;
-  GetSockAddr(Dart_GetNativeArgument(args, 1), &addr);
+  SocketAddress::GetSockAddr(Dart_GetNativeArgument(args, 1), &addr);
   int64_t port = DartUtils::GetInt64ValueCheckRange(
       Dart_GetNativeArgument(args, 2),
       0,
@@ -497,13 +435,9 @@
         entry->SetAt(1, as_string);
 
         RawAddr raw = addr->addr();
-        CObjectUint8Array* data = new CObjectUint8Array(CObject::NewUint8Array(
-            SocketAddress::GetAddrLength(&raw)));
-        memmove(data->Buffer(),
-                reinterpret_cast<void *>(&raw),
-                SocketAddress::GetAddrLength(&raw));
-
+        CObjectUint8Array* data = SocketAddress::ToCObject(&raw);
         entry->SetAt(2, data);
+
         array->SetAt(i + 1, entry);
       }
       result = array;
@@ -523,9 +457,21 @@
       request[0]->IsTypedData()) {
     CObjectUint8Array addr_object(request[0]);
     RawAddr addr;
-    memmove(reinterpret_cast<void *>(&addr),
-            addr_object.Buffer(),
-            addr_object.Length());
+    int len = addr_object.Length();
+    memset(reinterpret_cast<void*>(&addr), 0, sizeof(RawAddr));
+    if (len == sizeof(in_addr)) {
+      addr.in.sin_family = AF_INET;
+      memmove(reinterpret_cast<void*>(&addr.in.sin_addr),
+              addr_object.Buffer(),
+              len);
+    } else {
+      ASSERT(len == sizeof(in6_addr));
+      addr.in6.sin6_family = AF_INET6;
+      memmove(reinterpret_cast<void*>(&addr.in6.sin6_addr),
+              addr_object.Buffer(),
+              len);
+    }
+
     OSError* os_error = NULL;
     const intptr_t kMaxHostLength = 1025;
     char host[kMaxHostLength];
@@ -567,11 +513,7 @@
         entry->SetAt(1, as_string);
 
         RawAddr raw = addr->addr();
-        CObjectUint8Array* data = new CObjectUint8Array(CObject::NewUint8Array(
-            SocketAddress::GetAddrLength(&raw)));
-        memmove(data->Buffer(),
-                reinterpret_cast<void *>(&raw),
-                SocketAddress::GetAddrLength(&raw));
+        CObjectUint8Array* data = SocketAddress::ToCObject(&raw);
         entry->SetAt(2, data);
 
         CObjectString* interface_name = new CObjectString(CObject::NewString(
@@ -702,10 +644,10 @@
   intptr_t socket =
       Socket::GetSocketIdNativeField(Dart_GetNativeArgument(args, 0));
   RawAddr addr;
-  GetSockAddr(Dart_GetNativeArgument(args, 1), &addr);
+  SocketAddress::GetSockAddr(Dart_GetNativeArgument(args, 1), &addr);
   RawAddr interface;
   if (Dart_GetNativeArgument(args, 2) != Dart_Null()) {
-    GetSockAddr(Dart_GetNativeArgument(args, 2), &interface);
+    SocketAddress::GetSockAddr(Dart_GetNativeArgument(args, 2), &interface);
   }
   int interfaceIndex =
       DartUtils::GetIntegerValue(Dart_GetNativeArgument(args, 3));
@@ -721,10 +663,10 @@
   intptr_t socket =
       Socket::GetSocketIdNativeField(Dart_GetNativeArgument(args, 0));
   RawAddr addr;
-  GetSockAddr(Dart_GetNativeArgument(args, 1), &addr);
+  SocketAddress::GetSockAddr(Dart_GetNativeArgument(args, 1), &addr);
   RawAddr interface;
   if (Dart_GetNativeArgument(args, 2) != Dart_Null()) {
-    GetSockAddr(Dart_GetNativeArgument(args, 2), &interface);
+    SocketAddress::GetSockAddr(Dart_GetNativeArgument(args, 2), &interface);
   }
   int interfaceIndex =
       DartUtils::GetIntegerValue(Dart_GetNativeArgument(args, 3));
diff --git a/runtime/bin/socket.h b/runtime/bin/socket.h
index 0c009b0..b27a9c5 100644
--- a/runtime/bin/socket.h
+++ b/runtime/bin/socket.h
@@ -70,6 +70,36 @@
         sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in);
   }
 
+  static intptr_t GetInAddrLength(const RawAddr* addr) {
+    ASSERT(addr->ss.ss_family == AF_INET || addr->ss.ss_family == AF_INET6);
+    return addr->ss.ss_family == AF_INET6 ?
+        sizeof(struct in6_addr) : sizeof(struct in_addr);
+  }
+
+  static void GetSockAddr(Dart_Handle obj, RawAddr* addr) {
+    Dart_TypedData_Type data_type;
+    uint8_t* data = NULL;
+    intptr_t len;
+    Dart_Handle result = Dart_TypedDataAcquireData(
+        obj, &data_type, reinterpret_cast<void**>(&data), &len);
+    if (Dart_IsError(result)) Dart_PropagateError(result);
+    if (data_type != Dart_TypedData_kUint8 ||
+        (len != sizeof(in_addr) && len != sizeof(in6_addr))) {
+      Dart_PropagateError(
+          Dart_NewApiError("Unexpected type for socket address"));
+    }
+    memset(reinterpret_cast<void*>(addr), 0, sizeof(RawAddr));
+    if (len == sizeof(in_addr)) {
+      addr->in.sin_family = AF_INET;
+      memmove(reinterpret_cast<void *>(&addr->in.sin_addr), data, len);
+    } else {
+      ASSERT(len == sizeof(in6_addr));
+      addr->in6.sin6_family = AF_INET6;
+      memmove(reinterpret_cast<void*>(&addr->in6.sin6_addr), data, len);
+    }
+    Dart_TypedDataReleaseData(obj);
+  }
+
   static int16_t FromType(int type) {
     if (type == TYPE_ANY) return AF_UNSPEC;
     if (type == TYPE_IPV4) return AF_INET;
@@ -85,7 +115,7 @@
     }
   }
 
-  static intptr_t GetAddrPort(RawAddr* addr) {
+  static intptr_t GetAddrPort(const RawAddr* addr) {
     if (addr->ss.ss_family == AF_INET) {
       return ntohs(addr->in.sin_port);
     } else {
@@ -93,14 +123,36 @@
     }
   }
 
-  static Dart_Handle ToTypedData(RawAddr* addr) {
-    int len = GetAddrLength(addr);
+  static Dart_Handle ToTypedData(RawAddr* raw) {
+    int len = GetInAddrLength(raw);
     Dart_Handle result = Dart_NewTypedData(Dart_TypedData_kUint8, len);
     if (Dart_IsError(result)) Dart_PropagateError(result);
-    Dart_ListSetAsBytes(result, 0, reinterpret_cast<uint8_t *>(addr), len);
+    Dart_Handle err;
+    if (raw->addr.sa_family == AF_INET6) {
+      err = Dart_ListSetAsBytes(
+          result, 0, reinterpret_cast<uint8_t*>(&raw->in6.sin6_addr), len);
+    } else {
+      err = Dart_ListSetAsBytes(
+          result, 0, reinterpret_cast<uint8_t*>(&raw->in.sin_addr), len);
+    }
+    if (Dart_IsError(err)) Dart_PropagateError(err);
     return result;
   }
 
+  static CObjectUint8Array* ToCObject(RawAddr* raw) {
+    int in_addr_len = SocketAddress::GetInAddrLength(raw);
+    void* in_addr;
+    CObjectUint8Array* data =
+        new CObjectUint8Array(CObject::NewUint8Array(in_addr_len));
+    if (raw->addr.sa_family == AF_INET6) {
+      in_addr = reinterpret_cast<void*>(&raw->in6.sin6_addr);
+    } else {
+      in_addr = reinterpret_cast<void*>(&raw->in.sin_addr);
+    }
+    memmove(data->Buffer(), in_addr, in_addr_len);
+    return data;
+  }
+
  private:
   char as_string_[INET6_ADDRSTRLEN];
   RawAddr addr_;
diff --git a/runtime/bin/socket_android.cc b/runtime/bin/socket_android.cc
index 72a03bd..0ab6af4 100644
--- a/runtime/bin/socket_android.cc
+++ b/runtime/bin/socket_android.cc
@@ -16,6 +16,7 @@
 #include "bin/fdutils.h"
 #include "bin/file.h"
 #include "bin/log.h"
+#include "bin/signal_blocker.h"
 #include "bin/socket.h"
 
 
@@ -35,7 +36,7 @@
 
 bool Socket::FormatNumericAddress(RawAddr* addr, char* address, int len) {
   socklen_t salen = SocketAddress::GetAddrLength(addr);
-  if (TEMP_FAILURE_RETRY(getnameinfo(&addr->addr,
+  if (TEMP_FAILURE_RETRY_BLOCK_SIGNALS(getnameinfo(&addr->addr,
                                      salen,
                                      address,
                                      len,
@@ -56,8 +57,8 @@
 
 intptr_t Socket::Create(RawAddr addr) {
   intptr_t fd;
-
-  fd = TEMP_FAILURE_RETRY(socket(addr.ss.ss_family, SOCK_STREAM, 0));
+  fd = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(socket(addr.ss.ss_family, SOCK_STREAM,
+                                               0));
   if (fd < 0) {
     const int kBufferSize = 1024;
     char error_message[kBufferSize];
@@ -73,14 +74,14 @@
 
 intptr_t Socket::Connect(intptr_t fd, RawAddr addr, const intptr_t port) {
   SocketAddress::SetAddrPort(&addr, port);
-  intptr_t result = TEMP_FAILURE_RETRY(
+  intptr_t result = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(
       connect(fd,
               &addr.addr,
               SocketAddress::GetAddrLength(&addr)));
   if (result == 0 || errno == EINPROGRESS) {
     return fd;
   }
-  VOID_TEMP_FAILURE_RETRY(close(fd));
+  VOID_TEMP_FAILURE_RETRY_BLOCK_SIGNALS(close(fd));
   return -1;
 }
 
@@ -104,7 +105,8 @@
 
 int Socket::Read(intptr_t fd, void* buffer, intptr_t num_bytes) {
   ASSERT(fd >= 0);
-  ssize_t read_bytes = TEMP_FAILURE_RETRY(read(fd, buffer, num_bytes));
+  ssize_t read_bytes = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(read(fd, buffer,
+                                                             num_bytes));
   ASSERT(EAGAIN == EWOULDBLOCK);
   if (read_bytes == -1 && errno == EWOULDBLOCK) {
     // If the read would block we need to retry and therefore return 0
@@ -120,7 +122,7 @@
   ASSERT(fd >= 0);
   socklen_t addr_len = sizeof(addr->ss);
   ssize_t read_bytes =
-      TEMP_FAILURE_RETRY(
+      TEMP_FAILURE_RETRY_BLOCK_SIGNALS(
           recvfrom(fd, buffer, num_bytes, 0, &addr->addr, &addr_len));
   if (read_bytes == -1 && errno == EWOULDBLOCK) {
     // If the read would block we need to retry and therefore return 0
@@ -133,7 +135,8 @@
 
 int Socket::Write(intptr_t fd, const void* buffer, intptr_t num_bytes) {
   ASSERT(fd >= 0);
-  ssize_t written_bytes = TEMP_FAILURE_RETRY(write(fd, buffer, num_bytes));
+  ssize_t written_bytes = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(write(fd, buffer,
+                                                                 num_bytes));
   ASSERT(EAGAIN == EWOULDBLOCK);
   if (written_bytes == -1 && errno == EWOULDBLOCK) {
     // If the would block we need to retry and therefore return 0 as
@@ -148,7 +151,7 @@
                    RawAddr addr) {
   ASSERT(fd >= 0);
   ssize_t written_bytes =
-      TEMP_FAILURE_RETRY(
+      TEMP_FAILURE_RETRY_BLOCK_SIGNALS(
           sendto(fd, buffer, num_bytes, 0,
                  &addr.addr, SocketAddress::GetAddrLength(&addr)));
   ASSERT(EAGAIN == EWOULDBLOCK);
@@ -165,7 +168,7 @@
   ASSERT(fd >= 0);
   RawAddr raw;
   socklen_t size = sizeof(raw);
-  if (TEMP_FAILURE_RETRY(
+  if (TEMP_FAILURE_RETRY_BLOCK_SIGNALS(
           getsockname(fd,
                       &raw.addr,
                       &size))) {
@@ -183,7 +186,7 @@
   ASSERT(fd >= 0);
   RawAddr raw;
   socklen_t size = sizeof(raw);
-  if (TEMP_FAILURE_RETRY(
+  if (TEMP_FAILURE_RETRY_BLOCK_SIGNALS(
           getpeername(fd,
                       &raw.addr,
                       &size))) {
@@ -268,7 +271,7 @@
                            intptr_t host_len,
                            OSError** os_error) {
   ASSERT(host_len >= NI_MAXHOST);
-  int status = TEMP_FAILURE_RETRY(getnameinfo(
+  int status = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(getnameinfo(
       &addr.addr,
       SocketAddress::GetAddrLength(&addr),
       host,
@@ -303,7 +306,7 @@
     RawAddr* addr, intptr_t port, bool reuseAddress) {
   intptr_t fd;
 
-  fd = TEMP_FAILURE_RETRY(
+  fd = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(
       socket(addr->addr.sa_family, SOCK_DGRAM, IPPROTO_UDP));
   if (fd < 0) return -1;
 
@@ -311,16 +314,16 @@
 
   if (reuseAddress) {
     int optval = 1;
-    VOID_TEMP_FAILURE_RETRY(
+    VOID_TEMP_FAILURE_RETRY_BLOCK_SIGNALS(
         setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)));
   }
 
   SocketAddress::SetAddrPort(addr, port);
-  if (TEMP_FAILURE_RETRY(
+  if (TEMP_FAILURE_RETRY_BLOCK_SIGNALS(
           bind(fd,
                &addr->addr,
                SocketAddress::GetAddrLength(addr))) < 0) {
-    TEMP_FAILURE_RETRY(close(fd));
+    TEMP_FAILURE_RETRY_BLOCK_SIGNALS(close(fd));
     return -1;
   }
 
@@ -344,27 +347,28 @@
                                         bool v6_only) {
   intptr_t fd;
 
-  fd = TEMP_FAILURE_RETRY(socket(addr.ss.ss_family, SOCK_STREAM, 0));
+  fd = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(socket(addr.ss.ss_family, SOCK_STREAM,
+                                               0));
   if (fd < 0) return -1;
 
   FDUtils::SetCloseOnExec(fd);
 
   int optval = 1;
-  TEMP_FAILURE_RETRY(
+  TEMP_FAILURE_RETRY_BLOCK_SIGNALS(
       setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)));
 
   if (addr.ss.ss_family == AF_INET6) {
     optval = v6_only ? 1 : 0;
-    TEMP_FAILURE_RETRY(
+    TEMP_FAILURE_RETRY_BLOCK_SIGNALS(
         setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &optval, sizeof(optval)));
   }
 
   SocketAddress::SetAddrPort(&addr, port);
-  if (TEMP_FAILURE_RETRY(
+  if (TEMP_FAILURE_RETRY_BLOCK_SIGNALS(
           bind(fd,
                &addr.addr,
                SocketAddress::GetAddrLength(&addr))) < 0) {
-    VOID_TEMP_FAILURE_RETRY(close(fd));
+    VOID_TEMP_FAILURE_RETRY_BLOCK_SIGNALS(close(fd));
     return -1;
   }
 
@@ -374,13 +378,14 @@
     // that we do not get the bad port number again.
     intptr_t new_fd = CreateBindListen(addr, 0, backlog, v6_only);
     int err = errno;
-    VOID_TEMP_FAILURE_RETRY(close(fd));
+    VOID_TEMP_FAILURE_RETRY_BLOCK_SIGNALS(close(fd));
     errno = err;
     return new_fd;
   }
 
-  if (TEMP_FAILURE_RETRY(listen(fd, backlog > 0 ? backlog : SOMAXCONN)) != 0) {
-    VOID_TEMP_FAILURE_RETRY(close(fd));
+  if (TEMP_FAILURE_RETRY_BLOCK_SIGNALS(
+      listen(fd, backlog > 0 ? backlog : SOMAXCONN)) != 0) {
+    VOID_TEMP_FAILURE_RETRY_BLOCK_SIGNALS(close(fd));
     return -1;
   }
 
@@ -403,7 +408,7 @@
   intptr_t socket;
   struct sockaddr clientaddr;
   socklen_t addrlen = sizeof(clientaddr);
-  socket = TEMP_FAILURE_RETRY(accept(fd, &clientaddr, &addrlen));
+  socket = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(accept(fd, &clientaddr, &addrlen));
   if (socket == -1) {
     if (IsTemporaryAcceptError(errno)) {
       // We need to signal to the caller that this is actually not an
@@ -421,7 +426,7 @@
 
 void Socket::Close(intptr_t fd) {
   ASSERT(fd >= 0);
-  int err = TEMP_FAILURE_RETRY(close(fd));
+  int err = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(close(fd));
   if (err != 0) {
     const int kBufferSize = 1024;
     char error_message[kBufferSize];
@@ -444,7 +449,7 @@
 bool Socket::GetNoDelay(intptr_t fd, bool* enabled) {
   int on;
   socklen_t len = sizeof(on);
-  int err = TEMP_FAILURE_RETRY(getsockopt(fd,
+  int err = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(getsockopt(fd,
                                           IPPROTO_TCP,
                                           TCP_NODELAY,
                                           reinterpret_cast<void *>(&on),
@@ -458,7 +463,7 @@
 
 bool Socket::SetNoDelay(intptr_t fd, bool enabled) {
   int on = enabled ? 1 : 0;
-  return TEMP_FAILURE_RETRY(setsockopt(fd,
+  return TEMP_FAILURE_RETRY_BLOCK_SIGNALS(setsockopt(fd,
                                        IPPROTO_TCP,
                                        TCP_NODELAY,
                                        reinterpret_cast<char *>(&on),
@@ -472,7 +477,7 @@
   int level = protocol == SocketAddress::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6;
   int optname = protocol == SocketAddress::TYPE_IPV4
       ? IP_MULTICAST_LOOP : IPV6_MULTICAST_LOOP;
-  if (TEMP_FAILURE_RETRY(getsockopt(fd,
+  if (TEMP_FAILURE_RETRY_BLOCK_SIGNALS(getsockopt(fd,
                                      level,
                                      optname,
                                      reinterpret_cast<char *>(&on),
@@ -489,7 +494,7 @@
   int level = protocol == SocketAddress::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6;
   int optname = protocol == SocketAddress::TYPE_IPV4
       ? IP_MULTICAST_LOOP : IPV6_MULTICAST_LOOP;
-  return TEMP_FAILURE_RETRY(setsockopt(fd,
+  return TEMP_FAILURE_RETRY_BLOCK_SIGNALS(setsockopt(fd,
                                        level,
                                        optname,
                                        reinterpret_cast<char *>(&on),
@@ -503,7 +508,7 @@
   int level = protocol == SocketAddress::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6;
   int optname = protocol == SocketAddress::TYPE_IPV4
       ? IP_MULTICAST_TTL : IPV6_MULTICAST_HOPS;
-  if (TEMP_FAILURE_RETRY(getsockopt(fd,
+  if (TEMP_FAILURE_RETRY_BLOCK_SIGNALS(getsockopt(fd,
                                     level,
                                     optname,
                                     reinterpret_cast<char *>(&v),
@@ -520,7 +525,7 @@
   int level = protocol == SocketAddress::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6;
   int optname = protocol == SocketAddress::TYPE_IPV4
       ? IP_MULTICAST_TTL : IPV6_MULTICAST_HOPS;
-  return TEMP_FAILURE_RETRY(setsockopt(fd,
+  return TEMP_FAILURE_RETRY_BLOCK_SIGNALS(setsockopt(fd,
                                        level,
                                        optname,
                                        reinterpret_cast<char *>(&v),
@@ -531,7 +536,7 @@
 bool Socket::GetBroadcast(intptr_t fd, bool* enabled) {
   int on;
   socklen_t len = sizeof(on);
-  int err = TEMP_FAILURE_RETRY(getsockopt(fd,
+  int err = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(getsockopt(fd,
                                           SOL_SOCKET,
                                           SO_BROADCAST,
                                           reinterpret_cast<char *>(&on),
@@ -545,7 +550,7 @@
 
 bool Socket::SetBroadcast(intptr_t fd, bool enabled) {
   int on = enabled ? 1 : 0;
-  return TEMP_FAILURE_RETRY(setsockopt(fd,
+  return TEMP_FAILURE_RETRY_BLOCK_SIGNALS(setsockopt(fd,
                                        SOL_SOCKET,
                                        SO_BROADCAST,
                                        reinterpret_cast<char *>(&on),
@@ -559,7 +564,7 @@
   struct group_req mreq;
   mreq.gr_interface = interfaceIndex;
   memmove(&mreq.gr_group, &addr->ss, SocketAddress::GetAddrLength(addr));
-  return TEMP_FAILURE_RETRY(setsockopt(
+  return TEMP_FAILURE_RETRY_BLOCK_SIGNALS(setsockopt(
       fd, proto, MCAST_JOIN_GROUP, &mreq, sizeof(mreq))) == 0;
 }
 
@@ -570,7 +575,7 @@
   struct group_req mreq;
   mreq.gr_interface = interfaceIndex;
   memmove(&mreq.gr_group, &addr->ss, SocketAddress::GetAddrLength(addr));
-  return TEMP_FAILURE_RETRY(setsockopt(
+  return TEMP_FAILURE_RETRY_BLOCK_SIGNALS(setsockopt(
       fd, proto, MCAST_LEAVE_GROUP, &mreq, sizeof(mreq))) == 0;
 }
 
diff --git a/runtime/bin/socket_linux.cc b/runtime/bin/socket_linux.cc
index 2c4a337..08d8fe1 100644
--- a/runtime/bin/socket_linux.cc
+++ b/runtime/bin/socket_linux.cc
@@ -18,6 +18,7 @@
 #include "bin/fdutils.h"
 #include "bin/file.h"
 #include "bin/log.h"
+#include "bin/signal_blocker.h"
 #include "bin/socket.h"
 
 
@@ -37,7 +38,7 @@
 
 bool Socket::FormatNumericAddress(RawAddr* addr, char* address, int len) {
   socklen_t salen = SocketAddress::GetAddrLength(addr);
-  if (TEMP_FAILURE_RETRY(getnameinfo(&addr->addr,
+  if (TEMP_FAILURE_RETRY_BLOCK_SIGNALS(getnameinfo(&addr->addr,
                                      salen,
                                      address,
                                      len,
@@ -58,8 +59,8 @@
 
 intptr_t Socket::Create(RawAddr addr) {
   intptr_t fd;
-
-  fd = TEMP_FAILURE_RETRY(socket(addr.ss.ss_family, SOCK_STREAM, 0));
+  fd = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(socket(addr.ss.ss_family, SOCK_STREAM,
+                                               0));
   if (fd < 0) {
     const int kBufferSize = 1024;
     char error_buf[kBufferSize];
@@ -75,14 +76,14 @@
 
 intptr_t Socket::Connect(intptr_t fd, RawAddr addr, const intptr_t port) {
   SocketAddress::SetAddrPort(&addr, port);
-  intptr_t result = TEMP_FAILURE_RETRY(
+  intptr_t result = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(
       connect(fd,
               &addr.addr,
               SocketAddress::GetAddrLength(&addr)));
   if (result == 0 || errno == EINPROGRESS) {
     return fd;
   }
-  VOID_TEMP_FAILURE_RETRY(close(fd));
+  VOID_TEMP_FAILURE_RETRY_BLOCK_SIGNALS(close(fd));
   return -1;
 }
 
@@ -106,7 +107,8 @@
 
 int Socket::Read(intptr_t fd, void* buffer, intptr_t num_bytes) {
   ASSERT(fd >= 0);
-  ssize_t read_bytes = TEMP_FAILURE_RETRY(read(fd, buffer, num_bytes));
+  ssize_t read_bytes = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(read(fd, buffer,
+                                                             num_bytes));
   ASSERT(EAGAIN == EWOULDBLOCK);
   if (read_bytes == -1 && errno == EWOULDBLOCK) {
     // If the read would block we need to retry and therefore return 0
@@ -122,7 +124,7 @@
   ASSERT(fd >= 0);
   socklen_t addr_len = sizeof(addr->ss);
   ssize_t read_bytes =
-      TEMP_FAILURE_RETRY(
+      TEMP_FAILURE_RETRY_BLOCK_SIGNALS(
           recvfrom(fd, buffer, num_bytes, 0, &addr->addr, &addr_len));
   if (read_bytes == -1 && errno == EWOULDBLOCK) {
     // If the read would block we need to retry and therefore return 0
@@ -135,7 +137,8 @@
 
 int Socket::Write(intptr_t fd, const void* buffer, intptr_t num_bytes) {
   ASSERT(fd >= 0);
-  ssize_t written_bytes = TEMP_FAILURE_RETRY(write(fd, buffer, num_bytes));
+  ssize_t written_bytes = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(write(fd, buffer,
+                                                                 num_bytes));
   ASSERT(EAGAIN == EWOULDBLOCK);
   if (written_bytes == -1 && errno == EWOULDBLOCK) {
     // If the would block we need to retry and therefore return 0 as
@@ -150,7 +153,7 @@
                    RawAddr addr) {
   ASSERT(fd >= 0);
   ssize_t written_bytes =
-      TEMP_FAILURE_RETRY(
+      TEMP_FAILURE_RETRY_BLOCK_SIGNALS(
           sendto(fd, buffer, num_bytes, 0,
                  &addr.addr, SocketAddress::GetAddrLength(&addr)));
   ASSERT(EAGAIN == EWOULDBLOCK);
@@ -167,7 +170,7 @@
   ASSERT(fd >= 0);
   RawAddr raw;
   socklen_t size = sizeof(raw);
-  if (TEMP_FAILURE_RETRY(
+  if (TEMP_FAILURE_RETRY_BLOCK_SIGNALS(
           getsockname(fd,
                       &raw.addr,
                       &size))) {
@@ -185,7 +188,7 @@
   ASSERT(fd >= 0);
   RawAddr raw;
   socklen_t size = sizeof(raw);
-  if (TEMP_FAILURE_RETRY(
+  if (TEMP_FAILURE_RETRY_BLOCK_SIGNALS(
           getpeername(fd,
                       &raw.addr,
                       &size))) {
@@ -269,7 +272,7 @@
                            intptr_t host_len,
                            OSError** os_error) {
   ASSERT(host_len >= NI_MAXHOST);
-  int status = TEMP_FAILURE_RETRY(getnameinfo(
+  int status = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(getnameinfo(
       &addr.addr,
       SocketAddress::GetAddrLength(&addr),
       host,
@@ -304,7 +307,7 @@
     RawAddr* addr, intptr_t port, bool reuseAddress) {
   intptr_t fd;
 
-  fd = TEMP_FAILURE_RETRY(
+  fd = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(
       socket(addr->addr.sa_family, SOCK_DGRAM, IPPROTO_UDP));
   if (fd < 0) return -1;
 
@@ -312,16 +315,16 @@
 
   if (reuseAddress) {
     int optval = 1;
-    VOID_TEMP_FAILURE_RETRY(
+    VOID_TEMP_FAILURE_RETRY_BLOCK_SIGNALS(
         setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)));
   }
 
   SocketAddress::SetAddrPort(addr, port);
-  if (TEMP_FAILURE_RETRY(
+  if (TEMP_FAILURE_RETRY_BLOCK_SIGNALS(
           bind(fd,
                &addr->addr,
                SocketAddress::GetAddrLength(addr))) < 0) {
-    TEMP_FAILURE_RETRY(close(fd));
+    TEMP_FAILURE_RETRY_BLOCK_SIGNALS(close(fd));
     return -1;
   }
 
@@ -387,27 +390,28 @@
                                         bool v6_only) {
   intptr_t fd;
 
-  fd = TEMP_FAILURE_RETRY(socket(addr.ss.ss_family, SOCK_STREAM, 0));
+  fd = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(socket(addr.ss.ss_family, SOCK_STREAM,
+                                               0));
   if (fd < 0) return -1;
 
   FDUtils::SetCloseOnExec(fd);
 
   int optval = 1;
-  TEMP_FAILURE_RETRY(
+  TEMP_FAILURE_RETRY_BLOCK_SIGNALS(
       setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)));
 
   if (addr.ss.ss_family == AF_INET6) {
     optval = v6_only ? 1 : 0;
-    TEMP_FAILURE_RETRY(
+    TEMP_FAILURE_RETRY_BLOCK_SIGNALS(
         setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &optval, sizeof(optval)));
   }
 
   SocketAddress::SetAddrPort(&addr, port);
-  if (TEMP_FAILURE_RETRY(
+  if (TEMP_FAILURE_RETRY_BLOCK_SIGNALS(
           bind(fd,
                &addr.addr,
                SocketAddress::GetAddrLength(&addr))) < 0) {
-    VOID_TEMP_FAILURE_RETRY(close(fd));
+    VOID_TEMP_FAILURE_RETRY_BLOCK_SIGNALS(close(fd));
     return -1;
   }
 
@@ -417,13 +421,14 @@
     // that we do not get the bad port number again.
     intptr_t new_fd = CreateBindListen(addr, 0, backlog, v6_only);
     int err = errno;
-    VOID_TEMP_FAILURE_RETRY(close(fd));
+    VOID_TEMP_FAILURE_RETRY_BLOCK_SIGNALS(close(fd));
     errno = err;
     return new_fd;
   }
 
-  if (TEMP_FAILURE_RETRY(listen(fd, backlog > 0 ? backlog : SOMAXCONN)) != 0) {
-    VOID_TEMP_FAILURE_RETRY(close(fd));
+  if (TEMP_FAILURE_RETRY_BLOCK_SIGNALS(
+        listen(fd, backlog > 0 ? backlog : SOMAXCONN)) != 0) {
+    VOID_TEMP_FAILURE_RETRY_BLOCK_SIGNALS(close(fd));
     return -1;
   }
 
@@ -446,7 +451,7 @@
   intptr_t socket;
   struct sockaddr clientaddr;
   socklen_t addrlen = sizeof(clientaddr);
-  socket = TEMP_FAILURE_RETRY(accept(fd, &clientaddr, &addrlen));
+  socket = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(accept(fd, &clientaddr, &addrlen));
   if (socket == -1) {
     if (IsTemporaryAcceptError(errno)) {
       // We need to signal to the caller that this is actually not an
@@ -464,7 +469,7 @@
 
 void Socket::Close(intptr_t fd) {
   ASSERT(fd >= 0);
-  int err = TEMP_FAILURE_RETRY(close(fd));
+  int err = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(close(fd));
   if (err != 0) {
     const int kBufferSize = 1024;
     char error_buf[kBufferSize];
@@ -486,7 +491,7 @@
 bool Socket::GetNoDelay(intptr_t fd, bool* enabled) {
   int on;
   socklen_t len = sizeof(on);
-  int err = TEMP_FAILURE_RETRY(getsockopt(fd,
+  int err = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(getsockopt(fd,
                                           IPPROTO_TCP,
                                           TCP_NODELAY,
                                           reinterpret_cast<void *>(&on),
@@ -500,7 +505,7 @@
 
 bool Socket::SetNoDelay(intptr_t fd, bool enabled) {
   int on = enabled ? 1 : 0;
-  return TEMP_FAILURE_RETRY(setsockopt(fd,
+  return TEMP_FAILURE_RETRY_BLOCK_SIGNALS(setsockopt(fd,
                                        IPPROTO_TCP,
                                        TCP_NODELAY,
                                        reinterpret_cast<char *>(&on),
@@ -514,7 +519,7 @@
   int level = protocol == SocketAddress::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6;
   int optname = protocol == SocketAddress::TYPE_IPV4
       ? IP_MULTICAST_LOOP : IPV6_MULTICAST_LOOP;
-  if (TEMP_FAILURE_RETRY(getsockopt(fd,
+  if (TEMP_FAILURE_RETRY_BLOCK_SIGNALS(getsockopt(fd,
                                      level,
                                      optname,
                                      reinterpret_cast<char *>(&on),
@@ -531,7 +536,7 @@
   int level = protocol == SocketAddress::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6;
   int optname = protocol == SocketAddress::TYPE_IPV4
       ? IP_MULTICAST_LOOP : IPV6_MULTICAST_LOOP;
-  return TEMP_FAILURE_RETRY(setsockopt(fd,
+  return TEMP_FAILURE_RETRY_BLOCK_SIGNALS(setsockopt(fd,
                                        level,
                                        optname,
                                        reinterpret_cast<char *>(&on),
@@ -545,7 +550,7 @@
   int level = protocol == SocketAddress::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6;
   int optname = protocol == SocketAddress::TYPE_IPV4
       ? IP_MULTICAST_TTL : IPV6_MULTICAST_HOPS;
-  if (TEMP_FAILURE_RETRY(getsockopt(fd,
+  if (TEMP_FAILURE_RETRY_BLOCK_SIGNALS(getsockopt(fd,
                                     level,
                                     optname,
                                     reinterpret_cast<char *>(&v),
@@ -562,7 +567,7 @@
   int level = protocol == SocketAddress::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6;
   int optname = protocol == SocketAddress::TYPE_IPV4
       ? IP_MULTICAST_TTL : IPV6_MULTICAST_HOPS;
-  return TEMP_FAILURE_RETRY(setsockopt(fd,
+  return TEMP_FAILURE_RETRY_BLOCK_SIGNALS(setsockopt(fd,
                                        level,
                                        optname,
                                        reinterpret_cast<char *>(&v),
@@ -573,7 +578,7 @@
 bool Socket::GetBroadcast(intptr_t fd, bool* enabled) {
   int on;
   socklen_t len = sizeof(on);
-  int err = TEMP_FAILURE_RETRY(getsockopt(fd,
+  int err = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(getsockopt(fd,
                                           SOL_SOCKET,
                                           SO_BROADCAST,
                                           reinterpret_cast<char *>(&on),
@@ -587,7 +592,7 @@
 
 bool Socket::SetBroadcast(intptr_t fd, bool enabled) {
   int on = enabled ? 1 : 0;
-  return TEMP_FAILURE_RETRY(setsockopt(fd,
+  return TEMP_FAILURE_RETRY_BLOCK_SIGNALS(setsockopt(fd,
                                        SOL_SOCKET,
                                        SO_BROADCAST,
                                        reinterpret_cast<char *>(&on),
@@ -601,7 +606,7 @@
   struct group_req mreq;
   mreq.gr_interface = interfaceIndex;
   memmove(&mreq.gr_group, &addr->ss, SocketAddress::GetAddrLength(addr));
-  return TEMP_FAILURE_RETRY(setsockopt(
+  return TEMP_FAILURE_RETRY_BLOCK_SIGNALS(setsockopt(
       fd, proto, MCAST_JOIN_GROUP, &mreq, sizeof(mreq))) == 0;
 }
 
@@ -612,7 +617,7 @@
   struct group_req mreq;
   mreq.gr_interface = interfaceIndex;
   memmove(&mreq.gr_group, &addr->ss, SocketAddress::GetAddrLength(addr));
-  return TEMP_FAILURE_RETRY(setsockopt(
+  return TEMP_FAILURE_RETRY_BLOCK_SIGNALS(setsockopt(
       fd, proto, MCAST_LEAVE_GROUP, &mreq, sizeof(mreq))) == 0;
 }
 
diff --git a/runtime/bin/socket_macos.cc b/runtime/bin/socket_macos.cc
index f626dff..815b0f7 100644
--- a/runtime/bin/socket_macos.cc
+++ b/runtime/bin/socket_macos.cc
@@ -18,6 +18,7 @@
 #include "bin/fdutils.h"
 #include "bin/file.h"
 #include "bin/log.h"
+#include "bin/signal_blocker.h"
 #include "bin/socket.h"
 
 
@@ -37,7 +38,7 @@
 
 bool Socket::FormatNumericAddress(RawAddr* addr, char* address, int len) {
   socklen_t salen = SocketAddress::GetAddrLength(addr);
-  if (TEMP_FAILURE_RETRY(getnameinfo(&addr->addr,
+  if (TEMP_FAILURE_RETRY_BLOCK_SIGNALS(getnameinfo(&addr->addr,
                                      salen,
                                      address,
                                      len,
@@ -58,8 +59,8 @@
 
 intptr_t Socket::Create(RawAddr addr) {
   intptr_t fd;
-
-  fd = TEMP_FAILURE_RETRY(socket(addr.ss.ss_family, SOCK_STREAM, 0));
+  fd = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(socket(addr.ss.ss_family, SOCK_STREAM,
+                                               0));
   if (fd < 0) {
     const int kBufferSize = 1024;
     char error_message[kBufferSize];
@@ -75,14 +76,14 @@
 
 intptr_t Socket::Connect(intptr_t fd, RawAddr addr, const intptr_t port) {
   SocketAddress::SetAddrPort(&addr, port);
-  intptr_t result = TEMP_FAILURE_RETRY(
+  intptr_t result = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(
       connect(fd,
               &addr.addr,
               SocketAddress::GetAddrLength(&addr)));
   if (result == 0 || errno == EINPROGRESS) {
     return fd;
   }
-  VOID_TEMP_FAILURE_RETRY(close(fd));
+  VOID_TEMP_FAILURE_RETRY_BLOCK_SIGNALS(close(fd));
   return -1;
 }
 
@@ -106,7 +107,8 @@
 
 int Socket::Read(intptr_t fd, void* buffer, intptr_t num_bytes) {
   ASSERT(fd >= 0);
-  ssize_t read_bytes = TEMP_FAILURE_RETRY(read(fd, buffer, num_bytes));
+  ssize_t read_bytes = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(read(fd, buffer,
+                                                             num_bytes));
   ASSERT(EAGAIN == EWOULDBLOCK);
   if (read_bytes == -1 && errno == EWOULDBLOCK) {
     // If the read would block we need to retry and therefore return 0
@@ -122,7 +124,7 @@
   ASSERT(fd >= 0);
   socklen_t addr_len = sizeof(addr->ss);
   ssize_t read_bytes =
-      TEMP_FAILURE_RETRY(
+      TEMP_FAILURE_RETRY_BLOCK_SIGNALS(
           recvfrom(fd, buffer, num_bytes, 0, &addr->addr, &addr_len));
   if (read_bytes == -1 && errno == EWOULDBLOCK) {
     // If the read would block we need to retry and therefore return 0
@@ -135,7 +137,8 @@
 
 int Socket::Write(intptr_t fd, const void* buffer, intptr_t num_bytes) {
   ASSERT(fd >= 0);
-  ssize_t written_bytes = TEMP_FAILURE_RETRY(write(fd, buffer, num_bytes));
+  ssize_t written_bytes = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(write(fd, buffer,
+                                                                 num_bytes));
   ASSERT(EAGAIN == EWOULDBLOCK);
   if (written_bytes == -1 && errno == EWOULDBLOCK) {
     // If the would block we need to retry and therefore return 0 as
@@ -150,7 +153,7 @@
                    RawAddr addr) {
   ASSERT(fd >= 0);
   ssize_t written_bytes =
-      TEMP_FAILURE_RETRY(
+      TEMP_FAILURE_RETRY_BLOCK_SIGNALS(
           sendto(fd, buffer, num_bytes, 0,
                  &addr.addr, SocketAddress::GetAddrLength(&addr)));
   ASSERT(EAGAIN == EWOULDBLOCK);
@@ -167,7 +170,7 @@
   ASSERT(fd >= 0);
   RawAddr raw;
   socklen_t size = sizeof(raw);
-  if (TEMP_FAILURE_RETRY(
+  if (TEMP_FAILURE_RETRY_BLOCK_SIGNALS(
           getsockname(fd,
                       &raw.addr,
                       &size))) {
@@ -185,7 +188,7 @@
   ASSERT(fd >= 0);
   RawAddr raw;
   socklen_t size = sizeof(raw);
-  if (TEMP_FAILURE_RETRY(
+  if (TEMP_FAILURE_RETRY_BLOCK_SIGNALS(
           getpeername(fd,
                       &raw.addr,
                       &size))) {
@@ -269,7 +272,7 @@
                            intptr_t host_len,
                            OSError** os_error) {
   ASSERT(host_len >= NI_MAXHOST);
-  int status = TEMP_FAILURE_RETRY(getnameinfo(
+  int status = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(getnameinfo(
       &addr.addr,
       SocketAddress::GetAddrLength(&addr),
       host,
@@ -304,7 +307,7 @@
     RawAddr* addr, intptr_t port, bool reuseAddress) {
   intptr_t fd;
 
-  fd = TEMP_FAILURE_RETRY(
+  fd = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(
       socket(addr->addr.sa_family, SOCK_DGRAM, IPPROTO_UDP));
   if (fd < 0) return -1;
 
@@ -312,16 +315,16 @@
 
   if (reuseAddress) {
     int optval = 1;
-    VOID_TEMP_FAILURE_RETRY(
+    VOID_TEMP_FAILURE_RETRY_BLOCK_SIGNALS(
         setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)));
   }
 
   SocketAddress::SetAddrPort(addr, port);
-  if (TEMP_FAILURE_RETRY(
+  if (TEMP_FAILURE_RETRY_BLOCK_SIGNALS(
           bind(fd,
                &addr->addr,
                SocketAddress::GetAddrLength(addr))) < 0) {
-    VOID_TEMP_FAILURE_RETRY(close(fd));
+    VOID_TEMP_FAILURE_RETRY_BLOCK_SIGNALS(close(fd));
     return -1;
   }
 
@@ -387,27 +390,28 @@
                                         bool v6_only) {
   intptr_t fd;
 
-  fd = TEMP_FAILURE_RETRY(socket(addr.ss.ss_family, SOCK_STREAM, 0));
+  fd = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(socket(addr.ss.ss_family, SOCK_STREAM,
+                                               0));
   if (fd < 0) return -1;
 
   FDUtils::SetCloseOnExec(fd);
 
   int optval = 1;
-  VOID_TEMP_FAILURE_RETRY(
+  VOID_TEMP_FAILURE_RETRY_BLOCK_SIGNALS(
       setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)));
 
   if (addr.ss.ss_family == AF_INET6) {
     optval = v6_only ? 1 : 0;
-    VOID_TEMP_FAILURE_RETRY(
+    VOID_TEMP_FAILURE_RETRY_BLOCK_SIGNALS(
         setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &optval, sizeof(optval)));
   }
 
   SocketAddress::SetAddrPort(&addr, port);
-  if (TEMP_FAILURE_RETRY(
+  if (TEMP_FAILURE_RETRY_BLOCK_SIGNALS(
           bind(fd,
                &addr.addr,
                SocketAddress::GetAddrLength(&addr))) < 0) {
-    VOID_TEMP_FAILURE_RETRY(close(fd));
+    VOID_TEMP_FAILURE_RETRY_BLOCK_SIGNALS(close(fd));
     return -1;
   }
 
@@ -417,13 +421,14 @@
     // that we do not get the bad port number again.
     intptr_t new_fd = CreateBindListen(addr, 0, backlog, v6_only);
     int err = errno;
-    VOID_TEMP_FAILURE_RETRY(close(fd));
+    VOID_TEMP_FAILURE_RETRY_BLOCK_SIGNALS(close(fd));
     errno = err;
     return new_fd;
   }
 
-  if (TEMP_FAILURE_RETRY(listen(fd, backlog > 0 ? backlog : SOMAXCONN)) != 0) {
-    VOID_TEMP_FAILURE_RETRY(close(fd));
+  if (TEMP_FAILURE_RETRY_BLOCK_SIGNALS(
+      listen(fd, backlog > 0 ? backlog : SOMAXCONN)) != 0) {
+    VOID_TEMP_FAILURE_RETRY_BLOCK_SIGNALS(close(fd));
     return -1;
   }
 
@@ -436,7 +441,7 @@
   intptr_t socket;
   struct sockaddr clientaddr;
   socklen_t addrlen = sizeof(clientaddr);
-  socket = TEMP_FAILURE_RETRY(accept(fd, &clientaddr, &addrlen));
+  socket = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(accept(fd, &clientaddr, &addrlen));
   if (socket == -1) {
     if (errno == EAGAIN) {
       // We need to signal to the caller that this is actually not an
@@ -454,7 +459,7 @@
 
 void Socket::Close(intptr_t fd) {
   ASSERT(fd >= 0);
-  int err = TEMP_FAILURE_RETRY(close(fd));
+  int err = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(close(fd));
   if (err != 0) {
     const int kBufferSize = 1024;
     char error_message[kBufferSize];
@@ -477,7 +482,7 @@
 bool Socket::GetNoDelay(intptr_t fd, bool* enabled) {
   int on;
   socklen_t len = sizeof(on);
-  int err = TEMP_FAILURE_RETRY(getsockopt(fd,
+  int err = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(getsockopt(fd,
                                           IPPROTO_TCP,
                                           TCP_NODELAY,
                                           reinterpret_cast<void *>(&on),
@@ -491,7 +496,7 @@
 
 bool Socket::SetNoDelay(intptr_t fd, bool enabled) {
   int on = enabled ? 1 : 0;
-  return TEMP_FAILURE_RETRY(setsockopt(fd,
+  return TEMP_FAILURE_RETRY_BLOCK_SIGNALS(setsockopt(fd,
                                        IPPROTO_TCP,
                                        TCP_NODELAY,
                                        reinterpret_cast<char *>(&on),
@@ -505,7 +510,7 @@
   int level = protocol == SocketAddress::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6;
   int optname = protocol == SocketAddress::TYPE_IPV4
       ? IP_MULTICAST_LOOP : IPV6_MULTICAST_LOOP;
-  if (TEMP_FAILURE_RETRY(getsockopt(fd,
+  if (TEMP_FAILURE_RETRY_BLOCK_SIGNALS(getsockopt(fd,
                                      level,
                                      optname,
                                      reinterpret_cast<char *>(&on),
@@ -522,7 +527,7 @@
   int level = protocol == SocketAddress::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6;
   int optname = protocol == SocketAddress::TYPE_IPV4
       ? IP_MULTICAST_LOOP : IPV6_MULTICAST_LOOP;
-  return TEMP_FAILURE_RETRY(setsockopt(fd,
+  return TEMP_FAILURE_RETRY_BLOCK_SIGNALS(setsockopt(fd,
                                        level,
                                        optname,
                                        reinterpret_cast<char *>(&on),
@@ -536,7 +541,7 @@
   int level = protocol == SocketAddress::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6;
   int optname = protocol == SocketAddress::TYPE_IPV4
       ? IP_MULTICAST_TTL : IPV6_MULTICAST_HOPS;
-  if (TEMP_FAILURE_RETRY(getsockopt(fd,
+  if (TEMP_FAILURE_RETRY_BLOCK_SIGNALS(getsockopt(fd,
                                     level,
                                     optname,
                                     reinterpret_cast<char *>(&v),
@@ -553,7 +558,7 @@
   int level = protocol == SocketAddress::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6;
   int optname = protocol == SocketAddress::TYPE_IPV4
       ? IP_MULTICAST_TTL : IPV6_MULTICAST_HOPS;
-  return TEMP_FAILURE_RETRY(setsockopt(fd,
+  return TEMP_FAILURE_RETRY_BLOCK_SIGNALS(setsockopt(fd,
                                        level,
                                        optname,
                                        reinterpret_cast<char *>(&v),
@@ -564,7 +569,7 @@
 bool Socket::GetBroadcast(intptr_t fd, bool* enabled) {
   int on;
   socklen_t len = sizeof(on);
-  int err = TEMP_FAILURE_RETRY(getsockopt(fd,
+  int err = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(getsockopt(fd,
                                           SOL_SOCKET,
                                           SO_BROADCAST,
                                           reinterpret_cast<char *>(&on),
@@ -578,7 +583,7 @@
 
 bool Socket::SetBroadcast(intptr_t fd, bool enabled) {
   int on = enabled ? 1 : 0;
-  return TEMP_FAILURE_RETRY(setsockopt(fd,
+  return TEMP_FAILURE_RETRY_BLOCK_SIGNALS(setsockopt(fd,
                                        SOL_SOCKET,
                                        SO_BROADCAST,
                                        reinterpret_cast<char *>(&on),
@@ -596,15 +601,15 @@
     struct ip_mreq mreq;
     memmove(&mreq.imr_multiaddr,
             &addr->in.sin_addr,
-            SocketAddress::GetAddrLength(addr));
+            SocketAddress::GetInAddrLength(addr));
     memmove(&mreq.imr_interface,
             &interface->in.sin_addr,
-            SocketAddress::GetAddrLength(interface));
+            SocketAddress::GetInAddrLength(interface));
     if (join) {
-      return TEMP_FAILURE_RETRY(setsockopt(
+      return TEMP_FAILURE_RETRY_BLOCK_SIGNALS(setsockopt(
           fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq))) == 0;
     } else {
-      return TEMP_FAILURE_RETRY(setsockopt(
+      return TEMP_FAILURE_RETRY_BLOCK_SIGNALS(setsockopt(
           fd, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mreq, sizeof(mreq))) == 0;
     }
   } else {
@@ -612,43 +617,21 @@
     struct ipv6_mreq mreq;
     memmove(&mreq.ipv6mr_multiaddr,
             &addr->in6.sin6_addr,
-            SocketAddress::GetAddrLength(addr));
+            SocketAddress::GetInAddrLength(addr));
     mreq.ipv6mr_interface = interfaceIndex;
     if (join) {
-      return TEMP_FAILURE_RETRY(setsockopt(
+      return TEMP_FAILURE_RETRY_BLOCK_SIGNALS(setsockopt(
           fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq))) == 0;
     } else {
-      return TEMP_FAILURE_RETRY(setsockopt(
+      return TEMP_FAILURE_RETRY_BLOCK_SIGNALS(setsockopt(
           fd, IPPROTO_IPV6, IPV6_LEAVE_GROUP, &mreq, sizeof(mreq))) == 0;
     }
   }
 }
 
 bool Socket::JoinMulticast(
-  intptr_t fd, RawAddr* addr, RawAddr* interface, int interfaceIndex) {
-    return JoinOrLeaveMulticast(fd, addr, interface, interfaceIndex, true);
-  if (addr->addr.sa_family == AF_INET) {
-    ASSERT(interface->addr.sa_family == AF_INET);
-    struct ip_mreq mreq;
-    memmove(&mreq.imr_multiaddr,
-            &addr->in.sin_addr,
-            SocketAddress::GetAddrLength(addr));
-    memmove(&mreq.imr_interface,
-            &interface->in.sin_addr,
-            SocketAddress::GetAddrLength(interface));
-    return TEMP_FAILURE_RETRY(setsockopt(
-        fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq))) == 0;
-  } else {
-    ASSERT(addr->addr.sa_family == AF_INET6);
-    ASSERT(interface->addr.sa_family == AF_INET6);
-    struct ipv6_mreq mreq;
-    memmove(&mreq.ipv6mr_multiaddr,
-            &addr->in6.sin6_addr,
-            SocketAddress::GetAddrLength(addr));
-    mreq.ipv6mr_interface = interfaceIndex;
-    return TEMP_FAILURE_RETRY(setsockopt(
-        fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq))) == 0;
-  }
+    intptr_t fd, RawAddr* addr, RawAddr* interface, int interfaceIndex) {
+  return JoinOrLeaveMulticast(fd, addr, interface, interfaceIndex, true);
 }
 
 
diff --git a/runtime/bin/socket_patch.dart b/runtime/bin/socket_patch.dart
index a85320c..9076848 100644
--- a/runtime/bin/socket_patch.dart
+++ b/runtime/bin/socket_patch.dart
@@ -62,8 +62,7 @@
   static const int _ADDRESS_LOOPBACK_IP_V6 = 1;
   static const int _ADDRESS_ANY_IP_V4 = 2;
   static const int _ADDRESS_ANY_IP_V6 = 3;
-  static const int _IPV4_ADDR_OFFSET = 4;
-  static const int _IPV6_ADDR_OFFSET = 8;
+  static const int _IPV4_ADDR_LENGTH = 4;
   static const int _IPV6_ADDR_LENGTH = 16;
 
   static _InternetAddress LOOPBACK_IP_V4 =
@@ -75,24 +74,26 @@
   static _InternetAddress ANY_IP_V6 =
       new _InternetAddress.fixed(_ADDRESS_ANY_IP_V6);
 
-  final InternetAddressType type;
   final String address;
   final String _host;
-  final Uint8List _sockaddr_storage;
+  final Uint8List _in_addr;
+
+  InternetAddressType get type =>
+      _in_addr.length == _IPV4_ADDR_LENGTH ? InternetAddressType.IP_V4
+                                           : InternetAddressType.IP_V6;
 
   String get host => _host != null ? _host : address;
 
   bool get isLoopback {
     switch (type) {
       case InternetAddressType.IP_V4:
-        return _sockaddr_storage[_IPV4_ADDR_OFFSET] == 127;
+        return _in_addr[0] == 127;
 
       case InternetAddressType.IP_V6:
         for (int i = 0; i < _IPV6_ADDR_LENGTH - 1; i++) {
-          if (_sockaddr_storage[_IPV6_ADDR_OFFSET + i] != 0) return false;
+          if (_in_addr[i] != 0) return false;
         }
-        int lastByteIndex = _IPV6_ADDR_OFFSET + _IPV6_ADDR_LENGTH - 1;
-        return _sockaddr_storage[lastByteIndex] == 1;
+        return _in_addr[_IPV6_ADDR_LENGTH - 1] == 1;
     }
   }
 
@@ -100,13 +101,11 @@
     switch (type) {
       case InternetAddressType.IP_V4:
         // Checking for 169.254.0.0/16.
-        return _sockaddr_storage[_IPV4_ADDR_OFFSET] == 169 &&
-            _sockaddr_storage[_IPV4_ADDR_OFFSET + 1] == 254;
+        return _in_addr[0] == 169 && _in_addr[1] == 254;
 
       case InternetAddressType.IP_V6:
         // Checking for fe80::/10.
-        return _sockaddr_storage[_IPV6_ADDR_OFFSET] == 0xFE &&
-            (_sockaddr_storage[_IPV6_ADDR_OFFSET + 1] & 0xB0) == 0x80;
+        return _in_addr[0] == 0xFE && (_in_addr[1] & 0xB0) == 0x80;
     }
   }
 
@@ -114,48 +113,48 @@
     switch (type) {
       case InternetAddressType.IP_V4:
         // Checking for 224.0.0.0 through 239.255.255.255.
-        return _sockaddr_storage[_IPV4_ADDR_OFFSET] >= 224 &&
-            _sockaddr_storage[_IPV4_ADDR_OFFSET] < 240;
+        return _in_addr[0] >= 224 && _in_addr[0] < 240;
 
       case InternetAddressType.IP_V6:
         // Checking for ff00::/8.
-        return _sockaddr_storage[_IPV6_ADDR_OFFSET] == 0xFF;
+        return _in_addr[0] == 0xFF;
     }
   }
 
   Future<InternetAddress> reverse() => _NativeSocket.reverseLookup(this);
 
-  _InternetAddress(InternetAddressType this.type,
-                   String this.address,
+  _InternetAddress(String this.address,
                    String this._host,
-                   List<int> this._sockaddr_storage);
+                   List<int> this._in_addr);
 
   factory _InternetAddress.parse(String address) {
-    var type = address.indexOf(':') == -1
-        ? InternetAddressType.IP_V4
-        : InternetAddressType.IP_V6;
-    var raw = _parse(type._value, address);
-    if (raw == null) {
+    if (address is !String) {
       throw new ArgumentError("Invalid internet address $address");
     }
-    return new _InternetAddress(type, address, null, raw);
+    var in_addr = _parse(address);
+    if (in_addr == null) {
+      throw new ArgumentError("Invalid internet address $address");
+    }
+    return new _InternetAddress(address, null, in_addr);
   }
 
   factory _InternetAddress.fixed(int id) {
-    var sockaddr = _fixed(id);
     switch (id) {
       case _ADDRESS_LOOPBACK_IP_V4:
-        return new _InternetAddress(
-            InternetAddressType.IP_V4, "127.0.0.1", null, sockaddr);
+        var in_addr = new Uint8List(_IPV4_ADDR_LENGTH);
+        in_addr[0] = 127;
+        in_addr[_IPV4_ADDR_LENGTH - 1] = 1;
+        return new _InternetAddress("127.0.0.1", null, in_addr);
       case _ADDRESS_LOOPBACK_IP_V6:
-        return new _InternetAddress(
-            InternetAddressType.IP_V6, "::1", null, sockaddr);
+        var in_addr = new Uint8List(_IPV6_ADDR_LENGTH);
+        in_addr[_IPV6_ADDR_LENGTH - 1] = 1;
+        return new _InternetAddress("::1", null, in_addr);
       case _ADDRESS_ANY_IP_V4:
-        return new _InternetAddress(
-            InternetAddressType.IP_V4, "0.0.0.0", "0.0.0.0", sockaddr);
+        var in_addr = new Uint8List(_IPV4_ADDR_LENGTH);
+        return new _InternetAddress("0.0.0.0", "0.0.0.0", in_addr);
       case _ADDRESS_ANY_IP_V6:
-        return new _InternetAddress(
-            InternetAddressType.IP_V6, "::", "::", sockaddr);
+        var in_addr = new Uint8List(_IPV6_ADDR_LENGTH);
+        return new _InternetAddress("::", "::", in_addr);
       default:
         assert(false);
         throw new ArgumentError();
@@ -165,23 +164,23 @@
   // Create a clone of this _InternetAddress replacing the host.
   _InternetAddress _cloneWithNewHost(String host) {
     return new _InternetAddress(
-        type, address, host, new Uint8List.fromList(_sockaddr_storage));
+        address, host, new Uint8List.fromList(_in_addr));
   }
 
   bool operator ==(other) {
     if (!(other is _InternetAddress)) return false;
     if (other.type != type) return false;
     bool equals = true;
-    for (int i = 0; i < _sockaddr_storage.length && equals; i++) {
-      equals = other._sockaddr_storage[i] == _sockaddr_storage[i];
+    for (int i = 0; i < _in_addr.length && equals; i++) {
+      equals = other._in_addr[i] == _in_addr[i];
     }
     return equals;
   }
 
   int get hashCode {
     int result = 1;
-    for (int i = 0; i < _sockaddr_storage.length; i++) {
-      result = (result * 31 + _sockaddr_storage[i]) & 0x3FFFFFFF;
+    for (int i = 0; i < _in_addr.length; i++) {
+      result = (result * 31 + _in_addr[i]) & 0x3FFFFFFF;
     }
     return result;
   }
@@ -190,9 +189,7 @@
     return "InternetAddress('$address', ${type.name})";
   }
 
-  static Uint8List _fixed(int id) native "InternetAddress_Fixed";
-  static Uint8List _parse(int type, String address)
-      native "InternetAddress_Parse";
+  static Uint8List _parse(String address) native "InternetAddress_Parse";
 }
 
 class _NetworkInterface implements NetworkInterface {
@@ -284,14 +281,14 @@
           } else {
             return response.skip(1).map((result) {
               var type = new InternetAddressType._from(result[0]);
-              return new _InternetAddress(type, result[1], host, result[2]);
+              return new _InternetAddress(result[1], host, result[2]);
             }).toList();
           }
         });
   }
 
   static Future<InternetAddress> reverseLookup(InternetAddress addr) {
-    return _IOService.dispatch(_SOCKET_REVERSE_LOOKUP, [addr._sockaddr_storage])
+    return _IOService.dispatch(_SOCKET_REVERSE_LOOKUP, [addr._in_addr])
         .then((response) {
           if (isErrorResponse(response)) {
             throw createError(response, "Failed reverse host lookup", addr);
@@ -315,8 +312,7 @@
                   var type = new InternetAddressType._from(result[0]);
                   var name = result[3];
                   var index = result[4];
-                  var address = new _InternetAddress(
-                      type, result[1], "", result[2]);
+                  var address = new _InternetAddress(result[1], "", result[2]);
                   if (!includeLinkLocal && address.isLinkLocal) return map;
                   if (!includeLoopback && address.isLoopback) return map;
                   map.putIfAbsent(
@@ -345,7 +341,7 @@
           var socket = new _NativeSocket.normal();
           socket.address = address;
           var result = socket.nativeCreateConnect(
-              address._sockaddr_storage, port);
+              address._in_addr, port);
           if (result is OSError) {
             throw createError(result, "Connection failed", address, port);
           } else {
@@ -387,7 +383,7 @@
         .then((address) {
           var socket = new _NativeSocket.listen();
           socket.address = address;
-          var result = socket.nativeCreateBindListen(address._sockaddr_storage,
+          var result = socket.nativeCreateBindListen(address._in_addr,
                                                      port,
                                                      backlog,
                                                      v6Only);
@@ -418,7 +414,7 @@
         .then((address) {
           var socket = new _NativeSocket.datagram(address);
           var result = socket.nativeCreateBindDatagram(
-              address._sockaddr_storage, port, reuseAddress);
+              address._in_addr, port, reuseAddress);
           if (result is OSError) {
             throw new SocketException("Failed to create datagram socket",
                                       osError: result,
@@ -525,7 +521,7 @@
             buffer, offset, bytes);
     var result = nativeSendTo(
         bufferAndStart.buffer, bufferAndStart.start, bytes,
-        address._sockaddr_storage, port);
+        address._in_addr, port);
     if (result is OSError) {
       scheduleMicrotask(() => reportError(result, "Send failed"));
       result = 0;
@@ -555,7 +551,7 @@
   InternetAddress get remoteAddress {
     var result = nativeGetRemotePeer()[0];
     var type = new InternetAddressType._from(result[0]);
-    return new _InternetAddress(type, result[1], null, result[2]);
+    return new _InternetAddress(result[1], null, result[2]);
   }
 
   // Multiplexes socket events to the socket handlers.
@@ -780,7 +776,7 @@
     if (Platform.isMacOS && addr.type == InternetAddressType.IP_V4) {
       if (interface != null) {
         for (int i = 0; i < interface.addresses.length; i++) {
-          if (addr.type == InternetAddressType.IP_V4) {
+          if (interface.addresses[i].type == InternetAddressType.IP_V4) {
             return interface.addresses[i];
           }
         }
@@ -789,7 +785,7 @@
             "The network interface does not have an address "
             "of the same family as the multicast address");
       } else {
-        // Default to the ANY address if on iterface is specified.
+        // Default to the ANY address if no iterface is specified.
         return InternetAddress.ANY_IP_V4;
       }
     } else {
@@ -801,8 +797,8 @@
     var interfaceAddr = multicastAddress(addr, interface);
     var interfaceIndex = interface == null ? 0 : interface.index;
     var result = nativeJoinMulticast(
-        addr._sockaddr_storage,
-        interfaceAddr == null ? null : interfaceAddr._sockaddr_storage,
+        addr._in_addr,
+        interfaceAddr == null ? null : interfaceAddr._in_addr,
         interfaceIndex);
     if (result is OSError) throw result;
   }
@@ -811,8 +807,8 @@
     var interfaceAddr = multicastAddress(addr, interface);
     var interfaceIndex = interface == null ? 0 : interface.index;
     var result = nativeLeaveMulticast(
-        addr._sockaddr_storage,
-        interfaceAddr == null ? null : interfaceAddr._sockaddr_storage,
+        addr._in_addr,
+        interfaceAddr == null ? null : interfaceAddr._in_addr,
         interfaceIndex);
     if (result is OSError) throw result;
   }
@@ -1551,14 +1547,11 @@
 }
 
 Datagram _makeDatagram(List<int> data,
-                       bool ipV6,
                        String address,
-                       List<int> sockaddr_storage,
+                       List<int> in_addr,
                        int port) {
-  var addressType =
-      ipV6 ? InternetAddressType.IP_V6 : InternetAddressType.IP_V4;
   return new Datagram(
       data,
-      new _InternetAddress(addressType, address, null, sockaddr_storage),
+      new _InternetAddress(address, null, in_addr),
       port);
 }
diff --git a/runtime/bin/stdin.cc b/runtime/bin/stdio.cc
similarity index 75%
rename from runtime/bin/stdin.cc
rename to runtime/bin/stdio.cc
index ef7904a..916a3b8 100644
--- a/runtime/bin/stdin.cc
+++ b/runtime/bin/stdio.cc
@@ -5,7 +5,7 @@
 #include "bin/builtin.h"
 #include "bin/dartutils.h"
 #include "bin/utils.h"
-#include "bin/stdin.h"
+#include "bin/stdio.h"
 
 #include "platform/globals.h"
 #include "platform/thread.h"
@@ -43,5 +43,18 @@
   Stdin::SetLineMode(enabled);
 }
 
+
+void FUNCTION_NAME(Stdout_GetTerminalSize)(Dart_NativeArguments args) {
+  int size[2];
+  if (Stdout::GetTerminalSize(size)) {
+    Dart_Handle list = Dart_NewList(2);
+    Dart_ListSetAt(list, 0, Dart_NewInteger(size[0]));
+    Dart_ListSetAt(list, 1, Dart_NewInteger(size[1]));
+    Dart_SetReturnValue(args, list);
+  } else {
+    Dart_SetReturnValue(args, DartUtils::NewDartOSError());
+  }
+}
+
 }  // namespace bin
 }  // namespace dart
diff --git a/runtime/bin/stdin.h b/runtime/bin/stdio.h
similarity index 74%
rename from runtime/bin/stdin.h
rename to runtime/bin/stdio.h
index a0c6875..646629d 100644
--- a/runtime/bin/stdin.h
+++ b/runtime/bin/stdio.h
@@ -2,8 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-#ifndef BIN_STDIN_H_
-#define BIN_STDIN_H_
+#ifndef BIN_STDIO_H_
+#define BIN_STDIO_H_
 
 #include "bin/builtin.h"
 #include "bin/utils.h"
@@ -29,8 +29,18 @@
   DISALLOW_IMPLICIT_CONSTRUCTORS(Stdin);
 };
 
+
+class Stdout {
+ public:
+  static bool GetTerminalSize(int size[2]);
+
+ private:
+  DISALLOW_ALLOCATION();
+  DISALLOW_IMPLICIT_CONSTRUCTORS(Stdout);
+};
+
 }  // namespace bin
 }  // namespace dart
 
-#endif  // BIN_STDIN_H_
+#endif  // BIN_STDIO_H_
 
diff --git a/runtime/bin/stdin_android.cc b/runtime/bin/stdio_android.cc
similarity index 61%
rename from runtime/bin/stdin_android.cc
rename to runtime/bin/stdio_android.cc
index a1a4d63..b14dad8 100644
--- a/runtime/bin/stdin_android.cc
+++ b/runtime/bin/stdio_android.cc
@@ -5,61 +5,76 @@
 #include "platform/globals.h"
 #if defined(TARGET_OS_ANDROID)
 
+#include <errno.h>  // NOLINT
+#include <sys/ioctl.h>  // NOLINT
 #include <termios.h>  // NOLINT
 
-#include "bin/stdin.h"
+#include "bin/stdio.h"
 #include "bin/fdutils.h"
+#include "bin/signal_blocker.h"
 
 
 namespace dart {
 namespace bin {
 
 int Stdin::ReadByte() {
-  FDUtils::SetBlocking(fileno(stdin));
+  FDUtils::SetBlocking(STDIN_FILENO);
   int c = getchar();
   if (c == EOF) {
     c = -1;
   }
-  FDUtils::SetNonBlocking(fileno(stdin));
+  FDUtils::SetNonBlocking(STDIN_FILENO);
   return c;
 }
 
 
 bool Stdin::GetEchoMode() {
   struct termios term;
-  tcgetattr(fileno(stdin), &term);
+  tcgetattr(STDIN_FILENO, &term);
   return (term.c_lflag & ECHO) != 0;
 }
 
 
 void Stdin::SetEchoMode(bool enabled) {
   struct termios term;
-  tcgetattr(fileno(stdin), &term);
+  tcgetattr(STDIN_FILENO, &term);
   if (enabled) {
     term.c_lflag |= ECHO|ECHONL;
   } else {
     term.c_lflag &= ~(ECHO|ECHONL);
   }
-  tcsetattr(fileno(stdin), TCSANOW, &term);
+  tcsetattr(STDIN_FILENO, TCSANOW, &term);
 }
 
 
 bool Stdin::GetLineMode() {
   struct termios term;
-  tcgetattr(fileno(stdin), &term);
+  tcgetattr(STDIN_FILENO, &term);
   return (term.c_lflag & ICANON) != 0;
 }
 
 
 void Stdin::SetLineMode(bool enabled) {
   struct termios term;
-  tcgetattr(fileno(stdin), &term);
+  tcgetattr(STDIN_FILENO, &term);
   if (enabled) {
     term.c_lflag |= ICANON;
   } else {
     term.c_lflag &= ~(ICANON);
   }
-  tcsetattr(fileno(stdin), TCSANOW, &term);
+  tcsetattr(STDIN_FILENO, TCSANOW, &term);
+}
+
+
+bool Stdout::GetTerminalSize(int size[2]) {
+  struct winsize w;
+  if (TEMP_FAILURE_RETRY_BLOCK_SIGNALS(
+        ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) != 0)) {
+    return false;
+  }
+  size[0] = w.ws_col;
+  size[1] = w.ws_row;
+  return true;
 }
 
 }  // namespace bin
diff --git a/runtime/bin/stdin_linux.cc b/runtime/bin/stdio_linux.cc
similarity index 61%
rename from runtime/bin/stdin_linux.cc
rename to runtime/bin/stdio_linux.cc
index c64610a..5d1739a 100644
--- a/runtime/bin/stdin_linux.cc
+++ b/runtime/bin/stdio_linux.cc
@@ -5,61 +5,76 @@
 #include "platform/globals.h"
 #if defined(TARGET_OS_LINUX)
 
+#include <errno.h>  // NOLINT
+#include <sys/ioctl.h>  // NOLINT
 #include <termios.h>  // NOLINT
 
-#include "bin/stdin.h"
+#include "bin/stdio.h"
 #include "bin/fdutils.h"
+#include "bin/signal_blocker.h"
 
 
 namespace dart {
 namespace bin {
 
 int Stdin::ReadByte() {
-  FDUtils::SetBlocking(fileno(stdin));
+  FDUtils::SetBlocking(STDIN_FILENO);
   int c = getchar();
   if (c == EOF) {
     c = -1;
   }
-  FDUtils::SetNonBlocking(fileno(stdin));
+  FDUtils::SetNonBlocking(STDIN_FILENO);
   return c;
 }
 
 
 bool Stdin::GetEchoMode() {
   struct termios term;
-  tcgetattr(fileno(stdin), &term);
+  tcgetattr(STDIN_FILENO, &term);
   return (term.c_lflag & ECHO) != 0;
 }
 
 
 void Stdin::SetEchoMode(bool enabled) {
   struct termios term;
-  tcgetattr(fileno(stdin), &term);
+  tcgetattr(STDIN_FILENO, &term);
   if (enabled) {
     term.c_lflag |= ECHO|ECHONL;
   } else {
     term.c_lflag &= ~(ECHO|ECHONL);
   }
-  tcsetattr(fileno(stdin), TCSANOW, &term);
+  tcsetattr(STDIN_FILENO, TCSANOW, &term);
 }
 
 
 bool Stdin::GetLineMode() {
   struct termios term;
-  tcgetattr(fileno(stdin), &term);
+  tcgetattr(STDIN_FILENO, &term);
   return (term.c_lflag & ICANON) != 0;
 }
 
 
 void Stdin::SetLineMode(bool enabled) {
   struct termios term;
-  tcgetattr(fileno(stdin), &term);
+  tcgetattr(STDIN_FILENO, &term);
   if (enabled) {
     term.c_lflag |= ICANON;
   } else {
     term.c_lflag &= ~(ICANON);
   }
-  tcsetattr(fileno(stdin), TCSANOW, &term);
+  tcsetattr(STDIN_FILENO, TCSANOW, &term);
+}
+
+
+bool Stdout::GetTerminalSize(int size[2]) {
+  struct winsize w;
+  if (TEMP_FAILURE_RETRY_BLOCK_SIGNALS(
+        ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) != 0)) {
+    return false;
+  }
+  size[0] = w.ws_col;
+  size[1] = w.ws_row;
+  return true;
 }
 
 }  // namespace bin
diff --git a/runtime/bin/stdin_macos.cc b/runtime/bin/stdio_macos.cc
similarity index 61%
rename from runtime/bin/stdin_macos.cc
rename to runtime/bin/stdio_macos.cc
index a8afb77..623463a 100644
--- a/runtime/bin/stdin_macos.cc
+++ b/runtime/bin/stdio_macos.cc
@@ -5,65 +5,79 @@
 #include "platform/globals.h"
 #if defined(TARGET_OS_MACOS)
 
+#include <errno.h>  // NOLINT
+#include <sys/ioctl.h>  // NOLINT
 #include <termios.h>  // NOLINT
 
-#include "bin/stdin.h"
+#include "bin/stdio.h"
 #include "bin/fdutils.h"
+#include "bin/signal_blocker.h"
 
 
 namespace dart {
 namespace bin {
 
 int Stdin::ReadByte() {
-  FDUtils::SetBlocking(fileno(stdin));
+  FDUtils::SetBlocking(STDIN_FILENO);
   int c = getchar();
   if (c == EOF) {
     c = -1;
   }
-  FDUtils::SetNonBlocking(fileno(stdin));
+  FDUtils::SetNonBlocking(STDIN_FILENO);
   return c;
 }
 
 
 bool Stdin::GetEchoMode() {
   struct termios term;
-  tcgetattr(fileno(stdin), &term);
+  tcgetattr(STDIN_FILENO, &term);
   return (term.c_lflag & ECHO) != 0;
 }
 
 
 void Stdin::SetEchoMode(bool enabled) {
   struct termios term;
-  tcgetattr(fileno(stdin), &term);
+  tcgetattr(STDIN_FILENO, &term);
   if (enabled) {
     term.c_lflag |= ECHO|ECHONL;
   } else {
     term.c_lflag &= ~(ECHO|ECHONL);
   }
-  tcsetattr(fileno(stdin), TCSANOW, &term);
+  tcsetattr(STDIN_FILENO, TCSANOW, &term);
 }
 
 
 bool Stdin::GetLineMode() {
   struct termios term;
-  tcgetattr(fileno(stdin), &term);
+  tcgetattr(STDIN_FILENO, &term);
   return (term.c_lflag & ICANON) != 0;
 }
 
 
 void Stdin::SetLineMode(bool enabled) {
   struct termios term;
-  tcgetattr(fileno(stdin), &term);
+  tcgetattr(STDIN_FILENO, &term);
   if (enabled) {
     term.c_lflag |= ICANON;
   } else {
     term.c_lflag &= ~(ICANON);
   }
-  tcsetattr(fileno(stdin), TCSANOW, &term);
+  tcsetattr(STDIN_FILENO, TCSANOW, &term);
+}
+
+
+bool Stdout::GetTerminalSize(int size[2]) {
+  struct winsize w;
+  if (TEMP_FAILURE_RETRY_BLOCK_SIGNALS(
+        ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) != 0)) {
+    return false;
+  }
+  size[0] = w.ws_col;
+  size[1] = w.ws_row;
+  return true;
 }
 
 }  // namespace bin
 }  // namespace dart
 
 #endif  // defined(TARGET_OS_MACOS)
-
diff --git a/runtime/bin/stdio_patch.dart b/runtime/bin/stdio_patch.dart
index 5d5cdaf..2364281 100644
--- a/runtime/bin/stdio_patch.dart
+++ b/runtime/bin/stdio_patch.dart
@@ -16,15 +16,22 @@
     }
   }
 
-  static IOSink _getStdioOutputStream(int fd) {
+  static _getStdioOutputStream(int fd) {
+    wrap(sink) {
+      if (fd == 1) {
+        return new Stdout._(sink);
+      } else {
+        return new _StdSink(sink);
+      }
+    }
     assert(fd == 1 || fd == 2);
     switch (_getStdioHandleType(fd)) {
       case _STDIO_HANDLE_TYPE_TERMINAL:
       case _STDIO_HANDLE_TYPE_PIPE:
       case _STDIO_HANDLE_TYPE_SOCKET:
-        return new _StdSink(new _Socket._writePipe(fd));
+        return wrap(new _Socket._writePipe(fd));
       case _STDIO_HANDLE_TYPE_FILE:
-        return new _StdSink(new IOSink(new _FileStreamConsumer.fromStdio(fd)));
+        return wrap(new IOSink(new _FileStreamConsumer.fromStdio(fd)));
       default:
         throw new FileSystemException("Unsupported stdin type");
     }
@@ -54,6 +61,30 @@
   static void set _lineMode(bool enabled) native "Stdin_SetLineMode";
 }
 
+patch class Stdout {
+  /* patch */ bool get hasTerminal {
+    try {
+      _terminalSize;
+      return true;
+    } catch (_) {
+      return false;
+    }
+  }
+
+  /* patch */ int get terminalColumns => _terminalSize[0];
+  /* patch */ int get terminalLines => _terminalSize[1];
+
+  static List get _terminalSize {
+    var size = _getTerminalSize();
+    if (size is! List) {
+      throw new StdoutException("Could not get terminal size", size);
+    }
+    return size;
+  }
+
+  static _getTerminalSize() native "Stdout_GetTerminalSize";
+}
+
 
 _getStdioHandle(_NativeSocket socket, int num) native "Socket_GetStdioHandle";
 _getStdioHandleType(int num) native "File_GetStdioHandleType";
diff --git a/runtime/bin/stdin_win.cc b/runtime/bin/stdio_win.cc
similarity index 81%
rename from runtime/bin/stdin_win.cc
rename to runtime/bin/stdio_win.cc
index 44e517d..24ceb32 100644
--- a/runtime/bin/stdin_win.cc
+++ b/runtime/bin/stdio_win.cc
@@ -5,7 +5,7 @@
 #include "platform/globals.h"
 #if defined(TARGET_OS_WINDOWS)
 
-#include "bin/stdin.h"
+#include "bin/stdio.h"
 
 
 namespace dart {
@@ -64,6 +64,16 @@
   SetConsoleMode(h, mode);
 }
 
+
+bool Stdout::GetTerminalSize(int size[2]) {
+  HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
+  CONSOLE_SCREEN_BUFFER_INFO info;
+  if (!GetConsoleScreenBufferInfo(h, &info)) return false;
+  size[0] = info.srWindow.Right - info.srWindow.Left + 1;
+  size[1] = info.srWindow.Bottom - info.srWindow.Top + 1;
+  return true;
+}
+
 }  // namespace bin
 }  // namespace dart
 
diff --git a/runtime/bin/test_extension.c b/runtime/bin/test_extension.c
index a08a5fe..82387a2 100644
--- a/runtime/bin/test_extension.c
+++ b/runtime/bin/test_extension.c
@@ -32,11 +32,17 @@
 
 
 /* Native resolver for the extension library. */
-Dart_NativeFunction ResolveName(Dart_Handle name, int argc) {
+Dart_NativeFunction ResolveName(Dart_Handle name,
+                                int argc,
+                                bool* auto_setup_scope) {
   /* assert(Dart_IsString(name)); */
   const char* c_name;
   Dart_Handle check_error;
 
+  if (auto_setup_scope == NULL) {
+    return NULL;
+  }
+  *auto_setup_scope = 1;
   check_error = Dart_StringToCString(name, &c_name);
   if (Dart_IsError(check_error)) {
     Dart_PropagateError(check_error);
diff --git a/runtime/bin/utils_android.cc b/runtime/bin/utils_android.cc
index e88d248..615dae9 100644
--- a/runtime/bin/utils_android.cc
+++ b/runtime/bin/utils_android.cc
@@ -8,6 +8,7 @@
 #include <errno.h>  // NOLINT
 #include <netdb.h>  // NOLINT
 #include <sys/time.h>  // NOLINT
+#include <time.h>  // NOLINT
 
 #include "bin/utils.h"
 #include "platform/assert.h"
@@ -98,7 +99,24 @@
 }
 
 void TimerUtils::Sleep(int64_t millis) {
-  usleep(millis * 1000);
+  struct timespec req;  // requested.
+  struct timespec rem;  // remainder.
+  int64_t micros = millis * kMicrosecondsPerMillisecond;
+  int64_t seconds = micros / kMicrosecondsPerSecond;
+  micros = micros - seconds * kMicrosecondsPerSecond;
+  int64_t nanos = micros * kNanosecondsPerMicrosecond;
+  req.tv_sec = seconds;
+  req.tv_nsec = nanos;
+  while (true) {
+    int r = nanosleep(&req, &rem);
+    if (r == 0) {
+      break;
+    }
+    // We should only ever see an interrupt error.
+    ASSERT(errno == EINTR);
+    // Copy remainder into requested and repeat.
+    req = rem;
+  }
 }
 
 }  // namespace bin
diff --git a/runtime/bin/utils_linux.cc b/runtime/bin/utils_linux.cc
index 4506f6f..ce35eb7 100644
--- a/runtime/bin/utils_linux.cc
+++ b/runtime/bin/utils_linux.cc
@@ -8,6 +8,7 @@
 #include <errno.h>  // NOLINT
 #include <netdb.h>  // NOLINT
 #include <sys/time.h>  // NOLINT
+#include <time.h>  // NOLINT
 
 #include "bin/utils.h"
 #include "platform/assert.h"
@@ -96,16 +97,23 @@
 }
 
 void TimerUtils::Sleep(int64_t millis) {
-  // We must loop here because SIGPROF will interrupt usleep.
-  int64_t micros = millis * 1000;
-  int64_t start = GetCurrentTimeMicros();
-  while (micros > 0) {
-    usleep(micros);
-    int64_t now = GetCurrentTimeMicros();
-    int64_t delta = now - start;
-    ASSERT(delta >= 0);
-    start = now;
-    micros -= delta;
+  struct timespec req;  // requested.
+  struct timespec rem;  // remainder.
+  int64_t micros = millis * kMicrosecondsPerMillisecond;
+  int64_t seconds = micros / kMicrosecondsPerSecond;
+  micros = micros - seconds * kMicrosecondsPerSecond;
+  int64_t nanos = micros * kNanosecondsPerMicrosecond;
+  req.tv_sec = seconds;
+  req.tv_nsec = nanos;
+  while (true) {
+    int r = nanosleep(&req, &rem);
+    if (r == 0) {
+      break;
+    }
+    // We should only ever see an interrupt error.
+    ASSERT(errno == EINTR);
+    // Copy remainder into requested and repeat.
+    req = rem;
   }
 }
 
diff --git a/runtime/bin/utils_macos.cc b/runtime/bin/utils_macos.cc
index 1c83afd..460da35 100644
--- a/runtime/bin/utils_macos.cc
+++ b/runtime/bin/utils_macos.cc
@@ -8,6 +8,7 @@
 #include <errno.h>  // NOLINT
 #include <netdb.h>  // NOLINT
 #include <sys/time.h>  // NOLINT
+#include <time.h>  // NOLINT
 
 #include "bin/utils.h"
 #include "platform/assert.h"
@@ -98,16 +99,23 @@
 }
 
 void TimerUtils::Sleep(int64_t millis) {
-  // We must loop here because SIGPROF will interrupt usleep.
-  int64_t micros = millis * 1000;
-  int64_t start = GetCurrentTimeMicros();
-  while (micros > 0) {
-    usleep(micros);
-    int64_t now = GetCurrentTimeMicros();
-    int64_t delta = now - start;
-    ASSERT(delta >= 0);
-    start = now;
-    micros -= delta;
+  struct timespec req;  // requested.
+  struct timespec rem;  // remainder.
+  int64_t micros = millis * kMicrosecondsPerMillisecond;
+  int64_t seconds = micros / kMicrosecondsPerSecond;
+  micros = micros - seconds * kMicrosecondsPerSecond;
+  int64_t nanos = micros * kNanosecondsPerMicrosecond;
+  req.tv_sec = seconds;
+  req.tv_nsec = nanos;
+  while (true) {
+    int r = nanosleep(&req, &rem);
+    if (r == 0) {
+      break;
+    }
+    // We should only ever see an interrupt error.
+    ASSERT(errno == EINTR);
+    // Copy remainder into requested and repeat.
+    req = rem;
   }
 }
 
diff --git a/runtime/bin/vmservice/client.dart b/runtime/bin/vmservice/client.dart
new file mode 100644
index 0000000..553fa1f
--- /dev/null
+++ b/runtime/bin/vmservice/client.dart
@@ -0,0 +1,43 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of vmservice;
+
+// A service client.
+abstract class Client {
+  /// Port that lives as long as the network client.
+  final RawReceivePort receivePort = new RawReceivePort();
+  final VMService service;
+
+  Client(this.service) {
+    receivePort.handler = (response) {
+      post(null, response);
+    };
+    service._addClient(this);
+  }
+
+  /// When implementing, call [close] when the network connection closes.
+  void close() {
+    receivePort.close();
+    service._removeClient(this);
+  }
+
+  /// Call to process a message. Response will be posted with 'seq'.
+  void onMessage(var seq, Message message) {
+    // Call post when the response arrives.
+    message.response.then((response) {
+      post(seq, response);
+    });
+    // Send message to service.
+    service.route(message);
+  }
+
+  /// When implementing, responsible for sending [response] to the client.
+  void post(var seq, String response);
+
+  dynamic toJson() {
+    return {
+    };
+  }
+}
diff --git a/runtime/bin/vmservice/client/deployed/web/index.html b/runtime/bin/vmservice/client/deployed/web/index.html
index a0437be..b226dd5 100644
--- a/runtime/bin/vmservice/client/deployed/web/index.html
+++ b/runtime/bin/vmservice/client/deployed/web/index.html
@@ -11,6 +11,24 @@
 </head>
 <body><polymer-element name="observatory-element">
   
+</polymer-element><polymer-element name="breakpoint-list" extends="observatory-element">
+  <template>
+    <template if="{{ msg['breakpoints'].isEmpty }}">
+      <div class="panel panel-warning">
+        <div class="panel-body">No breakpoints</div>
+      </div>
+    </template>
+    <template if="{{ msg['breakpoints'].isNotEmpty }}">
+      <ul class="list-group">
+      <template repeat="{{ bpt in msg['breakpoints'] }}">
+        <li class="list-group-item">
+          {{ bpt }}
+        </li>
+      </template>
+      </ul>
+    </template>
+  </template>
+  
 </polymer-element><polymer-element name="error-view" extends="observatory-element">
   <template>
     <div class="row">
@@ -297,6 +315,9 @@
       <div class="col-md-1">
         <a href="{{ app.locationManager.relativeLink(isolate, 'library') }}">Library</a>
       </div>
+      <div class="col-md-1">
+        <a href="{{ app.locationManager.relativeLink(isolate, 'debug/breakpoints') }}">Breakpoints</a>
+      </div>
   	  <div class="col-md-8"></div>
     </div>
   </template>
@@ -514,6 +535,9 @@
     <template if="{{ messageType == 'StackTrace' }}">
       <stack-trace app="{{ app }}" trace="{{ message }}"></stack-trace>
     </template>
+    <template if="{{ messageType == 'BreakpointList' }}">
+      <breakpoint-list app="{{ app }}" msg="{{ message }}"></breakpoint-list>
+    </template>
     <!-- If the message type is a RequestError -->
     <template if="{{ messageType == 'RequestError' }}">
       <error-view app="{{ app }}" error="{{ message['error'] }}"></error-view>
diff --git a/runtime/bin/vmservice/client/deployed/web/index.html_bootstrap.dart.js b/runtime/bin/vmservice/client/deployed/web/index.html_bootstrap.dart.js
index a67ecba..1dd1331 100644
--- a/runtime/bin/vmservice/client/deployed/web/index.html_bootstrap.dart.js
+++ b/runtime/bin/vmservice/client/deployed/web/index.html_bootstrap.dart.js
@@ -7782,7 +7782,7 @@
 $$.Y7=[A,{"":"v;wc,nn,lv,Pp",
 call$2:function(a,b){return this.nn.call(this.wc,this.lv,a,b)},
 $is_bh:true}]
-$$.Dw=[T,{"":"v;wc,nn,lv,Pp",
+$$.PD=[T,{"":"v;wc,nn,lv,Pp",
 call$3:function(a,b,c){return this.nn.call(this.wc,a,b,c)}}]
 $$.zy=[H,{"":"Tp;call$2,$name",$is_bh:true}]
 $$.Nb=[H,{"":"Tp;call$1,$name",$is_HB:true,$is_Dv:true}]
@@ -7805,7 +7805,7 @@
 call$catchAll:function(){return{onError:null,radix:null}},
 $is_HB:true,
 $is_Dv:true}]
-;init.mangledNames={gB:"length",gDb:"_cachedDeclarations",gEI:"prefix",gF1:"isolate",gFF:"source",gFJ:"__$cls",gFT:"__$instruction",gFU:"_cachedMethodsMap",gG1:"message",gH8:"_fieldsDescriptor",gHt:"_fieldsMetadata",gKM:"$",gLA:"src",gLf:"__$field",gLy:"_cachedSetters",gM2:"_cachedVariables",gMj:"function",gNI:"instruction",gNl:"script",gO3:"url",gOk:"_cachedMetadata",gP:"value",gP2:"_collapsed",gPw:"__$isolate",gPy:"__$error",gQG:"app",gRu:"cls",gT1:"_cachedGetters",gTn:"json",gTx:"_jsConstructorOrInterceptor",gUF:"_cachedTypeVariables",gUz:"__$script",gV4:"__$trace",gVA:"__$displayValue",gVB:"error_obj",gWL:"_mangledName",gXB:"_message",gXJ:"lines",gXR:"scripts",gXf:"__$iconClass",gXh:"__$instance",gZ6:"locationManager",gZw:"__$code",ga:"a",gai:"displayValue",gb:"b",gb0:"_cachedConstructors",gcC:"hash",geV:"paddedLine",geb:"__$json",gfY:"kind",ghO:"__$error_obj",ghf:"instance",gi0:"__$name",gi2:"isolates",giI:"__$library",giK:"__$instance",gjO:"id",gjd:"_cachedMethods",gk5:"__$devtools",gkc:"error",gkf:"_count",gl7:"iconClass",glD:"currentHashUri",gle:"_metadata",glw:"requestManager",gn2:"responses",gnI:"isolateManager",gnz:"_owner",goc:"name",gpz:"_jsConstructorCache",gqN:"_superclass",gql:"__$function",gqm:"_cachedSuperinterfaces",gt0:"field",gtB:"_cachedFields",gtD:"library",gtH:"__$app",gtN:"trace",gtT:"code",guA:"_cachedMembers",gvH:"index",gvX:"__$source",gvt:"__$field",gxj:"collapsed",gzd:"currentHash",gzj:"devtools"};init.mangledGlobalNames={DI:"_closeIconClass",Vl:"_openIconClass"};(function (reflectionData) {
+;init.mangledNames={gB:"length",gDb:"_cachedDeclarations",gEI:"prefix",gF1:"isolate",gFF:"source",gFJ:"__$cls",gFT:"__$instruction",gFU:"_cachedMethodsMap",gG1:"message",gH8:"_fieldsDescriptor",gHt:"_fieldsMetadata",gKM:"$",gLA:"src",gLf:"__$field",gLy:"_cachedSetters",gM2:"_cachedVariables",gMj:"function",gNI:"instruction",gNl:"script",gO3:"url",gOk:"_cachedMetadata",gP:"value",gP2:"_collapsed",gPw:"__$isolate",gPy:"__$error",gQG:"app",gRu:"cls",gT1:"_cachedGetters",gTn:"json",gTx:"_jsConstructorOrInterceptor",gUF:"_cachedTypeVariables",gUz:"__$script",gV4:"__$trace",gVA:"__$displayValue",gVB:"error_obj",gWL:"_mangledName",gXB:"_message",gXJ:"lines",gXR:"scripts",gXf:"__$iconClass",gXh:"__$instance",gZ6:"locationManager",gZw:"__$code",ga:"a",gai:"displayValue",gb:"b",gb0:"_cachedConstructors",gcC:"hash",geE:"__$msg",geV:"paddedLine",geb:"__$json",gfY:"kind",ghO:"__$error_obj",ghf:"instance",gi0:"__$name",gi2:"isolates",giI:"__$library",giK:"__$instance",gjO:"id",gjd:"_cachedMethods",gk5:"__$devtools",gkc:"error",gkf:"_count",gl7:"iconClass",glD:"currentHashUri",gle:"_metadata",glw:"requestManager",gn2:"responses",gnI:"isolateManager",gnz:"_owner",goc:"name",gpz:"_jsConstructorCache",gqN:"_superclass",gql:"__$function",gqm:"_cachedSuperinterfaces",grs:"msg",gt0:"field",gtB:"_cachedFields",gtD:"library",gtH:"__$app",gtN:"trace",gtT:"code",guA:"_cachedMembers",gvH:"index",gvX:"__$source",gvt:"__$field",gxj:"collapsed",gzd:"currentHash",gzj:"devtools"};init.mangledGlobalNames={DI:"_closeIconClass",Vl:"_openIconClass"};(function (reflectionData) {
   function map(x){x={x:x};delete x.x;return x}
   if (!init.libraries) init.libraries = [];
   if (!init.mangledNames) init.mangledNames = map();
@@ -9438,14 +9438,38 @@
 t:function(a,b){if(!J.xC(b,0))H.vh(P.N(b))
 return this.zO},
 "+[]:1:0":0,
-$isOd:true}}],["app_bootstrap","index.html_bootstrap.dart",,E,{E2:function(){$.x2=["package:observatory/src/observatory_elements/observatory_element.dart","package:observatory/src/observatory_elements/error_view.dart","package:observatory/src/observatory_elements/field_ref.dart","package:observatory/src/observatory_elements/instance_ref.dart","package:observatory/src/observatory_elements/class_view.dart","package:observatory/src/observatory_elements/disassembly_entry.dart","package:observatory/src/observatory_elements/code_view.dart","package:observatory/src/observatory_elements/collapsible_content.dart","package:observatory/src/observatory_elements/field_view.dart","package:observatory/src/observatory_elements/function_view.dart","package:observatory/src/observatory_elements/isolate_summary.dart","package:observatory/src/observatory_elements/isolate_list.dart","package:observatory/src/observatory_elements/instance_view.dart","package:observatory/src/observatory_elements/json_view.dart","package:observatory/src/observatory_elements/library_view.dart","package:observatory/src/observatory_elements/source_view.dart","package:observatory/src/observatory_elements/script_view.dart","package:observatory/src/observatory_elements/stack_trace.dart","package:observatory/src/observatory_elements/message_viewer.dart","package:observatory/src/observatory_elements/navigation_bar.dart","package:observatory/src/observatory_elements/response_viewer.dart","package:observatory/src/observatory_elements/observatory_application.dart","index.html.0.dart"]
+$isOd:true}}],["app_bootstrap","index.html_bootstrap.dart",,E,{E2:function(){$.x2=["package:observatory/src/observatory_elements/observatory_element.dart","package:observatory/src/observatory_elements/breakpoint_list.dart","package:observatory/src/observatory_elements/error_view.dart","package:observatory/src/observatory_elements/field_ref.dart","package:observatory/src/observatory_elements/instance_ref.dart","package:observatory/src/observatory_elements/class_view.dart","package:observatory/src/observatory_elements/disassembly_entry.dart","package:observatory/src/observatory_elements/code_view.dart","package:observatory/src/observatory_elements/collapsible_content.dart","package:observatory/src/observatory_elements/field_view.dart","package:observatory/src/observatory_elements/function_view.dart","package:observatory/src/observatory_elements/isolate_summary.dart","package:observatory/src/observatory_elements/isolate_list.dart","package:observatory/src/observatory_elements/instance_view.dart","package:observatory/src/observatory_elements/json_view.dart","package:observatory/src/observatory_elements/library_view.dart","package:observatory/src/observatory_elements/source_view.dart","package:observatory/src/observatory_elements/script_view.dart","package:observatory/src/observatory_elements/stack_trace.dart","package:observatory/src/observatory_elements/message_viewer.dart","package:observatory/src/observatory_elements/navigation_bar.dart","package:observatory/src/observatory_elements/response_viewer.dart","package:observatory/src/observatory_elements/observatory_application.dart","index.html.0.dart"]
 $.uP=!1
-A.Ok()}},1],["class_view_element","package:observatory/src/observatory_elements/class_view.dart",,Z,{aC:{"":["Vf;FJ%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
+A.Ok()}},1],["breakpoint_list_element","package:observatory/src/observatory_elements/breakpoint_list.dart",,B,{G6:{"":["Vf;eE%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
+grs:function(a){return a.eE
+"38,39,40"},
+"+msg":1,
+srs:function(a,b){a.eE=this.pD(a,C.Ry,a.eE,b)
+"41,32,38,39"},
+"+msg=":1,
+"@":function(){return[C.PT]},
+static:{Dw:function(a){var z,y,x,w,v,u
+z=H.B7([],P.L5(null,null,null,null,null))
+z=R.Jk(z)
+y=$.Nd()
+x=P.Py(null,null,null,J.O,W.I0)
+w=J.O
+v=W.cv
+u=new V.br(P.Py(null,null,null,w,v),null,null)
+H.VM(u,[w,v])
+a.eE=z
+a.Ye=y
+a.mT=x
+a.KM=u
+C.J0.ZL(a)
+C.J0.FH(a)
+return a
+"9"},"+new BreakpointListElement$created:0:0":1}},"+BreakpointListElement": [42],Vf:{"":"uL+Pi;",$isd3:true}}],["class_view_element","package:observatory/src/observatory_elements/class_view.dart",,Z,{aC:{"":["tu;FJ%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
 gRu:function(a){return a.FJ
-"37,38,39"},
+"38,39,40"},
 "+cls":1,
 sRu:function(a,b){a.FJ=this.pD(a,C.XA,a.FJ,b)
-"40,31,37,38"},
+"41,32,38,39"},
 "+cls=":1,
 "@":function(){return[C.aQ]},
 static:{zg:function(a){var z,y,x,w,v
@@ -9461,12 +9485,12 @@
 C.kk.ZL(a)
 C.kk.FH(a)
 return a
-"9"},"+new ClassViewElement$created:0:0":1}},"+ClassViewElement": [41],Vf:{"":"uL+Pi;",$isd3:true}}],["code_view_element","package:observatory/src/observatory_elements/code_view.dart",,F,{Be:{"":["tu;Zw%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
+"10"},"+new ClassViewElement$created:0:0":1}},"+ClassViewElement": [43],tu:{"":"uL+Pi;",$isd3:true}}],["code_view_element","package:observatory/src/observatory_elements/code_view.dart",,F,{Be:{"":["Vc;Zw%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
 gtT:function(a){return a.Zw
-"37,38,39"},
+"38,39,40"},
 "+code":1,
 stT:function(a,b){a.Zw=this.pD(a,C.b1,a.Zw,b)
-"40,31,37,38"},
+"41,32,38,39"},
 "+code=":1,
 grK:function(a){var z=a.Zw
 if(z!=null&&J.UQ(z,"is_optimized")!=null)return"panel panel-success"
@@ -9490,41 +9514,41 @@
 C.YD.ZL(a)
 C.YD.FH(a)
 return a
-"10"},"+new CodeViewElement$created:0:0":1}},"+CodeViewElement": [42],tu:{"":"uL+Pi;",$isd3:true}}],["collapsible_content_element","package:observatory/src/observatory_elements/collapsible_content.dart",,R,{i6:{"":["Vc;Xf%-,VA%-,P2%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
+"11"},"+new CodeViewElement$created:0:0":1}},"+CodeViewElement": [44],Vc:{"":"uL+Pi;",$isd3:true}}],["collapsible_content_element","package:observatory/src/observatory_elements/collapsible_content.dart",,R,{i6:{"":["WZ;Xf%-,VA%-,P2%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
 gl7:function(a){return a.Xf
-"8,38,43"},
+"8,39,45"},
 "+iconClass":1,
 sl7:function(a,b){a.Xf=this.pD(a,C.Di,a.Xf,b)
-"40,31,8,38"},
+"41,32,8,39"},
 "+iconClass=":1,
 gai:function(a){return a.VA
-"8,38,43"},
+"8,39,45"},
 "+displayValue":1,
 sai:function(a,b){a.VA=this.pD(a,C.Jw,a.VA,b)
-"40,31,8,38"},
+"41,32,8,39"},
 "+displayValue=":1,
 gxj:function(a){return a.P2
-"44"},
+"46"},
 "+collapsed":1,
 sxj:function(a,b){a.P2=b
 this.dR(a)
-"40,45,44"},
+"41,47,46"},
 "+collapsed=":1,
 i4:function(a){Z.uL.prototype.i4.call(this,a)
 this.dR(a)
-"40"},
+"41"},
 "+enteredView:0:0":1,
 rS:function(a,b,c,d){a.P2=a.P2!==!0
 this.dR(a)
 this.dR(a)
-"40,46,47,48,40,49,50"},
+"41,48,49,50,41,51,52"},
 "+toggleDisplay:3:0":1,
 dR:function(a){var z,y
 z=a.P2
 y=a.Xf
 if(z===!0){a.Xf=this.pD(a,C.Di,y,"glyphicon glyphicon-chevron-down")
 a.VA=this.pD(a,C.Jw,a.VA,"none")}else{a.Xf=this.pD(a,C.Di,y,"glyphicon glyphicon-chevron-up")
-a.VA=this.pD(a,C.Jw,a.VA,"block")}"40"},
+a.VA=this.pD(a,C.Jw,a.VA,"block")}"41"},
 "+_refresh:0:0":1,
 "@":function(){return[C.Gu]},
 static:{"":"Vl<-,DI<-",IT:function(a){var z,y,x,w,v
@@ -9543,7 +9567,7 @@
 C.j8.ZL(a)
 C.j8.FH(a)
 return a
-"11"},"+new CollapsibleContentElement$created:0:0":1}},"+CollapsibleContentElement": [51],Vc:{"":"uL+Pi;",$isd3:true}}],["custom_element.polyfill","package:custom_element/polyfill.dart",,B,{G9:function(){if($.LX()==null)return!0
+"12"},"+new CollapsibleContentElement$created:0:0":1}},"+CollapsibleContentElement": [53],WZ:{"":"uL+Pi;",$isd3:true}}],["custom_element.polyfill","package:custom_element/polyfill.dart",,B,{G9:function(){if($.LX()==null)return!0
 var z=J.UQ($.LX(),"CustomElements")
 if(z==null)return"register" in document
 return J.xC(J.UQ(z,"ready"),!0)},zO:{"":"Tp;",
@@ -10111,7 +10135,7 @@
 if(typeof y==="object"&&y!==null&&!!z.$isZk)if(!("$reflectable" in y.dl))H.Hz(J.Z0(a))
 return H.vn(y.qj(b,c))},
 "+invoke:3:0":0,
-"*invoke":[40],
+"*invoke":[41],
 CI:function(a,b){return this.F2(a,b,null)},
 "+invoke:2:0":0,
 Z0:function(a){return $[a]},
@@ -10251,7 +10275,7 @@
 "+declarations":0,
 F2:function(a,b,c){throw H.b(P.lr(this,a,b,c,null))},
 "+invoke:3:0":0,
-"*invoke":[40],
+"*invoke":[41],
 CI:function(a,b){return this.F2(a,b,null)},
 "+invoke:2:0":0,
 rN:function(a){throw H.b(P.lr(this,a,null,null,null))},
@@ -10273,7 +10297,7 @@
 y=z+":"+b.length+":0"
 return this.tu(a,0,y,b)},
 "+invoke:3:0":0,
-"*invoke":[40],
+"*invoke":[41],
 CI:function(a,b){return this.F2(a,b,null)},
 "+invoke:2:0":0,
 tu:function(a,b,c,d){var z,y,x,w,v,u,t,s
@@ -10400,7 +10424,7 @@
 return z},
 F2:function(a,b,c){return this.NK.F2(a,b,c)},
 "+invoke:3:0":0,
-"*invoke":[40],
+"*invoke":[41],
 CI:function(a,b){return this.F2(a,b,null)},
 "+invoke:2:0":0,
 gHA:function(){return!1},
@@ -10452,7 +10476,7 @@
 y=J.x(z)
 if(typeof z==="object"&&z!==null&&!!y.$isGv)return z.constructor
 else return z
-"40"},
+"41"},
 "+_jsConstructor":1,
 gDI:function(){var z=this.b0
 if(z!=null)return z
@@ -10460,7 +10484,7 @@
 H.VM(z,[P.wv,P.RS])
 this.b0=z
 return z
-"52"},
+"54"},
 "+constructors":1,
 ly:function(a){var z,y,x,w,v,u,t,s,r,q,p,o,n,m,l,k
 z=this.gaB().prototype
@@ -10505,14 +10529,14 @@
 l=!1}s=H.Sd(k,o,!l,l)
 x.push(s)
 s.nz=a}return x
-"53,54,55"},
+"55,56,57"},
 "+_getMethodsWithOwner:1:0":1,
 gEO:function(){var z=this.jd
 if(z!=null)return z
 z=this.ly(this)
 this.jd=z
 return z
-"53"},
+"55"},
 "+_methods":1,
 ws:function(a){var z,y,x,w
 z=[]
@@ -10526,14 +10550,14 @@
 w=init.statics[this.WL]
 if(w!=null)H.jw(a,w[""],!0,z)
 return z
-"56,57,55"},
+"58,59,57"},
 "+_getFieldsWithOwner:1:0":1,
 gKn:function(){var z=this.tB
 if(z!=null)return z
 z=this.ws(this)
 this.tB=z
 return z
-"56"},
+"58"},
 "+_fields":1,
 gtx:function(){var z=this.FU
 if(z!=null)return z
@@ -10541,7 +10565,7 @@
 H.VM(z,[P.wv,P.RS])
 this.FU=z
 return z
-"52"},
+"54"},
 "+methods":1,
 gZ3:function(){var z,y,x
 z=this.M2
@@ -10552,7 +10576,7 @@
 H.VM(z,[P.wv,P.RY])
 this.M2=z
 return z
-"58"},
+"60"},
 "+variables":1,
 glc:function(a){var z=this.uA
 if(z!=null)return z
@@ -10560,7 +10584,7 @@
 H.VM(z,[P.wv,P.QF])
 this.uA=z
 return z
-"59"},
+"61"},
 "+members":1,
 gYK:function(){var z,y
 z=this.Db
@@ -10574,7 +10598,7 @@
 H.VM(z,[P.wv,P.NL])
 this.Db=z
 return z
-"60"},
+"62"},
 "+declarations":1,
 PU:function(a,b){var z,y
 z=J.UQ(this.gZ3(),a)
@@ -10582,7 +10606,7 @@
 if(!(y in $))throw H.b(H.Pa("Cannot find \""+y+"\" in current isolate."))
 $[y]=b
 return H.vn(b)}throw H.b(P.lr(this,H.X7(a),[b],null,null))
-"61,62,63,64,0"},
+"63,64,65,66,0"},
 "+setField:2:0":1,
 rN:function(a){var z,y
 z=J.UQ(this.gZ3(),a)
@@ -10590,7 +10614,7 @@
 if(!(y in $))throw H.b(H.Pa("Cannot find \""+y+"\" in current isolate."))
 if(y in init.lazies)return H.vn($[init.lazies[y]]())
 else return H.vn($[y])}throw H.b(P.lr(this,a,null,null,null))
-"61,62,63"},
+"63,64,65"},
 "+getField:1:0":1,
 gh7:function(){var z,y,x,w,v,u,t
 if(this.nz==null){z=this.Tx
@@ -10609,7 +10633,7 @@
 z=new H.MH(null,y,z.ew)
 z.$builtinTypeInfo=[u,t]
 for(;z.G();)for(y=J.GP(z.mD);y.G();)J.pP(y.gl())}if(this.nz==null)throw H.b(new P.lj("Class \""+H.d(J.Z0(this.If))+"\" has no owner"))}return this.nz
-"65"},
+"67"},
 "+owner":1,
 gc9:function(){var z=this.Ok
 if(z!=null)return z
@@ -10618,7 +10642,7 @@
 H.VM(z,[P.vr])
 this.Ok=z
 return z
-"66"},
+"68"},
 "+metadata":1,
 gAY:function(){var z,y,x,w,v,u
 if(this.qN==null){z=init.typeInformation[this.WL]
@@ -10632,7 +10656,7 @@
 u=v.length
 if(u>1){if(u!==2)throw H.b(H.Pa("Strange mixin: "+H.d(y)))
 this.qN=H.jO(v[0])}else this.qN=x.n(w,"")?this:H.jO(w)}}return J.xC(this.qN,this)?null:this.qN
-"67"},
+"69"},
 "+superclass":1,
 F2:function(a,b,c){var z
 if(c!=null&&J.FN(c)!==!0)throw H.b(P.f("Named arguments are not implemented."))
@@ -10640,16 +10664,16 @@
 if(z==null||!z.gFo())throw H.b(P.lr(this,a,b,c,null))
 if(!z.yR())H.Hz(J.Z0(a))
 return H.vn(z.qj(b,c))
-"61,68,63,69,70,71,72"},
+"63,70,65,71,72,73,74"},
 "+invoke:3:0":1,
-"*invoke":[40],
+"*invoke":[41],
 CI:function(a,b){return this.F2(a,b,null)},
 "+invoke:2:0":1,
 gHA:function(){return!0
-"44"},
+"46"},
 "+isOriginalDeclaration":1,
 gJi:function(){return this
-"67"},
+"69"},
 "+originalDeclaration":1,
 MR:function(a){var z,y,x
 z=init.typeInformation[this.WL]
@@ -10659,14 +10683,14 @@
 y=new P.Yp(x)
 H.VM(y,[P.Ms])
 return y
-"73,74,55"},
+"75,76,57"},
 "+_getSuperinterfacesWithOwner:1:0":1,
 gkZ:function(){var z=this.qm
 if(z!=null)return z
 z=this.MR(this)
 this.qm=z
 return z
-"73"},
+"75"},
 "+superinterfaces":1,
 gNy:function(){var z,y,x,w,v
 z=this.UF
@@ -10679,34 +10703,34 @@
 H.VM(z,[null])
 this.UF=z
 return z
-"75"},
+"77"},
 "+typeVariables":1,
 gw8:function(){return C.hU
-"76"},
+"78"},
 "+typeArguments":1,
 $isWf:true,
 $isMs:true,
 $isQF:true,
 $isL9u:true,
-$isNL:true},"+JsClassMirror": [77, 67],Un:{"":"EE+M2;",$isQF:true},Ei:{"":"Tp;a-",
+$isNL:true},"+JsClassMirror": [79, 69],Un:{"":"EE+M2;",$isQF:true},Ei:{"":"Tp;a-",
 call$2:function(a,b){J.kW(this.a,a,b)
-"40,78,63,31,79"},
+"41,80,65,32,81"},
 "+call:2:0":1,
 $isEH:true,
-$is_bh:true},"+JsClassMirror_declarations_addToResult": [80],U7:{"":"Tp;b-",
+$is_bh:true},"+JsClassMirror_declarations_addToResult": [82],U7:{"":"Tp;b-",
 call$1:function(a){J.kW(this.b,a.gIf(),a)
 return a
-"40,81,40"},
+"41,83,41"},
 "+call:1:0":1,
 $isEH:true,
 $is_HB:true,
-$is_Dv:true},"+JsClassMirror_declarations_closure": [80],t0:{"":"Tp;a-",
+$is_Dv:true},"+JsClassMirror_declarations_closure": [82],t0:{"":"Tp;a-",
 call$1:function(a){return H.Jf(this.a,init.metadata[a])
-"67,82,30"},
+"69,84,31"},
 "+call:1:0":1,
 $isEH:true,
 $is_HB:true,
-$is_Dv:true},"+JsClassMirror__getSuperinterfacesWithOwner_lookupType": [80],Ld:{"":"am;ao<,V5<,Fo<,n6,nz,le,If",
+$is_Dv:true},"+JsClassMirror__getSuperinterfacesWithOwner_lookupType": [82],Ld:{"":"am;ao<,V5<,Fo<,n6,nz,le,If",
 gOO:function(){return"VariableMirror"},
 "+_prettyName":0,
 gr9:function(a){return $.Cr()},
@@ -11373,7 +11397,7 @@
 $is_Dv:true},dm:{"":"Tp;b",
 call$2:function(a,b){this.b.K5(a,b)},
 "+call:2:0":0,
-"*call":[40],
+"*call":[41],
 call$1:function(a){return this.call$2(a,null)},
 "+call:1:0":0,
 $isEH:true,
@@ -11442,7 +11466,7 @@
 if(typeof y!=="object"||y===null||!x.$isvs){z.a=P.Dt(null)
 z.a.E6(a,b)}P.HZ(z.a,this.h)},
 "+call:2:0":0,
-"*call":[40],
+"*call":[41],
 call$1:function(a){return this.call$2(a,null)},
 "+call:1:0":0,
 $isEH:true,
@@ -14592,7 +14616,7 @@
 gor:function(a){return J.pO(this.iY)},
 "+isNotEmpty":0,
 $isL8:true}}],["dart.dom.html","dart:html",,W,{lq:function(){return window
-"12"},"+window":1,UE:function(a){if(P.F7()===!0)return"webkitTransitionEnd"
+"13"},"+window":1,UE:function(a){if(P.F7()===!0)return"webkitTransitionEnd"
 else if(P.dg()===!0)return"oTransitionEnd"
 return"transitionend"},r3:function(a,b){return document.createElement(a)},It:function(a,b,c){return W.lt(a,null,null,b,null,null,null,c).ml(new W.Kx())},lt:function(a,b,c,d,e,f,g,h){var z,y,x,w
 z=W.fJ
@@ -14663,7 +14687,7 @@
 q={prototype: s}
 if(!J.xC(w,"HTMLElement"))if(!v)q.extends=e
 b.register(c,q)},aF:function(a){if(J.xC($.X3,C.NU))return a
-return $.X3.oj(a,!0)},qE:{"":"cv;","%":"HTMLAppletElement|HTMLBRElement|HTMLBaseFontElement|HTMLBodyElement|HTMLCanvasElement|HTMLContentElement|HTMLDListElement|HTMLDataListElement|HTMLDetailsElement|HTMLDialogElement|HTMLDirectoryElement|HTMLDivElement|HTMLFontElement|HTMLFrameElement|HTMLFrameSetElement|HTMLHRElement|HTMLHeadElement|HTMLHeadingElement|HTMLHtmlElement|HTMLMarqueeElement|HTMLMenuElement|HTMLModElement|HTMLOptGroupElement|HTMLParagraphElement|HTMLPreElement|HTMLQuoteElement|HTMLShadowElement|HTMLSpanElement|HTMLTableCaptionElement|HTMLTableCellElement|HTMLTableColElement|HTMLTableDataCellElement|HTMLTableElement|HTMLTableHeaderCellElement|HTMLTableRowElement|HTMLTableSectionElement|HTMLTitleElement|HTMLUListElement|HTMLUnknownElement;HTMLElement;Sa|GN|ir|Nr|uL|Vf|aC|tu|Be|Vc|i6|WZ|Fv|pv|I3|Vfx|qr|Dsd|Gk|tuj|Ds|Vct|pR|D13|hx|u7|WZq|St|pva|vj|cda|CX|Nh|ih|waa|F1|XP|NQ|V0|fI|V4|kK|V6|uw"},Yy:{"":"Gv;",$isList:true,
+return $.X3.oj(a,!0)},qE:{"":"cv;","%":"HTMLAppletElement|HTMLBRElement|HTMLBaseFontElement|HTMLBodyElement|HTMLCanvasElement|HTMLContentElement|HTMLDListElement|HTMLDataListElement|HTMLDetailsElement|HTMLDialogElement|HTMLDirectoryElement|HTMLDivElement|HTMLFontElement|HTMLFrameElement|HTMLFrameSetElement|HTMLHRElement|HTMLHeadElement|HTMLHeadingElement|HTMLHtmlElement|HTMLMarqueeElement|HTMLMenuElement|HTMLModElement|HTMLOptGroupElement|HTMLParagraphElement|HTMLPreElement|HTMLQuoteElement|HTMLShadowElement|HTMLSpanElement|HTMLTableCaptionElement|HTMLTableCellElement|HTMLTableColElement|HTMLTableDataCellElement|HTMLTableElement|HTMLTableHeaderCellElement|HTMLTableRowElement|HTMLTableSectionElement|HTMLTitleElement|HTMLUListElement|HTMLUnknownElement;HTMLElement;Sa|GN|ir|Nr|uL|Vf|G6|tu|aC|Vc|Be|WZ|i6|pv|Fv|Vfx|I3|Dsd|qr|tuj|Gk|Vct|Ds|D13|pR|WZq|hx|u7|pva|St|cda|vj|waa|CX|Nh|ih|V0|F1|XP|NQ|V4|fI|V6|kK|V8|uw"},Yy:{"":"Gv;",$isList:true,
 $asWO:function(){return[W.M5]},
 $isqC:true,
 $iscX:true,
@@ -15697,12 +15721,12 @@
 $iscX:true,
 $ascX:function(){return[J.im]},
 $isXj:true,
-static:{"":"U9",}}}],["disassembly_entry_element","package:observatory/src/observatory_elements/disassembly_entry.dart",,E,{Fv:{"":["WZ;FT%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
+static:{"":"U9",}}}],["disassembly_entry_element","package:observatory/src/observatory_elements/disassembly_entry.dart",,E,{Fv:{"":["pv;FT%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
 gNI:function(a){return a.FT
-"37,38,39"},
+"38,39,40"},
 "+instruction":1,
 sNI:function(a,b){a.FT=this.pD(a,C.eJ,a.FT,b)
-"40,31,37,38"},
+"41,32,38,39"},
 "+instruction=":1,
 "@":function(){return[C.Vy]},
 static:{AH:function(a){var z,y,x,w,v,u
@@ -15721,18 +15745,18 @@
 C.Tl.ZL(a)
 C.Tl.FH(a)
 return a
-"13"},"+new DisassemblyEntryElement$created:0:0":1}},"+DisassemblyEntryElement": [83],WZ:{"":"uL+Pi;",$isd3:true}}],["error_view_element","package:observatory/src/observatory_elements/error_view.dart",,F,{I3:{"":["pv;Py%-,hO%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
+"14"},"+new DisassemblyEntryElement$created:0:0":1}},"+DisassemblyEntryElement": [85],pv:{"":"uL+Pi;",$isd3:true}}],["error_view_element","package:observatory/src/observatory_elements/error_view.dart",,F,{I3:{"":["Vfx;Py%-,hO%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
 gkc:function(a){return a.Py
-"8,38,39"},
+"8,39,40"},
 "+error":1,
 skc:function(a,b){a.Py=this.pD(a,C.YU,a.Py,b)
-"40,31,8,38"},
+"41,32,8,39"},
 "+error=":1,
 gVB:function(a){return a.hO
-"40,38,39"},
+"41,39,40"},
 "+error_obj":1,
 sVB:function(a,b){a.hO=this.pD(a,C.Yn,a.hO,b)
-"40,31,40,38"},
+"41,32,41,39"},
 "+error_obj=":1,
 "@":function(){return[C.uW]},
 static:{TW:function(a){var z,y,x,w,v
@@ -15749,12 +15773,12 @@
 C.OD.ZL(a)
 C.OD.FH(a)
 return a
-"14"},"+new ErrorViewElement$created:0:0":1}},"+ErrorViewElement": [84],pv:{"":"uL+Pi;",$isd3:true}}],["field_ref_element","package:observatory/src/observatory_elements/field_ref.dart",,D,{qr:{"":["Vfx;Lf%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
+"15"},"+new ErrorViewElement$created:0:0":1}},"+ErrorViewElement": [86],Vfx:{"":"uL+Pi;",$isd3:true}}],["field_ref_element","package:observatory/src/observatory_elements/field_ref.dart",,D,{qr:{"":["Dsd;Lf%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
 gt0:function(a){return a.Lf
-"37,38,39"},
+"38,39,40"},
 "+field":1,
 st0:function(a,b){a.Lf=this.pD(a,C.WQ,a.Lf,b)
-"40,31,37,38"},
+"41,32,38,39"},
 "+field=":1,
 "@":function(){return[C.ht]},
 static:{ip:function(a){var z,y,x,w,v
@@ -15770,12 +15794,12 @@
 C.WR.ZL(a)
 C.WR.FH(a)
 return a
-"15"},"+new FieldRefElement$created:0:0":1}},"+FieldRefElement": [85],Vfx:{"":"uL+Pi;",$isd3:true}}],["field_view_element","package:observatory/src/observatory_elements/field_view.dart",,A,{Gk:{"":["Dsd;vt%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
+"16"},"+new FieldRefElement$created:0:0":1}},"+FieldRefElement": [87],Dsd:{"":"uL+Pi;",$isd3:true}}],["field_view_element","package:observatory/src/observatory_elements/field_view.dart",,A,{Gk:{"":["tuj;vt%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
 gt0:function(a){return a.vt
-"37,38,39"},
+"38,39,40"},
 "+field":1,
 st0:function(a,b){a.vt=this.pD(a,C.WQ,a.vt,b)
-"40,31,37,38"},
+"41,32,38,39"},
 "+field=":1,
 "@":function(){return[C.Tq]},
 static:{cY:function(a){var z,y,x,w,v
@@ -15791,12 +15815,12 @@
 C.lS.ZL(a)
 C.lS.FH(a)
 return a
-"16"},"+new FieldViewElement$created:0:0":1}},"+FieldViewElement": [86],Dsd:{"":"uL+Pi;",$isd3:true}}],["function_view_element","package:observatory/src/observatory_elements/function_view.dart",,N,{Ds:{"":["tuj;ql%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
+"17"},"+new FieldViewElement$created:0:0":1}},"+FieldViewElement": [88],tuj:{"":"uL+Pi;",$isd3:true}}],["function_view_element","package:observatory/src/observatory_elements/function_view.dart",,N,{Ds:{"":["Vct;ql%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
 gMj:function(a){return a.ql
-"37,38,39"},
+"38,39,40"},
 "+function":1,
 sMj:function(a,b){a.ql=this.pD(a,C.nf,a.ql,b)
-"40,31,37,38"},
+"41,32,38,39"},
 "+function=":1,
 "@":function(){return[C.Uc]},
 static:{p7:function(a){var z,y,x,w,v
@@ -15812,7 +15836,7 @@
 C.PJ.ZL(a)
 C.PJ.FH(a)
 return a
-"17"},"+new FunctionViewElement$created:0:0":1}},"+FunctionViewElement": [87],tuj:{"":"uL+Pi;",$isd3:true}}],["html_common","dart:html_common",,P,{jD:function(a){return P.Wu(a.getTime(),!0)},bL:function(a){var z,y
+"18"},"+new FunctionViewElement$created:0:0":1}},"+FunctionViewElement": [89],Vct:{"":"uL+Pi;",$isd3:true}}],["html_common","dart:html_common",,P,{jD:function(a){return P.Wu(a.getTime(),!0)},bL:function(a){var z,y
 z=[]
 y=new P.Tm(new P.aI([],z),new P.rG(z),new P.yh(z)).call$1(a)
 new P.wO().call$0()
@@ -16000,12 +16024,12 @@
 "+call:1:0":0,
 $isEH:true,
 $is_HB:true,
-$is_Dv:true}}],["instance_ref_element","package:observatory/src/observatory_elements/instance_ref.dart",,B,{pR:{"":["Vct;iK%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
+$is_Dv:true}}],["instance_ref_element","package:observatory/src/observatory_elements/instance_ref.dart",,B,{pR:{"":["D13;iK%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
 ghf:function(a){return a.iK
-"37,38,39"},
+"38,39,40"},
 "+instance":1,
 shf:function(a,b){a.iK=this.pD(a,C.fn,a.iK,b)
-"40,31,37,38"},
+"41,32,38,39"},
 "+instance=":1,
 "@":function(){return[C.ay]},
 static:{lu:function(a){var z,y,x,w,v
@@ -16021,12 +16045,12 @@
 C.cp.ZL(a)
 C.cp.FH(a)
 return a
-"18"},"+new InstanceRefElement$created:0:0":1}},"+InstanceRefElement": [88],Vct:{"":"uL+Pi;",$isd3:true}}],["instance_view_element","package:observatory/src/observatory_elements/instance_view.dart",,Z,{hx:{"":["D13;Xh%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
+"19"},"+new InstanceRefElement$created:0:0":1}},"+InstanceRefElement": [90],D13:{"":"uL+Pi;",$isd3:true}}],["instance_view_element","package:observatory/src/observatory_elements/instance_view.dart",,Z,{hx:{"":["WZq;Xh%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
 ghf:function(a){return a.Xh
-"37,38,39"},
+"38,39,40"},
 "+instance":1,
 shf:function(a,b){a.Xh=this.pD(a,C.fn,a.Xh,b)
-"40,31,37,38"},
+"41,32,38,39"},
 "+instance=":1,
 "@":function(){return[C.ql]},
 static:{HC:function(a){var z,y,x,w,v
@@ -16042,7 +16066,7 @@
 C.yK.ZL(a)
 C.yK.FH(a)
 return a
-"19"},"+new InstanceViewElement$created:0:0":1}},"+InstanceViewElement": [89],D13:{"":"uL+Pi;",$isd3:true}}],["isolate_list_element","package:observatory/src/observatory_elements/isolate_list.dart",,L,{u7:{"":["uL;tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
+"20"},"+new InstanceViewElement$created:0:0":1}},"+InstanceViewElement": [91],WZq:{"":"uL+Pi;",$isd3:true}}],["isolate_list_element","package:observatory/src/observatory_elements/isolate_list.dart",,L,{u7:{"":["uL;tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
 "@":function(){return[C.jF]},
 static:{Tt:function(a){var z,y,x,w,v
 z=$.Nd()
@@ -16057,18 +16081,18 @@
 C.Dh.ZL(a)
 C.Dh.FH(a)
 return a
-"20"},"+new IsolateListElement$created:0:0":1}},"+IsolateListElement": [27]}],["isolate_summary_element","package:observatory/src/observatory_elements/isolate_summary.dart",,D,{St:{"":["WZq;Pw%-,i0%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
+"21"},"+new IsolateListElement$created:0:0":1}},"+IsolateListElement": [28]}],["isolate_summary_element","package:observatory/src/observatory_elements/isolate_summary.dart",,D,{St:{"":["pva;Pw%-,i0%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
 gF1:function(a){return a.Pw
-"30,38,39"},
+"31,39,40"},
 "+isolate":1,
 sF1:function(a,b){a.Pw=this.pD(a,C.Y2,a.Pw,b)
-"40,31,30,38"},
+"41,32,31,39"},
 "+isolate=":1,
 goc:function(a){return a.i0
-"8,38,39"},
+"8,39,40"},
 "+name":1,
 soc:function(a,b){a.i0=this.pD(a,C.YS,a.i0,b)
-"40,31,8,38"},
+"41,32,8,39"},
 "+name=":1,
 "@":function(){return[C.aM]},
 static:{N5:function(a){var z,y,x,w,v
@@ -16085,19 +16109,19 @@
 C.nM.ZL(a)
 C.nM.FH(a)
 return a
-"21"},"+new IsolateSummaryElement$created:0:0":1}},"+IsolateSummaryElement": [90],WZq:{"":"uL+Pi;",$isd3:true}}],["json_view_element","package:observatory/src/observatory_elements/json_view.dart",,Z,{vj:{"":["pva;eb%-,kf%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
+"22"},"+new IsolateSummaryElement$created:0:0":1}},"+IsolateSummaryElement": [92],pva:{"":"uL+Pi;",$isd3:true}}],["json_view_element","package:observatory/src/observatory_elements/json_view.dart",,Z,{vj:{"":["cda;eb%-,kf%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
 gTn:function(a){return a.eb
-"40,38,39"},
+"41,39,40"},
 "+json":1,
 sTn:function(a,b){a.eb=this.pD(a,C.Gd,a.eb,b)
-"40,31,40,38"},
+"41,32,41,39"},
 "+json=":1,
 i4:function(a){Z.uL.prototype.i4.call(this,a)
 a.kf=0
-"40"},
+"41"},
 "+enteredView:0:0":1,
 yC:function(a,b){this.pD(a,C.eR,"a","b")
-"40,91,40"},
+"41,93,41"},
 "+jsonChanged:1:0":1,
 gE8:function(a){return J.AG(a.eb)
 "8"},
@@ -16113,24 +16137,24 @@
 gFe:function(a){var z=a.kf
 a.kf=J.WB(z,1)
 return z
-"30"},
+"31"},
 "+counter":1,
 gqC:function(a){var z,y
 z=a.eb
 y=J.x(z)
 if(typeof z==="object"&&z!==null&&(z.constructor===Array||!!y.$isList))return z
 return[]
-"70"},
+"72"},
 "+list":1,
 gvc:function(a){var z,y
 z=a.eb
 y=J.RE(z)
 if(typeof z==="object"&&z!==null&&!!y.$isL8)return J.qA(y.gvc(z))
 return[]
-"70"},
+"72"},
 "+keys":1,
 r6:function(a,b){return J.UQ(a.eb,b)
-"40,78,8"},
+"41,80,8"},
 "+value:1:0":1,
 gP:function(a){return new P.C7(this,Z.vj.prototype.r6,a,"r6")},
 "@":function(){return[C.HN]},
@@ -16149,12 +16173,12 @@
 C.GB.ZL(a)
 C.GB.FH(a)
 return a
-"22"},"+new JsonViewElement$created:0:0":1}},"+JsonViewElement": [92],pva:{"":"uL+Pi;",$isd3:true}}],["library_view_element","package:observatory/src/observatory_elements/library_view.dart",,M,{CX:{"":["cda;iI%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
+"23"},"+new JsonViewElement$created:0:0":1}},"+JsonViewElement": [94],cda:{"":"uL+Pi;",$isd3:true}}],["library_view_element","package:observatory/src/observatory_elements/library_view.dart",,M,{CX:{"":["waa;iI%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
 gtD:function(a){return a.iI
-"37,38,39"},
+"38,39,40"},
 "+library":1,
 stD:function(a,b){a.iI=this.pD(a,C.EV,a.iI,b)
-"40,31,37,38"},
+"41,32,38,39"},
 "+library=":1,
 "@":function(){return[C.Oy]},
 static:{SP:function(a){var z,y,x,w,v,u
@@ -16173,7 +16197,7 @@
 C.MG.ZL(a)
 C.MG.FH(a)
 return a
-"23"},"+new LibraryViewElement$created:0:0":1}},"+LibraryViewElement": [93],cda:{"":"uL+Pi;",$isd3:true}}],["logging","package:logging/logging.dart",,N,{TJ:{"":"a;oc>,eT>,yz,Cj>,wd,Gs",
+"24"},"+new LibraryViewElement$created:0:0":1}},"+LibraryViewElement": [95],waa:{"":"uL+Pi;",$isd3:true}}],["logging","package:logging/logging.dart",,N,{TJ:{"":"a;oc>,eT>,yz,Cj>,wd,Gs",
 gB8:function(){var z,y,x
 z=this.eT
 y=z==null||J.xC(J.DA(z),"")
@@ -16241,26 +16265,27 @@
 giO:function(a){return this.P},
 bu:function(a){return this.oc},
 $isNg:true,
-static:{"":"bR,tm,EL,X8,IQ,Fn,Eb,AN,JY,bo",}},HV:{"":"a;OR<,G1>,iJ,Fl,O0,kc>,I4<",
+static:{"":"bR,tm,EL,X8,IQ,Fn,Eb,AN,JY,ac",}},HV:{"":"a;OR<,G1>,iJ,Fl,O0,kc>,I4<",
 bu:function(a){return"["+this.OR.oc+"] "+this.iJ+": "+this.G1},
 static:{"":"xO",}}}],["message_viewer_element","package:observatory/src/observatory_elements/message_viewer.dart",,L,{Nh:{"":["uL;XB%-,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
 gG1:function(a){return a.XB
-"37,39"},
+"38,40"},
 "+message":1,
 sG1:function(a,b){a.XB=b
 this.pD(a,C.KY,"",this.gQW(a))
 this.pD(a,C.wt,[],this.glc(a))
-"40,94,37,39"},
+"41,96,38,40"},
 "+message=":1,
 gQW:function(a){var z=a.XB
 if(z==null||J.UQ(z,"type")==null)return"Error"
+P.JS("Received message of type '"+H.d(J.UQ(a.XB,"type"))+"' :\n"+H.d(a.XB))
 return J.UQ(a.XB,"type")
 "8"},
 "+messageType":1,
 glc:function(a){var z=a.XB
 if(z==null||J.UQ(z,"members")==null)return[]
 return J.UQ(a.XB,"members")
-"95"},
+"97"},
 "+members":1,
 "@":function(){return[C.c0]},
 static:{rJ:function(a){var z,y,x,w,v
@@ -16276,7 +16301,7 @@
 C.Wp.ZL(a)
 C.Wp.FH(a)
 return a
-"24"},"+new MessageViewerElement$created:0:0":1}},"+MessageViewerElement": [27]}],["metadata","../../../../../../../../../dart/dart-sdk/lib/html/html_common/metadata.dart",,B,{fA:{"":"a;Kr,Jt",static:{"":"Xd,en,yS,PZ,xa",}},tz:{"":"a;"},jR:{"":"a;oc>"},PO:{"":"a;"},c5:{"":"a;"}}],["navigation_bar_element","package:observatory/src/observatory_elements/navigation_bar.dart",,Q,{ih:{"":["uL;tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
+"25"},"+new MessageViewerElement$created:0:0":1}},"+MessageViewerElement": [28]}],["metadata","../../../../../../../../../dart/dart-sdk/lib/html/html_common/metadata.dart",,B,{fA:{"":"a;Kr,Jt",static:{"":"Xd,en,yS,PZ,xa",}},tz:{"":"a;"},jR:{"":"a;oc>"},PO:{"":"a;"},c5:{"":"a;"}}],["navigation_bar_element","package:observatory/src/observatory_elements/navigation_bar.dart",,Q,{ih:{"":["uL;tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
 "@":function(){return[C.KG]},
 static:{BW:function(a){var z,y,x,w,v
 z=$.Nd()
@@ -16291,7 +16316,7 @@
 C.Xg.ZL(a)
 C.Xg.FH(a)
 return a
-"25"},"+new NavigationBarElement$created:0:0":1}},"+NavigationBarElement": [27]}],["observatory","package:observatory/observatory.dart",,L,{mL:{"":["Pi;Z6<-,lw<-,nI<-,VJ,Ai",function(){return[C.mI]},function(){return[C.mI]},function(){return[C.mI]},null,null],
+"26"},"+new NavigationBarElement$created:0:0":1}},"+NavigationBarElement": [28]}],["observatory","package:observatory/observatory.dart",,L,{mL:{"":["Pi;Z6<-,lw<-,nI<-,VJ,Ai",function(){return[C.mI]},function(){return[C.mI]},function(){return[C.mI]},null,null],
 Ey:function(){var z,y,x
 z=this.Z6
 z.sJR(this)
@@ -16325,16 +16350,16 @@
 y.US()
 return y}}},bv:{"":["Pi;nk,SS,XR<-,VJ,Ai",null,null,function(){return[C.mI]},null,null],
 gjO:function(a){return this.nk
-"30,38,43"},
+"31,39,45"},
 "+id":1,
 sjO:function(a,b){this.nk=F.Wi(this,C.EN,this.nk,b)
-"40,31,30,38"},
+"41,32,31,39"},
 "+id=":1,
 goc:function(a){return this.SS
-"8,38,43"},
+"8,39,45"},
 "+name":1,
 soc:function(a,b){this.SS=F.Wi(this,C.YS,this.SS,b)
-"40,31,8,38"},
+"41,32,8,39"},
 "+name=":1,
 bu:function(a){return H.d(this.nk)+" "+H.d(this.SS)},
 $isbv:true},pt:{"":["Pi;JR?,i2<-,VJ,Ai",null,function(){return[C.mI]},null,null],
@@ -16387,16 +16412,16 @@
 $is_HB:true,
 $is_Dv:true},dZ:{"":"Pi;JR?,IT,Jj,VJ,Ai",
 gzd:function(){return this.IT
-"8,38,43"},
+"8,39,45"},
 "+currentHash":1,
 szd:function(a){this.IT=F.Wi(this,C.h1,this.IT,a)
-"40,31,8,38"},
+"41,32,8,39"},
 "+currentHash=":1,
 glD:function(){return this.Jj
-"96,38,43"},
+"98,39,45"},
 "+currentHashUri":1,
 slD:function(a){this.Jj=F.Wi(this,C.tv,this.Jj,a)
-"40,31,96,38"},
+"41,32,98,39"},
 "+currentHashUri=":1,
 kI:function(){var z,y
 z=C.PP.aM(window)
@@ -16438,35 +16463,35 @@
 PI:function(a){var z=this.R6()
 if(J.xC(z,0))return"#/isolates/"
 return"#/isolates/"+H.d(z)+"/"+H.d(a)
-"8,97,8,43"},
+"8,99,8,45"},
 "+currentIsolateRelativeLink:1:0":1,
 Ao:function(a){var z=this.R6()
 if(J.xC(z,0))return"#/isolates/"
 return"#/isolates/"+H.d(z)+"/objects/"+H.d(a)
-"8,98,30,43"},
+"8,100,31,45"},
 "+currentIsolateObjectLink:1:0":1,
 dL:function(a){var z=this.R6()
 if(J.xC(z,0))return"#/isolates/"
 return"#/isolates/"+H.d(z)+"/classes/"+H.d(a)
-"8,99,30,43"},
+"8,101,31,45"},
 "+currentIsolateClassLink:1:0":1,
 WW:function(a,b){var z=this.R6()
 if(J.xC(z,0))return"#/isolates/"
 return this.yX(z,a,b)
-"8,98,30,7,8,43"},
+"8,100,31,7,8,45"},
 "+currentIsolateScriptLink:2:0":1,
 r4:function(a,b){return"#/isolates/"+H.d(a)+"/"+H.d(b)
-"8,100,30,97,8,43"},
+"8,102,31,99,8,45"},
 "+relativeLink:2:0":1,
 Dd:function(a,b){return"#/isolates/"+H.d(a)+"/objects/"+H.d(b)
-"8,100,30,98,30,43"},
+"8,102,31,100,31,45"},
 "+objectLink:2:0":1,
 bD:function(a,b){return"#/isolates/"+H.d(a)+"/classes/"+H.d(b)
-"8,100,30,99,30,43"},
+"8,102,31,101,31,45"},
 "+classLink:2:0":1,
 yX:function(a,b,c){var z=P.jW(C.kg,c,!0)
 return"#/isolates/"+H.d(a)+"/objects/"+H.d(b)+"?type=Script&name="+z
-"8,100,30,98,30,7,8,43"},
+"8,102,31,100,31,7,8,45"},
 "+scriptLink:3:0":1,
 static:{"":"kx,K3D,qY",}},Qe:{"":"Tp;a",
 call$1:function(a){var z=this.a
@@ -16478,16 +16503,16 @@
 $is_Dv:true},Nu:{"":"Pi;JR?,e0?",
 pG:function(){return this.e0.call$0()},
 gEI:function(){return this.oJ
-"8,38,43"},
+"8,39,45"},
 "+prefix":1,
 sEI:function(a){this.oJ=F.Wi(this,C.qb,this.oJ,a)
-"40,31,8,38"},
+"41,32,8,39"},
 "+prefix=":1,
 gn2:function(){return this.vm
-"95,38,43"},
+"97,39,45"},
 "+responses":1,
 sn2:function(a){this.vm=F.Wi(this,C.wH,this.vm,a)
-"40,31,95,38"},
+"41,32,97,39"},
 "+responses=":1,
 Qn:function(a){var z,y
 z=C.lM.kV(a)
@@ -16574,13 +16599,13 @@
 J.Ih(W.uV(window.parent),C.lM.KP(y),"*")
 return w.MM}},Zw:{"":["Pi;Rd,n7,LA>-,Vg,VJ,Ai",null,null,function(){return[C.mI]},null,null,null],
 geV:function(){return this.Vg
-"8,38,43"},
+"8,39,45"},
 "+paddedLine":1,
 seV:function(a){var z=this.Vg
 if(this.gUV(this)&&!J.xC(z,a)){z=new T.qI(this,C.X9,z,a)
 z.$builtinTypeInfo=[null]
 this.SZ(this,z)}this.Vg=a
-"40,31,8,38"},
+"41,32,8,39"},
 "+paddedLine=":1,
 QQ:function(a,b,c){var z,y,x,w,v
 z=""+this.Rd
@@ -16594,22 +16619,22 @@
 z.QQ(a,b,c)
 return z}}},Pf:{"":"Pi;WF,uM,ZQ,VJ,Ai",
 gfY:function(a){return this.WF
-"8,38,43"},
+"8,39,45"},
 "+kind":1,
 sfY:function(a,b){this.WF=F.Wi(this,C.fy,this.WF,b)
-"40,31,8,38"},
+"41,32,8,39"},
 "+kind=":1,
 gO3:function(a){return this.uM
-"8,38,43"},
+"8,39,45"},
 "+url":1,
 sO3:function(a,b){this.uM=F.Wi(this,C.Fh,this.uM,b)
-"40,31,8,38"},
+"41,32,8,39"},
 "+url=":1,
 gXJ:function(){return this.ZQ
-"101,38,43"},
+"103,39,45"},
 "+lines":1,
 sXJ:function(a){this.ZQ=F.Wi(this,C.Cv,this.ZQ,a)
-"40,31,101,38"},
+"41,32,103,39"},
 "+lines=":1,
 Cn:function(a){var z,y,x,w,v
 z=J.uH(a,"\n")
@@ -16629,17 +16654,17 @@
 static:{Sp:function(a){var z=R.Jk([])
 z=new L.Pf("","",z,null,null)
 z.EQ(a)
-return z}}}}],["observatory_application_element","package:observatory/src/observatory_elements/observatory_application.dart",,V,{F1:{"":["waa;k5%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
+return z}}}}],["observatory_application_element","package:observatory/src/observatory_elements/observatory_application.dart",,V,{F1:{"":["V0;k5%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
 gzj:function(a){return a.k5
-"44,38,39"},
+"46,39,40"},
 "+devtools":1,
 szj:function(a,b){a.k5=this.pD(a,C.Na,a.k5,b)
-"40,31,44,38"},
+"41,32,46,39"},
 "+devtools=":1,
 ZB:function(a){var z
 if(a.k5===!0){z=L.WS()
 a.tH=this.pD(a,C.wh,a.tH,z)}else{z=L.AK()
-a.tH=this.pD(a,C.wh,a.tH,z)}"40"},
+a.tH=this.pD(a,C.wh,a.tH,z)}"41"},
 "@":function(){return[C.bd]},
 static:{fv:function(a){var z,y,x,w,v
 z=$.Nd()
@@ -16656,23 +16681,23 @@
 C.k0.FH(a)
 C.k0.ZB(a)
 return a
-"26"},"+new ObservatoryApplicationElement$created:0:0":1}},"+ObservatoryApplicationElement": [102],waa:{"":"uL+Pi;",$isd3:true}}],["observatory_element","package:observatory/src/observatory_elements/observatory_element.dart",,Z,{uL:{"":["Nr;tH%-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
+"27"},"+new ObservatoryApplicationElement$created:0:0":1}},"+ObservatoryApplicationElement": [104],V0:{"":"uL+Pi;",$isd3:true}}],["observatory_element","package:observatory/src/observatory_elements/observatory_element.dart",,Z,{uL:{"":["Nr;tH%-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
 i4:function(a){A.dM.prototype.i4.call(this,a)
-"40"},
+"41"},
 "+enteredView:0:0":1,
 Nz:function(a){A.dM.prototype.Nz.call(this,a)
-"40"},
+"41"},
 "+leftView:0:0":1,
 gQG:function(a){return a.tH
-"103,38,39"},
+"105,39,40"},
 "+app":1,
 sQG:function(a,b){a.tH=this.pD(a,C.wh,a.tH,b)
-"40,31,103,38"},
+"41,32,105,39"},
 "+app=":1,
 gpQ:function(a){return!0
-"44"},
+"46"},
 "+applyAuthorStyles":1,
-"@":function(){return[C.J0]},
+"@":function(){return[C.Br]},
 static:{Hx:function(a){var z,y,x,w,v
 z=$.Nd()
 y=P.Py(null,null,null,J.O,W.I0)
@@ -16686,7 +16711,7 @@
 C.mk.ZL(a)
 C.mk.FH(a)
 return a
-"27"},"+new ObservatoryElement$created:0:0":1}},"+ObservatoryElement": [104],Nr:{"":"ir+Pi;",$isd3:true}}],["observe.src.change_notifier","package:observe/src/change_notifier.dart",,O,{Pi:{"":"a;",
+"28"},"+new ObservatoryElement$created:0:0":1}},"+ObservatoryElement": [106],Nr:{"":"ir+Pi;",$isd3:true}}],["observe.src.change_notifier","package:observe/src/change_notifier.dart",,O,{Pi:{"":"a;",
 gqh:function(a){var z,y
 if(a.VJ==null){z=this.gqw(a)
 a.VJ=P.bK(this.gl1(a),z,!0,null)}z=a.VJ
@@ -16730,7 +16755,7 @@
 gB:function(a){return this.b9.length},
 "+length":0,
 gP:function(a){return this.Sv
-"40,38"},
+"41,39"},
 "+value":1,
 r6:function(a,b){return this.gP(a).call$1(b)},
 wE:function(a){var z,y,x,w
@@ -17055,11 +17080,11 @@
 $isEH:true,
 $is_bh:true}}],["observe.src.observable_box","package:observe/src/observable_box.dart",,A,{xh:{"":"Pi;",
 gP:function(a){return this.L1
-"105,38"},
+"107,39"},
 "+value":1,
 r6:function(a,b){return this.gP(a).call$1(b)},
 sP:function(a,b){this.L1=F.Wi(this,C.ls,this.L1,b)
-"40,106,105,38"},
+"41,108,107,39"},
 "+value=":1,
 bu:function(a){return"#<"+H.d(new H.cu(H.dJ(this),null))+" value: "+H.d(this.L1)+">"}}}],["observe.src.observable_list","package:observe/src/observable_list.dart",,Q,{wn:{"":"uF;b3,xg,h3,VJ,Ai",
 gRT:function(){var z,y
@@ -17070,7 +17095,7 @@
 H.VM(y,[H.W8(z,"WV",0)])
 return y},
 gB:function(a){return this.h3.length
-"30,38"},
+"31,39"},
 "+length":1,
 sB:function(a,b){var z,y,x,w,v,u,t
 z=this.h3
@@ -17099,12 +17124,12 @@
 w=new P.Yp(t)
 w.$builtinTypeInfo=[null]
 this.iH(new G.W4(this,w,t,y,x))}}C.Nm.sB(z,b)
-"40,31,30,38"},
+"41,32,31,39"},
 "+length=":1,
 t:function(a,b){var z=this.h3
 if(b>>>0!==b||b>=z.length)throw H.e(z,b)
 return z[b]
-"107,29,30,38"},
+"109,30,31,39"},
 "+[]:1:0":1,
 u:function(a,b,c){var z,y,x,w
 z=this.h3
@@ -17118,7 +17143,7 @@
 w.$builtinTypeInfo=[null]
 this.iH(new G.W4(this,w,x,b,1))}if(b>=z.length)throw H.e(z,b)
 z[b]=c
-"40,29,30,31,107,38"},
+"41,30,31,32,109,39"},
 "+[]=:2:0":1,
 h:function(a,b){var z,y,x,w
 z=this.h3
@@ -17207,33 +17232,33 @@
 $isHA:true},br:{"":"Pi;Zp,VJ,Ai",
 gvc:function(a){var z=this.Zp
 return z.gvc(z)
-"108,38"},
+"110,39"},
 "+keys":1,
 gUQ:function(a){var z=this.Zp
 return z.gUQ(z)
-"109,38"},
+"111,39"},
 "+values":1,
 gB:function(a){var z=this.Zp
 return z.gB(z)
-"30,38"},
+"31,39"},
 "+length":1,
 gl0:function(a){var z=this.Zp
 return z.gB(z)===0
-"44,38"},
+"46,39"},
 "+isEmpty":1,
 gor:function(a){var z=this.Zp
 return z.gB(z)!==0
-"44,38"},
+"46,39"},
 "+isNotEmpty":1,
 PF:function(a){return this.Zp.PF(a)
-"44,31,0,38"},
+"46,32,0,39"},
 "+containsValue:1:0":1,
 x4:function(a){return this.Zp.x4(a)
-"44,78,0,38"},
+"46,80,0,39"},
 "+containsKey:1:0":1,
 t:function(a,b){var z=this.Zp
 return z.t(z,b)
-"110,78,0,38"},
+"112,80,0,39"},
 "+[]:1:0":1,
 u:function(a,b,c){var z,y,x,w,v
 z=this.Zp
@@ -17250,7 +17275,7 @@
 z.$builtinTypeInfo=[null,null]
 this.SZ(this,z)}else if(!J.xC(x,c)){z=new V.HA(b,x,c,!1,!1)
 z.$builtinTypeInfo=[null,null]
-this.SZ(this,z)}"40,78,111,31,110,38"},
+this.SZ(this,z)}"41,80,113,32,112,39"},
 "+[]=:2:0":1,
 Ay:function(a,b){b.aN(b,new V.zT(this))},
 Rz:function(a,b){var z,y,x,w,v
@@ -17361,7 +17386,7 @@
 z=y==null?z!=null:y!==z}else z=!1
 if(!z)this.ov()
 return C.Nm.grZ(this.kN)
-"40,38"},
+"41,39"},
 "+value":1,
 r6:function(a,b){return this.gP(a).call$1(b)},
 sP:function(a,b){var z,y,x,w
@@ -17379,7 +17404,7 @@
 if(w>=z.length)throw H.e(z,w)
 if(L.h6(x,z[w],b)){z=this.kN
 if(y>=z.length)throw H.e(z,y)
-z[y]=b}"40,106,0,38"},
+z[y]=b}"41,108,0,39"},
 "+value=":1,
 w3:function(a){O.Pi.prototype.w3.call(this,this)
 this.ov()
@@ -18541,7 +18566,7 @@
 y=typeof z==="object"&&z!==null&&!!y.$isEZ}else y=!1}else y=!1
 if(y)return
 return new T.Xy(this,b,z)},
-gca:function(){return new T.Dw(this,T.e9.prototype.yt,null,"yt")},
+gca:function(){return new T.PD(this,T.e9.prototype.yt,null,"yt")},
 A5:function(a){return new T.uK(this)}},Xy:{"":"Tp;a,b,c",
 call$2:function(a,b){var z=J.x(a)
 if(typeof a!=="object"||a===null||!z.$isz6)a=new K.z6(null,a,V.WF(this.a.nF,null,null),null)
@@ -18568,14 +18593,14 @@
 F.Wi(this,C.ls,z,this.uK)},
 gnc:function(){return new H.Pm(this,T.mY.prototype.vr,null,"vr")},
 gP:function(a){return this.uK
-"40,38"},
+"41,39"},
 "+value":1,
 r6:function(a,b){return this.gP(a).call$1(b)},
 sP:function(a,b){var z,y,x,w
 try{K.jX(this.jf,b,this.qc)}catch(y){x=H.Ru(y)
 w=J.x(x)
 if(typeof x==="object"&&x!==null&&!!w.$isB0){z=x
-$.IS().A3("Error evaluating expression '"+H.d(this.jf)+"': "+J.z2(z))}else throw y}"40,112,40,38"},
+$.IS().A3("Error evaluating expression '"+H.d(this.jf)+"': "+J.z2(z))}else throw y}"41,114,41,39"},
 "+value=":1,
 Va:function(a,b,c){var z,y,x,w,v
 y=this.jf
@@ -19037,7 +19062,7 @@
 return 536870911&a+((16383&a)<<15>>>0)},Fq:{"":"a;",
 F2:function(a,b,c){return new U.RW(a,b,c)},
 "+invoke:3:0":0,
-"*invoke":[40],
+"*invoke":[41],
 CI:function(a,b){return this.F2(a,b,null)},
 "+invoke:2:0":0},hw:{"":"a;",$ishw:true},EZ:{"":"hw;",
 RR:function(a,b){return b.W9(this)},
@@ -19331,7 +19356,7 @@
 static:{i0:function(a,b,c){var z=new K.Ae(a,b)
 H.VM(z,[c])
 return z
-"28,29,30,31,32"},"+new IndexedValue:2:0":1}},"+IndexedValue": [0],Bt:{"":"mW;YR",
+"29,30,31,32,33"},"+new IndexedValue:2:0":1}},"+IndexedValue": [0],Bt:{"":"mW;YR",
 gA:function(a){var z=J.GP(this.YR)
 z=new K.vR(z,0,null)
 H.VM(z,[H.W8(this,"Bt",0)])
@@ -19525,15 +19550,15 @@
 C.Cc.ZL(a)
 C.Cc.FH(a)
 return a
-"33"},"+new ResponseViewerElement$created:0:0":1}},"+ResponseViewerElement": [27]}],["script_view_element","package:observatory/src/observatory_elements/script_view.dart",,U,{fI:{"":["V0;Uz%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
+"34"},"+new ResponseViewerElement$created:0:0":1}},"+ResponseViewerElement": [28]}],["script_view_element","package:observatory/src/observatory_elements/script_view.dart",,U,{fI:{"":["V4;Uz%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
 gNl:function(a){return a.Uz
-"37,38,39"},
+"38,39,40"},
 "+script":1,
 sNl:function(a,b){a.Uz=this.pD(a,C.fX,a.Uz,b)
-"40,31,37,38"},
+"41,32,38,39"},
 "+script=":1,
 "@":function(){return[C.Er]},
-static:{Ry:function(a){var z,y,x,w,v
+static:{kL:function(a){var z,y,x,w,v
 z=$.Nd()
 y=P.Py(null,null,null,J.O,W.I0)
 x=J.O
@@ -19546,12 +19571,12 @@
 C.cJ.ZL(a)
 C.cJ.FH(a)
 return a
-"34"},"+new ScriptViewElement$created:0:0":1}},"+ScriptViewElement": [113],V0:{"":"uL+Pi;",$isd3:true}}],["source_view_element","package:observatory/src/observatory_elements/source_view.dart",,X,{kK:{"":["V4;vX%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
+"35"},"+new ScriptViewElement$created:0:0":1}},"+ScriptViewElement": [115],V4:{"":"uL+Pi;",$isd3:true}}],["source_view_element","package:observatory/src/observatory_elements/source_view.dart",,X,{kK:{"":["V6;vX%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
 gFF:function(a){return a.vX
-"114,38,39"},
+"116,39,40"},
 "+source":1,
 sFF:function(a,b){a.vX=this.pD(a,C.hn,a.vX,b)
-"40,31,114,38"},
+"41,32,116,39"},
 "+source=":1,
 "@":function(){return[C.H8]},
 static:{HO:function(a){var z,y,x,w,v
@@ -19567,12 +19592,12 @@
 C.Ks.ZL(a)
 C.Ks.FH(a)
 return a
-"35"},"+new SourceViewElement$created:0:0":1}},"+SourceViewElement": [115],V4:{"":"uL+Pi;",$isd3:true}}],["stack_trace_element","package:observatory/src/observatory_elements/stack_trace.dart",,X,{uw:{"":["V6;V4%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
+"36"},"+new SourceViewElement$created:0:0":1}},"+SourceViewElement": [117],V6:{"":"uL+Pi;",$isd3:true}}],["stack_trace_element","package:observatory/src/observatory_elements/stack_trace.dart",,X,{uw:{"":["V8;V4%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
 gtN:function(a){return a.V4
-"37,38,39"},
+"38,39,40"},
 "+trace":1,
 stN:function(a,b){a.V4=this.pD(a,C.kw,a.V4,b)
-"40,31,37,38"},
+"41,32,38,39"},
 "+trace=":1,
 "@":function(){return[C.js]},
 static:{bV:function(a){var z,y,x,w,v,u
@@ -19591,7 +19616,7 @@
 C.bg.ZL(a)
 C.bg.FH(a)
 return a
-"36"},"+new StackTraceElement$created:0:0":1}},"+StackTraceElement": [116],V6:{"":"uL+Pi;",$isd3:true}}],["template_binding","package:template_binding/template_binding.dart",,M,{IP:function(a){var z=J.RE(a)
+"37"},"+new StackTraceElement$created:0:0":1}},"+StackTraceElement": [118],V8:{"":"uL+Pi;",$isd3:true}}],["template_binding","package:template_binding/template_binding.dart",,M,{IP:function(a){var z=J.RE(a)
 if(typeof a==="object"&&a!==null&&!!z.$isQl)return C.io.f0(a)
 switch(z.gr9(a)){case"checkbox":return $.FF().aM(a)
 case"radio":case"select-multiple":case"select-one":return z.gEr(a)
@@ -20671,6 +20696,7 @@
 if(typeof a!="object")return a
 if(a instanceof P.a)return a
 return J.ks(a)}
+C.J0=B.G6.prototype
 C.OL=new U.EZ()
 C.Gw=new H.SJ()
 C.E3=new J.Q()
@@ -20691,7 +20717,7 @@
 C.YD=F.Be.prototype
 C.j8=R.i6.prototype
 C.Vy=new A.V3("disassembly-entry")
-C.J0=new A.V3("observatory-element")
+C.Br=new A.V3("observatory-element")
 C.Er=new A.V3("script-view")
 C.ht=new A.V3("field-ref")
 C.aM=new A.V3("isolate-summary")
@@ -20703,6 +20729,7 @@
 C.c0=new A.V3("message-viewer")
 C.js=new A.V3("stack-trace")
 C.jF=new A.V3("isolate-list")
+C.PT=new A.V3("breakpoint-list")
 C.KG=new A.V3("navigation-bar")
 C.ay=new A.V3("instance-ref")
 C.Gu=new A.V3("collapsible-content")
@@ -20936,6 +20963,7 @@
 C.PC=new H.GD("dart.core.int")
 C.wt=new H.GD("members")
 C.KY=new H.GD("messageType")
+C.Ry=new H.GD("msg")
 C.YS=new H.GD("name")
 C.OV=new H.GD("noSuchMethod")
 C.Ws=new H.GD("operatingSystem")
@@ -20963,14 +20991,15 @@
 C.Ti=H.mm('wn')
 C.Mt=new H.Lm(C.Ti,"E",0)
 C.Ye=H.mm('hx')
-C.G6=H.mm('F1')
+C.bD=H.mm('F1')
 C.NM=H.mm('Nh')
+C.z7=H.mm('G6')
 C.nY=H.mm('a')
 C.Yc=H.mm('iP')
 C.LN=H.mm('Be')
 C.Qa=H.mm('u7')
 C.xS=H.mm('UZ')
-C.PT=H.mm('CX')
+C.mA=H.mm('CX')
 C.Op=H.mm('G8')
 C.xF=H.mm('NQ')
 C.b4=H.mm('ih')
@@ -21175,8 +21204,8 @@
 J.z2=function(a){return J.RE(a).gG1(a)}
 J.zZ=function(a,b){return J.RE(a).Yv(a,b)}
 J.zj=function(a){return J.RE(a).gvH(a)}
-$.Dq=["Ay","BN","BT","Ba","C","C0","C8","Ch","D","D3","D6","Dh","E","Ec","F","FH","Fr","GB","HG","Hn","Id","Ih","Im","Is","J","J3","JP","JT","JV","Ja","Jk","Kb","LV","Md","Mi","Mu","Nj","Nz","O","On","PM","Pa","Pk","Pv","R3","R4","RB","RR","Rz","SZ","T","T2","TH","TP","TW","Tc","Td","U","UD","UH","UZ","Uc","V","V1","Vr","Vy","W","W3","W4","WO","WZ","Wt","Wz","X6","XG","XU","Xl","Y9","YU","YW","Ys","Yv","Z","Z1","Z2","ZB","ZF","ZL","ZP","Zv","aC","aN","aq","bA","bS","br","bu","cO","cn","d0","dR","dd","du","eR","ea","er","es","ev","ez","f6","fd","fj","fk","fm","g","gA","gB","gBb","gCd","gCj","gDD","gDg","gE8","gEX","gEr","gF1","gFF","gFJ","gFT","gFV","gFe","gG0","gG1","gG3","gGL","gHs","gI","gIi","gJS","gJf","gKE","gKM","gKV","gLA","gLU","gLf","gLm","gM0","gMB","gMj","gN","gNI","gNl","gO3","gP","gP1","gP2","gPp","gPu","gPw","gPy","gQ0","gQG","gQW","gQg","gRn","gRu","gT8","gTM","gTn","gTq","gUQ","gUV","gUz","gV4","gVA","gVB","gVl","gXB","gXf","gXh","gXt","gZw","gai","gbP","gbx","gcC","geT","geb","gey","gfY","ghO","ghf","ghr","gi0","giC","giI","giK","giO","gig","gjL","gjO","gjU","gjb","gk5","gkU","gkc","gkf","gkp","gl0","gl7","glc","gmW","gmm","gn4","goc","gor","gpQ","gpo","gq6","gqC","gqh","gql","gr3","gr9","grK","grZ","gt0","gtD","gtH","gtN","gtT","guD","gvH","gvX","gvc","gvt","gxj","gxr","gyT","gys","gzP","gzZ","gzj","h","h8","hV","hc","i","i4","iA","iM","iw","j","jT","jx","kO","l5","l8","lj","m","mK","mv","n","nB","nC","nH","nP","ni","oB","oW","od","oo","oq","pD","pZ","pl","pr","qZ","r6","rJ","rS","sB","sF1","sFF","sFJ","sFT","sG1","sIt","sLA","sLf","sMj","sNI","sNl","sO3","sP","sP2","sPw","sPy","sQG","sRu","sTn","sTq","sUz","sV4","sVA","sVB","sXB","sXf","sXh","sZw","sa4","sai","scC","seb","sfY","shO","shf","si0","siI","siK","sig","sjO","sk5","skc","skf","sl7","soc","sql","sr9","st0","stD","stH","stN","stT","svX","svt","sxj","sxr","szZ","szj","t","tZ","tg","tt","u","u5","u8","uG","vs","w3","wE","wL","wR","wg","x3","xI","xc","xe","y0","yC","yc","ym","yn","yq","yu","yx","yy","z2","zV"]
-$.Au=[C.Ye,Z.hx,{created:Z.HC},C.G6,V.F1,{created:V.fv},C.NM,L.Nh,{created:L.rJ},C.LN,F.Be,{created:F.Fe},C.Qa,L.u7,{created:L.Tt},C.xS,P.UZ,{},C.PT,M.CX,{created:M.SP},C.Op,P.G8,{},C.xF,Q.NQ,{created:Q.Zo},C.b4,Q.ih,{created:Q.BW},C.Ob,X.kK,{created:X.HO},C.hG,A.ir,{created:A.oa},C.aj,U.fI,{created:U.Ry},C.mo,E.Fv,{created:E.AH},C.xE,Z.aC,{created:Z.zg},C.vuj,X.uw,{created:X.bV},C.j6,D.qr,{created:D.ip},C.C6,Z.vj,{created:Z.un},C.CT,D.St,{created:D.N5},C.Q4,Z.uL,{created:Z.Hx},C.yg,F.I3,{created:F.TW},C.XU,R.i6,{created:R.IT},C.Bm,A.XP,{created:A.XL},C.Wz,B.pR,{created:B.lu},C.mnH,N.Ds,{created:N.p7},C.XK,A.Gk,{created:A.cY}]
+$.Dq=["Ay","BN","BT","Ba","C","C0","C8","Ch","D","D3","D6","Dh","E","Ec","F","FH","Fr","GB","HG","Hn","Id","Ih","Im","Is","J","J3","JP","JT","JV","Ja","Jk","Kb","LV","Md","Mi","Mu","Nj","Nz","O","On","PM","Pa","Pk","Pv","R3","R4","RB","RR","Rz","SZ","T","T2","TH","TP","TW","Tc","Td","U","UD","UH","UZ","Uc","V","V1","Vr","Vy","W","W3","W4","WO","WZ","Wt","Wz","X6","XG","XU","Xl","Y9","YU","YW","Ys","Yv","Z","Z1","Z2","ZB","ZF","ZL","ZP","Zv","aC","aN","aq","bA","bS","br","bu","cO","cn","d0","dR","dd","du","eR","ea","er","es","ev","ez","f6","fd","fj","fk","fm","g","gA","gB","gBb","gCd","gCj","gDD","gDg","gE8","gEX","gEr","gF1","gFF","gFJ","gFT","gFV","gFe","gG0","gG1","gG3","gGL","gHs","gI","gIi","gJS","gJf","gKE","gKM","gKV","gLA","gLU","gLf","gLm","gM0","gMB","gMj","gN","gNI","gNl","gO3","gP","gP1","gP2","gPp","gPu","gPw","gPy","gQ0","gQG","gQW","gQg","gRn","gRu","gT8","gTM","gTn","gTq","gUQ","gUV","gUz","gV4","gVA","gVB","gVl","gXB","gXf","gXh","gXt","gZw","gai","gbP","gbx","gcC","geE","geT","geb","gey","gfY","ghO","ghf","ghr","gi0","giC","giI","giK","giO","gig","gjL","gjO","gjU","gjb","gk5","gkU","gkc","gkf","gkp","gl0","gl7","glc","gmW","gmm","gn4","goc","gor","gpQ","gpo","gq6","gqC","gqh","gql","gr3","gr9","grK","grZ","grs","gt0","gtD","gtH","gtN","gtT","guD","gvH","gvX","gvc","gvt","gxj","gxr","gyT","gys","gzP","gzZ","gzj","h","h8","hV","hc","i","i4","iA","iM","iw","j","jT","jx","kO","l5","l8","lj","m","mK","mv","n","nB","nC","nH","nP","ni","oB","oW","od","oo","oq","pD","pZ","pl","pr","qZ","r6","rJ","rS","sB","sF1","sFF","sFJ","sFT","sG1","sIt","sLA","sLf","sMj","sNI","sNl","sO3","sP","sP2","sPw","sPy","sQG","sRu","sTn","sTq","sUz","sV4","sVA","sVB","sXB","sXf","sXh","sZw","sa4","sai","scC","seE","seb","sfY","shO","shf","si0","siI","siK","sig","sjO","sk5","skc","skf","sl7","soc","sql","sr9","srs","st0","stD","stH","stN","stT","svX","svt","sxj","sxr","szZ","szj","t","tZ","tg","tt","u","u5","u8","uG","vs","w3","wE","wL","wR","wg","x3","xI","xc","xe","y0","yC","yc","ym","yn","yq","yu","yx","yy","z2","zV"]
+$.Au=[C.Ye,Z.hx,{created:Z.HC},C.bD,V.F1,{created:V.fv},C.NM,L.Nh,{created:L.rJ},C.z7,B.G6,{created:B.Dw},C.LN,F.Be,{created:F.Fe},C.Qa,L.u7,{created:L.Tt},C.xS,P.UZ,{},C.mA,M.CX,{created:M.SP},C.Op,P.G8,{},C.xF,Q.NQ,{created:Q.Zo},C.b4,Q.ih,{created:Q.BW},C.Ob,X.kK,{created:X.HO},C.hG,A.ir,{created:A.oa},C.aj,U.fI,{created:U.kL},C.mo,E.Fv,{created:E.AH},C.xE,Z.aC,{created:Z.zg},C.vuj,X.uw,{created:X.bV},C.j6,D.qr,{created:D.ip},C.C6,Z.vj,{created:Z.un},C.CT,D.St,{created:D.N5},C.Q4,Z.uL,{created:Z.Hx},C.yg,F.I3,{created:F.TW},C.XU,R.i6,{created:R.IT},C.Bm,A.XP,{created:A.XL},C.Wz,B.pR,{created:B.lu},C.mnH,N.Ds,{created:N.p7},C.XK,A.Gk,{created:A.cY}]
 I.$lazy($,"globalThis","DX","jk",function(){return function() { return this; }()})
 I.$lazy($,"globalWindow","pG","Qm",function(){return $.jk().window})
 I.$lazy($,"globalWorker","zA","Nl",function(){return $.jk().Worker})
@@ -21276,7 +21305,7 @@
 return z})
 
 init.functionAliases={}
-init.metadata=[P.a,C.wK,C.wa,C.WX,C.Mt,C.wW,P.uq,"name",J.O,Z.aC,F.Be,R.i6,W.K5,E.Fv,F.I3,D.qr,A.Gk,N.Ds,B.pR,Z.hx,L.u7,D.St,Z.vj,M.CX,L.Nh,Q.ih,V.F1,Z.uL,[K.Ae,3],"index",J.im,"value",3,Q.NQ,U.fI,X.kK,X.uw,P.L8,C.nJ,C.Us,,Z.Vf,F.tu,C.mI,J.kn,"r","e",W.ea,"detail","target",W.KV,R.Vc,[P.L8,P.wv,P.RS],[J.Q,H.Zk],"methodOwner",P.NL,[J.Q,P.RY],"fieldOwner",[P.L8,P.wv,P.RY],[P.L8,P.wv,P.QF],[P.L8,P.wv,P.NL],P.vr,"fieldName",P.wv,"arg",H.Uz,[J.Q,P.vr],P.Ms,"memberName","positionalArguments",J.Q,"namedArguments",[P.L8,P.wv,null],[J.Q,P.Ms],"owner",[J.Q,P.Fw],[J.Q,P.L9u],H.Un,"key",P.QF,H.Tp,"tv","i",E.WZ,F.pv,D.Vfx,A.Dsd,N.tuj,B.Vct,Z.D13,D.WZq,"oldValue",Z.pva,M.cda,"m",[J.Q,P.L8],P.iD,"l","objectId","cid","isolateId",[J.Q,L.Zw],V.waa,L.mL,Z.Nr,5,"newValue",4,[P.cX,1],[P.cX,2],2,1,"v",U.V0,L.Pf,X.V4,X.V6,];$=null
+init.metadata=[P.a,C.wK,C.wa,C.WX,C.Mt,C.wW,P.uq,"name",J.O,B.G6,Z.aC,F.Be,R.i6,W.K5,E.Fv,F.I3,D.qr,A.Gk,N.Ds,B.pR,Z.hx,L.u7,D.St,Z.vj,M.CX,L.Nh,Q.ih,V.F1,Z.uL,[K.Ae,3],"index",J.im,"value",3,Q.NQ,U.fI,X.kK,X.uw,P.L8,C.nJ,C.Us,,B.Vf,Z.tu,F.Vc,C.mI,J.kn,"r","e",W.ea,"detail","target",W.KV,R.WZ,[P.L8,P.wv,P.RS],[J.Q,H.Zk],"methodOwner",P.NL,[J.Q,P.RY],"fieldOwner",[P.L8,P.wv,P.RY],[P.L8,P.wv,P.QF],[P.L8,P.wv,P.NL],P.vr,"fieldName",P.wv,"arg",H.Uz,[J.Q,P.vr],P.Ms,"memberName","positionalArguments",J.Q,"namedArguments",[P.L8,P.wv,null],[J.Q,P.Ms],"owner",[J.Q,P.Fw],[J.Q,P.L9u],H.Un,"key",P.QF,H.Tp,"tv","i",E.pv,F.Vfx,D.Dsd,A.tuj,N.Vct,B.D13,Z.WZq,D.pva,"oldValue",Z.cda,M.waa,"m",[J.Q,P.L8],P.iD,"l","objectId","cid","isolateId",[J.Q,L.Zw],V.V0,L.mL,Z.Nr,5,"newValue",4,[P.cX,1],[P.cX,2],2,1,"v",U.V4,L.Pf,X.V6,X.V8,];$=null
 I = I.$finishIsolateConstructor(I)
 $=new I()
 function convertToFastObject(properties) {
@@ -23577,6 +23606,35 @@
 $desc=$collectedClasses.tQ
 if($desc instanceof Array)$desc=$desc[1]
 tQ.prototype=$desc
+function G6(eE,VJ,Ai,tH,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM){this.eE=eE
+this.VJ=VJ
+this.Ai=Ai
+this.tH=tH
+this.VJ=VJ
+this.Ai=Ai
+this.VJ=VJ
+this.Ai=Ai
+this.ZI=ZI
+this.uN=uN
+this.z3=z3
+this.TQ=TQ
+this.Vk=Vk
+this.Ye=Ye
+this.mT=mT
+this.KM=KM}G6.builtin$cls="G6"
+if(!"name" in G6)G6.name="G6"
+$desc=$collectedClasses.G6
+if($desc instanceof Array)$desc=$desc[1]
+G6.prototype=$desc
+G6.prototype.geE=function(receiver){return receiver.eE}
+G6.prototype.geE.$reflectable=1
+G6.prototype.seE=function(receiver,v){return receiver.eE=v}
+G6.prototype.seE.$reflectable=1
+function Vf(){}Vf.builtin$cls="Vf"
+if(!"name" in Vf)Vf.name="Vf"
+$desc=$collectedClasses.Vf
+if($desc instanceof Array)$desc=$desc[1]
+Vf.prototype=$desc
 function aC(FJ,VJ,Ai,tH,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM){this.FJ=FJ
 this.VJ=VJ
 this.Ai=Ai
@@ -23601,11 +23659,11 @@
 aC.prototype.gFJ.$reflectable=1
 aC.prototype.sFJ=function(receiver,v){return receiver.FJ=v}
 aC.prototype.sFJ.$reflectable=1
-function Vf(){}Vf.builtin$cls="Vf"
-if(!"name" in Vf)Vf.name="Vf"
-$desc=$collectedClasses.Vf
+function tu(){}tu.builtin$cls="tu"
+if(!"name" in tu)tu.name="tu"
+$desc=$collectedClasses.tu
 if($desc instanceof Array)$desc=$desc[1]
-Vf.prototype=$desc
+tu.prototype=$desc
 function Be(Zw,VJ,Ai,tH,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM){this.Zw=Zw
 this.VJ=VJ
 this.Ai=Ai
@@ -23630,11 +23688,11 @@
 Be.prototype.gZw.$reflectable=1
 Be.prototype.sZw=function(receiver,v){return receiver.Zw=v}
 Be.prototype.sZw.$reflectable=1
-function tu(){}tu.builtin$cls="tu"
-if(!"name" in tu)tu.name="tu"
-$desc=$collectedClasses.tu
+function Vc(){}Vc.builtin$cls="Vc"
+if(!"name" in Vc)Vc.name="Vc"
+$desc=$collectedClasses.Vc
 if($desc instanceof Array)$desc=$desc[1]
-tu.prototype=$desc
+Vc.prototype=$desc
 function i6(Xf,VA,P2,VJ,Ai,tH,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM){this.Xf=Xf
 this.VA=VA
 this.P2=P2
@@ -23669,11 +23727,11 @@
 i6.prototype.gP2.$reflectable=1
 i6.prototype.sP2=function(receiver,v){return receiver.P2=v}
 i6.prototype.sP2.$reflectable=1
-function Vc(){}Vc.builtin$cls="Vc"
-if(!"name" in Vc)Vc.name="Vc"
-$desc=$collectedClasses.Vc
+function WZ(){}WZ.builtin$cls="WZ"
+if(!"name" in WZ)WZ.name="WZ"
+$desc=$collectedClasses.WZ
 if($desc instanceof Array)$desc=$desc[1]
-Vc.prototype=$desc
+WZ.prototype=$desc
 function zO(){}zO.builtin$cls="zO"
 if(!"name" in zO)zO.name="zO"
 $desc=$collectedClasses.zO
@@ -26130,11 +26188,11 @@
 Fv.prototype.gFT.$reflectable=1
 Fv.prototype.sFT=function(receiver,v){return receiver.FT=v}
 Fv.prototype.sFT.$reflectable=1
-function WZ(){}WZ.builtin$cls="WZ"
-if(!"name" in WZ)WZ.name="WZ"
-$desc=$collectedClasses.WZ
+function pv(){}pv.builtin$cls="pv"
+if(!"name" in pv)pv.name="pv"
+$desc=$collectedClasses.pv
 if($desc instanceof Array)$desc=$desc[1]
-WZ.prototype=$desc
+pv.prototype=$desc
 function I3(Py,hO,VJ,Ai,tH,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM){this.Py=Py
 this.hO=hO
 this.VJ=VJ
@@ -26164,11 +26222,11 @@
 I3.prototype.ghO.$reflectable=1
 I3.prototype.shO=function(receiver,v){return receiver.hO=v}
 I3.prototype.shO.$reflectable=1
-function pv(){}pv.builtin$cls="pv"
-if(!"name" in pv)pv.name="pv"
-$desc=$collectedClasses.pv
+function Vfx(){}Vfx.builtin$cls="Vfx"
+if(!"name" in Vfx)Vfx.name="Vfx"
+$desc=$collectedClasses.Vfx
 if($desc instanceof Array)$desc=$desc[1]
-pv.prototype=$desc
+Vfx.prototype=$desc
 function qr(Lf,VJ,Ai,tH,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM){this.Lf=Lf
 this.VJ=VJ
 this.Ai=Ai
@@ -26193,11 +26251,11 @@
 qr.prototype.gLf.$reflectable=1
 qr.prototype.sLf=function(receiver,v){return receiver.Lf=v}
 qr.prototype.sLf.$reflectable=1
-function Vfx(){}Vfx.builtin$cls="Vfx"
-if(!"name" in Vfx)Vfx.name="Vfx"
-$desc=$collectedClasses.Vfx
+function Dsd(){}Dsd.builtin$cls="Dsd"
+if(!"name" in Dsd)Dsd.name="Dsd"
+$desc=$collectedClasses.Dsd
 if($desc instanceof Array)$desc=$desc[1]
-Vfx.prototype=$desc
+Dsd.prototype=$desc
 function Gk(vt,VJ,Ai,tH,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM){this.vt=vt
 this.VJ=VJ
 this.Ai=Ai
@@ -26222,11 +26280,11 @@
 Gk.prototype.gvt.$reflectable=1
 Gk.prototype.svt=function(receiver,v){return receiver.vt=v}
 Gk.prototype.svt.$reflectable=1
-function Dsd(){}Dsd.builtin$cls="Dsd"
-if(!"name" in Dsd)Dsd.name="Dsd"
-$desc=$collectedClasses.Dsd
+function tuj(){}tuj.builtin$cls="tuj"
+if(!"name" in tuj)tuj.name="tuj"
+$desc=$collectedClasses.tuj
 if($desc instanceof Array)$desc=$desc[1]
-Dsd.prototype=$desc
+tuj.prototype=$desc
 function Ds(ql,VJ,Ai,tH,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM){this.ql=ql
 this.VJ=VJ
 this.Ai=Ai
@@ -26251,11 +26309,11 @@
 Ds.prototype.gql.$reflectable=1
 Ds.prototype.sql=function(receiver,v){return receiver.ql=v}
 Ds.prototype.sql.$reflectable=1
-function tuj(){}tuj.builtin$cls="tuj"
-if(!"name" in tuj)tuj.name="tuj"
-$desc=$collectedClasses.tuj
+function Vct(){}Vct.builtin$cls="Vct"
+if(!"name" in Vct)Vct.name="Vct"
+$desc=$collectedClasses.Vct
 if($desc instanceof Array)$desc=$desc[1]
-tuj.prototype=$desc
+Vct.prototype=$desc
 function aI(b,c){this.b=b
 this.c=c}aI.builtin$cls="aI"
 if(!"name" in aI)aI.name="aI"
@@ -26348,11 +26406,11 @@
 pR.prototype.giK.$reflectable=1
 pR.prototype.siK=function(receiver,v){return receiver.iK=v}
 pR.prototype.siK.$reflectable=1
-function Vct(){}Vct.builtin$cls="Vct"
-if(!"name" in Vct)Vct.name="Vct"
-$desc=$collectedClasses.Vct
+function D13(){}D13.builtin$cls="D13"
+if(!"name" in D13)D13.name="D13"
+$desc=$collectedClasses.D13
 if($desc instanceof Array)$desc=$desc[1]
-Vct.prototype=$desc
+D13.prototype=$desc
 function hx(Xh,VJ,Ai,tH,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM){this.Xh=Xh
 this.VJ=VJ
 this.Ai=Ai
@@ -26377,11 +26435,11 @@
 hx.prototype.gXh.$reflectable=1
 hx.prototype.sXh=function(receiver,v){return receiver.Xh=v}
 hx.prototype.sXh.$reflectable=1
-function D13(){}D13.builtin$cls="D13"
-if(!"name" in D13)D13.name="D13"
-$desc=$collectedClasses.D13
+function WZq(){}WZq.builtin$cls="WZq"
+if(!"name" in WZq)WZq.name="WZq"
+$desc=$collectedClasses.WZq
 if($desc instanceof Array)$desc=$desc[1]
-D13.prototype=$desc
+WZq.prototype=$desc
 function u7(tH,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM){this.tH=tH
 this.VJ=VJ
 this.Ai=Ai
@@ -26428,11 +26486,11 @@
 St.prototype.gi0.$reflectable=1
 St.prototype.si0=function(receiver,v){return receiver.i0=v}
 St.prototype.si0.$reflectable=1
-function WZq(){}WZq.builtin$cls="WZq"
-if(!"name" in WZq)WZq.name="WZq"
-$desc=$collectedClasses.WZq
+function pva(){}pva.builtin$cls="pva"
+if(!"name" in pva)pva.name="pva"
+$desc=$collectedClasses.pva
 if($desc instanceof Array)$desc=$desc[1]
-WZq.prototype=$desc
+pva.prototype=$desc
 function vj(eb,kf,VJ,Ai,tH,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM){this.eb=eb
 this.kf=kf
 this.VJ=VJ
@@ -26462,11 +26520,11 @@
 vj.prototype.gkf.$reflectable=1
 vj.prototype.skf=function(receiver,v){return receiver.kf=v}
 vj.prototype.skf.$reflectable=1
-function pva(){}pva.builtin$cls="pva"
-if(!"name" in pva)pva.name="pva"
-$desc=$collectedClasses.pva
+function cda(){}cda.builtin$cls="cda"
+if(!"name" in cda)cda.name="cda"
+$desc=$collectedClasses.cda
 if($desc instanceof Array)$desc=$desc[1]
-pva.prototype=$desc
+cda.prototype=$desc
 function CX(iI,VJ,Ai,tH,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM){this.iI=iI
 this.VJ=VJ
 this.Ai=Ai
@@ -26491,11 +26549,11 @@
 CX.prototype.giI.$reflectable=1
 CX.prototype.siI=function(receiver,v){return receiver.iI=v}
 CX.prototype.siI.$reflectable=1
-function cda(){}cda.builtin$cls="cda"
-if(!"name" in cda)cda.name="cda"
-$desc=$collectedClasses.cda
+function waa(){}waa.builtin$cls="waa"
+if(!"name" in waa)waa.name="waa"
+$desc=$collectedClasses.waa
 if($desc instanceof Array)$desc=$desc[1]
-cda.prototype=$desc
+waa.prototype=$desc
 function TJ(oc,eT,yz,Cj,wd,Gs){this.oc=oc
 this.eT=eT
 this.yz=yz
@@ -26783,11 +26841,11 @@
 F1.prototype.gk5.$reflectable=1
 F1.prototype.sk5=function(receiver,v){return receiver.k5=v}
 F1.prototype.sk5.$reflectable=1
-function waa(){}waa.builtin$cls="waa"
-if(!"name" in waa)waa.name="waa"
-$desc=$collectedClasses.waa
+function V0(){}V0.builtin$cls="V0"
+if(!"name" in V0)V0.name="V0"
+$desc=$collectedClasses.V0
 if($desc instanceof Array)$desc=$desc[1]
-waa.prototype=$desc
+V0.prototype=$desc
 function uL(tH,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM){this.tH=tH
 this.VJ=VJ
 this.Ai=Ai
@@ -27397,13 +27455,13 @@
 $desc=$collectedClasses.e9
 if($desc instanceof Array)$desc=$desc[1]
 e9.prototype=$desc
-function Dw(wc,nn,lv,Pp){this.wc=wc
+function PD(wc,nn,lv,Pp){this.wc=wc
 this.nn=nn
 this.lv=lv
-this.Pp=Pp}Dw.builtin$cls="Dw"
-$desc=$collectedClasses.Dw
+this.Pp=Pp}PD.builtin$cls="PD"
+$desc=$collectedClasses.PD
 if($desc instanceof Array)$desc=$desc[1]
-Dw.prototype=$desc
+PD.prototype=$desc
 function Xy(a,b,c){this.a=a
 this.b=b
 this.c=c}Xy.builtin$cls="Xy"
@@ -27938,11 +27996,11 @@
 fI.prototype.gUz.$reflectable=1
 fI.prototype.sUz=function(receiver,v){return receiver.Uz=v}
 fI.prototype.sUz.$reflectable=1
-function V0(){}V0.builtin$cls="V0"
-if(!"name" in V0)V0.name="V0"
-$desc=$collectedClasses.V0
+function V4(){}V4.builtin$cls="V4"
+if(!"name" in V4)V4.name="V4"
+$desc=$collectedClasses.V4
 if($desc instanceof Array)$desc=$desc[1]
-V0.prototype=$desc
+V4.prototype=$desc
 function kK(vX,VJ,Ai,tH,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM){this.vX=vX
 this.VJ=VJ
 this.Ai=Ai
@@ -27967,11 +28025,11 @@
 kK.prototype.gvX.$reflectable=1
 kK.prototype.svX=function(receiver,v){return receiver.vX=v}
 kK.prototype.svX.$reflectable=1
-function V4(){}V4.builtin$cls="V4"
-if(!"name" in V4)V4.name="V4"
-$desc=$collectedClasses.V4
+function V6(){}V6.builtin$cls="V6"
+if(!"name" in V6)V6.name="V6"
+$desc=$collectedClasses.V6
 if($desc instanceof Array)$desc=$desc[1]
-V4.prototype=$desc
+V6.prototype=$desc
 function uw(V4,VJ,Ai,tH,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM){this.V4=V4
 this.VJ=VJ
 this.Ai=Ai
@@ -27996,11 +28054,11 @@
 uw.prototype.gV4.$reflectable=1
 uw.prototype.sV4=function(receiver,v){return receiver.V4=v}
 uw.prototype.sV4.$reflectable=1
-function V6(){}V6.builtin$cls="V6"
-if(!"name" in V6)V6.name="V6"
-$desc=$collectedClasses.V6
+function V8(){}V8.builtin$cls="V8"
+if(!"name" in V8)V8.name="V8"
+$desc=$collectedClasses.V8
 if($desc instanceof Array)$desc=$desc[1]
-V6.prototype=$desc
+V8.prototype=$desc
 function V2(N1,bn,Ck){this.N1=N1
 this.bn=bn
 this.Ck=Ck}V2.builtin$cls="V2"
@@ -28338,4 +28396,4 @@
 $desc=$collectedClasses.PW
 if($desc instanceof Array)$desc=$desc[1]
 PW.prototype=$desc
-return[qE,Yy,Ps,rK,fY,Mr,zx,ct,nB,i3,it,Az,QP,QW,n6,Ny,OM,QQ,MA,y4,d7,na,oJ,DG,mN,vH,hh,Em,Sb,rV,Wy,YN,bA,Wq,rv,BK,wj,cv,Fs,SX,ea,D0,as,T5,Aa,u5,Yu,iG,jP,U2,tA,xn,Vb,QH,ST,X2,fJ,Vi,tX,Sg,pA,Mi,Gt,In,Gx,eP,AL,Og,cS,M6,El,zm,SV,aB,ku,KM,cW,DK,qm,ZY,cx,la,Vn,PG,xe,Hw,bn,Im,oB,Aj,oU,qT,KV,BH,mh,G7,wq,Ql,Xp,bP,mX,SN,HD,ni,p3,qj,qW,KR,ew,fs,bX,BL,MC,Mx,j2,yz,lp,pD,I0,QR,Cp,ua,zD,Ul,G0,wb,fq,h4,qk,GI,Tb,tV,BT,yY,kJ,AE,xV,FH,y6,RH,pU,Lq,Mf,BR,r4,aG,J6,K5,UM,UL,rq,nK,kc,ij,ty,Nf,Nc,rj,rh,Zv,Q7,hF,OF,HB,ZJ,mU,eZ,Fl,y5,nV,Zc,ui,D6,DQ,Sm,dx,es,eG,lv,pf,NV,W1,zo,wf,TU,bb,VE,lc,Xu,qM,tk,me,qN,nh,d4,MI,ca,xX,eW,um,Fu,OE,l6,BA,zp,rE,CC,PQ,uz,Yd,U0,AD,Gr,tc,GH,lo,NJ,nd,vt,rQ,EU,LR,MB,hy,r8,aS,CG,qF,MT,Rk,Eo,Dn,UD,ZD,NE,wD,BD,vRT,Fi,Qr,mj,cB,uY,yR,AX,xJ,l4,Et,NC,nb,By,xt,tG,P0,Jq,Xr,qD,Cf,I2,AS,Kq,oI,mJ,rF,vi,ZX,ycx,nE,zt,F0,Lt,Gv,kn,PE,QI,FP,is,Q,jx,ZC,Jt,P,im,Pp,O,PK,JO,O2,aX,cC,RA,IY,JH,jl,Iy,JM,Ua,JG,ns,wd,TA,YP,yc,I9,Bj,NO,II,aJ,X1,HU,Pm,oo,OW,Dd,AP,yH,FA,Av,oH,LP,c2,WT,p8,XR,LI,A2,F3,u8,Gi,t2,Zr,ZQ,az,vV,Hk,XO,dr,TL,KX,uZ,OQ,Tp,v,Z3,D2,GT,Pe,Eq,cu,Lm,dC,wN,VX,VR,EK,KW,Pb,tQ,aC,Vf,Be,tu,i6,Vc,zO,aL,nH,a7,i1,xy,MH,A8,U5,SO,zs,rR,AM,d5,U1,SJ,SU,Tv,XC,iK,GD,Sn,nI,jU,Lj,mb,am,cw,EE,Uz,uh,Kv,oP,YX,BI,y1,M2,iu,mg,zE,bl,Ef,Oo,Tc,Ax,Wf,Un,Ei,U7,t0,Ld,Sz,Zk,fu,ng,Ar,jB,ye,Gj,Zz,Xh,Ca,Ik,JI,Ip,WV,C7,CQ,dz,tK,OR,Bg,DL,b8,j7,oV,TP,Zf,vs,da,xw,dm,rH,ZL,mi,jb,wB,Pu,qh,QC,Yl,Rv,YJ,jv,LB,DO,lz,Rl,Jb,M4,Jp,h7,pr,eN,B5,PI,j4,i9,VV,Dy,lU,xp,UH,Z5,ii,ib,MO,ms,UO,Bc,vp,lk,Gh,XB,ly,cK,O9,yU,nP,KA,Vo,qB,ez,lx,LV,DS,dp,B3,CR,ny,dR,uR,QX,YR,fB,bq,nO,t3,dq,dX,aY,wJ,e4,JB,Id,fZ,TF,Xz,Cg,Hs,uo,pK,eM,Ue,W5,R8,k6,oi,ce,o2,jG,fG,EQ,YB,iX,ou,S9,ey,xd,v6,db,Cm,N6,jg,YO,oz,b6,ef,zQ,Yp,u3,mW,ar,lD,W0,Sw,o0,a1,jp,Xt,Ba,An,LD,YI,OG,ro,DN,ZM,HW,JC,f1,Uk,wI,ob,Ud,K8,by,dI,QM,Sh,tF,z0,Vx,Rw,GY,jZ,h0,CL,uA,a2,fR,iP,MF,Rq,Hn,Zl,pl,a6,P7,DW,Ge,LK,AT,bJ,mp,ub,ds,lj,UV,VS,t7,HG,aE,kM,EH,cX,eL,L8,c8,a,Od,mE,WU,Rn,wv,uq,iD,hb,XX,Kd,yZ,Gs,pm,Tw,wm,FB,Lk,XZ,qz,hQ,Nw,kZ,JT,d9,rI,dD,QZ,BV,E1,wz,B1,M5,Jn,DM,zL,ec,Kx,iO,bU,e7,nj,rl,RAp,ma,cf,E9,nF,FK,Si,vf,Fc,hD,I4,e0,RO,eu,ie,Ea,pu,i2,b0,Ov,qO,RX,kG,Gm,W9,vZ,dW,PA,H2,O7,HI,E4,r7,Tz,Wk,DV,Hp,Nz,Jd,QS,QF,NL,vr,D4,L9u,Ms,Fw,RS,RY,Ys,vg,xG,Vj,VW,RK,DH,ZK,Th,Vju,KB,RKu,xGn,TkQ,VWk,ZKG,DHb,w6W,Hna,z9g,G8,UZ,Fv,WZ,I3,pv,qr,Vfx,Gk,Dsd,Ds,tuj,aI,rG,yh,wO,Tm,rz,CA,YL,KC,xL,As,GE,pR,Vct,hx,D13,u7,St,WZq,vj,pva,CX,cda,TJ,dG,Ng,HV,Nh,fA,tz,jR,PO,c5,ih,mL,bv,pt,Zd,dY,vY,dS,ZW,dZ,Qe,Nu,pF,Ha,nu,be,Pg,jI,Rb,Zw,Pf,F1,waa,uL,Nr,Pi,yj,qI,J3,E5,o5,b5,zI,Zb,id,iV,W4,Fa,x9,d3,X6,xh,wn,uF,cj,HA,br,zT,D7,qL,C4,l9,lP,km,Qt,Dk,A0,rm,eY,OO,BE,Qb,xI,q1,Zj,XP,q6,CK,BO,ZG,Oc,MX,w12,fTP,yL,dM,Y7,WC,Xi,TV,Mq,Oa,n1,xf,L6,Rs,uJ,hm,Ji,Bf,ir,Sa,GN,k8,HJ,S0,V3,Bl,pM,Mh,Md,Lf,fT,pp,Nq,nl,mf,ej,HK,w13,o8,GL,e9,Dw,Xy,uK,mY,fE,mB,XF,iH,wJY,zOQ,W6o,MdQ,YJG,DOe,lPa,Ufa,Raa,w0,w4,w5,w7,w9,w10,w11,c4,z6,Ay,Ed,G1,Os,Dl,Wh,x5,ev,ID,jV,ek,OC,Xm,Jy,ky,fa,WW,vQ,a9,jh,e3,VA,J1,fk,wL,B0,Fq,hw,EZ,no,kB,ae,Iq,w6,jK,uk,K9,RW,xs,FX,Ae,Bt,vR,Pn,hc,hA,fr,a0,NQ,fI,V0,kK,V4,uw,V6,V2,D8,jY,ll,Uf,ik,LfS,NP,Vh,r0,jz,SA,zV,nv,ee,XI,hs,yp,ug,DT,OB,Ra,N9,NW,HS,TG,ts,Kj,VU,Ya,XT,ic,VT,T4,TR,VD,Oh,zy,Nb,Fy,eU,ADW,Ri,kq,Ag,PW]}
\ No newline at end of file
+return[qE,Yy,Ps,rK,fY,Mr,zx,ct,nB,i3,it,Az,QP,QW,n6,Ny,OM,QQ,MA,y4,d7,na,oJ,DG,mN,vH,hh,Em,Sb,rV,Wy,YN,bA,Wq,rv,BK,wj,cv,Fs,SX,ea,D0,as,T5,Aa,u5,Yu,iG,jP,U2,tA,xn,Vb,QH,ST,X2,fJ,Vi,tX,Sg,pA,Mi,Gt,In,Gx,eP,AL,Og,cS,M6,El,zm,SV,aB,ku,KM,cW,DK,qm,ZY,cx,la,Vn,PG,xe,Hw,bn,Im,oB,Aj,oU,qT,KV,BH,mh,G7,wq,Ql,Xp,bP,mX,SN,HD,ni,p3,qj,qW,KR,ew,fs,bX,BL,MC,Mx,j2,yz,lp,pD,I0,QR,Cp,ua,zD,Ul,G0,wb,fq,h4,qk,GI,Tb,tV,BT,yY,kJ,AE,xV,FH,y6,RH,pU,Lq,Mf,BR,r4,aG,J6,K5,UM,UL,rq,nK,kc,ij,ty,Nf,Nc,rj,rh,Zv,Q7,hF,OF,HB,ZJ,mU,eZ,Fl,y5,nV,Zc,ui,D6,DQ,Sm,dx,es,eG,lv,pf,NV,W1,zo,wf,TU,bb,VE,lc,Xu,qM,tk,me,qN,nh,d4,MI,ca,xX,eW,um,Fu,OE,l6,BA,zp,rE,CC,PQ,uz,Yd,U0,AD,Gr,tc,GH,lo,NJ,nd,vt,rQ,EU,LR,MB,hy,r8,aS,CG,qF,MT,Rk,Eo,Dn,UD,ZD,NE,wD,BD,vRT,Fi,Qr,mj,cB,uY,yR,AX,xJ,l4,Et,NC,nb,By,xt,tG,P0,Jq,Xr,qD,Cf,I2,AS,Kq,oI,mJ,rF,vi,ZX,ycx,nE,zt,F0,Lt,Gv,kn,PE,QI,FP,is,Q,jx,ZC,Jt,P,im,Pp,O,PK,JO,O2,aX,cC,RA,IY,JH,jl,Iy,JM,Ua,JG,ns,wd,TA,YP,yc,I9,Bj,NO,II,aJ,X1,HU,Pm,oo,OW,Dd,AP,yH,FA,Av,oH,LP,c2,WT,p8,XR,LI,A2,F3,u8,Gi,t2,Zr,ZQ,az,vV,Hk,XO,dr,TL,KX,uZ,OQ,Tp,v,Z3,D2,GT,Pe,Eq,cu,Lm,dC,wN,VX,VR,EK,KW,Pb,tQ,G6,Vf,aC,tu,Be,Vc,i6,WZ,zO,aL,nH,a7,i1,xy,MH,A8,U5,SO,zs,rR,AM,d5,U1,SJ,SU,Tv,XC,iK,GD,Sn,nI,jU,Lj,mb,am,cw,EE,Uz,uh,Kv,oP,YX,BI,y1,M2,iu,mg,zE,bl,Ef,Oo,Tc,Ax,Wf,Un,Ei,U7,t0,Ld,Sz,Zk,fu,ng,Ar,jB,ye,Gj,Zz,Xh,Ca,Ik,JI,Ip,WV,C7,CQ,dz,tK,OR,Bg,DL,b8,j7,oV,TP,Zf,vs,da,xw,dm,rH,ZL,mi,jb,wB,Pu,qh,QC,Yl,Rv,YJ,jv,LB,DO,lz,Rl,Jb,M4,Jp,h7,pr,eN,B5,PI,j4,i9,VV,Dy,lU,xp,UH,Z5,ii,ib,MO,ms,UO,Bc,vp,lk,Gh,XB,ly,cK,O9,yU,nP,KA,Vo,qB,ez,lx,LV,DS,dp,B3,CR,ny,dR,uR,QX,YR,fB,bq,nO,t3,dq,dX,aY,wJ,e4,JB,Id,fZ,TF,Xz,Cg,Hs,uo,pK,eM,Ue,W5,R8,k6,oi,ce,o2,jG,fG,EQ,YB,iX,ou,S9,ey,xd,v6,db,Cm,N6,jg,YO,oz,b6,ef,zQ,Yp,u3,mW,ar,lD,W0,Sw,o0,a1,jp,Xt,Ba,An,LD,YI,OG,ro,DN,ZM,HW,JC,f1,Uk,wI,ob,Ud,K8,by,dI,QM,Sh,tF,z0,Vx,Rw,GY,jZ,h0,CL,uA,a2,fR,iP,MF,Rq,Hn,Zl,pl,a6,P7,DW,Ge,LK,AT,bJ,mp,ub,ds,lj,UV,VS,t7,HG,aE,kM,EH,cX,eL,L8,c8,a,Od,mE,WU,Rn,wv,uq,iD,hb,XX,Kd,yZ,Gs,pm,Tw,wm,FB,Lk,XZ,qz,hQ,Nw,kZ,JT,d9,rI,dD,QZ,BV,E1,wz,B1,M5,Jn,DM,zL,ec,Kx,iO,bU,e7,nj,rl,RAp,ma,cf,E9,nF,FK,Si,vf,Fc,hD,I4,e0,RO,eu,ie,Ea,pu,i2,b0,Ov,qO,RX,kG,Gm,W9,vZ,dW,PA,H2,O7,HI,E4,r7,Tz,Wk,DV,Hp,Nz,Jd,QS,QF,NL,vr,D4,L9u,Ms,Fw,RS,RY,Ys,vg,xG,Vj,VW,RK,DH,ZK,Th,Vju,KB,RKu,xGn,TkQ,VWk,ZKG,DHb,w6W,Hna,z9g,G8,UZ,Fv,pv,I3,Vfx,qr,Dsd,Gk,tuj,Ds,Vct,aI,rG,yh,wO,Tm,rz,CA,YL,KC,xL,As,GE,pR,D13,hx,WZq,u7,St,pva,vj,cda,CX,waa,TJ,dG,Ng,HV,Nh,fA,tz,jR,PO,c5,ih,mL,bv,pt,Zd,dY,vY,dS,ZW,dZ,Qe,Nu,pF,Ha,nu,be,Pg,jI,Rb,Zw,Pf,F1,V0,uL,Nr,Pi,yj,qI,J3,E5,o5,b5,zI,Zb,id,iV,W4,Fa,x9,d3,X6,xh,wn,uF,cj,HA,br,zT,D7,qL,C4,l9,lP,km,Qt,Dk,A0,rm,eY,OO,BE,Qb,xI,q1,Zj,XP,q6,CK,BO,ZG,Oc,MX,w12,fTP,yL,dM,Y7,WC,Xi,TV,Mq,Oa,n1,xf,L6,Rs,uJ,hm,Ji,Bf,ir,Sa,GN,k8,HJ,S0,V3,Bl,pM,Mh,Md,Lf,fT,pp,Nq,nl,mf,ej,HK,w13,o8,GL,e9,PD,Xy,uK,mY,fE,mB,XF,iH,wJY,zOQ,W6o,MdQ,YJG,DOe,lPa,Ufa,Raa,w0,w4,w5,w7,w9,w10,w11,c4,z6,Ay,Ed,G1,Os,Dl,Wh,x5,ev,ID,jV,ek,OC,Xm,Jy,ky,fa,WW,vQ,a9,jh,e3,VA,J1,fk,wL,B0,Fq,hw,EZ,no,kB,ae,Iq,w6,jK,uk,K9,RW,xs,FX,Ae,Bt,vR,Pn,hc,hA,fr,a0,NQ,fI,V4,kK,V6,uw,V8,V2,D8,jY,ll,Uf,ik,LfS,NP,Vh,r0,jz,SA,zV,nv,ee,XI,hs,yp,ug,DT,OB,Ra,N9,NW,HS,TG,ts,Kj,VU,Ya,XT,ic,VT,T4,TR,VD,Oh,zy,Nb,Fy,eU,ADW,Ri,kq,Ag,PW]}
\ No newline at end of file
diff --git a/runtime/bin/vmservice/client/deployed/web/index_devtools.html b/runtime/bin/vmservice/client/deployed/web/index_devtools.html
index c776551..e931ab5 100644
--- a/runtime/bin/vmservice/client/deployed/web/index_devtools.html
+++ b/runtime/bin/vmservice/client/deployed/web/index_devtools.html
@@ -11,6 +11,24 @@
 </head>
 <body><polymer-element name="observatory-element">
   
+</polymer-element><polymer-element name="breakpoint-list" extends="observatory-element">
+  <template>
+    <template if="{{ msg['breakpoints'].isEmpty }}">
+      <div class="panel panel-warning">
+        <div class="panel-body">No breakpoints</div>
+      </div>
+    </template>
+    <template if="{{ msg['breakpoints'].isNotEmpty }}">
+      <ul class="list-group">
+      <template repeat="{{ bpt in msg['breakpoints'] }}">
+        <li class="list-group-item">
+          {{ bpt }}
+        </li>
+      </template>
+      </ul>
+    </template>
+  </template>
+  
 </polymer-element><polymer-element name="error-view" extends="observatory-element">
   <template>
     <div class="row">
@@ -297,6 +315,9 @@
       <div class="col-md-1">
         <a href="{{ app.locationManager.relativeLink(isolate, 'library') }}">Library</a>
       </div>
+      <div class="col-md-1">
+        <a href="{{ app.locationManager.relativeLink(isolate, 'debug/breakpoints') }}">Breakpoints</a>
+      </div>
   	  <div class="col-md-8"></div>
     </div>
   </template>
@@ -514,6 +535,9 @@
     <template if="{{ messageType == 'StackTrace' }}">
       <stack-trace app="{{ app }}" trace="{{ message }}"></stack-trace>
     </template>
+    <template if="{{ messageType == 'BreakpointList' }}">
+      <breakpoint-list app="{{ app }}" msg="{{ message }}"></breakpoint-list>
+    </template>
     <!-- If the message type is a RequestError -->
     <template if="{{ messageType == 'RequestError' }}">
       <error-view app="{{ app }}" error="{{ message['error'] }}"></error-view>
diff --git a/runtime/bin/vmservice/client/deployed/web/index_devtools.html_bootstrap.dart.js b/runtime/bin/vmservice/client/deployed/web/index_devtools.html_bootstrap.dart.js
index 1cb385f..5e54f7a 100644
--- a/runtime/bin/vmservice/client/deployed/web/index_devtools.html_bootstrap.dart.js
+++ b/runtime/bin/vmservice/client/deployed/web/index_devtools.html_bootstrap.dart.js
@@ -7782,7 +7782,7 @@
 $$.Y7=[A,{"":"v;wc,nn,lv,Pp",
 call$2:function(a,b){return this.nn.call(this.wc,this.lv,a,b)},
 $is_bh:true}]
-$$.Dw=[T,{"":"v;wc,nn,lv,Pp",
+$$.PD=[T,{"":"v;wc,nn,lv,Pp",
 call$3:function(a,b,c){return this.nn.call(this.wc,a,b,c)}}]
 $$.zy=[H,{"":"Tp;call$2,$name",$is_bh:true}]
 $$.Nb=[H,{"":"Tp;call$1,$name",$is_HB:true,$is_Dv:true}]
@@ -7805,7 +7805,7 @@
 call$catchAll:function(){return{onError:null,radix:null}},
 $is_HB:true,
 $is_Dv:true}]
-;init.mangledNames={gB:"length",gDb:"_cachedDeclarations",gEI:"prefix",gF1:"isolate",gFF:"source",gFJ:"__$cls",gFT:"__$instruction",gFU:"_cachedMethodsMap",gG1:"message",gH8:"_fieldsDescriptor",gHt:"_fieldsMetadata",gKM:"$",gLA:"src",gLf:"__$field",gLy:"_cachedSetters",gM2:"_cachedVariables",gMj:"function",gNI:"instruction",gNl:"script",gO3:"url",gOk:"_cachedMetadata",gP:"value",gP2:"_collapsed",gPw:"__$isolate",gPy:"__$error",gQG:"app",gRu:"cls",gT1:"_cachedGetters",gTn:"json",gTx:"_jsConstructorOrInterceptor",gUF:"_cachedTypeVariables",gUz:"__$script",gV4:"__$trace",gVA:"__$displayValue",gVB:"error_obj",gWL:"_mangledName",gXB:"_message",gXJ:"lines",gXR:"scripts",gXf:"__$iconClass",gXh:"__$instance",gZ6:"locationManager",gZw:"__$code",ga:"a",gai:"displayValue",gb:"b",gb0:"_cachedConstructors",gcC:"hash",geV:"paddedLine",geb:"__$json",gfY:"kind",ghO:"__$error_obj",ghf:"instance",gi0:"__$name",gi2:"isolates",giI:"__$library",giK:"__$instance",gjO:"id",gjd:"_cachedMethods",gk5:"__$devtools",gkc:"error",gkf:"_count",gl7:"iconClass",glD:"currentHashUri",gle:"_metadata",glw:"requestManager",gn2:"responses",gnI:"isolateManager",gnz:"_owner",goc:"name",gpz:"_jsConstructorCache",gqN:"_superclass",gql:"__$function",gqm:"_cachedSuperinterfaces",gt0:"field",gtB:"_cachedFields",gtD:"library",gtH:"__$app",gtN:"trace",gtT:"code",guA:"_cachedMembers",gvH:"index",gvX:"__$source",gvt:"__$field",gxj:"collapsed",gzd:"currentHash",gzj:"devtools"};init.mangledGlobalNames={DI:"_closeIconClass",Vl:"_openIconClass"};(function (reflectionData) {
+;init.mangledNames={gB:"length",gDb:"_cachedDeclarations",gEI:"prefix",gF1:"isolate",gFF:"source",gFJ:"__$cls",gFT:"__$instruction",gFU:"_cachedMethodsMap",gG1:"message",gH8:"_fieldsDescriptor",gHt:"_fieldsMetadata",gKM:"$",gLA:"src",gLf:"__$field",gLy:"_cachedSetters",gM2:"_cachedVariables",gMj:"function",gNI:"instruction",gNl:"script",gO3:"url",gOk:"_cachedMetadata",gP:"value",gP2:"_collapsed",gPw:"__$isolate",gPy:"__$error",gQG:"app",gRu:"cls",gT1:"_cachedGetters",gTn:"json",gTx:"_jsConstructorOrInterceptor",gUF:"_cachedTypeVariables",gUz:"__$script",gV4:"__$trace",gVA:"__$displayValue",gVB:"error_obj",gWL:"_mangledName",gXB:"_message",gXJ:"lines",gXR:"scripts",gXf:"__$iconClass",gXh:"__$instance",gZ6:"locationManager",gZw:"__$code",ga:"a",gai:"displayValue",gb:"b",gb0:"_cachedConstructors",gcC:"hash",geE:"__$msg",geV:"paddedLine",geb:"__$json",gfY:"kind",ghO:"__$error_obj",ghf:"instance",gi0:"__$name",gi2:"isolates",giI:"__$library",giK:"__$instance",gjO:"id",gjd:"_cachedMethods",gk5:"__$devtools",gkc:"error",gkf:"_count",gl7:"iconClass",glD:"currentHashUri",gle:"_metadata",glw:"requestManager",gn2:"responses",gnI:"isolateManager",gnz:"_owner",goc:"name",gpz:"_jsConstructorCache",gqN:"_superclass",gql:"__$function",gqm:"_cachedSuperinterfaces",grs:"msg",gt0:"field",gtB:"_cachedFields",gtD:"library",gtH:"__$app",gtN:"trace",gtT:"code",guA:"_cachedMembers",gvH:"index",gvX:"__$source",gvt:"__$field",gxj:"collapsed",gzd:"currentHash",gzj:"devtools"};init.mangledGlobalNames={DI:"_closeIconClass",Vl:"_openIconClass"};(function (reflectionData) {
   function map(x){x={x:x};delete x.x;return x}
   if (!init.libraries) init.libraries = [];
   if (!init.mangledNames) init.mangledNames = map();
@@ -9438,14 +9438,38 @@
 t:function(a,b){if(!J.xC(b,0))H.vh(P.N(b))
 return this.zO},
 "+[]:1:0":0,
-$isOd:true}}],["app_bootstrap","index.html_bootstrap.dart",,E,{E2:function(){$.x2=["package:observatory/src/observatory_elements/observatory_element.dart","package:observatory/src/observatory_elements/error_view.dart","package:observatory/src/observatory_elements/field_ref.dart","package:observatory/src/observatory_elements/instance_ref.dart","package:observatory/src/observatory_elements/class_view.dart","package:observatory/src/observatory_elements/disassembly_entry.dart","package:observatory/src/observatory_elements/code_view.dart","package:observatory/src/observatory_elements/collapsible_content.dart","package:observatory/src/observatory_elements/field_view.dart","package:observatory/src/observatory_elements/function_view.dart","package:observatory/src/observatory_elements/isolate_summary.dart","package:observatory/src/observatory_elements/isolate_list.dart","package:observatory/src/observatory_elements/instance_view.dart","package:observatory/src/observatory_elements/json_view.dart","package:observatory/src/observatory_elements/library_view.dart","package:observatory/src/observatory_elements/source_view.dart","package:observatory/src/observatory_elements/script_view.dart","package:observatory/src/observatory_elements/stack_trace.dart","package:observatory/src/observatory_elements/message_viewer.dart","package:observatory/src/observatory_elements/navigation_bar.dart","package:observatory/src/observatory_elements/response_viewer.dart","package:observatory/src/observatory_elements/observatory_application.dart","index.html.0.dart"]
+$isOd:true}}],["app_bootstrap","index.html_bootstrap.dart",,E,{E2:function(){$.x2=["package:observatory/src/observatory_elements/observatory_element.dart","package:observatory/src/observatory_elements/breakpoint_list.dart","package:observatory/src/observatory_elements/error_view.dart","package:observatory/src/observatory_elements/field_ref.dart","package:observatory/src/observatory_elements/instance_ref.dart","package:observatory/src/observatory_elements/class_view.dart","package:observatory/src/observatory_elements/disassembly_entry.dart","package:observatory/src/observatory_elements/code_view.dart","package:observatory/src/observatory_elements/collapsible_content.dart","package:observatory/src/observatory_elements/field_view.dart","package:observatory/src/observatory_elements/function_view.dart","package:observatory/src/observatory_elements/isolate_summary.dart","package:observatory/src/observatory_elements/isolate_list.dart","package:observatory/src/observatory_elements/instance_view.dart","package:observatory/src/observatory_elements/json_view.dart","package:observatory/src/observatory_elements/library_view.dart","package:observatory/src/observatory_elements/source_view.dart","package:observatory/src/observatory_elements/script_view.dart","package:observatory/src/observatory_elements/stack_trace.dart","package:observatory/src/observatory_elements/message_viewer.dart","package:observatory/src/observatory_elements/navigation_bar.dart","package:observatory/src/observatory_elements/response_viewer.dart","package:observatory/src/observatory_elements/observatory_application.dart","index.html.0.dart"]
 $.uP=!1
-A.Ok()}},1],["class_view_element","package:observatory/src/observatory_elements/class_view.dart",,Z,{aC:{"":["Vf;FJ%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
+A.Ok()}},1],["breakpoint_list_element","package:observatory/src/observatory_elements/breakpoint_list.dart",,B,{G6:{"":["Vf;eE%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
+grs:function(a){return a.eE
+"38,39,40"},
+"+msg":1,
+srs:function(a,b){a.eE=this.pD(a,C.Ry,a.eE,b)
+"41,32,38,39"},
+"+msg=":1,
+"@":function(){return[C.PT]},
+static:{Dw:function(a){var z,y,x,w,v,u
+z=H.B7([],P.L5(null,null,null,null,null))
+z=R.Jk(z)
+y=$.Nd()
+x=P.Py(null,null,null,J.O,W.I0)
+w=J.O
+v=W.cv
+u=new V.br(P.Py(null,null,null,w,v),null,null)
+H.VM(u,[w,v])
+a.eE=z
+a.Ye=y
+a.mT=x
+a.KM=u
+C.J0.ZL(a)
+C.J0.FH(a)
+return a
+"9"},"+new BreakpointListElement$created:0:0":1}},"+BreakpointListElement": [42],Vf:{"":"uL+Pi;",$isd3:true}}],["class_view_element","package:observatory/src/observatory_elements/class_view.dart",,Z,{aC:{"":["tu;FJ%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
 gRu:function(a){return a.FJ
-"37,38,39"},
+"38,39,40"},
 "+cls":1,
 sRu:function(a,b){a.FJ=this.pD(a,C.XA,a.FJ,b)
-"40,31,37,38"},
+"41,32,38,39"},
 "+cls=":1,
 "@":function(){return[C.aQ]},
 static:{zg:function(a){var z,y,x,w,v
@@ -9461,12 +9485,12 @@
 C.kk.ZL(a)
 C.kk.FH(a)
 return a
-"9"},"+new ClassViewElement$created:0:0":1}},"+ClassViewElement": [41],Vf:{"":"uL+Pi;",$isd3:true}}],["code_view_element","package:observatory/src/observatory_elements/code_view.dart",,F,{Be:{"":["tu;Zw%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
+"10"},"+new ClassViewElement$created:0:0":1}},"+ClassViewElement": [43],tu:{"":"uL+Pi;",$isd3:true}}],["code_view_element","package:observatory/src/observatory_elements/code_view.dart",,F,{Be:{"":["Vc;Zw%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
 gtT:function(a){return a.Zw
-"37,38,39"},
+"38,39,40"},
 "+code":1,
 stT:function(a,b){a.Zw=this.pD(a,C.b1,a.Zw,b)
-"40,31,37,38"},
+"41,32,38,39"},
 "+code=":1,
 grK:function(a){var z=a.Zw
 if(z!=null&&J.UQ(z,"is_optimized")!=null)return"panel panel-success"
@@ -9490,41 +9514,41 @@
 C.YD.ZL(a)
 C.YD.FH(a)
 return a
-"10"},"+new CodeViewElement$created:0:0":1}},"+CodeViewElement": [42],tu:{"":"uL+Pi;",$isd3:true}}],["collapsible_content_element","package:observatory/src/observatory_elements/collapsible_content.dart",,R,{i6:{"":["Vc;Xf%-,VA%-,P2%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
+"11"},"+new CodeViewElement$created:0:0":1}},"+CodeViewElement": [44],Vc:{"":"uL+Pi;",$isd3:true}}],["collapsible_content_element","package:observatory/src/observatory_elements/collapsible_content.dart",,R,{i6:{"":["WZ;Xf%-,VA%-,P2%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
 gl7:function(a){return a.Xf
-"8,38,43"},
+"8,39,45"},
 "+iconClass":1,
 sl7:function(a,b){a.Xf=this.pD(a,C.Di,a.Xf,b)
-"40,31,8,38"},
+"41,32,8,39"},
 "+iconClass=":1,
 gai:function(a){return a.VA
-"8,38,43"},
+"8,39,45"},
 "+displayValue":1,
 sai:function(a,b){a.VA=this.pD(a,C.Jw,a.VA,b)
-"40,31,8,38"},
+"41,32,8,39"},
 "+displayValue=":1,
 gxj:function(a){return a.P2
-"44"},
+"46"},
 "+collapsed":1,
 sxj:function(a,b){a.P2=b
 this.dR(a)
-"40,45,44"},
+"41,47,46"},
 "+collapsed=":1,
 i4:function(a){Z.uL.prototype.i4.call(this,a)
 this.dR(a)
-"40"},
+"41"},
 "+enteredView:0:0":1,
 rS:function(a,b,c,d){a.P2=a.P2!==!0
 this.dR(a)
 this.dR(a)
-"40,46,47,48,40,49,50"},
+"41,48,49,50,41,51,52"},
 "+toggleDisplay:3:0":1,
 dR:function(a){var z,y
 z=a.P2
 y=a.Xf
 if(z===!0){a.Xf=this.pD(a,C.Di,y,"glyphicon glyphicon-chevron-down")
 a.VA=this.pD(a,C.Jw,a.VA,"none")}else{a.Xf=this.pD(a,C.Di,y,"glyphicon glyphicon-chevron-up")
-a.VA=this.pD(a,C.Jw,a.VA,"block")}"40"},
+a.VA=this.pD(a,C.Jw,a.VA,"block")}"41"},
 "+_refresh:0:0":1,
 "@":function(){return[C.Gu]},
 static:{"":"Vl<-,DI<-",IT:function(a){var z,y,x,w,v
@@ -9543,7 +9567,7 @@
 C.j8.ZL(a)
 C.j8.FH(a)
 return a
-"11"},"+new CollapsibleContentElement$created:0:0":1}},"+CollapsibleContentElement": [51],Vc:{"":"uL+Pi;",$isd3:true}}],["custom_element.polyfill","package:custom_element/polyfill.dart",,B,{G9:function(){if($.LX()==null)return!0
+"12"},"+new CollapsibleContentElement$created:0:0":1}},"+CollapsibleContentElement": [53],WZ:{"":"uL+Pi;",$isd3:true}}],["custom_element.polyfill","package:custom_element/polyfill.dart",,B,{G9:function(){if($.LX()==null)return!0
 var z=J.UQ($.LX(),"CustomElements")
 if(z==null)return"register" in document
 return J.xC(J.UQ(z,"ready"),!0)},zO:{"":"Tp;",
@@ -10111,7 +10135,7 @@
 if(typeof y==="object"&&y!==null&&!!z.$isZk)if(!("$reflectable" in y.dl))H.Hz(J.Z0(a))
 return H.vn(y.qj(b,c))},
 "+invoke:3:0":0,
-"*invoke":[40],
+"*invoke":[41],
 CI:function(a,b){return this.F2(a,b,null)},
 "+invoke:2:0":0,
 Z0:function(a){return $[a]},
@@ -10251,7 +10275,7 @@
 "+declarations":0,
 F2:function(a,b,c){throw H.b(P.lr(this,a,b,c,null))},
 "+invoke:3:0":0,
-"*invoke":[40],
+"*invoke":[41],
 CI:function(a,b){return this.F2(a,b,null)},
 "+invoke:2:0":0,
 rN:function(a){throw H.b(P.lr(this,a,null,null,null))},
@@ -10273,7 +10297,7 @@
 y=z+":"+b.length+":0"
 return this.tu(a,0,y,b)},
 "+invoke:3:0":0,
-"*invoke":[40],
+"*invoke":[41],
 CI:function(a,b){return this.F2(a,b,null)},
 "+invoke:2:0":0,
 tu:function(a,b,c,d){var z,y,x,w,v,u,t,s
@@ -10400,7 +10424,7 @@
 return z},
 F2:function(a,b,c){return this.NK.F2(a,b,c)},
 "+invoke:3:0":0,
-"*invoke":[40],
+"*invoke":[41],
 CI:function(a,b){return this.F2(a,b,null)},
 "+invoke:2:0":0,
 gHA:function(){return!1},
@@ -10452,7 +10476,7 @@
 y=J.x(z)
 if(typeof z==="object"&&z!==null&&!!y.$isGv)return z.constructor
 else return z
-"40"},
+"41"},
 "+_jsConstructor":1,
 gDI:function(){var z=this.b0
 if(z!=null)return z
@@ -10460,7 +10484,7 @@
 H.VM(z,[P.wv,P.RS])
 this.b0=z
 return z
-"52"},
+"54"},
 "+constructors":1,
 ly:function(a){var z,y,x,w,v,u,t,s,r,q,p,o,n,m,l,k
 z=this.gaB().prototype
@@ -10505,14 +10529,14 @@
 l=!1}s=H.Sd(k,o,!l,l)
 x.push(s)
 s.nz=a}return x
-"53,54,55"},
+"55,56,57"},
 "+_getMethodsWithOwner:1:0":1,
 gEO:function(){var z=this.jd
 if(z!=null)return z
 z=this.ly(this)
 this.jd=z
 return z
-"53"},
+"55"},
 "+_methods":1,
 ws:function(a){var z,y,x,w
 z=[]
@@ -10526,14 +10550,14 @@
 w=init.statics[this.WL]
 if(w!=null)H.jw(a,w[""],!0,z)
 return z
-"56,57,55"},
+"58,59,57"},
 "+_getFieldsWithOwner:1:0":1,
 gKn:function(){var z=this.tB
 if(z!=null)return z
 z=this.ws(this)
 this.tB=z
 return z
-"56"},
+"58"},
 "+_fields":1,
 gtx:function(){var z=this.FU
 if(z!=null)return z
@@ -10541,7 +10565,7 @@
 H.VM(z,[P.wv,P.RS])
 this.FU=z
 return z
-"52"},
+"54"},
 "+methods":1,
 gZ3:function(){var z,y,x
 z=this.M2
@@ -10552,7 +10576,7 @@
 H.VM(z,[P.wv,P.RY])
 this.M2=z
 return z
-"58"},
+"60"},
 "+variables":1,
 glc:function(a){var z=this.uA
 if(z!=null)return z
@@ -10560,7 +10584,7 @@
 H.VM(z,[P.wv,P.QF])
 this.uA=z
 return z
-"59"},
+"61"},
 "+members":1,
 gYK:function(){var z,y
 z=this.Db
@@ -10574,7 +10598,7 @@
 H.VM(z,[P.wv,P.NL])
 this.Db=z
 return z
-"60"},
+"62"},
 "+declarations":1,
 PU:function(a,b){var z,y
 z=J.UQ(this.gZ3(),a)
@@ -10582,7 +10606,7 @@
 if(!(y in $))throw H.b(H.Pa("Cannot find \""+y+"\" in current isolate."))
 $[y]=b
 return H.vn(b)}throw H.b(P.lr(this,H.X7(a),[b],null,null))
-"61,62,63,64,0"},
+"63,64,65,66,0"},
 "+setField:2:0":1,
 rN:function(a){var z,y
 z=J.UQ(this.gZ3(),a)
@@ -10590,7 +10614,7 @@
 if(!(y in $))throw H.b(H.Pa("Cannot find \""+y+"\" in current isolate."))
 if(y in init.lazies)return H.vn($[init.lazies[y]]())
 else return H.vn($[y])}throw H.b(P.lr(this,a,null,null,null))
-"61,62,63"},
+"63,64,65"},
 "+getField:1:0":1,
 gh7:function(){var z,y,x,w,v,u,t
 if(this.nz==null){z=this.Tx
@@ -10609,7 +10633,7 @@
 z=new H.MH(null,y,z.ew)
 z.$builtinTypeInfo=[u,t]
 for(;z.G();)for(y=J.GP(z.mD);y.G();)J.pP(y.gl())}if(this.nz==null)throw H.b(new P.lj("Class \""+H.d(J.Z0(this.If))+"\" has no owner"))}return this.nz
-"65"},
+"67"},
 "+owner":1,
 gc9:function(){var z=this.Ok
 if(z!=null)return z
@@ -10618,7 +10642,7 @@
 H.VM(z,[P.vr])
 this.Ok=z
 return z
-"66"},
+"68"},
 "+metadata":1,
 gAY:function(){var z,y,x,w,v,u
 if(this.qN==null){z=init.typeInformation[this.WL]
@@ -10632,7 +10656,7 @@
 u=v.length
 if(u>1){if(u!==2)throw H.b(H.Pa("Strange mixin: "+H.d(y)))
 this.qN=H.jO(v[0])}else this.qN=x.n(w,"")?this:H.jO(w)}}return J.xC(this.qN,this)?null:this.qN
-"67"},
+"69"},
 "+superclass":1,
 F2:function(a,b,c){var z
 if(c!=null&&J.FN(c)!==!0)throw H.b(P.f("Named arguments are not implemented."))
@@ -10640,16 +10664,16 @@
 if(z==null||!z.gFo())throw H.b(P.lr(this,a,b,c,null))
 if(!z.yR())H.Hz(J.Z0(a))
 return H.vn(z.qj(b,c))
-"61,68,63,69,70,71,72"},
+"63,70,65,71,72,73,74"},
 "+invoke:3:0":1,
-"*invoke":[40],
+"*invoke":[41],
 CI:function(a,b){return this.F2(a,b,null)},
 "+invoke:2:0":1,
 gHA:function(){return!0
-"44"},
+"46"},
 "+isOriginalDeclaration":1,
 gJi:function(){return this
-"67"},
+"69"},
 "+originalDeclaration":1,
 MR:function(a){var z,y,x
 z=init.typeInformation[this.WL]
@@ -10659,14 +10683,14 @@
 y=new P.Yp(x)
 H.VM(y,[P.Ms])
 return y
-"73,74,55"},
+"75,76,57"},
 "+_getSuperinterfacesWithOwner:1:0":1,
 gkZ:function(){var z=this.qm
 if(z!=null)return z
 z=this.MR(this)
 this.qm=z
 return z
-"73"},
+"75"},
 "+superinterfaces":1,
 gNy:function(){var z,y,x,w,v
 z=this.UF
@@ -10679,34 +10703,34 @@
 H.VM(z,[null])
 this.UF=z
 return z
-"75"},
+"77"},
 "+typeVariables":1,
 gw8:function(){return C.hU
-"76"},
+"78"},
 "+typeArguments":1,
 $isWf:true,
 $isMs:true,
 $isQF:true,
 $isL9u:true,
-$isNL:true},"+JsClassMirror": [77, 67],Un:{"":"EE+M2;",$isQF:true},Ei:{"":"Tp;a-",
+$isNL:true},"+JsClassMirror": [79, 69],Un:{"":"EE+M2;",$isQF:true},Ei:{"":"Tp;a-",
 call$2:function(a,b){J.kW(this.a,a,b)
-"40,78,63,31,79"},
+"41,80,65,32,81"},
 "+call:2:0":1,
 $isEH:true,
-$is_bh:true},"+JsClassMirror_declarations_addToResult": [80],U7:{"":"Tp;b-",
+$is_bh:true},"+JsClassMirror_declarations_addToResult": [82],U7:{"":"Tp;b-",
 call$1:function(a){J.kW(this.b,a.gIf(),a)
 return a
-"40,81,40"},
+"41,83,41"},
 "+call:1:0":1,
 $isEH:true,
 $is_HB:true,
-$is_Dv:true},"+JsClassMirror_declarations_closure": [80],t0:{"":"Tp;a-",
+$is_Dv:true},"+JsClassMirror_declarations_closure": [82],t0:{"":"Tp;a-",
 call$1:function(a){return H.Jf(this.a,init.metadata[a])
-"67,82,30"},
+"69,84,31"},
 "+call:1:0":1,
 $isEH:true,
 $is_HB:true,
-$is_Dv:true},"+JsClassMirror__getSuperinterfacesWithOwner_lookupType": [80],Ld:{"":"am;ao<,V5<,Fo<,n6,nz,le,If",
+$is_Dv:true},"+JsClassMirror__getSuperinterfacesWithOwner_lookupType": [82],Ld:{"":"am;ao<,V5<,Fo<,n6,nz,le,If",
 gOO:function(){return"VariableMirror"},
 "+_prettyName":0,
 gr9:function(a){return $.Cr()},
@@ -11373,7 +11397,7 @@
 $is_Dv:true},dm:{"":"Tp;b",
 call$2:function(a,b){this.b.K5(a,b)},
 "+call:2:0":0,
-"*call":[40],
+"*call":[41],
 call$1:function(a){return this.call$2(a,null)},
 "+call:1:0":0,
 $isEH:true,
@@ -11442,7 +11466,7 @@
 if(typeof y!=="object"||y===null||!x.$isvs){z.a=P.Dt(null)
 z.a.E6(a,b)}P.HZ(z.a,this.h)},
 "+call:2:0":0,
-"*call":[40],
+"*call":[41],
 call$1:function(a){return this.call$2(a,null)},
 "+call:1:0":0,
 $isEH:true,
@@ -14592,7 +14616,7 @@
 gor:function(a){return J.pO(this.iY)},
 "+isNotEmpty":0,
 $isL8:true}}],["dart.dom.html","dart:html",,W,{lq:function(){return window
-"12"},"+window":1,UE:function(a){if(P.F7()===!0)return"webkitTransitionEnd"
+"13"},"+window":1,UE:function(a){if(P.F7()===!0)return"webkitTransitionEnd"
 else if(P.dg()===!0)return"oTransitionEnd"
 return"transitionend"},r3:function(a,b){return document.createElement(a)},It:function(a,b,c){return W.lt(a,null,null,b,null,null,null,c).ml(new W.Kx())},lt:function(a,b,c,d,e,f,g,h){var z,y,x,w
 z=W.fJ
@@ -14663,7 +14687,7 @@
 q={prototype: s}
 if(!J.xC(w,"HTMLElement"))if(!v)q.extends=e
 b.register(c,q)},aF:function(a){if(J.xC($.X3,C.NU))return a
-return $.X3.oj(a,!0)},qE:{"":"cv;","%":"HTMLAppletElement|HTMLBRElement|HTMLBaseFontElement|HTMLBodyElement|HTMLCanvasElement|HTMLContentElement|HTMLDListElement|HTMLDataListElement|HTMLDetailsElement|HTMLDialogElement|HTMLDirectoryElement|HTMLDivElement|HTMLFontElement|HTMLFrameElement|HTMLFrameSetElement|HTMLHRElement|HTMLHeadElement|HTMLHeadingElement|HTMLHtmlElement|HTMLMarqueeElement|HTMLMenuElement|HTMLModElement|HTMLOptGroupElement|HTMLParagraphElement|HTMLPreElement|HTMLQuoteElement|HTMLShadowElement|HTMLSpanElement|HTMLTableCaptionElement|HTMLTableCellElement|HTMLTableColElement|HTMLTableDataCellElement|HTMLTableElement|HTMLTableHeaderCellElement|HTMLTableRowElement|HTMLTableSectionElement|HTMLTitleElement|HTMLUListElement|HTMLUnknownElement;HTMLElement;Sa|GN|ir|Nr|uL|Vf|aC|tu|Be|Vc|i6|WZ|Fv|pv|I3|Vfx|qr|Dsd|Gk|tuj|Ds|Vct|pR|D13|hx|u7|WZq|St|pva|vj|cda|CX|Nh|ih|waa|F1|XP|NQ|V0|fI|V4|kK|V6|uw"},Yy:{"":"Gv;",$isList:true,
+return $.X3.oj(a,!0)},qE:{"":"cv;","%":"HTMLAppletElement|HTMLBRElement|HTMLBaseFontElement|HTMLBodyElement|HTMLCanvasElement|HTMLContentElement|HTMLDListElement|HTMLDataListElement|HTMLDetailsElement|HTMLDialogElement|HTMLDirectoryElement|HTMLDivElement|HTMLFontElement|HTMLFrameElement|HTMLFrameSetElement|HTMLHRElement|HTMLHeadElement|HTMLHeadingElement|HTMLHtmlElement|HTMLMarqueeElement|HTMLMenuElement|HTMLModElement|HTMLOptGroupElement|HTMLParagraphElement|HTMLPreElement|HTMLQuoteElement|HTMLShadowElement|HTMLSpanElement|HTMLTableCaptionElement|HTMLTableCellElement|HTMLTableColElement|HTMLTableDataCellElement|HTMLTableElement|HTMLTableHeaderCellElement|HTMLTableRowElement|HTMLTableSectionElement|HTMLTitleElement|HTMLUListElement|HTMLUnknownElement;HTMLElement;Sa|GN|ir|Nr|uL|Vf|G6|tu|aC|Vc|Be|WZ|i6|pv|Fv|Vfx|I3|Dsd|qr|tuj|Gk|Vct|Ds|D13|pR|WZq|hx|u7|pva|St|cda|vj|waa|CX|Nh|ih|V0|F1|XP|NQ|V4|fI|V6|kK|V8|uw"},Yy:{"":"Gv;",$isList:true,
 $asWO:function(){return[W.M5]},
 $isqC:true,
 $iscX:true,
@@ -15697,12 +15721,12 @@
 $iscX:true,
 $ascX:function(){return[J.im]},
 $isXj:true,
-static:{"":"U9",}}}],["disassembly_entry_element","package:observatory/src/observatory_elements/disassembly_entry.dart",,E,{Fv:{"":["WZ;FT%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
+static:{"":"U9",}}}],["disassembly_entry_element","package:observatory/src/observatory_elements/disassembly_entry.dart",,E,{Fv:{"":["pv;FT%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
 gNI:function(a){return a.FT
-"37,38,39"},
+"38,39,40"},
 "+instruction":1,
 sNI:function(a,b){a.FT=this.pD(a,C.eJ,a.FT,b)
-"40,31,37,38"},
+"41,32,38,39"},
 "+instruction=":1,
 "@":function(){return[C.Vy]},
 static:{AH:function(a){var z,y,x,w,v,u
@@ -15721,18 +15745,18 @@
 C.Tl.ZL(a)
 C.Tl.FH(a)
 return a
-"13"},"+new DisassemblyEntryElement$created:0:0":1}},"+DisassemblyEntryElement": [83],WZ:{"":"uL+Pi;",$isd3:true}}],["error_view_element","package:observatory/src/observatory_elements/error_view.dart",,F,{I3:{"":["pv;Py%-,hO%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
+"14"},"+new DisassemblyEntryElement$created:0:0":1}},"+DisassemblyEntryElement": [85],pv:{"":"uL+Pi;",$isd3:true}}],["error_view_element","package:observatory/src/observatory_elements/error_view.dart",,F,{I3:{"":["Vfx;Py%-,hO%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
 gkc:function(a){return a.Py
-"8,38,39"},
+"8,39,40"},
 "+error":1,
 skc:function(a,b){a.Py=this.pD(a,C.YU,a.Py,b)
-"40,31,8,38"},
+"41,32,8,39"},
 "+error=":1,
 gVB:function(a){return a.hO
-"40,38,39"},
+"41,39,40"},
 "+error_obj":1,
 sVB:function(a,b){a.hO=this.pD(a,C.Yn,a.hO,b)
-"40,31,40,38"},
+"41,32,41,39"},
 "+error_obj=":1,
 "@":function(){return[C.uW]},
 static:{TW:function(a){var z,y,x,w,v
@@ -15749,12 +15773,12 @@
 C.OD.ZL(a)
 C.OD.FH(a)
 return a
-"14"},"+new ErrorViewElement$created:0:0":1}},"+ErrorViewElement": [84],pv:{"":"uL+Pi;",$isd3:true}}],["field_ref_element","package:observatory/src/observatory_elements/field_ref.dart",,D,{qr:{"":["Vfx;Lf%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
+"15"},"+new ErrorViewElement$created:0:0":1}},"+ErrorViewElement": [86],Vfx:{"":"uL+Pi;",$isd3:true}}],["field_ref_element","package:observatory/src/observatory_elements/field_ref.dart",,D,{qr:{"":["Dsd;Lf%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
 gt0:function(a){return a.Lf
-"37,38,39"},
+"38,39,40"},
 "+field":1,
 st0:function(a,b){a.Lf=this.pD(a,C.WQ,a.Lf,b)
-"40,31,37,38"},
+"41,32,38,39"},
 "+field=":1,
 "@":function(){return[C.ht]},
 static:{ip:function(a){var z,y,x,w,v
@@ -15770,12 +15794,12 @@
 C.WR.ZL(a)
 C.WR.FH(a)
 return a
-"15"},"+new FieldRefElement$created:0:0":1}},"+FieldRefElement": [85],Vfx:{"":"uL+Pi;",$isd3:true}}],["field_view_element","package:observatory/src/observatory_elements/field_view.dart",,A,{Gk:{"":["Dsd;vt%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
+"16"},"+new FieldRefElement$created:0:0":1}},"+FieldRefElement": [87],Dsd:{"":"uL+Pi;",$isd3:true}}],["field_view_element","package:observatory/src/observatory_elements/field_view.dart",,A,{Gk:{"":["tuj;vt%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
 gt0:function(a){return a.vt
-"37,38,39"},
+"38,39,40"},
 "+field":1,
 st0:function(a,b){a.vt=this.pD(a,C.WQ,a.vt,b)
-"40,31,37,38"},
+"41,32,38,39"},
 "+field=":1,
 "@":function(){return[C.Tq]},
 static:{cY:function(a){var z,y,x,w,v
@@ -15791,12 +15815,12 @@
 C.lS.ZL(a)
 C.lS.FH(a)
 return a
-"16"},"+new FieldViewElement$created:0:0":1}},"+FieldViewElement": [86],Dsd:{"":"uL+Pi;",$isd3:true}}],["function_view_element","package:observatory/src/observatory_elements/function_view.dart",,N,{Ds:{"":["tuj;ql%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
+"17"},"+new FieldViewElement$created:0:0":1}},"+FieldViewElement": [88],tuj:{"":"uL+Pi;",$isd3:true}}],["function_view_element","package:observatory/src/observatory_elements/function_view.dart",,N,{Ds:{"":["Vct;ql%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
 gMj:function(a){return a.ql
-"37,38,39"},
+"38,39,40"},
 "+function":1,
 sMj:function(a,b){a.ql=this.pD(a,C.nf,a.ql,b)
-"40,31,37,38"},
+"41,32,38,39"},
 "+function=":1,
 "@":function(){return[C.Uc]},
 static:{p7:function(a){var z,y,x,w,v
@@ -15812,7 +15836,7 @@
 C.PJ.ZL(a)
 C.PJ.FH(a)
 return a
-"17"},"+new FunctionViewElement$created:0:0":1}},"+FunctionViewElement": [87],tuj:{"":"uL+Pi;",$isd3:true}}],["html_common","dart:html_common",,P,{jD:function(a){return P.Wu(a.getTime(),!0)},bL:function(a){var z,y
+"18"},"+new FunctionViewElement$created:0:0":1}},"+FunctionViewElement": [89],Vct:{"":"uL+Pi;",$isd3:true}}],["html_common","dart:html_common",,P,{jD:function(a){return P.Wu(a.getTime(),!0)},bL:function(a){var z,y
 z=[]
 y=new P.Tm(new P.aI([],z),new P.rG(z),new P.yh(z)).call$1(a)
 new P.wO().call$0()
@@ -16000,12 +16024,12 @@
 "+call:1:0":0,
 $isEH:true,
 $is_HB:true,
-$is_Dv:true}}],["instance_ref_element","package:observatory/src/observatory_elements/instance_ref.dart",,B,{pR:{"":["Vct;iK%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
+$is_Dv:true}}],["instance_ref_element","package:observatory/src/observatory_elements/instance_ref.dart",,B,{pR:{"":["D13;iK%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
 ghf:function(a){return a.iK
-"37,38,39"},
+"38,39,40"},
 "+instance":1,
 shf:function(a,b){a.iK=this.pD(a,C.fn,a.iK,b)
-"40,31,37,38"},
+"41,32,38,39"},
 "+instance=":1,
 "@":function(){return[C.ay]},
 static:{lu:function(a){var z,y,x,w,v
@@ -16021,12 +16045,12 @@
 C.cp.ZL(a)
 C.cp.FH(a)
 return a
-"18"},"+new InstanceRefElement$created:0:0":1}},"+InstanceRefElement": [88],Vct:{"":"uL+Pi;",$isd3:true}}],["instance_view_element","package:observatory/src/observatory_elements/instance_view.dart",,Z,{hx:{"":["D13;Xh%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
+"19"},"+new InstanceRefElement$created:0:0":1}},"+InstanceRefElement": [90],D13:{"":"uL+Pi;",$isd3:true}}],["instance_view_element","package:observatory/src/observatory_elements/instance_view.dart",,Z,{hx:{"":["WZq;Xh%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
 ghf:function(a){return a.Xh
-"37,38,39"},
+"38,39,40"},
 "+instance":1,
 shf:function(a,b){a.Xh=this.pD(a,C.fn,a.Xh,b)
-"40,31,37,38"},
+"41,32,38,39"},
 "+instance=":1,
 "@":function(){return[C.ql]},
 static:{HC:function(a){var z,y,x,w,v
@@ -16042,7 +16066,7 @@
 C.yK.ZL(a)
 C.yK.FH(a)
 return a
-"19"},"+new InstanceViewElement$created:0:0":1}},"+InstanceViewElement": [89],D13:{"":"uL+Pi;",$isd3:true}}],["isolate_list_element","package:observatory/src/observatory_elements/isolate_list.dart",,L,{u7:{"":["uL;tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
+"20"},"+new InstanceViewElement$created:0:0":1}},"+InstanceViewElement": [91],WZq:{"":"uL+Pi;",$isd3:true}}],["isolate_list_element","package:observatory/src/observatory_elements/isolate_list.dart",,L,{u7:{"":["uL;tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
 "@":function(){return[C.jF]},
 static:{Tt:function(a){var z,y,x,w,v
 z=$.Nd()
@@ -16057,18 +16081,18 @@
 C.Dh.ZL(a)
 C.Dh.FH(a)
 return a
-"20"},"+new IsolateListElement$created:0:0":1}},"+IsolateListElement": [27]}],["isolate_summary_element","package:observatory/src/observatory_elements/isolate_summary.dart",,D,{St:{"":["WZq;Pw%-,i0%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
+"21"},"+new IsolateListElement$created:0:0":1}},"+IsolateListElement": [28]}],["isolate_summary_element","package:observatory/src/observatory_elements/isolate_summary.dart",,D,{St:{"":["pva;Pw%-,i0%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
 gF1:function(a){return a.Pw
-"30,38,39"},
+"31,39,40"},
 "+isolate":1,
 sF1:function(a,b){a.Pw=this.pD(a,C.Y2,a.Pw,b)
-"40,31,30,38"},
+"41,32,31,39"},
 "+isolate=":1,
 goc:function(a){return a.i0
-"8,38,39"},
+"8,39,40"},
 "+name":1,
 soc:function(a,b){a.i0=this.pD(a,C.YS,a.i0,b)
-"40,31,8,38"},
+"41,32,8,39"},
 "+name=":1,
 "@":function(){return[C.aM]},
 static:{N5:function(a){var z,y,x,w,v
@@ -16085,19 +16109,19 @@
 C.nM.ZL(a)
 C.nM.FH(a)
 return a
-"21"},"+new IsolateSummaryElement$created:0:0":1}},"+IsolateSummaryElement": [90],WZq:{"":"uL+Pi;",$isd3:true}}],["json_view_element","package:observatory/src/observatory_elements/json_view.dart",,Z,{vj:{"":["pva;eb%-,kf%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
+"22"},"+new IsolateSummaryElement$created:0:0":1}},"+IsolateSummaryElement": [92],pva:{"":"uL+Pi;",$isd3:true}}],["json_view_element","package:observatory/src/observatory_elements/json_view.dart",,Z,{vj:{"":["cda;eb%-,kf%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
 gTn:function(a){return a.eb
-"40,38,39"},
+"41,39,40"},
 "+json":1,
 sTn:function(a,b){a.eb=this.pD(a,C.Gd,a.eb,b)
-"40,31,40,38"},
+"41,32,41,39"},
 "+json=":1,
 i4:function(a){Z.uL.prototype.i4.call(this,a)
 a.kf=0
-"40"},
+"41"},
 "+enteredView:0:0":1,
 yC:function(a,b){this.pD(a,C.eR,"a","b")
-"40,91,40"},
+"41,93,41"},
 "+jsonChanged:1:0":1,
 gE8:function(a){return J.AG(a.eb)
 "8"},
@@ -16113,24 +16137,24 @@
 gFe:function(a){var z=a.kf
 a.kf=J.WB(z,1)
 return z
-"30"},
+"31"},
 "+counter":1,
 gqC:function(a){var z,y
 z=a.eb
 y=J.x(z)
 if(typeof z==="object"&&z!==null&&(z.constructor===Array||!!y.$isList))return z
 return[]
-"70"},
+"72"},
 "+list":1,
 gvc:function(a){var z,y
 z=a.eb
 y=J.RE(z)
 if(typeof z==="object"&&z!==null&&!!y.$isL8)return J.qA(y.gvc(z))
 return[]
-"70"},
+"72"},
 "+keys":1,
 r6:function(a,b){return J.UQ(a.eb,b)
-"40,78,8"},
+"41,80,8"},
 "+value:1:0":1,
 gP:function(a){return new P.C7(this,Z.vj.prototype.r6,a,"r6")},
 "@":function(){return[C.HN]},
@@ -16149,12 +16173,12 @@
 C.GB.ZL(a)
 C.GB.FH(a)
 return a
-"22"},"+new JsonViewElement$created:0:0":1}},"+JsonViewElement": [92],pva:{"":"uL+Pi;",$isd3:true}}],["library_view_element","package:observatory/src/observatory_elements/library_view.dart",,M,{CX:{"":["cda;iI%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
+"23"},"+new JsonViewElement$created:0:0":1}},"+JsonViewElement": [94],cda:{"":"uL+Pi;",$isd3:true}}],["library_view_element","package:observatory/src/observatory_elements/library_view.dart",,M,{CX:{"":["waa;iI%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
 gtD:function(a){return a.iI
-"37,38,39"},
+"38,39,40"},
 "+library":1,
 stD:function(a,b){a.iI=this.pD(a,C.EV,a.iI,b)
-"40,31,37,38"},
+"41,32,38,39"},
 "+library=":1,
 "@":function(){return[C.Oy]},
 static:{SP:function(a){var z,y,x,w,v,u
@@ -16173,7 +16197,7 @@
 C.MG.ZL(a)
 C.MG.FH(a)
 return a
-"23"},"+new LibraryViewElement$created:0:0":1}},"+LibraryViewElement": [93],cda:{"":"uL+Pi;",$isd3:true}}],["logging","package:logging/logging.dart",,N,{TJ:{"":"a;oc>,eT>,yz,Cj>,wd,Gs",
+"24"},"+new LibraryViewElement$created:0:0":1}},"+LibraryViewElement": [95],waa:{"":"uL+Pi;",$isd3:true}}],["logging","package:logging/logging.dart",,N,{TJ:{"":"a;oc>,eT>,yz,Cj>,wd,Gs",
 gB8:function(){var z,y,x
 z=this.eT
 y=z==null||J.xC(J.DA(z),"")
@@ -16241,26 +16265,27 @@
 giO:function(a){return this.P},
 bu:function(a){return this.oc},
 $isNg:true,
-static:{"":"bR,tm,EL,X8,IQ,Fn,Eb,AN,JY,bo",}},HV:{"":"a;OR<,G1>,iJ,Fl,O0,kc>,I4<",
+static:{"":"bR,tm,EL,X8,IQ,Fn,Eb,AN,JY,ac",}},HV:{"":"a;OR<,G1>,iJ,Fl,O0,kc>,I4<",
 bu:function(a){return"["+this.OR.oc+"] "+this.iJ+": "+this.G1},
 static:{"":"xO",}}}],["message_viewer_element","package:observatory/src/observatory_elements/message_viewer.dart",,L,{Nh:{"":["uL;XB%-,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
 gG1:function(a){return a.XB
-"37,39"},
+"38,40"},
 "+message":1,
 sG1:function(a,b){a.XB=b
 this.pD(a,C.KY,"",this.gQW(a))
 this.pD(a,C.wt,[],this.glc(a))
-"40,94,37,39"},
+"41,96,38,40"},
 "+message=":1,
 gQW:function(a){var z=a.XB
 if(z==null||J.UQ(z,"type")==null)return"Error"
+P.JS("Received message of type '"+H.d(J.UQ(a.XB,"type"))+"' :\n"+H.d(a.XB))
 return J.UQ(a.XB,"type")
 "8"},
 "+messageType":1,
 glc:function(a){var z=a.XB
 if(z==null||J.UQ(z,"members")==null)return[]
 return J.UQ(a.XB,"members")
-"95"},
+"97"},
 "+members":1,
 "@":function(){return[C.c0]},
 static:{rJ:function(a){var z,y,x,w,v
@@ -16276,7 +16301,7 @@
 C.Wp.ZL(a)
 C.Wp.FH(a)
 return a
-"24"},"+new MessageViewerElement$created:0:0":1}},"+MessageViewerElement": [27]}],["metadata","../../../../../../../../../dart/dart-sdk/lib/html/html_common/metadata.dart",,B,{fA:{"":"a;Kr,Jt",static:{"":"Xd,en,yS,PZ,xa",}},tz:{"":"a;"},jR:{"":"a;oc>"},PO:{"":"a;"},c5:{"":"a;"}}],["navigation_bar_element","package:observatory/src/observatory_elements/navigation_bar.dart",,Q,{ih:{"":["uL;tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
+"25"},"+new MessageViewerElement$created:0:0":1}},"+MessageViewerElement": [28]}],["metadata","../../../../../../../../../dart/dart-sdk/lib/html/html_common/metadata.dart",,B,{fA:{"":"a;Kr,Jt",static:{"":"Xd,en,yS,PZ,xa",}},tz:{"":"a;"},jR:{"":"a;oc>"},PO:{"":"a;"},c5:{"":"a;"}}],["navigation_bar_element","package:observatory/src/observatory_elements/navigation_bar.dart",,Q,{ih:{"":["uL;tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
 "@":function(){return[C.KG]},
 static:{BW:function(a){var z,y,x,w,v
 z=$.Nd()
@@ -16291,7 +16316,7 @@
 C.Xg.ZL(a)
 C.Xg.FH(a)
 return a
-"25"},"+new NavigationBarElement$created:0:0":1}},"+NavigationBarElement": [27]}],["observatory","package:observatory/observatory.dart",,L,{mL:{"":["Pi;Z6<-,lw<-,nI<-,VJ,Ai",function(){return[C.mI]},function(){return[C.mI]},function(){return[C.mI]},null,null],
+"26"},"+new NavigationBarElement$created:0:0":1}},"+NavigationBarElement": [28]}],["observatory","package:observatory/observatory.dart",,L,{mL:{"":["Pi;Z6<-,lw<-,nI<-,VJ,Ai",function(){return[C.mI]},function(){return[C.mI]},function(){return[C.mI]},null,null],
 Ey:function(){var z,y,x
 z=this.Z6
 z.sJR(this)
@@ -16325,16 +16350,16 @@
 y.US()
 return y}}},bv:{"":["Pi;nk,SS,XR<-,VJ,Ai",null,null,function(){return[C.mI]},null,null],
 gjO:function(a){return this.nk
-"30,38,43"},
+"31,39,45"},
 "+id":1,
 sjO:function(a,b){this.nk=F.Wi(this,C.EN,this.nk,b)
-"40,31,30,38"},
+"41,32,31,39"},
 "+id=":1,
 goc:function(a){return this.SS
-"8,38,43"},
+"8,39,45"},
 "+name":1,
 soc:function(a,b){this.SS=F.Wi(this,C.YS,this.SS,b)
-"40,31,8,38"},
+"41,32,8,39"},
 "+name=":1,
 bu:function(a){return H.d(this.nk)+" "+H.d(this.SS)},
 $isbv:true},pt:{"":["Pi;JR?,i2<-,VJ,Ai",null,function(){return[C.mI]},null,null],
@@ -16387,16 +16412,16 @@
 $is_HB:true,
 $is_Dv:true},dZ:{"":"Pi;JR?,IT,Jj,VJ,Ai",
 gzd:function(){return this.IT
-"8,38,43"},
+"8,39,45"},
 "+currentHash":1,
 szd:function(a){this.IT=F.Wi(this,C.h1,this.IT,a)
-"40,31,8,38"},
+"41,32,8,39"},
 "+currentHash=":1,
 glD:function(){return this.Jj
-"96,38,43"},
+"98,39,45"},
 "+currentHashUri":1,
 slD:function(a){this.Jj=F.Wi(this,C.tv,this.Jj,a)
-"40,31,96,38"},
+"41,32,98,39"},
 "+currentHashUri=":1,
 kI:function(){var z,y
 z=C.PP.aM(window)
@@ -16438,35 +16463,35 @@
 PI:function(a){var z=this.R6()
 if(J.xC(z,0))return"#/isolates/"
 return"#/isolates/"+H.d(z)+"/"+H.d(a)
-"8,97,8,43"},
+"8,99,8,45"},
 "+currentIsolateRelativeLink:1:0":1,
 Ao:function(a){var z=this.R6()
 if(J.xC(z,0))return"#/isolates/"
 return"#/isolates/"+H.d(z)+"/objects/"+H.d(a)
-"8,98,30,43"},
+"8,100,31,45"},
 "+currentIsolateObjectLink:1:0":1,
 dL:function(a){var z=this.R6()
 if(J.xC(z,0))return"#/isolates/"
 return"#/isolates/"+H.d(z)+"/classes/"+H.d(a)
-"8,99,30,43"},
+"8,101,31,45"},
 "+currentIsolateClassLink:1:0":1,
 WW:function(a,b){var z=this.R6()
 if(J.xC(z,0))return"#/isolates/"
 return this.yX(z,a,b)
-"8,98,30,7,8,43"},
+"8,100,31,7,8,45"},
 "+currentIsolateScriptLink:2:0":1,
 r4:function(a,b){return"#/isolates/"+H.d(a)+"/"+H.d(b)
-"8,100,30,97,8,43"},
+"8,102,31,99,8,45"},
 "+relativeLink:2:0":1,
 Dd:function(a,b){return"#/isolates/"+H.d(a)+"/objects/"+H.d(b)
-"8,100,30,98,30,43"},
+"8,102,31,100,31,45"},
 "+objectLink:2:0":1,
 bD:function(a,b){return"#/isolates/"+H.d(a)+"/classes/"+H.d(b)
-"8,100,30,99,30,43"},
+"8,102,31,101,31,45"},
 "+classLink:2:0":1,
 yX:function(a,b,c){var z=P.jW(C.kg,c,!0)
 return"#/isolates/"+H.d(a)+"/objects/"+H.d(b)+"?type=Script&name="+z
-"8,100,30,98,30,7,8,43"},
+"8,102,31,100,31,7,8,45"},
 "+scriptLink:3:0":1,
 static:{"":"kx,K3D,qY",}},Qe:{"":"Tp;a",
 call$1:function(a){var z=this.a
@@ -16478,16 +16503,16 @@
 $is_Dv:true},Nu:{"":"Pi;JR?,e0?",
 pG:function(){return this.e0.call$0()},
 gEI:function(){return this.oJ
-"8,38,43"},
+"8,39,45"},
 "+prefix":1,
 sEI:function(a){this.oJ=F.Wi(this,C.qb,this.oJ,a)
-"40,31,8,38"},
+"41,32,8,39"},
 "+prefix=":1,
 gn2:function(){return this.vm
-"95,38,43"},
+"97,39,45"},
 "+responses":1,
 sn2:function(a){this.vm=F.Wi(this,C.wH,this.vm,a)
-"40,31,95,38"},
+"41,32,97,39"},
 "+responses=":1,
 Qn:function(a){var z,y
 z=C.lM.kV(a)
@@ -16574,13 +16599,13 @@
 J.Ih(W.uV(window.parent),C.lM.KP(y),"*")
 return w.MM}},Zw:{"":["Pi;Rd,n7,LA>-,Vg,VJ,Ai",null,null,function(){return[C.mI]},null,null,null],
 geV:function(){return this.Vg
-"8,38,43"},
+"8,39,45"},
 "+paddedLine":1,
 seV:function(a){var z=this.Vg
 if(this.gUV(this)&&!J.xC(z,a)){z=new T.qI(this,C.X9,z,a)
 z.$builtinTypeInfo=[null]
 this.SZ(this,z)}this.Vg=a
-"40,31,8,38"},
+"41,32,8,39"},
 "+paddedLine=":1,
 QQ:function(a,b,c){var z,y,x,w,v
 z=""+this.Rd
@@ -16594,22 +16619,22 @@
 z.QQ(a,b,c)
 return z}}},Pf:{"":"Pi;WF,uM,ZQ,VJ,Ai",
 gfY:function(a){return this.WF
-"8,38,43"},
+"8,39,45"},
 "+kind":1,
 sfY:function(a,b){this.WF=F.Wi(this,C.fy,this.WF,b)
-"40,31,8,38"},
+"41,32,8,39"},
 "+kind=":1,
 gO3:function(a){return this.uM
-"8,38,43"},
+"8,39,45"},
 "+url":1,
 sO3:function(a,b){this.uM=F.Wi(this,C.Fh,this.uM,b)
-"40,31,8,38"},
+"41,32,8,39"},
 "+url=":1,
 gXJ:function(){return this.ZQ
-"101,38,43"},
+"103,39,45"},
 "+lines":1,
 sXJ:function(a){this.ZQ=F.Wi(this,C.Cv,this.ZQ,a)
-"40,31,101,38"},
+"41,32,103,39"},
 "+lines=":1,
 Cn:function(a){var z,y,x,w,v
 z=J.uH(a,"\n")
@@ -16629,17 +16654,17 @@
 static:{Sp:function(a){var z=R.Jk([])
 z=new L.Pf("","",z,null,null)
 z.EQ(a)
-return z}}}}],["observatory_application_element","package:observatory/src/observatory_elements/observatory_application.dart",,V,{F1:{"":["waa;k5%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
+return z}}}}],["observatory_application_element","package:observatory/src/observatory_elements/observatory_application.dart",,V,{F1:{"":["V0;k5%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
 gzj:function(a){return a.k5
-"44,38,39"},
+"46,39,40"},
 "+devtools":1,
 szj:function(a,b){a.k5=this.pD(a,C.Na,a.k5,b)
-"40,31,44,38"},
+"41,32,46,39"},
 "+devtools=":1,
 ZB:function(a){var z
 if(a.k5===!0){z=L.WS()
 a.tH=this.pD(a,C.wh,a.tH,z)}else{z=L.AK()
-a.tH=this.pD(a,C.wh,a.tH,z)}"40"},
+a.tH=this.pD(a,C.wh,a.tH,z)}"41"},
 "@":function(){return[C.bd]},
 static:{fv:function(a){var z,y,x,w,v
 z=$.Nd()
@@ -16656,23 +16681,23 @@
 C.k0.FH(a)
 C.k0.ZB(a)
 return a
-"26"},"+new ObservatoryApplicationElement$created:0:0":1}},"+ObservatoryApplicationElement": [102],waa:{"":"uL+Pi;",$isd3:true}}],["observatory_element","package:observatory/src/observatory_elements/observatory_element.dart",,Z,{uL:{"":["Nr;tH%-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
+"27"},"+new ObservatoryApplicationElement$created:0:0":1}},"+ObservatoryApplicationElement": [104],V0:{"":"uL+Pi;",$isd3:true}}],["observatory_element","package:observatory/src/observatory_elements/observatory_element.dart",,Z,{uL:{"":["Nr;tH%-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
 i4:function(a){A.dM.prototype.i4.call(this,a)
-"40"},
+"41"},
 "+enteredView:0:0":1,
 Nz:function(a){A.dM.prototype.Nz.call(this,a)
-"40"},
+"41"},
 "+leftView:0:0":1,
 gQG:function(a){return a.tH
-"103,38,39"},
+"105,39,40"},
 "+app":1,
 sQG:function(a,b){a.tH=this.pD(a,C.wh,a.tH,b)
-"40,31,103,38"},
+"41,32,105,39"},
 "+app=":1,
 gpQ:function(a){return!0
-"44"},
+"46"},
 "+applyAuthorStyles":1,
-"@":function(){return[C.J0]},
+"@":function(){return[C.Br]},
 static:{Hx:function(a){var z,y,x,w,v
 z=$.Nd()
 y=P.Py(null,null,null,J.O,W.I0)
@@ -16686,7 +16711,7 @@
 C.mk.ZL(a)
 C.mk.FH(a)
 return a
-"27"},"+new ObservatoryElement$created:0:0":1}},"+ObservatoryElement": [104],Nr:{"":"ir+Pi;",$isd3:true}}],["observe.src.change_notifier","package:observe/src/change_notifier.dart",,O,{Pi:{"":"a;",
+"28"},"+new ObservatoryElement$created:0:0":1}},"+ObservatoryElement": [106],Nr:{"":"ir+Pi;",$isd3:true}}],["observe.src.change_notifier","package:observe/src/change_notifier.dart",,O,{Pi:{"":"a;",
 gqh:function(a){var z,y
 if(a.VJ==null){z=this.gqw(a)
 a.VJ=P.bK(this.gl1(a),z,!0,null)}z=a.VJ
@@ -16730,7 +16755,7 @@
 gB:function(a){return this.b9.length},
 "+length":0,
 gP:function(a){return this.Sv
-"40,38"},
+"41,39"},
 "+value":1,
 r6:function(a,b){return this.gP(a).call$1(b)},
 wE:function(a){var z,y,x,w
@@ -17055,11 +17080,11 @@
 $isEH:true,
 $is_bh:true}}],["observe.src.observable_box","package:observe/src/observable_box.dart",,A,{xh:{"":"Pi;",
 gP:function(a){return this.L1
-"105,38"},
+"107,39"},
 "+value":1,
 r6:function(a,b){return this.gP(a).call$1(b)},
 sP:function(a,b){this.L1=F.Wi(this,C.ls,this.L1,b)
-"40,106,105,38"},
+"41,108,107,39"},
 "+value=":1,
 bu:function(a){return"#<"+H.d(new H.cu(H.dJ(this),null))+" value: "+H.d(this.L1)+">"}}}],["observe.src.observable_list","package:observe/src/observable_list.dart",,Q,{wn:{"":"uF;b3,xg,h3,VJ,Ai",
 gRT:function(){var z,y
@@ -17070,7 +17095,7 @@
 H.VM(y,[H.W8(z,"WV",0)])
 return y},
 gB:function(a){return this.h3.length
-"30,38"},
+"31,39"},
 "+length":1,
 sB:function(a,b){var z,y,x,w,v,u,t
 z=this.h3
@@ -17099,12 +17124,12 @@
 w=new P.Yp(t)
 w.$builtinTypeInfo=[null]
 this.iH(new G.W4(this,w,t,y,x))}}C.Nm.sB(z,b)
-"40,31,30,38"},
+"41,32,31,39"},
 "+length=":1,
 t:function(a,b){var z=this.h3
 if(b>>>0!==b||b>=z.length)throw H.e(z,b)
 return z[b]
-"107,29,30,38"},
+"109,30,31,39"},
 "+[]:1:0":1,
 u:function(a,b,c){var z,y,x,w
 z=this.h3
@@ -17118,7 +17143,7 @@
 w.$builtinTypeInfo=[null]
 this.iH(new G.W4(this,w,x,b,1))}if(b>=z.length)throw H.e(z,b)
 z[b]=c
-"40,29,30,31,107,38"},
+"41,30,31,32,109,39"},
 "+[]=:2:0":1,
 h:function(a,b){var z,y,x,w
 z=this.h3
@@ -17207,33 +17232,33 @@
 $isHA:true},br:{"":"Pi;Zp,VJ,Ai",
 gvc:function(a){var z=this.Zp
 return z.gvc(z)
-"108,38"},
+"110,39"},
 "+keys":1,
 gUQ:function(a){var z=this.Zp
 return z.gUQ(z)
-"109,38"},
+"111,39"},
 "+values":1,
 gB:function(a){var z=this.Zp
 return z.gB(z)
-"30,38"},
+"31,39"},
 "+length":1,
 gl0:function(a){var z=this.Zp
 return z.gB(z)===0
-"44,38"},
+"46,39"},
 "+isEmpty":1,
 gor:function(a){var z=this.Zp
 return z.gB(z)!==0
-"44,38"},
+"46,39"},
 "+isNotEmpty":1,
 PF:function(a){return this.Zp.PF(a)
-"44,31,0,38"},
+"46,32,0,39"},
 "+containsValue:1:0":1,
 x4:function(a){return this.Zp.x4(a)
-"44,78,0,38"},
+"46,80,0,39"},
 "+containsKey:1:0":1,
 t:function(a,b){var z=this.Zp
 return z.t(z,b)
-"110,78,0,38"},
+"112,80,0,39"},
 "+[]:1:0":1,
 u:function(a,b,c){var z,y,x,w,v
 z=this.Zp
@@ -17250,7 +17275,7 @@
 z.$builtinTypeInfo=[null,null]
 this.SZ(this,z)}else if(!J.xC(x,c)){z=new V.HA(b,x,c,!1,!1)
 z.$builtinTypeInfo=[null,null]
-this.SZ(this,z)}"40,78,111,31,110,38"},
+this.SZ(this,z)}"41,80,113,32,112,39"},
 "+[]=:2:0":1,
 Ay:function(a,b){b.aN(b,new V.zT(this))},
 Rz:function(a,b){var z,y,x,w,v
@@ -17361,7 +17386,7 @@
 z=y==null?z!=null:y!==z}else z=!1
 if(!z)this.ov()
 return C.Nm.grZ(this.kN)
-"40,38"},
+"41,39"},
 "+value":1,
 r6:function(a,b){return this.gP(a).call$1(b)},
 sP:function(a,b){var z,y,x,w
@@ -17379,7 +17404,7 @@
 if(w>=z.length)throw H.e(z,w)
 if(L.h6(x,z[w],b)){z=this.kN
 if(y>=z.length)throw H.e(z,y)
-z[y]=b}"40,106,0,38"},
+z[y]=b}"41,108,0,39"},
 "+value=":1,
 w3:function(a){O.Pi.prototype.w3.call(this,this)
 this.ov()
@@ -18541,7 +18566,7 @@
 y=typeof z==="object"&&z!==null&&!!y.$isEZ}else y=!1}else y=!1
 if(y)return
 return new T.Xy(this,b,z)},
-gca:function(){return new T.Dw(this,T.e9.prototype.yt,null,"yt")},
+gca:function(){return new T.PD(this,T.e9.prototype.yt,null,"yt")},
 A5:function(a){return new T.uK(this)}},Xy:{"":"Tp;a,b,c",
 call$2:function(a,b){var z=J.x(a)
 if(typeof a!=="object"||a===null||!z.$isz6)a=new K.z6(null,a,V.WF(this.a.nF,null,null),null)
@@ -18568,14 +18593,14 @@
 F.Wi(this,C.ls,z,this.uK)},
 gnc:function(){return new H.Pm(this,T.mY.prototype.vr,null,"vr")},
 gP:function(a){return this.uK
-"40,38"},
+"41,39"},
 "+value":1,
 r6:function(a,b){return this.gP(a).call$1(b)},
 sP:function(a,b){var z,y,x,w
 try{K.jX(this.jf,b,this.qc)}catch(y){x=H.Ru(y)
 w=J.x(x)
 if(typeof x==="object"&&x!==null&&!!w.$isB0){z=x
-$.IS().A3("Error evaluating expression '"+H.d(this.jf)+"': "+J.z2(z))}else throw y}"40,112,40,38"},
+$.IS().A3("Error evaluating expression '"+H.d(this.jf)+"': "+J.z2(z))}else throw y}"41,114,41,39"},
 "+value=":1,
 Va:function(a,b,c){var z,y,x,w,v
 y=this.jf
@@ -19037,7 +19062,7 @@
 return 536870911&a+((16383&a)<<15>>>0)},Fq:{"":"a;",
 F2:function(a,b,c){return new U.RW(a,b,c)},
 "+invoke:3:0":0,
-"*invoke":[40],
+"*invoke":[41],
 CI:function(a,b){return this.F2(a,b,null)},
 "+invoke:2:0":0},hw:{"":"a;",$ishw:true},EZ:{"":"hw;",
 RR:function(a,b){return b.W9(this)},
@@ -19331,7 +19356,7 @@
 static:{i0:function(a,b,c){var z=new K.Ae(a,b)
 H.VM(z,[c])
 return z
-"28,29,30,31,32"},"+new IndexedValue:2:0":1}},"+IndexedValue": [0],Bt:{"":"mW;YR",
+"29,30,31,32,33"},"+new IndexedValue:2:0":1}},"+IndexedValue": [0],Bt:{"":"mW;YR",
 gA:function(a){var z=J.GP(this.YR)
 z=new K.vR(z,0,null)
 H.VM(z,[H.W8(this,"Bt",0)])
@@ -19525,15 +19550,15 @@
 C.Cc.ZL(a)
 C.Cc.FH(a)
 return a
-"33"},"+new ResponseViewerElement$created:0:0":1}},"+ResponseViewerElement": [27]}],["script_view_element","package:observatory/src/observatory_elements/script_view.dart",,U,{fI:{"":["V0;Uz%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
+"34"},"+new ResponseViewerElement$created:0:0":1}},"+ResponseViewerElement": [28]}],["script_view_element","package:observatory/src/observatory_elements/script_view.dart",,U,{fI:{"":["V4;Uz%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
 gNl:function(a){return a.Uz
-"37,38,39"},
+"38,39,40"},
 "+script":1,
 sNl:function(a,b){a.Uz=this.pD(a,C.fX,a.Uz,b)
-"40,31,37,38"},
+"41,32,38,39"},
 "+script=":1,
 "@":function(){return[C.Er]},
-static:{Ry:function(a){var z,y,x,w,v
+static:{kL:function(a){var z,y,x,w,v
 z=$.Nd()
 y=P.Py(null,null,null,J.O,W.I0)
 x=J.O
@@ -19546,12 +19571,12 @@
 C.cJ.ZL(a)
 C.cJ.FH(a)
 return a
-"34"},"+new ScriptViewElement$created:0:0":1}},"+ScriptViewElement": [113],V0:{"":"uL+Pi;",$isd3:true}}],["source_view_element","package:observatory/src/observatory_elements/source_view.dart",,X,{kK:{"":["V4;vX%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
+"35"},"+new ScriptViewElement$created:0:0":1}},"+ScriptViewElement": [115],V4:{"":"uL+Pi;",$isd3:true}}],["source_view_element","package:observatory/src/observatory_elements/source_view.dart",,X,{kK:{"":["V6;vX%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
 gFF:function(a){return a.vX
-"114,38,39"},
+"116,39,40"},
 "+source":1,
 sFF:function(a,b){a.vX=this.pD(a,C.hn,a.vX,b)
-"40,31,114,38"},
+"41,32,116,39"},
 "+source=":1,
 "@":function(){return[C.H8]},
 static:{HO:function(a){var z,y,x,w,v
@@ -19567,12 +19592,12 @@
 C.Ks.ZL(a)
 C.Ks.FH(a)
 return a
-"35"},"+new SourceViewElement$created:0:0":1}},"+SourceViewElement": [115],V4:{"":"uL+Pi;",$isd3:true}}],["stack_trace_element","package:observatory/src/observatory_elements/stack_trace.dart",,X,{uw:{"":["V6;V4%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
+"36"},"+new SourceViewElement$created:0:0":1}},"+SourceViewElement": [117],V6:{"":"uL+Pi;",$isd3:true}}],["stack_trace_element","package:observatory/src/observatory_elements/stack_trace.dart",,X,{uw:{"":["V8;V4%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
 gtN:function(a){return a.V4
-"37,38,39"},
+"38,39,40"},
 "+trace":1,
 stN:function(a,b){a.V4=this.pD(a,C.kw,a.V4,b)
-"40,31,37,38"},
+"41,32,38,39"},
 "+trace=":1,
 "@":function(){return[C.js]},
 static:{bV:function(a){var z,y,x,w,v,u
@@ -19591,7 +19616,7 @@
 C.bg.ZL(a)
 C.bg.FH(a)
 return a
-"36"},"+new StackTraceElement$created:0:0":1}},"+StackTraceElement": [116],V6:{"":"uL+Pi;",$isd3:true}}],["template_binding","package:template_binding/template_binding.dart",,M,{IP:function(a){var z=J.RE(a)
+"37"},"+new StackTraceElement$created:0:0":1}},"+StackTraceElement": [118],V8:{"":"uL+Pi;",$isd3:true}}],["template_binding","package:template_binding/template_binding.dart",,M,{IP:function(a){var z=J.RE(a)
 if(typeof a==="object"&&a!==null&&!!z.$isQl)return C.io.f0(a)
 switch(z.gr9(a)){case"checkbox":return $.FF().aM(a)
 case"radio":case"select-multiple":case"select-one":return z.gEr(a)
@@ -20671,6 +20696,7 @@
 if(typeof a!="object")return a
 if(a instanceof P.a)return a
 return J.ks(a)}
+C.J0=B.G6.prototype
 C.OL=new U.EZ()
 C.Gw=new H.SJ()
 C.E3=new J.Q()
@@ -20691,7 +20717,7 @@
 C.YD=F.Be.prototype
 C.j8=R.i6.prototype
 C.Vy=new A.V3("disassembly-entry")
-C.J0=new A.V3("observatory-element")
+C.Br=new A.V3("observatory-element")
 C.Er=new A.V3("script-view")
 C.ht=new A.V3("field-ref")
 C.aM=new A.V3("isolate-summary")
@@ -20703,6 +20729,7 @@
 C.c0=new A.V3("message-viewer")
 C.js=new A.V3("stack-trace")
 C.jF=new A.V3("isolate-list")
+C.PT=new A.V3("breakpoint-list")
 C.KG=new A.V3("navigation-bar")
 C.ay=new A.V3("instance-ref")
 C.Gu=new A.V3("collapsible-content")
@@ -20936,6 +20963,7 @@
 C.PC=new H.GD("dart.core.int")
 C.wt=new H.GD("members")
 C.KY=new H.GD("messageType")
+C.Ry=new H.GD("msg")
 C.YS=new H.GD("name")
 C.OV=new H.GD("noSuchMethod")
 C.Ws=new H.GD("operatingSystem")
@@ -20963,14 +20991,15 @@
 C.Ti=H.mm('wn')
 C.Mt=new H.Lm(C.Ti,"E",0)
 C.Ye=H.mm('hx')
-C.G6=H.mm('F1')
+C.bD=H.mm('F1')
 C.NM=H.mm('Nh')
+C.z7=H.mm('G6')
 C.nY=H.mm('a')
 C.Yc=H.mm('iP')
 C.LN=H.mm('Be')
 C.Qa=H.mm('u7')
 C.xS=H.mm('UZ')
-C.PT=H.mm('CX')
+C.mA=H.mm('CX')
 C.Op=H.mm('G8')
 C.xF=H.mm('NQ')
 C.b4=H.mm('ih')
@@ -21175,8 +21204,8 @@
 J.z2=function(a){return J.RE(a).gG1(a)}
 J.zZ=function(a,b){return J.RE(a).Yv(a,b)}
 J.zj=function(a){return J.RE(a).gvH(a)}
-$.Dq=["Ay","BN","BT","Ba","C","C0","C8","Ch","D","D3","D6","Dh","E","Ec","F","FH","Fr","GB","HG","Hn","Id","Ih","Im","Is","J","J3","JP","JT","JV","Ja","Jk","Kb","LV","Md","Mi","Mu","Nj","Nz","O","On","PM","Pa","Pk","Pv","R3","R4","RB","RR","Rz","SZ","T","T2","TH","TP","TW","Tc","Td","U","UD","UH","UZ","Uc","V","V1","Vr","Vy","W","W3","W4","WO","WZ","Wt","Wz","X6","XG","XU","Xl","Y9","YU","YW","Ys","Yv","Z","Z1","Z2","ZB","ZF","ZL","ZP","Zv","aC","aN","aq","bA","bS","br","bu","cO","cn","d0","dR","dd","du","eR","ea","er","es","ev","ez","f6","fd","fj","fk","fm","g","gA","gB","gBb","gCd","gCj","gDD","gDg","gE8","gEX","gEr","gF1","gFF","gFJ","gFT","gFV","gFe","gG0","gG1","gG3","gGL","gHs","gI","gIi","gJS","gJf","gKE","gKM","gKV","gLA","gLU","gLf","gLm","gM0","gMB","gMj","gN","gNI","gNl","gO3","gP","gP1","gP2","gPp","gPu","gPw","gPy","gQ0","gQG","gQW","gQg","gRn","gRu","gT8","gTM","gTn","gTq","gUQ","gUV","gUz","gV4","gVA","gVB","gVl","gXB","gXf","gXh","gXt","gZw","gai","gbP","gbx","gcC","geT","geb","gey","gfY","ghO","ghf","ghr","gi0","giC","giI","giK","giO","gig","gjL","gjO","gjU","gjb","gk5","gkU","gkc","gkf","gkp","gl0","gl7","glc","gmW","gmm","gn4","goc","gor","gpQ","gpo","gq6","gqC","gqh","gql","gr3","gr9","grK","grZ","gt0","gtD","gtH","gtN","gtT","guD","gvH","gvX","gvc","gvt","gxj","gxr","gyT","gys","gzP","gzZ","gzj","h","h8","hV","hc","i","i4","iA","iM","iw","j","jT","jx","kO","l5","l8","lj","m","mK","mv","n","nB","nC","nH","nP","ni","oB","oW","od","oo","oq","pD","pZ","pl","pr","qZ","r6","rJ","rS","sB","sF1","sFF","sFJ","sFT","sG1","sIt","sLA","sLf","sMj","sNI","sNl","sO3","sP","sP2","sPw","sPy","sQG","sRu","sTn","sTq","sUz","sV4","sVA","sVB","sXB","sXf","sXh","sZw","sa4","sai","scC","seb","sfY","shO","shf","si0","siI","siK","sig","sjO","sk5","skc","skf","sl7","soc","sql","sr9","st0","stD","stH","stN","stT","svX","svt","sxj","sxr","szZ","szj","t","tZ","tg","tt","u","u5","u8","uG","vs","w3","wE","wL","wR","wg","x3","xI","xc","xe","y0","yC","yc","ym","yn","yq","yu","yx","yy","z2","zV"]
-$.Au=[C.Ye,Z.hx,{created:Z.HC},C.G6,V.F1,{created:V.fv},C.NM,L.Nh,{created:L.rJ},C.LN,F.Be,{created:F.Fe},C.Qa,L.u7,{created:L.Tt},C.xS,P.UZ,{},C.PT,M.CX,{created:M.SP},C.Op,P.G8,{},C.xF,Q.NQ,{created:Q.Zo},C.b4,Q.ih,{created:Q.BW},C.Ob,X.kK,{created:X.HO},C.hG,A.ir,{created:A.oa},C.aj,U.fI,{created:U.Ry},C.mo,E.Fv,{created:E.AH},C.xE,Z.aC,{created:Z.zg},C.vuj,X.uw,{created:X.bV},C.j6,D.qr,{created:D.ip},C.C6,Z.vj,{created:Z.un},C.CT,D.St,{created:D.N5},C.Q4,Z.uL,{created:Z.Hx},C.yg,F.I3,{created:F.TW},C.XU,R.i6,{created:R.IT},C.Bm,A.XP,{created:A.XL},C.Wz,B.pR,{created:B.lu},C.mnH,N.Ds,{created:N.p7},C.XK,A.Gk,{created:A.cY}]
+$.Dq=["Ay","BN","BT","Ba","C","C0","C8","Ch","D","D3","D6","Dh","E","Ec","F","FH","Fr","GB","HG","Hn","Id","Ih","Im","Is","J","J3","JP","JT","JV","Ja","Jk","Kb","LV","Md","Mi","Mu","Nj","Nz","O","On","PM","Pa","Pk","Pv","R3","R4","RB","RR","Rz","SZ","T","T2","TH","TP","TW","Tc","Td","U","UD","UH","UZ","Uc","V","V1","Vr","Vy","W","W3","W4","WO","WZ","Wt","Wz","X6","XG","XU","Xl","Y9","YU","YW","Ys","Yv","Z","Z1","Z2","ZB","ZF","ZL","ZP","Zv","aC","aN","aq","bA","bS","br","bu","cO","cn","d0","dR","dd","du","eR","ea","er","es","ev","ez","f6","fd","fj","fk","fm","g","gA","gB","gBb","gCd","gCj","gDD","gDg","gE8","gEX","gEr","gF1","gFF","gFJ","gFT","gFV","gFe","gG0","gG1","gG3","gGL","gHs","gI","gIi","gJS","gJf","gKE","gKM","gKV","gLA","gLU","gLf","gLm","gM0","gMB","gMj","gN","gNI","gNl","gO3","gP","gP1","gP2","gPp","gPu","gPw","gPy","gQ0","gQG","gQW","gQg","gRn","gRu","gT8","gTM","gTn","gTq","gUQ","gUV","gUz","gV4","gVA","gVB","gVl","gXB","gXf","gXh","gXt","gZw","gai","gbP","gbx","gcC","geE","geT","geb","gey","gfY","ghO","ghf","ghr","gi0","giC","giI","giK","giO","gig","gjL","gjO","gjU","gjb","gk5","gkU","gkc","gkf","gkp","gl0","gl7","glc","gmW","gmm","gn4","goc","gor","gpQ","gpo","gq6","gqC","gqh","gql","gr3","gr9","grK","grZ","grs","gt0","gtD","gtH","gtN","gtT","guD","gvH","gvX","gvc","gvt","gxj","gxr","gyT","gys","gzP","gzZ","gzj","h","h8","hV","hc","i","i4","iA","iM","iw","j","jT","jx","kO","l5","l8","lj","m","mK","mv","n","nB","nC","nH","nP","ni","oB","oW","od","oo","oq","pD","pZ","pl","pr","qZ","r6","rJ","rS","sB","sF1","sFF","sFJ","sFT","sG1","sIt","sLA","sLf","sMj","sNI","sNl","sO3","sP","sP2","sPw","sPy","sQG","sRu","sTn","sTq","sUz","sV4","sVA","sVB","sXB","sXf","sXh","sZw","sa4","sai","scC","seE","seb","sfY","shO","shf","si0","siI","siK","sig","sjO","sk5","skc","skf","sl7","soc","sql","sr9","srs","st0","stD","stH","stN","stT","svX","svt","sxj","sxr","szZ","szj","t","tZ","tg","tt","u","u5","u8","uG","vs","w3","wE","wL","wR","wg","x3","xI","xc","xe","y0","yC","yc","ym","yn","yq","yu","yx","yy","z2","zV"]
+$.Au=[C.Ye,Z.hx,{created:Z.HC},C.bD,V.F1,{created:V.fv},C.NM,L.Nh,{created:L.rJ},C.z7,B.G6,{created:B.Dw},C.LN,F.Be,{created:F.Fe},C.Qa,L.u7,{created:L.Tt},C.xS,P.UZ,{},C.mA,M.CX,{created:M.SP},C.Op,P.G8,{},C.xF,Q.NQ,{created:Q.Zo},C.b4,Q.ih,{created:Q.BW},C.Ob,X.kK,{created:X.HO},C.hG,A.ir,{created:A.oa},C.aj,U.fI,{created:U.kL},C.mo,E.Fv,{created:E.AH},C.xE,Z.aC,{created:Z.zg},C.vuj,X.uw,{created:X.bV},C.j6,D.qr,{created:D.ip},C.C6,Z.vj,{created:Z.un},C.CT,D.St,{created:D.N5},C.Q4,Z.uL,{created:Z.Hx},C.yg,F.I3,{created:F.TW},C.XU,R.i6,{created:R.IT},C.Bm,A.XP,{created:A.XL},C.Wz,B.pR,{created:B.lu},C.mnH,N.Ds,{created:N.p7},C.XK,A.Gk,{created:A.cY}]
 I.$lazy($,"globalThis","DX","jk",function(){return function() { return this; }()})
 I.$lazy($,"globalWindow","pG","Qm",function(){return $.jk().window})
 I.$lazy($,"globalWorker","zA","Nl",function(){return $.jk().Worker})
@@ -21276,7 +21305,7 @@
 return z})
 
 init.functionAliases={}
-init.metadata=[P.a,C.wK,C.wa,C.WX,C.Mt,C.wW,P.uq,"name",J.O,Z.aC,F.Be,R.i6,W.K5,E.Fv,F.I3,D.qr,A.Gk,N.Ds,B.pR,Z.hx,L.u7,D.St,Z.vj,M.CX,L.Nh,Q.ih,V.F1,Z.uL,[K.Ae,3],"index",J.im,"value",3,Q.NQ,U.fI,X.kK,X.uw,P.L8,C.nJ,C.Us,,Z.Vf,F.tu,C.mI,J.kn,"r","e",W.ea,"detail","target",W.KV,R.Vc,[P.L8,P.wv,P.RS],[J.Q,H.Zk],"methodOwner",P.NL,[J.Q,P.RY],"fieldOwner",[P.L8,P.wv,P.RY],[P.L8,P.wv,P.QF],[P.L8,P.wv,P.NL],P.vr,"fieldName",P.wv,"arg",H.Uz,[J.Q,P.vr],P.Ms,"memberName","positionalArguments",J.Q,"namedArguments",[P.L8,P.wv,null],[J.Q,P.Ms],"owner",[J.Q,P.Fw],[J.Q,P.L9u],H.Un,"key",P.QF,H.Tp,"tv","i",E.WZ,F.pv,D.Vfx,A.Dsd,N.tuj,B.Vct,Z.D13,D.WZq,"oldValue",Z.pva,M.cda,"m",[J.Q,P.L8],P.iD,"l","objectId","cid","isolateId",[J.Q,L.Zw],V.waa,L.mL,Z.Nr,5,"newValue",4,[P.cX,1],[P.cX,2],2,1,"v",U.V0,L.Pf,X.V4,X.V6,];$=null
+init.metadata=[P.a,C.wK,C.wa,C.WX,C.Mt,C.wW,P.uq,"name",J.O,B.G6,Z.aC,F.Be,R.i6,W.K5,E.Fv,F.I3,D.qr,A.Gk,N.Ds,B.pR,Z.hx,L.u7,D.St,Z.vj,M.CX,L.Nh,Q.ih,V.F1,Z.uL,[K.Ae,3],"index",J.im,"value",3,Q.NQ,U.fI,X.kK,X.uw,P.L8,C.nJ,C.Us,,B.Vf,Z.tu,F.Vc,C.mI,J.kn,"r","e",W.ea,"detail","target",W.KV,R.WZ,[P.L8,P.wv,P.RS],[J.Q,H.Zk],"methodOwner",P.NL,[J.Q,P.RY],"fieldOwner",[P.L8,P.wv,P.RY],[P.L8,P.wv,P.QF],[P.L8,P.wv,P.NL],P.vr,"fieldName",P.wv,"arg",H.Uz,[J.Q,P.vr],P.Ms,"memberName","positionalArguments",J.Q,"namedArguments",[P.L8,P.wv,null],[J.Q,P.Ms],"owner",[J.Q,P.Fw],[J.Q,P.L9u],H.Un,"key",P.QF,H.Tp,"tv","i",E.pv,F.Vfx,D.Dsd,A.tuj,N.Vct,B.D13,Z.WZq,D.pva,"oldValue",Z.cda,M.waa,"m",[J.Q,P.L8],P.iD,"l","objectId","cid","isolateId",[J.Q,L.Zw],V.V0,L.mL,Z.Nr,5,"newValue",4,[P.cX,1],[P.cX,2],2,1,"v",U.V4,L.Pf,X.V6,X.V8,];$=null
 I = I.$finishIsolateConstructor(I)
 $=new I()
 function convertToFastObject(properties) {
@@ -23577,6 +23606,35 @@
 $desc=$collectedClasses.tQ
 if($desc instanceof Array)$desc=$desc[1]
 tQ.prototype=$desc
+function G6(eE,VJ,Ai,tH,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM){this.eE=eE
+this.VJ=VJ
+this.Ai=Ai
+this.tH=tH
+this.VJ=VJ
+this.Ai=Ai
+this.VJ=VJ
+this.Ai=Ai
+this.ZI=ZI
+this.uN=uN
+this.z3=z3
+this.TQ=TQ
+this.Vk=Vk
+this.Ye=Ye
+this.mT=mT
+this.KM=KM}G6.builtin$cls="G6"
+if(!"name" in G6)G6.name="G6"
+$desc=$collectedClasses.G6
+if($desc instanceof Array)$desc=$desc[1]
+G6.prototype=$desc
+G6.prototype.geE=function(receiver){return receiver.eE}
+G6.prototype.geE.$reflectable=1
+G6.prototype.seE=function(receiver,v){return receiver.eE=v}
+G6.prototype.seE.$reflectable=1
+function Vf(){}Vf.builtin$cls="Vf"
+if(!"name" in Vf)Vf.name="Vf"
+$desc=$collectedClasses.Vf
+if($desc instanceof Array)$desc=$desc[1]
+Vf.prototype=$desc
 function aC(FJ,VJ,Ai,tH,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM){this.FJ=FJ
 this.VJ=VJ
 this.Ai=Ai
@@ -23601,11 +23659,11 @@
 aC.prototype.gFJ.$reflectable=1
 aC.prototype.sFJ=function(receiver,v){return receiver.FJ=v}
 aC.prototype.sFJ.$reflectable=1
-function Vf(){}Vf.builtin$cls="Vf"
-if(!"name" in Vf)Vf.name="Vf"
-$desc=$collectedClasses.Vf
+function tu(){}tu.builtin$cls="tu"
+if(!"name" in tu)tu.name="tu"
+$desc=$collectedClasses.tu
 if($desc instanceof Array)$desc=$desc[1]
-Vf.prototype=$desc
+tu.prototype=$desc
 function Be(Zw,VJ,Ai,tH,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM){this.Zw=Zw
 this.VJ=VJ
 this.Ai=Ai
@@ -23630,11 +23688,11 @@
 Be.prototype.gZw.$reflectable=1
 Be.prototype.sZw=function(receiver,v){return receiver.Zw=v}
 Be.prototype.sZw.$reflectable=1
-function tu(){}tu.builtin$cls="tu"
-if(!"name" in tu)tu.name="tu"
-$desc=$collectedClasses.tu
+function Vc(){}Vc.builtin$cls="Vc"
+if(!"name" in Vc)Vc.name="Vc"
+$desc=$collectedClasses.Vc
 if($desc instanceof Array)$desc=$desc[1]
-tu.prototype=$desc
+Vc.prototype=$desc
 function i6(Xf,VA,P2,VJ,Ai,tH,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM){this.Xf=Xf
 this.VA=VA
 this.P2=P2
@@ -23669,11 +23727,11 @@
 i6.prototype.gP2.$reflectable=1
 i6.prototype.sP2=function(receiver,v){return receiver.P2=v}
 i6.prototype.sP2.$reflectable=1
-function Vc(){}Vc.builtin$cls="Vc"
-if(!"name" in Vc)Vc.name="Vc"
-$desc=$collectedClasses.Vc
+function WZ(){}WZ.builtin$cls="WZ"
+if(!"name" in WZ)WZ.name="WZ"
+$desc=$collectedClasses.WZ
 if($desc instanceof Array)$desc=$desc[1]
-Vc.prototype=$desc
+WZ.prototype=$desc
 function zO(){}zO.builtin$cls="zO"
 if(!"name" in zO)zO.name="zO"
 $desc=$collectedClasses.zO
@@ -26130,11 +26188,11 @@
 Fv.prototype.gFT.$reflectable=1
 Fv.prototype.sFT=function(receiver,v){return receiver.FT=v}
 Fv.prototype.sFT.$reflectable=1
-function WZ(){}WZ.builtin$cls="WZ"
-if(!"name" in WZ)WZ.name="WZ"
-$desc=$collectedClasses.WZ
+function pv(){}pv.builtin$cls="pv"
+if(!"name" in pv)pv.name="pv"
+$desc=$collectedClasses.pv
 if($desc instanceof Array)$desc=$desc[1]
-WZ.prototype=$desc
+pv.prototype=$desc
 function I3(Py,hO,VJ,Ai,tH,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM){this.Py=Py
 this.hO=hO
 this.VJ=VJ
@@ -26164,11 +26222,11 @@
 I3.prototype.ghO.$reflectable=1
 I3.prototype.shO=function(receiver,v){return receiver.hO=v}
 I3.prototype.shO.$reflectable=1
-function pv(){}pv.builtin$cls="pv"
-if(!"name" in pv)pv.name="pv"
-$desc=$collectedClasses.pv
+function Vfx(){}Vfx.builtin$cls="Vfx"
+if(!"name" in Vfx)Vfx.name="Vfx"
+$desc=$collectedClasses.Vfx
 if($desc instanceof Array)$desc=$desc[1]
-pv.prototype=$desc
+Vfx.prototype=$desc
 function qr(Lf,VJ,Ai,tH,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM){this.Lf=Lf
 this.VJ=VJ
 this.Ai=Ai
@@ -26193,11 +26251,11 @@
 qr.prototype.gLf.$reflectable=1
 qr.prototype.sLf=function(receiver,v){return receiver.Lf=v}
 qr.prototype.sLf.$reflectable=1
-function Vfx(){}Vfx.builtin$cls="Vfx"
-if(!"name" in Vfx)Vfx.name="Vfx"
-$desc=$collectedClasses.Vfx
+function Dsd(){}Dsd.builtin$cls="Dsd"
+if(!"name" in Dsd)Dsd.name="Dsd"
+$desc=$collectedClasses.Dsd
 if($desc instanceof Array)$desc=$desc[1]
-Vfx.prototype=$desc
+Dsd.prototype=$desc
 function Gk(vt,VJ,Ai,tH,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM){this.vt=vt
 this.VJ=VJ
 this.Ai=Ai
@@ -26222,11 +26280,11 @@
 Gk.prototype.gvt.$reflectable=1
 Gk.prototype.svt=function(receiver,v){return receiver.vt=v}
 Gk.prototype.svt.$reflectable=1
-function Dsd(){}Dsd.builtin$cls="Dsd"
-if(!"name" in Dsd)Dsd.name="Dsd"
-$desc=$collectedClasses.Dsd
+function tuj(){}tuj.builtin$cls="tuj"
+if(!"name" in tuj)tuj.name="tuj"
+$desc=$collectedClasses.tuj
 if($desc instanceof Array)$desc=$desc[1]
-Dsd.prototype=$desc
+tuj.prototype=$desc
 function Ds(ql,VJ,Ai,tH,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM){this.ql=ql
 this.VJ=VJ
 this.Ai=Ai
@@ -26251,11 +26309,11 @@
 Ds.prototype.gql.$reflectable=1
 Ds.prototype.sql=function(receiver,v){return receiver.ql=v}
 Ds.prototype.sql.$reflectable=1
-function tuj(){}tuj.builtin$cls="tuj"
-if(!"name" in tuj)tuj.name="tuj"
-$desc=$collectedClasses.tuj
+function Vct(){}Vct.builtin$cls="Vct"
+if(!"name" in Vct)Vct.name="Vct"
+$desc=$collectedClasses.Vct
 if($desc instanceof Array)$desc=$desc[1]
-tuj.prototype=$desc
+Vct.prototype=$desc
 function aI(b,c){this.b=b
 this.c=c}aI.builtin$cls="aI"
 if(!"name" in aI)aI.name="aI"
@@ -26348,11 +26406,11 @@
 pR.prototype.giK.$reflectable=1
 pR.prototype.siK=function(receiver,v){return receiver.iK=v}
 pR.prototype.siK.$reflectable=1
-function Vct(){}Vct.builtin$cls="Vct"
-if(!"name" in Vct)Vct.name="Vct"
-$desc=$collectedClasses.Vct
+function D13(){}D13.builtin$cls="D13"
+if(!"name" in D13)D13.name="D13"
+$desc=$collectedClasses.D13
 if($desc instanceof Array)$desc=$desc[1]
-Vct.prototype=$desc
+D13.prototype=$desc
 function hx(Xh,VJ,Ai,tH,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM){this.Xh=Xh
 this.VJ=VJ
 this.Ai=Ai
@@ -26377,11 +26435,11 @@
 hx.prototype.gXh.$reflectable=1
 hx.prototype.sXh=function(receiver,v){return receiver.Xh=v}
 hx.prototype.sXh.$reflectable=1
-function D13(){}D13.builtin$cls="D13"
-if(!"name" in D13)D13.name="D13"
-$desc=$collectedClasses.D13
+function WZq(){}WZq.builtin$cls="WZq"
+if(!"name" in WZq)WZq.name="WZq"
+$desc=$collectedClasses.WZq
 if($desc instanceof Array)$desc=$desc[1]
-D13.prototype=$desc
+WZq.prototype=$desc
 function u7(tH,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM){this.tH=tH
 this.VJ=VJ
 this.Ai=Ai
@@ -26428,11 +26486,11 @@
 St.prototype.gi0.$reflectable=1
 St.prototype.si0=function(receiver,v){return receiver.i0=v}
 St.prototype.si0.$reflectable=1
-function WZq(){}WZq.builtin$cls="WZq"
-if(!"name" in WZq)WZq.name="WZq"
-$desc=$collectedClasses.WZq
+function pva(){}pva.builtin$cls="pva"
+if(!"name" in pva)pva.name="pva"
+$desc=$collectedClasses.pva
 if($desc instanceof Array)$desc=$desc[1]
-WZq.prototype=$desc
+pva.prototype=$desc
 function vj(eb,kf,VJ,Ai,tH,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM){this.eb=eb
 this.kf=kf
 this.VJ=VJ
@@ -26462,11 +26520,11 @@
 vj.prototype.gkf.$reflectable=1
 vj.prototype.skf=function(receiver,v){return receiver.kf=v}
 vj.prototype.skf.$reflectable=1
-function pva(){}pva.builtin$cls="pva"
-if(!"name" in pva)pva.name="pva"
-$desc=$collectedClasses.pva
+function cda(){}cda.builtin$cls="cda"
+if(!"name" in cda)cda.name="cda"
+$desc=$collectedClasses.cda
 if($desc instanceof Array)$desc=$desc[1]
-pva.prototype=$desc
+cda.prototype=$desc
 function CX(iI,VJ,Ai,tH,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM){this.iI=iI
 this.VJ=VJ
 this.Ai=Ai
@@ -26491,11 +26549,11 @@
 CX.prototype.giI.$reflectable=1
 CX.prototype.siI=function(receiver,v){return receiver.iI=v}
 CX.prototype.siI.$reflectable=1
-function cda(){}cda.builtin$cls="cda"
-if(!"name" in cda)cda.name="cda"
-$desc=$collectedClasses.cda
+function waa(){}waa.builtin$cls="waa"
+if(!"name" in waa)waa.name="waa"
+$desc=$collectedClasses.waa
 if($desc instanceof Array)$desc=$desc[1]
-cda.prototype=$desc
+waa.prototype=$desc
 function TJ(oc,eT,yz,Cj,wd,Gs){this.oc=oc
 this.eT=eT
 this.yz=yz
@@ -26783,11 +26841,11 @@
 F1.prototype.gk5.$reflectable=1
 F1.prototype.sk5=function(receiver,v){return receiver.k5=v}
 F1.prototype.sk5.$reflectable=1
-function waa(){}waa.builtin$cls="waa"
-if(!"name" in waa)waa.name="waa"
-$desc=$collectedClasses.waa
+function V0(){}V0.builtin$cls="V0"
+if(!"name" in V0)V0.name="V0"
+$desc=$collectedClasses.V0
 if($desc instanceof Array)$desc=$desc[1]
-waa.prototype=$desc
+V0.prototype=$desc
 function uL(tH,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM){this.tH=tH
 this.VJ=VJ
 this.Ai=Ai
@@ -27397,13 +27455,13 @@
 $desc=$collectedClasses.e9
 if($desc instanceof Array)$desc=$desc[1]
 e9.prototype=$desc
-function Dw(wc,nn,lv,Pp){this.wc=wc
+function PD(wc,nn,lv,Pp){this.wc=wc
 this.nn=nn
 this.lv=lv
-this.Pp=Pp}Dw.builtin$cls="Dw"
-$desc=$collectedClasses.Dw
+this.Pp=Pp}PD.builtin$cls="PD"
+$desc=$collectedClasses.PD
 if($desc instanceof Array)$desc=$desc[1]
-Dw.prototype=$desc
+PD.prototype=$desc
 function Xy(a,b,c){this.a=a
 this.b=b
 this.c=c}Xy.builtin$cls="Xy"
@@ -27938,11 +27996,11 @@
 fI.prototype.gUz.$reflectable=1
 fI.prototype.sUz=function(receiver,v){return receiver.Uz=v}
 fI.prototype.sUz.$reflectable=1
-function V0(){}V0.builtin$cls="V0"
-if(!"name" in V0)V0.name="V0"
-$desc=$collectedClasses.V0
+function V4(){}V4.builtin$cls="V4"
+if(!"name" in V4)V4.name="V4"
+$desc=$collectedClasses.V4
 if($desc instanceof Array)$desc=$desc[1]
-V0.prototype=$desc
+V4.prototype=$desc
 function kK(vX,VJ,Ai,tH,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM){this.vX=vX
 this.VJ=VJ
 this.Ai=Ai
@@ -27967,11 +28025,11 @@
 kK.prototype.gvX.$reflectable=1
 kK.prototype.svX=function(receiver,v){return receiver.vX=v}
 kK.prototype.svX.$reflectable=1
-function V4(){}V4.builtin$cls="V4"
-if(!"name" in V4)V4.name="V4"
-$desc=$collectedClasses.V4
+function V6(){}V6.builtin$cls="V6"
+if(!"name" in V6)V6.name="V6"
+$desc=$collectedClasses.V6
 if($desc instanceof Array)$desc=$desc[1]
-V4.prototype=$desc
+V6.prototype=$desc
 function uw(V4,VJ,Ai,tH,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM){this.V4=V4
 this.VJ=VJ
 this.Ai=Ai
@@ -27996,11 +28054,11 @@
 uw.prototype.gV4.$reflectable=1
 uw.prototype.sV4=function(receiver,v){return receiver.V4=v}
 uw.prototype.sV4.$reflectable=1
-function V6(){}V6.builtin$cls="V6"
-if(!"name" in V6)V6.name="V6"
-$desc=$collectedClasses.V6
+function V8(){}V8.builtin$cls="V8"
+if(!"name" in V8)V8.name="V8"
+$desc=$collectedClasses.V8
 if($desc instanceof Array)$desc=$desc[1]
-V6.prototype=$desc
+V8.prototype=$desc
 function V2(N1,bn,Ck){this.N1=N1
 this.bn=bn
 this.Ck=Ck}V2.builtin$cls="V2"
@@ -28338,7 +28396,7 @@
 $desc=$collectedClasses.PW
 if($desc instanceof Array)$desc=$desc[1]
 PW.prototype=$desc
-return[qE,Yy,Ps,rK,fY,Mr,zx,ct,nB,i3,it,Az,QP,QW,n6,Ny,OM,QQ,MA,y4,d7,na,oJ,DG,mN,vH,hh,Em,Sb,rV,Wy,YN,bA,Wq,rv,BK,wj,cv,Fs,SX,ea,D0,as,T5,Aa,u5,Yu,iG,jP,U2,tA,xn,Vb,QH,ST,X2,fJ,Vi,tX,Sg,pA,Mi,Gt,In,Gx,eP,AL,Og,cS,M6,El,zm,SV,aB,ku,KM,cW,DK,qm,ZY,cx,la,Vn,PG,xe,Hw,bn,Im,oB,Aj,oU,qT,KV,BH,mh,G7,wq,Ql,Xp,bP,mX,SN,HD,ni,p3,qj,qW,KR,ew,fs,bX,BL,MC,Mx,j2,yz,lp,pD,I0,QR,Cp,ua,zD,Ul,G0,wb,fq,h4,qk,GI,Tb,tV,BT,yY,kJ,AE,xV,FH,y6,RH,pU,Lq,Mf,BR,r4,aG,J6,K5,UM,UL,rq,nK,kc,ij,ty,Nf,Nc,rj,rh,Zv,Q7,hF,OF,HB,ZJ,mU,eZ,Fl,y5,nV,Zc,ui,D6,DQ,Sm,dx,es,eG,lv,pf,NV,W1,zo,wf,TU,bb,VE,lc,Xu,qM,tk,me,qN,nh,d4,MI,ca,xX,eW,um,Fu,OE,l6,BA,zp,rE,CC,PQ,uz,Yd,U0,AD,Gr,tc,GH,lo,NJ,nd,vt,rQ,EU,LR,MB,hy,r8,aS,CG,qF,MT,Rk,Eo,Dn,UD,ZD,NE,wD,BD,vRT,Fi,Qr,mj,cB,uY,yR,AX,xJ,l4,Et,NC,nb,By,xt,tG,P0,Jq,Xr,qD,Cf,I2,AS,Kq,oI,mJ,rF,vi,ZX,ycx,nE,zt,F0,Lt,Gv,kn,PE,QI,FP,is,Q,jx,ZC,Jt,P,im,Pp,O,PK,JO,O2,aX,cC,RA,IY,JH,jl,Iy,JM,Ua,JG,ns,wd,TA,YP,yc,I9,Bj,NO,II,aJ,X1,HU,Pm,oo,OW,Dd,AP,yH,FA,Av,oH,LP,c2,WT,p8,XR,LI,A2,F3,u8,Gi,t2,Zr,ZQ,az,vV,Hk,XO,dr,TL,KX,uZ,OQ,Tp,v,Z3,D2,GT,Pe,Eq,cu,Lm,dC,wN,VX,VR,EK,KW,Pb,tQ,aC,Vf,Be,tu,i6,Vc,zO,aL,nH,a7,i1,xy,MH,A8,U5,SO,zs,rR,AM,d5,U1,SJ,SU,Tv,XC,iK,GD,Sn,nI,jU,Lj,mb,am,cw,EE,Uz,uh,Kv,oP,YX,BI,y1,M2,iu,mg,zE,bl,Ef,Oo,Tc,Ax,Wf,Un,Ei,U7,t0,Ld,Sz,Zk,fu,ng,Ar,jB,ye,Gj,Zz,Xh,Ca,Ik,JI,Ip,WV,C7,CQ,dz,tK,OR,Bg,DL,b8,j7,oV,TP,Zf,vs,da,xw,dm,rH,ZL,mi,jb,wB,Pu,qh,QC,Yl,Rv,YJ,jv,LB,DO,lz,Rl,Jb,M4,Jp,h7,pr,eN,B5,PI,j4,i9,VV,Dy,lU,xp,UH,Z5,ii,ib,MO,ms,UO,Bc,vp,lk,Gh,XB,ly,cK,O9,yU,nP,KA,Vo,qB,ez,lx,LV,DS,dp,B3,CR,ny,dR,uR,QX,YR,fB,bq,nO,t3,dq,dX,aY,wJ,e4,JB,Id,fZ,TF,Xz,Cg,Hs,uo,pK,eM,Ue,W5,R8,k6,oi,ce,o2,jG,fG,EQ,YB,iX,ou,S9,ey,xd,v6,db,Cm,N6,jg,YO,oz,b6,ef,zQ,Yp,u3,mW,ar,lD,W0,Sw,o0,a1,jp,Xt,Ba,An,LD,YI,OG,ro,DN,ZM,HW,JC,f1,Uk,wI,ob,Ud,K8,by,dI,QM,Sh,tF,z0,Vx,Rw,GY,jZ,h0,CL,uA,a2,fR,iP,MF,Rq,Hn,Zl,pl,a6,P7,DW,Ge,LK,AT,bJ,mp,ub,ds,lj,UV,VS,t7,HG,aE,kM,EH,cX,eL,L8,c8,a,Od,mE,WU,Rn,wv,uq,iD,hb,XX,Kd,yZ,Gs,pm,Tw,wm,FB,Lk,XZ,qz,hQ,Nw,kZ,JT,d9,rI,dD,QZ,BV,E1,wz,B1,M5,Jn,DM,zL,ec,Kx,iO,bU,e7,nj,rl,RAp,ma,cf,E9,nF,FK,Si,vf,Fc,hD,I4,e0,RO,eu,ie,Ea,pu,i2,b0,Ov,qO,RX,kG,Gm,W9,vZ,dW,PA,H2,O7,HI,E4,r7,Tz,Wk,DV,Hp,Nz,Jd,QS,QF,NL,vr,D4,L9u,Ms,Fw,RS,RY,Ys,vg,xG,Vj,VW,RK,DH,ZK,Th,Vju,KB,RKu,xGn,TkQ,VWk,ZKG,DHb,w6W,Hna,z9g,G8,UZ,Fv,WZ,I3,pv,qr,Vfx,Gk,Dsd,Ds,tuj,aI,rG,yh,wO,Tm,rz,CA,YL,KC,xL,As,GE,pR,Vct,hx,D13,u7,St,WZq,vj,pva,CX,cda,TJ,dG,Ng,HV,Nh,fA,tz,jR,PO,c5,ih,mL,bv,pt,Zd,dY,vY,dS,ZW,dZ,Qe,Nu,pF,Ha,nu,be,Pg,jI,Rb,Zw,Pf,F1,waa,uL,Nr,Pi,yj,qI,J3,E5,o5,b5,zI,Zb,id,iV,W4,Fa,x9,d3,X6,xh,wn,uF,cj,HA,br,zT,D7,qL,C4,l9,lP,km,Qt,Dk,A0,rm,eY,OO,BE,Qb,xI,q1,Zj,XP,q6,CK,BO,ZG,Oc,MX,w12,fTP,yL,dM,Y7,WC,Xi,TV,Mq,Oa,n1,xf,L6,Rs,uJ,hm,Ji,Bf,ir,Sa,GN,k8,HJ,S0,V3,Bl,pM,Mh,Md,Lf,fT,pp,Nq,nl,mf,ej,HK,w13,o8,GL,e9,Dw,Xy,uK,mY,fE,mB,XF,iH,wJY,zOQ,W6o,MdQ,YJG,DOe,lPa,Ufa,Raa,w0,w4,w5,w7,w9,w10,w11,c4,z6,Ay,Ed,G1,Os,Dl,Wh,x5,ev,ID,jV,ek,OC,Xm,Jy,ky,fa,WW,vQ,a9,jh,e3,VA,J1,fk,wL,B0,Fq,hw,EZ,no,kB,ae,Iq,w6,jK,uk,K9,RW,xs,FX,Ae,Bt,vR,Pn,hc,hA,fr,a0,NQ,fI,V0,kK,V4,uw,V6,V2,D8,jY,ll,Uf,ik,LfS,NP,Vh,r0,jz,SA,zV,nv,ee,XI,hs,yp,ug,DT,OB,Ra,N9,NW,HS,TG,ts,Kj,VU,Ya,XT,ic,VT,T4,TR,VD,Oh,zy,Nb,Fy,eU,ADW,Ri,kq,Ag,PW]}// Generated by dart2js, the Dart to JavaScript compiler version: 1.0.0.3_r30188.
+return[qE,Yy,Ps,rK,fY,Mr,zx,ct,nB,i3,it,Az,QP,QW,n6,Ny,OM,QQ,MA,y4,d7,na,oJ,DG,mN,vH,hh,Em,Sb,rV,Wy,YN,bA,Wq,rv,BK,wj,cv,Fs,SX,ea,D0,as,T5,Aa,u5,Yu,iG,jP,U2,tA,xn,Vb,QH,ST,X2,fJ,Vi,tX,Sg,pA,Mi,Gt,In,Gx,eP,AL,Og,cS,M6,El,zm,SV,aB,ku,KM,cW,DK,qm,ZY,cx,la,Vn,PG,xe,Hw,bn,Im,oB,Aj,oU,qT,KV,BH,mh,G7,wq,Ql,Xp,bP,mX,SN,HD,ni,p3,qj,qW,KR,ew,fs,bX,BL,MC,Mx,j2,yz,lp,pD,I0,QR,Cp,ua,zD,Ul,G0,wb,fq,h4,qk,GI,Tb,tV,BT,yY,kJ,AE,xV,FH,y6,RH,pU,Lq,Mf,BR,r4,aG,J6,K5,UM,UL,rq,nK,kc,ij,ty,Nf,Nc,rj,rh,Zv,Q7,hF,OF,HB,ZJ,mU,eZ,Fl,y5,nV,Zc,ui,D6,DQ,Sm,dx,es,eG,lv,pf,NV,W1,zo,wf,TU,bb,VE,lc,Xu,qM,tk,me,qN,nh,d4,MI,ca,xX,eW,um,Fu,OE,l6,BA,zp,rE,CC,PQ,uz,Yd,U0,AD,Gr,tc,GH,lo,NJ,nd,vt,rQ,EU,LR,MB,hy,r8,aS,CG,qF,MT,Rk,Eo,Dn,UD,ZD,NE,wD,BD,vRT,Fi,Qr,mj,cB,uY,yR,AX,xJ,l4,Et,NC,nb,By,xt,tG,P0,Jq,Xr,qD,Cf,I2,AS,Kq,oI,mJ,rF,vi,ZX,ycx,nE,zt,F0,Lt,Gv,kn,PE,QI,FP,is,Q,jx,ZC,Jt,P,im,Pp,O,PK,JO,O2,aX,cC,RA,IY,JH,jl,Iy,JM,Ua,JG,ns,wd,TA,YP,yc,I9,Bj,NO,II,aJ,X1,HU,Pm,oo,OW,Dd,AP,yH,FA,Av,oH,LP,c2,WT,p8,XR,LI,A2,F3,u8,Gi,t2,Zr,ZQ,az,vV,Hk,XO,dr,TL,KX,uZ,OQ,Tp,v,Z3,D2,GT,Pe,Eq,cu,Lm,dC,wN,VX,VR,EK,KW,Pb,tQ,G6,Vf,aC,tu,Be,Vc,i6,WZ,zO,aL,nH,a7,i1,xy,MH,A8,U5,SO,zs,rR,AM,d5,U1,SJ,SU,Tv,XC,iK,GD,Sn,nI,jU,Lj,mb,am,cw,EE,Uz,uh,Kv,oP,YX,BI,y1,M2,iu,mg,zE,bl,Ef,Oo,Tc,Ax,Wf,Un,Ei,U7,t0,Ld,Sz,Zk,fu,ng,Ar,jB,ye,Gj,Zz,Xh,Ca,Ik,JI,Ip,WV,C7,CQ,dz,tK,OR,Bg,DL,b8,j7,oV,TP,Zf,vs,da,xw,dm,rH,ZL,mi,jb,wB,Pu,qh,QC,Yl,Rv,YJ,jv,LB,DO,lz,Rl,Jb,M4,Jp,h7,pr,eN,B5,PI,j4,i9,VV,Dy,lU,xp,UH,Z5,ii,ib,MO,ms,UO,Bc,vp,lk,Gh,XB,ly,cK,O9,yU,nP,KA,Vo,qB,ez,lx,LV,DS,dp,B3,CR,ny,dR,uR,QX,YR,fB,bq,nO,t3,dq,dX,aY,wJ,e4,JB,Id,fZ,TF,Xz,Cg,Hs,uo,pK,eM,Ue,W5,R8,k6,oi,ce,o2,jG,fG,EQ,YB,iX,ou,S9,ey,xd,v6,db,Cm,N6,jg,YO,oz,b6,ef,zQ,Yp,u3,mW,ar,lD,W0,Sw,o0,a1,jp,Xt,Ba,An,LD,YI,OG,ro,DN,ZM,HW,JC,f1,Uk,wI,ob,Ud,K8,by,dI,QM,Sh,tF,z0,Vx,Rw,GY,jZ,h0,CL,uA,a2,fR,iP,MF,Rq,Hn,Zl,pl,a6,P7,DW,Ge,LK,AT,bJ,mp,ub,ds,lj,UV,VS,t7,HG,aE,kM,EH,cX,eL,L8,c8,a,Od,mE,WU,Rn,wv,uq,iD,hb,XX,Kd,yZ,Gs,pm,Tw,wm,FB,Lk,XZ,qz,hQ,Nw,kZ,JT,d9,rI,dD,QZ,BV,E1,wz,B1,M5,Jn,DM,zL,ec,Kx,iO,bU,e7,nj,rl,RAp,ma,cf,E9,nF,FK,Si,vf,Fc,hD,I4,e0,RO,eu,ie,Ea,pu,i2,b0,Ov,qO,RX,kG,Gm,W9,vZ,dW,PA,H2,O7,HI,E4,r7,Tz,Wk,DV,Hp,Nz,Jd,QS,QF,NL,vr,D4,L9u,Ms,Fw,RS,RY,Ys,vg,xG,Vj,VW,RK,DH,ZK,Th,Vju,KB,RKu,xGn,TkQ,VWk,ZKG,DHb,w6W,Hna,z9g,G8,UZ,Fv,pv,I3,Vfx,qr,Dsd,Gk,tuj,Ds,Vct,aI,rG,yh,wO,Tm,rz,CA,YL,KC,xL,As,GE,pR,D13,hx,WZq,u7,St,pva,vj,cda,CX,waa,TJ,dG,Ng,HV,Nh,fA,tz,jR,PO,c5,ih,mL,bv,pt,Zd,dY,vY,dS,ZW,dZ,Qe,Nu,pF,Ha,nu,be,Pg,jI,Rb,Zw,Pf,F1,V0,uL,Nr,Pi,yj,qI,J3,E5,o5,b5,zI,Zb,id,iV,W4,Fa,x9,d3,X6,xh,wn,uF,cj,HA,br,zT,D7,qL,C4,l9,lP,km,Qt,Dk,A0,rm,eY,OO,BE,Qb,xI,q1,Zj,XP,q6,CK,BO,ZG,Oc,MX,w12,fTP,yL,dM,Y7,WC,Xi,TV,Mq,Oa,n1,xf,L6,Rs,uJ,hm,Ji,Bf,ir,Sa,GN,k8,HJ,S0,V3,Bl,pM,Mh,Md,Lf,fT,pp,Nq,nl,mf,ej,HK,w13,o8,GL,e9,PD,Xy,uK,mY,fE,mB,XF,iH,wJY,zOQ,W6o,MdQ,YJG,DOe,lPa,Ufa,Raa,w0,w4,w5,w7,w9,w10,w11,c4,z6,Ay,Ed,G1,Os,Dl,Wh,x5,ev,ID,jV,ek,OC,Xm,Jy,ky,fa,WW,vQ,a9,jh,e3,VA,J1,fk,wL,B0,Fq,hw,EZ,no,kB,ae,Iq,w6,jK,uk,K9,RW,xs,FX,Ae,Bt,vR,Pn,hc,hA,fr,a0,NQ,fI,V4,kK,V6,uw,V8,V2,D8,jY,ll,Uf,ik,LfS,NP,Vh,r0,jz,SA,zV,nv,ee,XI,hs,yp,ug,DT,OB,Ra,N9,NW,HS,TG,ts,Kj,VU,Ya,XT,ic,VT,T4,TR,VD,Oh,zy,Nb,Fy,eU,ADW,Ri,kq,Ag,PW]}// Generated by dart2js, the Dart to JavaScript compiler version: 1.0.0.3_r30188.
 (function($){var A={}
 delete A.x
 var B={}
@@ -28420,7 +28478,7 @@
 $$.Y7=[A,{"":"v;wc,nn,lv,Pp",
 call$2:function(a,b){return this.nn.call(this.wc,this.lv,a,b)},
 $is_bh:true}]
-$$.Dw=[T,{"":"v;wc,nn,lv,Pp",
+$$.PD=[T,{"":"v;wc,nn,lv,Pp",
 call$3:function(a,b,c){return this.nn.call(this.wc,a,b,c)}}]
 $$.zy=[H,{"":"Tp;call$2,$name",$is_bh:true}]
 $$.Nb=[H,{"":"Tp;call$1,$name",$is_HB:true,$is_Dv:true}]
@@ -28443,7 +28501,7 @@
 call$catchAll:function(){return{onError:null,radix:null}},
 $is_HB:true,
 $is_Dv:true}]
-;init.mangledNames={gB:"length",gDb:"_cachedDeclarations",gEI:"prefix",gF1:"isolate",gFF:"source",gFJ:"__$cls",gFT:"__$instruction",gFU:"_cachedMethodsMap",gG1:"message",gH8:"_fieldsDescriptor",gHt:"_fieldsMetadata",gKM:"$",gLA:"src",gLf:"__$field",gLy:"_cachedSetters",gM2:"_cachedVariables",gMj:"function",gNI:"instruction",gNl:"script",gO3:"url",gOk:"_cachedMetadata",gP:"value",gP2:"_collapsed",gPw:"__$isolate",gPy:"__$error",gQG:"app",gRu:"cls",gT1:"_cachedGetters",gTn:"json",gTx:"_jsConstructorOrInterceptor",gUF:"_cachedTypeVariables",gUz:"__$script",gV4:"__$trace",gVA:"__$displayValue",gVB:"error_obj",gWL:"_mangledName",gXB:"_message",gXJ:"lines",gXR:"scripts",gXf:"__$iconClass",gXh:"__$instance",gZ6:"locationManager",gZw:"__$code",ga:"a",gai:"displayValue",gb:"b",gb0:"_cachedConstructors",gcC:"hash",geV:"paddedLine",geb:"__$json",gfY:"kind",ghO:"__$error_obj",ghf:"instance",gi0:"__$name",gi2:"isolates",giI:"__$library",giK:"__$instance",gjO:"id",gjd:"_cachedMethods",gk5:"__$devtools",gkc:"error",gkf:"_count",gl7:"iconClass",glD:"currentHashUri",gle:"_metadata",glw:"requestManager",gn2:"responses",gnI:"isolateManager",gnz:"_owner",goc:"name",gpz:"_jsConstructorCache",gqN:"_superclass",gql:"__$function",gqm:"_cachedSuperinterfaces",gt0:"field",gtB:"_cachedFields",gtD:"library",gtH:"__$app",gtN:"trace",gtT:"code",guA:"_cachedMembers",gvH:"index",gvX:"__$source",gvt:"__$field",gxj:"collapsed",gzd:"currentHash",gzj:"devtools"};init.mangledGlobalNames={DI:"_closeIconClass",Vl:"_openIconClass"};(function (reflectionData) {
+;init.mangledNames={gB:"length",gDb:"_cachedDeclarations",gEI:"prefix",gF1:"isolate",gFF:"source",gFJ:"__$cls",gFT:"__$instruction",gFU:"_cachedMethodsMap",gG1:"message",gH8:"_fieldsDescriptor",gHt:"_fieldsMetadata",gKM:"$",gLA:"src",gLf:"__$field",gLy:"_cachedSetters",gM2:"_cachedVariables",gMj:"function",gNI:"instruction",gNl:"script",gO3:"url",gOk:"_cachedMetadata",gP:"value",gP2:"_collapsed",gPw:"__$isolate",gPy:"__$error",gQG:"app",gRu:"cls",gT1:"_cachedGetters",gTn:"json",gTx:"_jsConstructorOrInterceptor",gUF:"_cachedTypeVariables",gUz:"__$script",gV4:"__$trace",gVA:"__$displayValue",gVB:"error_obj",gWL:"_mangledName",gXB:"_message",gXJ:"lines",gXR:"scripts",gXf:"__$iconClass",gXh:"__$instance",gZ6:"locationManager",gZw:"__$code",ga:"a",gai:"displayValue",gb:"b",gb0:"_cachedConstructors",gcC:"hash",geE:"__$msg",geV:"paddedLine",geb:"__$json",gfY:"kind",ghO:"__$error_obj",ghf:"instance",gi0:"__$name",gi2:"isolates",giI:"__$library",giK:"__$instance",gjO:"id",gjd:"_cachedMethods",gk5:"__$devtools",gkc:"error",gkf:"_count",gl7:"iconClass",glD:"currentHashUri",gle:"_metadata",glw:"requestManager",gn2:"responses",gnI:"isolateManager",gnz:"_owner",goc:"name",gpz:"_jsConstructorCache",gqN:"_superclass",gql:"__$function",gqm:"_cachedSuperinterfaces",grs:"msg",gt0:"field",gtB:"_cachedFields",gtD:"library",gtH:"__$app",gtN:"trace",gtT:"code",guA:"_cachedMembers",gvH:"index",gvX:"__$source",gvt:"__$field",gxj:"collapsed",gzd:"currentHash",gzj:"devtools"};init.mangledGlobalNames={DI:"_closeIconClass",Vl:"_openIconClass"};(function (reflectionData) {
   function map(x){x={x:x};delete x.x;return x}
   if (!init.libraries) init.libraries = [];
   if (!init.mangledNames) init.mangledNames = map();
@@ -30076,14 +30134,38 @@
 t:function(a,b){if(!J.xC(b,0))H.vh(P.N(b))
 return this.zO},
 "+[]:1:0":0,
-$isOd:true}}],["app_bootstrap","index_devtools.html_bootstrap.dart",,E,{E2:function(){$.x2=["package:observatory/src/observatory_elements/observatory_element.dart","package:observatory/src/observatory_elements/error_view.dart","package:observatory/src/observatory_elements/field_ref.dart","package:observatory/src/observatory_elements/instance_ref.dart","package:observatory/src/observatory_elements/class_view.dart","package:observatory/src/observatory_elements/disassembly_entry.dart","package:observatory/src/observatory_elements/code_view.dart","package:observatory/src/observatory_elements/collapsible_content.dart","package:observatory/src/observatory_elements/field_view.dart","package:observatory/src/observatory_elements/function_view.dart","package:observatory/src/observatory_elements/isolate_summary.dart","package:observatory/src/observatory_elements/isolate_list.dart","package:observatory/src/observatory_elements/instance_view.dart","package:observatory/src/observatory_elements/json_view.dart","package:observatory/src/observatory_elements/library_view.dart","package:observatory/src/observatory_elements/source_view.dart","package:observatory/src/observatory_elements/script_view.dart","package:observatory/src/observatory_elements/stack_trace.dart","package:observatory/src/observatory_elements/message_viewer.dart","package:observatory/src/observatory_elements/navigation_bar.dart","package:observatory/src/observatory_elements/response_viewer.dart","package:observatory/src/observatory_elements/observatory_application.dart","index_devtools.html.0.dart"]
+$isOd:true}}],["app_bootstrap","index_devtools.html_bootstrap.dart",,E,{E2:function(){$.x2=["package:observatory/src/observatory_elements/observatory_element.dart","package:observatory/src/observatory_elements/breakpoint_list.dart","package:observatory/src/observatory_elements/error_view.dart","package:observatory/src/observatory_elements/field_ref.dart","package:observatory/src/observatory_elements/instance_ref.dart","package:observatory/src/observatory_elements/class_view.dart","package:observatory/src/observatory_elements/disassembly_entry.dart","package:observatory/src/observatory_elements/code_view.dart","package:observatory/src/observatory_elements/collapsible_content.dart","package:observatory/src/observatory_elements/field_view.dart","package:observatory/src/observatory_elements/function_view.dart","package:observatory/src/observatory_elements/isolate_summary.dart","package:observatory/src/observatory_elements/isolate_list.dart","package:observatory/src/observatory_elements/instance_view.dart","package:observatory/src/observatory_elements/json_view.dart","package:observatory/src/observatory_elements/library_view.dart","package:observatory/src/observatory_elements/source_view.dart","package:observatory/src/observatory_elements/script_view.dart","package:observatory/src/observatory_elements/stack_trace.dart","package:observatory/src/observatory_elements/message_viewer.dart","package:observatory/src/observatory_elements/navigation_bar.dart","package:observatory/src/observatory_elements/response_viewer.dart","package:observatory/src/observatory_elements/observatory_application.dart","index_devtools.html.0.dart"]
 $.uP=!1
-A.Ok()}},1],["class_view_element","package:observatory/src/observatory_elements/class_view.dart",,Z,{aC:{"":["Vf;FJ%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
+A.Ok()}},1],["breakpoint_list_element","package:observatory/src/observatory_elements/breakpoint_list.dart",,B,{G6:{"":["Vf;eE%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
+grs:function(a){return a.eE
+"38,39,40"},
+"+msg":1,
+srs:function(a,b){a.eE=this.pD(a,C.Ry,a.eE,b)
+"41,32,38,39"},
+"+msg=":1,
+"@":function(){return[C.PT]},
+static:{Dw:function(a){var z,y,x,w,v,u
+z=H.B7([],P.L5(null,null,null,null,null))
+z=R.Jk(z)
+y=$.Nd()
+x=P.Py(null,null,null,J.O,W.I0)
+w=J.O
+v=W.cv
+u=new V.br(P.Py(null,null,null,w,v),null,null)
+H.VM(u,[w,v])
+a.eE=z
+a.Ye=y
+a.mT=x
+a.KM=u
+C.J0.ZL(a)
+C.J0.FH(a)
+return a
+"9"},"+new BreakpointListElement$created:0:0":1}},"+BreakpointListElement": [42],Vf:{"":"uL+Pi;",$isd3:true}}],["class_view_element","package:observatory/src/observatory_elements/class_view.dart",,Z,{aC:{"":["tu;FJ%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
 gRu:function(a){return a.FJ
-"37,38,39"},
+"38,39,40"},
 "+cls":1,
 sRu:function(a,b){a.FJ=this.pD(a,C.XA,a.FJ,b)
-"40,31,37,38"},
+"41,32,38,39"},
 "+cls=":1,
 "@":function(){return[C.aQ]},
 static:{zg:function(a){var z,y,x,w,v
@@ -30099,12 +30181,12 @@
 C.kk.ZL(a)
 C.kk.FH(a)
 return a
-"9"},"+new ClassViewElement$created:0:0":1}},"+ClassViewElement": [41],Vf:{"":"uL+Pi;",$isd3:true}}],["code_view_element","package:observatory/src/observatory_elements/code_view.dart",,F,{Be:{"":["tu;Zw%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
+"10"},"+new ClassViewElement$created:0:0":1}},"+ClassViewElement": [43],tu:{"":"uL+Pi;",$isd3:true}}],["code_view_element","package:observatory/src/observatory_elements/code_view.dart",,F,{Be:{"":["Vc;Zw%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
 gtT:function(a){return a.Zw
-"37,38,39"},
+"38,39,40"},
 "+code":1,
 stT:function(a,b){a.Zw=this.pD(a,C.b1,a.Zw,b)
-"40,31,37,38"},
+"41,32,38,39"},
 "+code=":1,
 grK:function(a){var z=a.Zw
 if(z!=null&&J.UQ(z,"is_optimized")!=null)return"panel panel-success"
@@ -30128,41 +30210,41 @@
 C.YD.ZL(a)
 C.YD.FH(a)
 return a
-"10"},"+new CodeViewElement$created:0:0":1}},"+CodeViewElement": [42],tu:{"":"uL+Pi;",$isd3:true}}],["collapsible_content_element","package:observatory/src/observatory_elements/collapsible_content.dart",,R,{i6:{"":["Vc;Xf%-,VA%-,P2%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
+"11"},"+new CodeViewElement$created:0:0":1}},"+CodeViewElement": [44],Vc:{"":"uL+Pi;",$isd3:true}}],["collapsible_content_element","package:observatory/src/observatory_elements/collapsible_content.dart",,R,{i6:{"":["WZ;Xf%-,VA%-,P2%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
 gl7:function(a){return a.Xf
-"8,38,43"},
+"8,39,45"},
 "+iconClass":1,
 sl7:function(a,b){a.Xf=this.pD(a,C.Di,a.Xf,b)
-"40,31,8,38"},
+"41,32,8,39"},
 "+iconClass=":1,
 gai:function(a){return a.VA
-"8,38,43"},
+"8,39,45"},
 "+displayValue":1,
 sai:function(a,b){a.VA=this.pD(a,C.Jw,a.VA,b)
-"40,31,8,38"},
+"41,32,8,39"},
 "+displayValue=":1,
 gxj:function(a){return a.P2
-"44"},
+"46"},
 "+collapsed":1,
 sxj:function(a,b){a.P2=b
 this.dR(a)
-"40,45,44"},
+"41,47,46"},
 "+collapsed=":1,
 i4:function(a){Z.uL.prototype.i4.call(this,a)
 this.dR(a)
-"40"},
+"41"},
 "+enteredView:0:0":1,
 rS:function(a,b,c,d){a.P2=a.P2!==!0
 this.dR(a)
 this.dR(a)
-"40,46,47,48,40,49,50"},
+"41,48,49,50,41,51,52"},
 "+toggleDisplay:3:0":1,
 dR:function(a){var z,y
 z=a.P2
 y=a.Xf
 if(z===!0){a.Xf=this.pD(a,C.Di,y,"glyphicon glyphicon-chevron-down")
 a.VA=this.pD(a,C.Jw,a.VA,"none")}else{a.Xf=this.pD(a,C.Di,y,"glyphicon glyphicon-chevron-up")
-a.VA=this.pD(a,C.Jw,a.VA,"block")}"40"},
+a.VA=this.pD(a,C.Jw,a.VA,"block")}"41"},
 "+_refresh:0:0":1,
 "@":function(){return[C.Gu]},
 static:{"":"Vl<-,DI<-",IT:function(a){var z,y,x,w,v
@@ -30181,7 +30263,7 @@
 C.j8.ZL(a)
 C.j8.FH(a)
 return a
-"11"},"+new CollapsibleContentElement$created:0:0":1}},"+CollapsibleContentElement": [51],Vc:{"":"uL+Pi;",$isd3:true}}],["custom_element.polyfill","package:custom_element/polyfill.dart",,B,{G9:function(){if($.LX()==null)return!0
+"12"},"+new CollapsibleContentElement$created:0:0":1}},"+CollapsibleContentElement": [53],WZ:{"":"uL+Pi;",$isd3:true}}],["custom_element.polyfill","package:custom_element/polyfill.dart",,B,{G9:function(){if($.LX()==null)return!0
 var z=J.UQ($.LX(),"CustomElements")
 if(z==null)return"register" in document
 return J.xC(J.UQ(z,"ready"),!0)},zO:{"":"Tp;",
@@ -30749,7 +30831,7 @@
 if(typeof y==="object"&&y!==null&&!!z.$isZk)if(!("$reflectable" in y.dl))H.Hz(J.Z0(a))
 return H.vn(y.qj(b,c))},
 "+invoke:3:0":0,
-"*invoke":[40],
+"*invoke":[41],
 CI:function(a,b){return this.F2(a,b,null)},
 "+invoke:2:0":0,
 Z0:function(a){return $[a]},
@@ -30889,7 +30971,7 @@
 "+declarations":0,
 F2:function(a,b,c){throw H.b(P.lr(this,a,b,c,null))},
 "+invoke:3:0":0,
-"*invoke":[40],
+"*invoke":[41],
 CI:function(a,b){return this.F2(a,b,null)},
 "+invoke:2:0":0,
 rN:function(a){throw H.b(P.lr(this,a,null,null,null))},
@@ -30911,7 +30993,7 @@
 y=z+":"+b.length+":0"
 return this.tu(a,0,y,b)},
 "+invoke:3:0":0,
-"*invoke":[40],
+"*invoke":[41],
 CI:function(a,b){return this.F2(a,b,null)},
 "+invoke:2:0":0,
 tu:function(a,b,c,d){var z,y,x,w,v,u,t,s
@@ -31038,7 +31120,7 @@
 return z},
 F2:function(a,b,c){return this.NK.F2(a,b,c)},
 "+invoke:3:0":0,
-"*invoke":[40],
+"*invoke":[41],
 CI:function(a,b){return this.F2(a,b,null)},
 "+invoke:2:0":0,
 gHA:function(){return!1},
@@ -31090,7 +31172,7 @@
 y=J.x(z)
 if(typeof z==="object"&&z!==null&&!!y.$isGv)return z.constructor
 else return z
-"40"},
+"41"},
 "+_jsConstructor":1,
 gDI:function(){var z=this.b0
 if(z!=null)return z
@@ -31098,7 +31180,7 @@
 H.VM(z,[P.wv,P.RS])
 this.b0=z
 return z
-"52"},
+"54"},
 "+constructors":1,
 ly:function(a){var z,y,x,w,v,u,t,s,r,q,p,o,n,m,l,k
 z=this.gaB().prototype
@@ -31143,14 +31225,14 @@
 l=!1}s=H.Sd(k,o,!l,l)
 x.push(s)
 s.nz=a}return x
-"53,54,55"},
+"55,56,57"},
 "+_getMethodsWithOwner:1:0":1,
 gEO:function(){var z=this.jd
 if(z!=null)return z
 z=this.ly(this)
 this.jd=z
 return z
-"53"},
+"55"},
 "+_methods":1,
 ws:function(a){var z,y,x,w
 z=[]
@@ -31164,14 +31246,14 @@
 w=init.statics[this.WL]
 if(w!=null)H.jw(a,w[""],!0,z)
 return z
-"56,57,55"},
+"58,59,57"},
 "+_getFieldsWithOwner:1:0":1,
 gKn:function(){var z=this.tB
 if(z!=null)return z
 z=this.ws(this)
 this.tB=z
 return z
-"56"},
+"58"},
 "+_fields":1,
 gtx:function(){var z=this.FU
 if(z!=null)return z
@@ -31179,7 +31261,7 @@
 H.VM(z,[P.wv,P.RS])
 this.FU=z
 return z
-"52"},
+"54"},
 "+methods":1,
 gZ3:function(){var z,y,x
 z=this.M2
@@ -31190,7 +31272,7 @@
 H.VM(z,[P.wv,P.RY])
 this.M2=z
 return z
-"58"},
+"60"},
 "+variables":1,
 glc:function(a){var z=this.uA
 if(z!=null)return z
@@ -31198,7 +31280,7 @@
 H.VM(z,[P.wv,P.QF])
 this.uA=z
 return z
-"59"},
+"61"},
 "+members":1,
 gYK:function(){var z,y
 z=this.Db
@@ -31212,7 +31294,7 @@
 H.VM(z,[P.wv,P.NL])
 this.Db=z
 return z
-"60"},
+"62"},
 "+declarations":1,
 PU:function(a,b){var z,y
 z=J.UQ(this.gZ3(),a)
@@ -31220,7 +31302,7 @@
 if(!(y in $))throw H.b(H.Pa("Cannot find \""+y+"\" in current isolate."))
 $[y]=b
 return H.vn(b)}throw H.b(P.lr(this,H.X7(a),[b],null,null))
-"61,62,63,64,0"},
+"63,64,65,66,0"},
 "+setField:2:0":1,
 rN:function(a){var z,y
 z=J.UQ(this.gZ3(),a)
@@ -31228,7 +31310,7 @@
 if(!(y in $))throw H.b(H.Pa("Cannot find \""+y+"\" in current isolate."))
 if(y in init.lazies)return H.vn($[init.lazies[y]]())
 else return H.vn($[y])}throw H.b(P.lr(this,a,null,null,null))
-"61,62,63"},
+"63,64,65"},
 "+getField:1:0":1,
 gh7:function(){var z,y,x,w,v,u,t
 if(this.nz==null){z=this.Tx
@@ -31247,7 +31329,7 @@
 z=new H.MH(null,y,z.ew)
 z.$builtinTypeInfo=[u,t]
 for(;z.G();)for(y=J.GP(z.mD);y.G();)J.pP(y.gl())}if(this.nz==null)throw H.b(new P.lj("Class \""+H.d(J.Z0(this.If))+"\" has no owner"))}return this.nz
-"65"},
+"67"},
 "+owner":1,
 gc9:function(){var z=this.Ok
 if(z!=null)return z
@@ -31256,7 +31338,7 @@
 H.VM(z,[P.vr])
 this.Ok=z
 return z
-"66"},
+"68"},
 "+metadata":1,
 gAY:function(){var z,y,x,w,v,u
 if(this.qN==null){z=init.typeInformation[this.WL]
@@ -31270,7 +31352,7 @@
 u=v.length
 if(u>1){if(u!==2)throw H.b(H.Pa("Strange mixin: "+H.d(y)))
 this.qN=H.jO(v[0])}else this.qN=x.n(w,"")?this:H.jO(w)}}return J.xC(this.qN,this)?null:this.qN
-"67"},
+"69"},
 "+superclass":1,
 F2:function(a,b,c){var z
 if(c!=null&&J.FN(c)!==!0)throw H.b(P.f("Named arguments are not implemented."))
@@ -31278,16 +31360,16 @@
 if(z==null||!z.gFo())throw H.b(P.lr(this,a,b,c,null))
 if(!z.yR())H.Hz(J.Z0(a))
 return H.vn(z.qj(b,c))
-"61,68,63,69,70,71,72"},
+"63,70,65,71,72,73,74"},
 "+invoke:3:0":1,
-"*invoke":[40],
+"*invoke":[41],
 CI:function(a,b){return this.F2(a,b,null)},
 "+invoke:2:0":1,
 gHA:function(){return!0
-"44"},
+"46"},
 "+isOriginalDeclaration":1,
 gJi:function(){return this
-"67"},
+"69"},
 "+originalDeclaration":1,
 MR:function(a){var z,y,x
 z=init.typeInformation[this.WL]
@@ -31297,14 +31379,14 @@
 y=new P.Yp(x)
 H.VM(y,[P.Ms])
 return y
-"73,74,55"},
+"75,76,57"},
 "+_getSuperinterfacesWithOwner:1:0":1,
 gkZ:function(){var z=this.qm
 if(z!=null)return z
 z=this.MR(this)
 this.qm=z
 return z
-"73"},
+"75"},
 "+superinterfaces":1,
 gNy:function(){var z,y,x,w,v
 z=this.UF
@@ -31317,34 +31399,34 @@
 H.VM(z,[null])
 this.UF=z
 return z
-"75"},
+"77"},
 "+typeVariables":1,
 gw8:function(){return C.hU
-"76"},
+"78"},
 "+typeArguments":1,
 $isWf:true,
 $isMs:true,
 $isQF:true,
 $isL9u:true,
-$isNL:true},"+JsClassMirror": [77, 67],Un:{"":"EE+M2;",$isQF:true},Ei:{"":"Tp;a-",
+$isNL:true},"+JsClassMirror": [79, 69],Un:{"":"EE+M2;",$isQF:true},Ei:{"":"Tp;a-",
 call$2:function(a,b){J.kW(this.a,a,b)
-"40,78,63,31,79"},
+"41,80,65,32,81"},
 "+call:2:0":1,
 $isEH:true,
-$is_bh:true},"+JsClassMirror_declarations_addToResult": [80],U7:{"":"Tp;b-",
+$is_bh:true},"+JsClassMirror_declarations_addToResult": [82],U7:{"":"Tp;b-",
 call$1:function(a){J.kW(this.b,a.gIf(),a)
 return a
-"40,81,40"},
+"41,83,41"},
 "+call:1:0":1,
 $isEH:true,
 $is_HB:true,
-$is_Dv:true},"+JsClassMirror_declarations_closure": [80],t0:{"":"Tp;a-",
+$is_Dv:true},"+JsClassMirror_declarations_closure": [82],t0:{"":"Tp;a-",
 call$1:function(a){return H.Jf(this.a,init.metadata[a])
-"67,82,30"},
+"69,84,31"},
 "+call:1:0":1,
 $isEH:true,
 $is_HB:true,
-$is_Dv:true},"+JsClassMirror__getSuperinterfacesWithOwner_lookupType": [80],Ld:{"":"am;ao<,V5<,Fo<,n6,nz,le,If",
+$is_Dv:true},"+JsClassMirror__getSuperinterfacesWithOwner_lookupType": [82],Ld:{"":"am;ao<,V5<,Fo<,n6,nz,le,If",
 gOO:function(){return"VariableMirror"},
 "+_prettyName":0,
 gr9:function(a){return $.Cr()},
@@ -32011,7 +32093,7 @@
 $is_Dv:true},dm:{"":"Tp;b",
 call$2:function(a,b){this.b.K5(a,b)},
 "+call:2:0":0,
-"*call":[40],
+"*call":[41],
 call$1:function(a){return this.call$2(a,null)},
 "+call:1:0":0,
 $isEH:true,
@@ -32080,7 +32162,7 @@
 if(typeof y!=="object"||y===null||!x.$isvs){z.a=P.Dt(null)
 z.a.E6(a,b)}P.HZ(z.a,this.h)},
 "+call:2:0":0,
-"*call":[40],
+"*call":[41],
 call$1:function(a){return this.call$2(a,null)},
 "+call:1:0":0,
 $isEH:true,
@@ -35230,7 +35312,7 @@
 gor:function(a){return J.pO(this.iY)},
 "+isNotEmpty":0,
 $isL8:true}}],["dart.dom.html","dart:html",,W,{lq:function(){return window
-"12"},"+window":1,UE:function(a){if(P.F7()===!0)return"webkitTransitionEnd"
+"13"},"+window":1,UE:function(a){if(P.F7()===!0)return"webkitTransitionEnd"
 else if(P.dg()===!0)return"oTransitionEnd"
 return"transitionend"},r3:function(a,b){return document.createElement(a)},It:function(a,b,c){return W.lt(a,null,null,b,null,null,null,c).ml(new W.Kx())},lt:function(a,b,c,d,e,f,g,h){var z,y,x,w
 z=W.fJ
@@ -35301,7 +35383,7 @@
 q={prototype: s}
 if(!J.xC(w,"HTMLElement"))if(!v)q.extends=e
 b.register(c,q)},aF:function(a){if(J.xC($.X3,C.NU))return a
-return $.X3.oj(a,!0)},qE:{"":"cv;","%":"HTMLAppletElement|HTMLBRElement|HTMLBaseFontElement|HTMLBodyElement|HTMLCanvasElement|HTMLContentElement|HTMLDListElement|HTMLDataListElement|HTMLDetailsElement|HTMLDialogElement|HTMLDirectoryElement|HTMLDivElement|HTMLFontElement|HTMLFrameElement|HTMLFrameSetElement|HTMLHRElement|HTMLHeadElement|HTMLHeadingElement|HTMLHtmlElement|HTMLMarqueeElement|HTMLMenuElement|HTMLModElement|HTMLOptGroupElement|HTMLParagraphElement|HTMLPreElement|HTMLQuoteElement|HTMLShadowElement|HTMLSpanElement|HTMLTableCaptionElement|HTMLTableCellElement|HTMLTableColElement|HTMLTableDataCellElement|HTMLTableElement|HTMLTableHeaderCellElement|HTMLTableRowElement|HTMLTableSectionElement|HTMLTitleElement|HTMLUListElement|HTMLUnknownElement;HTMLElement;Sa|GN|ir|Nr|uL|Vf|aC|tu|Be|Vc|i6|WZ|Fv|pv|I3|Vfx|qr|Dsd|Gk|tuj|Ds|Vct|pR|D13|hx|u7|WZq|St|pva|vj|cda|CX|Nh|ih|waa|F1|XP|NQ|V0|fI|V4|kK|V6|uw"},Yy:{"":"Gv;",$isList:true,
+return $.X3.oj(a,!0)},qE:{"":"cv;","%":"HTMLAppletElement|HTMLBRElement|HTMLBaseFontElement|HTMLBodyElement|HTMLCanvasElement|HTMLContentElement|HTMLDListElement|HTMLDataListElement|HTMLDetailsElement|HTMLDialogElement|HTMLDirectoryElement|HTMLDivElement|HTMLFontElement|HTMLFrameElement|HTMLFrameSetElement|HTMLHRElement|HTMLHeadElement|HTMLHeadingElement|HTMLHtmlElement|HTMLMarqueeElement|HTMLMenuElement|HTMLModElement|HTMLOptGroupElement|HTMLParagraphElement|HTMLPreElement|HTMLQuoteElement|HTMLShadowElement|HTMLSpanElement|HTMLTableCaptionElement|HTMLTableCellElement|HTMLTableColElement|HTMLTableDataCellElement|HTMLTableElement|HTMLTableHeaderCellElement|HTMLTableRowElement|HTMLTableSectionElement|HTMLTitleElement|HTMLUListElement|HTMLUnknownElement;HTMLElement;Sa|GN|ir|Nr|uL|Vf|G6|tu|aC|Vc|Be|WZ|i6|pv|Fv|Vfx|I3|Dsd|qr|tuj|Gk|Vct|Ds|D13|pR|WZq|hx|u7|pva|St|cda|vj|waa|CX|Nh|ih|V0|F1|XP|NQ|V4|fI|V6|kK|V8|uw"},Yy:{"":"Gv;",$isList:true,
 $asWO:function(){return[W.M5]},
 $isqC:true,
 $iscX:true,
@@ -36335,12 +36417,12 @@
 $iscX:true,
 $ascX:function(){return[J.im]},
 $isXj:true,
-static:{"":"U9",}}}],["disassembly_entry_element","package:observatory/src/observatory_elements/disassembly_entry.dart",,E,{Fv:{"":["WZ;FT%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
+static:{"":"U9",}}}],["disassembly_entry_element","package:observatory/src/observatory_elements/disassembly_entry.dart",,E,{Fv:{"":["pv;FT%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
 gNI:function(a){return a.FT
-"37,38,39"},
+"38,39,40"},
 "+instruction":1,
 sNI:function(a,b){a.FT=this.pD(a,C.eJ,a.FT,b)
-"40,31,37,38"},
+"41,32,38,39"},
 "+instruction=":1,
 "@":function(){return[C.Vy]},
 static:{AH:function(a){var z,y,x,w,v,u
@@ -36359,18 +36441,18 @@
 C.Tl.ZL(a)
 C.Tl.FH(a)
 return a
-"13"},"+new DisassemblyEntryElement$created:0:0":1}},"+DisassemblyEntryElement": [83],WZ:{"":"uL+Pi;",$isd3:true}}],["error_view_element","package:observatory/src/observatory_elements/error_view.dart",,F,{I3:{"":["pv;Py%-,hO%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
+"14"},"+new DisassemblyEntryElement$created:0:0":1}},"+DisassemblyEntryElement": [85],pv:{"":"uL+Pi;",$isd3:true}}],["error_view_element","package:observatory/src/observatory_elements/error_view.dart",,F,{I3:{"":["Vfx;Py%-,hO%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
 gkc:function(a){return a.Py
-"8,38,39"},
+"8,39,40"},
 "+error":1,
 skc:function(a,b){a.Py=this.pD(a,C.YU,a.Py,b)
-"40,31,8,38"},
+"41,32,8,39"},
 "+error=":1,
 gVB:function(a){return a.hO
-"40,38,39"},
+"41,39,40"},
 "+error_obj":1,
 sVB:function(a,b){a.hO=this.pD(a,C.Yn,a.hO,b)
-"40,31,40,38"},
+"41,32,41,39"},
 "+error_obj=":1,
 "@":function(){return[C.uW]},
 static:{TW:function(a){var z,y,x,w,v
@@ -36387,12 +36469,12 @@
 C.OD.ZL(a)
 C.OD.FH(a)
 return a
-"14"},"+new ErrorViewElement$created:0:0":1}},"+ErrorViewElement": [84],pv:{"":"uL+Pi;",$isd3:true}}],["field_ref_element","package:observatory/src/observatory_elements/field_ref.dart",,D,{qr:{"":["Vfx;Lf%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
+"15"},"+new ErrorViewElement$created:0:0":1}},"+ErrorViewElement": [86],Vfx:{"":"uL+Pi;",$isd3:true}}],["field_ref_element","package:observatory/src/observatory_elements/field_ref.dart",,D,{qr:{"":["Dsd;Lf%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
 gt0:function(a){return a.Lf
-"37,38,39"},
+"38,39,40"},
 "+field":1,
 st0:function(a,b){a.Lf=this.pD(a,C.WQ,a.Lf,b)
-"40,31,37,38"},
+"41,32,38,39"},
 "+field=":1,
 "@":function(){return[C.ht]},
 static:{ip:function(a){var z,y,x,w,v
@@ -36408,12 +36490,12 @@
 C.WR.ZL(a)
 C.WR.FH(a)
 return a
-"15"},"+new FieldRefElement$created:0:0":1}},"+FieldRefElement": [85],Vfx:{"":"uL+Pi;",$isd3:true}}],["field_view_element","package:observatory/src/observatory_elements/field_view.dart",,A,{Gk:{"":["Dsd;vt%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
+"16"},"+new FieldRefElement$created:0:0":1}},"+FieldRefElement": [87],Dsd:{"":"uL+Pi;",$isd3:true}}],["field_view_element","package:observatory/src/observatory_elements/field_view.dart",,A,{Gk:{"":["tuj;vt%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
 gt0:function(a){return a.vt
-"37,38,39"},
+"38,39,40"},
 "+field":1,
 st0:function(a,b){a.vt=this.pD(a,C.WQ,a.vt,b)
-"40,31,37,38"},
+"41,32,38,39"},
 "+field=":1,
 "@":function(){return[C.Tq]},
 static:{cY:function(a){var z,y,x,w,v
@@ -36429,12 +36511,12 @@
 C.lS.ZL(a)
 C.lS.FH(a)
 return a
-"16"},"+new FieldViewElement$created:0:0":1}},"+FieldViewElement": [86],Dsd:{"":"uL+Pi;",$isd3:true}}],["function_view_element","package:observatory/src/observatory_elements/function_view.dart",,N,{Ds:{"":["tuj;ql%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
+"17"},"+new FieldViewElement$created:0:0":1}},"+FieldViewElement": [88],tuj:{"":"uL+Pi;",$isd3:true}}],["function_view_element","package:observatory/src/observatory_elements/function_view.dart",,N,{Ds:{"":["Vct;ql%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
 gMj:function(a){return a.ql
-"37,38,39"},
+"38,39,40"},
 "+function":1,
 sMj:function(a,b){a.ql=this.pD(a,C.nf,a.ql,b)
-"40,31,37,38"},
+"41,32,38,39"},
 "+function=":1,
 "@":function(){return[C.Uc]},
 static:{p7:function(a){var z,y,x,w,v
@@ -36450,7 +36532,7 @@
 C.PJ.ZL(a)
 C.PJ.FH(a)
 return a
-"17"},"+new FunctionViewElement$created:0:0":1}},"+FunctionViewElement": [87],tuj:{"":"uL+Pi;",$isd3:true}}],["html_common","dart:html_common",,P,{jD:function(a){return P.Wu(a.getTime(),!0)},bL:function(a){var z,y
+"18"},"+new FunctionViewElement$created:0:0":1}},"+FunctionViewElement": [89],Vct:{"":"uL+Pi;",$isd3:true}}],["html_common","dart:html_common",,P,{jD:function(a){return P.Wu(a.getTime(),!0)},bL:function(a){var z,y
 z=[]
 y=new P.Tm(new P.aI([],z),new P.rG(z),new P.yh(z)).call$1(a)
 new P.wO().call$0()
@@ -36638,12 +36720,12 @@
 "+call:1:0":0,
 $isEH:true,
 $is_HB:true,
-$is_Dv:true}}],["instance_ref_element","package:observatory/src/observatory_elements/instance_ref.dart",,B,{pR:{"":["Vct;iK%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
+$is_Dv:true}}],["instance_ref_element","package:observatory/src/observatory_elements/instance_ref.dart",,B,{pR:{"":["D13;iK%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
 ghf:function(a){return a.iK
-"37,38,39"},
+"38,39,40"},
 "+instance":1,
 shf:function(a,b){a.iK=this.pD(a,C.fn,a.iK,b)
-"40,31,37,38"},
+"41,32,38,39"},
 "+instance=":1,
 "@":function(){return[C.ay]},
 static:{lu:function(a){var z,y,x,w,v
@@ -36659,12 +36741,12 @@
 C.cp.ZL(a)
 C.cp.FH(a)
 return a
-"18"},"+new InstanceRefElement$created:0:0":1}},"+InstanceRefElement": [88],Vct:{"":"uL+Pi;",$isd3:true}}],["instance_view_element","package:observatory/src/observatory_elements/instance_view.dart",,Z,{hx:{"":["D13;Xh%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
+"19"},"+new InstanceRefElement$created:0:0":1}},"+InstanceRefElement": [90],D13:{"":"uL+Pi;",$isd3:true}}],["instance_view_element","package:observatory/src/observatory_elements/instance_view.dart",,Z,{hx:{"":["WZq;Xh%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
 ghf:function(a){return a.Xh
-"37,38,39"},
+"38,39,40"},
 "+instance":1,
 shf:function(a,b){a.Xh=this.pD(a,C.fn,a.Xh,b)
-"40,31,37,38"},
+"41,32,38,39"},
 "+instance=":1,
 "@":function(){return[C.ql]},
 static:{HC:function(a){var z,y,x,w,v
@@ -36680,7 +36762,7 @@
 C.yK.ZL(a)
 C.yK.FH(a)
 return a
-"19"},"+new InstanceViewElement$created:0:0":1}},"+InstanceViewElement": [89],D13:{"":"uL+Pi;",$isd3:true}}],["isolate_list_element","package:observatory/src/observatory_elements/isolate_list.dart",,L,{u7:{"":["uL;tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
+"20"},"+new InstanceViewElement$created:0:0":1}},"+InstanceViewElement": [91],WZq:{"":"uL+Pi;",$isd3:true}}],["isolate_list_element","package:observatory/src/observatory_elements/isolate_list.dart",,L,{u7:{"":["uL;tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
 "@":function(){return[C.jF]},
 static:{Tt:function(a){var z,y,x,w,v
 z=$.Nd()
@@ -36695,18 +36777,18 @@
 C.Dh.ZL(a)
 C.Dh.FH(a)
 return a
-"20"},"+new IsolateListElement$created:0:0":1}},"+IsolateListElement": [27]}],["isolate_summary_element","package:observatory/src/observatory_elements/isolate_summary.dart",,D,{St:{"":["WZq;Pw%-,i0%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
+"21"},"+new IsolateListElement$created:0:0":1}},"+IsolateListElement": [28]}],["isolate_summary_element","package:observatory/src/observatory_elements/isolate_summary.dart",,D,{St:{"":["pva;Pw%-,i0%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
 gF1:function(a){return a.Pw
-"30,38,39"},
+"31,39,40"},
 "+isolate":1,
 sF1:function(a,b){a.Pw=this.pD(a,C.Y2,a.Pw,b)
-"40,31,30,38"},
+"41,32,31,39"},
 "+isolate=":1,
 goc:function(a){return a.i0
-"8,38,39"},
+"8,39,40"},
 "+name":1,
 soc:function(a,b){a.i0=this.pD(a,C.YS,a.i0,b)
-"40,31,8,38"},
+"41,32,8,39"},
 "+name=":1,
 "@":function(){return[C.aM]},
 static:{N5:function(a){var z,y,x,w,v
@@ -36723,19 +36805,19 @@
 C.nM.ZL(a)
 C.nM.FH(a)
 return a
-"21"},"+new IsolateSummaryElement$created:0:0":1}},"+IsolateSummaryElement": [90],WZq:{"":"uL+Pi;",$isd3:true}}],["json_view_element","package:observatory/src/observatory_elements/json_view.dart",,Z,{vj:{"":["pva;eb%-,kf%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
+"22"},"+new IsolateSummaryElement$created:0:0":1}},"+IsolateSummaryElement": [92],pva:{"":"uL+Pi;",$isd3:true}}],["json_view_element","package:observatory/src/observatory_elements/json_view.dart",,Z,{vj:{"":["cda;eb%-,kf%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
 gTn:function(a){return a.eb
-"40,38,39"},
+"41,39,40"},
 "+json":1,
 sTn:function(a,b){a.eb=this.pD(a,C.Gd,a.eb,b)
-"40,31,40,38"},
+"41,32,41,39"},
 "+json=":1,
 i4:function(a){Z.uL.prototype.i4.call(this,a)
 a.kf=0
-"40"},
+"41"},
 "+enteredView:0:0":1,
 yC:function(a,b){this.pD(a,C.eR,"a","b")
-"40,91,40"},
+"41,93,41"},
 "+jsonChanged:1:0":1,
 gE8:function(a){return J.AG(a.eb)
 "8"},
@@ -36751,24 +36833,24 @@
 gFe:function(a){var z=a.kf
 a.kf=J.WB(z,1)
 return z
-"30"},
+"31"},
 "+counter":1,
 gqC:function(a){var z,y
 z=a.eb
 y=J.x(z)
 if(typeof z==="object"&&z!==null&&(z.constructor===Array||!!y.$isList))return z
 return[]
-"70"},
+"72"},
 "+list":1,
 gvc:function(a){var z,y
 z=a.eb
 y=J.RE(z)
 if(typeof z==="object"&&z!==null&&!!y.$isL8)return J.qA(y.gvc(z))
 return[]
-"70"},
+"72"},
 "+keys":1,
 r6:function(a,b){return J.UQ(a.eb,b)
-"40,78,8"},
+"41,80,8"},
 "+value:1:0":1,
 gP:function(a){return new P.C7(this,Z.vj.prototype.r6,a,"r6")},
 "@":function(){return[C.HN]},
@@ -36787,12 +36869,12 @@
 C.GB.ZL(a)
 C.GB.FH(a)
 return a
-"22"},"+new JsonViewElement$created:0:0":1}},"+JsonViewElement": [92],pva:{"":"uL+Pi;",$isd3:true}}],["library_view_element","package:observatory/src/observatory_elements/library_view.dart",,M,{CX:{"":["cda;iI%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
+"23"},"+new JsonViewElement$created:0:0":1}},"+JsonViewElement": [94],cda:{"":"uL+Pi;",$isd3:true}}],["library_view_element","package:observatory/src/observatory_elements/library_view.dart",,M,{CX:{"":["waa;iI%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
 gtD:function(a){return a.iI
-"37,38,39"},
+"38,39,40"},
 "+library":1,
 stD:function(a,b){a.iI=this.pD(a,C.EV,a.iI,b)
-"40,31,37,38"},
+"41,32,38,39"},
 "+library=":1,
 "@":function(){return[C.Oy]},
 static:{SP:function(a){var z,y,x,w,v,u
@@ -36811,7 +36893,7 @@
 C.MG.ZL(a)
 C.MG.FH(a)
 return a
-"23"},"+new LibraryViewElement$created:0:0":1}},"+LibraryViewElement": [93],cda:{"":"uL+Pi;",$isd3:true}}],["logging","package:logging/logging.dart",,N,{TJ:{"":"a;oc>,eT>,yz,Cj>,wd,Gs",
+"24"},"+new LibraryViewElement$created:0:0":1}},"+LibraryViewElement": [95],waa:{"":"uL+Pi;",$isd3:true}}],["logging","package:logging/logging.dart",,N,{TJ:{"":"a;oc>,eT>,yz,Cj>,wd,Gs",
 gB8:function(){var z,y,x
 z=this.eT
 y=z==null||J.xC(J.DA(z),"")
@@ -36879,26 +36961,27 @@
 giO:function(a){return this.P},
 bu:function(a){return this.oc},
 $isNg:true,
-static:{"":"bR,tm,EL,X8,IQ,Fn,Eb,AN,JY,bo",}},HV:{"":"a;OR<,G1>,iJ,Fl,O0,kc>,I4<",
+static:{"":"bR,tm,EL,X8,IQ,Fn,Eb,AN,JY,ac",}},HV:{"":"a;OR<,G1>,iJ,Fl,O0,kc>,I4<",
 bu:function(a){return"["+this.OR.oc+"] "+this.iJ+": "+this.G1},
 static:{"":"xO",}}}],["message_viewer_element","package:observatory/src/observatory_elements/message_viewer.dart",,L,{Nh:{"":["uL;XB%-,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
 gG1:function(a){return a.XB
-"37,39"},
+"38,40"},
 "+message":1,
 sG1:function(a,b){a.XB=b
 this.pD(a,C.KY,"",this.gQW(a))
 this.pD(a,C.wt,[],this.glc(a))
-"40,94,37,39"},
+"41,96,38,40"},
 "+message=":1,
 gQW:function(a){var z=a.XB
 if(z==null||J.UQ(z,"type")==null)return"Error"
+P.JS("Received message of type '"+H.d(J.UQ(a.XB,"type"))+"' :\n"+H.d(a.XB))
 return J.UQ(a.XB,"type")
 "8"},
 "+messageType":1,
 glc:function(a){var z=a.XB
 if(z==null||J.UQ(z,"members")==null)return[]
 return J.UQ(a.XB,"members")
-"95"},
+"97"},
 "+members":1,
 "@":function(){return[C.c0]},
 static:{rJ:function(a){var z,y,x,w,v
@@ -36914,7 +36997,7 @@
 C.Wp.ZL(a)
 C.Wp.FH(a)
 return a
-"24"},"+new MessageViewerElement$created:0:0":1}},"+MessageViewerElement": [27]}],["metadata","../../../../../../../../../dart/dart-sdk/lib/html/html_common/metadata.dart",,B,{fA:{"":"a;Kr,Jt",static:{"":"Xd,en,yS,PZ,xa",}},tz:{"":"a;"},jR:{"":"a;oc>"},PO:{"":"a;"},c5:{"":"a;"}}],["navigation_bar_element","package:observatory/src/observatory_elements/navigation_bar.dart",,Q,{ih:{"":["uL;tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
+"25"},"+new MessageViewerElement$created:0:0":1}},"+MessageViewerElement": [28]}],["metadata","../../../../../../../../../dart/dart-sdk/lib/html/html_common/metadata.dart",,B,{fA:{"":"a;Kr,Jt",static:{"":"Xd,en,yS,PZ,xa",}},tz:{"":"a;"},jR:{"":"a;oc>"},PO:{"":"a;"},c5:{"":"a;"}}],["navigation_bar_element","package:observatory/src/observatory_elements/navigation_bar.dart",,Q,{ih:{"":["uL;tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
 "@":function(){return[C.KG]},
 static:{BW:function(a){var z,y,x,w,v
 z=$.Nd()
@@ -36929,7 +37012,7 @@
 C.Xg.ZL(a)
 C.Xg.FH(a)
 return a
-"25"},"+new NavigationBarElement$created:0:0":1}},"+NavigationBarElement": [27]}],["observatory","package:observatory/observatory.dart",,L,{mL:{"":["Pi;Z6<-,lw<-,nI<-,VJ,Ai",function(){return[C.mI]},function(){return[C.mI]},function(){return[C.mI]},null,null],
+"26"},"+new NavigationBarElement$created:0:0":1}},"+NavigationBarElement": [28]}],["observatory","package:observatory/observatory.dart",,L,{mL:{"":["Pi;Z6<-,lw<-,nI<-,VJ,Ai",function(){return[C.mI]},function(){return[C.mI]},function(){return[C.mI]},null,null],
 Ey:function(){var z,y,x
 z=this.Z6
 z.sJR(this)
@@ -36963,16 +37046,16 @@
 y.US()
 return y}}},bv:{"":["Pi;nk,SS,XR<-,VJ,Ai",null,null,function(){return[C.mI]},null,null],
 gjO:function(a){return this.nk
-"30,38,43"},
+"31,39,45"},
 "+id":1,
 sjO:function(a,b){this.nk=F.Wi(this,C.EN,this.nk,b)
-"40,31,30,38"},
+"41,32,31,39"},
 "+id=":1,
 goc:function(a){return this.SS
-"8,38,43"},
+"8,39,45"},
 "+name":1,
 soc:function(a,b){this.SS=F.Wi(this,C.YS,this.SS,b)
-"40,31,8,38"},
+"41,32,8,39"},
 "+name=":1,
 bu:function(a){return H.d(this.nk)+" "+H.d(this.SS)},
 $isbv:true},pt:{"":["Pi;JR?,i2<-,VJ,Ai",null,function(){return[C.mI]},null,null],
@@ -37025,16 +37108,16 @@
 $is_HB:true,
 $is_Dv:true},dZ:{"":"Pi;JR?,IT,Jj,VJ,Ai",
 gzd:function(){return this.IT
-"8,38,43"},
+"8,39,45"},
 "+currentHash":1,
 szd:function(a){this.IT=F.Wi(this,C.h1,this.IT,a)
-"40,31,8,38"},
+"41,32,8,39"},
 "+currentHash=":1,
 glD:function(){return this.Jj
-"96,38,43"},
+"98,39,45"},
 "+currentHashUri":1,
 slD:function(a){this.Jj=F.Wi(this,C.tv,this.Jj,a)
-"40,31,96,38"},
+"41,32,98,39"},
 "+currentHashUri=":1,
 kI:function(){var z,y
 z=C.PP.aM(window)
@@ -37076,35 +37159,35 @@
 PI:function(a){var z=this.R6()
 if(J.xC(z,0))return"#/isolates/"
 return"#/isolates/"+H.d(z)+"/"+H.d(a)
-"8,97,8,43"},
+"8,99,8,45"},
 "+currentIsolateRelativeLink:1:0":1,
 Ao:function(a){var z=this.R6()
 if(J.xC(z,0))return"#/isolates/"
 return"#/isolates/"+H.d(z)+"/objects/"+H.d(a)
-"8,98,30,43"},
+"8,100,31,45"},
 "+currentIsolateObjectLink:1:0":1,
 dL:function(a){var z=this.R6()
 if(J.xC(z,0))return"#/isolates/"
 return"#/isolates/"+H.d(z)+"/classes/"+H.d(a)
-"8,99,30,43"},
+"8,101,31,45"},
 "+currentIsolateClassLink:1:0":1,
 WW:function(a,b){var z=this.R6()
 if(J.xC(z,0))return"#/isolates/"
 return this.yX(z,a,b)
-"8,98,30,7,8,43"},
+"8,100,31,7,8,45"},
 "+currentIsolateScriptLink:2:0":1,
 r4:function(a,b){return"#/isolates/"+H.d(a)+"/"+H.d(b)
-"8,100,30,97,8,43"},
+"8,102,31,99,8,45"},
 "+relativeLink:2:0":1,
 Dd:function(a,b){return"#/isolates/"+H.d(a)+"/objects/"+H.d(b)
-"8,100,30,98,30,43"},
+"8,102,31,100,31,45"},
 "+objectLink:2:0":1,
 bD:function(a,b){return"#/isolates/"+H.d(a)+"/classes/"+H.d(b)
-"8,100,30,99,30,43"},
+"8,102,31,101,31,45"},
 "+classLink:2:0":1,
 yX:function(a,b,c){var z=P.jW(C.kg,c,!0)
 return"#/isolates/"+H.d(a)+"/objects/"+H.d(b)+"?type=Script&name="+z
-"8,100,30,98,30,7,8,43"},
+"8,102,31,100,31,7,8,45"},
 "+scriptLink:3:0":1,
 static:{"":"kx,K3D,qY",}},Qe:{"":"Tp;a",
 call$1:function(a){var z=this.a
@@ -37116,16 +37199,16 @@
 $is_Dv:true},Nu:{"":"Pi;JR?,e0?",
 pG:function(){return this.e0.call$0()},
 gEI:function(){return this.oJ
-"8,38,43"},
+"8,39,45"},
 "+prefix":1,
 sEI:function(a){this.oJ=F.Wi(this,C.qb,this.oJ,a)
-"40,31,8,38"},
+"41,32,8,39"},
 "+prefix=":1,
 gn2:function(){return this.vm
-"95,38,43"},
+"97,39,45"},
 "+responses":1,
 sn2:function(a){this.vm=F.Wi(this,C.wH,this.vm,a)
-"40,31,95,38"},
+"41,32,97,39"},
 "+responses=":1,
 Qn:function(a){var z,y
 z=C.lM.kV(a)
@@ -37212,13 +37295,13 @@
 J.Ih(W.uV(window.parent),C.lM.KP(y),"*")
 return w.MM}},Zw:{"":["Pi;Rd,n7,LA>-,Vg,VJ,Ai",null,null,function(){return[C.mI]},null,null,null],
 geV:function(){return this.Vg
-"8,38,43"},
+"8,39,45"},
 "+paddedLine":1,
 seV:function(a){var z=this.Vg
 if(this.gUV(this)&&!J.xC(z,a)){z=new T.qI(this,C.X9,z,a)
 z.$builtinTypeInfo=[null]
 this.SZ(this,z)}this.Vg=a
-"40,31,8,38"},
+"41,32,8,39"},
 "+paddedLine=":1,
 QQ:function(a,b,c){var z,y,x,w,v
 z=""+this.Rd
@@ -37232,22 +37315,22 @@
 z.QQ(a,b,c)
 return z}}},Pf:{"":"Pi;WF,uM,ZQ,VJ,Ai",
 gfY:function(a){return this.WF
-"8,38,43"},
+"8,39,45"},
 "+kind":1,
 sfY:function(a,b){this.WF=F.Wi(this,C.fy,this.WF,b)
-"40,31,8,38"},
+"41,32,8,39"},
 "+kind=":1,
 gO3:function(a){return this.uM
-"8,38,43"},
+"8,39,45"},
 "+url":1,
 sO3:function(a,b){this.uM=F.Wi(this,C.Fh,this.uM,b)
-"40,31,8,38"},
+"41,32,8,39"},
 "+url=":1,
 gXJ:function(){return this.ZQ
-"101,38,43"},
+"103,39,45"},
 "+lines":1,
 sXJ:function(a){this.ZQ=F.Wi(this,C.Cv,this.ZQ,a)
-"40,31,101,38"},
+"41,32,103,39"},
 "+lines=":1,
 Cn:function(a){var z,y,x,w,v
 z=J.uH(a,"\n")
@@ -37267,17 +37350,17 @@
 static:{Sp:function(a){var z=R.Jk([])
 z=new L.Pf("","",z,null,null)
 z.EQ(a)
-return z}}}}],["observatory_application_element","package:observatory/src/observatory_elements/observatory_application.dart",,V,{F1:{"":["waa;k5%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
+return z}}}}],["observatory_application_element","package:observatory/src/observatory_elements/observatory_application.dart",,V,{F1:{"":["V0;k5%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
 gzj:function(a){return a.k5
-"44,38,39"},
+"46,39,40"},
 "+devtools":1,
 szj:function(a,b){a.k5=this.pD(a,C.Na,a.k5,b)
-"40,31,44,38"},
+"41,32,46,39"},
 "+devtools=":1,
 ZB:function(a){var z
 if(a.k5===!0){z=L.WS()
 a.tH=this.pD(a,C.wh,a.tH,z)}else{z=L.AK()
-a.tH=this.pD(a,C.wh,a.tH,z)}"40"},
+a.tH=this.pD(a,C.wh,a.tH,z)}"41"},
 "@":function(){return[C.bd]},
 static:{fv:function(a){var z,y,x,w,v
 z=$.Nd()
@@ -37294,23 +37377,23 @@
 C.k0.FH(a)
 C.k0.ZB(a)
 return a
-"26"},"+new ObservatoryApplicationElement$created:0:0":1}},"+ObservatoryApplicationElement": [102],waa:{"":"uL+Pi;",$isd3:true}}],["observatory_element","package:observatory/src/observatory_elements/observatory_element.dart",,Z,{uL:{"":["Nr;tH%-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
+"27"},"+new ObservatoryApplicationElement$created:0:0":1}},"+ObservatoryApplicationElement": [104],V0:{"":"uL+Pi;",$isd3:true}}],["observatory_element","package:observatory/src/observatory_elements/observatory_element.dart",,Z,{uL:{"":["Nr;tH%-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
 i4:function(a){A.dM.prototype.i4.call(this,a)
-"40"},
+"41"},
 "+enteredView:0:0":1,
 Nz:function(a){A.dM.prototype.Nz.call(this,a)
-"40"},
+"41"},
 "+leftView:0:0":1,
 gQG:function(a){return a.tH
-"103,38,39"},
+"105,39,40"},
 "+app":1,
 sQG:function(a,b){a.tH=this.pD(a,C.wh,a.tH,b)
-"40,31,103,38"},
+"41,32,105,39"},
 "+app=":1,
 gpQ:function(a){return!0
-"44"},
+"46"},
 "+applyAuthorStyles":1,
-"@":function(){return[C.J0]},
+"@":function(){return[C.Br]},
 static:{Hx:function(a){var z,y,x,w,v
 z=$.Nd()
 y=P.Py(null,null,null,J.O,W.I0)
@@ -37324,7 +37407,7 @@
 C.mk.ZL(a)
 C.mk.FH(a)
 return a
-"27"},"+new ObservatoryElement$created:0:0":1}},"+ObservatoryElement": [104],Nr:{"":"ir+Pi;",$isd3:true}}],["observe.src.change_notifier","package:observe/src/change_notifier.dart",,O,{Pi:{"":"a;",
+"28"},"+new ObservatoryElement$created:0:0":1}},"+ObservatoryElement": [106],Nr:{"":"ir+Pi;",$isd3:true}}],["observe.src.change_notifier","package:observe/src/change_notifier.dart",,O,{Pi:{"":"a;",
 gqh:function(a){var z,y
 if(a.VJ==null){z=this.gqw(a)
 a.VJ=P.bK(this.gl1(a),z,!0,null)}z=a.VJ
@@ -37368,7 +37451,7 @@
 gB:function(a){return this.b9.length},
 "+length":0,
 gP:function(a){return this.Sv
-"40,38"},
+"41,39"},
 "+value":1,
 r6:function(a,b){return this.gP(a).call$1(b)},
 wE:function(a){var z,y,x,w
@@ -37693,11 +37776,11 @@
 $isEH:true,
 $is_bh:true}}],["observe.src.observable_box","package:observe/src/observable_box.dart",,A,{xh:{"":"Pi;",
 gP:function(a){return this.L1
-"105,38"},
+"107,39"},
 "+value":1,
 r6:function(a,b){return this.gP(a).call$1(b)},
 sP:function(a,b){this.L1=F.Wi(this,C.ls,this.L1,b)
-"40,106,105,38"},
+"41,108,107,39"},
 "+value=":1,
 bu:function(a){return"#<"+H.d(new H.cu(H.dJ(this),null))+" value: "+H.d(this.L1)+">"}}}],["observe.src.observable_list","package:observe/src/observable_list.dart",,Q,{wn:{"":"uF;b3,xg,h3,VJ,Ai",
 gRT:function(){var z,y
@@ -37708,7 +37791,7 @@
 H.VM(y,[H.W8(z,"WV",0)])
 return y},
 gB:function(a){return this.h3.length
-"30,38"},
+"31,39"},
 "+length":1,
 sB:function(a,b){var z,y,x,w,v,u,t
 z=this.h3
@@ -37737,12 +37820,12 @@
 w=new P.Yp(t)
 w.$builtinTypeInfo=[null]
 this.iH(new G.W4(this,w,t,y,x))}}C.Nm.sB(z,b)
-"40,31,30,38"},
+"41,32,31,39"},
 "+length=":1,
 t:function(a,b){var z=this.h3
 if(b>>>0!==b||b>=z.length)throw H.e(z,b)
 return z[b]
-"107,29,30,38"},
+"109,30,31,39"},
 "+[]:1:0":1,
 u:function(a,b,c){var z,y,x,w
 z=this.h3
@@ -37756,7 +37839,7 @@
 w.$builtinTypeInfo=[null]
 this.iH(new G.W4(this,w,x,b,1))}if(b>=z.length)throw H.e(z,b)
 z[b]=c
-"40,29,30,31,107,38"},
+"41,30,31,32,109,39"},
 "+[]=:2:0":1,
 h:function(a,b){var z,y,x,w
 z=this.h3
@@ -37845,33 +37928,33 @@
 $isHA:true},br:{"":"Pi;Zp,VJ,Ai",
 gvc:function(a){var z=this.Zp
 return z.gvc(z)
-"108,38"},
+"110,39"},
 "+keys":1,
 gUQ:function(a){var z=this.Zp
 return z.gUQ(z)
-"109,38"},
+"111,39"},
 "+values":1,
 gB:function(a){var z=this.Zp
 return z.gB(z)
-"30,38"},
+"31,39"},
 "+length":1,
 gl0:function(a){var z=this.Zp
 return z.gB(z)===0
-"44,38"},
+"46,39"},
 "+isEmpty":1,
 gor:function(a){var z=this.Zp
 return z.gB(z)!==0
-"44,38"},
+"46,39"},
 "+isNotEmpty":1,
 PF:function(a){return this.Zp.PF(a)
-"44,31,0,38"},
+"46,32,0,39"},
 "+containsValue:1:0":1,
 x4:function(a){return this.Zp.x4(a)
-"44,78,0,38"},
+"46,80,0,39"},
 "+containsKey:1:0":1,
 t:function(a,b){var z=this.Zp
 return z.t(z,b)
-"110,78,0,38"},
+"112,80,0,39"},
 "+[]:1:0":1,
 u:function(a,b,c){var z,y,x,w,v
 z=this.Zp
@@ -37888,7 +37971,7 @@
 z.$builtinTypeInfo=[null,null]
 this.SZ(this,z)}else if(!J.xC(x,c)){z=new V.HA(b,x,c,!1,!1)
 z.$builtinTypeInfo=[null,null]
-this.SZ(this,z)}"40,78,111,31,110,38"},
+this.SZ(this,z)}"41,80,113,32,112,39"},
 "+[]=:2:0":1,
 Ay:function(a,b){b.aN(b,new V.zT(this))},
 Rz:function(a,b){var z,y,x,w,v
@@ -37999,7 +38082,7 @@
 z=y==null?z!=null:y!==z}else z=!1
 if(!z)this.ov()
 return C.Nm.grZ(this.kN)
-"40,38"},
+"41,39"},
 "+value":1,
 r6:function(a,b){return this.gP(a).call$1(b)},
 sP:function(a,b){var z,y,x,w
@@ -38017,7 +38100,7 @@
 if(w>=z.length)throw H.e(z,w)
 if(L.h6(x,z[w],b)){z=this.kN
 if(y>=z.length)throw H.e(z,y)
-z[y]=b}"40,106,0,38"},
+z[y]=b}"41,108,0,39"},
 "+value=":1,
 w3:function(a){O.Pi.prototype.w3.call(this,this)
 this.ov()
@@ -39179,7 +39262,7 @@
 y=typeof z==="object"&&z!==null&&!!y.$isEZ}else y=!1}else y=!1
 if(y)return
 return new T.Xy(this,b,z)},
-gca:function(){return new T.Dw(this,T.e9.prototype.yt,null,"yt")},
+gca:function(){return new T.PD(this,T.e9.prototype.yt,null,"yt")},
 A5:function(a){return new T.uK(this)}},Xy:{"":"Tp;a,b,c",
 call$2:function(a,b){var z=J.x(a)
 if(typeof a!=="object"||a===null||!z.$isz6)a=new K.z6(null,a,V.WF(this.a.nF,null,null),null)
@@ -39206,14 +39289,14 @@
 F.Wi(this,C.ls,z,this.uK)},
 gnc:function(){return new H.Pm(this,T.mY.prototype.vr,null,"vr")},
 gP:function(a){return this.uK
-"40,38"},
+"41,39"},
 "+value":1,
 r6:function(a,b){return this.gP(a).call$1(b)},
 sP:function(a,b){var z,y,x,w
 try{K.jX(this.jf,b,this.qc)}catch(y){x=H.Ru(y)
 w=J.x(x)
 if(typeof x==="object"&&x!==null&&!!w.$isB0){z=x
-$.IS().A3("Error evaluating expression '"+H.d(this.jf)+"': "+J.z2(z))}else throw y}"40,112,40,38"},
+$.IS().A3("Error evaluating expression '"+H.d(this.jf)+"': "+J.z2(z))}else throw y}"41,114,41,39"},
 "+value=":1,
 Va:function(a,b,c){var z,y,x,w,v
 y=this.jf
@@ -39675,7 +39758,7 @@
 return 536870911&a+((16383&a)<<15>>>0)},Fq:{"":"a;",
 F2:function(a,b,c){return new U.RW(a,b,c)},
 "+invoke:3:0":0,
-"*invoke":[40],
+"*invoke":[41],
 CI:function(a,b){return this.F2(a,b,null)},
 "+invoke:2:0":0},hw:{"":"a;",$ishw:true},EZ:{"":"hw;",
 RR:function(a,b){return b.W9(this)},
@@ -39969,7 +40052,7 @@
 static:{i0:function(a,b,c){var z=new K.Ae(a,b)
 H.VM(z,[c])
 return z
-"28,29,30,31,32"},"+new IndexedValue:2:0":1}},"+IndexedValue": [0],Bt:{"":"mW;YR",
+"29,30,31,32,33"},"+new IndexedValue:2:0":1}},"+IndexedValue": [0],Bt:{"":"mW;YR",
 gA:function(a){var z=J.GP(this.YR)
 z=new K.vR(z,0,null)
 H.VM(z,[H.W8(this,"Bt",0)])
@@ -40163,15 +40246,15 @@
 C.Cc.ZL(a)
 C.Cc.FH(a)
 return a
-"33"},"+new ResponseViewerElement$created:0:0":1}},"+ResponseViewerElement": [27]}],["script_view_element","package:observatory/src/observatory_elements/script_view.dart",,U,{fI:{"":["V0;Uz%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
+"34"},"+new ResponseViewerElement$created:0:0":1}},"+ResponseViewerElement": [28]}],["script_view_element","package:observatory/src/observatory_elements/script_view.dart",,U,{fI:{"":["V4;Uz%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
 gNl:function(a){return a.Uz
-"37,38,39"},
+"38,39,40"},
 "+script":1,
 sNl:function(a,b){a.Uz=this.pD(a,C.fX,a.Uz,b)
-"40,31,37,38"},
+"41,32,38,39"},
 "+script=":1,
 "@":function(){return[C.Er]},
-static:{Ry:function(a){var z,y,x,w,v
+static:{kL:function(a){var z,y,x,w,v
 z=$.Nd()
 y=P.Py(null,null,null,J.O,W.I0)
 x=J.O
@@ -40184,12 +40267,12 @@
 C.cJ.ZL(a)
 C.cJ.FH(a)
 return a
-"34"},"+new ScriptViewElement$created:0:0":1}},"+ScriptViewElement": [113],V0:{"":"uL+Pi;",$isd3:true}}],["source_view_element","package:observatory/src/observatory_elements/source_view.dart",,X,{kK:{"":["V4;vX%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
+"35"},"+new ScriptViewElement$created:0:0":1}},"+ScriptViewElement": [115],V4:{"":"uL+Pi;",$isd3:true}}],["source_view_element","package:observatory/src/observatory_elements/source_view.dart",,X,{kK:{"":["V6;vX%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
 gFF:function(a){return a.vX
-"114,38,39"},
+"116,39,40"},
 "+source":1,
 sFF:function(a,b){a.vX=this.pD(a,C.hn,a.vX,b)
-"40,31,114,38"},
+"41,32,116,39"},
 "+source=":1,
 "@":function(){return[C.H8]},
 static:{HO:function(a){var z,y,x,w,v
@@ -40205,12 +40288,12 @@
 C.Ks.ZL(a)
 C.Ks.FH(a)
 return a
-"35"},"+new SourceViewElement$created:0:0":1}},"+SourceViewElement": [115],V4:{"":"uL+Pi;",$isd3:true}}],["stack_trace_element","package:observatory/src/observatory_elements/stack_trace.dart",,X,{uw:{"":["V6;V4%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
+"36"},"+new SourceViewElement$created:0:0":1}},"+SourceViewElement": [117],V6:{"":"uL+Pi;",$isd3:true}}],["stack_trace_element","package:observatory/src/observatory_elements/stack_trace.dart",,X,{uw:{"":["V8;V4%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
 gtN:function(a){return a.V4
-"37,38,39"},
+"38,39,40"},
 "+trace":1,
 stN:function(a,b){a.V4=this.pD(a,C.kw,a.V4,b)
-"40,31,37,38"},
+"41,32,38,39"},
 "+trace=":1,
 "@":function(){return[C.js]},
 static:{bV:function(a){var z,y,x,w,v,u
@@ -40229,7 +40312,7 @@
 C.bg.ZL(a)
 C.bg.FH(a)
 return a
-"36"},"+new StackTraceElement$created:0:0":1}},"+StackTraceElement": [116],V6:{"":"uL+Pi;",$isd3:true}}],["template_binding","package:template_binding/template_binding.dart",,M,{IP:function(a){var z=J.RE(a)
+"37"},"+new StackTraceElement$created:0:0":1}},"+StackTraceElement": [118],V8:{"":"uL+Pi;",$isd3:true}}],["template_binding","package:template_binding/template_binding.dart",,M,{IP:function(a){var z=J.RE(a)
 if(typeof a==="object"&&a!==null&&!!z.$isQl)return C.io.f0(a)
 switch(z.gr9(a)){case"checkbox":return $.FF().aM(a)
 case"radio":case"select-multiple":case"select-one":return z.gEr(a)
@@ -41309,6 +41392,7 @@
 if(typeof a!="object")return a
 if(a instanceof P.a)return a
 return J.ks(a)}
+C.J0=B.G6.prototype
 C.OL=new U.EZ()
 C.Gw=new H.SJ()
 C.E3=new J.Q()
@@ -41329,7 +41413,7 @@
 C.YD=F.Be.prototype
 C.j8=R.i6.prototype
 C.Vy=new A.V3("disassembly-entry")
-C.J0=new A.V3("observatory-element")
+C.Br=new A.V3("observatory-element")
 C.Er=new A.V3("script-view")
 C.ht=new A.V3("field-ref")
 C.aM=new A.V3("isolate-summary")
@@ -41341,6 +41425,7 @@
 C.c0=new A.V3("message-viewer")
 C.js=new A.V3("stack-trace")
 C.jF=new A.V3("isolate-list")
+C.PT=new A.V3("breakpoint-list")
 C.KG=new A.V3("navigation-bar")
 C.ay=new A.V3("instance-ref")
 C.Gu=new A.V3("collapsible-content")
@@ -41574,6 +41659,7 @@
 C.PC=new H.GD("dart.core.int")
 C.wt=new H.GD("members")
 C.KY=new H.GD("messageType")
+C.Ry=new H.GD("msg")
 C.YS=new H.GD("name")
 C.OV=new H.GD("noSuchMethod")
 C.Ws=new H.GD("operatingSystem")
@@ -41601,14 +41687,15 @@
 C.Ti=H.mm('wn')
 C.Mt=new H.Lm(C.Ti,"E",0)
 C.Ye=H.mm('hx')
-C.G6=H.mm('F1')
+C.bD=H.mm('F1')
 C.NM=H.mm('Nh')
+C.z7=H.mm('G6')
 C.nY=H.mm('a')
 C.Yc=H.mm('iP')
 C.LN=H.mm('Be')
 C.Qa=H.mm('u7')
 C.xS=H.mm('UZ')
-C.PT=H.mm('CX')
+C.mA=H.mm('CX')
 C.Op=H.mm('G8')
 C.xF=H.mm('NQ')
 C.b4=H.mm('ih')
@@ -41813,8 +41900,8 @@
 J.z2=function(a){return J.RE(a).gG1(a)}
 J.zZ=function(a,b){return J.RE(a).Yv(a,b)}
 J.zj=function(a){return J.RE(a).gvH(a)}
-$.Dq=["Ay","BN","BT","Ba","C","C0","C8","Ch","D","D3","D6","Dh","E","Ec","F","FH","Fr","GB","HG","Hn","Id","Ih","Im","Is","J","J3","JP","JT","JV","Ja","Jk","Kb","LV","Md","Mi","Mu","Nj","Nz","O","On","PM","Pa","Pk","Pv","R3","R4","RB","RR","Rz","SZ","T","T2","TH","TP","TW","Tc","Td","U","UD","UH","UZ","Uc","V","V1","Vr","Vy","W","W3","W4","WO","WZ","Wt","Wz","X6","XG","XU","Xl","Y9","YU","YW","Ys","Yv","Z","Z1","Z2","ZB","ZF","ZL","ZP","Zv","aC","aN","aq","bA","bS","br","bu","cO","cn","d0","dR","dd","du","eR","ea","er","es","ev","ez","f6","fd","fj","fk","fm","g","gA","gB","gBb","gCd","gCj","gDD","gDg","gE8","gEX","gEr","gF1","gFF","gFJ","gFT","gFV","gFe","gG0","gG1","gG3","gGL","gHs","gI","gIi","gJS","gJf","gKE","gKM","gKV","gLA","gLU","gLf","gLm","gM0","gMB","gMj","gN","gNI","gNl","gO3","gP","gP1","gP2","gPp","gPu","gPw","gPy","gQ0","gQG","gQW","gQg","gRn","gRu","gT8","gTM","gTn","gTq","gUQ","gUV","gUz","gV4","gVA","gVB","gVl","gXB","gXf","gXh","gXt","gZw","gai","gbP","gbx","gcC","geT","geb","gey","gfY","ghO","ghf","ghr","gi0","giC","giI","giK","giO","gig","gjL","gjO","gjU","gjb","gk5","gkU","gkc","gkf","gkp","gl0","gl7","glc","gmW","gmm","gn4","goc","gor","gpQ","gpo","gq6","gqC","gqh","gql","gr3","gr9","grK","grZ","gt0","gtD","gtH","gtN","gtT","guD","gvH","gvX","gvc","gvt","gxj","gxr","gyT","gys","gzP","gzZ","gzj","h","h8","hV","hc","i","i4","iA","iM","iw","j","jT","jx","kO","l5","l8","lj","m","mK","mv","n","nB","nC","nH","nP","ni","oB","oW","od","oo","oq","pD","pZ","pl","pr","qZ","r6","rJ","rS","sB","sF1","sFF","sFJ","sFT","sG1","sIt","sLA","sLf","sMj","sNI","sNl","sO3","sP","sP2","sPw","sPy","sQG","sRu","sTn","sTq","sUz","sV4","sVA","sVB","sXB","sXf","sXh","sZw","sa4","sai","scC","seb","sfY","shO","shf","si0","siI","siK","sig","sjO","sk5","skc","skf","sl7","soc","sql","sr9","st0","stD","stH","stN","stT","svX","svt","sxj","sxr","szZ","szj","t","tZ","tg","tt","u","u5","u8","uG","vs","w3","wE","wL","wR","wg","x3","xI","xc","xe","y0","yC","yc","ym","yn","yq","yu","yx","yy","z2","zV"]
-$.Au=[C.Ye,Z.hx,{created:Z.HC},C.G6,V.F1,{created:V.fv},C.NM,L.Nh,{created:L.rJ},C.LN,F.Be,{created:F.Fe},C.Qa,L.u7,{created:L.Tt},C.xS,P.UZ,{},C.PT,M.CX,{created:M.SP},C.Op,P.G8,{},C.xF,Q.NQ,{created:Q.Zo},C.b4,Q.ih,{created:Q.BW},C.Ob,X.kK,{created:X.HO},C.hG,A.ir,{created:A.oa},C.aj,U.fI,{created:U.Ry},C.mo,E.Fv,{created:E.AH},C.xE,Z.aC,{created:Z.zg},C.vuj,X.uw,{created:X.bV},C.j6,D.qr,{created:D.ip},C.C6,Z.vj,{created:Z.un},C.CT,D.St,{created:D.N5},C.Q4,Z.uL,{created:Z.Hx},C.yg,F.I3,{created:F.TW},C.XU,R.i6,{created:R.IT},C.Bm,A.XP,{created:A.XL},C.Wz,B.pR,{created:B.lu},C.mnH,N.Ds,{created:N.p7},C.XK,A.Gk,{created:A.cY}]
+$.Dq=["Ay","BN","BT","Ba","C","C0","C8","Ch","D","D3","D6","Dh","E","Ec","F","FH","Fr","GB","HG","Hn","Id","Ih","Im","Is","J","J3","JP","JT","JV","Ja","Jk","Kb","LV","Md","Mi","Mu","Nj","Nz","O","On","PM","Pa","Pk","Pv","R3","R4","RB","RR","Rz","SZ","T","T2","TH","TP","TW","Tc","Td","U","UD","UH","UZ","Uc","V","V1","Vr","Vy","W","W3","W4","WO","WZ","Wt","Wz","X6","XG","XU","Xl","Y9","YU","YW","Ys","Yv","Z","Z1","Z2","ZB","ZF","ZL","ZP","Zv","aC","aN","aq","bA","bS","br","bu","cO","cn","d0","dR","dd","du","eR","ea","er","es","ev","ez","f6","fd","fj","fk","fm","g","gA","gB","gBb","gCd","gCj","gDD","gDg","gE8","gEX","gEr","gF1","gFF","gFJ","gFT","gFV","gFe","gG0","gG1","gG3","gGL","gHs","gI","gIi","gJS","gJf","gKE","gKM","gKV","gLA","gLU","gLf","gLm","gM0","gMB","gMj","gN","gNI","gNl","gO3","gP","gP1","gP2","gPp","gPu","gPw","gPy","gQ0","gQG","gQW","gQg","gRn","gRu","gT8","gTM","gTn","gTq","gUQ","gUV","gUz","gV4","gVA","gVB","gVl","gXB","gXf","gXh","gXt","gZw","gai","gbP","gbx","gcC","geE","geT","geb","gey","gfY","ghO","ghf","ghr","gi0","giC","giI","giK","giO","gig","gjL","gjO","gjU","gjb","gk5","gkU","gkc","gkf","gkp","gl0","gl7","glc","gmW","gmm","gn4","goc","gor","gpQ","gpo","gq6","gqC","gqh","gql","gr3","gr9","grK","grZ","grs","gt0","gtD","gtH","gtN","gtT","guD","gvH","gvX","gvc","gvt","gxj","gxr","gyT","gys","gzP","gzZ","gzj","h","h8","hV","hc","i","i4","iA","iM","iw","j","jT","jx","kO","l5","l8","lj","m","mK","mv","n","nB","nC","nH","nP","ni","oB","oW","od","oo","oq","pD","pZ","pl","pr","qZ","r6","rJ","rS","sB","sF1","sFF","sFJ","sFT","sG1","sIt","sLA","sLf","sMj","sNI","sNl","sO3","sP","sP2","sPw","sPy","sQG","sRu","sTn","sTq","sUz","sV4","sVA","sVB","sXB","sXf","sXh","sZw","sa4","sai","scC","seE","seb","sfY","shO","shf","si0","siI","siK","sig","sjO","sk5","skc","skf","sl7","soc","sql","sr9","srs","st0","stD","stH","stN","stT","svX","svt","sxj","sxr","szZ","szj","t","tZ","tg","tt","u","u5","u8","uG","vs","w3","wE","wL","wR","wg","x3","xI","xc","xe","y0","yC","yc","ym","yn","yq","yu","yx","yy","z2","zV"]
+$.Au=[C.Ye,Z.hx,{created:Z.HC},C.bD,V.F1,{created:V.fv},C.NM,L.Nh,{created:L.rJ},C.z7,B.G6,{created:B.Dw},C.LN,F.Be,{created:F.Fe},C.Qa,L.u7,{created:L.Tt},C.xS,P.UZ,{},C.mA,M.CX,{created:M.SP},C.Op,P.G8,{},C.xF,Q.NQ,{created:Q.Zo},C.b4,Q.ih,{created:Q.BW},C.Ob,X.kK,{created:X.HO},C.hG,A.ir,{created:A.oa},C.aj,U.fI,{created:U.kL},C.mo,E.Fv,{created:E.AH},C.xE,Z.aC,{created:Z.zg},C.vuj,X.uw,{created:X.bV},C.j6,D.qr,{created:D.ip},C.C6,Z.vj,{created:Z.un},C.CT,D.St,{created:D.N5},C.Q4,Z.uL,{created:Z.Hx},C.yg,F.I3,{created:F.TW},C.XU,R.i6,{created:R.IT},C.Bm,A.XP,{created:A.XL},C.Wz,B.pR,{created:B.lu},C.mnH,N.Ds,{created:N.p7},C.XK,A.Gk,{created:A.cY}]
 I.$lazy($,"globalThis","DX","jk",function(){return function() { return this; }()})
 I.$lazy($,"globalWindow","pG","Qm",function(){return $.jk().window})
 I.$lazy($,"globalWorker","zA","Nl",function(){return $.jk().Worker})
@@ -41914,7 +42001,7 @@
 return z})
 
 init.functionAliases={}
-init.metadata=[P.a,C.wK,C.wa,C.WX,C.Mt,C.wW,P.uq,"name",J.O,Z.aC,F.Be,R.i6,W.K5,E.Fv,F.I3,D.qr,A.Gk,N.Ds,B.pR,Z.hx,L.u7,D.St,Z.vj,M.CX,L.Nh,Q.ih,V.F1,Z.uL,[K.Ae,3],"index",J.im,"value",3,Q.NQ,U.fI,X.kK,X.uw,P.L8,C.nJ,C.Us,,Z.Vf,F.tu,C.mI,J.kn,"r","e",W.ea,"detail","target",W.KV,R.Vc,[P.L8,P.wv,P.RS],[J.Q,H.Zk],"methodOwner",P.NL,[J.Q,P.RY],"fieldOwner",[P.L8,P.wv,P.RY],[P.L8,P.wv,P.QF],[P.L8,P.wv,P.NL],P.vr,"fieldName",P.wv,"arg",H.Uz,[J.Q,P.vr],P.Ms,"memberName","positionalArguments",J.Q,"namedArguments",[P.L8,P.wv,null],[J.Q,P.Ms],"owner",[J.Q,P.Fw],[J.Q,P.L9u],H.Un,"key",P.QF,H.Tp,"tv","i",E.WZ,F.pv,D.Vfx,A.Dsd,N.tuj,B.Vct,Z.D13,D.WZq,"oldValue",Z.pva,M.cda,"m",[J.Q,P.L8],P.iD,"l","objectId","cid","isolateId",[J.Q,L.Zw],V.waa,L.mL,Z.Nr,5,"newValue",4,[P.cX,1],[P.cX,2],2,1,"v",U.V0,L.Pf,X.V4,X.V6,];$=null
+init.metadata=[P.a,C.wK,C.wa,C.WX,C.Mt,C.wW,P.uq,"name",J.O,B.G6,Z.aC,F.Be,R.i6,W.K5,E.Fv,F.I3,D.qr,A.Gk,N.Ds,B.pR,Z.hx,L.u7,D.St,Z.vj,M.CX,L.Nh,Q.ih,V.F1,Z.uL,[K.Ae,3],"index",J.im,"value",3,Q.NQ,U.fI,X.kK,X.uw,P.L8,C.nJ,C.Us,,B.Vf,Z.tu,F.Vc,C.mI,J.kn,"r","e",W.ea,"detail","target",W.KV,R.WZ,[P.L8,P.wv,P.RS],[J.Q,H.Zk],"methodOwner",P.NL,[J.Q,P.RY],"fieldOwner",[P.L8,P.wv,P.RY],[P.L8,P.wv,P.QF],[P.L8,P.wv,P.NL],P.vr,"fieldName",P.wv,"arg",H.Uz,[J.Q,P.vr],P.Ms,"memberName","positionalArguments",J.Q,"namedArguments",[P.L8,P.wv,null],[J.Q,P.Ms],"owner",[J.Q,P.Fw],[J.Q,P.L9u],H.Un,"key",P.QF,H.Tp,"tv","i",E.pv,F.Vfx,D.Dsd,A.tuj,N.Vct,B.D13,Z.WZq,D.pva,"oldValue",Z.cda,M.waa,"m",[J.Q,P.L8],P.iD,"l","objectId","cid","isolateId",[J.Q,L.Zw],V.V0,L.mL,Z.Nr,5,"newValue",4,[P.cX,1],[P.cX,2],2,1,"v",U.V4,L.Pf,X.V6,X.V8,];$=null
 I = I.$finishIsolateConstructor(I)
 $=new I()
 function convertToFastObject(properties) {
@@ -44215,6 +44302,35 @@
 $desc=$collectedClasses.tQ
 if($desc instanceof Array)$desc=$desc[1]
 tQ.prototype=$desc
+function G6(eE,VJ,Ai,tH,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM){this.eE=eE
+this.VJ=VJ
+this.Ai=Ai
+this.tH=tH
+this.VJ=VJ
+this.Ai=Ai
+this.VJ=VJ
+this.Ai=Ai
+this.ZI=ZI
+this.uN=uN
+this.z3=z3
+this.TQ=TQ
+this.Vk=Vk
+this.Ye=Ye
+this.mT=mT
+this.KM=KM}G6.builtin$cls="G6"
+if(!"name" in G6)G6.name="G6"
+$desc=$collectedClasses.G6
+if($desc instanceof Array)$desc=$desc[1]
+G6.prototype=$desc
+G6.prototype.geE=function(receiver){return receiver.eE}
+G6.prototype.geE.$reflectable=1
+G6.prototype.seE=function(receiver,v){return receiver.eE=v}
+G6.prototype.seE.$reflectable=1
+function Vf(){}Vf.builtin$cls="Vf"
+if(!"name" in Vf)Vf.name="Vf"
+$desc=$collectedClasses.Vf
+if($desc instanceof Array)$desc=$desc[1]
+Vf.prototype=$desc
 function aC(FJ,VJ,Ai,tH,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM){this.FJ=FJ
 this.VJ=VJ
 this.Ai=Ai
@@ -44239,11 +44355,11 @@
 aC.prototype.gFJ.$reflectable=1
 aC.prototype.sFJ=function(receiver,v){return receiver.FJ=v}
 aC.prototype.sFJ.$reflectable=1
-function Vf(){}Vf.builtin$cls="Vf"
-if(!"name" in Vf)Vf.name="Vf"
-$desc=$collectedClasses.Vf
+function tu(){}tu.builtin$cls="tu"
+if(!"name" in tu)tu.name="tu"
+$desc=$collectedClasses.tu
 if($desc instanceof Array)$desc=$desc[1]
-Vf.prototype=$desc
+tu.prototype=$desc
 function Be(Zw,VJ,Ai,tH,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM){this.Zw=Zw
 this.VJ=VJ
 this.Ai=Ai
@@ -44268,11 +44384,11 @@
 Be.prototype.gZw.$reflectable=1
 Be.prototype.sZw=function(receiver,v){return receiver.Zw=v}
 Be.prototype.sZw.$reflectable=1
-function tu(){}tu.builtin$cls="tu"
-if(!"name" in tu)tu.name="tu"
-$desc=$collectedClasses.tu
+function Vc(){}Vc.builtin$cls="Vc"
+if(!"name" in Vc)Vc.name="Vc"
+$desc=$collectedClasses.Vc
 if($desc instanceof Array)$desc=$desc[1]
-tu.prototype=$desc
+Vc.prototype=$desc
 function i6(Xf,VA,P2,VJ,Ai,tH,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM){this.Xf=Xf
 this.VA=VA
 this.P2=P2
@@ -44307,11 +44423,11 @@
 i6.prototype.gP2.$reflectable=1
 i6.prototype.sP2=function(receiver,v){return receiver.P2=v}
 i6.prototype.sP2.$reflectable=1
-function Vc(){}Vc.builtin$cls="Vc"
-if(!"name" in Vc)Vc.name="Vc"
-$desc=$collectedClasses.Vc
+function WZ(){}WZ.builtin$cls="WZ"
+if(!"name" in WZ)WZ.name="WZ"
+$desc=$collectedClasses.WZ
 if($desc instanceof Array)$desc=$desc[1]
-Vc.prototype=$desc
+WZ.prototype=$desc
 function zO(){}zO.builtin$cls="zO"
 if(!"name" in zO)zO.name="zO"
 $desc=$collectedClasses.zO
@@ -46768,11 +46884,11 @@
 Fv.prototype.gFT.$reflectable=1
 Fv.prototype.sFT=function(receiver,v){return receiver.FT=v}
 Fv.prototype.sFT.$reflectable=1
-function WZ(){}WZ.builtin$cls="WZ"
-if(!"name" in WZ)WZ.name="WZ"
-$desc=$collectedClasses.WZ
+function pv(){}pv.builtin$cls="pv"
+if(!"name" in pv)pv.name="pv"
+$desc=$collectedClasses.pv
 if($desc instanceof Array)$desc=$desc[1]
-WZ.prototype=$desc
+pv.prototype=$desc
 function I3(Py,hO,VJ,Ai,tH,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM){this.Py=Py
 this.hO=hO
 this.VJ=VJ
@@ -46802,11 +46918,11 @@
 I3.prototype.ghO.$reflectable=1
 I3.prototype.shO=function(receiver,v){return receiver.hO=v}
 I3.prototype.shO.$reflectable=1
-function pv(){}pv.builtin$cls="pv"
-if(!"name" in pv)pv.name="pv"
-$desc=$collectedClasses.pv
+function Vfx(){}Vfx.builtin$cls="Vfx"
+if(!"name" in Vfx)Vfx.name="Vfx"
+$desc=$collectedClasses.Vfx
 if($desc instanceof Array)$desc=$desc[1]
-pv.prototype=$desc
+Vfx.prototype=$desc
 function qr(Lf,VJ,Ai,tH,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM){this.Lf=Lf
 this.VJ=VJ
 this.Ai=Ai
@@ -46831,11 +46947,11 @@
 qr.prototype.gLf.$reflectable=1
 qr.prototype.sLf=function(receiver,v){return receiver.Lf=v}
 qr.prototype.sLf.$reflectable=1
-function Vfx(){}Vfx.builtin$cls="Vfx"
-if(!"name" in Vfx)Vfx.name="Vfx"
-$desc=$collectedClasses.Vfx
+function Dsd(){}Dsd.builtin$cls="Dsd"
+if(!"name" in Dsd)Dsd.name="Dsd"
+$desc=$collectedClasses.Dsd
 if($desc instanceof Array)$desc=$desc[1]
-Vfx.prototype=$desc
+Dsd.prototype=$desc
 function Gk(vt,VJ,Ai,tH,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM){this.vt=vt
 this.VJ=VJ
 this.Ai=Ai
@@ -46860,11 +46976,11 @@
 Gk.prototype.gvt.$reflectable=1
 Gk.prototype.svt=function(receiver,v){return receiver.vt=v}
 Gk.prototype.svt.$reflectable=1
-function Dsd(){}Dsd.builtin$cls="Dsd"
-if(!"name" in Dsd)Dsd.name="Dsd"
-$desc=$collectedClasses.Dsd
+function tuj(){}tuj.builtin$cls="tuj"
+if(!"name" in tuj)tuj.name="tuj"
+$desc=$collectedClasses.tuj
 if($desc instanceof Array)$desc=$desc[1]
-Dsd.prototype=$desc
+tuj.prototype=$desc
 function Ds(ql,VJ,Ai,tH,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM){this.ql=ql
 this.VJ=VJ
 this.Ai=Ai
@@ -46889,11 +47005,11 @@
 Ds.prototype.gql.$reflectable=1
 Ds.prototype.sql=function(receiver,v){return receiver.ql=v}
 Ds.prototype.sql.$reflectable=1
-function tuj(){}tuj.builtin$cls="tuj"
-if(!"name" in tuj)tuj.name="tuj"
-$desc=$collectedClasses.tuj
+function Vct(){}Vct.builtin$cls="Vct"
+if(!"name" in Vct)Vct.name="Vct"
+$desc=$collectedClasses.Vct
 if($desc instanceof Array)$desc=$desc[1]
-tuj.prototype=$desc
+Vct.prototype=$desc
 function aI(b,c){this.b=b
 this.c=c}aI.builtin$cls="aI"
 if(!"name" in aI)aI.name="aI"
@@ -46986,11 +47102,11 @@
 pR.prototype.giK.$reflectable=1
 pR.prototype.siK=function(receiver,v){return receiver.iK=v}
 pR.prototype.siK.$reflectable=1
-function Vct(){}Vct.builtin$cls="Vct"
-if(!"name" in Vct)Vct.name="Vct"
-$desc=$collectedClasses.Vct
+function D13(){}D13.builtin$cls="D13"
+if(!"name" in D13)D13.name="D13"
+$desc=$collectedClasses.D13
 if($desc instanceof Array)$desc=$desc[1]
-Vct.prototype=$desc
+D13.prototype=$desc
 function hx(Xh,VJ,Ai,tH,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM){this.Xh=Xh
 this.VJ=VJ
 this.Ai=Ai
@@ -47015,11 +47131,11 @@
 hx.prototype.gXh.$reflectable=1
 hx.prototype.sXh=function(receiver,v){return receiver.Xh=v}
 hx.prototype.sXh.$reflectable=1
-function D13(){}D13.builtin$cls="D13"
-if(!"name" in D13)D13.name="D13"
-$desc=$collectedClasses.D13
+function WZq(){}WZq.builtin$cls="WZq"
+if(!"name" in WZq)WZq.name="WZq"
+$desc=$collectedClasses.WZq
 if($desc instanceof Array)$desc=$desc[1]
-D13.prototype=$desc
+WZq.prototype=$desc
 function u7(tH,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM){this.tH=tH
 this.VJ=VJ
 this.Ai=Ai
@@ -47066,11 +47182,11 @@
 St.prototype.gi0.$reflectable=1
 St.prototype.si0=function(receiver,v){return receiver.i0=v}
 St.prototype.si0.$reflectable=1
-function WZq(){}WZq.builtin$cls="WZq"
-if(!"name" in WZq)WZq.name="WZq"
-$desc=$collectedClasses.WZq
+function pva(){}pva.builtin$cls="pva"
+if(!"name" in pva)pva.name="pva"
+$desc=$collectedClasses.pva
 if($desc instanceof Array)$desc=$desc[1]
-WZq.prototype=$desc
+pva.prototype=$desc
 function vj(eb,kf,VJ,Ai,tH,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM){this.eb=eb
 this.kf=kf
 this.VJ=VJ
@@ -47100,11 +47216,11 @@
 vj.prototype.gkf.$reflectable=1
 vj.prototype.skf=function(receiver,v){return receiver.kf=v}
 vj.prototype.skf.$reflectable=1
-function pva(){}pva.builtin$cls="pva"
-if(!"name" in pva)pva.name="pva"
-$desc=$collectedClasses.pva
+function cda(){}cda.builtin$cls="cda"
+if(!"name" in cda)cda.name="cda"
+$desc=$collectedClasses.cda
 if($desc instanceof Array)$desc=$desc[1]
-pva.prototype=$desc
+cda.prototype=$desc
 function CX(iI,VJ,Ai,tH,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM){this.iI=iI
 this.VJ=VJ
 this.Ai=Ai
@@ -47129,11 +47245,11 @@
 CX.prototype.giI.$reflectable=1
 CX.prototype.siI=function(receiver,v){return receiver.iI=v}
 CX.prototype.siI.$reflectable=1
-function cda(){}cda.builtin$cls="cda"
-if(!"name" in cda)cda.name="cda"
-$desc=$collectedClasses.cda
+function waa(){}waa.builtin$cls="waa"
+if(!"name" in waa)waa.name="waa"
+$desc=$collectedClasses.waa
 if($desc instanceof Array)$desc=$desc[1]
-cda.prototype=$desc
+waa.prototype=$desc
 function TJ(oc,eT,yz,Cj,wd,Gs){this.oc=oc
 this.eT=eT
 this.yz=yz
@@ -47421,11 +47537,11 @@
 F1.prototype.gk5.$reflectable=1
 F1.prototype.sk5=function(receiver,v){return receiver.k5=v}
 F1.prototype.sk5.$reflectable=1
-function waa(){}waa.builtin$cls="waa"
-if(!"name" in waa)waa.name="waa"
-$desc=$collectedClasses.waa
+function V0(){}V0.builtin$cls="V0"
+if(!"name" in V0)V0.name="V0"
+$desc=$collectedClasses.V0
 if($desc instanceof Array)$desc=$desc[1]
-waa.prototype=$desc
+V0.prototype=$desc
 function uL(tH,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM){this.tH=tH
 this.VJ=VJ
 this.Ai=Ai
@@ -48035,13 +48151,13 @@
 $desc=$collectedClasses.e9
 if($desc instanceof Array)$desc=$desc[1]
 e9.prototype=$desc
-function Dw(wc,nn,lv,Pp){this.wc=wc
+function PD(wc,nn,lv,Pp){this.wc=wc
 this.nn=nn
 this.lv=lv
-this.Pp=Pp}Dw.builtin$cls="Dw"
-$desc=$collectedClasses.Dw
+this.Pp=Pp}PD.builtin$cls="PD"
+$desc=$collectedClasses.PD
 if($desc instanceof Array)$desc=$desc[1]
-Dw.prototype=$desc
+PD.prototype=$desc
 function Xy(a,b,c){this.a=a
 this.b=b
 this.c=c}Xy.builtin$cls="Xy"
@@ -48576,11 +48692,11 @@
 fI.prototype.gUz.$reflectable=1
 fI.prototype.sUz=function(receiver,v){return receiver.Uz=v}
 fI.prototype.sUz.$reflectable=1
-function V0(){}V0.builtin$cls="V0"
-if(!"name" in V0)V0.name="V0"
-$desc=$collectedClasses.V0
+function V4(){}V4.builtin$cls="V4"
+if(!"name" in V4)V4.name="V4"
+$desc=$collectedClasses.V4
 if($desc instanceof Array)$desc=$desc[1]
-V0.prototype=$desc
+V4.prototype=$desc
 function kK(vX,VJ,Ai,tH,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM){this.vX=vX
 this.VJ=VJ
 this.Ai=Ai
@@ -48605,11 +48721,11 @@
 kK.prototype.gvX.$reflectable=1
 kK.prototype.svX=function(receiver,v){return receiver.vX=v}
 kK.prototype.svX.$reflectable=1
-function V4(){}V4.builtin$cls="V4"
-if(!"name" in V4)V4.name="V4"
-$desc=$collectedClasses.V4
+function V6(){}V6.builtin$cls="V6"
+if(!"name" in V6)V6.name="V6"
+$desc=$collectedClasses.V6
 if($desc instanceof Array)$desc=$desc[1]
-V4.prototype=$desc
+V6.prototype=$desc
 function uw(V4,VJ,Ai,tH,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM){this.V4=V4
 this.VJ=VJ
 this.Ai=Ai
@@ -48634,11 +48750,11 @@
 uw.prototype.gV4.$reflectable=1
 uw.prototype.sV4=function(receiver,v){return receiver.V4=v}
 uw.prototype.sV4.$reflectable=1
-function V6(){}V6.builtin$cls="V6"
-if(!"name" in V6)V6.name="V6"
-$desc=$collectedClasses.V6
+function V8(){}V8.builtin$cls="V8"
+if(!"name" in V8)V8.name="V8"
+$desc=$collectedClasses.V8
 if($desc instanceof Array)$desc=$desc[1]
-V6.prototype=$desc
+V8.prototype=$desc
 function V2(N1,bn,Ck){this.N1=N1
 this.bn=bn
 this.Ck=Ck}V2.builtin$cls="V2"
@@ -48976,4 +49092,4 @@
 $desc=$collectedClasses.PW
 if($desc instanceof Array)$desc=$desc[1]
 PW.prototype=$desc
-return[qE,Yy,Ps,rK,fY,Mr,zx,ct,nB,i3,it,Az,QP,QW,n6,Ny,OM,QQ,MA,y4,d7,na,oJ,DG,mN,vH,hh,Em,Sb,rV,Wy,YN,bA,Wq,rv,BK,wj,cv,Fs,SX,ea,D0,as,T5,Aa,u5,Yu,iG,jP,U2,tA,xn,Vb,QH,ST,X2,fJ,Vi,tX,Sg,pA,Mi,Gt,In,Gx,eP,AL,Og,cS,M6,El,zm,SV,aB,ku,KM,cW,DK,qm,ZY,cx,la,Vn,PG,xe,Hw,bn,Im,oB,Aj,oU,qT,KV,BH,mh,G7,wq,Ql,Xp,bP,mX,SN,HD,ni,p3,qj,qW,KR,ew,fs,bX,BL,MC,Mx,j2,yz,lp,pD,I0,QR,Cp,ua,zD,Ul,G0,wb,fq,h4,qk,GI,Tb,tV,BT,yY,kJ,AE,xV,FH,y6,RH,pU,Lq,Mf,BR,r4,aG,J6,K5,UM,UL,rq,nK,kc,ij,ty,Nf,Nc,rj,rh,Zv,Q7,hF,OF,HB,ZJ,mU,eZ,Fl,y5,nV,Zc,ui,D6,DQ,Sm,dx,es,eG,lv,pf,NV,W1,zo,wf,TU,bb,VE,lc,Xu,qM,tk,me,qN,nh,d4,MI,ca,xX,eW,um,Fu,OE,l6,BA,zp,rE,CC,PQ,uz,Yd,U0,AD,Gr,tc,GH,lo,NJ,nd,vt,rQ,EU,LR,MB,hy,r8,aS,CG,qF,MT,Rk,Eo,Dn,UD,ZD,NE,wD,BD,vRT,Fi,Qr,mj,cB,uY,yR,AX,xJ,l4,Et,NC,nb,By,xt,tG,P0,Jq,Xr,qD,Cf,I2,AS,Kq,oI,mJ,rF,vi,ZX,ycx,nE,zt,F0,Lt,Gv,kn,PE,QI,FP,is,Q,jx,ZC,Jt,P,im,Pp,O,PK,JO,O2,aX,cC,RA,IY,JH,jl,Iy,JM,Ua,JG,ns,wd,TA,YP,yc,I9,Bj,NO,II,aJ,X1,HU,Pm,oo,OW,Dd,AP,yH,FA,Av,oH,LP,c2,WT,p8,XR,LI,A2,F3,u8,Gi,t2,Zr,ZQ,az,vV,Hk,XO,dr,TL,KX,uZ,OQ,Tp,v,Z3,D2,GT,Pe,Eq,cu,Lm,dC,wN,VX,VR,EK,KW,Pb,tQ,aC,Vf,Be,tu,i6,Vc,zO,aL,nH,a7,i1,xy,MH,A8,U5,SO,zs,rR,AM,d5,U1,SJ,SU,Tv,XC,iK,GD,Sn,nI,jU,Lj,mb,am,cw,EE,Uz,uh,Kv,oP,YX,BI,y1,M2,iu,mg,zE,bl,Ef,Oo,Tc,Ax,Wf,Un,Ei,U7,t0,Ld,Sz,Zk,fu,ng,Ar,jB,ye,Gj,Zz,Xh,Ca,Ik,JI,Ip,WV,C7,CQ,dz,tK,OR,Bg,DL,b8,j7,oV,TP,Zf,vs,da,xw,dm,rH,ZL,mi,jb,wB,Pu,qh,QC,Yl,Rv,YJ,jv,LB,DO,lz,Rl,Jb,M4,Jp,h7,pr,eN,B5,PI,j4,i9,VV,Dy,lU,xp,UH,Z5,ii,ib,MO,ms,UO,Bc,vp,lk,Gh,XB,ly,cK,O9,yU,nP,KA,Vo,qB,ez,lx,LV,DS,dp,B3,CR,ny,dR,uR,QX,YR,fB,bq,nO,t3,dq,dX,aY,wJ,e4,JB,Id,fZ,TF,Xz,Cg,Hs,uo,pK,eM,Ue,W5,R8,k6,oi,ce,o2,jG,fG,EQ,YB,iX,ou,S9,ey,xd,v6,db,Cm,N6,jg,YO,oz,b6,ef,zQ,Yp,u3,mW,ar,lD,W0,Sw,o0,a1,jp,Xt,Ba,An,LD,YI,OG,ro,DN,ZM,HW,JC,f1,Uk,wI,ob,Ud,K8,by,dI,QM,Sh,tF,z0,Vx,Rw,GY,jZ,h0,CL,uA,a2,fR,iP,MF,Rq,Hn,Zl,pl,a6,P7,DW,Ge,LK,AT,bJ,mp,ub,ds,lj,UV,VS,t7,HG,aE,kM,EH,cX,eL,L8,c8,a,Od,mE,WU,Rn,wv,uq,iD,hb,XX,Kd,yZ,Gs,pm,Tw,wm,FB,Lk,XZ,qz,hQ,Nw,kZ,JT,d9,rI,dD,QZ,BV,E1,wz,B1,M5,Jn,DM,zL,ec,Kx,iO,bU,e7,nj,rl,RAp,ma,cf,E9,nF,FK,Si,vf,Fc,hD,I4,e0,RO,eu,ie,Ea,pu,i2,b0,Ov,qO,RX,kG,Gm,W9,vZ,dW,PA,H2,O7,HI,E4,r7,Tz,Wk,DV,Hp,Nz,Jd,QS,QF,NL,vr,D4,L9u,Ms,Fw,RS,RY,Ys,vg,xG,Vj,VW,RK,DH,ZK,Th,Vju,KB,RKu,xGn,TkQ,VWk,ZKG,DHb,w6W,Hna,z9g,G8,UZ,Fv,WZ,I3,pv,qr,Vfx,Gk,Dsd,Ds,tuj,aI,rG,yh,wO,Tm,rz,CA,YL,KC,xL,As,GE,pR,Vct,hx,D13,u7,St,WZq,vj,pva,CX,cda,TJ,dG,Ng,HV,Nh,fA,tz,jR,PO,c5,ih,mL,bv,pt,Zd,dY,vY,dS,ZW,dZ,Qe,Nu,pF,Ha,nu,be,Pg,jI,Rb,Zw,Pf,F1,waa,uL,Nr,Pi,yj,qI,J3,E5,o5,b5,zI,Zb,id,iV,W4,Fa,x9,d3,X6,xh,wn,uF,cj,HA,br,zT,D7,qL,C4,l9,lP,km,Qt,Dk,A0,rm,eY,OO,BE,Qb,xI,q1,Zj,XP,q6,CK,BO,ZG,Oc,MX,w12,fTP,yL,dM,Y7,WC,Xi,TV,Mq,Oa,n1,xf,L6,Rs,uJ,hm,Ji,Bf,ir,Sa,GN,k8,HJ,S0,V3,Bl,pM,Mh,Md,Lf,fT,pp,Nq,nl,mf,ej,HK,w13,o8,GL,e9,Dw,Xy,uK,mY,fE,mB,XF,iH,wJY,zOQ,W6o,MdQ,YJG,DOe,lPa,Ufa,Raa,w0,w4,w5,w7,w9,w10,w11,c4,z6,Ay,Ed,G1,Os,Dl,Wh,x5,ev,ID,jV,ek,OC,Xm,Jy,ky,fa,WW,vQ,a9,jh,e3,VA,J1,fk,wL,B0,Fq,hw,EZ,no,kB,ae,Iq,w6,jK,uk,K9,RW,xs,FX,Ae,Bt,vR,Pn,hc,hA,fr,a0,NQ,fI,V0,kK,V4,uw,V6,V2,D8,jY,ll,Uf,ik,LfS,NP,Vh,r0,jz,SA,zV,nv,ee,XI,hs,yp,ug,DT,OB,Ra,N9,NW,HS,TG,ts,Kj,VU,Ya,XT,ic,VT,T4,TR,VD,Oh,zy,Nb,Fy,eU,ADW,Ri,kq,Ag,PW]}
\ No newline at end of file
+return[qE,Yy,Ps,rK,fY,Mr,zx,ct,nB,i3,it,Az,QP,QW,n6,Ny,OM,QQ,MA,y4,d7,na,oJ,DG,mN,vH,hh,Em,Sb,rV,Wy,YN,bA,Wq,rv,BK,wj,cv,Fs,SX,ea,D0,as,T5,Aa,u5,Yu,iG,jP,U2,tA,xn,Vb,QH,ST,X2,fJ,Vi,tX,Sg,pA,Mi,Gt,In,Gx,eP,AL,Og,cS,M6,El,zm,SV,aB,ku,KM,cW,DK,qm,ZY,cx,la,Vn,PG,xe,Hw,bn,Im,oB,Aj,oU,qT,KV,BH,mh,G7,wq,Ql,Xp,bP,mX,SN,HD,ni,p3,qj,qW,KR,ew,fs,bX,BL,MC,Mx,j2,yz,lp,pD,I0,QR,Cp,ua,zD,Ul,G0,wb,fq,h4,qk,GI,Tb,tV,BT,yY,kJ,AE,xV,FH,y6,RH,pU,Lq,Mf,BR,r4,aG,J6,K5,UM,UL,rq,nK,kc,ij,ty,Nf,Nc,rj,rh,Zv,Q7,hF,OF,HB,ZJ,mU,eZ,Fl,y5,nV,Zc,ui,D6,DQ,Sm,dx,es,eG,lv,pf,NV,W1,zo,wf,TU,bb,VE,lc,Xu,qM,tk,me,qN,nh,d4,MI,ca,xX,eW,um,Fu,OE,l6,BA,zp,rE,CC,PQ,uz,Yd,U0,AD,Gr,tc,GH,lo,NJ,nd,vt,rQ,EU,LR,MB,hy,r8,aS,CG,qF,MT,Rk,Eo,Dn,UD,ZD,NE,wD,BD,vRT,Fi,Qr,mj,cB,uY,yR,AX,xJ,l4,Et,NC,nb,By,xt,tG,P0,Jq,Xr,qD,Cf,I2,AS,Kq,oI,mJ,rF,vi,ZX,ycx,nE,zt,F0,Lt,Gv,kn,PE,QI,FP,is,Q,jx,ZC,Jt,P,im,Pp,O,PK,JO,O2,aX,cC,RA,IY,JH,jl,Iy,JM,Ua,JG,ns,wd,TA,YP,yc,I9,Bj,NO,II,aJ,X1,HU,Pm,oo,OW,Dd,AP,yH,FA,Av,oH,LP,c2,WT,p8,XR,LI,A2,F3,u8,Gi,t2,Zr,ZQ,az,vV,Hk,XO,dr,TL,KX,uZ,OQ,Tp,v,Z3,D2,GT,Pe,Eq,cu,Lm,dC,wN,VX,VR,EK,KW,Pb,tQ,G6,Vf,aC,tu,Be,Vc,i6,WZ,zO,aL,nH,a7,i1,xy,MH,A8,U5,SO,zs,rR,AM,d5,U1,SJ,SU,Tv,XC,iK,GD,Sn,nI,jU,Lj,mb,am,cw,EE,Uz,uh,Kv,oP,YX,BI,y1,M2,iu,mg,zE,bl,Ef,Oo,Tc,Ax,Wf,Un,Ei,U7,t0,Ld,Sz,Zk,fu,ng,Ar,jB,ye,Gj,Zz,Xh,Ca,Ik,JI,Ip,WV,C7,CQ,dz,tK,OR,Bg,DL,b8,j7,oV,TP,Zf,vs,da,xw,dm,rH,ZL,mi,jb,wB,Pu,qh,QC,Yl,Rv,YJ,jv,LB,DO,lz,Rl,Jb,M4,Jp,h7,pr,eN,B5,PI,j4,i9,VV,Dy,lU,xp,UH,Z5,ii,ib,MO,ms,UO,Bc,vp,lk,Gh,XB,ly,cK,O9,yU,nP,KA,Vo,qB,ez,lx,LV,DS,dp,B3,CR,ny,dR,uR,QX,YR,fB,bq,nO,t3,dq,dX,aY,wJ,e4,JB,Id,fZ,TF,Xz,Cg,Hs,uo,pK,eM,Ue,W5,R8,k6,oi,ce,o2,jG,fG,EQ,YB,iX,ou,S9,ey,xd,v6,db,Cm,N6,jg,YO,oz,b6,ef,zQ,Yp,u3,mW,ar,lD,W0,Sw,o0,a1,jp,Xt,Ba,An,LD,YI,OG,ro,DN,ZM,HW,JC,f1,Uk,wI,ob,Ud,K8,by,dI,QM,Sh,tF,z0,Vx,Rw,GY,jZ,h0,CL,uA,a2,fR,iP,MF,Rq,Hn,Zl,pl,a6,P7,DW,Ge,LK,AT,bJ,mp,ub,ds,lj,UV,VS,t7,HG,aE,kM,EH,cX,eL,L8,c8,a,Od,mE,WU,Rn,wv,uq,iD,hb,XX,Kd,yZ,Gs,pm,Tw,wm,FB,Lk,XZ,qz,hQ,Nw,kZ,JT,d9,rI,dD,QZ,BV,E1,wz,B1,M5,Jn,DM,zL,ec,Kx,iO,bU,e7,nj,rl,RAp,ma,cf,E9,nF,FK,Si,vf,Fc,hD,I4,e0,RO,eu,ie,Ea,pu,i2,b0,Ov,qO,RX,kG,Gm,W9,vZ,dW,PA,H2,O7,HI,E4,r7,Tz,Wk,DV,Hp,Nz,Jd,QS,QF,NL,vr,D4,L9u,Ms,Fw,RS,RY,Ys,vg,xG,Vj,VW,RK,DH,ZK,Th,Vju,KB,RKu,xGn,TkQ,VWk,ZKG,DHb,w6W,Hna,z9g,G8,UZ,Fv,pv,I3,Vfx,qr,Dsd,Gk,tuj,Ds,Vct,aI,rG,yh,wO,Tm,rz,CA,YL,KC,xL,As,GE,pR,D13,hx,WZq,u7,St,pva,vj,cda,CX,waa,TJ,dG,Ng,HV,Nh,fA,tz,jR,PO,c5,ih,mL,bv,pt,Zd,dY,vY,dS,ZW,dZ,Qe,Nu,pF,Ha,nu,be,Pg,jI,Rb,Zw,Pf,F1,V0,uL,Nr,Pi,yj,qI,J3,E5,o5,b5,zI,Zb,id,iV,W4,Fa,x9,d3,X6,xh,wn,uF,cj,HA,br,zT,D7,qL,C4,l9,lP,km,Qt,Dk,A0,rm,eY,OO,BE,Qb,xI,q1,Zj,XP,q6,CK,BO,ZG,Oc,MX,w12,fTP,yL,dM,Y7,WC,Xi,TV,Mq,Oa,n1,xf,L6,Rs,uJ,hm,Ji,Bf,ir,Sa,GN,k8,HJ,S0,V3,Bl,pM,Mh,Md,Lf,fT,pp,Nq,nl,mf,ej,HK,w13,o8,GL,e9,PD,Xy,uK,mY,fE,mB,XF,iH,wJY,zOQ,W6o,MdQ,YJG,DOe,lPa,Ufa,Raa,w0,w4,w5,w7,w9,w10,w11,c4,z6,Ay,Ed,G1,Os,Dl,Wh,x5,ev,ID,jV,ek,OC,Xm,Jy,ky,fa,WW,vQ,a9,jh,e3,VA,J1,fk,wL,B0,Fq,hw,EZ,no,kB,ae,Iq,w6,jK,uk,K9,RW,xs,FX,Ae,Bt,vR,Pn,hc,hA,fr,a0,NQ,fI,V4,kK,V6,uw,V8,V2,D8,jY,ll,Uf,ik,LfS,NP,Vh,r0,jz,SA,zV,nv,ee,XI,hs,yp,ug,DT,OB,Ra,N9,NW,HS,TG,ts,Kj,VU,Ya,XT,ic,VT,T4,TR,VD,Oh,zy,Nb,Fy,eU,ADW,Ri,kq,Ag,PW]}
\ No newline at end of file
diff --git a/runtime/bin/vmservice/client/lib/observatory_elements.dart b/runtime/bin/vmservice/client/lib/observatory_elements.dart
index 0f50949..c483042 100644
--- a/runtime/bin/vmservice/client/lib/observatory_elements.dart
+++ b/runtime/bin/vmservice/client/lib/observatory_elements.dart
@@ -1,6 +1,7 @@
 library observatory_elements;
 
 // Export elements.
+export 'package:observatory/src/observatory_elements/breakpoint_list.dart';
 export 'package:observatory/src/observatory_elements/class_view.dart';
 export 'package:observatory/src/observatory_elements/code_view.dart';
 export 'package:observatory/src/observatory_elements/collapsible_content.dart';
diff --git a/runtime/bin/vmservice/client/lib/observatory_elements.html b/runtime/bin/vmservice/client/lib/observatory_elements.html
index ae96d66..0342b45 100644
--- a/runtime/bin/vmservice/client/lib/observatory_elements.html
+++ b/runtime/bin/vmservice/client/lib/observatory_elements.html
@@ -1,6 +1,7 @@
 <!DOCTYPE html>
 <html>
 <head>
+ <link rel="import" href="src/observatory_elements/breakpoint_list.html">
  <link rel="import" href="src/observatory_elements/class_view.html">
  <link rel="import" href="src/observatory_elements/code_view.html">
  <link rel="import" href="src/observatory_elements/collapsible_content.html">
diff --git a/runtime/bin/vmservice/client/lib/src/observatory_elements/breakpoint_list.dart b/runtime/bin/vmservice/client/lib/src/observatory_elements/breakpoint_list.dart
new file mode 100644
index 0000000..deab7a2
--- /dev/null
+++ b/runtime/bin/vmservice/client/lib/src/observatory_elements/breakpoint_list.dart
@@ -0,0 +1,15 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library breakpoint_list_element;
+
+import 'observatory_element.dart';
+import 'package:polymer/polymer.dart';
+
+@CustomTag('breakpoint-list')
+class BreakpointListElement extends ObservatoryElement {
+  @published Map msg = toObservable({});
+
+  BreakpointListElement.created() : super.created();
+}
\ No newline at end of file
diff --git a/runtime/bin/vmservice/client/lib/src/observatory_elements/breakpoint_list.html b/runtime/bin/vmservice/client/lib/src/observatory_elements/breakpoint_list.html
new file mode 100644
index 0000000..8496dd2
--- /dev/null
+++ b/runtime/bin/vmservice/client/lib/src/observatory_elements/breakpoint_list.html
@@ -0,0 +1,22 @@
+<head>
+  <link rel="import" href="observatory_element.html">
+</head>
+<polymer-element name="breakpoint-list" extends="observatory-element">
+  <template>
+    <template if="{{ msg['breakpoints'].isEmpty }}">
+      <div class="panel panel-warning">
+        <div class="panel-body">No breakpoints</div>
+      </div>
+    </template>
+    <template if="{{ msg['breakpoints'].isNotEmpty }}">
+      <ul class="list-group">
+      <template repeat="{{ bpt in msg['breakpoints'] }}">
+        <li class="list-group-item">
+          {{ bpt }}
+        </li>
+      </template>
+      </ul>
+    </template>
+  </template>
+  <script type="application/dart" src="breakpoint_list.dart"></script>
+</polymer-element>
\ No newline at end of file
diff --git a/runtime/bin/vmservice/client/lib/src/observatory_elements/isolate_summary.html b/runtime/bin/vmservice/client/lib/src/observatory_elements/isolate_summary.html
index 10b6a0d..dc54b34 100644
--- a/runtime/bin/vmservice/client/lib/src/observatory_elements/isolate_summary.html
+++ b/runtime/bin/vmservice/client/lib/src/observatory_elements/isolate_summary.html
@@ -18,6 +18,9 @@
       <div class="col-md-1">
         <a href="{{ app.locationManager.relativeLink(isolate, 'library') }}">Library</a>
       </div>
+      <div class="col-md-1">
+        <a href="{{ app.locationManager.relativeLink(isolate, 'debug/breakpoints') }}">Breakpoints</a>
+      </div>
   	  <div class="col-md-8"></div>
     </div>
   </template>
diff --git a/runtime/bin/vmservice/client/lib/src/observatory_elements/message_viewer.dart b/runtime/bin/vmservice/client/lib/src/observatory_elements/message_viewer.dart
index 10342aa..641d11f 100644
--- a/runtime/bin/vmservice/client/lib/src/observatory_elements/message_viewer.dart
+++ b/runtime/bin/vmservice/client/lib/src/observatory_elements/message_viewer.dart
@@ -24,6 +24,7 @@
     if (message == null || message['type'] == null) {
       return 'Error';
     }
+    print("Received message of type '${message['type']}' :\n$message");
     return message['type'];
   }
 
diff --git a/runtime/bin/vmservice/client/lib/src/observatory_elements/message_viewer.html b/runtime/bin/vmservice/client/lib/src/observatory_elements/message_viewer.html
index 3bd2aff..f66a3fa 100644
--- a/runtime/bin/vmservice/client/lib/src/observatory_elements/message_viewer.html
+++ b/runtime/bin/vmservice/client/lib/src/observatory_elements/message_viewer.html
@@ -1,4 +1,5 @@
 <head>
+  <link rel="import" href="breakpoint_list.html">
   <link rel="import" href="class_view.html">
   <link rel="import" href="code_view.html">
   <link rel="import" href="error_view.html">
@@ -26,6 +27,9 @@
     <template if="{{ messageType == 'StackTrace' }}">
       <stack-trace app="{{ app }}" trace="{{ message }}"></stack-trace>
     </template>
+    <template if="{{ messageType == 'BreakpointList' }}">
+      <breakpoint-list app="{{ app }}" msg="{{ message }}"></breakpoint-list>
+    </template>
     <!-- If the message type is a RequestError -->
     <template if="{{ messageType == 'RequestError' }}">
       <error-view app="{{ app }}" error="{{ message['error'] }}"></error-view>
diff --git a/runtime/bin/vmservice/message.dart b/runtime/bin/vmservice/message.dart
new file mode 100644
index 0000000..9dce2a1
--- /dev/null
+++ b/runtime/bin/vmservice/message.dart
@@ -0,0 +1,82 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of vmservice;
+
+class Message {
+  final Completer _completer = new Completer.sync();
+  bool get completed => _completer.isCompleted;
+  /// Future of response.
+  Future<String> get response => _completer.future;
+  /// Path.
+  final List<String> path = new List<String>();
+  /// Options.
+  final Map<String, String> options = new Map<String, String>();
+
+  void _setPath(List<String> pathSegments) {
+    if (pathSegments == null) {
+      return;
+    }
+    pathSegments.forEach((String segment) {
+      if (segment == null || segment == '') {
+        return;
+      }
+      path.add(segment);
+    });
+  }
+
+  Message.fromUri(Uri uri) {
+    var split = uri.path.split('/');
+    if (split.length == 0) {
+      setErrorResponse('Invalid uri: $uri.');
+      return;
+    }
+    _setPath(split);
+    options.addAll(uri.queryParameters);
+  }
+
+  Message.fromMap(Map map) {
+    _setPath(map['path']);
+    if (map['options'] != null) {
+      options.addAll(map['options']);
+    }
+  }
+
+  dynamic toJson() {
+    return {
+      'path': path,
+      'options': options
+    };
+  }
+
+  Future<String> send(SendPort sendPort) {
+    final receivePort = new RawReceivePort();
+    receivePort.handler = (value) {
+      receivePort.close();
+      if (value is Exception) {
+        _completer.completeError(value);
+      } else {
+        _completer.complete(value);
+      }
+    };
+    var keys = options.keys.toList();
+    var values = options.values.toList();
+    var request = [receivePort.sendPort, path, keys, values];
+    sendServiceMessage(sendPort, request);
+    return _completer.future;
+  }
+
+  void setResponse(String response) {
+    _completer.complete(response);
+  }
+
+  void setErrorResponse(String error) {
+    _completer.complete(JSON.encode({
+        'type': 'Error',
+        'msg': error,
+        'path': path,
+        'options': options
+    }));
+  }
+}
diff --git a/runtime/bin/vmservice/service_request_router.dart b/runtime/bin/vmservice/message_router.dart
similarity index 75%
rename from runtime/bin/vmservice/service_request_router.dart
rename to runtime/bin/vmservice/message_router.dart
index c889c85..6f8a1ea 100644
--- a/runtime/bin/vmservice/service_request_router.dart
+++ b/runtime/bin/vmservice/message_router.dart
@@ -4,6 +4,6 @@
 
 part of vmservice;
 
-abstract class ServiceRequestRouter {
-  Future route(ServiceRequest request);
+abstract class MessageRouter {
+  Future<String> route(Message message);
 }
diff --git a/runtime/bin/vmservice/running_isolate.dart b/runtime/bin/vmservice/running_isolate.dart
index cf726c8..3dd4839 100644
--- a/runtime/bin/vmservice/running_isolate.dart
+++ b/runtime/bin/vmservice/running_isolate.dart
@@ -4,34 +4,15 @@
 
 part of vmservice;
 
-class RunningIsolate implements ServiceRequestRouter {
+class RunningIsolate implements MessageRouter {
   final int portId;
   final SendPort sendPort;
   final String name;
 
   RunningIsolate(this.portId, this.sendPort, this.name);
 
-  Future sendMessage(List request) {
-    final completer = new Completer.sync();
-    final receivePort = new RawReceivePort();
-    sendServiceMessage(sendPort, receivePort, request);
-    receivePort.handler = (value) {
-      receivePort.close();
-      if (value is Exception) {
-        completer.completeError(value);
-      } else {
-        completer.complete(value);
-      }
-    };
-    return completer.future;
-  }
-
-  Future route(ServiceRequest request) {
+  Future<String> route(Message message) {
     // Send message to isolate.
-    var message = request.toServiceCallMessage();
-    return sendMessage(message).then((response) {
-      request.setResponse(response);
-      return new Future.value(request);
-    });
+    return message.send(sendPort);
   }
 }
diff --git a/runtime/bin/vmservice/running_isolates.dart b/runtime/bin/vmservice/running_isolates.dart
index 547b9b5..36a0c484 100644
--- a/runtime/bin/vmservice/running_isolates.dart
+++ b/runtime/bin/vmservice/running_isolates.dart
@@ -4,7 +4,7 @@
 
 part of vmservice;
 
-class RunningIsolates implements ServiceRequestRouter {
+class RunningIsolates implements MessageRouter {
   final Map<int, RunningIsolate> isolates = new Map<int, RunningIsolate>();
 
   RunningIsolates();
@@ -24,7 +24,7 @@
     isolates.remove(portId);
   }
 
-  void _isolateCollectionRequest(ServiceRequest request) {
+  void _isolateCollectionRequest(Message message) {
     var members = [];
     var result = {};
     isolates.forEach((portId, runningIsolate) {
@@ -35,42 +35,42 @@
     });
     result['type'] = 'IsolateList';
     result['members'] = members;
-    request.setResponse(JSON.encode(result));
+    message.setResponse(JSON.encode(result));
   }
 
-  Future route(ServiceRequest request) {
-    if (request.pathSegments.length == 0) {
-      request.setErrorResponse('No path.');
-      return new Future.value(request);
+  Future<String> route(Message message) {
+    if (message.path.length == 0) {
+      message.setErrorResponse('No path.');
+      return message.response;
     }
-    if (request.pathSegments[0] != 'isolates') {
-      request.setErrorResponse('Path must begin with /isolates/.');
-      return new Future.value(request);
+    if (message.path[0] != 'isolates') {
+      message.setErrorResponse('Path must begin with /isolates/.');
+      return message.response;
     }
-    if (request.pathSegments.length == 1) {
+    if (message.path.length == 1) {
       // Requesting list of running isolates.
-      _isolateCollectionRequest(request);
-      return new Future.value(request);
+      _isolateCollectionRequest(message);
+      return message.response;
     }
     var isolateId;
     try {
-      isolateId = int.parse(request.pathSegments[1]);
+      isolateId = int.parse(message.path[1]);
     } catch (e) {
-      request.setErrorResponse('Could not parse isolate id: $e');
-      return new Future.value(request);
+      message.setErrorResponse('Could not parse isolate id: $e');
+      return message.response;
     }
     var isolate = isolates[isolateId];
     if (isolate == null) {
-      request.setErrorResponse('Cannot find isolate id: $isolateId');
-      return new Future.value(request);
+      message.setErrorResponse('Cannot find isolate id: $isolateId');
+      return message.response;
     }
     // Consume '/isolates/isolateId'
-    request.pathSegments.removeRange(0, 2);
-    if (request.pathSegments.length == 0) {
-      // The request is now empty.
-      request.setErrorResponse('No request for isolate: /isolates/$isolateId');
-      return new Future.value(request);
+    message.path.removeRange(0, 2);
+    if (message.path.length == 0) {
+      // The message now has an empty path.
+      message.setErrorResponse('Empty path for isolate: /isolates/$isolateId');
+      return message.response;
     }
-    return isolate.route(request);
+    return isolate.route(message);
   }
 }
diff --git a/runtime/bin/vmservice/server.dart b/runtime/bin/vmservice/server.dart
index 19490a1..6467b7d 100644
--- a/runtime/bin/vmservice/server.dart
+++ b/runtime/bin/vmservice/server.dart
@@ -4,26 +4,95 @@
 
 part of vmservice_io;
 
-class Server {
-  int port;
+class WebSocketClient extends Client {
+  static const int PARSE_ERROR_CODE = 4000;
+  static const int BINARY_MESSAGE_ERROR_CODE = 4001;
+  static const int NOT_MAP_ERROR_CODE = 4002;
+  final WebSocket socket;
+
+  WebSocketClient(this.socket, service) : super(service) {
+    socket.listen((message) => onWebSocketMessage(message));
+    socket.done.then((_) => close());
+  }
+
+  void onWebSocketMessage(message) {
+    if (message is String) {
+      var map;
+      try {
+        map = JSON.decode(message);
+      } catch (e) {
+        socket.close(PARSE_ERROR_CODE, 'Message parse error: $e');
+        return;
+      }
+      if (map is! Map) {
+        socket.close(NOT_MAP_ERROR_CODE, 'Message must be a JSON map.');
+        return;
+      }
+      var seq = map['seq'];
+      onMessage(seq, new Message.fromMap(map));
+    } else {
+      socket.close(BINARY_MESSAGE_ERROR_CODE, 'message must be a string.');
+    }
+  }
+
+  void post(var seq, String response) {
+    try {
+      Map map = {
+        'seq': seq,
+        'response': response
+      };
+      socket.add(JSON.encode(map));
+    } catch (_) {
+      // Error posting over WebSocket.
+    }
+  }
+
+  dynamic toJson() {
+    Map map = super.toJson();
+    map['type'] = 'WebSocketClient';
+    map['socket'] = '$socket';
+    return map;
+  }
+}
+
+
+class HttpRequestClient extends Client {
   static ContentType jsonContentType = ContentType.parse('application/json');
-  final VmService service;
-  HttpServer _server;
+  final HttpRequest request;
 
-  Server(this.service, this.port);
+  HttpRequestClient(this.request, service) : super(service);
 
-  void _sendResponse(HttpRequest request, String response) {
+  void post(var seq, String response) {
     request.response..headers.contentType = jsonContentType
                     ..write(response)
                     ..close();
+    close();
   }
 
+  dynamic toJson() {
+    Map map = super.toJson();
+    map['type'] = 'HttpRequestClient';
+    map['request'] = '$request';
+    return map;
+  }
+}
+
+class Server {
+  static const WEBSOCKET_PATH = '/ws';
+  String defaultPath = '/index.html';
+  int port;
+
+  final VMService service;
+  HttpServer _server;
+
+  Server(this.service, this.port);
+
   void _requestHandler(HttpRequest request) {
     // Allow cross origin requests.
     request.response.headers.add('Access-Control-Allow-Origin', '*');
 
     final String path =
-          request.uri.path == '/' ? '/index.html' : request.uri.path;
+          request.uri.path == '/' ? defaultPath : request.uri.path;
 
     var resource = Resource.resources[path];
     if (resource != null) {
@@ -35,19 +104,16 @@
       return;
     }
 
-    var serviceRequest = new ServiceRequest();
-    var r = serviceRequest.parse(request.uri);
-    if (r) {
-      var f = service.runningIsolates.route(serviceRequest);
-      assert(f != null);
-      f.then((_) {
-        _sendResponse(request, serviceRequest.response);
-      }).catchError((e) {
-        // Error replying over HTTP.
+    if (path == WEBSOCKET_PATH) {
+      WebSocketTransformer.upgrade(request).then((WebSocket webSocket) {
+        new WebSocketClient(webSocket, service);
       });
       return;
     }
-    _sendResponse(request, serviceRequest.response);
+
+    var message = new Message.fromUri(request.uri);
+    var client = new HttpRequestClient(request, service);
+    client.onMessage(null, message);
   }
 
   Future startServer() {
@@ -59,7 +125,7 @@
       _server = s;
       _server.listen(_requestHandler);
       if (display_message) {
-        print('VmService listening on port $port');
+        print('VMService listening on port $port');
       }
       return s;
     });
diff --git a/runtime/bin/vmservice/service_request.dart b/runtime/bin/vmservice/service_request.dart
deleted file mode 100644
index 8d7eb52..0000000
--- a/runtime/bin/vmservice/service_request.dart
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-part of vmservice;
-
-class ServiceRequest {
-  final List<String> pathSegments = new List<String>();
-  final Map<String, String> parameters = new Map<String, String>();
-  String _response;
-  String get response => _response;
-
-  ServiceRequest();
-
-  bool parse(Uri uri) {
-    var path = uri.path;
-    var split = path.split('/');
-    if (split.length == 0) {
-      setErrorResponse('Invalid request uri: ${request.uri}');
-      return false;
-    }
-    for (int i = 0; i < split.length; i++) {
-      var pathSegment = split[i];
-      if (pathSegment == '') {
-        continue;
-      }
-      pathSegments.add(pathSegment);
-    }
-    uri.queryParameters.forEach((k, v) {
-      parameters[k] = v;
-    });
-    return true;
-  }
-
-  List toServiceCallMessage() {
-    return [pathSegments, parameters.keys.toList(), parameters.values.toList()];
-  }
-
-  void setErrorResponse(String error) {
-    _response = JSON.encode({
-        'type': 'Error',
-        'msg': error,
-        'pathSegments': pathSegments,
-        'parameters': parameters
-    });
-  }
-
-  void setResponse(String response) {
-    _response = response;
-  }
-
-}
diff --git a/runtime/bin/vmservice/vmservice.dart b/runtime/bin/vmservice/vmservice.dart
index 309399f..5532428 100644
--- a/runtime/bin/vmservice/vmservice.dart
+++ b/runtime/bin/vmservice/vmservice.dart
@@ -9,16 +9,21 @@
 import 'dart:isolate';
 import 'dart:typed_data';
 
+part 'client.dart';
 part 'constants.dart';
 part 'resources.dart';
 part 'running_isolate.dart';
 part 'running_isolates.dart';
-part 'service_request.dart';
-part 'service_request_router.dart';
+part 'message.dart';
+part 'message_router.dart';
 
-class VMService {
+class VMService extends MessageRouter {
   static VMService _instance;
+  /// Collection of currently connected clients.
+  final Set<Client> clients = new Set<Client>();
+  /// Collection of currently running isolates.
   RunningIsolates runningIsolates = new RunningIsolates();
+  /// Isolate startup and shutdown messages are sent on this port.
   final RawReceivePort receivePort;
 
   void controlMessageHandler(int code, int port_id, SendPort sp, String name) {
@@ -32,6 +37,14 @@
     }
   }
 
+  void _addClient(Client client) {
+    clients.add(client);
+  }
+
+  void _removeClient(Client client) {
+    clients.remove(client);
+  }
+
   void messageHandler(message) {
     assert(message is List);
     assert(message.length == 4);
@@ -50,7 +63,29 @@
     }
     return _instance;
   }
+
+  void _clientCollection(Message message) {
+    var members = [];
+    var result = {};
+    clients.forEach((client) {
+      members.add(client.toJson());
+    });
+    result['type'] = 'ClientList';
+    result['members'] = members;
+    message.setResponse(JSON.encode(result));
+  }
+
+  Future<String> route(Message message) {
+    if (message.completed) {
+      return message.response;
+    }
+    if ((message.path.length == 1) && (message.path[0] == 'clients')) {
+      _clientCollection(message);
+      return message.response;
+    }
+    return runningIsolates.route(message);
+  }
 }
 
-void sendServiceMessage(SendPort sp, ReceivePort rp, Object m)
+void sendServiceMessage(SendPort sp, Object m)
     native "VMService_SendServiceMessage";
diff --git a/runtime/bin/vmservice/vmservice_dartium.dart b/runtime/bin/vmservice/vmservice_dartium.dart
index 249455d..99f04fa 100644
--- a/runtime/bin/vmservice/vmservice_dartium.dart
+++ b/runtime/bin/vmservice/vmservice_dartium.dart
@@ -15,41 +15,44 @@
 // The native method that is called to post the response back to DevTools.
 void postResponse(String response, int cookie) native "VMService_PostResponse";
 
-void handleRequest(service, String uri, cookie) {
-  var serviceRequest = new ServiceRequest();
-  var r = serviceRequest.parse(Uri.parse(uri));
-  if (r) {
-    var f = service.runningIsolates.route(serviceRequest);
-    assert(f != null);
-    f.then((_) {
-      postResponse(serviceRequest.response, cookie);
-    }).catchError((e) {
-      // Error posting response back to Dartium.
+/// Dartium recieves messages through the _requestPort and posts
+/// responses via postResponse. It has a single persistent client.
+class DartiumClient extends Client {
+  DartiumClient(port, service) : super(service) {
+    port.handler = ((message) {
+      if (message == null) {
+        return;
+      }
+      if (message is! List) {
+        return;
+      }
+      if (message.length != 2) {
+        return;
+      }
+      if (message[0] is! String) {
+        return;
+      }
+      var uri = Uri.parse(message[0]);
+      var cookie = message[1];
+      onMessage(cookie, new Message.fromUri(uri));
     });
-    return;
   }
-  postResponse(serviceRequest.response, cookie);
+
+  void post(var seq, String response) {
+    postResponse(response, seq);
+  }
+
+  dynamic toJson() {
+    var map = super.toJson();
+    map['type'] = 'DartiumClient';
+  }
 }
 
+
 main() {
   // Create VmService.
   var service = new VMService();
   _receivePort = service.receivePort;
-  _requestPort = new RawReceivePort((message) {
-    if (message == null) {
-      return;
-    }
-    if (message is! List) {
-      return;
-    }
-    if (message.length != 2) {
-      return;
-    }
-    var uri = message[0];
-    if (uri is! String) {
-      return;
-    }
-    var cookie = message[1];
-    handleRequest(service, uri, cookie);
-  });
+  _requestPort = new RawReceivePort();
+  new DartiumClient(_requestPort, service);
 }
diff --git a/runtime/bin/vmservice/vmservice_io.dart b/runtime/bin/vmservice/vmservice_io.dart
index d4590ce..fd7b785 100644
--- a/runtime/bin/vmservice/vmservice_io.dart
+++ b/runtime/bin/vmservice/vmservice_io.dart
@@ -4,6 +4,7 @@
 
 library vmservice_io;
 
+import 'dart:convert';
 import 'dart:io';
 import 'vmservice.dart';
 
diff --git a/runtime/bin/vmservice_impl.cc b/runtime/bin/vmservice_impl.cc
index 74fb836..9e738cd 100644
--- a/runtime/bin/vmservice_impl.cc
+++ b/runtime/bin/vmservice_impl.cc
@@ -60,7 +60,8 @@
 
 
 static Dart_NativeFunction VmServiceNativeResolver(Dart_Handle name,
-                                                   int num_arguments);
+                                                   int num_arguments,
+                                                   bool* auto_setup_scope);
 
 
 bool VmService::Start(intptr_t server_port) {
@@ -491,8 +492,7 @@
   StackZone zone(isolate);
   HANDLESCOPE(isolate);
   GET_NON_NULL_NATIVE_ARGUMENT(Instance, sp, arguments->NativeArgAt(0));
-  GET_NON_NULL_NATIVE_ARGUMENT(Instance, rp, arguments->NativeArgAt(1));
-  GET_NON_NULL_NATIVE_ARGUMENT(Instance, message, arguments->NativeArgAt(2));
+  GET_NON_NULL_NATIVE_ARGUMENT(Instance, message, arguments->NativeArgAt(1));
 
   // Extract SendPort port id.
   const Object& sp_id_obj = Object::Handle(DartLibraryCalls::PortGetId(sp));
@@ -502,19 +502,7 @@
   Integer& id = Integer::Handle();
   id ^= sp_id_obj.raw();
   Dart_Port sp_id = static_cast<Dart_Port>(id.AsInt64Value());
-
-  // Extract ReceivePort port id.
-  const Object& rp_id_obj = Object::Handle(DartLibraryCalls::PortGetId(rp));
-  if (rp_id_obj.IsError()) {
-    Exceptions::PropagateError(Error::Cast(rp_id_obj));
-  }
-  ASSERT(rp_id_obj.IsSmi() || rp_id_obj.IsMint());
-  id ^= rp_id_obj.raw();
-  Dart_Port rp_id = static_cast<Dart_Port>(id.AsInt64Value());
-
-  // Both are valid ports.
   ASSERT(sp_id != ILLEGAL_PORT);
-  ASSERT(rp_id != ILLEGAL_PORT);
 
   // Serialize message.
   uint8_t* data = NULL;
@@ -522,7 +510,7 @@
   writer.WriteMessage(message);
 
   // TODO(turnidge): Throw an exception when the return value is false?
-  PortMap::PostMessage(new Message(sp_id, rp_id, data, writer.BytesWritten(),
+  PortMap::PostMessage(new Message(sp_id, data, writer.BytesWritten(),
                                    Message::kOOBPriority));
 }
 
@@ -535,18 +523,21 @@
 
 
 static VmServiceNativeEntry _VmServiceNativeEntries[] = {
-  {"VMService_SendServiceMessage", 3, SendServiceMessage}
+  {"VMService_SendServiceMessage", 2, SendServiceMessage}
 };
 
 
 static Dart_NativeFunction VmServiceNativeResolver(Dart_Handle name,
-                                                   int num_arguments) {
+                                                   int num_arguments,
+                                                   bool* auto_setup_scope) {
   const Object& obj = Object::Handle(Api::UnwrapHandle(name));
   if (!obj.IsString()) {
     return NULL;
   }
   const char* function_name = obj.ToCString();
   ASSERT(function_name != NULL);
+  ASSERT(auto_setup_scope != NULL);
+  *auto_setup_scope = true;
   intptr_t n =
       sizeof(_VmServiceNativeEntries) / sizeof(_VmServiceNativeEntries[0]);
   for (intptr_t i = 0; i < n; i++) {
diff --git a/runtime/include/dart_api.h b/runtime/include/dart_api.h
index feb3819..8698bd6 100755
--- a/runtime/include/dart_api.h
+++ b/runtime/include/dart_api.h
@@ -983,6 +983,18 @@
 DART_EXPORT Dart_Handle Dart_HandleMessage();
 
 /**
+ * Handles any pending messages for the vm service for the current
+ * isolate.
+ *
+ * This function may be used by an embedder at a breakpoint to avoid
+ * pausing the vm service.
+ *
+ * \return true if the vm service requests the program resume
+ * execution, false otherwise
+ */
+DART_EXPORT bool Dart_HandleServiceMessages();
+
+/**
  * Processes any incoming messages for the current isolate.
  *
  * This function may only be used when the embedder has not provided
@@ -2110,7 +2122,8 @@
  * See Dart_SetNativeResolver.
  */
 typedef Dart_NativeFunction (*Dart_NativeEntryResolver)(Dart_Handle name,
-                                                        int num_of_arguments);
+                                                        int num_of_arguments,
+                                                        bool* auto_setup_scope);
 /* TODO(turnidge): Consider renaming to NativeFunctionResolver or
  * NativeResolver. */
 
diff --git a/runtime/include/dart_debugger_api.h b/runtime/include/dart_debugger_api.h
index c2c5aaa..5f3f234 100755
--- a/runtime/include/dart_debugger_api.h
+++ b/runtime/include/dart_debugger_api.h
@@ -679,25 +679,33 @@
 
 
 /**
-* Returns the url of the library \library_id.
-*
-* Requires there to be a current isolate.
-*
-* \return A string handle containing the URL of the library.
-*/
+ * Returns the url of the library \library_id.
+ *
+ * Requires there to be a current isolate.
+ *
+ * \return A string handle containing the URL of the library.
+ */
 DART_EXPORT Dart_Handle Dart_GetLibraryURL(intptr_t library_id);
 
 
 /**
-* Returns the isolate object corresponding to the isolate id.
-*
-* \return The Dart_Isolate object corresponding to the isolate id.
-* If the specified id is invalid NULL is returned.
-*/
+ * Returns the isolate object corresponding to the isolate id.
+ *
+ * \return The Dart_Isolate object corresponding to the isolate id.
+ * If the specified id is invalid NULL is returned.
+ */
 DART_EXPORT Dart_Isolate Dart_GetIsolate(Dart_IsolateId isolate_id);
 
 
 /**
+ * Returns the isolate id for an isolate.
+ *
+ * \return The Dart_IsolateId value corresponding to the isolate.
+ */
+DART_EXPORT Dart_IsolateId Dart_GetIsolateId(Dart_Isolate isolate);
+
+
+/**
  * Returns VM status information. VM status is implemented using a
  * different status plug-in for each type of status; for example, there
  * might be an "isolate" plug-in that returns information about the
diff --git a/runtime/lib/array.dart b/runtime/lib/array.dart
index a0fb5f9..2369b4c 100644
--- a/runtime/lib/array.dart
+++ b/runtime/lib/array.dart
@@ -78,7 +78,7 @@
       _copyFromObjectArray(iterable, skipCount, start, length);
     } else {
       if (iterable is List) {
-        Arrays.copy(iterable, skipCount, this, start, length);
+        Lists.copy(iterable, skipCount, this, start, length);
       } else {
         Iterator it = iterable.iterator;
         while (skipCount > 0) {
@@ -108,13 +108,13 @@
   }
 
   List<E> sublist(int start, [int end]) {
-    Arrays.indicesCheck(this, start, end);
+    Lists.indicesCheck(this, start, end);
     if (end == null) end = this.length;
     int length = end - start;
     if (start == end) return [];
     List list = new _GrowableList<E>.withCapacity(length);
     list.length = length;
-    Arrays.copy(this, start, list, 0, length);
+    Lists.copy(this, start, list, 0, length);
     return list;
   }
 
@@ -209,12 +209,12 @@
   }
 
   int indexOf(Object element, [int start = 0]) {
-    return Arrays.indexOf(this, element, start, this.length);
+    return Lists.indexOf(this, element, start, this.length);
   }
 
   int lastIndexOf(Object element, [int start = null]) {
     if (start == null) start = length - 1;
-    return Arrays.lastIndexOf(this, element, start);
+    return Lists.lastIndexOf(this, element, start);
   }
 
   Iterator<E> get iterator {
@@ -361,13 +361,13 @@
   }
 
   List<E> sublist(int start, [int end]) {
-    Arrays.indicesCheck(this, start, end);
+    Lists.indicesCheck(this, start, end);
     if (end == null) end = this.length;
     int length = end - start;
     if (start == end) return [];
     List list = new List<E>();
     list.length = length;
-    Arrays.copy(this, start, list, 0, length);
+    Lists.copy(this, start, list, 0, length);
     return list;
   }
 
@@ -472,12 +472,12 @@
   }
 
   int indexOf(Object element, [int start = 0]) {
-    return Arrays.indexOf(this, element, start, this.length);
+    return Lists.indexOf(this, element, start, this.length);
   }
 
   int lastIndexOf(Object element, [int start = null]) {
     if (start == null) start = length - 1;
-    return Arrays.lastIndexOf(this, element, start);
+    return Lists.lastIndexOf(this, element, start);
   }
 
   Iterator<E> get iterator {
diff --git a/runtime/lib/corelib_sources.gypi b/runtime/lib/corelib_sources.gypi
index dde6721..1b94b04 100644
--- a/runtime/lib/corelib_sources.gypi
+++ b/runtime/lib/corelib_sources.gypi
@@ -32,7 +32,6 @@
     'integers.cc',
     'integers.dart',
     'integers_patch.dart',
-    'invocation_mirror.cc',
     'invocation_mirror.h',
     'invocation_mirror_patch.dart',
     'map_patch.dart',
diff --git a/runtime/lib/double.dart b/runtime/lib/double.dart
index c5b2c38..8efe789 100644
--- a/runtime/lib/double.dart
+++ b/runtime/lib/double.dart
@@ -104,6 +104,12 @@
     return this < 0.0 ? -this : this;
   }
 
+  double get sign {
+    if (this > 0.0) return 1.0;
+    if (this < 0.0) return -1.0;
+    return this;  // +/-0.0 or NaN.
+  }
+
   int round() => roundToDouble().toInt();
   int floor() => floorToDouble().toInt();
   int ceil () => ceilToDouble().toInt();
diff --git a/runtime/lib/growable_array.dart b/runtime/lib/growable_array.dart
index c3e6204..e9c1082 100644
--- a/runtime/lib/growable_array.dart
+++ b/runtime/lib/growable_array.dart
@@ -19,7 +19,7 @@
     // (with a length that has been increased, but without a new element).
     if (index is! int) throw new ArgumentError(index);
     this.length++;
-    Arrays.copy(this,
+    Lists.copy(this,
                 index,
                 this,
                 index + 1,
@@ -31,7 +31,7 @@
     if (index is! int) throw new ArgumentError(index);
     T result = this[index];
     int newLength = this.length - 1;
-    Arrays.copy(this,
+    Lists.copy(this,
                 index + 1,
                 this,
                 index,
@@ -95,8 +95,8 @@
   }
 
   void removeRange(int start, int end) {
-    Arrays.indicesCheck(this, start, end);
-    Arrays.copy(this,
+    Lists.indicesCheck(this, start, end);
+    Lists.copy(this,
                 end,
                 this,
                 start,
@@ -113,13 +113,13 @@
   }
 
   List<T> sublist(int start, [int end]) {
-    Arrays.indicesCheck(this, start, end);
+    Lists.indicesCheck(this, start, end);
     if (end == null) end = this.length;
     int length = end - start;
     if (start == end) return <T>[];
     List list = new _GrowableList<T>.withCapacity(length);
     list.length = length;
-    Arrays.copy(this, start, list, 0, length);
+    Lists.copy(this, start, list, 0, length);
     return list;
   }
 
diff --git a/runtime/lib/integers.dart b/runtime/lib/integers.dart
index 7f7fc90..9c503c4 100644
--- a/runtime/lib/integers.dart
+++ b/runtime/lib/integers.dart
@@ -92,6 +92,9 @@
   int abs() {
     return this < 0 ? -this : this;
   }
+  int get sign {
+    return (this > 0) ? 1 : (this < 0) ? -1 : 0;
+  }
   bool get isEven => ((this & 1) == 0);
   bool get isOdd => !isEven;
   bool get isNaN => false;
diff --git a/runtime/lib/invocation_mirror.cc b/runtime/lib/invocation_mirror.cc
deleted file mode 100644
index 913dcf4..0000000
--- a/runtime/lib/invocation_mirror.cc
+++ /dev/null
@@ -1,56 +0,0 @@
-// 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
-// BSD-style license that can be found in the LICENSE file.
-
-#include "vm/bootstrap_natives.h"
-
-#include "vm/compiler.h"
-#include "vm/dart_entry.h"
-#include "vm/exceptions.h"
-#include "vm/native_entry.h"
-#include "vm/object_store.h"
-#include "vm/resolver.h"
-#include "vm/symbols.h"
-
-namespace dart {
-
-DEFINE_NATIVE_ENTRY(InvocationMirror_invoke, 4) {
-  const Instance& receiver = Instance::CheckedHandle(arguments->NativeArgAt(0));
-  const String& fun_name = String::CheckedHandle(arguments->NativeArgAt(1));
-  const Array& fun_args_desc = Array::CheckedHandle(arguments->NativeArgAt(2));
-  const Array& fun_arguments = Array::CheckedHandle(arguments->NativeArgAt(3));
-
-  // Allocate a fixed-length array duplicating the original function arguments
-  // and replace the receiver.
-  const int num_arguments = fun_arguments.Length();
-  const Array& invoke_arguments = Array::Handle(Array::New(num_arguments));
-  invoke_arguments.SetAt(0, receiver);
-  Object& arg = Object::Handle();
-  for (int i = 1; i < num_arguments; i++) {
-    arg = fun_arguments.At(i);
-    invoke_arguments.SetAt(i, arg);
-  }
-  // Resolve dynamic function given by name.
-  const ArgumentsDescriptor args_desc(fun_args_desc);
-  const Function& function = Function::Handle(
-      Resolver::ResolveDynamic(receiver,
-                               fun_name,
-                               args_desc));
-  Object& result = Object::Handle();
-  if (function.IsNull()) {
-    result = DartEntry::InvokeNoSuchMethod(receiver,
-                                           fun_name,
-                                           invoke_arguments,
-                                           fun_args_desc);
-  } else {
-    result = DartEntry::InvokeFunction(function,
-                                       invoke_arguments,
-                                       fun_args_desc);
-  }
-  if (result.IsError()) {
-    Exceptions::PropagateError(Error::Cast(result));
-  }
-  return result.raw();
-}
-
-}  // namespace dart
diff --git a/runtime/lib/invocation_mirror_patch.dart b/runtime/lib/invocation_mirror_patch.dart
index 4c2e7e5..3f76e4e 100644
--- a/runtime/lib/invocation_mirror_patch.dart
+++ b/runtime/lib/invocation_mirror_patch.dart
@@ -133,18 +133,4 @@
                                  arguments,
                                  isSuperInvocation);
   }
-
-  static _invoke(Object receiver,
-                 String functionName,
-                 List argumentsDescriptor,
-                 List arguments)
-      native "InvocationMirror_invoke";
-
-  _invokeOn(Object receiver) {
-    return _invoke(receiver, _functionName, _argumentsDescriptor, _arguments);
-  }
-
-  // TODO(ahe): This is a hack.  See _LocalInstanceMirrorImpl.delegate
-  // in mirrors_impl.dart
-  static final _invokeOnClosure = (x, y) => y._invokeOn(x);
 }
diff --git a/runtime/lib/isolate.cc b/runtime/lib/isolate.cc
index 0f7da54..4e78b26 100644
--- a/runtime/lib/isolate.cc
+++ b/runtime/lib/isolate.cc
@@ -105,7 +105,7 @@
   writer.WriteMessage(obj);
 
   // TODO(turnidge): Throw an exception when the return value is false?
-  PortMap::PostMessage(new Message(send_id.Value(), Message::kIllegalPort,
+  PortMap::PostMessage(new Message(send_id.Value(),
                                    data, writer.BytesWritten(),
                                    Message::kNormalPriority));
   return Object::null();
diff --git a/runtime/lib/isolate_patch.dart b/runtime/lib/isolate_patch.dart
index 3792a5b..80e830b 100644
--- a/runtime/lib/isolate_patch.dart
+++ b/runtime/lib/isolate_patch.dart
@@ -107,8 +107,7 @@
   }
 
   // Called from the VM to dispatch to the handler.
-  static void _handleMessage(
-      _RawReceivePortImpl port, int replyId, var message) {
+  static void _handleMessage(_RawReceivePortImpl port, var message) {
     assert(port != null);
     // TODO(floitsch): this relies on the fact that any exception aborts the
     // VM. Once we have non-fatal global exceptions we need to catch errors
@@ -229,40 +228,39 @@
 patch class Isolate {
   /* patch */ static Future<Isolate> spawn(
       void entryPoint(message), var message) {
-    Completer completer = new Completer<Isolate>.sync();
     try {
       // The VM will invoke [_startIsolate] with entryPoint as argument.
       SendPort controlPort = _spawnFunction(entryPoint);
       RawReceivePort readyPort = new RawReceivePort();
       controlPort.send([readyPort.sendPort, message]);
+      Completer completer = new Completer<Isolate>.sync();
       readyPort.handler = (readyMessage) {
         assert(readyMessage == 'started');
         readyPort.close();
         completer.complete(new Isolate._fromControlPort(controlPort));
       };
-    } catch(e, st) {
-      // TODO(14718): we want errors to go into the returned future.
-      rethrow;
+      return completer.future;
+    } catch (e, st) {
+      return new Future<Isolate>.error(e, st);
     };
-    return completer.future;
   }
 
   /* patch */ static Future<Isolate> spawnUri(
       Uri uri, List<String> args, var message) {
-    Completer completer = new Completer<Isolate>.sync();
     try {
       // The VM will invoke [_startIsolate] and not `main`.
       SendPort controlPort = _spawnUri(uri.toString());
       RawReceivePort readyPort = new RawReceivePort();
       controlPort.send([readyPort.sendPort, args, message]);
+      Completer completer = new Completer<Isolate>.sync();
       readyPort.handler = (readyMessage) {
         assert(readyMessage == 'started');
         readyPort.close();
         completer.complete(new Isolate._fromControlPort(controlPort));
       };
-    } catch(e, st) {
-      // TODO(14718): we want errors to go into the returned future.
-      rethrow;
+      return completer.future;
+    } catch (e, st) {
+      return new Future<Isolate>.error(e, st);
     };
     return completer.future;
   }
diff --git a/runtime/lib/mirrors.cc b/runtime/lib/mirrors.cc
index 59d95bc..3d228cd 100644
--- a/runtime/lib/mirrors.cc
+++ b/runtime/lib/mirrors.cc
@@ -97,22 +97,6 @@
 }
 
 
-DEFINE_NATIVE_ENTRY(Mirrors_isLocalPort, 1) {
-  GET_NON_NULL_NATIVE_ARGUMENT(Instance, port, arguments->NativeArgAt(0));
-
-  // Get the port id from the SendPort instance.
-  const Object& id_obj = Object::Handle(DartLibraryCalls::PortGetId(port));
-  if (id_obj.IsError()) {
-    Exceptions::PropagateError(Error::Cast(id_obj));
-    UNREACHABLE();
-  }
-  ASSERT(id_obj.IsSmi() || id_obj.IsMint());
-  Integer& id = Integer::Handle();
-  id ^= id_obj.raw();
-  Dart_Port port_id = static_cast<Dart_Port>(id.AsInt64Value());
-  return Bool::Get(PortMap::IsLocalPort(port_id)).raw();
-}
-
 static void EnsureConstructorsAreCompiled(const Function& func) {
   // Only generative constructors can have initializing formals.
   if (!func.IsConstructor()) return;
@@ -1712,6 +1696,16 @@
     UNREACHABLE();
   }
 
+  if (klass.is_abstract() && !lookup_constructor.IsFactory()) {
+    const Array& error_args = Array::Handle(Array::New(3));
+    error_args.SetAt(0, klass_name);
+    // 1 = script url
+    // 2 = token position
+    Exceptions::ThrowByType(Exceptions::kAbstractClassInstantiation,
+                            error_args);
+    UNREACHABLE();
+  }
+
   ASSERT(!type.IsNull());
   AbstractTypeArguments& type_arguments =
       AbstractTypeArguments::Handle(type.arguments());
diff --git a/runtime/lib/mirrors_impl.dart b/runtime/lib/mirrors_impl.dart
index e057fd2..5f0983a 100644
--- a/runtime/lib/mirrors_impl.dart
+++ b/runtime/lib/mirrors_impl.dart
@@ -262,8 +262,6 @@
 
 class _LocalInstanceMirror extends _LocalObjectMirror
     implements InstanceMirror {
-  // TODO(ahe): This is a hack, see delegate below.
-  static Function _invokeOnClosure;
 
   _LocalInstanceMirror(reflectee) : super(reflectee);
 
@@ -283,17 +281,22 @@
   get reflectee => _reflectee;
 
   delegate(Invocation invocation) {
-    if (_invokeOnClosure == null) {
-      // TODO(ahe): This is a total hack.  We're using the mirror
-      // system to access a private field in a different library.  For
-      // some reason, that works.  On the other hand, calling a
-      // private method does not work.
-      ClassMirror invocationImplClass = reflect(invocation).type;
-      Symbol fieldName = MirrorSystem.getSymbol('_invokeOnClosure',
-                                                invocationImplClass.owner);
-      _invokeOnClosure = invocationImplClass.getField(fieldName).reflectee;
+    if (invocation.isMethod) {
+      return this.invoke(invocation.memberName,
+                         invocation.positionalArguments,
+                         invocation.namedArguments).reflectee;
     }
-    return _invokeOnClosure(reflectee, invocation);
+    if (invocation.isGetter) {
+      return this.getField(invocation.memberName).reflectee;
+    }
+    if (invocation.isSetter) {
+      var unwrapped = _n(invocation.memberName);
+      var withoutEqual = _s(unwrapped.substring(0, unwrapped.length - 1));
+      var arg = invocation.positionalArguments[0];
+      this.setField(withoutEqual, arg).reflectee;
+      return arg;
+    }
+    throw "UNREACHABLE";
   }
 
   String toString() => 'InstanceMirror on ${Error.safeToString(_reflectee)}';
@@ -1072,11 +1075,34 @@
         new _UnmodifiableMapView<Symbol, DeclarationMirror>(_members);
   }
 
+
+  var _cachedTopLevelMembers;
   Map<Symbol, MethodMirror> get topLevelMembers {
-    throw new UnimplementedError(
-        'LibraryMirror.topLevelMembers is not implemented');
+    if (_cachedTopLevelMembers != null) return _cachedTopLevelMembers;
+    var result = new Map<Symbol, MethodMirror>();
+    declarations.values.forEach((decl) {
+      if (decl is MethodMirror && !decl.isAbstract) {
+        result[decl.simpleName] = decl;
+      }
+      if (decl is VariableMirror) {
+        var getterName = decl.simpleName;
+        result[getterName] =
+            new _SyntheticAccessor(this, getterName, true, true, true, decl);
+        if (!decl.isFinal) {
+          var setterName = _asSetter(decl.simpleName, this);
+          result[setterName] = new _SyntheticAccessor(
+              this, setterName, false, true, true, decl);
+        }
+      }
+      // if (decl is TypeMirror) {
+      //  var getterName = decl.simpleName;
+      //  result[getterName] = new _SyntheticTypeGetter(this, getterName, decl);
+      // }
+    });
+    return _cachedTopLevelMembers = result;
   }
 
+
   Map<Symbol, Mirror> _cachedMembers;
   Map<Symbol, Mirror> get _members {
     if (_cachedMembers == null) {
@@ -1414,9 +1440,6 @@
 }
 
 class _Mirrors {
-  // Does a port refer to our local isolate?
-  static bool isLocalPort(SendPort port) native 'Mirrors_isLocalPort';
-
   static MirrorSystem _currentMirrorSystem = null;
 
   // Creates a new local MirrorSystem.
diff --git a/runtime/lib/object.cc b/runtime/lib/object.cc
index 3774913..e040d9f 100644
--- a/runtime/lib/object.cc
+++ b/runtime/lib/object.cc
@@ -105,10 +105,7 @@
   const Instance& instance = Instance::CheckedHandle(arguments->NativeArgAt(0));
   // Special handling for following types outside this native.
   ASSERT(!instance.IsString() && !instance.IsInteger() && !instance.IsDouble());
-  const Type& type = Type::Handle(instance.GetType());
-  // The static type of null is specified to be the bottom type, however, the
-  // runtime type of null is the Null type, which we correctly return here.
-  return type.Canonicalize();
+  return instance.GetType();
 }
 
 
diff --git a/runtime/lib/print_patch.dart b/runtime/lib/print_patch.dart
index 186b4fb..539294a 100644
--- a/runtime/lib/print_patch.dart
+++ b/runtime/lib/print_patch.dart
@@ -2,13 +2,15 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-typedef void _PrintClosure(Object obj);
+// A print-closure gets a String that should be printed. In general the
+// string is a line, but it may contain "\n" characters.
+typedef void _PrintClosure(String line);
 
 patch void printToConsole(String line) {
   _printClosure(line);
 }
 
-void _unsupportedPrint(Object obj) {
+void _unsupportedPrint(String line) {
   throw new UnsupportedError("'print' is not supported");
 }
 
diff --git a/runtime/platform/thread.h b/runtime/platform/thread.h
index 02ad51e..fb56a50 100644
--- a/runtime/platform/thread.h
+++ b/runtime/platform/thread.h
@@ -25,6 +25,7 @@
 class Thread {
  public:
   static ThreadLocalKey kUnsetThreadLocalKey;
+  static ThreadId kInvalidThreadId;
 
   typedef void (*ThreadStartFunction) (uword parameter);
 
@@ -41,6 +42,8 @@
   static void SetThreadLocal(ThreadLocalKey key, uword value);
   static intptr_t GetMaxStackSize();
   static ThreadId GetCurrentThreadId();
+  static intptr_t ThreadIdToIntPtr(ThreadId id);
+  static bool Compare(ThreadId a, ThreadId b);
   static void GetThreadCpuUsage(ThreadId thread_id, int64_t* cpu_usage);
 };
 
@@ -91,58 +94,6 @@
 };
 
 
-class ScopedMutex {
- public:
-  explicit ScopedMutex(Mutex* mutex) : mutex_(mutex) {
-    ASSERT(mutex_ != NULL);
-    mutex_->Lock();
-  }
-
-  ~ScopedMutex() {
-    mutex_->Unlock();
-  }
-
- private:
-  Mutex* const mutex_;
-
-  DISALLOW_COPY_AND_ASSIGN(ScopedMutex);
-};
-
-
-class ScopedMonitor {
- public:
-  explicit ScopedMonitor(Monitor* monitor) : monitor_(monitor) {
-    ASSERT(monitor_ != NULL);
-    monitor_->Enter();
-  }
-
-  ~ScopedMonitor() {
-    monitor_->Exit();
-  }
-
-  Monitor::WaitResult Wait(int64_t millis = dart::Monitor::kNoTimeout) {
-    return monitor_->Wait(millis);
-  }
-
-  Monitor::WaitResult WaitMicros(int64_t micros = dart::Monitor::kNoTimeout) {
-    return monitor_->WaitMicros(micros);
-  }
-
-  void Notify() {
-    monitor_->Notify();
-  }
-
-  void NotifyAll() {
-    monitor_->NotifyAll();
-  }
-
- private:
-  Monitor* const monitor_;
-
-  DISALLOW_COPY_AND_ASSIGN(ScopedMonitor);
-};
-
-
 }  // namespace dart
 
 
diff --git a/runtime/platform/thread_android.cc b/runtime/platform/thread_android.cc
index f29ffdb..ae68de6 100644
--- a/runtime/platform/thread_android.cc
+++ b/runtime/platform/thread_android.cc
@@ -113,7 +113,7 @@
 
 
 ThreadLocalKey Thread::kUnsetThreadLocalKey = static_cast<pthread_key_t>(-1);
-
+ThreadId Thread::kInvalidThreadId = static_cast<ThreadId>(0);
 
 ThreadLocalKey Thread::CreateThreadLocal() {
   pthread_key_t key = kUnsetThreadLocalKey;
@@ -149,6 +149,17 @@
 }
 
 
+intptr_t Thread::ThreadIdToIntPtr(ThreadId id) {
+  ASSERT(sizeof(id) == sizeof(intptr_t));
+  return static_cast<intptr_t>(id);
+}
+
+
+bool Thread::Compare(ThreadId a, ThreadId b) {
+  return pthread_equal(a, b) != 0;
+}
+
+
 void Thread::GetThreadCpuUsage(ThreadId thread_id, int64_t* cpu_usage) {
   ASSERT(thread_id == GetCurrentThreadId());
   ASSERT(cpu_usage != NULL);
diff --git a/runtime/platform/thread_linux.cc b/runtime/platform/thread_linux.cc
index 36bcfe4..12ea1f9 100644
--- a/runtime/platform/thread_linux.cc
+++ b/runtime/platform/thread_linux.cc
@@ -114,7 +114,7 @@
 
 
 ThreadLocalKey Thread::kUnsetThreadLocalKey = static_cast<pthread_key_t>(-1);
-
+ThreadId Thread::kInvalidThreadId = static_cast<ThreadId>(0);
 
 ThreadLocalKey Thread::CreateThreadLocal() {
   pthread_key_t key = kUnsetThreadLocalKey;
@@ -150,6 +150,17 @@
 }
 
 
+intptr_t Thread::ThreadIdToIntPtr(ThreadId id) {
+  ASSERT(sizeof(id) == sizeof(intptr_t));
+  return static_cast<intptr_t>(id);
+}
+
+
+bool Thread::Compare(ThreadId a, ThreadId b) {
+  return pthread_equal(a, b) != 0;
+}
+
+
 void Thread::GetThreadCpuUsage(ThreadId thread_id, int64_t* cpu_usage) {
   ASSERT(thread_id == GetCurrentThreadId());
   ASSERT(cpu_usage != NULL);
diff --git a/runtime/platform/thread_macos.cc b/runtime/platform/thread_macos.cc
index c4167d4..01c5c8c 100644
--- a/runtime/platform/thread_macos.cc
+++ b/runtime/platform/thread_macos.cc
@@ -106,7 +106,7 @@
 
 
 ThreadLocalKey Thread::kUnsetThreadLocalKey = static_cast<pthread_key_t>(-1);
-
+ThreadId Thread::kInvalidThreadId = reinterpret_cast<ThreadId>(NULL);
 
 ThreadLocalKey Thread::CreateThreadLocal() {
   pthread_key_t key = kUnsetThreadLocalKey;
@@ -142,6 +142,17 @@
 }
 
 
+intptr_t Thread::ThreadIdToIntPtr(ThreadId id) {
+  ASSERT(sizeof(id) == sizeof(intptr_t));
+  return reinterpret_cast<intptr_t>(id);
+}
+
+
+bool Thread::Compare(ThreadId a, ThreadId b) {
+  return pthread_equal(a, b) != 0;
+}
+
+
 void Thread::GetThreadCpuUsage(ThreadId thread_id, int64_t* cpu_usage) {
   ASSERT(thread_id == GetCurrentThreadId());
   ASSERT(cpu_usage != NULL);
diff --git a/runtime/platform/thread_win.cc b/runtime/platform/thread_win.cc
index f4494ae..afbae8b 100644
--- a/runtime/platform/thread_win.cc
+++ b/runtime/platform/thread_win.cc
@@ -99,7 +99,8 @@
 ThreadLocalKey ThreadInlineImpl::thread_id_key = Thread::kUnsetThreadLocalKey;
 
 ThreadLocalKey Thread::kUnsetThreadLocalKey = TLS_OUT_OF_INDEXES;
-
+ThreadId Thread::kInvalidThreadId =
+    reinterpret_cast<ThreadId>(INVALID_HANDLE_VALUE);
 
 ThreadLocalKey Thread::CreateThreadLocal() {
   ThreadLocalKey key = TlsAlloc();
@@ -133,6 +134,17 @@
 }
 
 
+intptr_t Thread::ThreadIdToIntPtr(ThreadId id) {
+  ASSERT(sizeof(id) == sizeof(intptr_t));
+  return reinterpret_cast<intptr_t>(id);
+}
+
+
+bool Thread::Compare(ThreadId a, ThreadId b) {
+  return a == b;
+}
+
+
 void Thread::GetThreadCpuUsage(ThreadId thread_id, int64_t* cpu_usage) {
   static const int64_t kTimeEpoc = 116444736000000000LL;
   static const int64_t kTimeScaler = 10;  // 100 ns to us.
diff --git a/runtime/tests/vm/vm.status b/runtime/tests/vm/vm.status
index 07c7ffc..669168b 100644
--- a/runtime/tests/vm/vm.status
+++ b/runtime/tests/vm/vm.status
@@ -23,6 +23,19 @@
 [ $system == windows ]
 cc/Dart2JSCompileAll: Skip
 cc/ExternalizeConstantStrings: Skip
+cc/ThreadInterrupterHigh: Skip
+cc/ThreadInterrupterMedium: Skip
+cc/ThreadInterrupterLow: Skip
+
+[ $system == macos ]
+cc/ThreadInterrupterHigh: Skip
+cc/ThreadInterrupterMedium: Skip
+cc/ThreadInterrupterLow: Skip
+
+[ $arch == simarm || $arch == simmips ]
+cc/ThreadInterrupterHigh: Skip
+cc/ThreadInterrupterMedium: Skip
+cc/ThreadInterrupterLow: Skip
 
 [ $compiler == dart2js ]
 dart/mirrored_compilation_error_test: Skip # VM-specific flag
diff --git a/runtime/vm/atomic.h b/runtime/vm/atomic.h
new file mode 100644
index 0000000..64defc0
--- /dev/null
+++ b/runtime/vm/atomic.h
@@ -0,0 +1,22 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#ifndef VM_ATOMIC_H_
+#define VM_ATOMIC_H_
+
+#include "vm/allocation.h"
+
+namespace dart {
+
+class AtomicOperations : public AllStatic {
+ public:
+  // Atomically fetch the value at p and increment the value at p.
+  // Returns the original value at p.
+  static uintptr_t FetchAndIncrement(uintptr_t* p);
+};
+
+
+}  // namespace dart
+
+#endif  // VM_ATOMIC_H_
diff --git a/runtime/vm/atomic_android.cc b/runtime/vm/atomic_android.cc
new file mode 100644
index 0000000..d11a59d
--- /dev/null
+++ b/runtime/vm/atomic_android.cc
@@ -0,0 +1,20 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#include "platform/globals.h"
+#if defined(TARGET_OS_ANDROID)
+
+#include "vm/atomic.h"
+
+namespace dart {
+
+
+uintptr_t AtomicOperations::FetchAndIncrement(uintptr_t* p) {
+  return __sync_fetch_and_add(p, 1);
+}
+
+
+}  // namespace dart
+
+#endif  // defined(TARGET_OS_ANDROID)
diff --git a/runtime/vm/atomic_linux.cc b/runtime/vm/atomic_linux.cc
new file mode 100644
index 0000000..f5888b0
--- /dev/null
+++ b/runtime/vm/atomic_linux.cc
@@ -0,0 +1,21 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#include "platform/globals.h"
+#if defined(TARGET_OS_LINUX)
+
+#include "vm/atomic.h"
+
+namespace dart {
+
+
+uintptr_t AtomicOperations::FetchAndIncrement(uintptr_t* p) {
+  return __sync_fetch_and_add(p, 1);
+}
+
+
+}  // namespace dart
+
+
+#endif  // defined(TARGET_OS_LINUX)
diff --git a/runtime/vm/atomic_macos.cc b/runtime/vm/atomic_macos.cc
new file mode 100644
index 0000000..213ccf4
--- /dev/null
+++ b/runtime/vm/atomic_macos.cc
@@ -0,0 +1,20 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#include "platform/globals.h"
+#if defined(TARGET_OS_MACOS)
+
+#include "vm/atomic.h"
+
+namespace dart {
+
+
+uintptr_t AtomicOperations::FetchAndIncrement(uintptr_t* p) {
+  return __sync_fetch_and_add(p, 1);
+}
+
+
+}  // namespace dart
+
+#endif  // defined(TARGET_OS_MACOS)
diff --git a/runtime/vm/atomic_win.cc b/runtime/vm/atomic_win.cc
new file mode 100644
index 0000000..78a3fd6
--- /dev/null
+++ b/runtime/vm/atomic_win.cc
@@ -0,0 +1,28 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#include "platform/globals.h"
+#if defined(TARGET_OS_WINDOWS)
+
+#include "vm/atomic.h"
+
+namespace dart {
+
+
+uintptr_t AtomicOperations::FetchAndIncrement(uintptr_t* p) {
+#if defined(TARGET_ARCH_X64)
+  return static_cast<uintptr_t>(
+      InterlockedIncrement64(reinterpret_cast<LONGLONG*>(p))) - 1;
+#elif defined(TARGET_ARCH_IA32)
+  return static_cast<uintptr_t>(
+      InterlockedIncrement(reinterpret_cast<LONG*>(p))) - 1;
+#else
+  UNIMPLEMENTED();
+#endif
+}
+
+
+}  // namespace dart
+
+#endif  // defined(TARGET_OS_WINDOWS)
diff --git a/runtime/vm/benchmark_test.cc b/runtime/vm/benchmark_test.cc
index ff4e164..2a07e64 100644
--- a/runtime/vm/benchmark_test.cc
+++ b/runtime/vm/benchmark_test.cc
@@ -134,7 +134,11 @@
 }
 
 
-static Dart_NativeFunction bm_uda_lookup(Dart_Handle name, int argument_count) {
+static Dart_NativeFunction bm_uda_lookup(Dart_Handle name,
+                                         int argument_count,
+                                         bool* auto_setup_scope) {
+  ASSERT(auto_setup_scope != NULL);
+  *auto_setup_scope = false;
   const char* cstr = NULL;
   Dart_Handle result = Dart_StringToCString(name, &cstr);
   EXPECT_VALID(result);
@@ -265,7 +269,10 @@
 
 
 static Dart_NativeFunction NativeResolver(Dart_Handle name,
-                                          int arg_count) {
+                                          int arg_count,
+                                          bool* auto_setup_scope) {
+  ASSERT(auto_setup_scope != NULL);
+  *auto_setup_scope = false;
   return &func;
 }
 
@@ -335,7 +342,10 @@
 
 
 static Dart_NativeFunction StackFrameNativeResolver(Dart_Handle name,
-                                                    int arg_count) {
+                                                    int arg_count,
+                                                    bool* auto_setup_scope) {
+  ASSERT(auto_setup_scope != NULL);
+  *auto_setup_scope = false;
   return &StackFrame_accessFrame;
 }
 
diff --git a/runtime/vm/bootstrap_natives.cc b/runtime/vm/bootstrap_natives.cc
index a072563..a278799 100644
--- a/runtime/vm/bootstrap_natives.cc
+++ b/runtime/vm/bootstrap_natives.cc
@@ -31,11 +31,14 @@
 
 
 Dart_NativeFunction BootstrapNatives::Lookup(Dart_Handle name,
-                                             int argument_count) {
+                                             int argument_count,
+                                             bool* auto_setup_scope) {
   const Object& obj = Object::Handle(Api::UnwrapHandle(name));
   if (!obj.IsString()) {
     return NULL;
   }
+  ASSERT(auto_setup_scope);
+  *auto_setup_scope = false;
   const char* function_name = obj.ToCString();
   ASSERT(function_name != NULL);
   int num_entries = sizeof(BootStrapEntries) / sizeof(struct NativeEntries);
diff --git a/runtime/vm/bootstrap_natives.h b/runtime/vm/bootstrap_natives.h
index 02729d4..5747777 100644
--- a/runtime/vm/bootstrap_natives.h
+++ b/runtime/vm/bootstrap_natives.h
@@ -25,7 +25,6 @@
   V(Function_apply, 2)                                                         \
   V(FunctionImpl_equals, 2)                                                    \
   V(FunctionImpl_hashCode, 1)                                                  \
-  V(InvocationMirror_invoke, 4)                                                \
   V(AbstractType_toString, 1)                                                  \
   V(Identical_comparison, 2)                                                   \
   V(Integer_bitAndFromInteger, 2)                                              \
@@ -259,7 +258,6 @@
   V(Isolate_mainPort, 0)                                                       \
   V(Isolate_spawnFunction, 1)                                                  \
   V(Isolate_spawnUri, 1)                                                       \
-  V(Mirrors_isLocalPort, 1)                                                    \
   V(Mirrors_makeLocalClassMirror, 1)                                           \
   V(Mirrors_makeLocalTypeMirror, 1)                                            \
   V(Mirrors_makeLocalMirrorSystem, 0)                                          \
@@ -320,7 +318,9 @@
 
 class BootstrapNatives : public AllStatic {
  public:
-  static Dart_NativeFunction Lookup(Dart_Handle name, int argument_count);
+  static Dart_NativeFunction Lookup(Dart_Handle name,
+                                    int argument_count,
+                                    bool* auto_setup_scope);
 
 #define DECLARE_BOOTSTRAP_NATIVE(name, ignored)                                \
   static void DN_##name(Dart_NativeArguments args);
diff --git a/runtime/vm/code_descriptors_test.cc b/runtime/vm/code_descriptors_test.cc
index 11536a9..5b2ccb0 100644
--- a/runtime/vm/code_descriptors_test.cc
+++ b/runtime/vm/code_descriptors_test.cc
@@ -194,7 +194,10 @@
 
 
 static Dart_NativeFunction native_resolver(Dart_Handle name,
-                                           int argument_count) {
+                                           int argument_count,
+                                           bool* auto_setup_scope) {
+  ASSERT(auto_setup_scope);
+  *auto_setup_scope = false;
   return reinterpret_cast<Dart_NativeFunction>(&NativeFunc);
 }
 
diff --git a/runtime/vm/code_generator.cc b/runtime/vm/code_generator.cc
index 44ddb3e..d838eff 100644
--- a/runtime/vm/code_generator.cc
+++ b/runtime/vm/code_generator.cc
@@ -1276,7 +1276,7 @@
       return false;
     }
   }
-  if (!function.is_optimizable()) {
+  if (!function.IsOptimizable()) {
     if (FLAG_trace_failed_optimization_attempts) {
       OS::PrintErr("Not Optimizable: %s\n", function.ToFullyQualifiedCString());
     }
diff --git a/runtime/vm/compiler.cc b/runtime/vm/compiler.cc
index 90f22b4..288dc59 100644
--- a/runtime/vm/compiler.cc
+++ b/runtime/vm/compiler.cc
@@ -263,7 +263,7 @@
                                         bool optimized,
                                         intptr_t osr_id) {
   const Function& function = parsed_function->function();
-  if (optimized && !function.is_optimizable()) {
+  if (optimized && !function.IsOptimizable()) {
     return false;
   }
   TimerScope timer(FLAG_compiler_stats, &CompilerStats::codegen_timer);
@@ -786,7 +786,7 @@
       } else if (FLAG_trace_failed_optimization_attempts) {
         OS::Print("Cannot optimize: %s\n", function.ToFullyQualifiedCString());
       }
-      function.set_is_optimizable(false);
+      function.SetIsOptimizable(false);
       isolate->set_long_jump_base(base);
       return Error::null();
     }
@@ -939,7 +939,7 @@
     func.set_num_fixed_parameters(0);
     func.SetNumOptionalParameters(0, true);
     // Manually generated AST, do not recompile.
-    func.set_is_optimizable(false);
+    func.SetIsOptimizable(false);
 
     // We compile the function here, even though InvokeStatic() below
     // would compile func automatically. We are checking fewer invariants
diff --git a/runtime/vm/custom_isolate_test.cc b/runtime/vm/custom_isolate_test.cc
index 7d43473..9394e57 100644
--- a/runtime/vm/custom_isolate_test.cc
+++ b/runtime/vm/custom_isolate_test.cc
@@ -18,7 +18,9 @@
 
 static void native_echo(Dart_NativeArguments args);
 static void CustomIsolateImpl_start(Dart_NativeArguments args);
-static Dart_NativeFunction NativeLookup(Dart_Handle name, int argc);
+static Dart_NativeFunction NativeLookup(Dart_Handle name,
+                                        int argc,
+                                        bool* auto_setup_scope);
 
 
 static const char* kCustomIsolateScriptChars =
@@ -229,7 +231,11 @@
 }
 
 
-static Dart_NativeFunction NativeLookup(Dart_Handle name, int argc) {
+static Dart_NativeFunction NativeLookup(Dart_Handle name,
+                                        int argc,
+                                        bool* auto_setup_scope) {
+  ASSERT(auto_setup_scope != NULL);
+  *auto_setup_scope = false;
   const char* name_str = NULL;
   EXPECT(Dart_IsString(name));
   EXPECT_VALID(Dart_StringToCString(name, &name_str));
diff --git a/runtime/vm/dart.cc b/runtime/vm/dart.cc
index 2633f25..248d413 100644
--- a/runtime/vm/dart.cc
+++ b/runtime/vm/dart.cc
@@ -21,6 +21,7 @@
 #include "vm/snapshot.h"
 #include "vm/stub_code.h"
 #include "vm/symbols.h"
+#include "vm/thread_interrupter.h"
 #include "vm/thread_pool.h"
 #include "vm/virtual_memory.h"
 #include "vm/zone.h"
@@ -97,7 +98,7 @@
   FreeListElement::InitOnce();
   Api::InitOnce();
   CodeObservers::InitOnce();
-  ProfilerManager::InitOnce();
+  Profiler::InitOnce();
 #if defined(USING_SIMULATOR)
   Simulator::InitOnce();
 #endif
@@ -172,7 +173,7 @@
   vm_isolate_ = NULL;
 #endif
 
-  ProfilerManager::Shutdown();
+  Profiler::Shutdown();
   CodeObservers::DeleteAll();
 
   return NULL;
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index 8280f94..a25c698 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -293,6 +293,27 @@
 }
 
 
+bool Api::GetNativeBooleanArgument(Dart_NativeArguments args,
+                                   int arg_index,
+                                   bool* value) {
+  NoGCScope no_gc_scope;
+  NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
+  RawObject* raw_obj = arguments->NativeArgAt(arg_index);
+  if (raw_obj->IsHeapObject()) {
+      intptr_t cid = raw_obj->GetClassId();
+      if (cid == kBoolCid) {
+        *value = (raw_obj == Object::bool_true().raw());
+        return true;
+      }
+      if (cid == kNullCid) {
+        *value = false;
+        return true;
+      }
+  }
+  return false;
+}
+
+
 void Api::SetWeakHandleReturnValue(NativeArguments* args,
                                    Dart_WeakPersistentHandle retval) {
   args->SetReturnUnsafe(Api::UnwrapAsWeakPersistentHandle(retval)->raw());
@@ -1033,6 +1054,17 @@
 }
 
 
+DART_EXPORT bool Dart_HandleServiceMessages() {
+  Isolate* isolate = Isolate::Current();
+  CHECK_ISOLATE_SCOPE(isolate);
+  CHECK_CALLBACK_STATE(isolate);
+  isolate->message_handler()->HandleOOBMessages();
+  // TODO(turnidge): The return value here should indicate whether an
+  // OOB message should cause the program to resume.  Implement.
+  return false;
+}
+
+
 DART_EXPORT bool Dart_HasLivePorts() {
   Isolate* isolate = Isolate::Current();
   ASSERT(isolate);
@@ -1055,7 +1087,7 @@
   writer.WriteMessage(object);
   intptr_t len = writer.BytesWritten();
   return PortMap::PostMessage(new Message(
-      port_id, Message::kIllegalPort, data, len, Message::kNormalPriority));
+      port_id, data, len, Message::kNormalPriority));
 }
 
 
@@ -1161,7 +1193,7 @@
 
 DART_EXPORT Dart_Handle Dart_Null() {
   Isolate* isolate = Isolate::Current();
-  CHECK_ISOLATE_SCOPE(isolate);
+  CHECK_ISOLATE(isolate);
   return Api::Null();
 }
 
@@ -1540,21 +1572,21 @@
 
 DART_EXPORT Dart_Handle Dart_True() {
   Isolate* isolate = Isolate::Current();
-  CHECK_ISOLATE_SCOPE(isolate);
+  CHECK_ISOLATE(isolate);
   return Api::True();
 }
 
 
 DART_EXPORT Dart_Handle Dart_False() {
   Isolate* isolate = Isolate::Current();
-  CHECK_ISOLATE_SCOPE(isolate);
+  CHECK_ISOLATE(isolate);
   return Api::False();
 }
 
 
 DART_EXPORT Dart_Handle Dart_NewBoolean(bool value) {
   Isolate* isolate = Isolate::Current();
-  CHECK_ISOLATE_SCOPE(isolate);
+  CHECK_ISOLATE(isolate);
   return value ? Api::True() : Api::False();
 }
 
@@ -3846,21 +3878,10 @@
         "%s: argument 'index' out of range. Expected 0..%d but saw %d.",
         CURRENT_FUNC, arguments->NativeArgCount() - 1, index);
   }
-  Isolate* isolate = arguments->isolate();
-  ReusableObjectHandleScope reused_obj_handle(isolate);
-  Object& obj = reused_obj_handle.Handle();
-  obj = arguments->NativeArgAt(index);
-  intptr_t cid = obj.GetClassId();
-  if (cid == kBoolCid) {
-    *value = Bool::Cast(obj).value();
+  if (Api::GetNativeBooleanArgument(args, index, value)) {
     return Api::Success();
   }
-  if (obj.IsNull()) {
-    *value = false;
-    return Api::Success();
-  }
-  return Api::NewError(
-      "%s: argument %d is not a Boolean argument.",
+  return Api::NewError("%s: argument %d is not a Boolean argument.",
       CURRENT_FUNC, index);
 }
 
diff --git a/runtime/vm/dart_api_impl.h b/runtime/vm/dart_api_impl.h
index 762ade4..1cc84a5 100644
--- a/runtime/vm/dart_api_impl.h
+++ b/runtime/vm/dart_api_impl.h
@@ -209,6 +209,11 @@
                                   int arg_index,
                                   void** peer);
 
+  // Helper function to get the boolean value of a Bool native argument.
+  static bool GetNativeBooleanArgument(Dart_NativeArguments args,
+                                       int arg_index,
+                                       bool* value);
+
   // Helper function to set the return value of native functions.
   static void SetReturnValue(NativeArguments* args, Dart_Handle retval) {
     args->SetReturnUnsafe(UnwrapHandle(retval));
diff --git a/runtime/vm/dart_api_impl_test.cc b/runtime/vm/dart_api_impl_test.cc
index cb7e97c..6dfbf5c 100644
--- a/runtime/vm/dart_api_impl_test.cc
+++ b/runtime/vm/dart_api_impl_test.cc
@@ -370,7 +370,9 @@
 
 
 static Dart_NativeFunction CurrentStackTraceNativeLookup(
-    Dart_Handle name, int argument_count) {
+    Dart_Handle name, int argument_count, bool* auto_setup_scope) {
+  ASSERT(auto_setup_scope != NULL);
+  *auto_setup_scope = false;
   return reinterpret_cast<Dart_NativeFunction>(&CurrentStackTraceNative);
 }
 
@@ -458,7 +460,9 @@
 
 
 static Dart_NativeFunction PropagateError_native_lookup(
-    Dart_Handle name, int argument_count) {
+    Dart_Handle name, int argument_count, bool* auto_setup_scope) {
+  ASSERT(auto_setup_scope != NULL);
+  *auto_setup_scope = false;
   return reinterpret_cast<Dart_NativeFunction>(&PropagateErrorNative);
 }
 
@@ -1266,7 +1270,10 @@
 
 
 static Dart_NativeFunction ByteDataNativeResolver(Dart_Handle name,
-                                                  int arg_count) {
+                                                  int arg_count,
+                                                  bool* auto_setup_scope) {
+  ASSERT(auto_setup_scope != NULL);
+  *auto_setup_scope = false;
   return &ByteDataNativeFunction;
 }
 
@@ -1324,8 +1331,10 @@
 }
 
 
-static Dart_NativeFunction ExternalByteDataNativeResolver(Dart_Handle name,
-                                                          int arg_count) {
+static Dart_NativeFunction ExternalByteDataNativeResolver(
+    Dart_Handle name, int arg_count, bool* auto_setup_scope) {
+  ASSERT(auto_setup_scope != NULL);
+  *auto_setup_scope = false;
   return &ExternalByteDataNativeFunction;
 }
 
@@ -3580,7 +3589,10 @@
 
 
 static Dart_NativeFunction native_field_lookup(Dart_Handle name,
-                                               int argument_count) {
+                                               int argument_count,
+                                               bool* auto_setup_scope) {
+  ASSERT(auto_setup_scope != NULL);
+  *auto_setup_scope = false;
   return reinterpret_cast<Dart_NativeFunction>(&NativeFieldLookup);
 }
 
@@ -4744,7 +4756,11 @@
 }
 
 
-static Dart_NativeFunction native_lookup(Dart_Handle name, int argument_count) {
+static Dart_NativeFunction native_lookup(Dart_Handle name,
+                                         int argument_count,
+                                         bool* auto_setup_scope) {
+  ASSERT(auto_setup_scope != NULL);
+  *auto_setup_scope = false;
   return reinterpret_cast<Dart_NativeFunction>(&ExceptionNative);
 }
 
@@ -4788,7 +4804,11 @@
 }
 
 
-static Dart_NativeFunction gnac_lookup(Dart_Handle name, int argument_count) {
+static Dart_NativeFunction gnac_lookup(Dart_Handle name,
+                                       int argument_count,
+                                       bool* auto_setup_scope) {
+  ASSERT(auto_setup_scope != NULL);
+  *auto_setup_scope = false;
   return reinterpret_cast<Dart_NativeFunction>(&NativeArgumentCounter);
 }
 
@@ -5682,7 +5702,10 @@
 
 
 static Dart_NativeFunction PatchNativeResolver(Dart_Handle name,
-                                               int arg_count) {
+                                               int arg_count,
+                                               bool* auto_setup_scope) {
+  ASSERT(auto_setup_scope != NULL);
+  *auto_setup_scope = false;
   return &PatchNativeFunction;
 }
 
@@ -5876,13 +5899,19 @@
 
 
 static Dart_NativeFunction MyNativeResolver1(Dart_Handle name,
-                                             int arg_count) {
+                                             int arg_count,
+                                             bool* auto_setup_scope) {
+  ASSERT(auto_setup_scope != NULL);
+  *auto_setup_scope = false;
   return &MyNativeFunction1;
 }
 
 
 static Dart_NativeFunction MyNativeResolver2(Dart_Handle name,
-                                             int arg_count) {
+                                             int arg_count,
+                                             bool* auto_setup_scope) {
+  ASSERT(auto_setup_scope != NULL);
+  *auto_setup_scope = false;
   return &MyNativeFunction2;
 }
 
@@ -6343,7 +6372,9 @@
 
 
 static Dart_NativeFunction IsolateInterruptTestNativeLookup(
-    Dart_Handle name, int argument_count) {
+    Dart_Handle name, int argument_count, bool* auto_setup_scope) {
+  ASSERT(auto_setup_scope != NULL);
+  *auto_setup_scope = false;
   return reinterpret_cast<Dart_NativeFunction>(&MarkMainEntered);
 }
 
@@ -6648,7 +6679,10 @@
 
 
 static Dart_NativeFunction MyNativeClosureResolver(Dart_Handle name,
-                                                   int arg_count) {
+                                                   int arg_count,
+                                                   bool* auto_setup_scope) {
+  ASSERT(auto_setup_scope != NULL);
+  *auto_setup_scope = false;
   const Object& obj = Object::Handle(Api::UnwrapHandle(name));
   if (!obj.IsString()) {
     return NULL;
@@ -6791,8 +6825,10 @@
 }
 
 
-static Dart_NativeFunction MyStaticNativeClosureResolver(Dart_Handle name,
-                                                         int arg_count) {
+static Dart_NativeFunction MyStaticNativeClosureResolver(
+    Dart_Handle name, int arg_count, bool* auto_setup_scope) {
+  ASSERT(auto_setup_scope != NULL);
+  *auto_setup_scope = false;
   const Object& obj = Object::Handle(Api::UnwrapHandle(name));
   if (!obj.IsString()) {
     return NULL;
@@ -7598,7 +7634,9 @@
 
 
 static Dart_NativeFunction ExternalStringDeoptimize_native_lookup(
-    Dart_Handle name, int argument_count) {
+    Dart_Handle name, int argument_count, bool* auto_setup_scope) {
+  ASSERT(auto_setup_scope != NULL);
+  *auto_setup_scope = false;
   return reinterpret_cast<Dart_NativeFunction>(&A_change_str_native);
 }
 
diff --git a/runtime/vm/dart_entry.cc b/runtime/vm/dart_entry.cc
index 39e53aa..97dd924 100644
--- a/runtime/vm/dart_entry.cc
+++ b/runtime/vm/dart_entry.cc
@@ -401,20 +401,18 @@
 
 
 RawObject* DartLibraryCalls::HandleMessage(const Object& receive_port,
-                                           Dart_Port reply_port_id,
                                            const Instance& message) {
   Isolate* isolate = Isolate::Current();
-  Function& function =
-      Function::Handle(isolate,
-                       isolate->object_store()->handle_message_function());
-  const int kNumArguments = 3;
+  Function& function = Function::Handle(isolate,
+      isolate->object_store()->handle_message_function());
+  const int kNumArguments = 2;
   if (function.IsNull()) {
-    Library& isolate_lib = Library::Handle(Library::IsolateLibrary());
+    Library& isolate_lib = Library::Handle(isolate, Library::IsolateLibrary());
     ASSERT(!isolate_lib.IsNull());
-    const String& class_name =
-        String::Handle(isolate_lib.PrivateName(Symbols::_RawReceivePortImpl()));
-    const String& function_name =
-        String::Handle(isolate_lib.PrivateName(Symbols::_handleMessage()));
+    const String& class_name = String::Handle(isolate,
+        isolate_lib.PrivateName(Symbols::_RawReceivePortImpl()));
+    const String& function_name = String::Handle(isolate,
+        isolate_lib.PrivateName(Symbols::_handleMessage()));
     function = Resolver::ResolveStatic(isolate_lib,
                                        class_name,
                                        function_name,
@@ -425,16 +423,15 @@
   }
   const Array& args = Array::Handle(isolate, Array::New(kNumArguments));
   args.SetAt(0, receive_port);
-  args.SetAt(1, Integer::Handle(isolate, Integer::New(reply_port_id)));
-  args.SetAt(2, message);
+  args.SetAt(1, message);
   if (isolate->debugger()->IsStepping()) {
     // If the isolate is being debugged and the debugger was stepping
     // through code, enable single stepping so debugger will stop
     // at the first location the user is interested in.
     isolate->debugger()->SetSingleStep();
   }
-  const Object& result =
-      Object::Handle(isolate, DartEntry::InvokeFunction(function, args));
+  const Object& result = Object::Handle(isolate,
+      DartEntry::InvokeFunction(function, args));
   ASSERT(result.IsNull() || result.IsError());
   return result.raw();
 }
diff --git a/runtime/vm/dart_entry.h b/runtime/vm/dart_entry.h
index 5b3a851..7420e8b 100644
--- a/runtime/vm/dart_entry.h
+++ b/runtime/vm/dart_entry.h
@@ -167,7 +167,6 @@
 
   // Returns null on success, a RawError on failure.
   static RawObject* HandleMessage(const Object& receive_port,
-                                  Dart_Port reply_port_id,
                                   const Instance& dart_message);
 
   // On success returns new SendPort, on failure returns a RawError.
diff --git a/runtime/vm/debugger.cc b/runtime/vm/debugger.cc
index bd9cbf3..097cee8 100644
--- a/runtime/vm/debugger.cc
+++ b/runtime/vm/debugger.cc
@@ -14,6 +14,7 @@
 #include "vm/flags.h"
 #include "vm/globals.h"
 #include "vm/longjump.h"
+#include "vm/json_stream.h"
 #include "vm/object.h"
 #include "vm/object_store.h"
 #include "vm/os.h"
@@ -27,8 +28,6 @@
 namespace dart {
 
 DEFINE_FLAG(bool, verbose_debug, false, "Verbose debugger messages");
-DEFINE_FLAG(bool, use_new_stacktrace, true,
-            "Use new stacktrace creation");
 
 
 Debugger::EventHandler* Debugger::event_handler_ = NULL;
@@ -86,7 +85,7 @@
 void SourceBreakpoint::GetCodeLocation(
     Library* lib,
     Script* script,
-    intptr_t* pos) {
+    intptr_t* pos) const {
   const Function& func = Function::Handle(function_);
   const Class& cls = Class::Handle(func.origin());
   *lib = cls.library();
@@ -121,11 +120,39 @@
 }
 
 
+void SourceBreakpoint::PrintToJSONStream(JSONStream* stream) const {
+  Isolate* isolate = Isolate::Current();
+
+  JSONObject jsobj(stream);
+  jsobj.AddProperty("type", "Breakpoint");
+
+  jsobj.AddProperty("id", id());
+  jsobj.AddProperty("enabled", IsEnabled());
+
+  const Function& func = Function::Handle(function());
+  jsobj.AddProperty("resolved", func.HasCode());
+
+  Library& library = Library::Handle(isolate);
+  Script& script = Script::Handle(isolate);
+  intptr_t token_pos;
+  GetCodeLocation(&library, &script, &token_pos);
+  {
+    JSONObject location(&jsobj, "location");
+    location.AddProperty("type", "Location");
+    location.AddProperty("libId", library.index());
+
+    const String& url = String::Handle(script.url());
+    location.AddProperty("script", url.ToCString());
+    location.AddProperty("tokenPos", token_pos);
+  }
+}
+
 
 void CodeBreakpoint::VisitObjectPointers(ObjectPointerVisitor* visitor) {
   visitor->VisitPointer(reinterpret_cast<RawObject**>(&function_));
 }
 
+
 ActivationFrame::ActivationFrame(
     uword pc,
     uword fp,
@@ -221,6 +248,15 @@
 }
 
 
+void Debugger::PrintBreakpointsToJSONArray(JSONArray* jsarr) const {
+  SourceBreakpoint* sbpt = src_breakpoints_;
+  while (sbpt != NULL) {
+    jsarr->AddValue(sbpt);
+    sbpt = sbpt->next_;
+  }
+}
+
+
 RawString* ActivationFrame::QualifiedFunctionName() {
   return String::New(Debugger::QualifiedFunctionName(function()));
 }
@@ -366,23 +402,7 @@
 }
 
 
-// Get the caller's context, or return ctx if the function does not
-// save the caller's context on entry.
-RawContext* ActivationFrame::GetSavedEntryContext(const Context& ctx) {
-  GetVarDescriptors();
-  intptr_t var_desc_len = var_descriptors_.Length();
-  for (intptr_t i = 0; i < var_desc_len; i++) {
-    RawLocalVarDescriptors::VarInfo var_info;
-    var_descriptors_.GetInfo(i, &var_info);
-    if (var_info.kind == RawLocalVarDescriptors::kSavedEntryContext) {
-      return GetLocalContextVar(var_info.index);
-    }
-  }
-  return ctx.raw();
-}
-
-
-RawContext* ActivationFrame::GetSavedEntryContextNew() {
+RawContext* ActivationFrame::GetSavedEntryContext() {
   if (ctx_.IsNull()) {
     // We have bailed on providing a context for this frame.  Bail for
     // the caller as well.
@@ -466,15 +486,6 @@
   }
   GetVarDescriptors();
 
-  // We don't trust variable descriptors in optimized code.
-  // Rather than potentially displaying incorrect values, we
-  // pretend that there are no variables in the frame.
-  // We should be more clever about this in the future.
-  if (!FLAG_use_new_stacktrace && code().is_optimized()) {
-    vars_initialized_ = true;
-    return;
-  }
-
   intptr_t activation_token_pos = TokenPos();
   if (activation_token_pos < 0) {
     // We don't have a token position for this frame, so can't determine
@@ -598,28 +609,15 @@
     ASSERT(var_info.kind == RawLocalVarDescriptors::kContextVar);
     // The context level at the PC/token index of this activation frame.
     intptr_t frame_ctx_level = ContextLevel();
-    if (ctx_.IsNull()) {
-      if (FLAG_use_new_stacktrace) {
-        UNREACHABLE();  // ctx_ should never be null.
-      }
-      *value = Symbols::New("<unknown>");
-      return;
-    }
+    ASSERT(!ctx_.IsNull());
+
     // The context level of the variable.
     intptr_t var_ctx_level = var_info.scope_id;
     intptr_t level_diff = frame_ctx_level - var_ctx_level;
     intptr_t ctx_slot = var_info.index;
     if (level_diff == 0) {
-      // TODO(12767) : Need to ensure that we end up with the correct context
-      // here so that this check can be an assert.
-      if ((ctx_slot < ctx_.num_variables()) && (ctx_slot >= 0)) {
-        *value = ctx_.At(ctx_slot);
-      } else {
-        if (FLAG_use_new_stacktrace) {
-          UNREACHABLE();  // ctx_ should be correct.
-        }
-        *value = Symbols::New("<unknown>");
-      }
+      ASSERT((ctx_slot >= 0) && (ctx_slot < ctx_.num_variables()));
+      *value = ctx_.At(ctx_slot);
     } else {
       ASSERT(level_diff > 0);
       Context& var_ctx = Context::Handle(ctx_.raw());
@@ -627,17 +625,9 @@
         level_diff--;
         var_ctx = var_ctx.parent();
       }
-      // TODO(12767) : Need to ensure that we end up with the correct context
-      // here so that this check can be assert.
-      if (!var_ctx.IsNull() &&
-          ((ctx_slot < var_ctx.num_variables()) && (ctx_slot >= 0))) {
-        *value = var_ctx.At(ctx_slot);
-      } else {
-        if (FLAG_use_new_stacktrace) {
-          UNREACHABLE();  // var_ctx should be correct.
-        }
-        *value = Symbols::New("<unknown>");
-      }
+      ASSERT(!var_ctx.IsNull());
+      ASSERT((ctx_slot >= 0) && (ctx_slot < var_ctx.num_variables()));
+      *value = var_ctx.At(ctx_slot);
     }
   }
 }
@@ -1050,25 +1040,6 @@
 }
 
 
-static void PrintStackTraceError(const char* message,
-                                 ActivationFrame* current_activation,
-                                 ActivationFrame* callee_activation) {
-  const Function& current = current_activation->function();
-  const Function& callee = callee_activation->function();
-  const Script& script =
-      Script::Handle(Class::Handle(current.Owner()).script());
-  intptr_t line, col;
-  script.GetTokenLocation(current_activation->TokenPos(), &line, &col);
-  OS::PrintErr("Error building stack trace: %s:"
-               "current function '%s' callee_function '%s' "
-               " line %" Pd " column %" Pd "\n",
-               message,
-               current.ToFullyQualifiedCString(),
-               callee.ToFullyQualifiedCString(),
-               line, col);
-}
-
-
 ActivationFrame* Debugger::CollectDartFrame(Isolate* isolate,
                                             uword pc,
                                             StackFrame* frame,
@@ -1095,26 +1066,15 @@
     // in the current frame before making the call.
     const Context& closure_call_ctx =
         Context::Handle(isolate, activation->GetSavedCurrentContext());
+    ASSERT(!closure_call_ctx.IsNull());
     activation->SetContext(closure_call_ctx);
 
-    // Sometimes there is no saved context. This is a bug.
-    // https://code.google.com/p/dart/issues/detail?id=12767
-    if ((FLAG_verbose_debug || FLAG_use_new_stacktrace) &&
-        closure_call_ctx.IsNull()) {
-      PrintStackTraceError(
-          "Expected to find saved context for call to closure function",
-          activation, callee_activation);
-      if (FLAG_use_new_stacktrace) {
-        UNREACHABLE();  // This bug should be fixed with new stack collection.
-      }
-    }
-
   } else {
     // Use the context provided by our callee.  This is either the
     // callee's context or a context that was saved in the callee's
     // frame.
     const Context& callee_ctx =
-        Context::Handle(isolate, callee_activation->GetSavedEntryContextNew());
+        Context::Handle(isolate, callee_activation->GetSavedEntryContext());
     activation->SetContext(callee_ctx);
   }
   return activation;
@@ -1144,7 +1104,7 @@
 }
 
 
-DebuggerStackTrace* Debugger::CollectStackTraceNew() {
+DebuggerStackTrace* Debugger::CollectStackTrace() {
   Isolate* isolate = Isolate::Current();
   DebuggerStackTrace* stack_trace = new DebuggerStackTrace(8);
   StackFrameIterator iterator(false);
@@ -1200,70 +1160,6 @@
 }
 
 
-
-DebuggerStackTrace* Debugger::CollectStackTrace() {
-  if (FLAG_use_new_stacktrace) {
-    // Guard new stack trace generation under a flag in case there are
-    // problems rolling it out.
-    return CollectStackTraceNew();
-  }
-  Isolate* isolate = Isolate::Current();
-  DebuggerStackTrace* stack_trace = new DebuggerStackTrace(8);
-  Context& ctx = Context::Handle(isolate->top_context());
-  Code& code = Code::Handle(isolate);
-  StackFrameIterator iterator(false);
-  ActivationFrame* callee_activation = NULL;
-  bool optimized_frame_found = false;
-  for (StackFrame* frame = iterator.NextFrame();
-       frame != NULL;
-       frame = iterator.NextFrame()) {
-    ASSERT(frame->IsValid());
-    if (frame->IsDartFrame()) {
-      code = frame->LookupDartCode();
-      ActivationFrame* activation =
-          new ActivationFrame(frame->pc(), frame->fp(), frame->sp(), code,
-                              Object::null_array(), 0);
-      // If this activation frame called a closure, the function has
-      // saved its context before the call.
-      if ((callee_activation != NULL) &&
-          (callee_activation->function().IsClosureFunction())) {
-        ctx = activation->GetSavedCurrentContext();
-        if (FLAG_verbose_debug && ctx.IsNull()) {
-          const Function& caller = activation->function();
-          const Function& callee = callee_activation->function();
-          const Script& script =
-              Script::Handle(Class::Handle(caller.Owner()).script());
-          intptr_t line, col;
-          script.GetTokenLocation(activation->TokenPos(), &line, &col);
-          OS::Print("CollectStackTrace error: no saved context in function "
-              "'%s' which calls closure '%s' "
-              " in line %" Pd " column %" Pd "\n",
-              caller.ToFullyQualifiedCString(),
-              callee.ToFullyQualifiedCString(),
-              line, col);
-        }
-      }
-      if (optimized_frame_found || code.is_optimized()) {
-        // Set context to null, to avoid returning bad context variable values.
-        activation->SetContext(Context::Handle());
-        optimized_frame_found = true;
-      } else {
-        ASSERT(!ctx.IsNull());
-        activation->SetContext(ctx);
-      }
-      stack_trace->AddActivation(activation);
-      callee_activation = activation;
-      // Get caller's context if this function saved it on entry.
-      ctx = activation->GetSavedEntryContext(ctx);
-    } else if (frame->IsEntryFrame()) {
-      ctx = reinterpret_cast<EntryFrame*>(frame)->SavedContext();
-      callee_activation = NULL;
-    }
-  }
-  return stack_trace;
-}
-
-
 ActivationFrame* Debugger::TopDartFrame() const {
   StackFrameIterator iterator(false);
   StackFrame* frame = iterator.NextFrame();
@@ -1283,7 +1179,7 @@
 }
 
 DebuggerStackTrace* Debugger::CurrentStackTrace() {
-  return CollectStackTraceNew();
+  return CollectStackTrace();
 }
 
 DebuggerStackTrace* Debugger::StackTraceFrom(const Stacktrace& ex_trace) {
@@ -1588,7 +1484,7 @@
 
 
 SourceBreakpoint* Debugger::SetBreakpointAtLine(const String& script_url,
-                                          intptr_t line_number) {
+                                                intptr_t line_number) {
   Library& lib = Library::Handle(isolate_);
   Script& script = Script::Handle(isolate_);
   const GrowableObjectArray& libs =
diff --git a/runtime/vm/debugger.h b/runtime/vm/debugger.h
index f70debf..c484b56 100644
--- a/runtime/vm/debugger.h
+++ b/runtime/vm/debugger.h
@@ -15,6 +15,8 @@
 class ActiveVariables;
 class CodeBreakpoint;
 class Isolate;
+class JSONArray;
+class JSONStream;
 class ObjectPointerVisitor;
 class RemoteObjectCache;
 class SourceBreakpoint;
@@ -36,12 +38,16 @@
   RawString* SourceUrl();
   intptr_t LineNumber();
 
-  void GetCodeLocation(Library* lib, Script* script, intptr_t* token_pos);
+  void GetCodeLocation(Library* lib,
+                       Script* script,
+                       intptr_t* token_pos) const;
 
   void Enable();
   void Disable();
   bool IsEnabled() const { return is_enabled_; }
 
+  void PrintToJSONStream(JSONStream* stream) const;
+
  private:
   void VisitObjectPointers(ObjectPointerVisitor* visitor);
 
@@ -167,8 +173,7 @@
                   Instance* value);
 
   RawArray* GetLocalVariables();
-  RawContext* GetSavedEntryContext(const Context& ctx);
-  RawContext* GetSavedEntryContextNew();
+  RawContext* GetSavedEntryContext();
   RawContext* GetSavedCurrentContext();
 
  private:
@@ -353,6 +358,8 @@
 
   uword GetPatchedStubAddress(uword breakpoint_address);
 
+  void PrintBreakpointsToJSONArray(JSONArray* jsarr) const;
+
   static bool IsDebuggable(const Function& func);
 
  private:
@@ -386,7 +393,6 @@
   void SyncBreakpoint(SourceBreakpoint* bpt);
 
   ActivationFrame* TopDartFrame() const;
-  static DebuggerStackTrace* CollectStackTrace();
   static ActivationFrame* CollectDartFrame(Isolate* isolate,
                                            uword pc,
                                            StackFrame* frame,
@@ -398,7 +404,7 @@
   static RawArray* DeoptimizeToArray(Isolate* isolate,
                                      StackFrame* frame,
                                      const Code& code);
-  static DebuggerStackTrace* CollectStackTraceNew();
+  static DebuggerStackTrace* CollectStackTrace();
   void SignalBpResolved(SourceBreakpoint *bpt);
   void SignalPausedEvent(ActivationFrame* top_frame,
                          SourceBreakpoint* bpt);
diff --git a/runtime/vm/debugger_api_impl.cc b/runtime/vm/debugger_api_impl.cc
index a2ec598..01676eb 100644
--- a/runtime/vm/debugger_api_impl.cc
+++ b/runtime/vm/debugger_api_impl.cc
@@ -973,6 +973,12 @@
 }
 
 
+DART_EXPORT Dart_IsolateId Dart_GetIsolateId(Dart_Isolate dart_isolate) {
+  Isolate* isolate = reinterpret_cast<Isolate*>(dart_isolate);
+  return isolate->debugger()->GetIsolateId();
+}
+
+
 DART_EXPORT char* Dart_GetVmStatus(const char* request) {
   if (strncmp(request, "/isolate/", 9) == 0) {
     return Isolate::GetStatus(request);
diff --git a/runtime/vm/debugger_api_impl_test.cc b/runtime/vm/debugger_api_impl_test.cc
index 9089e5c..c4e07a5 100644
--- a/runtime/vm/debugger_api_impl_test.cc
+++ b/runtime/vm/debugger_api_impl_test.cc
@@ -1300,6 +1300,7 @@
   EXPECT_VALID(retval);
   EXPECT(test_isolate_id != ILLEGAL_ISOLATE_ID);
   EXPECT(Dart_GetIsolate(test_isolate_id) == isolate);
+  EXPECT(Dart_GetIsolateId(isolate) == test_isolate_id);
   Dart_ExitScope();
   Dart_ShutdownIsolate();
   EXPECT(verify_callback == 0x5);  // Only created and shutdown events.
@@ -1349,7 +1350,10 @@
 
 
 static Dart_NativeFunction InterruptNativeResolver(Dart_Handle name,
-                                                   int arg_count) {
+                                                   int arg_count,
+                                                   bool* auto_setup_scope) {
+  ASSERT(auto_setup_scope != NULL);
+  *auto_setup_scope = false;
   return &InterruptNativeFunction;
 }
 
diff --git a/runtime/vm/debugger_test.cc b/runtime/vm/debugger_test.cc
new file mode 100644
index 0000000..17f1780
--- /dev/null
+++ b/runtime/vm/debugger_test.cc
@@ -0,0 +1,57 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#include "vm/debugger.h"
+#include "vm/unit_test.h"
+
+namespace dart {
+
+TEST_CASE(Debugger_PrintBreakpointsToJSONArray) {
+  const char* kScriptChars =
+      "void main() {\n"
+      "  print('won');\n"
+      "  print('too');\n"
+      "  print('free');\n"
+      "  print('for');\n"
+      "}\n";
+  Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
+  EXPECT_VALID(lib);
+
+  Isolate* isolate = Isolate::Current();
+  Debugger* debugger = isolate->debugger();
+  const String& url = String::Handle(String::New(TestCase::url()));
+
+  // Empty case.
+  {
+    JSONStream js;
+    {
+      JSONArray jsarr(&js);
+      debugger->PrintBreakpointsToJSONArray(&jsarr);
+    }
+    EXPECT_STREQ("[]", js.ToCString());
+  }
+
+  // Test with a couple of breakpoints.
+  debugger->SetBreakpointAtLine(url, 2);
+  debugger->SetBreakpointAtLine(url, 3);
+  {
+    JSONStream js;
+    {
+      JSONArray jsarr(&js);
+      debugger->PrintBreakpointsToJSONArray(&jsarr);
+    }
+    EXPECT_STREQ(
+       "[{\"type\":\"Breakpoint\",\"id\":2,"
+         "\"enabled\":true,\"resolved\":false,"
+         "\"location\":{\"type\":\"Location\",\"libId\":12,"
+                       "\"script\":\"dart:test-lib\",\"tokenPos\":12}},"
+        "{\"type\":\"Breakpoint\",\"id\":1,"
+         "\"enabled\":true,\"resolved\":false,"
+         "\"location\":{\"type\":\"Location\",\"libId\":12,"
+                       "\"script\":\"dart:test-lib\",\"tokenPos\":6}}]",
+       js.ToCString());
+  }
+}
+
+}  // namespace dart
diff --git a/runtime/vm/exceptions_test.cc b/runtime/vm/exceptions_test.cc
index 6586435..e3138a3 100644
--- a/runtime/vm/exceptions_test.cc
+++ b/runtime/vm/exceptions_test.cc
@@ -76,7 +76,10 @@
 
 
 static Dart_NativeFunction native_lookup(Dart_Handle name,
-                                         int argument_count) {
+                                         int argument_count,
+                                         bool* auto_setup_scope) {
+  ASSERT(auto_setup_scope != NULL);
+  *auto_setup_scope = false;
   const Object& obj = Object::Handle(Api::UnwrapHandle(name));
   ASSERT(obj.IsString());
   const char* function_name = obj.ToCString();
diff --git a/runtime/vm/flow_graph_allocator.cc b/runtime/vm/flow_graph_allocator.cc
index f40c175..b59a05b 100644
--- a/runtime/vm/flow_graph_allocator.cc
+++ b/runtime/vm/flow_graph_allocator.cc
@@ -122,6 +122,7 @@
       }
 
       // Handle uses.
+      current->InitializeLocationSummary(true);  // Optimizing.
       LocationSummary* locs = current->locs();
       ASSERT(locs->input_count() == current->InputCount());
       for (intptr_t j = 0; j < current->InputCount(); j++) {
diff --git a/runtime/vm/flow_graph_builder.cc b/runtime/vm/flow_graph_builder.cc
index 848a632..fb064ba 100644
--- a/runtime/vm/flow_graph_builder.cc
+++ b/runtime/vm/flow_graph_builder.cc
@@ -3175,7 +3175,6 @@
     }
   }
   InlineBailout("EffectGraphVisitor::VisitNativeBodyNode");
-  function.set_is_optimizable(false);
   NativeCallInstr* native_call = new NativeCallInstr(node);
   ReturnDefinition(native_call);
 }
@@ -3285,18 +3284,12 @@
       new StoreInstanceFieldInstr(node->field(),
                                   for_instance.value(),
                                   store_value,
-                                  kEmitStoreBarrier);
+                                  kEmitStoreBarrier,
+                                  true);  // Maybe initializing store.
   ReturnDefinition(store);
 }
 
 
-// StoreInstanceFieldNode does not return result.
-void ValueGraphVisitor::VisitStoreInstanceFieldNode(
-    StoreInstanceFieldNode* node) {
-  UNIMPLEMENTED();
-}
-
-
 void EffectGraphVisitor::VisitLoadStaticFieldNode(LoadStaticFieldNode* node) {
   if (node->field().is_const()) {
     ASSERT(node->field().value() != Object::sentinel().raw());
diff --git a/runtime/vm/flow_graph_builder.h b/runtime/vm/flow_graph_builder.h
index f9adcd6..ead8e24 100644
--- a/runtime/vm/flow_graph_builder.h
+++ b/runtime/vm/flow_graph_builder.h
@@ -454,7 +454,6 @@
   virtual void VisitLoadLocalNode(LoadLocalNode* node);
   virtual void VisitStoreLocalNode(StoreLocalNode* node);
   virtual void VisitStoreIndexedNode(StoreIndexedNode* node);
-  virtual void VisitStoreInstanceFieldNode(StoreInstanceFieldNode* node);
   virtual void VisitInstanceSetterNode(InstanceSetterNode* node);
   virtual void VisitThrowNode(ThrowNode* node);
   virtual void VisitClosureCallNode(ClosureCallNode* node);
diff --git a/runtime/vm/flow_graph_compiler.cc b/runtime/vm/flow_graph_compiler.cc
index 9f99579..2e90989b 100644
--- a/runtime/vm/flow_graph_compiler.cc
+++ b/runtime/vm/flow_graph_compiler.cc
@@ -131,7 +131,9 @@
         if ((ic_data != NULL) && (ic_data->NumberOfChecks() == 0)) {
           may_reoptimize_ = true;
         }
-        if (is_leaf && !current->IsCheckStackOverflow()) {
+        if (is_leaf &&
+            !current->IsCheckStackOverflow() &&
+            !current->IsParallelMove()) {
           // Note that we do not care if the code contains instructions that
           // can deoptimize.
           LocationSummary* locs = current->locs();
@@ -267,7 +269,6 @@
       if (instr->IsParallelMove()) {
         parallel_move_resolver_.EmitNativeCode(instr->AsParallelMove());
       } else {
-        ASSERT(instr->locs() != NULL);
         EmitInstructionPrologue(instr);
         ASSERT(pending_deoptimization_env_ == NULL);
         pending_deoptimization_env_ = instr->env();
@@ -636,7 +637,11 @@
       ASSERT(return_node.value()->IsLoadInstanceFieldNode());
       const LoadInstanceFieldNode& load_node =
           *return_node.value()->AsLoadInstanceFieldNode();
-      GenerateInlinedGetter(load_node.field().Offset());
+      // Only intrinsify getter if the field cannot contain a mutable double.
+      // Reading from a mutable double box requires allocating a fresh double.
+      if (load_node.field().guarded_cid() == kDynamicCid) {
+        GenerateInlinedGetter(load_node.field().Offset());
+      }
       return;
     }
     if (parsed_function().function().kind() == RawFunction::kImplicitSetter) {
@@ -819,6 +824,7 @@
 void FlowGraphCompiler::AllocateRegistersLocally(Instruction* instr) {
   ASSERT(!is_optimizing());
 
+  instr->InitializeLocationSummary(false);  // Not optimizing.
   LocationSummary* locs = instr->locs();
 
   bool blocked_registers[kNumberOfCpuRegisters];
diff --git a/runtime/vm/flow_graph_compiler_arm.cc b/runtime/vm/flow_graph_compiler_arm.cc
index f4bc5f9..f8d4182 100644
--- a/runtime/vm/flow_graph_compiler_arm.cc
+++ b/runtime/vm/flow_graph_compiler_arm.cc
@@ -1037,7 +1037,7 @@
 void FlowGraphCompiler::EmitFrameEntry() {
   const Function& function = parsed_function().function();
   if (CanOptimizeFunction() &&
-      function.is_optimizable() &&
+      function.IsOptimizable() &&
       (!is_optimizing() || may_reoptimize())) {
     const Register function_reg = R6;
 
diff --git a/runtime/vm/flow_graph_compiler_ia32.cc b/runtime/vm/flow_graph_compiler_ia32.cc
index a1661e0..807e6e4 100644
--- a/runtime/vm/flow_graph_compiler_ia32.cc
+++ b/runtime/vm/flow_graph_compiler_ia32.cc
@@ -1064,7 +1064,7 @@
 void FlowGraphCompiler::EmitFrameEntry() {
   const Function& function = parsed_function().function();
   if (CanOptimizeFunction() &&
-      function.is_optimizable() &&
+      function.IsOptimizable() &&
       (!is_optimizing() || may_reoptimize())) {
     const Register function_reg = EDI;
     __ LoadObject(function_reg, function);
diff --git a/runtime/vm/flow_graph_compiler_mips.cc b/runtime/vm/flow_graph_compiler_mips.cc
index c615a12..f524363 100644
--- a/runtime/vm/flow_graph_compiler_mips.cc
+++ b/runtime/vm/flow_graph_compiler_mips.cc
@@ -1065,7 +1065,7 @@
 void FlowGraphCompiler::EmitFrameEntry() {
   const Function& function = parsed_function().function();
   if (CanOptimizeFunction() &&
-      function.is_optimizable() &&
+      function.IsOptimizable() &&
       (!is_optimizing() || may_reoptimize())) {
     const Register function_reg = T0;
 
diff --git a/runtime/vm/flow_graph_compiler_x64.cc b/runtime/vm/flow_graph_compiler_x64.cc
index 9a28abd..496ea0a 100644
--- a/runtime/vm/flow_graph_compiler_x64.cc
+++ b/runtime/vm/flow_graph_compiler_x64.cc
@@ -1046,7 +1046,7 @@
   Register new_pp = kNoRegister;
   Register new_pc = kNoRegister;
   if (CanOptimizeFunction() &&
-      function.is_optimizable() &&
+      function.IsOptimizable() &&
       (!is_optimizing() || may_reoptimize())) {
     const Register function_reg = RDI;
     new_pp = R13;
diff --git a/runtime/vm/flow_graph_inliner.cc b/runtime/vm/flow_graph_inliner.cc
index dd798b8..c6e88b6 100644
--- a/runtime/vm/flow_graph_inliner.cc
+++ b/runtime/vm/flow_graph_inliner.cc
@@ -1065,7 +1065,7 @@
 
 bool PolymorphicInliner::TryInlining(intptr_t receiver_cid,
                                      const Function& target) {
-  if (!target.is_optimizable()) {
+  if (!target.IsOptimizable()) {
     if (TryInlineRecognizedMethod(receiver_cid, target)) {
       owner_->inlined_ = true;
       return true;
diff --git a/runtime/vm/flow_graph_optimizer.cc b/runtime/vm/flow_graph_optimizer.cc
index 9e89082..74f9080 100644
--- a/runtime/vm/flow_graph_optimizer.cc
+++ b/runtime/vm/flow_graph_optimizer.cc
@@ -41,6 +41,8 @@
     "Print live sets for load optimization pass.");
 DEFINE_FLAG(bool, enable_simd_inline, true,
     "Enable inlining of SIMD related method calls.");
+DEFINE_FLAG(int, getter_setter_ratio, 10,
+    "Ratio of getter/setter usage used for double field unboxing heuristics");
 DECLARE_FLAG(bool, eliminate_type_checks);
 DECLARE_FLAG(bool, enable_type_checks);
 DECLARE_FLAG(bool, trace_type_check_elimination);
@@ -62,9 +64,12 @@
 }
 
 
-// Optimize instance calls using cid.
+// Optimize instance calls using cid.  This is called after optimizer
+// converted instance calls to instructions. Any remaining
+// instance calls are either megamorphic calls, cannot be optimized or
+// have no runtime type feedback collected.
 // Attempts to convert an instance call (IC call) using propagated class-ids,
-// e.g., receiver class id, guarded-cid.
+// e.g., receiver class id, guarded-cid, or by guessing cid-s.
 void FlowGraphOptimizer::ApplyClassIds() {
   ASSERT(current_iterator_ == NULL);
   for (intptr_t i = 0; i < block_order_.length(); ++i) {
@@ -96,20 +101,42 @@
 }
 
 
+// TODO(srdjan): Test/support other number types as well.
+static bool IsNumberCid(intptr_t cid) {
+  return (cid == kSmiCid) || (cid == kDoubleCid);
+}
+
+
 // Attempt to build ICData for call using propagated class-ids.
 bool FlowGraphOptimizer::TryCreateICData(InstanceCallInstr* call) {
   ASSERT(call->HasICData());
   if (call->ic_data()->NumberOfChecks() > 0) {
-    // This occurs when an instance call has too many checks.
+    // This occurs when an instance call has too many checks, will be converted
+    // to megamorphic call.
     return false;
   }
   GrowableArray<intptr_t> class_ids(call->ic_data()->num_args_tested());
   ASSERT(call->ic_data()->num_args_tested() <= call->ArgumentCount());
   for (intptr_t i = 0; i < call->ic_data()->num_args_tested(); i++) {
-    intptr_t cid = call->PushArgumentAt(i)->value()->Type()->ToCid();
+    const intptr_t cid = call->PushArgumentAt(i)->value()->Type()->ToCid();
     class_ids.Add(cid);
   }
 
+  const Token::Kind op_kind = call->token_kind();
+  if (Token::IsRelationalOperator(op_kind) ||
+      Token::IsRelationalOperator(op_kind) ||
+      Token::IsBinaryOperator(op_kind)) {
+    // Guess cid: if one of the inputs is a number assume that the other
+    // is a number of same type.
+    const intptr_t cid_0 = class_ids[0];
+    const intptr_t cid_1 = class_ids[1];
+    if ((cid_0 == kDynamicCid) && (IsNumberCid(cid_1))) {
+      class_ids[0] = cid_1;
+    } else if (IsNumberCid(cid_0) && (cid_1 == kDynamicCid)) {
+      class_ids[1] = cid_0;
+    }
+  }
+
   for (intptr_t i = 0; i < class_ids.length(); i++) {
     if (class_ids[i] == kDynamicCid) {
       // Not all cid-s known.
@@ -3506,6 +3533,40 @@
 }
 
 
+void FlowGraphOptimizer::VisitStoreInstanceField(
+    StoreInstanceFieldInstr* instr) {
+  if (instr->IsUnboxedStore()) {
+    ASSERT(instr->is_initialization_);
+    // Determine if this field should be unboxed based on the usage of getter
+    // and setter functions: The heuristic requires that the setter has a
+    // usage count of at least 1/kGetterSetterRatio of the getter usage count.
+    // This is to avoid unboxing fields where the setter is never or rarely
+    // executed.
+    const Field& field = Field::ZoneHandle(instr->field().raw());
+    const String& field_name = String::Handle(field.name());
+    class Class& owner = Class::Handle(field.owner());
+    const Function& getter =
+        Function::Handle(owner.LookupGetterFunction(field_name));
+    const Function& setter =
+        Function::Handle(owner.LookupSetterFunction(field_name));
+    bool result = !getter.IsNull()
+               && !setter.IsNull()
+               && (setter.usage_counter() > 0)
+               && (FLAG_getter_setter_ratio * setter.usage_counter() >
+                   getter.usage_counter());
+    if (!result) {
+      if (FLAG_trace_optimization) {
+        OS::Print("Disabling unboxing of %s\n", field.ToCString());
+      }
+      field.set_is_unboxing_candidate(false);
+      field.DeoptimizeDependentCode();
+    } else {
+      FlowGraph::AddToGuardedFields(flow_graph_->guarded_fields(), &field);
+    }
+  }
+}
+
+
 bool FlowGraphOptimizer::TryInlineInstanceSetter(InstanceCallInstr* instr,
                                                  const ICData& unary_ic_data) {
   ASSERT((unary_ic_data.NumberOfChecks() > 0) &&
@@ -3536,7 +3597,7 @@
   // Inline implicit instance setter.
   const String& field_name =
       String::Handle(Field::NameFromSetter(instr->function_name()));
-  const Field& field = Field::Handle(GetField(class_id, field_name));
+  const Field& field = Field::ZoneHandle(GetField(class_id, field_name));
   ASSERT(!field.IsNull());
 
   if (InstanceCallNeedsClassCheck(instr)) {
@@ -3567,6 +3628,11 @@
       new Value(instr->ArgumentAt(0)),
       new Value(instr->ArgumentAt(1)),
       needs_store_barrier);
+
+  if (store->IsUnboxedStore()) {
+    FlowGraph::AddToGuardedFields(flow_graph_->guarded_fields(), &field);
+  }
+
   // Discard the environment from the original instruction because the store
   // can't deoptimize.
   instr->RemoveEnvironment();
@@ -4373,9 +4439,12 @@
           }
           if (inputs_loop_invariant &&
               !current->IsAssertAssignable() &&
-              !current->IsAssertBoolean()) {
+              !current->IsAssertBoolean() &&
+              !current->IsGuardField()) {
             // TODO(fschneider): Enable hoisting of Assert-instructions
             // if it safe to do.
+            // TODO(15652): Hoisting guard-field instructions causes the
+            // optimizing compiler to crash.
             Hoist(&it, pre_header, current);
           } else if (current->IsCheckSmi() &&
                      current->InputAt(0)->definition()->IsPhi()) {
@@ -6605,7 +6674,37 @@
 
 
 void ConstantPropagator::VisitLoadIndexed(LoadIndexedInstr* instr) {
-  SetValue(instr, non_constant_);
+  const Object& array_obj = instr->array()->definition()->constant_value();
+  const Object& index_obj = instr->index()->definition()->constant_value();
+  if (IsNonConstant(array_obj) || IsNonConstant(index_obj)) {
+    SetValue(instr, non_constant_);
+  } else if (IsConstant(array_obj) && IsConstant(index_obj)) {
+    // Need index to be Smi and array to be either String or an immutable array.
+    if (!index_obj.IsSmi()) {
+      // Should not occur.
+      SetValue(instr, non_constant_);
+      return;
+    }
+    const intptr_t index = Smi::Cast(index_obj).Value();
+    if (index >= 0) {
+      if (array_obj.IsString()) {
+        const String& str = String::Cast(array_obj);
+        if (str.Length() > index) {
+          SetValue(instr, Smi::Handle(Smi::New(str.CharAt(index))));
+          return;
+        }
+      } else if (array_obj.IsArray()) {
+        const Array& a = Array::Cast(array_obj);
+        if ((a.Length() > index) && a.IsImmutable()) {
+          Instance& result = Instance::Handle();
+          result ^= a.At(index);
+          SetValue(instr, result);
+          return;
+        }
+      }
+    }
+    SetValue(instr, non_constant_);
+  }
 }
 
 
diff --git a/runtime/vm/flow_graph_optimizer.h b/runtime/vm/flow_graph_optimizer.h
index c473514..0f611df 100644
--- a/runtime/vm/flow_graph_optimizer.h
+++ b/runtime/vm/flow_graph_optimizer.h
@@ -59,6 +59,7 @@
 
   virtual void VisitStaticCall(StaticCallInstr* instr);
   virtual void VisitInstanceCall(InstanceCallInstr* instr);
+  virtual void VisitStoreInstanceField(StoreInstanceFieldInstr* instr);
 
   void InsertBefore(Instruction* next,
                     Instruction* instr,
diff --git a/runtime/vm/flow_graph_type_propagator.cc b/runtime/vm/flow_graph_type_propagator.cc
index 249bcf1..9fecfe9 100644
--- a/runtime/vm/flow_graph_type_propagator.cc
+++ b/runtime/vm/flow_graph_type_propagator.cc
@@ -758,7 +758,7 @@
   CompileType* value_type = value()->Type();
 
   if (value_type->IsMoreSpecificThan(dst_type())) {
-    return value_type;
+    return ZoneCompileType::Wrap(*value_type);
   }
 
   if (dst_type().IsVoidType()) {
@@ -772,13 +772,9 @@
 
 bool AssertAssignableInstr::RecomputeType() {
   CompileType* value_type = value()->Type();
-  if (value_type == Type()) {
-    return false;
-  }
-
   return UpdateType(value_type->IsMoreSpecificThan(dst_type())
-      ? *value_type
-      : CompileType::FromAbstractType(dst_type()));
+                      ? *value_type
+                      : CompileType::FromAbstractType(dst_type()));
 }
 
 
@@ -820,17 +816,23 @@
 
 
 CompileType CurrentContextInstr::ComputeType() const {
-  return CompileType::FromCid(kContextCid);
+  return CompileType(CompileType::kNonNullable,
+                     kContextCid,
+                     &AbstractType::ZoneHandle(Type::DynamicType()));
 }
 
 
 CompileType CloneContextInstr::ComputeType() const {
-  return CompileType::FromCid(kContextCid);
+  return CompileType(CompileType::kNonNullable,
+                     kContextCid,
+                     &AbstractType::ZoneHandle(Type::DynamicType()));
 }
 
 
 CompileType AllocateContextInstr::ComputeType() const {
-  return CompileType::FromCid(kContextCid);
+  return CompileType(CompileType::kNonNullable,
+                     kContextCid,
+                     &AbstractType::ZoneHandle(Type::DynamicType()));
 }
 
 
diff --git a/runtime/vm/il_printer.cc b/runtime/vm/il_printer.cc
index 7af39e3..05995dd 100644
--- a/runtime/vm/il_printer.cc
+++ b/runtime/vm/il_printer.cc
@@ -79,7 +79,7 @@
   if (FLAG_print_environments && (instr->env() != NULL)) {
     instr->env()->PrintTo(&f);
   }
-  if (print_locations && (instr->locs() != NULL)) {
+  if (print_locations && (instr->locs_ != NULL)) {
     instr->locs()->PrintTo(&f);
   }
   if (instr->lifetime_position() != -1) {
diff --git a/runtime/vm/intermediate_language.cc b/runtime/vm/intermediate_language.cc
index edc727e..ed4f5c4 100644
--- a/runtime/vm/intermediate_language.cc
+++ b/runtime/vm/intermediate_language.cc
@@ -26,6 +26,7 @@
 
 DEFINE_FLAG(bool, propagate_ic_data, true,
     "Propagate IC data from unoptimized to optimized IC calls.");
+DEFINE_FLAG(bool, unbox_double_fields, true, "Support unboxed double fields.");
 DECLARE_FLAG(bool, enable_type_checks);
 DECLARE_FLAG(bool, eliminate_type_checks);
 DECLARE_FLAG(bool, trace_optimization);
@@ -136,6 +137,30 @@
 }
 
 
+bool LoadFieldInstr::IsUnboxedLoad() const {
+  return FLAG_unbox_double_fields
+      && (field() != NULL)
+      && field()->IsUnboxedField();
+}
+
+
+bool LoadFieldInstr::IsPotentialUnboxedLoad() const {
+  return FLAG_unbox_double_fields
+      && (field() != NULL)
+      && field()->IsPotentialUnboxedField();
+}
+
+
+bool StoreInstanceFieldInstr::IsUnboxedStore() const {
+  return FLAG_unbox_double_fields && field().IsUnboxedField();
+}
+
+
+bool StoreInstanceFieldInstr::IsPotentialUnboxedStore() const {
+  return FLAG_unbox_double_fields && field().IsPotentialUnboxedField();
+}
+
+
 bool GuardFieldInstr::AttributesEqual(Instruction* other) const {
   return field().raw() == other->AsGuardField()->field().raw();
 }
@@ -1757,13 +1782,13 @@
 
 #define __ compiler->assembler()->
 
-LocationSummary* GraphEntryInstr::MakeLocationSummary() const {
+LocationSummary* GraphEntryInstr::MakeLocationSummary(bool optimizing) const {
   UNREACHABLE();
   return NULL;
 }
 
 
-LocationSummary* JoinEntryInstr::MakeLocationSummary() const {
+LocationSummary* JoinEntryInstr::MakeLocationSummary(bool optimizing) const {
   UNREACHABLE();
   return NULL;
 }
@@ -1782,7 +1807,7 @@
 }
 
 
-LocationSummary* TargetEntryInstr::MakeLocationSummary() const {
+LocationSummary* TargetEntryInstr::MakeLocationSummary(bool optimizing) const {
   // FlowGraphCompiler::EmitInstructionPrologue is not called for block
   // entry instructions, so this function is unused.  If it becomes
   // reachable, note that the deoptimization descriptor in unoptimized code
@@ -1794,7 +1819,7 @@
 }
 
 
-LocationSummary* PhiInstr::MakeLocationSummary() const {
+LocationSummary* PhiInstr::MakeLocationSummary(bool optimizing) const {
   UNREACHABLE();
   return NULL;
 }
@@ -1805,7 +1830,7 @@
 }
 
 
-LocationSummary* RedefinitionInstr::MakeLocationSummary() const {
+LocationSummary* RedefinitionInstr::MakeLocationSummary(bool optimizing) const {
   UNREACHABLE();
   return NULL;
 }
@@ -1816,7 +1841,7 @@
 }
 
 
-LocationSummary* ParameterInstr::MakeLocationSummary() const {
+LocationSummary* ParameterInstr::MakeLocationSummary(bool optimizing) const {
   UNREACHABLE();
   return NULL;
 }
@@ -1827,7 +1852,7 @@
 }
 
 
-LocationSummary* ParallelMoveInstr::MakeLocationSummary() const {
+LocationSummary* ParallelMoveInstr::MakeLocationSummary(bool optimizing) const {
   return NULL;
 }
 
@@ -1837,7 +1862,7 @@
 }
 
 
-LocationSummary* ConstraintInstr::MakeLocationSummary() const {
+LocationSummary* ConstraintInstr::MakeLocationSummary(bool optimizing) const {
   UNREACHABLE();
   return NULL;
 }
@@ -1848,7 +1873,8 @@
 }
 
 
-LocationSummary* MaterializeObjectInstr::MakeLocationSummary() const {
+LocationSummary* MaterializeObjectInstr::MakeLocationSummary(
+    bool optimizing) const {
   UNREACHABLE();
   return NULL;
 }
@@ -1859,7 +1885,7 @@
 }
 
 
-LocationSummary* StoreContextInstr::MakeLocationSummary() const {
+LocationSummary* StoreContextInstr::MakeLocationSummary(bool optimizing) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -1869,7 +1895,7 @@
 }
 
 
-LocationSummary* PushTempInstr::MakeLocationSummary() const {
+LocationSummary* PushTempInstr::MakeLocationSummary(bool optimizing) const {
   return LocationSummary::Make(1,
                                Location::NoLocation(),
                                LocationSummary::kNoCall);
@@ -1882,7 +1908,7 @@
 }
 
 
-LocationSummary* DropTempsInstr::MakeLocationSummary() const {
+LocationSummary* DropTempsInstr::MakeLocationSummary(bool optimizing) const {
   return LocationSummary::Make(1,
                                Location::SameAsFirstInput(),
                                LocationSummary::kNoCall);
@@ -1915,7 +1941,7 @@
 }
 
 
-LocationSummary* InstanceCallInstr::MakeLocationSummary() const {
+LocationSummary* InstanceCallInstr::MakeLocationSummary(bool optimizing) const {
   return MakeCallSummary();
 }
 
@@ -1976,7 +2002,7 @@
 }
 
 
-LocationSummary* StaticCallInstr::MakeLocationSummary() const {
+LocationSummary* StaticCallInstr::MakeLocationSummary(bool optimizing) const {
   return MakeCallSummary();
 }
 
@@ -2870,7 +2896,6 @@
     intptr_t original_deopt_id,
     MethodRecognizer::Kind recognized_kind)
     : inputs_(inputs),
-      locs_(NULL),
       recognized_kind_(recognized_kind) {
   ASSERT(inputs_->length() == ArgumentCountFor(recognized_kind_));
   for (intptr_t i = 0; i < inputs_->length(); ++i) {
@@ -2978,7 +3003,6 @@
                                  intptr_t original_deopt_id,
                                  MergedMathInstr::Kind kind)
     : inputs_(inputs),
-      locs_(NULL),
       kind_(kind) {
   ASSERT(inputs_->length() == InputCountFor(kind_));
   for (intptr_t i = 0; i < inputs_->length(); ++i) {
diff --git a/runtime/vm/intermediate_language.h b/runtime/vm/intermediate_language.h
index 43b9873..01dda16 100644
--- a/runtime/vm/intermediate_language.h
+++ b/runtime/vm/intermediate_language.h
@@ -302,7 +302,7 @@
   // Create None CompileType. It is the bottom of the lattice and is used to
   // represent type of the phi that was not yet inferred.
   static CompileType None() {
-    return CompileType(true, kIllegalCid, NULL);
+    return CompileType(kNullable, kIllegalCid, NULL);
   }
 
   // Create Dynamic CompileType. It is the top of the lattice and is used to
@@ -711,7 +711,7 @@
   virtual void Accept(FlowGraphVisitor* visitor);                              \
   virtual type##Instr* As##type() { return this; }                             \
   virtual const char* DebugName() const { return #type; }                      \
-  virtual LocationSummary* MakeLocationSummary() const;                        \
+  virtual LocationSummary* MakeLocationSummary(bool optimizing) const;         \
   virtual void EmitNativeCode(FlowGraphCompiler* compiler);                    \
 
 
@@ -729,6 +729,7 @@
         previous_(NULL),
         next_(NULL),
         env_(NULL),
+        locs_(NULL),
         place_id_(kNoPlaceId) { }
 
   virtual Tag tag() const = 0;
@@ -830,13 +831,16 @@
   // Returns structure describing location constraints required
   // to emit native code for this instruction.
   virtual LocationSummary* locs() {
-    // TODO(vegorov): This should be pure virtual method.
-    // However we are temporary using NULL for instructions that
-    // were not converted to the location based code generation yet.
-    return NULL;
+    ASSERT(locs_ != NULL);
+    return locs_;
   }
 
-  virtual LocationSummary* MakeLocationSummary() const = 0;
+  virtual LocationSummary* MakeLocationSummary(bool is_optimizing) const = 0;
+
+  void InitializeLocationSummary(bool optimizing) {
+    ASSERT(locs_ == NULL);
+    locs_ = MakeLocationSummary(optimizing);
+  }
 
   static LocationSummary* MakeCallSummary();
 
@@ -953,6 +957,7 @@
   }
 
  private:
+  friend class FlowGraphPrinter;
   friend class Definition;  // Needed for InsertBefore, InsertAfter.
 
   // Classes that set or read deopt_id_.
@@ -1027,6 +1032,7 @@
   Instruction* previous_;
   Instruction* next_;
   Environment* env_;
+  LocationSummary* locs_;
   intptr_t place_id_;
 
   DISALLOW_COPY_AND_ASSIGN(Instruction);
@@ -1036,18 +1042,11 @@
 template<intptr_t N>
 class TemplateInstruction: public Instruction {
  public:
-  TemplateInstruction<N>() : locs_(NULL) { }
+  TemplateInstruction<N>() : inputs_() { }
 
   virtual intptr_t InputCount() const { return N; }
   virtual Value* InputAt(intptr_t i) const { return inputs_[i]; }
 
-  virtual LocationSummary* locs() {
-    if (locs_ == NULL) {
-      locs_ = MakeLocationSummary();
-    }
-    return locs_;
-  }
-
  protected:
   EmbeddedArray<Value*, N> inputs_;
 
@@ -1055,8 +1054,6 @@
   virtual void RawSetInputAt(intptr_t i, Value* value) {
     inputs_[i] = value;
   }
-
-  LocationSummary* locs_;
 };
 
 
@@ -1929,7 +1926,7 @@
 
 class PushArgumentInstr : public Definition {
  public:
-  explicit PushArgumentInstr(Value* value) : locs_(NULL) {
+  explicit PushArgumentInstr(Value* value) {
     SetInputAt(0, value);
     set_use_kind(kEffect);  // Override the default.
   }
@@ -1948,13 +1945,6 @@
 
   Value* value() const { return value_; }
 
-  virtual LocationSummary* locs() {
-    if (locs_ == NULL) {
-      locs_ = MakeLocationSummary();
-    }
-    return locs_;
-  }
-
   virtual intptr_t Hashcode() const {
     UNREACHABLE();
     return 0;
@@ -1975,7 +1965,6 @@
   }
 
   Value* value_;
-  LocationSummary* locs_;
 
   DISALLOW_COPY_AND_ASSIGN(PushArgumentInstr);
 };
@@ -2133,20 +2122,11 @@
 template<intptr_t N>
 class TemplateDefinition : public Definition {
  public:
-  TemplateDefinition<N>() : locs_(NULL) { }
+  TemplateDefinition<N>() : inputs_() { }
 
   virtual intptr_t InputCount() const { return N; }
   virtual Value* InputAt(intptr_t i) const { return inputs_[i]; }
 
-  // Returns a structure describing the location constraints required
-  // to emit native code for this definition.
-  LocationSummary* locs() {
-    if (locs_ == NULL) {
-      locs_ = MakeLocationSummary();
-    }
-    return locs_;
-  }
-
  protected:
   EmbeddedArray<Value*, N> inputs_;
 
@@ -2157,8 +2137,6 @@
   virtual void RawSetInputAt(intptr_t i, Value* value) {
     inputs_[i] = value;
   }
-
-  LocationSummary* locs_;
 };
 
 
@@ -2260,18 +2238,6 @@
 
   bool is_checked() const { return is_checked_; }
 
-  virtual LocationSummary* locs() {
-    if (comparison()->locs_ == NULL) {
-      LocationSummary* summary = comparison()->MakeLocationSummary();
-      // Branches don't produce a result.
-      summary->set_out(Location::NoLocation());
-      // The back-end expects the location summary to be stored in the
-      // comparison.
-      comparison()->locs_ = summary;
-    }
-    return comparison()->locs_;
-  }
-
   virtual intptr_t DeoptimizationTarget() const {
     return comparison()->DeoptimizationTarget();
   }
@@ -3154,16 +3120,6 @@
     return comparison()->CanBecomeDeoptimizationTarget();
   }
 
-  virtual LocationSummary* locs() {
-    if (comparison()->locs_ == NULL) {
-      LocationSummary* summary = MakeLocationSummary();
-      // The back-end expects the location summary to be stored in the
-      // comparison.
-      comparison()->locs_ = summary;
-    }
-    return comparison()->locs_;
-  }
-
   virtual intptr_t DeoptimizationTarget() const {
     return comparison()->DeoptimizationTarget();
   }
@@ -3470,9 +3426,11 @@
   StoreInstanceFieldInstr(const Field& field,
                           Value* instance,
                           Value* value,
-                          StoreBarrierType emit_store_barrier)
+                          StoreBarrierType emit_store_barrier,
+                          bool is_initialization = false)
       : field_(field),
-        emit_store_barrier_(emit_store_barrier) {
+        emit_store_barrier_(emit_store_barrier),
+        is_initialization_(is_initialization) {
     SetInputAt(kInstancePos, instance);
     SetInputAt(kValuePos, value);
   }
@@ -3500,6 +3458,11 @@
 
   virtual bool CanDeoptimize() const { return false; }
 
+  // May require a deoptimization target for input conversions.
+  virtual intptr_t DeoptimizationTarget() const {
+    return GetDeoptId();
+  }
+
   // Currently CSE/LICM don't operate on any instructions that can be affected
   // by stores/loads. LoadOptimizer handles loads separately. Hence stores
   // are marked as having no side-effects.
@@ -3507,7 +3470,19 @@
 
   virtual bool MayThrow() const { return false; }
 
+  bool IsUnboxedStore() const;
+
+  bool IsPotentialUnboxedStore() const;
+
+  virtual Representation RequiredInputRepresentation(intptr_t index) const {
+    ASSERT((index == 0) || (index == 1));
+    if ((index == 1) && IsUnboxedStore()) return kUnboxedDouble;
+    return kTagged;
+  }
+
  private:
+  friend class FlowGraphOptimizer;  // For ASSERT(initialization_).
+
   bool CanValueBeSmi() const {
     const intptr_t cid = value()->Type()->ToNullableCid();
     // Write barrier is skipped for nullable and non-nullable smis.
@@ -3517,6 +3492,7 @@
 
   const Field& field_;
   const StoreBarrierType emit_store_barrier_;
+  const bool is_initialization_;  // Marks stores in the constructor.
 
   DISALLOW_COPY_AND_ASSIGN(StoreInstanceFieldInstr);
 };
@@ -3997,11 +3973,6 @@
   virtual bool CanDeoptimize() const { return false; }
   virtual EffectSet Effects() const { return EffectSet::None(); }
 
-  LocationSummary* locs() {
-    UNREACHABLE();
-    return NULL;
-  }
-
   Location* locations() { return locations_; }
   void set_locations(Location* locations) { locations_ = locations; }
 
@@ -4217,6 +4188,14 @@
   const Field* field() const { return field_; }
   void set_field(const Field* field) { field_ = field; }
 
+  virtual Representation representation() const {
+    return IsUnboxedLoad() ? kUnboxedDouble : kTagged;
+  }
+
+  bool IsUnboxedLoad() const;
+
+  bool IsPotentialUnboxedLoad() const;
+
   void set_recognized_kind(MethodRecognizer::Kind kind) {
     recognized_kind_ = kind;
   }
@@ -6618,15 +6597,6 @@
     return (*inputs_)[i];
   }
 
-  // Returns a structure describing the location constraints required
-  // to emit native code for this definition.
-  LocationSummary* locs() {
-    if (locs_ == NULL) {
-      locs_ = MakeLocationSummary();
-    }
-    return locs_;
-  }
-
   virtual bool AllowsCSE() const { return true; }
   virtual EffectSet Effects() const { return EffectSet::None(); }
   virtual EffectSet Dependencies() const { return EffectSet::None(); }
@@ -6644,8 +6614,6 @@
 
   ZoneGrowableArray<Value*>* inputs_;
 
-  LocationSummary* locs_;
-
   const MethodRecognizer::Kind recognized_kind_;
 
   DISALLOW_COPY_AND_ASSIGN(InvokeMathCFunctionInstr);
@@ -6728,15 +6696,6 @@
 
   DECLARE_INSTRUCTION(MergedMath)
 
-  // Returns a structure describing the location constraints required
-  // to emit native code for this definition.
-  LocationSummary* locs() {
-    if (locs_ == NULL) {
-      locs_ = MakeLocationSummary();
-    }
-    return locs_;
-  }
-
   virtual bool AllowsCSE() const { return true; }
   virtual EffectSet Effects() const { return EffectSet::None(); }
   virtual EffectSet Dependencies() const { return EffectSet::None(); }
@@ -6760,7 +6719,6 @@
   }
 
   ZoneGrowableArray<Value*>* inputs_;
-  LocationSummary* locs_;
   MergedMathInstr::Kind kind_;
 
   DISALLOW_COPY_AND_ASSIGN(MergedMathInstr);
diff --git a/runtime/vm/intermediate_language_arm.cc b/runtime/vm/intermediate_language_arm.cc
index 1266a3b..c3c2676 100644
--- a/runtime/vm/intermediate_language_arm.cc
+++ b/runtime/vm/intermediate_language_arm.cc
@@ -34,7 +34,7 @@
 }
 
 
-LocationSummary* PushArgumentInstr::MakeLocationSummary() const {
+LocationSummary* PushArgumentInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps= 0;
   LocationSummary* locs =
@@ -63,7 +63,7 @@
 }
 
 
-LocationSummary* ReturnInstr::MakeLocationSummary() const {
+LocationSummary* ReturnInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* locs =
@@ -135,8 +135,9 @@
 }
 
 
-LocationSummary* IfThenElseInstr::MakeLocationSummary() const {
-  return comparison()->MakeLocationSummary();
+LocationSummary* IfThenElseInstr::MakeLocationSummary(bool opt) const {
+  comparison()->InitializeLocationSummary(opt);
+  return comparison()->locs();
 }
 
 
@@ -193,7 +194,7 @@
 }
 
 
-LocationSummary* ClosureCallInstr::MakeLocationSummary() const {
+LocationSummary* ClosureCallInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 0;
   const intptr_t kNumTemps = 1;
   LocationSummary* result =
@@ -223,7 +224,7 @@
 }
 
 
-LocationSummary* LoadLocalInstr::MakeLocationSummary() const {
+LocationSummary* LoadLocalInstr::MakeLocationSummary(bool opt) const {
   return LocationSummary::Make(0,
                                Location::RequiresRegister(),
                                LocationSummary::kNoCall);
@@ -236,7 +237,7 @@
 }
 
 
-LocationSummary* StoreLocalInstr::MakeLocationSummary() const {
+LocationSummary* StoreLocalInstr::MakeLocationSummary(bool opt) const {
   return LocationSummary::Make(1,
                                Location::SameAsFirstInput(),
                                LocationSummary::kNoCall);
@@ -251,7 +252,7 @@
 }
 
 
-LocationSummary* ConstantInstr::MakeLocationSummary() const {
+LocationSummary* ConstantInstr::MakeLocationSummary(bool opt) const {
   return LocationSummary::Make(0,
                                Location::RequiresRegister(),
                                LocationSummary::kNoCall);
@@ -267,7 +268,7 @@
 }
 
 
-LocationSummary* AssertAssignableInstr::MakeLocationSummary() const {
+LocationSummary* AssertAssignableInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 3;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -280,7 +281,7 @@
 }
 
 
-LocationSummary* AssertBooleanInstr::MakeLocationSummary() const {
+LocationSummary* AssertBooleanInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* locs =
@@ -341,7 +342,7 @@
 }
 
 
-LocationSummary* EqualityCompareInstr::MakeLocationSummary() const {
+LocationSummary* EqualityCompareInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 2;
   if (operation_cid() == kMintCid) {
     const intptr_t kNumTemps = 1;
@@ -538,7 +539,7 @@
 }
 
 
-LocationSummary* TestSmiInstr::MakeLocationSummary() const {
+LocationSummary* TestSmiInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 2;
   const intptr_t kNumTemps = 0;
   LocationSummary* locs =
@@ -581,7 +582,7 @@
 }
 
 
-LocationSummary* RelationalOpInstr::MakeLocationSummary() const {
+LocationSummary* RelationalOpInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 2;
   const intptr_t kNumTemps = 0;
   if (operation_cid() == kMintCid) {
@@ -664,7 +665,7 @@
 }
 
 
-LocationSummary* NativeCallInstr::MakeLocationSummary() const {
+LocationSummary* NativeCallInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 0;
   const intptr_t kNumTemps = 3;
   LocationSummary* locs =
@@ -708,6 +709,12 @@
     // stub generates the redirection address when running under the simulator
     // and hence we do not change 'entry' here.
     stub_entry = &StubCode::CallNativeCFunctionLabel();
+#if defined(USING_SIMULATOR)
+    if (!function().IsNativeAutoSetupScope()) {
+      entry = Simulator::RedirectExternalReference(
+          entry, Simulator::kBootstrapNativeCall, function().NumParameters());
+    }
+#endif
   }
   __ LoadImmediate(R5, entry);
   __ LoadImmediate(R1, NativeArguments::ComputeArgcTag(function()));
@@ -719,7 +726,7 @@
 }
 
 
-LocationSummary* StringFromCharCodeInstr::MakeLocationSummary() const {
+LocationSummary* StringFromCharCodeInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   // TODO(fschneider): Allow immediate operands for the char code.
   return LocationSummary::Make(kNumInputs,
@@ -738,7 +745,7 @@
 }
 
 
-LocationSummary* StringInterpolateInstr::MakeLocationSummary() const {
+LocationSummary* StringInterpolateInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -764,7 +771,7 @@
 }
 
 
-LocationSummary* LoadUntaggedInstr::MakeLocationSummary() const {
+LocationSummary* LoadUntaggedInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   return LocationSummary::Make(kNumInputs,
                                Location::RequiresRegister(),
@@ -779,7 +786,7 @@
 }
 
 
-LocationSummary* LoadClassIdInstr::MakeLocationSummary() const {
+LocationSummary* LoadClassIdInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   return LocationSummary::Make(kNumInputs,
                                Location::RequiresRegister(),
@@ -875,7 +882,7 @@
 }
 
 
-LocationSummary* LoadIndexedInstr::MakeLocationSummary() const {
+LocationSummary* LoadIndexedInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 2;
   const intptr_t kNumTemps = 0;
   LocationSummary* locs =
@@ -1060,7 +1067,7 @@
 }
 
 
-LocationSummary* StoreIndexedInstr::MakeLocationSummary() const {
+LocationSummary* StoreIndexedInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 3;
   const intptr_t kNumTemps = 0;
   LocationSummary* locs =
@@ -1247,7 +1254,7 @@
 }
 
 
-LocationSummary* GuardFieldInstr::MakeLocationSummary() const {
+LocationSummary* GuardFieldInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   LocationSummary* summary =
       new LocationSummary(kNumInputs, 0, LocationSummary::kNoCall);
@@ -1572,21 +1579,147 @@
 }
 
 
-LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary() const {
+class StoreInstanceFieldSlowPath : public SlowPathCode {
+ public:
+  explicit StoreInstanceFieldSlowPath(StoreInstanceFieldInstr* instruction)
+      : instruction_(instruction) { }
+
+  virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
+    __ Comment("StoreInstanceFieldSlowPath");
+    __ Bind(entry_label());
+    const Class& double_class = compiler->double_class();
+    const Code& stub =
+        Code::Handle(StubCode::GetAllocationStubForClass(double_class));
+    const ExternalLabel label(double_class.ToCString(), stub.EntryPoint());
+
+    LocationSummary* locs = instruction_->locs();
+    locs->live_registers()->Remove(locs->out());
+
+    compiler->SaveLiveRegisters(locs);
+    compiler->GenerateCall(Scanner::kDummyTokenIndex,  // No token position.
+                           &label,
+                           PcDescriptors::kOther,
+                           locs);
+    __ MoveRegister(locs->temp(0).reg(), R0);
+    compiler->RestoreLiveRegisters(locs);
+
+    __ b(exit_label());
+  }
+
+ private:
+  StoreInstanceFieldInstr* instruction_;
+};
+
+
+LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 2;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
-      new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
+      new LocationSummary(kNumInputs, kNumTemps,
+          (field().guarded_cid() == kIllegalCid) || (is_initialization_)
+          ? LocationSummary::kCallOnSlowPath
+          : LocationSummary::kNoCall);
+
   summary->set_in(0, Location::RequiresRegister());
-  summary->set_in(1, ShouldEmitStoreBarrier()
+  if (IsUnboxedStore() && opt) {
+    summary->set_in(1, Location::RequiresFpuRegister());
+    summary->AddTemp(Location::RequiresRegister());
+    summary->AddTemp(Location::RequiresRegister());
+  } else if (IsPotentialUnboxedStore()) {
+    summary->set_in(1, ShouldEmitStoreBarrier()
+        ? Location::WritableRegister()
+        :  Location::RequiresRegister());
+    summary->AddTemp(Location::RequiresRegister());
+    summary->AddTemp(Location::RequiresRegister());
+    summary->AddTemp(opt ? Location::RequiresFpuRegister()
+                         : Location::FpuRegisterLocation(Q1));
+  } else {
+    summary->set_in(1, ShouldEmitStoreBarrier()
                        ? Location::WritableRegister()
                        : Location::RegisterOrConstant(value()));
+  }
   return summary;
 }
 
 
 void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  Label skip_store;
+
   Register instance_reg = locs()->in(0).reg();
+
+  if (IsUnboxedStore() && compiler->is_optimizing()) {
+    DRegister value = EvenDRegisterOf(locs()->in(1).fpu_reg());
+    Register temp = locs()->temp(0).reg();
+    Register temp2 = locs()->temp(1).reg();
+
+    if (is_initialization_) {
+      StoreInstanceFieldSlowPath* slow_path =
+          new StoreInstanceFieldSlowPath(this);
+      compiler->AddSlowPathCode(slow_path);
+      __ TryAllocate(compiler->double_class(),
+                     slow_path->entry_label(),
+                     temp);
+      __ Bind(slow_path->exit_label());
+      __ MoveRegister(temp2, temp);
+      __ StoreIntoObject(instance_reg,
+                         FieldAddress(instance_reg, field().Offset()),
+                         temp2);
+    } else {
+      __ ldr(temp, FieldAddress(instance_reg, field().Offset()));
+    }
+    __ StoreDToOffset(value, temp, Double::value_offset() - kHeapObjectTag);
+    return;
+  }
+
+  if (IsPotentialUnboxedStore()) {
+    Register value_reg = locs()->in(1).reg();
+    Register temp = locs()->temp(0).reg();
+    Register temp2 = locs()->temp(1).reg();
+    DRegister fpu_temp = EvenDRegisterOf(locs()->temp(2).fpu_reg());
+
+    Label store_pointer, copy_payload;
+    __ LoadObject(temp, Field::ZoneHandle(field().raw()));
+    __ ldr(temp2, FieldAddress(temp, Field::guarded_cid_offset()));
+    __ CompareImmediate(temp2, kDoubleCid);
+    __ b(&store_pointer, NE);
+    __ ldr(temp2, FieldAddress(temp, Field::is_nullable_offset()));
+    __ CompareImmediate(temp2, kNullCid);
+    __ b(&store_pointer, EQ);
+    __ ldrb(temp2, FieldAddress(temp, Field::kind_bits_offset()));
+    __ tst(temp2, ShifterOperand(1 << Field::kUnboxingCandidateBit));
+    __ b(&store_pointer, EQ);
+
+    __ ldr(temp, FieldAddress(instance_reg, field().Offset()));
+    __ CompareImmediate(temp,
+                        reinterpret_cast<intptr_t>(Object::null()));
+    __ b(&copy_payload, NE);
+
+    StoreInstanceFieldSlowPath* slow_path =
+        new StoreInstanceFieldSlowPath(this);
+    compiler->AddSlowPathCode(slow_path);
+
+    if (!compiler->is_optimizing()) {
+      locs()->live_registers()->Add(locs()->in(0));
+      locs()->live_registers()->Add(locs()->in(1));
+    }
+
+    __ TryAllocate(compiler->double_class(),
+                   slow_path->entry_label(),
+                   temp);
+    __ Bind(slow_path->exit_label());
+    __ MoveRegister(temp2, temp);
+    __ StoreIntoObject(instance_reg,
+                       FieldAddress(instance_reg, field().Offset()),
+                       temp2);
+    __ Bind(&copy_payload);
+    __ LoadDFromOffset(fpu_temp,
+                       value_reg,
+                       Double::value_offset() - kHeapObjectTag);
+    __ StoreDToOffset(fpu_temp, temp, Double::value_offset() - kHeapObjectTag);
+    __ b(&skip_store);
+    __ Bind(&store_pointer);
+  }
+
   if (ShouldEmitStoreBarrier()) {
     Register value_reg = locs()->in(1).reg();
     __ StoreIntoObject(instance_reg,
@@ -1605,10 +1738,11 @@
           FieldAddress(instance_reg, field().Offset()), value_reg);
     }
   }
+  __ Bind(&skip_store);
 }
 
 
-LocationSummary* LoadStaticFieldInstr::MakeLocationSummary() const {
+LocationSummary* LoadStaticFieldInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -1632,7 +1766,7 @@
 }
 
 
-LocationSummary* StoreStaticFieldInstr::MakeLocationSummary() const {
+LocationSummary* StoreStaticFieldInstr::MakeLocationSummary(bool opt) const {
   LocationSummary* locs = new LocationSummary(1, 1, LocationSummary::kNoCall);
   locs->set_in(0, value()->NeedsStoreBuffer() ? Location::WritableRegister()
                                               : Location::RequiresRegister());
@@ -1656,7 +1790,7 @@
 }
 
 
-LocationSummary* InstanceOfInstr::MakeLocationSummary() const {
+LocationSummary* InstanceOfInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 3;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -1683,7 +1817,7 @@
 }
 
 
-LocationSummary* CreateArrayInstr::MakeLocationSummary() const {
+LocationSummary* CreateArrayInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* locs =
@@ -1707,7 +1841,7 @@
 
 
 LocationSummary*
-AllocateObjectWithBoundsCheckInstr::MakeLocationSummary() const {
+AllocateObjectWithBoundsCheckInstr::MakeLocationSummary(bool opt) const {
   return MakeCallSummary();
 }
 
@@ -1725,23 +1859,119 @@
 }
 
 
-LocationSummary* LoadFieldInstr::MakeLocationSummary() const {
-  return LocationSummary::Make(1,
-                               Location::RequiresRegister(),
-                               LocationSummary::kNoCall);
+class BoxDoubleSlowPath : public SlowPathCode {
+ public:
+  explicit BoxDoubleSlowPath(Instruction* instruction)
+      : instruction_(instruction) { }
+
+  virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
+    __ Comment("BoxDoubleSlowPath");
+    __ Bind(entry_label());
+    const Class& double_class = compiler->double_class();
+    const Code& stub =
+        Code::Handle(StubCode::GetAllocationStubForClass(double_class));
+    const ExternalLabel label(double_class.ToCString(), stub.EntryPoint());
+
+    LocationSummary* locs = instruction_->locs();
+    locs->live_registers()->Remove(locs->out());
+
+    compiler->SaveLiveRegisters(locs);
+    compiler->GenerateCall(Scanner::kDummyTokenIndex,  // No token position.
+                           &label,
+                           PcDescriptors::kOther,
+                           locs);
+    __ MoveRegister(locs->out().reg(), R0);
+    compiler->RestoreLiveRegisters(locs);
+
+    __ b(exit_label());
+  }
+
+ private:
+  Instruction* instruction_;
+};
+
+
+LocationSummary* LoadFieldInstr::MakeLocationSummary(bool opt) const {
+  const intptr_t kNumInputs = 1;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* locs =
+      new LocationSummary(
+          kNumInputs, kNumTemps,
+          (opt && !IsPotentialUnboxedLoad())
+          ? LocationSummary::kNoCall
+          : LocationSummary::kCallOnSlowPath);
+
+  locs->set_in(0, Location::RequiresRegister());
+
+  if (IsUnboxedLoad() && opt) {
+    locs->AddTemp(Location::RequiresRegister());
+  } else if (IsPotentialUnboxedLoad()) {
+    locs->AddTemp(opt ? Location::RequiresFpuRegister()
+                      : Location::FpuRegisterLocation(Q1));
+    locs->AddTemp(Location::RequiresRegister());
+  }
+  locs->set_out(Location::RequiresRegister());
+  return locs;
 }
 
 
 void LoadFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   Register instance_reg = locs()->in(0).reg();
-  Register result_reg = locs()->out().reg();
+  if (IsUnboxedLoad() && compiler->is_optimizing()) {
+    DRegister result = EvenDRegisterOf(locs()->out().fpu_reg());
+    Register temp = locs()->temp(0).reg();
+    __ ldr(temp, FieldAddress(instance_reg, offset_in_bytes()));
+    __ LoadDFromOffset(result, temp, Double::value_offset() - kHeapObjectTag);
+    return;
+  }
 
+  Label done;
+  Register result_reg = locs()->out().reg();
+  if (IsPotentialUnboxedLoad()) {
+    Register temp = locs()->temp(1).reg();
+    DRegister value = EvenDRegisterOf(locs()->temp(0).fpu_reg());
+
+    Label load_pointer;
+    __ LoadObject(result_reg, Field::ZoneHandle(field()->raw()));
+
+    FieldAddress field_cid_operand(result_reg, Field::guarded_cid_offset());
+    FieldAddress field_nullability_operand(result_reg,
+                                           Field::is_nullable_offset());
+
+    __ ldr(temp, field_cid_operand);
+    __ CompareImmediate(temp, kDoubleCid);
+    __ b(&load_pointer, NE);
+
+    __ ldr(temp, field_nullability_operand);
+    __ CompareImmediate(temp, kNullCid);
+    __ b(&load_pointer, EQ);
+
+    BoxDoubleSlowPath* slow_path = new BoxDoubleSlowPath(this);
+    compiler->AddSlowPathCode(slow_path);
+
+    if (!compiler->is_optimizing()) {
+      locs()->live_registers()->Add(locs()->in(0));
+    }
+
+    __ TryAllocate(compiler->double_class(),
+                   slow_path->entry_label(),
+                   result_reg);
+    __ Bind(slow_path->exit_label());
+    __ ldr(temp, FieldAddress(instance_reg, offset_in_bytes()));
+    __ LoadDFromOffset(value, temp, Double::value_offset() - kHeapObjectTag);
+    __ StoreDToOffset(value,
+                      result_reg,
+                      Double::value_offset() - kHeapObjectTag);
+    __ b(&done);
+    __ Bind(&load_pointer);
+  }
   __ LoadFromOffset(kWord, result_reg,
                     instance_reg, offset_in_bytes() - kHeapObjectTag);
+  __ Bind(&done);
 }
 
 
-LocationSummary* InstantiateTypeInstr::MakeLocationSummary() const {
+LocationSummary* InstantiateTypeInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* locs =
@@ -1773,7 +2003,8 @@
 }
 
 
-LocationSummary* InstantiateTypeArgumentsInstr::MakeLocationSummary() const {
+LocationSummary* InstantiateTypeArgumentsInstr::MakeLocationSummary(
+    bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* locs =
@@ -1822,7 +2053,7 @@
 
 
 LocationSummary*
-ExtractConstructorTypeArgumentsInstr::MakeLocationSummary() const {
+ExtractConstructorTypeArgumentsInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* locs =
@@ -1864,7 +2095,7 @@
 
 
 LocationSummary*
-ExtractConstructorInstantiatorInstr::MakeLocationSummary() const {
+ExtractConstructorInstantiatorInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* locs =
@@ -1903,7 +2134,7 @@
 }
 
 
-LocationSummary* AllocateContextInstr::MakeLocationSummary() const {
+LocationSummary* AllocateContextInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 0;
   const intptr_t kNumTemps = 1;
   LocationSummary* locs =
@@ -1928,7 +2159,7 @@
 }
 
 
-LocationSummary* CloneContextInstr::MakeLocationSummary() const {
+LocationSummary* CloneContextInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* locs =
@@ -1955,7 +2186,7 @@
 }
 
 
-LocationSummary* CatchBlockEntryInstr::MakeLocationSummary() const {
+LocationSummary* CatchBlockEntryInstr::MakeLocationSummary(bool opt) const {
   UNREACHABLE();
   return NULL;
 }
@@ -1992,7 +2223,7 @@
 }
 
 
-LocationSummary* CheckStackOverflowInstr::MakeLocationSummary() const {
+LocationSummary* CheckStackOverflowInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 0;
   const intptr_t kNumTemps = 1;
   LocationSummary* summary =
@@ -2175,7 +2406,7 @@
 }
 
 
-LocationSummary* BinarySmiOpInstr::MakeLocationSummary() const {
+LocationSummary* BinarySmiOpInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 2;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -2506,7 +2737,7 @@
 }
 
 
-LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary() const {
+LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary(bool opt) const {
   intptr_t left_cid = left()->Type()->ToCid();
   intptr_t right_cid = right()->Type()->ToCid();
   ASSERT((left_cid != kDoubleCid) && (right_cid != kDoubleCid));
@@ -2538,7 +2769,7 @@
 }
 
 
-LocationSummary* BoxDoubleInstr::MakeLocationSummary() const {
+LocationSummary* BoxDoubleInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -2551,38 +2782,6 @@
 }
 
 
-class BoxDoubleSlowPath : public SlowPathCode {
- public:
-  explicit BoxDoubleSlowPath(BoxDoubleInstr* instruction)
-      : instruction_(instruction) { }
-
-  virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
-    __ Comment("BoxDoubleSlowPath");
-    __ Bind(entry_label());
-    const Class& double_class = compiler->double_class();
-    const Code& stub =
-        Code::Handle(StubCode::GetAllocationStubForClass(double_class));
-    const ExternalLabel label(double_class.ToCString(), stub.EntryPoint());
-
-    LocationSummary* locs = instruction_->locs();
-    locs->live_registers()->Remove(locs->out());
-
-    compiler->SaveLiveRegisters(locs);
-    compiler->GenerateCall(Scanner::kDummyTokenIndex,  // No token position.
-                           &label,
-                           PcDescriptors::kOther,
-                           locs);
-    __ MoveRegister(locs->out().reg(), R0);
-    compiler->RestoreLiveRegisters(locs);
-
-    __ b(exit_label());
-  }
-
- private:
-  BoxDoubleInstr* instruction_;
-};
-
-
 void BoxDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   BoxDoubleSlowPath* slow_path = new BoxDoubleSlowPath(this);
   compiler->AddSlowPathCode(slow_path);
@@ -2598,7 +2797,7 @@
 }
 
 
-LocationSummary* UnboxDoubleInstr::MakeLocationSummary() const {
+LocationSummary* UnboxDoubleInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t value_cid = value()->Type()->ToCid();
   const bool needs_temp = ((value_cid != kSmiCid) && (value_cid != kDoubleCid));
@@ -2646,7 +2845,7 @@
 }
 
 
-LocationSummary* BoxFloat32x4Instr::MakeLocationSummary() const {
+LocationSummary* BoxFloat32x4Instr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -2712,7 +2911,7 @@
 }
 
 
-LocationSummary* UnboxFloat32x4Instr::MakeLocationSummary() const {
+LocationSummary* UnboxFloat32x4Instr::MakeLocationSummary(bool opt) const {
   const intptr_t value_cid = value()->Type()->ToCid();
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = value_cid == kFloat32x4Cid ? 0 : 1;
@@ -2751,7 +2950,7 @@
 }
 
 
-LocationSummary* BoxInt32x4Instr::MakeLocationSummary() const {
+LocationSummary* BoxInt32x4Instr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -2816,7 +3015,7 @@
 }
 
 
-LocationSummary* UnboxInt32x4Instr::MakeLocationSummary() const {
+LocationSummary* UnboxInt32x4Instr::MakeLocationSummary(bool opt) const {
   const intptr_t value_cid = value()->Type()->ToCid();
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = value_cid == kInt32x4Cid ? 0 : 1;
@@ -2855,7 +3054,7 @@
 }
 
 
-LocationSummary* BinaryDoubleOpInstr::MakeLocationSummary() const {
+LocationSummary* BinaryDoubleOpInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 2;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -2881,7 +3080,7 @@
 }
 
 
-LocationSummary* BinaryFloat32x4OpInstr::MakeLocationSummary() const {
+LocationSummary* BinaryFloat32x4OpInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 2;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -2908,7 +3107,7 @@
 }
 
 
-LocationSummary* Simd32x4ShuffleInstr::MakeLocationSummary() const {
+LocationSummary* Simd32x4ShuffleInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -2988,7 +3187,7 @@
 }
 
 
-LocationSummary* Simd32x4ShuffleMixInstr::MakeLocationSummary() const {
+LocationSummary* Simd32x4ShuffleMixInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 2;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -3044,7 +3243,7 @@
 }
 
 
-LocationSummary* Simd32x4GetSignMaskInstr::MakeLocationSummary() const {
+LocationSummary* Simd32x4GetSignMaskInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 1;
   LocationSummary* summary =
@@ -3084,7 +3283,8 @@
 }
 
 
-LocationSummary* Float32x4ConstructorInstr::MakeLocationSummary() const {
+LocationSummary* Float32x4ConstructorInstr::MakeLocationSummary(
+    bool opt) const {
   const intptr_t kNumInputs = 4;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -3116,7 +3316,7 @@
 }
 
 
-LocationSummary* Float32x4ZeroInstr::MakeLocationSummary() const {
+LocationSummary* Float32x4ZeroInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 0;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -3132,7 +3332,7 @@
 }
 
 
-LocationSummary* Float32x4SplatInstr::MakeLocationSummary() const {
+LocationSummary* Float32x4SplatInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -3157,7 +3357,7 @@
 }
 
 
-LocationSummary* Float32x4ComparisonInstr::MakeLocationSummary() const {
+LocationSummary* Float32x4ComparisonInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 2;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -3202,7 +3402,7 @@
 }
 
 
-LocationSummary* Float32x4MinMaxInstr::MakeLocationSummary() const {
+LocationSummary* Float32x4MinMaxInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 2;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -3231,7 +3431,7 @@
 }
 
 
-LocationSummary* Float32x4SqrtInstr::MakeLocationSummary() const {
+LocationSummary* Float32x4SqrtInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 1;
   LocationSummary* summary =
@@ -3263,7 +3463,7 @@
 }
 
 
-LocationSummary* Float32x4ScaleInstr::MakeLocationSummary() const {
+LocationSummary* Float32x4ScaleInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 2;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -3291,7 +3491,7 @@
 }
 
 
-LocationSummary* Float32x4ZeroArgInstr::MakeLocationSummary() const {
+LocationSummary* Float32x4ZeroArgInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -3318,7 +3518,7 @@
 }
 
 
-LocationSummary* Float32x4ClampInstr::MakeLocationSummary() const {
+LocationSummary* Float32x4ClampInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 3;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -3341,7 +3541,7 @@
 }
 
 
-LocationSummary* Float32x4WithInstr::MakeLocationSummary() const {
+LocationSummary* Float32x4WithInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 2;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -3389,7 +3589,7 @@
 }
 
 
-LocationSummary* Float32x4ToInt32x4Instr::MakeLocationSummary() const {
+LocationSummary* Float32x4ToInt32x4Instr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -3410,7 +3610,8 @@
 }
 
 
-LocationSummary* Int32x4BoolConstructorInstr::MakeLocationSummary() const {
+LocationSummary* Int32x4BoolConstructorInstr::MakeLocationSummary(
+    bool opt) const {
   const intptr_t kNumInputs = 4;
   const intptr_t kNumTemps = 1;
   LocationSummary* summary =
@@ -3457,7 +3658,7 @@
 }
 
 
-LocationSummary* Int32x4GetFlagInstr::MakeLocationSummary() const {
+LocationSummary* Int32x4GetFlagInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -3502,7 +3703,7 @@
 }
 
 
-LocationSummary* Int32x4SelectInstr::MakeLocationSummary() const {
+LocationSummary* Int32x4SelectInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 3;
   const intptr_t kNumTemps = 1;
   LocationSummary* summary =
@@ -3537,7 +3738,7 @@
 }
 
 
-LocationSummary* Int32x4SetFlagInstr::MakeLocationSummary() const {
+LocationSummary* Int32x4SetFlagInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 2;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -3587,7 +3788,7 @@
 }
 
 
-LocationSummary* Int32x4ToFloat32x4Instr::MakeLocationSummary() const {
+LocationSummary* Int32x4ToFloat32x4Instr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -3608,7 +3809,7 @@
 }
 
 
-LocationSummary* BinaryInt32x4OpInstr::MakeLocationSummary() const {
+LocationSummary* BinaryInt32x4OpInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 2;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -3648,7 +3849,7 @@
 }
 
 
-LocationSummary* MathUnaryInstr::MakeLocationSummary() const {
+LocationSummary* MathUnaryInstr::MakeLocationSummary(bool opt) const {
   if ((kind() == MethodRecognizer::kMathSin) ||
       (kind() == MethodRecognizer::kMathCos)) {
     const intptr_t kNumInputs = 1;
@@ -3698,7 +3899,7 @@
 }
 
 
-LocationSummary* MathMinMaxInstr::MakeLocationSummary() const {
+LocationSummary* MathMinMaxInstr::MakeLocationSummary(bool opt) const {
   if (result_cid() == kDoubleCid) {
     const intptr_t kNumInputs = 2;
     const intptr_t kNumTemps = 1;
@@ -3783,7 +3984,7 @@
 }
 
 
-LocationSummary* UnarySmiOpInstr::MakeLocationSummary() const {
+LocationSummary* UnarySmiOpInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -3818,7 +4019,7 @@
 }
 
 
-LocationSummary* UnaryDoubleOpInstr::MakeLocationSummary() const {
+LocationSummary* UnaryDoubleOpInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -3836,7 +4037,7 @@
 }
 
 
-LocationSummary* SmiToDoubleInstr::MakeLocationSummary() const {
+LocationSummary* SmiToDoubleInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* result =
@@ -3856,7 +4057,7 @@
 }
 
 
-LocationSummary* DoubleToIntegerInstr::MakeLocationSummary() const {
+LocationSummary* DoubleToIntegerInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* result =
@@ -3908,7 +4109,7 @@
 }
 
 
-LocationSummary* DoubleToSmiInstr::MakeLocationSummary() const {
+LocationSummary* DoubleToSmiInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* result = new LocationSummary(
@@ -3938,7 +4139,7 @@
 }
 
 
-LocationSummary* DoubleToDoubleInstr::MakeLocationSummary() const {
+LocationSummary* DoubleToDoubleInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* result =
@@ -3971,7 +4172,7 @@
 }
 
 
-LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary() const {
+LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary(bool opt) const {
   ASSERT((InputCount() == 1) || (InputCount() == 2));
   const intptr_t kNumTemps = 0;
   LocationSummary* result =
@@ -4055,7 +4256,7 @@
 }
 
 
-LocationSummary* MergedMathInstr::MakeLocationSummary() const {
+LocationSummary* MergedMathInstr::MakeLocationSummary(bool opt) const {
   if (kind() == MergedMathInstr::kTruncDivMod) {
     const intptr_t kNumInputs = 2;
     const intptr_t kNumTemps = 4;
@@ -4144,7 +4345,8 @@
 }
 
 
-LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary() const {
+LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary(
+    bool opt) const {
   return MakeCallSummary();
 }
 
@@ -4187,9 +4389,11 @@
 }
 
 
-LocationSummary* BranchInstr::MakeLocationSummary() const {
-  UNREACHABLE();
-  return NULL;
+LocationSummary* BranchInstr::MakeLocationSummary(bool opt) const {
+  comparison()->InitializeLocationSummary(opt);
+  // Branches don't produce a result.
+  comparison()->locs()->set_out(Location::NoLocation());
+  return comparison()->locs();
 }
 
 
@@ -4198,7 +4402,7 @@
 }
 
 
-LocationSummary* CheckClassInstr::MakeLocationSummary() const {
+LocationSummary* CheckClassInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -4252,7 +4456,7 @@
 }
 
 
-LocationSummary* CheckSmiInstr::MakeLocationSummary() const {
+LocationSummary* CheckSmiInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -4271,7 +4475,7 @@
 }
 
 
-LocationSummary* CheckArrayBoundInstr::MakeLocationSummary() const {
+LocationSummary* CheckArrayBoundInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 2;
   const intptr_t kNumTemps = 0;
   LocationSummary* locs =
@@ -4324,7 +4528,7 @@
 }
 
 
-LocationSummary* UnboxIntegerInstr::MakeLocationSummary() const {
+LocationSummary* UnboxIntegerInstr::MakeLocationSummary(bool opt) const {
   UNIMPLEMENTED();
   return NULL;
 }
@@ -4335,7 +4539,7 @@
 }
 
 
-LocationSummary* BoxIntegerInstr::MakeLocationSummary() const {
+LocationSummary* BoxIntegerInstr::MakeLocationSummary(bool opt) const {
   UNIMPLEMENTED();
   return NULL;
 }
@@ -4346,7 +4550,7 @@
 }
 
 
-LocationSummary* BinaryMintOpInstr::MakeLocationSummary() const {
+LocationSummary* BinaryMintOpInstr::MakeLocationSummary(bool opt) const {
   UNIMPLEMENTED();
   return NULL;
 }
@@ -4357,7 +4561,7 @@
 }
 
 
-LocationSummary* ShiftMintOpInstr::MakeLocationSummary() const {
+LocationSummary* ShiftMintOpInstr::MakeLocationSummary(bool opt) const {
   UNIMPLEMENTED();
   return NULL;
 }
@@ -4368,7 +4572,7 @@
 }
 
 
-LocationSummary* UnaryMintOpInstr::MakeLocationSummary() const {
+LocationSummary* UnaryMintOpInstr::MakeLocationSummary(bool opt) const {
   UNIMPLEMENTED();
   return NULL;
 }
@@ -4379,7 +4583,7 @@
 }
 
 
-LocationSummary* ThrowInstr::MakeLocationSummary() const {
+LocationSummary* ThrowInstr::MakeLocationSummary(bool opt) const {
   return new LocationSummary(0, 0, LocationSummary::kCall);
 }
 
@@ -4394,7 +4598,7 @@
 }
 
 
-LocationSummary* ReThrowInstr::MakeLocationSummary() const {
+LocationSummary* ReThrowInstr::MakeLocationSummary(bool opt) const {
   return new LocationSummary(0, 0, LocationSummary::kCall);
 }
 
@@ -4435,7 +4639,7 @@
 }
 
 
-LocationSummary* GotoInstr::MakeLocationSummary() const {
+LocationSummary* GotoInstr::MakeLocationSummary(bool opt) const {
   return new LocationSummary(0, 0, LocationSummary::kNoCall);
 }
 
@@ -4464,7 +4668,7 @@
 }
 
 
-LocationSummary* CurrentContextInstr::MakeLocationSummary() const {
+LocationSummary* CurrentContextInstr::MakeLocationSummary(bool opt) const {
   return LocationSummary::Make(0,
                                Location::RequiresRegister(),
                                LocationSummary::kNoCall);
@@ -4476,7 +4680,7 @@
 }
 
 
-LocationSummary* StrictCompareInstr::MakeLocationSummary() const {
+LocationSummary* StrictCompareInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 2;
   const intptr_t kNumTemps = 0;
   if (needs_number_check()) {
@@ -4549,7 +4753,7 @@
 }
 
 
-LocationSummary* BooleanNegateInstr::MakeLocationSummary() const {
+LocationSummary* BooleanNegateInstr::MakeLocationSummary(bool opt) const {
   return LocationSummary::Make(1,
                                Location::RequiresRegister(),
                                LocationSummary::kNoCall);
@@ -4566,7 +4770,7 @@
 }
 
 
-LocationSummary* StoreVMFieldInstr::MakeLocationSummary() const {
+LocationSummary* StoreVMFieldInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 2;
   const intptr_t kNumTemps = 0;
   LocationSummary* locs =
@@ -4592,7 +4796,7 @@
 }
 
 
-LocationSummary* AllocateObjectInstr::MakeLocationSummary() const {
+LocationSummary* AllocateObjectInstr::MakeLocationSummary(bool opt) const {
   return MakeCallSummary();
 }
 
@@ -4608,7 +4812,7 @@
 }
 
 
-LocationSummary* CreateClosureInstr::MakeLocationSummary() const {
+LocationSummary* CreateClosureInstr::MakeLocationSummary(bool opt) const {
   return MakeCallSummary();
 }
 
diff --git a/runtime/vm/intermediate_language_ia32.cc b/runtime/vm/intermediate_language_ia32.cc
index 8c9c9eb..46babb9 100644
--- a/runtime/vm/intermediate_language_ia32.cc
+++ b/runtime/vm/intermediate_language_ia32.cc
@@ -34,7 +34,7 @@
 }
 
 
-LocationSummary* PushArgumentInstr::MakeLocationSummary() const {
+LocationSummary* PushArgumentInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps= 0;
   LocationSummary* locs =
@@ -61,7 +61,7 @@
 }
 
 
-LocationSummary* ReturnInstr::MakeLocationSummary() const {
+LocationSummary* ReturnInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* locs =
@@ -108,7 +108,7 @@
 }
 
 
-LocationSummary* LoadLocalInstr::MakeLocationSummary() const {
+LocationSummary* LoadLocalInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 0;
   return LocationSummary::Make(kNumInputs,
                                Location::RequiresRegister(),
@@ -122,7 +122,7 @@
 }
 
 
-LocationSummary* StoreLocalInstr::MakeLocationSummary() const {
+LocationSummary* StoreLocalInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   return LocationSummary::Make(kNumInputs,
                                Location::SameAsFirstInput(),
@@ -138,7 +138,7 @@
 }
 
 
-LocationSummary* ConstantInstr::MakeLocationSummary() const {
+LocationSummary* ConstantInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 0;
   return LocationSummary::Make(kNumInputs,
                                Location::RequiresRegister(),
@@ -155,7 +155,7 @@
 }
 
 
-LocationSummary* AssertAssignableInstr::MakeLocationSummary() const {
+LocationSummary* AssertAssignableInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 3;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -168,7 +168,7 @@
 }
 
 
-LocationSummary* AssertBooleanInstr::MakeLocationSummary() const {
+LocationSummary* AssertBooleanInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* locs =
@@ -229,7 +229,7 @@
 }
 
 
-LocationSummary* EqualityCompareInstr::MakeLocationSummary() const {
+LocationSummary* EqualityCompareInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 2;
   if (operation_cid() == kMintCid) {
     const intptr_t kNumTemps = 1;
@@ -549,7 +549,7 @@
 }
 
 
-LocationSummary* TestSmiInstr::MakeLocationSummary() const {
+LocationSummary* TestSmiInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 2;
   const intptr_t kNumTemps = 0;
   LocationSummary* locs =
@@ -593,7 +593,7 @@
 }
 
 
-LocationSummary* RelationalOpInstr::MakeLocationSummary() const {
+LocationSummary* RelationalOpInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 2;
   const intptr_t kNumTemps = 0;
   if (operation_cid() == kMintCid) {
@@ -667,7 +667,7 @@
 }
 
 
-LocationSummary* NativeCallInstr::MakeLocationSummary() const {
+LocationSummary* NativeCallInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 0;
   const intptr_t kNumTemps = 3;
   LocationSummary* locs =
@@ -721,7 +721,7 @@
 }
 
 
-LocationSummary* StringFromCharCodeInstr::MakeLocationSummary() const {
+LocationSummary* StringFromCharCodeInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   // TODO(fschneider): Allow immediate operands for the char code.
   return LocationSummary::Make(kNumInputs,
@@ -742,7 +742,7 @@
 }
 
 
-LocationSummary* StringInterpolateInstr::MakeLocationSummary() const {
+LocationSummary* StringInterpolateInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -768,7 +768,7 @@
 }
 
 
-LocationSummary* LoadUntaggedInstr::MakeLocationSummary() const {
+LocationSummary* LoadUntaggedInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   return LocationSummary::Make(kNumInputs,
                                Location::RequiresRegister(),
@@ -783,7 +783,7 @@
 }
 
 
-LocationSummary* LoadClassIdInstr::MakeLocationSummary() const {
+LocationSummary* LoadClassIdInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   return LocationSummary::Make(kNumInputs,
                                Location::RequiresRegister(),
@@ -879,7 +879,7 @@
 }
 
 
-LocationSummary* LoadIndexedInstr::MakeLocationSummary() const {
+LocationSummary* LoadIndexedInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 2;
   const intptr_t kNumTemps = 0;
   LocationSummary* locs =
@@ -1048,7 +1048,7 @@
 }
 
 
-LocationSummary* StoreIndexedInstr::MakeLocationSummary() const {
+LocationSummary* StoreIndexedInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 3;
   const intptr_t kNumTemps = 0;
   LocationSummary* locs =
@@ -1232,7 +1232,7 @@
 }
 
 
-LocationSummary* GuardFieldInstr::MakeLocationSummary() const {
+LocationSummary* GuardFieldInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   LocationSummary* summary =
       new LocationSummary(kNumInputs, 0, LocationSummary::kNoCall);
@@ -1581,21 +1581,150 @@
 }
 
 
-LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary() const {
+class StoreInstanceFieldSlowPath : public SlowPathCode {
+ public:
+  explicit StoreInstanceFieldSlowPath(StoreInstanceFieldInstr* instruction)
+      : instruction_(instruction) { }
+
+  virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
+    __ Comment("StoreInstanceFieldSlowPath");
+    __ Bind(entry_label());
+    const Class& double_class = compiler->double_class();
+    const Code& stub =
+        Code::Handle(StubCode::GetAllocationStubForClass(double_class));
+    const ExternalLabel label(double_class.ToCString(), stub.EntryPoint());
+
+    LocationSummary* locs = instruction_->locs();
+    locs->live_registers()->Remove(locs->out());
+
+    compiler->SaveLiveRegisters(locs);
+    compiler->GenerateCall(Scanner::kDummyTokenIndex,  // No token position.
+                           &label,
+                           PcDescriptors::kOther,
+                           locs);
+    __ MoveRegister(locs->temp(0).reg(), EAX);
+    compiler->RestoreLiveRegisters(locs);
+
+    __ jmp(exit_label());
+  }
+
+ private:
+  StoreInstanceFieldInstr* instruction_;
+};
+
+
+LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 2;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
-      new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
+      new LocationSummary(kNumInputs, kNumTemps,
+          (field().guarded_cid() == kIllegalCid) || (is_initialization_)
+          ? LocationSummary::kCallOnSlowPath
+          : LocationSummary::kNoCall);
+
   summary->set_in(0, Location::RequiresRegister());
-  summary->set_in(1, ShouldEmitStoreBarrier()
+  if (IsUnboxedStore() && opt) {
+    summary->set_in(1, Location::RequiresFpuRegister());
+    summary->AddTemp(Location::RequiresRegister());
+    summary->AddTemp(Location::RequiresRegister());
+  } else if (IsPotentialUnboxedStore()) {
+    summary->set_in(1, ShouldEmitStoreBarrier()
+        ? Location::WritableRegister()
+        :  Location::RequiresRegister());
+    summary->AddTemp(Location::RequiresRegister());
+    summary->AddTemp(Location::RequiresRegister());
+    summary->AddTemp(opt ? Location::RequiresFpuRegister()
+                         : Location::FpuRegisterLocation(XMM1));
+  } else {
+    summary->set_in(1, ShouldEmitStoreBarrier()
                        ? Location::WritableRegister()
                        : Location::RegisterOrConstant(value()));
+  }
   return summary;
 }
 
 
 void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  Label skip_store;
+
   Register instance_reg = locs()->in(0).reg();
+
+  if (IsUnboxedStore() && compiler->is_optimizing()) {
+    XmmRegister value = locs()->in(1).fpu_reg();
+    Register temp = locs()->temp(0).reg();
+    Register temp2 = locs()->temp(1).reg();
+
+    if (is_initialization_) {
+      StoreInstanceFieldSlowPath* slow_path =
+          new StoreInstanceFieldSlowPath(this);
+      compiler->AddSlowPathCode(slow_path);
+
+      __ TryAllocate(compiler->double_class(),
+                     slow_path->entry_label(),
+                     Assembler::kFarJump,
+                     temp);
+      __ Bind(slow_path->exit_label());
+      __ movl(temp2, temp);
+      __ StoreIntoObject(instance_reg,
+                         FieldAddress(instance_reg, field().Offset()),
+                         temp2);
+    } else {
+      __ movl(temp, FieldAddress(instance_reg, field().Offset()));
+    }
+    __ movsd(FieldAddress(temp, Double::value_offset()), value);
+    return;
+  }
+
+  if (IsPotentialUnboxedStore()) {
+    Register value_reg = locs()->in(1).reg();
+    Register temp = locs()->temp(0).reg();
+    Register temp2 = locs()->temp(1).reg();
+    FpuRegister fpu_temp = locs()->temp(2).fpu_reg();
+
+    Label store_pointer, copy_payload;
+    __ LoadObject(temp, Field::ZoneHandle(field().raw()));
+    __ cmpl(FieldAddress(temp, Field::guarded_cid_offset()),
+            Immediate(kDoubleCid));
+    __ j(NOT_EQUAL, &store_pointer);
+    __ cmpl(FieldAddress(temp, Field::is_nullable_offset()),
+            Immediate(kNullCid));
+    __ j(EQUAL, &store_pointer);
+    __ movzxb(temp2, FieldAddress(temp, Field::kind_bits_offset()));
+    __ testl(temp2, Immediate(1 << Field::kUnboxingCandidateBit));
+    __ j(ZERO, &store_pointer);
+
+    const Immediate& raw_null =
+        Immediate(reinterpret_cast<intptr_t>(Object::null()));
+    __ movl(temp, FieldAddress(instance_reg, field().Offset()));
+    __ cmpl(temp, raw_null);
+    __ j(NOT_EQUAL, &copy_payload);
+
+    StoreInstanceFieldSlowPath* slow_path =
+        new StoreInstanceFieldSlowPath(this);
+    compiler->AddSlowPathCode(slow_path);
+
+    if (!compiler->is_optimizing()) {
+      locs()->live_registers()->Add(locs()->in(0));
+      locs()->live_registers()->Add(locs()->in(1));
+    }
+
+    __ TryAllocate(compiler->double_class(),
+                   slow_path->entry_label(),
+                   Assembler::kFarJump,
+                   temp);
+    __ Bind(slow_path->exit_label());
+    __ movl(temp2, temp);
+    __ StoreIntoObject(instance_reg,
+                       FieldAddress(instance_reg, field().Offset()),
+                       temp2);
+
+    __ Bind(&copy_payload);
+    __ movsd(fpu_temp, FieldAddress(value_reg, Double::value_offset()));
+    __ movsd(FieldAddress(temp, Double::value_offset()), fpu_temp);
+    __ jmp(&skip_store);
+    __ Bind(&store_pointer);
+  }
+
   if (ShouldEmitStoreBarrier()) {
     Register value_reg = locs()->in(1).reg();
     __ StoreIntoObject(instance_reg,
@@ -1614,10 +1743,11 @@
           FieldAddress(instance_reg, field().Offset()), value_reg);
     }
   }
+  __ Bind(&skip_store);
 }
 
 
-LocationSummary* LoadStaticFieldInstr::MakeLocationSummary() const {
+LocationSummary* LoadStaticFieldInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -1642,7 +1772,7 @@
 }
 
 
-LocationSummary* StoreStaticFieldInstr::MakeLocationSummary() const {
+LocationSummary* StoreStaticFieldInstr::MakeLocationSummary(bool opt) const {
   LocationSummary* locs = new LocationSummary(1, 1, LocationSummary::kNoCall);
   locs->set_in(0, value()->NeedsStoreBuffer() ? Location::WritableRegister()
                                               : Location::RequiresRegister());
@@ -1666,7 +1796,7 @@
 }
 
 
-LocationSummary* InstanceOfInstr::MakeLocationSummary() const {
+LocationSummary* InstanceOfInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 3;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -1693,7 +1823,7 @@
 }
 
 
-LocationSummary* CreateArrayInstr::MakeLocationSummary() const {
+LocationSummary* CreateArrayInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* locs =
@@ -1717,7 +1847,7 @@
 
 
 LocationSummary*
-AllocateObjectWithBoundsCheckInstr::MakeLocationSummary() const {
+AllocateObjectWithBoundsCheckInstr::MakeLocationSummary(bool opt) const {
   return MakeCallSummary();
 }
 
@@ -1735,22 +1865,114 @@
 }
 
 
-LocationSummary* LoadFieldInstr::MakeLocationSummary() const {
-  return LocationSummary::Make(1,
-                               Location::RequiresRegister(),
-                               LocationSummary::kNoCall);
+class BoxDoubleSlowPath : public SlowPathCode {
+ public:
+  explicit BoxDoubleSlowPath(Instruction* instruction)
+      : instruction_(instruction) { }
+
+  virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
+    __ Comment("BoxDoubleSlowPath");
+    __ Bind(entry_label());
+    const Class& double_class = compiler->double_class();
+    const Code& stub =
+        Code::Handle(StubCode::GetAllocationStubForClass(double_class));
+    const ExternalLabel label(double_class.ToCString(), stub.EntryPoint());
+
+    LocationSummary* locs = instruction_->locs();
+    locs->live_registers()->Remove(locs->out());
+
+    compiler->SaveLiveRegisters(locs);
+    compiler->GenerateCall(Scanner::kDummyTokenIndex,  // No token position.
+                           &label,
+                           PcDescriptors::kOther,
+                           locs);
+    __ MoveRegister(locs->out().reg(), EAX);
+    compiler->RestoreLiveRegisters(locs);
+
+    __ jmp(exit_label());
+  }
+
+ private:
+  Instruction* instruction_;
+};
+
+
+LocationSummary* LoadFieldInstr::MakeLocationSummary(bool opt) const {
+  const intptr_t kNumInputs = 1;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* locs =
+      new LocationSummary(
+          kNumInputs, kNumTemps,
+          (opt && !IsPotentialUnboxedLoad())
+          ? LocationSummary::kNoCall
+          : LocationSummary::kCallOnSlowPath);
+
+  locs->set_in(0, Location::RequiresRegister());
+
+  if (IsUnboxedLoad() && opt) {
+    locs->AddTemp(Location::RequiresRegister());
+  } else if (IsPotentialUnboxedLoad()) {
+    locs->AddTemp(opt ? Location::RequiresFpuRegister()
+                      : Location::FpuRegisterLocation(XMM1));
+    locs->AddTemp(Location::RequiresRegister());
+  }
+  locs->set_out(Location::RequiresRegister());
+  return locs;
 }
 
 
 void LoadFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   Register instance_reg = locs()->in(0).reg();
-  Register result_reg = locs()->out().reg();
+  if (IsUnboxedLoad() && compiler->is_optimizing()) {
+    XmmRegister result = locs()->out().fpu_reg();
+    Register temp = locs()->temp(0).reg();
+    __ movl(temp, FieldAddress(instance_reg, offset_in_bytes()));
+    __ movsd(result, FieldAddress(temp, Double::value_offset()));
+    return;
+  }
 
-  __ movl(result_reg, FieldAddress(instance_reg, offset_in_bytes()));
+  Label done;
+  Register result = locs()->out().reg();
+  if (IsPotentialUnboxedLoad()) {
+    Register temp = locs()->temp(1).reg();
+    XmmRegister value = locs()->temp(0).fpu_reg();
+
+    Label load_pointer;
+    __ LoadObject(result, Field::ZoneHandle(field()->raw()));
+
+    FieldAddress field_cid_operand(result, Field::guarded_cid_offset());
+    FieldAddress field_nullability_operand(result, Field::is_nullable_offset());
+
+    __ cmpl(field_cid_operand, Immediate(kDoubleCid));
+    __ j(NOT_EQUAL, &load_pointer);
+
+    __ cmpl(field_nullability_operand, Immediate(kNullCid));
+    __ j(EQUAL, &load_pointer);
+
+    BoxDoubleSlowPath* slow_path = new BoxDoubleSlowPath(this);
+    compiler->AddSlowPathCode(slow_path);
+
+    if (!compiler->is_optimizing()) {
+      locs()->live_registers()->Add(locs()->in(0));
+    }
+
+    __ TryAllocate(compiler->double_class(),
+                   slow_path->entry_label(),
+                   Assembler::kFarJump,
+                   result);
+    __ Bind(slow_path->exit_label());
+    __ movl(temp, FieldAddress(instance_reg, offset_in_bytes()));
+    __ movsd(value, FieldAddress(temp, Double::value_offset()));
+    __ movsd(FieldAddress(result, Double::value_offset()), value);
+    __ jmp(&done);
+    __ Bind(&load_pointer);
+  }
+  __ movl(result, FieldAddress(instance_reg, offset_in_bytes()));
+  __ Bind(&done);
 }
 
 
-LocationSummary* InstantiateTypeInstr::MakeLocationSummary() const {
+LocationSummary* InstantiateTypeInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* locs =
@@ -1782,7 +2004,8 @@
 }
 
 
-LocationSummary* InstantiateTypeArgumentsInstr::MakeLocationSummary() const {
+LocationSummary* InstantiateTypeArgumentsInstr::MakeLocationSummary(
+    bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* locs =
@@ -1832,7 +2055,7 @@
 
 
 LocationSummary*
-ExtractConstructorTypeArgumentsInstr::MakeLocationSummary() const {
+ExtractConstructorTypeArgumentsInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* locs =
@@ -1875,7 +2098,7 @@
 
 
 LocationSummary*
-ExtractConstructorInstantiatorInstr::MakeLocationSummary() const {
+ExtractConstructorInstantiatorInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* locs =
@@ -1915,7 +2138,7 @@
 }
 
 
-LocationSummary* AllocateContextInstr::MakeLocationSummary() const {
+LocationSummary* AllocateContextInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 0;
   const intptr_t kNumTemps = 1;
   LocationSummary* locs =
@@ -1940,7 +2163,7 @@
 }
 
 
-LocationSummary* CloneContextInstr::MakeLocationSummary() const {
+LocationSummary* CloneContextInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* locs =
@@ -1967,7 +2190,7 @@
 }
 
 
-LocationSummary* CatchBlockEntryInstr::MakeLocationSummary() const {
+LocationSummary* CatchBlockEntryInstr::MakeLocationSummary(bool opt) const {
   UNREACHABLE();
   return NULL;
 }
@@ -2000,7 +2223,7 @@
 }
 
 
-LocationSummary* CheckStackOverflowInstr::MakeLocationSummary() const {
+LocationSummary* CheckStackOverflowInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 0;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -2190,7 +2413,7 @@
 }
 
 
-LocationSummary* BinarySmiOpInstr::MakeLocationSummary() const {
+LocationSummary* BinarySmiOpInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 2;
   if (op_kind() == Token::kTRUNCDIV) {
     const intptr_t kNumTemps = 1;
@@ -2560,7 +2783,7 @@
 }
 
 
-LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary() const {
+LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary(bool opt) const {
   intptr_t left_cid = left()->Type()->ToCid();
   intptr_t right_cid = right()->Type()->ToCid();
   ASSERT((left_cid != kDoubleCid) && (right_cid != kDoubleCid));
@@ -2596,7 +2819,7 @@
 }
 
 
-LocationSummary* BoxDoubleInstr::MakeLocationSummary() const {
+LocationSummary* BoxDoubleInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -2609,38 +2832,6 @@
 }
 
 
-class BoxDoubleSlowPath : public SlowPathCode {
- public:
-  explicit BoxDoubleSlowPath(BoxDoubleInstr* instruction)
-      : instruction_(instruction) { }
-
-  virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
-    __ Comment("BoxDoubleSlowPath");
-    __ Bind(entry_label());
-    const Class& double_class = compiler->double_class();
-    const Code& stub =
-        Code::Handle(StubCode::GetAllocationStubForClass(double_class));
-    const ExternalLabel label(double_class.ToCString(), stub.EntryPoint());
-
-    LocationSummary* locs = instruction_->locs();
-    locs->live_registers()->Remove(locs->out());
-
-    compiler->SaveLiveRegisters(locs);
-    compiler->GenerateCall(Scanner::kDummyTokenIndex,  // No token position.
-                           &label,
-                           PcDescriptors::kOther,
-                           locs);
-    __ MoveRegister(locs->out().reg(), EAX);
-    compiler->RestoreLiveRegisters(locs);
-
-    __ jmp(exit_label());
-  }
-
- private:
-  BoxDoubleInstr* instruction_;
-};
-
-
 void BoxDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   BoxDoubleSlowPath* slow_path = new BoxDoubleSlowPath(this);
   compiler->AddSlowPathCode(slow_path);
@@ -2657,7 +2848,7 @@
 }
 
 
-LocationSummary* UnboxDoubleInstr::MakeLocationSummary() const {
+LocationSummary* UnboxDoubleInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t value_cid = value()->Type()->ToCid();
   const bool needs_temp = ((value_cid != kSmiCid) && (value_cid != kDoubleCid));
@@ -2703,7 +2894,7 @@
 }
 
 
-LocationSummary* BoxFloat32x4Instr::MakeLocationSummary() const {
+LocationSummary* BoxFloat32x4Instr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -2764,7 +2955,7 @@
 }
 
 
-LocationSummary* UnboxFloat32x4Instr::MakeLocationSummary() const {
+LocationSummary* UnboxFloat32x4Instr::MakeLocationSummary(bool opt) const {
   const intptr_t value_cid = value()->Type()->ToCid();
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = value_cid == kFloat32x4Cid ? 0 : 1;
@@ -2797,7 +2988,7 @@
 }
 
 
-LocationSummary* BoxInt32x4Instr::MakeLocationSummary() const {
+LocationSummary* BoxInt32x4Instr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -2858,7 +3049,7 @@
 }
 
 
-LocationSummary* UnboxInt32x4Instr::MakeLocationSummary() const {
+LocationSummary* UnboxInt32x4Instr::MakeLocationSummary(bool opt) const {
   const intptr_t value_cid = value()->Type()->ToCid();
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = value_cid == kInt32x4Cid ? 0 : 1;
@@ -2892,7 +3083,7 @@
 
 
 
-LocationSummary* BinaryDoubleOpInstr::MakeLocationSummary() const {
+LocationSummary* BinaryDoubleOpInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 2;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -2920,7 +3111,7 @@
 }
 
 
-LocationSummary* BinaryFloat32x4OpInstr::MakeLocationSummary() const {
+LocationSummary* BinaryFloat32x4OpInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 2;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -2948,7 +3139,7 @@
 }
 
 
-LocationSummary* Simd32x4ShuffleInstr::MakeLocationSummary() const {
+LocationSummary* Simd32x4ShuffleInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -2990,7 +3181,7 @@
 }
 
 
-LocationSummary* Simd32x4ShuffleMixInstr::MakeLocationSummary() const {
+LocationSummary* Simd32x4ShuffleMixInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 2;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -3017,7 +3208,7 @@
 }
 
 
-LocationSummary* Simd32x4GetSignMaskInstr::MakeLocationSummary() const {
+LocationSummary* Simd32x4GetSignMaskInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -3037,7 +3228,8 @@
 }
 
 
-LocationSummary* Float32x4ConstructorInstr::MakeLocationSummary() const {
+LocationSummary* Float32x4ConstructorInstr::MakeLocationSummary(
+    bool opt) const {
   const intptr_t kNumInputs = 4;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -3074,7 +3266,7 @@
 }
 
 
-LocationSummary* Float32x4ZeroInstr::MakeLocationSummary() const {
+LocationSummary* Float32x4ZeroInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 0;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -3090,7 +3282,7 @@
 }
 
 
-LocationSummary* Float32x4SplatInstr::MakeLocationSummary() const {
+LocationSummary* Float32x4SplatInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -3111,7 +3303,7 @@
 }
 
 
-LocationSummary* Float32x4ComparisonInstr::MakeLocationSummary() const {
+LocationSummary* Float32x4ComparisonInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 2;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -3154,7 +3346,7 @@
 }
 
 
-LocationSummary* Float32x4MinMaxInstr::MakeLocationSummary() const {
+LocationSummary* Float32x4MinMaxInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 2;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -3184,7 +3376,7 @@
 }
 
 
-LocationSummary* Float32x4ScaleInstr::MakeLocationSummary() const {
+LocationSummary* Float32x4ScaleInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 2;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -3213,7 +3405,7 @@
 }
 
 
-LocationSummary* Float32x4SqrtInstr::MakeLocationSummary() const {
+LocationSummary* Float32x4SqrtInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -3244,7 +3436,7 @@
 }
 
 
-LocationSummary* Float32x4ZeroArgInstr::MakeLocationSummary() const {
+LocationSummary* Float32x4ZeroArgInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -3271,7 +3463,7 @@
 }
 
 
-LocationSummary* Float32x4ClampInstr::MakeLocationSummary() const {
+LocationSummary* Float32x4ClampInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 3;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -3294,7 +3486,7 @@
 }
 
 
-LocationSummary* Float32x4WithInstr::MakeLocationSummary() const {
+LocationSummary* Float32x4WithInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 2;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -3362,7 +3554,7 @@
 }
 
 
-LocationSummary* Float32x4ToInt32x4Instr::MakeLocationSummary() const {
+LocationSummary* Float32x4ToInt32x4Instr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -3378,7 +3570,8 @@
 }
 
 
-LocationSummary* Int32x4BoolConstructorInstr::MakeLocationSummary() const {
+LocationSummary* Int32x4BoolConstructorInstr::MakeLocationSummary(
+    bool opt) const {
   const intptr_t kNumInputs = 4;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -3440,7 +3633,7 @@
 }
 
 
-LocationSummary* Int32x4GetFlagInstr::MakeLocationSummary() const {
+LocationSummary* Int32x4GetFlagInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -3485,7 +3678,7 @@
 }
 
 
-LocationSummary* Int32x4SelectInstr::MakeLocationSummary() const {
+LocationSummary* Int32x4SelectInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 3;
   const intptr_t kNumTemps = 1;
   LocationSummary* summary =
@@ -3519,7 +3712,7 @@
 }
 
 
-LocationSummary* Int32x4SetFlagInstr::MakeLocationSummary() const {
+LocationSummary* Int32x4SetFlagInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 2;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -3575,7 +3768,7 @@
 }
 
 
-LocationSummary* Int32x4ToFloat32x4Instr::MakeLocationSummary() const {
+LocationSummary* Int32x4ToFloat32x4Instr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -3591,7 +3784,7 @@
 }
 
 
-LocationSummary* BinaryInt32x4OpInstr::MakeLocationSummary() const {
+LocationSummary* BinaryInt32x4OpInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 2;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -3631,7 +3824,7 @@
 }
 
 
-LocationSummary* MathUnaryInstr::MakeLocationSummary() const {
+LocationSummary* MathUnaryInstr::MakeLocationSummary(bool opt) const {
   if ((kind() == MethodRecognizer::kMathSin) ||
       (kind() == MethodRecognizer::kMathCos)) {
     const intptr_t kNumInputs = 1;
@@ -3667,7 +3860,7 @@
 }
 
 
-LocationSummary* MathMinMaxInstr::MakeLocationSummary() const {
+LocationSummary* MathMinMaxInstr::MakeLocationSummary(bool opt) const {
   if (result_cid() == kDoubleCid) {
     const intptr_t kNumInputs = 2;
     const intptr_t kNumTemps = 1;
@@ -3755,7 +3948,7 @@
 }
 
 
-LocationSummary* UnarySmiOpInstr::MakeLocationSummary() const {
+LocationSummary* UnarySmiOpInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   return LocationSummary::Make(kNumInputs,
                                Location::SameAsFirstInput(),
@@ -3784,7 +3977,7 @@
 }
 
 
-LocationSummary* UnaryDoubleOpInstr::MakeLocationSummary() const {
+LocationSummary* UnaryDoubleOpInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -3802,7 +3995,7 @@
 }
 
 
-LocationSummary* SmiToDoubleInstr::MakeLocationSummary() const {
+LocationSummary* SmiToDoubleInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* result =
@@ -3821,7 +4014,7 @@
 }
 
 
-LocationSummary* DoubleToIntegerInstr::MakeLocationSummary() const {
+LocationSummary* DoubleToIntegerInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* result =
@@ -3865,7 +4058,7 @@
 }
 
 
-LocationSummary* DoubleToSmiInstr::MakeLocationSummary() const {
+LocationSummary* DoubleToSmiInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* result = new LocationSummary(
@@ -3888,7 +4081,7 @@
 }
 
 
-LocationSummary* DoubleToDoubleInstr::MakeLocationSummary() const {
+LocationSummary* DoubleToDoubleInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* result =
@@ -3918,7 +4111,7 @@
 }
 
 
-LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary() const {
+LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary(bool opt) const {
   ASSERT((InputCount() == 1) || (InputCount() == 2));
   const intptr_t kNumTemps = 0;
   LocationSummary* result =
@@ -3989,7 +4182,7 @@
 }
 
 
-LocationSummary* MergedMathInstr::MakeLocationSummary() const {
+LocationSummary* MergedMathInstr::MakeLocationSummary(bool opt) const {
   if (kind() == MergedMathInstr::kTruncDivMod) {
     const intptr_t kNumInputs = 2;
     const intptr_t kNumTemps = 1;
@@ -4139,7 +4332,8 @@
 }
 
 
-LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary() const {
+LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary(
+    bool opt) const {
   return MakeCallSummary();
 }
 
@@ -4182,9 +4376,11 @@
 }
 
 
-LocationSummary* BranchInstr::MakeLocationSummary() const {
-  UNREACHABLE();
-  return NULL;
+LocationSummary* BranchInstr::MakeLocationSummary(bool opt) const {
+  comparison()->InitializeLocationSummary(opt);
+  // Branches don't produce a result.
+  comparison()->locs()->set_out(Location::NoLocation());
+  return comparison()->locs();
 }
 
 
@@ -4193,7 +4389,7 @@
 }
 
 
-LocationSummary* CheckClassInstr::MakeLocationSummary() const {
+LocationSummary* CheckClassInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -4253,7 +4449,7 @@
 }
 
 
-LocationSummary* CheckSmiInstr::MakeLocationSummary() const {
+LocationSummary* CheckSmiInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -4272,7 +4468,7 @@
 }
 
 
-LocationSummary* CheckArrayBoundInstr::MakeLocationSummary() const {
+LocationSummary* CheckArrayBoundInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 2;
   const intptr_t kNumTemps = 0;
   LocationSummary* locs =
@@ -4325,7 +4521,7 @@
 }
 
 
-LocationSummary* UnboxIntegerInstr::MakeLocationSummary() const {
+LocationSummary* UnboxIntegerInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t value_cid = value()->Type()->ToCid();
   const bool needs_temp = ((value_cid != kSmiCid) && (value_cid != kMintCid));
@@ -4373,7 +4569,7 @@
 }
 
 
-LocationSummary* BoxIntegerInstr::MakeLocationSummary() const {
+LocationSummary* BoxIntegerInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 2;
   LocationSummary* summary =
@@ -4461,7 +4657,7 @@
 }
 
 
-LocationSummary* BinaryMintOpInstr::MakeLocationSummary() const {
+LocationSummary* BinaryMintOpInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 2;
   switch (op_kind()) {
     case Token::kBIT_AND:
@@ -4551,7 +4747,7 @@
 }
 
 
-LocationSummary* ShiftMintOpInstr::MakeLocationSummary() const {
+LocationSummary* ShiftMintOpInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 2;
   const intptr_t kNumTemps = op_kind() == Token::kSHL ? 2 : 1;
   LocationSummary* summary =
@@ -4625,7 +4821,7 @@
 }
 
 
-LocationSummary* UnaryMintOpInstr::MakeLocationSummary() const {
+LocationSummary* UnaryMintOpInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps =
       FLAG_throw_on_javascript_int_overflow ? 1 : 0;
@@ -4658,7 +4854,7 @@
 }
 
 
-LocationSummary* ThrowInstr::MakeLocationSummary() const {
+LocationSummary* ThrowInstr::MakeLocationSummary(bool opt) const {
   return new LocationSummary(0, 0, LocationSummary::kCall);
 }
 
@@ -4674,7 +4870,7 @@
 }
 
 
-LocationSummary* ReThrowInstr::MakeLocationSummary() const {
+LocationSummary* ReThrowInstr::MakeLocationSummary(bool opt) const {
   return new LocationSummary(0, 0, LocationSummary::kCall);
 }
 
@@ -4714,7 +4910,7 @@
 }
 
 
-LocationSummary* GotoInstr::MakeLocationSummary() const {
+LocationSummary* GotoInstr::MakeLocationSummary(bool opt) const {
   return new LocationSummary(0, 0, LocationSummary::kNoCall);
 }
 
@@ -4743,7 +4939,7 @@
 }
 
 
-LocationSummary* CurrentContextInstr::MakeLocationSummary() const {
+LocationSummary* CurrentContextInstr::MakeLocationSummary(bool opt) const {
   return LocationSummary::Make(0,
                                Location::RequiresRegister(),
                                LocationSummary::kNoCall);
@@ -4755,7 +4951,7 @@
 }
 
 
-LocationSummary* StrictCompareInstr::MakeLocationSummary() const {
+LocationSummary* StrictCompareInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 2;
   const intptr_t kNumTemps = 0;
   if (needs_number_check()) {
@@ -4841,11 +5037,11 @@
 }
 
 
-LocationSummary* IfThenElseInstr::MakeLocationSummary() const {
-  LocationSummary* locs = comparison()->MakeLocationSummary();
+LocationSummary* IfThenElseInstr::MakeLocationSummary(bool opt) const {
+  comparison()->InitializeLocationSummary(opt);
   // TODO(vegorov): support byte register constraints in the register allocator.
-  locs->set_out(Location::RegisterLocation(EDX));
-  return locs;
+  comparison()->locs()->set_out(Location::RegisterLocation(EDX));
+  return comparison()->locs();
 }
 
 
@@ -4898,7 +5094,7 @@
 }
 
 
-LocationSummary* ClosureCallInstr::MakeLocationSummary() const {
+LocationSummary* ClosureCallInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 0;
   const intptr_t kNumTemps = 1;
   LocationSummary* result =
@@ -4928,7 +5124,7 @@
 }
 
 
-LocationSummary* BooleanNegateInstr::MakeLocationSummary() const {
+LocationSummary* BooleanNegateInstr::MakeLocationSummary(bool opt) const {
   return LocationSummary::Make(1,
                                Location::RequiresRegister(),
                                LocationSummary::kNoCall);
@@ -4948,7 +5144,7 @@
 }
 
 
-LocationSummary* StoreVMFieldInstr::MakeLocationSummary() const {
+LocationSummary* StoreVMFieldInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 2;
   const intptr_t kNumTemps = 0;
   LocationSummary* locs =
@@ -4974,7 +5170,7 @@
 }
 
 
-LocationSummary* AllocateObjectInstr::MakeLocationSummary() const {
+LocationSummary* AllocateObjectInstr::MakeLocationSummary(bool opt) const {
   return MakeCallSummary();
 }
 
@@ -4990,7 +5186,7 @@
 }
 
 
-LocationSummary* CreateClosureInstr::MakeLocationSummary() const {
+LocationSummary* CreateClosureInstr::MakeLocationSummary(bool opt) const {
   return MakeCallSummary();
 }
 
diff --git a/runtime/vm/intermediate_language_mips.cc b/runtime/vm/intermediate_language_mips.cc
index 07ac406..3473a36 100644
--- a/runtime/vm/intermediate_language_mips.cc
+++ b/runtime/vm/intermediate_language_mips.cc
@@ -34,7 +34,7 @@
 }
 
 
-LocationSummary* PushArgumentInstr::MakeLocationSummary() const {
+LocationSummary* PushArgumentInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps= 0;
   LocationSummary* locs =
@@ -64,7 +64,7 @@
 }
 
 
-LocationSummary* ReturnInstr::MakeLocationSummary() const {
+LocationSummary* ReturnInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* locs =
@@ -134,8 +134,9 @@
 }
 
 
-LocationSummary* IfThenElseInstr::MakeLocationSummary() const {
-  return comparison()->MakeLocationSummary();
+LocationSummary* IfThenElseInstr::MakeLocationSummary(bool opt) const {
+  comparison()->InitializeLocationSummary(opt);
+  return comparison()->locs();
 }
 
 
@@ -215,7 +216,7 @@
 }
 
 
-LocationSummary* ClosureCallInstr::MakeLocationSummary() const {
+LocationSummary* ClosureCallInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 0;
   const intptr_t kNumTemps = 1;
   LocationSummary* result =
@@ -245,7 +246,7 @@
 }
 
 
-LocationSummary* LoadLocalInstr::MakeLocationSummary() const {
+LocationSummary* LoadLocalInstr::MakeLocationSummary(bool opt) const {
   return LocationSummary::Make(0,
                                Location::RequiresRegister(),
                                LocationSummary::kNoCall);
@@ -259,7 +260,7 @@
 }
 
 
-LocationSummary* StoreLocalInstr::MakeLocationSummary() const {
+LocationSummary* StoreLocalInstr::MakeLocationSummary(bool opt) const {
   return LocationSummary::Make(1,
                                Location::SameAsFirstInput(),
                                LocationSummary::kNoCall);
@@ -275,7 +276,7 @@
 }
 
 
-LocationSummary* ConstantInstr::MakeLocationSummary() const {
+LocationSummary* ConstantInstr::MakeLocationSummary(bool opt) const {
   return LocationSummary::Make(0,
                                Location::RequiresRegister(),
                                LocationSummary::kNoCall);
@@ -292,7 +293,7 @@
 }
 
 
-LocationSummary* AssertAssignableInstr::MakeLocationSummary() const {
+LocationSummary* AssertAssignableInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 3;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -305,7 +306,7 @@
 }
 
 
-LocationSummary* AssertBooleanInstr::MakeLocationSummary() const {
+LocationSummary* AssertBooleanInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* locs =
@@ -350,7 +351,7 @@
 }
 
 
-LocationSummary* EqualityCompareInstr::MakeLocationSummary() const {
+LocationSummary* EqualityCompareInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 2;
   if (operation_cid() == kMintCid) {
     const intptr_t kNumTemps = 1;
@@ -602,7 +603,7 @@
 }
 
 
-LocationSummary* TestSmiInstr::MakeLocationSummary() const {
+LocationSummary* TestSmiInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 2;
   const intptr_t kNumTemps = 0;
   LocationSummary* locs =
@@ -647,7 +648,7 @@
 }
 
 
-LocationSummary* RelationalOpInstr::MakeLocationSummary() const {
+LocationSummary* RelationalOpInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 2;
   const intptr_t kNumTemps = 0;
   if (operation_cid() == kMintCid) {
@@ -723,7 +724,7 @@
 }
 
 
-LocationSummary* NativeCallInstr::MakeLocationSummary() const {
+LocationSummary* NativeCallInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 0;
   const intptr_t kNumTemps = 3;
   LocationSummary* locs =
@@ -768,6 +769,12 @@
     // stub generates the redirection address when running under the simulator
     // and hence we do not change 'entry' here.
     stub_entry = &StubCode::CallNativeCFunctionLabel();
+#if defined(USING_SIMULATOR)
+    if (!function().IsNativeAutoSetupScope()) {
+      entry = Simulator::RedirectExternalReference(
+          entry, Simulator::kBootstrapNativeCall, function().NumParameters());
+    }
+#endif
   }
   __ LoadImmediate(T5, entry);
   __ LoadImmediate(A1, NativeArguments::ComputeArgcTag(function()));
@@ -779,7 +786,7 @@
 }
 
 
-LocationSummary* StringFromCharCodeInstr::MakeLocationSummary() const {
+LocationSummary* StringFromCharCodeInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   // TODO(fschneider): Allow immediate operands for the char code.
   return LocationSummary::Make(kNumInputs,
@@ -803,7 +810,7 @@
 }
 
 
-LocationSummary* StringInterpolateInstr::MakeLocationSummary() const {
+LocationSummary* StringInterpolateInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -829,7 +836,7 @@
 }
 
 
-LocationSummary* LoadUntaggedInstr::MakeLocationSummary() const {
+LocationSummary* LoadUntaggedInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   return LocationSummary::Make(kNumInputs,
                                Location::RequiresRegister(),
@@ -844,7 +851,7 @@
 }
 
 
-LocationSummary* LoadClassIdInstr::MakeLocationSummary() const {
+LocationSummary* LoadClassIdInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   return LocationSummary::Make(kNumInputs,
                                Location::RequiresRegister(),
@@ -940,7 +947,7 @@
 }
 
 
-LocationSummary* LoadIndexedInstr::MakeLocationSummary() const {
+LocationSummary* LoadIndexedInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 2;
   const intptr_t kNumTemps = 0;
   LocationSummary* locs =
@@ -1123,7 +1130,7 @@
 }
 
 
-LocationSummary* StoreIndexedInstr::MakeLocationSummary() const {
+LocationSummary* StoreIndexedInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 3;
   const intptr_t kNumTemps = 0;
   LocationSummary* locs =
@@ -1307,7 +1314,7 @@
 }
 
 
-LocationSummary* GuardFieldInstr::MakeLocationSummary() const {
+LocationSummary* GuardFieldInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   LocationSummary* summary =
       new LocationSummary(kNumInputs, 0, LocationSummary::kNoCall);
@@ -1640,21 +1647,145 @@
 }
 
 
-LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary() const {
+class StoreInstanceFieldSlowPath : public SlowPathCode {
+ public:
+  explicit StoreInstanceFieldSlowPath(StoreInstanceFieldInstr* instruction)
+      : instruction_(instruction) { }
+
+  virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
+    __ Comment("StoreInstanceFieldSlowPath");
+    __ Bind(entry_label());
+    const Class& double_class = compiler->double_class();
+    const Code& stub =
+        Code::Handle(StubCode::GetAllocationStubForClass(double_class));
+    const ExternalLabel label(double_class.ToCString(), stub.EntryPoint());
+
+    LocationSummary* locs = instruction_->locs();
+    locs->live_registers()->Remove(locs->out());
+
+    compiler->SaveLiveRegisters(locs);
+    compiler->GenerateCall(Scanner::kDummyTokenIndex,  // No token position.
+                           &label,
+                           PcDescriptors::kOther,
+                           locs);
+    __ mov(locs->temp(0).reg(), V0);
+    compiler->RestoreLiveRegisters(locs);
+
+    __ b(exit_label());
+  }
+
+ private:
+  StoreInstanceFieldInstr* instruction_;
+};
+
+
+LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 2;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
-      new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
+      new LocationSummary(kNumInputs, kNumTemps,
+          (field().guarded_cid() == kIllegalCid) || (is_initialization_)
+          ? LocationSummary::kCallOnSlowPath
+          : LocationSummary::kNoCall);
+
   summary->set_in(0, Location::RequiresRegister());
-  summary->set_in(1, ShouldEmitStoreBarrier()
+  if (IsUnboxedStore() && opt) {
+    summary->set_in(1, Location::RequiresFpuRegister());
+    summary->AddTemp(Location::RequiresRegister());
+    summary->AddTemp(Location::RequiresRegister());
+  } else if (IsPotentialUnboxedStore()) {
+    summary->set_in(1, ShouldEmitStoreBarrier()
+        ? Location::WritableRegister()
+        :  Location::RequiresRegister());
+    summary->AddTemp(Location::RequiresRegister());
+    summary->AddTemp(Location::RequiresRegister());
+    summary->AddTemp(opt ? Location::RequiresFpuRegister()
+                         : Location::FpuRegisterLocation(D1));
+  } else {
+    summary->set_in(1, ShouldEmitStoreBarrier()
                        ? Location::WritableRegister()
                        : Location::RegisterOrConstant(value()));
+  }
   return summary;
 }
 
 
 void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  Label skip_store;
+
   Register instance_reg = locs()->in(0).reg();
+
+  if (IsUnboxedStore() && compiler->is_optimizing()) {
+    DRegister value = locs()->in(1).fpu_reg();
+    Register temp = locs()->temp(0).reg();
+    Register temp2 = locs()->temp(1).reg();
+
+    if (is_initialization_) {
+      StoreInstanceFieldSlowPath* slow_path =
+          new StoreInstanceFieldSlowPath(this);
+      compiler->AddSlowPathCode(slow_path);
+      __ TryAllocate(compiler->double_class(),
+                     slow_path->entry_label(),
+                     temp);
+      __ Bind(slow_path->exit_label());
+      __ mov(temp2, temp);
+      __ StoreIntoObject(instance_reg,
+                         FieldAddress(instance_reg, field().Offset()),
+                         temp2);
+    } else {
+      __ lw(temp, FieldAddress(instance_reg, field().Offset()));
+    }
+    __ StoreDToOffset(value, temp, Double::value_offset() - kHeapObjectTag);
+    return;
+  }
+
+  if (IsPotentialUnboxedStore()) {
+    Register value_reg = locs()->in(1).reg();
+    Register temp = locs()->temp(0).reg();
+    Register temp2 = locs()->temp(1).reg();
+    DRegister fpu_temp = locs()->temp(2).fpu_reg();
+
+    Label store_pointer, copy_payload;
+    __ LoadObject(temp, Field::ZoneHandle(field().raw()));
+    __ lw(temp2, FieldAddress(temp, Field::guarded_cid_offset()));
+    __ BranchNotEqual(temp2, kDoubleCid, &store_pointer);
+    __ lw(temp2, FieldAddress(temp, Field::is_nullable_offset()));
+    __ BranchEqual(temp2, kNullCid, &store_pointer);
+    __ lbu(temp2, FieldAddress(temp, Field::kind_bits_offset()));
+    __ andi(CMPRES1, temp2, Immediate(1 << Field::kUnboxingCandidateBit));
+    __ beq(CMPRES1, ZR, &store_pointer);
+
+    __ lw(temp, FieldAddress(instance_reg, field().Offset()));
+    __ BranchNotEqual(temp, reinterpret_cast<int32_t>(Object::null()),
+                      &copy_payload);
+
+    StoreInstanceFieldSlowPath* slow_path =
+        new StoreInstanceFieldSlowPath(this);
+    compiler->AddSlowPathCode(slow_path);
+
+    if (!compiler->is_optimizing()) {
+      locs()->live_registers()->Add(locs()->in(0));
+      locs()->live_registers()->Add(locs()->in(1));
+    }
+
+    __ TryAllocate(compiler->double_class(),
+                   slow_path->entry_label(),
+                   temp);
+    __ Bind(slow_path->exit_label());
+    __ mov(temp2, temp);
+    __ StoreIntoObject(instance_reg,
+                       FieldAddress(instance_reg, field().Offset()),
+                       temp2);
+
+    __ Bind(&copy_payload);
+    __ LoadDFromOffset(fpu_temp,
+                       value_reg,
+                       Double::value_offset() - kHeapObjectTag);
+    __ StoreDToOffset(fpu_temp, temp, Double::value_offset() - kHeapObjectTag);
+    __ b(&skip_store);
+    __ Bind(&store_pointer);
+  }
+
   if (ShouldEmitStoreBarrier()) {
     Register value_reg = locs()->in(1).reg();
     __ StoreIntoObject(instance_reg,
@@ -1673,10 +1804,11 @@
           FieldAddress(instance_reg, field().Offset()), value_reg);
     }
   }
+  __ Bind(&skip_store);
 }
 
 
-LocationSummary* LoadStaticFieldInstr::MakeLocationSummary() const {
+LocationSummary* LoadStaticFieldInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -1700,7 +1832,7 @@
 }
 
 
-LocationSummary* StoreStaticFieldInstr::MakeLocationSummary() const {
+LocationSummary* StoreStaticFieldInstr::MakeLocationSummary(bool opt) const {
   LocationSummary* locs = new LocationSummary(1, 1, LocationSummary::kNoCall);
   locs->set_in(0, value()->NeedsStoreBuffer() ? Location::WritableRegister()
                                               : Location::RequiresRegister());
@@ -1725,7 +1857,7 @@
 }
 
 
-LocationSummary* InstanceOfInstr::MakeLocationSummary() const {
+LocationSummary* InstanceOfInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 3;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -1753,7 +1885,7 @@
 }
 
 
-LocationSummary* CreateArrayInstr::MakeLocationSummary() const {
+LocationSummary* CreateArrayInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* locs =
@@ -1778,7 +1910,7 @@
 
 
 LocationSummary*
-AllocateObjectWithBoundsCheckInstr::MakeLocationSummary() const {
+AllocateObjectWithBoundsCheckInstr::MakeLocationSummary(bool opt) const {
   return MakeCallSummary();
 }
 
@@ -1796,22 +1928,118 @@
 }
 
 
-LocationSummary* LoadFieldInstr::MakeLocationSummary() const {
-  return LocationSummary::Make(1,
-                               Location::RequiresRegister(),
-                               LocationSummary::kNoCall);
+class BoxDoubleSlowPath : public SlowPathCode {
+ public:
+  explicit BoxDoubleSlowPath(Instruction* instruction)
+      : instruction_(instruction) { }
+
+  virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
+    __ Comment("BoxDoubleSlowPath");
+    __ Bind(entry_label());
+    const Class& double_class = compiler->double_class();
+    const Code& stub =
+        Code::Handle(StubCode::GetAllocationStubForClass(double_class));
+    const ExternalLabel label(double_class.ToCString(), stub.EntryPoint());
+
+    LocationSummary* locs = instruction_->locs();
+    locs->live_registers()->Remove(locs->out());
+
+    compiler->SaveLiveRegisters(locs);
+    compiler->GenerateCall(Scanner::kDummyTokenIndex,  // No token position.
+                           &label,
+                           PcDescriptors::kOther,
+                           locs);
+    if (locs->out().reg() != V0) {
+      __ mov(locs->out().reg(), V0);
+    }
+    compiler->RestoreLiveRegisters(locs);
+
+    __ b(exit_label());
+  }
+
+ private:
+  Instruction* instruction_;
+};
+
+
+LocationSummary* LoadFieldInstr::MakeLocationSummary(bool opt) const {
+  const intptr_t kNumInputs = 1;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* locs =
+      new LocationSummary(
+          kNumInputs, kNumTemps,
+          (opt && !IsPotentialUnboxedLoad())
+          ? LocationSummary::kNoCall
+          : LocationSummary::kCallOnSlowPath);
+
+  locs->set_in(0, Location::RequiresRegister());
+
+  if (IsUnboxedLoad() && opt) {
+    locs->AddTemp(Location::RequiresRegister());
+  } else if (IsPotentialUnboxedLoad()) {
+    locs->AddTemp(opt ? Location::RequiresFpuRegister()
+                      : Location::FpuRegisterLocation(D1));
+    locs->AddTemp(Location::RequiresRegister());
+  }
+  locs->set_out(Location::RequiresRegister());
+  return locs;
 }
 
 
 void LoadFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   Register instance_reg = locs()->in(0).reg();
-  Register result_reg = locs()->out().reg();
+  if (IsUnboxedLoad() && compiler->is_optimizing()) {
+    DRegister result = locs()->out().fpu_reg();
+    Register temp = locs()->temp(0).reg();
+    __ lw(temp, FieldAddress(instance_reg, offset_in_bytes()));
+    __ LoadDFromOffset(result, temp, Double::value_offset() - kHeapObjectTag);
+    return;
+  }
 
+  Label done;
+  Register result_reg = locs()->out().reg();
+  if (IsPotentialUnboxedLoad()) {
+    Register temp = locs()->temp(1).reg();
+    DRegister value = locs()->temp(0).fpu_reg();
+
+    Label load_pointer;
+    __ LoadObject(result_reg, Field::ZoneHandle(field()->raw()));
+
+    FieldAddress field_cid_operand(result_reg, Field::guarded_cid_offset());
+    FieldAddress field_nullability_operand(result_reg,
+                                           Field::is_nullable_offset());
+
+    __ lw(temp, field_cid_operand);
+    __ BranchNotEqual(temp, kDoubleCid, &load_pointer);
+
+    __ lw(temp, field_nullability_operand);
+    __ BranchEqual(temp, kNullCid, &load_pointer);
+
+    BoxDoubleSlowPath* slow_path = new BoxDoubleSlowPath(this);
+    compiler->AddSlowPathCode(slow_path);
+
+    if (!compiler->is_optimizing()) {
+      locs()->live_registers()->Add(locs()->in(0));
+    }
+
+    __ TryAllocate(compiler->double_class(),
+                   slow_path->entry_label(),
+                   result_reg);
+    __ Bind(slow_path->exit_label());
+    __ lw(temp, FieldAddress(instance_reg, offset_in_bytes()));
+    __ LoadDFromOffset(value, temp, Double::value_offset() - kHeapObjectTag);
+    __ StoreDToOffset(value,
+                      result_reg,
+                      Double::value_offset() - kHeapObjectTag);
+    __ b(&done);
+    __ Bind(&load_pointer);
+  }
   __ lw(result_reg, Address(instance_reg, offset_in_bytes() - kHeapObjectTag));
+  __ Bind(&done);
 }
 
 
-LocationSummary* InstantiateTypeInstr::MakeLocationSummary() const {
+LocationSummary* InstantiateTypeInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* locs =
@@ -1851,7 +2079,8 @@
 }
 
 
-LocationSummary* InstantiateTypeArgumentsInstr::MakeLocationSummary() const {
+LocationSummary* InstantiateTypeArgumentsInstr::MakeLocationSummary(
+    bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* locs =
@@ -1907,7 +2136,7 @@
 
 
 LocationSummary*
-ExtractConstructorTypeArgumentsInstr::MakeLocationSummary() const {
+ExtractConstructorTypeArgumentsInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* locs =
@@ -1948,7 +2177,7 @@
 
 
 LocationSummary*
-ExtractConstructorInstantiatorInstr::MakeLocationSummary() const {
+ExtractConstructorInstantiatorInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* locs =
@@ -1986,7 +2215,7 @@
 }
 
 
-LocationSummary* AllocateContextInstr::MakeLocationSummary() const {
+LocationSummary* AllocateContextInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 0;
   const intptr_t kNumTemps = 1;
   LocationSummary* locs =
@@ -2013,7 +2242,7 @@
 }
 
 
-LocationSummary* CloneContextInstr::MakeLocationSummary() const {
+LocationSummary* CloneContextInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* locs =
@@ -2045,7 +2274,7 @@
 }
 
 
-LocationSummary* CatchBlockEntryInstr::MakeLocationSummary() const {
+LocationSummary* CatchBlockEntryInstr::MakeLocationSummary(bool opt) const {
   UNREACHABLE();
   return NULL;
 }
@@ -2085,7 +2314,7 @@
 }
 
 
-LocationSummary* CheckStackOverflowInstr::MakeLocationSummary() const {
+LocationSummary* CheckStackOverflowInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 0;
   const intptr_t kNumTemps = 1;
   LocationSummary* summary =
@@ -2273,7 +2502,7 @@
 }
 
 
-LocationSummary* BinarySmiOpInstr::MakeLocationSummary() const {
+LocationSummary* BinarySmiOpInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 2;
   const intptr_t kNumTemps = op_kind() == Token::kADD ? 1 : 0;
   LocationSummary* summary =
@@ -2619,7 +2848,7 @@
 }
 
 
-LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary() const {
+LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary(bool opt) const {
   intptr_t left_cid = left()->Type()->ToCid();
   intptr_t right_cid = right()->Type()->ToCid();
   ASSERT((left_cid != kDoubleCid) && (right_cid != kDoubleCid));
@@ -2651,7 +2880,7 @@
 }
 
 
-LocationSummary* BoxDoubleInstr::MakeLocationSummary() const {
+LocationSummary* BoxDoubleInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -2664,40 +2893,6 @@
 }
 
 
-class BoxDoubleSlowPath : public SlowPathCode {
- public:
-  explicit BoxDoubleSlowPath(BoxDoubleInstr* instruction)
-      : instruction_(instruction) { }
-
-  virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
-    __ Comment("BoxDoubleSlowPath");
-    __ Bind(entry_label());
-    const Class& double_class = compiler->double_class();
-    const Code& stub =
-        Code::Handle(StubCode::GetAllocationStubForClass(double_class));
-    const ExternalLabel label(double_class.ToCString(), stub.EntryPoint());
-
-    LocationSummary* locs = instruction_->locs();
-    locs->live_registers()->Remove(locs->out());
-
-    compiler->SaveLiveRegisters(locs);
-    compiler->GenerateCall(Scanner::kDummyTokenIndex,  // No token position.
-                           &label,
-                           PcDescriptors::kOther,
-                           locs);
-    if (locs->out().reg() != V0) {
-      __ mov(locs->out().reg(), V0);
-    }
-    compiler->RestoreLiveRegisters(locs);
-
-    __ b(exit_label());
-  }
-
- private:
-  BoxDoubleInstr* instruction_;
-};
-
-
 void BoxDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   BoxDoubleSlowPath* slow_path = new BoxDoubleSlowPath(this);
   compiler->AddSlowPathCode(slow_path);
@@ -2713,7 +2908,7 @@
 }
 
 
-LocationSummary* UnboxDoubleInstr::MakeLocationSummary() const {
+LocationSummary* UnboxDoubleInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t value_cid = value()->Type()->ToCid();
   const bool needs_writable_input = (value_cid == kSmiCid);
@@ -2759,7 +2954,7 @@
 }
 
 
-LocationSummary* BoxFloat32x4Instr::MakeLocationSummary() const {
+LocationSummary* BoxFloat32x4Instr::MakeLocationSummary(bool opt) const {
   UNIMPLEMENTED();
   return NULL;
 }
@@ -2770,7 +2965,7 @@
 }
 
 
-LocationSummary* UnboxFloat32x4Instr::MakeLocationSummary() const {
+LocationSummary* UnboxFloat32x4Instr::MakeLocationSummary(bool opt) const {
   UNIMPLEMENTED();
   return NULL;
 }
@@ -2781,7 +2976,7 @@
 }
 
 
-LocationSummary* BoxInt32x4Instr::MakeLocationSummary() const {
+LocationSummary* BoxInt32x4Instr::MakeLocationSummary(bool opt) const {
   UNIMPLEMENTED();
   return NULL;
 }
@@ -2792,7 +2987,7 @@
 }
 
 
-LocationSummary* UnboxInt32x4Instr::MakeLocationSummary() const {
+LocationSummary* UnboxInt32x4Instr::MakeLocationSummary(bool opt) const {
   UNIMPLEMENTED();
   return NULL;
 }
@@ -2803,7 +2998,7 @@
 }
 
 
-LocationSummary* BinaryDoubleOpInstr::MakeLocationSummary() const {
+LocationSummary* BinaryDoubleOpInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 2;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -2829,7 +3024,7 @@
 }
 
 
-LocationSummary* BinaryFloat32x4OpInstr::MakeLocationSummary() const {
+LocationSummary* BinaryFloat32x4OpInstr::MakeLocationSummary(bool opt) const {
   UNIMPLEMENTED();
   return NULL;
 }
@@ -2840,7 +3035,7 @@
 }
 
 
-LocationSummary* Simd32x4ShuffleInstr::MakeLocationSummary() const {
+LocationSummary* Simd32x4ShuffleInstr::MakeLocationSummary(bool opt) const {
   UNIMPLEMENTED();
   return NULL;
 }
@@ -2852,7 +3047,7 @@
 
 
 
-LocationSummary* Simd32x4ShuffleMixInstr::MakeLocationSummary() const {
+LocationSummary* Simd32x4ShuffleMixInstr::MakeLocationSummary(bool opt) const {
   UNIMPLEMENTED();
   return NULL;
 }
@@ -2863,7 +3058,8 @@
 }
 
 
-LocationSummary* Float32x4ConstructorInstr::MakeLocationSummary() const {
+LocationSummary* Float32x4ConstructorInstr::MakeLocationSummary(
+    bool opt) const {
   UNIMPLEMENTED();
   return NULL;
 }
@@ -2874,7 +3070,7 @@
 }
 
 
-LocationSummary* Float32x4ZeroInstr::MakeLocationSummary() const {
+LocationSummary* Float32x4ZeroInstr::MakeLocationSummary(bool opt) const {
   UNIMPLEMENTED();
   return NULL;
 }
@@ -2885,7 +3081,7 @@
 }
 
 
-LocationSummary* Float32x4SplatInstr::MakeLocationSummary() const {
+LocationSummary* Float32x4SplatInstr::MakeLocationSummary(bool opt) const {
   UNIMPLEMENTED();
   return NULL;
 }
@@ -2896,7 +3092,7 @@
 }
 
 
-LocationSummary* Float32x4ComparisonInstr::MakeLocationSummary() const {
+LocationSummary* Float32x4ComparisonInstr::MakeLocationSummary(bool opt) const {
   UNIMPLEMENTED();
   return NULL;
 }
@@ -2907,7 +3103,7 @@
 }
 
 
-LocationSummary* Float32x4MinMaxInstr::MakeLocationSummary() const {
+LocationSummary* Float32x4MinMaxInstr::MakeLocationSummary(bool opt) const {
   UNIMPLEMENTED();
   return NULL;
 }
@@ -2918,7 +3114,7 @@
 }
 
 
-LocationSummary* Float32x4SqrtInstr::MakeLocationSummary() const {
+LocationSummary* Float32x4SqrtInstr::MakeLocationSummary(bool opt) const {
   UNIMPLEMENTED();
   return NULL;
 }
@@ -2929,7 +3125,7 @@
 }
 
 
-LocationSummary* Float32x4ScaleInstr::MakeLocationSummary() const {
+LocationSummary* Float32x4ScaleInstr::MakeLocationSummary(bool opt) const {
   UNIMPLEMENTED();
   return NULL;
 }
@@ -2940,7 +3136,7 @@
 }
 
 
-LocationSummary* Float32x4ZeroArgInstr::MakeLocationSummary() const {
+LocationSummary* Float32x4ZeroArgInstr::MakeLocationSummary(bool opt) const {
   UNIMPLEMENTED();
   return NULL;
 }
@@ -2951,7 +3147,7 @@
 }
 
 
-LocationSummary* Float32x4ClampInstr::MakeLocationSummary() const {
+LocationSummary* Float32x4ClampInstr::MakeLocationSummary(bool opt) const {
   UNIMPLEMENTED();
   return NULL;
 }
@@ -2962,7 +3158,7 @@
 }
 
 
-LocationSummary* Float32x4WithInstr::MakeLocationSummary() const {
+LocationSummary* Float32x4WithInstr::MakeLocationSummary(bool opt) const {
   UNIMPLEMENTED();
   return NULL;
 }
@@ -2973,7 +3169,7 @@
 }
 
 
-LocationSummary* Float32x4ToInt32x4Instr::MakeLocationSummary() const {
+LocationSummary* Float32x4ToInt32x4Instr::MakeLocationSummary(bool opt) const {
   UNIMPLEMENTED();
   return NULL;
 }
@@ -2984,7 +3180,8 @@
 }
 
 
-LocationSummary* Int32x4BoolConstructorInstr::MakeLocationSummary() const {
+LocationSummary* Int32x4BoolConstructorInstr::MakeLocationSummary(
+    bool opt) const {
   UNIMPLEMENTED();
   return NULL;
 }
@@ -2995,7 +3192,7 @@
 }
 
 
-LocationSummary* Int32x4GetFlagInstr::MakeLocationSummary() const {
+LocationSummary* Int32x4GetFlagInstr::MakeLocationSummary(bool opt) const {
   UNIMPLEMENTED();
   return NULL;
 }
@@ -3006,7 +3203,7 @@
 }
 
 
-LocationSummary* Simd32x4GetSignMaskInstr::MakeLocationSummary() const {
+LocationSummary* Simd32x4GetSignMaskInstr::MakeLocationSummary(bool opt) const {
   UNIMPLEMENTED();
   return NULL;
 }
@@ -3017,7 +3214,7 @@
 }
 
 
-LocationSummary* Int32x4SelectInstr::MakeLocationSummary() const {
+LocationSummary* Int32x4SelectInstr::MakeLocationSummary(bool opt) const {
   UNIMPLEMENTED();
   return NULL;
 }
@@ -3028,7 +3225,7 @@
 }
 
 
-LocationSummary* Int32x4SetFlagInstr::MakeLocationSummary() const {
+LocationSummary* Int32x4SetFlagInstr::MakeLocationSummary(bool opt) const {
   UNIMPLEMENTED();
   return NULL;
 }
@@ -3039,7 +3236,7 @@
 }
 
 
-LocationSummary* Int32x4ToFloat32x4Instr::MakeLocationSummary() const {
+LocationSummary* Int32x4ToFloat32x4Instr::MakeLocationSummary(bool opt) const {
   UNIMPLEMENTED();
   return NULL;
 }
@@ -3050,7 +3247,7 @@
 }
 
 
-LocationSummary* BinaryInt32x4OpInstr::MakeLocationSummary() const {
+LocationSummary* BinaryInt32x4OpInstr::MakeLocationSummary(bool opt) const {
   UNIMPLEMENTED();
   return NULL;
 }
@@ -3061,7 +3258,7 @@
 }
 
 
-LocationSummary* MathUnaryInstr::MakeLocationSummary() const {
+LocationSummary* MathUnaryInstr::MakeLocationSummary(bool opt) const {
   if ((kind() == MethodRecognizer::kMathSin) ||
       (kind() == MethodRecognizer::kMathCos)) {
     const intptr_t kNumInputs = 1;
@@ -3091,7 +3288,7 @@
 }
 
 
-LocationSummary* MathMinMaxInstr::MakeLocationSummary() const {
+LocationSummary* MathMinMaxInstr::MakeLocationSummary(bool opt) const {
   if (result_cid() == kDoubleCid) {
     const intptr_t kNumInputs = 2;
     const intptr_t kNumTemps = 1;
@@ -3182,7 +3379,7 @@
 }
 
 
-LocationSummary* UnarySmiOpInstr::MakeLocationSummary() const {
+LocationSummary* UnarySmiOpInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -3216,7 +3413,7 @@
 }
 
 
-LocationSummary* UnaryDoubleOpInstr::MakeLocationSummary() const {
+LocationSummary* UnaryDoubleOpInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 1;
   LocationSummary* summary =
@@ -3241,7 +3438,7 @@
 
 
 
-LocationSummary* SmiToDoubleInstr::MakeLocationSummary() const {
+LocationSummary* SmiToDoubleInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* result =
@@ -3261,7 +3458,7 @@
 }
 
 
-LocationSummary* DoubleToIntegerInstr::MakeLocationSummary() const {
+LocationSummary* DoubleToIntegerInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* result =
@@ -3307,7 +3504,7 @@
 }
 
 
-LocationSummary* DoubleToSmiInstr::MakeLocationSummary() const {
+LocationSummary* DoubleToSmiInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* result = new LocationSummary(
@@ -3333,7 +3530,7 @@
 }
 
 
-LocationSummary* DoubleToDoubleInstr::MakeLocationSummary() const {
+LocationSummary* DoubleToDoubleInstr::MakeLocationSummary(bool opt) const {
   UNIMPLEMENTED();
   return NULL;
 }
@@ -3344,7 +3541,7 @@
 }
 
 
-LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary() const {
+LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary(bool opt) const {
   // Calling convetion on MIPS uses D6 and D7 to pass the first two
   // double arguments.
   ASSERT((InputCount() == 1) || (InputCount() == 2));
@@ -3406,7 +3603,7 @@
 }
 
 
-LocationSummary* MergedMathInstr::MakeLocationSummary() const {
+LocationSummary* MergedMathInstr::MakeLocationSummary(bool opt) const {
   if (kind() == MergedMathInstr::kTruncDivMod) {
     const intptr_t kNumInputs = 2;
     const intptr_t kNumTemps = 3;
@@ -3494,7 +3691,8 @@
 }
 
 
-LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary() const {
+LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary(
+    bool opt) const {
   return MakeCallSummary();
 }
 
@@ -3537,9 +3735,11 @@
 }
 
 
-LocationSummary* BranchInstr::MakeLocationSummary() const {
-  UNREACHABLE();
-  return NULL;
+LocationSummary* BranchInstr::MakeLocationSummary(bool opt) const {
+  comparison()->InitializeLocationSummary(opt);
+  // Branches don't produce a result.
+  comparison()->locs()->set_out(Location::NoLocation());
+  return comparison()->locs();
 }
 
 
@@ -3549,7 +3749,7 @@
 }
 
 
-LocationSummary* CheckClassInstr::MakeLocationSummary() const {
+LocationSummary* CheckClassInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -3603,7 +3803,7 @@
 }
 
 
-LocationSummary* CheckSmiInstr::MakeLocationSummary() const {
+LocationSummary* CheckSmiInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -3623,7 +3823,7 @@
 }
 
 
-LocationSummary* CheckArrayBoundInstr::MakeLocationSummary() const {
+LocationSummary* CheckArrayBoundInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 2;
   const intptr_t kNumTemps = 0;
   LocationSummary* locs =
@@ -3675,7 +3875,7 @@
 }
 
 
-LocationSummary* UnboxIntegerInstr::MakeLocationSummary() const {
+LocationSummary* UnboxIntegerInstr::MakeLocationSummary(bool opt) const {
   UNIMPLEMENTED();
   return NULL;
 }
@@ -3686,7 +3886,7 @@
 }
 
 
-LocationSummary* BoxIntegerInstr::MakeLocationSummary() const {
+LocationSummary* BoxIntegerInstr::MakeLocationSummary(bool opt) const {
   UNIMPLEMENTED();
   return NULL;
 }
@@ -3697,7 +3897,7 @@
 }
 
 
-LocationSummary* BinaryMintOpInstr::MakeLocationSummary() const {
+LocationSummary* BinaryMintOpInstr::MakeLocationSummary(bool opt) const {
   UNIMPLEMENTED();
   return NULL;
 }
@@ -3708,7 +3908,7 @@
 }
 
 
-LocationSummary* ShiftMintOpInstr::MakeLocationSummary() const {
+LocationSummary* ShiftMintOpInstr::MakeLocationSummary(bool opt) const {
   UNIMPLEMENTED();
   return NULL;
 }
@@ -3719,7 +3919,7 @@
 }
 
 
-LocationSummary* UnaryMintOpInstr::MakeLocationSummary() const {
+LocationSummary* UnaryMintOpInstr::MakeLocationSummary(bool opt) const {
   UNIMPLEMENTED();
   return NULL;
 }
@@ -3730,7 +3930,7 @@
 }
 
 
-LocationSummary* ThrowInstr::MakeLocationSummary() const {
+LocationSummary* ThrowInstr::MakeLocationSummary(bool opt) const {
   return new LocationSummary(0, 0, LocationSummary::kCall);
 }
 
@@ -3746,7 +3946,7 @@
 }
 
 
-LocationSummary* ReThrowInstr::MakeLocationSummary() const {
+LocationSummary* ReThrowInstr::MakeLocationSummary(bool opt) const {
   return new LocationSummary(0, 0, LocationSummary::kCall);
 }
 
@@ -3786,7 +3986,7 @@
 }
 
 
-LocationSummary* GotoInstr::MakeLocationSummary() const {
+LocationSummary* GotoInstr::MakeLocationSummary(bool opt) const {
   return new LocationSummary(0, 0, LocationSummary::kNoCall);
 }
 
@@ -3816,7 +4016,7 @@
 }
 
 
-LocationSummary* CurrentContextInstr::MakeLocationSummary() const {
+LocationSummary* CurrentContextInstr::MakeLocationSummary(bool opt) const {
   return LocationSummary::Make(0,
                                Location::RequiresRegister(),
                                LocationSummary::kNoCall);
@@ -3828,7 +4028,7 @@
 }
 
 
-LocationSummary* StrictCompareInstr::MakeLocationSummary() const {
+LocationSummary* StrictCompareInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 2;
   const intptr_t kNumTemps = 0;
   if (needs_number_check()) {
@@ -3910,7 +4110,7 @@
 }
 
 
-LocationSummary* BooleanNegateInstr::MakeLocationSummary() const {
+LocationSummary* BooleanNegateInstr::MakeLocationSummary(bool opt) const {
   return LocationSummary::Make(1,
                                Location::RequiresRegister(),
                                LocationSummary::kNoCall);
@@ -3928,7 +4128,7 @@
 }
 
 
-LocationSummary* StoreVMFieldInstr::MakeLocationSummary() const {
+LocationSummary* StoreVMFieldInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 2;
   const intptr_t kNumTemps = 0;
   LocationSummary* locs =
@@ -3954,7 +4154,7 @@
 }
 
 
-LocationSummary* AllocateObjectInstr::MakeLocationSummary() const {
+LocationSummary* AllocateObjectInstr::MakeLocationSummary(bool opt) const {
   return MakeCallSummary();
 }
 
@@ -3972,7 +4172,7 @@
 }
 
 
-LocationSummary* CreateClosureInstr::MakeLocationSummary() const {
+LocationSummary* CreateClosureInstr::MakeLocationSummary(bool opt) const {
   return MakeCallSummary();
 }
 
diff --git a/runtime/vm/intermediate_language_x64.cc b/runtime/vm/intermediate_language_x64.cc
index 72160c2..a1eb248 100644
--- a/runtime/vm/intermediate_language_x64.cc
+++ b/runtime/vm/intermediate_language_x64.cc
@@ -34,7 +34,7 @@
 }
 
 
-LocationSummary* PushArgumentInstr::MakeLocationSummary() const {
+LocationSummary* PushArgumentInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps= 0;
   LocationSummary* locs =
@@ -61,7 +61,7 @@
 }
 
 
-LocationSummary* ReturnInstr::MakeLocationSummary() const {
+LocationSummary* ReturnInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* locs =
@@ -130,11 +130,11 @@
 }
 
 
-LocationSummary* IfThenElseInstr::MakeLocationSummary() const {
-  LocationSummary* locs = comparison()->MakeLocationSummary();
+LocationSummary* IfThenElseInstr::MakeLocationSummary(bool opt) const {
+  comparison()->InitializeLocationSummary(opt);
   // TODO(vegorov): support byte register constraints in the register allocator.
-  locs->set_out(Location::RegisterLocation(RDX));
-  return locs;
+  comparison()->locs()->set_out(Location::RegisterLocation(RDX));
+  return comparison()->locs();
 }
 
 
@@ -187,7 +187,7 @@
 }
 
 
-LocationSummary* LoadLocalInstr::MakeLocationSummary() const {
+LocationSummary* LoadLocalInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 0;
   return LocationSummary::Make(kNumInputs,
                                Location::RequiresRegister(),
@@ -201,7 +201,7 @@
 }
 
 
-LocationSummary* StoreLocalInstr::MakeLocationSummary() const {
+LocationSummary* StoreLocalInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   return LocationSummary::Make(kNumInputs,
                                Location::SameAsFirstInput(),
@@ -217,7 +217,7 @@
 }
 
 
-LocationSummary* ConstantInstr::MakeLocationSummary() const {
+LocationSummary* ConstantInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 0;
   return LocationSummary::Make(kNumInputs,
                                Location::RequiresRegister(),
@@ -234,7 +234,7 @@
 }
 
 
-LocationSummary* AssertAssignableInstr::MakeLocationSummary() const {
+LocationSummary* AssertAssignableInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 3;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -247,7 +247,7 @@
 }
 
 
-LocationSummary* AssertBooleanInstr::MakeLocationSummary() const {
+LocationSummary* AssertBooleanInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* locs =
@@ -308,7 +308,7 @@
 }
 
 
-LocationSummary* EqualityCompareInstr::MakeLocationSummary() const {
+LocationSummary* EqualityCompareInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 2;
   if (operation_cid() == kDoubleCid) {
     const intptr_t kNumTemps =  0;
@@ -491,7 +491,7 @@
 }
 
 
-LocationSummary* TestSmiInstr::MakeLocationSummary() const {
+LocationSummary* TestSmiInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 2;
   const intptr_t kNumTemps = 0;
   LocationSummary* locs =
@@ -535,7 +535,7 @@
 }
 
 
-LocationSummary* RelationalOpInstr::MakeLocationSummary() const {
+LocationSummary* RelationalOpInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 2;
   const intptr_t kNumTemps = 0;
   if (operation_cid() == kDoubleCid) {
@@ -596,7 +596,7 @@
 }
 
 
-LocationSummary* NativeCallInstr::MakeLocationSummary() const {
+LocationSummary* NativeCallInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 0;
   const intptr_t kNumTemps = 3;
   LocationSummary* locs =
@@ -652,7 +652,7 @@
 }
 
 
-LocationSummary* StringFromCharCodeInstr::MakeLocationSummary() const {
+LocationSummary* StringFromCharCodeInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   // TODO(fschneider): Allow immediate operands for the char code.
   return LocationSummary::Make(kNumInputs,
@@ -673,7 +673,7 @@
 }
 
 
-LocationSummary* StringInterpolateInstr::MakeLocationSummary() const {
+LocationSummary* StringInterpolateInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -699,7 +699,7 @@
 }
 
 
-LocationSummary* LoadUntaggedInstr::MakeLocationSummary() const {
+LocationSummary* LoadUntaggedInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   return LocationSummary::Make(kNumInputs,
                                Location::RequiresRegister(),
@@ -714,7 +714,7 @@
 }
 
 
-LocationSummary* LoadClassIdInstr::MakeLocationSummary() const {
+LocationSummary* LoadClassIdInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   return LocationSummary::Make(kNumInputs,
                                Location::RequiresRegister(),
@@ -801,7 +801,7 @@
 }
 
 
-LocationSummary* LoadIndexedInstr::MakeLocationSummary() const {
+LocationSummary* LoadIndexedInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 2;
   const intptr_t kNumTemps = 0;
   LocationSummary* locs =
@@ -952,7 +952,7 @@
 }
 
 
-LocationSummary* StoreIndexedInstr::MakeLocationSummary() const {
+LocationSummary* StoreIndexedInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 3;
   const intptr_t kNumTemps = 0;
   LocationSummary* locs =
@@ -1130,7 +1130,7 @@
 }
 
 
-LocationSummary* GuardFieldInstr::MakeLocationSummary() const {
+LocationSummary* GuardFieldInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   LocationSummary* summary =
       new LocationSummary(kNumInputs, 0, LocationSummary::kNoCall);
@@ -1476,21 +1476,149 @@
 }
 
 
-LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary() const {
+class StoreInstanceFieldSlowPath : public SlowPathCode {
+ public:
+  explicit StoreInstanceFieldSlowPath(StoreInstanceFieldInstr* instruction)
+      : instruction_(instruction) { }
+
+  virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
+    __ Comment("StoreInstanceFieldSlowPath");
+    __ Bind(entry_label());
+    const Class& double_class = compiler->double_class();
+    const Code& stub =
+        Code::Handle(StubCode::GetAllocationStubForClass(double_class));
+    const ExternalLabel label(double_class.ToCString(), stub.EntryPoint());
+
+    LocationSummary* locs = instruction_->locs();
+    locs->live_registers()->Remove(locs->out());
+
+    compiler->SaveLiveRegisters(locs);
+    compiler->GenerateCall(Scanner::kDummyTokenIndex,  // No token position.
+                           &label,
+                           PcDescriptors::kOther,
+                           locs);
+    __ MoveRegister(locs->temp(0).reg(), RAX);
+    compiler->RestoreLiveRegisters(locs);
+
+    __ jmp(exit_label());
+  }
+
+ private:
+  StoreInstanceFieldInstr* instruction_;
+};
+
+
+LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 2;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
-      new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
+      new LocationSummary(kNumInputs, kNumTemps,
+          (field().guarded_cid() == kIllegalCid) || (is_initialization_)
+          ? LocationSummary::kCallOnSlowPath
+          : LocationSummary::kNoCall);
+
   summary->set_in(0, Location::RequiresRegister());
-  summary->set_in(1, ShouldEmitStoreBarrier()
+  if (IsUnboxedStore() && opt) {
+    summary->set_in(1, Location::RequiresFpuRegister());
+    summary->AddTemp(Location::RequiresRegister());
+    summary->AddTemp(Location::RequiresRegister());
+  } else if (IsPotentialUnboxedStore()) {
+    summary->set_in(1, ShouldEmitStoreBarrier()
+        ? Location::WritableRegister()
+        :  Location::RequiresRegister());
+    summary->AddTemp(Location::RequiresRegister());
+    summary->AddTemp(Location::RequiresRegister());
+    summary->AddTemp(opt ? Location::RequiresFpuRegister()
+                         : Location::FpuRegisterLocation(XMM1));
+  } else {
+    summary->set_in(1, ShouldEmitStoreBarrier()
                        ? Location::WritableRegister()
                        : Location::RegisterOrConstant(value()));
+  }
   return summary;
 }
 
 
 void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  Label skip_store;
+
   Register instance_reg = locs()->in(0).reg();
+
+  if (IsUnboxedStore() && compiler->is_optimizing()) {
+    XmmRegister value = locs()->in(1).fpu_reg();
+    Register temp = locs()->temp(0).reg();
+    Register temp2 = locs()->temp(1).reg();
+
+    if (is_initialization_) {
+      StoreInstanceFieldSlowPath* slow_path =
+          new StoreInstanceFieldSlowPath(this);
+      compiler->AddSlowPathCode(slow_path);
+
+      __ TryAllocate(compiler->double_class(),
+                     slow_path->entry_label(),
+                     Assembler::kFarJump,
+                     temp,
+                     PP);
+      __ Bind(slow_path->exit_label());
+      __ movq(temp2, temp);
+      __ StoreIntoObject(instance_reg,
+                         FieldAddress(instance_reg, field().Offset()),
+                         temp2);
+    } else {
+      __ movq(temp, FieldAddress(instance_reg, field().Offset()));
+    }
+    __ movsd(FieldAddress(temp, Double::value_offset()), value);
+    return;
+  }
+
+  if (IsPotentialUnboxedStore()) {
+    Register value_reg = locs()->in(1).reg();
+    Register temp = locs()->temp(0).reg();
+    Register temp2 = locs()->temp(1).reg();
+    FpuRegister fpu_temp = locs()->temp(2).fpu_reg();
+
+    Label store_pointer, copy_payload;
+    __ LoadObject(temp, Field::ZoneHandle(field().raw()), PP);
+    __ cmpq(FieldAddress(temp, Field::guarded_cid_offset()),
+            Immediate(kDoubleCid));
+    __ j(NOT_EQUAL, &store_pointer);
+    __ cmpq(FieldAddress(temp, Field::is_nullable_offset()),
+            Immediate(kNullCid));
+    __ j(EQUAL, &store_pointer);
+    __ movzxb(temp2, FieldAddress(temp, Field::kind_bits_offset()));
+    __ testq(temp2, Immediate(1 << Field::kUnboxingCandidateBit));
+    __ j(ZERO, &store_pointer);
+
+    __ movq(temp, FieldAddress(instance_reg, field().Offset()));
+    __ CompareObject(temp, Object::null_object(), PP);
+    __ j(NOT_EQUAL, &copy_payload);
+
+    StoreInstanceFieldSlowPath* slow_path =
+        new StoreInstanceFieldSlowPath(this);
+    compiler->AddSlowPathCode(slow_path);
+
+    if (!compiler->is_optimizing()) {
+      locs()->live_registers()->Add(locs()->in(0));
+      locs()->live_registers()->Add(locs()->in(1));
+    }
+    __ TryAllocate(compiler->double_class(),
+                   slow_path->entry_label(),
+                   Assembler::kFarJump,
+                   temp,
+                   PP);
+    __ Bind(slow_path->exit_label());
+    __ movq(temp2, temp);
+    __ StoreIntoObject(instance_reg,
+                       FieldAddress(instance_reg, field().Offset()),
+                       temp2);
+
+    __ Bind(&copy_payload);
+    __ movsd(fpu_temp, FieldAddress(value_reg, Double::value_offset()));
+    __ movsd(FieldAddress(temp, Double::value_offset()), fpu_temp);
+    __ jmp(&skip_store);
+    __ Bind(&store_pointer);
+  }
+
   if (ShouldEmitStoreBarrier()) {
     Register value_reg = locs()->in(1).reg();
     __ StoreIntoObject(instance_reg,
@@ -1507,10 +1635,11 @@
           FieldAddress(instance_reg, field().Offset()), value_reg);
     }
   }
+  __ Bind(&skip_store);
 }
 
 
-LocationSummary* LoadStaticFieldInstr::MakeLocationSummary() const {
+LocationSummary* LoadStaticFieldInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -1533,7 +1662,7 @@
 }
 
 
-LocationSummary* StoreStaticFieldInstr::MakeLocationSummary() const {
+LocationSummary* StoreStaticFieldInstr::MakeLocationSummary(bool opt) const {
   LocationSummary* locs = new LocationSummary(1, 1, LocationSummary::kNoCall);
   locs->set_in(0, value()->NeedsStoreBuffer() ? Location::WritableRegister()
                                               : Location::RequiresRegister());
@@ -1557,7 +1686,7 @@
 }
 
 
-LocationSummary* InstanceOfInstr::MakeLocationSummary() const {
+LocationSummary* InstanceOfInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 3;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -1584,7 +1713,7 @@
 }
 
 
-LocationSummary* CreateArrayInstr::MakeLocationSummary() const {
+LocationSummary* CreateArrayInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* locs =
@@ -1608,7 +1737,7 @@
 
 
 LocationSummary*
-AllocateObjectWithBoundsCheckInstr::MakeLocationSummary() const {
+AllocateObjectWithBoundsCheckInstr::MakeLocationSummary(bool opt) const {
   return MakeCallSummary();
 }
 
@@ -1626,22 +1755,114 @@
 }
 
 
-LocationSummary* LoadFieldInstr::MakeLocationSummary() const {
-  return LocationSummary::Make(1,
-                               Location::RequiresRegister(),
-                               LocationSummary::kNoCall);
+class BoxDoubleSlowPath : public SlowPathCode {
+ public:
+  explicit BoxDoubleSlowPath(Instruction* instruction)
+      : instruction_(instruction) { }
+
+  virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
+    __ Comment("BoxDoubleSlowPath");
+    __ Bind(entry_label());
+    const Class& double_class = compiler->double_class();
+    const Code& stub =
+        Code::Handle(StubCode::GetAllocationStubForClass(double_class));
+    const ExternalLabel label(double_class.ToCString(), stub.EntryPoint());
+
+    LocationSummary* locs = instruction_->locs();
+    locs->live_registers()->Remove(locs->out());
+
+    compiler->SaveLiveRegisters(locs);
+    compiler->GenerateCall(Scanner::kDummyTokenIndex,  // No token position.
+                           &label,
+                           PcDescriptors::kOther,
+                           locs);
+    __ MoveRegister(locs->out().reg(), RAX);
+    compiler->RestoreLiveRegisters(locs);
+
+    __ jmp(exit_label());
+  }
+
+ private:
+  Instruction* instruction_;
+};
+
+
+LocationSummary* LoadFieldInstr::MakeLocationSummary(bool opt) const {
+  const intptr_t kNumInputs = 1;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* locs =
+      new LocationSummary(
+          kNumInputs, kNumTemps,
+          (opt && !IsPotentialUnboxedLoad())
+          ? LocationSummary::kNoCall
+          : LocationSummary::kCallOnSlowPath);
+
+  locs->set_in(0, Location::RequiresRegister());
+
+  if (IsUnboxedLoad() && opt) {
+    locs->AddTemp(Location::RequiresRegister());
+  } else if (IsPotentialUnboxedLoad()) {
+    locs->AddTemp(opt ? Location::RequiresFpuRegister()
+                      : Location::FpuRegisterLocation(XMM1));
+    locs->AddTemp(Location::RequiresRegister());
+  }
+  locs->set_out(Location::RequiresRegister());
+  return locs;
 }
 
 
 void LoadFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   Register instance_reg = locs()->in(0).reg();
-  Register result_reg = locs()->out().reg();
+  if (IsUnboxedLoad() && compiler->is_optimizing()) {
+    XmmRegister result = locs()->out().fpu_reg();
+    Register temp = locs()->temp(0).reg();
+    __ movq(temp, FieldAddress(instance_reg, offset_in_bytes()));
+    __ movsd(result, FieldAddress(temp, Double::value_offset()));
+    return;
+  }
 
-  __ movq(result_reg, FieldAddress(instance_reg, offset_in_bytes()));
+  Label done;
+  Register result = locs()->out().reg();
+  if (IsPotentialUnboxedLoad()) {
+    Register temp = locs()->temp(1).reg();
+    XmmRegister value = locs()->temp(0).fpu_reg();
+
+    Label load_pointer;
+    __ LoadObject(result, Field::ZoneHandle(field()->raw()), PP);
+
+
+    __ cmpq(FieldAddress(result, Field::guarded_cid_offset()),
+            Immediate(kDoubleCid));
+    __ j(NOT_EQUAL, &load_pointer);
+    __ cmpq(FieldAddress(result, Field::is_nullable_offset()),
+            Immediate(kNullCid));
+    __ j(EQUAL, &load_pointer);
+
+    BoxDoubleSlowPath* slow_path = new BoxDoubleSlowPath(this);
+    compiler->AddSlowPathCode(slow_path);
+
+    if (!compiler->is_optimizing()) {
+      locs()->live_registers()->Add(locs()->in(0));
+    }
+
+    __ TryAllocate(compiler->double_class(),
+                   slow_path->entry_label(),
+                   Assembler::kFarJump,
+                   result,
+                   PP);
+    __ Bind(slow_path->exit_label());
+    __ movq(temp, FieldAddress(instance_reg, offset_in_bytes()));
+    __ movsd(value, FieldAddress(temp, Double::value_offset()));
+    __ movsd(FieldAddress(result, Double::value_offset()), value);
+    __ jmp(&done);
+    __ Bind(&load_pointer);
+  }
+  __ movq(result, FieldAddress(instance_reg, offset_in_bytes()));
+  __ Bind(&done);
 }
 
 
-LocationSummary* InstantiateTypeInstr::MakeLocationSummary() const {
+LocationSummary* InstantiateTypeInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* locs =
@@ -1673,7 +1894,8 @@
 }
 
 
-LocationSummary* InstantiateTypeArgumentsInstr::MakeLocationSummary() const {
+LocationSummary* InstantiateTypeArgumentsInstr::MakeLocationSummary(
+    bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* locs =
@@ -1721,7 +1943,7 @@
 
 
 LocationSummary*
-ExtractConstructorTypeArgumentsInstr::MakeLocationSummary() const {
+ExtractConstructorTypeArgumentsInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* locs =
@@ -1763,7 +1985,7 @@
 
 
 LocationSummary*
-ExtractConstructorInstantiatorInstr::MakeLocationSummary() const {
+ExtractConstructorInstantiatorInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* locs =
@@ -1802,7 +2024,7 @@
 }
 
 
-LocationSummary* AllocateContextInstr::MakeLocationSummary() const {
+LocationSummary* AllocateContextInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 0;
   const intptr_t kNumTemps = 1;
   LocationSummary* locs =
@@ -1827,7 +2049,7 @@
 }
 
 
-LocationSummary* CloneContextInstr::MakeLocationSummary() const {
+LocationSummary* CloneContextInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* locs =
@@ -1854,7 +2076,7 @@
 }
 
 
-LocationSummary* CatchBlockEntryInstr::MakeLocationSummary() const {
+LocationSummary* CatchBlockEntryInstr::MakeLocationSummary(bool opt) const {
   UNREACHABLE();
   return NULL;
 }
@@ -1891,7 +2113,7 @@
 }
 
 
-LocationSummary* CheckStackOverflowInstr::MakeLocationSummary() const {
+LocationSummary* CheckStackOverflowInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 0;
   const intptr_t kNumTemps = 1;
   LocationSummary* summary =
@@ -2114,7 +2336,7 @@
 }
 
 
-LocationSummary* BinarySmiOpInstr::MakeLocationSummary() const {
+LocationSummary* BinarySmiOpInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 2;
 
   ConstantInstr* right_constant = right()->definition()->AsConstant();
@@ -2565,7 +2787,7 @@
 }
 
 
-LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary() const {
+LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary(bool opt) const {
   intptr_t left_cid = left()->Type()->ToCid();
   intptr_t right_cid = right()->Type()->ToCid();
   ASSERT((left_cid != kDoubleCid) && (right_cid != kDoubleCid));
@@ -2601,7 +2823,7 @@
 }
 
 
-LocationSummary* BoxDoubleInstr::MakeLocationSummary() const {
+LocationSummary* BoxDoubleInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -2614,38 +2836,6 @@
 }
 
 
-class BoxDoubleSlowPath : public SlowPathCode {
- public:
-  explicit BoxDoubleSlowPath(BoxDoubleInstr* instruction)
-      : instruction_(instruction) { }
-
-  virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
-    __ Comment("BoxDoubleSlowPath");
-    __ Bind(entry_label());
-    const Class& double_class = compiler->double_class();
-    const Code& stub =
-        Code::Handle(StubCode::GetAllocationStubForClass(double_class));
-    const ExternalLabel label(double_class.ToCString(), stub.EntryPoint());
-
-    LocationSummary* locs = instruction_->locs();
-    locs->live_registers()->Remove(locs->out());
-
-    compiler->SaveLiveRegisters(locs);
-    compiler->GenerateCall(Scanner::kDummyTokenIndex,  // No token position.
-                           &label,
-                           PcDescriptors::kOther,
-                           locs);
-    __ MoveRegister(locs->out().reg(), RAX);
-    compiler->RestoreLiveRegisters(locs);
-
-    __ jmp(exit_label());
-  }
-
- private:
-  BoxDoubleInstr* instruction_;
-};
-
-
 void BoxDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   BoxDoubleSlowPath* slow_path = new BoxDoubleSlowPath(this);
   compiler->AddSlowPathCode(slow_path);
@@ -2663,7 +2853,7 @@
 }
 
 
-LocationSummary* UnboxDoubleInstr::MakeLocationSummary() const {
+LocationSummary* UnboxDoubleInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -2704,7 +2894,7 @@
 }
 
 
-LocationSummary* BoxFloat32x4Instr::MakeLocationSummary() const {
+LocationSummary* BoxFloat32x4Instr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -2766,7 +2956,7 @@
 }
 
 
-LocationSummary* UnboxFloat32x4Instr::MakeLocationSummary() const {
+LocationSummary* UnboxFloat32x4Instr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   return LocationSummary::Make(kNumInputs,
                                Location::RequiresFpuRegister(),
@@ -2790,7 +2980,7 @@
 }
 
 
-LocationSummary* BoxInt32x4Instr::MakeLocationSummary() const {
+LocationSummary* BoxInt32x4Instr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -2852,7 +3042,7 @@
 }
 
 
-LocationSummary* UnboxInt32x4Instr::MakeLocationSummary() const {
+LocationSummary* UnboxInt32x4Instr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -2879,7 +3069,7 @@
 }
 
 
-LocationSummary* BinaryDoubleOpInstr::MakeLocationSummary() const {
+LocationSummary* BinaryDoubleOpInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 2;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -2907,7 +3097,7 @@
 }
 
 
-LocationSummary* BinaryFloat32x4OpInstr::MakeLocationSummary() const {
+LocationSummary* BinaryFloat32x4OpInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 2;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -2935,7 +3125,7 @@
 }
 
 
-LocationSummary* Simd32x4ShuffleInstr::MakeLocationSummary() const {
+LocationSummary* Simd32x4ShuffleInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -2977,7 +3167,7 @@
 }
 
 
-LocationSummary* Simd32x4ShuffleMixInstr::MakeLocationSummary() const {
+LocationSummary* Simd32x4ShuffleMixInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 2;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -3004,7 +3194,7 @@
 }
 
 
-LocationSummary* Simd32x4GetSignMaskInstr::MakeLocationSummary() const {
+LocationSummary* Simd32x4GetSignMaskInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -3024,7 +3214,8 @@
 }
 
 
-LocationSummary* Float32x4ConstructorInstr::MakeLocationSummary() const {
+LocationSummary* Float32x4ConstructorInstr::MakeLocationSummary(
+    bool opt) const {
   const intptr_t kNumInputs = 4;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -3061,7 +3252,7 @@
 }
 
 
-LocationSummary* Float32x4ZeroInstr::MakeLocationSummary() const {
+LocationSummary* Float32x4ZeroInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 0;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -3077,7 +3268,7 @@
 }
 
 
-LocationSummary* Float32x4SplatInstr::MakeLocationSummary() const {
+LocationSummary* Float32x4SplatInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -3098,7 +3289,7 @@
 }
 
 
-LocationSummary* Float32x4ComparisonInstr::MakeLocationSummary() const {
+LocationSummary* Float32x4ComparisonInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 2;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -3141,7 +3332,7 @@
 }
 
 
-LocationSummary* Float32x4MinMaxInstr::MakeLocationSummary() const {
+LocationSummary* Float32x4MinMaxInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 2;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -3171,7 +3362,7 @@
 }
 
 
-LocationSummary* Float32x4ScaleInstr::MakeLocationSummary() const {
+LocationSummary* Float32x4ScaleInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 2;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -3200,7 +3391,7 @@
 }
 
 
-LocationSummary* Float32x4SqrtInstr::MakeLocationSummary() const {
+LocationSummary* Float32x4SqrtInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -3231,7 +3422,7 @@
 }
 
 
-LocationSummary* Float32x4ZeroArgInstr::MakeLocationSummary() const {
+LocationSummary* Float32x4ZeroArgInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -3258,7 +3449,7 @@
 }
 
 
-LocationSummary* Float32x4ClampInstr::MakeLocationSummary() const {
+LocationSummary* Float32x4ClampInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 3;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -3281,7 +3472,7 @@
 }
 
 
-LocationSummary* Float32x4WithInstr::MakeLocationSummary() const {
+LocationSummary* Float32x4WithInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 2;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -3349,7 +3540,7 @@
 }
 
 
-LocationSummary* Float32x4ToInt32x4Instr::MakeLocationSummary() const {
+LocationSummary* Float32x4ToInt32x4Instr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -3365,7 +3556,8 @@
 }
 
 
-LocationSummary* Int32x4BoolConstructorInstr::MakeLocationSummary() const {
+LocationSummary* Int32x4BoolConstructorInstr::MakeLocationSummary(
+    bool opt) const {
   const intptr_t kNumInputs = 4;
   const intptr_t kNumTemps = 1;
   LocationSummary* summary =
@@ -3434,7 +3626,7 @@
 }
 
 
-LocationSummary* Int32x4GetFlagInstr::MakeLocationSummary() const {
+LocationSummary* Int32x4GetFlagInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -3479,7 +3671,7 @@
 }
 
 
-LocationSummary* Int32x4SelectInstr::MakeLocationSummary() const {
+LocationSummary* Int32x4SelectInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 3;
   const intptr_t kNumTemps = 1;
   LocationSummary* summary =
@@ -3513,7 +3705,7 @@
 }
 
 
-LocationSummary* Int32x4SetFlagInstr::MakeLocationSummary() const {
+LocationSummary* Int32x4SetFlagInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 2;
   const intptr_t kNumTemps = 1;
   LocationSummary* summary =
@@ -3579,7 +3771,7 @@
 }
 
 
-LocationSummary* Int32x4ToFloat32x4Instr::MakeLocationSummary() const {
+LocationSummary* Int32x4ToFloat32x4Instr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -3595,7 +3787,7 @@
 }
 
 
-LocationSummary* BinaryInt32x4OpInstr::MakeLocationSummary() const {
+LocationSummary* BinaryInt32x4OpInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 2;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -3635,7 +3827,7 @@
 }
 
 
-LocationSummary* MathUnaryInstr::MakeLocationSummary() const {
+LocationSummary* MathUnaryInstr::MakeLocationSummary(bool opt) const {
   if ((kind() == MethodRecognizer::kMathSin) ||
       (kind() == MethodRecognizer::kMathCos)) {
     // Calling convention on x64 uses XMM0 and XMM1 to pass the first two
@@ -3674,7 +3866,7 @@
 }
 
 
-LocationSummary* UnarySmiOpInstr::MakeLocationSummary() const {
+LocationSummary* UnarySmiOpInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   return LocationSummary::Make(kNumInputs,
                                Location::SameAsFirstInput(),
@@ -3707,7 +3899,7 @@
 }
 
 
-LocationSummary* UnaryDoubleOpInstr::MakeLocationSummary() const {
+LocationSummary* UnaryDoubleOpInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -3725,7 +3917,7 @@
 }
 
 
-LocationSummary* MathMinMaxInstr::MakeLocationSummary() const {
+LocationSummary* MathMinMaxInstr::MakeLocationSummary(bool opt) const {
   if (result_cid() == kDoubleCid) {
     const intptr_t kNumInputs = 2;
     const intptr_t kNumTemps = 1;
@@ -3814,7 +4006,7 @@
 }
 
 
-LocationSummary* SmiToDoubleInstr::MakeLocationSummary() const {
+LocationSummary* SmiToDoubleInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* result =
@@ -3833,7 +4025,7 @@
 }
 
 
-LocationSummary* DoubleToIntegerInstr::MakeLocationSummary() const {
+LocationSummary* DoubleToIntegerInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 1;
   LocationSummary* result =
@@ -3884,7 +4076,7 @@
 }
 
 
-LocationSummary* DoubleToSmiInstr::MakeLocationSummary() const {
+LocationSummary* DoubleToSmiInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 1;
   LocationSummary* result = new LocationSummary(
@@ -3916,7 +4108,7 @@
 }
 
 
-LocationSummary* DoubleToDoubleInstr::MakeLocationSummary() const {
+LocationSummary* DoubleToDoubleInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* result =
@@ -3946,7 +4138,7 @@
 }
 
 
-LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary() const {
+LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary(bool opt) const {
   // Calling convention on x64 uses XMM0 and XMM1 to pass the first two
   // double arguments and XMM0 to return the result. Unfortunately
   // currently we can't specify these registers because ParallelMoveResolver
@@ -4030,7 +4222,7 @@
 }
 
 
-LocationSummary* MergedMathInstr::MakeLocationSummary() const {
+LocationSummary* MergedMathInstr::MakeLocationSummary(bool opt) const {
   if (kind() == MergedMathInstr::kTruncDivMod) {
     const intptr_t kNumInputs = 2;
     const intptr_t kNumTemps = 1;
@@ -4219,7 +4411,8 @@
 }
 
 
-LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary() const {
+LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary(
+    bool opt) const {
   return MakeCallSummary();
 }
 
@@ -4260,9 +4453,11 @@
 }
 
 
-LocationSummary* BranchInstr::MakeLocationSummary() const {
-  UNREACHABLE();
-  return NULL;
+LocationSummary* BranchInstr::MakeLocationSummary(bool opt) const {
+  comparison()->InitializeLocationSummary(opt);
+  // Branches don't produce a result.
+  comparison()->locs()->set_out(Location::NoLocation());
+  return comparison()->locs();
 }
 
 
@@ -4271,7 +4466,7 @@
 }
 
 
-LocationSummary* CheckClassInstr::MakeLocationSummary() const {
+LocationSummary* CheckClassInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -4330,7 +4525,7 @@
 }
 
 
-LocationSummary* CheckSmiInstr::MakeLocationSummary() const {
+LocationSummary* CheckSmiInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
   const intptr_t kNumTemps = 0;
   LocationSummary* summary =
@@ -4349,7 +4544,7 @@
 }
 
 
-LocationSummary* CheckArrayBoundInstr::MakeLocationSummary() const {
+LocationSummary* CheckArrayBoundInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 2;
   const intptr_t kNumTemps = 0;
   LocationSummary* locs =
@@ -4404,7 +4599,7 @@
 }
 
 
-LocationSummary* UnboxIntegerInstr::MakeLocationSummary() const {
+LocationSummary* UnboxIntegerInstr::MakeLocationSummary(bool opt) const {
   UNIMPLEMENTED();
   return NULL;
 }
@@ -4415,7 +4610,7 @@
 }
 
 
-LocationSummary* BoxIntegerInstr::MakeLocationSummary() const {
+LocationSummary* BoxIntegerInstr::MakeLocationSummary(bool opt) const {
   UNIMPLEMENTED();
   return NULL;
 }
@@ -4426,7 +4621,7 @@
 }
 
 
-LocationSummary* BinaryMintOpInstr::MakeLocationSummary() const {
+LocationSummary* BinaryMintOpInstr::MakeLocationSummary(bool opt) const {
   UNIMPLEMENTED();
   return NULL;
 }
@@ -4437,7 +4632,7 @@
 }
 
 
-LocationSummary* UnaryMintOpInstr::MakeLocationSummary() const {
+LocationSummary* UnaryMintOpInstr::MakeLocationSummary(bool opt) const {
   UNIMPLEMENTED();
   return NULL;
 }
@@ -4448,7 +4643,7 @@
 }
 
 
-LocationSummary* ShiftMintOpInstr::MakeLocationSummary() const {
+LocationSummary* ShiftMintOpInstr::MakeLocationSummary(bool opt) const {
   UNIMPLEMENTED();
   return NULL;
 }
@@ -4459,7 +4654,7 @@
 }
 
 
-LocationSummary* ThrowInstr::MakeLocationSummary() const {
+LocationSummary* ThrowInstr::MakeLocationSummary(bool opt) const {
   return new LocationSummary(0, 0, LocationSummary::kCall);
 }
 
@@ -4474,7 +4669,7 @@
 }
 
 
-LocationSummary* ReThrowInstr::MakeLocationSummary() const {
+LocationSummary* ReThrowInstr::MakeLocationSummary(bool opt) const {
   return new LocationSummary(0, 0, LocationSummary::kCall);
 }
 
@@ -4514,7 +4709,7 @@
 }
 
 
-LocationSummary* GotoInstr::MakeLocationSummary() const {
+LocationSummary* GotoInstr::MakeLocationSummary(bool opt) const {
   return new LocationSummary(0, 0, LocationSummary::kNoCall);
 }
 
@@ -4543,7 +4738,7 @@
 }
 
 
-LocationSummary* CurrentContextInstr::MakeLocationSummary() const {
+LocationSummary* CurrentContextInstr::MakeLocationSummary(bool opt) const {
   return LocationSummary::Make(0,
                                Location::RequiresRegister(),
                                LocationSummary::kNoCall);
@@ -4555,7 +4750,7 @@
 }
 
 
-LocationSummary* StrictCompareInstr::MakeLocationSummary() const {
+LocationSummary* StrictCompareInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 2;
   const intptr_t kNumTemps = 0;
   if (needs_number_check()) {
@@ -4636,7 +4831,7 @@
 }
 
 
-LocationSummary* ClosureCallInstr::MakeLocationSummary() const {
+LocationSummary* ClosureCallInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 0;
   const intptr_t kNumTemps = 1;
   LocationSummary* result =
@@ -4666,7 +4861,7 @@
 }
 
 
-LocationSummary* BooleanNegateInstr::MakeLocationSummary() const {
+LocationSummary* BooleanNegateInstr::MakeLocationSummary(bool opt) const {
   return LocationSummary::Make(1,
                                Location::RequiresRegister(),
                                LocationSummary::kNoCall);
@@ -4686,7 +4881,7 @@
 }
 
 
-LocationSummary* StoreVMFieldInstr::MakeLocationSummary() const {
+LocationSummary* StoreVMFieldInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 2;
   const intptr_t kNumTemps = 0;
   LocationSummary* locs =
@@ -4712,7 +4907,7 @@
 }
 
 
-LocationSummary* AllocateObjectInstr::MakeLocationSummary() const {
+LocationSummary* AllocateObjectInstr::MakeLocationSummary(bool opt) const {
   return MakeCallSummary();
 }
 
@@ -4728,7 +4923,7 @@
 }
 
 
-LocationSummary* CreateClosureInstr::MakeLocationSummary() const {
+LocationSummary* CreateClosureInstr::MakeLocationSummary(bool opt) const {
   return MakeCallSummary();
 }
 
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index 1874127..4d05b64 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -30,6 +30,7 @@
 #include "vm/stub_code.h"
 #include "vm/symbols.h"
 #include "vm/thread.h"
+#include "vm/thread_interrupter.h"
 #include "vm/timer.h"
 #include "vm/visitor.h"
 
@@ -142,11 +143,10 @@
 
   bool success = true;
   if (message->IsOOB()) {
-    Service::HandleServiceMessage(isolate_, message->reply_port(), msg);
+    Service::HandleServiceMessage(isolate_, msg);
   } else {
     const Object& result = Object::Handle(
-        DartLibraryCalls::HandleMessage(
-            receive_port, message->reply_port(), msg));
+        DartLibraryCalls::HandleMessage(receive_port, msg));
     if (result.IsError()) {
       success = ProcessUnhandledException(msg, Error::Cast(result));
     } else {
@@ -339,13 +339,11 @@
 }
 
 void Isolate::SetCurrent(Isolate* current) {
-  Isolate* old_isolate = Current();
-  if (old_isolate != NULL) {
-    ProfilerManager::DescheduleIsolate(old_isolate);
-  }
-  Thread::SetThreadLocal(isolate_key, reinterpret_cast<uword>(current));
-  if (current != NULL) {
-    ProfilerManager::ScheduleIsolate(current);
+  Isolate* old_current = Current();
+  if (old_current != current) {
+    Profiler::EndExecution(old_current);
+    Thread::SetThreadLocal(isolate_key, reinterpret_cast<uword>(current));
+    Profiler::BeginExecution(current);
   }
 }
 
@@ -370,7 +368,7 @@
   ASSERT(result != NULL);
 
   // Setup for profiling.
-  ProfilerManager::SetupIsolateForProfiling(result);
+  Profiler::InitProfilingForIsolate(result);
 
   // TODO(5411455): For now just set the recently created isolate as
   // the current isolate.
@@ -724,6 +722,9 @@
       PrintInvokedFunctions();
     }
 
+    // Write out profiler data if requested.
+    Profiler::WriteTracing(this);
+
     // Write out the coverage data if collection has been enabled.
     CodeCoverage::Write(this);
 
@@ -744,8 +745,7 @@
   // TODO(5411455): For now just make sure there are no current isolates
   // as we are shutting down the isolate.
   SetCurrent(NULL);
-  ProfilerManager::DescheduleIsolate(this);
-  ProfilerManager::ShutdownIsolateForProfiling(this);
+  Profiler::ShutdownProfilingForIsolate(this);
 }
 
 
diff --git a/runtime/vm/isolate_test.cc b/runtime/vm/isolate_test.cc
index 2af007e..ee39fb0 100644
--- a/runtime/vm/isolate_test.cc
+++ b/runtime/vm/isolate_test.cc
@@ -23,17 +23,56 @@
 TEST_CASE(IsolateSpawn) {
   const char* kScriptChars =
       "import 'dart:isolate';\n"
+      // Ignores printed lines.
+      "var _nullPrintClosure = (String line) {};\n"
       "void entry(message) {}\n"
       "int testMain() {\n"
-      "  try {\n"
-      "    Isolate.spawn(entry, null);\n"
-      "  } catch (e) {\n"
-      "    rethrow;\n"
-      "  }\n"
-      "  return 0;\n"
+      "  Isolate.spawn(entry, null);\n"
+      // TODO(floitsch): the following code is only to bump the event loop
+      // so it executes asynchronous microtasks.
+      "  var rp = new RawReceivePort();\n"
+      "  rp.sendPort.send(null);\n"
+      "  rp.handler = (_) { rp.close(); };\n"
       "}\n";
-  Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
-  Dart_Handle result = Dart_Invoke(lib, NewString("testMain"), 0, NULL);
+
+  Dart_Handle test_lib = TestCase::LoadTestScript(kScriptChars, NULL);
+
+  // Setup the internal library's 'internalPrint' function.
+  // Necessary because asynchronous errors use "print" to print their
+  // stack trace.
+  Dart_Handle url = NewString("dart:_collection-dev");
+  DART_CHECK_VALID(url);
+  Dart_Handle internal_lib = Dart_LookupLibrary(url);
+  DART_CHECK_VALID(internal_lib);
+  Dart_Handle print = Dart_GetField(test_lib, NewString("_nullPrintClosure"));
+  Dart_Handle result = Dart_SetField(internal_lib,
+                                     NewString("_printClosure"),
+                                     print);
+
+  DART_CHECK_VALID(result);
+
+  // Setup the 'scheduleImmediate' closure.
+  url = NewString("dart:isolate");
+  DART_CHECK_VALID(url);
+  Dart_Handle isolate_lib = Dart_LookupLibrary(url);
+  DART_CHECK_VALID(isolate_lib);
+  Dart_Handle schedule_immediate_closure =
+      Dart_Invoke(isolate_lib, NewString("_getIsolateScheduleImmediateClosure"),
+                  0, NULL);
+  Dart_Handle args[1];
+  args[0] = schedule_immediate_closure;
+  url = NewString("dart:async");
+  DART_CHECK_VALID(url);
+  Dart_Handle async_lib = Dart_LookupLibrary(url);
+  DART_CHECK_VALID(async_lib);
+  DART_CHECK_VALID(Dart_Invoke(
+      async_lib, NewString("_setScheduleImmediateClosure"), 1, args));
+
+
+  result = Dart_Invoke(test_lib, NewString("testMain"), 0, NULL);
+  EXPECT(!Dart_IsError(result));
+  // Run until all ports to isolate are closed.
+  result = Dart_RunLoop();
   EXPECT_ERROR(result, "Null callback specified for isolate creation");
   EXPECT(Dart_ErrorHasException(result));
   Dart_Handle exception_result = Dart_ErrorGetException(result);
diff --git a/runtime/vm/json_stream.cc b/runtime/vm/json_stream.cc
index ae06d19..0ab2cd5 100644
--- a/runtime/vm/json_stream.cc
+++ b/runtime/vm/json_stream.cc
@@ -4,6 +4,7 @@
 
 #include "platform/assert.h"
 #include "vm/object.h"
+#include "vm/debugger.h"
 #include "vm/json_stream.h"
 
 
@@ -23,6 +24,16 @@
 }
 
 
+const char* JSONStream::LookupOption(const char* key) const {
+  for (int i = 0; i < num_options(); i++) {
+    if (!strcmp(key, option_keys_[i])) {
+      return option_values_[i];
+    }
+  }
+  return NULL;
+}
+
+
 void JSONStream::Clear() {
   buffer_.Clear();
   open_objects_ = 0;
@@ -122,6 +133,12 @@
 }
 
 
+void JSONStream::PrintValue(const SourceBreakpoint* bpt) {
+  PrintCommaIfNeeded();
+  bpt->PrintToJSONStream(this);
+}
+
+
 void JSONStream::PrintPropertyBool(const char* name, bool b) {
   PrintPropertyName(name);
   PrintValueBool(b);
diff --git a/runtime/vm/json_stream.h b/runtime/vm/json_stream.h
index 5410314..9829995 100644
--- a/runtime/vm/json_stream.h
+++ b/runtime/vm/json_stream.h
@@ -15,6 +15,7 @@
 class JSONArray;
 class JSONObject;
 class Object;
+class SourceBreakpoint;
 
 class JSONStream : ValueObject {
  public:
@@ -40,6 +41,8 @@
     return option_values_[i];
   }
 
+  const char* LookupOption(const char* key) const;
+
  private:
   void Clear();
 
@@ -56,6 +59,7 @@
   void PrintfValue(const char* format, ...) PRINTF_ATTRIBUTE(2, 3);
   void PrintValue(const Object& o, bool ref = true);
   void PrintValue(const Field& f, const Instance& instance, bool ref = true);
+  void PrintValue(const SourceBreakpoint* bpt);
 
   void PrintPropertyBool(const char* name, bool b);
   void PrintProperty(const char* name, intptr_t i);
@@ -154,6 +158,9 @@
                 bool ref = true) const {
     stream_->PrintValue(field, instance, ref);
   }
+  void AddValue(const SourceBreakpoint* bpt) const {
+    stream_->PrintValue(bpt);
+  }
   void AddValueF(const char* format, ...) const PRINTF_ATTRIBUTE(2, 3);
 
  private:
diff --git a/runtime/vm/message.h b/runtime/vm/message.h
index 4b894174e..e6a6f96 100644
--- a/runtime/vm/message.h
+++ b/runtime/vm/message.h
@@ -29,13 +29,9 @@
   // A new message to be sent between two isolates. The data handed to this
   // message will be disposed by calling free() once the message object is
   // being destructed (after delivery or when the receiving port is closed).
-  //
-  // If reply_port is kIllegalPort, then there is no reply port.
-  Message(Dart_Port dest_port, Dart_Port reply_port, uint8_t* data,
-          intptr_t len, Priority priority)
+  Message(Dart_Port dest_port, uint8_t* data, intptr_t len, Priority priority)
       : next_(NULL),
         dest_port_(dest_port),
-        reply_port_(reply_port),
         data_(data),
         len_(len),
         priority_(priority) {}
@@ -44,7 +40,6 @@
   }
 
   Dart_Port dest_port() const { return dest_port_; }
-  Dart_Port reply_port() const { return reply_port_; }
   uint8_t* data() const { return data_; }
   intptr_t len() const { return len_; }
   Priority priority() const { return priority_; }
@@ -56,7 +51,6 @@
 
   Message* next_;
   Dart_Port dest_port_;
-  Dart_Port reply_port_;
   uint8_t* data_;
   intptr_t len_;
   Priority priority_;
diff --git a/runtime/vm/message_handler.cc b/runtime/vm/message_handler.cc
index a1df2a8..332a6e6 100644
--- a/runtime/vm/message_handler.cc
+++ b/runtime/vm/message_handler.cc
@@ -97,10 +97,9 @@
     }
     OS::Print("[>] Posting message:\n"
               "\tsource:     %s\n"
-              "\treply_port: %" Pd64 "\n"
               "\tdest:       %s\n"
               "\tdest_port:  %" Pd64 "\n",
-              source_name, message->reply_port(), name(), message->dest_port());
+              source_name, name(), message->dest_port());
   }
 
   Message::Priority saved_priority = message->priority();
diff --git a/runtime/vm/message_handler_test.cc b/runtime/vm/message_handler_test.cc
index 7fcf7dd..fbf69f5 100644
--- a/runtime/vm/message_handler_test.cc
+++ b/runtime/vm/message_handler_test.cc
@@ -123,7 +123,7 @@
   EXPECT_EQ(0, handler.notify_count());
 
   // Post a message.
-  Message* message = new Message(0, 0, NULL, 0, Message::kNormalPriority);
+  Message* message = new Message(0, NULL, 0, Message::kNormalPriority);
   handler_peer.PostMessage(message);
 
   // The notify callback is called.
@@ -135,7 +135,7 @@
   delete message;
 
   // Post an oob message.
-  message = new Message(0, 0, NULL, 0, Message::kOOBPriority);
+  message = new Message(0, NULL, 0, Message::kOOBPriority);
   handler_peer.PostMessage(message);
 
   // The notify callback is called.
@@ -151,9 +151,9 @@
 UNIT_TEST_CASE(MessageHandler_ClosePort) {
   TestMessageHandler handler;
   MessageHandlerTestPeer handler_peer(&handler);
-  Message* message1 = new Message(1, 0, NULL, 0, Message::kNormalPriority);
+  Message* message1 = new Message(1, NULL, 0, Message::kNormalPriority);
   handler_peer.PostMessage(message1);
-  Message* message2 = new Message(2, 0, NULL, 0, Message::kNormalPriority);
+  Message* message2 = new Message(2, NULL, 0, Message::kNormalPriority);
   handler_peer.PostMessage(message2);
 
   handler_peer.ClosePort(1);
@@ -169,9 +169,9 @@
 UNIT_TEST_CASE(MessageHandler_CloseAllPorts) {
   TestMessageHandler handler;
   MessageHandlerTestPeer handler_peer(&handler);
-  Message* message1 = new Message(1, 0, NULL, 0, Message::kNormalPriority);
+  Message* message1 = new Message(1, NULL, 0, Message::kNormalPriority);
   handler_peer.PostMessage(message1);
-  Message* message2 = new Message(2, 0, NULL, 0, Message::kNormalPriority);
+  Message* message2 = new Message(2, NULL, 0, Message::kNormalPriority);
   handler_peer.PostMessage(message2);
 
   handler_peer.CloseAllPorts();
@@ -187,13 +187,13 @@
   Dart_Port port1 = PortMap::CreatePort(&handler);
   Dart_Port port2 = PortMap::CreatePort(&handler);
   Dart_Port port3 = PortMap::CreatePort(&handler);
-  Message* message1 = new Message(port1, 0, NULL, 0, Message::kNormalPriority);
+  Message* message1 = new Message(port1, NULL, 0, Message::kNormalPriority);
   handler_peer.PostMessage(message1);
-  Message* oob_message1 = new Message(port2, 0, NULL, 0, Message::kOOBPriority);
+  Message* oob_message1 = new Message(port2, NULL, 0, Message::kOOBPriority);
   handler_peer.PostMessage(oob_message1);
-  Message* message2 = new Message(port2, 0, NULL, 0, Message::kNormalPriority);
+  Message* message2 = new Message(port2, NULL, 0, Message::kNormalPriority);
   handler_peer.PostMessage(message2);
-  Message* oob_message2 = new Message(port3, 0, NULL, 0, Message::kOOBPriority);
+  Message* oob_message2 = new Message(port3, NULL, 0, Message::kOOBPriority);
   handler_peer.PostMessage(oob_message2);
 
   // We handle both oob messages and a single normal message.
@@ -214,13 +214,13 @@
   Dart_Port port2 = PortMap::CreatePort(&handler);
   Dart_Port port3 = PortMap::CreatePort(&handler);
   Dart_Port port4 = PortMap::CreatePort(&handler);
-  Message* message1 = new Message(port1, 0, NULL, 0, Message::kNormalPriority);
+  Message* message1 = new Message(port1, NULL, 0, Message::kNormalPriority);
   handler_peer.PostMessage(message1);
-  Message* message2 = new Message(port2, 0, NULL, 0, Message::kNormalPriority);
+  Message* message2 = new Message(port2, NULL, 0, Message::kNormalPriority);
   handler_peer.PostMessage(message2);
-  Message* oob_message1 = new Message(port3, 0, NULL, 0, Message::kOOBPriority);
+  Message* oob_message1 = new Message(port3, NULL, 0, Message::kOOBPriority);
   handler_peer.PostMessage(oob_message1);
-  Message* oob_message2 = new Message(port4, 0, NULL, 0, Message::kOOBPriority);
+  Message* oob_message2 = new Message(port4, NULL, 0, Message::kOOBPriority);
   handler_peer.PostMessage(oob_message2);
 
   // We handle both oob messages but no normal messages.
@@ -246,7 +246,7 @@
   MessageHandlerTestPeer handler_peer(handler);
   for (int i = 0; i < info->count; i++) {
     Message* message =
-        new Message(info->ports[i], 0, NULL, 0, Message::kNormalPriority);
+        new Message(info->ports[i], NULL, 0, Message::kNormalPriority);
     handler_peer.PostMessage(message);
   }
 }
@@ -267,7 +267,7 @@
               TestEndFunction,
               reinterpret_cast<uword>(&handler));
   Dart_Port port = PortMap::CreatePort(&handler);
-  Message* message = new Message(port, 0, NULL, 0, Message::kNormalPriority);
+  Message* message = new Message(port, NULL, 0, Message::kNormalPriority);
   handler_peer.PostMessage(message);
 
   // Wait for the first message to be handled.
diff --git a/runtime/vm/message_test.cc b/runtime/vm/message_test.cc
index e2bb672..bc47b39 100644
--- a/runtime/vm/message_test.cc
+++ b/runtime/vm/message_test.cc
@@ -45,13 +45,13 @@
 
   // Add two messages.
   Message* msg1 =
-      new Message(port, 0, AllocMsg(str1), strlen(str1) + 1,
+      new Message(port, AllocMsg(str1), strlen(str1) + 1,
                   Message::kNormalPriority);
   queue.Enqueue(msg1);
   EXPECT(queue_peer.HasMessage());
 
   Message* msg2 =
-      new Message(port, 0, AllocMsg(str2), strlen(str2) + 1,
+      new Message(port, AllocMsg(str2), strlen(str2) + 1,
                   Message::kNormalPriority);
 
   queue.Enqueue(msg2);
@@ -84,11 +84,11 @@
 
   // Add two messages.
   Message* msg1 =
-      new Message(port1, 0, AllocMsg(str1), strlen(str1) + 1,
+      new Message(port1, AllocMsg(str1), strlen(str1) + 1,
                   Message::kNormalPriority);
   queue.Enqueue(msg1);
   Message* msg2 =
-      new Message(port2, 0, AllocMsg(str2), strlen(str2) + 1,
+      new Message(port2, AllocMsg(str2), strlen(str2) + 1,
                   Message::kNormalPriority);
   queue.Enqueue(msg2);
 
diff --git a/runtime/vm/native_api_impl.cc b/runtime/vm/native_api_impl.cc
index cb21834..9ff6f7f 100644
--- a/runtime/vm/native_api_impl.cc
+++ b/runtime/vm/native_api_impl.cc
@@ -31,8 +31,7 @@
 
   // Post the message at the given port.
   return PortMap::PostMessage(new Message(
-      port_id, Message::kIllegalPort, buffer, writer.BytesWritten(),
-      Message::kNormalPriority));
+      port_id, buffer, writer.BytesWritten(), Message::kNormalPriority));
 }
 
 
diff --git a/runtime/vm/native_arguments.h b/runtime/vm/native_arguments.h
index 5194493..f25e723 100644
--- a/runtime/vm/native_arguments.h
+++ b/runtime/vm/native_arguments.h
@@ -131,6 +131,9 @@
   static intptr_t retval_offset() {
     return OFFSET_OF(NativeArguments, retval_);
   }
+  static intptr_t AutoSetupScopeMask() {
+    return AutoSetupScopeBits::mask_in_place();
+  }
 
   static int ParameterCountForResolution(const Function& function) {
     ASSERT(function.is_native());
@@ -157,7 +160,11 @@
     if (function.IsClosureFunction()) {
       function_bits |= kClosureFunctionBit;
     }
-    return FunctionBits::update(function_bits, tag);
+    tag = FunctionBits::update(function_bits, tag);
+    if (function.IsNativeAutoSetupScope()) {
+      tag = AutoSetupScopeBits::update(1, tag);
+    }
+    return tag;
   }
 
  private:
@@ -170,9 +177,11 @@
     kArgcSize = 24,
     kFunctionBit = 24,
     kFunctionSize = 2,
+    kAutoSetupScopeBit = 26,
   };
   class ArgcBits : public BitField<int, kArgcBit, kArgcSize> {};
   class FunctionBits : public BitField<int, kFunctionBit, kFunctionSize> {};
+  class AutoSetupScopeBits : public BitField<int, kAutoSetupScopeBit, 1> {};
   friend class Api;
   friend class BootstrapNatives;
   friend class Simulator;
diff --git a/runtime/vm/native_entry.cc b/runtime/vm/native_entry.cc
index c16af33..af4bd96 100644
--- a/runtime/vm/native_entry.cc
+++ b/runtime/vm/native_entry.cc
@@ -22,7 +22,8 @@
 
 NativeFunction NativeEntry::ResolveNative(const Library& library,
                                           const String& function_name,
-                                          int number_of_arguments) {
+                                          int number_of_arguments,
+                                          bool* auto_setup_scope) {
   // Now resolve the native function to the corresponding native entrypoint.
   if (library.native_entry_resolver() == 0) {
     // Native methods are not allowed in the library to which this
@@ -33,7 +34,7 @@
   Dart_NativeEntryResolver resolver = library.native_entry_resolver();
   Dart_NativeFunction native_function =
       resolver(Api::NewHandle(Isolate::Current(), function_name.raw()),
-               number_of_arguments);
+               number_of_arguments, auto_setup_scope);
   Dart_ExitScope();  // Exit the Dart API scope.
   return reinterpret_cast<NativeFunction>(native_function);
 }
diff --git a/runtime/vm/native_entry.h b/runtime/vm/native_entry.h
index e2dc1cd..6c98d3a 100644
--- a/runtime/vm/native_entry.h
+++ b/runtime/vm/native_entry.h
@@ -93,7 +93,8 @@
   // Resolve specified dart native function to the actual native entrypoint.
   static NativeFunction ResolveNative(const Library& library,
                                       const String& function_name,
-                                      int number_of_arguments);
+                                      int number_of_arguments,
+                                      bool* auto_setup_scope);
   static void NativeCallWrapper(Dart_NativeArguments args,
                                 Dart_NativeFunction func);
   static const ExternalLabel& NativeCallWrapperLabel();
diff --git a/runtime/vm/native_symbol_linux.cc b/runtime/vm/native_symbol_linux.cc
index 225a4b0..4a0e12f 100644
--- a/runtime/vm/native_symbol_linux.cc
+++ b/runtime/vm/native_symbol_linux.cc
@@ -8,7 +8,7 @@
 #include "vm/native_symbol.h"
 #include "vm/thread.h"
 
-
+#include <cxxabi.h>  // NOLINT
 #include <dlfcn.h>  // NOLINT
 
 namespace dart {
@@ -30,6 +30,11 @@
   if (info.dli_sname == NULL) {
     return NULL;
   }
+  int status;
+  char* demangled = abi::__cxa_demangle(info.dli_sname, NULL, NULL, &status);
+  if (status == 0) {
+    return demangled;
+  }
   return strdup(info.dli_sname);
 }
 
diff --git a/runtime/vm/native_symbol_macos.cc b/runtime/vm/native_symbol_macos.cc
index 3b240bd..4de33ce 100644
--- a/runtime/vm/native_symbol_macos.cc
+++ b/runtime/vm/native_symbol_macos.cc
@@ -8,6 +8,7 @@
 #include "vm/native_symbol.h"
 #include "vm/thread.h"
 
+#include <cxxabi.h>  // NOLINT
 #include <dlfcn.h>  // NOLINT
 
 namespace dart {
@@ -29,6 +30,11 @@
   if (info.dli_sname == NULL) {
     return NULL;
   }
+  int status;
+  char* demangled = abi::__cxa_demangle(info.dli_sname, NULL, NULL, &status);
+  if (status == 0) {
+    return demangled;
+  }
   return strdup(info.dli_sname);
 }
 
diff --git a/runtime/vm/native_symbol_win.cc b/runtime/vm/native_symbol_win.cc
index 7e8350f..b44633f 100644
--- a/runtime/vm/native_symbol_win.cc
+++ b/runtime/vm/native_symbol_win.cc
@@ -32,7 +32,7 @@
 
 
 void NativeSymbolResolver::ShutdownOnce() {
-  ScopedMutex lock(lock_);
+  MutexLocker lock(lock_);
   if (!running_) {
     return;
   }
@@ -52,7 +52,7 @@
   static const intptr_t kSymbolInfoSize = sizeof(SYMBOL_INFO);  // NOLINT.
   static char buffer[kSymbolInfoSize + kMaxNameLength];
   static char name_buffer[kMaxNameLength];
-  ScopedMutex lock(lock_);
+  MutexLocker lock(lock_);
   if (!running_) {
     return NULL;
   }
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 01c7690..99bad2b6 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -143,7 +143,6 @@
 RawClass* Object::unhandled_exception_class_ =
     reinterpret_cast<RawClass*>(RAW_NULL);
 RawClass* Object::unwind_error_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
-#undef RAW_NULL
 
 
 const double MegamorphicCache::kLoadFactor = 0.75;
@@ -1612,7 +1611,12 @@
   // finalization time. The optimizer may canonicalize instantiated function
   // types of the same signature class, but these will be added after the
   // uninstantiated signature class at index 0.
-  const Array& signature_types = Array::Handle(canonical_types());
+  Array& signature_types = Array::Handle();
+  signature_types ^= canonical_types();
+  if (signature_types.IsNull()) {
+    set_canonical_types(empty_array());
+    signature_types ^= canonical_types();
+  }
   // The canonical_types array is initialized to the empty array.
   ASSERT(!signature_types.IsNull());
   if (signature_types.Length() > 0) {
@@ -1736,7 +1740,6 @@
   }
   StorePointer(&raw_ptr()->interfaces_, Object::empty_array().raw());
   StorePointer(&raw_ptr()->constants_, Object::empty_array().raw());
-  StorePointer(&raw_ptr()->canonical_types_, Object::empty_array().raw());
   StorePointer(&raw_ptr()->functions_, Object::empty_array().raw());
   StorePointer(&raw_ptr()->fields_, Object::empty_array().raw());
   StorePointer(&raw_ptr()->invocation_dispatcher_cache_,
@@ -2355,7 +2358,7 @@
   eval_func.set_result_type(Type::Handle(Type::DynamicType()));
   eval_func.set_num_fixed_parameters(0);
   eval_func.SetNumOptionalParameters(0, true);
-  eval_func.set_is_optimizable(false);
+  eval_func.SetIsOptimizable(false);
 
   const Array& args = Array::Handle(Array::New(0));
   const Object& result =
@@ -2719,11 +2722,11 @@
 }
 
 
-RawArray* Class::canonical_types() const {
+RawObject* Class::canonical_types() const {
   return raw_ptr()->canonical_types_;
 }
 
-void Class::set_canonical_types(const Array& value) const {
+void Class::set_canonical_types(const Object& value) const {
   ASSERT(!value.IsNull());
   StorePointer(&raw_ptr()->canonical_types_, value.raw());
 }
@@ -4551,13 +4554,16 @@
 }
 
 
-bool Function::is_optimizable() const {
+bool Function::IsOptimizable() const {
   if (FLAG_coverage_dir != NULL) {
     // Do not optimize if collecting coverage data.
     return false;
   }
-  if (OptimizableBit::decode(raw_ptr()->kind_tag_) &&
-      (script() != Script::null()) &&
+  if (is_native()) {
+    // Native methods don't need to be optimized.
+    return false;
+  }
+  if (is_optimizable() && (script() != Script::null()) &&
       ((end_token_pos() - token_pos()) < FLAG_huge_method_cutoff_in_tokens)) {
     // Additional check needed for implicit getters.
     if (HasCode() &&
@@ -4572,6 +4578,22 @@
 }
 
 
+bool Function::IsNativeAutoSetupScope() const {
+  return is_native() ? is_optimizable() : false;
+}
+
+
+void Function::SetIsOptimizable(bool value) const {
+  ASSERT(!is_native());
+  set_is_optimizable(value);
+}
+
+
+void Function::SetIsNativeAutoSetupScope(bool value) const {
+  ASSERT(is_native());
+  set_is_optimizable(value);
+}
+
 void Function::set_is_optimizable(bool value) const {
   set_kind_tag(OptimizableBit::update(value, raw_ptr()->kind_tag_));
 }
@@ -5093,7 +5115,7 @@
   result.set_deoptimization_counter(0);
   result.set_optimized_instruction_count(0);
   result.set_optimized_call_site_count(0);
-  result.set_is_optimizable(true);
+  result.set_is_optimizable(is_native ? false : true);
   result.set_has_finally(false);
   result.set_is_inlinable(true);
   if (kind == RawFunction::kClosureFunction) {
@@ -5533,7 +5555,7 @@
   // optimizing compiler can eliminate the call to the static initializer
   // via constant folding.
   init_function.set_is_visible(false);
-  init_function.set_is_optimizable(false);
+  init_function.SetIsOptimizable(false);
   init_function.set_is_inlinable(false);
   init_function.set_saved_static_field(field);
   return init_function.raw();
@@ -5855,6 +5877,7 @@
   result.set_owner(owner);
   result.set_token_pos(token_pos);
   result.set_has_initializer(false);
+  result.set_is_unboxing_candidate(true);
   result.set_guarded_cid(kIllegalCid);
   result.set_is_nullable(false);
   // Presently, we only attempt to remember the list length for final fields.
@@ -8833,7 +8856,7 @@
     return;
   }
   // Only check ids for unoptimized code that is optimizable.
-  if (!function.is_optimizable()) return;
+  if (!function.IsOptimizable()) return;
   for (intptr_t i = 0; i < Length(); i++) {
     PcDescriptors::Kind kind = DescriptorKind(i);
     // 'deopt_id' is set for kDeopt and kIcCall and must be unique for one kind.
@@ -11082,7 +11105,7 @@
   eval_func.set_result_type(Type::Handle(Type::DynamicType()));
   eval_func.set_num_fixed_parameters(1);
   eval_func.SetNumOptionalParameters(0, true);
-  eval_func.set_is_optimizable(false);
+  eval_func.SetIsOptimizable(false);
 
   const Array& args = Array::Handle(Array::New(1));
   args.SetAt(0, *this);
@@ -11228,13 +11251,16 @@
     return Type::NullType();
   }
   const Class& cls = Class::Handle(clazz());
-  AbstractTypeArguments& type_arguments = AbstractTypeArguments::Handle();
-  if (cls.NumTypeArguments() > 0) {
-    type_arguments = GetTypeArguments();
+  Type& type = Type::Handle(cls.CanonicalType());
+  if (type.IsNull()) {
+    AbstractTypeArguments& type_arguments = AbstractTypeArguments::Handle();
+    if (cls.NumTypeArguments() > 0) {
+      type_arguments = GetTypeArguments();
+    }
+    type = Type::New(cls, type_arguments, Scanner::kDummyTokenIndex);
+    type.SetIsFinalized();
+    type ^= type.Canonicalize();
   }
-  const Type& type = Type::Handle(
-      Type::New(cls, type_arguments, Scanner::kDummyTokenIndex));
-  type.SetIsFinalized();
   return type.raw();
 }
 
@@ -11434,7 +11460,7 @@
 }
 
 
-const char* Instance::ToUserCString(intptr_t maxLen) const {
+const char* Instance::ToUserCString(intptr_t max_len, intptr_t nesting) const {
   if (raw() == Object::sentinel().raw()) {
     return "<not initialized>";
   } else if (raw() == Object::transition_sentinel().raw()) {
@@ -11958,13 +11984,23 @@
 
 RawType* Type::NewNonParameterizedType(const Class& type_class) {
   ASSERT(type_class.NumTypeArguments() == 0);
-  const TypeArguments& no_type_arguments = TypeArguments::Handle();
-  Type& type = Type::Handle();
-  type ^= Type::New(Object::Handle(type_class.raw()),
-                    no_type_arguments,
-                    Scanner::kDummyTokenIndex);
-  type.SetIsFinalized();
-  type ^= type.Canonicalize();
+  if (type_class.raw() == Object::dynamic_class()) {
+    // If the dynamic type has not been setup in the VM isolate, then we need
+    // to allocate it here.
+    if (Object::dynamic_type() != reinterpret_cast<RawType*>(RAW_NULL)) {
+      return Object::dynamic_type();
+    }
+    ASSERT(Isolate::Current() == Dart::vm_isolate());
+  }
+  Type& type = Type::Handle(type_class.CanonicalType());
+  if (type.IsNull()) {
+    const TypeArguments& no_type_arguments = TypeArguments::Handle();
+    type ^= Type::New(Object::Handle(type_class.raw()),
+                      no_type_arguments,
+                      Scanner::kDummyTokenIndex);
+    type.SetIsFinalized();
+    type ^= type.Canonicalize();
+  }
   return type.raw();
 }
 
@@ -12201,18 +12237,35 @@
     ASSERT(IsMalformed() || AbstractTypeArguments::Handle(arguments()).IsOld());
     return this->raw();
   }
-  const Class& cls = Class::Handle(type_class());
-  Array& canonical_types = Array::Handle(cls.canonical_types());
+  Isolate* isolate = Isolate::Current();
+  Type& type = Type::Handle(isolate);
+  const Class& cls = Class::Handle(isolate, type_class());
+  if (cls.raw() == Object::dynamic_class() && (isolate != Dart::vm_isolate())) {
+    return Object::dynamic_type();
+  }
+  // Fast canonical lookup/registry for simple types.
+  if ((cls.NumTypeArguments() == 0) && !cls.IsSignatureClass()) {
+    type = cls.CanonicalType();
+    if (type.IsNull()) {
+      ASSERT(!cls.raw()->IsVMHeapObject() || (isolate == Dart::vm_isolate()));
+      cls.set_canonical_types(*this);
+      SetCanonical();
+      return this->raw();
+    }
+    ASSERT(this->Equals(type));
+    return type.raw();
+  }
+
+  Array& canonical_types = Array::Handle(isolate);
+  canonical_types ^= cls.canonical_types();
   if (canonical_types.IsNull()) {
-    // Types defined in the VM isolate are canonicalized via the object store.
-    return this->raw();
+    canonical_types = empty_array().raw();
   }
   const intptr_t canonical_types_len = canonical_types.Length();
   // Linear search to see whether this type is already present in the
   // list of canonicalized types.
   // TODO(asiva): Try to re-factor this lookup code to make sharing
   // easy between the 4 versions of this loop.
-  Type& type = Type::Handle();
   intptr_t index = 0;
   while (index < canonical_types_len) {
     type ^= canonical_types.At(index);
@@ -12226,7 +12279,8 @@
     index++;
   }
   // Canonicalize the type arguments.
-  AbstractTypeArguments& type_args = AbstractTypeArguments::Handle(arguments());
+  AbstractTypeArguments& type_args =
+      AbstractTypeArguments::Handle(isolate, arguments());
   ASSERT(type_args.IsNull() || (type_args.Length() == cls.NumTypeArguments()));
   type_args = type_args.Canonicalize();
   set_arguments(type_args);
@@ -12234,8 +12288,8 @@
   if (index == canonical_types_len) {
     const intptr_t kLengthIncrement = 2;  // Raw and parameterized.
     const intptr_t new_length = canonical_types.Length() + kLengthIncrement;
-    const Array& new_canonical_types =
-        Array::Handle(Array::Grow(canonical_types, new_length, Heap::kOld));
+    const Array& new_canonical_types = Array::Handle(
+        isolate, Array::Grow(canonical_types, new_length, Heap::kOld));
     cls.set_canonical_types(new_canonical_types);
     new_canonical_types.SetAt(index, *this);
   } else {
@@ -12253,11 +12307,11 @@
     // of the super class of the owner class of its signature function will be
     // prepended to the type argument vector during class finalization.
     const TypeArguments& type_params =
-      TypeArguments::Handle(cls.type_parameters());
+      TypeArguments::Handle(isolate, cls.type_parameters());
     const intptr_t num_type_params = cls.NumTypeParameters();
     const intptr_t num_type_args = cls.NumTypeArguments();
-    TypeParameter& type_arg = TypeParameter::Handle();
-    TypeParameter& type_param = TypeParameter::Handle();
+    TypeParameter& type_arg = TypeParameter::Handle(isolate);
+    TypeParameter& type_param = TypeParameter::Handle(isolate);
     for (intptr_t i = 0; i < num_type_params; i++) {
       type_arg ^= type_args.TypeAt(num_type_args - num_type_params + i);
       type_param ^= type_params.TypeAt(i);
@@ -14433,33 +14487,34 @@
 }
 
 
-static bool IsAsciiPrintChar(intptr_t codePoint) {
-  return codePoint >= ' ' && codePoint <= '~';
+static bool IsAsciiPrintChar(intptr_t code_point) {
+  return code_point >= ' ' && code_point <= '~';
 }
 
 
 // Does not null-terminate.
-intptr_t String::EscapedString(char* buffer, int maxLen) const {
+intptr_t String::EscapedString(char* buffer, int max_len) const {
   int pos = 0;
 
   CodePointIterator cpi(*this);
   while (cpi.Next()) {
-    int32_t codePoint = cpi.Current();
-    if (IsSpecialCharacter(codePoint)) {
-      if (pos + 2 > maxLen) {
+    int32_t code_point = cpi.Current();
+    if (IsSpecialCharacter(code_point)) {
+      if (pos + 2 > max_len) {
         return pos;
       }
       buffer[pos++] = '\\';
-      buffer[pos++] = SpecialCharacter(codePoint);
-    } else if (IsAsciiPrintChar(codePoint)) {
-      buffer[pos++] = codePoint;
+      buffer[pos++] = SpecialCharacter(code_point);
+    } else if (IsAsciiPrintChar(code_point)) {
+      buffer[pos++] = code_point;
     } else {
-      if (pos + 6 > maxLen) {
+      if (pos + 6 > max_len) {
         return pos;
       }
-      pos += OS::SNPrint((buffer + pos), (maxLen - pos), "\\u%04x", codePoint);
+      pos += OS::SNPrint((buffer + pos), (max_len - pos),
+                         "\\u%04x", code_point);
     }
-    if (pos == maxLen) {
+    if (pos == max_len) {
       return pos;
     }
   }
@@ -14467,20 +14522,20 @@
 }
 
 
-intptr_t String::EscapedStringLen(intptr_t tooLong) const {
+intptr_t String::EscapedStringLen(intptr_t too_long) const {
   intptr_t len = 0;
 
   CodePointIterator cpi(*this);
   while (cpi.Next()) {
-    int32_t codePoint = cpi.Current();
-    if (IsSpecialCharacter(codePoint)) {
+    int32_t code_point = cpi.Current();
+    if (IsSpecialCharacter(code_point)) {
       len += 2;  // e.g. "\n"
-    } else if (IsAsciiPrintChar(codePoint)) {
+    } else if (IsAsciiPrintChar(code_point)) {
       len += 1;
     } else {
       len += 6;  // e.g. "\u0000".
     }
-    if (len > tooLong) {
+    if (len > too_long) {
       // No point going further.
       break;
     }
@@ -14489,36 +14544,36 @@
 }
 
 
-const char* String::ToUserCString(intptr_t maxLen) const {
+const char* String::ToUserCString(intptr_t max_len, intptr_t nesting) const {
   // Compute the needed length for the buffer.
-  const intptr_t escapedLen = EscapedStringLen(maxLen);
-  intptr_t printLen = escapedLen;
-  intptr_t bufferLen = escapedLen + 2;  // +2 for quotes.
-  if (bufferLen > maxLen) {
-    bufferLen = maxLen;     // Truncate.
-    printLen = maxLen - 5;  // -2 for quotes, -3 for elipsis.
+  const intptr_t escaped_len = EscapedStringLen(max_len);
+  intptr_t print_len = escaped_len;
+  intptr_t buffer_len = escaped_len + 2;  // +2 for quotes.
+  if (buffer_len > max_len) {
+    buffer_len = max_len;     // Truncate.
+    print_len = max_len - 5;  // -2 for quotes, -3 for elipsis.
   }
 
   // Allocate the buffer.
   Zone* zone = Isolate::Current()->current_zone();
-  char* buffer = zone->Alloc<char>(bufferLen + 1);
+  char* buffer = zone->Alloc<char>(buffer_len + 1);
 
   // Leading quote.
   intptr_t pos = 0;
   buffer[pos++] = '\"';
 
   // Print escaped string.
-  pos += EscapedString((buffer + pos), printLen);
+  pos += EscapedString((buffer + pos), print_len);
 
   // Trailing quote.
   buffer[pos++] = '\"';
 
-  if (printLen < escapedLen) {
+  if (print_len < escaped_len) {
     buffer[pos++] = '.';
     buffer[pos++] = '.';
     buffer[pos++] = '.';
   }
-  ASSERT(pos <= bufferLen);
+  ASSERT(pos <= buffer_len);
   buffer[pos++] = '\0';
 
   return buffer;
@@ -15581,6 +15636,107 @@
 }
 
 
+const char* GrowableObjectArray::ToUserCString(intptr_t max_len,
+                                               intptr_t nesting) const {
+  if (Length() == 0) {
+    return "[]";
+  }
+  if (nesting > 3) {
+    return "[...]";
+  }
+
+  Isolate* isolate = Isolate::Current();
+  Zone* zone = isolate->current_zone();
+  Object& obj = Object::Handle(isolate);
+  Instance& element = Instance::Handle(isolate);
+
+  // Pre-print the suffix that we will use if the string is truncated.
+  // It is important to know the suffix length when deciding where to
+  // limit the list.
+  const intptr_t kMaxTruncSuffixLen = 16;
+  char trunc_suffix[kMaxTruncSuffixLen];
+  intptr_t trunc_suffix_len;
+  if (nesting == 0) {
+    trunc_suffix_len = OS::SNPrint(trunc_suffix, 16, "...](length:%" Pd ")",
+                                   Length());
+  } else {
+    trunc_suffix_len = OS::SNPrint(trunc_suffix, 16, "...]");
+  }
+  bool truncate = false;
+
+  const int kMaxPrintElements = 128;
+  const char* strings[kMaxPrintElements];
+  intptr_t print_len = 1;  // +1 for "["
+
+  // Figure out how many elements will fit in the string.
+  int i = 0;
+  while (i < Length()) {
+    if (i == kMaxPrintElements) {
+      if (i < Length()) {
+        truncate = true;
+      }
+      break;
+    }
+    obj = At(i);
+    if (!obj.IsInstance()) {
+      // Bail.
+      UNREACHABLE();
+      return "[<invalid list>]";
+    }
+    element ^= obj.raw();
+
+    // Choose max child length.  This is chosen so that it is small
+    // enough to maybe fit but not so small that we can't print
+    // anything.
+    int child_max_len = max_len - print_len;
+    if ((i + 1) < Length()) {
+      child_max_len -= (trunc_suffix_len + 1);  // 1 for ","
+    } else {
+      child_max_len -= 1;  // 1 for "]"
+    }
+    if (child_max_len < 8) {
+      child_max_len = 8;
+    }
+
+    strings[i] = element.ToUserCString(child_max_len,  nesting + 1);
+    print_len += strlen(strings[i]) + 1;  // +1 for "," or "]"
+    i++;
+    if (print_len > max_len) {
+      truncate = true;
+      break;
+    }
+  }
+  if (truncate) {
+    // Go backwards until there is enough room for the truncation suffix.
+    while (i >= 0 && (print_len + trunc_suffix_len) > max_len) {
+      i--;
+      print_len -= (strlen(strings[i]) + 1);  // +1 for ","
+    }
+  }
+
+  // Finally, allocate and print the string.
+  int num_to_print = i;
+  char* buffer = zone->Alloc<char>(print_len + 1);  // +1 for "\0"
+  intptr_t pos = 0;
+  buffer[pos++] = '[';
+  for (i = 0; i < num_to_print; i++) {
+    if ((i + 1) == Length()) {
+      pos += OS::SNPrint((buffer + pos), (max_len + 1 - pos),
+                         "%s]", strings[i]);
+    } else {
+      pos += OS::SNPrint((buffer + pos), (max_len + 1 - pos),
+                         "%s,", strings[i]);
+    }
+  }
+  if (i < Length()) {
+    pos += OS::SNPrint((buffer + pos), (max_len + 1 - pos), "%s", trunc_suffix);
+  }
+  ASSERT(pos <= max_len);
+  buffer[pos] = '\0';
+  return buffer;
+}
+
+
 void GrowableObjectArray::PrintToJSONStream(JSONStream* stream,
                                             bool ref) const {
   Instance::PrintToJSONStream(stream, ref);
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 51d6418..93c865f 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -778,6 +778,13 @@
     return OFFSET_OF(RawClass, type_arguments_field_offset_in_words_);
   }
 
+  RawType* CanonicalType() const {
+    if ((NumTypeArguments() == 0) && !IsSignatureClass()) {
+      return reinterpret_cast<RawType*>(raw_ptr()->canonical_types_);
+    }
+    return reinterpret_cast<RawType*>(Object::null());
+  }
+
   // The super type of this class, Object type if not explicitly specified.
   // Note that the super type may be bounded, as in this example:
   // class C<T> extends S<T> { }; class S<T extends num> { };
@@ -1084,8 +1091,8 @@
 
   void set_constants(const Array& value) const;
 
-  void set_canonical_types(const Array& value) const;
-  RawArray* canonical_types() const;
+  void set_canonical_types(const Object& value) const;
+  RawObject* canonical_types() const;
 
   RawArray* invocation_dispatcher_cache() const;
   void set_invocation_dispatcher_cache(const Array& cache) const;
@@ -1727,8 +1734,10 @@
     raw_ptr()->optimized_call_site_count_ = static_cast<uint16_t>(value);
   }
 
-  bool is_optimizable() const;
-  void set_is_optimizable(bool value) const;
+  bool IsOptimizable() const;
+  bool IsNativeAutoSetupScope() const;
+  void SetIsOptimizable(bool value) const;
+  void SetIsNativeAutoSetupScope(bool value) const;
 
   bool has_finally() const {
     return HasFinallyBit::decode(raw_ptr()->kind_tag_);
@@ -1965,6 +1974,10 @@
   void set_num_optional_parameters(intptr_t value) const;  // Encoded value.
   void set_kind_tag(intptr_t value) const;
   void set_data(const Object& value) const;
+  bool is_optimizable() const {
+    return OptimizableBit::decode(raw_ptr()->kind_tag_);
+  }
+  void set_is_optimizable(bool value) const;
 
   static RawFunction* New();
 
@@ -2106,6 +2119,8 @@
 
   static intptr_t value_offset() { return OFFSET_OF(RawField, value_); }
 
+  static intptr_t kind_bits_offset() { return OFFSET_OF(RawField, kind_bits_); }
+
   intptr_t token_pos() const { return raw_ptr()->token_pos_; }
 
   bool has_initializer() const {
@@ -2142,6 +2157,25 @@
     return r;
   }
 
+  bool IsUnboxedField() const {
+    return is_unboxing_candidate()
+        && !is_final()
+        && (guarded_cid() == kDoubleCid && !is_nullable());
+  }
+
+  bool IsPotentialUnboxedField() const {
+    return is_unboxing_candidate()
+        && (IsUnboxedField() ||
+            (!is_final() && (guarded_cid() == kIllegalCid)));
+  }
+
+  bool is_unboxing_candidate() const {
+    return UnboxingCandidateBit::decode(raw_ptr()->kind_bits_);
+  }
+  void set_is_unboxing_candidate(bool b) const {
+    set_kind_bits(UnboxingCandidateBit::update(b, raw_ptr()->kind_bits_));
+  }
+
   static bool IsExternalizableCid(intptr_t cid) {
     return (cid == kOneByteStringCid) || (cid == kTwoByteStringCid);
   }
@@ -2201,16 +2235,22 @@
       JSONStream* stream, const Instance& instance, bool ref) const;
 
  private:
+  friend class StoreInstanceFieldInstr;  // Generated code access to bit field.
+
   enum {
-    kConstBit = 1,
+    kConstBit = 0,
     kStaticBit,
     kFinalBit,
     kHasInitializerBit,
+    kUnboxingCandidateBit
   };
   class ConstBit : public BitField<bool, kConstBit, 1> {};
   class StaticBit : public BitField<bool, kStaticBit, 1> {};
   class FinalBit : public BitField<bool, kFinalBit, 1> {};
   class HasInitializerBit : public BitField<bool, kHasInitializerBit, 1> {};
+  class UnboxingCandidateBit : public BitField<bool,
+                                               kUnboxingCandidateBit, 1> {
+  };
 
   // Update guarded class id and nullability of the field to reflect assignment
   // of the value with the given class id to this field. Returns true, if
@@ -3970,7 +4010,11 @@
 
   // Returns a string representation of this instance in a form
   // that is suitable for an end user.
-  virtual const char* ToUserCString(intptr_t maxLen = 40) const;
+  //
+  // max_len is advisory, and the returned string may exceed this max
+  // length.
+  virtual const char* ToUserCString(intptr_t max_len = 40,
+                                    intptr_t nesting = 0) const;
 
   static intptr_t InstanceSize() {
     return RoundedAllocationSize(sizeof(RawInstance));
@@ -4965,7 +5009,8 @@
                           Dart_PeerFinalizer cback) const;
 
   // Produces a quoted, escaped, (possibly) truncated string.
-  const char* ToUserCString(intptr_t maxLen = 40) const;
+  const char* ToUserCString(intptr_t max_len = 40,
+                            intptr_t nesting = 0) const;
 
   // Creates a new String object from a C string that is assumed to contain
   // UTF-8 encoded characters and '\0' is considered a termination character.
@@ -5091,7 +5136,7 @@
                            CallbackType new_symbol,
                            Snapshot::Kind kind);
 
-  intptr_t EscapedString(char* buffer, int maxLen) const;
+  intptr_t EscapedString(char* buffer, int max_len) const;
   intptr_t EscapedStringLen(intptr_t tooLong) const;
 
   FINAL_HEAP_OBJECT_IMPLEMENTATION(String, Instance);
@@ -5693,6 +5738,11 @@
     return Instance::null();
   }
 
+  // Produces a readable representation of this array, e.g. '[1,2,3]',
+  // subject to length limits.
+  const char* ToUserCString(intptr_t max_len = 40,
+                            intptr_t nesting = 0) const;
+
   static intptr_t type_arguments_offset() {
     return OFFSET_OF(RawGrowableObjectArray, type_arguments_);
   }
diff --git a/runtime/vm/object_test.cc b/runtime/vm/object_test.cc
index ec1fc42..00c19bd 100644
--- a/runtime/vm/object_test.cc
+++ b/runtime/vm/object_test.cc
@@ -3643,7 +3643,15 @@
       "class _Cobra { }\n"
       "var instance = new _Cobra();\n"
       "\n"
+      "var empty_list = [];\n"
       "var simple_list = [1,2,'otter'];\n"
+      "var nested_list = [[[[1]]],[2,'otter']];\n"
+      "var deeply_nested_list = [[[[[1]]]],[2,'otter']];\n"
+      "var toolong_list = "
+      "['0123456789','0123456789','0123456789','0123456789'];\n"
+      "var toolong2_list = [toolong];\n"
+      "var justenough_list = [0,1,2,3,4,0,1,2,3,4,0,1,2,3,4,0,1,2,99];"
+      "var toolong3_list = [0,1,2,3,4,0,1,2,3,4,0,1,2,3,4,0,1,2,3,4];"
       "\n"
       "var simple_map = {1: 2, 2: 'otter'};\n";
   Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
@@ -3704,13 +3712,56 @@
   obj ^= Api::UnwrapHandle(result);
   EXPECT_STREQ("Instance of '_Cobra'", obj.ToUserCString());
 
+  // Empty list.
+  result = Dart_GetField(lib, NewString("empty_list"));
+  EXPECT_VALID(result);
+  obj ^= Api::UnwrapHandle(result);
+  EXPECT_STREQ("[]", obj.ToUserCString());
+
   // Simple list.
-  //
-  // TODO(turnidge): Consider showing something like: [1, 2, 'otter'].
   result = Dart_GetField(lib, NewString("simple_list"));
   EXPECT_VALID(result);
   obj ^= Api::UnwrapHandle(result);
-  EXPECT_STREQ("Instance(length:3) of '_GrowableList'",
+  EXPECT_STREQ("[1,2,\"otter\"]", obj.ToUserCString());
+
+  // Nested list.
+  result = Dart_GetField(lib, NewString("nested_list"));
+  EXPECT_VALID(result);
+  obj ^= Api::UnwrapHandle(result);
+  EXPECT_STREQ("[[[[1]]],[2,\"otter\"]]", obj.ToUserCString());
+
+  // Deeply ested list.
+  result = Dart_GetField(lib, NewString("deeply_nested_list"));
+  EXPECT_VALID(result);
+  obj ^= Api::UnwrapHandle(result);
+  EXPECT_STREQ("[[[[[...]]]],[2,\"otter\"]]", obj.ToUserCString());
+
+  // Truncation.
+  result = Dart_GetField(lib, NewString("toolong_list"));
+  EXPECT_VALID(result);
+  obj ^= Api::UnwrapHandle(result);
+  EXPECT_STREQ("[\"0123456789\",\"012345\"...,...](length:4)",
+               obj.ToUserCString());
+
+  // More truncation.
+  result = Dart_GetField(lib, NewString("toolong2_list"));
+  EXPECT_VALID(result);
+  obj ^= Api::UnwrapHandle(result);
+  EXPECT_STREQ("[\"012345678901234567890123456789012\"...]",
+               obj.ToUserCString());
+
+  // Just fits.
+  result = Dart_GetField(lib, NewString("justenough_list"));
+  EXPECT_VALID(result);
+  obj ^= Api::UnwrapHandle(result);
+  EXPECT_STREQ("[0,1,2,3,4,0,1,2,3,4,0,1,2,3,4,0,1,2,99]",
+               obj.ToUserCString());
+
+  // Just too big, small elements.
+  result = Dart_GetField(lib, NewString("toolong3_list"));
+  EXPECT_VALID(result);
+  obj ^= Api::UnwrapHandle(result);
+  EXPECT_STREQ("[0,1,2,3,4,0,1,2,3,4,0,1,...](length:20)",
                obj.ToUserCString());
 
   // Simple map.
diff --git a/runtime/vm/os.h b/runtime/vm/os.h
index 9eddae5..e260853 100644
--- a/runtime/vm/os.h
+++ b/runtime/vm/os.h
@@ -84,6 +84,9 @@
   // Sleep the currently executing thread for millis ms.
   static void Sleep(int64_t millis);
 
+  // Sleep the currently executing thread for micros microseconds.
+  static void SleepMicros(int64_t micros);
+
   // Debug break.
   static void DebugBreak();
 
diff --git a/runtime/vm/os_android.cc b/runtime/vm/os_android.cc
index cbce25c..c78bda5 100644
--- a/runtime/vm/os_android.cc
+++ b/runtime/vm/os_android.cc
@@ -319,8 +319,29 @@
 
 
 void OS::Sleep(int64_t millis) {
-  // TODO(5411554):  For now just use usleep we may have to revisit this.
-  usleep(millis * 1000);
+  int64_t micros = millis * kMicrosecondsPerMillisecond;
+  SleepMicros(micros);
+}
+
+
+void OS::SleepMicros(int64_t micros) {
+  struct timespec req;  // requested.
+  struct timespec rem;  // remainder.
+  int64_t seconds = micros / kMicrosecondsPerSecond;
+  micros = micros - seconds * kMicrosecondsPerSecond;
+  int64_t nanos = micros * kNanosecondsPerMicrosecond;
+  req.tv_sec = seconds;
+  req.tv_nsec = nanos;
+  while (true) {
+    int r = nanosleep(&req, &rem);
+    if (r == 0) {
+      break;
+    }
+    // We should only ever see an interrupt error.
+    ASSERT(errno == EINTR);
+    // Copy remainder into requested and repeat.
+    req = rem;
+  }
 }
 
 
diff --git a/runtime/vm/os_linux.cc b/runtime/vm/os_linux.cc
index ed1d668..97e9e55 100644
--- a/runtime/vm/os_linux.cc
+++ b/runtime/vm/os_linux.cc
@@ -404,8 +404,29 @@
 
 
 void OS::Sleep(int64_t millis) {
-  // TODO(5411554):  For now just use usleep we may have to revisit this.
-  usleep(millis * 1000);
+  int64_t micros = millis * kMicrosecondsPerMillisecond;
+  SleepMicros(micros);
+}
+
+
+void OS::SleepMicros(int64_t micros) {
+  struct timespec req;  // requested.
+  struct timespec rem;  // remainder.
+  int64_t seconds = micros / kMicrosecondsPerSecond;
+  micros = micros - seconds * kMicrosecondsPerSecond;
+  int64_t nanos = micros * kNanosecondsPerMicrosecond;
+  req.tv_sec = seconds;
+  req.tv_nsec = nanos;
+  while (true) {
+    int r = nanosleep(&req, &rem);
+    if (r == 0) {
+      break;
+    }
+    // We should only ever see an interrupt error.
+    ASSERT(errno == EINTR);
+    // Copy remainder into requested and repeat.
+    req = rem;
+  }
 }
 
 
diff --git a/runtime/vm/os_macos.cc b/runtime/vm/os_macos.cc
index 76d9fb6..10f6dcf 100644
--- a/runtime/vm/os_macos.cc
+++ b/runtime/vm/os_macos.cc
@@ -131,8 +131,29 @@
 
 
 void OS::Sleep(int64_t millis) {
-  // TODO(5411554):  For now just use usleep we may have to revisit this.
-  usleep(millis * 1000);
+  int64_t micros = millis * kMicrosecondsPerMillisecond;
+  SleepMicros(micros);
+}
+
+
+void OS::SleepMicros(int64_t micros) {
+  struct timespec req;  // requested.
+  struct timespec rem;  // remainder.
+  int64_t seconds = micros / kMicrosecondsPerSecond;
+  micros = micros - seconds * kMicrosecondsPerSecond;
+  int64_t nanos = micros * kNanosecondsPerMicrosecond;
+  req.tv_sec = seconds;
+  req.tv_nsec = nanos;
+  while (true) {
+    int r = nanosleep(&req, &rem);
+    if (r == 0) {
+      break;
+    }
+    // We should only ever see an interrupt error.
+    ASSERT(errno == EINTR);
+    // Copy remainder into requested and repeat.
+    req = rem;
+  }
 }
 
 
diff --git a/runtime/vm/os_win.cc b/runtime/vm/os_win.cc
index fcb8447..98e864e 100644
--- a/runtime/vm/os_win.cc
+++ b/runtime/vm/os_win.cc
@@ -174,6 +174,16 @@
 }
 
 
+void OS::SleepMicros(int64_t micros) {
+  // Windows only supports millisecond sleeps.
+  if (micros < kMicrosecondsPerMillisecond) {
+    // Calling ::Sleep with 0 has no determined behaviour, round up.
+    micros = kMicrosecondsPerMillisecond;
+  }
+  OS::Sleep(micros / kMicrosecondsPerMillisecond);
+}
+
+
 void OS::DebugBreak() {
 #if defined(_MSC_VER)
   // Microsoft Visual C/C++ or drop-in replacement.
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
index 7ffa22e..72f93d8 100644
--- a/runtime/vm/parser.cc
+++ b/runtime/vm/parser.cc
@@ -5317,12 +5317,14 @@
 
   // Now resolve the native function to the corresponding native entrypoint.
   const int num_params = NativeArguments::ParameterCountForResolution(func);
+  bool auto_setup_scope = true;
   NativeFunction native_function = NativeEntry::ResolveNative(
-      library, native_name, num_params);
+      library, native_name, num_params, &auto_setup_scope);
   if (native_function == NULL) {
     ErrorMsg(native_pos, "native function '%s' cannot be found",
         native_name.ToCString());
   }
+  func.SetIsNativeAutoSetupScope(auto_setup_scope);
 
   // Now add the NativeBodyNode and return statement.
   Dart_NativeEntryResolver resolver = library.native_entry_resolver();
@@ -8825,7 +8827,7 @@
           // An exception may not occur in every parse attempt, i.e., the
           // generated AST is not deterministic. Therefore mark the function as
           // not optimizable.
-          current_function().set_is_optimizable(false);
+          current_function().SetIsOptimizable(false);
           field.set_value(Object::null_instance());
           // It is a compile-time error if evaluation of a compile-time constant
           // would raise an exception.
@@ -8907,7 +8909,7 @@
       // An exception may not occur in every parse attempt, i.e., the
       // generated AST is not deterministic. Therefore mark the function as
       // not optimizable.
-      current_function().set_is_optimizable(false);
+      current_function().SetIsOptimizable(false);
       if (result.IsUnhandledException()) {
         return result.raw();
       } else {
diff --git a/runtime/vm/port_test.cc b/runtime/vm/port_test.cc
index 329f81c..e2482e9 100644
--- a/runtime/vm/port_test.cc
+++ b/runtime/vm/port_test.cc
@@ -125,7 +125,7 @@
   intptr_t message_len = strlen(message) + 1;
 
   EXPECT(PortMap::PostMessage(new Message(
-      port, 0, reinterpret_cast<uint8_t*>(strdup(message)), message_len,
+      port, reinterpret_cast<uint8_t*>(strdup(message)), message_len,
       Message::kNormalPriority)));
 
   // Check that the message notify callback was called.
@@ -139,7 +139,7 @@
   intptr_t message_len = strlen(message) + 1;
 
   EXPECT(!PortMap::PostMessage(new Message(
-      0, 0, reinterpret_cast<uint8_t*>(strdup(message)), message_len,
+      0, reinterpret_cast<uint8_t*>(strdup(message)), message_len,
       Message::kNormalPriority)));
 }
 
diff --git a/runtime/vm/profiler.cc b/runtime/vm/profiler.cc
index 8de6d12..d254520 100644
--- a/runtime/vm/profiler.cc
+++ b/runtime/vm/profiler.cc
@@ -6,6 +6,7 @@
 
 #include "platform/utils.h"
 
+#include "vm/atomic.h"
 #include "vm/isolate.h"
 #include "vm/json_stream.h"
 #include "vm/native_symbol.h"
@@ -13,573 +14,437 @@
 #include "vm/os.h"
 #include "vm/profiler.h"
 #include "vm/signal_handler.h"
+#include "vm/simulator.h"
 
 namespace dart {
 
-// Notes on locking and signal handling:
-//
-// The ProfilerManager has a single monitor (monitor_). This monitor guards
-// access to the schedule list of isolates (isolates_, isolates_size_, etc).
-//
-// Each isolate has a mutex (profiler_data_mutex_) which protects access
-// to the isolate's profiler data.
-//
-// Locks can be taken in this order:
-//   1. ProfilerManager::monitor_
-//   2. isolate->profiler_data_mutex_
-// In other words, it is not acceptable to take ProfilerManager::monitor_
-// after grabbing isolate->profiler_data_mutex_.
-//
-// ProfileManager::monitor_ taking entry points:
-//   InitOnce, Shutdown
-//       ProfilerManager::monitor_
-//   ScheduleIsolate, DescheduleIsolate.
-//       ProfilerManager::monitor_, isolate->profiler_data_mutex_
-//   ThreadMain
-// isolate->profiler_data_mutex_ taking entry points:
-//     SetupIsolateForProfiling, FreeIsolateForProfiling.
-//       ProfilerManager::monitor_, isolate->profiler_data_mutex_
-//     ScheduleIsolate, DescheduleIsolate.
-//       ProfilerManager::monitor_, isolate->profiler_data_mutex_
-//     ProfileSignalAction
-//       isolate->profiler_data_mutex_
-//       ProfilerManager::monitor_, isolate->profiler_data_mutex_
-//
-// Signal handling and locking:
-// On OSes with pthreads (Android, Linux, and Mac) we use signal delivery
-// to interrupt the isolate running thread for sampling. After a thread
-// is sent the SIGPROF, it is removed from the scheduled isolate list.
-// Inside the signal handler, after the sample is taken, the isolate is
-// added to the scheduled isolate list again. The side effect of this is
-// that the signal handler must be able to acquire the isolate profiler data
-// mutex and the profile manager monitor. When an isolate running thread
-// (potential signal target) calls into an entry point which acquires
-// ProfileManager::monitor_ signal delivery must be blocked. An example is
-// ProfileManager::ScheduleIsolate which blocks signal delivery while removing
-// the scheduling the isolate.
-//
 
 // Notes on stack frame walking:
 //
 // The sampling profiler will collect up to Sample::kNumStackFrames stack frames
 // The stack frame walking code uses the frame pointer to traverse the stack.
 // If the VM is compiled without frame pointers (which is the default on
-// recent GCC versions with optimizing enabled) the stack walking code will
+// recent GCC versions with optimizing enabled) the stack walking code may
 // fail (sometimes leading to a crash).
 //
 
-DEFINE_FLAG(bool, profile, false, "Enable Sampling Profiler");
+#if defined(USING_SIMULATOR) || defined(TARGET_OS_WINDOWS) || \
+    defined(TARGET_OS_MACOS) || defined(TARGET_OS_ANDROID)
+  DEFINE_FLAG(bool, profile, false, "Enable Sampling Profiler");
+#else
+  DEFINE_FLAG(bool, profile, true, "Enable Sampling Profiler");
+#endif
 DEFINE_FLAG(bool, trace_profiled_isolates, false, "Trace profiled isolates.");
+DEFINE_FLAG(charp, profile_dir, NULL,
+            "Enable writing profile data into specified directory.");
+DEFINE_FLAG(int, profile_period, 1000,
+            "Time between profiler samples in microseconds. Minimum 250.");
 
-bool ProfilerManager::initialized_ = false;
-bool ProfilerManager::shutdown_ = false;
-bool ProfilerManager::thread_running_ = false;
-Monitor* ProfilerManager::monitor_ = NULL;
-Monitor* ProfilerManager::start_stop_monitor_ = NULL;
-Isolate** ProfilerManager::isolates_ = NULL;
-intptr_t ProfilerManager::isolates_capacity_ = 0;
-intptr_t ProfilerManager::isolates_size_ = 0;
+bool Profiler::initialized_ = false;
+Monitor* Profiler::monitor_ = NULL;
+SampleBuffer* Profiler::sample_buffer_ = NULL;
 
-
-void ProfilerManager::InitOnce() {
-#if defined(USING_SIMULATOR)
-  // Force disable of profiling on simulator.
-  FLAG_profile = false;
-#endif
-#if defined(TARGET_OS_WINDOWS)
-  // Force disable of profiling on Windows.
-  FLAG_profile = false;
-#endif
+void Profiler::InitOnce() {
+  const int kMinimumProfilePeriod = 250;
   if (!FLAG_profile) {
     return;
   }
-  NativeSymbolResolver::InitOnce();
   ASSERT(!initialized_);
-  monitor_ = new Monitor();
-  start_stop_monitor_ = new Monitor();
   initialized_ = true;
-  ResizeIsolates(16);
-  if (FLAG_trace_profiled_isolates) {
-    OS::Print("ProfilerManager starting up.\n");
+  monitor_ = new Monitor();
+  sample_buffer_ = new SampleBuffer();
+  NativeSymbolResolver::InitOnce();
+  ThreadInterrupter::InitOnce();
+  if (FLAG_profile_period < kMinimumProfilePeriod) {
+    FLAG_profile_period = kMinimumProfilePeriod;
   }
-  {
-    ScopedMonitor startup_lock(start_stop_monitor_);
-    Thread::Start(ThreadMain, 0);
-    while (!thread_running_) {
-      // Wait until profiler thread has started up.
-      startup_lock.Wait();
-    }
-  }
-  if (FLAG_trace_profiled_isolates) {
-    OS::Print("ProfilerManager running.\n");
-  }
+  ThreadInterrupter::SetInterruptPeriod(FLAG_profile_period);
 }
 
 
-void ProfilerManager::Shutdown() {
+void Profiler::Shutdown() {
   if (!FLAG_profile) {
     return;
   }
   ASSERT(initialized_);
-  if (FLAG_trace_profiled_isolates) {
-    OS::Print("ProfilerManager shutting down.\n");
-  }
-  intptr_t size_at_shutdown = 0;
-  {
-    ScopedSignalBlocker ssb;
-    {
-      ScopedMonitor lock(monitor_);
-      shutdown_ = true;
-      size_at_shutdown = isolates_size_;
-      isolates_size_ = 0;
-      free(isolates_);
-      isolates_ = NULL;
-      lock.Notify();
-    }
-  }
+  ThreadInterrupter::Shutdown();
   NativeSymbolResolver::ShutdownOnce();
-  {
-    ScopedMonitor shutdown_lock(start_stop_monitor_);
-    while (thread_running_) {
-      // Wait until profiler thread has exited.
-      shutdown_lock.Wait();
-    }
-  }
-  if (FLAG_trace_profiled_isolates) {
-    OS::Print("ProfilerManager shut down (%" Pd ").\n", size_at_shutdown);
-  }
 }
 
 
-void ProfilerManager::SetupIsolateForProfiling(Isolate* isolate) {
+void Profiler::InitProfilingForIsolate(Isolate* isolate, bool shared_buffer) {
   if (!FLAG_profile) {
     return;
   }
   ASSERT(isolate != NULL);
+  ASSERT(sample_buffer_ != NULL);
+  MonitorLocker ml(monitor_);
   {
-    ScopedSignalBlocker ssb;
-    {
-      ScopedMutex profiler_data_lock(isolate->profiler_data_mutex());
-      SampleBuffer* sample_buffer = new SampleBuffer();
-      ASSERT(sample_buffer != NULL);
-      IsolateProfilerData* profiler_data =
-          new IsolateProfilerData(isolate, sample_buffer);
-      ASSERT(profiler_data != NULL);
-      profiler_data->set_sample_interval_micros(1000);
-      isolate->set_profiler_data(profiler_data);
-      if (FLAG_trace_profiled_isolates) {
-        OS::Print("ProfilerManager Setup Isolate %p %s %p\n",
-            isolate,
-            isolate->name(),
-            reinterpret_cast<void*>(Thread::GetCurrentThreadId()));
-      }
+    MutexLocker profiler_data_lock(isolate->profiler_data_mutex());
+    SampleBuffer* sample_buffer = sample_buffer_;
+    if (!shared_buffer) {
+      sample_buffer = new SampleBuffer();
+    }
+    IsolateProfilerData* profiler_data =
+        new IsolateProfilerData(sample_buffer, !shared_buffer);
+    ASSERT(profiler_data != NULL);
+    isolate->set_profiler_data(profiler_data);
+    if (FLAG_trace_profiled_isolates) {
+      OS::Print("Profiler Setup %p %s\n", isolate, isolate->name());
     }
   }
 }
 
 
-void ProfilerManager::FreeIsolateProfilingData(Isolate* isolate) {
-  ScopedMutex profiler_data_lock(isolate->profiler_data_mutex());
-  IsolateProfilerData* profiler_data = isolate->profiler_data();
-  if (profiler_data == NULL) {
-    // Already freed.
-    return;
-  }
-  isolate->set_profiler_data(NULL);
-  SampleBuffer* sample_buffer = profiler_data->sample_buffer();
-  ASSERT(sample_buffer != NULL);
-  profiler_data->set_sample_buffer(NULL);
-  delete sample_buffer;
-  delete profiler_data;
-  if (FLAG_trace_profiled_isolates) {
-    OS::Print("ProfilerManager Shutdown Isolate %p %s %p\n",
-        isolate,
-        isolate->name(),
-        reinterpret_cast<void*>(Thread::GetCurrentThreadId()));
-  }
-}
-
-
-void ProfilerManager::ShutdownIsolateForProfiling(Isolate* isolate) {
+void Profiler::ShutdownProfilingForIsolate(Isolate* isolate) {
   ASSERT(isolate != NULL);
   if (!FLAG_profile) {
     return;
   }
+  // We do not have a current isolate.
+  ASSERT(Isolate::Current() == NULL);
+  MonitorLocker ml(monitor_);
   {
-    ScopedSignalBlocker ssb;
-    FreeIsolateProfilingData(isolate);
-  }
-}
-
-
-void ProfilerManager::ScheduleIsolateHelper(Isolate* isolate) {
-  ScopedMonitor lock(monitor_);
-  {
-    if (shutdown_) {
-      // Shutdown.
-      return;
-    }
-    ScopedMutex profiler_data_lock(isolate->profiler_data_mutex());
+    MutexLocker profiler_data_lock(isolate->profiler_data_mutex());
     IsolateProfilerData* profiler_data = isolate->profiler_data();
     if (profiler_data == NULL) {
+      // Already freed.
       return;
     }
-    profiler_data->Scheduled(OS::GetCurrentTimeMicros(),
-                             Thread::GetCurrentThreadId());
+    isolate->set_profiler_data(NULL);
+    profiler_data->set_sample_buffer(NULL);
+    delete profiler_data;
+    if (FLAG_trace_profiled_isolates) {
+      OS::Print("Profiler Shutdown %p %s\n", isolate, isolate->name());
+    }
   }
-  intptr_t i = FindIsolate(isolate);
-  if (i >= 0) {
-    // Already scheduled.
-    return;
-  }
-  AddIsolate(isolate);
-  lock.Notify();
 }
 
 
-void ProfilerManager::ScheduleIsolate(Isolate* isolate, bool inside_signal) {
+void Profiler::BeginExecution(Isolate* isolate) {
+  if (isolate == NULL) {
+    return;
+  }
   if (!FLAG_profile) {
     return;
   }
   ASSERT(initialized_);
-  ASSERT(isolate != NULL);
-  if (!inside_signal) {
-    ScopedSignalBlocker ssb;
-    {
-      ScheduleIsolateHelper(isolate);
-    }
-  } else {
-    // Do not need a signal blocker inside a signal handler.
-    {
-      ScheduleIsolateHelper(isolate);
-    }
+  IsolateProfilerData* profiler_data = isolate->profiler_data();
+  if (profiler_data == NULL) {
+    return;
   }
+  SampleBuffer* sample_buffer = profiler_data->sample_buffer();
+  if (sample_buffer == NULL) {
+    return;
+  }
+  Sample* sample = sample_buffer->ReserveSample();
+  sample->Init(Sample::kIsolateStart, isolate, OS::GetCurrentTimeMicros(),
+               Thread::GetCurrentThreadId());
+  ThreadInterrupter::Register(RecordSampleInterruptCallback, isolate);
 }
 
 
-void ProfilerManager::DescheduleIsolate(Isolate* isolate) {
+void Profiler::EndExecution(Isolate* isolate) {
+  if (isolate == NULL) {
+    return;
+  }
   if (!FLAG_profile) {
     return;
   }
   ASSERT(initialized_);
-  ASSERT(isolate != NULL);
-  {
-    ScopedSignalBlocker ssb;
-    {
-      ScopedMonitor lock(monitor_);
-      if (shutdown_) {
-        // Shutdown.
-        return;
-      }
-      intptr_t i = FindIsolate(isolate);
-      if (i < 0) {
-        // Not scheduled.
-        return;
-      }
-      {
-        ScopedMutex profiler_data_lock(isolate->profiler_data_mutex());
-        IsolateProfilerData* profiler_data = isolate->profiler_data();
-        if (profiler_data != NULL) {
-          profiler_data->Descheduled();
-        }
-      }
-      RemoveIsolate(i);
-      lock.Notify();
-    }
+  ThreadInterrupter::Unregister();
+  IsolateProfilerData* profiler_data = isolate->profiler_data();
+  if (profiler_data == NULL) {
+    return;
   }
+  SampleBuffer* sample_buffer = profiler_data->sample_buffer();
+  if (sample_buffer == NULL) {
+    return;
+  }
+  Sample* sample = sample_buffer->ReserveSample();
+  sample->Init(Sample::kIsolateStop, isolate, OS::GetCurrentTimeMicros(),
+               Thread::GetCurrentThreadId());
 }
 
 
-void PrintToJSONStream(Isolate* isolate, JSONStream* stream) {
+void Profiler::RecordTickInterruptCallback(const InterruptedThreadState& state,
+                                           void* data) {
+  Isolate* isolate = reinterpret_cast<Isolate*>(data);
+  if (isolate == NULL) {
+    return;
+  }
+  IsolateProfilerData* profiler_data = isolate->profiler_data();
+  if (profiler_data == NULL) {
+    return;
+  }
+  SampleBuffer* sample_buffer = profiler_data->sample_buffer();
+  if (sample_buffer == NULL) {
+    return;
+  }
+  Sample* sample = sample_buffer->ReserveSample();
+  sample->Init(Sample::kIsolateSample, isolate, OS::GetCurrentTimeMicros(),
+               state.tid);
+}
+
+
+void Profiler::RecordSampleInterruptCallback(
+    const InterruptedThreadState& state,
+    void* data) {
+  Isolate* isolate = reinterpret_cast<Isolate*>(data);
+  if (isolate == NULL) {
+    return;
+  }
+  IsolateProfilerData* profiler_data = isolate->profiler_data();
+  if (profiler_data == NULL) {
+    return;
+  }
+  SampleBuffer* sample_buffer = profiler_data->sample_buffer();
+  if (sample_buffer == NULL) {
+    return;
+  }
+  Sample* sample = sample_buffer->ReserveSample();
+  sample->Init(Sample::kIsolateSample, isolate, OS::GetCurrentTimeMicros(),
+               state.tid);
+  uintptr_t stack_lower = 0;
+  uintptr_t stack_upper = 0;
+  isolate->GetStackBounds(&stack_lower, &stack_upper);
+  if ((stack_lower == 0) || (stack_upper == 0)) {
+    stack_lower = 0;
+    stack_upper = 0;
+  }
+  ProfilerSampleStackWalker stackWalker(sample, stack_lower, stack_upper,
+                                        state.pc, state.fp, state.sp);
+  stackWalker.walk();
+}
+
+
+void Profiler::PrintToJSONStream(Isolate* isolate, JSONStream* stream) {
   ASSERT(isolate == Isolate::Current());
-  {
-    // We can't get signals here.
-  }
   UNIMPLEMENTED();
 }
 
 
-void ProfilerManager::ResizeIsolates(intptr_t new_capacity) {
-  ASSERT(new_capacity < kMaxProfiledIsolates);
-  ASSERT(new_capacity > isolates_capacity_);
-  Isolate* isolate = NULL;
-  isolates_ = reinterpret_cast<Isolate**>(
-      realloc(isolates_, sizeof(isolate) * new_capacity));
-  isolates_capacity_ = new_capacity;
-}
-
-
-void ProfilerManager::AddIsolate(Isolate* isolate) {
-  // Must be called with monitor_ locked.
-  if (isolates_ == NULL) {
-    // We are shutting down.
-    return;
-  }
-  if (isolates_size_ == isolates_capacity_) {
-    ResizeIsolates(isolates_capacity_ == 0 ? 16 : isolates_capacity_ * 2);
-  }
-  isolates_[isolates_size_] = isolate;
-  isolates_size_++;
-}
-
-
-intptr_t ProfilerManager::FindIsolate(Isolate* isolate) {
-  // Must be called with monitor_ locked.
-  if (isolates_ == NULL) {
-    // We are shutting down.
-    return -1;
-  }
-  for (intptr_t i = 0; i < isolates_size_; i++) {
-    if (isolates_[i] == isolate) {
-      return i;
-    }
-  }
-  return -1;
-}
-
-
-void ProfilerManager::RemoveIsolate(intptr_t i) {
-  // Must be called with monitor_ locked.
-  if (isolates_ == NULL) {
-    // We are shutting down.
-    return;
-  }
-  ASSERT(i < isolates_size_);
-  intptr_t last = isolates_size_ - 1;
-  if (i != last) {
-    isolates_[i] = isolates_[last];
-  }
-  // Mark last as NULL.
-  isolates_[last] = NULL;
-  // Pop.
-  isolates_size_--;
-}
-
-
-static char* FindSymbolName(uintptr_t pc, bool* native_symbol) {
+static const char* FindSymbolName(uintptr_t pc, bool* symbol_name_allocated) {
   // TODO(johnmccutchan): Differentiate between symbols which can't be found
   // and symbols which were GCed. (Heap::CodeContains).
-  ASSERT(native_symbol != NULL);
+  ASSERT(symbol_name_allocated != NULL);
   const char* symbol_name = "Unknown";
-  *native_symbol = false;
+  *symbol_name_allocated = false;
+  if (pc == 0) {
+    return const_cast<char*>(Sample::kNoFrame);
+  }
   const Code& code = Code::Handle(Code::LookupCode(pc));
-  if (code.IsNull()) {
-    // Possibly a native symbol.
-    char* native_name = NativeSymbolResolver::LookupSymbolName(pc);
-    if (native_name != NULL) {
-      symbol_name = native_name;
-      *native_symbol = true;
-    }
-  } else {
+  if (!code.IsNull()) {
     const Function& function = Function::Handle(code.function());
     if (!function.IsNull()) {
       const String& name = String::Handle(function.QualifiedUserVisibleName());
       if (!name.IsNull()) {
         symbol_name = name.ToCString();
+        return symbol_name;
       }
     }
+  } else {
+    // Possibly a native symbol.
+    char* native_name = NativeSymbolResolver::LookupSymbolName(pc);
+    if (native_name != NULL) {
+      symbol_name = native_name;
+      *symbol_name_allocated = true;
+      return symbol_name;
+    }
   }
-  return const_cast<char*>(symbol_name);
-}
-
-
-void ProfilerManager::WriteTracing(Isolate* isolate, const char* name,
-                                   Dart_Port port) {
-  ASSERT(isolate == Isolate::Current());
+  const intptr_t kBucketSize = 256;
+  const intptr_t kBucketMask = ~(kBucketSize - 1);
+  // Not a Dart symbol or a native symbol. Bin into buckets by PC.
+  pc &= kBucketMask;
   {
-    ScopedSignalBlocker ssb;
-    {
-      ScopedMutex profiler_data_lock(isolate->profiler_data_mutex());
-      IsolateProfilerData* profiler_data = isolate->profiler_data();
-      if (profiler_data == NULL) {
-        return;
-      }
-      SampleBuffer* sample_buffer = profiler_data->sample_buffer();
-      ASSERT(sample_buffer != NULL);
-      JSONStream stream(10 * MB);
-      intptr_t tid = reinterpret_cast<intptr_t>(sample_buffer);
-      intptr_t pid = 1;
-      {
-        JSONArray events(&stream);
-        {
-          JSONObject thread_name(&events);
-          thread_name.AddProperty("name", "thread_name");
-          thread_name.AddProperty("ph", "M");
-          thread_name.AddProperty("tid", tid);
-          thread_name.AddProperty("pid", pid);
-          {
-            JSONObject args(&thread_name, "args");
-            args.AddProperty("name", name);
-          }
-        }
-        {
-          JSONObject process_name(&events);
-          process_name.AddProperty("name", "process_name");
-          process_name.AddProperty("ph", "M");
-          process_name.AddProperty("tid", tid);
-          process_name.AddProperty("pid", pid);
-          {
-            JSONObject args(&process_name, "args");
-            args.AddProperty("name", "Dart VM");
-          }
-        }
-        uint64_t last_time = 0;
-        for (Sample* i = sample_buffer->FirstSample();
-             i != sample_buffer->LastSample();
-             i = sample_buffer->NextSample(i)) {
-          if (last_time == 0) {
-            last_time = i->timestamp;
-          }
-          intptr_t delta = i->timestamp - last_time;
-          {
-            double percentage = static_cast<double>(i->cpu_usage) /
-                                static_cast<double>(delta) * 100.0;
-            if (percentage != percentage) {
-              percentage = 0.0;
-            }
-            percentage = percentage < 0.0 ? 0.0 : percentage;
-            percentage = percentage > 100.0 ? 100.0 : percentage;
-            {
-              JSONObject cpu_usage(&events);
-              cpu_usage.AddProperty("name", "CPU Usage");
-              cpu_usage.AddProperty("ph", "C");
-              cpu_usage.AddProperty("tid", tid);
-              cpu_usage.AddProperty("pid", pid);
-              cpu_usage.AddProperty("ts", static_cast<double>(last_time));
-              {
-                JSONObject args(&cpu_usage, "args");
-                args.AddProperty("CPU", percentage);
-              }
-            }
-            {
-              JSONObject cpu_usage(&events);
-              cpu_usage.AddProperty("name", "CPU Usage");
-              cpu_usage.AddProperty("ph", "C");
-              cpu_usage.AddProperty("tid", tid);
-              cpu_usage.AddProperty("pid", pid);
-              cpu_usage.AddProperty("ts", static_cast<double>(i->timestamp));
-              {
-                JSONObject args(&cpu_usage, "args");
-                args.AddProperty("CPU", percentage);
-              }
-            }
-          }
-          for (int j = 0; j < Sample::kNumStackFrames; j++) {
-            if (i->pcs[j] == 0) {
-              continue;
-            }
-            bool native_symbol = false;
-            char* symbol_name = FindSymbolName(i->pcs[j], &native_symbol);
-            {
-              JSONObject begin(&events);
-              begin.AddProperty("ph", "B");
-              begin.AddProperty("tid", tid);
-              begin.AddProperty("pid", pid);
-              begin.AddProperty("name", symbol_name);
-              begin.AddProperty("ts", static_cast<double>(last_time));
-            }
-            if (native_symbol) {
-              NativeSymbolResolver::FreeSymbolName(symbol_name);
-            }
-          }
-          for (int j = Sample::kNumStackFrames-1; j >= 0; j--) {
-            if (i->pcs[j] == 0) {
-              continue;
-            }
-            bool native_symbol = false;
-            char* symbol_name = FindSymbolName(i->pcs[j], &native_symbol);
-            {
-              JSONObject end(&events);
-              end.AddProperty("ph", "E");
-              end.AddProperty("tid", tid);
-              end.AddProperty("pid", pid);
-              end.AddProperty("name", symbol_name);
-              end.AddProperty("ts", static_cast<double>(i->timestamp));
-            }
-            if (native_symbol) {
-              NativeSymbolResolver::FreeSymbolName(symbol_name);
-            }
-          }
-          last_time = i->timestamp;
-        }
-      }
-      char fname[1024];
-    #if defined(TARGET_OS_WINDOWS)
-      snprintf(fname, sizeof(fname)-1, "c:\\tmp\\isolate-%d.prof",
-               static_cast<int>(port));
-    #else
-      snprintf(fname, sizeof(fname)-1, "/tmp/isolate-%d.prof",
-               static_cast<int>(port));
-    #endif
-      printf("%s\n", fname);
-      FILE* f = fopen(fname, "wb");
-      ASSERT(f != NULL);
-      fputs(stream.ToCString(), f);
-      fclose(f);
+    const intptr_t kBuffSize = 256;
+    char buff[kBuffSize];
+    OS::SNPrint(&buff[0], kBuffSize-1, "Unknown [%" Px ", %" Px ")",
+                pc, pc + kBucketSize);
+    symbol_name = strdup(buff);
+    *symbol_name_allocated = true;
+  }
+  return symbol_name;
+}
+
+
+void Profiler::WriteTracingSample(Isolate* isolate, intptr_t pid,
+                                  Sample* sample, JSONArray& events) {
+  Sample::SampleType type = sample->type;
+  intptr_t tid = Thread::ThreadIdToIntPtr(sample->tid);
+  double timestamp = static_cast<double>(sample->timestamp);
+  const char* isolate_name = isolate->name();
+  switch (type) {
+    case Sample::kIsolateStart: {
+      JSONObject begin(&events);
+      begin.AddProperty("ph", "B");
+      begin.AddProperty("tid", tid);
+      begin.AddProperty("pid", pid);
+      begin.AddProperty("name", isolate_name);
+      begin.AddProperty("ts", timestamp);
     }
+    break;
+    case Sample::kIsolateStop: {
+      JSONObject begin(&events);
+      begin.AddProperty("ph", "E");
+      begin.AddProperty("tid", tid);
+      begin.AddProperty("pid", pid);
+      begin.AddProperty("name", isolate_name);
+      begin.AddProperty("ts", timestamp);
+    }
+    break;
+    case Sample::kIsolateSample:
+      // Write "B" events.
+      for (int i = Sample::kNumStackFrames - 1; i >= 0; i--) {
+        bool symbol_name_allocated = false;
+        const char* symbol_name = FindSymbolName(sample->pcs[i],
+                                                 &symbol_name_allocated);
+        {
+          JSONObject begin(&events);
+          begin.AddProperty("ph", "B");
+          begin.AddProperty("tid", tid);
+          begin.AddProperty("pid", pid);
+          begin.AddProperty("name", symbol_name);
+          begin.AddProperty("ts", timestamp);
+        }
+        if (symbol_name_allocated) {
+          free(const_cast<char*>(symbol_name));
+        }
+      }
+      // Write "E" events.
+      for (int i = 0; i < Sample::kNumStackFrames; i++) {
+        bool symbol_name_allocated = false;
+        const char* symbol_name = FindSymbolName(sample->pcs[i],
+                                                 &symbol_name_allocated);
+        {
+          JSONObject begin(&events);
+          begin.AddProperty("ph", "E");
+          begin.AddProperty("tid", tid);
+          begin.AddProperty("pid", pid);
+          begin.AddProperty("name", symbol_name);
+          begin.AddProperty("ts", timestamp);
+        }
+        if (symbol_name_allocated) {
+          free(const_cast<char*>(symbol_name));
+        }
+      }
+    break;
+    default:
+      UNIMPLEMENTED();
   }
 }
 
 
-IsolateProfilerData::IsolateProfilerData(Isolate* isolate,
-                                         SampleBuffer* sample_buffer) {
-  isolate_ = isolate;
+void Profiler::WriteTracing(Isolate* isolate) {
+  if (isolate == NULL) {
+    return;
+  }
+  if (!FLAG_profile) {
+    return;
+  }
+  ASSERT(initialized_);
+  if (FLAG_profile_dir == NULL) {
+    return;
+  }
+  Dart_FileOpenCallback file_open = Isolate::file_open_callback();
+  Dart_FileCloseCallback file_close = Isolate::file_close_callback();
+  Dart_FileWriteCallback file_write = Isolate::file_write_callback();
+  if ((file_open == NULL) || (file_close == NULL) || (file_write == NULL)) {
+    // Embedder has not provided necessary callbacks.
+    return;
+  }
+  // We will be looking up code objects within the isolate.
+  ASSERT(Isolate::Current() != NULL);
+  // We do not want to be interrupted while processing the buffer.
+  EndExecution(isolate);
+  MutexLocker profiler_data_lock(isolate->profiler_data_mutex());
+  IsolateProfilerData* profiler_data = isolate->profiler_data();
+  if (profiler_data == NULL) {
+    return;
+  }
+  SampleBuffer* sample_buffer = profiler_data->sample_buffer();
+  ASSERT(sample_buffer != NULL);
+  JSONStream stream(10 * MB);
+  intptr_t pid = OS::ProcessId();
+  {
+    JSONArray events(&stream);
+    {
+      JSONObject process_name(&events);
+      process_name.AddProperty("name", "process_name");
+      process_name.AddProperty("ph", "M");
+      process_name.AddProperty("pid", pid);
+      {
+        JSONObject args(&process_name, "args");
+        args.AddProperty("name", "Dart VM");
+      }
+    }
+    for (intptr_t i = 0; i < sample_buffer->capacity(); i++) {
+      Sample* sample = sample_buffer->GetSample(i);
+      if (sample->isolate != isolate) {
+        continue;
+      }
+      if (sample->timestamp == 0) {
+        continue;
+      }
+      WriteTracingSample(isolate, pid, sample, events);
+    }
+  }
+  const char* format = "%s/dart-profile-%" Pd "-%" Pd ".json";
+  intptr_t len = OS::SNPrint(NULL, 0, format,
+                             FLAG_profile_dir, pid, isolate->main_port());
+  char* filename = Isolate::Current()->current_zone()->Alloc<char>(len + 1);
+  OS::SNPrint(filename, len + 1, format,
+              FLAG_profile_dir, pid, isolate->main_port());
+  void* f = file_open(filename, true);
+  if (f == NULL) {
+    // Cannot write.
+    return;
+  }
+  TextBuffer* buffer = stream.buffer();
+  ASSERT(buffer != NULL);
+  file_write(buffer->buf(), buffer->length(), f);
+  file_close(f);
+  BeginExecution(isolate);
+}
+
+
+IsolateProfilerData::IsolateProfilerData(SampleBuffer* sample_buffer,
+                                         bool own_sample_buffer) {
   sample_buffer_ = sample_buffer;
-  timer_expiration_micros_ = kNoExpirationTime;
-  last_sampled_micros_ = 0;
-  thread_id_ = 0;
+  own_sample_buffer_ = own_sample_buffer;
 }
 
 
 IsolateProfilerData::~IsolateProfilerData() {
-}
-
-
-void IsolateProfilerData::SampledAt(int64_t current_time) {
-  last_sampled_micros_ = current_time;
-}
-
-
-void IsolateProfilerData::Scheduled(int64_t current_time, ThreadId thread_id) {
-  timer_expiration_micros_ = current_time + sample_interval_micros_;
-  thread_id_ = thread_id;
-  Thread::GetThreadCpuUsage(thread_id_, &cpu_usage_);
-}
-
-
-void IsolateProfilerData::Descheduled() {
-  // TODO(johnmccutchan): Track when we ran for a fraction of our sample
-  // interval and incorporate the time difference when scheduling the
-  // isolate again.
-  cpu_usage_ = kDescheduledCpuUsage;
-  timer_expiration_micros_ = kNoExpirationTime;
-  Sample* sample = sample_buffer_->ReserveSample();
-  ASSERT(sample != NULL);
-  sample->timestamp = OS::GetCurrentTimeMicros();
-  sample->cpu_usage = 0;
-  sample->vm_tags = Sample::kIdle;
+  if (own_sample_buffer_) {
+    delete sample_buffer_;
+    sample_buffer_ = NULL;
+    own_sample_buffer_ = false;
+  }
 }
 
 
 const char* Sample::kLookupSymbol = "Symbol Not Looked Up";
 const char* Sample::kNoSymbol = "No Symbol Found";
+const char* Sample::kNoFrame = "<no frame>";
 
-Sample::Sample()  {
-  timestamp = 0;
-  cpu_usage = 0;
-  for (int i = 0; i < kNumStackFrames; i++) {
+void Sample::Init(SampleType type, Isolate* isolate, int64_t timestamp,
+                  ThreadId tid) {
+  this->timestamp = timestamp;
+  this->tid = tid;
+  this->isolate = isolate;
+  for (intptr_t i = 0; i < kNumStackFrames; i++) {
     pcs[i] = 0;
   }
-  vm_tags = kIdle;
+  this->type = type;
+  vm_tags = 0;
   runtime_tags = 0;
 }
 
-
 SampleBuffer::SampleBuffer(intptr_t capacity) {
-  start_ = 0;
-  end_ = 0;
   capacity_ = capacity;
   samples_ = reinterpret_cast<Sample*>(calloc(capacity, sizeof(Sample)));
+  cursor_ = 0;
 }
 
 
@@ -587,8 +452,7 @@
   if (samples_ != NULL) {
     free(samples_);
     samples_ = NULL;
-    start_ = 0;
-    end_ = 0;
+    cursor_ = 0;
     capacity_ = 0;
   }
 }
@@ -596,40 +460,10 @@
 
 Sample* SampleBuffer::ReserveSample() {
   ASSERT(samples_ != NULL);
-  intptr_t index = end_;
-  end_ = WrapIncrement(end_);
-  if (end_ == start_) {
-    start_ = WrapIncrement(start_);
-  }
-  ASSERT(index >= 0);
-  ASSERT(index < capacity_);
-  // Reset.
-  samples_[index] = Sample();
-  return &samples_[index];
-}
-
-
-Sample* SampleBuffer::FirstSample() const {
-  return &samples_[start_];
-}
-
-
-Sample* SampleBuffer::NextSample(Sample* sample) const {
-  ASSERT(sample >= &samples_[0]);
-  ASSERT(sample < &samples_[capacity_]);
-  intptr_t index = sample - samples_;
-  index = WrapIncrement(index);
-  return &samples_[index];
-}
-
-
-Sample* SampleBuffer::LastSample() const {
-  return &samples_[end_];
-}
-
-
-intptr_t SampleBuffer::WrapIncrement(intptr_t i) const {
-  return (i + 1) % capacity_;
+  uintptr_t cursor = AtomicOperations::FetchAndIncrement(&cursor_);
+  // Map back into sample buffer range.
+  cursor = cursor % capacity_;
+  return &samples_[cursor];
 }
 
 
@@ -651,10 +485,22 @@
 
 
 int ProfilerSampleStackWalker::walk() {
+  const intptr_t kMaxStep = 0x1000;  // 4K.
   uword* pc = reinterpret_cast<uword*>(original_pc_);
+#define WALK_STACK
 #if defined(WALK_STACK)
   uword* fp = reinterpret_cast<uword*>(original_fp_);
   uword* previous_fp = fp;
+  if (original_sp_ > original_fp_) {
+    // Stack pointer should not be above frame pointer.
+    return 0;
+  }
+  intptr_t gap = original_fp_ - original_sp_;
+  if (gap >= kMaxStep) {
+    // Gap between frame pointer and stack pointer is
+    // too large.
+    return 0;
+  }
   if (original_sp_ < lower_bound_) {
     // The stack pointer gives us a better lower bound than
     // the isolates stack limit.
@@ -669,8 +515,11 @@
     pc = CallerPC(fp);
     previous_fp = fp;
     fp = CallerFP(fp);
-    if ((fp <= previous_fp) || !ValidFramePointer(fp)) {
-      // Frame pointers should only move to higher addresses.
+    intptr_t step = fp - previous_fp;
+    if ((step >= kMaxStep) || (fp <= previous_fp) || !ValidFramePointer(fp)) {
+      // Frame pointer step is too large.
+      // Frame pointer did not move to a higher address.
+      // Frame pointer is outside of isolate stack bounds.
       break;
     }
     // Move the lower bound up.
diff --git a/runtime/vm/profiler.h b/runtime/vm/profiler.h
index bec51e6..1e0ab73 100644
--- a/runtime/vm/profiler.h
+++ b/runtime/vm/profiler.h
@@ -5,110 +5,62 @@
 #ifndef VM_PROFILER_H_
 #define VM_PROFILER_H_
 
-#include "platform/hashmap.h"
-#include "platform/thread.h"
 #include "vm/allocation.h"
 #include "vm/code_observers.h"
 #include "vm/globals.h"
+#include "vm/thread.h"
+#include "vm/thread_interrupter.h"
 
 namespace dart {
 
 // Forward declarations.
+class JSONArray;
 class JSONStream;
+struct Sample;
 
-// Profiler manager.
-class ProfilerManager : public AllStatic {
+// Profiler
+class Profiler : public AllStatic {
  public:
   static void InitOnce();
   static void Shutdown();
 
-  static void SetupIsolateForProfiling(Isolate* isolate);
-  static void ShutdownIsolateForProfiling(Isolate* isolate);
-  static void ScheduleIsolate(Isolate* isolate, bool inside_signal = false);
-  static void DescheduleIsolate(Isolate* isolate);
+  static void InitProfilingForIsolate(Isolate* isolate,
+                                      bool shared_buffer = false);
+  static void ShutdownProfilingForIsolate(Isolate* isolate);
+
+  static void BeginExecution(Isolate* isolate);
+  static void EndExecution(Isolate* isolate);
 
   static void PrintToJSONStream(Isolate* isolate, JSONStream* stream);
 
-  static void WriteTracing(Isolate* isolate, const char* name, Dart_Port port);
+  static void WriteTracing(Isolate* isolate);
+
+  static SampleBuffer* sample_buffer() {
+    return sample_buffer_;
+  }
 
  private:
-  static const intptr_t kMaxProfiledIsolates = 4096;
   static bool initialized_;
-  static bool shutdown_;
-  static bool thread_running_;
   static Monitor* monitor_;
-  static Monitor* start_stop_monitor_;
 
-  static Isolate** isolates_;
-  static intptr_t isolates_capacity_;
-  static intptr_t isolates_size_;
+  static void WriteTracingSample(Isolate* isolate, intptr_t pid,
+                                 Sample* sample, JSONArray& events);
 
-  static void ScheduleIsolateHelper(Isolate* isolate);
-  static void ResizeIsolates(intptr_t new_capacity);
-  static void AddIsolate(Isolate* isolate);
-  static intptr_t FindIsolate(Isolate* isolate);
-  static void RemoveIsolate(intptr_t i);
+  static void RecordTickInterruptCallback(const InterruptedThreadState& state,
+                                          void* data);
 
-  // Returns the microseconds until the next live timer fires.
-  static int64_t SampleAndRescheduleIsolates(int64_t current_time);
-  static void FreeIsolateProfilingData(Isolate* isolate);
-  static void ThreadMain(uword parameters);
+  static void RecordSampleInterruptCallback(const InterruptedThreadState& state,
+                                            void* data);
+
+  static SampleBuffer* sample_buffer_;
 };
 
 
 class IsolateProfilerData {
  public:
-  static const int64_t kDescheduledCpuUsage = -1;
-  static const int64_t kNoExpirationTime = -2;
-
-  IsolateProfilerData(Isolate* isolate, SampleBuffer* sample_buffer);
+  IsolateProfilerData(SampleBuffer* sample_buffer, bool own_sample_buffer);
   ~IsolateProfilerData();
 
-  int64_t sample_interval_micros() const { return sample_interval_micros_; }
-
-  void set_sample_interval_micros(int64_t sample_interval) {
-    sample_interval_micros_ = sample_interval;
-  }
-
-  bool CanExpire() const {
-    return timer_expiration_micros_ != kNoExpirationTime;
-  }
-
-  bool ShouldSample(int64_t current_time) const {
-    return CanExpire() && TimeUntilExpiration(current_time) <= 0;
-  }
-
-  int64_t TimeUntilExpiration(int64_t current_time_micros) const {
-    ASSERT(CanExpire());
-    return timer_expiration_micros_ - current_time_micros;
-  }
-
-  void set_cpu_usage(int64_t cpu_usage) {
-    cpu_usage_ = cpu_usage;
-  }
-
-  void SampledAt(int64_t current_time);
-
-  void Scheduled(int64_t current_time, ThreadId thread);
-
-  void Descheduled();
-
-  int64_t cpu_usage() const { return cpu_usage_; }
-
-  int64_t ComputeDeltaAndSetCpuUsage(int64_t cpu_usage) {
-    int64_t delta = 0;
-    if (cpu_usage_ != kDescheduledCpuUsage) {
-      // Only compute the real delta if we are being sampled regularly.
-      delta = cpu_usage - cpu_usage_;
-    }
-    set_cpu_usage(cpu_usage);
-    return delta;
-  }
-
-  ThreadId thread_id() const { return thread_id_; }
-
-  Isolate* isolate() const { return isolate_; }
-
   SampleBuffer* sample_buffer() const { return sample_buffer_; }
 
   void set_sample_buffer(SampleBuffer* sample_buffer) {
@@ -116,13 +68,8 @@
   }
 
  private:
-  int64_t last_sampled_micros_;
-  int64_t timer_expiration_micros_;
-  int64_t sample_interval_micros_;
-  int64_t cpu_usage_;
-  ThreadId thread_id_;
-  Isolate* isolate_;
   SampleBuffer* sample_buffer_;
+  bool own_sample_buffer_;
   DISALLOW_COPY_AND_ASSIGN(IsolateProfilerData);
 };
 
@@ -131,22 +78,26 @@
 struct Sample {
   static const char* kLookupSymbol;
   static const char* kNoSymbol;
-  static const intptr_t kNumStackFrames = 4;
-  enum SampleState {
-    kIdle = 0,
-    kExecuting = 1,
-    kNumSampleStates
+  static const char* kNoFrame;
+  static const intptr_t kNumStackFrames = 6;
+  enum SampleType {
+    kIsolateStart,
+    kIsolateStop,
+    kIsolateSample,
   };
   int64_t timestamp;
-  int64_t cpu_usage;
+  ThreadId tid;
+  Isolate* isolate;
   uintptr_t pcs[kNumStackFrames];
+  SampleType type;
   uint16_t vm_tags;
   uint16_t runtime_tags;
-  Sample();
+
+  void Init(SampleType type, Isolate* isolate, int64_t timestamp, ThreadId tid);
 };
 
 
-// Ring buffer of samples. One per isolate.
+// Ring buffer of samples.
 class SampleBuffer {
  public:
   static const intptr_t kDefaultBufferCapacity = 120000;  // 2 minutes @ 1000hz.
@@ -158,16 +109,17 @@
 
   Sample* ReserveSample();
 
-  Sample* FirstSample() const;
-  Sample* NextSample(Sample* sample) const;
-  Sample* LastSample() const;
+  Sample* GetSample(intptr_t i) const {
+    ASSERT(i >= 0);
+    ASSERT(i < capacity_);
+    return &samples_[i];
+  }
+
  private:
   Sample* samples_;
   intptr_t capacity_;
-  intptr_t start_;
-  intptr_t end_;
+  uintptr_t cursor_;
 
-  intptr_t WrapIncrement(intptr_t i) const;
   DISALLOW_COPY_AND_ASSIGN(SampleBuffer);
 };
 
diff --git a/runtime/vm/profiler_android.cc b/runtime/vm/profiler_android.cc
deleted file mode 100644
index f1d5704..0000000
--- a/runtime/vm/profiler_android.cc
+++ /dev/null
@@ -1,129 +0,0 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-#include "platform/globals.h"
-#if defined(TARGET_OS_ANDROID)
-
-#include "vm/isolate.h"
-#include "vm/json_stream.h"
-#include "vm/profiler.h"
-#include "vm/signal_handler.h"
-
-namespace dart {
-
-DECLARE_FLAG(bool, profile);
-DECLARE_FLAG(bool, trace_profiled_isolates);
-
-static void ProfileSignalAction(int signal, siginfo_t* info, void* context_) {
-  if (signal != SIGPROF) {
-    return;
-  }
-  Isolate* isolate = Isolate::Current();
-  if (isolate == NULL) {
-    return;
-  }
-  // Thread owns no profiler locks at this point.
-  {
-    // Thread owns isolate profiler data mutex.
-    ScopedMutex profiler_data_lock(isolate->profiler_data_mutex());
-    IsolateProfilerData* profiler_data = isolate->profiler_data();
-    if ((profiler_data == NULL) || !profiler_data->CanExpire() ||
-        (profiler_data->sample_buffer() == NULL)) {
-      // Descheduled.
-      return;
-    }
-    if (profiler_data->thread_id() == Thread::GetCurrentThreadId()) {
-      // Still scheduled on this thread.
-      // TODO(johnmccutchan): Perform sample on Android.
-    }
-  }
-  // Thread owns no profiler locks at this point.
-  // This call will acquire both ProfilerManager::monitor and the
-  // isolate's profiler data mutex.
-  ProfilerManager::ScheduleIsolate(isolate, true);
-}
-
-
-int64_t ProfilerManager::SampleAndRescheduleIsolates(int64_t current_time) {
-  if (isolates_size_ == 0) {
-    return 0;
-  }
-  static const int64_t max_time = 0x7fffffffffffffffLL;
-  int64_t lowest = max_time;
-  intptr_t i = 0;
-  while (i < isolates_size_) {
-    Isolate* isolate = isolates_[i];
-    ScopedMutex isolate_lock(isolate->profiler_data_mutex());
-    IsolateProfilerData* profiler_data = isolate->profiler_data();
-    if (profiler_data == NULL) {
-      // Isolate has been shutdown for profiling.
-      RemoveIsolate(i);
-      // Remove moves the last element into i, do not increment i.
-      continue;
-    }
-    ASSERT(profiler_data != NULL);
-    if (profiler_data->ShouldSample(current_time)) {
-      pthread_kill(profiler_data->thread_id(), SIGPROF);
-      RemoveIsolate(i);
-      // Remove moves the last element into i, do not increment i.
-      continue;
-    }
-    if (profiler_data->CanExpire()) {
-      int64_t isolate_time_left =
-          profiler_data->TimeUntilExpiration(current_time);
-      if (isolate_time_left < 0) {
-        continue;
-      }
-      if (isolate_time_left < lowest) {
-        lowest = isolate_time_left;
-      }
-    }
-    i++;
-  }
-  if (isolates_size_ == 0) {
-    return 0;
-  }
-  if (lowest == max_time) {
-    return 0;
-  }
-  ASSERT(lowest != max_time);
-  ASSERT(lowest > 0);
-  return lowest;
-}
-
-
-void ProfilerManager::ThreadMain(uword parameters) {
-  ASSERT(initialized_);
-  ASSERT(FLAG_profile);
-  SignalHandler::Install(ProfileSignalAction);
-  if (FLAG_trace_profiled_isolates) {
-    OS::Print("ProfilerManager Android ready.\n");
-  }
-  {
-    // Signal to main thread we are ready.
-    ScopedMonitor startup_lock(start_stop_monitor_);
-    thread_running_ = true;
-    startup_lock.Notify();
-  }
-  ScopedMonitor lock(monitor_);
-  while (!shutdown_) {
-    int64_t current_time = OS::GetCurrentTimeMicros();
-    int64_t next_sample = SampleAndRescheduleIsolates(current_time);
-    lock.WaitMicros(next_sample);
-  }
-  if (FLAG_trace_profiled_isolates) {
-    OS::Print("ProfilerManager Android exiting.\n");
-  }
-  {
-    // Signal to main thread we are exiting.
-    ScopedMonitor shutdown_lock(start_stop_monitor_);
-    thread_running_ = false;
-    shutdown_lock.Notify();
-  }
-}
-
-
-}  // namespace dart
-
-#endif  // defined(TARGET_OS_ANDROID)
diff --git a/runtime/vm/profiler_linux.cc b/runtime/vm/profiler_linux.cc
deleted file mode 100644
index 6489a43..0000000
--- a/runtime/vm/profiler_linux.cc
+++ /dev/null
@@ -1,162 +0,0 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-#include "platform/globals.h"
-#if defined(TARGET_OS_LINUX)
-
-#include "vm/isolate.h"
-#include "vm/json_stream.h"
-#include "vm/profiler.h"
-#include "vm/signal_handler.h"
-
-namespace dart {
-
-DECLARE_FLAG(bool, profile);
-DECLARE_FLAG(bool, trace_profiled_isolates);
-
-static void CollectSample(IsolateProfilerData* profiler_data,
-                          uintptr_t pc,
-                          uintptr_t fp,
-                          uintptr_t sp,
-                          uintptr_t stack_lower,
-                          uintptr_t stack_upper) {
-  SampleBuffer* sample_buffer = profiler_data->sample_buffer();
-  Sample* sample = sample_buffer->ReserveSample();
-  ASSERT(sample != NULL);
-  sample->timestamp = OS::GetCurrentTimeMicros();
-  // TODO(johnmccutchan): Make real use of vm_tags and runtime_tags.
-  // Issue # 14777
-  sample->vm_tags = Sample::kExecuting;
-  sample->runtime_tags = 0;
-  int64_t cpu_usage;
-  Thread::GetThreadCpuUsage(profiler_data->thread_id(), &cpu_usage);
-  sample->cpu_usage = profiler_data->ComputeDeltaAndSetCpuUsage(cpu_usage);
-  ProfilerSampleStackWalker stackWalker(sample, stack_lower, stack_upper,
-                                        pc, fp, sp);
-  stackWalker.walk();
-}
-
-
-static void ProfileSignalAction(int signal, siginfo_t* info, void* context_) {
-  if (signal != SIGPROF) {
-    return;
-  }
-  ucontext_t* context = reinterpret_cast<ucontext_t*>(context_);
-  mcontext_t mcontext = context->uc_mcontext;
-  Isolate* isolate = Isolate::Current();
-  if (isolate == NULL) {
-    return;
-  }
-  // Thread owns no profiler locks at this point.
-  {
-    // Thread owns isolate profiler data mutex.
-    ScopedMutex profiler_data_lock(isolate->profiler_data_mutex());
-    IsolateProfilerData* profiler_data = isolate->profiler_data();
-    if ((profiler_data == NULL) || !profiler_data->CanExpire() ||
-        (profiler_data->sample_buffer() == NULL)) {
-      // Descheduled.
-      return;
-    }
-    if (profiler_data->thread_id() == Thread::GetCurrentThreadId()) {
-      // Still scheduled on this thread.
-      uintptr_t stack_lower = 0;
-      uintptr_t stack_upper = 0;
-      isolate->GetStackBounds(&stack_lower, &stack_upper);
-      uintptr_t PC = SignalHandler::GetProgramCounter(mcontext);
-      uintptr_t FP = SignalHandler::GetFramePointer(mcontext);
-      uintptr_t SP = SignalHandler::GetStackPointer(mcontext);
-      int64_t sample_time = OS::GetCurrentTimeMicros();
-      profiler_data->SampledAt(sample_time);
-      CollectSample(profiler_data, PC, FP, SP, stack_lower, stack_upper);
-    }
-  }
-  // Thread owns no profiler locks at this point.
-  // This call will acquire both ProfilerManager::monitor and the
-  // isolate's profiler data mutex.
-  ProfilerManager::ScheduleIsolate(isolate, true);
-}
-
-
-int64_t ProfilerManager::SampleAndRescheduleIsolates(int64_t current_time) {
-  if (isolates_size_ == 0) {
-    return 0;
-  }
-  static const int64_t max_time = 0x7fffffffffffffffLL;
-  int64_t lowest = max_time;
-  intptr_t i = 0;
-  while (i < isolates_size_) {
-    Isolate* isolate = isolates_[i];
-    ScopedMutex isolate_lock(isolate->profiler_data_mutex());
-    IsolateProfilerData* profiler_data = isolate->profiler_data();
-    if (profiler_data == NULL) {
-      // Isolate has been shutdown for profiling.
-      RemoveIsolate(i);
-      // Remove moves the last element into i, do not increment i.
-      continue;
-    }
-    ASSERT(profiler_data != NULL);
-    if (profiler_data->ShouldSample(current_time)) {
-      pthread_kill(profiler_data->thread_id(), SIGPROF);
-      RemoveIsolate(i);
-      // Remove moves the last element into i, do not increment i.
-      continue;
-    }
-    if (profiler_data->CanExpire()) {
-      int64_t isolate_time_left =
-          profiler_data->TimeUntilExpiration(current_time);
-      if (isolate_time_left < 0) {
-        continue;
-      }
-      if (isolate_time_left < lowest) {
-        lowest = isolate_time_left;
-      }
-    }
-    i++;
-  }
-  if (isolates_size_ == 0) {
-    return 0;
-  }
-  if (lowest == max_time) {
-    return 0;
-  }
-  ASSERT(lowest != max_time);
-  ASSERT(lowest > 0);
-  return lowest;
-}
-
-
-void ProfilerManager::ThreadMain(uword parameters) {
-  ASSERT(initialized_);
-  ASSERT(FLAG_profile);
-  SignalHandler::Install(ProfileSignalAction);
-  if (FLAG_trace_profiled_isolates) {
-    OS::Print("ProfilerManager Linux ready.\n");
-  }
-  {
-    // Signal to main thread we are ready.
-    ScopedMonitor startup_lock(start_stop_monitor_);
-    thread_running_ = true;
-    startup_lock.Notify();
-  }
-  ScopedMonitor lock(monitor_);
-  while (!shutdown_) {
-    int64_t current_time = OS::GetCurrentTimeMicros();
-    int64_t next_sample = SampleAndRescheduleIsolates(current_time);
-    lock.WaitMicros(next_sample);
-  }
-  if (FLAG_trace_profiled_isolates) {
-    OS::Print("ProfilerManager Linux exiting.\n");
-  }
-  {
-    // Signal to main thread we are exiting.
-    ScopedMonitor shutdown_lock(start_stop_monitor_);
-    thread_running_ = false;
-    shutdown_lock.Notify();
-  }
-}
-
-
-}  // namespace dart
-
-#endif  // defined(TARGET_OS_LINUX)
diff --git a/runtime/vm/profiler_macos.cc b/runtime/vm/profiler_macos.cc
deleted file mode 100644
index e1ae399..0000000
--- a/runtime/vm/profiler_macos.cc
+++ /dev/null
@@ -1,162 +0,0 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-#include "platform/globals.h"
-#if defined(TARGET_OS_MACOS)
-
-#include "vm/isolate.h"
-#include "vm/json_stream.h"
-#include "vm/profiler.h"
-#include "vm/signal_handler.h"
-
-namespace dart {
-
-DECLARE_FLAG(bool, profile);
-DECLARE_FLAG(bool, trace_profiled_isolates);
-
-static void CollectSample(IsolateProfilerData* profiler_data,
-                          uintptr_t pc,
-                          uintptr_t fp,
-                          uintptr_t sp,
-                          uintptr_t stack_lower,
-                          uintptr_t stack_upper) {
-  SampleBuffer* sample_buffer = profiler_data->sample_buffer();
-  Sample* sample = sample_buffer->ReserveSample();
-  ASSERT(sample != NULL);
-  sample->timestamp = OS::GetCurrentTimeMicros();
-  // TODO(johnmccutchan): Make real use of vm_tags and runtime_tags.
-  // Issue # 14777
-  sample->vm_tags = Sample::kExecuting;
-  sample->runtime_tags = 0;
-  int64_t cpu_usage = 0;
-  Thread::GetThreadCpuUsage(profiler_data->thread_id(), &cpu_usage);
-  sample->cpu_usage = profiler_data->ComputeDeltaAndSetCpuUsage(cpu_usage);
-  ProfilerSampleStackWalker stackWalker(sample, stack_lower, stack_upper,
-                                        pc, fp, sp);
-  stackWalker.walk();
-}
-
-
-static void ProfileSignalAction(int signal, siginfo_t* info, void* context_) {
-  if (signal != SIGPROF) {
-    return;
-  }
-  ucontext_t* context = reinterpret_cast<ucontext_t*>(context_);
-  mcontext_t mcontext = context->uc_mcontext;
-  Isolate* isolate = Isolate::Current();
-  if (isolate == NULL) {
-    return;
-  }
-  // Thread owns no profiler locks at this point.
-  {
-    // Thread owns isolate profiler data mutex.
-    ScopedMutex profiler_data_lock(isolate->profiler_data_mutex());
-    IsolateProfilerData* profiler_data = isolate->profiler_data();
-    if ((profiler_data == NULL) || !profiler_data->CanExpire() ||
-        (profiler_data->sample_buffer() == NULL)) {
-      // Descheduled.
-      return;
-    }
-    if (profiler_data->thread_id() == Thread::GetCurrentThreadId()) {
-      // Still scheduled on this thread.
-      uintptr_t stack_lower = 0;
-      uintptr_t stack_upper = 0;
-      isolate->GetStackBounds(&stack_lower, &stack_upper);
-      uintptr_t PC = SignalHandler::GetProgramCounter(mcontext);
-      uintptr_t FP = SignalHandler::GetFramePointer(mcontext);
-      uintptr_t SP = SignalHandler::GetStackPointer(mcontext);
-      int64_t sample_time = OS::GetCurrentTimeMicros();
-      profiler_data->SampledAt(sample_time);
-      CollectSample(profiler_data, PC, FP, SP, stack_lower, stack_upper);
-    }
-  }
-  // Thread owns no profiler locks at this point.
-  // This call will acquire both ProfilerManager::monitor and the
-  // isolate's profiler data mutex.
-  ProfilerManager::ScheduleIsolate(isolate, true);
-}
-
-
-int64_t ProfilerManager::SampleAndRescheduleIsolates(int64_t current_time) {
-  if (isolates_size_ == 0) {
-    return 0;
-  }
-  static const int64_t max_time = 0x7fffffffffffffffLL;
-  int64_t lowest = max_time;
-  intptr_t i = 0;
-  while (i < isolates_size_) {
-    Isolate* isolate = isolates_[i];
-    ScopedMutex isolate_lock(isolate->profiler_data_mutex());
-    IsolateProfilerData* profiler_data = isolate->profiler_data();
-    if (profiler_data == NULL) {
-      // Isolate has been shutdown for profiling.
-      RemoveIsolate(i);
-      // Remove moves the last element into i, do not increment i.
-      continue;
-    }
-    ASSERT(profiler_data != NULL);
-    if (profiler_data->ShouldSample(current_time)) {
-      pthread_kill(profiler_data->thread_id(), SIGPROF);
-      RemoveIsolate(i);
-      // Remove moves the last element into i, do not increment i.
-      continue;
-    }
-    if (profiler_data->CanExpire()) {
-      int64_t isolate_time_left =
-          profiler_data->TimeUntilExpiration(current_time);
-      if (isolate_time_left < 0) {
-        continue;
-      }
-      if (isolate_time_left < lowest) {
-        lowest = isolate_time_left;
-      }
-    }
-    i++;
-  }
-  if (isolates_size_ == 0) {
-    return 0;
-  }
-  if (lowest == max_time) {
-    return 0;
-  }
-  ASSERT(lowest != max_time);
-  ASSERT(lowest > 0);
-  return lowest;
-}
-
-
-void ProfilerManager::ThreadMain(uword parameters) {
-  ASSERT(initialized_);
-  ASSERT(FLAG_profile);
-  SignalHandler::Install(ProfileSignalAction);
-  if (FLAG_trace_profiled_isolates) {
-    OS::Print("ProfilerManager MacOS ready.\n");
-  }
-  {
-    // Signal to main thread we are ready.
-    ScopedMonitor startup_lock(start_stop_monitor_);
-    thread_running_ = true;
-    startup_lock.Notify();
-  }
-  ScopedMonitor lock(monitor_);
-  while (!shutdown_) {
-    int64_t current_time = OS::GetCurrentTimeMicros();
-    int64_t next_sample = SampleAndRescheduleIsolates(current_time);
-    lock.WaitMicros(next_sample);
-  }
-  if (FLAG_trace_profiled_isolates) {
-    OS::Print("ProfilerManager MacOS exiting.\n");
-  }
-  {
-    // Signal to main thread we are exiting.
-    ScopedMonitor shutdown_lock(start_stop_monitor_);
-    thread_running_ = false;
-    shutdown_lock.Notify();
-  }
-}
-
-
-}  // namespace dart
-
-#endif  // defined(TARGET_OS_MACOS)
diff --git a/runtime/vm/profiler_test.cc b/runtime/vm/profiler_test.cc
index a974b85..610fa41 100644
--- a/runtime/vm/profiler_test.cc
+++ b/runtime/vm/profiler_test.cc
@@ -14,23 +14,29 @@
 
 class ProfileSampleBufferTestHelper {
  public:
-  static intptr_t IterateCount(const SampleBuffer& sample_buffer) {
+  static intptr_t IterateCount(const Isolate* isolate,
+                               const SampleBuffer& sample_buffer) {
     intptr_t c = 0;
-    for (Sample* i = sample_buffer.FirstSample();
-         i != sample_buffer.LastSample();
-         i = sample_buffer.NextSample(i)) {
+    for (intptr_t i = 0; i < sample_buffer.capacity(); i++) {
+      Sample* sample = sample_buffer.GetSample(i);
+      if (sample->isolate != isolate) {
+        continue;
+      }
       c++;
     }
     return c;
   }
 
 
-  static intptr_t IterateSumPC(const SampleBuffer& sample_buffer) {
+  static intptr_t IterateSumPC(const Isolate* isolate,
+                               const SampleBuffer& sample_buffer) {
     intptr_t c = 0;
-    for (Sample* i = sample_buffer.FirstSample();
-         i != sample_buffer.LastSample();
-         i = sample_buffer.NextSample(i)) {
-      c += i->pcs[0];
+    for (intptr_t i = 0; i < sample_buffer.capacity(); i++) {
+      Sample* sample = sample_buffer.GetSample(i);
+      if (sample->isolate != isolate) {
+        continue;
+      }
+      c += sample->pcs[0];
     }
     return c;
   }
@@ -39,35 +45,46 @@
 
 TEST_CASE(ProfilerSampleBufferWrapTest) {
   SampleBuffer* sample_buffer = new SampleBuffer(3);
-  EXPECT_EQ(0, ProfileSampleBufferTestHelper::IterateSumPC(*sample_buffer));
+  Isolate* i = reinterpret_cast<Isolate*>(0x1);
+  EXPECT_EQ(0, ProfileSampleBufferTestHelper::IterateSumPC(i, *sample_buffer));
   Sample* s;
   s = sample_buffer->ReserveSample();
+  s->isolate = i;
   s->pcs[0] = 2;
-  EXPECT_EQ(2, ProfileSampleBufferTestHelper::IterateSumPC(*sample_buffer));
+  EXPECT_EQ(2, ProfileSampleBufferTestHelper::IterateSumPC(i, *sample_buffer));
   s = sample_buffer->ReserveSample();
+  s->isolate = i;
   s->pcs[0] = 4;
-  EXPECT_EQ(6, ProfileSampleBufferTestHelper::IterateSumPC(*sample_buffer));
+  EXPECT_EQ(6, ProfileSampleBufferTestHelper::IterateSumPC(i, *sample_buffer));
   s = sample_buffer->ReserveSample();
+  s->isolate = i;
   s->pcs[0] = 6;
-  EXPECT_EQ(10, ProfileSampleBufferTestHelper::IterateSumPC(*sample_buffer));
+  EXPECT_EQ(12, ProfileSampleBufferTestHelper::IterateSumPC(i, *sample_buffer));
   s = sample_buffer->ReserveSample();
+  s->isolate = i;
   s->pcs[0] = 8;
-  EXPECT_EQ(14, ProfileSampleBufferTestHelper::IterateSumPC(*sample_buffer));
+  EXPECT_EQ(18, ProfileSampleBufferTestHelper::IterateSumPC(i, *sample_buffer));
   delete sample_buffer;
 }
 
 
 TEST_CASE(ProfilerSampleBufferIterateTest) {
   SampleBuffer* sample_buffer = new SampleBuffer(3);
-  EXPECT_EQ(0, ProfileSampleBufferTestHelper::IterateCount(*sample_buffer));
-  sample_buffer->ReserveSample();
-  EXPECT_EQ(1, ProfileSampleBufferTestHelper::IterateCount(*sample_buffer));
-  sample_buffer->ReserveSample();
-  EXPECT_EQ(2, ProfileSampleBufferTestHelper::IterateCount(*sample_buffer));
-  sample_buffer->ReserveSample();
-  EXPECT_EQ(2, ProfileSampleBufferTestHelper::IterateCount(*sample_buffer));
-  sample_buffer->ReserveSample();
-  EXPECT_EQ(2, ProfileSampleBufferTestHelper::IterateCount(*sample_buffer));
+  Isolate* i = reinterpret_cast<Isolate*>(0x1);
+  EXPECT_EQ(0, ProfileSampleBufferTestHelper::IterateCount(i, *sample_buffer));
+  Sample* s;
+  s = sample_buffer->ReserveSample();
+  s->isolate = i;
+  EXPECT_EQ(1, ProfileSampleBufferTestHelper::IterateCount(i, *sample_buffer));
+  s = sample_buffer->ReserveSample();
+  s->isolate = i;
+  EXPECT_EQ(2, ProfileSampleBufferTestHelper::IterateCount(i, *sample_buffer));
+  s = sample_buffer->ReserveSample();
+  s->isolate = i;
+  EXPECT_EQ(3, ProfileSampleBufferTestHelper::IterateCount(i, *sample_buffer));
+  s = sample_buffer->ReserveSample();
+  s->isolate = i;
+  EXPECT_EQ(3, ProfileSampleBufferTestHelper::IterateCount(i, *sample_buffer));
   delete sample_buffer;
 }
 
diff --git a/runtime/vm/profiler_win.cc b/runtime/vm/profiler_win.cc
deleted file mode 100644
index 3bc9e41..0000000
--- a/runtime/vm/profiler_win.cc
+++ /dev/null
@@ -1,170 +0,0 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-#include "platform/globals.h"
-#if defined(TARGET_OS_WINDOWS)
-
-#include "vm/isolate.h"
-#include "vm/profiler.h"
-
-namespace dart {
-
-#define kThreadError -1
-
-DECLARE_FLAG(bool, profile);
-DECLARE_FLAG(bool, trace_profiled_isolates);
-
-static void CollectSample(IsolateProfilerData* profiler_data,
-                          uintptr_t pc,
-                          uintptr_t fp,
-                          uintptr_t stack_lower,
-                          uintptr_t stack_upper) {
-  uintptr_t sp = stack_lower;
-  ASSERT(profiler_data != NULL);
-  SampleBuffer* sample_buffer = profiler_data->sample_buffer();
-  ASSERT(sample_buffer != NULL);
-  Sample* sample = sample_buffer->ReserveSample();
-  ASSERT(sample != NULL);
-  sample->timestamp = OS::GetCurrentTimeMicros();
-  // TODO(johnmccutchan): Make real use of vm_tags and runtime_tags.
-  // Issue # 14777
-  sample->vm_tags = Sample::kExecuting;
-  sample->runtime_tags = 0;
-  int64_t cpu_usage;
-  Thread::GetThreadCpuUsage(profiler_data->thread_id(), &cpu_usage);
-  sample->cpu_usage = profiler_data->ComputeDeltaAndSetCpuUsage(cpu_usage);
-  ProfilerSampleStackWalker stackWalker(sample, stack_lower, stack_upper,
-                                        pc, fp, sp);
-  stackWalker.walk();
-}
-
-
-static bool GrabRegisters(ThreadId thread, uintptr_t* pc, uintptr_t* fp,
-                          uintptr_t* sp) {
-  CONTEXT context;
-  memset(&context, 0, sizeof(context));
-  context.ContextFlags = CONTEXT_FULL;
-  if (GetThreadContext(thread, &context) != 0) {
-#if defined(TARGET_ARCH_IA32)
-    *pc = static_cast<uintptr_t>(context.Eip);
-    *fp = static_cast<uintptr_t>(context.Ebp);
-    *sp = static_cast<uintptr_t>(context.Esp);
-#elif defined(TARGET_ARCH_X64)
-    *pc = reinterpret_cast<uintptr_t>(context.Rip);
-    *fp = reinterpret_cast<uintptr_t>(context.Rbp);
-    *sp = reinterpret_cast<uintptr_t>(context.Rsp);
-#else
-    UNIMPLEMENTED();
-#endif
-    return true;
-  }
-  return false;
-}
-
-
-static void SuspendAndSample(Isolate* isolate,
-                             IsolateProfilerData* profiler_data) {
-  ASSERT(GetCurrentThread() != profiler_data->thread_id());
-  DWORD result = SuspendThread(profiler_data->thread_id());
-  if (result == kThreadError) {
-    return;
-  }
-  uintptr_t PC;
-  uintptr_t FP;
-  uintptr_t stack_lower;
-  uintptr_t stack_upper;
-  bool r = isolate->GetStackBounds(&stack_lower, &stack_upper);
-  if (r) {
-    r = GrabRegisters(profiler_data->thread_id(), &PC, &FP, &stack_lower);
-    if (r) {
-      int64_t sample_time = OS::GetCurrentTimeMicros();
-      profiler_data->SampledAt(sample_time);
-      CollectSample(profiler_data, PC, FP, stack_lower, stack_upper);
-    }
-  }
-
-  ResumeThread(profiler_data->thread_id());
-}
-
-
-static void Reschedule(IsolateProfilerData* profiler_data) {
-  profiler_data->Scheduled(OS::GetCurrentTimeMicros(),
-                           profiler_data->thread_id());
-}
-
-
-int64_t ProfilerManager::SampleAndRescheduleIsolates(int64_t current_time) {
-  if (isolates_size_ == 0) {
-    return 0;
-  }
-  static const int64_t max_time = 0x7fffffffffffffffLL;
-  int64_t lowest = max_time;
-  for (intptr_t i = 0; i < isolates_size_; i++) {
-    Isolate* isolate = isolates_[i];
-    ScopedMutex isolate_lock(isolate->profiler_data_mutex());
-    IsolateProfilerData* profiler_data = isolate->profiler_data();
-    if ((profiler_data == NULL) || !profiler_data->CanExpire() ||
-        (profiler_data->sample_buffer() == NULL)) {
-      // Descheduled.
-      continue;
-    }
-    if (profiler_data->ShouldSample(current_time)) {
-      SuspendAndSample(isolate, profiler_data);
-      Reschedule(profiler_data);
-    }
-    if (profiler_data->CanExpire()) {
-      int64_t isolate_time_left =
-          profiler_data->TimeUntilExpiration(current_time);
-      if (isolate_time_left < 0) {
-        continue;
-      }
-      if (isolate_time_left < lowest) {
-        lowest = isolate_time_left;
-      }
-    }
-  }
-  if (isolates_size_ == 0) {
-    return 0;
-  }
-  if (lowest == max_time) {
-    return 0;
-  }
-  ASSERT(lowest != max_time);
-  ASSERT(lowest > 0);
-  return lowest;
-}
-
-
-void ProfilerManager::ThreadMain(uword parameters) {
-  ASSERT(initialized_);
-  ASSERT(FLAG_profile);
-  if (FLAG_trace_profiled_isolates) {
-    OS::Print("ProfilerManager Windows ready.\n");
-  }
-  {
-    // Signal to main thread we are ready.
-    ScopedMonitor startup_lock(start_stop_monitor_);
-    thread_running_ = true;
-    startup_lock.Notify();
-  }
-  ScopedMonitor lock(monitor_);
-  while (!shutdown_) {
-    int64_t current_time = OS::GetCurrentTimeMicros();
-    int64_t next_sample = SampleAndRescheduleIsolates(current_time);
-    lock.WaitMicros(next_sample);
-  }
-  if (FLAG_trace_profiled_isolates) {
-    OS::Print("ProfilerManager Windows exiting.\n");
-  }
-  {
-    // Signal to main thread we are exiting.
-    ScopedMonitor shutdown_lock(start_stop_monitor_);
-    thread_running_ = false;
-    shutdown_lock.Notify();
-  }
-}
-
-}  // namespace dart
-
-#endif  // defined(TARGET_OS_WINDOWS)
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index b5514df..0ac92dc 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -490,7 +490,8 @@
   RawClass* patch_class_;
   RawFunction* signature_function_;  // Associated function for signature class.
   RawArray* constants_;  // Canonicalized values of this class.
-  RawArray* canonical_types_;  // Canonicalized types of this class.
+  RawObject* canonical_types_;  // An array of canonicalized types of this class
+                                // or the canonical type.
   RawArray* invocation_dispatcher_cache_;   // Cache for dispatcher functions.
   RawCode* allocation_stub_;  // Stub code for allocation of instances.
   RawObject** to() {
diff --git a/runtime/vm/scavenger.cc b/runtime/vm/scavenger.cc
index dd63408..7458954 100644
--- a/runtime/vm/scavenger.cc
+++ b/runtime/vm/scavenger.cc
@@ -21,6 +21,9 @@
 
 namespace dart {
 
+  DEFINE_FLAG(int, early_tenuring_threshold, 66, "Skip TO space when promoting"
+                                                 " above this percentage.");
+
 // Scavenger uses RawObject::kMarkBit to distinguish forwaded and non-forwarded
 // objects. The kMarkBit does not intersect with the target address because of
 // object alignment.
@@ -369,10 +372,22 @@
 }
 
 
-void Scavenger::Epilogue(Isolate* isolate, bool invoke_api_callbacks) {
+void Scavenger::Epilogue(Isolate* isolate,
+                         ScavengerVisitor* visitor,
+                         bool invoke_api_callbacks) {
   // All objects in the to space have been copied from the from space at this
   // moment.
-  survivor_end_ = top_;
+  int promotion_ratio = static_cast<int>(
+      (static_cast<double>(visitor->bytes_promoted()) /
+       static_cast<double>(to_->size())) * 100.0);
+  if (promotion_ratio < FLAG_early_tenuring_threshold) {
+    // Remember the limit to which objects have been copied.
+    survivor_end_ = top_;
+  } else {
+    // Move survivor end to the end of the to_ space, making all surviving
+    // objects candidates for promotion.
+    survivor_end_ = end_;
+  }
 
 #if defined(DEBUG)
   VerifyStoreBufferPointerVisitor verify_store_buffer_visitor(isolate, to_);
@@ -673,7 +688,7 @@
   int64_t end = OS::GetCurrentTimeMicros();
   heap_->RecordTime(kProcessToSpace, middle - start);
   heap_->RecordTime(kIterateWeaks, end - middle);
-  Epilogue(isolate, invoke_api_callbacks);
+  Epilogue(isolate, &visitor, invoke_api_callbacks);
 
   if (FLAG_verify_after_gc) {
     OS::PrintErr("Verifying after Scavenge...");
diff --git a/runtime/vm/scavenger.h b/runtime/vm/scavenger.h
index d1405ff..249df65 100644
--- a/runtime/vm/scavenger.h
+++ b/runtime/vm/scavenger.h
@@ -119,7 +119,9 @@
   void ProcessToSpace(ScavengerVisitor* visitor);
   uword ProcessWeakProperty(RawWeakProperty* raw_weak,
                             ScavengerVisitor* visitor);
-  void Epilogue(Isolate* isolate, bool invoke_api_callbacks);
+  void Epilogue(Isolate* isolate,
+                ScavengerVisitor* visitor,
+                bool invoke_api_callbacks);
 
   bool IsUnreachable(RawObject** p);
 
diff --git a/runtime/vm/service.cc b/runtime/vm/service.cc
index 2b3e633..087c933 100644
--- a/runtime/vm/service.cc
+++ b/runtime/vm/service.cc
@@ -2,6 +2,10 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+#include "vm/service.h"
+
+#include "vm/cpu.h"
+#include "vm/dart_entry.h"
 #include "vm/debugger.h"
 #include "vm/heap_histogram.h"
 #include "vm/isolate.h"
@@ -10,7 +14,6 @@
 #include "vm/object_id_ring.h"
 #include "vm/object_store.h"
 #include "vm/port.h"
-#include "vm/service.h"
 
 namespace dart {
 
@@ -30,36 +33,46 @@
 }
 
 
-static void PostReply(const String& reply, Dart_Port reply_port) {
+static void PostReply(const String& reply, const Instance& reply_port) {
+  const Object& id_obj = Object::Handle(
+      DartLibraryCalls::PortGetId(reply_port));
+  if (id_obj.IsError()) {
+    Exceptions::PropagateError(Error::Cast(id_obj));
+  }
+  const Integer& id = Integer::Cast(id_obj);
+  Dart_Port port = static_cast<Dart_Port>(id.AsInt64Value());
+  ASSERT(port != ILLEGAL_PORT);
+
   uint8_t* data = NULL;
   MessageWriter writer(&data, &allocator);
   writer.WriteMessage(reply);
-  PortMap::PostMessage(new Message(reply_port, Message::kIllegalPort, data,
+  PortMap::PostMessage(new Message(port, data,
                                    writer.BytesWritten(),
                                    Message::kNormalPriority));
 }
 
 
-void Service::HandleServiceMessage(Isolate* isolate, Dart_Port reply_port,
-                                   const Instance& msg) {
+void Service::HandleServiceMessage(Isolate* isolate, const Instance& msg) {
   ASSERT(isolate != NULL);
-  ASSERT(reply_port != ILLEGAL_PORT);
   ASSERT(!msg.IsNull());
   ASSERT(msg.IsGrowableObjectArray());
 
   {
     StackZone zone(isolate);
     HANDLESCOPE(isolate);
+
     const GrowableObjectArray& message = GrowableObjectArray::Cast(msg);
     // Message is a list with three entries.
-    ASSERT(message.Length() == 3);
+    ASSERT(message.Length() == 4);
 
-    GrowableObjectArray& path = GrowableObjectArray::Handle();
-    GrowableObjectArray& option_keys = GrowableObjectArray::Handle();
-    GrowableObjectArray& option_values = GrowableObjectArray::Handle();
-    path ^= message.At(0);
-    option_keys ^= message.At(1);
-    option_values ^= message.At(2);
+    Instance& reply_port = Instance::Handle(isolate);
+    GrowableObjectArray& path = GrowableObjectArray::Handle(isolate);
+    GrowableObjectArray& option_keys = GrowableObjectArray::Handle(isolate);
+    GrowableObjectArray& option_values = GrowableObjectArray::Handle(isolate);
+    reply_port ^= message.At(0);
+    path ^= message.At(1);
+    option_keys ^= message.At(2);
+    option_values ^= message.At(3);
 
     ASSERT(!path.IsNull());
     ASSERT(!option_keys.IsNull());
@@ -140,19 +153,31 @@
 }
 
 
-static void PrintCollectionErrorResponse(const char* collection_name,
-                                         JSONStream* js) {
+static void PrintGenericError(JSONStream* js) {
   JSONObject jsobj(js);
-  jsobj.AddProperty("type", "error");
-  jsobj.AddPropertyF("text", "Must specify collection object id: /%s/id",
-                     collection_name);
+  jsobj.AddProperty("type", "Error");
+  jsobj.AddProperty("text", "Invalid request.");
+  PrintArgumentsAndOptions(jsobj, js);
 }
 
 
-static void PrintGenericError(JSONStream* js) {
+static void PrintError(JSONStream* js, const char* format, ...) {
+  Isolate* isolate = Isolate::Current();
+
+  va_list args;
+  va_start(args, format);
+  intptr_t len = OS::VSNPrint(NULL, 0, format, args);
+  va_end(args);
+
+  char* buffer = isolate->current_zone()->Alloc<char>(len + 1);
+  va_list args2;
+  va_start(args2, format);
+  OS::VSNPrint(buffer, (len + 1), format, args2);
+  va_end(args2);
+
   JSONObject jsobj(js);
-  jsobj.AddProperty("type", "error");
-  jsobj.AddProperty("text", "Invalid request.");
+  jsobj.AddProperty("type", "Error");
+  jsobj.AddProperty("text", buffer);
   PrintArgumentsAndOptions(jsobj, js);
 }
 
@@ -191,7 +216,7 @@
   ObjectHistogram* histogram = Isolate::Current()->object_histogram();
   if (histogram == NULL) {
     JSONObject jsobj(js);
-    jsobj.AddProperty("type", "error");
+    jsobj.AddProperty("type", "Error");
     jsobj.AddProperty("text", "Run with --print_object_histogram");
     return;
   }
@@ -207,10 +232,10 @@
 
 
 // Print an error message if there is no ID argument.
-#define REQUIRE_COLLECTION_ID(collection)                                      \
-  if (js->num_arguments() == 1) {                                              \
-    PrintCollectionErrorResponse(collection, js);                              \
-    return;                                                                    \
+#define REQUIRE_COLLECTION_ID(collection)                                     \
+  if (js->num_arguments() == 1) {                                             \
+    PrintError(js, "Must specify collection object id: /%s/id", collection);  \
+    return;                                                                   \
   }
 
 
@@ -254,20 +279,62 @@
 }
 
 
+static void HandleDebug(Isolate* isolate, JSONStream* js) {
+  if (js->num_arguments() == 1) {
+    PrintError(js, "Must specify a subcommand");
+    return;
+  }
+  const char* command = js->GetArgument(1);
+  if (!strcmp(command, "breakpoints")) {
+    if (js->num_arguments() == 2) {
+      // Print breakpoint list.
+      JSONObject jsobj(js);
+      jsobj.AddProperty("type", "BreakpointList");
+      JSONArray jsarr(&jsobj, "breakpoints");
+      isolate->debugger()->PrintBreakpointsToJSONArray(&jsarr);
+
+    } else if (js->num_arguments() == 3) {
+      // Print individual breakpoint.
+      intptr_t id = atoi(js->GetArgument(2));
+      SourceBreakpoint* bpt = isolate->debugger()->GetBreakpointById(id);
+      if (bpt != NULL) {
+        bpt->PrintToJSONStream(js);
+      } else {
+        PrintError(js, "Unrecognized breakpoint id %s", js->GetArgument(2));
+      }
+
+    } else {
+      PrintError(js, "Command too long");
+    }
+  } else {
+    PrintError(js, "Unrecognized subcommand '%s'", js->GetArgument(1));
+  }
+}
+
+
+static void HandleCpu(Isolate* isolate, JSONStream* js) {
+  JSONObject jsobj(js);
+  jsobj.AddProperty("type", "CPU");
+  jsobj.AddProperty("architecture", CPU::Id());
+}
+
+
 static ServiceMessageHandlerEntry __message_handlers[] = {
-  { "name", HandleName },
-  { "stacktrace", HandleStackTrace },
-  { "objecthistogram", HandleObjectHistogram},
-  { "library", HandleLibrary },
-  { "classes", HandleClasses },
-  { "objects", HandleObjects },
   { "_echo", HandleEcho },
+  { "classes", HandleClasses },
+  { "cpu", HandleCpu },
+  { "debug", HandleDebug },
+  { "library", HandleLibrary },
+  { "name", HandleName },
+  { "objecthistogram", HandleObjectHistogram},
+  { "objects", HandleObjects },
+  { "stacktrace", HandleStackTrace },
 };
 
 
 static void HandleFallthrough(Isolate* isolate, JSONStream* js) {
   JSONObject jsobj(js);
-  jsobj.AddProperty("type", "error");
+  jsobj.AddProperty("type", "Error");
   jsobj.AddProperty("text", "request not understood.");
   PrintArgumentsAndOptions(jsobj, js);
 }
diff --git a/runtime/vm/service.h b/runtime/vm/service.h
index b7a6d40..84b467b 100644
--- a/runtime/vm/service.h
+++ b/runtime/vm/service.h
@@ -7,6 +7,8 @@
 
 #include "include/dart_api.h"
 
+#include "vm/allocation.h"
+
 namespace dart {
 
 class Instance;
@@ -14,8 +16,7 @@
 
 class Service : public AllStatic {
  public:
-  static void HandleServiceMessage(Isolate* isolate, Dart_Port reply_port,
-                                   const Instance& message);
+  static void HandleServiceMessage(Isolate* isolate, const Instance& message);
 };
 
 }  // namespace dart
diff --git a/runtime/vm/service_test.cc b/runtime/vm/service_test.cc
new file mode 100644
index 0000000..1a7bfcb
--- /dev/null
+++ b/runtime/vm/service_test.cc
@@ -0,0 +1,149 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#include "include/dart_debugger_api.h"
+#include "vm/dart_api_impl.h"
+#include "vm/dart_entry.h"
+#include "vm/debugger.h"
+#include "vm/globals.h"
+#include "vm/message_handler.h"
+#include "vm/os.h"
+#include "vm/port.h"
+#include "vm/service.h"
+#include "vm/unit_test.h"
+
+namespace dart {
+
+class ServiceTestMessageHandler : public MessageHandler {
+ public:
+  ServiceTestMessageHandler() : _msg(NULL) {}
+
+  ~ServiceTestMessageHandler() {
+    free(_msg);
+  }
+
+  bool HandleMessage(Message* message) {
+    if (_msg != NULL) {
+      free(_msg);
+    }
+
+    // Parse the message.
+    SnapshotReader reader(message->data(), message->len(),
+                          Snapshot::kMessage, Isolate::Current());
+    const Object& response_obj = Object::Handle(reader.ReadObject());
+    String& response = String::Handle();
+    response ^= response_obj.raw();
+    _msg = strdup(response.ToCString());
+    return true;
+  }
+
+  const char* msg() const { return _msg; }
+
+ private:
+  char* _msg;
+};
+
+
+static RawInstance* Eval(Dart_Handle lib, const char* expr) {
+  Dart_Handle result = Dart_EvaluateExpr(lib, NewString(expr));
+  EXPECT_VALID(result);
+  Isolate* isolate = Isolate::Current();
+  const Instance& instance = Api::UnwrapInstanceHandle(isolate, result);
+  return instance.raw();
+}
+
+
+TEST_CASE(Service_DebugBreakpoints) {
+  const char* kScript =
+      "var port;\n"  // Set to our mock port by C++.
+      "\n"
+      "main() {\n"   // We set breakpoint here.
+      "}";
+
+  Isolate* isolate = Isolate::Current();
+  Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
+  EXPECT_VALID(lib);
+
+  // Build a mock message handler and wrap it in a dart port.
+  ServiceTestMessageHandler handler;
+  Dart_Port port_id = PortMap::CreatePort(&handler);
+  Dart_Handle port =
+      Api::NewHandle(isolate, DartLibraryCalls::NewSendPort(port_id));
+  EXPECT_VALID(port);
+  EXPECT_VALID(Dart_SetField(lib, NewString("port"), port));
+
+  Instance& service_msg = Instance::Handle();
+
+  // Add a breakpoint.
+  const String& url = String::Handle(String::New(TestCase::url()));
+  isolate->debugger()->SetBreakpointAtLine(url, 3);
+
+  // Get the breakpoint list.
+  service_msg = Eval(lib, "[port, ['debug', 'breakpoints'], [], []]");
+  Service::HandleServiceMessage(isolate, service_msg);
+  handler.HandleNextMessage();
+  EXPECT_STREQ(
+      "{\"type\":\"BreakpointList\",\"breakpoints\":[{"
+          "\"type\":\"Breakpoint\",\"id\":1,\"enabled\":true,"
+          "\"resolved\":false,"
+          "\"location\":{\"type\":\"Location\",\"libId\":12,"
+                        "\"script\":\"dart:test-lib\",\"tokenPos\":5}}]}",
+      handler.msg());
+
+  // Individual breakpoint.
+  service_msg = Eval(lib, "[port, ['debug', 'breakpoints', '1'], [], []]");
+  Service::HandleServiceMessage(isolate, service_msg);
+  handler.HandleNextMessage();
+  EXPECT_STREQ(
+      "{\"type\":\"Breakpoint\",\"id\":1,\"enabled\":true,"
+       "\"resolved\":false,"
+       "\"location\":{\"type\":\"Location\",\"libId\":12,"
+                     "\"script\":\"dart:test-lib\",\"tokenPos\":5}}",
+      handler.msg());
+
+  // Missing sub-command.
+  service_msg = Eval(lib, "[port, ['debug'], [], []]");
+  Service::HandleServiceMessage(isolate, service_msg);
+  handler.HandleNextMessage();
+  EXPECT_STREQ(
+      "{\"type\":\"Error\","
+       "\"text\":\"Must specify a subcommand\","
+       "\"message\":{\"arguments\":[\"debug\"],\"option_keys\":[],"
+                    "\"option_values\":[]}}",
+      handler.msg());
+
+  // Unrecognized breakpoint.
+  service_msg = Eval(lib, "[port, ['debug', 'breakpoints', '1111'], [], []]");
+  Service::HandleServiceMessage(isolate, service_msg);
+  handler.HandleNextMessage();
+  EXPECT_STREQ("{\"type\":\"Error\","
+                "\"text\":\"Unrecognized breakpoint id 1111\","
+                "\"message\":{"
+                    "\"arguments\":[\"debug\",\"breakpoints\",\"1111\"],"
+                    "\"option_keys\":[],\"option_values\":[]}}",
+               handler.msg());
+
+  // Command too long.
+  service_msg =
+      Eval(lib, "[port, ['debug', 'breakpoints', '1111', 'green'], [], []]");
+  Service::HandleServiceMessage(isolate, service_msg);
+  handler.HandleNextMessage();
+  EXPECT_STREQ("{\"type\":\"Error\",\"text\":\"Command too long\","
+                "\"message\":{\"arguments\":[\"debug\",\"breakpoints\","
+                                            "\"1111\",\"green\"],"
+                             "\"option_keys\":[],\"option_values\":[]}}",
+               handler.msg());
+
+  // Unrecognized subcommand.
+  service_msg = Eval(lib, "[port, ['debug', 'nosferatu'], [], []]");
+  Service::HandleServiceMessage(isolate, service_msg);
+  handler.HandleNextMessage();
+  EXPECT_STREQ("{\"type\":\"Error\","
+                "\"text\":\"Unrecognized subcommand 'nosferatu'\","
+                "\"message\":{\"arguments\":[\"debug\",\"nosferatu\"],"
+                             "\"option_keys\":[],\"option_values\":[]}}",
+               handler.msg());
+}
+
+}  // namespace dart
diff --git a/runtime/vm/signal_handler.h b/runtime/vm/signal_handler.h
index 67e1cfa..18909cb 100644
--- a/runtime/vm/signal_handler.h
+++ b/runtime/vm/signal_handler.h
@@ -40,16 +40,6 @@
 };
 
 
-class ScopedSignalBlocker {
- public:
-  ScopedSignalBlocker();
-  ~ScopedSignalBlocker();
-
- private:
-  sigset_t old_;
-};
-
-
 }  // namespace dart
 
 #endif  // VM_SIGNAL_HANDLER_H_
diff --git a/runtime/vm/signal_handler_android.cc b/runtime/vm/signal_handler_android.cc
index 11adfc7..7f04c2fb 100644
--- a/runtime/vm/signal_handler_android.cc
+++ b/runtime/vm/signal_handler_android.cc
@@ -29,18 +29,6 @@
 }
 
 
-ScopedSignalBlocker::ScopedSignalBlocker() {
-  sigset_t set;
-  sigemptyset(&set);
-  sigaddset(&set, SIGPROF);
-  pthread_sigmask(SIG_SETMASK, &set, &old_);
-}
-
-
-ScopedSignalBlocker::~ScopedSignalBlocker() {
-  pthread_sigmask(SIG_SETMASK, &old_, NULL);
-}
-
 }  // namespace dart
 
 #endif  // defined(TARGET_OS_ANDROID)
diff --git a/runtime/vm/signal_handler_linux.cc b/runtime/vm/signal_handler_linux.cc
index 4345dd4..7de4697 100644
--- a/runtime/vm/signal_handler_linux.cc
+++ b/runtime/vm/signal_handler_linux.cc
@@ -22,6 +22,8 @@
   pc = static_cast<uintptr_t>(mcontext.gregs[REG_EIP]);
 #elif defined(TARGET_ARCH_ARM)
   pc = static_cast<uintptr_t>(mcontext.arm_pc);
+#elif defined(TARGET_ARCH_MIPS)
+  pc = static_cast<uintptr_t>(mcontext.pc);
 #else
   UNIMPLEMENTED();
 #endif  // TARGET_ARCH_...
@@ -42,6 +44,8 @@
   fp = static_cast<uintptr_t>(mcontext.gregs[REG_EBP]);
 #elif defined(TARGET_ARCH_ARM)
   fp = static_cast<uintptr_t>(mcontext.arm_fp);
+#elif defined(TARGET_ARCH_MIPS)
+  fp = static_cast<uintptr_t>(mcontext.gregs[30]);
 #else
   UNIMPLEMENTED();
 #endif  // TARGET_ARCH_...
@@ -63,6 +67,8 @@
   sp = static_cast<uintptr_t>(mcontext.gregs[REG_ESP]);
 #elif defined(TARGET_ARCH_ARM)
   sp = static_cast<uintptr_t>(mcontext.arm_sp);
+#elif defined(TARGET_ARCH_MIPS)
+  sp = static_cast<uintptr_t>(mcontext.gregs[29]);
 #else
   UNIMPLEMENTED();
 #endif  // TARGET_ARCH_...
@@ -83,18 +89,6 @@
 }
 
 
-ScopedSignalBlocker::ScopedSignalBlocker() {
-  sigset_t set;
-  sigemptyset(&set);
-  sigaddset(&set, SIGPROF);
-  pthread_sigmask(SIG_SETMASK, &set, &old_);
-}
-
-
-ScopedSignalBlocker::~ScopedSignalBlocker() {
-  pthread_sigmask(SIG_SETMASK, &old_, NULL);
-}
-
 }  // namespace dart
 
 #endif  // defined(TARGET_OS_LINUX)
diff --git a/runtime/vm/signal_handler_macos.cc b/runtime/vm/signal_handler_macos.cc
index f0e5b15..11e6234 100644
--- a/runtime/vm/signal_handler_macos.cc
+++ b/runtime/vm/signal_handler_macos.cc
@@ -79,18 +79,6 @@
 }
 
 
-ScopedSignalBlocker::ScopedSignalBlocker() {
-  sigset_t set;
-  sigemptyset(&set);
-  sigaddset(&set, SIGPROF);
-  pthread_sigmask(SIG_SETMASK, &set, &old_);
-}
-
-
-ScopedSignalBlocker::~ScopedSignalBlocker() {
-  pthread_sigmask(SIG_SETMASK, &old_, NULL);
-}
-
 }  // namespace dart
 
 #endif  // defined(TARGET_OS_MACOS)
diff --git a/runtime/vm/signal_handler_win.cc b/runtime/vm/signal_handler_win.cc
index 8a4b86c..6fc7723 100644
--- a/runtime/vm/signal_handler_win.cc
+++ b/runtime/vm/signal_handler_win.cc
@@ -31,13 +31,6 @@
 }
 
 
-ScopedSignalBlocker::ScopedSignalBlocker() {
-}
-
-
-ScopedSignalBlocker::~ScopedSignalBlocker() {
-}
-
 }  // namespace dart
 
 #endif  // defined(TARGET_OS_WINDOWS)
diff --git a/runtime/vm/stack_frame_test.cc b/runtime/vm/stack_frame_test.cc
index fc5e269..4a06610 100644
--- a/runtime/vm/stack_frame_test.cc
+++ b/runtime/vm/stack_frame_test.cc
@@ -136,7 +136,10 @@
 
 
 static Dart_NativeFunction native_lookup(Dart_Handle name,
-                                         int argument_count) {
+                                         int argument_count,
+                                         bool* auto_setup_scope) {
+  ASSERT(auto_setup_scope != NULL);
+  *auto_setup_scope = false;
   const Object& obj = Object::Handle(Api::UnwrapHandle(name));
   ASSERT(obj.IsString());
   const char* function_name = obj.ToCString();
diff --git a/runtime/vm/stub_code_arm.cc b/runtime/vm/stub_code_arm.cc
index d921151..11350d3 100644
--- a/runtime/vm/stub_code_arm.cc
+++ b/runtime/vm/stub_code_arm.cc
@@ -181,8 +181,14 @@
   // For now, space is reserved on the stack and we pass a pointer to it.
   __ stm(IA, SP,  (1 << R0) | (1 << R1) | (1 << R2) | (1 << R3));
   __ mov(R0, ShifterOperand(SP));  // Pass the pointer to the NativeArguments.
-  __ mov(R1, ShifterOperand(R5));  // Pass the function entrypoint to call.
 
+  // Call native function (setsup scope if not leaf function).
+  Label leaf_call;
+  Label done;
+  __ TestImmediate(R1, NativeArguments::AutoSetupScopeMask());
+  __ b(&leaf_call, EQ);
+
+  __ mov(R1, ShifterOperand(R5));  // Pass the function entrypoint to call.
   // Call native function invocation wrapper or redirection via simulator.
 #if defined(USING_SIMULATOR)
   uword entry = reinterpret_cast<uword>(NativeEntry::NativeCallWrapper);
@@ -193,6 +199,13 @@
 #else
   __ BranchLink(&NativeEntry::NativeCallWrapperLabel());
 #endif
+  __ b(&done);
+
+  __ Bind(&leaf_call);
+  // Call native function or redirection via simulator.
+  __ blx(R5);
+
+  __ Bind(&done);
 
   // Reset exit frame information in Isolate structure.
   __ LoadImmediate(R2, 0);
diff --git a/runtime/vm/stub_code_ia32.cc b/runtime/vm/stub_code_ia32.cc
index 49df45c..9a8f88a 100644
--- a/runtime/vm/stub_code_ia32.cc
+++ b/runtime/vm/stub_code_ia32.cc
@@ -163,8 +163,18 @@
   __ movl(Address(ESP, retval_offset), EAX);  // Set retval in NativeArguments.
   __ leal(EAX, Address(ESP, 2 * kWordSize));  // Pointer to the NativeArguments.
   __ movl(Address(ESP, 0), EAX);  // Pass the pointer to the NativeArguments.
+
+  // Call native function (setsup scope if not leaf function).
+  Label leaf_call;
+  Label done;
+  __ testl(EDX, Immediate(NativeArguments::AutoSetupScopeMask()));
+  __ j(ZERO, &leaf_call, Assembler::kNearJump);
   __ movl(Address(ESP, kWordSize), ECX);  // Function to call.
   __ call(&NativeEntry::NativeCallWrapperLabel());
+  __ jmp(&done);
+  __ Bind(&leaf_call);
+  __ call(ECX);
+  __ Bind(&done);
 
   // Reset exit frame information in Isolate structure.
   __ movl(Address(CTX, Isolate::top_exit_frame_info_offset()), Immediate(0));
diff --git a/runtime/vm/stub_code_mips.cc b/runtime/vm/stub_code_mips.cc
index dbec240..33437e4 100644
--- a/runtime/vm/stub_code_mips.cc
+++ b/runtime/vm/stub_code_mips.cc
@@ -192,10 +192,15 @@
   __ sw(A1, Address(SP, 1 * kWordSize));
   __ sw(A0, Address(SP, 0 * kWordSize));
   __ mov(A0, SP);  // Pass the pointer to the NativeArguments.
+
+  // Call native function (setup scope if not leaf function).
+  Label leaf_call;
+  Label done;
+  __ AndImmediate(CMPRES1, A1, NativeArguments::AutoSetupScopeMask());
+  __ beq(CMPRES1, ZR, &leaf_call);
+
   __ mov(A1, T5);  // Pass the function entrypoint.
-
   __ ReserveAlignedFrameSpace(2 * kWordSize);  // Just passing A0, A1.
-
   // Call native wrapper function or redirection via simulator.
 #if defined(USING_SIMULATOR)
   uword entry = reinterpret_cast<uword>(NativeEntry::NativeCallWrapper);
@@ -207,6 +212,14 @@
   __ BranchLink(&NativeEntry::NativeCallWrapperLabel());
 #endif
   __ TraceSimMsg("CallNativeCFunctionStub return");
+  __ b(&done);
+
+  __ Bind(&leaf_call);
+  // Call native function or redirection via simulator.
+  __ ReserveAlignedFrameSpace(kWordSize);  // Just passing A0.
+  __ jalr(T5);
+
+  __ Bind(&done);
 
   // Reset exit frame information in Isolate structure.
   __ sw(ZR, Address(CTX, Isolate::top_exit_frame_info_offset()));
diff --git a/runtime/vm/stub_code_x64.cc b/runtime/vm/stub_code_x64.cc
index 5e0b9af..dac3e5c 100644
--- a/runtime/vm/stub_code_x64.cc
+++ b/runtime/vm/stub_code_x64.cc
@@ -161,8 +161,18 @@
   __ leaq(RAX, Address(RBP, 2 * kWordSize));  // Compute return value addr.
   __ movq(Address(RSP, retval_offset), RAX);  // Set retval in NativeArguments.
   __ movq(RDI, RSP);  // Pass the pointer to the NativeArguments.
+
+  // Call native function (setsup scope if not leaf function).
+  Label leaf_call;
+  Label done;
+  __ testq(R10, Immediate(NativeArguments::AutoSetupScopeMask()));
+  __ j(ZERO, &leaf_call);
   __ movq(RSI, RBX);  // Pass pointer to function entrypoint.
   __ call(&NativeEntry::NativeCallWrapperLabel());
+  __ jmp(&done);
+  __ Bind(&leaf_call);
+  __ call(RBX);
+  __ Bind(&done);
 
   // Reset exit frame information in Isolate structure.
   __ movq(Address(CTX, Isolate::top_exit_frame_info_offset()), Immediate(0));
diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h
index 4527379..c636537 100644
--- a/runtime/vm/symbols.h
+++ b/runtime/vm/symbols.h
@@ -184,8 +184,8 @@
   V(_Uint64ArrayFactory, "_Uint64Array.")                                      \
   V(_Float32x4Array, "_Float32x4Array")                                        \
   V(_Float32x4ArrayFactory, "_Float32x4Array.")                                \
-  V(_Int32x4Array, "_Int32x4Array")                                          \
-  V(_Int32x4ArrayFactory, "_Int32x4Array.")                                  \
+  V(_Int32x4Array, "_Int32x4Array")                                            \
+  V(_Int32x4ArrayFactory, "_Int32x4Array.")                                    \
   V(_Float32Array, "_Float32Array")                                            \
   V(_Float32ArrayFactory, "_Float32Array.")                                    \
   V(_Float64Array, "_Float64Array")                                            \
@@ -202,7 +202,7 @@
   V(_Float32ArrayView, "_Float32ArrayView")                                    \
   V(_Float64ArrayView, "_Float64ArrayView")                                    \
   V(_Float32x4ArrayView, "_Float32x4ArrayView")                                \
-  V(_Int32x4ArrayView, "_Int32x4ArrayView")                                  \
+  V(_Int32x4ArrayView, "_Int32x4ArrayView")                                    \
   V(_ExternalInt8Array, "_ExternalInt8Array")                                  \
   V(_ExternalUint8Array, "_ExternalUint8Array")                                \
   V(_ExternalUint8ClampedArray, "_ExternalUint8ClampedArray")                  \
@@ -213,7 +213,7 @@
   V(_ExternalInt64Array, "_ExternalInt64Array")                                \
   V(_ExternalUint64Array, "_ExternalUint64Array")                              \
   V(_ExternalFloat32x4Array, "_ExternalFloat32x4Array")                        \
-  V(_ExternalInt32x4Array, "_ExternalInt32x4Array")                          \
+  V(_ExternalInt32x4Array, "_ExternalInt32x4Array")                            \
   V(_ExternalFloat32Array, "_ExternalFloat32Array")                            \
   V(_ExternalFloat64Array, "_ExternalFloat64Array")                            \
   V(ByteData, "ByteData")                                                      \
@@ -240,7 +240,7 @@
   V(UnsupportedError, "UnsupportedError")                                      \
   V(StackOverflowError, "StackOverflowError")                                  \
   V(OutOfMemoryError, "OutOfMemoryError")                                      \
-  V(InternalError, "InternalError")                                            \
+  V(InternalError, "_InternalError")                                           \
   V(NullThrownError, "NullThrownError")                                        \
   V(IsolateSpawnException, "IsolateSpawnException")                            \
   V(IsolateUnhandledException, "_IsolateUnhandledException")                   \
diff --git a/runtime/vm/thread.h b/runtime/vm/thread.h
index c554fb6..debe182 100644
--- a/runtime/vm/thread.h
+++ b/runtime/vm/thread.h
@@ -54,6 +54,10 @@
     return monitor_->Wait(millis);
   }
 
+  Monitor::WaitResult WaitMicros(int64_t micros = dart::Monitor::kNoTimeout) {
+    return monitor_->WaitMicros(micros);
+  }
+
   void Notify() {
     monitor_->Notify();
   }
diff --git a/runtime/vm/thread_interrupter.cc b/runtime/vm/thread_interrupter.cc
new file mode 100644
index 0000000..2d44208
--- /dev/null
+++ b/runtime/vm/thread_interrupter.cc
@@ -0,0 +1,388 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#include "vm/simulator.h"
+#include "vm/thread_interrupter.h"
+
+namespace dart {
+
+// Notes:
+//
+// The ThreadInterrupter interrupts all registered threads once per
+// interrupt period (default is every millisecond). While the thread is
+// interrupted, the thread's interrupt callback is invoked. Callbacks cannot
+// rely on being executed on the interrupted thread.
+//
+// There are two mechanisms used to interrupt a thread. The first, used on OSs
+// with pthreads (Android, Linux, and Mac), is thread specific signal delivery.
+// The second, used on Windows, is explicit suspend and resume thread system
+// calls. Signal delivery forbids taking locks and allocating memory (which
+// takes a lock). Explicit suspend and resume means that the interrupt callback
+// will not be executing on the interrupted thread, making it meaningless to
+// access TLS from within the thread interrupt callback. Combining these
+// limitations, thread interrupt callbacks are forbidden from:
+//
+//   * Accessing TLS.
+//   * Allocating memory.
+//   * Taking a lock.
+//
+// The ThreadInterrupter has a single monitor (monitor_). This monitor guards
+// access to the list of threads registered to receive interrupts (threads_).
+//
+// A thread can only register and unregister itself. Each thread has a heap
+// allocated ThreadState. A thread's ThreadState is lazily allocated the first
+// time the thread is registered. A pointer to a thread's ThreadState is stored
+// in the list of threads registered to receive interrupts (threads_) and in
+// thread local storage. When a thread's ThreadState is being modified, the
+// thread local storage pointer is temporarily set to NULL while the
+// modification is occurring. After the ThreadState has been updated, the
+// thread local storage pointer is set again. This has an important side
+// effect: if the thread is interrupted by a signal handler during a ThreadState
+// update the signal handler will immediately return.
+
+DEFINE_FLAG(bool, trace_thread_interrupter, false,
+            "Trace thread interrupter");
+
+bool ThreadInterrupter::initialized_ = false;
+bool ThreadInterrupter::shutdown_ = false;
+bool ThreadInterrupter::thread_running_ = false;
+ThreadId ThreadInterrupter::interrupter_thread_id_ = Thread::kInvalidThreadId;
+Monitor* ThreadInterrupter::monitor_ = NULL;
+intptr_t ThreadInterrupter::interrupt_period_ = 1000;
+ThreadLocalKey ThreadInterrupter::thread_state_key_ =
+    Thread::kUnsetThreadLocalKey;
+ThreadInterrupter::ThreadState** ThreadInterrupter::threads_ = NULL;
+intptr_t ThreadInterrupter::threads_capacity_ = 0;
+intptr_t ThreadInterrupter::threads_size_ = 0;
+
+
+void ThreadInterrupter::InitOnce() {
+  ASSERT(!initialized_);
+  initialized_ = true;
+  ASSERT(thread_state_key_ == Thread::kUnsetThreadLocalKey);
+  thread_state_key_ = Thread::CreateThreadLocal();
+  ASSERT(thread_state_key_ != Thread::kUnsetThreadLocalKey);
+  monitor_ = new Monitor();
+  ResizeThreads(16);
+  if (FLAG_trace_thread_interrupter) {
+    OS::Print("ThreadInterrupter starting up.\n");
+  }
+  ASSERT(interrupter_thread_id_ == Thread::kInvalidThreadId);
+  {
+    MonitorLocker startup_ml(monitor_);
+    Thread::Start(ThreadMain, 0);
+    while (!thread_running_) {
+      startup_ml.Wait();
+    }
+  }
+  ASSERT(interrupter_thread_id_ != Thread::kInvalidThreadId);
+  if (FLAG_trace_thread_interrupter) {
+    OS::Print("ThreadInterrupter running.\n");
+  }
+}
+
+
+void ThreadInterrupter::Shutdown() {
+  if (shutdown_) {
+    // Already shutdown.
+    return;
+  }
+  ASSERT(initialized_);
+  if (FLAG_trace_thread_interrupter) {
+    OS::Print("ThreadInterrupter shutting down.\n");
+  }
+  intptr_t size_at_shutdown = 0;
+  {
+    MonitorLocker ml(monitor_);
+    shutdown_ = true;
+    size_at_shutdown = threads_size_;
+    threads_size_ = 0;
+    threads_capacity_ = 0;
+    free(threads_);
+    threads_ = NULL;
+  }
+  {
+    MonitorLocker shutdown_ml(monitor_);
+    while (thread_running_) {
+      shutdown_ml.Wait();
+    }
+  }
+  interrupter_thread_id_ = Thread::kInvalidThreadId;
+  if (FLAG_trace_thread_interrupter) {
+    OS::Print("ThreadInterrupter shut down (%" Pd ").\n", size_at_shutdown);
+  }
+}
+
+// Delay between interrupts.
+void ThreadInterrupter::SetInterruptPeriod(intptr_t period) {
+  if (shutdown_) {
+    return;
+  }
+  ASSERT(initialized_);
+  ASSERT(period > 0);
+  {
+    MonitorLocker ml(monitor_);
+    interrupt_period_ = period;
+  }
+}
+
+
+// Register the currently running thread for interrupts. If the current thread
+// is already registered, callback and data will be updated.
+void ThreadInterrupter::Register(ThreadInterruptCallback callback, void* data) {
+  if (shutdown_) {
+    return;
+  }
+  ASSERT(initialized_);
+  {
+    MonitorLocker ml(monitor_);
+    _EnsureThreadStateCreated();
+    // Set callback and data.
+    UpdateStateObject(callback, data);
+    _Enable();
+  }
+}
+
+
+// Unregister the currently running thread for interrupts.
+void ThreadInterrupter::Unregister() {
+  if (shutdown_) {
+    return;
+  }
+  ASSERT(initialized_);
+  {
+    MonitorLocker ml(monitor_);
+    _EnsureThreadStateCreated();
+    // Clear callback and data.
+    UpdateStateObject(NULL, NULL);
+    _Disable();
+  }
+}
+
+
+void ThreadInterrupter::Enable() {
+  if (shutdown_) {
+    return;
+  }
+  ASSERT(initialized_);
+  {
+    MonitorLocker ml(monitor_);
+    _EnsureThreadStateCreated();
+    _Enable();
+  }
+}
+
+
+void ThreadInterrupter::Disable() {
+  if (shutdown_) {
+    return;
+  }
+  ASSERT(initialized_);
+  {
+    MonitorLocker ml(monitor_);
+    _EnsureThreadStateCreated();
+    _Disable();
+  }
+}
+
+
+void ThreadInterrupter::_EnsureThreadStateCreated() {
+  ThreadState* state = CurrentThreadState();
+  if (state == NULL) {
+    // Create thread state object lazily.
+    ThreadId current_thread = Thread::GetCurrentThreadId();
+    if (FLAG_trace_thread_interrupter) {
+      intptr_t tid = Thread::ThreadIdToIntPtr(current_thread);
+      OS::Print("ThreadInterrupter Tracking %p\n",
+                reinterpret_cast<void*>(tid));
+    }
+    state = new ThreadState();
+    state->callback = NULL;
+    state->data = NULL;
+    state->id = current_thread;
+    SetCurrentThreadState(state);
+  }
+}
+
+
+void ThreadInterrupter::_Enable() {
+  // Must be called with monitor_ locked.
+  ThreadId current_thread = Thread::GetCurrentThreadId();
+  if (Thread::Compare(current_thread, interrupter_thread_id_)) {
+    return;
+  }
+  intptr_t i = FindThreadIndex(current_thread);
+  if (i >= 0) {
+    return;
+  }
+  AddThread(current_thread);
+  if (FLAG_trace_thread_interrupter) {
+    intptr_t tid = Thread::ThreadIdToIntPtr(current_thread);
+    OS::Print("ThreadInterrupter Added %p\n", reinterpret_cast<void*>(tid));
+  }
+}
+
+void ThreadInterrupter::_Disable() {
+  // Must be called with monitor_ locked.
+  ThreadId current_thread = Thread::GetCurrentThreadId();
+  if (Thread::Compare(current_thread, interrupter_thread_id_)) {
+    return;
+  }
+  intptr_t index = FindThreadIndex(current_thread);
+  if (index < 0) {
+    // Not registered.
+    return;
+  }
+  ThreadState* state = RemoveThread(index);
+  ASSERT(state != NULL);
+  ASSERT(state == ThreadInterrupter::CurrentThreadState());
+  if (FLAG_trace_thread_interrupter) {
+    intptr_t tid = Thread::ThreadIdToIntPtr(current_thread);
+    OS::Print("ThreadInterrupter Removed %p\n", reinterpret_cast<void*>(tid));
+  }
+}
+
+void ThreadInterrupter::UpdateStateObject(ThreadInterruptCallback callback,
+                                          void* data) {
+  // Must be called with monitor_ locked.
+  ThreadState* state = CurrentThreadState();
+  ThreadId current_thread = Thread::GetCurrentThreadId();
+  ASSERT(state != NULL);
+  ASSERT(Thread::Compare(state->id, Thread::GetCurrentThreadId()));
+  SetCurrentThreadState(NULL);
+  // It is now safe to modify the state object. If an interrupt occurs,
+  // the current thread state will be NULL.
+  state->callback = callback;
+  state->data = data;
+  SetCurrentThreadState(state);
+  if (FLAG_trace_thread_interrupter) {
+    intptr_t tid = Thread::ThreadIdToIntPtr(current_thread);
+    if (callback == NULL) {
+      OS::Print("ThreadInterrupter Cleared %p\n", reinterpret_cast<void*>(tid));
+    } else {
+      OS::Print("ThreadInterrupter Updated %p\n", reinterpret_cast<void*>(tid));
+    }
+  }
+}
+
+
+ThreadInterrupter::ThreadState* ThreadInterrupter::CurrentThreadState() {
+  ThreadState* state = reinterpret_cast<ThreadState*>(
+      Thread::GetThreadLocal(thread_state_key_));
+  return state;
+}
+
+
+void ThreadInterrupter::SetCurrentThreadState(ThreadState* state) {
+  Thread::SetThreadLocal(thread_state_key_, reinterpret_cast<uword>(state));
+}
+
+
+void ThreadInterrupter::ResizeThreads(intptr_t new_capacity) {
+  // Must be called with monitor_ locked.
+  ASSERT(new_capacity < kMaxThreads);
+  ASSERT(new_capacity > threads_capacity_);
+  ThreadState* state = NULL;
+  threads_ = reinterpret_cast<ThreadState**>(
+      realloc(threads_, sizeof(state) * new_capacity));
+  for (intptr_t i = threads_capacity_; i < new_capacity; i++) {
+    threads_[i] = NULL;
+  }
+  threads_capacity_ = new_capacity;
+}
+
+
+void ThreadInterrupter::AddThread(ThreadId id) {
+  // Must be called with monitor_ locked.
+  if (threads_ == NULL) {
+    // We are shutting down.
+    return;
+  }
+  ThreadState* state = CurrentThreadState();
+  if (state->callback == NULL) {
+    // No callback.
+    return;
+  }
+  if (threads_size_ == threads_capacity_) {
+    ResizeThreads(threads_capacity_ == 0 ? 16 : threads_capacity_ * 2);
+  }
+  threads_[threads_size_] = state;
+  threads_size_++;
+}
+
+
+intptr_t ThreadInterrupter::FindThreadIndex(ThreadId id) {
+  // Must be called with monitor_ locked.
+  if (threads_ == NULL) {
+    // We are shutting down.
+    return -1;
+  }
+  for (intptr_t i = 0; i < threads_size_; i++) {
+    if (threads_[i]->id == id) {
+      return i;
+    }
+  }
+  return -1;
+}
+
+
+ThreadInterrupter::ThreadState* ThreadInterrupter::RemoveThread(intptr_t i) {
+  // Must be called with monitor_ locked.
+  if (threads_ == NULL) {
+    // We are shutting down.
+    return NULL;
+  }
+  ASSERT(i < threads_size_);
+  ThreadState* state = threads_[i];
+  ASSERT(state != NULL);
+  intptr_t last = threads_size_ - 1;
+  if (i != last) {
+    threads_[i] = threads_[last];
+  }
+  // Mark last as NULL.
+  threads_[last] = NULL;
+  // Pop.
+  threads_size_--;
+  return state;
+}
+
+
+void ThreadInterruptNoOp(const InterruptedThreadState& state, void* data) {
+  // NoOp.
+}
+
+
+void ThreadInterrupter::ThreadMain(uword parameters) {
+  ASSERT(initialized_);
+  InstallSignalHandler();
+  if (FLAG_trace_thread_interrupter) {
+    OS::Print("ThreadInterrupter thread running.\n");
+  }
+  {
+    // Signal to main thread we are ready.
+    MonitorLocker startup_ml(monitor_);
+    thread_running_ = true;
+    interrupter_thread_id_ = Thread::GetCurrentThreadId();
+    startup_ml.Notify();
+  }
+  {
+    MonitorLocker ml(monitor_);
+    while (!shutdown_) {
+      int64_t current_time = OS::GetCurrentTimeMicros();
+      InterruptThreads(current_time);
+      ml.WaitMicros(interrupt_period_);
+    }
+  }
+  if (FLAG_trace_thread_interrupter) {
+    OS::Print("ThreadInterrupter thread exiting.\n");
+  }
+  {
+    // Signal to main thread we are exiting.
+    MonitorLocker shutdown_ml(monitor_);
+    thread_running_ = false;
+    shutdown_ml.Notify();
+  }
+}
+
+}  // namespace dart
diff --git a/runtime/vm/thread_interrupter.h b/runtime/vm/thread_interrupter.h
new file mode 100644
index 0000000..3a31683
--- /dev/null
+++ b/runtime/vm/thread_interrupter.h
@@ -0,0 +1,99 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#ifndef VM_THREAD_INTERRUPTER_H_
+#define VM_THREAD_INTERRUPTER_H_
+
+#include "vm/allocation.h"
+#include "vm/signal_handler.h"
+#include "vm/thread.h"
+
+
+namespace dart {
+
+struct InterruptedThreadState {
+  ThreadId tid;
+  uintptr_t pc;
+  uintptr_t sp;
+  uintptr_t fp;
+};
+
+// When a thread is interrupted the thread specific interrupt
+// callback will be invoked at the interrupt period. Each callback is given an
+// InterruptedThreadState and the thread specific data pointer. When inside a
+// thread interrupt callback doing any of the following
+// is forbidden:
+//   * Accessing TLS.
+//   * Allocating memory.
+//   * Taking a lock.
+typedef void (*ThreadInterruptCallback)(const InterruptedThreadState& state,
+                                        void* data);
+
+class ThreadInterrupter : public AllStatic {
+ public:
+  static void InitOnce();
+  static void Shutdown();
+
+  // Delay between interrupts.
+  static void SetInterruptPeriod(intptr_t period);
+
+  // Register the currently running thread for interrupts. If the current thread
+  // is already registered, callback and data will be updated.
+  static void Register(ThreadInterruptCallback callback, void* data);
+  // Unregister the currently running thread for interrupts.
+  static void Unregister();
+
+  // Enable interrupts for this thread. Does not alter callback.
+  static void Enable();
+  // Disable interrupts for this thread. Does not alter callback.
+  static void Disable();
+
+ private:
+  static const intptr_t kMaxThreads = 4096;
+  static bool initialized_;
+  static bool shutdown_;
+  static bool thread_running_;
+  static ThreadId interrupter_thread_id_;
+  static Monitor* monitor_;
+  static intptr_t interrupt_period_;
+  static ThreadLocalKey thread_state_key_;
+  // State stored per registered thread.
+  struct ThreadState {
+    ThreadId id;
+    ThreadInterruptCallback callback;
+    void* data;
+  };
+
+  static void UpdateStateObject(ThreadInterruptCallback callback, void* data);
+  static ThreadState* CurrentThreadState();
+  static void SetCurrentThreadState(ThreadState* state);
+
+  // Registered thread table.
+  static ThreadState** threads_;
+  static intptr_t threads_capacity_;
+  static intptr_t threads_size_;
+  static void _EnsureThreadStateCreated();
+  static void _Enable();
+  static void _Disable();
+  static void ResizeThreads(intptr_t new_capacity);
+  static void AddThread(ThreadId id);
+  static intptr_t FindThreadIndex(ThreadId id);
+  static ThreadState* RemoveThread(intptr_t i);
+
+  friend class ThreadInterrupterAndroid;
+  friend class ThreadInterrupterMacOS;
+  friend class ThreadInterrupterLinux;
+  friend class ThreadInterrupterWin;
+
+  static void InterruptThreads(int64_t current_time);
+  static void ThreadMain(uword parameters);
+
+  static void InstallSignalHandler();
+};
+
+void ThreadInterruptNoOp(const InterruptedThreadState& state, void* data);
+
+}  // namespace dart
+
+#endif  // VM_THREAD_INTERRUPTER_H_
diff --git a/runtime/vm/thread_interrupter_android.cc b/runtime/vm/thread_interrupter_android.cc
new file mode 100644
index 0000000..a5a4f8a
--- /dev/null
+++ b/runtime/vm/thread_interrupter_android.cc
@@ -0,0 +1,55 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#include "platform/globals.h"
+#if defined(TARGET_OS_ANDROID)
+
+#include "vm/signal_handler.h"
+#include "vm/thread_interrupter.h"
+
+namespace dart {
+
+DECLARE_FLAG(bool, thread_interrupter);
+DECLARE_FLAG(bool, trace_thread_interrupter);
+
+class ThreadInterrupterAndroid : public AllStatic {
+ public:
+  static void ThreadInterruptSignalHandler(int signal, siginfo_t* info,
+                                           void* context_) {
+    if (signal != SIGPROF) {
+      return;
+    }
+    ThreadInterrupter::ThreadState* state =
+        ThreadInterrupter::CurrentThreadState();
+    if ((state == NULL) || (state->callback == NULL)) {
+      // No interrupter state or callback.
+      return;
+    }
+    ASSERT(Thread::Compare(state->id, Thread::GetCurrentThreadId()));
+  }
+};
+
+
+void ThreadInterrupter::InterruptThreads(int64_t current_time) {
+  for (intptr_t i = 0; i < threads_size_; i++) {
+    ThreadState* state = threads_[i];
+    ASSERT(state->id != Thread::kInvalidThreadId);
+    if (FLAG_trace_thread_interrupter) {
+      OS::Print("ThreadInterrupter interrupting %p\n",
+                reinterpret_cast<void*>(state->id));
+    }
+    pthread_kill(state->id, SIGPROF);
+  }
+}
+
+
+void ThreadInterrupter::InstallSignalHandler() {
+  SignalHandler::Install(
+      ThreadInterrupterAndroid::ThreadInterruptSignalHandler);
+}
+
+
+}  // namespace dart
+
+#endif  // defined(TARGET_OS_ANDROID)
diff --git a/runtime/vm/thread_interrupter_linux.cc b/runtime/vm/thread_interrupter_linux.cc
new file mode 100644
index 0000000..ee6b4a7
--- /dev/null
+++ b/runtime/vm/thread_interrupter_linux.cc
@@ -0,0 +1,63 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#include "platform/globals.h"
+#if defined(TARGET_OS_LINUX)
+
+#include "vm/signal_handler.h"
+#include "vm/thread_interrupter.h"
+
+namespace dart {
+
+DECLARE_FLAG(bool, thread_interrupter);
+DECLARE_FLAG(bool, trace_thread_interrupter);
+
+class ThreadInterrupterLinux : public AllStatic {
+ public:
+  static void ThreadInterruptSignalHandler(int signal, siginfo_t* info,
+                                           void* context_) {
+    if (signal != SIGPROF) {
+      return;
+    }
+    ThreadInterrupter::ThreadState* state =
+        ThreadInterrupter::CurrentThreadState();
+    if ((state == NULL) || (state->callback == NULL)) {
+      // No interrupter state or callback.
+      return;
+    }
+    ASSERT(Thread::Compare(state->id, Thread::GetCurrentThreadId()));
+    // Extract thread state.
+    ucontext_t* context = reinterpret_cast<ucontext_t*>(context_);
+    mcontext_t mcontext = context->uc_mcontext;
+    InterruptedThreadState its;
+    its.tid = state->id;
+    its.pc = SignalHandler::GetProgramCounter(mcontext);
+    its.fp = SignalHandler::GetFramePointer(mcontext);
+    its.sp = SignalHandler::GetStackPointer(mcontext);
+    state->callback(its, state->data);
+  }
+};
+
+
+void ThreadInterrupter::InterruptThreads(int64_t current_time) {
+  for (intptr_t i = 0; i < threads_size_; i++) {
+    ThreadState* state = threads_[i];
+    ASSERT(state->id != Thread::kInvalidThreadId);
+    if (FLAG_trace_thread_interrupter) {
+      OS::Print("ThreadInterrupter interrupting %p\n",
+                reinterpret_cast<void*>(state->id));
+    }
+    pthread_kill(state->id, SIGPROF);
+  }
+}
+
+
+void ThreadInterrupter::InstallSignalHandler() {
+  SignalHandler::Install(ThreadInterrupterLinux::ThreadInterruptSignalHandler);
+}
+
+
+}  // namespace dart
+
+#endif  // defined(TARGET_OS_LINUX)
diff --git a/runtime/vm/thread_interrupter_macos.cc b/runtime/vm/thread_interrupter_macos.cc
new file mode 100644
index 0000000..f9deca5
--- /dev/null
+++ b/runtime/vm/thread_interrupter_macos.cc
@@ -0,0 +1,64 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#include "platform/globals.h"
+#if defined(TARGET_OS_MACOS)
+
+#include "vm/signal_handler.h"
+#include "vm/thread_interrupter.h"
+
+namespace dart {
+
+DECLARE_FLAG(bool, thread_interrupter);
+DECLARE_FLAG(bool, trace_thread_interrupter);
+
+class ThreadInterrupterMacOS : public AllStatic {
+ public:
+  static void ThreadInterruptSignalHandler(int signal, siginfo_t* info,
+                                           void* context_) {
+    if (signal != SIGPROF) {
+      return;
+    }
+    ThreadInterrupter::ThreadState* state =
+        ThreadInterrupter::CurrentThreadState();
+    if ((state == NULL) || (state->callback == NULL)) {
+      // No interrupter state or callback.
+      return;
+    }
+    ASSERT(Thread::Compare(state->id, Thread::GetCurrentThreadId()));
+
+    // Extract thread state.
+    ucontext_t* context = reinterpret_cast<ucontext_t*>(context_);
+    mcontext_t mcontext = context->uc_mcontext;
+    InterruptedThreadState its;
+    its.tid = state->id;
+    its.pc = SignalHandler::GetProgramCounter(mcontext);
+    its.fp = SignalHandler::GetFramePointer(mcontext);
+    its.sp = SignalHandler::GetStackPointer(mcontext);
+    state->callback(its, state->data);
+  }
+};
+
+
+void ThreadInterrupter::InterruptThreads(int64_t current_time) {
+  for (intptr_t i = 0; i < threads_size_; i++) {
+    ThreadState* state = threads_[i];
+    ASSERT(state->id != Thread::kInvalidThreadId);
+    if (FLAG_trace_thread_interrupter) {
+      OS::Print("ThreadInterrupter interrupting %p\n", state->id);
+    }
+    pthread_kill(state->id, SIGPROF);
+  }
+}
+
+
+void ThreadInterrupter::InstallSignalHandler() {
+  SignalHandler::Install(ThreadInterrupterMacOS::ThreadInterruptSignalHandler);
+}
+
+
+}  // namespace dart
+
+#endif  // defined(TARGET_OS_MACOS)
+
diff --git a/runtime/vm/thread_interrupter_test.cc b/runtime/vm/thread_interrupter_test.cc
new file mode 100644
index 0000000..4d69edd
--- /dev/null
+++ b/runtime/vm/thread_interrupter_test.cc
@@ -0,0 +1,65 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#include "platform/assert.h"
+
+#include "vm/dart_api_impl.h"
+#include "vm/dart_api_state.h"
+#include "vm/globals.h"
+#include "vm/thread_interrupter.h"
+#include "vm/unit_test.h"
+
+namespace dart {
+
+class ThreadInterrupterTestHelper : public AllStatic {
+ public:
+  static void InterruptTest(const intptr_t run_time, const intptr_t period) {
+    const double allowed_error = 0.25;  // +/- 25%
+    intptr_t count = 0;
+    ThreadInterrupter::Unregister();
+    ThreadInterrupter::SetInterruptPeriod(period);
+    ThreadInterrupter::Register(IncrementCallback, &count);
+    OS::Sleep(run_time * kMillisecondsPerSecond);
+    ThreadInterrupter::Unregister();
+    intptr_t run_time_micros = run_time * kMicrosecondsPerSecond;
+    intptr_t expected_interrupts = run_time_micros / period;
+    intptr_t error = allowed_error * expected_interrupts;
+    intptr_t low_bar = expected_interrupts - error;
+    intptr_t high_bar = expected_interrupts + error;
+    EXPECT_GE(count, low_bar);
+    EXPECT_LE(count, high_bar);
+  }
+
+  static void IncrementCallback(const InterruptedThreadState& state,
+                                void* data) {
+    ASSERT(data != NULL);
+    intptr_t* counter = reinterpret_cast<intptr_t*>(data);
+    *counter = *counter + 1;
+  }
+};
+
+
+TEST_CASE(ThreadInterrupterHigh) {
+  const intptr_t kRunTimeSeconds = 5;
+  const intptr_t kInterruptPeriodMicros = 250;
+  ThreadInterrupterTestHelper::InterruptTest(kRunTimeSeconds,
+                                             kInterruptPeriodMicros);
+}
+
+TEST_CASE(ThreadInterrupterMedium) {
+  const intptr_t kRunTimeSeconds = 5;
+  const intptr_t kInterruptPeriodMicros = 500;
+  ThreadInterrupterTestHelper::InterruptTest(kRunTimeSeconds,
+                                             kInterruptPeriodMicros);
+}
+
+TEST_CASE(ThreadInterrupterLow) {
+  const intptr_t kRunTimeSeconds = 5;
+  const intptr_t kInterruptPeriodMicros = 1000;
+  ThreadInterrupterTestHelper::InterruptTest(kRunTimeSeconds,
+                                             kInterruptPeriodMicros);
+}
+
+
+}  // namespace dart
diff --git a/runtime/vm/thread_interrupter_win.cc b/runtime/vm/thread_interrupter_win.cc
new file mode 100644
index 0000000..c933cbb
--- /dev/null
+++ b/runtime/vm/thread_interrupter_win.cc
@@ -0,0 +1,98 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#include "platform/globals.h"
+#if defined(TARGET_OS_WINDOWS)
+
+#include "vm/thread_interrupter.h"
+
+namespace dart {
+
+DECLARE_FLAG(bool, thread_interrupter);
+DECLARE_FLAG(bool, trace_thread_interrupter);
+
+#define kThreadError -1
+
+class ThreadInterrupterWin : public AllStatic {
+ public:
+  static bool GrabRegisters(ThreadId thread, InterruptedThreadState* state) {
+    CONTEXT context;
+    memset(&context, 0, sizeof(context));
+    context.ContextFlags = CONTEXT_FULL;
+    if (GetThreadContext(thread, &context) != 0) {
+#if defined(TARGET_ARCH_IA32)
+      state->pc = static_cast<uintptr_t>(context.Eip);
+      state->fp = static_cast<uintptr_t>(context.Ebp);
+      state->sp = static_cast<uintptr_t>(context.Esp);
+#elif defined(TARGET_ARCH_X64)
+      state->pc = reinterpret_cast<uintptr_t>(context.Rip);
+      state->fp = reinterpret_cast<uintptr_t>(context.Rbp);
+      state->sp = reinterpret_cast<uintptr_t>(context.Rsp);
+#else
+      UNIMPLEMENTED();
+#endif
+      return true;
+    }
+    return false;
+  }
+
+
+  static void Interrupt(ThreadInterrupter::ThreadState* state) {
+    ASSERT(GetCurrentThread() != state->id);
+    DWORD result = SuspendThread(state->id);
+    if (result == kThreadError) {
+      if (FLAG_trace_thread_interrupter) {
+        OS::Print("ThreadInterrupted failed to suspend thread %p\n",
+                  reinterpret_cast<void*>(state->id));
+      }
+      return;
+    }
+    InterruptedThreadState its;
+    its.tid = state->id;
+    if (!GrabRegisters(state->id, &its)) {
+      // Failed to get thread registers.
+      ResumeThread(state->id);
+      if (FLAG_trace_thread_interrupter) {
+        OS::Print("ThreadInterrupted failed to get registers for %p\n",
+                  reinterpret_cast<void*>(state->id));
+      }
+      return;
+    }
+    if (state->callback == NULL) {
+      // No callback registered.
+      ResumeThread(state->id);
+      return;
+    }
+    state->callback(its, state->data);
+    ResumeThread(state->id);
+  }
+};
+
+
+void ThreadInterrupter::InterruptThreads(int64_t current_time) {
+  for (intptr_t i = 0; i < threads_size_; i++) {
+    ThreadState* state = threads_[i];
+    ASSERT(state->id != Thread::kInvalidThreadId);
+    if (FLAG_trace_thread_interrupter) {
+      OS::Print("ThreadInterrupter suspending %p\n",
+                reinterpret_cast<void*>(state->id));
+    }
+    ThreadInterrupterWin::Interrupt(state);
+    if (FLAG_trace_thread_interrupter) {
+      OS::Print("ThreadInterrupter resuming %p\n",
+                reinterpret_cast<void*>(state->id));
+    }
+  }
+}
+
+
+void ThreadInterrupter::InstallSignalHandler() {
+  // Nothing to do on Windows.
+}
+
+
+}  // namespace dart
+
+#endif  // defined(TARGET_OS_WINDOWS)
+
diff --git a/runtime/vm/thread_test.cc b/runtime/vm/thread_test.cc
index 1305a1c..0c0c912 100644
--- a/runtime/vm/thread_test.cc
+++ b/runtime/vm/thread_test.cc
@@ -5,7 +5,7 @@
 #include "platform/assert.h"
 #include "vm/isolate.h"
 #include "vm/unit_test.h"
-#include "vm/signal_handler.h"
+#include "vm/profiler.h"
 #include "vm/thread.h"
 
 namespace dart {
@@ -35,7 +35,8 @@
 UNIT_TEST_CASE(Monitor) {
   // This unit test case needs a running isolate.
   Isolate* isolate = Isolate::Init(NULL);
-
+  // Profiler interrupts interfere with this test.
+  Profiler::EndExecution(isolate);
   Monitor* monitor = new Monitor();
   monitor->Enter();
   monitor->Exit();
@@ -43,10 +44,6 @@
   const int kNumAttempts = 5;
   int attempts = 0;
   while (attempts < kNumAttempts) {
-    // This test verifies that a monitor returns after the specified timeout. If
-    // a signal is delivered to this thread, the monitor may return early.
-    // Block signal delivery in this scope.
-    ScopedSignalBlocker ssb;
     MonitorLocker ml(monitor);
     int64_t start = OS::GetCurrentTimeMillis();
     int64_t wait_time = 2017;
diff --git a/runtime/vm/vm_sources.gypi b/runtime/vm/vm_sources.gypi
index 10f4950..92c5524 100644
--- a/runtime/vm/vm_sources.gypi
+++ b/runtime/vm/vm_sources.gypi
@@ -31,6 +31,11 @@
     'ast_printer.h',
     'ast_printer_test.cc',
     'ast_test.cc',
+    'atomic.h',
+    'atomic_android.cc',
+    'atomic_linux.cc',
+    'atomic_macos.cc',
+    'atomic_win.cc',
     'base_isolate.h',
     'benchmark_test.cc',
     'benchmark_test.h',
@@ -107,6 +112,7 @@
     'dart_entry.h',
     'dart_entry_test.cc',
     'debugger.cc',
+    'debugger_test.cc',
     'debugger.h',
     'debugger_api_impl_test.cc',
     'debugger_arm.cc',
@@ -277,11 +283,7 @@
     'port_test.cc',
     'profiler.cc',
     'profiler.h',
-    'profiler_android.cc',
-    'profiler_linux.cc',
-    'profiler_macos.cc',
     'profiler_test.cc',
-    'profiler_win.cc',
     'random.cc',
     'random.h',
     'raw_object.cc',
@@ -306,6 +308,7 @@
     'scopes.h',
     'scopes_test.cc',
     'service.cc',
+    'service_test.cc',
     'service.h',
     'signal_handler_android.cc',
     'signal_handler_linux.cc',
@@ -343,6 +346,13 @@
     'symbols.cc',
     'symbols.h',
     'thread.h',
+    'thread_interrupter.cc',
+    'thread_interrupter.h',
+    'thread_interrupter_android.cc',
+    'thread_interrupter_linux.cc',
+    'thread_interrupter_macos.cc',
+    'thread_interrupter_test.cc',
+    'thread_interrupter_win.cc',
     'thread_pool.cc',
     'thread_pool.h',
     'thread_pool_test.cc',
diff --git a/sdk/bin/pub.bat b/sdk/bin/pub.bat
index 03213fd..9294231 100644
--- a/sdk/bin/pub.bat
+++ b/sdk/bin/pub.bat
@@ -18,16 +18,16 @@
 IF %SDK_DIR:~-1%==\ set SDK_DIR=%SDK_DIR:~0,-1%
 
 set PUB=%SDK_DIR%\lib\_internal\pub\bin\pub.dart
-set BUILD_DIR=%SDK_DIR%\..\build\ReleaseIA32
-set PACKAGES_DIR=%BUILD_DIR%\packages\
 set DART=%BIN_DIR%\dart
-set DART_IN_BUILT_SDK=%BUILD_DIR%\dart-sdk\bin\dart
 set SNAPSHOT=%BIN_DIR%\snapshots\pub.dart.snapshot
+set BUILD_DIR=%SDK_DIR%\..\build\ReleaseIA32
+set PACKAGES_DIR=%BUILD_DIR%\packages
+set DART_IN_BUILT_SDK=%BUILD_DIR%\dart-sdk\bin\dart
 
 if exist "%SNAPSHOT%" (
   "%DART%" "%SNAPSHOT%" %*
 ) else (
-  "%DART_IN_BUILT_SDK%" --package-root=%PACKAGES_DIR% "%PUB%" %*
+  "%DART_IN_BUILT_SDK%" --package-root="%PACKAGES_DIR%" "%PUB%" %*
 )
 
 endlocal
@@ -38,8 +38,8 @@
 setlocal
 for %%i in (%1) do set result=%%~fi
 set current=
-for /f "tokens=2 delims=[]" %%i in ('dir /a:l ^"%~dp1^" 2^>nul ^
-                                     ^| find ">     %~n1 ["') do (
+for /f "usebackq tokens=2 delims=[]" %%i in (`dir /a:l "%~dp1" 2^>nul ^
+                                             ^| find ">     %~n1 ["`) do (
   set current=%%i
 )
 if not "%current%"=="" call :follow_links "%current%", result
diff --git a/sdk/bin/pub_developer.bat b/sdk/bin/pub_developer.bat
index 6f0d4e0..9c77b79 100644
--- a/sdk/bin/pub_developer.bat
+++ b/sdk/bin/pub_developer.bat
@@ -18,16 +18,16 @@
 IF %SDK_DIR:~-1%==\ set SDK_DIR=%SDK_DIR:~0,-1%
 
 set PUB=%SDK_DIR%\lib\_internal\pub\bin\pub.dart
-set BUILD_DIR=%SDK_DIR%\..\build\ReleaseIA32
-set PACKAGES_DIR=%BUILD_DIR%\packages\
 set DART=%BIN_DIR%\dart
-set DART_IN_BUILT_SDK=%BUILD_DIR%\dart-sdk\bin\dart
 set SNAPSHOT=%BIN_DIR%\snapshots\pub.dart.snapshot
+set BUILD_DIR=%SDK_DIR%\..\build\ReleaseIA32
+set PACKAGES_DIR=%BUILD_DIR%\packages
+set DART_IN_BUILT_SDK=%BUILD_DIR%\dart-sdk\bin\dart
 
 if exist "%SNAPSHOT%" (
   "%DART%" --checked "%SNAPSHOT%" %*
 ) else (
-  "%DART_IN_BUILT_SDK%" --checked --package-root=%PACKAGES_DIR% "%PUB%" %*
+  "%DART_IN_BUILT_SDK%" --checked --package-root="%PACKAGES_DIR%" "%PUB%" %*
 )
 
 endlocal
@@ -38,8 +38,8 @@
 setlocal
 for %%i in (%1) do set result=%%~fi
 set current=
-for /f "tokens=2 delims=[]" %%i in ('dir /a:l ^"%~dp1^" 2^>nul ^
-                                     ^| find ">     %~n1 ["') do (
+for /f "usebackq tokens=2 delims=[]" %%i in (`dir /a:l "%~dp1" 2^>nul ^
+                                             ^| find ">     %~n1 ["`) do (
   set current=%%i
 )
 if not "%current%"=="" call :follow_links "%current%", result
diff --git a/sdk/lib/_collection_dev/collection_dev.dart b/sdk/lib/_collection_dev/collection_dev.dart
index 6e883f6..9902b0e 100644
--- a/sdk/lib/_collection_dev/collection_dev.dart
+++ b/sdk/lib/_collection_dev/collection_dev.dart
@@ -10,9 +10,9 @@
 import 'dart:core' as core;
 import 'dart:math' show Random;
 
-part 'arrays.dart';
 part 'iterable.dart';
 part 'list.dart';
+part 'lists.dart';
 part 'print.dart';
 part 'sort.dart';
 part 'symbol.dart';
diff --git a/sdk/lib/_collection_dev/collection_dev_sources.gypi b/sdk/lib/_collection_dev/collection_dev_sources.gypi
index c85469d..bb25742 100644
--- a/sdk/lib/_collection_dev/collection_dev_sources.gypi
+++ b/sdk/lib/_collection_dev/collection_dev_sources.gypi
@@ -7,9 +7,9 @@
   'sources': [
     'collection_dev.dart',
     # The above file needs to be first as it lists the parts below.
-    'arrays.dart',
     'iterable.dart',
     'list.dart',
+    'lists.dart',
     'print.dart',
     'sort.dart',
     'symbol.dart',
diff --git a/sdk/lib/_collection_dev/iterable.dart b/sdk/lib/_collection_dev/iterable.dart
index 651e346..4bcc7b8 100644
--- a/sdk/lib/_collection_dev/iterable.dart
+++ b/sdk/lib/_collection_dev/iterable.dart
@@ -1016,12 +1016,12 @@
   }
 
   static int indexOfList(List list, var element, int start) {
-    return Arrays.indexOf(list, element, start, list.length);
+    return Lists.indexOf(list, element, start, list.length);
   }
 
   static int lastIndexOfList(List list, var element, int start) {
     if (start == null) start = list.length - 1;
-    return Arrays.lastIndexOf(list, element, start);
+    return Lists.lastIndexOf(list, element, start);
   }
 
   static void _rangeCheck(List list, int start, int end) {
@@ -1060,7 +1060,7 @@
     if (otherStart + length > otherList.length) {
       throw new StateError("Not enough elements");
     }
-    Arrays.copy(otherList, otherStart, list, start, length);
+    Lists.copy(otherList, otherStart, list, start, length);
   }
 
   static void replaceRangeList(List list, int start, int end,
diff --git a/sdk/lib/_collection_dev/arrays.dart b/sdk/lib/_collection_dev/lists.dart
similarity index 97%
rename from sdk/lib/_collection_dev/arrays.dart
rename to sdk/lib/_collection_dev/lists.dart
index deaa169..eed1df5 100644
--- a/sdk/lib/_collection_dev/arrays.dart
+++ b/sdk/lib/_collection_dev/lists.dart
@@ -4,8 +4,7 @@
 
 part of dart._collection.dev;
 
-// TODO(ngeoffray): Rename to Lists.
-class Arrays {
+class Lists {
   static void copy(List src, int srcStart,
                    List dst, int dstStart, int count) {
     if (srcStart < dstStart) {
diff --git a/sdk/lib/_internal/compiler/implementation/constants.dart b/sdk/lib/_internal/compiler/implementation/constants.dart
index d030524..272fd6a 100644
--- a/sdk/lib/_internal/compiler/implementation/constants.dart
+++ b/sdk/lib/_internal/compiler/implementation/constants.dart
@@ -17,6 +17,7 @@
   R visitConstructed(ConstructedConstant constant);
   R visitType(TypeConstant constant);
   R visitInterceptor(InterceptorConstant constant);
+  R visitDummyReceiver(DummyReceiverConstant constant);
 }
 
 abstract class Constant {
@@ -41,6 +42,7 @@
   bool isType() => false;
   bool isSentinel() => false;
   bool isInterceptor() => false;
+  bool isDummyReceiver() => false;
 
   bool isNaN() => false;
   bool isMinusZero() => false;
@@ -538,6 +540,33 @@
   }
 }
 
+class DummyReceiverConstant extends Constant {
+  final ti.TypeMask typeMask;
+
+  DummyReceiverConstant(this.typeMask);
+
+  bool isDummyReceiver() => true;
+
+  bool operator ==(other) {
+    return other is DummyReceiverConstant
+        && typeMask == other.typeMask;
+  }
+
+  get hashCode => typeMask.hashCode;
+
+  List<Constant> getDependencies() => const <Constant>[];
+
+  accept(ConstantVisitor visitor) => visitor.visitDummyReceiver(this);
+
+  DartType computeType(Compiler compiler) => compiler.types.dynamicType;
+
+  ti.TypeMask computeMask(Compiler compiler) => typeMask;
+
+  String toString() {
+    return 'DummyReceiverConstant($typeMask)';
+  }
+}
+
 class ConstructedConstant extends ObjectConstant {
   final List<Constant> fields;
   final int hashCode;
diff --git a/sdk/lib/_internal/compiler/implementation/inferrer/closure_tracer.dart b/sdk/lib/_internal/compiler/implementation/inferrer/closure_tracer.dart
new file mode 100644
index 0000000..3d41263
--- /dev/null
+++ b/sdk/lib/_internal/compiler/implementation/inferrer/closure_tracer.dart
@@ -0,0 +1,79 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of type_graph_inferrer;
+
+class ClosureTracerVisitor extends TracerVisitor {
+  ClosureTracerVisitor(tracedType, inferrer) : super(tracedType, inferrer);
+
+  void run() {
+    ClosureTypeInformation closure = tracedType;
+    FunctionElement element = closure.element;
+    element.functionSignature.forEachParameter((Element parameter) {
+      ElementTypeInformation info = inferrer.types.getInferredTypeOf(parameter);
+      info.abandonInferencing = false;
+    });
+    analyze();
+    element.functionSignature.forEachParameter((Element parameter) {
+      ElementTypeInformation info = inferrer.types.getInferredTypeOf(parameter);
+      if (continueAnalyzing) {
+        info.disableHandleSpecialCases = true;
+      } else {
+        info.giveUp(inferrer);
+      }
+    });
+  }
+
+  visitMapTypeInformation(MapTypeInformation info) {
+    bailout('Stored in a map');
+  }
+
+  void analyzeCall(CallSiteTypeInformation info) {
+    ClosureTypeInformation closure = tracedType;
+    FunctionElement element = closure.element;
+    Selector selector = info.selector;
+    if (!selector.signatureApplies(element, compiler)) return;
+    inferrer.updateParameterAssignments(
+        info, element, info.arguments, selector, remove: false,
+        addToQueue: false);
+  }
+
+  visitClosureCallSiteTypeInformation(ClosureCallSiteTypeInformation info) {
+    super.visitClosureCallSiteTypeInformation(info);
+    if (info.closure == currentUser) {
+      analyzeCall(info);
+    } else {
+      bailout('Passed to a closure');
+    }
+  }
+
+  visitStaticCallSiteTypeInformation(StaticCallSiteTypeInformation info) {
+    super.visitStaticCallSiteTypeInformation(info);
+    Element called = info.calledElement;
+    if (called.isForeign(compiler) && called.name == 'JS') {
+      bailout('Used in JS ${info.call}');
+    }
+    if (inferrer.types.getInferredTypeOf(called) == currentUser) {
+      // This node can be a closure call as well. For example, `foo()`
+      // where `foo` is a getter.
+      analyzeCall(info);
+    }
+  }
+
+  bool checkIfCurrentUser(element) {
+    return inferrer.types.getInferredTypeOf(element) == currentUser;
+  }
+
+  visitDynamicCallSiteTypeInformation(DynamicCallSiteTypeInformation info) {
+    super.visitDynamicCallSiteTypeInformation(info);
+    if (info.selector.isCall()) {
+      if (info.arguments.contains(currentUser)
+          && !info.targets.every((element) => element.isFunction())) {
+        bailout('Passed to a closure');
+      } else if (info.targets.any((element) => checkIfCurrentUser(element))) {
+        analyzeCall(info);
+      }
+    }
+  }
+}
diff --git a/sdk/lib/_internal/compiler/implementation/inferrer/container_tracer.dart b/sdk/lib/_internal/compiler/implementation/inferrer/container_tracer.dart
deleted file mode 100644
index bc1dc7f..0000000
--- a/sdk/lib/_internal/compiler/implementation/inferrer/container_tracer.dart
+++ /dev/null
@@ -1,404 +0,0 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-part of type_graph_inferrer;
-
-/**
- * A set of selector names that [List] implements, that we know do not
- * change the element type of the list, or let the list escape to code
- * that might change the element type.
- */
-Set<String> okSelectorsSet = new Set<String>.from(
-  const <String>[
-    // From Object.
-    '==',
-    'hashCode',
-    'toString',
-    'noSuchMethod',
-    'runtimeType',
-
-    // From Iterable.
-    'iterator',
-    'map',
-    'where',
-    'expand',
-    'contains',
-    'forEach',
-    'reduce',
-    'fold',
-    'every',
-    'join',
-    'any',
-    'toList',
-    'toSet',
-    'length',
-    'isEmpty',
-    'isNotEmpty',
-    'take',
-    'takeWhile',
-    'skip',
-    'skipWhile',
-    'first',
-    'last',
-    'single',
-    'firstWhere',
-    'lastWhere',
-    'singleWhere',
-    'elementAt',
-
-    // From List.
-    '[]',
-    'length',
-    'reversed',
-    'sort',
-    'indexOf',
-    'lastIndexOf',
-    'clear',
-    'remove',
-    'removeAt',
-    'removeLast',
-    'removeWhere',
-    'retainWhere',
-    'sublist',
-    'getRange',
-    'removeRange',
-    'asMap',
-
-    // From JSArray.
-    'checkMutable',
-    'checkGrowable',
-  ]);
-
-Set<String> doNotChangeLengthSelectorsSet = new Set<String>.from(
-  const <String>[
-    // From Object.
-    '==',
-    'hashCode',
-    'toString',
-    'noSuchMethod',
-    'runtimeType',
-
-    // From Iterable.
-    'iterator',
-    'map',
-    'where',
-    'expand',
-    'contains',
-    'forEach',
-    'reduce',
-    'fold',
-    'every',
-    'join',
-    'any',
-    'toList',
-    'toSet',
-    'length',
-    'isEmpty',
-    'isNotEmpty',
-    'take',
-    'takeWhile',
-    'skip',
-    'skipWhile',
-    'first',
-    'last',
-    'single',
-    'firstWhere',
-    'lastWhere',
-    'singleWhere',
-    'elementAt',
-
-    // From List.
-    '[]',
-    '[]=',
-    'length',
-    'reversed',
-    'sort',
-    'indexOf',
-    'lastIndexOf',
-    'sublist',
-    'getRange',
-    'asMap',
-
-    // From JSArray.
-    'checkMutable',
-    'checkGrowable',
-  ]);
-
-// A set of selectors we know do not escape the elements inside the
-// list.
-Set<String> doesNotEscapeElementSet = new Set<String>.from(
-  const <String>[
-    // From Object.
-    '==',
-    'hashCode',
-    'toString',
-    'noSuchMethod',
-    'runtimeType',
-
-    // From Iterable.
-    'isEmpty',
-    'isNotEmpty',
-    'length',
-    'any',
-    'contains',
-    'every',
-    'join',
-
-    // From List.
-    'add',
-    'addAll',
-    'clear',
-    'fillRange',
-    'indexOf',
-    'insert',
-    'insertAll',
-    'lastIndexOf',
-    'remove',
-    'removeRange',
-    'replaceRange',
-    'setAll',
-    'setRange',
-    'shuffle',
-    '[]=',
-
-    // From JSArray.
-    'checkMutable',
-    'checkGrowable',
-  ]);
-
-bool _VERBOSE = false;
-
-class ContainerTracerVisitor implements TypeInformationVisitor {
-  final ListTypeInformation container;
-  final TypeGraphInferrerEngine inferrer;
-  final Compiler compiler;
-
-
-  // Work list that gets populated with [TypeInformation] that could
-  // contain the container.
-  final List<TypeInformation> workList = <TypeInformation>[];
-
-  // Work list of containers to analyze after analyzing the users of a
-  // [TypeInformation] that may be [container]. We know [container]
-  // has been stored in these containers and we must check how
-  // [container] escapes from these containers.
-  final List<ListTypeInformation> containersToAnalyze =
-      <ListTypeInformation>[];
-
-  // The current [TypeInformation] in the analysis.
-  TypeInformation currentUser;
-
-  // The list of found assignments to the container.
-  final List<TypeInformation> assignments = <TypeInformation>[];
-
-  bool callsGrowableMethod = false;
-  bool continueAnalyzing = true;
-  
-  static const int MAX_ANALYSIS_COUNT = 16;
-  final Setlet<Element> analyzedElements = new Setlet<Element>();
-
-  ContainerTracerVisitor(this.container, inferrer)
-      : this.inferrer = inferrer, this.compiler = inferrer.compiler;
-
-  void addNewEscapeInformation(TypeInformation info) {
-    if (container.flowsInto.contains(info)) return;
-    container.flowsInto.add(info);
-    workList.add(info);
-  }
-
-  List<TypeInformation> run() {
-    // Collect the [TypeInformation] where the container can flow in,
-    // as well as the operations done on all these [TypeInformation]s.
-    addNewEscapeInformation(container);
-    while (!workList.isEmpty) {
-      currentUser = workList.removeLast();
-      currentUser.users.forEach((TypeInformation info) {
-        analyzedElements.add(info.owner);
-        info.accept(this);
-      });
-      while (!containersToAnalyze.isEmpty) {
-        analyzeStoredIntoContainer(containersToAnalyze.removeLast());
-      }
-      if (!continueAnalyzing) break;
-      if (analyzedElements.length > MAX_ANALYSIS_COUNT) {
-        bailout('Too many users');
-        break;
-      }
-    }
-
-    if (continueAnalyzing) {
-      if (!callsGrowableMethod && container.inferredLength == null) {
-        container.inferredLength = container.originalLength;
-      }
-      return assignments;
-    }
-    return null;
-  }
-
-  void bailout(String reason) {
-    if (_VERBOSE) {
-      ContainerTypeMask mask = container.type;
-      print('Bailing out on ${mask.allocationNode} ${mask.allocationElement} '
-            'because: $reason');
-    }
-    continueAnalyzing = false;
-    callsGrowableMethod = true;
-  }
-
-  visitNarrowTypeInformation(NarrowTypeInformation info) {
-    addNewEscapeInformation(info);
-  }
-
-  visitPhiElementTypeInformation(PhiElementTypeInformation info) {
-    addNewEscapeInformation(info);
-  }
-
-  visitElementInContainerTypeInformation(
-      ElementInContainerTypeInformation info) {
-    addNewEscapeInformation(info);
-  }
-
-  visitListTypeInformation(ListTypeInformation info) {
-    containersToAnalyze.add(info);
-  }
-
-  visitMapTypeInformation(MapTypeInformation info) {
-    bailout('Stored in a map');
-  }
-
-  visitConcreteTypeInformation(ConcreteTypeInformation info) {}
-
-  visitClosureCallSiteTypeInformation(ClosureCallSiteTypeInformation info) {
-    bailout('Passed to a closure');
-  }
-
-  visitStaticCallSiteTypeInformation(StaticCallSiteTypeInformation info) {
-    Element called = info.calledElement;
-    if (called.isForeign(compiler) && called.name == 'JS') {
-      bailout('Used in JS ${info.call}');
-    }
-    if (inferrer.types.getInferredTypeOf(called) == currentUser) {
-      addNewEscapeInformation(info);
-    }
-  }
-
-  void analyzeStoredIntoContainer(ListTypeInformation container) {
-    inferrer.analyzeContainer(container);
-    if (container.bailedOut) {
-      bailout('Stored in a container that bailed out');
-    } else {
-      container.flowsInto.forEach((flow) {
-        flow.users.forEach((user) {
-          if (user is !DynamicCallSiteTypeInformation) return;
-          if (user.receiver != flow) return;
-          if (returnsElementTypeSet.contains(user.selector)) {
-            addNewEscapeInformation(user);
-          } else if (!doesNotEscapeElementSet.contains(user.selector.name)) {
-            bailout('Escape from a container');
-          }
-        });
-      });
-    }
-  }
-
-  bool isAddedToContainer(DynamicCallSiteTypeInformation info) {
-    var receiverType = info.receiver.type;
-    if (!receiverType.isContainer) return false;
-    String selectorName = info.selector.name;
-    List<TypeInformation> arguments = info.arguments.positional;
-    return (selectorName == '[]=' && currentUser == arguments[1])
-        || (selectorName == 'insert' && currentUser == arguments[0])
-        || (selectorName == 'add' && currentUser == arguments[0]);
-  }
-
-  visitDynamicCallSiteTypeInformation(DynamicCallSiteTypeInformation info) {
-    Selector selector = info.selector;
-    String selectorName = selector.name;
-    if (currentUser == info.receiver) {
-      if (!okSelectorsSet.contains(selectorName)) {
-        if (selector.isCall()) {
-          int positionalLength = info.arguments.positional.length;
-          if (selectorName == 'add') {
-            if (positionalLength == 1) {
-              assignments.add(info.arguments.positional[0]);
-            }
-          } else if (selectorName == 'insert') {
-            if (positionalLength == 2) {
-              assignments.add(info.arguments.positional[1]);
-            }
-          } else {
-            bailout('Used in a not-ok selector');
-            return;
-          }
-        } else if (selector.isIndexSet()) {
-          assignments.add(info.arguments.positional[1]);
-        } else if (!selector.isIndex()) {
-          bailout('Used in a not-ok selector');
-          return;
-        }
-      }
-      if (!doNotChangeLengthSelectorsSet.contains(selectorName)) {
-        callsGrowableMethod = true;
-      }
-      if (selectorName == 'length' && selector.isSetter()) {
-        callsGrowableMethod = true;
-        assignments.add(inferrer.types.nullType);
-      }
-    } else if (selector.isCall()
-               && !info.targets.every((element) => element.isFunction())) {
-      bailout('Passed to a closure');
-      return;
-    } else if (isAddedToContainer(info)) {
-      ContainerTypeMask mask = info.receiver.type;
-      if (mask.allocationNode != null) {
-        ListTypeInformation container =
-            inferrer.types.allocatedLists[mask.allocationNode];
-        containersToAnalyze.add(container);
-      } else {
-        // The [ContainerTypeMask] is a union of two containers, and
-        // we lose track of where these containers have been allocated
-        // at this point.
-        bailout('Stored in too many containers');
-      }
-    }
-
-    if (info.targets
-            .map((element) => inferrer.types.getInferredTypeOf(element))
-            .any((other) => other == currentUser)) {
-      addNewEscapeInformation(info);
-    }
-  }
-
-  bool isClosure(Element element) {
-    if (!element.isFunction()) return false;
-    Element outermost = element.getOutermostEnclosingMemberOrTopLevel();
-    return outermost.declaration != element.declaration;
-  }
-
-  bool isParameterOfListAddingMethod(Element element) {
-    if (!element.isParameter()) return false;
-    if (element.getEnclosingClass() != compiler.backend.listImplementation) {
-      return false;
-    }
-    Element method = element.enclosingElement;
-    return (method.name == '[]=')
-        || (method.name == 'add')
-        || (method.name == 'insert');
-  }
-
-  visitElementTypeInformation(ElementTypeInformation info) {
-    if (isClosure(info.element)) {
-      bailout('Returned from a closure');
-    }
-    if (compiler.backend.isNeededForReflection(info.element)) {
-      bailout('Escape in reflection');
-    }
-    if (isParameterOfListAddingMethod(info.element)) {
-      // These elements are being handled in
-      // [visitDynamicCallSiteTypeInformation].
-      return;
-    }
-    addNewEscapeInformation(info);
-  }
-}
diff --git a/sdk/lib/_internal/compiler/implementation/inferrer/inferrer_visitor.dart b/sdk/lib/_internal/compiler/implementation/inferrer/inferrer_visitor.dart
index 7db8c95..6890de7 100644
--- a/sdk/lib/_internal/compiler/implementation/inferrer/inferrer_visitor.dart
+++ b/sdk/lib/_internal/compiler/implementation/inferrer/inferrer_visitor.dart
@@ -49,6 +49,8 @@
 
   T allocateMap(T keyType, T valueType, T type);
 
+  T allocateClosure(Node node, Element element);
+
   /**
    * Returns the least upper bound between [firstType] and
    * [secondType].
@@ -271,6 +273,10 @@
   bool every(bool f(T type)) {
     return positional.every(f) && named.values.every(f);
   }
+
+  bool contains(T type) {
+    return positional.contains(type) || named.containsValue(type);
+  }
 }
 
 abstract class MinimalInferrerEngine<T> {
@@ -734,6 +740,11 @@
       return thisType;
     } else if (node.isSuper()) {
       return superType;
+    } else {
+      Element element = elements[node];
+      if (Elements.isLocal(element)) {
+        return locals.use(element);
+      }
     }
   }
 
@@ -847,6 +858,9 @@
                || '!==' == op.source) {
       node.visitChildren(this);
       return types.boolType;
+    } else if ('!=' == op.source) {
+      visitDynamicSend(node);
+      return types.boolType;
     } else {
       // Binary operator.
       return visitDynamicSend(node);
diff --git a/sdk/lib/_internal/compiler/implementation/inferrer/list_tracer.dart b/sdk/lib/_internal/compiler/implementation/inferrer/list_tracer.dart
new file mode 100644
index 0000000..1d2d063
--- /dev/null
+++ b/sdk/lib/_internal/compiler/implementation/inferrer/list_tracer.dart
@@ -0,0 +1,207 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of type_graph_inferrer;
+
+/**
+ * A set of selector names that [List] implements, that we know do not
+ * change the element type of the list, or let the list escape to code
+ * that might change the element type.
+ */
+Set<String> okSelectorsSet = new Set<String>.from(
+  const <String>[
+    // From Object.
+    '==',
+    'hashCode',
+    'toString',
+    'noSuchMethod',
+    'runtimeType',
+
+    // From Iterable.
+    'iterator',
+    'map',
+    'where',
+    'expand',
+    'contains',
+    'forEach',
+    'reduce',
+    'fold',
+    'every',
+    'join',
+    'any',
+    'toList',
+    'toSet',
+    'length',
+    'isEmpty',
+    'isNotEmpty',
+    'take',
+    'takeWhile',
+    'skip',
+    'skipWhile',
+    'first',
+    'last',
+    'single',
+    'firstWhere',
+    'lastWhere',
+    'singleWhere',
+    'elementAt',
+
+    // From List.
+    '[]',
+    'length',
+    'reversed',
+    'sort',
+    'indexOf',
+    'lastIndexOf',
+    'clear',
+    'remove',
+    'removeAt',
+    'removeLast',
+    'removeWhere',
+    'retainWhere',
+    'sublist',
+    'getRange',
+    'removeRange',
+    'asMap',
+
+    // From JSArray.
+    'checkMutable',
+    'checkGrowable',
+  ]);
+
+Set<String> doNotChangeLengthSelectorsSet = new Set<String>.from(
+  const <String>[
+    // From Object.
+    '==',
+    'hashCode',
+    'toString',
+    'noSuchMethod',
+    'runtimeType',
+
+    // From Iterable.
+    'iterator',
+    'map',
+    'where',
+    'expand',
+    'contains',
+    'forEach',
+    'reduce',
+    'fold',
+    'every',
+    'join',
+    'any',
+    'toList',
+    'toSet',
+    'length',
+    'isEmpty',
+    'isNotEmpty',
+    'take',
+    'takeWhile',
+    'skip',
+    'skipWhile',
+    'first',
+    'last',
+    'single',
+    'firstWhere',
+    'lastWhere',
+    'singleWhere',
+    'elementAt',
+
+    // From List.
+    '[]',
+    '[]=',
+    'length',
+    'reversed',
+    'sort',
+    'indexOf',
+    'lastIndexOf',
+    'sublist',
+    'getRange',
+    'asMap',
+
+    // From JSArray.
+    'checkMutable',
+    'checkGrowable',
+  ]);
+
+
+class ListTracerVisitor extends TracerVisitor {
+  // The list of found assignments to the container.
+  final List<TypeInformation> assignments = <TypeInformation>[];
+  bool callsGrowableMethod = false;
+  
+  ListTracerVisitor(tracedType, inferrer) : super(tracedType, inferrer);
+
+  List<TypeInformation> run() {
+    analyze();
+    ListTypeInformation container = tracedType;
+    if (continueAnalyzing) {
+      if (!callsGrowableMethod && container.inferredLength == null) {
+        container.inferredLength = container.originalLength;
+      }
+      container.flowsInto.addAll(flowsInto);
+      return assignments;
+    } else {
+      callsGrowableMethod = true;
+      return null;
+    }
+  }
+
+  visitMapTypeInformation(MapTypeInformation info) {
+    bailout('Stored in a map');
+  }
+
+  visitClosureCallSiteTypeInformation(ClosureCallSiteTypeInformation info) {
+    bailout('Passed to a closure');
+  }
+
+  visitStaticCallSiteTypeInformation(StaticCallSiteTypeInformation info) {
+    super.visitStaticCallSiteTypeInformation(info);
+    Element called = info.calledElement;
+    if (called.isForeign(compiler) && called.name == 'JS') {
+      bailout('Used in JS ${info.call}');
+    }
+  }
+
+  visitDynamicCallSiteTypeInformation(DynamicCallSiteTypeInformation info) {
+    super.visitDynamicCallSiteTypeInformation(info);
+    Selector selector = info.selector;
+    String selectorName = selector.name;
+    if (currentUser == info.receiver) {
+      if (!okSelectorsSet.contains(selectorName)) {
+        if (selector.isCall()) {
+          int positionalLength = info.arguments.positional.length;
+          if (selectorName == 'add') {
+            if (positionalLength == 1) {
+              assignments.add(info.arguments.positional[0]);
+            }
+          } else if (selectorName == 'insert') {
+            if (positionalLength == 2) {
+              assignments.add(info.arguments.positional[1]);
+            }
+          } else {
+            bailout('Used in a not-ok selector');
+            return;
+          }
+        } else if (selector.isIndexSet()) {
+          assignments.add(info.arguments.positional[1]);
+        } else if (!selector.isIndex()) {
+          bailout('Used in a not-ok selector');
+          return;
+        }
+      }
+      if (!doNotChangeLengthSelectorsSet.contains(selectorName)) {
+        callsGrowableMethod = true;
+      }
+      if (selectorName == 'length' && selector.isSetter()) {
+        callsGrowableMethod = true;
+        assignments.add(inferrer.types.nullType);
+      }
+    } else if (selector.isCall()
+               && !info.targets.every((element) => element.isFunction())) {
+      bailout('Passed to a closure');
+      return;
+    }
+  }
+}
diff --git a/sdk/lib/_internal/compiler/implementation/inferrer/node_tracer.dart b/sdk/lib/_internal/compiler/implementation/inferrer/node_tracer.dart
new file mode 100644
index 0000000..380a472
--- /dev/null
+++ b/sdk/lib/_internal/compiler/implementation/inferrer/node_tracer.dart
@@ -0,0 +1,235 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of type_graph_inferrer;
+
+// A set of selectors we know do not escape the elements inside the
+// list.
+Set<String> doesNotEscapeElementSet = new Set<String>.from(
+  const <String>[
+    // From Object.
+    '==',
+    'hashCode',
+    'toString',
+    'noSuchMethod',
+    'runtimeType',
+
+    // From Iterable.
+    'isEmpty',
+    'isNotEmpty',
+    'length',
+    'any',
+    'contains',
+    'every',
+    'join',
+
+    // From List.
+    'add',
+    'addAll',
+    'clear',
+    'fillRange',
+    'indexOf',
+    'insert',
+    'insertAll',
+    'lastIndexOf',
+    'remove',
+    'removeRange',
+    'replaceRange',
+    'setAll',
+    'setRange',
+    'shuffle',
+    '[]=',
+
+    // From JSArray.
+    'checkMutable',
+    'checkGrowable',
+  ]);
+
+abstract class TracerVisitor implements TypeInformationVisitor {
+  final TypeInformation tracedType;
+  final TypeGraphInferrerEngine inferrer;
+  final Compiler compiler;
+
+  static const int MAX_ANALYSIS_COUNT = 16;
+  final Setlet<Element> analyzedElements = new Setlet<Element>();
+
+  TracerVisitor(this.tracedType, inferrer)
+      : this.inferrer = inferrer, this.compiler = inferrer.compiler;
+
+  // Work list that gets populated with [TypeInformation] that could
+  // contain the container.
+  final List<TypeInformation> workList = <TypeInformation>[];
+
+  // Work list of containers to analyze after analyzing the users of a
+  // [TypeInformation] that may be [container]. We know [container]
+  // has been stored in these containers and we must check how
+  // [container] escapes from these containers.
+  final List<ListTypeInformation> containersToAnalyze =
+      <ListTypeInformation>[];
+
+  final Setlet<TypeInformation> flowsInto = new Setlet<TypeInformation>();
+
+  // The current [TypeInformation] in the analysis.
+  TypeInformation currentUser;
+  bool continueAnalyzing = true;
+
+  void addNewEscapeInformation(TypeInformation info) {
+    if (flowsInto.contains(info)) return;
+    flowsInto.add(info);
+    workList.add(info);
+  }
+
+  void analyze() {
+    // Collect the [TypeInformation] where the container can flow in,
+    // as well as the operations done on all these [TypeInformation]s.
+    addNewEscapeInformation(tracedType);
+    while (!workList.isEmpty) {
+      currentUser = workList.removeLast();
+      currentUser.users.forEach((TypeInformation info) {
+        analyzedElements.add(info.owner);
+        info.accept(this);
+      });
+      while (!containersToAnalyze.isEmpty) {
+        analyzeStoredIntoContainer(containersToAnalyze.removeLast());
+      }
+      if (!continueAnalyzing) break;
+      if (analyzedElements.length > MAX_ANALYSIS_COUNT) {
+        bailout('Too many users');
+        break;
+      }
+    }
+  }
+
+  void bailout(String reason) {
+    if (_VERBOSE) {
+      print('Bailing out on $tracedType because: $reason');
+    }
+    continueAnalyzing = false;
+  }
+
+  void visitNarrowTypeInformation(NarrowTypeInformation info) {
+    addNewEscapeInformation(info);
+  }
+
+  void visitPhiElementTypeInformation(PhiElementTypeInformation info) {
+    addNewEscapeInformation(info);
+  }
+
+  void visitElementInContainerTypeInformation(
+      ElementInContainerTypeInformation info) {
+    addNewEscapeInformation(info);
+  }
+
+  visitListTypeInformation(ListTypeInformation info) {
+    containersToAnalyze.add(info);
+  }
+
+  void visitConcreteTypeInformation(ConcreteTypeInformation info) {}
+
+  void visitClosureTypeInformation(ClosureTypeInformation info) {}
+
+  void visitClosureCallSiteTypeInformation(
+      ClosureCallSiteTypeInformation info) {}
+
+  visitStaticCallSiteTypeInformation(StaticCallSiteTypeInformation info) {
+    Element called = info.calledElement;
+    if (inferrer.types.getInferredTypeOf(called) == currentUser) {
+      addNewEscapeInformation(info);
+    }
+  }
+
+  void analyzeStoredIntoContainer(ListTypeInformation container) {
+    inferrer.analyzeContainer(container);
+    if (container.bailedOut) {
+      bailout('Stored in a container that bailed out');
+    } else {
+      container.flowsInto.forEach((flow) {
+        flow.users.forEach((user) {
+          if (user is !DynamicCallSiteTypeInformation) return;
+          if (user.receiver != flow) return;
+          if (returnsElementTypeSet.contains(user.selector)) {
+            addNewEscapeInformation(user);
+          } else if (!doesNotEscapeElementSet.contains(user.selector.name)) {
+            bailout('Escape from a container');
+          }
+        });
+      });
+    }
+  }
+
+  bool isAddedToContainer(DynamicCallSiteTypeInformation info) {
+    if (info.arguments == null) return false;
+    var receiverType = info.receiver.type;
+    if (!receiverType.isContainer) return false;
+    String selectorName = info.selector.name;
+    List<TypeInformation> arguments = info.arguments.positional;
+    return (selectorName == '[]=' && currentUser == arguments[1])
+        || (selectorName == 'insert' && currentUser == arguments[0])
+        || (selectorName == 'add' && currentUser == arguments[0]);
+  }
+
+  void visitDynamicCallSiteTypeInformation(
+      DynamicCallSiteTypeInformation info) {
+    if (isAddedToContainer(info)) {
+      ContainerTypeMask mask = info.receiver.type;
+      if (mask.allocationNode != null) {
+        ListTypeInformation container =
+            inferrer.types.allocatedLists[mask.allocationNode];
+        containersToAnalyze.add(container);
+      } else {
+        // The [ContainerTypeMask] is a union of two containers, and
+        // we lose track of where these containers have been allocated
+        // at this point.
+        bailout('Stored in too many containers');
+      }
+    }
+
+    Iterable<Element> inferredTargetTypes = info.targets.map((element) {
+      return inferrer.types.getInferredTypeOf(element);
+    });
+    if (inferredTargetTypes.any((user) => user == currentUser)) {
+      addNewEscapeInformation(info);
+    }
+  }
+
+  bool isParameterOfListAddingMethod(Element element) {
+    if (!element.isParameter()) return false;
+    if (element.getEnclosingClass() != compiler.backend.listImplementation) {
+      return false;
+    }
+    Element method = element.enclosingElement;
+    return (method.name == '[]=')
+        || (method.name == 'add')
+        || (method.name == 'insert');
+  }
+
+  bool isClosure(Element element) {
+    if (!element.isFunction()) return false;
+    Element outermost = element.getOutermostEnclosingMemberOrTopLevel();
+    return outermost.declaration != element.declaration;
+  }
+
+  void visitElementTypeInformation(ElementTypeInformation info) {
+    Element element = info.element;
+    if (element.isParameter()
+        && inferrer.isNativeElement(element.enclosingElement)) {
+      bailout('Passed to a native method');
+    }
+    if (info.isClosurized()) {
+      bailout('Returned from a closurized method');
+    }
+    if (isClosure(info.element)) {
+      bailout('Returned from a closure');
+    }
+    if (compiler.backend.isNeededForReflection(info.element)) {
+      bailout('Escape in reflection');
+    }
+    if (isParameterOfListAddingMethod(info.element)) {
+      // These elements are being handled in
+      // [visitDynamicCallSiteTypeInformation].
+      return;
+    }
+    addNewEscapeInformation(info);
+  }
+}
diff --git a/sdk/lib/_internal/compiler/implementation/inferrer/simple_types_inferrer.dart b/sdk/lib/_internal/compiler/implementation/inferrer/simple_types_inferrer.dart
index 29c46fa..b54ae28 100644
--- a/sdk/lib/_internal/compiler/implementation/inferrer/simple_types_inferrer.dart
+++ b/sdk/lib/_internal/compiler/implementation/inferrer/simple_types_inferrer.dart
@@ -111,6 +111,10 @@
     return type;
   }
 
+  TypeMask allocateClosure(Node node, Element element) {
+    return functionType;
+  }
+
   Selector newTypedSelector(TypeMask receiver, Selector selector) {
     return new TypedSelector(receiver, selector);
   }
@@ -566,10 +570,7 @@
 
     // Record the types of captured non-boxed variables. Types of
     // these variables may already be there, because of an analysis of
-    // a previous closure. Note that analyzing the same closure multiple
-    // times closure will refine the type of those variables, therefore
-    // [:inferrer.typeOf[variable]:] is not necessarilly null, nor the
-    // same as [newType].
+    // a previous closure.
     ClosureClassMap nestedClosureData =
         compiler.closureToClassMapper.getMappingForNestedFunction(node);
     nestedClosureData.forEachCapturedVariable((variable, field) {
@@ -584,7 +585,19 @@
       capturedVariables.add(variable);
     });
 
-    return types.functionType;
+    return inferrer.concreteTypes.putIfAbsent(node, () {
+      return types.allocateClosure(node, element);
+    });
+  }
+
+  T visitFunctionDeclaration(FunctionDeclaration node) {
+    Element element = elements[node];
+    T type = inferrer.concreteTypes.putIfAbsent(node.function, () {
+      return types.allocateClosure(node.function, element);
+    });
+    locals.update(element, type, node);
+    visit(node.function);
+    return type;
   }
 
   T visitLiteralList(LiteralList node) {
diff --git a/sdk/lib/_internal/compiler/implementation/inferrer/type_graph_inferrer.dart b/sdk/lib/_internal/compiler/implementation/inferrer/type_graph_inferrer.dart
index c31b2c0..6f17205 100644
--- a/sdk/lib/_internal/compiler/implementation/inferrer/type_graph_inferrer.dart
+++ b/sdk/lib/_internal/compiler/implementation/inferrer/type_graph_inferrer.dart
@@ -20,7 +20,11 @@
 import '../dart2jslib.dart' show invariant, Constant;
 
 part 'type_graph_nodes.dart';
-part 'container_tracer.dart';
+part 'closure_tracer.dart';
+part 'list_tracer.dart';
+part 'node_tracer.dart';
+
+bool _VERBOSE = false;
 
 /**
  * A set of selector names that [List] implements, that we know return
@@ -55,6 +59,10 @@
   final Map<Node, TypeInformation> allocatedLists =
       new Map<Node, TypeInformation>();
 
+  /// [ClosureTypeInformation] for allocated closures.
+  final Map<Node, TypeInformation> allocatedClosures =
+      new Map<Node, TypeInformation>();
+
   /// Cache of [ConcreteTypeInformation].
   final Map<TypeMask, TypeInformation> concreteTypes =
       new Map<TypeMask, TypeInformation>();
@@ -298,6 +306,11 @@
         new ListTypeInformation(mask, element, length);
   }
 
+  TypeInformation allocateClosure(Node node, Element element) {
+    return allocatedClosures[node] =
+        new ClosureTypeInformation(node, element);
+  }
+
   TypeInformation allocateMap(TypeInformation keyType,
                               TypeInformation valueType,
                               ConcreteTypeInformation type) {
@@ -406,12 +419,6 @@
  * [TypeInformation] nodes by visiting the AST of the application, and
  * then does the inferencing on the graph.
  *
- * The inferencing is currently done in three steps:
- *
- * 1) Compute the call graph.
- * 2) Refine all nodes in a way that avoids cycles.
- * 3) Refine all nodes.
- *
  */
 class TypeGraphInferrerEngine
     extends InferrerEngine<TypeInformation, TypeInformationSystem> {
@@ -437,7 +444,7 @@
   void analyzeContainer(ListTypeInformation info) {
     if (info.analyzed) return;
     info.analyzed = true;
-    ContainerTracerVisitor tracer = new ContainerTracerVisitor(info, this);
+    ListTracerVisitor tracer = new ListTracerVisitor(info, this);
     List<TypeInformation> newAssignments = tracer.run();
     if (newAssignments == null) {
       return;
@@ -479,6 +486,16 @@
       workQueue.add(info.elementType);
     });
 
+    types.allocatedClosures.values.forEach((ClosureTypeInformation info) {
+      ClosureTracerVisitor tracer = new ClosureTracerVisitor(info, this);
+      tracer.run();
+      if (!tracer.continueAnalyzing) return;
+      FunctionElement element = info.element;
+      element.functionSignature.forEachParameter((parameter) {
+        workQueue.add(types.getInferredTypeOf(parameter));
+      });
+    });
+
     // Reset all nodes that use lists that have been inferred, as well
     // as nodes that use elements fetched from these lists. The
     // workset for a new run of the analysis will be these nodes.
@@ -609,6 +626,7 @@
   void buildWorkQueue() {
     workQueue.addAll(types.typeInformations.values);
     workQueue.addAll(types.allocatedTypes);
+    workQueue.addAll(types.allocatedClosures.values);
     workQueue.addAll(allocatedCalls);
   }
 
@@ -621,7 +639,7 @@
                                   Element callee,
                                   ArgumentsTypes arguments,
                                   Selector selector,
-                                  {bool remove, bool init: false}) {
+                                  {bool remove, bool addToQueue: true}) {
     if (callee.name == Compiler.NO_SUCH_METHOD) return;
     if (callee.isField()) {
       if (selector.isSetter()) {
@@ -631,18 +649,22 @@
         } else {
           info.addAssignment(arguments.positional[0]);
         }
-        if (!init) workQueue.add(info);
+        if (addToQueue) workQueue.add(info);
       }
     } else if (callee.isGetter()) {
       return;
     } else if (selector != null && selector.isGetter()) {
-      if (!remove) {
+      ElementTypeInformation info = types.getInferredTypeOf(callee);
+      if (remove) {
+        info.closurizedCount--;
+      } else {
+        info.closurizedCount++;
         FunctionElement function = callee.implementation;
         FunctionSignature signature = function.computeSignature(compiler);
         signature.forEachParameter((Element parameter) {
           ElementTypeInformation info = types.getInferredTypeOf(parameter);
           info.giveUp(this);
-          if (!init) workQueue.addAll(info.users);
+          if (addToQueue) workQueue.addAll(info.users);
         });
       }
     } else {
@@ -669,7 +691,7 @@
           info.addAssignment(type);
         }
         parameterIndex++;
-        if (!init) workQueue.add(info);
+        if (addToQueue) workQueue.add(info);
       });
     }
   }
@@ -813,7 +835,7 @@
   }
 
   // Sorts the resolved elements by size. We do this for this inferrer
-  // to get the same results for [ContainerTracer] compared to the
+  // to get the same results for [ListTracer] compared to the
   // [SimpleTypesInferrer].
   Iterable<Element> sortResolvedElements() {
     int max = 0;
@@ -856,6 +878,7 @@
     types.typeInformations.values.forEach((info) => info.clear());
     types.allocatedTypes.clear();
     types.concreteTypes.clear();
+    types.allocatedClosures.clear();
     analyzedElements.clear();
     generativeConstructorsExposingThis.clear();
   }
diff --git a/sdk/lib/_internal/compiler/implementation/inferrer/type_graph_nodes.dart b/sdk/lib/_internal/compiler/implementation/inferrer/type_graph_nodes.dart
index 3f4dc37..fa0082a 100644
--- a/sdk/lib/_internal/compiler/implementation/inferrer/type_graph_nodes.dart
+++ b/sdk/lib/_internal/compiler/implementation/inferrer/type_graph_nodes.dart
@@ -92,13 +92,13 @@
     return type;
   }
 
-  void giveUp(TypeGraphInferrerEngine inferrer) {
+  void giveUp(TypeGraphInferrerEngine inferrer, {bool clearAssignments: true}) {
     abandonInferencing = true;
     type = inferrer.types.dynamicType.type;
     // Do not remove [this] as a user of nodes in [assignments],
     // because our tracing analysis could be interested in tracing
     // this node.
-    assignments = const <TypeInformation>[];
+    if (clearAssignments) assignments = const <TypeInformation>[];
     // Do not remove users because our tracing analysis could be
     // interested in tracing the users of this node.
   }
@@ -209,6 +209,16 @@
 class ElementTypeInformation extends TypeInformation {
   final Element element;
 
+  // Marker to disable [handleSpecialCases]. For example, parameters
+  // of closures that are traced can be inferred.
+  bool disableHandleSpecialCases = false;
+
+  /**
+   * If [element] is a function, [closurizedCount] is the number of
+   * times it is closurized. The value gets updated while infering.
+   */
+  int closurizedCount = 0;
+
   /**
    * This map contains the callers of [element]. It stores all unique call sites
    * to enable counting the global number of call sites of [element].
@@ -256,15 +266,19 @@
     return count == 1;
   }
 
+  bool isClosurized() => closurizedCount > 0;
+
   TypeMask handleSpecialCases(TypeGraphInferrerEngine inferrer) {
-    if (abandonInferencing) {
-      return type;
-    }
+    if (abandonInferencing) return type;
+    if (disableHandleSpecialCases) return null;
+
     if (element.isParameter()) {
       Element enclosing = element.enclosingElement;
       if (Elements.isLocal(enclosing)) {
-        // Do not infer types for parameters of closures.
-        giveUp(inferrer);
+        // Do not infer types for parameters of closures. We do not
+        // clear the assignments in case the closure is successfully
+        // traced.
+        giveUp(inferrer, clearAssignments: false);
         return type;
       } else if (enclosing.isInstanceMember()
                  && (enclosing.name == Compiler.NO_SUCH_METHOD
@@ -433,7 +447,8 @@
       arguments.forEach((info) => info.addUser(this));
     }
     inferrer.updateParameterAssignments(
-        this, calledElement, arguments, selector, remove: false, init: true);
+        this, calledElement, arguments, selector, remove: false,
+        addToQueue: false);
   }
 
   bool get isSynthesized {
@@ -502,7 +517,8 @@
       callee.addCall(caller, call);
       callee.addUser(this);
       inferrer.updateParameterAssignments(
-          this, element, arguments, typedSelector, remove: false, init: true);
+          this, element, arguments, typedSelector, remove: false,
+          addToQueue: false);
     }
   }
 
@@ -626,7 +642,8 @@
         callee.addCall(caller, call);
         callee.addUser(this);
         inferrer.updateParameterAssignments(
-            this, element, arguments, typedSelector, remove: false);
+            this, element, arguments, typedSelector, remove: false,
+            addToQueue: true);
       }
 
       // If [canReachAll] is true, then we are iterating over all
@@ -658,14 +675,15 @@
         callee.removeCall(caller, call);
         callee.removeUser(this);
         inferrer.updateParameterAssignments(
-            this, element, arguments, typedSelector, remove: true);
+            this, element, arguments, typedSelector, remove: true,
+            addToQueue: true);
       }
     });
 
     return newType;
   }
 
-  void giveUp(TypeGraphInferrerEngine inferrer) {
+  void giveUp(TypeGraphInferrerEngine inferrer, {bool clearAssignments: true}) {
     inferrer.updateSelectorInTree(caller, call, selector);
     Iterable<Element> oldTargets = targets;
     targets = inferrer.compiler.world.allFunctions.filter(selector);
@@ -675,10 +693,11 @@
             inferrer.types.getInferredTypeOf(element);
         callee.addCall(caller, call);
         inferrer.updateParameterAssignments(
-            this, element, arguments, selector, remove: false);
+            this, element, arguments, selector, remove: false,
+            addToQueue: true);
       }
     }
-    super.giveUp(inferrer);
+    super.giveUp(inferrer, clearAssignments: clearAssignments);
   }
 
   void removeAndClearReferences(TypeGraphInferrerEngine inferrer) {
@@ -720,6 +739,7 @@
 
   void addToGraph(TypeGraphInferrerEngine inferrer) {
     arguments.forEach((info) => info.addUser(this));
+    closure.addUser(this);
   }
 
   TypeMask refine(TypeGraphInferrerEngine inferrer) {
@@ -975,6 +995,27 @@
   }
 }
 
+class ClosureTypeInformation extends TypeInformation {
+  final Node node;
+  final Element element;
+
+  ClosureTypeInformation(this.node, this.element);
+
+  TypeMask refine(TypeGraphInferrerEngine inferrer) {
+    return inferrer.types.functionType.type;
+  }
+
+  String toString() => 'Closure $element';
+
+  accept(TypeInformationVisitor visitor) {
+    return visitor.visitClosureTypeInformation(this);
+  }
+
+  bool hasStableType(TypeGraphInferrerEngine inferrer) {
+    return false;
+  }
+}
+
 abstract class TypeInformationVisitor<T> {
   T visitNarrowTypeInformation(NarrowTypeInformation info);
   T visitPhiElementTypeInformation(PhiElementTypeInformation info);
@@ -987,4 +1028,5 @@
   T visitStaticCallSiteTypeInformation(StaticCallSiteTypeInformation info);
   T visitDynamicCallSiteTypeInformation(DynamicCallSiteTypeInformation info);
   T visitElementTypeInformation(ElementTypeInformation info);
+  T visitClosureTypeInformation(ClosureTypeInformation info);
 }
diff --git a/sdk/lib/_internal/compiler/implementation/ir/ir_builder.dart b/sdk/lib/_internal/compiler/implementation/ir/ir_builder.dart
index 0a747e5..925841e 100644
--- a/sdk/lib/_internal/compiler/implementation/ir/ir_builder.dart
+++ b/sdk/lib/_internal/compiler/implementation/ir/ir_builder.dart
@@ -83,6 +83,7 @@
             unlinkTreeAndToken(element);
           }
         }
+        ensureIr(element);
       });
     });
   }
@@ -114,15 +115,69 @@
     // TODO(lry): support native functions (also in [visitReturn]).
     if (function.isNative()) return false;
 
+    // Methods annotated @IrRepresentation(false).
+    if (enforceAstRepresentation(function)) return false;
+
     return true;
   }
 
+  bool get inCheckedMode {
+    bool result = false;
+    assert((result = true));
+    return result;
+  }
+
+  bool enforceAstRepresentation(Element element) {
+    return irRepresentationValue(element, false);
+  }
+
+  bool enforceIrRepresentation(Element element) {
+    return irRepresentationValue(element, true);
+  }
+
+  /**
+   * In host-checked mode, the @IrRepresentation annotation can be used to
+   * enforce the internal representation of a function.
+   */
+  bool irRepresentationValue(Element element, bool expected) {
+    if (!inCheckedMode || compiler.backend is !JavaScriptBackend) return false;
+    JavaScriptBackend backend = compiler.backend;
+    for (MetadataAnnotation metadata in element.metadata) {
+      if (metadata.value == null ||
+          !metadata.value.isConstructedObject()) {
+        continue;
+      }
+      ObjectConstant value = metadata.value;
+      ClassElement cls = value.type.element;
+      if (cls == backend.irRepresentationClass) {
+        ConstructedConstant classConstant = value;
+        BoolConstant constant = classConstant.fields[0];
+        return constant.value == expected;
+      }
+    }
+    return false;
+  }
+
+  void ensureIr(Element element) {
+    // If no IR was built for [element], ensure it is not annotated
+    // @IrRepresentation(true).
+    if (inCheckedMode &&
+        !compiler.irBuilder.hasIr(element) &&
+        enforceIrRepresentation(element)) {
+      compiler.reportFatalError(
+          element,
+          MessageKind.GENERIC,
+          {'text': "Error: cannot build IR for $element."});
+    }
+  }
+
   void unlinkTreeAndToken(element) {
-    // Ensure the funciton signature has been computed (requires the AST).
+    // Ensure the function signature has been computed (requires the AST).
     assert(element is !FunctionElementX || element.functionSignature != null);
-    element.beginToken.next = null;
-    // TODO(lry): Mark [element] so that parseNode will fail an assertion.
-    // element.cachedNode = null;
+    if (inCheckedMode) {
+      element.beginToken.next = null;
+      element.cachedNode = null;
+    }
   }
 
   SourceFile elementSourceFile(Element element) {
diff --git a/sdk/lib/_internal/compiler/implementation/ir/ir_nodes.dart b/sdk/lib/_internal/compiler/implementation/ir/ir_nodes.dart
index 1aeeca8..dfdadaf 100644
--- a/sdk/lib/_internal/compiler/implementation/ir/ir_nodes.dart
+++ b/sdk/lib/_internal/compiler/implementation/ir/ir_nodes.dart
@@ -94,6 +94,15 @@
   accept(IrNodesVisitor visitor) => visitor.visitIrInvokeStatic(this);
 }
 
+/**
+ * This class is only used during SSA generation, its instances never appear in
+ * the representation of a function. See [SsaFromAstInliner.enterInlinedMethod].
+ */
+class IrInlinedInvocationDummy extends IrExpression {
+  IrInlinedInvocationDummy() : super(0);
+  accept(IrNodesVisitor visitor) => throw "IrInlinedInvocationDummy.accept";
+}
+
 
 abstract class IrNodesVisitor<T> {
   T visit(IrNode node) => node.accept(this);
diff --git a/sdk/lib/_internal/compiler/implementation/ir/ir_pickler.dart b/sdk/lib/_internal/compiler/implementation/ir/ir_pickler.dart
index 317940c..bd79382 100644
--- a/sdk/lib/_internal/compiler/implementation/ir/ir_pickler.dart
+++ b/sdk/lib/_internal/compiler/implementation/ir/ir_pickler.dart
@@ -8,7 +8,8 @@
 import '../dart2jslib.dart' show
     Constant, FalseConstant, TrueConstant, IntConstant, DoubleConstant,
     StringConstant, NullConstant, ListConstant, MapConstant,
-    InterceptorConstant, FunctionConstant, TypeConstant, ConstructedConstant,
+    InterceptorConstant, DummyReceiverConstant, FunctionConstant, TypeConstant,
+    ConstructedConstant,
     ConstantVisitor, ConstantSystem,
     Compiler;
 import 'dart:typed_data' show ByteData, Endianness, Uint8List;
@@ -18,7 +19,7 @@
     ConsDartString;
 import '../elements/elements.dart' show
     Element, LibraryElement, FunctionElement;
-import '../universe/universe.dart' show Selector;
+import '../universe/universe.dart' show Selector, TypedSelector, SelectorKind;
 
 part 'ir_unpickler.dart';
 
@@ -36,8 +37,8 @@
  *                    int(namePosition) int(statements) {node(statement)}
  *              | byte(NODE_RETURN) position reference(value)
  *              | byte(NODE_CONST) position constant
- *              | byte(NODE_INVOKE_STATIC) position element int(arguments)
- *                    {reference(argument)}
+ *              | byte(NODE_INVOKE_STATIC) position element selector
+ *                    int(arguments) {reference(argument)}
  *
  * reference  ::= int(indexDelta)
  *
@@ -53,10 +54,17 @@
  *              | byte(CONST_STRING_CONS) constant(left) constant(right)
  *              | byte(CONST_NULL)
  *
+ * selector   ::= byte(BACKREFERENCE) reference
+ *              | byte(SELECTOR_UNTYPED) int(kind) string(name) element(library)
+ *                    int(argumentsCount) int(namedArgumentsCount)
+ *                    {string(parameterName)}
+ *
  * element    ::= int(constantPoolIndex)
  */
 class Pickles {
-  static const int STRING_ASCII = 1;
+  static const int BACKREFERENCE = 1;
+
+  static const int STRING_ASCII = BACKREFERENCE + 1;
   static const int STRING_UTF8  = STRING_ASCII + 1;
 
   static const int BEGIN_STATEMENT_NODE = STRING_UTF8 + 1;
@@ -85,11 +93,31 @@
   static const int CONST_NULL           = CONST_STRING_CONS + 1;
   static const int END_CONST            = CONST_NULL;
 
-  static const int END_TAG = END_CONST;
+  static const int BEGIN_SELECTOR   = END_CONST + 1;
+  static const int SELECTOR_UNTYPED = BEGIN_SELECTOR;
+  static const int END_SELECTOR     = SELECTOR_UNTYPED + 1;
+
+  static const int END_TAG = END_SELECTOR;
 
   static bool isExpressionTag(int tag) {
     return BEGIN_EXPRESSION_NODE <= tag && tag <= END_EXPRESSION_NODE;
   }
+
+  static final List<SelectorKind> selectorKindFromId = _selectorKindFromId();
+
+  static List<SelectorKind> _selectorKindFromId() {
+    List<SelectorKind> result = <SelectorKind>[
+        SelectorKind.GETTER,
+        SelectorKind.SETTER,
+        SelectorKind.CALL,
+        SelectorKind.OPERATOR,
+        SelectorKind.INDEX];
+    for (int i = 0; i < result.length; i++) {
+      assert(result[i].hashCode == i);
+    }
+    return result;
+  }
+
 }
 
 class IrConstantPool {
@@ -254,21 +282,21 @@
   }
 
   /**
-   * This function records [IrExpression] nodes in the [emitted] table. It
-   * needs to be invoked for each visited expression node to enable pickling
-   * back references to the node in [writeBackReference].
+   * This function records [entry] in the [emitted] table. It needs to be
+   * invoked when pickling an object which might later on be used in a back
+   * reference, for example expression nodes or selectors.
    */
-  void recordForBackReference(IrExpression entry) {
+  void recordForBackReference(Object entry) {
     assert(emitted[entry] == null);
     emitted[entry] = index++;
   }
 
-  void writeBackReference(IrExpression entry) {
+  void writeBackReference(Object entry) {
     int entryIndex = emitted[entry];
     writeInt(index - entryIndex);
   }
 
-  void writeBackReferenceList(List<IrExpression> entries) {
+  void writeBackReferenceList(List entries) {
     writeInt(entries.length);
     for (int i = 0; i < entries.length; i++) {
       writeBackReference(entries[i]);
@@ -335,7 +363,23 @@
   }
 
   void writeSelector(Selector selector) {
-    writeInt(constantPool.add(selector));
+    if (emitted.containsKey(selector)) {
+      writeByte(Pickles.BACKREFERENCE);
+      writeBackReference(selector);
+    } else {
+      recordForBackReference(selector);
+      assert(selector is !TypedSelector);
+      writeByte(Pickles.SELECTOR_UNTYPED);
+      writeInt(selector.kind.hashCode);
+      writeString(selector.name);
+      writeElement(selector.library);
+      writeInt(selector.argumentCount);
+      int namedArgumentsCount = selector.namedArguments.length;
+      writeInt(namedArgumentsCount);
+      for (int i = 0; i < namedArgumentsCount; i++) {
+        writeString(selector.namedArguments[i]);
+      }
+    }
   }
 
   void writeNodeList(List<IrNode> nodes) {
@@ -418,6 +462,7 @@
   void visitList(ListConstant constant) => abort(constant);
   void visitMap(MapConstant constant) => abort(constant);
   void visitInterceptor(InterceptorConstant constant) => abort(constant);
+  void visitDummyReceiver(DummyReceiverConstant constant) => abort(constant);
   void visitFunction(FunctionConstant constant) => abort(constant);
   void visitType(TypeConstant constant) => abort(constant);
   void visitConstructed(ConstructedConstant constant) => abort(constant);
diff --git a/sdk/lib/_internal/compiler/implementation/ir/ir_unpickler.dart b/sdk/lib/_internal/compiler/implementation/ir/ir_unpickler.dart
index 6f70d59..04190e6 100644
--- a/sdk/lib/_internal/compiler/implementation/ir/ir_unpickler.dart
+++ b/sdk/lib/_internal/compiler/implementation/ir/ir_unpickler.dart
@@ -35,7 +35,7 @@
     int numEntries = readInt();
     unpickled = new List<Object>(numEntries);
     index = 0;
-    return readEntry();
+    return readNode();
   }
 
   int readByte() {
@@ -77,18 +77,35 @@
   }
 
   Selector readSelector() {
-    int elementIndex = readInt();
-    return constantPool.get(elementIndex);
+    int tag = readByte();
+    if (tag == Pickles.BACKREFERENCE) {
+      return readBackReference();
+    }
+    assert(tag == Pickles.SELECTOR_UNTYPED);
+    int entryIndex = index++;
+    SelectorKind kind = Pickles.selectorKindFromId[readInt()];
+    String name = readString();
+    Element library = readElement();
+    int argumentsCount = readInt();
+    int namedArgumentsCount = readInt();
+    List<String> namedArguments = new List<String>(namedArgumentsCount);
+    for (int i = 0; i < namedArgumentsCount; i++) {
+      namedArguments[i] = readString();
+    }
+    Selector result = new Selector(
+        kind, name, library, argumentsCount, namedArguments);
+    unpickled[entryIndex] = result;
+    return result;
   }
 
   /**
-   * Read an entry that might be a back reference, or that might be used
-   * in a back reference.
+   * Reads a [IrNode]. Expression nodes are added to the [unpickled] map to
+   * enable unpickling back references.
    */
-  IrNode readEntry() {
+  IrNode readNode() {
     int tag = readByte();
     if (Pickles.isExpressionTag(tag)) {
-      return readExpressionEntry(tag);
+      return readExpressionNode(tag);
     } else if (tag == Pickles.NODE_RETURN) {
       return readReturnNode();
     } else {
@@ -96,7 +113,7 @@
     }
   }
 
-  IrExpression readExpressionEntry(int tag) {
+  IrExpression readExpressionNode(int tag) {
     int entryIndex = index++;
     IrExpression result;
     if (tag == Pickles.NODE_CONST) {
@@ -111,14 +128,14 @@
     return unpickled[entryIndex] = result;
   }
 
-  IrExpression readBackReference() {
+  Object readBackReference() {
     int indexDelta = readInt();
     int entryIndex = index - indexDelta;
     assert(unpickled[entryIndex] != null);
     return unpickled[entryIndex];
   }
 
-  List<IrExpression> readBackReferenceList() {
+  List<IrExpression> readExpressionBackReferenceList() {
     int length = readInt();
     List<IrExpression> result = new List<IrExpression>(length);
     for (int i = 0; i < length; i++) {
@@ -129,9 +146,9 @@
 
   List<IrNode> readNodeList() {
     int length = readInt();
-    List nodes = new List<IrNode>(length);
+    List<IrNode> nodes = new List<IrNode>(length);
     for (int i = 0; i < length; i++) {
-      nodes[i] = readEntry();
+      nodes[i] = readNode();
     }
     return nodes;
   }
@@ -160,7 +177,7 @@
     var position = readPosition();
     FunctionElement functionElement = readElement();
     Selector selector = readSelector();
-    List<IrExpression> arguments = readBackReferenceList();
+    List<IrExpression> arguments = readExpressionBackReferenceList();
     return new IrInvokeStatic(position, functionElement, selector, arguments);
   }
 
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart b/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart
index 9151b71..b9901e4 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart
@@ -107,6 +107,7 @@
   ClassElement noSideEffectsClass;
   ClassElement noThrowsClass;
   ClassElement noInlineClass;
+  ClassElement irRepresentationClass;
 
   Element getInterceptorMethod;
   Element interceptedNames;
@@ -164,11 +165,17 @@
    * know whether a send must be intercepted or not.
    */
   final Map<String, Set<Element>> interceptedElements;
-  // TODO(sra): Not all methods in the Set always require an interceptor.  A
-  // method may be mixed into a true interceptor *and* a plain class. For the
-  // method to work on the interceptor class it needs to use the explicit
-  // receiver.  This constrains the call on a known plain receiver to pass the
-  // explicit receiver.  https://code.google.com/p/dart/issues/detail?id=8942
+
+  /**
+   * The members of mixin classes that are mixed into an instantiated
+   * interceptor class.  This is a cached subset of [interceptedElements].
+   * These members must be invoked with a correct explicit receiver even when
+   * the receiver is not an intercepted class because the function uses the
+   * explicit interceptor parameter since it may be called on an intercepted
+   * class.
+   */
+  final Map<String, Set<Element>> interceptedMixinElements =
+      new Map<String, Set<Element>>();
 
   /**
    * A map of specialized versions of the [getInterceptorMethod].
@@ -367,6 +374,29 @@
     return interceptedElements[selector.name] != null;
   }
 
+  /**
+   * Returns `true` iff [selector] matches an element defined in a class mixed
+   * into an intercepted class.  These selectors are not eligible for the 'dummy
+   * explicit receiver' optimization.
+   */
+  bool isInterceptedMixinSelector(Selector selector) {
+    Set<Element> elements = interceptedMixinElements.putIfAbsent(
+        selector.name,
+        () {
+          Set<Element> elements = interceptedElements[selector.name];
+          if (elements == null) return null;
+          return elements
+              .where((element) =>
+                  classesMixedIntoNativeClasses.contains(
+                      element.getEnclosingClass()))
+              .toSet();
+        });
+
+    if (elements == null) return false;
+    if (elements.isEmpty) return false;
+    return elements.any((element) => selector.applies(element, compiler));
+  }
+
   final Map<String, Set<ClassElement>> interceptedClassesCache =
       new Map<String, Set<ClassElement>>();
 
@@ -521,6 +551,7 @@
     noSideEffectsClass = compiler.findHelper('NoSideEffects');
     noThrowsClass = compiler.findHelper('NoThrows');
     noInlineClass = compiler.findHelper('NoInline');
+    irRepresentationClass = compiler.findHelper('IrRepresentation');
   }
 
   void validateInterceptorImplementsAllObjectMethods(
@@ -1853,6 +1884,8 @@
 
   void visitInterceptor(InterceptorConstant constant) => copy(constant);
 
+  void visitDummyReceiver(DummyReceiverConstant constant) => copy(constant);
+
   void visitList(ListConstant constant) {
     copy(constant.entries);
     copy(constant);
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/constant_emitter.dart b/sdk/lib/_internal/compiler/implementation/js_backend/constant_emitter.dart
index c6ee2e5..c436744 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/constant_emitter.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/constant_emitter.dart
@@ -144,6 +144,10 @@
   jsAst.Expression visitInterceptor(InterceptorConstant constant) {
     return emitCanonicalVersion(constant);
   }
+
+  jsAst.Expression visitDummyReceiver(DummyReceiverConstant constant) {
+    return new jsAst.LiteralNumber('0');
+  }
 }
 
 /**
@@ -313,6 +317,10 @@
         'prototype');
   }
 
+  jsAst.Expression visitDummyReceiver(DummyReceiverConstant constant) {
+    return _reference(constant);
+  }
+
   jsAst.Expression visitConstructed(ConstructedConstant constant) {
     Element element = constant.type.element;
     if (element.isForeign(compiler)
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/namer.dart b/sdk/lib/_internal/compiler/implementation/js_backend/namer.dart
index 9b18a37..484fa22 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/namer.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/namer.dart
@@ -1181,6 +1181,10 @@
     addRoot(constant.dispatchedType.element.name);
     add('methods');
   }
+
+  visitDummyReceiver(DummyReceiverConstant constant) {
+    add('dummy_receiver');
+  }
 }
 
 /**
@@ -1258,6 +1262,11 @@
     return _hashString(5, typeName);
   }
 
+  visitDummyReceiver(DummyReceiverConstant constant) {
+    compiler.internalError(
+        'DummyReceiverConstant should never be named and never be subconstant');
+  }
+
   int _hashString(int hash, String s) {
     int length = s.length;
     hash = _combine(hash, length);
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/type_variable_handler.dart b/sdk/lib/_internal/compiler/implementation/js_backend/type_variable_handler.dart
index cae5491..5dc0126 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/type_variable_handler.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/type_variable_handler.dart
@@ -66,10 +66,10 @@
       InterfaceType typeVariableType = typeVariableClass.computeType(compiler);
       List<int> constants = <int>[];
       evaluator = new CompileTimeConstantEvaluator(
-          compiler.constantHandler, 
-          compiler.globalDependencies, 
+          compiler.constantHandler,
+          compiler.globalDependencies,
           compiler);
-      
+
       for (TypeVariableType currentTypeVariable in cls.typeVariables) {
         List<Constant> createArguments(FunctionElement constructor) {
         if (constructor != typeVariableConstructor) {
@@ -154,7 +154,8 @@
       return typeVariableConstants[variable];
     }
 
-    emitter.globalMetadata.add('Placeholder for ${variable}');
+    // TODO(15613): Remove quotes.
+    emitter.globalMetadata.add('"Placeholder for ${variable}"');
     return typeVariableConstants[variable] = emitter.globalMetadata.length - 1;
   }
 
diff --git a/sdk/lib/_internal/compiler/implementation/js_emitter/code_emitter_task.dart b/sdk/lib/_internal/compiler/implementation/js_emitter/code_emitter_task.dart
index 835a673..6b9a62c 100644
--- a/sdk/lib/_internal/compiler/implementation/js_emitter/code_emitter_task.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_emitter/code_emitter_task.dart
@@ -909,8 +909,9 @@
   }
 
   bool isConstantInlinedOrAlreadyEmitted(Constant constant) {
-    if (constant.isFunction()) return true;   // Already emitted.
-    if (constant.isPrimitive()) return true;  // Inlined.
+    if (constant.isFunction()) return true;       // Already emitted.
+    if (constant.isPrimitive()) return true;      // Inlined.
+    if (constant.isDummyReceiver()) return true;  // Inlined.
     // The name is null when the constant is already a JS constant.
     // TODO(floitsch): every constant should be registered, so that we can
     // share the ones that take up too much space (like some strings).
diff --git a/sdk/lib/_internal/compiler/implementation/js_emitter/type_test_emitter.dart b/sdk/lib/_internal/compiler/implementation/js_emitter/type_test_emitter.dart
index 92e4f63..076240a 100644
--- a/sdk/lib/_internal/compiler/implementation/js_emitter/type_test_emitter.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_emitter/type_test_emitter.dart
@@ -56,9 +56,14 @@
     void generateFunctionTypeSignature(Element method, FunctionType type) {
       assert(method.isImplementation);
       jsAst.Expression thisAccess = new jsAst.This();
-      Node node = method.parseNode(compiler);
-      ClosureClassMap closureData =
-          compiler.closureToClassMapper.closureMappingCache[node];
+      ClosureClassMap closureData;
+      // TODO(lry): Once the IR can express methods containing closures, find
+      // a way to get the [:thisName:]. The solution to this problem depends on
+      // how closures are represented in the IR, which is not yet decided.
+      if (!compiler.irBuilder.hasIr(method)) {
+        Node node = method.parseNode(compiler);
+        closureData = compiler.closureToClassMapper.closureMappingCache[node];
+      }
       if (closureData != null) {
         Element thisElement =
             closureData.freeVariableMapping[closureData.thisElement];
diff --git a/sdk/lib/_internal/compiler/implementation/native_handler.dart b/sdk/lib/_internal/compiler/implementation/native_handler.dart
index b4e8016..5a0d890 100644
--- a/sdk/lib/_internal/compiler/implementation/native_handler.dart
+++ b/sdk/lib/_internal/compiler/implementation/native_handler.dart
@@ -1047,10 +1047,10 @@
 
 final RegExp nativeRedirectionRegExp = new RegExp(r'^[a-zA-Z][a-zA-Z_$0-9]*$');
 
-void handleSsaNative(SsaBuilder builder, Expression nativeBody) {
+void handleSsaNative(SsaFromAstBuilder builder, Expression nativeBody) {
   Compiler compiler = builder.compiler;
   FunctionElement element = builder.work.element;
-  NativeEmitter nativeEmitter = builder.emitter.nativeEmitter;
+  NativeEmitter nativeEmitter = builder.nativeEmitter;
   JavaScriptBackend backend = builder.backend;
 
   HInstruction convertDartClosure(Element parameter, FunctionType type) {
diff --git a/sdk/lib/_internal/compiler/implementation/resolution/members.dart b/sdk/lib/_internal/compiler/implementation/resolution/members.dart
index 9f58576..a396889 100644
--- a/sdk/lib/_internal/compiler/implementation/resolution/members.dart
+++ b/sdk/lib/_internal/compiler/implementation/resolution/members.dart
@@ -1468,14 +1468,16 @@
     }
     FunctionElement result;
     bool resolvedSuper = false;
-    for (Link<Node> link = initializers;
-         !link.isEmpty;
-         link = link.tail) {
+    for (Link<Node> link = initializers; !link.isEmpty; link = link.tail) {
       if (link.head.asSendSet() != null) {
         final SendSet init = link.head.asSendSet();
         resolveFieldInitializer(constructor, init);
       } else if (link.head.asSend() != null) {
         final Send call = link.head.asSend();
+        if (call.argumentsNode == null) {
+          error(link.head, MessageKind.INVALID_INITIALIZER);
+          continue;
+        }
         if (Initializers.isSuperConstructorCall(call)) {
           if (resolvedSuper) {
             error(call, MessageKind.DUPLICATE_SUPER_INITIALIZER);
@@ -1533,7 +1535,7 @@
   /** Convenience method for visiting nodes that may be null. */
   R visit(Node node) => (node == null) ? null : node.accept(this);
 
-  void error(Node node, MessageKind kind, [Map arguments = const {}]) {
+  void error(Spannable node, MessageKind kind, [Map arguments = const {}]) {
     compiler.reportFatalError(node, kind, arguments);
   }
 
@@ -1551,10 +1553,6 @@
     compiler.internalError(message, node: node);
   }
 
-  void unimplemented(Node node, String message) {
-    compiler.unimplemented(message, node: node);
-  }
-
   void addDeferredAction(Element element, DeferredAction action) {
     compiler.enqueuer.resolution.addDeferredAction(element, action);
   }
@@ -2681,8 +2679,6 @@
       }
     }
 
-    // TODO(ngeoffray): Warn if target is null and the send is
-    // unqualified.
     useElement(node, target);
     registerSend(selector, target);
     if (node.isPropertyAccess && Elements.isStaticOrTopLevelFunction(target)) {
@@ -2736,14 +2732,21 @@
           compiler.backend.registerThrowNoSuchMethod(mapping);
         }
       } else if (target.impliesType()) {
+        setter = warnAndCreateErroneousElement(
+            node.selector, target.name, MessageKind.ASSIGNING_TYPE);
         compiler.backend.registerThrowNoSuchMethod(mapping);
       } else if (target.modifiers.isFinal() ||
                  target.modifiers.isConst() ||
                  (target.isFunction() &&
-                     Elements.isStaticOrTopLevelFunction(target) &&
-                     !target.isSetter())) {
-        setter = warnAndCreateErroneousElement(
-            node.selector, target.name, MessageKind.CANNOT_RESOLVE_SETTER);
+                  Elements.isStaticOrTopLevelFunction(target) && 
+                  !target.isSetter())) {
+        if (target.isFunction()) {
+          setter = warnAndCreateErroneousElement(
+              node.selector, target.name, MessageKind.ASSIGNING_METHOD);
+        } else {
+          setter = warnAndCreateErroneousElement(
+              node.selector, target.name, MessageKind.CANNOT_RESOLVE_SETTER);
+        }
         compiler.backend.registerThrowNoSuchMethod(mapping);
       }
       if (isPotentiallyMutableTarget(target)) {
@@ -2759,10 +2762,6 @@
 
     resolveArguments(node.argumentsNode);
 
-    // TODO(ngeoffray): Check if the target can be assigned.
-    // TODO(ngeoffray): Warn if target is null and the send is
-    // unqualified.
-
     Selector selector = mapping.getSelector(node);
     if (isComplex) {
       Selector getterSelector;
@@ -2870,7 +2869,7 @@
   }
 
   visitOperator(Operator node) {
-    unimplemented(node, 'operator');
+    internalError(node, 'operator');
   }
 
   visitRethrow(Rethrow node) {
@@ -3166,8 +3165,7 @@
   }
 
   visitModifiers(Modifiers node) {
-    // TODO(ngeoffray): Implement this.
-    unimplemented(node, 'modifiers');
+    internalError(node, 'modifiers');
   }
 
   visitLiteralList(LiteralList node) {
@@ -3503,8 +3501,8 @@
         mapping.remove(label.label);
       }
     });
-    // TODO(ngeoffray): We should check here instead of the SSA backend if
-    // there might be an error.
+    // TODO(15575): We should warn if we can detect a fall through
+    // error.
     compiler.backend.registerFallThroughError(mapping);
   }
 
@@ -3520,9 +3518,7 @@
   visitTryStatement(TryStatement node) {
     visit(node.tryBlock);
     if (node.catchBlocks.isEmpty && node.finallyBlock == null) {
-      // TODO(ngeoffray): The precise location is
-      // node.getEndtoken.next. Adjust when issue #1581 is fixed.
-      error(node, MessageKind.NO_CATCH_NOR_FINALLY);
+      error(node.getEndToken().next, MessageKind.NO_CATCH_NOR_FINALLY);
     }
     visit(node.catchBlocks);
     visit(node.finallyBlock);
@@ -3599,7 +3595,7 @@
   }
 
   visitTypedef(Typedef node) {
-    unimplemented(node, 'typedef');
+    internalError(node, 'typedef');
   }
 }
 
@@ -4642,10 +4638,9 @@
             resolver.enclosingElement.getLibrary());
   }
 
-  // TODO(ngeoffray): method named lookup should not report errors.
-  FunctionElement lookupConstructor(ClassElement cls,
-                                    Node diagnosticNode,
-                                    String constructorName) {
+  FunctionElement resolveConstructor(ClassElement cls,
+                                     Node diagnosticNode,
+                                     String constructorName) {
     cls.ensureResolved(compiler);
     Selector selector = createConstructorSelector(constructorName);
     Element result = cls.lookupConstructor(selector);
@@ -4689,7 +4684,7 @@
         ClassElement cls = element;
         cls.ensureResolved(compiler);
         // The unnamed constructor may not exist, so [e] may become unresolved.
-        element = lookupConstructor(cls, diagnosticNode, '');
+        element = resolveConstructor(cls, diagnosticNode, '');
       } else {
         element = failOrReturnErroneousElement(
             element, diagnosticNode, element.name, MessageKind.NOT_A_TYPE,
@@ -4726,7 +4721,7 @@
     if (element.isClass()) {
       ClassElement cls = element;
       cls.ensureResolved(compiler);
-      return lookupConstructor(cls, name, name.source);
+      return resolveConstructor(cls, name, name.source);
     } else if (element.isPrefix()) {
       PrefixElement prefix = element;
       element = prefix.lookupLocalMember(name.source);
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/builder.dart b/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
index 9bf573c..77d6903 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
@@ -35,8 +35,8 @@
       Element element = work.element.implementation;
       return compiler.withCurrentElement(element, () {
         HInstruction.idCounter = 0;
-        ConstantSystem constantSystem = compiler.backend.constantSystem;
-        SsaBuilder builder = new SsaBuilder(constantSystem, this, work);
+        SsaFromAstBuilder builder =
+            new SsaFromAstBuilder(backend, work, emitter.nativeEmitter);
         HGraph graph;
         ElementKind kind = element.kind;
         if (kind == ElementKind.GENERATIVE_CONSTRUCTOR) {
@@ -91,7 +91,7 @@
     });
   }
 
-  HGraph compileConstructor(SsaBuilder builder, CodegenWorkItem work) {
+  HGraph compileConstructor(SsaFromAstBuilder builder, CodegenWorkItem work) {
     return builder.buildFactory(work.element);
   }
 }
@@ -114,7 +114,7 @@
    */
   Map<Element, HInstruction> directLocals;
   Map<Element, Element> redirectionMapping;
-  SsaBuilder builder;
+  SsaFromAstMixin builder;
   ClosureClassMap closureData;
 
   LocalsHandler(this.builder)
@@ -672,7 +672,7 @@
 
 
 abstract class JumpHandler {
-  factory JumpHandler(SsaBuilder builder, TargetElement target) {
+  factory JumpHandler(SsaFromAstMixin builder, TargetElement target) {
     return new TargetJumpHandler(builder, target);
   }
   void generateBreak([LabelElement label]);
@@ -718,11 +718,11 @@
 // Continues in loops are implemented as breaks of the body.
 // Continues in switches is currently not handled.
 class TargetJumpHandler implements JumpHandler {
-  final SsaBuilder builder;
+  final SsaFromAstMixin builder;
   final TargetElement target;
   final List<JumpHandlerEntry> jumps;
 
-  TargetJumpHandler(SsaBuilder builder, this.target)
+  TargetJumpHandler(SsaFromAstMixin builder, this.target)
       : this.builder = builder,
         jumps = <JumpHandlerEntry>[] {
     assert(builder.jumpTargets[target] == null);
@@ -804,12 +804,12 @@
   /// switch case loop.
   final Map<TargetElement, int> targetIndexMap = new Map<TargetElement, int>();
 
-  SwitchCaseJumpHandler(SsaBuilder builder,
+  SwitchCaseJumpHandler(SsaFromAstMixin builder,
                         TargetElement target,
                         SwitchStatement node)
       : super(builder, target) {
     // The switch case indices must match those computed in
-    // [SsaBuilder.buildSwitchCaseConstants].
+    // [SsaFromAstMixin.buildSwitchCaseConstants].
     // Switch indices are 1-based so we can bypass the synthetic loop when no
     // cases match simply by branching on the index (which defaults to null).
     int switchIndex = 1;
@@ -834,7 +834,7 @@
     if (label == null) {
       // Creates a special break instruction for the synthetic loop generated
       // for a switch statement with continue statements. See
-      // [SsaBuilder.buildComplexSwitchStatement] for detail.
+      // [SsaFromAstMixin.buildComplexSwitchStatement] for detail.
 
       HInstruction breakInstruction =
           new HBreak(target, breakSwitchContinueLoop: true);
@@ -854,7 +854,7 @@
     if (isContinueToSwitchCase(label)) {
       // Creates the special instructions 'label = i; continue l;' used in
       // switch statements with continue statements. See
-      // [SsaBuilder.buildComplexSwitchStatement] for detail.
+      // [SsaFromAstMixin.buildComplexSwitchStatement] for detail.
 
       assert(label != null);
       HInstruction value = builder.graph.addConstantInt(
@@ -882,19 +882,60 @@
 }
 
 /**
- * This mixin implements functionality that is shared between the [SsaBuilder]
- * and the [SsaFromIrBuilder] classes.
+ * This mixin implements functionality that is shared between [SsaFromIrBuilder]
+ * and [SsaFromAstBuilder].
  *
  * The type parameter [N] represents the node type from which the SSA form is
  * built, either [IrNode] or [Node].
  *
- * This class does not define any fields because [SsaFromIrInliner], one of its
- * subclasses, is implemented using delegation and does not need fields. The two
- * other subclasses, [SsaBuilder] and [SsaFromIrBuilder], implement most of the
- * properties as fields. To avoid copy-pasting these definitions, the mixin
- * [SsaGraphBuilderFields] is inserted in between.
+ * The following diagram shows the mixin structure of the AST and IR builders
+ * and inliners, which is explained in the text below.
+ *
+ *                                 SsaBuilderMixin
+ *                     ___________/   |     |     \_________
+ *                    /               |     |               \
+ *     SsaBuilderDelegate            /       \            SsaBuilderFields
+ *       |     |                    /         \                  /     |
+ *       |     |        SsaFromAstMixin      SsaFromIrMixin     /      |
+ *       |      \    _____/    |       _____________|____\_____/       |
+ *       |       \__/__________|______/______       |     \______      |
+ *       |         /           |     /       \      |            \     |
+ * SsaFromAstInliner   SsaFromAstBuilder    SsaFromIrInliner   SsaFromIrBuilder
+ *
+ * The entry point to building an SSA graph is either an [SsaFromAstBuilder] or
+ * an [SsaFromIrBuilder]. These builder classes hold the [HGraph] data structure
+ * (inherited from [SsaBuilderFields]) into which blocks and instructions are
+ * inserted. The visitor methods for IR / AST nodes are defined in the
+ * [SsaFromIrMixin] / [SsaFromAstMixin] mixins.
+ *
+ * When inlining a function invocation of the same kind (SSA function in SSA
+ * builder, for example), the state of the builder pushed on the [inliningStack]
+ * and the same builder instance continues visiting the inlined function's body.
+ *
+ * When inlining a function of the other kind, the builder state is also pushed
+ * on the inlining stack, and an inliner instance is created.
+ *
+ * We consider inlining an IR function into an AST builder, which creates an
+ * [SsaFromIrInliner]. The IR inliner implements an IR visitor (defined in the
+ * [SsaFromIrMixin]) and inserts SSA instructions into the [HGraph] of the
+ * AST builder by delegation (inherited from the [SsaBuilderDelegate] mixin).
+ * When encountering the [:return:] instruction (inlining is only performed if
+ * there is exactly one), the IR inliner updates the [returnElement] field of
+ * the AST builder.
+ *
+ * In the opposite case (inlining an AST function into an IR builder), the AST
+ * inliner updates the [emitted] map of the IR builder with the return value.
+ *
+ * Finally, inlining can be nested. For example, we might start with an AST
+ * builder and inline an invocation of an IR function. The IR inliner will
+ * then again inline invocations of functions that are in either IR or AST.
+ *
+ * Note that [SsaBuilderMixin] does not define any fields because the inliner
+ * subclasses are implemented using delegation ([SsaBuilderDelegate]). The
+ * builder subclasses implement most of the properties as fields by extending
+ * [SsaBuilderFields].
  */
-abstract class SsaGraphBuilderMixin<N> {
+abstract class SsaBuilderMixin<N> {
   Compiler get compiler;
 
   JavaScriptBackend get backend;
@@ -934,6 +975,8 @@
    */
   bool get inThrowExpression;
 
+  void set inThrowExpression(bool value);
+
   /**
    * The loop nesting is consulted when inlining a function invocation in
    * [tryInlineMethod]. The inlining heuristics take this information into
@@ -941,6 +984,8 @@
    */
   int get loopNesting;
 
+  void set loopNesting(int value);
+
   List<InliningState> get inliningStack;
 
   /**
@@ -1031,16 +1076,16 @@
   }
 
   /**
-   * Prepares the state of the builder for inlining an invocaiton of [function].
+   * Returns a complete argument list for a call of [function].
    */
-  void enterInlinedMethod(FunctionElement function,
-                          Selector selector,
-                          List<HInstruction> providedArguments,
-                          N currentNode) {
+  List<HInstruction> completeSendArgumentsList(
+      FunctionElement function,
+      Selector selector,
+      List<HInstruction> providedArguments,
+      N currentNode) {
     assert(invariant(function, function.isImplementation));
     assert(providedArguments != null);
 
-    List<HInstruction> compiledArguments;
     bool isInstanceMember = function.isInstanceMember();
     // For static calls, [providedArguments] is complete, default arguments
     // have been included if necessary, see [addStaticSendArgumentsToList].
@@ -1050,12 +1095,11 @@
         || function.isGenerativeConstructorBody()
         || selector.isGetter()) {
       // For these cases, the provided argument list is known to be complete.
-      compiledArguments = providedArguments;
+      return providedArguments;
     } else {
-      compiledArguments = completeDynamicSendArgumentsList(
+      return completeDynamicSendArgumentsList(
           selector, function, providedArguments);
     }
-    setupInliningState(function, compiledArguments);
   }
 
   /**
@@ -1127,7 +1171,11 @@
     return compiledArguments;
   }
 
-  void setupInliningState(FunctionElement function,
+  /**
+   * Prepares the state of the builder for inlining an invocaiton of [function].
+   */
+  void enterInlinedMethod(FunctionElement function,
+                          N currentNode,
                           List<HInstruction> compiledArguments);
 
   void leaveInlinedMethod();
@@ -1265,10 +1313,15 @@
                           isAssignable: false),
             currentNode);
       }
-      enterInlinedMethod(function, selector, providedArguments, currentNode);
+      List<HInstruction> compiledArguments = completeSendArgumentsList(
+          function, selector, providedArguments, currentNode);
+      enterInlinedMethod(function, currentNode, compiledArguments);
       inlinedFrom(function, () {
-        potentiallyCheckInlinedParameterTypes(element);
-        doInline(function);
+        if (!isReachable) {
+          emitReturn(graph.addConstantNull(compiler), null);
+        } else {
+          doInline(function);
+        }
       });
       leaveInlinedMethod();
     }
@@ -1281,7 +1334,9 @@
     return false;
   }
 
-  void doInline(Element element);
+  void emitReturn(HInstruction value, N node);
+
+  void doInline(FunctionElement function);
 
   inlinedFrom(Element element, f()) {
     assert(element is FunctionElement || element is VariableElement);
@@ -1315,10 +1370,10 @@
 }
 
 /**
- * This class defines the abstract properties of [SsaGraphBuilderMixin] as
- * fields. It is shared between the [SsaBuilder] and the [SsaFromIrBuilder].
+ * This class defines the abstract properties of [SsaBuilderMixin] as fields.
+ * It is mixed into [SsaFromAstBuilder] and [SsaFromIrBuilder].
  */
-abstract class SsaGraphBuilderFields<N> implements SsaGraphBuilderMixin<N> {
+abstract class SsaBuilderFields<N> implements SsaBuilderMixin<N> {
   final HGraph graph = new HGraph();
 
   HBasicBlock _current;
@@ -1338,34 +1393,90 @@
 
   int loopNesting = 0;
 
-  final List<InliningState> inliningStack = <InliningState>[];
-
   final List<Element> sourceElementStack = <Element>[];
 }
 
-class SsaBuilder extends ResolvedVisitor
-    with SsaGraphBuilderMixin<Node>, SsaGraphBuilderFields<Node> {
-  final SsaBuilderTask builder;
-  final JavaScriptBackend backend;
-  final CodegenWorkItem work;
-  final ConstantSystem constantSystem;
+/**
+ * This class defines the abstract properties of [SsaBuilderMixin] by
+ * delegation to the [builder], which is either an [SsaFromAstBuilder] or an
+ * [SsaFromIrBuilder].
+ * It is mixed into [SsaFromAstInliner] and [SsaFromIrInliner].
+ */
+abstract class SsaBuilderDelegate<N, M> implements SsaBuilderMixin<N> {
+  SsaBuilderFields<M> get builder;
+
+  Compiler get compiler => builder.compiler;
+
+  JavaScriptBackend get backend => builder.backend;
+
+  Element get sourceElement => builder.sourceElementStack.last;
+
+  HGraph get graph => builder.graph;
+
+  HBasicBlock get current => builder.current;
+
+  void set current(HBasicBlock block) {
+    builder.current = block;
+  }
+
+  HBasicBlock get lastOpenedBlock => builder.lastOpenedBlock;
+
+  void set lastOpenedBlock(HBasicBlock block) {
+    builder.lastOpenedBlock = block;
+  }
+
+  bool get isReachable => builder.isReachable;
+
+  void set isReachable(bool value) {
+    builder.isReachable = value;
+  }
+
+  bool get inThrowExpression => builder.inThrowExpression;
+
+  void set inThrowExpression(bool value) {
+    builder.inThrowExpression = value;
+  }
+
+  int get loopNesting => builder.loopNesting;
+
+  void set loopNesting(int value) {
+    builder.loopNesting = value;
+  }
+
+  List<InliningState> get inliningStack => builder.inliningStack;
+
+  List<Element> get sourceElementStack => builder.sourceElementStack;
+}
+
+/**
+ * This class is a tree visitor which builds SSA nodes. It is mixed into
+ * [SsaFromAstBuilder] and [SsaFromAstInliner].
+ */
+abstract class SsaFromAstMixin
+    implements ResolvedVisitor, SsaBuilderMixin<Node> {
+  CodegenWorkItem get work;
+  ConstantSystem get constantSystem;
+  RuntimeTypes get rti;
+
   LocalsHandler localsHandler;
+
   HInstruction rethrowableException;
-  Map<Element, HInstruction> parameters;
-  final RuntimeTypes rti;
+
   HParameterValue lastAddedParameter;
 
-  Map<TargetElement, JumpHandler> jumpTargets;
+  Map<Element, HInstruction> parameters = <Element, HInstruction>{};
+
+  Map<TargetElement, JumpHandler> jumpTargets = <TargetElement, JumpHandler>{};
 
   /**
    * Variables stored in the current activation. These variables are
    * being updated in try/catch blocks, and should be
    * accessed indirectly through [HLocalGet] and [HLocalSet].
    */
-  Map<Element, HLocalValue> activationVariables;
+  Map<Element, HLocalValue> activationVariables = <Element, HLocalValue>{};
 
   // We build the Ssa graph by simulating a stack machine.
-  List<HInstruction> stack;
+  List<HInstruction> stack = <HInstruction>[];
 
   Element get currentNonClosureClass {
     ClassElement cls = sourceElement.getEnclosingClass();
@@ -1392,22 +1503,7 @@
   // types of the type variables in an environment (like the [LocalsHandler]).
   final List<DartType> currentInlinedInstantiations = <DartType>[];
 
-  Compiler get compiler => builder.compiler;
-  CodeEmitterTask get emitter => builder.emitter;
-
-  SsaBuilder(this.constantSystem, SsaBuilderTask builder, CodegenWorkItem work)
-    : this.builder = builder,
-      this.backend = builder.backend,
-      this.work = work,
-      stack = new List<HInstruction>(),
-      activationVariables = new Map<Element, HLocalValue>(),
-      jumpTargets = new Map<TargetElement, JumpHandler>(),
-      parameters = new Map<Element, HInstruction>(),
-      rti = builder.backend.rti,
-      super(work.resolutionTree, builder.compiler) {
-    localsHandler = new LocalsHandler(this);
-    sourceElementStack.add(work.element);
-  }
+  final List<AstInliningState> inliningStack = <AstInliningState>[];
 
   Element returnElement;
   DartType returnType;
@@ -1582,6 +1678,101 @@
     return result;
   }
 
+  /**
+   * This method sets up the local state of the builder for inlining [function].
+   * The arguments of the function are inserted into the [localsHandler].
+   *
+   * When inlining a function, [:return:] statements are not emitted as
+   * [HReturn] instructions. Instead, the value of a synthetic element is
+   * updated in the [localsHandler]. This function creates such an element and
+   * stores it in the [returnElement] field.
+   */
+  void setupStateForInlining(FunctionElement function,
+                             List<HInstruction> compiledArguments) {
+    bool hasIr = compiler.irBuilder.hasIr(function);
+    localsHandler = new LocalsHandler(this);
+    if (hasIr) {
+      // If the inlined function is in IR, the inliner will not use the locals
+      // handler of this class. However, it will use the [returnElement].
+      // When creating the [returnElement] (see below), the invocation of
+      // [updateLocal] requires [closureData] to be non-null.
+      localsHandler.closureData =
+          new ClosureClassMap(null, null, null, new ThisElement(function));
+    } else {
+      localsHandler.closureData =
+          compiler.closureToClassMapper.computeClosureToClassMapping(
+              function, function.parseNode(compiler), elements);
+    }
+    // TODO(kasperl): Bad smell. We shouldn't be constructing elements here.
+    returnElement = new VariableElementX.synthetic("result",
+        ElementKind.VARIABLE, function);
+    localsHandler.updateLocal(returnElement,
+        graph.addConstantNull(compiler));
+
+    // If the inlined function is in IR, the [SsaFromIrInliner] will use the
+    // the [returnElement]. The remaining state of this AST builder is not used
+    // and does need to be set up.
+    if (!hasIr) {
+      inTryStatement = false; // TODO(lry): why? Document.
+
+      int argumentIndex = 0;
+      if (function.isInstanceMember()) {
+        localsHandler.updateLocal(localsHandler.closureData.thisElement,
+            compiledArguments[argumentIndex++]);
+      }
+
+      FunctionSignature signature = function.computeSignature(compiler);
+      signature.orderedForEachParameter((Element parameter) {
+        HInstruction argument = compiledArguments[argumentIndex++];
+        localsHandler.updateLocal(parameter, argument);
+      });
+
+      ClassElement enclosing = function.getEnclosingClass();
+      if ((function.isConstructor() || function.isGenerativeConstructorBody())
+          && backend.classNeedsRti(enclosing)) {
+        enclosing.typeVariables.forEach((TypeVariableType typeVariable) {
+          HInstruction argument = compiledArguments[argumentIndex++];
+          localsHandler.updateLocal(typeVariable.element, argument);
+        });
+      }
+      assert(argumentIndex == compiledArguments.length);
+
+      elements = compiler.enqueuer.resolution.getCachedElements(function);
+      assert(elements != null);
+      returnType = signature.returnType;
+      stack = <HInstruction>[];
+    }
+  }
+
+  void restoreState(AstInliningState state) {
+    localsHandler = state.oldLocalsHandler;
+    returnElement = state.oldReturnElement;
+    if (state.irInliner == null) {
+      // These fields only need to be restored if the function that was inlined
+      // is in AST form, see [setupStateForInlining] above.
+      inTryStatement = state.inTryStatement;
+      elements = state.oldElements;
+      returnType = state.oldReturnType;
+      assert(stack.isEmpty);
+      stack = state.oldStack;
+    }
+  }
+
+  /**
+   * Run this builder on the body of the [function] to be inlined.
+   */
+  void visitInlinedFunction(FunctionElement function) {
+    assert(!compiler.irBuilder.hasIr(function));
+    potentiallyCheckInlinedParameterTypes(function);
+    if (function.isGenerativeConstructor()) {
+      buildFactory(function);
+    } else {
+      FunctionExpression functionNode = function.parseNode(compiler);
+      functionNode.body.accept(this);
+    }
+  }
+
+
   addInlinedInstantiation(DartType type) {
     if (type != null) {
       currentInlinedInstantiations.add(type);
@@ -1594,90 +1785,6 @@
     }
   }
 
-  void setupInliningState(FunctionElement function,
-                          List<HInstruction> compiledArguments) {
-    InliningState state = new InliningState(
-        function, returnElement, returnType, elements, stack,
-        localsHandler, inTryStatement);
-    inTryStatement = false; // TODO(lry): why? Document.
-    LocalsHandler newLocalsHandler = new LocalsHandler(this);
-    if (compiler.irBuilder.hasIr(function)) {
-      // TODO(lry): handle ir functions with nested closure definitions.
-      newLocalsHandler.closureData =
-          new ClosureClassMap(null, null, null, new ThisElement(function));
-    } else {
-      newLocalsHandler.closureData =
-          compiler.closureToClassMapper.computeClosureToClassMapping(
-              function, function.parseNode(compiler), elements);
-    }
-
-    int argumentIndex = 0;
-    if (function.isInstanceMember()) {
-      newLocalsHandler.updateLocal(newLocalsHandler.closureData.thisElement,
-                                   compiledArguments[argumentIndex++]);
-    }
-
-    FunctionSignature signature = function.computeSignature(compiler);
-    signature.orderedForEachParameter((Element parameter) {
-      HInstruction argument = compiledArguments[argumentIndex++];
-      newLocalsHandler.updateLocal(parameter, argument);
-    });
-
-    ClassElement enclosing = function.getEnclosingClass();
-    if ((function.isConstructor() || function.isGenerativeConstructorBody())
-        && backend.classNeedsRti(enclosing)) {
-      enclosing.typeVariables.forEach((TypeVariableType typeVariable) {
-        HInstruction argument = compiledArguments[argumentIndex++];
-        newLocalsHandler.updateLocal(typeVariable.element, argument);
-      });
-    }
-    assert(argumentIndex == compiledArguments.length);
-
-    // TODO(kasperl): Bad smell. We shouldn't be constructing elements here.
-    returnElement = new VariableElementX.synthetic("result",
-        ElementKind.VARIABLE, function);
-    newLocalsHandler.updateLocal(returnElement,
-                                 graph.addConstantNull(compiler));
-    elements = compiler.enqueuer.resolution.getCachedElements(function);
-    assert(elements != null);
-    returnType = signature.returnType;
-    stack = <HInstruction>[];
-    inliningStack.add(state);
-    localsHandler = newLocalsHandler;
-  }
-
-  void leaveInlinedMethod() {
-    InliningState state = inliningStack.removeLast();
-    elements = state.oldElements;
-    stack.add(localsHandler.readLocal(returnElement));
-    returnElement = state.oldReturnElement;
-    returnType = state.oldReturnType;
-    assert(stack.length == 1);
-    state.oldStack.add(stack[0]);
-    stack = state.oldStack;
-    localsHandler = state.oldLocalsHandler;
-    inTryStatement = state.inTryStatement;
-  }
-
-  void doInline(FunctionElement function) {
-    if (function.isGenerativeConstructor()) {
-      // TODO(lry): inline constructors in IR.
-      assert(!compiler.irBuilder.hasIr(function));
-      buildFactory(function);
-    } else if (compiler.irBuilder.hasIr(function)) {
-      IrFunction irFunction = compiler.irBuilder.getIr(function);
-      SsaFromIrInliner irInliner = new SsaFromIrInliner(this);
-      irInliner.visitAll(irFunction.statements);
-      // The [IrInliner] does not push the final instruction on the [stack].
-      // In a way, this violates the invariant of the [SsaBuilder], however
-      // it works just fine because [leaveInlinedMethod] will restore the
-      // stack of the callee and push the value of the [returnElement].
-    } else {
-      FunctionExpression functionNode = function.parseNode(compiler);
-      functionNode.body.accept(this);
-    }
-  }
-
   bool providedArgumentsKnownToBeComplete(Node currentNode) {
     /* When inlining the iterator methods generated for a [:for-in:] loop, the
      * [currentNode] is the [ForIn] tree. The compiler-generated iterator
@@ -2884,7 +2991,7 @@
     if (node.isThis()) {
       stack.add(localsHandler.readThis());
     } else {
-      compiler.internalError("SsaBuilder.visitIdentifier on non-this",
+      compiler.internalError("SsaFromAstMixin.visitIdentifier on non-this",
                              node: node);
     }
   }
@@ -2999,14 +3106,18 @@
         value = compiler.constantHandler.getConstantForVariable(element);
       }
       if (value != null) {
-        HInstruction instruction = graph.addConstant(value, compiler);
+        HConstant instruction = graph.addConstant(value, compiler);
         stack.add(instruction);
         // The inferrer may have found a better type than the constant
         // handler in the case of lists, because the constant handler
         // does not look at elements in the list.
         TypeMask type =
             TypeMaskFactory.inferredTypeForElement(element, compiler);
-        if (!type.containsAll(compiler)) instruction.instructionType = type;
+        if (!type.containsAll(compiler) && !instruction.isConstantNull()) {
+          // TODO(13429): The inferrer should know that an element
+          // cannot be null.
+          instruction.instructionType = type.nonNullable();
+        }
       } else if (element.isField() && isLazilyInitialized(element)) {
         HInstruction instruction = new HLazyStatic(
             element,
@@ -3686,14 +3797,6 @@
     push(buildInvokeSuper(compiler.noSuchMethodSelector, element, inputs));
   }
 
-  visitSend(Send node) {
-    Element element = elements[node];
-    if (element != null && identical(element, sourceElement)) {
-      graph.isRecursiveMethod = true;
-    }
-    super.visitSend(node);
-  }
-
   visitSuperSend(Send node) {
     Selector selector = elements.getSelector(node);
     Element element = elements[node];
@@ -3737,7 +3840,7 @@
 
     Set<ClassElement> subclasses = compiler.world.subclassesOf(cls);
     return subclasses != null && subclasses.any((ClassElement subclass) {
-      return !backend.rti.isTrivialSubstitution(subclass, cls);
+      return !rti.isTrivialSubstitution(subclass, cls);
     });
   }
 
@@ -3896,6 +3999,11 @@
         typeInfoSetterElement,
         <HInstruction>[newObject, typeInfo],
         backend.dynamicType);
+
+    // The new object will now be referenced through the
+    // `setRuntimeTypeInfo` call. We therefore set the type of that
+    // instruction to be of the object's type.
+    assert(stack.last is HInvokeStatic || stack.last == newObject);
     stack.last.instructionType = newObject.instructionType;
     return pop();
   }
@@ -4230,7 +4338,7 @@
     generateGetter(node, elements[node]);
   }
 
-  // TODO(antonm): migrate rest of SsaBuilder to internalError.
+  // TODO(antonm): migrate rest of SsaFromAstMixin to internalError.
   internalError(String reason, {Node node}) {
     compiler.internalError(reason, node: node);
   }
@@ -4609,12 +4717,19 @@
 
       // [receiver] is only used if the node is an instance send.
       HInstruction receiver = null;
-      if (Elements.isInstanceSend(node, elements)) {
+      Element getter = elements[node.selector];
+
+      if (!Elements.isUnresolved(getter) && getter.impliesType()) {
+        Identifier selector = node.selector;
+        generateThrowNoSuchMethod(node, selector.source,
+                                  argumentNodes: node.arguments);
+        return;
+      } else if (Elements.isInstanceSend(node, elements)) {
         receiver = generateInstanceSendReceiver(node);
         generateInstanceGetterWithCompiledReceiver(
             node, elements.getGetterSelectorInComplexSendSet(node), receiver);
       } else {
-        generateGetter(node, elements[node.selector]);
+        generateGetter(node, getter);
       }
       HInstruction getterInstruction = pop();
       handleComplexOperatorSend(node, getterInstruction, node.arguments);
@@ -4768,12 +4883,7 @@
     }
 
     handleInTryStatement();
-
-    if (!inliningStack.isEmpty) {
-      localsHandler.updateLocal(returnElement, value);
-    } else {
-      closeAndGotoExit(attachPosition(new HReturn(value), node));
-    }
+    emitReturn(value, node);
   }
 
   visitThrow(Throw node) {
@@ -4869,7 +4979,7 @@
   }
 
   visitModifiers(Modifiers node) {
-    compiler.unimplemented('SsaBuilder.visitModifiers', node: node);
+    compiler.unimplemented('SsaFromAstMixin.visitModifiers', node: node);
   }
 
   visitBreakStatement(BreakStatement node) {
@@ -4977,7 +5087,7 @@
   }
 
   visitLabel(Label node) {
-    compiler.internalError('SsaBuilder.visitLabel', node: node);
+    compiler.internalError('SsaFromAstMixin.visitLabel', node: node);
   }
 
   visitLabeledStatement(LabeledStatement node) {
@@ -5407,11 +5517,11 @@
   }
 
   visitSwitchCase(SwitchCase node) {
-    compiler.internalError('SsaBuilder.visitSwitchCase');
+    compiler.internalError('SsaFromAstMixin.visitSwitchCase');
   }
 
   visitCaseMatch(CaseMatch node) {
-    compiler.internalError('SsaBuilder.visitCaseMatch');
+    compiler.internalError('SsaFromAstMixin.visitCaseMatch');
   }
 
   visitTryStatement(TryStatement node) {
@@ -5611,11 +5721,157 @@
   }
 
   visitTypedef(Typedef node) {
-    compiler.unimplemented('SsaBuilder.visitTypedef', node: node);
+    compiler.unimplemented('SsaFromAstMixin.visitTypedef', node: node);
   }
 
   visitTypeVariable(TypeVariable node) {
-    compiler.internalError('SsaBuilder.visitTypeVariable');
+    compiler.internalError('SsaFromAstMixin.visitTypeVariable');
+  }
+}
+
+/**
+ * This class builds SSA nodes for functions represented in AST.
+ */
+class SsaFromAstBuilder extends ResolvedVisitor with
+    SsaBuilderMixin<Node>,
+    SsaFromAstMixin,
+    SsaBuilderFields<Node> {
+  final Compiler compiler;
+  final JavaScriptBackend backend;
+  final ConstantSystem constantSystem;
+  final CodegenWorkItem work;
+  final RuntimeTypes rti;
+
+  /* This field is used by the native handler. */
+  final NativeEmitter nativeEmitter;
+
+  SsaFromAstBuilder(JavaScriptBackend backend,
+                    CodegenWorkItem work,
+                    this.nativeEmitter)
+    : this.backend = backend,
+      this.compiler = backend.compiler,
+      this.constantSystem = backend.constantSystem,
+      this.work = work,
+      this.rti = backend.rti,
+      super(work.resolutionTree, backend.compiler) {
+    localsHandler = new LocalsHandler(this);
+    sourceElementStack.add(work.element);
+  }
+
+  /**
+   * This method is invoked before inlining the body of [function] into this
+   * [SsaFromAstBuilder]. The inlined function can be either in AST or IR.
+   *
+   * The method is also invoked from the [SsaFromIrInliner], that is, if we
+   * are currently inlining an IR function and encounter a function invocation
+   * that should be inlined.
+   */
+  void enterInlinedMethod(FunctionElement function,
+                          Node _,
+                          List<HInstruction> compiledArguments) {
+    SsaFromIrInliner irInliner;
+    if (compiler.irBuilder.hasIr(function)) {
+      irInliner = new SsaFromIrInliner(this, function, compiledArguments);
+    }
+    AstInliningState state = new AstInliningState(
+        function, returnElement, returnType, elements, stack, localsHandler,
+        inTryStatement, irInliner);
+    inliningStack.add(state);
+
+    // Setting up the state of the (AST) builder is performed even when the
+    // inlined function is in IR, because the irInliner uses the [returnElement]
+    // of the AST builder.
+    setupStateForInlining(function, compiledArguments);
+  }
+
+  void leaveInlinedMethod() {
+    HInstruction result = localsHandler.readLocal(returnElement);
+    AstInliningState state = inliningStack.removeLast();
+    restoreState(state);
+    stack.add(result);
+  }
+
+  void doInline(FunctionElement function) {
+    if (compiler.irBuilder.hasIr(function)) {
+      AstInliningState state = inliningStack.last;
+      state.irInliner.visitInlinedFunction(function);
+    } else {
+      visitInlinedFunction(function);
+    }
+  }
+
+  void emitReturn(HInstruction value, Node node) {
+    if (inliningStack.isEmpty) {
+      closeAndGotoExit(attachPosition(new HReturn(value), node));
+    } else {
+      localsHandler.updateLocal(returnElement, value);
+    }
+  }
+}
+
+/**
+ * This class inlines an AST function into an [SsaFromIrBuilder].
+ */
+class SsaFromAstInliner extends ResolvedVisitor with
+    SsaBuilderMixin<Node>,
+    SsaFromAstMixin,
+    SsaBuilderDelegate<Node, IrNode> {
+  final SsaFromIrBuilder builder;
+
+  SsaFromAstInliner.internal(SsaFromIrBuilder builder)
+    : this.builder = builder,
+      super(builder.work.resolutionTree, builder.compiler);
+
+  factory SsaFromAstInliner(SsaFromIrBuilder builder,
+                            FunctionElement function,
+                            List<HInstruction> compiledArguments) {
+    SsaFromAstInliner result = new SsaFromAstInliner.internal(builder);
+    result.setupStateForInlining(function, compiledArguments);
+    return result;
+  }
+
+  ConstantSystem get constantSystem => builder.backend.constantSystem;
+  RuntimeTypes get rti => builder.backend.rti;
+  CodegenWorkItem get work => builder.work;
+
+  void emitReturn(HInstruction value, Node node) {
+    IrInliningState state = inliningStack.last;
+    builder.emitted[state.invokeNode] = value;
+  }
+
+  void enterInlinedMethod(FunctionElement function,
+                          Node currentNode,
+                          List<HInstruction> compiledArguments) {
+    // At this point we are inside the [SsaFromAstInliner] (inlining an AST
+    // function into an IR builder), and we encounter a function invocation that
+    // should be inlined.
+    // When inlining into an IR builder (which is what we are doing here), the
+    // returned value is stored in the builder's [emitted] map using the
+    // function invocation's IrNode as key.
+    // Since we are currently inlining an AST function, the invocation node is
+    // an AST node. A synthetic [IrInlinedInvocationDummy] is added to the
+    // [emitted] map to hold the result of the inlined function.
+    IrNode invokeNode = new IrInlinedInvocationDummy();
+    builder.enterInlinedMethod(function, invokeNode, compiledArguments);
+  }
+
+  void leaveInlinedMethod() {
+    IrInliningState state = inliningStack.last;
+    assert(state.invokeNode is IrInlinedInvocationDummy);
+    HInstruction result = builder.emitted.remove(state.invokeNode);
+    if (result == null) {
+      // When the inlined function is in AST form, it might not have an explicit
+      // [:return:] statement, and the result value might be undefined.
+      assert(!compiler.irBuilder.hasIr(state.function));
+      result = graph.addConstantNull(compiler);
+    }
+    assert(result != null);
+    stack.add(result);
+    builder.leaveInlinedMethod();
+  }
+
+  void doInline(FunctionElement function) {
+    builder.doInline(function);
   }
 }
 
@@ -5627,7 +5883,7 @@
  * expressions as well.
  */
 class StringBuilderVisitor extends Visitor {
-  final SsaBuilder builder;
+  final SsaFromAstMixin builder;
   final Node diagnosticNode;
 
   /**
@@ -5784,29 +6040,42 @@
   }
 }
 
-class InliningState {
+abstract class InliningState {
   /**
-   * Documentation wanted -- johnniwinther
-   *
    * Invariant: [function] must be an implementation element.
    */
   final FunctionElement function;
+
+  InliningState(this.function) {
+    assert(function.isImplementation);
+  }
+}
+
+class AstInliningState extends InliningState {
   final Element oldReturnElement;
   final DartType oldReturnType;
   final TreeElements oldElements;
   final List<HInstruction> oldStack;
   final LocalsHandler oldLocalsHandler;
   final bool inTryStatement;
+  final SsaFromIrInliner irInliner;
 
-  InliningState(this.function,
-                this.oldReturnElement,
-                this.oldReturnType,
-                this.oldElements,
-                this.oldStack,
-                this.oldLocalsHandler,
-                this.inTryStatement) {
-    assert(function.isImplementation);
-  }
+  AstInliningState(FunctionElement function,
+                   this.oldReturnElement,
+                   this.oldReturnType,
+                   this.oldElements,
+                   this.oldStack,
+                   this.oldLocalsHandler,
+                   this.inTryStatement,
+                   this.irInliner): super(function);
+}
+
+class IrInliningState extends InliningState {
+  final IrNode invokeNode;
+  final SsaFromAstInliner astInliner;
+
+  IrInliningState(FunctionElement function, this.invokeNode, this.astInliner)
+    : super(function);
 }
 
 class SsaBranch {
@@ -5820,7 +6089,7 @@
 }
 
 class SsaBranchBuilder {
-  final SsaBuilder builder;
+  final SsaFromAstMixin builder;
   final Node diagnosticNode;
 
   SsaBranchBuilder(this.builder, [this.diagnosticNode]);
@@ -6048,18 +6317,18 @@
   }
 }
 
-class TypeBuilder implements DartTypeVisitor<dynamic, SsaBuilder> {
+class TypeBuilder implements DartTypeVisitor<dynamic, SsaFromAstMixin> {
   void visitType(DartType type, _) {
     throw 'Internal error $type';
   }
 
-  void visitVoidType(VoidType type, SsaBuilder builder) {
+  void visitVoidType(VoidType type, SsaFromAstMixin builder) {
     ClassElement cls = builder.compiler.findHelper('VoidRuntimeType');
     builder.push(new HVoidType(type, new TypeMask.exact(cls)));
   }
 
   void visitTypeVariableType(TypeVariableType type,
-                             SsaBuilder builder) {
+                             SsaFromAstMixin builder) {
     ClassElement cls = builder.compiler.findHelper('RuntimeType');
     TypeMask instructionType = new TypeMask.subclass(cls);
     if (!builder.sourceElement.enclosingElement.isClosure() &&
@@ -6073,7 +6342,7 @@
     }
   }
 
-  void visitFunctionType(FunctionType type, SsaBuilder builder) {
+  void visitFunctionType(FunctionType type, SsaFromAstMixin builder) {
     type.returnType.accept(this, builder);
     HInstruction returnType = builder.pop();
     List<HInstruction> inputs = <HInstruction>[returnType];
@@ -6102,19 +6371,19 @@
     builder.push(new HFunctionType(inputs, type, new TypeMask.exact(cls)));
   }
 
-  void visitMalformedType(MalformedType type, SsaBuilder builder) {
+  void visitMalformedType(MalformedType type, SsaFromAstMixin builder) {
     visitDynamicType(builder.compiler.types.dynamicType, builder);
   }
 
-  void visitStatementType(StatementType type, SsaBuilder builder) {
+  void visitStatementType(StatementType type, SsaFromAstMixin builder) {
     throw 'not implemented visitStatementType($type)';
   }
 
-  void visitGenericType(GenericType type, SsaBuilder builder) {
+  void visitGenericType(GenericType type, SsaFromAstMixin builder) {
     throw 'not implemented visitGenericType($type)';
   }
 
-  void visitInterfaceType(InterfaceType type, SsaBuilder builder) {
+  void visitInterfaceType(InterfaceType type, SsaFromAstMixin builder) {
     List<HInstruction> inputs = <HInstruction>[];
     for (DartType typeArgument in type.typeArguments) {
       typeArgument.accept(this, builder);
@@ -6129,13 +6398,13 @@
     builder.push(new HInterfaceType(inputs, type, new TypeMask.exact(cls)));
   }
 
-  void visitTypedefType(TypedefType type, SsaBuilder builder) {
+  void visitTypedefType(TypedefType type, SsaFromAstMixin builder) {
     DartType unaliased = type.unalias(builder.compiler);
     if (unaliased is TypedefType) throw 'unable to unalias $type';
     unaliased.accept(this, builder);
   }
 
-  void visitDynamicType(DynamicType type, SsaBuilder builder) {
+  void visitDynamicType(DynamicType type, SsaFromAstMixin builder) {
     ClassElement cls = builder.compiler.findHelper('DynamicRuntimeType');
     builder.push(new HDynamicType(type, new TypeMask.exact(cls)));
   }
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/from_ir_builder.dart b/sdk/lib/_internal/compiler/implementation/ssa/from_ir_builder.dart
index 84b6a6c..f5aa966 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/from_ir_builder.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/from_ir_builder.dart
@@ -16,9 +16,8 @@
       Element element = work.element.implementation;
       return compiler.withCurrentElement(element, () {
         HInstruction.idCounter = 0;
-
-        SsaFromIrBuilder builder = new SsaFromIrBuilder(backend, work);
-
+        SsaFromIrBuilder builder =
+            new SsaFromIrBuilder(backend, work, backend.emitter.nativeEmitter);
         HGraph graph;
         ElementKind kind = element.kind;
         if (kind == ElementKind.GENERATIVE_CONSTRUCTOR) {
@@ -50,7 +49,8 @@
  * This class contains code that is shared between [SsaFromIrBuilder] and
  * [SsaFromIrInliner].
  */
-abstract class SsaFromIrMixin implements SsaGraphBuilderMixin<IrNode> {
+abstract class SsaFromIrMixin
+    implements IrNodesVisitor, SsaBuilderMixin<IrNode> {
   /**
    * Maps IR expressions to the generated [HInstruction]. Because the IR is
    * in an SSA form, the arguments of an [IrNode] have already been visited
@@ -60,13 +60,30 @@
   final Map<IrExpression, HInstruction> emitted =
       new Map<IrExpression, HInstruction>();
 
-  Compiler get compiler;
+  /**
+   * This method sets up the state of the IR visitor for inlining an invocation
+   * of [function].
+   */
+  void setupStateForInlining(FunctionElement function,
+                             List<HInstruction> compiledArguments) {
+    // TODO(lry): once the IR supports functions with parameters or dynamic
+    // invocations, map the parameters (and [:this:]) to the argument
+    // instructions by extending the [emitted] mapping.
+    assert(function.computeSignature(compiler).parameterCount == 0);
+  }
 
-  void emitReturn(HInstruction value, IrReturn node);
+  /**
+   * Run this builder on the body of the [function] to be inlined.
+   */
+  void visitInlinedFunction(FunctionElement function) {
+    assert(compiler.irBuilder.hasIr(function));
+    potentiallyCheckInlinedParameterTypes(function);
+    IrFunction functionNode = compiler.irBuilder.getIr(function);
+    visitAll(functionNode.statements);
+  }
 
-  HInstruction addExpression(IrExpression irNode, HInstruction ssaNode) {
+  void addExpression(IrExpression irNode, HInstruction ssaNode) {
     current.add(emitted[irNode] = ssaNode);
-    return ssaNode;
   }
 
   HInstruction attachPosition(HInstruction target, IrNode node) {
@@ -88,7 +105,7 @@
   }
 
   bool providedArgumentsKnownToBeComplete(IrNode currentNode) {
-    // See comment in [SsaBuilder.providedArgumentsKnownToBeComplete].
+    // See comment in [SsaFromAstBuilder.providedArgumentsKnownToBeComplete].
     return false;
   }
 
@@ -96,22 +113,33 @@
     return nodes.map((e) => emitted[e]).toList(growable: false);
   }
 
-  HInstruction createInvokeStatic(IrNode node,
-                                  Element element,
-                                  List<HInstruction> arguments,
-                                  [TypeMask type]) {
-//    TODO(lry): enable inlining when building from IR.
-//    if (tryInlineMethod(element, null, arguments, node)) {
-//      return emitted[node];
-//    }
-    if (type == null) {
-      type = TypeMaskFactory.inferredReturnTypeForElement(element, compiler);
+  void addInvokeStatic(IrInvokeStatic node,
+                       FunctionElement function,
+                       List<HInstruction> arguments,
+                       [TypeMask type]) {
+    if (tryInlineMethod(function, null, arguments, node)) {
+      // When encountering a [:return:] instruction in the inlined function,
+      // the value in the [emitted] map is updated. This is performed either
+      // by [SsaFromIrBuilder.emitReturn] (if this is an [SsaFromIrBuilder] or
+      // and [SsaFromAstInliner]), or by [SsaFromAstInliner.leaveInlinedMethod]
+      // if this is an [SsaFromIrInliner].
+      // If the inlined function is in AST form, it might not have an explicit
+      // [:return:] statement and therefore the return value can be [:null:].
+      if (emitted[node] == null) {
+        // IR functions should always have an explicit [:return:].
+        assert(!compiler.irBuilder.hasIr(function.implementation));
+        emitted[node] = graph.addConstantNull(compiler);
+      }
+      return;
     }
-    bool targetCanThrow = !compiler.world.getCannotThrow(element);
+    if (type == null) {
+      type = TypeMaskFactory.inferredReturnTypeForElement(function, compiler);
+    }
+    bool targetCanThrow = !compiler.world.getCannotThrow(function);
     HInvokeStatic instruction = new HInvokeStatic(
-        element.declaration, arguments, type, targetCanThrow: targetCanThrow);
-    instruction.sideEffects = compiler.world.getSideEffectsOfElement(element);
-    return attachPosition(instruction, node);
+        function.declaration, arguments, type, targetCanThrow: targetCanThrow);
+    instruction.sideEffects = compiler.world.getSideEffectsOfElement(function);
+    addExpression(node, attachPosition(instruction, node));
   }
 
   void visitIrConstant(IrConstant node) {
@@ -119,11 +147,9 @@
   }
 
   void visitIrInvokeStatic(IrInvokeStatic node) {
-    Element element = node.target;
-    assert(element.isFunction());
+    FunctionElement function = node.target;
     List<HInstruction> arguments = toInstructionList(node.arguments);
-    HInstruction instruction = createInvokeStatic(node, element, arguments);
-    addExpression(node, instruction);
+    addInvokeStatic(node, function, arguments);
   }
 
   void visitIrNode(IrNode node) {
@@ -131,7 +157,6 @@
   }
 
   void visitIrReturn(IrReturn node) {
-    assert(isReachable);
     HInstruction value = emitted[node.value];
     // TODO(lry): add code for dynamic type check.
     // value = potentiallyCheckType(value, returnType);
@@ -140,24 +165,32 @@
 }
 
 /**
- * This builder generates SSA nodes for elements that have an IR representation.
- * It mixes in [SsaGraphBuilderMixin] to share functionality with the
- * [SsaBuilder] that creates SSA nodes from trees.
+ * This builder generates SSA nodes for IR functions. It mixes in
+ * [SsaBuilderMixin] to share functionality with the [SsaFromAstBuilder] that
+ * creates SSA nodes from trees.
  */
 class SsaFromIrBuilder extends IrNodesVisitor with
-    SsaGraphBuilderMixin<IrNode>,
+    SsaBuilderMixin<IrNode>,
     SsaFromIrMixin,
-    SsaGraphBuilderFields<IrNode> {
+    SsaBuilderFields<IrNode> {
   final Compiler compiler;
-
   final JavaScriptBackend backend;
+  final CodegenWorkItem work;
 
-  SsaFromIrBuilder(JavaScriptBackend backend, CodegenWorkItem work)
+  /* See comment on [SsaFromAstBuilder.nativeEmitter]. */
+  final NativeEmitter nativeEmitter;
+
+  SsaFromIrBuilder(JavaScriptBackend backend,
+                   CodegenWorkItem work,
+                   this.nativeEmitter)
    : this.backend = backend,
-     this.compiler = backend.compiler {
+     this.compiler = backend.compiler,
+     this.work = work {
     sourceElementStack.add(work.element);
   }
 
+  final List<IrInliningState> inliningStack = <IrInliningState>[];
+
   HGraph buildMethod() {
     FunctionElement functionElement = sourceElement.implementation;
     graph.calledInLoop = compiler.world.isCalledInLoop(functionElement);
@@ -175,22 +208,49 @@
   }
 
   void emitReturn(HInstruction value, IrReturn node) {
-    closeAndGotoExit(attachPosition(new HReturn(value), node));
+    if (inliningStack.isEmpty) {
+      closeAndGotoExit(attachPosition(new HReturn(value), node));
+    } else {
+      IrInliningState state = inliningStack.last;
+      emitted[state.invokeNode] = value;
+    }
   }
 
-  void setupInliningState(FunctionElement function,
+  /**
+   * This method is invoked before inlining the body of [function] into this
+   * [SsaFromIrBuilder]. The inlined function can be either in AST or IR.
+   *
+   * The method is also invoked from the [SsaFromAstInliner], that is, if we
+   * are currently inlining an AST function and encounter a function invocation
+   * that should be inlined.
+   */
+  void enterInlinedMethod(FunctionElement function,
+                          IrNode callNode,
                           List<HInstruction> compiledArguments) {
-    // TODO(lry): inlining when building from IR.
-    throw "setup inlining for $function";
+    bool hasIr = compiler.irBuilder.hasIr(function);
+
+    SsaFromAstInliner astInliner;
+    if (!hasIr) {
+      astInliner = new SsaFromAstInliner(this, function, compiledArguments);
+    }
+
+    IrInliningState state = new IrInliningState(function, callNode, astInliner);
+    inliningStack.add(state);
+    if (hasIr) {
+      setupStateForInlining(function, compiledArguments);
+    }
   }
 
   void leaveInlinedMethod() {
-    // TODO(lry): inlining when building from IR.
-    throw "leave inlining in ir";
+    inliningStack.removeLast();
   }
 
-  void doInline(Element element) {
-    // TODO(lry): inlining when building from IR.
-    throw "inline ir in ir for $element";
+  void doInline(FunctionElement function) {
+    if (compiler.irBuilder.hasIr(function)) {
+      visitInlinedFunction(function);
+    } else {
+      IrInliningState state = inliningStack.last;
+      state.astInliner.visitInlinedFunction(function);
+    }
   }
 }
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/from_ir_inliner.dart b/sdk/lib/_internal/compiler/implementation/ssa/from_ir_inliner.dart
index d802603..e88f130 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/from_ir_inliner.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/from_ir_inliner.dart
@@ -6,59 +6,47 @@
 
 /**
  * This class implements an [IrNodesVisitor] that inlines a function represented
- * as IR into an [SsaBuilder].
+ * as IR into an [SsaFromAstBuilder].
  */
-class SsaFromIrInliner
-    extends IrNodesVisitor with SsaGraphBuilderMixin<IrNode>, SsaFromIrMixin {
-  final SsaBuilder builder;
+class SsaFromIrInliner extends IrNodesVisitor with
+    SsaBuilderMixin<IrNode>,
+    SsaFromIrMixin,
+    SsaBuilderDelegate<IrNode, Node> {
+  final SsaFromAstBuilder builder;
 
-  SsaFromIrInliner(this.builder);
+  SsaFromIrInliner.internal(this.builder);
 
-  Compiler get compiler => builder.compiler;
-
-  JavaScriptBackend get backend => builder.backend;
-
-  Element get sourceElement => builder.sourceElementStack.last;
-
-  HGraph get graph => builder.graph;
-
-  HBasicBlock get current => builder.current;
-
-  void set current(HBasicBlock block) {
-    builder.current = block;
+  factory SsaFromIrInliner(SsaFromAstBuilder builder,
+                           FunctionElement function,
+                           List<HInstruction> compiledArguments) {
+    SsaFromIrInliner irInliner = new SsaFromIrInliner.internal(builder);
+    irInliner.setupStateForInlining(function, compiledArguments);
+    return irInliner;
   }
 
-  HBasicBlock get lastOpenedBlock => builder.lastOpenedBlock;
+  final List<IrExpression> inlinedCalls = <IrExpression>[];
 
-  void set lastOpenedBlock(HBasicBlock block) {
-    builder.lastOpenedBlock = block;
-  }
-
-  bool get isReachable => builder.isReachable;
-
-  void set isReachable(bool value) {
-    builder.isReachable = value;
-  }
-
-  bool get inThrowExpression => builder.inThrowExpression;
-
-  int get loopNesting => builder.loopNesting;
-
-  List<InliningState> get inliningStack => builder.inliningStack;
-
-  List<Element> get sourceElementStack => builder.sourceElementStack;
-
-  void setupInliningState(FunctionElement function,
+  /**
+   * This function is invoked when we are currently inlining an IR function
+   * into an AST builder, and we encounter an infocation that is inlined.
+   */
+  void enterInlinedMethod(FunctionElement function,
+                          IrNode callNode,
                           List<HInstruction> compiledArguments) {
-    builder.setupInliningState(function, compiledArguments);
+    assert(callNode != null);
+    inlinedCalls.add(callNode);
+    builder.enterInlinedMethod(function, null, compiledArguments);
   }
 
   void leaveInlinedMethod() {
     builder.leaveInlinedMethod();
+    // [leaveInlinedMethod] pushes the returned value on the builder's stack,
+    // no matter if the inlined function is represented in AST or IR.
+    emitted[inlinedCalls.removeLast()] = builder.pop();
   }
 
-  void doInline(Element element) {
-    builder.doInline(element);
+  void doInline(FunctionElement function) {
+    builder.doInline(function);
   }
 
   void emitReturn(HInstruction value, IrReturn node) {
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/interceptor_simplifier.dart b/sdk/lib/_internal/compiler/implementation/ssa/interceptor_simplifier.dart
index e4a4ad8..5cf4392 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/interceptor_simplifier.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/interceptor_simplifier.dart
@@ -186,7 +186,7 @@
       if (interceptedClasses.contains(backend.jsNumberClass)
           && !(interceptedClasses.contains(backend.jsDoubleClass)
                || interceptedClasses.contains(backend.jsIntClass))) {
-        for (var user in node.usedBy) {
+        for (HInstruction user in node.usedBy) {
           if (user is! HInvoke) continue;
           Set<ClassElement> intercepted =
               backend.getInterceptedClassesOn(user.selector.name);
@@ -200,7 +200,7 @@
       }
     } else {
       interceptedClasses = new Set<ClassElement>();
-      for (var user in node.usedBy) {
+      for (HInstruction user in node.usedBy) {
         if (user is HIs) {
           // Is-checks can be performed on any intercepted class.
           interceptedClasses.addAll(backend.interceptedClasses);
@@ -215,8 +215,7 @@
 
     HInstruction receiver = node.receiver;
     if (canUseSelfForInterceptor(receiver, interceptedClasses)) {
-      node.block.rewrite(node, receiver);
-      return false;
+      return rewriteToUseSelfAsInterceptor(node, receiver);
     }
 
     // Try computing a constant interceptor.
@@ -254,6 +253,51 @@
     return true;
   }
 
+  bool rewriteToUseSelfAsInterceptor(HInterceptor node, HInstruction receiver) {
+    // `rewrite` below clears `node.usedBy`.
+    List<HInstruction> originalUsers = node.usedBy.toList();
+
+    node.block.rewrite(node, receiver);
+
+    // We have just rewritten:
+    //
+    //     m = getInterceptor(a)
+    //     m.foo$1(a, x)
+    // -->
+    //     m = getInterceptor(a)
+    //     a.foo$1(a, x)
+    //
+    // For the rewritten calls, if the selector matches only methods that ignore
+    // the explicit receiver parameter, replace occurences of the receiver
+    // argument with a dummy receiver '0':
+    //
+    //     a.foo$1(a, x)   -->   a.foo$1(0, x)
+    //
+    JavaScriptBackend backend = compiler.backend;
+    for (HInstruction user in originalUsers) {
+      if (user is HInvokeDynamic) {
+        HInvokeDynamic invoke = user;
+        if (invoke.receiver == receiver &&
+            !backend.isInterceptedMixinSelector(invoke.selector)) {
+          HInstruction receiverArgument = invoke.inputs[1];
+          // TODO(15720): The test here should be
+          //
+          //     invoke.receiver.nonCheck() == receiverArgument.nonCheck()
+          //
+          if (invoke.receiver == receiverArgument) {  // recognize a.foo(a,...)
+            Constant constant = new DummyReceiverConstant(
+                receiverArgument.instructionType);
+            HConstant dummy = graph.addConstant(constant, compiler);
+            receiverArgument.usedBy.remove(invoke);
+            invoke.inputs[1] = dummy;
+            dummy.usedBy.add(invoke);
+          }
+        }
+      }
+    }
+    return false;
+  }
+
   bool visitOneShotInterceptor(HOneShotInterceptor node) {
     HInstruction constant = tryComputeConstantInterceptor(
         node.inputs[1], node.interceptedClasses);
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/invoke_dynamic_specializers.dart b/sdk/lib/_internal/compiler/implementation/ssa/invoke_dynamic_specializers.dart
index daf4f1e..727a7d4 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/invoke_dynamic_specializers.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/invoke_dynamic_specializers.dart
@@ -388,12 +388,12 @@
         if (left.isUInt31(compiler)) {
           return newBuiltinVariant(instruction, compiler);
         }
-        clearAllSideEffects(instruction);
         // We can call _tdivFast because the rhs is a 32bit integer
         // and not 0, nor -1.
         instruction.selector = renameToOptimizedSelector(
             '_tdivFast', instruction.selector, compiler);
       }
+      clearAllSideEffects(instruction);
     }
     return null;
   }
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart b/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart
index 64b666c..ea74d96 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart
@@ -1414,9 +1414,9 @@
   bool canThrow() => targetCanThrow;
 
   /// If this instruction is a call to a constructor, [instantiatedTypes]
-  /// contains the type(s) used in the (Dart) `New` expression(s).
-  /// The [instructionType] of this node is not enough, because we also need
-  /// the type arguments.  See also [SsaBuilder.currentInlinedInstantiations].
+  /// contains the type(s) used in the (Dart) `New` expression(s). The
+  /// [instructionType] of this node is not enough, because we also need the
+  /// type arguments. See also [SsaFromAstMixin.currentInlinedInstantiations].
   List<DartType> instantiatedTypes;
 
   /** The first input must be the target. */
@@ -1424,7 +1424,7 @@
                 {this.targetCanThrow: true})
     : super(inputs, type);
 
-  toString() => 'invoke static: ${element.name}';
+  toString() => 'invoke static: $element';
   accept(HVisitor visitor) => visitor.visitInvokeStatic(this);
   int typeCode() => HInstruction.INVOKE_STATIC_TYPECODE;
 }
@@ -1605,9 +1605,9 @@
   ClassElement element;
 
   /// If this field is not `null`, this call is from an inlined constructor and
-  /// we have to register the instantiated type in the code generator.
-  /// The [instructionType] of this node is not enough, because we also need
-  /// the type arguments.  See also [SsaBuilder.currentInlinedInstantiations].
+  /// we have to register the instantiated type in the code generator. The
+  /// [instructionType] of this node is not enough, because we also need the
+  /// type arguments. See also [SsaFromAstMixin.currentInlinedInstantiations].
   List<DartType> instantiatedTypes;
 
   HForeignNew(this.element, TypeMask type, List<HInstruction> inputs,
@@ -1837,7 +1837,7 @@
   /**
    * Signals that this is a special break instruction for the synthetic loop
    * generatedfor a switch statement with continue statements. See
-   * [SsaBuilder.buildComplexSwitchStatement] for detail.
+   * [SsaFromAstMixin.buildComplexSwitchStatement] for detail.
    */
   final bool breakSwitchContinueLoop;
   HBreak(TargetElement target, {bool this.breakSwitchContinueLoop: false})
@@ -1931,6 +1931,14 @@
 
   // Maybe avoid this if the literal is big?
   bool isCodeMotionInvariant() => true;
+
+  set instructionType(type) {
+    // Only lists can be specialized. The SSA builder uses the
+    // inferrer for finding the type of a constant list. We should
+    // have the constant know its type instead.
+    if (!isConstantList()) return;
+    super.instructionType = type;
+  }
 }
 
 class HNot extends HInstruction {
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart b/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart
index 6b8eaaf..cd96172 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart
@@ -123,11 +123,19 @@
       if (replacement != instruction) {
         block.rewrite(instruction, replacement);
 
-        // If we can replace [instruction] with [replacement], then
-        // [replacement]'s type can be narrowed.
-        TypeMask newType = replacement.instructionType.intersection(
-            instruction.instructionType, compiler);
-        replacement.instructionType = newType;
+        // The intersection of double and int return conflicting, and
+        // because of our number implementation for JavaScript, it
+        // might be that an operation thought to return double, can be
+        // simplified to an int. For example:
+        // `2.5 * 10`.
+        if (!(replacement.isNumberOrNull(compiler)
+              && instruction.isNumberOrNull(compiler))) {
+          // If we can replace [instruction] with [replacement], then
+          // [replacement]'s type can be narrowed.
+          TypeMask newType = replacement.instructionType.intersection(
+              instruction.instructionType, compiler);
+          replacement.instructionType = newType;
+        }
 
         // If the replacement instruction does not know its
         // source element, use the source element of the
diff --git a/sdk/lib/_internal/compiler/implementation/universe/universe.dart b/sdk/lib/_internal/compiler/implementation/universe/universe.dart
index eed40c8..36181ce 100644
--- a/sdk/lib/_internal/compiler/implementation/universe/universe.dart
+++ b/sdk/lib/_internal/compiler/implementation/universe/universe.dart
@@ -334,8 +334,10 @@
     }
     if (isGetter()) return true;
     if (isSetter()) return false;
+    return signatureApplies(element, compiler);
+  }
 
-    FunctionElement function = element;
+  bool signatureApplies(FunctionElement function, Compiler compiler) {
     FunctionSignature parameters = function.computeSignature(compiler);
     if (argumentCount > parameters.parameterCount) return false;
     int requiredParameterCount = parameters.requiredParameterCount;
diff --git a/sdk/lib/_internal/compiler/implementation/warnings.dart b/sdk/lib/_internal/compiler/implementation/warnings.dart
index e1a8516..5d5c72d 100644
--- a/sdk/lib/_internal/compiler/implementation/warnings.dart
+++ b/sdk/lib/_internal/compiler/implementation/warnings.dart
@@ -970,6 +970,15 @@
       error: const MessageKind("Error: Cannot resolve setter."),
       warning: const MessageKind("Warning: Cannot resolve setter."));
 
+  static const DualKind ASSIGNING_METHOD = const DualKind(
+      error: const MessageKind("Error: Cannot resolve setter."),
+      warning:
+        const MessageKind("Warning: Cannot assign a value to a method."));
+
+  static const DualKind ASSIGNING_TYPE = const DualKind(
+      error: const MessageKind("Error: Cannot resolve setter."),
+      warning: const MessageKind("Warning: Cannot assign a value to a type."));
+
   static const MessageKind VOID_NOT_ALLOWED = const MessageKind(
       "Error: Type 'void' can't be used here because it isn't a return type.",
       howToFix: "Try removing 'void' keyword or replace it with 'var', 'final',"
diff --git a/sdk/lib/_internal/lib/annotations.dart b/sdk/lib/_internal/lib/annotations.dart
index 66d4818..23f1234 100644
--- a/sdk/lib/_internal/lib/annotations.dart
+++ b/sdk/lib/_internal/lib/annotations.dart
@@ -21,3 +21,10 @@
 class NoInline {
   const NoInline();
 }
+
+// Ensures that the annotated method is represented internally using
+// IR nodes ([:value == true:]) or AST nodes ([:value == false:]).
+class IrRepresentation {
+  final bool value;
+  const IrRepresentation(this.value);
+}
diff --git a/sdk/lib/_internal/lib/interceptors.dart b/sdk/lib/_internal/lib/interceptors.dart
index 3bab8fd..1562b57 100644
--- a/sdk/lib/_internal/lib/interceptors.dart
+++ b/sdk/lib/_internal/lib/interceptors.dart
@@ -180,8 +180,7 @@
 var mapTypeToInterceptor;
 
 int findIndexForNativeSubclassType(Type type) {
-  JS_EFFECT((_){ mapTypeToInterceptor = _; });
-  if (mapTypeToInterceptor == null) return null;
+  if (JS('bool', '# == null', mapTypeToInterceptor)) return null;
   List map = JS('JSFixedArray', '#', mapTypeToInterceptor);
   for (int i = 0; i + 1 < map.length; i += 3) {
     if (type == map[i]) {
@@ -195,7 +194,7 @@
   var index = findIndexForNativeSubclassType(type);
   if (index == null) return null;
   List map = JS('JSFixedArray', '#', mapTypeToInterceptor);
-  return mapTypeToInterceptor[index + 1];
+  return map[index + 1];
 }
 
 /**
@@ -208,7 +207,7 @@
   var index = findIndexForNativeSubclassType(type);
   if (index == null) return null;
   List map = JS('JSFixedArray', '#', mapTypeToInterceptor);
-  var constructorMap = mapTypeToInterceptor[index + 2];
+  var constructorMap = map[index + 2];
   var constructorFn = JS('', '#[#]', constructorMap, name);
   return constructorFn;
 }
diff --git a/sdk/lib/_internal/lib/io_patch.dart b/sdk/lib/_internal/lib/io_patch.dart
index 2f3db18..88e4f86 100644
--- a/sdk/lib/_internal/lib/io_patch.dart
+++ b/sdk/lib/_internal/lib/io_patch.dart
@@ -83,6 +83,9 @@
   patch static _renameLink(String oldPath, String newPath) {
     throw new UnsupportedError("File._renameLink");
   }
+  patch static _copy(String oldPath, String newPath) {
+    throw new UnsupportedError("File._copy");
+  }
   patch static _lengthFromPath(String path) {
     throw new UnsupportedError("File._lengthFromPath");
   }
@@ -182,6 +185,9 @@
   patch static int _pid(Process process) {
     throw new UnsupportedError("ProcessUtils._pid");
   }
+  patch static Stream<ProcessSignal> _watchSignal(ProcessSignal signal) {
+    throw new UnsupportedError("ProcessUtils._watchSignal");
+  }
 }
 
 patch class Process {
@@ -310,7 +316,7 @@
   patch static Stdin _getStdioInputStream() {
     throw new UnsupportedError("StdIOUtils._getStdioInputStream");
   }
-  patch static IOSink _getStdioOutputStream(int fd) {
+  patch static _getStdioOutputStream(int fd) {
     throw new UnsupportedError("StdIOUtils._getStdioOutputStream");
   }
   patch static int _socketType(nativeSocket) {
@@ -357,6 +363,18 @@
   }
 }
 
+patch class Stdout {
+  patch bool get hasTerminal {
+    throw new UnsupportedError("Stdout.hasTerminal");
+  }
+  patch int get terminalColumns {
+    throw new UnsupportedError("Stdout.terminalColumns");
+  }
+  patch int get terminalLines {
+    throw new UnsupportedError("Stdout.terminalLines");
+  }
+}
+
 patch class _FileSystemWatcher {
   patch static Stream<FileSystemEvent> watch(
       String path, int events, bool recursive) {
diff --git a/sdk/lib/_internal/lib/isolate_patch.dart b/sdk/lib/_internal/lib/isolate_patch.dart
index 560fb1f..45de5af 100644
--- a/sdk/lib/_internal/lib/isolate_patch.dart
+++ b/sdk/lib/_internal/lib/isolate_patch.dart
@@ -12,23 +12,31 @@
 
 patch class Isolate {
   patch static Future<Isolate> spawn(void entryPoint(message), var message) {
-    return IsolateNatives.spawnFunction(entryPoint, message)
-        .then((controlPort) => new Isolate._fromControlPort(controlPort));
+    try {
+      return IsolateNatives.spawnFunction(entryPoint, message)
+          .then((controlPort) => new Isolate._fromControlPort(controlPort));
+    } catch (e, st) {
+      return new Future<Isolate>.error(e, st);
+    }
   }
 
   patch static Future<Isolate> spawnUri(
       Uri uri, List<String> args, var message) {
-    if (args is List<String>) {
-      for (int i = 0; i < args.length; i++) {
-        if (args[i] is! String) {
-          throw new ArgumentError("Args must be a list of Strings $args");
+    try {
+      if (args is List<String>) {
+        for (int i = 0; i < args.length; i++) {
+          if (args[i] is! String) {
+            throw new ArgumentError("Args must be a list of Strings $args");
+          }
         }
+      } else if (args != null) {
+        throw new ArgumentError("Args must be a list of Strings $args");
       }
-    } else if (args != null) {
-      throw new ArgumentError("Args must be a list of Strings $args");
+      return IsolateNatives.spawnUri(uri, args, message)
+          .then((controlPort) => new Isolate._fromControlPort(controlPort));
+    } catch (e, st) {
+      return new Future<Isolate>.error(e, st);
     }
-    return IsolateNatives.spawnUri(uri, args, message)
-        .then((controlPort) => new Isolate._fromControlPort(controlPort));
   }
 }
 
diff --git a/sdk/lib/_internal/lib/js_array.dart b/sdk/lib/_internal/lib/js_array.dart
index 9ce29f9..730d063 100644
--- a/sdk/lib/_internal/lib/js_array.dart
+++ b/sdk/lib/_internal/lib/js_array.dart
@@ -269,11 +269,11 @@
     if (end < start || end > receiverLength) {
       throw new RangeError.range(end, start, receiverLength);
     }
-    Arrays.copy(this,
-                end,
-                this,
-                start,
-                receiverLength - end);
+    Lists.copy(this,
+               end,
+               this,
+               start,
+               receiverLength - end);
     this.length = receiverLength - (end - start);
   }
 
diff --git a/sdk/lib/_internal/lib/js_mirrors.dart b/sdk/lib/_internal/lib/js_mirrors.dart
index f27c8cc..18829bf 100644
--- a/sdk/lib/_internal/lib/js_mirrors.dart
+++ b/sdk/lib/_internal/lib/js_mirrors.dart
@@ -67,12 +67,12 @@
 
   final IsolateMirror isolate = new JsIsolateMirror();
 
-  TypeMirror get dynamicType => _dynamicType;
-  TypeMirror get voidType => _voidType;
+  JsTypeMirror get dynamicType => _dynamicType;
+  JsTypeMirror get voidType => _voidType;
 
-  final static TypeMirror _dynamicType =
+  final static JsTypeMirror _dynamicType =
       new JsTypeMirror(const Symbol('dynamic'));
-  final static TypeMirror _voidType = new JsTypeMirror(const Symbol('void'));
+  final static JsTypeMirror _voidType = new JsTypeMirror(const Symbol('void'));
 
   static final Map<String, List<LibraryMirror>> librariesByName =
       computeLibrariesByName();
@@ -226,6 +226,8 @@
     return _cachedUpperBound = typeMirrorFromRuntimeTypeRepresentation(
         owner, getMetadata(_typeVariable.bound));
   }
+
+  _asRuntimeType() => _metadataIndex;
 }
 
 class JsTypeMirror extends JsDeclarationMirror implements TypeMirror {
@@ -244,7 +246,7 @@
 
   bool get hasReflectedType => false;
   Type get reflectedType {
-    throw new UnsupportedError("This type does not support reflectedTypees");
+    throw new UnsupportedError("This type does not support reflectedType");
   }
 
   List<TypeVariableMirror> get typeVariables => const <TypeVariableMirror>[];
@@ -252,6 +254,12 @@
 
   bool get isOriginalDeclaration => true;
   TypeMirror get originalDeclaration => this;
+
+  _asRuntimeType() {
+    if (this == JsMirrorSystem._dynamicType) return null;
+    if (this == JsMirrorSystem._voidType) return null;
+    throw new RuntimeError('Should not call _asRuntimeType');
+  }
 }
 
 class JsLibraryMirror extends JsDeclarationMirror with JsObjectMirror
@@ -713,6 +721,8 @@
 
   Map<Symbol, DeclarationMirror> get declarations => mixin.declarations;
 
+  _asRuntimeType() => null;
+
   InstanceMirror invoke(
       Symbol memberName,
       List positionalArguments,
@@ -963,7 +973,16 @@
         super(originalDeclaration.simpleName);
 
   String get _prettyName => 'ClassMirror';
-  String get _mangledName => '${_class._mangledName}<$_typeArguments>';
+  String get _mangledName {
+    for (TypeMirror typeArgument in typeArguments) {
+      if (typeArgument != JsMirrorSystem._dynamicType) {
+        return '${_class._mangledName}<$_typeArguments>';
+      }
+    }
+    // When all type arguments are dynamic, the canonical representation is to
+    // drop them.
+    return _class._mangledName;
+  }
 
   List<TypeVariableMirror> get typeVariables => _class.typeVariables;
 
@@ -1082,9 +1101,16 @@
   InstanceMirror newInstance(Symbol constructorName,
                              List positionalArguments,
                              [Map<Symbol, dynamic> namedArguments]) {
-    return _class.newInstance(constructorName,
-                              positionalArguments,
-                              namedArguments);
+    var instance = _class._getInvokedInstance(constructorName,
+                                              positionalArguments,
+                                              namedArguments);
+    return reflect(setRuntimeTypeInfo(
+        instance, typeArguments.map((t) => t._asRuntimeType()).toList()));
+  }
+
+  _asRuntimeType() {
+    return [_class._jsConstructor].addAll(
+        typeArguments.map((t) => t._asRuntimeType()));
   }
 
   JsLibraryMirror get owner => _class.owner;
@@ -1116,8 +1142,6 @@
     return _cachedSuperinterfaces = _class._getSuperinterfacesWithOwner(this);
   }
 
-  bool get hasReflectedType => _class.hasReflectedType;
-
   bool get isPrivate => _class.isPrivate;
 
   bool get isTopLevel => _class.isTopLevel;
@@ -1128,7 +1152,9 @@
 
   Symbol get qualifiedName => _class.qualifiedName;
 
-  Type get reflectedType => _class.reflectedType;
+  bool get hasReflectedType => true;
+
+  Type get reflectedType => createRuntimeType(_mangledName);
 
   Symbol get simpleName => _class.simpleName;
 
@@ -1195,6 +1221,15 @@
             filterConstructors(_methods));
   }
 
+  _asRuntimeType() {
+    if (typeVariables.isEmpty)  return _jsConstructor;
+    var type = [_jsConstructor];
+    for (int i = 0; i < typeVariables.length; i ++) {
+      type.add(JsMirrorSystem._dynamicType._asRuntimeType);
+    }
+    return type;
+  }
+
   List<JsMethodMirror> _getMethodsWithOwner(DeclarationMirror methodOwner) {
     var prototype = JS('', '#.prototype', _jsConstructor);
     List<String> keys = extractKeys(prototype);
@@ -1357,25 +1392,33 @@
     throw new NoSuchMethodError(this, fieldName, null, null);
   }
 
+  _getInvokedInstance(Symbol constructorName,
+                      List positionalArguments,
+                      [Map<Symbol, dynamic> namedArguments]) {
+     if (namedArguments != null && !namedArguments.isEmpty) {
+       throw new UnsupportedError('Named arguments are not implemented.');
+     }
+     JsMethodMirror mirror =
+         JsCache.fetch(_jsConstructorCache, n(constructorName));
+     if (mirror == null) {
+       mirror = __constructors.values.firstWhere(
+           (m) => m.constructorName == constructorName,
+           orElse: () {
+             // TODO(ahe): What receiver to use?
+             throw new NoSuchMethodError(
+                 this, constructorName, positionalArguments, namedArguments);
+           });
+       JsCache.update(_jsConstructorCache, n(constructorName), mirror);
+     }
+     return mirror._invoke(positionalArguments, namedArguments);
+   }
+
   InstanceMirror newInstance(Symbol constructorName,
                              List positionalArguments,
                              [Map<Symbol, dynamic> namedArguments]) {
-    if (namedArguments != null && !namedArguments.isEmpty) {
-      throw new UnsupportedError('Named arguments are not implemented.');
-    }
-    JsMethodMirror mirror =
-        JsCache.fetch(_jsConstructorCache, n(constructorName));
-    if (mirror == null) {
-      mirror = __constructors.values.firstWhere(
-          (m) => m.constructorName == constructorName,
-          orElse: () {
-            // TODO(ahe): What receiver to use?
-            throw new NoSuchStaticMethodError.missingConstructor(
-                this, constructorName, positionalArguments, namedArguments);
-          });
-      JsCache.update(_jsConstructorCache, n(constructorName), mirror);
-    }
-    return reflect(mirror._invoke(positionalArguments, namedArguments));
+    return reflect(_getInvokedInstance(constructorName,
+                                       positionalArguments,
+                                       namedArguments));
   }
 
   JsLibraryMirror get owner {
@@ -1498,6 +1541,16 @@
 
   List<TypeMirror> get typeArguments => const <TypeMirror>[];
 
+  bool get hasReflectedType => typeVariables.length == 0;
+
+  Type get reflectedType {
+    if (!hasReflectedType) {
+      throw new UnsupportedError(
+          "Declarations of generics have no reflected type");
+    }
+    return createRuntimeType(_mangledName);
+  }
+
   // TODO(ahe): Implement this.
   Map<Symbol, MethodMirror> get instanceMembers
       => throw new UnimplementedError();
diff --git a/sdk/lib/_internal/lib/js_number.dart b/sdk/lib/_internal/lib/js_number.dart
index b6606f0..7aaeb93 100644
--- a/sdk/lib/_internal/lib/js_number.dart
+++ b/sdk/lib/_internal/lib/js_number.dart
@@ -59,6 +59,8 @@
 
   num abs() => JS('num', r'Math.abs(#)', this);
 
+  num get sign => this > 0 ? 1 : this < 0 ? -1 : this;
+
   static const int _MIN_INT32 = -0x80000000;
   static const int _MAX_INT32 = 0x7FFFFFFF;
 
@@ -240,7 +242,7 @@
   }
 
   num operator >>(num other) {
-    if (false) _shrReceiverPositive(other); 
+    if (false) _shrReceiverPositive(other);
     if (other is !num) throw new ArgumentError(other);
     if (JS('num', '#', other) < 0) throw new ArgumentError(other);
     return _shrOtherPositive(other);
diff --git a/sdk/lib/_internal/lib/js_rti.dart b/sdk/lib/_internal/lib/js_rti.dart
index 3c4da5a..ca1d2d1 100644
--- a/sdk/lib/_internal/lib/js_rti.dart
+++ b/sdk/lib/_internal/lib/js_rti.dart
@@ -161,7 +161,7 @@
 /**
  * Returns a human-readable representation of the type representation [type].
  */
-String runtimeTypeToString(var type , {String onTypeVariable(int i)}) {
+String runtimeTypeToString(var type, {String onTypeVariable(int i)}) {
   if (isNull(type)) {
     return 'dynamic';
   } else if (isJsArray(type)) {
diff --git a/sdk/lib/_internal/pub/bin/pub.dart b/sdk/lib/_internal/pub/bin/pub.dart
index e19d9a0..451ee6c 100644
--- a/sdk/lib/_internal/pub/bin/pub.dart
+++ b/sdk/lib/_internal/pub/bin/pub.dart
@@ -121,7 +121,7 @@
 /// Checks that pub is running on a supported platform. If it isn't, it prints
 /// an error message and exits. Completes when the validation is done.
 Future validatePlatform() {
-  return new Future.sync(() {
+  return syncFuture(() {
     if (Platform.operatingSystem != 'windows') return null;
 
     return runProcess('ver', []).then((result) {
diff --git a/sdk/lib/_internal/pub/lib/src/barback.dart b/sdk/lib/_internal/pub/lib/src/barback.dart
index 6f14935..a5a48a6 100644
--- a/sdk/lib/_internal/pub/lib/src/barback.dart
+++ b/sdk/lib/_internal/pub/lib/src/barback.dart
@@ -141,7 +141,7 @@
 
   return BarbackServer.bind(host, port, barback, graph.entrypoint.root.name)
       .then((server) {
-    return new Future.sync(() {
+    return syncFuture(() {
       if (watcher != WatcherType.NONE) {
         return watchSources(graph, barback, watcher);
       }
@@ -157,7 +157,7 @@
         server.barback.errors.listen((error) {
           if (error is TransformerException) error = error.error;
           if (!completer.isCompleted) {
-            completer.completeError(error, new Trace.current());
+            completer.completeError(error, new Chain.current());
           }
         }),
         server.barback.results.listen((_) {}, onError: (error, stackTrace) {
@@ -295,7 +295,7 @@
 
   // Show the level (unless the message mentions it).
   if (!messageMentions(entry.level.name)) {
-    prefixParts.add("${entry.level} in");
+    prefixParts.add("${entry.level} from");
   }
 
   // Show the transformer.
@@ -329,7 +329,7 @@
       break;
 
     case LogLevel.INFO:
-      log.message("$prefix\n$message");
+      log.message("${log.cyan(prefix)}\n$message");
       break;
   }
 }
diff --git a/sdk/lib/_internal/pub/lib/src/barback/dart2js_transformer.dart b/sdk/lib/_internal/pub/lib/src/barback/dart2js_transformer.dart
index c4b0597..9bb3022 100644
--- a/sdk/lib/_internal/pub/lib/src/barback/dart2js_transformer.dart
+++ b/sdk/lib/_internal/pub/lib/src/barback/dart2js_transformer.dart
@@ -11,6 +11,7 @@
 import 'package:analyzer/analyzer.dart';
 import 'package:barback/barback.dart';
 import 'package:path/path.dart' as path;
+import 'package:stack_trace/stack_trace.dart';
 
 import '../../../../compiler/compiler.dart' as compiler;
 import '../../../../compiler/implementation/dart2js.dart'
@@ -101,9 +102,10 @@
       // Need to report compile errors to the user in an easily visible way.
       // Need to make sure paths in errors are mapped to the original source
       // path so they can understand them.
-      return dart.compile(entrypoint, provider,
+      return Chain.track(dart.compile(
+          entrypoint, provider,
           packageRoot: packageRoot,
-          minify: _mode == BarbackMode.RELEASE).then((_) {
+          minify: _mode == BarbackMode.RELEASE)).then((_) {
         stopwatch.stop();
         transform.logger.info("Took ${stopwatch.elapsed} to compile $id.");
       });
@@ -259,6 +261,7 @@
   Future<String> _readResource(Uri url) {
     // See if the path is within a package. If so, use Barback so we can use
     // generated Dart assets.
+
     var id = _sourceUrlToId(url);
     if (id != null) return _transform.readInputAsString(id);
 
@@ -266,7 +269,7 @@
     // skip Barback and just hit the file system. This will occur at the very
     // least for dart2js's implementations of the core libraries.
     var sourcePath = path.fromUri(url);
-    return new File(sourcePath).readAsString();
+    return Chain.track(new File(sourcePath).readAsString());
   }
 
   AssetId _sourceUrlToId(Uri url) {
@@ -274,11 +277,16 @@
     var id = specialUrlToId(url);
     if (id != null) return id;
 
-    // See if it's a path within the root package.
+    // See if it's a path to a "public" asset within the root package. All
+    // other files in the root package are not visible to transformers, so
+    // should be loaded directly from disk.
     var rootDir = _graph.entrypoint.root.dir;
     var sourcePath = path.fromUri(url);
-    if (isBeneath(sourcePath, rootDir)) {
+    if (isBeneath(sourcePath, path.join(rootDir, "lib")) ||
+        isBeneath(sourcePath, path.join(rootDir, "asset")) ||
+        isBeneath(sourcePath, path.join(rootDir, "web"))) {
       var relative = path.relative(sourcePath, from: rootDir);
+
       return new AssetId(_graph.entrypoint.root.name, relative);
     }
 
diff --git a/sdk/lib/_internal/pub/lib/src/barback/load_transformers.dart b/sdk/lib/_internal/pub/lib/src/barback/load_transformers.dart
index 7c4e2a1..c92791b 100644
--- a/sdk/lib/_internal/pub/lib/src/barback/load_transformers.dart
+++ b/sdk/lib/_internal/pub/lib/src/barback/load_transformers.dart
@@ -12,6 +12,7 @@
 // TODO(nweiz): don't import from "src" once issue 14966 is fixed.
 import 'package:barback/src/internal_asset.dart';
 import 'package:source_maps/source_maps.dart';
+import 'package:stack_trace/stack_trace.dart';
 
 import '../barback.dart';
 import '../dart.dart' as dart;
@@ -542,7 +543,7 @@
 /// throws an error, that will also be sent.
 void _respond(wrappedMessage, callback(message)) {
   var replyTo = wrappedMessage['replyTo'];
-  new Future.sync(() => callback(wrappedMessage['message']))
+  syncFuture(() => callback(wrappedMessage['message']))
       .then((result) => replyTo.send({'type': 'success', 'value': result}))
       .catchError((error, stackTrace) {
     // TODO(nweiz): at least MissingInputException should be preserved here.
@@ -565,10 +566,11 @@
     'replyTo': receivePort.sendPort
   });
 
-  return receivePort.first.then((response) {
+  return Chain.track(receivePort.first).then((response) {
     if (response['type'] == 'success') return response['value'];
     assert(response['type'] == 'error');
     return new Future.error(
-        new dart.CrossIsolateException.deserialize(response['error']));
+        new dart.CrossIsolateException.deserialize(response['error']),
+        new Chain.current());
   });
 }
diff --git a/sdk/lib/_internal/pub/lib/src/barback/server.dart b/sdk/lib/_internal/pub/lib/src/barback/server.dart
index f491aab..cb6c46e 100644
--- a/sdk/lib/_internal/pub/lib/src/barback/server.dart
+++ b/sdk/lib/_internal/pub/lib/src/barback/server.dart
@@ -61,7 +61,7 @@
   /// root package.
   static Future<BarbackServer> bind(String host, int port, Barback barback,
       String rootPackage) {
-    return HttpServer.bind(host, port)
+    return Chain.track(HttpServer.bind(host, port))
         .then((server) => new BarbackServer._(server, barback, rootPackage));
   }
 
@@ -69,7 +69,7 @@
       : _server = server,
         port = server.port,
         address = server.address {
-    _server.listen(_handleRequest, onError: (error, stackTrace) {
+    Chain.track(_server).listen(_handleRequest, onError: (error, stackTrace) {
       _resultsController.addError(error, stackTrace);
       close();
     });
@@ -115,7 +115,7 @@
         _resultsController.add(
             new BarbackServerResult._success(request.uri, id));
         // TODO(rnystrom): Set content-type based on asset type.
-        return request.response.addStream(stream).then((_) {
+        return Chain.track(request.response.addStream(stream)).then((_) {
           // Log successful requests both so we can provide debugging
           // information and so scheduled_test knows we haven't timed out while
           // loading transformers.
@@ -134,7 +134,7 @@
           return;
         }
 
-        trace = new Trace.from(trace);
+        trace = new Chain.forTrace(trace);
         _logRequest(request, "$error\n$trace");
 
         // Otherwise, it's some internal error.
@@ -145,7 +145,7 @@
       });
     }).catchError((error, trace) {
       if (error is! AssetNotFoundException) {
-        trace = new Trace.from(trace);
+        trace = new Chain.forTrace(trace);
         _logRequest(request, "$error\n$trace");
 
         _resultsController.addError(error, trace);
@@ -161,7 +161,7 @@
 
   /// Creates a web socket for [request] which should be an upgrade request.
   void _handleWebSocket(HttpRequest request) {
-    WebSocketTransformer.upgrade(request).then((socket) {
+    Chain.track(WebSocketTransformer.upgrade(request)).then((socket) {
       socket.listen((data) {
         var command;
         try {
diff --git a/sdk/lib/_internal/pub/lib/src/command.dart b/sdk/lib/_internal/pub/lib/src/command.dart
index 221bc45..5e0229c 100644
--- a/sdk/lib/_internal/pub/lib/src/command.dart
+++ b/sdk/lib/_internal/pub/lib/src/command.dart
@@ -88,19 +88,17 @@
 
     cache = new SystemCache.withSources(cacheDir, isOffline: isOffline);
 
-    handleError(error, trace) {
+    handleError(error, Chain chain) {
       // This is basically the top-level exception handler so that we don't
       // spew a stack trace on our users.
       var message;
 
       log.error(getErrorMessage(error));
 
-      if (trace != null) {
-        if (options['trace'] || !isUserFacingException(error)) {
-          log.error(new Trace.from(trace).terse);
-        } else {
-          log.fine(new Trace.from(trace).terse);
-        }
+      if (options['trace'] || !isUserFacingException(error)) {
+        log.error(chain.terse);
+      } else {
+        log.fine(chain.terse);
       }
 
       if (error is ApplicationException && error.innerError != null) {
@@ -124,28 +122,31 @@
       return flushThenExit(_chooseExitCode(error));
     }
 
-    new Future.sync(() {
-      // Make sure there aren't unexpected arguments.
-      if (!takesArguments && commandOptions.rest.isNotEmpty) {
-        log.error('Command "${commandOptions.name}" does not take any '
-                  'arguments.');
-        this.printUsage();
-        return flushThenExit(exit_codes.USAGE);
-      }
+    var captureStackChains =
+        options['trace'] || options['verbose'] || options['verbosity'] == 'all';
+    captureErrors(() {
+      return syncFuture(() {
+        // Make sure there aren't unexpected arguments.
+        if (!takesArguments && commandOptions.rest.isNotEmpty) {
+          log.error('Command "${commandOptions.name}" does not take any '
+                    'arguments.');
+          this.printUsage();
+          return flushThenExit(exit_codes.USAGE);
+        }
 
-      if (requiresEntrypoint) {
-        // TODO(rnystrom): Will eventually need better logic to walk up
-        // subdirectories until we hit one that looks package-like. For now,
-        // just assume the cwd is it.
-        entrypoint = new Entrypoint(path.current, cache);
-      }
+        if (requiresEntrypoint) {
+          // TODO(rnystrom): Will eventually need better logic to walk up
+          // subdirectories until we hit one that looks package-like. For now,
+          // just assume the cwd is it.
+          entrypoint = new Entrypoint(path.current, cache);
+        }
 
-      var commandFuture = onRun();
-      if (commandFuture == null) return true;
+        var commandFuture = onRun();
+        if (commandFuture == null) return true;
 
-      return commandFuture;
-    }).whenComplete(() => cache.deleteTempDir())
-        .catchError(handleError)
+        return commandFuture;
+      }).whenComplete(() => cache.deleteTempDir());
+    }, captureStackChains: captureStackChains).catchError(handleError)
         .then((_) {
       // Explicitly exit on success to ensure that any dangling dart:io handles
       // don't cause the process to never terminate.
diff --git a/sdk/lib/_internal/pub/lib/src/command/build.dart b/sdk/lib/_internal/pub/lib/src/command/build.dart
index 1c9e37e..b13e4d8 100644
--- a/sdk/lib/_internal/pub/lib/src/command/build.dart
+++ b/sdk/lib/_internal/pub/lib/src/command/build.dart
@@ -44,7 +44,7 @@
 
   Future onRun() {
     if (!dirExists(source)) {
-      throw new ApplicationException("There is no '$source' directory.");
+      throw new ApplicationException('There is no "$source" directory.');
     }
 
     cleanDir(target);
@@ -52,9 +52,7 @@
     var dart2jsTransformer;
     var builtFiles = 0;
 
-    return entrypoint.ensureLockFileIsUpToDate().then((_) {
-      return entrypoint.loadPackageGraph();
-    }).then((graph) {
+    return entrypoint.loadPackageGraph().then((graph) {
       dart2jsTransformer = new Dart2JSTransformer(graph, mode);
       var builtInTransformers = [
         dart2jsTransformer,
diff --git a/sdk/lib/_internal/pub/lib/src/command/get.dart b/sdk/lib/_internal/pub/lib/src/command/get.dart
index 51c5f0a..fbe86ae 100644
--- a/sdk/lib/_internal/pub/lib/src/command/get.dart
+++ b/sdk/lib/_internal/pub/lib/src/command/get.dart
@@ -22,7 +22,7 @@
   }
 
   Future onRun() {
-    return entrypoint.getDependencies()
+    return entrypoint.acquireDependencies()
         .then((_) => log.message("Got dependencies!"));
   }
 }
diff --git a/sdk/lib/_internal/pub/lib/src/command/lish.dart b/sdk/lib/_internal/pub/lib/src/command/lish.dart
index 6d75814..bd9c445 100644
--- a/sdk/lib/_internal/pub/lib/src/command/lish.dart
+++ b/sdk/lib/_internal/pub/lib/src/command/lish.dart
@@ -15,7 +15,6 @@
 import '../io.dart';
 import '../log.dart' as log;
 import '../oauth2.dart' as oauth2;
-import '../sdk.dart' as sdk;
 import '../source/hosted.dart';
 import '../utils.dart';
 import '../validator.dart';
@@ -106,7 +105,7 @@
       // Show the package contents so the user can verify they look OK.
       var package = entrypoint.root;
       log.message(
-          'Publishing "${package.name}" ${package.version} to $server:\n'
+          'Publishing ${package.name} ${package.version} to $server:\n'
           '${generateTree(files, baseDir: entrypoint.root.dir)}');
 
       return createTarGz(files, baseDir: entrypoint.root.dir);
diff --git a/sdk/lib/_internal/pub/lib/src/command/serve.dart b/sdk/lib/_internal/pub/lib/src/command/serve.dart
index f6df4ce..f99df21 100644
--- a/sdk/lib/_internal/pub/lib/src/command/serve.dart
+++ b/sdk/lib/_internal/pub/lib/src/command/serve.dart
@@ -65,9 +65,7 @@
       return flushThenExit(exit_codes.USAGE);
     }
 
-    return entrypoint.ensureLockFileIsUpToDate().then((_) {
-      return entrypoint.loadPackageGraph();
-    }).then((graph) {
+    return entrypoint.loadPackageGraph().then((graph) {
       var builtInTransformers = [new DartForwardingTransformer(mode)];
       if (useDart2JS) {
         builtInTransformers.add(new Dart2JSTransformer(graph, mode));
diff --git a/sdk/lib/_internal/pub/lib/src/command/upgrade.dart b/sdk/lib/_internal/pub/lib/src/command/upgrade.dart
index 306e027..a14ab6f 100644
--- a/sdk/lib/_internal/pub/lib/src/command/upgrade.dart
+++ b/sdk/lib/_internal/pub/lib/src/command/upgrade.dart
@@ -26,15 +26,19 @@
   }
 
   Future onRun() {
-    var future;
-    if (commandOptions.rest.isEmpty) {
-      future = entrypoint.upgradeAllDependencies();
-    } else {
-      future = entrypoint.upgradeDependencies(commandOptions.rest);
-    }
+    var upgradeAll = commandOptions.rest.isEmpty;
+    return entrypoint.acquireDependencies(useLatest: commandOptions.rest,
+        upgradeAll: upgradeAll).then((numChanged) {
+      // TODO(rnystrom): Show a more detailed message about what was added,
+      // removed, modified, and/or upgraded?
+      if (numChanged == 0) {
+        log.message("No dependencies changed.");
+      } else if (numChanged == 1) {
+        log.message("Changed $numChanged dependency!");
+      } else {
+        log.message("Changed $numChanged dependencies!");
+      }
 
-    return future.then((_) {
-      log.message("Dependencies upgraded!");
       if (isOffline) {
         log.warning("Warning: Upgrading when offline may not update you to the "
                     "latest versions of your dependencies.");
diff --git a/sdk/lib/_internal/pub/lib/src/command/uploader.dart b/sdk/lib/_internal/pub/lib/src/command/uploader.dart
index 330efcc..5158662 100644
--- a/sdk/lib/_internal/pub/lib/src/command/uploader.dart
+++ b/sdk/lib/_internal/pub/lib/src/command/uploader.dart
@@ -16,6 +16,7 @@
 import '../log.dart' as log;
 import '../oauth2.dart' as oauth2;
 import '../source/hosted.dart';
+import '../utils.dart';
 
 /// Handles the `uploader` pub command.
 class UploaderCommand extends PubCommand {
@@ -57,7 +58,7 @@
       return flushThenExit(exit_codes.USAGE);
     }
 
-    return new Future.sync(() {
+    return syncFuture(() {
       var package = commandOptions['package'];
       if (package != null) return package;
       return new Entrypoint(path.current, cache).root.name;
diff --git a/sdk/lib/_internal/pub/lib/src/dart.dart b/sdk/lib/_internal/pub/lib/src/dart.dart
index bf6cb2a..6833282 100644
--- a/sdk/lib/_internal/pub/lib/src/dart.dart
+++ b/sdk/lib/_internal/pub/lib/src/dart.dart
@@ -12,8 +12,6 @@
 import 'package:path/path.dart' as path;
 import 'package:stack_trace/stack_trace.dart';
 import '../../../compiler/compiler.dart' as compiler;
-import '../../../compiler/implementation/source_file_provider.dart'
-    show FormattingDiagnosticHandler, CompilerSourceFileProvider;
 import '../../../compiler/implementation/filenames.dart'
     show appendSlash;
 
@@ -53,7 +51,7 @@
 /// if [packageRoot] is passed that will be used instead.
 Future compile(String entrypoint, CompilerProvider provider, {
     String packageRoot, bool toDart: false, bool minify: true}) {
-  return new Future.sync(() {
+  return syncFuture(() {
     var options = <String>['--categories=Client,Server'];
     if (toDart) options.add('--output-type=dart');
     if (minify) options.add('--minify');
@@ -62,14 +60,14 @@
       packageRoot = path.join(path.dirname(entrypoint), 'packages');
     }
 
-    return compiler.compile(
+    return Chain.track(compiler.compile(
         path.toUri(entrypoint),
         path.toUri(appendSlash(_libPath)),
         path.toUri(appendSlash(packageRoot)),
         provider.provideInput,
         provider.handleDiagnostic,
         options,
-        provider.provideOutput);
+        provider.provideOutput));
   });
 }
 
@@ -106,15 +104,16 @@
     var dartPath = path.join(dir, 'runInIsolate.dart');
     writeTextFile(dartPath, code, dontLogContents: true);
     var port = new ReceivePort();
-    return Isolate.spawn(_isolateBuffer, {
+    return Chain.track(Isolate.spawn(_isolateBuffer, {
       'replyTo': port.sendPort,
       'uri': path.toUri(dartPath).toString(),
       'message': message
-    }).then((_) => port.first).then((response) {
+    })).then((_) => port.first).then((response) {
       if (response['type'] == 'success') return null;
       assert(response['type'] == 'error');
       return new Future.error(
-          new CrossIsolateException.deserialize(response['error']));
+          new CrossIsolateException.deserialize(response['error']),
+          new Chain.current());
     });
   });
 }
@@ -127,11 +126,10 @@
 /// Adding an additional isolate in the middle works around this.
 void _isolateBuffer(message) {
   var replyTo = message['replyTo'];
-  // TODO(floitsch): If we do it right we shouldn't need to capture synchronous
-  // errors.
-  new Future.sync(() {
-    return Isolate.spawnUri(Uri.parse(message['uri']), [], message['message']);
-  }).then((_) => replyTo.send({'type': 'success'})).catchError((e, stack) {
+  Chain.track(Isolate.spawnUri(
+          Uri.parse(message['uri']), [], message['message']))
+      .then((_) => replyTo.send({'type': 'success'}))
+      .catchError((e, stack) {
     replyTo.send({
       'type': 'error',
       'error': CrossIsolateException.serialize(e, stack)
diff --git a/sdk/lib/_internal/pub/lib/src/entrypoint.dart b/sdk/lib/_internal/pub/lib/src/entrypoint.dart
index cf7e5d0..918736a 100644
--- a/sdk/lib/_internal/pub/lib/src/entrypoint.dart
+++ b/sdk/lib/_internal/pub/lib/src/entrypoint.dart
@@ -17,7 +17,6 @@
 import 'solver/version_solver.dart';
 import 'system_cache.dart';
 import 'utils.dart';
-import 'version.dart';
 
 /// Pub operates over a directed graph of dependencies that starts at a root
 /// "entrypoint" package. This is typically the package where the current
@@ -81,7 +80,7 @@
     var packageDir = path.join(packagesDir, id.name);
     var source;
 
-    var future = new Future.sync(() {
+    var future = syncFuture(() {
       ensureDir(path.dirname(packageDir));
 
       if (entryExists(packageDir)) {
@@ -109,60 +108,36 @@
     return future;
   }
 
-  /// Gets all dependencies of the [root] package, respecting the [LockFile]
-  /// if present.
+  /// Gets all dependencies of the [root] package.
   ///
-  /// Returns a [Future] that completes when all dependencies are available.
-  Future getDependencies() {
-    return new Future.sync(() {
-      return resolveVersions(cache.sources, root, lockFile: loadLockFile());
-    }).then(_getDependencies);
-  }
-
-  /// Gets the latest available versions of all dependencies of the [root]
-  /// package, writing a new [LockFile].
+  /// [useLatest], if provided, defines a list of packages that will be
+  /// unlocked and forced to their latest versions. If [upgradeAll] is
+  /// true, the previous lockfile is ignored and all packages are re-resolved
+  /// from scratch. Otherwise, it will attempt to preserve the versions of all
+  /// previously locked packages.
   ///
-  /// Returns a [Future] that completes when all dependencies are available.
-  Future upgradeAllDependencies() {
-    return resolveVersions(cache.sources, root).then(_getDependencies);
-  }
-
-  /// Gets the latest available versions of [dependencies], while leaving
-  /// other dependencies as specified by the [LockFile] if possible.
+  /// If [useLatest] is non-empty or [upgradeAll] is true, displays a detailed
+  /// report of the changes made relative to the previous lockfile.
   ///
-  /// Returns a [Future] that completes when all dependencies are available.
-  Future upgradeDependencies(List<String> dependencies) {
-    return new Future.sync(() {
-      return resolveVersions(cache.sources, root,
-          lockFile: loadLockFile(), useLatest: dependencies);
-    }).then(_getDependencies);
-  }
+  /// Returns a [Future] that completes to the number of changed dependencies.
+  /// It completes when an up-to-date lockfile has been generated and all
+  /// dependencies are available.
+  Future<int> acquireDependencies({List<String> useLatest,
+      bool upgradeAll: false}) {
+    var numChanged = 0;
 
-  /// Removes the old packages directory, gets all dependencies listed in
-  /// [result], and writes a [LockFile].
-  Future _getDependencies(SolveResult result) {
-    return new Future.sync(() {
+    return syncFuture(() {
+      return resolveVersions(cache.sources, root, lockFile: loadLockFile(),
+          useLatest: useLatest, upgradeAll: upgradeAll);
+    }).then((result) {
       if (!result.succeeded) throw result.error;
 
-      // Warn the user if any overrides were in effect.
-      if (result.overrides.isNotEmpty) {
-        var buffer = new StringBuffer();
-        buffer.write("Warning: You are using these overridden dependencies:");
-        for (var override in result.overrides) {
-          var source = cache.sources[override.source];
-          buffer.write("\n- ${override.name}");
-          if (override.constraint != VersionConstraint.any) {
-            buffer.write(" version ${override.constraint}");
-          }
-          if (source != cache.sources.defaultSource) {
-            var description = source.formatDescription(root.dir,
-                override.description);
-            buffer.write(" (from ${override.source} $description)");
-          }
-        }
-        log.warning(buffer);
-      }
+      // TODO(rnystrom): Should also show the report if there were changes.
+      // That way pub get/build/serve will show the report when relevant.
+      // https://code.google.com/p/dart/issues/detail?id=15587
+      numChanged = result.showReport(showAll: useLatest != null || upgradeAll);
 
+      // Install the packages.
       cleanDir(packagesDir);
       return Future.wait(result.packages.map((id) {
         if (id.isRoot) return new Future.value(id);
@@ -172,6 +147,8 @@
       _saveLockFile(ids);
       _linkSelf();
       _linkSecondaryPackageDirs();
+
+      return numChanged;
     });
   }
 
@@ -234,8 +211,8 @@
 
   /// Gets dependencies if the lockfile is out of date with respect to the
   /// pubspec.
-  Future ensureLockFileIsUpToDate() {
-    return new Future.sync(() {
+  Future _ensureLockFileIsUpToDate() {
+    return syncFuture(() {
       var lockFile = loadLockFile();
 
       // If we don't have a current lock file, we definitely need to install.
@@ -265,23 +242,48 @@
       });
     }).then((upToDate) {
       if (upToDate) return null;
-      return getDependencies().then((_) => log.message("Got dependencies!"));
+      return acquireDependencies().then((_) {
+        log.message("Got dependencies!");
+      });
     });
   }
 
+  /// Warns users if they have directory or file named `assets` _anywhere_
+  /// inside `web` directory.
+  void _warnOnAssetsPaths() {
+    var webDir = path.join(root.dir, 'web');
+    if (!dirExists(webDir)) return;
+
+    listDir(webDir, recursive: true)
+      .where((p) => path.basename(p) == 'assets')
+      .forEach((p) {
+        var assetsPath = path.relative(p, from: root.dir);
+        log.warning(
+            'Warning: Pub reserves paths containing "assets" for using assets '
+            'from packages. Please rename the path "$assetsPath".');
+      });
+  }
+
+  /// Loads the package graph for the application and all of its transitive
+  /// dependencies. Before loading makes sure the lockfile and dependencies are
+  /// installed and up to date.
+  Future<PackageGraph> loadPackageGraph() =>
+    _ensureLockFileIsUpToDate()
+      .then((_) {
+        _warnOnAssetsPaths();
+        return _loadPackageGraph();
+      });
+
   /// Loads the package graph for the application and all of its transitive
   /// dependencies.
-  Future<PackageGraph> loadPackageGraph() {
+  Future<PackageGraph> _loadPackageGraph() {
     var lockFile = loadLockFile();
     return Future.wait(lockFile.packages.values.map((id) {
       var source = cache.sources[id.source];
       return source.getDirectory(id)
           .then((dir) => new Package.load(id.name, dir, cache.sources));
     })).then((packages) {
-      var packageMap = <String, Package>{};
-      for (var package in packages) {
-        packageMap[package.name] = package;
-      }
+      var packageMap = new Map.fromIterable(packages, key: (p) => p.name);
       packageMap[root.name] = root;
       return new PackageGraph(this, lockFile, packageMap);
     });
diff --git a/sdk/lib/_internal/pub/lib/src/http.dart b/sdk/lib/_internal/pub/lib/src/http.dart
index 017b387..afaefd8 100644
--- a/sdk/lib/_internal/pub/lib/src/http.dart
+++ b/sdk/lib/_internal/pub/lib/src/http.dart
@@ -32,10 +32,6 @@
 /// it's not supported.
 final PUB_API_HEADERS = const {'Accept': 'application/vnd.pub.v2+json'};
 
-/// Whether dart:io's SecureSocket has been initialized with pub's resources
-/// yet.
-bool _initializedSecureSocket = false;
-
 /// An HTTP client that transforms 40* errors and socket exceptions into more
 /// user-friendly error messages.
 class PubHttpClient extends http.BaseClient {
@@ -44,11 +40,7 @@
   http.Client inner;
 
   PubHttpClient([http.Client inner])
-      : this.inner = inner == null ? new http.Client() : inner {
-    if (!_initializedSecureSocket) {
-      SecureSocket.initialize(database: resourcePath('certs'));
-    }
-  }
+      : this.inner = inner == null ? new http.Client() : inner;
 
   Future<http.StreamedResponse> send(http.BaseRequest request) {
     _requestStopwatches[request] = new Stopwatch()..start();
diff --git a/sdk/lib/_internal/pub/lib/src/io.dart b/sdk/lib/_internal/pub/lib/src/io.dart
index bc6ffd1..06bd104 100644
--- a/sdk/lib/_internal/pub/lib/src/io.dart
+++ b/sdk/lib/_internal/pub/lib/src/io.dart
@@ -190,7 +190,7 @@
   log.io("Creating $file from stream.");
 
   return _descriptorPool.withResource(() {
-    return stream.pipe(new File(file).openWrite()).then((_) {
+    return Chain.track(stream.pipe(new File(file).openWrite())).then((_) {
       log.fine("Created $file from stream.");
       return file;
     });
@@ -372,7 +372,7 @@
   // directory since it may just be a leaf application that only has
   // code in bin or web.
   if (!isSelfLink) {
-    log.warning('Warning: Package "$name" does not have a "lib" directory so '
+    log.warning('Warning: Package $name does not have a "lib" directory so '
                 'you will not be able to import any libraries from it.');
   }
 }
@@ -404,7 +404,7 @@
 
 /// A line-by-line stream of standard input.
 final Stream<String> stdinLines = streamToLines(
-    new ByteStream(stdin).toStringStream());
+    new ByteStream(Chain.track(stdin)).toStringStream());
 
 /// Displays a message and reads a yes/no confirmation from the user. Returns
 /// a [Future] that completes to `true` if the user confirms or `false` if they
@@ -435,8 +435,12 @@
 /// This returns a Future that will never complete, since the program will have
 /// exited already. This is useful to prevent Future chains from proceeding
 /// after you've decided to exit.
-Future flushThenExit(int status) =>
-  Future.wait([stdout.close(), stderr.close()]).then((_) => exit(status));
+Future flushThenExit(int status) {
+  return Future.wait([
+    Chain.track(stdout.close()),
+    Chain.track(stderr.close())
+  ]).then((_) => exit(status));
+}
 
 /// Returns a [EventSink] that pipes all data to [consumer] and a [Future] that
 /// will succeed when [EventSink] is closed or fail with any errors that occur
@@ -586,15 +590,16 @@
 
     var pair = consumerToSink(process.stdin);
     _stdin = pair.first;
-    _stdinClosed = errorGroup.registerFuture(pair.last);
+    _stdinClosed = errorGroup.registerFuture(Chain.track(pair.last));
 
     _stdout = new ByteStream(
-        errorGroup.registerStream(process.stdout));
+        errorGroup.registerStream(Chain.track(process.stdout)));
     _stderr = new ByteStream(
-        errorGroup.registerStream(process.stderr));
+        errorGroup.registerStream(Chain.track(process.stderr)));
 
     var exitCodeCompleter = new Completer();
-    _exitCode = errorGroup.registerFuture(exitCodeCompleter.future);
+    _exitCode = errorGroup.registerFuture(
+        Chain.track(exitCodeCompleter.future));
     _process.exitCode.then((code) => exitCodeCompleter.complete(code));
   }
 
@@ -620,10 +625,10 @@
 
   log.process(executable, args);
 
-  return fn(executable,
-            args,
-            workingDirectory: workingDir,
-            environment: environment);
+  return Chain.track(fn(executable,
+      args,
+      workingDirectory: workingDir,
+      environment: environment));
 }
 
 /// Wraps [input] to provide a timeout. If [input] completes before
@@ -641,7 +646,7 @@
   var timer = new Timer(duration, () {
     completer.completeError(new TimeoutException(
         'Timed out while $description.', duration),
-        new Trace.current());
+        new Chain.current());
   });
   input.then((value) {
     if (completer.isCompleted) return;
@@ -663,9 +668,9 @@
 /// Returns a future that completes to the value that the future returned from
 /// [fn] completes to.
 Future withTempDir(Future fn(String path)) {
-  return new Future.sync(() {
+  return syncFuture(() {
     var tempDir = createSystemTempDir();
-    return new Future.sync(() => fn(tempDir))
+    return syncFuture(() => fn(tempDir))
         .whenComplete(() => deleteEntry(tempDir));
   });
 }
@@ -757,14 +762,12 @@
 /// considered to be [baseDir], which defaults to the current working directory.
 /// Returns a [ByteStream] that will emit the contents of the archive.
 ByteStream createTarGz(List contents, {baseDir}) {
-  return new ByteStream(futureStream(new Future.sync(() {
+  return new ByteStream(futureStream(syncFuture(() {
     var buffer = new StringBuffer();
     buffer.write('Creating .tag.gz stream containing:\n');
     contents.forEach((file) => buffer.write('$file\n'));
     log.fine(buffer.toString());
 
-    var controller = new StreamController<List<int>>(sync: true);
-
     if (baseDir == null) baseDir = path.current;
     baseDir = path.absolute(baseDir);
     contents = contents.map((entry) {
@@ -788,7 +791,7 @@
     // Don't use [withTempDir] here because we don't want to delete the temp
     // directory until the returned stream has closed.
     var tempDir = createSystemTempDir();
-    return new Future.sync(() {
+    return syncFuture(() {
       // Create the tar file.
       var tarFile = path.join(tempDir, "intermediate.tar");
       var args = ["a", "-w$baseDir", tarFile];
diff --git a/sdk/lib/_internal/pub/lib/src/log.dart b/sdk/lib/_internal/pub/lib/src/log.dart
index 86c2b7f..bbbcb3c 100644
--- a/sdk/lib/_internal/pub/lib/src/log.dart
+++ b/sdk/lib/_internal/pub/lib/src/log.dart
@@ -6,7 +6,6 @@
 library pub.log;
 
 import 'dart:async';
-import 'dart:collection';
 import 'dart:io';
 
 import 'io.dart';
@@ -35,10 +34,13 @@
 /// progress is done, a single entry will be added to the log for it.
 String _progressMessage;
 
+final _cyan = getSpecial('\u001b[36m');
 final _green = getSpecial('\u001b[32m');
+final _magenta = getSpecial('\u001b[35m');
 final _red = getSpecial('\u001b[31m');
 final _yellow = getSpecial('\u001b[33m');
 final _none = getSpecial('\u001b[0m');
+final _bold = getSpecial('\u001b[1m');
 
 /// An enum type for defining the different logging levels. By default, [ERROR]
 /// and [WARNING] messages are printed to sterr. [MESSAGE] messages are printed
@@ -218,16 +220,42 @@
   return callback().whenComplete(_stopProgress);
 }
 
+/// Wraps [text] in the ANSI escape codes to make it bold when on a platform
+/// that supports that.
+///
+/// Use this to highlight the most important piece of a long chunk of text.
+String bold(text) => "$_bold$text$_none";
+
+/// Wraps [text] in the ANSI escape codes to color it cyan when on a platform
+/// that supports that.
+///
+/// Use this to highlight something interesting but neither good nor bad.
+String cyan(text) => "$_cyan$text$_none";
+
 /// Wraps [text] in the ANSI escape codes to color it green when on a platform
 /// that supports that.
+///
+/// Use this to highlight something successful or otherwise positive.
 String green(text) => "$_green$text$_none";
 
+/// Wraps [text] in the ANSI escape codes to color it magenta when on a
+/// platform that supports that.
+///
+/// Use this to highlight something risky that the user should be aware of but
+/// may intend to do.
+String magenta(text) => "$_magenta$text$_none";
+
 /// Wraps [text] in the ANSI escape codes to color it red when on a platform
 /// that supports that.
+///
+/// Use this to highlight unequivocal errors, problems, or failures.
 String red(text) => "$_red$text$_none";
 
 /// Wraps [text] in the ANSI escape codes to color it yellow when on a platform
 /// that supports that.
+///
+/// Use this to highlight warnings, cautions or other things that are bad but
+/// do not prevent the user's goal from being reached.
 String yellow(text) => "$_yellow$text$_none";
 
 /// Stops the running progress indicator, if currently running.
diff --git a/sdk/lib/_internal/pub/lib/src/solver/backtracking_solver.dart b/sdk/lib/_internal/pub/lib/src/solver/backtracking_solver.dart
index 882ef36..6229c6e 100644
--- a/sdk/lib/_internal/pub/lib/src/solver/backtracking_solver.dart
+++ b/sdk/lib/_internal/pub/lib/src/solver/backtracking_solver.dart
@@ -55,13 +55,19 @@
 class BacktrackingSolver {
   final SourceRegistry sources;
   final Package root;
+
+  /// The lockfile that was present before solving.
   final LockFile lockFile;
+
   final PubspecCache cache;
 
   /// The set of packages that are being explicitly upgraded. The solver will
   /// only allow the very latest version for each of these packages.
   final _forceLatest = new Set<String>();
 
+  /// If this is set, the contents of [lockFile] are ignored while solving.
+  final bool _upgradeAll;
+
   /// The set of packages whose dependecy is being overridden by the root
   /// package, keyed by the name of the package.
   ///
@@ -93,12 +99,12 @@
   var _attemptedSolutions = 1;
 
   BacktrackingSolver(SourceRegistry sources, this.root, this.lockFile,
-                     List<String> useLatest)
+                     List<String> useLatest, {bool upgradeAll: false})
       : sources = sources,
-        cache = new PubspecCache(sources) {
+        cache = new PubspecCache(sources),
+        _upgradeAll = upgradeAll {
     for (var package in useLatest) {
-      forceLatestVersion(package);
-      lockFile.packages.remove(package);
+      _forceLatest.add(package);
     }
 
     for (var override in root.dependencyOverrides) {
@@ -126,12 +132,14 @@
       _validateSdkConstraint(root.pubspec);
       return _traverseSolution();
     }).then((packages) {
-      return new SolveResult(packages, overrides, null, attemptedSolutions);
+      return new SolveResult.success(sources, root, lockFile, packages,
+          overrides, _getAvailableVersions(packages), attemptedSolutions);
     }).catchError((error) {
       if (error is! SolveFailure) throw error;
 
       // Wrap a failure in a result so we can attach some other data.
-      return new SolveResult(null, overrides, error, attemptedSolutions);
+      return new SolveResult.failure(sources, root, lockFile, overrides,
+          error, attemptedSolutions);
     }).whenComplete(() {
       // Gather some solving metrics.
       var buffer = new StringBuffer();
@@ -148,8 +156,30 @@
     });
   }
 
-  void forceLatestVersion(String package) {
-    _forceLatest.add(package);
+  /// Generates a map containing all of the known available versions for each
+  /// package in [packages].
+  ///
+  /// The version list may not always be complete. The the package is the root
+  /// root package, or its a package that we didn't unlock while solving
+  /// because we weren't trying to upgrade it, we will just know the current
+  /// version.
+  Map<String, List<Version>> _getAvailableVersions(List<PackageId> packages) {
+    var availableVersions = new Map<String, List<Version>>();
+    for (var package in packages) {
+      var cached = cache.getCachedVersions(package.toRef());
+      var versions;
+      if (cached != null) {
+        versions = cached.map((id) => id.version).toList();
+      } else {
+        // If the version list was never requested, just use the one known
+        // version.
+        versions = [package.version];
+      }
+
+      availableVersions[package.name] = versions;
+    }
+
+    return availableVersions;
   }
 
   /// Adds [versions], which is the list of all allowed versions of a given
@@ -179,7 +209,12 @@
 
   /// Gets the version of [package] currently locked in the lock file. Returns
   /// `null` if it isn't in the lockfile (or has been unlocked).
-  PackageId getLocked(String package) => lockFile.packages[package];
+  PackageId getLocked(String package) {
+    if (_upgradeAll) return null;
+    if (_forceLatest.contains(package)) return null;
+
+    return lockFile.packages[package];
+  }
 
   /// Traverses the root package's dependency graph using the current potential
   /// solution. If successful, completes to the solution. If not, backtracks
@@ -251,6 +286,15 @@
       // when that happens.
       var selected = _selected[i].current;
 
+      // If the failure is a disjoint version range, then no possible versions
+      // for that package can match and there's no reason to try them. Instead,
+      // just backjump past it.
+      if (failure is DisjointConstraintException &&
+          selected.name == failure.package) {
+        logSolve("skipping past disjoint selected ${selected.name}");
+        continue;
+      }
+
       // If we get to the package that failed, backtrack to here.
       if (selected.name == failure.package) {
         logSolve('backjump to failed package ${selected.name}');
@@ -335,10 +379,11 @@
     buffer.writeln("Solving dependencies:");
     for (var package in root.dependencies) {
       buffer.write("- $package");
+      var locked = getLocked(package.name);
       if (_forceLatest.contains(package.name)) {
         buffer.write(" (use latest)");
-      } else if (lockFile.packages.containsKey(package.name)) {
-        var version = lockFile.packages[package.name].version;
+      } else if (locked != null) {
+        var version = locked.version;
         buffer.write(" (locked to $version)");
       }
       buffer.writeln();
@@ -473,12 +518,35 @@
         var dependencies = _getDependencies(dep.name);
         dependencies.add(new Dependency(depender, dep));
 
+        // If the package is barback, pub has an implicit version constraint on
+        // it since pub itself uses barback too. Note that we don't check for
+        // the hosted source here because we still want to do this even when
+        // people on the Dart team are on the bleeding edge and have a path
+        // dependency on the tip version of barback in the Dart repo.
+        //
+        // The length check here is to ensure we only add the barback
+        // dependency once.
+        if (dep.name == "barback" && dependencies.length == 1) {
+          var range = new VersionRange(
+              min: barback.supportedVersion, includeMin: true,
+              max: barback.supportedVersion.nextMinor, includeMax: false);
+          _solver.logSolve('add implicit $range pub dependency on barback');
+
+          // Use the same source and description as the explicit dependency.
+          // That way, this doesn't fail with a source/desc conflict if users
+          // (like Dart team members) use things like a path dependency to
+          // find barback.
+          var barbackDep = new PackageDep(dep.name, dep.source, range,
+              dep.description);
+          dependencies.add(new Dependency("pub itself", barbackDep));
+        }
+
         var constraint = _getConstraint(dep.name);
 
         // See if it's possible for a package to match that constraint.
         if (constraint.isEmpty) {
           _solver.logSolve('disjoint constraints on ${dep.name}');
-          throw new DisjointConstraintException(depender, dependencies);
+          throw new DisjointConstraintException(dep.name, dependencies);
         }
 
         var selected = _validateSelected(dep, constraint);
@@ -525,6 +593,14 @@
       }
 
       return allowed;
+    }).catchError((error, stackTrace) {
+      if (error is PackageNotFoundException) {
+        // Show the user why the package was being requested.
+        throw new DependencyNotFoundException(
+            dep.name, error, _getDependencies(dep.name));
+      }
+
+      throw error;
     });
   }
 
@@ -603,19 +679,6 @@
         .map((dep) => dep.dep.constraint)
         .fold(VersionConstraint.any, (a, b) => a.intersect(b));
 
-    // If the package is barback, pub has an implicit version constraint on it
-    // since pub itself uses barback too. Note that we don't check for the
-    // hosted source here because we still want to do this even when people on
-    // the Dart team are on the bleeding edge and have a path dependency on the
-    // tip version of barback in the Dart repo.
-    if (name == "barback") {
-      var range = new VersionRange(
-          min: barback.supportedVersion, includeMin: true,
-          max: barback.supportedVersion.nextMinor, includeMax: false);
-      constraint = constraint.intersect(range);
-      _solver.logSolve('add implicit $range constraint to barback');
-    }
-
     return constraint;
   }
 
diff --git a/sdk/lib/_internal/pub/lib/src/solver/solve_report.dart b/sdk/lib/_internal/pub/lib/src/solver/solve_report.dart
new file mode 100644
index 0000000..6856878
--- /dev/null
+++ b/sdk/lib/_internal/pub/lib/src/solver/solve_report.dart
@@ -0,0 +1,267 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library pub.solver.solve_report;
+
+import '../lock_file.dart';
+import '../log.dart' as log;
+import '../package.dart';
+import '../source_registry.dart';
+import '../utils.dart';
+import 'version_solver.dart';
+
+/// Generates and displays nicely formatted reports for the results of running
+/// a version resolution.
+///
+/// If [showAll] is true, then all of the previous and current dependencies
+/// are shown and their changes relative to the previous lock file are
+/// highlighted. Otherwise, only overrides are shown.
+///
+/// Returns the number of changed dependencies.
+int show(SourceRegistry sources, Package root, LockFile previousLockFile,
+         SolveResult result, {bool showAll: false}) {
+  var report = new _SolveReport(sources, root, previousLockFile, result);
+  return report.show(showAll: showAll);
+}
+
+/// Unlike [SolveResult], which is the static data describing a resolution,
+/// this class contains the mutable state used while generating the report
+/// itself. It's a report builder.
+class _SolveReport {
+  final SourceRegistry _sources;
+  final Package _root;
+  final LockFile _previousLockFile;
+  final SolveResult _result;
+
+  /// The dependencies in [_result], keyed by package name.
+  final _dependencies = new Map<String, PackageId>();
+
+  final _output = new StringBuffer();
+
+  /// To avoid emitting trailing newlines, we track if any are needed and only
+  /// emit then when text on the next line is about to be written.
+  // TODO(rnystrom): Move this into a separate class that wraps any StringSink
+  // with this logic.
+  int _pendingLines = 0;
+
+  _SolveReport(this._sources, this._root, this._previousLockFile,
+      this._result) {
+    // Fill the map so we can use it later.
+    for (var id in _result.packages) {
+      _dependencies[id.name] = id;
+    }
+  }
+
+  /// Displays a report of the results of the version resolution relative to
+  /// the previous lock file.
+  ///
+  /// If [showAll] is true, then all of the previous and current dependencies
+  /// are shown and their changes relative to the previous lock file are
+  /// highlighted. Otherwise, only overrides are shown.
+  ///
+  /// Returns the number of changed dependencies.
+  int show({bool showAll: false}) {
+    if (showAll) _reportChanges();
+    _reportOverrides();
+
+    // Count how many dependencies actually changed.
+    var dependencies = _dependencies.keys.toSet();
+    dependencies.addAll(_previousLockFile.packages.keys);
+    dependencies.remove(_root.name);
+
+    return dependencies.where((name) {
+      var oldId = _previousLockFile.packages[name];
+      var newId = _dependencies[name];
+
+      // Added or removed dependencies count.
+      if (oldId == null) return true;
+      if (newId == null) return true;
+
+      // The dependency existed before, so see if it was modified.
+      return !_descriptionsEqual(oldId, newId) ||
+          oldId.version != newId.version;
+    }).length;
+  }
+
+  /// Displays a report of all of the previous and current dependencies and
+  /// how they have changed.
+  void _reportChanges() {
+    _output.clear();
+
+    // Show the new set of dependencies ordered by name.
+    var names = _result.packages.map((id) => id.name).toList();
+    names.remove(_root.name);
+    names.sort();
+    names.forEach(_reportPackage);
+
+    // Show any removed ones.
+    var removed = _previousLockFile.packages.keys.toSet();
+    removed.removeAll(names);
+    if (removed.isNotEmpty) {
+      _writeln("These packages are no longer being depended on:");
+      removed = removed.toList();
+      removed.sort();
+      removed.forEach(_reportPackage);
+    }
+
+    log.message(_output.toString());
+  }
+
+  /// Displays a warning about the overrides currently in effect.
+  void _reportOverrides() {
+    _output.clear();
+
+    if (_result.overrides.isNotEmpty) {
+      _writeln("Warning: You are using these overridden dependencies:");
+      var overrides = _result.overrides.map((dep) => dep.name).toList();
+      overrides.sort((a, b) => a.compareTo(b));
+
+      overrides.forEach(
+          (name) => _reportPackage(name, highlightOverride: false));
+
+      log.warning(_output.toString());
+    }
+  }
+
+  /// Reports the results of the upgrade on the package named [name].
+  ///
+  /// If [highlightOverride] is true (or absent), writes "(override)" next to
+  /// overridden packages.
+  void _reportPackage(String name, {bool highlightOverride}) {
+    if (highlightOverride == null) highlightOverride = true;
+
+    var newId = _dependencies[name];
+    var oldId = _previousLockFile.packages[name];
+    var id = newId != null ? newId : oldId;
+
+    var isOverridden = _result.overrides.map(
+        (dep) => dep.name).contains(id.name);
+
+    var changed = false;
+
+    // Show a one-character "icon" describing the change. They are:
+    //
+    //     ! The package is being overridden.
+    //     - The package was removed.
+    //     + The package was added.
+    //     > The package was upgraded from a lower version.
+    //     < The package was downgraded from a higher version.
+    //     * Any other change between the old and new package.
+    if (isOverridden) {
+      _write(log.magenta("! "));
+    } else if (newId == null) {
+      _write(log.red("- "));
+    } else if (oldId == null) {
+      _write(log.green("+ "));
+    } else if (!_descriptionsEqual(oldId, newId)) {
+      _write(log.cyan("* "));
+      changed = true;
+    } else if (oldId.version < newId.version) {
+      _write(log.green("> "));
+      changed = true;
+    } else if (oldId.version > newId.version) {
+      _write(log.cyan("< "));
+      changed = true;
+    } else {
+      // Unchanged.
+      _write("  ");
+    }
+
+    _write(log.bold(id.name));
+    _write(" ");
+    _writeId(id);
+
+    // If the package was upgraded, show what it was upgraded from.
+    if (changed) {
+      _write(" (was ");
+      _writeId(oldId);
+      _write(")");
+    }
+
+    // Highlight overridden packages.
+    if (isOverridden && highlightOverride) {
+      _write(" ${log.magenta('(overridden)')}");
+    }
+
+    // See if there are any newer versions of the package that we were
+    // unable to upgrade to.
+    if (newId != null) {
+      var versions = _result.availableVersions[newId.name];
+      var newerStable = 0;
+      var newerUnstable = 0;
+
+      for (var version in versions) {
+        if (version > newId.version) {
+          if (version.isPreRelease) {
+            newerUnstable++;
+          } else {
+            newerStable++;
+          }
+        }
+      }
+
+      // If there are newer stable versions, only show those.
+      var message;
+      if (newerStable > 0) {
+        message = "($newerStable newer "
+            "${pluralize('version', newerStable)} available)";
+      } else if (newerUnstable > 0) {
+        message = "($newerUnstable newer unstable "
+            "${pluralize('version', newerUnstable)} available)";
+      }
+
+      if (message != null) _write(" ${log.cyan(message)}");
+    }
+
+    _writeln();
+  }
+
+  /// Returns `true` if [a] and [b] are from the same source and have the same
+  /// description.
+  bool _descriptionsEqual(PackageId a, PackageId b) {
+    if (a.source != b.source) return false;
+
+    if (_sources.contains(a.source)) {
+      var source = _sources[a.source];
+      return source.descriptionsEqual(a.description, b.description);
+    } else {
+      // Unknown source, so just do a literal comparison.
+      return a.description == b.description;
+    }
+  }
+
+  /// Writes a terse description of [id] (not including its name) to the output.
+  void _writeId(PackageId id) {
+    _write(id.version);
+
+    var source = null;
+    if (_sources.contains(id.source)) {
+      source = _sources[id.source];
+    }
+
+    if (source != null && source != _sources.defaultSource) {
+      var description = source.formatDescription(_root.dir, id.description);
+      _write(" from ${id.source} $description");
+    }
+  }
+
+  /// Writes [obj] to the output.
+  void _write(Object obj) {
+    while (_pendingLines > 0) {
+      _output.writeln();
+      _pendingLines--;
+    }
+    _output.write(obj);
+  }
+
+  /// Writes [obj] (if not null) followed by a newline to the output.
+  ///
+  /// Doesn't actually immediately write a newline. Instead, it waits until
+  /// output is written on the next line. That way, trailing newlines aren't
+  /// displayed.
+  void _writeln([Object obj]) {
+    if (obj != null) _write(obj);
+    _pendingLines++;
+  }
+}
\ No newline at end of file
diff --git a/sdk/lib/_internal/pub/lib/src/solver/version_queue.dart b/sdk/lib/_internal/pub/lib/src/solver/version_queue.dart
index 529cf74..021b60e 100644
--- a/sdk/lib/_internal/pub/lib/src/solver/version_queue.dart
+++ b/sdk/lib/_internal/pub/lib/src/solver/version_queue.dart
@@ -8,7 +8,6 @@
 import 'dart:collection' show Queue;
 
 import '../package.dart';
-import 'backtracking_solver.dart';
 
 /// A function that asynchronously returns a sequence of package IDs.
 typedef Future<Iterable<PackageId>> PackageIdGenerator();
diff --git a/sdk/lib/_internal/pub/lib/src/solver/version_solver.dart b/sdk/lib/_internal/pub/lib/src/solver/version_solver.dart
index 54c5ab4..60e71a6f 100644
--- a/sdk/lib/_internal/pub/lib/src/solver/version_solver.dart
+++ b/sdk/lib/_internal/pub/lib/src/solver/version_solver.dart
@@ -15,6 +15,7 @@
 import '../version.dart';
 import '../utils.dart';
 import 'backtracking_solver.dart';
+import 'solve_report.dart' as solve_report;
 
 /// Attempts to select the best concrete versions for all of the transitive
 /// dependencies of [root] taking into account all of the [VersionConstraint]s
@@ -24,13 +25,16 @@
 /// If [useLatest] is given, then only the latest versions of the referenced
 /// packages will be used. This is for forcing an upgrade to one or more
 /// packages.
+///
+/// If [upgradeAll] is true, the contents of [lockFile] are ignored.
 Future<SolveResult> resolveVersions(SourceRegistry sources, Package root,
-    {LockFile lockFile, List<String> useLatest}) {
+    {LockFile lockFile, List<String> useLatest, bool upgradeAll: false}) {
   if (lockFile == null) lockFile = new LockFile.empty();
   if (useLatest == null) useLatest = [];
 
   return log.progress('Resolving dependencies', () {
-    return new BacktrackingSolver(sources, root, lockFile, useLatest).solve();
+    return new BacktrackingSolver(sources, root, lockFile, useLatest,
+        upgradeAll: upgradeAll).solve();
   });
 }
 
@@ -46,6 +50,13 @@
   /// The dependency overrides that were used in the solution.
   final List<PackageDep> overrides;
 
+  /// The available versions of all selected packages from their source.
+  ///
+  /// Will be empty if the solve failed. An entry here may not include the full
+  /// list of versions available if the given package was locked and did not
+  /// need to be unlocked during the solve.
+  final Map<String, List<Version>> availableVersions;
+
   /// The error that prevented the solver from finding a solution or `null` if
   /// it was successful.
   final SolveFailure error;
@@ -56,8 +67,30 @@
   /// solution.
   final int attemptedSolutions;
 
-  SolveResult(this.packages, this.overrides, this.error,
-      this.attemptedSolutions);
+  final SourceRegistry _sources;
+  final Package _root;
+  final LockFile _previousLockFile;
+
+  SolveResult.success(this._sources, this._root, this._previousLockFile,
+      this.packages, this.overrides, this.availableVersions,
+      this.attemptedSolutions)
+      : error = null;
+
+  SolveResult.failure(this._sources, this._root, this._previousLockFile,
+      this.overrides, this.error, this.attemptedSolutions)
+      : this.packages = null,
+        this.availableVersions = {};
+
+  /// Displays a report of what changes were made to the lockfile.
+  ///
+  /// If [showAll] is true, displays all new and previous dependencies.
+  /// Otherwise, just shows a warning for any overrides in effect.
+  ///
+  /// Returns the number of changed (added, removed, or modified) dependencies.
+  int showReport({bool showAll: false}) {
+    return solve_report.show(_sources, _root, _previousLockFile, this,
+        showAll: showAll);
+  }
 
   String toString() {
     if (!succeeded) {
@@ -163,6 +196,10 @@
       return ids;
     });
   }
+
+  /// Returns the previously cached list of versions for the package identified
+  /// by [package] or returns `null` if not in the cache.
+  List<PackageId> getCachedVersions(PackageRef package) => _versions[package];
 }
 
 /// A reference from a depending package to a package that it depends on.
@@ -191,6 +228,13 @@
   final innerError = null;
   final innerTrace = null;
 
+  String get message => toString();
+
+  /// A message describing the specific kind of solve failure.
+  String get _message {
+    throw new UnimplementedError("Must override _message or toString().");
+  }
+
   SolveFailure(this.package, Iterable<Dependency> dependencies)
       : dependencies = dependencies != null ? dependencies : <Dependency>[];
 
@@ -198,7 +242,7 @@
     if (dependencies.isEmpty) return _message;
 
     var buffer = new StringBuffer();
-    buffer.writeln("$_message:");
+    buffer.write("$_message:");
 
     var map = {};
     for (var dep in dependencies) {
@@ -207,20 +251,15 @@
 
     var names = ordered(map.keys);
 
-    buffer.writeAll(names.map(
-        (name) => "- '$name' ${_describeDependency(map[name])}"), '\n');
+    for (var name in names) {
+      buffer.writeln();
+      buffer.write("- $name ${_describeDependency(map[name])}");
+    }
 
     return buffer.toString();
   }
 
-  String get message => toString();
-
-  /// A message describing the specific kind of solve failure.
-  String get _message {
-    throw new UnimplementedError("Must override _message or toString().");
-  }
-
-  /// Describes a dependencie's reference in the output message. Override this
+  /// Describes a dependency's reference in the output message. Override this
   /// to highlight which aspect of [dep] led to the failure.
   String _describeDependency(PackageDep dep) =>
       "depends on version ${dep.constraint}";
@@ -229,12 +268,11 @@
 /// Exception thrown when the current SDK's version does not match a package's
 /// constraint on it.
 class BadSdkVersionException extends SolveFailure {
+  final String _message;
+
   BadSdkVersionException(String package, String message)
       : super(package, null),
         _message = message;
-
-  /// A message describing the specific kind of solve failure.
-  final String _message;
 }
 
 /// Exception thrown when the [VersionConstraint] used to match a package is
@@ -247,7 +285,7 @@
       Iterable<Dependency> dependencies)
       : super(package, dependencies);
 
-  String get _message => "Package '$package' has no versions that match "
+  String get _message => "Package $package has no versions that match "
       "$constraint derived from";
 }
 
@@ -262,7 +300,7 @@
       : super(package, null);
 
   String get _message =>
-      "The latest version of '$package', $best, does not match $constraint.";
+      "The latest version of $package, $best, does not match $constraint.";
 }
 
 /// Exception thrown when the [VersionConstraint] used to match a package is
@@ -272,17 +310,17 @@
   DisjointConstraintException(String package, Iterable<Dependency> dependencies)
       : super(package, dependencies);
 
-  String get _message => "Incompatible version constraints on '$package'";
+  String get _message => "Incompatible version constraints on $package";
 }
 
 /// Exception thrown when two packages with the same name but different sources
 /// are depended upon.
 class SourceMismatchException extends SolveFailure {
+  String get _message => "Incompatible dependencies on $package";
+
   SourceMismatchException(String package, Iterable<Dependency> dependencies)
       : super(package, dependencies);
 
-  String get _message => "Incompatible dependencies on '$package'";
-
   String _describeDependency(PackageDep dep) =>
       "depends on it from source ${dep.source}";
 }
@@ -294,22 +332,40 @@
 
   String toString() {
     var dep = dependencies.single;
-    return "Package '${dep.depender}' depends on '${dep.dep.name}' from "
-           "unknown source '${dep.dep.source}'.";
+    return 'Package ${dep.depender} depends on ${dep.dep.name} from unknown '
+           'source "${dep.dep.source}".';
   }
 }
 
 /// Exception thrown when two packages with the same name and source but
 /// different descriptions are depended upon.
 class DescriptionMismatchException extends SolveFailure {
+  String get _message => "Incompatible dependencies on $package";
+
   DescriptionMismatchException(String package,
       Iterable<Dependency> dependencies)
       : super(package, dependencies);
 
-  String get _message => "Incompatible dependencies on '$package'";
-
   String _describeDependency(PackageDep dep) {
     // TODO(nweiz): Dump descriptions to YAML when that's supported.
     return "depends on it with description ${JSON.encode(dep.description)}";
   }
 }
+
+/// Exception thrown when a dependency could not be found in its source.
+///
+/// Unlike [PackageNotFoundException], this includes information about the
+/// dependent packages requesting the missing one.
+class DependencyNotFoundException extends SolveFailure {
+  final PackageNotFoundException _innerException;
+  String get _message => "${_innerException.message}\nDepended on by";
+
+  DependencyNotFoundException(String package, this._innerException,
+      Iterable<Dependency> dependencies)
+      : super(package, dependencies);
+
+  /// The failure isn't because of the version of description of the package,
+  /// it's the package itself that can't be found, so just show the name and no
+  /// descriptive details.
+  String _describeDependency(PackageDep dep) => "";
+}
diff --git a/sdk/lib/_internal/pub/lib/src/source.dart b/sdk/lib/_internal/pub/lib/src/source.dart
index a27a909..299f6cf 100644
--- a/sdk/lib/_internal/pub/lib/src/source.dart
+++ b/sdk/lib/_internal/pub/lib/src/source.dart
@@ -7,6 +7,7 @@
 import 'dart:async';
 
 import 'package:path/path.dart' as path;
+import 'package:stack_trace/stack_trace.dart';
 
 import 'io.dart';
 import 'package.dart';
@@ -203,7 +204,8 @@
   /// This doesn't need to be implemented if [shouldCache] is false.
   Future<String> systemCacheDirectory(PackageId id) {
     return new Future.error(
-        "systemCacheDirectory() must be implemented if shouldCache is true.");
+        "systemCacheDirectory() must be implemented if shouldCache is true.",
+        new Chain.current());
   }
 
   /// When a [Pubspec] or [LockFile] is parsed, it reads in the description for
diff --git a/sdk/lib/_internal/pub/lib/src/source/git.dart b/sdk/lib/_internal/pub/lib/src/source/git.dart
index 5a7f5e5..c50e719 100644
--- a/sdk/lib/_internal/pub/lib/src/source/git.dart
+++ b/sdk/lib/_internal/pub/lib/src/source/git.dart
@@ -40,7 +40,7 @@
     return git.isInstalled.then((installed) {
       if (!installed) {
         throw new Exception(
-            "Cannot get '${id.name}' from Git (${_getUrl(id)}).\n"
+            "Cannot get ${id.name} from Git (${_getUrl(id)}).\n"
             "Please ensure Git is correctly installed.");
       }
 
@@ -121,7 +121,7 @@
   /// future that completes once this is finished and throws an exception if it
   /// fails.
   Future _ensureRepoCache(PackageId id) {
-    return new Future.sync(() {
+    return syncFuture(() {
       var path = _repoCachePath(id);
       if (!entryExists(path)) return _clone(_getUrl(id), path, mirror: true);
       return git.run(["fetch"], workingDir: path).then((result) => null);
@@ -141,7 +141,7 @@
   /// the working tree, but instead makes the repository a local mirror of the
   /// remote repository. See the manpage for `git clone` for more information.
   Future _clone(String from, String to, {bool mirror: false}) {
-    return new Future.sync(() {
+    return syncFuture(() {
       // Git on Windows does not seem to automatically create the destination
       // directory.
       ensureDir(to);
diff --git a/sdk/lib/_internal/pub/lib/src/source/hosted.dart b/sdk/lib/_internal/pub/lib/src/source/hosted.dart
index 1429e28..781ab0c 100644
--- a/sdk/lib/_internal/pub/lib/src/source/hosted.dart
+++ b/sdk/lib/_internal/pub/lib/src/source/hosted.dart
@@ -78,7 +78,7 @@
 
   /// Downloads a package from the site and unpacks it.
   Future<bool> get(PackageId id, String destPath) {
-    return new Future.sync(() {
+    return syncFuture(() {
       var url = _makeVersionUrl(id, (server, package, version) =>
           "$server/packages/$package/versions/$version.tar.gz");
       log.io("Get package from $url.");
@@ -156,16 +156,17 @@
       String url) {
     if (error is PubHttpException &&
         error.response.statusCode == 404) {
-      fail('Could not find package "$package" at $url.', error, stackTrace);
+      throw new PackageNotFoundException(
+          "Could not find package $package at $url.", error, stackTrace);
     }
 
     if (error is TimeoutException) {
-      fail('Timed out trying to find package "$package" at $url.',
+      fail("Timed out trying to find package $package at $url.",
           error, stackTrace);
     }
 
     if (error is io.SocketException) {
-      fail('Got socket error trying to find package "$package" at $url.',
+      fail("Got socket error trying to find package $package at $url.",
            error, stackTrace);
     }
 
@@ -191,7 +192,7 @@
           .toList();
     }).then((versions) {
       // If there are no versions in the cache, report a clearer error.
-      if (versions.isEmpty) fail('Could not find package "$name" in cache.');
+      if (versions.isEmpty) fail("Could not find package $name in cache.");
 
       return versions;
     });
diff --git a/sdk/lib/_internal/pub/lib/src/source/path.dart b/sdk/lib/_internal/pub/lib/src/source/path.dart
index 76892e1..52f6212 100644
--- a/sdk/lib/_internal/pub/lib/src/source/path.dart
+++ b/sdk/lib/_internal/pub/lib/src/source/path.dart
@@ -20,7 +20,7 @@
   final shouldCache = false;
 
   Future<Pubspec> describeUncached(PackageId id) {
-    return new Future.sync(() {
+    return syncFuture(() {
       var dir = _validatePath(id.name, id.description);
       return new Pubspec.load(dir, systemCache.sources,
           expectedName: id.name);
@@ -35,7 +35,7 @@
   }
 
   Future<bool> get(PackageId id, String destination) {
-    return new Future.sync(() {
+    return syncFuture(() {
       try {
         var dir = _validatePath(id.name, id.description);
         createPackageSymlink(id.name, dir, destination,
@@ -135,10 +135,11 @@
     if (dirExists(dir)) return dir;
 
     if (fileExists(dir)) {
-      fail("Path dependency for package '$name' must refer to a "
-           "directory, not a file. Was '$dir'.");
+      fail('Path dependency for package $name must refer to a directory, '
+           'not a file. Was "$dir".');
     }
 
-    fail("Could not find package '$name' at '$dir'.");
+    throw new PackageNotFoundException(
+        'Could not find package $name at "$dir".');
   }
 }
diff --git a/sdk/lib/_internal/pub/lib/src/source_registry.dart b/sdk/lib/_internal/pub/lib/src/source_registry.dart
index 6dbe58e..cd3dc3e 100644
--- a/sdk/lib/_internal/pub/lib/src/source_registry.dart
+++ b/sdk/lib/_internal/pub/lib/src/source_registry.dart
@@ -43,6 +43,8 @@
 
   /// Returns the source named [name]. Throws an error if no such source has
   /// been registered. If [name] is null, returns the default source.
+  // TODO(rnystrom): Return a NullSource that does nothing safely so that
+  // calling code doesn't have to worry about it.
   Source operator[](String name) {
     if (name == null) {
       if (defaultSource != null) return defaultSource;
diff --git a/sdk/lib/_internal/pub/lib/src/utils.dart b/sdk/lib/_internal/pub/lib/src/utils.dart
index 222941a..dc25e53 100644
--- a/sdk/lib/_internal/pub/lib/src/utils.dart
+++ b/sdk/lib/_internal/pub/lib/src/utils.dart
@@ -77,9 +77,6 @@
   Future<List> get future => _completer.future;
 }
 
-/// Like [Future.sync], but wraps the Future in [Chain.track] as well.
-Future syncFuture(callback()) => Chain.track(new Future.sync(callback));
-
 /// Returns a buffered stream that will emit the same values as the stream
 /// returned by [future] once [future] completes.
 ///
@@ -131,6 +128,37 @@
 /// under the covers.
 Future newFuture(callback()) => new Future.value().then((_) => callback());
 
+/// Like [new Future.sync], but automatically wraps the future in a
+/// [Chain.track] call.
+Future syncFuture(callback()) => Chain.track(new Future.sync(callback));
+
+/// Runs [callback] in an error zone and pipes any unhandled error to the
+/// returned [Future].
+///
+/// If the returned [Future] produces an error, its stack trace will always be a
+/// [Chain]. By default, this chain will contain only the local stack trace, but
+/// if [captureStackChains] is passed, it will contain the full stack chain for
+/// the error.
+Future captureErrors(Future callback(), {bool captureStackChains: false}) {
+  var completer = new Completer();
+  var wrappedCallback = () {
+    new Future.sync(callback).then(completer.complete)
+        .catchError((e, stackTrace) {
+      completer.completeError(e, new Chain.forTrace(stackTrace));
+    });
+  };
+
+  if (captureStackChains) {
+    Chain.capture(wrappedCallback, onError: completer.completeError);
+  } else {
+    runZoned(wrappedCallback, onError: (e, stackTrace) {
+      completer.completeError(e, new Chain([new Trace.from(stackTrace)]));
+    });
+  }
+
+  return completer.future;
+}
+
 /// Returns a [StreamTransformer] that will call [onDone] when the stream
 /// completes.
 ///
@@ -411,7 +439,7 @@
   }, onError: (e, [stackTrace]) {
     completer.completeError(e, stackTrace);
   }, onDone: () {
-    completer.completeError(new StateError("No elements"));
+    completer.completeError(new StateError("No elements"), new Chain.current());
   }, cancelOnError: true);
   return completer.future;
 }
@@ -804,6 +832,16 @@
   String toString() => message;
 }
 
+/// An class for exceptions where a package could not be found in a [Source].
+///
+/// The source is responsible for wrapping its internal exceptions in this so
+/// that other code in pub can use this to show a more detailed explanation of
+/// why the package was being requested.
+class PackageNotFoundException extends ApplicationException {
+  PackageNotFoundException(String message, [innerError, StackTrace innerTrace])
+      : super(message, innerError, innerTrace);
+}
+
 /// Throw a [ApplicationException] with [message].
 void fail(String message, [innerError, StackTrace innerTrace]) {
   throw new ApplicationException(message, innerError, innerTrace);
diff --git a/sdk/lib/_internal/pub/lib/src/validator/compiled_dartdoc.dart b/sdk/lib/_internal/pub/lib/src/validator/compiled_dartdoc.dart
index d6abf6d..400e6b2 100644
--- a/sdk/lib/_internal/pub/lib/src/validator/compiled_dartdoc.dart
+++ b/sdk/lib/_internal/pub/lib/src/validator/compiled_dartdoc.dart
@@ -10,6 +10,7 @@
 
 import '../entrypoint.dart';
 import '../io.dart';
+import '../utils.dart';
 import '../validator.dart';
 
 /// Validates that a package doesn't contain compiled Dartdoc
@@ -19,7 +20,7 @@
     : super(entrypoint);
 
   Future validate() {
-    return new Future.sync(() {
+    return syncFuture(() {
       for (var entry in listDir(entrypoint.root.dir, recursive: true)) {
         if (path.basename(entry) != "nav.json") continue;
         var dir = path.dirname(entry);
diff --git a/sdk/lib/_internal/pub/lib/src/validator/directory.dart b/sdk/lib/_internal/pub/lib/src/validator/directory.dart
index 6039fc5..f733e4e 100644
--- a/sdk/lib/_internal/pub/lib/src/validator/directory.dart
+++ b/sdk/lib/_internal/pub/lib/src/validator/directory.dart
@@ -10,6 +10,7 @@
 
 import '../entrypoint.dart';
 import '../io.dart';
+import '../utils.dart';
 import '../validator.dart';
 
 /// A validator that validates a package's top-level directories.
@@ -22,7 +23,7 @@
   ];
 
   Future validate() {
-    return new Future.sync(() {
+    return syncFuture(() {
       for (var dir in listDir(entrypoint.root.dir)) {
         if (!dirExists(dir)) continue;
 
diff --git a/sdk/lib/_internal/pub/lib/src/validator/lib.dart b/sdk/lib/_internal/pub/lib/src/validator/lib.dart
index 98bed28..22ed406 100644
--- a/sdk/lib/_internal/pub/lib/src/validator/lib.dart
+++ b/sdk/lib/_internal/pub/lib/src/validator/lib.dart
@@ -10,6 +10,7 @@
 
 import '../entrypoint.dart';
 import '../io.dart';
+import '../utils.dart';
 import '../validator.dart';
 
 // TODO(nweiz): When issue 7196 is fixed, complain about non-Dart files in lib.
@@ -20,7 +21,7 @@
     : super(entrypoint);
 
   Future validate() {
-    return new Future.sync(() {
+    return syncFuture(() {
       var libDir = path.join(entrypoint.root.dir, "lib");
 
       if (!dirExists(libDir)) {
diff --git a/sdk/lib/_internal/pub/lib/src/validator/license.dart b/sdk/lib/_internal/pub/lib/src/validator/license.dart
index 222d693..ffad6a7 100644
--- a/sdk/lib/_internal/pub/lib/src/validator/license.dart
+++ b/sdk/lib/_internal/pub/lib/src/validator/license.dart
@@ -10,6 +10,7 @@
 
 import '../entrypoint.dart';
 import '../io.dart';
+import '../utils.dart';
 import '../validator.dart';
 
 /// A validator that checks that a LICENSE-like file exists.
@@ -18,7 +19,7 @@
     : super(entrypoint);
 
   Future validate() {
-    return new Future.sync(() {
+    return syncFuture(() {
       var licenseLike = new RegExp(
           r"^([a-zA-Z0-9]+[-_])?(LICENSE|COPYING)(\..*)?$");
       if (listDir(entrypoint.root.dir)
diff --git a/sdk/lib/_internal/pub/lib/src/validator/name.dart b/sdk/lib/_internal/pub/lib/src/validator/name.dart
index 1285fb1..1b77ead 100644
--- a/sdk/lib/_internal/pub/lib/src/validator/name.dart
+++ b/sdk/lib/_internal/pub/lib/src/validator/name.dart
@@ -10,6 +10,7 @@
 
 import '../entrypoint.dart';
 import '../io.dart';
+import '../utils.dart';
 import '../validator.dart';
 
 /// Dart reserved words, from the Dart spec.
@@ -26,7 +27,7 @@
     : super(entrypoint);
 
   Future validate() {
-    return new Future.sync(() {
+    return syncFuture(() {
       _checkName(entrypoint.root.name, 'Package name "${entrypoint.root.name}"',
           isPackage: true);
 
diff --git a/sdk/lib/_internal/pub/lib/src/validator/utf8_readme.dart b/sdk/lib/_internal/pub/lib/src/validator/utf8_readme.dart
index 9f30d65..da0c223 100644
--- a/sdk/lib/_internal/pub/lib/src/validator/utf8_readme.dart
+++ b/sdk/lib/_internal/pub/lib/src/validator/utf8_readme.dart
@@ -9,6 +9,7 @@
 
 import '../entrypoint.dart';
 import '../io.dart';
+import '../utils.dart';
 import '../validator.dart';
 
 /// Validates that a package's README is valid utf-8.
@@ -17,7 +18,7 @@
     : super(entrypoint);
 
   Future validate() {
-    return new Future.sync(() {
+    return syncFuture(() {
       var readme = entrypoint.root.readmePath;
       if (readme == null) return;
       var bytes = readBinaryFile(readme);
diff --git a/sdk/lib/_internal/pub/lib/src/version.dart b/sdk/lib/_internal/pub/lib/src/version.dart
index e8738ff..8c34d57 100644
--- a/sdk/lib/_internal/pub/lib/src/version.dart
+++ b/sdk/lib/_internal/pub/lib/src/version.dart
@@ -9,7 +9,7 @@
 
 import 'dart:math';
 
-import 'package:collection_helpers/equality.dart';
+import 'package:collection/equality.dart';
 
 /// Regex that matches a version number at the beginning of a string.
 final _START_VERSION = new RegExp(
diff --git a/sdk/lib/_internal/pub/pub.status b/sdk/lib/_internal/pub/pub.status
index 3e49ab9..2165264 100644
--- a/sdk/lib/_internal/pub/pub.status
+++ b/sdk/lib/_internal/pub/pub.status
@@ -9,6 +9,7 @@
 [ $runtime == vm && $system == windows ]
 test/serve/watch_removed_file_test: Pass, Fail # Issue 13026
 test/serve/missing_file_test: Pass, Fail # Issue 15431
+test/serve/warns_on_assets_paths_test: Pass, Fail # Issue 15741
 
 # Pub only runs on the VM, so just rule out all compilers.
 [ $compiler == dart2js || $compiler == dart2dart ]
diff --git a/sdk/lib/_internal/pub/resource/certs/cert9.db b/sdk/lib/_internal/pub/resource/certs/cert9.db
deleted file mode 100644
index 955f26d..0000000
--- a/sdk/lib/_internal/pub/resource/certs/cert9.db
+++ /dev/null
Binary files differ
diff --git a/sdk/lib/_internal/pub/resource/certs/key4.db b/sdk/lib/_internal/pub/resource/certs/key4.db
deleted file mode 100644
index 1b6b97a..0000000
--- a/sdk/lib/_internal/pub/resource/certs/key4.db
+++ /dev/null
Binary files differ
diff --git a/sdk/lib/_internal/pub/resource/certs/pkcs11.txt b/sdk/lib/_internal/pub/resource/certs/pkcs11.txt
deleted file mode 100644
index 81f899b..0000000
--- a/sdk/lib/_internal/pub/resource/certs/pkcs11.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-library=
-name=NSS Internal PKCS #11 Module
-parameters=configdir='utils/pub/resource/certs' certPrefix='' keyPrefix='' secmod='secmod.db' flags= updatedir='' updateCertPrefix='' updateKeyPrefix='' updateid='' updateTokenDescription='' 
-NSS=Flags=internal,critical trustOrder=75 cipherOrder=100 slotParams=(1={slotFlags=[RSA,DSA,DH,RC2,RC4,DES,RANDOM,SHA1,MD5,MD2,SSL,TLS,AES,Camellia,SEED,SHA256,SHA512] askpw=any timeout=30})
-
diff --git a/sdk/lib/_internal/pub/test/build/warns_on_assets_paths_test.dart b/sdk/lib/_internal/pub/test/build/warns_on_assets_paths_test.dart
new file mode 100644
index 0000000..90c69f0
--- /dev/null
+++ b/sdk/lib/_internal/pub/test/build/warns_on_assets_paths_test.dart
@@ -0,0 +1,101 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library pub_tests;
+
+import 'package:path/path.dart' as path;
+
+import '../descriptor.dart' as d;
+import '../test_pub.dart';
+
+getWarningRegExp(String assetsPath) {
+  // Escape backslashes since they are metacharacters in a regex.
+  assetsPath = assetsPath.replaceAll("\\", "\\\\");
+  return new RegExp(
+      '^Warning: Pub reserves paths containing "assets" for using assets from '
+      'packages\\. Please rename the path "$assetsPath"\\.\$');
+}
+
+main() {
+  initConfig();
+
+  integration('warns user about assets dir in the root of "web"', () {
+    d.dir(appPath, [
+      d.appPubspec(),
+      d.dir('web', [
+        d.file('index.html'),
+        d.dir('assets')
+      ])
+    ]).create();
+
+    var assetsPath = path.join('web', 'assets');
+    schedulePub(args: ['build'],
+        error: getWarningRegExp(assetsPath),
+        exitCode: 0);
+  });
+
+  integration('warns user about assets dir nested anywhere in "web"', () {
+    d.dir(appPath, [
+      d.appPubspec(),
+      d.dir('web', [
+        d.file('index.html'),
+        d.dir('foo', [
+          d.dir('assets')
+        ])
+      ])
+    ]).create();
+
+    var assetsPath = path.join('web', 'foo', 'assets');
+    schedulePub(args: ['build'],
+        error: getWarningRegExp(assetsPath),
+        exitCode: 0);
+  });
+
+  integration('warns user about assets file in the root of "web"', () {
+    d.dir(appPath, [
+      d.appPubspec(),
+      d.dir('web', [
+        d.file('index.html'),
+        d.file('assets')
+      ])
+    ]).create();
+
+    var assetsPath = path.join('web', 'assets');
+    schedulePub(args: ['build'],
+        error: getWarningRegExp(assetsPath),
+        exitCode: 0);
+  });
+
+  integration('warns user about assets file nested anywhere in "web"', () {
+    d.dir(appPath, [
+      d.appPubspec(),
+      d.dir('web', [
+        d.file('index.html'),
+        d.dir('foo', [
+          d.file('assets')
+        ])
+      ])
+    ]).create();
+
+    var assetsPath = path.join('web', 'foo', 'assets');
+    schedulePub(args: ['build'],
+        error: getWarningRegExp(assetsPath),
+        exitCode: 0);
+  });
+
+  integration('does not warn if no assets dir or file anywhere in "web"', () {
+    d.dir(appPath, [
+      d.appPubspec(),
+      d.dir('web', [
+        d.file('index.html'),
+        d.dir('foo')
+      ])
+    ]).create();
+
+    schedulePub(args: ['build'],
+        error: new RegExp(
+            r'^(?!Warning: Pub reserves paths containing "assets").*$'),
+        exitCode: 0);
+  });
+}
diff --git a/sdk/lib/_internal/pub/test/build/with_no_web_directory_test.dart b/sdk/lib/_internal/pub/test/build/with_no_web_directory_test.dart
index 95a8e3c..d25df72 100644
--- a/sdk/lib/_internal/pub/test/build/with_no_web_directory_test.dart
+++ b/sdk/lib/_internal/pub/test/build/with_no_web_directory_test.dart
@@ -12,7 +12,7 @@
     d.appDir().create();
 
     schedulePub(args: ["build"],
-        error: new RegExp(r"^There is no '[^']+[/\\]web' directory.$",
+        error: new RegExp(r'^There is no "[^"]+[/\\]web" directory.$',
             multiLine: true),
         exitCode: 1);
   });
diff --git a/sdk/lib/_internal/pub/test/dependency_override_test.dart b/sdk/lib/_internal/pub/test/dependency_override_test.dart
index 7e0f229..fcbb3bc 100644
--- a/sdk/lib/_internal/pub/test/dependency_override_test.dart
+++ b/sdk/lib/_internal/pub/test/dependency_override_test.dart
@@ -112,9 +112,9 @@
       schedulePub(args: [command.name], output: command.success, error:
           """
           Warning: You are using these overridden dependencies:
-          - bar
-          - baz (from path $bazPath)
-          - foo
+          ! bar 1.0.0
+          ! baz 0.0.1 from path $bazPath
+          ! foo 1.0.0
           """);
     });
   });
diff --git a/sdk/lib/_internal/pub/test/get/hosted/get_test.dart b/sdk/lib/_internal/pub/test/get/hosted/get_test.dart
index 40eaca5..8dd1d0e 100644
--- a/sdk/lib/_internal/pub/test/get/hosted/get_test.dart
+++ b/sdk/lib/_internal/pub/test/get/hosted/get_test.dart
@@ -26,6 +26,6 @@
     d.appDir({"bad name!": "1.2.3"}).create();
 
     pubGet(error: new RegExp(
-        r'Could not find package "bad name!" at http://127\.0\.0\.1:\d+\.$'));
+        r"Could not find package bad name! at http://127\.0\.0\.1:\d+\."));
   });
 }
diff --git a/sdk/lib/_internal/pub/test/get/path/nonexistent_dir_test.dart b/sdk/lib/_internal/pub/test/get/path/nonexistent_dir_test.dart
index 2db4d38..35552bb 100644
--- a/sdk/lib/_internal/pub/test/get/path/nonexistent_dir_test.dart
+++ b/sdk/lib/_internal/pub/test/get/path/nonexistent_dir_test.dart
@@ -18,6 +18,8 @@
       })
     ]).create();
 
-    pubGet(error: "Could not find package 'foo' at '$badPath'.");
+    pubGet(error: """Could not find package foo at "$badPath".
+Depended on by:
+- myapp""");
   });
 }
\ No newline at end of file
diff --git a/sdk/lib/_internal/pub/test/get/path/path_is_file_test.dart b/sdk/lib/_internal/pub/test/get/path/path_is_file_test.dart
index 288f68f..81524c8 100644
--- a/sdk/lib/_internal/pub/test/get/path/path_is_file_test.dart
+++ b/sdk/lib/_internal/pub/test/get/path/path_is_file_test.dart
@@ -24,7 +24,7 @@
       })
     ]).create();
 
-    pubGet(error: "Path dependency for package 'foo' must refer to a "
-                      "directory, not a file. Was '$dummyPath'.");
+    pubGet(error: 'Path dependency for package foo must refer to a '
+                  'directory, not a file. Was "$dummyPath".');
   });
 }
\ No newline at end of file
diff --git a/sdk/lib/_internal/pub/test/hosted/fail_gracefully_on_missing_package_test.dart b/sdk/lib/_internal/pub/test/hosted/fail_gracefully_on_missing_package_test.dart
index 18fed7f..944e6ed 100644
--- a/sdk/lib/_internal/pub/test/hosted/fail_gracefully_on_missing_package_test.dart
+++ b/sdk/lib/_internal/pub/test/hosted/fail_gracefully_on_missing_package_test.dart
@@ -16,8 +16,10 @@
 
       d.appDir({"foo": "1.2.3"}).create();
 
-      pubCommand(command, error: new RegExp(
-          r'Could not find package "foo" at http://127\.0\.0\.1:\d+\.$'));
+      pubCommand(command, error: new RegExp(r"""
+Could not find package foo at http://127\.0\.0\.1:\d+\.
+Depended on by:
+- myapp""", multiLine: true));
     });
   });
 }
diff --git a/sdk/lib/_internal/pub/test/hosted/offline_test.dart b/sdk/lib/_internal/pub/test/hosted/offline_test.dart
index 16be30c..b799198 100644
--- a/sdk/lib/_internal/pub/test/hosted/offline_test.dart
+++ b/sdk/lib/_internal/pub/test/hosted/offline_test.dart
@@ -46,7 +46,7 @@
       d.appDir({"foo": "any"}).create();
 
       pubCommand(command, args: ['--offline'],
-          error: 'Could not find package "foo" in cache.');
+          error: "Could not find package foo in cache.");
     });
 
     integration('fails gracefully no cached versions match', () {
@@ -60,8 +60,8 @@
       d.appDir({"foo": ">2.0.0"}).create();
 
       pubCommand(command, args: ['--offline'], error:
-          "Package 'foo' has no versions that match >2.0.0 derived from:\n"
-          "- 'myapp' depends on version >2.0.0");
+          "Package foo has no versions that match >2.0.0 derived from:\n"
+          "- myapp depends on version >2.0.0");
     });
   });
 }
diff --git a/sdk/lib/_internal/pub/test/implicit_barback_dependency_test.dart b/sdk/lib/_internal/pub/test/implicit_barback_dependency_test.dart
index 02f2363..894cf51 100644
--- a/sdk/lib/_internal/pub/test/implicit_barback_dependency_test.dart
+++ b/sdk/lib/_internal/pub/test/implicit_barback_dependency_test.dart
@@ -10,16 +10,19 @@
 main() {
   initConfig();
 
-  var previousVersion = new Version(
-      barback.supportedVersion.major, barback.supportedVersion.minor - 1, 0);
+  var current = barback.supportedVersion.toString();
+  var previous = new Version(barback.supportedVersion.major,
+      barback.supportedVersion.minor - 1, 0).toString();
+  var nextPatch = barback.supportedVersion.nextPatch.toString();
+  var max = barback.supportedVersion.nextMinor.toString();
 
   forBothPubGetAndUpgrade((command) {
     integration("implicitly constrains barback to versions pub supports", () {
       servePackages([
-        packageMap("barback", previousVersion.toString()),
-        packageMap("barback", barback.supportedVersion.toString()),
-        packageMap("barback", barback.supportedVersion.nextPatch.toString()),
-        packageMap("barback", barback.supportedVersion.nextMinor.toString())
+        packageMap("barback", previous),
+        packageMap("barback", current),
+        packageMap("barback", nextPatch),
+        packageMap("barback", max)
       ]);
 
       d.appDir({
@@ -35,10 +38,10 @@
 
     integration("discovers transitive dependency on barback", () {
       servePackages([
-        packageMap("barback", previousVersion.toString()),
-        packageMap("barback", barback.supportedVersion.toString()),
-        packageMap("barback", barback.supportedVersion.nextPatch.toString()),
-        packageMap("barback", barback.supportedVersion.nextMinor.toString())
+        packageMap("barback", previous),
+        packageMap("barback", current),
+        packageMap("barback", nextPatch),
+        packageMap("barback", max)
       ]);
 
       d.dir("foo", [
@@ -55,30 +58,78 @@
       pubCommand(command);
 
       d.packagesDir({
-        "barback": barback.supportedVersion.nextPatch.toString(),
+        "barback": nextPatch,
         "foo": "0.0.1"
       }).validate();
     });
+
+    integration("pub's implicit constraint uses the same source and "
+        "description as the explicit one", () {
+      d.dir('barback', [
+        d.libDir('barback', 'barback $current'),
+        d.libPubspec('barback', current)
+      ]).create();
+
+      d.dir(appPath, [
+        d.appPubspec({
+          "barback": {"path": "../barback"}
+        })
+      ]).create();
+
+      pubCommand(command);
+
+      d.packagesDir({
+        "barback": current
+      }).validate();
+    });
   });
 
   integration("unlock if the locked version doesn't meet pub's constraint", () {
     servePackages([
-      packageMap("barback", previousVersion.toString()),
-      packageMap("barback", barback.supportedVersion.toString())
+      packageMap("barback", previous),
+      packageMap("barback", current)
     ]);
 
     d.appDir({"barback": "any"}).create();
 
     // Hand-create a lockfile to pin barback to an older version.
     createLockFile("myapp", hosted: {
-      "barback": previousVersion.toString()
+      "barback": previous
     });
 
     pubGet();
 
     // It should be upgraded.
     d.packagesDir({
-      "barback": barback.supportedVersion.toString()
+      "barback": current
     }).validate();
   });
+
+  integration("includes pub in the error if a solve failed because there "
+      "is no version available", () {
+    servePackages([
+      packageMap("barback", previous)
+    ]);
+
+    d.appDir({"barback": "any"}).create();
+
+    pubGet(error: """
+Package barback has no versions that match >=$current <$max derived from:
+- myapp depends on version any
+- pub itself depends on version >=$current <$max""");
+  });
+
+  integration("includes pub in the error if a solve failed because there "
+      "is a disjoint constraint", () {
+    servePackages([
+      packageMap("barback", current)
+    ]);
+
+    d.appDir({"barback": previous}).create();
+
+    pubGet(error: """
+Incompatible version constraints on barback:
+- myapp depends on version $previous
+- pub itself depends on version >=$current <$max""");
+  });
 }
\ No newline at end of file
diff --git a/sdk/lib/_internal/pub/test/pub_get_and_upgrade_test.dart b/sdk/lib/_internal/pub/test/pub_get_and_upgrade_test.dart
index f0df450..337c957 100644
--- a/sdk/lib/_internal/pub/test/pub_get_and_upgrade_test.dart
+++ b/sdk/lib/_internal/pub/test/pub_get_and_upgrade_test.dart
@@ -110,7 +110,7 @@
       ]).create();
 
       pubCommand(command,
-          error: new RegExp("^Incompatible dependencies on 'baz':\n"));
+          error: new RegExp("^Incompatible dependencies on baz:\n"));
     });
 
     integration('does not allow a dependency on itself', () {
diff --git a/sdk/lib/_internal/pub/test/serve/warns_on_assets_paths_test.dart b/sdk/lib/_internal/pub/test/serve/warns_on_assets_paths_test.dart
new file mode 100644
index 0000000..c4ae0c5
--- /dev/null
+++ b/sdk/lib/_internal/pub/test/serve/warns_on_assets_paths_test.dart
@@ -0,0 +1,117 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library pub_tests;
+
+import 'package:path/path.dart' as path;
+import 'package:scheduled_test/scheduled_test.dart';
+
+import '../descriptor.dart' as d;
+import '../test_pub.dart';
+import 'utils.dart';
+
+getWarningRegExp(String assetsPath) {
+  // Escape backslashes since they are metacharacters in a regex.
+  assetsPath = assetsPath.replaceAll("\\", "\\\\");
+  return new RegExp(
+      '^Warning: Pub reserves paths containing "assets" for using assets from '
+      'packages\\. Please rename the path "$assetsPath"\\.\$');
+}
+
+main() {
+  initConfig();
+
+  integration('warns user about assets dir in the root of "web"', () {
+    d.dir(appPath, [
+      d.appPubspec(),
+      d.dir('web', [
+        d.file('index.html'),
+        d.dir('assets')
+      ])
+    ]).create();
+
+    var pub = pubServe();
+    waitForBuildSuccess();
+    endPubServe();
+
+    var assetsPath = path.join('web', 'assets');
+    expect(pub.remainingStderr(), completion(
+        matches(getWarningRegExp(assetsPath))));
+  });
+
+  integration('warns user about assets dir nested anywhere in "web"', () {
+    d.dir(appPath, [
+      d.appPubspec(),
+      d.dir('web', [
+        d.file('index.html'),
+        d.dir('foo', [
+          d.dir('assets')
+        ])
+      ])
+    ]).create();
+
+    var pub = pubServe();
+    waitForBuildSuccess();
+    endPubServe();
+
+    var assetsPath = path.join('web', 'foo', 'assets');
+    expect(pub.remainingStderr(), completion(
+        matches(getWarningRegExp(assetsPath))));
+  });
+
+  integration('warns user about assets file in the root of "web"', () {
+    d.dir(appPath, [
+      d.appPubspec(),
+      d.dir('web', [
+        d.file('index.html'),
+        d.file('assets')
+      ])
+    ]).create();
+
+    var pub = pubServe();
+    waitForBuildSuccess();
+    endPubServe();
+
+    var assetsPath = path.join('web', 'assets');
+    expect(pub.remainingStderr(), completion(
+        matches(getWarningRegExp(assetsPath))));
+  });
+
+  integration('warns user about assets file nested anywhere in "web"', () {
+    d.dir(appPath, [
+      d.appPubspec(),
+      d.dir('web', [
+        d.file('index.html'),
+        d.dir('foo', [
+          d.file('assets')
+        ])
+      ])
+    ]).create();
+
+    var pub = pubServe();
+    waitForBuildSuccess();
+    endPubServe();
+
+    var assetsPath = path.join('web', 'foo', 'assets');
+    expect(pub.remainingStderr(), completion(
+        matches(getWarningRegExp(assetsPath))));
+  });
+
+  integration('does not warn if no assets dir or file anywhere in "web"', () {
+    d.dir(appPath, [
+      d.appPubspec(),
+      d.dir('web', [
+        d.file('index.html'),
+        d.dir('foo')
+      ])
+    ]).create();
+
+    var pub = pubServe();
+    waitForBuildSuccess();
+    endPubServe();
+
+    expect(pub.remainingStderr(), completion(
+        matches(r'^(?!Warning: Pub reserves paths containing "assets").*$')));
+  });
+}
diff --git a/sdk/lib/_internal/pub/test/test_pub.dart b/sdk/lib/_internal/pub/test/test_pub.dart
index 6eef80b..22c12b2 100644
--- a/sdk/lib/_internal/pub/test/test_pub.dart
+++ b/sdk/lib/_internal/pub/test/test_pub.dart
@@ -147,6 +147,7 @@
   if (_server == null) return new Future.value();
   var future = _server.close();
   _server = null;
+  _hasServer = false;
   _portCompleterCache = null;
   return future;
 }
@@ -263,13 +264,13 @@
 /// Enum identifying a pub command that can be run with a well-defined success
 /// output.
 class RunCommand {
-  static final get = new RunCommand('get', 'Got dependencies!');
-  static final upgrade = new RunCommand('upgrade', 'Dependencies upgraded!');
+  static final get = new RunCommand('get', new RegExp(r'Got dependencies!$'));
+  static final upgrade = new RunCommand('upgrade', new RegExp(
+      r'(No dependencies changed\.|Changed \d+ dependenc(y|ies)!)$'));
 
   final String name;
   final RegExp success;
-  RunCommand(this.name, String message)
-      : success = new RegExp("$message\$");
+  RunCommand(this.name, this.success);
 }
 
 /// Many tests validate behavior that is the same between pub get and
@@ -290,8 +291,8 @@
 /// [warning] to stderr. If [error] is given, it expects the command to *only*
 /// print [error] to stderr.
 // TODO(rnystrom): Clean up other tests to call this when possible.
-void pubCommand(RunCommand command, {Iterable<String> args, Pattern error,
-    Pattern warning}) {
+void pubCommand(RunCommand command,
+    {Iterable<String> args, Pattern output, Pattern error, Pattern warning}) {
   if (error != null && warning != null) {
     throw new ArgumentError("Cannot pass both 'error' and 'warning'.");
   }
@@ -299,7 +300,7 @@
   var allArgs = [command.name];
   if (args != null) allArgs.addAll(args);
 
-  var output = command.success;
+  if (output == null) output = command.success;
 
   var exitCode = null;
   if (error != null) exitCode = 1;
@@ -316,9 +317,10 @@
   pubCommand(RunCommand.get, args: args, error: error, warning: warning);
 }
 
-void pubUpgrade({Iterable<String> args, Pattern error,
+void pubUpgrade({Iterable<String> args, Pattern output, Pattern error,
     Pattern warning}) {
-  pubCommand(RunCommand.upgrade, args: args, error: error, warning: warning);
+  pubCommand(RunCommand.upgrade, args: args, output: output, error: error,
+      warning: warning);
 }
 
 /// Defines an integration test. The [body] should schedule a series of
@@ -433,7 +435,7 @@
   // TODO(rnystrom): This is overly specific and inflexible regarding different
   // test packages. Should validate this a little more loosely.
   expect(pub.nextLine(), completion(startsWith(
-      'Publishing "test_pkg" 1.0.0 to ')));
+      'Publishing test_pkg 1.0.0 to ')));
   expect(pub.nextLine(), completion(equals("|-- LICENSE")));
   expect(pub.nextLine(), completion(equals("|-- lib")));
   expect(pub.nextLine(), completion(equals("|   '-- test_pkg.dart")));
@@ -835,7 +837,7 @@
   return schedule(() {
     var cache = new SystemCache.withSources(path.join(sandboxDir, cachePath));
 
-    return new Future.sync(() {
+    return syncFuture(() {
       var validator = fn(new Entrypoint(path.join(sandboxDir, appPath), cache));
       return validator.validate().then((_) {
         return new Pair(validator.errors, validator.warnings);
diff --git a/sdk/lib/_internal/pub/test/transformer/dart2js/reads_nonpublic_files_from_disk_test.dart b/sdk/lib/_internal/pub/test/transformer/dart2js/reads_nonpublic_files_from_disk_test.dart
new file mode 100644
index 0000000..982c45e
--- /dev/null
+++ b/sdk/lib/_internal/pub/test/transformer/dart2js/reads_nonpublic_files_from_disk_test.dart
@@ -0,0 +1,42 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS d.file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library pub_tests;
+
+import 'package:scheduled_test/scheduled_test.dart';
+
+import '../../descriptor.dart' as d;
+import '../../test_pub.dart';
+import '../../serve/utils.dart';
+
+main() {
+  initConfig();
+  integration("reads imported files from non-public directories straight from"
+      "the file system", () {
+    // Since the "private" directory isn't served by the barback server, the
+    // relative import for it will fail if the dart2js transformer tries to
+    // get it from barback. This is a regression test for dartbug.com/15688.
+    d.dir(appPath, [
+      d.appPubspec(),
+      d.dir("private", [
+        d.file("lib.dart", """
+library lib;
+lib() => 'libtext';
+""")
+      ]),
+      d.dir("web", [
+        d.file("main.dart", """
+import '../private/lib.dart';
+void main() {
+  print(lib());
+}
+""")
+      ])
+    ]).create();
+
+    pubServe();
+    requestShouldSucceed("main.dart.js", contains("libtext"));
+    endPubServe();
+  });
+}
diff --git a/sdk/lib/_internal/pub/test/unknown_source_test.dart b/sdk/lib/_internal/pub/test/unknown_source_test.dart
index d198083..9ecc3a9 100644
--- a/sdk/lib/_internal/pub/test/unknown_source_test.dart
+++ b/sdk/lib/_internal/pub/test/unknown_source_test.dart
@@ -17,7 +17,7 @@
       d.appDir({"foo": {"bad": "foo"}}).create();
 
       pubCommand(command, error:
-          "Package 'myapp' depends on 'foo' from unknown source 'bad'.");
+          'Package myapp depends on foo from unknown source "bad".');
     });
 
     integration('fails gracefully on transitive dependency from an unknown '
@@ -30,7 +30,7 @@
       d.appDir({"foo": {"path": "../foo"}}).create();
 
       pubCommand(command, error:
-          "Package 'foo' depends on 'bar' from unknown source 'bad'.");
+          'Package foo depends on bar from unknown source "bad".');
     });
 
     integration('ignores unknown source in lockfile', () {
diff --git a/sdk/lib/_internal/pub/test/upgrade/report/describes_change_test.dart b/sdk/lib/_internal/pub/test/upgrade/report/describes_change_test.dart
new file mode 100644
index 0000000..9bb02a5
--- /dev/null
+++ b/sdk/lib/_internal/pub/test/upgrade/report/describes_change_test.dart
@@ -0,0 +1,62 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library pub_tests;
+
+import '../../descriptor.dart' as d;
+import '../../test_pub.dart';
+
+main() {
+  initConfig();
+  integration("shows how package changed from previous lockfile", () {
+    servePackages([
+      packageMap("unchanged", "1.0.0"),
+      packageMap("version_changed", "1.0.0"),
+      packageMap("version_changed", "2.0.0"),
+      packageMap("source_changed", "1.0.0")
+    ]);
+
+    d.dir("source_changed", [
+      d.libDir("source_changed"),
+      d.libPubspec("source_changed", "2.0.0")
+    ]).create();
+
+    d.dir("description_changed_1", [
+      d.libDir("description_changed"),
+      d.libPubspec("description_changed", "1.0.0")
+    ]).create();
+
+    d.dir("description_changed_2", [
+      d.libDir("description_changed"),
+      d.libPubspec("description_changed", "1.0.0")
+    ]).create();
+
+    // Create the first lockfile.
+    d.appDir({
+      "unchanged": "any",
+      "version_changed": "1.0.0",
+      "source_changed": "any",
+      "description_changed": {"path": "../description_changed_1"}
+    }).create();
+
+    pubGet();
+
+    // Change the pubspec.
+    d.appDir({
+      "unchanged": "any",
+      "version_changed": "any",
+      "source_changed": {"path": "../source_changed"},
+      "description_changed": {"path": "../description_changed_2"}
+    }).create();
+
+    // Upgrade everything.
+    pubUpgrade(output: new RegExp(r"""
+Resolving dependencies\.+
+. description_changed 1\.0\.0 from path \.\.[/\\]description_changed_2 \(was 1\.0\.0 from path \.\.[/\\]description_changed_1\)
+. source_changed 2\.0\.0 from path \.\.[/\\]source_changed \(was 1\.0\.0\)
+. unchanged 1\.0\.0
+. version_changed 2\.0\.0 \(was 1\.0\.0\)
+""", multiLine: true));
+  });
+}
diff --git a/sdk/lib/_internal/pub/test/upgrade/report/does_not_show_newer_versions_for_locked_packages_test.dart b/sdk/lib/_internal/pub/test/upgrade/report/does_not_show_newer_versions_for_locked_packages_test.dart
new file mode 100644
index 0000000..b442686
--- /dev/null
+++ b/sdk/lib/_internal/pub/test/upgrade/report/does_not_show_newer_versions_for_locked_packages_test.dart
@@ -0,0 +1,44 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library pub_tests;
+
+import '../../descriptor.dart' as d;
+import '../../test_pub.dart';
+
+main() {
+  initConfig();
+  integration("does not show how many newer versions are available for "
+      "packages that are locked and not being upgraded", () {
+    servePackages([
+      packageMap("not_upgraded", "1.0.0"),
+      packageMap("not_upgraded", "2.0.0"),
+      packageMap("not_upgraded", "3.0.0-dev"),
+      packageMap("upgraded", "1.0.0"),
+      packageMap("upgraded", "2.0.0"),
+      packageMap("upgraded", "3.0.0-dev")
+    ]);
+
+    // Constraint everything to the first version.
+    d.appDir({
+      "not_upgraded": "1.0.0",
+      "upgraded": "1.0.0"
+    }).create();
+
+    pubGet();
+
+    // Loosen the constraints.
+    d.appDir({
+      "not_upgraded": "any",
+      "upgraded": "any"
+    }).create();
+
+    // Only upgrade "upgraded".
+    pubUpgrade(args: ["upgraded"], output: new RegExp(r"""
+Resolving dependencies\.+
+  not_upgraded 1\.0\.0
+. upgraded 2\.0\.0 \(was 1\.0\.0\) \(1 newer unstable version available\)
+""", multiLine: true));
+  });
+}
diff --git a/sdk/lib/_internal/pub/test/upgrade/report/highlights_overrides_test.dart b/sdk/lib/_internal/pub/test/upgrade/report/highlights_overrides_test.dart
new file mode 100644
index 0000000..6bbccc5
--- /dev/null
+++ b/sdk/lib/_internal/pub/test/upgrade/report/highlights_overrides_test.dart
@@ -0,0 +1,32 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library pub_tests;
+
+import '../../descriptor.dart' as d;
+import '../../test_pub.dart';
+
+main() {
+  initConfig();
+  integration("highlights overridden packages", () {
+    servePackages([
+      packageMap("overridden", "1.0.0")
+    ]);
+
+    d.dir(appPath, [
+      d.pubspec({
+        "name": "myapp",
+        "dependency_overrides": {
+          "overridden": "any"
+        }
+      })
+    ]).create();
+
+    // Upgrade everything.
+    pubUpgrade(output: new RegExp(r"""
+Resolving dependencies\.+
+! overridden 1\.0\.0 \(overridden\)
+""", multiLine: true));
+  });
+}
diff --git a/sdk/lib/_internal/pub/test/upgrade/report/leading_character_shows_change_test.dart b/sdk/lib/_internal/pub/test/upgrade/report/leading_character_shows_change_test.dart
new file mode 100644
index 0000000..815f640
--- /dev/null
+++ b/sdk/lib/_internal/pub/test/upgrade/report/leading_character_shows_change_test.dart
@@ -0,0 +1,92 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library pub_tests;
+
+import '../../descriptor.dart' as d;
+import '../../test_pub.dart';
+
+main() {
+  initConfig();
+  integration("the character before each package describes the change", () {
+    servePackages([
+      packageMap("added", "1.0.0"),
+      packageMap("downgraded", "1.0.0"),
+      packageMap("downgraded", "2.0.0"),
+      packageMap("overridden", "1.0.0"),
+      packageMap("removed", "1.0.0"),
+      packageMap("source_changed", "1.0.0"),
+      packageMap("upgraded", "1.0.0"),
+      packageMap("upgraded", "2.0.0"),
+      packageMap("unchanged", "1.0.0")
+    ]);
+
+    d.dir("description_changed_1", [
+      d.libDir("description_changed"),
+      d.libPubspec("description_changed", "1.0.0")
+    ]).create();
+
+    d.dir("description_changed_2", [
+      d.libDir("description_changed"),
+      d.libPubspec("description_changed", "1.0.0")
+    ]).create();
+
+    d.dir("source_changed", [
+      d.libDir("source_changed"),
+      d.libPubspec("source_changed", "1.0.0")
+    ]).create();
+
+    // Create the first lockfile.
+    d.dir(appPath, [
+      d.pubspec({
+        "name": "myapp",
+        "dependencies": {
+          "description_changed": {"path": "../description_changed_1"},
+          "downgraded": "2.0.0",
+          "removed": "any",
+          "source_changed": "any",
+          "unchanged": "any",
+          "upgraded": "1.0.0"
+        },
+        "dependency_overrides": {
+          "overridden": "any"
+        }
+      })
+    ]).create();
+
+    pubGet();
+
+    // Change the pubspec.
+    d.dir(appPath, [
+      d.pubspec({
+        "name": "myapp",
+        "dependencies": {
+          "added": "any",
+          "description_changed": {"path": "../description_changed_2"},
+          "downgraded": "1.0.0",
+          "source_changed": {"path": "../source_changed"},
+          "unchanged": "any",
+          "upgraded": "2.0.0"
+        },
+        "dependency_overrides": {
+          "overridden": "any"
+        }
+      })
+    ]).create();
+
+    // Upgrade everything.
+    pubUpgrade(output: new RegExp(r"""
+Resolving dependencies\.+
+\+ added .*
+\* description_changed .*
+< downgraded .*
+! overridden .*
+\* source_changed .*
+  unchanged .*
+> upgraded .*
+These packages are no longer being depended on:
+- removed .*
+""", multiLine: true));
+  });
+}
diff --git a/sdk/lib/_internal/pub/test/upgrade/report/shows_newer_available_versions_test.dart b/sdk/lib/_internal/pub/test/upgrade/report/shows_newer_available_versions_test.dart
new file mode 100644
index 0000000..c887135
--- /dev/null
+++ b/sdk/lib/_internal/pub/test/upgrade/report/shows_newer_available_versions_test.dart
@@ -0,0 +1,52 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library pub_tests;
+
+import '../../descriptor.dart' as d;
+import '../../test_pub.dart';
+
+main() {
+  initConfig();
+  integration("shows how many newer versions are available", () {
+    servePackages([
+      packageMap("multiple_newer", "1.0.0"),
+      packageMap("multiple_newer", "1.0.1-unstable.1"),
+      packageMap("multiple_newer", "1.0.1"),
+      packageMap("multiple_newer", "1.0.2-unstable.1"),
+      packageMap("multiple_newer_stable", "1.0.0"),
+      packageMap("multiple_newer_stable", "1.0.1"),
+      packageMap("multiple_newer_stable", "1.0.2"),
+      packageMap("multiple_newer_unstable", "1.0.0"),
+      packageMap("multiple_newer_unstable", "1.0.1-unstable.1"),
+      packageMap("multiple_newer_unstable", "1.0.1-unstable.2"),
+      packageMap("no_newer", "1.0.0"),
+      packageMap("one_newer_unstable", "1.0.0"),
+      packageMap("one_newer_unstable", "1.0.1-unstable.1"),
+      packageMap("one_newer_stable", "1.0.0"),
+      packageMap("one_newer_stable", "1.0.1")
+    ]);
+
+    // Constraint everything to the first version.
+    d.appDir({
+      "multiple_newer": "1.0.0",
+      "multiple_newer_stable": "1.0.0",
+      "multiple_newer_unstable": "1.0.0",
+      "no_newer": "1.0.0",
+      "one_newer_unstable": "1.0.0",
+      "one_newer_stable": "1.0.0"
+    }).create();
+
+    // Upgrade everything.
+    pubUpgrade(output: new RegExp(r"""
+Resolving dependencies\.+
+. multiple_newer 1\.0\.0 \(1 newer version available\)
+. multiple_newer_stable 1\.0\.0 \(2 newer versions available\)
+. multiple_newer_unstable 1\.0\.0 \(2 newer unstable versions available\)
+. no_newer 1\.0\.0
+. one_newer_stable 1\.0\.0 \(1 newer version available\)
+. one_newer_unstable 1\.0\.0 \(1 newer unstable version available\)
+""", multiLine: true));
+  });
+}
diff --git a/sdk/lib/_internal/pub/test/upgrade/report/shows_number_of_changed_dependencies_test.dart b/sdk/lib/_internal/pub/test/upgrade/report/shows_number_of_changed_dependencies_test.dart
new file mode 100644
index 0000000..77010e2c
--- /dev/null
+++ b/sdk/lib/_internal/pub/test/upgrade/report/shows_number_of_changed_dependencies_test.dart
@@ -0,0 +1,38 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library pub_tests;
+
+import '../../descriptor.dart' as d;
+import '../../test_pub.dart';
+
+main() {
+  initConfig();
+  integration("does not show how many newer versions are available for "
+      "packages that are locked and not being upgraded", () {
+    servePackages([
+      packageMap("a", "1.0.0"),
+      packageMap("b", "1.0.0"),
+      packageMap("c", "2.0.0")
+    ]);
+
+    d.appDir({
+      "a": "any"
+    }).create();
+
+    // One dependency changed.
+    pubUpgrade(output: new RegExp(r"Changed 1 dependency!$"));
+
+    // Remove one and add two.
+    d.appDir({
+      "b": "any",
+      "c": "any"
+    }).create();
+
+    pubUpgrade(output: new RegExp(r"Changed 3 dependencies!$"));
+
+    // Don't change anything.
+    pubUpgrade(output: new RegExp(r"No dependencies changed.$"));
+  });
+}
diff --git a/sdk/lib/_internal/pub/test/version_solver_test.dart b/sdk/lib/_internal/pub/test/version_solver_test.dart
index 4200480..11afd79 100644
--- a/sdk/lib/_internal/pub/test/version_solver_test.dart
+++ b/sdk/lib/_internal/pub/test/version_solver_test.dart
@@ -15,6 +15,7 @@
 import '../lib/src/sdk.dart' as sdk;
 import '../lib/src/source.dart';
 import '../lib/src/system_cache.dart';
+import '../lib/src/utils.dart';
 import '../lib/src/version.dart';
 import '../lib/src/solver/version_solver.dart';
 import 'test_pub.dart';
@@ -261,7 +262,7 @@
     'bar 1.0.0': {
       'myapp from mock2': '>=1.0.0'
     }
-  }, error: sourceMismatch('foo', 'bar'));
+  }, error: sourceMismatch('myapp', 'foo', 'bar'));
 
   testResolve('with wrong version', {
     'myapp 1.0.0': {
@@ -322,7 +323,7 @@
     },
     'foo 2.0.0': {},
     'foo 2.1.3': {}
-  }, error: noVersion(['myapp']));
+  }, error: noVersion(['myapp', 'foo']));
 
   testResolve('no version that matches combined constraint', {
     'myapp 0.0.0': {
@@ -337,7 +338,7 @@
     },
     'shared 2.5.0': {},
     'shared 3.5.0': {}
-  }, error: noVersion(['foo', 'bar']));
+  }, error: noVersion(['shared', 'foo', 'bar']));
 
   testResolve('disjoint constraints', {
     'myapp 0.0.0': {
@@ -352,7 +353,7 @@
     },
     'shared 2.0.0': {},
     'shared 4.0.0': {}
-  }, error: disjointConstraint(['foo', 'bar']));
+  }, error: disjointConstraint(['shared', 'foo', 'bar']));
 
   testResolve('mismatched descriptions', {
     'myapp 0.0.0': {
@@ -367,7 +368,7 @@
     },
     'shared-x 1.0.0': {},
     'shared-y 1.0.0': {}
-  }, error: descriptionMismatch('foo', 'bar'));
+  }, error: descriptionMismatch('shared', 'foo', 'bar'));
 
   testResolve('mismatched sources', {
     'myapp 0.0.0': {
@@ -382,7 +383,7 @@
     },
     'shared 1.0.0': {},
     'shared 1.0.0 from mock2': {}
-  }, error: sourceMismatch('foo', 'bar'));
+  }, error: sourceMismatch('shared', 'foo', 'bar'));
 
   testResolve('no valid solution', {
     'myapp 0.0.0': {
@@ -411,7 +412,7 @@
     },
     'a 1.0.0': {},
     'b 1.0.0': {}
-  }, error: noVersion(['myapp']), maxTries: 1);
+  }, error: noVersion(['myapp', 'b']), maxTries: 1);
 }
 
 badSource() {
@@ -632,7 +633,7 @@
     'c 3.0.0': {},
     'c 4.0.0': {},
     'c 5.0.0': {},
-  }, error: sourceMismatch('myapp', 'b'), maxTries: 1);
+  }, error: sourceMismatch('a', 'myapp', 'b'), maxTries: 1);
 
   testResolve('backjump to conflicting description', {
     'myapp 0.0.0': {
@@ -650,7 +651,7 @@
     'c 3.0.0': {},
     'c 4.0.0': {},
     'c 5.0.0': {},
-  }, error: descriptionMismatch('myapp', 'b'), maxTries: 1);
+  }, error: descriptionMismatch('a', 'myapp', 'b'), maxTries: 1);
 
   // Dependencies are ordered so that packages with fewer versions are tried
   // first. Here, there are two valid solutions (either a or b must be
@@ -1083,9 +1084,10 @@
       DisjointConstraintException);
 }
 
-FailMatcherBuilder descriptionMismatch(String package1, String package2) {
-  return (maxTries) => new SolveFailMatcher([package1, package2], maxTries,
-      DescriptionMismatchException);
+FailMatcherBuilder descriptionMismatch(
+    String package, String depender1, String depender2) {
+  return (maxTries) => new SolveFailMatcher([package, depender1, depender2],
+      maxTries, DescriptionMismatchException);
 }
 
 // If no solution can be found, the solver just reports the last failure that
@@ -1094,9 +1096,10 @@
 SolveFailMatcher couldNotSolve(maxTries) =>
     new SolveFailMatcher([], maxTries, null);
 
-FailMatcherBuilder sourceMismatch(String package1, String package2) {
-  return (maxTries) => new SolveFailMatcher([package1, package2], maxTries,
-      SourceMismatchException);
+FailMatcherBuilder sourceMismatch(
+    String package, String depender1, String depender2) {
+  return (maxTries) => new SolveFailMatcher([package, depender1, depender2],
+      maxTries, SourceMismatchException);
 }
 
 unknownSource(String depender, String dependency, String source) {
@@ -1268,7 +1271,7 @@
   }
 
   Future<List<Version>> getVersions(String name, String description) {
-    return new Future.sync(() {
+    return syncFuture(() {
       // Make sure the solver doesn't request the same thing twice.
       if (_requestedVersions.contains(description)) {
         throw new Exception('Version list for $description was already '
@@ -1287,7 +1290,7 @@
   }
 
   Future<Pubspec> describe(PackageId id) {
-    return new Future.sync(() {
+    return syncFuture(() {
       // Make sure the solver doesn't request the same thing twice.
       if (_requestedPubspecs.containsKey(id.description) &&
           _requestedPubspecs[id.description].contains(id.version)) {
diff --git a/sdk/lib/async/stream.dart b/sdk/lib/async/stream.dart
index 957ca2e..b722e46 100644
--- a/sdk/lib/async/stream.dart
+++ b/sdk/lib/async/stream.dart
@@ -49,6 +49,11 @@
  *
  * Broadcast streams are used for independent events/observers.
  *
+ * Stream transformations, such as [where] and [skip], always return
+ * non-broadcast streams. If several listeners want to listen to the returned
+ * stream, use [asBroadcastStream] to create a broadcast stream on top of the
+ * non-broadcast stream.
+ *
  * The default implementation of [isBroadcast] returns false.
  * A broadcast stream inheriting from [Stream] must override [isBroadcast]
  * to return [:true:].
@@ -256,6 +261,8 @@
    *
    * The new stream sends the same error and done events as this stream,
    * but it only sends the data events that satisfy the [test].
+   *
+   * The returned stream is not a broadcast stream, even if this stream is.
    */
   Stream<T> where(bool test(T event)) {
     return new _WhereStream<T>(this, test);
@@ -264,6 +271,8 @@
   /**
    * Creates a new stream that converts each element of this stream
    * to a new value using the [convert] function.
+   *
+   * The returned stream is not a broadcast stream, even if this stream is.
    */
   Stream map(convert(T event)) {
     return new _MapStream<T, dynamic>(this, convert);
@@ -281,8 +290,8 @@
    * trace. The stack trace argument might be `null` if the stream itself
    * received an error without stack trace.
    *
-   * An [AsyncError] [:e:] is matched by a test function if [:test(e):] returns
-   * true. If [test] is omitted, every error is considered matching.
+   * An asynchronous error [:e:] is matched by a test function if [:test(e):]
+   * returns true. If [test] is omitted, every error is considered matching.
    *
    * If the error is intercepted, the [handle] function can decide what to do
    * with it. It can throw if it wants to raise a new (or the same) error,
@@ -291,6 +300,8 @@
    * If you need to transform an error into a data event, use the more generic
    * [Stream.transform] to handle the event by writing a data event to
    * the output sink
+   *
+   * The returned stream is not a broadcast stream, even if this stream is.
    */
   Stream<T> handleError(Function onError, { bool test(error) }) {
     return new _HandleErrorStream<T>(this, onError, test);
@@ -303,6 +314,8 @@
    * Each incoming event is converted to an [Iterable] of new events,
    * and each of these new events are then sent by the returned stream
    * in order.
+   *
+   * The returned stream is not a broadcast stream, even if this stream is.
    */
   Stream expand(Iterable convert(T value)) {
     return new _ExpandStream<T, dynamic>(this, convert);
@@ -637,6 +650,8 @@
    * Internally the method cancels its subscription after these elements. This
    * means that single-subscription (non-broadcast) streams are closed and
    * cannot be reused after a call to this method.
+   *
+   * The returned stream is not a broadcast stream, even if this stream is.
    */
   Stream<T> take(int count) {
     return new _TakeStream(this, count);
@@ -655,6 +670,8 @@
    * Internally the method cancels its subscription after these elements. This
    * means that single-subscription (non-broadcast) streams are closed and
    * cannot be reused after a call to this method.
+   *
+   * The returned stream is not a broadcast stream, even if this stream is.
    */
   Stream<T> takeWhile(bool test(T element)) {
     return new _TakeWhileStream(this, test);
@@ -662,6 +679,8 @@
 
   /**
    * Skips the first [count] data events from this stream.
+   *
+   * The returned stream is not a broadcast stream, even if this stream is.
    */
   Stream<T> skip(int count) {
     return new _SkipStream(this, count);
@@ -674,6 +693,8 @@
    *
    * Starting with the first data event where [test] returns false for the
    * event data, the returned stream will have the same events as this stream.
+   *
+   * The returned stream is not a broadcast stream, even if this stream is.
    */
   Stream<T> skipWhile(bool test(T element)) {
     return new _SkipWhileStream(this, test);
@@ -687,6 +708,8 @@
    *
    * Equality is determined by the provided [equals] method. If that is
    * omitted, the '==' operator on the last provided data element is used.
+   *
+   * The returned stream is not a broadcast stream, even if this stream is.
    */
   Stream<T> distinct([bool equals(T previous, T next)]) {
     return new _DistinctStream(this, equals);
@@ -977,6 +1000,8 @@
    *
    * If `onTimeout` is omitted, a timeout will just put a [TimeoutException]
    * into the error channel of the returned stream.
+   *
+   * The returned stream is not a broadcast stream, even if this stream is.
    */
   Stream timeout(Duration timeLimit, {void onTimeout(EventSink sink)}) {
     StreamSubscription<T> subscription;
diff --git a/sdk/lib/collection/list.dart b/sdk/lib/collection/list.dart
index ca2b39e..d4dac6a 100644
--- a/sdk/lib/collection/list.dart
+++ b/sdk/lib/collection/list.dart
@@ -20,7 +20,7 @@
  * repeatedly increasing the length of a growable list is not efficient.
  * To avoid this, either override 'add' and 'addAll' to also forward directly
  * to the growable list, or, preferably, use `DelegatingList` from
- * "package:collection_helpers/wrappers.dart" instead.
+ * "package:collection/wrappers.dart" instead.
  */
 abstract class ListBase<E> = Object with ListMixin<E>;
 
@@ -40,7 +40,7 @@
  * repeatedly increasing the length of a growable list is not efficient.
  * To avoid this, either override 'add' and 'addAll' to also forward directly
  * to the growable list, or, if possible, use `DelegatingList` from
- * "package:collection_helpers/wrappers.dart" instead.
+ * "package:collection/wrappers.dart" instead.
  */
 abstract class ListMixin<E> implements List<E> {
 
diff --git a/sdk/lib/collection/splay_tree.dart b/sdk/lib/collection/splay_tree.dart
index 389e678..114505e 100644
--- a/sdk/lib/collection/splay_tree.dart
+++ b/sdk/lib/collection/splay_tree.dart
@@ -625,10 +625,47 @@
 }
 
 
+/**
+ * A [Set] of objects that can be ordered relative to each other.
+ *
+ * The set is based on a self-balancing binary tree. It allows most operations
+ * in amortized logarithmic time.
+ *
+ * Elements of the set are compared using the `compare` function passed in
+ * the constructor. If that is omitted, the objects are assumed to be
+ * [Comparable], and are compared using their [Comparable.compareTo]
+ * method. Non-comparable objects (including `null`) will not work as an element
+ * in that case.
+ */
 class SplayTreeSet<E> extends _SplayTree<E> with IterableMixin<E>
                       implements Set<E> {
   Comparator _comparator;
   _Predicate _validKey;
+
+  /**
+   * Create a new [SplayTreeSet] with the given compare function.
+   *
+   * If the [compare] function is omitted, it defaults to [Comparable.compare],
+   * and the elements must be comparable.
+   *
+   * A provided `compare` function may not work on all objects. It may not even
+   * work on all `E` instances.
+   *
+   * For operations that add elements to the set, the user is supposed to not
+   * pass in objects that doesn't work with the compare function.
+   *
+   * The methods [contains], [remove], [lookup], [removeAll] or [retainAll]
+   * are typed to accept any object(s), and the [isValidKey] test can used to
+   * filter those objects before handing them to the `compare` function.
+   *
+   * If [isValidKey] is provided, only values satisfying `isValidKey(other)`
+   * are compared using the `compare` method in the methods mentioned above.
+   * If the `isValidKey` function returns false for an object, it is assumed to
+   * not be in the set.
+   *
+   * If omitted, the `isValidKey` function defaults to checking against the
+   * type parameter: `other is E`.
+   */
   SplayTreeSet([int compare(E key1, E key2), bool isValidKey(potentialKey)])
       : _comparator = (compare == null) ? Comparable.compare : compare,
         _validKey = (isValidKey != null) ? isValidKey : ((v) => v is E);
@@ -685,7 +722,7 @@
     }
   }
 
-  void removeAll(Iterable elements) {
+  void removeAll(Iterable<Object> elements) {
     for (Object element in elements) {
       if (_validKey(element)) _remove(element);
     }
@@ -703,7 +740,8 @@
         // The iterator should not have side effects.
         throw new ConcurrentModificationError(this);
       }
-      if (this.contains(object)) retainSet.add(object);
+      // Equivalent to this.contains(object).
+      if (_validKey(object) && _splay(object) == 0) retainSet.add(_root.key);
     }
     // Take over the elements from the retained set, if it differs.
     if (retainSet._count != _count) {
@@ -745,7 +783,7 @@
   }
 
   Set<E> intersection(Set<E> other) {
-    Set<E> result = new SplayTreeSet<E>();
+    Set<E> result = new SplayTreeSet<E>(_compare, _validKey);
     for (E element in this) {
       if (other.contains(element)) result.add(element);
     }
@@ -753,7 +791,7 @@
   }
 
   Set<E> difference(Set<E> other) {
-    Set<E> result = new SplayTreeSet<E>();
+    Set<E> result = new SplayTreeSet<E>(_compare, _validKey);
     for (E element in this) {
       if (!other.contains(element)) result.add(element);
     }
@@ -765,7 +803,7 @@
   }
 
   SplayTreeSet<E> _clone() {
-    var set = new SplayTreeSet<E>();
+    var set = new SplayTreeSet<E>(_compare, _validKey);
     set._count = _count;
     set._root = _cloneNode(_root);
     return set;
@@ -777,7 +815,7 @@
                                           ..right = _cloneNode(node.right);
   }
 
-  bool containsAll(Iterable other) {
+  bool containsAll(Iterable<Object> other) {
     for (var element in other) {
       if (!this.contains(element)) return false;
     }
diff --git a/sdk/lib/convert/chunked_conversion.dart b/sdk/lib/convert/chunked_conversion.dart
index 80425fd..c0a5c65 100644
--- a/sdk/lib/convert/chunked_conversion.dart
+++ b/sdk/lib/convert/chunked_conversion.dart
@@ -9,6 +9,9 @@
 /**
  * A [ChunkedConversionSink] is used to transmit data more efficiently between
  * two converters during chunked conversions.
+ *
+ * It is recommended that implementations of `ChunkedConversionSink` extends
+ * this class, to inherit any further methods that may be added to the class.
  */
 abstract class ChunkedConversionSink<T> {
   ChunkedConversionSink();
diff --git a/sdk/lib/convert/converter.dart b/sdk/lib/convert/converter.dart
index 0556761..b4c12f0 100644
--- a/sdk/lib/convert/converter.dart
+++ b/sdk/lib/convert/converter.dart
@@ -7,8 +7,8 @@
 /**
  * A [Converter] converts data from one representation into another.
  *
- * *Converters are still experimental and are subject to change without notice.*
- *
+ * It is recommended that implementations of `Converter` extend this class,
+ * to inherit any further methods that may be added to the class.
  */
 abstract class Converter<S, T> implements StreamTransformer {
   const Converter();
diff --git a/sdk/lib/core/comparable.dart b/sdk/lib/core/comparable.dart
index 21161df..8896b25 100644
--- a/sdk/lib/core/comparable.dart
+++ b/sdk/lib/core/comparable.dart
@@ -35,10 +35,10 @@
   int compareTo(T other);
 
   /**
-   * Compare one comparable to another.
+   * A [Comparator] that compares one comparable to another.
    *
    * This utility function is used as the default comparator
-   * for the [List] sort function.
+   * for ordering collections, for example in the [List] sort function.
    */
   static int compare(Comparable a, Comparable b) => a.compareTo(b);
 }
diff --git a/sdk/lib/core/double.dart b/sdk/lib/core/double.dart
index 4aa161b..53964e4 100644
--- a/sdk/lib/core/double.dart
+++ b/sdk/lib/core/double.dart
@@ -60,6 +60,15 @@
   double abs();
 
   /**
+   * Returns the sign of the double's numerical value.
+   *
+   * Returns -1.0 if the value is less than zero,
+   * +1.0 if the value is greater than zero,
+   * and the value itself if it is -0.0, 0.0 or NaN.
+   */
+  double get sign;
+
+  /**
    * Returns the integer closest to `this`.
    *
    * Rounds away from zero when there is no closest integer:
diff --git a/sdk/lib/core/int.dart b/sdk/lib/core/int.dart
index 6ca2718..23eda31 100644
--- a/sdk/lib/core/int.dart
+++ b/sdk/lib/core/int.dart
@@ -196,6 +196,14 @@
    */
   int abs();
 
+  /**
+   * Returns the sign of this integer.
+   *
+   * Returns 0 for zero, -1 for values less than zero and
+   * +1 for values greater than zero.
+   */
+  int get sign;
+
   /** Returns `this`. */
   int round();
 
diff --git a/sdk/lib/core/list.dart b/sdk/lib/core/list.dart
index a33cd35..cf4da42 100644
--- a/sdk/lib/core/list.dart
+++ b/sdk/lib/core/list.dart
@@ -16,6 +16,14 @@
  *
  * * Growable list. Full implementation of the API defined in this class.
  *
+ * The default growable list, as returned by `new List()` or `[]`, keeps
+ * an internal buffer, and grows that buffer when necessary. This guarantees
+ * that a sequence of [add] operations will each execute in amortized constant
+ * time. Setting the length directly may take time proportional to the new
+ * length, and may change the internal capacity so that a following add
+ * operation will need to immediately increase the buffer capacity.
+ * Other list implementations may have different performance behavior.
+ *
  * The following code illustrates that some List implementations support
  * only a subset of the API.
  *
diff --git a/sdk/lib/core/map.dart b/sdk/lib/core/map.dart
index fb09d30..b289d9a 100644
--- a/sdk/lib/core/map.dart
+++ b/sdk/lib/core/map.dart
@@ -18,17 +18,26 @@
  */
 abstract class Map<K, V> {
   /**
-   * Creates a Map instance with the default implementation.
+   * Creates a Map instance with the default implementation, [LinkedHashMap].
+   *
+   * A `LinkedHashMap` requires the keys to implement compatible
+   * `operator==` and `hashCode`, and it allows null as a key.
    */
   factory Map() = LinkedHashMap<K, V>;
 
   /**
-   * Creates a Map instance that contains all key-value pairs of [other].
+   * Creates a [LinkedHashMap] instance that contains all key-value pairs of
+   * [other].
+   *
+   * A `LinkedHashMap` requires the keys to implement compatible
+   * `operator==` and `hashCode`, and it allows null as a key.
    */
   factory Map.from(Map<K, V> other) = LinkedHashMap<K, V>.from;
 
   /**
-   * Creates an identity map with the default implementation.
+   * Creates an identity map with the default implementation, [LinkedHashMap].
+   *
+   * The returned map allows `null` as a key.
    */
   factory Map.identity() = LinkedHashMap<K, V>.identity;
 
@@ -36,6 +45,10 @@
    * Creates a Map instance in which the keys and values are computed from the
    * [iterable].
    *
+   * The created map is a [LinkedHashMap].
+   * A `LinkedHashMap` requires the keys to implement compatible
+   * `operator==` and `hashCode`, and it allows null as a key.
+   *
    * For each element of the [iterable] this constructor computes a key-value
    * pair, by applying [key] and [value] respectively.
    *
@@ -70,6 +83,10 @@
   /**
    * Creates a Map instance associating the given [keys] to [values].
    *
+   * The created map is a [LinkedHashMap].
+   * A `LinkedHashMap` requires the keys to implement compatible
+   * `operator==` and `hashCode`, and it allows null as a key.
+   *
    * This constructor iterates over [keys] and [values] and maps each element of
    * [keys] to the corresponding element of [values].
    *
diff --git a/sdk/lib/core/num.dart b/sdk/lib/core/num.dart
index 7e4bf45..fc89d65 100644
--- a/sdk/lib/core/num.dart
+++ b/sdk/lib/core/num.dart
@@ -170,6 +170,27 @@
   num abs();
 
   /**
+   * Returns minus one, zero or plus one depending on the sign and
+   * numerical value of the number.
+   *
+   * Returns minus one if the number is less than zero,
+   * plus one if the number is greater than zero,
+   * and zero if the number is equal to zero.
+   *
+   * Returns NaN if the number is the double NaN value.
+   *
+   * Returns a number of the same type as this number.
+   * For doubles, `-0.0.sign == -0.0`.
+
+   * The result satisfies:
+   *
+   *     n == n.sign * n.abs()
+   *
+   * for all numbers `n` (except NaN, because NaN isn't `==` to itself).
+   */
+  num get sign;
+
+  /**
    * Returns the integer closest to `this`.
    *
    * Rounds away from zero when there is no closest integer:
diff --git a/sdk/lib/core/set.dart b/sdk/lib/core/set.dart
index 2dff5f2..059f320 100644
--- a/sdk/lib/core/set.dart
+++ b/sdk/lib/core/set.dart
@@ -13,11 +13,11 @@
  * Set implementations may consider some elements indistinguishable. These
  * elements are treated as being the same for any operation on the set.
  *
- * The default `Set` implementation, [HashSet], considers objects
+ * The default `Set` implementation, [LinkedHashSet], considers objects
  * indistinguishable if they are equal with regard to [Object.operator==].
  *
- * Sets may be either ordered or unordered. [HashSet] is unordered and doesn't
- * guarantee anything about the order that elements are accessed in by
+ * Sets may be either ordered or unordered. [HashSet] is unordered and
+ * doesn't guarantee anything about the order that elements are accessed in by
  * iteration. [LinkedHashSet] iterates in the insertion order of its elements.
  *
  * It is generally not allowed to modify the set (add or remove elements) while
@@ -47,7 +47,7 @@
   /**
    * Creates a [Set] that contains all elements of [other].
    *
-   * The created `Set` is a [HashSet]. As such, it considers elements that
+   * The created `Set` is a [LinkedHashSet]. As such, it considers elements that
    * are equal (using `==`) to be undistinguishable, and requires them to
    * have a compatible [Object.hashCode] implementation.
    */
@@ -95,6 +95,11 @@
 
   /**
    * Removes all elements of this set that are not elements in [elements].
+   *
+   * Checks for each element of [elements] whether there is an element in this
+   * set that is equal to it (according to `this.contains`), and if so, the
+   * equal element in this set is retained, and elements that are not equal
+   * to any element in `elements` are removed.
    */
   void retainAll(Iterable<Object> elements);
 
diff --git a/sdk/lib/io/file.dart b/sdk/lib/io/file.dart
index 152fb6e..7369640 100644
--- a/sdk/lib/io/file.dart
+++ b/sdk/lib/io/file.dart
@@ -107,6 +107,26 @@
   File renameSync(String newPath);
 
   /**
+   * Copy this file. Returns a `Future<File>` that completes
+   * with a [File] instance for the copied file.
+   *
+   * If [newPath] identifies an existing file, that file is
+   * replaced. If [newPath] identifies an existing directory, the
+   * operation fails and the future completes with an exception.
+   */
+  Future<File> copy(String newPath);
+
+   /**
+   * Synchronously copy this file. Returns a [File]
+   * instance for the copied file.
+   *
+   * If [newPath] identifies an existing file, that file is
+   * replaced. If [newPath] identifies an existing directory the
+   * operation fails and an exception is thrown.
+   */
+  File copySync(String newPath);
+
+  /**
    * Get the length of the file. Returns a [:Future<int>:] that
    * completes with the length in bytes.
    */
diff --git a/sdk/lib/io/file_impl.dart b/sdk/lib/io/file_impl.dart
index cb1efe3..fcf2f5e 100644
--- a/sdk/lib/io/file_impl.dart
+++ b/sdk/lib/io/file_impl.dart
@@ -327,6 +327,24 @@
     return new File(newPath);
   }
 
+  Future<File> copy(String newPath) {
+    return _IOService.dispatch(_FILE_COPY, [path, newPath]).then((response) {
+      if (_isErrorResponse(response)) {
+        throw _exceptionFromResponse(
+            response, "Cannot copy file to '$newPath'", path);
+      }
+      return new File(newPath);
+    });
+  }
+
+  external static _copy(String oldPath, String newPath);
+
+  File copySync(String newPath) {
+    var result = _copy(path, newPath);
+    throwIfError(result, "Cannot copy file to '$newPath'", path);
+    return new File(newPath);
+  }
+
   Future<RandomAccessFile> open({FileMode mode: FileMode.READ}) {
     if (mode != FileMode.READ &&
         mode != FileMode.WRITE &&
diff --git a/sdk/lib/io/io_service.dart b/sdk/lib/io/io_service.dart
index bf4b42b..4becb03 100644
--- a/sdk/lib/io/io_service.dart
+++ b/sdk/lib/io/io_service.dart
@@ -9,40 +9,41 @@
 const int _FILE_CREATE = 1;
 const int _FILE_DELETE = 2;
 const int _FILE_RENAME = 3;
-const int _FILE_OPEN = 4;
-const int _FILE_RESOLVE_SYMBOLIC_LINKS = 5;
-const int _FILE_CLOSE = 6;
-const int _FILE_POSITION = 7;
-const int _FILE_SET_POSITION = 8;
-const int _FILE_TRUNCATE = 9;
-const int _FILE_LENGTH = 10;
-const int _FILE_LENGTH_FROM_PATH = 11;
-const int _FILE_LAST_MODIFIED = 12;
-const int _FILE_FLUSH = 13;
-const int _FILE_READ_BYTE = 14;
-const int _FILE_WRITE_BYTE = 15;
-const int _FILE_READ = 16;
-const int _FILE_READ_INTO = 17;
-const int _FILE_WRITE_FROM = 18;
-const int _FILE_CREATE_LINK = 19;
-const int _FILE_DELETE_LINK = 20;
-const int _FILE_RENAME_LINK = 21;
-const int _FILE_LINK_TARGET = 22;
-const int _FILE_TYPE = 23;
-const int _FILE_IDENTICAL = 24;
-const int _FILE_STAT = 25;
-const int _SOCKET_LOOKUP = 26;
-const int _SOCKET_LIST_INTERFACES = 27;
-const int _SOCKET_REVERSE_LOOKUP = 28;
-const int _DIRECTORY_CREATE = 29;
-const int _DIRECTORY_DELETE = 30;
-const int _DIRECTORY_EXISTS = 31;
-const int _DIRECTORY_CREATE_TEMP = 32;
-const int _DIRECTORY_LIST_START = 33;
-const int _DIRECTORY_LIST_NEXT = 34;
-const int _DIRECTORY_LIST_STOP = 35;
-const int _DIRECTORY_RENAME = 36;
-const int _SSL_PROCESS_FILTER = 37;
+const int _FILE_COPY = 4;
+const int _FILE_OPEN = 5;
+const int _FILE_RESOLVE_SYMBOLIC_LINKS = 6;
+const int _FILE_CLOSE = 7;
+const int _FILE_POSITION = 8;
+const int _FILE_SET_POSITION = 9;
+const int _FILE_TRUNCATE = 10;
+const int _FILE_LENGTH = 11;
+const int _FILE_LENGTH_FROM_PATH = 12;
+const int _FILE_LAST_MODIFIED = 13;
+const int _FILE_FLUSH = 14;
+const int _FILE_READ_BYTE = 15;
+const int _FILE_WRITE_BYTE = 16;
+const int _FILE_READ = 17;
+const int _FILE_READ_INTO = 18;
+const int _FILE_WRITE_FROM = 19;
+const int _FILE_CREATE_LINK = 20;
+const int _FILE_DELETE_LINK = 21;
+const int _FILE_RENAME_LINK = 22;
+const int _FILE_LINK_TARGET = 23;
+const int _FILE_TYPE = 24;
+const int _FILE_IDENTICAL = 25;
+const int _FILE_STAT = 26;
+const int _SOCKET_LOOKUP = 27;
+const int _SOCKET_LIST_INTERFACES = 28;
+const int _SOCKET_REVERSE_LOOKUP = 29;
+const int _DIRECTORY_CREATE = 30;
+const int _DIRECTORY_DELETE = 31;
+const int _DIRECTORY_EXISTS = 32;
+const int _DIRECTORY_CREATE_TEMP = 33;
+const int _DIRECTORY_LIST_START = 34;
+const int _DIRECTORY_LIST_NEXT = 35;
+const int _DIRECTORY_LIST_STOP = 36;
+const int _DIRECTORY_RENAME = 37;
+const int _SSL_PROCESS_FILTER = 38;
 
 class _IOService {
   external static Future dispatch(int request, List data);
diff --git a/sdk/lib/io/process.dart b/sdk/lib/io/process.dart
index 3c0f0fe..3b340c3 100644
--- a/sdk/lib/io/process.dart
+++ b/sdk/lib/io/process.dart
@@ -11,6 +11,7 @@
   external static void _setExitCode(int status);
   external static void _sleep(int millis);
   external static int _pid(Process process);
+  external static Stream<ProcessSignal> _watchSignal(ProcessSignal signal);
 }
 
 /**
@@ -310,37 +311,60 @@
  * to a child process, see [:Process.kill:].
  */
 class ProcessSignal {
-  static const ProcessSignal SIGHUP = const ProcessSignal._signal(1);
-  static const ProcessSignal SIGINT = const ProcessSignal._signal(2);
-  static const ProcessSignal SIGQUIT = const ProcessSignal._signal(3);
-  static const ProcessSignal SIGILL = const ProcessSignal._signal(4);
-  static const ProcessSignal SIGTRAP = const ProcessSignal._signal(5);
-  static const ProcessSignal SIGABRT = const ProcessSignal._signal(6);
-  static const ProcessSignal SIGBUS = const ProcessSignal._signal(7);
-  static const ProcessSignal SIGFPE = const ProcessSignal._signal(8);
-  static const ProcessSignal SIGKILL = const ProcessSignal._signal(9);
-  static const ProcessSignal SIGUSR1 = const ProcessSignal._signal(10);
-  static const ProcessSignal SIGSEGV = const ProcessSignal._signal(11);
-  static const ProcessSignal SIGUSR2 = const ProcessSignal._signal(12);
-  static const ProcessSignal SIGPIPE = const ProcessSignal._signal(13);
-  static const ProcessSignal SIGALRM = const ProcessSignal._signal(14);
-  static const ProcessSignal SIGTERM = const ProcessSignal._signal(15);
-  static const ProcessSignal SIGCHLD = const ProcessSignal._signal(17);
-  static const ProcessSignal SIGCONT = const ProcessSignal._signal(18);
-  static const ProcessSignal SIGSTOP = const ProcessSignal._signal(19);
-  static const ProcessSignal SIGTSTP = const ProcessSignal._signal(20);
-  static const ProcessSignal SIGTTIN = const ProcessSignal._signal(21);
-  static const ProcessSignal SIGTTOU = const ProcessSignal._signal(22);
-  static const ProcessSignal SIGURG = const ProcessSignal._signal(23);
-  static const ProcessSignal SIGXCPU = const ProcessSignal._signal(24);
-  static const ProcessSignal SIGXFSZ = const ProcessSignal._signal(25);
-  static const ProcessSignal SIGVTALRM = const ProcessSignal._signal(26);
-  static const ProcessSignal SIGPROF = const ProcessSignal._signal(27);
-  static const ProcessSignal SIGPOLL = const ProcessSignal._signal(29);
-  static const ProcessSignal SIGSYS = const ProcessSignal._signal(31);
+  static const ProcessSignal SIGHUP = const ProcessSignal._(1, "SIGHUP");
+  static const ProcessSignal SIGINT = const ProcessSignal._(2, "SIGINT");
+  static const ProcessSignal SIGQUIT = const ProcessSignal._(3, "SIGQUIT");
+  static const ProcessSignal SIGILL = const ProcessSignal._(4, "SIGILL");
+  static const ProcessSignal SIGTRAP = const ProcessSignal._(5, "SIGTRAP");
+  static const ProcessSignal SIGABRT = const ProcessSignal._(6, "SIGABRT");
+  static const ProcessSignal SIGBUS = const ProcessSignal._(7, "SIGBUS");
+  static const ProcessSignal SIGFPE = const ProcessSignal._(8, "SIGFPE");
+  static const ProcessSignal SIGKILL = const ProcessSignal._(9, "SIGKILL");
+  static const ProcessSignal SIGUSR1 = const ProcessSignal._(10, "SIGUSR1");
+  static const ProcessSignal SIGSEGV = const ProcessSignal._(11, "SIGSEGV");
+  static const ProcessSignal SIGUSR2 = const ProcessSignal._(12, "SIGUSR2");
+  static const ProcessSignal SIGPIPE = const ProcessSignal._(13, "SIGPIPE");
+  static const ProcessSignal SIGALRM = const ProcessSignal._(14, "SIGALRM");
+  static const ProcessSignal SIGTERM = const ProcessSignal._(15, "SIGTERM");
+  static const ProcessSignal SIGCHLD = const ProcessSignal._(17, "SIGCHLD");
+  static const ProcessSignal SIGCONT = const ProcessSignal._(18, "SIGCONT");
+  static const ProcessSignal SIGSTOP = const ProcessSignal._(19, "SIGSTOP");
+  static const ProcessSignal SIGTSTP = const ProcessSignal._(20, "SIGTSTP");
+  static const ProcessSignal SIGTTIN = const ProcessSignal._(21, "SIGTTIN");
+  static const ProcessSignal SIGTTOU = const ProcessSignal._(22, "SIGTTOU");
+  static const ProcessSignal SIGURG = const ProcessSignal._(23, "SIGURG");
+  static const ProcessSignal SIGXCPU = const ProcessSignal._(24, "SIGXCPU");
+  static const ProcessSignal SIGXFSZ = const ProcessSignal._(25, "SIGXFSZ");
+  static const ProcessSignal SIGVTALRM = const ProcessSignal._(26, "SIGVTALRM");
+  static const ProcessSignal SIGPROF = const ProcessSignal._(27, "SIGPROF");
+  static const ProcessSignal SIGWINCH = const ProcessSignal._(28, "SIGWINCH");
+  static const ProcessSignal SIGPOLL = const ProcessSignal._(29, "SIGPOLL");
+  static const ProcessSignal SIGSYS = const ProcessSignal._(31, "SIGSYS");
 
-  const ProcessSignal._signal(int this._signalNumber);
   final int _signalNumber;
+  final String _name;
+
+  const ProcessSignal._(this._signalNumber, this._name);
+
+  String toString() => _name;
+
+  Stream<ProcessSignal> watch() => _ProcessUtils._watchSignal(this);
+}
+
+
+class SignalException implements IOException {
+  final String message;
+  final osError;
+
+  const SignalException(String this.message, [this.osError = null]);
+
+  String toString() {
+    var msg = "";
+    if (osError != null) {
+      msg = ", osError: $osError";
+    }
+    return "SignalException: $message$msg";
+  }
 }
 
 
diff --git a/sdk/lib/io/secure_socket.dart b/sdk/lib/io/secure_socket.dart
index 7d8c685..9bfa032 100644
--- a/sdk/lib/io/secure_socket.dart
+++ b/sdk/lib/io/secure_socket.dart
@@ -540,7 +540,7 @@
         _socketSubscription.onDone(_doneHandler);
       }
       _secureFilter.connect(address.host,
-                            (address as dynamic)._sockaddr_storage,
+                            (address as dynamic)._in_addr,
                             port,
                             is_server,
                             certificateName,
diff --git a/sdk/lib/io/stdio.dart b/sdk/lib/io/stdio.dart
index ab2f03a..5626d84 100644
--- a/sdk/lib/io/stdio.dart
+++ b/sdk/lib/io/stdio.dart
@@ -159,6 +159,50 @@
 }
 
 
+/**
+ * [Stdout] exposes methods to query the terminal for properties.
+ *
+ * Use [hasTerminal] to test if there is a terminal associated to stdout.
+ */
+class Stdout extends _StdSink {
+  // TODO(15721): Should implement IOSink (for documentation purpose).
+  Stdout._(IOSink sink) : super(sink);
+
+  /**
+   * Returns true if there is a terminal attached to stdout.
+   */
+  external bool get hasTerminal;
+
+  /**
+   * Get the number of columns of the terminal.
+   *
+   * If no terminal is attached to stdout, a [StdoutException] is thrown. See
+   * [hasTerminal] for more info.
+   */
+  external int get terminalColumns;
+
+  /**
+   * Get the number of lines of the terminal.
+   *
+   * If no terminal is attached to stdout, a [StdoutException] is thrown. See
+   * [hasTerminal] for more info.
+   */
+  external int get terminalLines;
+}
+
+
+class StdoutException implements IOException {
+  final String message;
+  final OSError osError;
+
+  const StdoutException(this.message, [this.osError]);
+
+  String toString() {
+    return "StdoutException: $message${osError == null ? "" : ", $osError"}";
+  }
+}
+
+
 class _StdSink implements IOSink {
   final IOSink _sink;
 
@@ -194,7 +238,7 @@
 
 
 Stdin _stdin;
-IOSink _stdout;
+Stdout _stdout;
 IOSink _stderr;
 
 
@@ -208,7 +252,7 @@
 
 
 /// The standard output stream of data written by this program.
-IOSink get stdout {
+Stdout get stdout {
   if (_stdout == null) {
     _stdout = _StdIOUtils._getStdioOutputStream(1);
   }
@@ -257,7 +301,7 @@
 
 
 class _StdIOUtils {
-  external static IOSink _getStdioOutputStream(int fd);
+  external static _getStdioOutputStream(int fd);
   external static Stdin _getStdioInputStream();
   external static int _socketType(nativeSocket);
 }
diff --git a/sdk/lib/io/timer_impl.dart b/sdk/lib/io/timer_impl.dart
index 883d09e..5396a6a 100644
--- a/sdk/lib/io/timer_impl.dart
+++ b/sdk/lib/io/timer_impl.dart
@@ -4,19 +4,137 @@
 
 part of dart.io;
 
-class _Timer extends LinkedListEntry<_Timer> implements Timer {
+// Timer heap implemented as a array-based binary heap[0].
+// This allows for O(1) `first`, O(log(n)) `remove`/`removeFirst` and O(log(n))
+// `add`.
+//
+// To ensure the timers are ordered by insertion time, the _Timer class has a
+// `_id` field set when added to the heap.
+//
+// [0] http://en.wikipedia.org/wiki/Binary_heap
+class _TimerHeap {
+  List<_Timer> _list;
+  int _used = 0;
+
+  _TimerHeap([int initSize = 7])
+      : _list = new List<_Timer>(initSize);
+
+  bool get isEmpty => _used == 0;
+  bool get isNotEmpty => _used > 0;
+
+  _Timer get first => _list[0];
+
+  bool isFirst(_Timer timer) => timer._indexOrNext == 0;
+
+  void add(_Timer timer) {
+    if (_used == _list.length) {
+      _resize();
+    }
+    timer._indexOrNext = _used++;
+    _list[timer._indexOrNext] = timer;
+    _bubbleUp(timer);
+  }
+
+  _Timer removeFirst() {
+    var f = first;
+    remove(f);
+    return f;
+  }
+
+  void remove(_Timer timer) {
+    _used--;
+    timer._id = -1;
+    if (isEmpty) {
+      _list[0] = null;
+      timer._indexOrNext = null;
+      return;
+    }
+    var last = _list[_used];
+    if (!identical(last, timer)) {
+      last._indexOrNext = timer._indexOrNext;
+      _list[last._indexOrNext] = last;
+      if (last._compareTo(timer) < 0) {
+        _bubbleUp(last);
+      } else {
+        _bubbleDown(last);
+      }
+    }
+    _list[_used] = null;
+    timer._indexOrNext = null;
+  }
+
+  void _resize() {
+    var newList = new List(_list.length * 2 + 1);
+    newList.setRange(0, _used, _list);
+    _list = newList;
+  }
+
+  void _bubbleUp(_Timer timer) {
+    while (!isFirst(timer)) {
+      Timer parent = _parent(timer);
+      if (timer._compareTo(parent) < 0) {
+        _swap(timer, parent);
+      } else {
+        break;
+      }
+    }
+  }
+
+  void _bubbleDown(_Timer timer) {
+    while (true) {
+      int leftIndex = _leftChildIndex(timer._indexOrNext);
+      int rightIndex = _rightChildIndex(timer._indexOrNext);
+      _Timer newest = timer;
+      if (leftIndex < _used && _list[leftIndex]._compareTo(newest) < 0) {
+        newest = _list[leftIndex];
+      }
+      if (rightIndex < _used && _list[rightIndex]._compareTo(newest) < 0) {
+        newest = _list[rightIndex];
+      }
+      if (identical(newest, timer)) {
+        // We are where we should be, break.
+        break;
+      }
+      _swap(newest, timer);
+    }
+  }
+
+  void _swap(_Timer first, _Timer second) {
+    int tmp = first._indexOrNext;
+    first._indexOrNext = second._indexOrNext;
+    second._indexOrNext = tmp;
+    _list[first._indexOrNext] = first;
+    _list[second._indexOrNext] = second;
+  }
+
+  Timer _parent(_Timer timer) => _list[_parentIndex(timer._indexOrNext)];
+  Timer _leftChild(_Timer timer) => _list[_leftChildIndex(timer._indexOrNext)];
+  Timer _rightChild(_Timer timer) =>
+      _list[_rightChildIndex(timer._indexOrNext)];
+
+  static int _parentIndex(int index) => (index - 1) ~/ 2;
+  static int _leftChildIndex(int index) => 2 * index + 1;
+  static int _rightChildIndex(int index) => 2 * index + 2;
+}
+
+class _Timer implements Timer {
   // Disables the timer.
   static const int _NO_TIMER = -1;
 
   // Timers are ordered by wakeup time.
-  static LinkedList<_Timer> _timers = new LinkedList<_Timer>();
+  static _TimerHeap _heap = new _TimerHeap();
+  static _Timer _firstZeroTimer;
+  static _Timer _lastZeroTimer;
+  static int _idCount = 0;
 
   static RawReceivePort _receivePort;
-  static bool _handling_callbacks = false;
+  static bool _handlingCallbacks = false;
 
   Function _callback;
   int _milliSeconds;
   int _wakeupTime = 0;
+  var _indexOrNext;
+  int _id = -1;
 
   static Timer _createTimer(void callback(Timer timer),
                             int milliSeconds,
@@ -32,10 +150,9 @@
           new DateTime.now().millisecondsSinceEpoch + 1 + milliSeconds;
     }
     timer._milliSeconds = repeating ? milliSeconds : -1;
-    timer._addTimerToList();
-    if (identical(timer, _timers.first)) {
+    if (timer._addTimerToHeap()) {
       // The new timer is the first in queue. Update event handler.
-      timer._notifyEventHandler();
+      _notifyEventHandler();
     }
     return timer;
   }
@@ -50,10 +167,16 @@
 
   _Timer._internal() {}
 
+  bool get _isInHeap => _id >= 0;
+
   void _clear() {
     _callback = null;
-    _milliSeconds = 0;
-    _wakeupTime = 0;
+  }
+
+  int _compareTo(_Timer other) {
+    int c = _wakeupTime - other._wakeupTime;
+    if (c != 0) return c;
+    return _id - other._id;
   }
 
   bool get _repeating => _milliSeconds >= 0;
@@ -64,12 +187,11 @@
   // the given timer is the earliest timer the native timer is reset.
   void cancel() {
     _clear();
-    // Return if already canceled.
-    if (list == null) return;
-    assert(!_timers.isEmpty);
-    _Timer first = _timers.first;
-    unlink();
-    if (identical(first, this)) {
+    if (!_isInHeap) return;
+    assert(_wakeupTime != 0);
+    bool update = _firstZeroTimer == null && _heap.isFirst(this);
+    _heap.remove(this);
+    if (update) {
       _notifyEventHandler();
     }
   }
@@ -81,34 +203,32 @@
 
   // Adds a timer to the timer list. Timers with the same wakeup time are
   // enqueued in order and notified in FIFO order.
-  void _addTimerToList() {
-    _Timer entry = _timers.isEmpty ? null : _timers.first;
-    // If timer is last, add to end.
-    if (entry == null || _timers.last._wakeupTime <= _wakeupTime) {
-      _timers.add(this);
-      return;
-    }
-    // Otherwise scan through and find the right position.
-    while (entry != null) {
-      if (_wakeupTime < entry._wakeupTime) {
-        entry.insertBefore(this);
-        return;
+  bool _addTimerToHeap() {
+    if (_wakeupTime == 0) {
+      if (_firstZeroTimer == null) {
+        _lastZeroTimer = _firstZeroTimer = this;
+        return true;
+      } else {
+        _lastZeroTimer = _lastZeroTimer._indexOrNext = this;
+        return false;
       }
-      entry = entry.next;
+    } else {
+      _id = _idCount++;
+      _heap.add(this);
+      return _firstZeroTimer == null && _heap.isFirst(this);
     }
-    _timers.add(this);
   }
 
 
-  void _notifyEventHandler() {
-    if (_handling_callbacks) {
+  static void _notifyEventHandler() {
+    if (_handlingCallbacks) {
       // While we are already handling callbacks we will not notify the event
       // handler. _handleTimeout will call _notifyEventHandler once all pending
       // timers are processed.
       return;
     }
 
-    if (_timers.isEmpty) {
+    if (_firstZeroTimer == null && _heap.isEmpty) {
       // No pending timers: Close the receive port and let the event handler
       // know.
       if (_receivePort != null) {
@@ -123,65 +243,67 @@
       }
       _EventHandler._sendData(null,
                               _receivePort,
-                              _timers.first._wakeupTime);
+                              _firstZeroTimer != null ?
+                                  0 : _heap.first._wakeupTime);
     }
   }
 
+  static void _handleTimeout(_) {
+    int currentTime = new DateTime.now().millisecondsSinceEpoch;
+    // Collect all pending timers.
+    var timer = _firstZeroTimer;
+    var nextTimer = _lastZeroTimer;
+    _firstZeroTimer = _lastZeroTimer = null;
+    while (_heap.isNotEmpty && _heap.first._wakeupTime <= currentTime) {
+      var next = _heap.removeFirst();
+      if (timer == null) {
+        nextTimer = timer = next;
+      } else {
+        nextTimer = nextTimer._indexOrNext = next;
+      }
+    }
+
+    // Trigger all of the pending timers. New timers added as part of the
+    // callbacks will be enqueued now and notified in the next spin at the
+    // earliest.
+    _handlingCallbacks = true;
+    try {
+      while (timer != null) {
+        var next = timer._indexOrNext;
+        timer._indexOrNext = null;
+        // One of the timers in the pending_timers list can cancel
+        // one of the later timers which will set the callback to
+        // null.
+        if (timer._callback != null) {
+          var callback = timer._callback;
+          if (!timer._repeating) {
+            // Mark timer as inactive.
+            timer._callback = null;
+          }
+          callback(timer);
+          // Re-insert repeating timer if not canceled.
+          if (timer._repeating && timer._callback != null) {
+            timer._advanceWakeupTime();
+            timer._addTimerToHeap();
+          }
+        }
+        timer = next;
+      }
+    } finally {
+      _handlingCallbacks = false;
+      _notifyEventHandler();
+    }
+  }
 
   // Creates a receive port and registers the timer handler on that
   // receive port.
-  void _createTimerHandler() {
-
-    void _handleTimeout() {
-      int currentTime = new DateTime.now().millisecondsSinceEpoch;
-
-      // Collect all pending timers.
-      var pending_timers = new List();
-      while (!_timers.isEmpty) {
-        _Timer entry = _timers.first;
-        if (entry._wakeupTime <= currentTime) {
-          entry.unlink();
-          pending_timers.add(entry);
-        } else {
-          break;
-        }
-      }
-
-      // Trigger all of the pending timers. New timers added as part of the
-      // callbacks will be enqueued now and notified in the next spin at the
-      // earliest.
-      _handling_callbacks = true;
-      try {
-        for (var timer in pending_timers) {
-          // One of the timers in the pending_timers list can cancel
-          // one of the later timers which will set the callback to
-          // null.
-          if (timer._callback != null) {
-            var callback = timer._callback;
-            if (!timer._repeating) {
-              //Mark timer as inactive.
-              timer._callback = null;
-            }
-            callback(timer);
-            // Re-insert repeating timer if not canceled.
-            if (timer._repeating && timer._callback != null) {
-              timer._advanceWakeupTime();
-              timer._addTimerToList();
-            }
-          }
-        }
-      } finally {
-        _handling_callbacks = false;
-        _notifyEventHandler();
-      }
-    }
-
+  static void _createTimerHandler() {
     if(_receivePort == null) {
-      _receivePort = new RawReceivePort((_) { _handleTimeout(); });
+      _receivePort = new RawReceivePort(_handleTimeout);
     }
   }
 
-  void _shutdownTimerHandler() {
+  static void _shutdownTimerHandler() {
     _receivePort.close();
     _receivePort = null;
   }
diff --git a/tests/co19/co19-analyzer.status b/tests/co19/co19-analyzer.status
index 28c3b88..7c23629 100644
--- a/tests/co19/co19-analyzer.status
+++ b/tests/co19/co19-analyzer.status
@@ -129,7 +129,6 @@
 
 Language/07_Classes/10_Superinterfaces_A07_t05: StaticWarning # co19-roll r667: Please triage this failure
 LibTest/convert/JsonEncoder/JsonEncoder_A01_t01: StaticWarning # co19-roll r667: Please triage this failure
-LibTest/async/Zone/operator_subscript_A01_t01: StaticWarning # co19-roll r672: Please triage this failure
 
 # co19 issue 656
 LibTest/typed_data/Float32x4/equal_A01_t01: Skip # co19 issue 656
diff --git a/tests/co19/co19-co19.status b/tests/co19/co19-co19.status
index bd7e326..c126519 100644
--- a/tests/co19/co19-co19.status
+++ b/tests/co19/co19-co19.status
@@ -40,8 +40,6 @@
 LibTest/collection/ListBase/ListBase_class_A01_t01: Skip, OK # co19 issue 661
 LibTest/collection/ListMixin/ListMixin_class_A01_t01: Skip, OK # co19 issue 661
 
-LibTest/isolate/Isolate/spawnUri_A02_t04: Fail # co19-roll r672: Please triage this failure
-
 [ $runtime == vm || $runtime == dartium || $compiler == dart2js ]
 LibTest/math/acos_A01_t01: PASS, FAIL, OK # co19 issue 44
 LibTest/math/asin_A01_t01: PASS, FAIL, OK # co19 issue 44
diff --git a/tests/co19/co19-dart2dart.status b/tests/co19/co19-dart2dart.status
index c3e7ab4..f42fb63 100644
--- a/tests/co19/co19-dart2dart.status
+++ b/tests/co19/co19-dart2dart.status
@@ -160,6 +160,9 @@
 LibTest/core/Function/Function_class_A01_t01: RuntimeError # co19-roll r623: Please triage this failure
 Language/13_Statements/04_Local_Function_Declaration_A04_t03: MissingCompileTimeError # co19-roll r667: Please triage this failure
 
+LibTest/isolate/Isolate/spawn_A02_t02: RuntimeError # Dart issue 15617
+LibTest/isolate/Isolate/spawnUri_A02_t01: RuntimeError # Dart issue 15617
+
 [ $compiler == dart2dart && $minified ]
 Language/12_Expressions/14_Function_Invocation/4_Function_Expression_Invocation_A01_t02: fail # co19-roll r559: Please triage this failure
 Language/12_Expressions/17_Getter_Invocation_A02_t01: fail # co19-roll r559: Please triage this failure
diff --git a/tests/co19/co19-dart2js.status b/tests/co19/co19-dart2js.status
index ec96ae9..92d3ba4 100644
--- a/tests/co19/co19-dart2js.status
+++ b/tests/co19/co19-dart2js.status
@@ -62,6 +62,9 @@
 LibTest/typed_data/Float32x4/lessThan_A01_t01: Skip # co19 issue 656
 LibTest/typed_data/Float32x4/lessThanOrEqual_A01_t01: Skip # co19 issue 656
 
+LibTest/isolate/Isolate/spawnUri_A02_t01: RuntimeError # Dart issue 15617
+LibTest/isolate/Isolate/spawn_A02_t02: RuntimeError # Dart issue 15617
+
 [ $compiler == dart2js && $runtime != ie9 ]
 LibTest/typed_data/ByteData/ByteData_A02_t01: fail # co19-roll r576: Please triage this failure
 
@@ -648,8 +651,6 @@
 LibTest/isolate/Isolate/spawnUri_A01_t03: Fail # co19-roll r672: Please triage this failure
 LibTest/isolate/Isolate/spawnUri_A01_t04: Fail # co19-roll r672: Please triage this failure
 LibTest/isolate/Isolate/spawnUri_A01_t05: Fail # co19-roll r672: Please triage this failure
-LibTest/isolate/Isolate/spawnUri_A02_t02: Fail # co19-roll r672: Please triage this failure
-LibTest/isolate/Isolate/spawnUri_A02_t03: Fail # co19-roll r672: Please triage this failure
 
 [ $compiler == dart2js ]
 LibTest/core/List/List_class_A01_t01: RuntimeError # co19-roll r623: Please triage this failure
diff --git a/tests/co19/co19-runtime.status b/tests/co19/co19-runtime.status
index 16f1123..9f1ca00 100644
--- a/tests/co19/co19-runtime.status
+++ b/tests/co19/co19-runtime.status
@@ -33,8 +33,10 @@
 LibTest/isolate/IsolateStream/contains_A02_t01: fail # co19-roll r546: Please triage this failure
 LibTest/isolate/ReceivePort/receive_A01_t02: Fail # VM triage, check spec.
 
+LibTest/isolate/Isolate/spawnUri_A02_t01: RuntimeError # Dart issue 15617
 LibTest/isolate/Isolate/spawnUri_A02_t02: Timeout # co19-roll r672: Please triage this failure
 LibTest/isolate/Isolate/spawnUri_A02_t03: Timeout # co19-roll r672: Please triage this failure
+LibTest/isolate/Isolate/spawn_A02_t02: RuntimeError # Dart issue 15617
 
 LibTest/core/Invocation/positionalArguments_A01_t01: RuntimeError # co19-roll r607: Please triage this failure
 LibTest/core/RegExp/Pattern_semantics/splitQueryString_A02_t01: RuntimeError # co19-roll r607: Please triage this failure
@@ -77,6 +79,9 @@
 [ $compiler == none && $runtime == vm && ($arch == simarm || $arch == simmips) ]
 LibTest/core/Uri/Uri_A06_t03: Pass, Timeout # co19-roll r576: Please triage this failure
 
+[ $compiler == none && $runtime == vm && $arch == simarm ]
+LibTest/typed_data/Float32x4/sqrt_A01_t01: Pass, Fail # co19 issue 666.
+
 [ $compiler == none && $checked && ($runtime == vm || $runtime == dartium) ]
 Language/15_Types/1_Static_Types_A03_t01: RuntimeError # co19-roll r667: Please triage this failure
 
diff --git a/tests/compiler/dart2js/literal_map_test.dart b/tests/compiler/dart2js/literal_map_test.dart
index 0e30d4e..1b51336 100644
--- a/tests/compiler/dart2js/literal_map_test.dart
+++ b/tests/compiler/dart2js/literal_map_test.dart
@@ -19,5 +19,7 @@
   Expect.isFalse(generated.contains('bailout'));
   Expect.isFalse(generated.contains('interceptor'));
   // Make sure we don't go through an interceptor.
-  Expect.isTrue(generated.contains('a.\$indexSet'));
+  Expect.isTrue(
+      generated.contains(r'a.$indexSet(a') ||
+      generated.contains(r'.$indexSet(0'));
 }
diff --git a/tests/compiler/dart2js/mirrors_used_test.dart b/tests/compiler/dart2js/mirrors_used_test.dart
index 50ca509..9415463 100644
--- a/tests/compiler/dart2js/mirrors_used_test.dart
+++ b/tests/compiler/dart2js/mirrors_used_test.dart
@@ -58,7 +58,7 @@
     // 2. Some code was refactored, and there are more methods.
     // Either situation could be problematic, but in situation 2, it is often
     // acceptable to increase [expectedMethodCount] a little.
-    int expectedMethodCount = 351;
+    int expectedMethodCount = 352;
     Expect.isTrue(
         generatedCode.length <= expectedMethodCount,
         'Too many compiled methods: '
diff --git a/tests/compiler/dart2js/mock_compiler.dart b/tests/compiler/dart2js/mock_compiler.dart
index 1214f30..5a9cb74 100644
--- a/tests/compiler/dart2js/mock_compiler.dart
+++ b/tests/compiler/dart2js/mock_compiler.dart
@@ -151,7 +151,12 @@
     operator ==(other) => true;
     get hashCode => throw "JSNumber.hashCode not implemented.";
 
-    _tdivFast(other) => 42;
+    // We force side effects on _tdivFast to mimic the shortcomings of
+    // the effect analysis: because the `_tdivFast` implementation of
+    // the core library has calls that may not already be analyzed,
+    // the analysis will conclude that `_tdivFast` may have side
+    // effects.
+    _tdivFast(other) => new List()..length = 42;
     _shlPositive(other) => 42;
     _shrBothPositive(other) => 42;
     _shrReceiverPositive(other) => 42;
@@ -207,6 +212,7 @@
   class Type {}
   class Function {}
   class List<E> {
+    var length;
     List([length]);
     List.filled(length, element);
   }
diff --git a/tests/compiler/dart2js/side_effect_tdiv_regression_test.dart b/tests/compiler/dart2js/side_effect_tdiv_regression_test.dart
new file mode 100644
index 0000000..1cede18
--- /dev/null
+++ b/tests/compiler/dart2js/side_effect_tdiv_regression_test.dart
@@ -0,0 +1,30 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:expect/expect.dart';
+import "package:async_helper/async_helper.dart";
+
+import 'compiler_helper.dart';
+import 'parser_helper.dart';
+
+const String TEST = r'''
+class A {
+  var field = 42;
+}
+main() {
+  var a = new A();
+  var b = [42, -1];
+  // Force a setter on [field].
+  if (false) a.field = 12;
+  var c = a.field;
+  print(b[0] ~/ b[1]);
+  return c + a.field;
+}
+''';
+
+void main() {
+  asyncTest(() => compileAll(TEST).then((generated) {
+    Expect.isTrue(generated.contains('return c + c;'));
+  }));  
+}
diff --git a/tests/compiler/dart2js/simple_inferrer_test.dart b/tests/compiler/dart2js/simple_inferrer_test.dart
index 81007d0..b2dd57f 100644
--- a/tests/compiler/dart2js/simple_inferrer_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_test.dart
@@ -538,6 +538,10 @@
   return a;
 }
 
+testReturnNotEquals() {
+  return new A() != 54;
+}
+
 testReturnInvokeDynamicGetter() => new A().myFactory();
 
 var topLevelConstList = const [42];
@@ -695,6 +699,7 @@
   testReturnNull4();
   testReturnNull5();
   testReturnNull6();
+  testReturnNotEquals();
 }
 """;
 
@@ -837,5 +842,6 @@
     checkReturn('testReturnNull4', typesTask.nullType);
     checkReturn('testReturnNull5', typesTask.nullType);
     checkReturn('testReturnNull6', typesTask.dynamicType);
+    checkReturn('testReturnNotEquals', typesTask.boolType);
   }));
 }
diff --git a/tests/compiler/dart2js_extra/dart2js_extra.status b/tests/compiler/dart2js_extra/dart2js_extra.status
index c694332..f9eed72 100644
--- a/tests/compiler/dart2js_extra/dart2js_extra.status
+++ b/tests/compiler/dart2js_extra/dart2js_extra.status
@@ -14,6 +14,12 @@
 variable_type_test/03: Fail, OK
 variable_type_test/01: Fail, OK
 
+[ $compiler == dart2js && $host_checked && $checked == false ]
+# Test that @IrRepresentation yields compile-time errors in host-checked mode.
+# The condition "$checked == false" is to be removed once we build IR in
+# target-checked mode.
+ir_representation_test: CompileTimeError, OK
+
 [ $compiler == dart2js && $mode == debug ]
 operator_test: Skip
 string_interpolation_test: Skip
diff --git a/tests/compiler/dart2js_extra/ir_representation_test.dart b/tests/compiler/dart2js_extra/ir_representation_test.dart
new file mode 100644
index 0000000..4b037c4
--- /dev/null
+++ b/tests/compiler/dart2js_extra/ir_representation_test.dart
@@ -0,0 +1,62 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// The multitest framework does not support import paths that contain '..',
+// therefore it's not used in this file.
+import '../dart2js_native/compiler_test_internals.dart';
+
+/**
+ * This test verifies that the @IrRepresentation annotation works as expected.
+ * It might fail when extending the IR to express more of Dart.
+ */
+
+// closure
+@IrRepresentation(true)
+test1() {
+  var f = () => 42;
+  return 1;
+}
+
+// parameter
+@IrRepresentation(true)
+test2(x) {
+  return x;
+}
+
+// dynamic invocation, construction
+@IrRepresentation(true)
+test3() {
+  new Object().hashCode;
+}
+
+// exceptions
+@IrRepresentation(true)
+test4() {
+  try {
+    throw "possum";
+  } catch (e) {
+    return e;
+  }
+}
+
+// control flow, loops
+@IrRepresentation(true)
+test5(x) {
+  while (x < 100) {
+    x += x;
+  }
+  if (x % 2 == 0) {
+    return 1;
+  } else {
+    return 2;
+  }
+}
+
+main() {
+  print(test1());
+  print(test2(1));
+  print(test3());
+  print(test4());
+  print(test5(2));
+}
diff --git a/tests/compiler/dart2js_extra/ssa_inlining_test.dart b/tests/compiler/dart2js_extra/ssa_inlining_test.dart
new file mode 100644
index 0000000..b043c77
--- /dev/null
+++ b/tests/compiler/dart2js_extra/ssa_inlining_test.dart
@@ -0,0 +1,118 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import '../dart2js_native/compiler_test_internals.dart';
+import 'package:expect/expect.dart';
+
+// The function ast01 is built by an SsaFromAstBuilder.
+// Ir functions are inlined by an SsaFromIrInliner.
+
+@NoInline()
+@IrRepresentation(false)
+ast01() {
+  checkAst01(JS('', 'arguments.callee'));
+  print(ir01());
+  print(ir02());
+  return ast02(11);
+}
+
+@IrRepresentation(true)
+ir01() => ir04();
+
+@IrRepresentation(true)
+ir02() => ast06(10, 20);
+
+@IrRepresentation(false)
+ast06(a,b) {
+  JS('', 'String("in ast06")');
+  return 3*a + b;
+}
+
+@IrRepresentation(true)
+ir04() => ir05();
+
+@IrRepresentation(true)
+ir05() => ast07(1, 22);
+
+@IrRepresentation(false)
+ast07(i, j) {
+  var x = 0;
+  return ast08(i,j) ? i : j;
+}
+
+@IrRepresentation(false)
+ast08(x,y) {
+  JS('', 'String("in ast08")');
+  return x - y < 0;
+}
+
+@IrRepresentation(false)
+ast02(x) {
+  print(x);
+  ir06();
+  print(ir07());
+}
+
+@IrRepresentation(true)
+ir06() => ast04(1,2,3);
+
+@IrRepresentation(false)
+ast04(a, b, c) {
+  print(a + b - c);
+  JS('', 'String("in ast04")');
+}
+
+@IrRepresentation(true)
+ir07() => ir03();
+
+@IrRepresentation(true)
+ir03() => ast05(1,3);
+
+@IrRepresentation(false)
+ast05(a, b) {
+  JS('', 'String("in ast05")');
+  return (a+b)/2;
+}
+
+// The function ir08 is built by an SsaFromIrBuilder.
+// Ast functions are inlined by an SsaFromAstInliner.
+
+@NoInline()
+@IrRepresentation(true)
+ir08() => ir09();
+
+ir09() => ast09();
+
+ast09() {
+  checkIr08(JS('', 'arguments.callee'));
+  JS('', 'String("in ast09")');
+  print(ir01());
+  print(ir02());
+  print(ast02(11));
+}
+
+main() {
+  ast01();
+  ir08();
+}
+
+@NoInline()
+check(func, names) {
+  var source = JS('String', 'String(#)', func);
+  print(source);
+  for (var f in names) {
+    Expect.isTrue(source.contains('"in $f"'), "should inline '$f'");
+  }
+}
+
+@NoInline
+checkAst01(func) {
+  var names = ["ast04", "ast05", "ast06", "ast08"];
+  check(func, names);
+}
+
+checkIr08(func) {
+  var names = ["ast09", "ast04", "ast05", "ast06", "ast08"];
+  check(func, names);
+}
diff --git a/tests/compiler/dart2js_native/bound_closure_test.dart b/tests/compiler/dart2js_native/bound_closure_test.dart
new file mode 100644
index 0000000..59dc306
--- /dev/null
+++ b/tests/compiler/dart2js_native/bound_closure_test.dart
@@ -0,0 +1,83 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+// Test calling convention of property extraction closures.
+
+class AA {
+  bar(a, [b = 'A']) => 'AA.bar($a, $b)';   // bar is plain dart convention.
+  foo(a, [b = 'A']) => 'AA.foo($a, $b)';   // foo has interceptor convention.
+}
+
+class BB native "BB" {
+  foo(a, [b = 'B']) native;
+}
+
+class CC extends BB native "CC" {
+  foo(a, [b = 'C']) native;
+
+  get superfoo => super.foo;
+}
+
+makeBB() native;
+makeCC() native;
+inscrutable(a) native;
+
+void setup() native r"""
+function BB() {}
+BB.prototype.foo = function(u, v) {
+  return 'BB.foo(' + u + ', ' + v + ')';
+};
+
+function CC() {}
+CC.prototype.foo = function(u, v) {
+  return 'CC.foo(' + u + ', ' + v + ')';
+};
+
+makeBB = function(){return new BB;};
+makeCC = function(){return new CC;};
+inscrutable = function(a){return a;};
+""";
+
+
+main() {
+  setup();
+  var a = inscrutable(new AA());
+  var b = inscrutable(makeBB());
+  var c = inscrutable(makeCC);
+
+  Expect.equals('AA.bar(1, A)', inscrutable(a).bar(1));
+  Expect.equals('AA.bar(2, 3)', inscrutable(a).bar(2, 3));
+
+  Expect.equals('AA.foo(1, A)', inscrutable(a).foo(1));
+  Expect.equals('AA.foo(2, 3)', inscrutable(a).foo(2, 3));
+
+  Expect.equals('BB.foo(1, B)', inscrutable(b).foo(1));
+  Expect.equals('BB.foo(2, 3)', inscrutable(b).foo(2, 3));
+
+  Expect.equals('CC.foo(1, C)', inscrutable(c).foo(1));
+  Expect.equals('CC.foo(2, 3)', inscrutable(c).foo(2, 3));
+
+  var abar = inscrutable(a).bar;
+  var afoo = inscrutable(a).foo;
+  var bfoo = inscrutable(b).foo;
+  var cfoo = inscrutable(c).foo;
+  var csfoo = inscrutable(c).superfoo;
+
+  Expect.equals('AA.bar(1, A)', abar(1));
+  Expect.equals('AA.bar(2, 3)', abar(2, 3));
+
+  Expect.equals('AA.foo(1, A)', afoo(1));
+  Expect.equals('AA.foo(2, 3)', afoo(2, 3));
+
+  Expect.equals('BB.foo(1, B)', bfoo(1));
+  Expect.equals('BB.foo(2, 3)', bfoo(2, 3));
+
+  Expect.equals('CC.foo(1, C)', cfoo(1));
+  Expect.equals('CC.foo(2, 3)', cfoo(2, 3));
+
+  Expect.equals('BB.foo(1, B)', csfoo(1));
+  Expect.equals('BB.foo(2, 3)', csfoo(2, 3));
+}
diff --git a/tests/compiler/dart2js_native/compiler_test_internals.dart b/tests/compiler/dart2js_native/compiler_test_internals.dart
new file mode 100644
index 0000000..be2c4b6
--- /dev/null
+++ b/tests/compiler/dart2js_native/compiler_test_internals.dart
@@ -0,0 +1,10 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library compiler_test_internals;
+
+export 'dart:_js_helper' show
+    NoSideEffects, NoThrows, NoInline, IrRepresentation;
+
+export 'dart:_foreign_helper' show JS;
diff --git a/tests/compiler/dart2js_native/dart2js_native.status b/tests/compiler/dart2js_native/dart2js_native.status
index 10785bb..499d474 100644
--- a/tests/compiler/dart2js_native/dart2js_native.status
+++ b/tests/compiler/dart2js_native/dart2js_native.status
@@ -6,9 +6,10 @@
 *: Skip
 
 [ $compiler == dart2js ]
+bound_closure_test: Fail
+call_on_native_class_test: CompileTimeError # Issue 14813
 native_no_such_method_exception4_frog_test: Fail  # Issue 9631
 native_no_such_method_exception5_frog_test: Fail  # Issue 9631
-call_on_native_class_test: CompileTimeError # Issue 14813
 
 [ $compiler == dart2js && $unminified ]
 fake_thing_test: Fail # Issue 13010
diff --git a/tests/corelib/corelib.status b/tests/corelib/corelib.status
index e97e429..6fce1d2 100644
--- a/tests/corelib/corelib.status
+++ b/tests/corelib/corelib.status
@@ -54,6 +54,7 @@
 
 [ $compiler == none || $compiler == dart2dart ]
 symbol_test/none: Fail # bug 11669
+symbol_operator_test/03: Fail # bug 11669
 
 [ $compiler == none && $runtime == drt ]
 main_test: Fail  # Dartium needs to check for both main() and main(args).
@@ -88,6 +89,10 @@
 string_base_vm_test: RuntimeError, OK # VM specific test.
 nan_infinity_test/01: Fail # Issue 11551
 
+[ $compiler == dart2js || $compiler == dart2dart]
+symbol_operator_test/01: CompileTimeError # Issue 15653.
+symbol_operator_test/02: CompileTimeError # Issue 15653.
+
 [ $compiler == dart2js && $runtime == none ]
 *: Fail, Pass # TODO(ahe): Triage these tests.
 
diff --git a/tests/corelib/for_in_test.dart b/tests/corelib/for_in_test.dart
index 82ea7b9..616d721 100644
--- a/tests/corelib/for_in_test.dart
+++ b/tests/corelib/for_in_test.dart
@@ -53,10 +53,9 @@
       count += i;
     }
     Expect.equals(7, count);
-    // TODO(ngeoffray): We should really test that [i] is 4 with a set
-    // that preserves order. For now, making sure [i] is in the set
-    // will have to do.
     Expect.equals(true, set.contains(i));
+    // The default implementation of [Set] preserves order.
+    Expect.equals(4, i);
   }
 
   static void testBreak() {
diff --git a/tests/corelib/hash_map_test.dart b/tests/corelib/hash_map_test.dart
index 1bdc7be..52848e1 100644
--- a/tests/corelib/hash_map_test.dart
+++ b/tests/corelib/hash_map_test.dart
@@ -9,8 +9,6 @@
 class HashMapTest {
 
   static testMain() {
-    // TODO(srdjan/ngeoffray): Add more meaningful testing below. For now this
-    // is used to verify that the test script is picking up these tests.
     var m = new Map();
     Expect.equals(0, m.length);
     Expect.equals(true, m.isEmpty);
diff --git a/tests/corelib/num_sign_test.dart b/tests/corelib/num_sign_test.dart
new file mode 100644
index 0000000..d2ee968
--- /dev/null
+++ b/tests/corelib/num_sign_test.dart
@@ -0,0 +1,107 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// Test num.clamp.
+
+import "package:expect/expect.dart";
+
+// Pedestrian implementation of sign, following its specification directly.
+num sign(num value) {
+  if (value is int) {
+    if (value < 0) return -1;
+    if (value > 0) return 1;
+    return 0;
+  }
+  if (value.isNaN) return value;
+  if (value == 0.0) return value;
+  if (value > 0.0) return 1.0;
+  return -1.0;
+}
+
+var numbers = [
+  // Integers
+  0,
+  1,
+  2,
+  0x7f,                     // ~7 bits
+  0x80,
+  0xff,                     // ~8 bits
+  0x100,
+  0xffff,                   // ~16 bits
+  0x10000,
+  0x3fffffff,               // ~30 bits (max positive 32-bit tagged smi)
+  0x40000000,
+  0x40000001,
+  0x7fffffff,               // ~31 bits
+  0x80000000,
+  0x80000001,
+  0xfffffffff,              // ~32 bits
+  0x100000000,
+  0x100000001,
+  0x10000000000000,         // ~53 bits
+  0x10000000000001,
+  0x1fffffffffffff,
+  0x20000000000000,
+  0x20000000000001,         // first integer not representable as double.
+  0x20000000000002,
+  0x7fffffffffffffff,       // ~63 bits
+  0x8000000000000000,
+  0x8000000000000001,
+  0xffffffffffffffff,       // ~64 bits
+  0x10000000000000000,
+  0x10000000000000001,
+  // Integers around the max-double range (2^1024, ~1025 bits).
+  0xfffffffffffff800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,
+  0xfffffffffffffc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,
+  0x10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,
+  // Doubles.
+  0.0,
+  5e-324,                   // min positive
+  2.225073858507201e-308,   // max denormal
+  2.2250738585072014e-308,  // min normal
+  0.49999999999999994,      // ~0.5
+  0.5,
+  0.5000000000000001,
+  0.9999999999999999,       // ~1.0
+  1.0,
+  1.0000000000000002,
+  4294967295.0,             // ~32 bits
+  4294967296.0,
+  4503599627370495.5,       // max fractional
+  4503599627370497.0,
+  9007199254740991.0,
+  9007199254740992.0,       // max exact (+1 is not a double)
+  1.7976931348623157e+308,  // max finite double
+  1.0 / 0.0,                // Infinity
+  0.0 / 0.0,                // NaN
+];
+
+main() {
+  for (num number in numbers) {
+    test(number);
+    test(-number);
+  }
+}
+
+void test(number) {
+  num expectSign = sign(number);
+  num actualSign = number.sign;
+  if (expectSign.isNaN) {
+    Expect.isTrue(actualSign.isNaN, "$number: $actualSign != NaN");
+  } else {
+    if (number is int) {
+      Expect.isTrue(actualSign is int, "$number.sign is int");
+    } else {
+      Expect.isTrue(actualSign is double, "$number.sign is double");
+    }
+    Expect.equals(expectSign, actualSign, "$number");
+    Expect.equals(number.isNegative, actualSign.isNegative, "$number:negative");
+    var renumber = actualSign * number.abs();
+    Expect.equals(number, renumber, "$number (sign*abs)");
+    if (number is int) {
+      Expect.isTrue(renumber is int, "$number (sign*abs) is int");
+    } else {
+      Expect.isTrue(renumber is double, "$number (sign*abs) is double");
+    }
+  }
+}
diff --git a/tests/corelib/string_test.dart b/tests/corelib/string_test.dart
index aeb00c3..2d34c063 100644
--- a/tests/corelib/string_test.dart
+++ b/tests/corelib/string_test.dart
@@ -4,7 +4,6 @@
 
 import "package:expect/expect.dart";
 
-// TODO(ngeoffray): test String methods with null arguments.
 class StringTest {
 
   static testMain() {
diff --git a/tests/corelib/symbol_operator_test.dart b/tests/corelib/symbol_operator_test.dart
new file mode 100644
index 0000000..13cd8bc
--- /dev/null
+++ b/tests/corelib/symbol_operator_test.dart
@@ -0,0 +1,81 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test of Symbol class for operators..
+
+var $ = new Symbolize();
+
+main() {
+  testSymbol(#+, $+$, "+");
+  testSymbol(#-, $-$, "-");
+  testSymbol(#*, $*$, "*");
+  testSymbol(#/, $/$, "/");
+  testSymbol(#~/, $~/$, "~/");
+  testSymbol(#%, $%$, "%");
+  testSymbol(#<<, $<<$, "<<");
+  testSymbol(#>>, $>>$, ">>");
+  testSymbol(#~, ~$, "~");
+  testSymbol(#|, $|$, "|");
+  testSymbol(#&, $&$, "&");
+  testSymbol(#^, $^$, "^");
+  testSymbol(#<, $<$, "<");
+  testSymbol(#<=, $<=$, "<=");
+  testSymbol(#>, $>$, ">");
+  testSymbol(#>=, $>=$, ">=");
+  testSymbol(#==, new Symbol("=="), "==");  // Can't hit noSuchMethod.
+  testSymbol(#[], $[$], "[]");                      /// 01: ok
+  testSymbol(#[]=, ($[$]=$).lastMember, "[]=");     /// 02: ok
+  testSymbol(const Symbol("unary-"), -$, "unary-");
+
+  testSymbolThrows(">>>");  /// 03: ok
+  testSymbolThrows("!");    /// 03: continued
+  testSymbolThrows("&&");   /// 03: continued
+  testSymbolThrows("||");   /// 03: continued
+  testSymbolThrows("?");    /// 03: continued
+  testSymbolThrows("?:");   /// 03: continued
+  testSymbolThrows("#");    /// 03: continued
+  testSymbolThrows("//");   /// 03: continued
+}
+
+void testSymbol(Symbol constSymbol, var mirrorSymbol, String name) {
+  Symbol dynamicSymbol = new Symbol(name);
+  if (constSymbol != mirrorSymbol) {
+    throw "Not equal #$name, \$$name: $constSymbol, $mirrorSymbol";
+  }
+  if (constSymbol != dynamicSymbol) {
+    throw "Not equal #$name, new Symbol('$name'): $constSymbol, $dynamicSymbol";
+  }
+  if (mirrorSymbol != dynamicSymbol) {
+    throw "Not equal \$$name, new Symbol('$name'): "
+          "$mirrorSymbol, $dynamicSymbol";
+  }
+  if (constSymbol.hashCode != mirrorSymbol.hashCode) {
+    throw "HashCode not equal #$name, \$$name: $constSymbol, $mirrorSymbol";
+  }
+  if (constSymbol.hashCode != dynamicSymbol.hashCode) {
+    throw "HashCode not equal #$name, new Symbol('$name'): "
+          "$constSymbol, $dynamicSymbol";
+  }
+  if (mirrorSymbol.hashCode != dynamicSymbol.hashCode) {
+    throw "HashCode not equal \$$name, new Symbol('$name'): "
+          "$mirrorSymbol, $dynamicSymbol";
+  }
+}
+
+void testSymbolThrows(name) {
+  bool fails = false;
+  try {
+    new Symbol(name);
+  } catch (e) {
+    fails = true;
+  }
+  if (!fails) {
+    throw "Didn't throw: $name";
+  }
+}
+
+class Symbolize {
+  Symbol lastMember;
+  noSuchMethod(m) => lastMember = m.memberName;
+}
diff --git a/tests/html/custom/mirrors_test.dart b/tests/html/custom/mirrors_test.dart
new file mode 100644
index 0000000..ea6b091
--- /dev/null
+++ b/tests/html/custom/mirrors_test.dart
@@ -0,0 +1,66 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library tests.html.mirrors_test;
+
+import 'dart:mirrors';
+import 'dart:html';
+import 'package:unittest/unittest.dart';
+import 'package:unittest/html_config.dart';
+import '../utils.dart';
+
+/// Regression test for a tricky mirrors+custom_elements issue:
+/// dart2js mirrors cache dispatch information on the Object's constructor.
+/// This was failing for custom elements on IE 10, because the constructor was
+/// HTMLUnknownElement for all of them. So mirrors called the wrong method.
+main() {
+  useHtmlConfiguration();
+
+  var registered = false;
+  setUp(() => loadPolyfills().then((_) {
+    if (!registered) {
+      registered = true;
+      document.register(A.tag, A);
+      document.register(B.tag, B);
+    }
+  }));
+
+  test('dynamic dispatch', () {
+    var a = new A();
+    expect(a.fooBar, 1);
+    reflect(a).setField(#fooBar, 123);
+    expect(a.fooBar, 123);
+
+    // Even though A was set first, B.fooBar= should dispatch to B.
+    var b = new B();
+    expect(b.fooBar, 2);
+    expect(b._fooBarSet, 0);
+    reflect(b).setField(#fooBar, 123);
+    expect(b.fooBar, 123);
+    expect(b._fooBarSet, 1);
+  });
+}
+
+class A extends HtmlElement {
+  static final tag = 'x-a';
+  factory A() => new Element.tag(tag);
+  A.created() : super.created();
+
+  int fooBar = 1;
+}
+
+class B extends HtmlElement {
+  static final tag = 'x-b';
+  factory B() => new Element.tag(tag);
+  B.created() : super.created();
+
+  int _fooBar = 2;
+  int _fooBarSet = 0;
+
+  int get fooBar => _fooBar;
+  set fooBar(value) {
+    _fooBarSet++;
+    _fooBar = value;
+  }
+}
diff --git a/tests/html/html.status b/tests/html/html.status
index 9eaefff..b7fa8d6 100644
--- a/tests/html/html.status
+++ b/tests/html/html.status
@@ -6,9 +6,6 @@
 interactive_test: Skip # Must be run manually.
 dromaeo_smoke_test: Skip # Issue 14521, 8257
 
-[ $compiler == dart2js && $csp && $runtime == drt ]
-mutationobserver_test: Skip # http://dartbug.com/15497
-
 [ $compiler == dart2js && $csp ]
 custom/js_custom_test: Fail # Issue 14643
 
@@ -280,7 +277,7 @@
 canvasrenderingcontext2d_test/drawImage_video_element_dataUrl: Fail # Safari does not support drawImage w/ video element
 audiocontext_test/functional: Fail # Issue 14354
 websql_test/functional: RuntimeError # Issue 14523
-
+custom/mirrors_test: Fail # Issue 15737
 
 # Safari Feature support statuses-
 # All changes should be accompanied by platform support annotation changes.
@@ -341,6 +338,10 @@
 speechrecognition_test/supported: Fail
 websql_test/supported: Fail
 
+[ $runtime == ff && $system == windows ]
+messageevent_test: RuntimeError # Issue 15651
+serialized_script_value_test: RuntimeError # Issue 15651
+
 [ $runtime == ff ]
 xhr_test/xhr: Pass, Fail # Issue 11602
 dart_object_local_storage_test: Skip  # sessionStorage NS_ERROR_DOM_NOT_SUPPORTED_ERR
diff --git a/tests/html/mutationobserver_test.dart b/tests/html/mutationobserver_test.dart
index 0af69c5..582f084 100644
--- a/tests/html/mutationobserver_test.dart
+++ b/tests/html/mutationobserver_test.dart
@@ -7,6 +7,12 @@
 import '../../pkg/unittest/lib/html_individual_config.dart';
 import 'dart:html';
 
+// Due to https://code.google.com/p/chromium/issues/detail?id=329103
+// mutationObservers sometimes do not fire if the node being observed is GCed
+// so we keep around references to all nodes we have created mutation
+// observers for.
+var keepAlive = [];
+
 /**
  * Test suite for Mutation Observers. This is just a small set of sanity
  * checks, not a complete test suite.
@@ -61,6 +67,7 @@
     test('direct-parallel options-named', () {
       expect(() {
         var container = new DivElement();
+        keepAlive.add(container);
         var div1 = new DivElement();
         var div2 = new DivElement();
         var mutationObserver = new MutationObserver(
@@ -75,6 +82,7 @@
     test('direct-nested options-named', () {
       expect(() {
         var container = new DivElement();
+        keepAlive.add(container);
         var div1 = new DivElement();
         var div2 = new DivElement();
         var mutationObserver =
@@ -89,6 +97,7 @@
     test('subtree options-named', () {
       expect(() {
         var container = new DivElement();
+        keepAlive.add(container);
         var div1 = new DivElement();
         var div2 = new DivElement();
         var mutationObserver = new MutationObserver(
diff --git a/tests/isolate/static_function_test.dart b/tests/isolate/static_function_test.dart
index db0beba..28e06b4 100644
--- a/tests/isolate/static_function_test.dart
+++ b/tests/isolate/static_function_test.dart
@@ -70,9 +70,11 @@
   });
 }
 
-void throwsTest(name, function) {
+void functionFailTest(name, function) {
   test("throws on $name", () {
-    expect(() { Isolate.spawn(function, null); }, throws);
+    Isolate.spawn(function, null).catchError(expectAsync1((e) {
+      /* do nothing */
+    }));
   });
 }
 
@@ -97,12 +99,14 @@
   spawnTest("lib._class._function", lib.privateClassAndFunction, "_LIBPRIVATE");
 
   // Negative tests
-  throwsTest("static closure", staticClosure);
-  throwsTest("dynamic closure", dynamicClosure);
-  throwsTest("named dynamic closure", namedDynamicClosure);
-  throwsTest("instance closure", new C().instanceClosure);
-  throwsTest("initializer closure", new C().constructorInitializerClosure);
-  throwsTest("constructor closure", new C().constructorBodyClosure);
-  throwsTest("named constructor closure", new C().namedConstructorBodyClosure);
-  throwsTest("instance method", new C().instanceMethod);
+  functionFailTest("static closure", staticClosure);
+  functionFailTest("dynamic closure", dynamicClosure);
+  functionFailTest("named dynamic closure", namedDynamicClosure);
+  functionFailTest("instance closure", new C().instanceClosure);
+  functionFailTest("initializer closure",
+                   new C().constructorInitializerClosure);
+  functionFailTest("constructor closure", new C().constructorBodyClosure);
+  functionFailTest("named constructor closure",
+                   new C().namedConstructorBodyClosure);
+  functionFailTest("instance method", new C().instanceMethod);
 }
diff --git a/tests/language/assert_assignable_type_test.dart b/tests/language/assert_assignable_type_test.dart
new file mode 100644
index 0000000..246f13e
--- /dev/null
+++ b/tests/language/assert_assignable_type_test.dart
@@ -0,0 +1,31 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// Dart test program to test arithmetic operations.
+// VMOptions=--optimization-counter-threshold=10 --checked
+
+// This test crashes if we recompute type of AssertAssignableInstr based on its
+// output types. By doing that we would eliminate not only the unnecessary
+// AssertAssignableInstr but also the trailing class check.
+
+main() {
+  // Foul up  IC data in integer's unary minus.
+  var y = -0x80000000;
+  testInt64List();
+}
+
+testInt64List() {
+  var array = new List(10);
+  testInt64ListImpl(array);
+}
+
+
+testInt64ListImpl(array) {
+  for (int i = 0; i < 10; ++i) {
+  }
+  int sum = 0;
+  for (int i = 0; i < 10; ++i) {
+    array[i] = -0x80000000000000 + i;
+  }
+}
+
diff --git a/tests/language/guess_cid_test.dart b/tests/language/guess_cid_test.dart
new file mode 100644
index 0000000..3759cb9
--- /dev/null
+++ b/tests/language/guess_cid_test.dart
@@ -0,0 +1,88 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// Dart test program to test cid guessing optimizations.
+// VMOptions=--optimization-counter-threshold=10
+
+import "package:expect/expect.dart";
+
+main() {
+  // Warmup optimizes methods.
+  for (int i = 0; i < 100; i++) {
+    Expect.equals(i, compareInt(i));
+    Expect.equals(i.toDouble(), compareDouble(i.toDouble()));
+    Expect.equals(i, binOpInt(i, i));
+    Expect.equals(i.toDouble(), binOpDouble(i.toDouble(), i.toDouble()));
+  }
+  Expect.equals(3, compareInt(3));
+  Expect.equals(-2, compareInt(-2));
+  Expect.equals(0, compareInt(-1));
+  
+  Expect.equals(3, binOpInt(3, 3));
+  Expect.equals(0, binOpInt(-2, -2));
+  
+  Expect.equals(3.0, binOpDouble(3.0, 3.0));
+  Expect.equals(0.0, binOpDouble(-2.0, -2.0));
+  
+  Expect.equals(3.0, compareDouble(3.0));
+  Expect.equals(-2.0, compareDouble(-2.0));
+  Expect.equals(0.0, compareDouble(-1.0));
+  
+  testOSR();
+}
+
+int compareInt(int i) {
+  if (i < 0) {
+    // Not visited in before optimization.
+    // Guess cid of comparison below.
+    if (i == -1) return 0;
+  }
+  return i;
+}
+
+double compareDouble(double i) {
+  if (i < 0.0) {
+    // Not visited in before optimization.
+    // Guess cid of comparison below.
+    if (i == -1.0) return 0.0;
+  }
+  return i;
+}
+
+int binOpInt(int i, int x) {
+  if (i < 0) {
+    // Not visited in before optimization.
+    // Guess cid of binary operation below.
+    return x + 2;
+  }
+  return i;
+}
+
+double binOpDouble(double i, double x) {
+  if (i < 0.0) {
+    // Not visited in before optimization.
+    // Guess cid of binary operation below.
+    return x + 2.0;
+  }
+  return i;
+}
+
+testOSR() {
+  // Foul up  IC data in integer's unary minus.
+  var y = -0x80000000;
+  Expect.equals(1475739525896764129300, testLoop(10, 0x80000000000000000));
+  // Second time no deoptimization can occur, since runtime feedback has been collected.
+  Expect.equals(1475739525896764129300, testLoop(10, 0x80000000000000000));
+}
+
+testLoop(N, x) {
+  for (int i = 0; i < N; ++i) {
+    // Will trigger OSR. Operation in loop below will use guessed cids.
+  }
+  int sum = 0;
+  for (int i = 0; i < N; ++i) {
+    // Guess 'x' is Smi, but is actually Bigint: deoptimize.
+    sum += x + 2;
+  }
+  return sum;
+}
diff --git a/tests/language/illegal_initializer_test.dart b/tests/language/illegal_initializer_test.dart
new file mode 100644
index 0000000..64d54f9
--- /dev/null
+++ b/tests/language/illegal_initializer_test.dart
@@ -0,0 +1,43 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+class A {
+  A();
+  A.foo();
+}
+
+class B extends A {
+  B.c1() : super.foo
+  /*  /// 01: compile-time error
+  ()
+  */  /// 01: continued
+  ;
+
+  B.foo();
+  B.c2() : this.foo
+  /*  /// 02: compile-time error
+  ()
+  */  /// 02: continued
+  ;
+
+  B.c3() : super
+  /*  /// 03: compile-time error
+  ()
+  */  /// 03: continued
+  ;
+
+  B();
+  B.c4() : this
+  /*  /// 04: compile-time error
+  ()
+  */  /// 04: continued
+  ;
+}
+
+main() {
+  new B.c1();
+  new B.c2();
+  new B.c3();
+  new B.c4();
+}
diff --git a/tests/language/inferrer_closure_test.dart b/tests/language/inferrer_closure_test.dart
new file mode 100644
index 0000000..0106ce6
--- /dev/null
+++ b/tests/language/inferrer_closure_test.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Regression test for dart2js that used to not see a closure could be
+// invoked through a getter access followed by an invocation.
+
+var closure = (a) => a.toString();
+
+get foo => closure;
+
+main() {
+  if (foo(42) != '42') {
+    throw 'Test failed';
+  }
+}
diff --git a/tests/language/invocation_mirror2_test.dart b/tests/language/invocation_mirror2_test.dart
index c07330c..3e64ba4 100644
--- a/tests/language/invocation_mirror2_test.dart
+++ b/tests/language/invocation_mirror2_test.dart
@@ -9,7 +9,7 @@
   set flif(_) => "flif=";
 }
 
-String getName(im) => reflect(new GetName()).delegate(im);
+int getName(im) => reflect(new GetName()).delegate(im);
 
 class C {
   var im;
@@ -20,6 +20,6 @@
 main() {
  var c = new C();
  c.flif = 42;
- Expect.equals('flif=', getName(c.im));
+ Expect.equals(42, getName(c.im));
  Expect.equals(42, c.im.positionalArguments[0]);
 }
diff --git a/tests/language/issue15606_test.dart b/tests/language/issue15606_test.dart
new file mode 100644
index 0000000..d50b576
--- /dev/null
+++ b/tests/language/issue15606_test.dart
@@ -0,0 +1,21 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+class Foo<T> {}
+
+var a = [new Object(), 42];
+
+main() {
+  while (false) { // Comply to inlining heuristics.
+    // Use an unresolved prefix.
+    var foo = Unresolved.foo( /// 01: static type warning
+      // Make dart2js generate a call to setRuntimeTypeInfo.
+      new Foo<int>(), /// 01: continued
+      // Use a one-shot interceptor.
+      a[0].toString()); /// 01: continued
+
+    // Do an is test on `Foo` to require setRuntimeTypeInfo.
+    print(foo is Foo<int>); /// 01: continued
+  }
+}
diff --git a/tests/language/issue15702_test.dart b/tests/language/issue15702_test.dart
new file mode 100644
index 0000000..283a021
--- /dev/null
+++ b/tests/language/issue15702_test.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+main() {
+  Amount stake = new Amount(2.5);
+  if ((stake.value * 10).toInt() != 25) {
+    throw 'Test failed';
+  }
+}
+
+class Amount {
+  num value;
+  Amount(this.value);
+}
+
diff --git a/tests/language/language_analyzer.status b/tests/language/language_analyzer.status
index bcdd6cf..ee85f4c 100644
--- a/tests/language/language_analyzer.status
+++ b/tests/language/language_analyzer.status
@@ -314,7 +314,6 @@
 malbounded_type_literal_test: StaticWarning
 malformed_type_test: StaticWarning
 malformed2_test/01: MissingCompileTimeError
-map_literal11_test: StaticWarning
 map_literal2_negative_test: CompileTimeError
 map_literal3_test: StaticWarning
 map_literal4_test: StaticWarning
diff --git a/tests/language/language_dart2js.status b/tests/language/language_dart2js.status
index 8b873d9..1942eb0 100644
--- a/tests/language/language_dart2js.status
+++ b/tests/language/language_dart2js.status
@@ -137,6 +137,7 @@
 mixin_regress_13688_test: RuntimeError # Issue 13109.
 modulo_test: RuntimeError # Issue 15246
 truncdiv_test: RuntimeError # Issue 15246
+invocation_mirror2_test: RuntimeError # Issue 6490 (wrong retval).
 
 # Compilation errors.
 const_var_test: CompileTimeError # Issue 12793
diff --git a/tests/language/list_tracer_return_from_tearoff_closure_test.dart b/tests/language/list_tracer_return_from_tearoff_closure_test.dart
new file mode 100644
index 0000000..47e1bb49
--- /dev/null
+++ b/tests/language/list_tracer_return_from_tearoff_closure_test.dart
@@ -0,0 +1,20 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Regression test for dart2js's list tracer, that used to not see a
+// returned value of a method can escape to places where that method
+// is closurized and invoked.
+
+var a = [42];
+
+foo() {
+  return a;
+}
+
+main() {
+  (foo)().clear();
+  if (a.length == 1) {
+    throw 'Test failed';
+  }
+}
diff --git a/tests/language/load_indexed_constant_test.dart b/tests/language/load_indexed_constant_test.dart
new file mode 100644
index 0000000..cf45b18
--- /dev/null
+++ b/tests/language/load_indexed_constant_test.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// Test constant propgation of load-indexed operations
+// VMOptions=--optimization-counter-threshold=10
+
+import "package:expect/expect.dart";
+
+
+main() {
+  Expect.equals(101, stringIndexedLoad());
+  Expect.equals(102, arrayIndexedLoad());
+  for (int i = 0; i < 20; i++) {
+    stringIndexedLoad();
+    arrayIndexedLoad();
+  }
+  Expect.equals(101, stringIndexedLoad());
+  Expect.equals(102, arrayIndexedLoad());
+}
+
+stringIndexedLoad() => ("Hello").codeUnitAt(1);
+arrayIndexedLoad() => (const [101, 102, 103])[1];
\ No newline at end of file
diff --git a/tests/language/super_abstract_method_test.dart b/tests/language/super_abstract_method_test.dart
index fbb3648..b501b7f 100644
--- a/tests/language/super_abstract_method_test.dart
+++ b/tests/language/super_abstract_method_test.dart
@@ -17,6 +17,7 @@
 
 class B extends A {
   testSuperCall() => super.foo();
+  foo() => 42; // required since if is removed, then a warning is introduced on 'B' above
 }
 
 main() {
diff --git a/tests/lib/lib.status b/tests/lib/lib.status
index 789712d..1762ceb 100644
--- a/tests/lib/lib.status
+++ b/tests/lib/lib.status
@@ -21,6 +21,7 @@
 mirrors/closures_test/none: RuntimeError # Issue 6490
 mirrors/constructor_kinds_test: RuntimeError # Issue 13799
 mirrors/constructor_private_name_test: CompileTimeError # Issue 13597
+mirrors/delegate_call_through_getter_test: RuntimeError # Issue 15138
 mirrors/equality_test/02: RuntimeError # Issue 12785
 mirrors/fake_function_with_call_test: RuntimeError # Issue 11612
 mirrors/fake_function_without_call_test: RuntimeError # Issue 11612
@@ -41,6 +42,7 @@
 mirrors/instance_members_test: RuntimeError # Issue 14633
 mirrors/instance_members_with_override_test: RuntimeError # Issue 14633
 mirrors/instance_members_unimplemented_interface_test: RuntimeError # Issue 14633
+mirrors/instantiate_abstract_class_test: RuntimeError # Issue 6490
 mirrors/intercepted_superclass_test: RuntimeError # Issue 13644
 mirrors/invoke_test: RuntimeError # Issue 11954
 mirrors/invoke_call_through_getter_test: RuntimeError # Issue 15138
@@ -64,7 +66,6 @@
 mirrors/mirrors_test: RuntimeError # TODO(ahe): I'm working on fixing this.
 mirrors/mixin_test: RuntimeError # Issue 12464
 mirrors/mixin_application_test/none: RuntimeError # Issue 12464
-mirrors/new_instance_with_type_arguments_test: RuntimeError # Issue 12333
 mirrors/null_test : RuntimeError # Issue 12129
 mirrors/parameter_test/none: RuntimeError # Issue 6490
 mirrors/parameter_metadata_test: CompileTimeError # Issue 10905
@@ -72,7 +73,6 @@
 mirrors/proxy_type_test: RuntimeError # Issue 13842
 mirrors/redirecting_factory_test/none: RuntimeError # Issue 6490
 mirrors/redirecting_factory_test/02: RuntimeError # Issue 6490
-mirrors/reflected_type_test: RuntimeError # Issue 12607
 mirrors/repeated_private_anon_mixin_app_test: RuntimeError # Issue 14670
 mirrors/symbol_validation_test: RuntimeError # Issue 13597
 mirrors/static_members_test: RuntimeError # Issue 14633, Issue 12164
@@ -161,6 +161,8 @@
 [ $compiler == dart2js && $minified ]
 mirrors/typedef_test/01: Fail # http://dartbug.com/6490
 mirrors/list_constructor_test/none: Fail # http://dartbug.com/15555
+mirrors/mirrors_used_get_name_test: RuntimeError
+mirrors/mirrors_used_get_name2_test: RuntimeError
 
 [ $runtime == ff ]
 # FF setTimeout can fire early: https://bugzilla.mozilla.org/show_bug.cgi?id=291386
@@ -207,7 +209,7 @@
 mirrors/generic_local_function_test: RuntimeError # Issue 14913
 mirrors/symbol_validation_test: RuntimeError # Issue 13596
 mirrors/synthetic_accessor_properties_test/none: RuntimeError # Issue 14632
-mirrors/toplevel_members_test: RuntimeError # Issue 14632
+mirrors/toplevel_members_test/01: RuntimeError # Issue 14632
 
 async/timer_not_available_test: SkipByDesign # only meant to test when there is no way to implement timer (currently only in d8)
 
@@ -254,7 +256,6 @@
 
 [ $compiler == dartanalyzer || $compiler == dart2analyzer ]
 mirrors/generic_f_bounded_mixin_application_test: CompileTimeError # Issue 14116
-mirrors/invoke_named_test: StaticWarning # Issue 14522
 
 mirrors/redirecting_factory_test/01: StaticWarning # test issue X, The return type 'Class<T2, T1>' of the redirected constructor is not assignable to 'Class<T1, T2>'
 mirrors/redirecting_factory_test/none: StaticWarning # test issue X, The return type 'Class<T2, T1>' of the redirected constructor is not assignable to 'Class<T1, T2>
diff --git a/tests/lib/mirrors/delegate_call_through_getter_test.dart b/tests/lib/mirrors/delegate_call_through_getter_test.dart
new file mode 100644
index 0000000..4d0d088
--- /dev/null
+++ b/tests/lib/mirrors/delegate_call_through_getter_test.dart
@@ -0,0 +1,45 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library test.invoke_call_through_getter;
+
+import 'dart:mirrors';
+
+import 'package:expect/expect.dart';
+
+class FakeFunctionCall {
+  call(x, y) => '1 $x $y';
+}
+class FakeFunctionNSM {
+  noSuchMethod(msg) => msg.positionalArguments.join(', ');
+}
+
+class C {
+  get fakeFunctionCall => new FakeFunctionCall();
+  get fakeFunctionNSM => new FakeFunctionNSM();
+  get closure => (x, y) => '2 $this $x $y';
+  get closureOpt => (x, y, [z, w]) => '3 $this $x $y $z $w';
+  get closureNamed => (x, y, {z, w}) => '4 $this $x $y $z $w';
+  get notAClosure => 'Not a closure';
+  noSuchMethod(msg) => 'DNU';
+
+  toString() => 'C';
+}
+
+class Forwarder {
+  noSuchMethod(msg) => reflect(new C()).delegate(msg);
+}
+
+main() {
+  var f = new Forwarder();
+
+  Expect.equals('1 5 6', f.fakeFunctionCall(5, 6));
+  Expect.equals('7, 8', f.fakeFunctionNSM(7, 8));
+  Expect.equals('2 C 9 10', f.closure(9, 10));
+  Expect.equals('3 C 11 12 13 null', f.closureOpt(11, 12, 13));
+  Expect.equals('4 C 14 15 null 16', f.closureNamed(14, 15, w: 16));
+  Expect.equals('DNU', f.doesNotExist(17, 18));
+  Expect.throws(() => f.closure('wrong arity'), (e) => e is NoSuchMethodError);
+  Expect.throws(() => f.notAClosure(), (e) => e is NoSuchMethodError);
+}
diff --git a/tests/lib/mirrors/initializing_formals_test.dart b/tests/lib/mirrors/initializing_formals_test.dart
index 2729524..cbb0812 100644
--- a/tests/lib/mirrors/initializing_formals_test.dart
+++ b/tests/lib/mirrors/initializing_formals_test.dart
@@ -46,7 +46,7 @@
   Expect.isFalse(pm.isPrivate);
   Expect.isFalse(pm.isStatic);
   Expect.isFalse(pm.isTopLevel);
-  
+
   mm = reflectClass(Class).declarations[#Class.named];
   pm = mm.parameters.single;
   Expect.equals(#boolField, pm.simpleName);
@@ -71,11 +71,11 @@
   Expect.isFalse(pm.isPrivate);
   Expect.isFalse(pm.isStatic);
   Expect.isFalse(pm.isTopLevel);
-  
+
   mm = reflectClass(Class).declarations[#Class.generic];
   pm = mm.parameters.single;
   Expect.equals(#tField, pm.simpleName);
-  Expect.equals(reflectClass(Class).typeVariables.single, pm.type);  
+  Expect.equals(reflectClass(Class).typeVariables.single, pm.type);
   Expect.isFalse(pm.isNamed);  /// 01: ok
   Expect.isFalse(pm.isFinal);  /// 01: ok
   Expect.isFalse(pm.isOptional);  /// 01: ok
diff --git a/tests/lib/mirrors/instantiate_abstract_class_test.dart b/tests/lib/mirrors/instantiate_abstract_class_test.dart
new file mode 100644
index 0000000..e86e534
--- /dev/null
+++ b/tests/lib/mirrors/instantiate_abstract_class_test.dart
@@ -0,0 +1,46 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library test.instantiate_abstract_class;
+
+import 'dart:mirrors';
+import 'package:expect/expect.dart';
+
+
+assertInstanitationErrorOnGenerativeConstructors(classMirror) {
+  classMirror.declarations.values.forEach((decl) {
+    if (decl is! MethodMirror) return;
+    if (!decl.isGenerativeConstructor) return;
+    var args = new List(decl.parameters.length);
+    Expect.throws(() => classMirror.newInstance(decl.constructorName, args),
+                  (e) => e is AbstractClassInstantiationError,
+                  '${decl.qualifiedName} should have failed');
+  });
+}
+
+runFactoryConstructors(classMirror) {
+  classMirror.declarations.values.forEach((decl) {
+    if (decl is! MethodMirror) return;
+    if (!decl.isFactoryConstructor) return;
+    var args = new List(decl.parameters.length);
+    classMirror.newInstance(decl.constructorName, args);  // Should not throw.
+  });
+}
+
+abstract class AbstractClass {
+  AbstractClass();
+  AbstractClass.named();
+  factory AbstractClass.named2() => new ConcreteClass();
+}
+
+class ConcreteClass implements AbstractClass {}
+
+main() {
+  assertInstanitationErrorOnGenerativeConstructors(reflectType(num));
+  assertInstanitationErrorOnGenerativeConstructors(reflectType(double));
+  assertInstanitationErrorOnGenerativeConstructors(reflectType(StackTrace));
+
+  assertInstanitationErrorOnGenerativeConstructors(reflectType(AbstractClass));
+  runFactoryConstructors(reflectType(AbstractClass));
+}
diff --git a/tests/lib/mirrors/mirrors_used_get_name2_test.dart b/tests/lib/mirrors/mirrors_used_get_name2_test.dart
new file mode 100644
index 0000000..762665e
--- /dev/null
+++ b/tests/lib/mirrors/mirrors_used_get_name2_test.dart
@@ -0,0 +1,35 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test to make sure that the names of classes that are marked with meta
+// annotations of MirrorsUsed are preserved.
+// In the test the class B is not instantiated, but we still want its names
+// ("foo") to be preserved.
+
+@MirrorsUsed(metaTargets: "Meta")
+import 'dart:mirrors';
+import 'package:expect/expect.dart';
+
+class A {
+  noSuchMethod(invocationMirror) {
+    return MirrorSystem.getName(invocationMirror.memberName);
+  }
+}
+
+class B {
+  @Meta()
+  foo() => 499;
+}
+
+class Meta {
+  const Meta();
+}
+
+void main() {
+  var a = new A();
+  if (new DateTime.now().year == 1984) {
+    a = A;
+  }
+  Expect.equals("foo", a.foo());
+}
diff --git a/tests/lib/mirrors/mirrors_used_get_name_test.dart b/tests/lib/mirrors/mirrors_used_get_name_test.dart
new file mode 100644
index 0000000..f87ee52
--- /dev/null
+++ b/tests/lib/mirrors/mirrors_used_get_name_test.dart
@@ -0,0 +1,30 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test to make sure that the names of classes that are marked with mirrors-used
+// are preserved.
+// In the test the class B is not instantiated, but we still want its names (the
+// "foo") to be preserved.
+
+@MirrorsUsed(targets: "B")
+import 'dart:mirrors';
+import 'package:expect/expect.dart';
+
+class A {
+  noSuchMethod(invocationMirror) {
+    return MirrorSystem.getName(invocationMirror.memberName);
+  }
+}
+
+class B {
+  foo() => 499;
+}
+
+void main() {
+  var a = new A();
+  if (new DateTime.now().year == 1984) {
+    a = A;
+  }
+  Expect.equals("foo", a.foo());
+}
diff --git a/tests/lib/mirrors/new_instance_with_type_arguments_test.dart b/tests/lib/mirrors/new_instance_with_type_arguments_test.dart
index 44238ad..2885bbb 100644
--- a/tests/lib/mirrors/new_instance_with_type_arguments_test.dart
+++ b/tests/lib/mirrors/new_instance_with_type_arguments_test.dart
@@ -20,7 +20,7 @@
   ClassMirror cmA = reflectClass(A);
   ClassMirror cmB = reflectClass(B);
   ClassMirror cmC = reflectClass(C);
-  
+
   var a_int = new A<int>();
   var a_dynamic = new A();
   var b = new B();
@@ -36,31 +36,26 @@
   Expect.equals(String, c_string.s);
   Expect.equals(dynamic, c_dynamic.s);
 
-
   var reflective_a_int =
       cmB.superclass.newInstance(const Symbol(''), []).reflectee;
   var reflective_a_dynamic =
       cmA.newInstance(const Symbol(''), []).reflectee;
   var reflective_b =
       cmB.newInstance(const Symbol(''), []).reflectee;
-  // TODO(rmacnak): Uncomment when reflectType is added to the API.
-  // var reflective_c_string =
-  //   reflectType(cmC.runtimeType).newInstance(const Symbol(''), []).reflectee;
   var reflective_c_dynamic =
       cmC.newInstance(const Symbol(''), []).reflectee;
 
   Expect.equals(int, reflective_a_int.t);
   Expect.equals(dynamic, reflective_a_dynamic.t);
   Expect.equals(int, reflective_b.t);
-  // Expect.equals(num, c_string.t);
+  Expect.equals(num, c_string.t);
   Expect.equals(num, reflective_c_dynamic.t);
 
-  // Expect.equals(String, c_string.s);
+  Expect.equals(String, c_string.s);
   Expect.equals(dynamic, reflective_c_dynamic.s);
 
   Expect.equals(a_int.runtimeType, reflective_a_int.runtimeType);
   Expect.equals(a_dynamic.runtimeType, reflective_a_dynamic.runtimeType);
   Expect.equals(b.runtimeType, reflective_b.runtimeType);
-  // Expect.equals(c_string.runtimeType, reflective_c_string.runtimeType);
   Expect.equals(c_dynamic.runtimeType, reflective_c_dynamic.runtimeType);
 }
diff --git a/tests/lib/mirrors/reflected_type_test.dart b/tests/lib/mirrors/reflected_type_test.dart
index 70ebcf3..a574434 100644
--- a/tests/lib/mirrors/reflected_type_test.dart
+++ b/tests/lib/mirrors/reflected_type_test.dart
@@ -19,17 +19,27 @@
 
 expectReflectedType(classMirror, expectedType) {
   if (expectedType == null) {
-    Expect.isFalse(classMirror.hasReflectedType);
+    Expect.isFalse(classMirror.hasReflectedType,
+                   "$classMirror should not have a reflected type");
     Expect.throws(() => classMirror.reflectedType,
-                  (e) => e is UnsupportedError,
-                  "Should not have a reflected type");
+                  (e) => e is UnsupportedError);
   } else {
-    Expect.isTrue(classMirror.hasReflectedType);
+    Expect.isTrue(classMirror.hasReflectedType,
+                  "$classMirror should have a reflected type");
     Expect.equals(expectedType, classMirror.reflectedType);
   }
 }
 
 main() {
+  // Basic non-generic types, including intercepted types.
+  expectReflectedType(reflectClass(Object), Object);
+  expectReflectedType(reflectClass(String), String);
+  expectReflectedType(reflectClass(int), int);
+  expectReflectedType(reflectClass(num), num);
+  expectReflectedType(reflectClass(double), double);
+  expectReflectedType(reflectClass(bool), bool);
+  expectReflectedType(reflectClass(Null), Null);
+
   // Declarations.
   expectReflectedType(reflectClass(A), null);
   expectReflectedType(reflectClass(B), B);
diff --git a/tests/lib/mirrors/synthetic_accessor_properties_test.dart b/tests/lib/mirrors/synthetic_accessor_properties_test.dart
index fc96b6d..215d3a3 100644
--- a/tests/lib/mirrors/synthetic_accessor_properties_test.dart
+++ b/tests/lib/mirrors/synthetic_accessor_properties_test.dart
@@ -68,7 +68,6 @@
   mm = cm.staticMembers[const Symbol('finalStaticField=')];
   Expect.isNull(mm);
 
-  return;  /// 01: ok
 
   mm = lm.topLevelMembers[#topLevelField];
   expect('Method(s(topLevelField) in s(test.synthetic_accessor_properties),'
@@ -93,6 +92,8 @@
   mm = lm.topLevelMembers[const Symbol('finalTopLevelField=')];
   Expect.isNull(mm);
 
+  return;  /// 01: ok
+
   mm = lm.topLevelMembers[#C];
   expect('Method(s(C) in s(test.synthetic_accessor_properties),'
          ' top-level, synthetic, static, getter)', mm);
diff --git a/tests/lib/mirrors/toplevel_members_test.dart b/tests/lib/mirrors/toplevel_members_test.dart
index 1fe613b..84839d8 100644
--- a/tests/lib/mirrors/toplevel_members_test.dart
+++ b/tests/lib/mirrors/toplevel_members_test.dart
@@ -29,13 +29,14 @@
      MirrorSystem.getSymbol('_libraryGetter', lm),
      MirrorSystem.getSymbol('_librarySetter=', lm),
      MirrorSystem.getSymbol('_libraryMethod', lm),
-     #Predicate,
-     #Superclass,
-     #Interface,
-     #Mixin,
-     #Class,
-     MirrorSystem.getSymbol('_PrivateClass', lm),
-     #ConcreteClass],
+     #Predicate,  /// 01: ok
+     #Superclass,  /// 01: continued
+     #Interface,  /// 01: continued
+     #Mixin,  /// 01: continued
+     #Class,  /// 01: continued
+     MirrorSystem.getSymbol('_PrivateClass', lm),  /// 01: continued
+     #ConcreteClass  /// 01: continued
+     ],
     selectKeys(lm.topLevelMembers, (dm) => true));
 
   Expect.setEquals(
@@ -43,12 +44,13 @@
      const Symbol('libraryVariable='),
      MirrorSystem.getSymbol('_libraryVariable', lm),
      MirrorSystem.getSymbol('_libraryVariable=', lm),
-     #Predicate,
-     #Superclass,
-     #Interface,
-     #Mixin,
-     #Class,
-     MirrorSystem.getSymbol('_PrivateClass', lm),
-     #ConcreteClass],
+     #Predicate,  /// 01: continued
+     #Superclass,  /// 01: continued
+     #Interface,  /// 01: continued
+     #Mixin,  /// 01: continued
+     #Class,  /// 01: continued
+     MirrorSystem.getSymbol('_PrivateClass', lm),  /// 01: continued
+     #ConcreteClass  /// 01: continued
+     ],
     selectKeys(lm.topLevelMembers, (dm) => dm.isSynthetic));
 }
diff --git a/tests/lib/mirrors/unused_mirrors_used_test.dart b/tests/lib/mirrors/unused_mirrors_used_test.dart
new file mode 100644
index 0000000..0fe1e37
--- /dev/null
+++ b/tests/lib/mirrors/unused_mirrors_used_test.dart
@@ -0,0 +1,17 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Regression test.
+// The MirrorsUsed annotation made dart2js to mark List as needed for reflection
+// but tree-shaking wasn't turned off (since there is no actual mirror use)
+// which led to a broken output.
+
+@MirrorsUsed(targets: "List")
+import 'dart:mirrors';
+
+void main() {
+  var l = new List<int>();
+  var f = l.retainWhere;
+  f((x) => true);
+}
diff --git a/tests/standalone/io/file_copy_test.dart b/tests/standalone/io/file_copy_test.dart
new file mode 100644
index 0000000..2ef7358
--- /dev/null
+++ b/tests/standalone/io/file_copy_test.dart
@@ -0,0 +1,86 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+//
+// Dart test program for testing File.copy*
+
+import 'dart:io';
+
+import "package:expect/expect.dart";
+import "package:async_helper/async_helper.dart";
+
+const FILE_CONTENT1 = 'some string';
+const FILE_CONTENT2 = 'some other string';
+
+void testCopySync() {
+  var tmp = Directory.systemTemp.createTempSync('dart-file-copy');
+
+  var file1 = new File('${tmp.path}/file1');
+  file1.writeAsStringSync(FILE_CONTENT1);
+  Expect.equals(FILE_CONTENT1, file1.readAsStringSync());
+
+  // Copy to new file works.
+  var file2 = file1.copySync('${tmp.path}/file2');
+  Expect.equals(FILE_CONTENT1, file1.readAsStringSync());
+  Expect.equals(FILE_CONTENT1, file2.readAsStringSync());
+
+  // Override works for files.
+  file2.writeAsStringSync(FILE_CONTENT2);
+  file2.copySync(file1.path);
+  Expect.equals(FILE_CONTENT2, file1.readAsStringSync());
+  Expect.equals(FILE_CONTENT2, file2.readAsStringSync());
+
+  // Fail when coping to directory.
+  var dir = new Directory('${tmp.path}/dir')..createSync();
+  Expect.throws(() => file1.copySync(dir.path));
+  Expect.equals(FILE_CONTENT2, file1.readAsStringSync());
+
+  tmp.deleteSync(recursive: true);
+}
+
+
+void testCopy() {
+  asyncStart();
+  var tmp = Directory.systemTemp.createTempSync('dart-file-copy');
+
+  var file1 = new File('${tmp.path}/file1');
+  file1.writeAsStringSync(FILE_CONTENT1);
+  Expect.equals(FILE_CONTENT1, file1.readAsStringSync());
+
+  // Copy to new file works.
+  file1.copy('${tmp.path}/file2')
+    .then((file2) {
+      Expect.equals(FILE_CONTENT1, file1.readAsStringSync());
+      Expect.equals(FILE_CONTENT1, file2.readAsStringSync());
+
+      // Override works for files.
+      file2.writeAsStringSync(FILE_CONTENT2);
+      return file2.copy(file1.path)
+        .then((_) {
+          Expect.equals(FILE_CONTENT2, file1.readAsStringSync());
+          Expect.equals(FILE_CONTENT2, file2.readAsStringSync());
+
+          // Fail when coping to directory.
+          var dir = new Directory('${tmp.path}/dir')..createSync();
+
+          return file1.copy(dir.path)
+            .then((_) => Expect.fail('expected error'),
+                  onError: (_) {})
+            .then((_) {
+              Expect.equals(FILE_CONTENT2, file1.readAsStringSync());
+            });
+
+        });
+    })
+    .whenComplete(() {
+      tmp.deleteSync(recursive: true);
+      asyncEnd();
+    });
+
+}
+
+
+main() {
+  testCopySync();
+  testCopy();
+}
diff --git a/tests/standalone/io/internet_address_invalid_arguments_test.dart b/tests/standalone/io/internet_address_invalid_arguments_test.dart
new file mode 100644
index 0000000..59610e1
--- /dev/null
+++ b/tests/standalone/io/internet_address_invalid_arguments_test.dart
@@ -0,0 +1,21 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io';
+
+import "package:expect/expect.dart";
+
+void testIllegalArguments() {
+  var args = [
+      null, 1, 1.1, new Object(), [], {'a' : '127.0.0.1'},
+      "", "." , ":", ":::"];
+  args.forEach((arg) {
+    Expect.throws(() => new InternetAddress(arg),
+                  (e) => e is ArgumentError);
+  });
+}
+
+void main() {
+  testIllegalArguments();
+}
diff --git a/tests/standalone/io/raw_datagram_socket_test.dart b/tests/standalone/io/raw_datagram_socket_test.dart
index 6f3ebef..86fb5e4 100644
--- a/tests/standalone/io/raw_datagram_socket_test.dart
+++ b/tests/standalone/io/raw_datagram_socket_test.dart
@@ -25,7 +25,9 @@
     RawDatagramSocket.bind(address, 0).then((socket) {
       Expect.isFalse(socket.broadcastEnabled);
       socket.broadcastEnabled = true;
-      Expect.isTrue(socket.broadcastEnabled);
+      if (!Platform.isMacOS) {
+        Expect.isTrue(socket.broadcastEnabled);
+      }
       socket.broadcastEnabled = false;
       Expect.isFalse(socket.broadcastEnabled);
       asyncEnd();
@@ -177,8 +179,10 @@
 
   test(InternetAddress.ANY_IP_V4, new InternetAddress("228.0.0.4"), true);
   test(InternetAddress.ANY_IP_V4, new InternetAddress("224.0.0.0"), false);
-  test(InternetAddress.ANY_IP_V6, new InternetAddress("ff11::0"), true);
-  test(InternetAddress.ANY_IP_V6, new InternetAddress("ff11::0"), false);
+  if (!Platform.isMacOS) {
+    test(InternetAddress.ANY_IP_V6, new InternetAddress("ff11::0"), true);
+    test(InternetAddress.ANY_IP_V6, new InternetAddress("ff11::0"), false);
+  }
 }
 
 testSendReceive(InternetAddress bindAddress) {
@@ -297,7 +301,9 @@
 main() {
   testDatagramBroadcastOptions();
   testDatagramMulticastOptions();
-  testDatagramSocketReuseAddress();
+  if (!Platform.isMacOS) {
+    testDatagramSocketReuseAddress();
+  }
   testBroadcast();
   testLoopbackMulticast();
   testSendReceive(InternetAddress.LOOPBACK_IP_V4);
diff --git a/tests/standalone/io/signals_test.dart b/tests/standalone/io/signals_test.dart
new file mode 100644
index 0000000..00805a5
--- /dev/null
+++ b/tests/standalone/io/signals_test.dart
@@ -0,0 +1,64 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "dart:io";
+
+import "package:expect/expect.dart";
+import "package:async_helper/async_helper.dart";
+
+void testSignals(int usr1Expect,
+                 int usr2Expect,
+                 [int usr1Send,
+                  int usr2Send,
+                  bool shouldFail = false]) {
+  if (usr1Send == null) usr1Send = usr1Expect;
+  if (usr2Send == null) usr2Send = usr2Expect;
+  asyncStart();
+  Process.start(Platform.executable,
+      [Platform.script.resolve('signals_test_script.dart').toFilePath(),
+       usr1Expect.toString(),
+       usr2Expect.toString()])
+    .then((process) {
+      process.stdin.close();
+      process.stderr.drain();
+      int v = 0;
+      process.stdout.listen((out) {
+        // Send as many signals as 'ready\n' received on stdout
+        int count = out.where((c) => c == '\n'.codeUnitAt(0)).length;
+        for (int i = 0; i < count; i++) {
+          if (v < usr1Send) {
+            process.kill(ProcessSignal.SIGUSR1);
+          } else if (v < usr1Send + usr2Send) {
+            process.kill(ProcessSignal.SIGUSR2);
+          }
+          v++;
+        }
+      });
+      process.exitCode.then((exitCode) {
+        Expect.equals(shouldFail, exitCode != 0);
+        asyncEnd();
+      });
+    });
+}
+
+
+void testListenCancel() {
+  for (int i = 0; i < 10; i++) {
+    ProcessSignal.SIGINT.watch().listen(null).cancel();
+  }
+}
+
+void main() {
+  testListenCancel();
+  if (Platform.isWindows) return;
+  testSignals(0, 0);
+  testSignals(1, 0);
+  testSignals(0, 1);
+  testSignals(1, 1);
+  testSignals(10, 10);
+  testSignals(10, 1);
+  testSignals(1, 10);
+  testSignals(1, 0, 0, 1, true);
+  testSignals(0, 1, 1, 0, true);
+}
diff --git a/tests/standalone/io/signals_test_script.dart b/tests/standalone/io/signals_test_script.dart
new file mode 100644
index 0000000..5a2c7bc
--- /dev/null
+++ b/tests/standalone/io/signals_test_script.dart
@@ -0,0 +1,31 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "dart:io";
+
+void main(args) {
+  int usr1Count = int.parse(args[0]);
+  int usr2Count = int.parse(args[1]);
+  var sub1;
+  var sub2;
+  void check() {
+    if (usr1Count < 0 || usr2Count < 0) exit(1);
+    if (usr1Count == 0 && usr2Count == 0) {
+      sub1.cancel();
+      sub2.cancel();
+    }
+    print("ready");
+  }
+  sub1 = ProcessSignal.SIGUSR1.watch().listen((signal) {
+    if (signal != ProcessSignal.SIGUSR1) exit(1);
+    usr1Count--;
+    check();
+  });
+  sub2 = ProcessSignal.SIGUSR2.watch().listen((signal) {
+    if (signal != ProcessSignal.SIGUSR2) exit(1);
+    usr2Count--;
+    check();
+  });
+  check();
+}
diff --git a/tests/standalone/io/skipping_dart2js_compilations_test.dart b/tests/standalone/io/skipping_dart2js_compilations_test.dart
index 95ae623..55ef68b 100644
--- a/tests/standalone/io/skipping_dart2js_compilations_test.dart
+++ b/tests/standalone/io/skipping_dart2js_compilations_test.dart
@@ -160,8 +160,7 @@
       false,
       bootstrapDeps,
       executable,
-      arguments,
-      'ReleaseIA32');
+      arguments, {});
 }
 
 void main() {
diff --git a/tests/standalone/io/stdin_sync_test.dart b/tests/standalone/io/stdin_sync_test.dart
index 03e794c..97c4b58 100644
--- a/tests/standalone/io/stdin_sync_test.dart
+++ b/tests/standalone/io/stdin_sync_test.dart
@@ -44,6 +44,7 @@
   test("hej", ['hej']);
 }
 
+
 void testEchoMode() {
   stdin.echoMode = true;
   Expect.isTrue(stdin.echoMode);
@@ -55,6 +56,7 @@
   }
 }
 
+
 void testLineMode() {
   stdin.lineMode = true;
   Expect.isTrue(stdin.lineMode);
@@ -70,7 +72,7 @@
 void main() {
   testReadByte();
 
-  // testEchoMode and testLineMode is an developer-interactive test, thus not
+  // testEchoMode and testLineMode is developer-interactive tests, thus not
   // enabled.
   //testEchoMode();
   //testLineMode();
diff --git a/tests/standalone/io/stdout_test.dart b/tests/standalone/io/stdout_test.dart
new file mode 100644
index 0000000..57a7e1c
--- /dev/null
+++ b/tests/standalone/io/stdout_test.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "dart:io";
+
+import "package:expect/expect.dart";
+
+void testTerminalSize() {
+  if (stdout.hasTerminal) {
+    Expect.notEquals(0, stdout.terminalColumns);
+    Expect.notEquals(0, stdout.terminalLines);
+  } else {
+    Expect.throws(() => stdout.terminalColumns, (e) => e is StdoutException);
+    Expect.throws(() => stdout.terminalLines, (e) => e is StdoutException);
+  }
+}
+
+
+void main() {
+  testTerminalSize();
+}
diff --git a/tests/standalone/io/test_runner_test.dart b/tests/standalone/io/test_runner_test.dart
index 4b2fe2a..61e762b 100644
--- a/tests/standalone/io/test_runner_test.dart
+++ b/tests/standalone/io/test_runner_test.dart
@@ -82,16 +82,16 @@
   }
 
   TestCase _makeNormalTestCase(name, expectations) {
-    var command = CommandBuilder.instance.getCommand(
+    var command = CommandBuilder.instance.getProcessCommand(
         'custom', Platform.executable, [Platform.script.toFilePath(), name],
-        'ReleaseIA32');
+        {});
     return _makeTestCase(name, DEFAULT_TIMEOUT, command, expectations);
   }
 
   _makeCrashTestCase(name, expectations) {
-    var crashCommand = CommandBuilder.instance.getCommand(
+    var crashCommand = CommandBuilder.instance.getProcessCommand(
         'custom_crash', getProcessTestFileName(), ["0", "0", "1", "1"],
-        'ReleaseIA32');
+        {});
     // The crash test sometimes times out. Run it with a large timeout
     // to help diagnose the delay.
     // The test loads a new executable, which may sometimes take a long time.
diff --git a/tests/standalone/standalone.status b/tests/standalone/standalone.status
index fcab8b1..6cc81d2 100644
--- a/tests/standalone/standalone.status
+++ b/tests/standalone/standalone.status
@@ -19,6 +19,7 @@
 io/process_invalid_arguments_test: Fail, OK
 io/directory_invalid_arguments_test: Fail, OK
 io/file_invalid_arguments_test: Fail, OK
+io/internet_address_invalid_arguments_test: Fail, OK
 io/socket_invalid_arguments_test: Fail, OK
 io/stdout_bad_argument_test: Fail, OK
 # These test have type errors on purpose and take very long to run in
@@ -31,9 +32,6 @@
 # This is expected as MacOS by default runs with a very low number
 # of allowed open files ('ulimit -n' says something like 256).
 io/socket_many_connections_test: Skip
-# The UDP tests are currently skipped on Mac OS as multicast configuration
-# needs to be resolved.
-io/raw_datagram_socket_test: Skip # Issue 1975
 
 [ $compiler == none && ($runtime == drt || $runtime == dartium) ]
 typed_array_test: Fail # Issue 13921
diff --git a/tests/standalone/vmservice/isolate_bad_class_test.dart b/tests/standalone/vmservice/isolate_bad_class_test.dart
index 8e0b2d3..1b6c0ca 100644
--- a/tests/standalone/vmservice/isolate_bad_class_test.dart
+++ b/tests/standalone/vmservice/isolate_bad_class_test.dart
@@ -22,7 +22,7 @@
       super('http://127.0.0.1:$port/isolates/$id/$collection');
 
   onRequestCompleted(Map reply) {
-    Expect.equals('error', reply['type']);
+    Expect.equals('Error', reply['type']);
   }
 }
 
diff --git a/tests/standalone/vmservice/isolate_bad_object_test.dart b/tests/standalone/vmservice/isolate_bad_object_test.dart
index b7d2ef5..314c608 100644
--- a/tests/standalone/vmservice/isolate_bad_object_test.dart
+++ b/tests/standalone/vmservice/isolate_bad_object_test.dart
@@ -22,7 +22,7 @@
       super('http://127.0.0.1:$port/isolates/$id/objects');
 
   onRequestCompleted(Map reply) {
-    Expect.equals('error', reply['type']);
+    Expect.equals('Error', reply['type']);
   }
 }
 
diff --git a/tests/standalone/vmservice/test_helper.dart b/tests/standalone/vmservice/test_helper.dart
index 94c8ab8..b584a86 100644
--- a/tests/standalone/vmservice/test_helper.dart
+++ b/tests/standalone/vmservice/test_helper.dart
@@ -9,6 +9,47 @@
 import 'dart:io';
 import 'package:expect/expect.dart';
 
+abstract class ServiceWebSocketRequestHelper {
+  final String url;
+  final Completer _completer = new Completer();
+  WebSocket _socket;
+
+  ServiceWebSocketRequestHelper(this.url);
+
+  // Returns [this] when connected.
+  Future connect() {
+    return WebSocket.connect(url).then((ws) {
+      _socket = ws;
+      _socket.listen((message) {
+        var map = JSON.decode(message);
+        var response = JSON.decode(map['response']);
+        onResponse(map['seq'], response);
+      });
+      return this;
+    });
+  }
+
+  void complete() {
+    _completer.complete(this);
+  }
+
+  Future get completed => _completer.future;
+
+  // Must call complete.
+  void onResponse(var seq, Map response);
+  void runTest();
+
+  Future sendMessage(var seq, List<String> path) {
+    var map = {
+      'seq': seq,
+      'path': path
+    };
+    var message = JSON.encode(map);
+    _socket.add(message);
+    return _completer.future;
+  }
+}
+
 abstract class VmServiceRequestHelper {
   final Uri uri;
   final HttpClient client;
@@ -99,7 +140,7 @@
       var first = true;
       process.stdout.transform(UTF8.decoder)
                     .transform(new LineSplitter()).listen((line) {
-        if (line.startsWith('VmService listening on port ')) {
+        if (line.startsWith('VMService listening on port ')) {
           RegExp portExp = new RegExp(r"\d+");
           var port = portExp.stringMatch(line);
           portNumber = int.parse(port);
diff --git a/tests/standalone/vmservice/websocket_client_test.dart b/tests/standalone/vmservice/websocket_client_test.dart
new file mode 100644
index 0000000..97f4492
--- /dev/null
+++ b/tests/standalone/vmservice/websocket_client_test.dart
@@ -0,0 +1,49 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library unknown_command_test;
+
+import 'test_helper.dart';
+import 'package:expect/expect.dart';
+
+class ClientsRequestTest extends ServiceWebSocketRequestHelper {
+  ClientsRequestTest(port) : super('ws://127.0.0.1:$port/ws');
+  int _count = 0;
+
+  onResponse(var seq, Map response) {
+    if (seq == 'cli') {
+      // Verify response is correct for 'cli' sequence id.
+      Expect.equals('ClientList', response['type']);
+      Expect.equals(1, response['members'].length);
+      _count++;
+    } else if (seq == 'iso') {
+      // Verify response is correct for 'iso' sequence id.
+      Expect.equals('IsolateList', response['type']);
+      _count++;
+    }
+    if (_count == 2) {
+      // After receiving both responses, the test is complete.
+      complete();
+    }
+  }
+
+  runTest() {
+    // Send a request for clients with 'cli' sequence id.
+    sendMessage('cli', ['clients']);
+    // Send a request for isolates with 'iso' sequence id.
+    sendMessage('iso', ['isolates']);
+  }
+}
+
+main() {
+  var process = new TestLauncher('unknown_command_script.dart');
+  process.launch().then((port) {
+    new ClientsRequestTest(port).connect().then((test) {
+      test.completed.then((_) {
+        process.requestExit();
+      });
+      test.runTest();
+    });
+  });
+}
\ No newline at end of file
diff --git a/tools/VERSION b/tools/VERSION
index 575e350..64ffd99 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 1
 MINOR 1
 PATCH 0
-PRERELEASE 4
+PRERELEASE 5
 PRERELEASE_PATCH 0
diff --git a/tools/bots/compiler.py b/tools/bots/compiler.py
index 7087a31..fd4880a 100644
--- a/tools/bots/compiler.py
+++ b/tools/bots/compiler.py
@@ -33,6 +33,8 @@
   'windows' : [
     {'runtime' : 'ie9'},
     {'runtime' : 'ie9', 'additional_flags' : ['--checked']},
+    {'runtime' : 'ff'},
+    {'runtime' : 'chrome'},
   ],
 }
 
diff --git a/tools/create_sdk.py b/tools/create_sdk.py
index 97b14a4..5261e71 100755
--- a/tools/create_sdk.py
+++ b/tools/create_sdk.py
@@ -195,7 +195,6 @@
   for library in [join('_chrome', 'dart2js'), join('_chrome', 'dartium'),
                   join('_internal', 'compiler'),
                   join('_internal', 'dartdoc'),
-                  join('_internal', 'pub', 'resource'),
                   join('_internal', 'lib'),
                   'async', 'collection', '_collection_dev', 'convert',
                   'core', 'crypto', 'io', 'isolate',
@@ -231,8 +230,10 @@
 
   # Copy in 7zip for Windows.
   if HOST_OS == 'win32':
+    RESOURCE = join(SDK_tmp, 'lib', '_internal', 'pub', 'resource')
+    os.makedirs(RESOURCE)
     copytree(join(HOME, 'third_party', '7zip'),
-             join(SDK_tmp, 'lib', '_internal', 'pub', 'resource', '7zip'),
+             join(RESOURCE, '7zip'),
              ignore=ignore_patterns('.svn'))
 
   # Copy dart2js/dartdoc/pub.
diff --git a/tools/ddbg.dart b/tools/ddbg.dart
index 7e53ab6..504d67b 100644
--- a/tools/ddbg.dart
+++ b/tools/ddbg.dart
@@ -78,11 +78,27 @@
 
 
 bool checkCurrentIsolate() {
-  if (currentIsolate != null) {
-    return true;
+  if (vmSock == null) {
+    print("There is no active script.  Try 'help run'.");
+    return false;
   }
-  print("Need valid current isolate");
-  return false;
+  if (currentIsolate == null) {
+    print('There is no current isolate.');
+    return false;
+  }
+  return true;
+}
+
+
+void setCurrentIsolate(TargetIsolate isolate) {
+  if (isolate != currentIsolate) {
+    currentIsolate = isolate;
+    if (mainIsolate == null) {
+      print("Main isolate is ${isolate.id}");
+      mainIsolate = isolate;
+    }
+    print("Current isolate is now ${isolate.id}");
+  }
 }
 
 
@@ -526,22 +542,37 @@
   var resume_commands =
       { 'r':'resume', 's':'stepOver', 'si':'stepInto', 'so':'stepOut'};
   if (resume_commands[command] != null) {
-    if (!checkPaused()) return;
+    if (!checkPaused()) {
+      cmdo.show();
+      return;
+    }
     var cmd = { "id": seqNum,
                 "command": resume_commands[command],
                 "params": { "isolateId" : currentIsolate.id } };
     sendCmd(cmd).then(showPromptAfter(handleResumedResponse));
   } else if (command == "bt") {
+    if (!checkCurrentIsolate()) {
+      cmdo.show();
+      return;
+    }
     var cmd = { "id": seqNum,
                 "command": "getStackTrace",
                 "params": { "isolateId" : currentIsolate.id } };
     sendCmd(cmd).then(showPromptAfter(handleStackTraceResponse));
   } else if (command == "ll") {
+    if (!checkCurrentIsolate()) {
+      cmdo.show();
+      return;
+    }
     var cmd = { "id": seqNum,
                 "command": "getLibraries",
                 "params": { "isolateId" : currentIsolate.id } };
     sendCmd(cmd).then(showPromptAfter(handleGetLibraryResponse));
   } else if (command == "sbp" && args.length >= 2) {
+    if (!checkCurrentIsolate()) {
+      cmdo.show();
+      return;
+    }
     var url, line;
     if (args.length == 2 && currentIsolate.pausedLocation != null) {
       url = currentIsolate.pausedLocation["url"];
@@ -558,18 +589,30 @@
                             "line": line }};
     sendCmd(cmd).then(showPromptAfter(handleSetBpResponse));
   } else if (command == "rbp" && args.length == 2) {
+    if (!checkCurrentIsolate()) {
+      cmdo.show();
+      return;
+    }
     var cmd = { "id": seqNum,
                 "command": "removeBreakpoint",
                 "params": { "isolateId" : currentIsolate.id,
                             "breakpointId": int.parse(args[1]) } };
     sendCmd(cmd).then(showPromptAfter(handleGenericResponse));
   } else if (command == "ls" && args.length == 2) {
+    if (!checkCurrentIsolate()) {
+      cmdo.show();
+      return;
+    }
     var cmd = { "id": seqNum,
                 "command": "getScriptURLs",
                 "params": { "isolateId" : currentIsolate.id,
                             "libraryId": int.parse(args[1]) } };
     sendCmd(cmd).then(showPromptAfter(handleGetScriptsResponse));
   } else if (command == "eval" && args.length > 3) {
+    if (!checkCurrentIsolate()) {
+      cmdo.show();
+      return;
+    }
     var expr = args.getRange(3, args.length).join(" ");
     var target = args[1];
     if (target == "obj") {
@@ -589,12 +632,20 @@
                             "expression": expr } };
     sendCmd(cmd).then(showPromptAfter(handleEvalResponse));
   } else if (command == "po" && args.length == 2) {
+    if (!checkCurrentIsolate()) {
+      cmdo.show();
+      return;
+    }
     var cmd = { "id": seqNum,
                 "command": "getObjectProperties",
                 "params": { "isolateId" : currentIsolate.id,
                             "objectId": int.parse(args[1]) } };
     sendCmd(cmd).then(showPromptAfter(handleGetObjPropsResponse));
   } else if (command == "pl" && args.length >= 3) {
+    if (!checkCurrentIsolate()) {
+      cmdo.show();
+      return;
+    }
     var cmd;
     if (args.length == 3) {
       cmd = { "id": seqNum,
@@ -612,18 +663,30 @@
     }
     sendCmd(cmd).then(showPromptAfter(handleGetListResponse));
   } else if (command == "pc" && args.length == 2) {
+    if (!checkCurrentIsolate()) {
+      cmdo.show();
+      return;
+    }
     var cmd = { "id": seqNum,
                 "command": "getClassProperties",
                 "params": { "isolateId" : currentIsolate.id,
                             "classId": int.parse(args[1]) } };
     sendCmd(cmd).then(showPromptAfter(handleGetClassPropsResponse));
   } else if (command == "plib" && args.length == 2) {
+    if (!checkCurrentIsolate()) {
+      cmdo.show();
+      return;
+    }
     var cmd = { "id": seqNum,
                 "command": "getLibraryProperties",
                 "params": {"isolateId" : currentIsolate.id,
                            "libraryId": int.parse(args[1]) } };
     sendCmd(cmd).then(showPromptAfter(handleGetLibraryPropsResponse));
   } else if (command == "slib" && args.length == 3) {
+    if (!checkCurrentIsolate()) {
+      cmdo.show();
+      return;
+    }
     var cmd = { "id": seqNum,
                 "command": "setLibraryProperties",
                 "params": {"isolateId" : currentIsolate.id,
@@ -631,12 +694,20 @@
                            "debuggingEnabled": args[2] } };
     sendCmd(cmd).then(showPromptAfter(handleSetLibraryPropsResponse));
   } else if (command == "pg" && args.length == 2) {
+    if (!checkCurrentIsolate()) {
+      cmdo.show();
+      return;
+    }
     var cmd = { "id": seqNum,
                 "command": "getGlobalVariables",
                 "params": { "isolateId" : currentIsolate.id,
                             "libraryId": int.parse(args[1]) } };
     sendCmd(cmd).then(showPromptAfter(handleGetGlobalVarsResponse));
   } else if (command == "gs" && args.length == 3) {
+    if (!checkCurrentIsolate()) {
+      cmdo.show();
+      return;
+    }
     var cmd = { "id": seqNum,
                 "command":  "getScriptSource",
                 "params": { "isolateId" : currentIsolate.id,
@@ -644,6 +715,10 @@
                             "url": args[2] } };
     sendCmd(cmd).then(showPromptAfter(handleGetSourceResponse));
   } else if (command == "tok" && args.length == 3) {
+    if (!checkCurrentIsolate()) {
+      cmdo.show();
+      return;
+    }
     var cmd = { "id": seqNum,
                 "command":  "getLineNumberTable",
                 "params": { "isolateId" : currentIsolate.id,
@@ -651,19 +726,26 @@
                             "url": args[2] } };
     sendCmd(cmd).then(showPromptAfter(handleGetLineTableResponse));
   } else if (command == "epi" && args.length == 2) {
+    if (!checkCurrentIsolate()) {
+      cmdo.show();
+      return;
+    }
     var cmd = { "id": seqNum,
                 "command":  "setPauseOnException",
                 "params": { "isolateId" : currentIsolate.id,
                             "exceptions": args[1] } };
     sendCmd(cmd).then(showPromptAfter(handleGenericResponse));
   } else if (command == "li") {
+    if (!checkCurrentIsolate()) {
+      cmdo.show();
+      return;
+    }
     var cmd = { "id": seqNum, "command": "getIsolateIds" };
     sendCmd(cmd).then(showPromptAfter(handleGetIsolatesResponse));
   } else if (command == "sci" && args.length == 2) {
     var id = int.parse(args[1]);
     if (targetIsolates[id] != null) {
-      currentIsolate = targetIsolates[id];
-      print("Setting current target isolate to $id");
+      setCurrentIsolate(targetIsolates[id]);
     } else {
       print("$id is not a valid isolate id");
     }
@@ -1027,6 +1109,7 @@
   assert(!isolate.isPaused);
   var location = msg["params"]["location"];;
   assert(location != null);
+  setCurrentIsolate(isolate);
   isolate.pausedLocation = location;
   if (reason == "breakpoint") {
     var bpId = (msg["params"]["breakpointId"]);
@@ -1052,11 +1135,6 @@
     print("Isolate $isolateId has been created.");
     assert(targetIsolates[isolateId] == null);
     targetIsolates[isolateId] = new TargetIsolate(isolateId);
-    if (mainIsolate == null) {
-      mainIsolate = targetIsolates[isolateId];
-      currentIsolate = mainIsolate;
-      print("Current isolate set to ${currentIsolate.id}.");
-    }
   } else {
     assert(reason == "shutdown");
     var isolate = targetIsolates.remove(isolateId);
@@ -1070,7 +1148,7 @@
     if (isolate == currentIsolate) {
       currentIsolate = mainIsolate;
       if (currentIsolate == null && !targetIsolates.isEmpty) {
-        currentIsolate = targetIsolates.first;
+        currentIsolate = targetIsolates.values.first;
       }
       if (currentIsolate != null) {
         print("Setting current isolate to ${currentIsolate.id}.");
diff --git a/tools/dom/scripts/systemnative.py b/tools/dom/scripts/systemnative.py
index 6871269..e016f3f 100644
--- a/tools/dom/scripts/systemnative.py
+++ b/tools/dom/scripts/systemnative.py
@@ -1078,8 +1078,10 @@
     cpp_callback_name = '%s%s' % (idl_name, native_suffix)
 
     self._cpp_resolver_emitter.Emit(
-        '    if (argumentCount == $ARGC && name == "$NATIVE_BINDING")\n'
-        '        return Dart$(INTERFACE_NAME)Internal::$CPP_CALLBACK_NAME;\n',
+        '    if (argumentCount == $ARGC && name == "$NATIVE_BINDING") {\n'
+        '        *autoSetupScope = true;\n'
+        '        return Dart$(INTERFACE_NAME)Internal::$CPP_CALLBACK_NAME;\n'
+        '    }\n',
         ARGC=argument_count,
         NATIVE_BINDING=native_binding,
         INTERFACE_NAME=self._interface.id,
@@ -1181,7 +1183,7 @@
         path = os.path.relpath(header_file, output_dir)
         includes_emitter.Emit('#include "$PATH"\n', PATH=path)
         body_emitter.Emit(
-            '    if (Dart_NativeFunction func = $CLASS_NAME::resolver(name, argumentCount))\n'
+            '    if (Dart_NativeFunction func = $CLASS_NAME::resolver(name, argumentCount, autoSetupScope))\n'
             '        return func;\n',
             CLASS_NAME=os.path.splitext(os.path.basename(path))[0])
 
diff --git a/tools/dom/templates/html/dartium/cpp_header.template b/tools/dom/templates/html/dartium/cpp_header.template
index d3e9582..a8a0340 100644
--- a/tools/dom/templates/html/dartium/cpp_header.template
+++ b/tools/dom/templates/html/dartium/cpp_header.template
@@ -39,7 +39,7 @@
         return returnToDart(args, value.get());
     }
 
-    static Dart_NativeFunction resolver(Dart_Handle name, int argumentCount);
+    static Dart_NativeFunction resolver(Dart_Handle name, int argumentCount, bool* autoSetupScope);
 };
 
 Dart_Handle $(WEBCORE_CLASS_NAME_ESCAPED)_toDart(PassRefPtr< $WEBCORE_CLASS_NAME > value);
diff --git a/tools/dom/templates/html/dartium/cpp_implementation.template b/tools/dom/templates/html/dartium/cpp_implementation.template
index 15eaa70..9f978790 100644
--- a/tools/dom/templates/html/dartium/cpp_implementation.template
+++ b/tools/dom/templates/html/dartium/cpp_implementation.template
@@ -19,7 +19,7 @@
 $CALLBACKS
 }
 
-Dart_NativeFunction Dart$(INTERFACE)::resolver(Dart_Handle nameHandle, int argumentCount)
+Dart_NativeFunction Dart$(INTERFACE)::resolver(Dart_Handle nameHandle, int argumentCount, bool* autoSetupScope)
 {
     String name = DartUtilities::toString(nameHandle);
 
diff --git a/tools/dom/templates/html/dartium/cpp_resolver.template b/tools/dom/templates/html/dartium/cpp_resolver.template
index 2a021c1..9b6eaf8 100644
--- a/tools/dom/templates/html/dartium/cpp_resolver.template
+++ b/tools/dom/templates/html/dartium/cpp_resolver.template
@@ -10,7 +10,7 @@
 
 namespace WebCore {
 
-Dart_NativeFunction $(LIBRARY_NAME)SnapshotResolver(Dart_Handle name, int argumentCount)
+Dart_NativeFunction $(LIBRARY_NAME)SnapshotResolver(Dart_Handle name, int argumentCount, bool* autoSetupScope)
 {
 $!RESOLVER_BODY
     return 0;
diff --git a/tools/gyp/configurations_make.gypi b/tools/gyp/configurations_make.gypi
index 73d7350..6ffc920 100644
--- a/tools/gyp/configurations_make.gypi
+++ b/tools/gyp/configurations_make.gypi
@@ -93,6 +93,9 @@
           '-O<(dart_debug_optimization_level)',
           # The sampling profiler uses the frame pointer to walk the stack.
           '-fno-omit-frame-pointer',
+          # Clang on Linux will still omit frame pointers from leaf functions
+          # unless told otherwise:
+          # '-mno-omit-leaf-frame-pointer',
         ],
       },
 
@@ -101,6 +104,9 @@
           '-O3',
           # The sampling profiler uses the frame pointer to walk the stack.
           '-fno-omit-frame-pointer',
+          # Clang on Linux will still omit frame pointers from leaf functions
+          # unless told otherwise:
+          # '-mno-omit-leaf-frame-pointer',
         ],
       },
     },
diff --git a/tools/testing/dart/co19_test.dart b/tools/testing/dart/co19_test.dart
index e793344..a55f0a7 100644
--- a/tools/testing/dart/co19_test.dart
+++ b/tools/testing/dart/co19_test.dart
@@ -19,14 +19,10 @@
 import "dart:io";
 
 import "test_options.dart";
-import "test_progress.dart";
-import "test_runner.dart";
 import "test_suite.dart";
 import "utils.dart" show Path;
 import "../../test.dart" as test_dart;
 
-import "../../../tests/co19/test_config.dart";
-
 const List<String> COMMON_ARGUMENTS =
     const <String>['--report', '--progress=diff', 'co19'];
 
diff --git a/tools/testing/dart/launch_browser.dart b/tools/testing/dart/launch_browser.dart
index 269d151..66264d9 100644
--- a/tools/testing/dart/launch_browser.dart
+++ b/tools/testing/dart/launch_browser.dart
@@ -10,7 +10,6 @@
  * DARTBIN should be the checked in stable binary.
  */
 
-import "dart:io";
 import "browser_controller.dart";
 import "utils.dart";
 
diff --git a/tools/testing/dart/record_and_replay.dart b/tools/testing/dart/record_and_replay.dart
index f60be45..5abb41c 100644
--- a/tools/testing/dart/record_and_replay.dart
+++ b/tools/testing/dart/record_and_replay.dart
@@ -55,7 +55,7 @@
     _cwd  = Directory.current.path;
   }
 
-  void nextCommand(Command command, int timeout) {
+  void nextCommand(ProcessCommand command, int timeout) {
     // Convert arguments from absolute to relative paths (relative to the dart
     // directory) because the absolute path on the machine where we record
     // may be different from the absolute path on the machine where we execute
@@ -100,7 +100,7 @@
     }
   }
 
-  CommandOutput outputOf(Command command) {
+  CommandOutput outputOf(ProcessCommand command) {
     // Convert arguments from absolute to relative paths (relative to the dart
     // directory) because the absolute path on the machine where we record
     // may be different from the absolute path on the machine where we execute
diff --git a/tools/testing/dart/test_runner.dart b/tools/testing/dart/test_runner.dart
index 38f500b..8792355 100644
--- a/tools/testing/dart/test_runner.dart
+++ b/tools/testing/dart/test_runner.dart
@@ -45,49 +45,23 @@
 
 /** A command executed as a step in a test case. */
 class Command {
-  /** Path to the executable of this command. */
-  String executable;
+  /** A descriptive name for this command. */
+  String displayName;
 
   /** The actual command line that will be executed. */
   String commandLine;
 
-  /** A descriptive name for this command. */
-  String displayName;
-
-  /** Command line arguments to the executable. */
-  List<String> arguments;
-
-  /** Environment for the command */
-  Map<String, String> environmentOverrides;
-
   /** Number of times this command *can* be retried */
   int get maxNumRetries => 2;
 
+  /** Reproduction command */
+  String get reproductionCommand => null;
+
   // We compute the Command.hashCode lazily and cache it here, since it might
   // be expensive to compute (and hashCode is called often).
   int _cachedHashCode;
 
-  Command._(this.displayName, this.executable,
-            this.arguments, String configurationDir,
-            [this.environmentOverrides = null]) {
-    if (io.Platform.operatingSystem == 'windows') {
-      // Windows can't handle the first command if it is a .bat file or the like
-      // with the slashes going the other direction.
-      // TODO(efortuna): Remove this when fixed (Issue 1306).
-      executable = executable.replaceAll('/', '\\');
-    }
-    var quotedArguments = [];
-    quotedArguments.add(escapeCommandLineArgument(executable));
-    quotedArguments.addAll(arguments.map(escapeCommandLineArgument));
-    commandLine = quotedArguments.join(' ');
-
-    if (configurationDir != null) {
-      if (environmentOverrides == null) {
-        environmentOverrides = new Map<String, String>();
-      }
-      environmentOverrides['DART_CONFIGURATION'] = configurationDir;
-    }
-  }
+  Command._(this.displayName);
 
   int get hashCode {
     if (_cachedHashCode == null) {
@@ -106,9 +80,46 @@
   }
 
   void _buildHashCode(HashCodeBuilder builder) {
-    builder.add(executable);
     builder.add(commandLine);
     builder.add(displayName);
+  }
+
+  bool _equal(Command other) {
+    return hashCode == other.hashCode &&
+        commandLine == other.commandLine &&
+        displayName == other.displayName;
+  }
+
+  String toString() => reproductionCommand;
+
+  Future<bool> get outputIsUpToDate => new Future.value(false);
+}
+
+class ProcessCommand extends Command {
+  /** Path to the executable of this command. */
+  String executable;
+
+  /** Command line arguments to the executable. */
+  List<String> arguments;
+
+  /** Environment for the command */
+  Map<String, String> environmentOverrides;
+
+  ProcessCommand._(String displayName, this.executable,
+                   this.arguments,
+                   [this.environmentOverrides = null])
+      : super._(displayName) {
+    if (io.Platform.operatingSystem == 'windows') {
+      // Windows can't handle the first command if it is a .bat file or the like
+      // with the slashes going the other direction.
+      // NOTE: Issue 1306
+      executable = executable.replaceAll('/', '\\');
+    }
+  }
+
+  void _buildHashCode(HashCodeBuilder builder) {
+    super._buildHashCode(builder);
+    builder.add(executable);
     for (var object in arguments) builder.add(object);
     if (environmentOverrides != null) {
       for (var key in environmentOverrides.keys) {
@@ -119,45 +130,34 @@
   }
 
   bool _equal(Command other) {
-    if (hashCode != other.hashCode ||
-        executable != other.executable ||
-        commandLine != other.commandLine ||
-        displayName != other.displayName ||
-        arguments.length != other.arguments.length) {
-      return false;
-    }
+    if (!super._equal(other)) return false;
+      if (other is ProcessCommand) {
 
-    if ((environmentOverrides != other.environmentOverrides) &&
-        (environmentOverrides == null || other.environmentOverrides == null)) {
-      return false;
-    }
-
-    if (environmentOverrides != null &&
-        environmentOverrides.length != other.environmentOverrides.length) {
-      return false;
-    }
-
-    for (var i = 0; i < arguments.length; i++) {
-      if (arguments[i] != other.arguments[i]) return false;
-    }
-
-    if (environmentOverrides != null) {
-      for (var key in environmentOverrides.keys) {
-        if (!other.environmentOverrides.containsKey(key) ||
-            environmentOverrides[key] != other.environmentOverrides[key]) {
-          return false;
-        }
+      if (hashCode != other.hashCode ||
+          executable != other.executable ||
+          arguments.length != other.arguments.length) {
+        return false;
       }
+
+      if (!deepJsonCompare(arguments, other.arguments)) return false;
+      if (!deepJsonCompare(environmentOverrides, other.environmentOverrides)) {
+        return false;
+      }
+
+      return true;
     }
-    return true;
+    return false;
   }
 
-  String toString() => commandLine;
+  String get reproductionCommand {
+    return ([executable]..addAll(arguments))
+        .map(escapeCommandLineArgument).join(' ');
+  }
 
   Future<bool> get outputIsUpToDate => new Future.value(false);
 }
 
-class CompilationCommand extends Command {
+class CompilationCommand extends ProcessCommand {
   String _outputFile;
   bool _neverSkipCompilation;
   List<Uri> _bootstrapDependencies;
@@ -165,11 +165,11 @@
   CompilationCommand._(String displayName,
                        this._outputFile,
                        this._neverSkipCompilation,
-                       List<String> bootstrapDependencies,
+                       List<Uri> bootstrapDependencies,
                        String executable,
                        List<String> arguments,
-                       String configurationDir)
-      : super._(displayName, executable, arguments, configurationDir) {
+                       Map<String, String> environmentOverrides)
+      : super._(displayName, executable, arguments, environmentOverrides) {
     // We sort here, so we can do a fast hashCode/operator==
     _bootstrapDependencies = new List.from(bootstrapDependencies);
     _bootstrapDependencies.sort();
@@ -240,24 +240,26 @@
   }
 }
 
-class ContentShellCommand extends Command {
+class ContentShellCommand extends ProcessCommand {
   ContentShellCommand._(String executable,
                         String htmlFile,
                         List<String> options,
                         List<String> dartFlags,
-                        String configurationDir)
+                        Map<String, String> environmentOverrides)
       : super._("content_shell",
                executable,
                _getArguments(options, htmlFile),
-               configurationDir,
-               _getEnvironment(dartFlags));
+               _getEnvironment(environmentOverrides, dartFlags));
 
-  static Map _getEnvironment(List<String> dartFlags) {
+  static Map _getEnvironment(Map<String, String> env, List<String> dartFlags) {
     var needDartFlags = dartFlags != null && dartFlags.length > 0;
 
-    var env = null;
     if (needDartFlags) {
-      env = new Map<String, String>();
+      if (env != null) {
+        env = new Map<String, String>.from(env);
+      } else {
+        env = new Map<String, String>();
+      }
       env['DART_FLAGS'] = dartFlags.join(" ");
       env['DART_FORWARDING_PRINT'] = '1';
     }
@@ -285,12 +287,8 @@
 
   BrowserTestCommand._(String _browser,
                        this.url,
-                       String executable,
-                       List<String> arguments,
-                       String configurationDir,
                        {bool this.checkedMode: false})
-      : super._(_browser, executable, arguments, configurationDir),
-        browser = _browser;
+      : super._(_browser), browser = _browser;
 
   void _buildHashCode(HashCodeBuilder builder) {
     super._buildHashCode(builder);
@@ -307,17 +305,25 @@
         url == other.url &&
         checkedMode == other.checkedMode;
   }
+
+  String get reproductionCommand {
+    var parts = [TestUtils.dartTestExecutable.toString(),
+                'tools/testing/dart/launch_browser.dart',
+                browser,
+                url];
+    return parts.map(escapeCommandLineArgument).join(' ');
+  }
 }
 
-class AnalysisCommand extends Command {
+class AnalysisCommand extends ProcessCommand {
   final String flavor;
 
   AnalysisCommand._(this.flavor,
                     String displayName,
                     String executable,
                     List<String> arguments,
-                    String configurationDir)
-      : super._(displayName, executable, arguments, configurationDir);
+                    Map<String, String> environmentOverrides)
+      : super._(displayName, executable, arguments, environmentOverrides);
 
   void _buildHashCode(HashCodeBuilder builder) {
     super._buildHashCode(builder);
@@ -332,28 +338,26 @@
   }
 }
 
-class VmCommand extends Command {
+class VmCommand extends ProcessCommand {
   VmCommand._(String executable,
               List<String> arguments,
-              String configurationDir)
-      : super._("vm", executable, arguments, configurationDir);
+              Map<String,String> environmentOverrides)
+      : super._("vm", executable, arguments, environmentOverrides);
 }
 
-class JSCommandlineCommand extends Command {
+class JSCommandlineCommand extends ProcessCommand {
   JSCommandlineCommand._(String displayName,
                          String executable,
                          List<String> arguments,
-                         String configurationDir,
                          [Map<String, String> environmentOverrides = null])
       : super._(displayName,
                 executable,
                 arguments,
-                configurationDir,
                 environmentOverrides);
 }
 
 class CommandBuilder {
-  static final instance = new CommandBuilder._();
+  static final CommandBuilder instance = new CommandBuilder._();
 
   final _cachedCommands = new Map<Command, Command>();
 
@@ -363,64 +367,60 @@
                                              String htmlFile,
                                              List<String> options,
                                              List<String> dartFlags,
-                                             String configurationDir) {
+                                             Map<String, String> environment) {
     ContentShellCommand command = new ContentShellCommand._(
-        executable, htmlFile, options, dartFlags, configurationDir);
+        executable, htmlFile, options, dartFlags, environment);
     return _getUniqueCommand(command);
   }
 
   BrowserTestCommand getBrowserTestCommand(String browser,
                                            String url,
-                                           String executable,
-                                           List<String> arguments,
-                                           String configurationDir,
                                            {bool checkedMode: false}) {
     var command = new BrowserTestCommand._(
-        browser, url, executable, arguments, configurationDir,
-        checkedMode: checkedMode);
+        browser, url, checkedMode: checkedMode);
     return _getUniqueCommand(command);
   }
 
   CompilationCommand getCompilationCommand(String displayName,
                                            outputFile,
                                            neverSkipCompilation,
-                                           List<String> bootstrapDependencies,
+                                           List<Uri> bootstrapDependencies,
                                            String executable,
                                            List<String> arguments,
-                                           String configurationDir) {
+                                           Map<String, String> environment) {
     var command =
-        new CompilationCommand._(displayName, outputFile, neverSkipCompilation,
-                                 bootstrapDependencies, executable, arguments,
-                                 configurationDir);
+        new CompilationCommand._(
+            displayName, outputFile, neverSkipCompilation,
+            bootstrapDependencies, executable, arguments, environment);
     return _getUniqueCommand(command);
   }
 
   AnalysisCommand getAnalysisCommand(
-      String displayName, executable, arguments, String configurationDir,
+      String displayName, executable, arguments, environmentOverrides,
       {String flavor: 'dartanalyzer'}) {
     var command = new AnalysisCommand._(
-        flavor, displayName, executable, arguments, configurationDir);
+        flavor, displayName, executable, arguments, environmentOverrides);
     return _getUniqueCommand(command);
   }
 
   VmCommand getVmCommand(String executable,
                          List<String> arguments,
-                         String configurationDir) {
-    var command = new VmCommand._(executable, arguments, configurationDir);
+                         Map<String, String> environmentOverrides) {
+    var command = new VmCommand._(executable, arguments, environmentOverrides);
     return _getUniqueCommand(command);
   }
 
   Command getJSCommandlineCommand(String displayName, executable, arguments,
-                     String configurationDir, [environment = null]) {
+                                  [environment = null]) {
     var command = new JSCommandlineCommand._(displayName, executable, arguments,
-                                             configurationDir, environment);
+                                             environment);
     return _getUniqueCommand(command);
   }
 
-  Command getCommand(String displayName, executable, arguments,
-                     String configurationDir, [environment = null]) {
-    var command = new Command._(displayName, executable, arguments,
-                                configurationDir, environment);
+  Command getProcessCommand(String displayName, executable, arguments,
+                     [environment = null]) {
+    var command = new ProcessCommand._(displayName, executable, arguments,
+                                       environment);
     return _getUniqueCommand(command);
   }
 
@@ -516,7 +516,10 @@
     return "$compiler-$runtime$checked ${mode}_$arch";
   }
 
-  List<String> get batchTestArguments => commands.last.arguments;
+  List<String> get batchTestArguments {
+    assert(commands.last is ProcessCommand);
+    return (commands.last as ProcessCommand).arguments;
+  }
 
   bool get isFlaky {
       if (expectedOutcomes.contains(Expectation.SKIP) ||
@@ -1367,7 +1370,7 @@
  * be garbage collected as soon as it is done.
  */
 class RunningProcess {
-  Command command;
+  ProcessCommand command;
   int timeout;
   bool timedOut = false;
   DateTime startTime;
@@ -1377,7 +1380,7 @@
   bool compilationSkipped = false;
   Completer<CommandOutput> completer;
 
-  RunningProcess(Command this.command, this.timeout);
+  RunningProcess(this.command, this.timeout);
 
   Future<CommandOutput> run() {
     completer = new Completer<CommandOutput>();
@@ -1432,7 +1435,7 @@
     completer.complete(commandOutput);
   }
 
-  CommandOutput _createCommandOutput(Command command, int exitCode) {
+  CommandOutput _createCommandOutput(ProcessCommand command, int exitCode) {
     var commandOutput = createCommandOutput(
         command,
         exitCode,
@@ -1504,7 +1507,7 @@
 
   BatchRunnerProcess();
 
-  Future<CommandOutput> runCommand(String runnerType, Command command,
+  Future<CommandOutput> runCommand(String runnerType, ProcessCommand command,
                                    int timeout, List<String> arguments) {
     assert(_completer == null);
     assert(!_currentlyRunning);
@@ -1794,10 +1797,12 @@
     });
 
     eventCondition((e) => e is dgraph.StateChangedEvent).listen((event) {
-      if (event.from == dgraph.NodeState.Processing) {
-        assert(FINISHED_STATES.contains(event.to));
-        for (var dependendNode in event.node.neededFor) {
-          _changeNodeStateIfNecessary(dependendNode);
+      if ([dgraph.NodeState.Waiting,
+           dgraph.NodeState.Processing].contains(event.from)) {
+        if (FINISHED_STATES.contains(event.to)){
+          for (var dependendNode in event.node.neededFor) {
+            _changeNodeStateIfNecessary(dependendNode);
+          }
         }
       }
     });
@@ -1806,23 +1811,25 @@
   // Called when either a new node was added or if one of it's dependencies
   // changed it's state.
   void _changeNodeStateIfNecessary(dgraph.Node node) {
-    assert(INIT_STATES.contains(node.state));
-    bool allDependenciesFinished =
-        node.dependencies.every((node) => FINISHED_STATES.contains(node.state));
+    if (INIT_STATES.contains(node.state)) {
+      bool anyDependenciesUnsuccessful = node.dependencies.any(
+          (dep) => [dgraph.NodeState.Failed,
+                    dgraph.NodeState.UnableToRun].contains(dep.state));
 
-    var newState = dgraph.NodeState.Waiting;
-    if (allDependenciesFinished) {
-      bool allDependenciesSuccessful = node.dependencies.every(
-          (dep) => dep.state == dgraph.NodeState.Successful);
-
-      if (allDependenciesSuccessful) {
-        newState = dgraph.NodeState.Enqueuing;
-      } else {
+      var newState = dgraph.NodeState.Waiting;
+      if (anyDependenciesUnsuccessful) {
         newState = dgraph.NodeState.UnableToRun;
+      } else {
+        bool allDependenciesSuccessful = node.dependencies.every(
+            (dep) => dep.state == dgraph.NodeState.Successful);
+
+        if (allDependenciesSuccessful) {
+          newState = dgraph.NodeState.Enqueuing;
+        }
       }
-    }
-    if (node.state != newState) {
-      _graph.changeState(node, newState);
+      if (node.state != newState) {
+        _graph.changeState(node, newState);
+      }
     }
   }
 }
@@ -2113,7 +2120,7 @@
   RecordingCommandExecutor(Path path)
       : _recorder = new TestCaseRecorder(path);
 
-  Future<CommandOutput> runCommand(node, Command command, int timeout) {
+  Future<CommandOutput> runCommand(node, ProcessCommand command, int timeout) {
     assert(node.dependencies.length == 0);
     assert(_cleanEnvironmentOverrides(command.environmentOverrides));
     _recorder.nextCommand(command, timeout);
@@ -2147,7 +2154,7 @@
 
   Future cleanup() => new Future.value();
 
-  Future<CommandOutput> runCommand(node, Command command, int timeout) {
+  Future<CommandOutput> runCommand(node, ProcessCommand command, int timeout) {
     assert(node.dependencies.length == 0);
     return new Future.value(_archive.outputOf(command));
   }
diff --git a/tools/testing/dart/test_suite.dart b/tools/testing/dart/test_suite.dart
index 9745387..686c6e0 100644
--- a/tools/testing/dart/test_suite.dart
+++ b/tools/testing/dart/test_suite.dart
@@ -15,7 +15,6 @@
 library test_suite;
 
 import "dart:async";
-import "dart:convert" show LineSplitter, UTF8;
 import "dart:io";
 import "drt_updater.dart";
 import "multitest.dart";
@@ -111,8 +110,10 @@
 
   TestSuite(this.configuration, this.suiteName);
 
-  String get configurationDir {
-    return TestUtils.configurationDir(configuration);
+  Map<String, String> get environmentOverrides {
+    return {
+      'DART_CONFIGURATION' : TestUtils.configurationDir(configuration),
+    };
   }
 
   /**
@@ -389,8 +390,8 @@
     var args = TestUtils.standardOptions(configuration);
     args.add(testName);
 
-    var command = CommandBuilder.instance.getCommand(
-        'run_vm_unittest', targetRunnerPath, args, configurationDir);
+    var command = CommandBuilder.instance.getProcessCommand(
+        'run_vm_unittest', targetRunnerPath, args, environmentOverrides);
     enqueueNewTestCase(
         new TestCase(constructedName, [command], configuration, expectations));
   }
@@ -739,7 +740,8 @@
 
       var command = CommandBuilder.instance.getCompilationCommand(
           compiler, "$tempDir/out.js", !useSdk,
-          dart2JsBootstrapDependencies, compilerPath, args, configurationDir);
+          dart2JsBootstrapDependencies, compilerPath, args,
+          environmentOverrides);
 
       List<Command> commands = <Command>[command];
       if (info.hasCompileError) {
@@ -747,10 +749,11 @@
         // error should be reported by the compilation command.
       } else if (configuration['runtime'] == 'd8') {
         commands.add(CommandBuilder.instance.getJSCommandlineCommand(
-            "d8", d8FileName, ['$tempDir/out.js'], configurationDir));
+            "d8", d8FileName, ['$tempDir/out.js'], environmentOverrides));
       } else if (configuration['runtime'] == 'jsshell') {
         commands.add(CommandBuilder.instance.getJSCommandlineCommand(
-            "jsshell", jsShellFileName, ['$tempDir/out.js'], configurationDir));
+            "jsshell", jsShellFileName, ['$tempDir/out.js'],
+            environmentOverrides));
       }
       return commands;
     case 'dart2dart':
@@ -764,7 +767,7 @@
           <Command>[CommandBuilder.instance.getCompilationCommand(
               compiler, "$tempDir/out.dart", !useSdk,
               dart2JsBootstrapDependencies, compilerPath, args,
-              configurationDir)];
+              environmentOverrides)];
       if (info.hasCompileError) {
         // Do not attempt to run the compiled result. A compilation
         // error should be reported by the compilation command.
@@ -774,7 +777,7 @@
         vmArguments.addAll([
             '--ignore-unrecognized-flags', '$tempDir/out.dart']);
         commands.add(CommandBuilder.instance.getVmCommand(
-            vmFileName, vmArguments, configurationDir));
+            vmFileName, vmArguments, environmentOverrides));
       } else {
         throw 'Unsupported runtime ${configuration["runtime"]} for dart2dart';
       }
@@ -785,7 +788,7 @@
       arguments.addAll(sharedOptions);
       arguments.addAll(args);
       return <Command>[CommandBuilder.instance.getVmCommand(
-          dartShellFileName, arguments, configurationDir)];
+          dartShellFileName, arguments, environmentOverrides)];
 
     case 'dartanalyzer':
     case 'dart2analyzer':
@@ -800,7 +803,8 @@
                                       List<String> arguments) {
     return CommandBuilder.instance.getAnalysisCommand(
         configuration['compiler'], dartShellFileName, arguments,
-        configurationDir, flavor: configuration['compiler']);
+        environmentOverrides,
+        flavor: configuration['compiler']);
   }
 
   CreateTest makeTestCaseCreator(Map optionsFromFile) {
@@ -827,7 +831,6 @@
     };
   }
 
-
   /**
    * _createUrlPathFromFile takes a [file], which is either located in the dart
    * or in the build directory, and will return a String representing
@@ -1073,16 +1076,10 @@
 
           commandSet.add(CommandBuilder.instance.getContentShellCommand(
               contentShellFilename, fullHtmlPath, contentShellOptions,
-              dartFlags, configurationDir));
+              dartFlags, environmentOverrides));
         } else {
-          // This command is not actually run, it is used for reproducing
-          // the failure.
-          args = ['tools/testing/dart/launch_browser.dart',
-                  runtime,
-                  fullHtmlPath];
           commandSet.add(CommandBuilder.instance.getBrowserTestCommand(
-              runtime, fullHtmlPath, TestUtils.dartTestExecutable.toString(),
-              args, configurationDir, checkedMode: configuration['checked']));
+              runtime, fullHtmlPath, checkedMode: configuration['checked']));
         }
 
         // Create BrowserTestCase and queue it.
@@ -1127,7 +1124,7 @@
     }
     return CommandBuilder.instance.getCompilationCommand(
         compiler, outputFile, !useSdk,
-        dart2JsBootstrapDependencies, compilerPath, args, configurationDir);
+        dart2JsBootstrapDependencies, compilerPath, args, environmentOverrides);
   }
 
   /** Helper to create a Polymer deploy command for a single HTML file. */
@@ -1141,8 +1138,8 @@
         ..add('--out')..add(outputDir);
     if (configuration['csp']) args.add('--csp');
 
-    return CommandBuilder.instance.getCommand(
-        'polymer_deploy', vmFileName, args, configurationDir);
+    return CommandBuilder.instance.getProcessCommand(
+        'polymer_deploy', vmFileName, args, environmentOverrides);
   }
 
   /**
@@ -1579,123 +1576,12 @@
                                       List<String> arguments) {
     return CommandBuilder.instance.getAnalysisCommand(
         configuration['compiler'], dartShellFileName, arguments,
-        configurationDir, flavor: configuration['compiler']);
+        environmentOverrides, flavor: configuration['compiler']);
   }
 
   bool get listRecursively => true;
 }
 
-class JUnitTestSuite extends TestSuite {
-  String directoryPath;
-  String statusFilePath;
-  final String dartDir;
-  String classPath;
-  List<String> testClasses;
-  VoidFunction doDone;
-  TestExpectations testExpectations;
-
-  JUnitTestSuite(Map configuration,
-                 String suiteName,
-                 String this.directoryPath,
-                 String this.statusFilePath)
-      : super(configuration, suiteName),
-        dartDir = TestUtils.dartDir().toNativePath();
-
-  bool isTestFile(String filename) => filename.endsWith("Tests.java") &&
-      !filename.contains('com/google/dart/compiler/vm') &&
-      !filename.contains('com/google/dart/corelib/SharedTests.java');
-
-  void forEachTest(TestCaseEvent onTest,
-                   Map testCacheIgnored,
-                   [VoidFunction onDone]) {
-    doTest = onTest;
-    doDone = onDone;
-
-    if (!configuration['analyzer']) {
-      // Do nothing. Asynchronously report that the suite is enqueued.
-      asynchronously(doDone);
-      return;
-    }
-    RegExp pattern = configuration['selectors']['dartc'];
-    if (!pattern.hasMatch('junit_tests')) {
-      asynchronously(doDone);
-      return;
-    }
-
-    computeClassPath();
-    testClasses = <String>[];
-    // Do not read the status file.
-    // All exclusions are hardcoded in this script, as they are in testcfg.py.
-    processDirectory();
-  }
-
-  void processDirectory() {
-    directoryPath = '$dartDir/$directoryPath';
-    Directory dir = new Directory(directoryPath);
-
-    dir.list(recursive: true).listen((FileSystemEntity fse) {
-      if (fse is File) processFile(fse.path);
-    },
-    onDone: createTest);
-  }
-
-  void processFile(String filename) {
-    if (!isTestFile(filename)) return;
-
-    int index = filename.indexOf('compiler/javatests/com/google/dart');
-    if (index != -1) {
-      String testRelativePath =
-          filename.substring(index + 'compiler/javatests/'.length,
-                             filename.length - '.java'.length);
-      String testClass = testRelativePath.replaceAll('/', '.');
-      testClasses.add(testClass);
-    }
-  }
-
-  void createTest() {
-    var sdkDir = "$buildDir/dart-sdk".trim();
-    List<String> args = <String>[
-        '-ea',
-        '-classpath', classPath,
-        '-Dcom.google.dart.sdk=$sdkDir',
-        '-Dcom.google.dart.corelib.SharedTests.test_py=$dartDir/tools/test.py',
-        'org.junit.runner.JUnitCore'];
-    args.addAll(testClasses);
-
-    // Lengthen the timeout for JUnit tests.  It is normal for them
-    // to run for a few minutes.
-    Map updatedConfiguration = new Map();
-    configuration.forEach((key, value) {
-      updatedConfiguration[key] = value;
-    });
-    updatedConfiguration['timeout'] *= 3;
-    var command = CommandBuilder.instance.getCommand(
-        'junit_test', 'java', args, configurationDir);
-    enqueueNewTestCase(
-        new TestCase(suiteName,
-                     [command],
-                     updatedConfiguration,
-                     new Set<Expectation>.from([Expectation.PASS])));
-    doDone();
-  }
-
-  void computeClassPath() {
-    classPath =
-        ['$buildDir/analyzer/util/analyzer/dart_analyzer.jar',
-         '$buildDir/analyzer/dart_analyzer_tests.jar',
-         // Third party libraries.
-         '$dartDir/third_party/args4j/2.0.12/args4j-2.0.12.jar',
-         '$dartDir/third_party/guava/r13/guava-13.0.1.jar',
-         '$dartDir/third_party/rhino/1_7R3/js.jar',
-         '$dartDir/third_party/hamcrest/v1_3/hamcrest-core-1.3.0RC2.jar',
-         '$dartDir/third_party/hamcrest/v1_3/hamcrest-generator-1.3.0RC2.jar',
-         '$dartDir/third_party/hamcrest/v1_3/hamcrest-integration-1.3.0RC2.jar',
-         '$dartDir/third_party/hamcrest/v1_3/hamcrest-library-1.3.0RC2.jar',
-         '$dartDir/third_party/junit/v4_8_2/junit.jar']
-        .join(Platform.operatingSystem == 'windows'? ';': ':');
-  }
-}
-
 class LastModifiedCache {
   Map<String, DateTime> _cache = <String, DateTime>{};
 
diff --git a/tools/testing/dart/utils.dart b/tools/testing/dart/utils.dart
index ab81b51..eacba54 100644
--- a/tools/testing/dart/utils.dart
+++ b/tools/testing/dart/utils.dart
@@ -178,7 +178,7 @@
     if (location != null && location != '') {
       return location;
     }
-    final browserLocations = const {
+    var browserLocations = {
         'firefox': const {
           'windows': 'C:\\Program Files (x86)\\Mozilla Firefox\\firefox.exe',
           'linux': 'firefox',
@@ -205,6 +205,7 @@
         'ie10': const {
           'windows': 'C:\\Program Files\\Internet Explorer\\iexplore.exe'
         }};
+    browserLocations['ff'] = browserLocations['firefox'];
 
     assert(browserLocations[browserName] != null);
     location = browserLocations[browserName][Platform.operatingSystem];
@@ -235,6 +236,36 @@
   int get value => _value;
 }
 
+bool deepJsonCompare(Object a, Object b) {
+  if (a == null || a is num || a is String) {
+    return a == b;
+  } else if (a is List) {
+    if (b is List) {
+      if (a.length != b.length) return false;
+
+      for (int i = 0; i < a.length; i++) {
+        if (!deepJsonCompare(a[i], b[i])) return false;
+      }
+      return true;
+    }
+    return false;
+  } else if (a is Map) {
+    if (b is Map) {
+      if (a.length != b.length) return false;
+
+      for (var key in a.keys) {
+        if (!b.containsKey(key)) return false;
+        if (!deepJsonCompare(a[key], b[key])) return false;
+      }
+      return true;
+    }
+    return false;
+  } else {
+    throw new Exception("Can't compare two non json-like objects "
+        "(a: ${a.runtimeType}, b: ${b.runtimeType})");
+  }
+}
+
 class UniqueObject {
   static int _nextId = 1;
   final int _hashCode;
diff --git a/tools/tracemerge.dart b/tools/tracemerge.dart
new file mode 100644
index 0000000..6c7d5dd
--- /dev/null
+++ b/tools/tracemerge.dart
@@ -0,0 +1,361 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Merge multiple isolate profiler tracing dumps into one.
+
+import 'dart:convert';
+import 'dart:io';
+
+/**
+ * Sort a list using insertion sort.
+ *
+ * Insertion sort is a simple sorting algorithm. For `n` elements it does on
+ * the order of `n * log(n)` comparisons but up to `n` squared moves. The
+ * sorting is performed in-place, without using extra memory.
+ *
+ * For short lists the many moves have less impact than the simple algorithm,
+ * and it is often the favored sorting algorithm for short lists.
+ *
+ * This insertion sort is stable: Equal elements end up in the same order
+ * as they started in.
+ */
+void insertionSort(List list,
+                   { int compare(a, b),
+                     int start: 0,
+                     int end: null }) {
+  // If the same method could have both positional and named optional
+  // parameters, this should be (list, [start, end], {compare}).
+  if (end == null) end = list.length;
+  if (compare == null) compare = Comparable.compare;
+  _insertionSort(list, compare, start, end, start + 1);
+}
+
+/**
+ * Internal helper function that assumes arguments correct.
+ *
+ * Assumes that the elements up to [sortedUntil] (not inclusive) are
+ * already sorted. The [sortedUntil] values should always be at least
+ * `start + 1`.
+ */
+void _insertionSort(List list, int compare(a, b), int start, int end,
+                    int sortedUntil) {
+  for (int pos = sortedUntil; pos < end; pos++) {
+    int min = start;
+    int max = pos;
+    var element = list[pos];
+    while (min < max) {
+      int mid = min + ((max - min) >> 1);
+      int comparison = compare(element, list[mid]);
+      if (comparison < 0) {
+        max = mid;
+      } else {
+        min = mid + 1;
+      }
+    }
+    list.setRange(min + 1, pos + 1, list, min);
+    list[min] = element;
+  }
+}
+
+/** Limit below which merge sort defaults to insertion sort. */
+const int _MERGE_SORT_LIMIT = 32;
+
+/**
+ * Sorts a list, or a range of a list, using the merge sort algorithm.
+ *
+ * Merge-sorting works by splitting the job into two parts, sorting each
+ * recursively, and then merging the two sorted parts.
+ *
+ * This takes on the order of `n * log(n)` comparisons and moves to sort
+ * `n` elements, but requires extra space of about the same size as the list
+ * being sorted.
+ *
+ * This merge sort is stable: Equal elements end up in the same order
+ * as they started in.
+ */
+void mergeSort(List list, {int start: 0, int end: null, int compare(a, b)}) {
+  if (end == null) end = list.length;
+  if (compare == null) compare = Comparable.compare;
+  int length = end - start;
+  if (length < 2) return;
+  if (length < _MERGE_SORT_LIMIT) {
+    _insertionSort(list, compare, start, end, start + 1);
+    return;
+  }
+  // Special case the first split instead of directly calling
+  // _mergeSort, because the _mergeSort requires its target to
+  // be different from its source, and it requires extra space
+  // of the same size as the list to sort.
+  // This split allows us to have only half as much extra space,
+  // and it ends up in the original place.
+  int middle = start + ((end - start) >> 1);
+  int firstLength = middle - start;
+  int secondLength = end - middle;
+  // secondLength is always the same as firstLength, or one greater.
+  List scratchSpace = new List(secondLength);
+  _mergeSort(list, compare, middle, end, scratchSpace, 0);
+  int firstTarget = end - firstLength;
+  _mergeSort(list, compare, start, middle, list, firstTarget);
+  _merge(compare,
+         list, firstTarget, end,
+         scratchSpace, 0, secondLength,
+         list, start);
+}
+
+/**
+ * Performs an insertion sort into a potentially different list than the
+ * one containing the original values.
+ *
+ * It will work in-place as well.
+ */
+void _movingInsertionSort(List list, int compare(a, b), int start, int end,
+                          List target, int targetOffset) {
+  int length = end - start;
+  if (length == 0) return;
+  target[targetOffset] = list[start];
+  for (int i = 1; i < length; i++) {
+    var element = list[start + i];
+    int min = targetOffset;
+    int max = targetOffset + i;
+    while (min < max) {
+      int mid = min + ((max - min) >> 1);
+      if (compare(element, target[mid]) < 0) {
+        max = mid;
+      } else {
+        min = mid + 1;
+      }
+    }
+    target.setRange(min + 1, targetOffset + i + 1,
+                    target, min);
+    target[min] = element;
+  }
+}
+
+/**
+ * Sorts [list] from [start] to [end] into [target] at [targetOffset].
+ *
+ * The `target` list must be able to contain the range from `start` to `end`
+ * after `targetOffset`.
+ *
+ * Allows target to be the same list as [list], as long as it's not
+ * overlapping the `start..end` range.
+ */
+void _mergeSort(List list, int compare(a, b), int start, int end,
+                List target, int targetOffset) {
+  int length = end - start;
+  if (length < _MERGE_SORT_LIMIT) {
+    _movingInsertionSort(list, compare, start, end, target, targetOffset);
+    return;
+  }
+  int middle = start + (length >> 1);
+  int firstLength = middle - start;
+  int secondLength = end - middle;
+  // Here secondLength >= firstLength (differs by at most one).
+  int targetMiddle = targetOffset + firstLength;
+  // Sort the second half into the end of the target area.
+  _mergeSort(list, compare, middle, end,
+             target, targetMiddle);
+  // Sort the first half into the end of the source area.
+  _mergeSort(list, compare, start, middle,
+             list, middle);
+  // Merge the two parts into the target area.
+  _merge(compare,
+         list, middle, middle + firstLength,
+         target, targetMiddle, targetMiddle + secondLength,
+         target, targetOffset);
+}
+
+/**
+ * Merges two lists into a target list.
+ *
+ * One of the input lists may be positioned at the end of the target
+ * list.
+ *
+ * For equal object, elements from [firstList] are always preferred.
+ * This allows the merge to be stable if the first list contains elements
+ * that started out earlier than the ones in [secondList]
+ */
+void _merge(int compare(a, b),
+            List firstList, int firstStart, int firstEnd,
+            List secondList, int secondStart, int secondEnd,
+            List target, int targetOffset) {
+  // No empty lists reaches here.
+  assert(firstStart < firstEnd);
+  assert(secondStart < secondEnd);
+  int cursor1 = firstStart;
+  int cursor2 = secondStart;
+  var firstElement = firstList[cursor1++];
+  var secondElement = secondList[cursor2++];
+  while (true) {
+    if (compare(firstElement, secondElement) <= 0) {
+      target[targetOffset++] = firstElement;
+      if (cursor1 == firstEnd) break;  // Flushing second list after loop.
+      firstElement = firstList[cursor1++];
+    } else {
+      target[targetOffset++] = secondElement;
+      if (cursor2 != secondEnd) {
+        secondElement = secondList[cursor2++];
+        continue;
+      }
+      // Second list empties first. Flushing first list here.
+      target[targetOffset++] = firstElement;
+      target.setRange(targetOffset, targetOffset + (firstEnd - cursor1),
+          firstList, cursor1);
+      return;
+    }
+  }
+  // First list empties first. Reached by break above.
+  target[targetOffset++] = secondElement;
+  target.setRange(targetOffset, targetOffset + (secondEnd - cursor2),
+      secondList, cursor2);
+}
+
+class TraceMerge {
+  Map _processes = {};
+  List _metaEvents = [];
+
+  void _processEventsFromFile(String name) {
+    var file = new File(name);
+    var events = [];
+    try {
+      var contents = file.readAsStringSync();
+      events = JSON.decode(contents);
+    } catch (e) {
+      print('Exception for $name $e');
+    }
+    _processEvents(events);
+  }
+
+  List _findOrAddProcessThread(pid, tid) {
+    var process = _processes[pid];
+    if (process == null) {
+      process = {};
+      _processes[pid] = process;
+    }
+    var thread = process[tid];
+    if (thread == null) {
+      thread = [];
+      process[tid] = thread;
+    }
+    return thread;
+  }
+
+  void _processEvents(List events) {
+    for (var i = 0; i < events.length; i++) {
+      Map event = events[i];
+      if (event['ph'] == 'M') {
+        _metaEvents.add(event);
+      } else {
+        var pid = event['pid'];
+        if (pid == null) {
+          throw "No pid in ${event}";
+        }
+        var tid = event['tid'];
+        if (tid == null) {
+          throw "No tid in ${event}";
+        }
+        var thread = _findOrAddProcessThread(pid, tid);
+        if (thread == null) {
+          throw "No thread list returned.";
+        }
+        thread.add(event);
+      }
+    }
+  }
+
+  int _compare(Map a, Map b) {
+    if (a['ts'] > b['ts']) {
+      return 1;
+    } else if (a['ts'] < b['ts']) {
+      return -1;
+    }
+    return 0;
+  }
+
+  void _sortEvents() {
+    _processes.forEach((k, Map process) {
+      process.forEach((k, List thread) {
+        mergeSort(thread, compare:_compare);
+      });
+    });
+  }
+
+  void _mergeEventsForThread(List thread) {
+    List<Map> stack = [];
+    int stackDepth = 0;
+    thread.forEach((event) {
+      if (event['ph'] == 'B') {
+        if (stackDepth == stack.length) {
+          stack.add(null);
+        }
+        stackDepth++;
+        var end_event = stack[stackDepth - 1];
+        if (end_event != null) {
+          if (end_event['name'] == event['name'] && stackDepth > 1) {
+            // Kill these events.
+            // event['dead'] = true;
+            // end_event['dead'] = true;
+          }
+        }
+      } else {
+        if (event['ph'] != 'E') {
+          throw 'Expected E event: ${event}';
+        }
+        if (stackDepth <= 0) {
+          throw 'Stack out of sync ${event}.';
+        }
+        stackDepth--;
+        stack[stackDepth] = event;
+      }
+    });
+  }
+
+  void _mergeEvents() {
+    _processes.forEach((k, Map process) {
+      process.forEach((k, List thread) {
+        _mergeEventsForThread(thread);
+      });
+    });
+  }
+
+  void writeEventsToFile(String name) {
+    var file = new File(name);
+    List final_events = _metaEvents;
+    _processes.forEach((pid, Map process) {
+      process.forEach((tid, List thread) {
+        thread.forEach((event) {
+          if (event['dead'] == null) {
+            // Not dead.
+            final_events.add(event);
+          }
+        });
+      });
+    });
+    file.writeAsStringSync(JSON.encode(final_events));
+  }
+
+  void merge(List<String> inputs) {
+    for (var i = 0; i < inputs.length; i++) {
+      _processEventsFromFile(inputs[i]);
+    }
+    _sortEvents();
+    _mergeEvents();
+  }
+}
+
+main(List<String> arguments) {
+  if (arguments.length < 2) {
+    print('${Platform.executable} ${Platform.script} <output> <inputs>');
+    return;
+  }
+  String output = arguments[0];
+  List<String> inputs = new List<String>();
+  for (var i = 1; i < arguments.length; i++) {
+    inputs.add(arguments[i]);
+  }
+  print('Merging $inputs into $output.');
+  TraceMerge tm = new TraceMerge();
+  tm.merge(inputs);
+  tm.writeEventsToFile(output);
+}
diff --git a/tools/tracesummary.dart b/tools/tracesummary.dart
new file mode 100644
index 0000000..587894c
--- /dev/null
+++ b/tools/tracesummary.dart
@@ -0,0 +1,163 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Print a summary of a profile trace.
+
+import 'dart:convert';
+import 'dart:io';
+
+class TraceSymbol {
+  final String name;
+  int exclusive = 0;
+  int inclusive = 0;
+  TraceSymbol(this.name);
+}
+
+class TraceSummary {
+  final int numSymbols;
+
+  Map<String, TraceSymbol> _symbols = {};
+  List _events = [];
+  List<TraceSymbol> _stack = [];
+  List<TraceSymbol> _topExclusive = [];
+  List<TraceSymbol> _topInclusive = [];
+  bool _marked = false;
+  int _totalSamples = 0;
+
+  TraceSummary(this.numSymbols);
+
+  void _processEventsFromFile(String name) {
+    var file = new File(name);
+    var events = [];
+    try {
+      var contents = file.readAsStringSync();
+      events = JSON.decode(contents);
+    } catch (e) {
+      print('Exception for $name $e');
+    }
+    _processEvents(events);
+  }
+
+  void _processBegin(Map event) {
+    var name = event['name'];
+    if (name == '<no frame>') {
+      return;
+    }
+    var symbol = _symbols[name];
+    if (symbol == null) {
+      symbol = new TraceSymbol(name);
+      _symbols[name] = symbol;
+    }
+    _stack.add(symbol);
+    _marked = false;
+  }
+
+  void _processEnd(Map event) {
+    var name = event['name'];
+    if (name == '<no frame>') {
+      return;
+    }
+    var symbol = _stack.last;
+    if (symbol.name != name) {
+      throw new StateError('$name not found at top of stack.');
+    }
+    if ((_stack.length > 1) && (_marked == false)) {
+      // We are transitioning from the sequence of begins to the sequence
+      // of ends. Mark the symbols on the stack.
+      _marked = true;
+      _totalSamples++;
+      // Mark all symbols except the top with an inclusive tick.
+      for (int i = 1; i < _stack.length; i++) {
+        _stack[i].inclusive++;
+      }
+      _stack.last.exclusive++;
+    }
+    _stack.removeLast();
+  }
+
+  void _processEvents(List events) {
+    for (var i = 0; i < events.length; i++) {
+      Map event = events[i];
+      if (event['ph'] == 'M') {
+        // Ignore.
+      } else if (event['ph'] == 'B') {
+        _processBegin(event);
+      } else if (event['ph'] == 'E') {
+        _processEnd(event);
+      }
+    }
+  }
+
+  void _findTopExclusive() {
+    _topExclusive = _symbols.values.toList();
+    _topExclusive.sort((a, b) {
+      return b.exclusive - a.exclusive;
+    });
+  }
+
+
+  void _findTopInclusive() {
+    _topInclusive = _symbols.values.toList();
+    _topInclusive.sort((a, b) {
+      return b.inclusive - a.inclusive;
+    });
+  }
+
+  void summarize(String input) {
+    _processEventsFromFile(input);
+    _findTopExclusive();
+    _findTopInclusive();
+    _print();
+  }
+
+  String _pad(String input, int minLength) {
+    int length = input.length;
+    for (int i = 0; i < minLength - length; i++) {
+      input = ' $input';
+    }
+    return input;
+  }
+
+  static const TICKS_LENGTH = 10;
+  static const PERCENT_LENGTH = 7;
+
+  void _printSymbol(int t, String name) {
+    String ticks = t.toString();
+    ticks = _pad(ticks, TICKS_LENGTH);
+    double total = (t / _totalSamples);
+    String percent = (total * 100.0).toStringAsFixed(2);
+    percent = _pad(percent, PERCENT_LENGTH);
+    print('$ticks  $percent  $name');
+  }
+
+  void _print() {
+    print('Top ${numSymbols} inclusive symbols');
+    print('--------------------------');
+    print('     ticks  percent  name');
+    _topInclusive.getRange(0, numSymbols).forEach((a) {
+      _printSymbol(a.inclusive, a.name);
+    });
+    print('');
+    print('Top ${numSymbols} exclusive symbols');
+    print('--------------------------');
+    print('     ticks  percent  name');
+    _topExclusive.getRange(0, numSymbols).forEach((a) {
+      _printSymbol(a.exclusive, a.name);
+    });
+  }
+}
+
+main(List<String> arguments) {
+  if (arguments.length < 1) {
+    print('${Platform.executable} ${Platform.script} <input> [symbol count]');
+    return;
+  }
+  String input = arguments[0];
+  int numSymbols = 10;
+  if (arguments.length >= 2) {
+    numSymbols = int.parse(arguments[1]);
+  }
+  TraceSummary ts = new TraceSummary(numSymbols);
+  ts.summarize(input);
+}