Version 0.5.13.0 .

svn merge -r 23342:23474 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 23501 https://dart.googlecode.com/svn/branches/bleeding_edge trunk

git-svn-id: http://dart.googlecode.com/svn/trunk@23503 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/pkg/analyzer_experimental/lib/options.dart b/pkg/analyzer_experimental/lib/options.dart
index c6fd30d..9ada7ac4 100644
--- a/pkg/analyzer_experimental/lib/options.dart
+++ b/pkg/analyzer_experimental/lib/options.dart
@@ -9,7 +9,7 @@
 import 'dart:io';
 
 
-const _BINARY_NAME = 'analyzer';
+const _BINARY_NAME = 'dartanalyzer';
 
 /**
  * Analyzer commandline configuration options.
@@ -22,6 +22,9 @@
   /** Whether to use machine format for error display */
   final bool machineFormat;
 
+  /** Whether to display version information */
+  final bool displayVersion;
+
   /** Whether to ignore unrecognized flags */
   final bool ignoreUnrecognizedFlags;
 
@@ -48,7 +51,8 @@
    */
   CommandLineOptions._fromArgs(ArgResults args)
     : shouldBatch = args['batch'],
-      machineFormat = args['machine-format'],
+      machineFormat = args['machine'],
+      displayVersion = args['version'],
       ignoreUnrecognizedFlags = args['ignore-unrecognized-flags'],
       showPackageWarnings = args['show-package-warnings'],
       showSdkWarnings = args['show-sdk-warnings'],
@@ -87,20 +91,23 @@
           defaultsTo: false, negatable: false)
       ..addOption('dart-sdk', help: 'The path to the Dart SDK')
       ..addOption('package-root', help: 'The path to the package root')
-      ..addFlag('machine-format', help: 'Specify whether errors '
-        'should be in machine format',
+      ..addFlag('machine',
+          help: 'Print errors in a format suitable for parsing',
+          defaultsTo: false, negatable: false)
+      ..addFlag('version', help: 'Print the analyzer version',
           defaultsTo: false, negatable: false)
       ..addFlag('ignore-unrecognized-flags',
           help: 'Ignore unrecognized command line flags',
           defaultsTo: false, negatable: false)
       ..addFlag('fatal-warnings', help: 'Treat non-type warnings as fatal',
           defaultsTo: false, negatable: false)
-      ..addFlag('show-package-warnings', help: 'Show warnings from package: imports',
-         defaultsTo: false, negatable: false)
+      ..addFlag('show-package-warnings',
+          help: 'Show warnings from package: imports',
+          defaultsTo: false, negatable: false)
       ..addFlag('show-sdk-warnings', help: 'Show warnings from SDK imports',
-         defaultsTo: false, negatable: false)
+          defaultsTo: false, negatable: false)
       ..addFlag('help', abbr: 'h', help: 'Display this help message',
-         defaultsTo: false, negatable: false);
+          defaultsTo: false, negatable: false);
 
     try {
       var results = parser.parse(args);
@@ -116,6 +123,9 @@
           _showUsage(parser);
           exit(15);
         }
+      } if (results['version']) {
+        print('$_BINARY_NAME version ${_getVersion()}');
+        exit(0);
       } else {
         if (results.rest.length == 0) {
           _showUsage(parser);
@@ -134,8 +144,22 @@
   static _showUsage(parser) {
     print('Usage: $_BINARY_NAME [options...] <libraries to analyze...>');
     print(parser.getUsage());
+    print('');
+    print('For more information, see http://www.dartlang.org/tools/analyzer.');
   }
 
+  static String _getVersion() {
+    try {
+      Path path = new Path(new Options().script);
+      Path versionPath = path.directoryPath.append('..').append('version');
+      File versionFile = new File.fromPath(versionPath);
+      
+      return versionFile.readAsStringSync().trim();
+    } catch (_) {
+      // This happens when the script is not running in the context of an SDK.
+      return "<unknown>";
+    }
+  }
 }
 
 /**
diff --git a/pkg/analyzer_experimental/lib/src/error_formatter.dart b/pkg/analyzer_experimental/lib/src/error_formatter.dart
index d36cab4..34d0fb4 100644
--- a/pkg/analyzer_experimental/lib/src/error_formatter.dart
+++ b/pkg/analyzer_experimental/lib/src/error_formatter.dart
@@ -124,18 +124,10 @@
       out.write('|');
       out.writeln(escapePipe(error.message));
     } else {
-      // [warning] 'foo' is not a method or function (/Users/devoncarew/temp/foo.dart:-1:-1)
-      out.write('[');
-      out.write(severity.displayName);
-      out.write('] ');
-      out.write(error.message);
-      out.write(' (');
-      out.write(source.fullName);
-      out.write(':');
-      out.write(location.lineNumber);
-      out.write(':');
-      out.write(location.columnNumber);
-      out.writeln(')');
+      // [warning] 'foo' is not a... (/Users/.../tmp/foo.dart, line 1, col 2)
+      out.write('[${severity.displayName}] ${error.message} ');
+      out.write('(${source.fullName}');
+      out.write(', line ${location.lineNumber}, col ${location.columnNumber})');
     }
   }
 
diff --git a/pkg/expect/lib/expect.dart b/pkg/expect/lib/expect.dart
index 0f83041..20d216f 100644
--- a/pkg/expect/lib/expect.dart
+++ b/pkg/expect/lib/expect.dart
@@ -17,11 +17,88 @@
  */
 class Expect {
   /**
+   * Return a slice of a string.
+   *
+   * The slice will contain at least the substring from [start] to the lower of
+   * [end] and `start + length`.
+   * If the result is no more than `length - 10` characters long,
+   * context may be added by extending the range of the slice, by decreasing
+   * [start] and increasing [end], up to at most length characters.
+   * If the start or end of the slice are not matching the start or end of
+   * the string, ellipses are added before or after the slice.
+   * Control characters may be encoded as "\xhh" codes.
+   */
+  static String _truncateString(String string, int start, int end, int length) {
+    if (end - start > length) {
+      end = start + length;
+    } else if (end - start < length) {
+      int overflow = length - (end - start);
+      if (overflow > 10) overflow = 10;
+      // Add context.
+      start = start - ((overflow + 1) ~/ 2);
+      end = end + (overflow ~/ 2);
+      if (start < 0) start = 0;
+      if (end > string.length) end = string.length;
+    }
+    if (start == 0 && end == string.length) return string;
+    StringBuffer buf = new StringBuffer();
+    if (start > 0) buf.write("...");
+    for (int i = start; i < end; i++) {
+      int code = string.codeUnitAt(i);
+      if (code < 0x20) {
+        buf.write(r"\x");
+        buf.write("0123456789abcdef"[code ~/ 16]);
+        buf.write("0123456789abcdef"[code % 16]);
+      } else {
+        buf.writeCharCode(string.codeUnitAt(i));
+      }
+    }
+    if (end < string.length) buf.write("...");
+    return buf.toString();
+  }
+
+  /**
+   * Find the difference between two strings.
+   *
+   * This finds the first point where two strings differ, and returns
+   * a text describing the difference.
+   *
+   * For small strings (length less than 20) nothing is done, and null is
+   * returned. Small strings can be compared visually, but for longer strings
+   * only a slice  containing the first difference will be shown.
+   */
+  static String _stringDifference(String expected, String actual) {
+    if (expected.length < 20 && actual.length < 20) return null;
+    for (int i = 0; i < expected.length && i < actual.length; i++) {
+      if (expected.codeUnitAt(i) != actual.codeUnitAt(i)) {
+        int start = i;
+        i++;
+        while (i < expected.length && i < actual.length) {
+          if (expected.codeUnitAt(i) == actual.codeUnitAt(i)) break;
+          i++;
+        }
+        int end = i;
+        var truncExpected = _truncateString(expected, start, end, 20);
+        var truncActual = _truncateString(actual, start, end, 20);
+        return "at index $start: Expected <$truncExpected>, "
+                                "Found: <$truncActual>";
+      }
+    }
+    return null;
+  }
+
+  /**
    * Checks whether the expected and actual values are equal (using `==`).
    */
   static void equals(var expected, var actual, [String reason = null]) {
     if (expected == actual) return;
     String msg = _getMessage(reason);
+    if (expected is String && actual is String) {
+      String stringDifference = _stringDifference(expected, actual);
+      if (stringDifference != null) {
+        _fail("Expect.equals($stringDifference$msg) fails.");
+      }
+    }
     _fail("Expect.equals(expected: <$expected>, actual: <$actual>$msg) fails.");
   }
 
diff --git a/pkg/http/lib/src/multipart_request.dart b/pkg/http/lib/src/multipart_request.dart
index 6d8f03b..051ac76 100644
--- a/pkg/http/lib/src/multipart_request.dart
+++ b/pkg/http/lib/src/multipart_request.dart
@@ -89,7 +89,7 @@
     headers['content-transfer-encoding'] = 'binary';
     super.finalize();
 
-    var controller = new StreamController<List<int>>();
+    var controller = new StreamController<List<int>>(sync: true);
 
     void writeAscii(String string) {
       assert(isPlainAscii(string));
diff --git a/pkg/http/lib/src/streamed_request.dart b/pkg/http/lib/src/streamed_request.dart
index 1b72eab..ceff1a1 100644
--- a/pkg/http/lib/src/streamed_request.dart
+++ b/pkg/http/lib/src/streamed_request.dart
@@ -32,7 +32,7 @@
   /// Creates a new streaming request.
   StreamedRequest(String method, Uri url)
     : super(method, url),
-      _controller = new StreamController<List<int>>();
+      _controller = new StreamController<List<int>>(sync: true);
 
   /// Freezes all mutable fields other than [stream] and returns a
   /// single-subscription [ByteStream] that emits the data being written to
diff --git a/pkg/http/lib/src/utils.dart b/pkg/http/lib/src/utils.dart
index 4a3b84c..7be3938 100644
--- a/pkg/http/lib/src/utils.dart
+++ b/pkg/http/lib/src/utils.dart
@@ -173,7 +173,7 @@
 /// Creates a single-subscription stream that emits the items in [iter] and then
 /// ends.
 Stream streamFromIterable(Iterable iter) {
-  var controller = new StreamController();
+  var controller = new StreamController(sync: true);
   iter.forEach(controller.add);
   controller.close();
   return controller.stream;
@@ -184,8 +184,8 @@
 /// errors from [stream]. This is useful if [stream] is single-subscription but
 /// multiple subscribers are necessary.
 Pair<Stream, Stream> tee(Stream stream) {
-  var controller1 = new StreamController();
-  var controller2 = new StreamController();
+  var controller1 = new StreamController(sync: true);
+  var controller2 = new StreamController(sync: true);
   stream.listen((value) {
     controller1.add(value);
     controller2.add(value);
diff --git a/pkg/http/test/mock_client_test.dart b/pkg/http/test/mock_client_test.dart
index 8e46ccc..f9f7769 100644
--- a/pkg/http/test/mock_client_test.dart
+++ b/pkg/http/test/mock_client_test.dart
@@ -35,7 +35,7 @@
   test('handles a streamed request', () {
     var client = new MockClient.streaming((request, bodyStream) {
       return bodyStream.bytesToString().then((bodyString) {
-        var controller = new StreamController<List<int>>();
+        var controller = new StreamController<List<int>>(sync: true);
         async.then((_) {
           controller.add('Request body was "$bodyString"'.codeUnits);
           controller.close();
diff --git a/pkg/http/test/multipart_test.dart b/pkg/http/test/multipart_test.dart
index 1be547d..78121f6 100644
--- a/pkg/http/test/multipart_test.dart
+++ b/pkg/http/test/multipart_test.dart
@@ -154,7 +154,7 @@
 
   test('with a stream file', () {
     var request = new http.MultipartRequest('POST', dummyUrl);
-    var controller = new StreamController();
+    var controller = new StreamController(sync: true);
     request.files.add(new http.MultipartFile('file', controller.stream, 5));
 
     expect(request, bodyMatches('''
@@ -172,7 +172,7 @@
 
   test('with an empty stream file', () {
     var request = new http.MultipartRequest('POST', dummyUrl);
-    var controller = new StreamController();
+    var controller = new StreamController(sync: true);
     request.files.add(new http.MultipartFile('file', controller.stream, 0));
 
     expect(request, bodyMatches('''
diff --git a/pkg/http/test/response_test.dart b/pkg/http/test/response_test.dart
index 17b2b60..5fafa37 100644
--- a/pkg/http/test/response_test.dart
+++ b/pkg/http/test/response_test.dart
@@ -44,7 +44,7 @@
 
   group('.fromStream()', () {
     test('sets body', () {
-      var controller = new StreamController();
+      var controller = new StreamController(sync: true);
       var streamResponse = new http.StreamedResponse(
           controller.stream, 200, 13);
       var future = http.Response.fromStream(streamResponse)
@@ -57,7 +57,7 @@
     });
 
     test('sets bodyBytes', () {
-      var controller = new StreamController();
+      var controller = new StreamController(sync: true);
       var streamResponse = new http.StreamedResponse(controller.stream, 200, 5);
       var future = http.Response.fromStream(streamResponse)
         .then((response) => response.bodyBytes);
diff --git a/pkg/http/test/safe_http_server.dart b/pkg/http/test/safe_http_server.dart
index c9885f1..a580770b 100644
--- a/pkg/http/test/safe_http_server.dart
+++ b/pkg/http/test/safe_http_server.dart
@@ -76,7 +76,6 @@
   int get contentLength => _inner.contentLength;
   String get method => _inner.method;
   Uri get uri => _inner.uri;
-  Map<String, String> get queryParameters => _inner.queryParameters;
   HttpHeaders get headers => _inner.headers;
   List<Cookie> get cookies => _inner.cookies;
   bool get persistentConnection => _inner.persistentConnection;
diff --git a/pkg/http/test/utils.dart b/pkg/http/test/utils.dart
index 786bb84..c2ce9c4 100644
--- a/pkg/http/test/utils.dart
+++ b/pkg/http/test/utils.dart
@@ -59,7 +59,7 @@
 
       new ByteStream(request).toBytes().then((requestBodyBytes) {
         var outputEncoding;
-        var encodingName = request.queryParameters['response-encoding'];
+        var encodingName = request.uri.queryParameters['response-encoding'];
         if (encodingName != null) {
           outputEncoding = requiredEncodingForCharset(encodingName);
         } else {
diff --git a/pkg/logging/lib/logging.dart b/pkg/logging/lib/logging.dart
index 94bf5f3..b29f076c 100644
--- a/pkg/logging/lib/logging.dart
+++ b/pkg/logging/lib/logging.dart
@@ -196,7 +196,7 @@
   Stream<LogRecord> _getStream() {
     if (hierarchicalLoggingEnabled || parent == null) {
       if (_controller == null) {
-        _controller = new StreamController<LogRecord>();
+        _controller = new StreamController<LogRecord>(sync: true);
         _stream = _controller.stream.asBroadcastStream();
       }
       return _stream;
diff --git a/pkg/oauth2/lib/oauth2.dart b/pkg/oauth2/lib/oauth2.dart
index 96bffcf..cca66ab 100644
--- a/pkg/oauth2/lib/oauth2.dart
+++ b/pkg/oauth2/lib/oauth2.dart
@@ -96,7 +96,7 @@
 ///         // Once the user is redirected to `redirectUrl`, pass the query
 ///         // parameters to the AuthorizationCodeGrant. It will validate them
 ///         // and extract the authorization code to create a new Client.
-///         return grant.handleAuthorizationResponse(request.queryParameters);
+///         return grant.handleAuthorizationResponse(request.uri.queryParameters);
 ///       })
 ///     }).then((client) {
 ///       // Once you have a Client, you can use it just like any other HTTP
diff --git a/pkg/pkg.status b/pkg/pkg.status
index 161a54b..06ccb56 100644
--- a/pkg/pkg.status
+++ b/pkg/pkg.status
@@ -143,6 +143,9 @@
 [ $compiler == none && $runtime == drt ]
 dartdoc/test/dartdoc_test: Skip # See dartbug.com/4541.
 
+[ $arch == arm ]
+*: Skip
+
 [ $arch == simarm ]
 *: Skip
 
diff --git a/pkg/scheduled_test/lib/src/mock_clock.dart b/pkg/scheduled_test/lib/src/mock_clock.dart
index 0d77e5a..ba353fa 100644
--- a/pkg/scheduled_test/lib/src/mock_clock.dart
+++ b/pkg/scheduled_test/lib/src/mock_clock.dart
@@ -45,13 +45,13 @@
   int _time = 0;
 
   /// Controller providing streams for listening.
-  StreamController<int> _multiplexController =
-      new StreamController<int>.broadcast();
+  StreamController<int> _broadcastController =
+      new StreamController<int>.broadcast(sync: true);
 
   Clock._();
 
   /// The stream of millisecond ticks of the clock.
-  Stream<int> get onTick => _multiplexController.stream;
+  Stream<int> get onTick => _broadcastController.stream;
 
   /// Advances the clock forward by [milliseconds]. This works like synchronous
   /// code that takes [milliseconds] to execute; any [Timer]s that are scheduled
@@ -61,7 +61,7 @@
     for (var i = 0; i < milliseconds; i++) {
       var tickTime = ++_time;
       runAsync(() {
-        _multiplexController.add(tickTime);
+        _broadcastController.add(tickTime);
       });
     }
   }
@@ -72,7 +72,7 @@
   /// code runs before the next tick.
   void run() {
     pumpEventQueue().then((_) {
-      if (!_multiplexController.hasListener) return;
+      if (!_broadcastController.hasListener) return;
       tick();
       return run();
     });
diff --git a/pkg/scheduled_test/lib/src/scheduled_server/safe_http_server.dart b/pkg/scheduled_test/lib/src/scheduled_server/safe_http_server.dart
index c9885f1..a580770b 100644
--- a/pkg/scheduled_test/lib/src/scheduled_server/safe_http_server.dart
+++ b/pkg/scheduled_test/lib/src/scheduled_server/safe_http_server.dart
@@ -76,7 +76,6 @@
   int get contentLength => _inner.contentLength;
   String get method => _inner.method;
   Uri get uri => _inner.uri;
-  Map<String, String> get queryParameters => _inner.queryParameters;
   HttpHeaders get headers => _inner.headers;
   List<Cookie> get cookies => _inner.cookies;
   bool get persistentConnection => _inner.persistentConnection;
diff --git a/pkg/scheduled_test/lib/src/utils.dart b/pkg/scheduled_test/lib/src/utils.dart
index 62461a6..31abe95 100644
--- a/pkg/scheduled_test/lib/src/utils.dart
+++ b/pkg/scheduled_test/lib/src/utils.dart
@@ -81,7 +81,7 @@
 /// returned by [future] once [future] completes. If [future] completes to an
 /// error, the return value will emit that error and then close.
 Stream futureStream(Future<Stream> future) {
-  var controller = new StreamController();
+  var controller = new StreamController(sync: true);
   future.then((stream) {
     stream.listen(
         controller.add,
@@ -137,7 +137,7 @@
 /// the wrapped stream. Unlike [StreamSubscription], this canceller will send a
 /// "done" message to the wrapped stream.
 Pair<Stream, StreamCanceller> streamWithCanceller(Stream stream) {
-  var controller = new StreamController();
+  var controller = new StreamController(sync: true);
   var controllerStream = stream.isBroadcast ?
       controller.stream.asBroadcastStream() :
       controller.stream;
@@ -154,8 +154,8 @@
 /// errors from [stream]. This is useful if [stream] is single-subscription but
 /// multiple subscribers are necessary.
 Pair<Stream, Stream> tee(Stream stream) {
-  var controller1 = new StreamController();
-  var controller2 = new StreamController();
+  var controller1 = new StreamController(sync: true);
+  var controller2 = new StreamController(sync: true);
   stream.listen((value) {
     controller1.add(value);
     controller2.add(value);
diff --git a/pkg/unittest/lib/test_controller.js b/pkg/unittest/lib/test_controller.js
index d8ef908..f3932d3 100644
--- a/pkg/unittest/lib/test_controller.js
+++ b/pkg/unittest/lib/test_controller.js
@@ -33,9 +33,22 @@
 
 var waitForDone = false;
 
+// Returns the driving window object if available
+function getDriverWindow() {
+  if (window != window.parent) {
+    // We're running in an iframe.
+    return window.parent;
+  } else if (window.opener) {
+    // We were opened by another window.
+    return window.opener;
+  }
+  return null;
+}
+
 function notifyStart() {
-  if (window.opener) {
-    window.opener.postMessage("STARTING", "*");
+  var driver = getDriverWindow();
+  if (driver) {
+    driver.postMessage("STARTING", "*");
   }
 }
 
@@ -43,8 +56,9 @@
   if (testRunner) testRunner.notifyDone();
   // To support in browser launching of tests we post back start and result
   // messages to the window.opener.
-  if (window.opener) {
-    window.opener.postMessage(window.document.body.innerHTML, "*");
+  var driver = getDriverWindow();
+  if (driver) {
+    driver.postMessage(window.document.body.innerHTML, "*");
   }
 }
 
diff --git a/runtime/bin/bin.gypi b/runtime/bin/bin.gypi
index 033539e..8b0db92 100644
--- a/runtime/bin/bin.gypi
+++ b/runtime/bin/bin.gypi
@@ -251,6 +251,7 @@
       'dependencies': [
         'libdart_withcore',
         'libdart_builtin',
+        'libdart_io',
       ],
       'include_dirs': [
         '..',
diff --git a/runtime/bin/builtin.dart b/runtime/bin/builtin.dart
index 808124a..bae6952 100644
--- a/runtime/bin/builtin.dart
+++ b/runtime/bin/builtin.dart
@@ -106,6 +106,9 @@
     case 'package':
       path = _filePathFromPackageUri(uri);
       break;
+    case 'http':
+      path = _filePathFromHttpUri(uri);
+      break;
     default:
       // Only handling file and package URIs in standalone binary.
       _logResolution("# Unknown scheme (${uri.scheme}) in $uri.");
@@ -162,3 +165,23 @@
   _logResolution("# Package: $path");
   return path;
 }
+
+String _filePathFromHttpUri(Uri uri) {
+  _logResolution('# Path: $uri');
+  return uri.toString();
+}
+
+String _pathFromHttpUri(String userUri) {
+  var uri = Uri.parse(userUri);
+  return uri.path;
+}
+
+String _domainFromHttpUri(String userUri) {
+  var uri = Uri.parse(userUri);
+  return uri.domain;
+}
+
+int _portFromHttpUri(String userUri) {
+  var uri = Uri.parse(userUri);
+  return uri.port == 0 ? 80 : uri.port;
+}
diff --git a/runtime/bin/builtin_natives.cc b/runtime/bin/builtin_natives.cc
index 9a6bafe..fa7a79c 100644
--- a/runtime/bin/builtin_natives.cc
+++ b/runtime/bin/builtin_natives.cc
@@ -52,7 +52,6 @@
   V(File_LinkTarget, 1)                                                        \
   V(File_Delete, 1)                                                            \
   V(File_DeleteLink, 1)                                                        \
-  V(File_Directory, 1)                                                         \
   V(File_FullPath, 1)                                                          \
   V(File_OpenStdio, 1)                                                         \
   V(File_GetStdioHandleType, 1)                                                \
diff --git a/runtime/bin/common.cc b/runtime/bin/common.cc
index 030fcfa..ce9a9ef 100644
--- a/runtime/bin/common.cc
+++ b/runtime/bin/common.cc
@@ -18,38 +18,38 @@
   // Fetch the cached builtin array types for this isolate.
   IsolateData* isolate_data =
       reinterpret_cast<IsolateData*>(Dart_CurrentIsolateData());
-  Dart_Handle object_array_class = isolate_data->object_array_class;
-  Dart_Handle growable_object_array_class =
-      isolate_data->growable_object_array_class;
-  Dart_Handle immutable_array_class = isolate_data->immutable_array_class;
 
   // If we have not cached the class pointers in the isolate data,
   // look them up and cache them now.
-  if (object_array_class == NULL) {
+  if (isolate_data->object_array_class == NULL) {
     Dart_Handle core_lib =
         Dart_LookupLibrary(Dart_NewStringFromCString("dart:core"));
     ASSERT(!Dart_IsError(core_lib));
-    object_array_class =
+
+    Dart_Handle cls =
         Dart_GetClass(core_lib, Dart_NewStringFromCString("_ObjectArray"));
-    ASSERT(!Dart_IsError(object_array_class));
-    immutable_array_class =
-        Dart_GetClass(core_lib, Dart_NewStringFromCString("_ImmutableArray"));
-    ASSERT(!Dart_IsError(immutable_array_class));
-    growable_object_array_class = Dart_GetClass(
+    ASSERT(!Dart_IsError(cls));
+    isolate_data->object_array_class = Dart_NewPersistentHandle(cls);
+    ASSERT(isolate_data->object_array_class != NULL);
+
+    cls = Dart_GetClass(core_lib, Dart_NewStringFromCString("_ImmutableArray"));
+    ASSERT(!Dart_IsError(cls));
+    isolate_data->immutable_array_class = Dart_NewPersistentHandle(cls);
+    ASSERT(isolate_data->immutable_array_class != NULL);
+
+    cls = Dart_GetClass(
         core_lib, Dart_NewStringFromCString("_GrowableObjectArray"));
-    ASSERT(!Dart_IsError(growable_object_array_class));
-    // Update the cache.
-    isolate_data->object_array_class =
-        Dart_NewPersistentHandle(object_array_class);
-    ASSERT(!Dart_IsError(isolate_data->object_array_class));
-    isolate_data->growable_object_array_class =
-        Dart_NewPersistentHandle(growable_object_array_class);
-    ASSERT(!Dart_IsError(isolate_data->growable_object_array_class));
-    isolate_data->immutable_array_class =
-        Dart_NewPersistentHandle(immutable_array_class);
-    ASSERT(!Dart_IsError(isolate_data->immutable_array_class));
+    ASSERT(!Dart_IsError(cls));
+    isolate_data->growable_object_array_class = Dart_NewPersistentHandle(cls);
+    ASSERT(isolate_data->growable_object_array_class != NULL);
   }
 
+  Dart_Handle object_array_class =
+      Dart_HandleFromPersistent(isolate_data->object_array_class);
+  Dart_Handle growable_object_array_class =
+      Dart_HandleFromPersistent(isolate_data->growable_object_array_class);
+  Dart_Handle immutable_array_class =
+      Dart_HandleFromPersistent(isolate_data->immutable_array_class);
   bool builtin_array =
       (Dart_IdentityEquals(list_class, growable_object_array_class) ||
        Dart_IdentityEquals(list_class, object_array_class) ||
diff --git a/runtime/bin/dartutils.cc b/runtime/bin/dartutils.cc
index 89a84c4..9e26305 100644
--- a/runtime/bin/dartutils.cc
+++ b/runtime/bin/dartutils.cc
@@ -14,6 +14,7 @@
 #include "bin/file.h"
 #include "bin/io_buffer.h"
 #include "bin/utils.h"
+#include "bin/socket.h"
 
 namespace dart {
 namespace bin {
@@ -26,6 +27,8 @@
 const char* DartUtils::kCoreLibURL = "dart:core";
 const char* DartUtils::kIOLibURL = "dart:io";
 const char* DartUtils::kIOLibPatchURL = "dart:io-patch";
+const char* DartUtils::kUriLibURL = "dart:uri";
+const char* DartUtils::kHttpScheme = "http:";
 
 const char* DartUtils::kIdFieldName = "_id";
 
@@ -141,6 +144,12 @@
 }
 
 
+bool DartUtils::IsHttpSchemeURL(const char* url_name) {
+  static const intptr_t kHttpSchemeLen = strlen(kHttpScheme);
+  return (strncmp(url_name, kHttpScheme, kHttpSchemeLen) == 0);
+}
+
+
 bool DartUtils::IsDartExtensionSchemeURL(const char* url_name) {
   static const intptr_t kDartExtensionSchemeLen = strlen(kDartExtensionScheme);
   // If the URL starts with "dartext:" then it is considered as a special
@@ -233,18 +242,223 @@
 }
 
 
+// Writes string into socket.
+// Return < 0 indicates an error.
+// Return >= 0 number of bytes written.
+static intptr_t SocketWriteString(intptr_t socket, const char* str,
+                                  intptr_t len) {
+    int r;
+    intptr_t cursor = 0;
+    do {
+      r = Socket::Write(socket, &str[cursor], len);
+      if (r < 0) {
+        return r;
+      }
+      cursor += r;
+      len -= r;
+    } while (len > 0);
+    ASSERT(len == 0);
+    return cursor;
+}
+
+
+static uint8_t* SocketReadUntilEOF(intptr_t socket, intptr_t* response_len) {
+  const intptr_t kInitialBufferSize = 16 * KB;
+  intptr_t buffer_size = kInitialBufferSize;
+  uint8_t* buffer = reinterpret_cast<uint8_t*>(malloc(buffer_size));
+  ASSERT(buffer != NULL);
+  intptr_t buffer_cursor = 0;
+  do {
+    int bytes_read = Socket::Read(socket, &buffer[buffer_cursor],
+                                      buffer_size - buffer_cursor - 1);
+    if (bytes_read < 0) {
+      free(buffer);
+      return NULL;
+    }
+
+    buffer_cursor += bytes_read;
+
+    if (bytes_read == 0) {
+      *response_len = buffer_cursor;
+      buffer[buffer_cursor] = '\0';
+      break;
+    }
+
+    // There is still more data to be read, check that we have room in the
+    // buffer for more data.
+    if (buffer_cursor == buffer_size - 1) {
+      // Buffer is full. Increase buffer size.
+      buffer_size *= 2;
+      buffer = reinterpret_cast<uint8_t*>(realloc(buffer, buffer_size));
+      ASSERT(buffer != NULL);
+    }
+  } while (true);
+  return buffer;
+}
+
+
+static bool HttpGetRequestOkay(const char* response) {
+  static const char* kOkayReply = "HTTP/1.0 200 OK";
+  static const intptr_t kOkayReplyLen = strlen(kOkayReply);
+  return (strncmp(response, kOkayReply, kOkayReplyLen) == 0);
+}
+
+
+static const uint8_t* HttpRequestGetPayload(const char* response) {
+  const char* split = strstr(response, "\r\n\r\n");
+  if (split != NULL) {
+    return reinterpret_cast<const uint8_t*>(split+4);
+  }
+  return NULL;
+}
+
+
+// TODO(iposva): Allocate from the zone instead of leaking error string
+// here. On the other hand the binary is about the exit anyway.
+#define SET_ERROR_MSG(error_msg, format, ...)                                  \
+  intptr_t len = snprintf(NULL, 0, format, __VA_ARGS__);                       \
+  char *msg = reinterpret_cast<char*>(malloc(len + 1));                        \
+  snprintf(msg, len + 1, format, __VA_ARGS__);                                 \
+  *error_msg = msg
+
+
+static const uint8_t* HttpGetRequest(const char* host, const char* path,
+                                     int port, intptr_t* response_len,
+                                     const char** error_msg) {
+  OSError* error = NULL;
+  SocketAddresses* addresses = Socket::LookupAddress(host, -1, &error);
+  if (addresses == NULL || addresses->count() == 0) {
+    SET_ERROR_MSG(error_msg, "Unable to resolve %s", host);
+    return NULL;
+  }
+
+  int preferred_address = 0;
+  for (int i = 0; i < addresses->count(); i++) {
+    SocketAddress* address = addresses->GetAt(i);
+    if (address->GetType() == SocketAddress::ADDRESS_LOOPBACK_IP_V4) {
+      // Prefer the IP_V4 loop back.
+      preferred_address = i;
+      break;
+    }
+  }
+
+  RawAddr addr = addresses->GetAt(preferred_address)->addr();
+  intptr_t tcp_client = Socket::Create(addr);
+  if (tcp_client < 0) {
+    SET_ERROR_MSG(error_msg, "Unable to create socket to %s:%d", host, port);
+    return NULL;
+  }
+  Socket::Connect(tcp_client, addr, port);
+  if (tcp_client < 0) {
+    SET_ERROR_MSG(error_msg, "Unable to connect to %s:%d", host, port);
+    return NULL;
+  }
+  // Send get request.
+  {
+    const char* format =
+        "GET %s HTTP/1.0\r\nUser-Agent: Dart VM\r\nHost: %s\r\n\r\n";
+    intptr_t len = snprintf(NULL, 0, format, path, host);
+    char* get_request = reinterpret_cast<char*>(malloc(len + 1));
+    snprintf(get_request, len + 1, format, path, host);
+    intptr_t r = SocketWriteString(tcp_client, get_request, len);
+    free(get_request);
+    if (r < len) {
+      SET_ERROR_MSG(error_msg, "Unable to write to %s:%d - %d", host, port,
+                    static_cast<int>(r));
+      Socket::Close(tcp_client);
+      return NULL;
+    }
+    ASSERT(r == len);
+  }
+  // Consume response.
+  uint8_t* response = SocketReadUntilEOF(tcp_client, response_len);
+  // Close socket.
+  Socket::Close(tcp_client);
+  if (response == NULL) {
+    SET_ERROR_MSG(error_msg, "Unable to read from %s:%d", host, port);
+    return NULL;
+  }
+  if (HttpGetRequestOkay(reinterpret_cast<const char*>(response)) == false) {
+    SET_ERROR_MSG(error_msg, "Invalid HTTP response from %s:%d", host, port);
+    free(response);
+    return NULL;
+  }
+  return response;
+}
+
+
+static Dart_Handle ParseHttpUri(const char* script_uri, const char** host_str,
+                                int64_t* port_int, const char** path_str) {
+  ASSERT(script_uri != NULL);
+  ASSERT(host_str != NULL);
+  ASSERT(port_int != NULL);
+  ASSERT(path_str != NULL);
+  Dart_Handle result;
+  Dart_Handle uri = DartUtils::NewString(script_uri);
+  Dart_Handle builtin_lib =
+      Builtin::LoadAndCheckLibrary(Builtin::kBuiltinLibrary);
+  Dart_Handle path = DartUtils::PathFromUri(uri, builtin_lib);
+  if (Dart_IsError(path)) {
+    return path;
+  }
+  Dart_Handle host = DartUtils::DomainFromUri(uri, builtin_lib);
+  if (Dart_IsError(host)) {
+    return host;
+  }
+  Dart_Handle port = DartUtils::PortFromUri(uri, builtin_lib);
+  if (Dart_IsError(port)) {
+    return port;
+  }
+  result = Dart_StringToCString(path, path_str);
+  if (Dart_IsError(result)) {
+    return result;
+  }
+  result = Dart_StringToCString(host, host_str);
+  if (Dart_IsError(result)) {
+    return result;
+  }
+  if (DartUtils::GetInt64Value(port, port_int) == false) {
+    return Dart_Error("Invalid port");
+  }
+  return result;
+}
+
+
+Dart_Handle DartUtils::ReadStringFromHttp(const char* script_uri) {
+  const char* host_str = NULL;
+  int64_t port_int = 0;
+  const char* path_str = NULL;
+  Dart_Handle result = ParseHttpUri(script_uri, &host_str, &port_int,
+                                    &path_str);
+  if (Dart_IsError(result)) {
+    return result;
+  }
+  const char* error_msg = NULL;
+  intptr_t len;
+  const uint8_t* text_buffer = HttpGetRequest(host_str, path_str, port_int,
+                                              &len, &error_msg);
+  if (text_buffer == NULL) {
+    return Dart_Error(error_msg);
+  }
+  const uint8_t* payload = HttpRequestGetPayload(
+      reinterpret_cast<const char*>(text_buffer));
+  if (payload == NULL) {
+    return Dart_Error("Invalid HTTP response.");
+  }
+  // Subtract HTTP response from length.
+  len -= (payload-text_buffer);
+  ASSERT(len >= 0);
+  Dart_Handle str = Dart_NewStringFromUTF8(payload, len);
+  return str;
+}
+
+
 static const uint8_t* ReadFileFully(const char* filename,
                                     intptr_t* file_len,
                                     const char** error_msg) {
   void* stream = DartUtils::OpenFile(filename, false);
   if (stream == NULL) {
-    const char* format = "Unable to open file: %s";
-    intptr_t len = snprintf(NULL, 0, format, filename);
-    // TODO(iposva): Allocate from the zone instead of leaking error string
-    // here. On the other hand the binary is about the exit anyway.
-    char* msg = reinterpret_cast<char*>(malloc(len + 1));
-    snprintf(msg, len + 1, format, filename);
-    *error_msg = msg;
+    SET_ERROR_MSG(error_msg, "Unable to open file: %s", filename);
     return NULL;
   }
   *file_len = -1;
@@ -298,6 +512,32 @@
 }
 
 
+static Dart_Handle SingleArgDart_Invoke(Dart_Handle arg, Dart_Handle lib,
+                                        const char* method) {
+  const int kNumArgs = 1;
+  Dart_Handle dart_args[kNumArgs];
+  dart_args[0] = arg;
+  return Dart_Invoke(lib, DartUtils::NewString(method), kNumArgs, dart_args);
+}
+
+Dart_Handle DartUtils::PathFromUri(Dart_Handle script_uri,
+                                   Dart_Handle builtin_lib) {
+  return SingleArgDart_Invoke(script_uri, builtin_lib, "_pathFromHttpUri");
+}
+
+
+Dart_Handle DartUtils::DomainFromUri(Dart_Handle script_uri,
+                                     Dart_Handle builtin_lib) {
+  return SingleArgDart_Invoke(script_uri, builtin_lib, "_domainFromHttpUri");
+}
+
+
+Dart_Handle DartUtils::PortFromUri(Dart_Handle script_uri,
+                                   Dart_Handle builtin_lib) {
+  return SingleArgDart_Invoke(script_uri, builtin_lib, "_portFromHttpUri");
+}
+
+
 Dart_Handle DartUtils::ResolveUri(Dart_Handle library_url,
                                   Dart_Handle url,
                                   Dart_Handle builtin_lib) {
@@ -425,8 +665,57 @@
 }
 
 
+Dart_Handle DartUtils::LoadScriptHttp(const char* script_uri,
+                                      Dart_Handle builtin_lib) {
+  Dart_Handle uri = NewString(script_uri);
+  if (Dart_IsError(uri)) {
+    return uri;
+  }
+  const char* host_str = NULL;
+  int64_t port_int = 0;
+  const char* path_str = NULL;
+  Dart_Handle result = ParseHttpUri(script_uri, &host_str, &port_int,
+                                    &path_str);
+  if (Dart_IsError(result)) {
+    return result;
+  }
+  const char* error_msg = NULL;
+  intptr_t len;
+  const uint8_t* text_buffer;
+  text_buffer = HttpGetRequest(host_str, path_str, port_int, &len,
+                               &error_msg);
+  if (text_buffer == NULL) {
+    return Dart_Error(error_msg);
+  }
+  const uint8_t* payload = HttpRequestGetPayload(
+      reinterpret_cast<const char*>(text_buffer));
+  if (payload == NULL) {
+    return Dart_Error("Invalid HTTP response.");
+  }
+  // Subtract HTTP response from length.
+  len -= (payload-text_buffer);
+  ASSERT(len >= 0);
+  // At this point we have received a valid HTTP 200 reply and
+  // payload points at the beginning of the script or snapshot.
+  bool is_snapshot = false;
+  payload = SniffForMagicNumber(payload, &len, &is_snapshot);
+  if (is_snapshot) {
+    return Dart_LoadScriptFromSnapshot(payload, len);
+  } else {
+    Dart_Handle source = Dart_NewStringFromUTF8(payload, len);
+    if (Dart_IsError(source)) {
+      return source;
+    }
+    return Dart_LoadScript(uri, source, 0, 0);
+  }
+}
+
+
 Dart_Handle DartUtils::LoadScript(const char* script_uri,
                                   Dart_Handle builtin_lib) {
+  if (DartUtils::IsHttpSchemeURL(script_uri)) {
+    return LoadScriptHttp(script_uri, builtin_lib);
+  }
   Dart_Handle resolved_script_uri;
   resolved_script_uri = ResolveScriptUri(NewString(script_uri), builtin_lib);
   if (Dart_IsError(resolved_script_uri)) {
@@ -466,6 +755,7 @@
                                   Dart_Handle url,
                                   Dart_LibraryTag tag,
                                   const char* url_string) {
+  bool is_http_scheme_url = DartUtils::IsHttpSchemeURL(url_string);
   if (url_mapping != NULL && IsDartSchemeURL(url_string)) {
     const char* mapped_url_string = MapLibraryUrl(url_mapping, url_string);
     if (mapped_url_string == NULL) {
@@ -475,12 +765,19 @@
     // URL mapping specifies and load it.
     url_string = mapped_url_string;
   }
-  // The tag is either an import or a source tag.
-  // Read the file and load it according to the specified tag.
-  Dart_Handle source = DartUtils::ReadStringFromFile(url_string);
+  Dart_Handle source;
+  if (is_http_scheme_url) {
+    // Read the file over http.
+    source = DartUtils::ReadStringFromHttp(url_string);
+  } else {
+    // Read the file.
+    source = DartUtils::ReadStringFromFile(url_string);
+  }
   if (Dart_IsError(source)) {
     return source;  // source contains the error string.
   }
+  // The tag is either an import or a source tag.
+  // Load it according to the specified tag.
   if (tag == kImportTag) {
     // Return library object or an error string.
     return Dart_LoadLibrary(url, source);
diff --git a/runtime/bin/dartutils.h b/runtime/bin/dartutils.h
index 437570d..dcc67d1 100644
--- a/runtime/bin/dartutils.h
+++ b/runtime/bin/dartutils.h
@@ -106,6 +106,7 @@
   static bool IsDartExtensionSchemeURL(const char* url_name);
   static bool IsDartIOLibURL(const char* url_name);
   static bool IsDartBuiltinLibURL(const char* url_name);
+  static bool IsHttpSchemeURL(const char* url_name);
   static Dart_Handle CanonicalizeURL(CommandLineOptions* url_mapping,
                                      Dart_Handle library,
                                      const char* url_str);
@@ -114,11 +115,14 @@
   static void WriteFile(const void* buffer, intptr_t num_bytes, void* stream);
   static void CloseFile(void* stream);
   static Dart_Handle ReadStringFromFile(const char* filename);
+  static Dart_Handle ReadStringFromHttp(const char* filename);
   static Dart_Handle LibraryTagHandler(Dart_LibraryTag tag,
                                        Dart_Handle library,
                                        Dart_Handle url);
   static Dart_Handle LoadScript(const char* script_uri,
                                 Dart_Handle builtin_lib);
+  static Dart_Handle LoadScriptHttp(const char* script_uri,
+                                    Dart_Handle builtin_lib);
   static Dart_Handle LoadSource(CommandLineOptions* url_mapping,
                                 Dart_Handle library,
                                 Dart_Handle url,
@@ -164,6 +168,15 @@
   static Dart_Handle FilePathFromUri(Dart_Handle script_uri,
                                      Dart_Handle builtin_lib);
 
+  static Dart_Handle PathFromUri(Dart_Handle script_uri,
+                                 Dart_Handle builtin_lib);
+
+  static Dart_Handle DomainFromUri(Dart_Handle script_uri,
+                                   Dart_Handle builtin_lib);
+
+  static Dart_Handle PortFromUri(Dart_Handle script_uri,
+                                 Dart_Handle builtin_lib);
+
   static Dart_Handle ResolveUri(Dart_Handle library_url,
                                 Dart_Handle url,
                                 Dart_Handle builtin_lib);
@@ -191,6 +204,7 @@
   static const char* kIOLibURL;
   static const char* kIOLibPatchURL;
   static const char* kUriLibURL;
+  static const char* kHttpScheme;
 
   static const char* kIdFieldName;
 
diff --git a/runtime/bin/file.cc b/runtime/bin/file.cc
index b885f54..67d67e3 100644
--- a/runtime/bin/file.cc
+++ b/runtime/bin/file.cc
@@ -506,25 +506,6 @@
 }
 
 
-void FUNCTION_NAME(File_Directory)(Dart_NativeArguments args) {
-  Dart_EnterScope();
-  const char* str =
-      DartUtils::GetStringValue(Dart_GetNativeArgument(args, 0));
-  char* str_copy = strdup(str);
-  char* path = File::GetContainingDirectory(str_copy);
-  free(str_copy);
-  if (path != NULL) {
-    Dart_SetReturnValue(args, DartUtils::NewString(path));
-    free(path);
-  } else {
-    Dart_Handle err = DartUtils::NewDartOSError();
-    if (Dart_IsError(err)) Dart_PropagateError(err);
-    Dart_SetReturnValue(args, err);
-  }
-  Dart_ExitScope();
-}
-
-
 void FUNCTION_NAME(File_FullPath)(Dart_NativeArguments args) {
   Dart_EnterScope();
   const char* str =
@@ -735,24 +716,6 @@
 }
 
 
-static CObject* FileDirectoryRequest(const CObjectArray& request) {
-  if (request.Length() == 2 && request[1]->IsString()) {
-    CObjectString filename(request[1]);
-    char* str_copy = strdup(filename.CString());
-    char* path = File::GetContainingDirectory(str_copy);
-    free(str_copy);
-    if (path != NULL) {
-      CObject* result = new CObjectString(CObject::NewString(path));
-      free(path);
-      return result;
-    } else {
-      return CObject::NewOSError();
-    }
-  }
-  return CObject::Null();
-}
-
-
 static CObject* FileCloseRequest(const CObjectArray& request) {
   intptr_t return_value = -1;
   if (request.Length() == 2 && request[1]->IsIntptr()) {
@@ -1198,9 +1161,6 @@
         case File::kFullPathRequest:
           response = FileFullPathRequest(request);
           break;
-        case File::kDirectoryRequest:
-          response = FileDirectoryRequest(request);
-          break;
         case File::kCloseRequest:
           response = FileCloseRequest(request);
           break;
diff --git a/runtime/bin/file.h b/runtime/bin/file.h
index cfc48c1..839c557 100644
--- a/runtime/bin/file.h
+++ b/runtime/bin/file.h
@@ -67,26 +67,25 @@
     kDeleteRequest = 2,
     kOpenRequest = 3,
     kFullPathRequest = 4,
-    kDirectoryRequest = 5,
-    kCloseRequest = 6,
-    kPositionRequest = 7,
-    kSetPositionRequest = 8,
-    kTruncateRequest = 9,
-    kLengthRequest = 10,
-    kLengthFromPathRequest = 11,
-    kLastModifiedRequest = 12,
-    kFlushRequest = 13,
-    kReadByteRequest = 14,
-    kWriteByteRequest = 15,
-    kReadRequest = 16,
-    kReadIntoRequest = 17,
-    kWriteFromRequest = 18,
-    kCreateLinkRequest = 19,
-    kDeleteLinkRequest = 20,
-    kLinkTargetRequest = 21,
-    kTypeRequest = 22,
-    kIdenticalRequest = 23,
-    kStatRequest = 24
+    kCloseRequest = 5,
+    kPositionRequest = 6,
+    kSetPositionRequest = 7,
+    kTruncateRequest = 8,
+    kLengthRequest = 9,
+    kLengthFromPathRequest = 10,
+    kLastModifiedRequest = 11,
+    kFlushRequest = 12,
+    kReadByteRequest = 13,
+    kWriteByteRequest = 14,
+    kReadRequest = 15,
+    kReadIntoRequest = 16,
+    kWriteFromRequest = 17,
+    kCreateLinkRequest = 18,
+    kDeleteLinkRequest = 19,
+    kLinkTargetRequest = 20,
+    kTypeRequest = 21,
+    kIdenticalRequest = 22,
+    kStatRequest = 23
   };
 
   enum FileStat {
@@ -159,7 +158,6 @@
   static char* LinkTarget(const char* pathname);
   static bool IsAbsolutePath(const char* path);
   static char* GetCanonicalPath(const char* path);
-  static char* GetContainingDirectory(char* path);
   static const char* PathSeparator();
   static const char* StringEscapedPathSeparator();
   static Type GetType(const char* path, bool follow_links);
diff --git a/runtime/bin/file_android.cc b/runtime/bin/file_android.cc
index b166aad..ba7ac88 100644
--- a/runtime/bin/file_android.cc
+++ b/runtime/bin/file_android.cc
@@ -281,25 +281,6 @@
 }
 
 
-char* File::GetContainingDirectory(char* pathname) {
-  // Report errors for non-regular files.
-  struct stat st;
-  if (TEMP_FAILURE_RETRY(stat(pathname, &st)) == 0) {
-    if (!S_ISREG(st.st_mode)) {
-      errno = (S_ISDIR(st.st_mode)) ? EISDIR : ENOENT;
-      return NULL;
-    }
-  } else {
-    return NULL;
-  }
-  char* path = NULL;
-  do {
-    path = dirname(pathname);
-  } while (path == NULL && errno == EINTR);
-  return GetCanonicalPath(path);
-}
-
-
 const char* File::PathSeparator() {
   return "/";
 }
diff --git a/runtime/bin/file_linux.cc b/runtime/bin/file_linux.cc
index 7c4ddda..7d974a4 100644
--- a/runtime/bin/file_linux.cc
+++ b/runtime/bin/file_linux.cc
@@ -275,25 +275,6 @@
 }
 
 
-char* File::GetContainingDirectory(char* pathname) {
-  // Report errors for non-regular files.
-  struct stat st;
-  if (TEMP_FAILURE_RETRY(stat(pathname, &st)) == 0) {
-    if (!S_ISREG(st.st_mode)) {
-      errno = (S_ISDIR(st.st_mode)) ? EISDIR : ENOENT;
-      return NULL;
-    }
-  } else {
-    return NULL;
-  }
-  char* path = NULL;
-  do {
-    path = dirname(pathname);
-  } while (path == NULL && errno == EINTR);
-  return GetCanonicalPath(path);
-}
-
-
 const char* File::PathSeparator() {
   return "/";
 }
diff --git a/runtime/bin/file_macos.cc b/runtime/bin/file_macos.cc
index c693f94..27f7177 100644
--- a/runtime/bin/file_macos.cc
+++ b/runtime/bin/file_macos.cc
@@ -283,25 +283,6 @@
 }
 
 
-char* File::GetContainingDirectory(char* pathname) {
-  // Report errors for non-regular files.
-  struct stat st;
-  if (TEMP_FAILURE_RETRY(stat(pathname, &st)) == 0) {
-    if (!S_ISREG(st.st_mode)) {
-      errno = (S_ISDIR(st.st_mode)) ? EISDIR : ENOENT;
-      return NULL;
-    }
-  } else {
-    return NULL;
-  }
-  char* path = NULL;
-  do {
-    path = dirname(pathname);
-  } while (path == NULL && errno == EINTR);
-  return GetCanonicalPath(path);
-}
-
-
 const char* File::PathSeparator() {
   return "/";
 }
diff --git a/runtime/bin/file_patch.dart b/runtime/bin/file_patch.dart
index 65ac0a4..218c729 100644
--- a/runtime/bin/file_patch.dart
+++ b/runtime/bin/file_patch.dart
@@ -14,7 +14,6 @@
   /* patch */ static _linkTarget(String path) native "File_LinkTarget";
   /* patch */ static _delete(String path) native "File_Delete";
   /* patch */ static _deleteLink(String path) native "File_DeleteLink";
-  /* patch */ static _directory(String path) native "File_Directory";
   /* 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 3162003..d0f4c82 100644
--- a/runtime/bin/file_win.cc
+++ b/runtime/bin/file_win.cc
@@ -458,39 +458,6 @@
 }
 
 
-char* File::GetContainingDirectory(char* pathname) {
-  struct _stat st;
-  wchar_t* system_name = StringUtils::Utf8ToWide(pathname);
-  int stat_status = _wstat(system_name, &st);
-  if (stat_status == 0) {
-    if ((st.st_mode & S_IFMT) != S_IFREG) {
-      SetLastError(ERROR_FILE_NOT_FOUND);
-      free(system_name);
-      return NULL;
-    }
-  } else {
-    SetLastError(ERROR_FILE_NOT_FOUND);
-    free(system_name);
-    return NULL;
-  }
-  int required_size = GetFullPathNameW(system_name, 0, NULL, NULL);
-  wchar_t* path =
-      static_cast<wchar_t*>(malloc(required_size * sizeof(wchar_t)));
-  wchar_t* file_part = NULL;
-  int written =
-    GetFullPathNameW(system_name, required_size, path, &file_part);
-  free(system_name);
-  ASSERT(written == (required_size - 1));
-  ASSERT(file_part != NULL);
-  ASSERT(file_part > path);
-  ASSERT(file_part[-1] == L'\\');
-  file_part[-1] = '\0';
-  char* result = StringUtils::WideToUtf8(path);
-  free(path);
-  return result;
-}
-
-
 const char* File::PathSeparator() {
   // This is already UTF-8 encoded.
   return "\\";
diff --git a/runtime/bin/io_buffer.cc b/runtime/bin/io_buffer.cc
index 65fe234..cbef566 100644
--- a/runtime/bin/io_buffer.cc
+++ b/runtime/bin/io_buffer.cc
@@ -10,9 +10,9 @@
 
 Dart_Handle IOBuffer::Allocate(intptr_t size, uint8_t **buffer) {
   uint8_t* data = Allocate(size);
-  Dart_Handle result = Dart_NewExternalTypedData(kUint8,
-                                                 data, size,
-                                                 data, IOBuffer::Finalizer);
+  Dart_Handle result = Dart_NewExternalTypedData(kUint8, data, size);
+  Dart_NewWeakPersistentHandle(result, data, IOBuffer::Finalizer);
+
   if (Dart_IsError(result)) {
     Free(data);
     Dart_PropagateError(result);
diff --git a/runtime/bin/io_buffer.h b/runtime/bin/io_buffer.h
index 06ce0a6..1dfcc00 100644
--- a/runtime/bin/io_buffer.h
+++ b/runtime/bin/io_buffer.h
@@ -29,10 +29,10 @@
   }
 
   // Function for finalizing external byte arrays used as IO buffers.
-  static void Finalizer(Dart_Handle handle, void* buffer) {
+  static void Finalizer(Dart_WeakPersistentHandle handle, void* buffer) {
     Free(buffer);
     if (handle != NULL) {
-      Dart_DeletePersistentHandle(handle);
+      Dart_DeleteWeakPersistentHandle(handle);
     }
   }
 
diff --git a/runtime/bin/isolate_data.h b/runtime/bin/isolate_data.h
index 9b0806e..2992a08 100644
--- a/runtime/bin/isolate_data.h
+++ b/runtime/bin/isolate_data.h
@@ -26,9 +26,9 @@
   }
 
   EventHandler* event_handler;
-  Dart_Handle object_array_class;
-  Dart_Handle growable_object_array_class;
-  Dart_Handle immutable_array_class;
+  Dart_PersistentHandle object_array_class;
+  Dart_PersistentHandle growable_object_array_class;
+  Dart_PersistentHandle immutable_array_class;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(IsolateData);
diff --git a/runtime/bin/secure_socket.cc b/runtime/bin/secure_socket.cc
index 4f7bd6b..e785620 100644
--- a/runtime/bin/secure_socket.cc
+++ b/runtime/bin/secure_socket.cc
@@ -272,10 +272,15 @@
   if (!library_initialized_) {
     InitializeLibrary(NULL, "", true, false);
   }
-  string_start_ = ThrowIfError(
-      Dart_NewPersistentHandle(DartUtils::NewString("start")));
-  string_length_ = ThrowIfError(
-      Dart_NewPersistentHandle(DartUtils::NewString("length")));
+  ASSERT(string_start_ == NULL);
+  string_start_ = Dart_NewPersistentHandle(DartUtils::NewString("start"));
+  ASSERT(string_start_ != NULL);
+  ASSERT(string_length_ == NULL);
+  string_length_ = Dart_NewPersistentHandle(DartUtils::NewString("length"));
+  ASSERT(string_length_ != NULL);
+  ASSERT(bad_certificate_callback_ == NULL);
+  bad_certificate_callback_ = Dart_NewPersistentHandle(Dart_Null());
+  ASSERT(bad_certificate_callback_ != NULL);
 
   InitializeBuffers(dart_this);
   filter_ = memio_CreateIOLayer(kMemioBufferSize);
@@ -313,29 +318,32 @@
   Dart_Handle data_identifier = DartUtils::NewString("data");
   for (int i = 0; i < kNumBuffers; ++i) {
     int size = isEncrypted(i) ? encrypted_buffer_size_ : buffer_size_;
-    dart_buffer_objects_[i] = ThrowIfError(
-        Dart_NewPersistentHandle(Dart_ListGetAt(dart_buffers_object, i)));
+    dart_buffer_objects_[i] =
+        Dart_NewPersistentHandle(Dart_ListGetAt(dart_buffers_object, i));
+    ASSERT(dart_buffer_objects_[i] != NULL);
     buffers_[i] = new uint8_t[size];
     Dart_Handle data = ThrowIfError(
-        Dart_NewExternalTypedData(kUint8, buffers_[i], size, NULL, NULL));
-    ThrowIfError(Dart_SetField(dart_buffer_objects_[i],
-                               data_identifier,
-                               data));
+        Dart_NewExternalTypedData(kUint8, buffers_[i], size));
+    ThrowIfError(
+        Dart_SetField(Dart_HandleFromPersistent(dart_buffer_objects_[i]),
+                      data_identifier,
+                      data));
   }
 }
 
 
 void SSLFilter::RegisterHandshakeCompleteCallback(Dart_Handle complete) {
   ASSERT(NULL == handshake_complete_);
-  handshake_complete_ = ThrowIfError(Dart_NewPersistentHandle(complete));
+  handshake_complete_ = Dart_NewPersistentHandle(complete);
+  ASSERT(handshake_complete_ != NULL);
 }
 
 
 void SSLFilter::RegisterBadCertificateCallback(Dart_Handle callback) {
-  if (NULL != bad_certificate_callback_) {
-    Dart_DeletePersistentHandle(bad_certificate_callback_);
-  }
-  bad_certificate_callback_ = ThrowIfError(Dart_NewPersistentHandle(callback));
+  ASSERT(bad_certificate_callback_ != NULL);
+  Dart_DeletePersistentHandle(bad_certificate_callback_);
+  bad_certificate_callback_ = Dart_NewPersistentHandle(callback);
+  ASSERT(bad_certificate_callback_ != NULL);
 }
 
 static const char* builtin_roots_module =
@@ -427,7 +435,7 @@
 SECStatus BadCertificateCallback(void* filter, PRFileDesc* fd) {
   SSLFilter* ssl_filter = static_cast<SSLFilter*>(filter);
   Dart_Handle callback = ssl_filter->bad_certificate_callback();
-  if (callback == NULL || Dart_IsNull(callback)) return SECFailure;
+  if (Dart_IsNull(callback)) return SECFailure;
 
   Dart_EnterScope();
   Dart_Handle x509_object = ssl_filter->PeerCertificate();
@@ -582,7 +590,8 @@
   SECStatus status = SSL_ForceHandshake(filter_);
   if (status == SECSuccess) {
     if (in_handshake_) {
-      ThrowIfError(Dart_InvokeClosure(handshake_complete_, 0, NULL));
+      ThrowIfError(Dart_InvokeClosure(
+          Dart_HandleFromPersistent(handshake_complete_), 0, NULL));
       in_handshake_ = false;
     }
   } else {
@@ -610,9 +619,7 @@
   Dart_DeletePersistentHandle(string_start_);
   Dart_DeletePersistentHandle(string_length_);
   Dart_DeletePersistentHandle(handshake_complete_);
-  if (bad_certificate_callback_ != NULL) {
-    Dart_DeletePersistentHandle(bad_certificate_callback_);
-  }
+  Dart_DeletePersistentHandle(bad_certificate_callback_);
   free(client_certificate_name_);
 
   PR_Close(filter_);
@@ -621,11 +628,12 @@
 
 intptr_t SSLFilter::ProcessBuffer(int buffer_index) {
   int size = isEncrypted(buffer_index) ? encrypted_buffer_size_ : buffer_size_;
-  Dart_Handle buffer_object = dart_buffer_objects_[buffer_index];
+  Dart_Handle buffer_object =
+      Dart_HandleFromPersistent(dart_buffer_objects_[buffer_index]);
   Dart_Handle start_object = ThrowIfError(
-      Dart_GetField(buffer_object, string_start_));
+      Dart_GetField(buffer_object, Dart_HandleFromPersistent(string_start_)));
   Dart_Handle length_object = ThrowIfError(
-      Dart_GetField(buffer_object, string_length_));
+      Dart_GetField(buffer_object, Dart_HandleFromPersistent(string_length_)));
   int64_t unsafe_start = DartUtils::GetIntegerValue(start_object);
   int64_t unsafe_length = DartUtils::GetIntegerValue(length_object);
   ASSERT(unsafe_start >= 0);
diff --git a/runtime/bin/secure_socket.h b/runtime/bin/secure_socket.h
index 88b4c73..0eecd3c 100644
--- a/runtime/bin/secure_socket.h
+++ b/runtime/bin/secure_socket.h
@@ -89,7 +89,9 @@
   void Handshake();
   void RegisterHandshakeCompleteCallback(Dart_Handle handshake_complete);
   void RegisterBadCertificateCallback(Dart_Handle callback);
-  Dart_Handle bad_certificate_callback() { return bad_certificate_callback_; }
+  Dart_Handle bad_certificate_callback() {
+    return Dart_HandleFromPersistent(bad_certificate_callback_);
+  }
   static void InitializeLibrary(const char* certificate_database,
                                 const char* password,
                                 bool use_builtin_root_certificates,
@@ -106,11 +108,11 @@
   uint8_t* buffers_[kNumBuffers];
   int buffer_size_;
   int encrypted_buffer_size_;
-  Dart_Handle string_start_;
-  Dart_Handle string_length_;
-  Dart_Handle dart_buffer_objects_[kNumBuffers];
-  Dart_Handle handshake_complete_;
-  Dart_Handle bad_certificate_callback_;
+  Dart_PersistentHandle string_start_;
+  Dart_PersistentHandle string_length_;
+  Dart_PersistentHandle dart_buffer_objects_[kNumBuffers];
+  Dart_PersistentHandle handshake_complete_;
+  Dart_PersistentHandle bad_certificate_callback_;
   bool in_handshake_;
   bool is_server_;
   char* client_certificate_name_;
diff --git a/runtime/bin/socket.h b/runtime/bin/socket.h
index 5c191a0..46780fc 100644
--- a/runtime/bin/socket.h
+++ b/runtime/bin/socket.h
@@ -130,6 +130,8 @@
   static intptr_t Available(intptr_t fd);
   static int Read(intptr_t fd, void* buffer, intptr_t num_bytes);
   static int Write(intptr_t fd, const void* buffer, intptr_t num_bytes);
+  static intptr_t Create(RawAddr addr);
+  static intptr_t Connect(intptr_t fd, RawAddr addr, const intptr_t port);
   static intptr_t CreateConnect(RawAddr addr,
                                 const intptr_t port);
   static intptr_t GetPort(intptr_t fd);
diff --git a/runtime/bin/socket_android.cc b/runtime/bin/socket_android.cc
index 20715a3..c0fbacd 100644
--- a/runtime/bin/socket_android.cc
+++ b/runtime/bin/socket_android.cc
@@ -42,18 +42,21 @@
 }
 
 
-intptr_t Socket::CreateConnect(RawAddr addr, const intptr_t port) {
+intptr_t Socket::Create(RawAddr addr) {
   intptr_t fd;
 
   fd = TEMP_FAILURE_RETRY(socket(addr.ss.ss_family, SOCK_STREAM, 0));
   if (fd < 0) {
-    Log::PrintErr("Error CreateConnect: %s\n", strerror(errno));
+    Log::PrintErr("Error Create: %s\n", strerror(errno));
     return -1;
   }
 
   FDUtils::SetCloseOnExec(fd);
-  Socket::SetNonBlocking(fd);
+  return fd;
+}
 
+
+intptr_t Socket::Connect(intptr_t fd, RawAddr addr, const intptr_t port) {
   SocketAddress::SetAddrPort(&addr, port);
   intptr_t result = TEMP_FAILURE_RETRY(
       connect(fd,
@@ -62,11 +65,23 @@
   if (result == 0 || errno == EINPROGRESS) {
     return fd;
   }
-  TEMP_FAILURE_RETRY(close(fd));
+  VOID_TEMP_FAILURE_RETRY(close(fd));
   return -1;
 }
 
 
+intptr_t Socket::CreateConnect(RawAddr addr, const intptr_t port) {
+  intptr_t fd = Socket::Create(addr);
+  if (fd < 0) {
+    return fd;
+  }
+
+  Socket::SetNonBlocking(fd);
+
+  return Socket::Connect(fd, addr, port);
+}
+
+
 intptr_t Socket::Available(intptr_t fd) {
   return FDUtils::AvailableBytes(fd);
 }
diff --git a/runtime/bin/socket_linux.cc b/runtime/bin/socket_linux.cc
index cfc9b12..04ecbe7 100644
--- a/runtime/bin/socket_linux.cc
+++ b/runtime/bin/socket_linux.cc
@@ -42,18 +42,21 @@
 }
 
 
-intptr_t Socket::CreateConnect(RawAddr addr, const intptr_t port) {
+intptr_t Socket::Create(RawAddr addr) {
   intptr_t fd;
 
   fd = TEMP_FAILURE_RETRY(socket(addr.ss.ss_family, SOCK_STREAM, 0));
   if (fd < 0) {
-    Log::PrintErr("Error CreateConnect: %s\n", strerror(errno));
+    Log::PrintErr("Error Create: %s\n", strerror(errno));
     return -1;
   }
 
   FDUtils::SetCloseOnExec(fd);
-  Socket::SetNonBlocking(fd);
+  return fd;
+}
 
+
+intptr_t Socket::Connect(intptr_t fd, RawAddr addr, const intptr_t port) {
   SocketAddress::SetAddrPort(&addr, port);
   intptr_t result = TEMP_FAILURE_RETRY(
       connect(fd,
@@ -62,11 +65,23 @@
   if (result == 0 || errno == EINPROGRESS) {
     return fd;
   }
-  TEMP_FAILURE_RETRY(close(fd));
+  VOID_TEMP_FAILURE_RETRY(close(fd));
   return -1;
 }
 
 
+intptr_t Socket::CreateConnect(RawAddr addr, const intptr_t port) {
+  intptr_t fd = Socket::Create(addr);
+  if (fd < 0) {
+    return fd;
+  }
+
+  Socket::SetNonBlocking(fd);
+
+  return Socket::Connect(fd, addr, port);
+}
+
+
 intptr_t Socket::Available(intptr_t fd) {
   return FDUtils::AvailableBytes(fd);
 }
diff --git a/runtime/bin/socket_macos.cc b/runtime/bin/socket_macos.cc
index 94363fb..40b92cf 100644
--- a/runtime/bin/socket_macos.cc
+++ b/runtime/bin/socket_macos.cc
@@ -42,18 +42,21 @@
 }
 
 
-intptr_t Socket::CreateConnect(RawAddr addr, const intptr_t port) {
+intptr_t Socket::Create(RawAddr addr) {
   intptr_t fd;
 
   fd = TEMP_FAILURE_RETRY(socket(addr.ss.ss_family, SOCK_STREAM, 0));
   if (fd < 0) {
-    Log::PrintErr("Error CreateConnect: %s\n", strerror(errno));
+    Log::PrintErr("Error Create: %s\n", strerror(errno));
     return -1;
   }
 
   FDUtils::SetCloseOnExec(fd);
-  Socket::SetNonBlocking(fd);
+  return fd;
+}
 
+
+intptr_t Socket::Connect(intptr_t fd, RawAddr addr, const intptr_t port) {
   SocketAddress::SetAddrPort(&addr, port);
   intptr_t result = TEMP_FAILURE_RETRY(
       connect(fd,
@@ -67,6 +70,18 @@
 }
 
 
+intptr_t Socket::CreateConnect(RawAddr addr, const intptr_t port) {
+  intptr_t fd = Socket::Create(addr);
+  if (fd < 0) {
+    return fd;
+  }
+
+  Socket::SetNonBlocking(fd);
+
+  return Socket::Connect(fd, addr, port);
+}
+
+
 intptr_t Socket::Available(intptr_t fd) {
   return FDUtils::AvailableBytes(fd);
 }
diff --git a/runtime/bin/socket_patch.dart b/runtime/bin/socket_patch.dart
index d86a17c..d603532 100644
--- a/runtime/bin/socket_patch.dart
+++ b/runtime/bin/socket_patch.dart
@@ -558,7 +558,7 @@
   }
 
   _RawServerSocket(this._socket) {
-    _controller = new StreamController(
+    _controller = new StreamController(sync: true,
         onListen: _onSubscriptionStateChange,
         onCancel: _onSubscriptionStateChange,
         onPause: _onPauseStateChange,
@@ -630,7 +630,7 @@
   }
 
   _RawSocket(this._socket) {
-    _controller = new StreamController(
+    _controller = new StreamController(sync: true,
         onListen: _onSubscriptionStateChange,
         onCancel: _onSubscriptionStateChange,
         onPause: _onPauseStateChange,
@@ -886,7 +886,7 @@
   var _detachReady;
 
   _Socket(RawSocket this._raw) {
-    _controller = new StreamController<List<int>>(
+    _controller = new StreamController<List<int>>(sync: true,
         onListen: _onSubscriptionStateChange,
         onCancel: _onSubscriptionStateChange,
         onPause: _onPauseStateChange,
diff --git a/runtime/bin/socket_win.cc b/runtime/bin/socket_win.cc
index 60a6163..ec54765 100644
--- a/runtime/bin/socket_win.cc
+++ b/runtime/bin/socket_win.cc
@@ -113,7 +113,8 @@
   return true;
 }
 
-intptr_t Socket::CreateConnect(RawAddr addr, const intptr_t port) {
+
+intptr_t Socket::Create(RawAddr addr) {
   SOCKET s = socket(addr.ss.ss_family, SOCK_STREAM, 0);
   if (s == INVALID_SOCKET) {
     return -1;
@@ -131,20 +132,35 @@
     FATAL("Failed setting SO_LINGER on socket");
   }
 
+  ClientSocket* client_socket = new ClientSocket(s);
+  return reinterpret_cast<intptr_t>(client_socket);
+}
+
+
+intptr_t Socket::Connect(intptr_t fd, RawAddr addr, const intptr_t port) {
+  ASSERT(reinterpret_cast<Handle*>(fd)->is_socket());
+  SocketHandle* handle = reinterpret_cast<SocketHandle*>(fd);
+  SOCKET s = handle->socket();
   SocketAddress::SetAddrPort(&addr, port);
-  status = connect(
-      s,
-      &addr.addr,
-      SocketAddress::GetAddrLength(addr));
+  int status = connect(s, &addr.addr, SocketAddress::GetAddrLength(addr));
   if (status == SOCKET_ERROR) {
     DWORD rc = WSAGetLastError();
-    closesocket(s);
+    ClientSocket* client_socket = reinterpret_cast<ClientSocket*>(fd);
+    client_socket->Close();
     SetLastError(rc);
     return -1;
   }
+  return fd;
+}
 
-  ClientSocket* client_socket = new ClientSocket(s);
-  return reinterpret_cast<intptr_t>(client_socket);
+
+intptr_t Socket::CreateConnect(RawAddr addr, const intptr_t port) {
+  intptr_t fd = Socket::Create(addr);
+  if (fd < 0) {
+    return fd;
+  }
+
+  return Socket::Connect(fd, addr, port);
 }
 
 
diff --git a/runtime/include/dart_api.h b/runtime/include/dart_api.h
index bbaed07..abb5a6c 100755
--- a/runtime/include/dart_api.h
+++ b/runtime/include/dart_api.h
@@ -176,9 +176,12 @@
  * deallocated (see Dart_DeletePersistentHandle).
  */
 typedef struct _Dart_Handle* Dart_Handle;
+typedef struct _Dart_PersistentHandle* Dart_PersistentHandle;
+typedef struct _Dart_WeakPersistentHandle* Dart_WeakPersistentHandle;
 
-typedef void (*Dart_WeakPersistentHandleFinalizer)(Dart_Handle handle,
-                                                   void* peer);
+typedef void (*Dart_WeakPersistentHandleFinalizer)(
+    Dart_WeakPersistentHandle handle,
+    void* peer);
 typedef void (*Dart_PeerFinalizer)(void* peer);
 
 /**
@@ -361,6 +364,17 @@
 DART_EXPORT bool Dart_IdentityEquals(Dart_Handle obj1, Dart_Handle obj2);
 
 /**
+ * Allocates a handle in the current scope from a persistent handle.
+ */
+DART_EXPORT Dart_Handle Dart_HandleFromPersistent(Dart_PersistentHandle object);
+
+/**
+ * Allocates a handle in the current scope from a weak persistent handle.
+ */
+DART_EXPORT Dart_Handle Dart_HandleFromWeakPersistent(
+    Dart_WeakPersistentHandle object);
+
+/**
  * Allocates a persistent handle for an object.
  *
  * This handle has the lifetime of the current isolate unless it is
@@ -368,14 +382,14 @@
  *
  * Requires there to be a current isolate.
  */
-DART_EXPORT Dart_Handle Dart_NewPersistentHandle(Dart_Handle object);
+DART_EXPORT Dart_PersistentHandle Dart_NewPersistentHandle(Dart_Handle object);
 
 /**
  * Deallocates a persistent handle.
  *
  * Requires there to be a current isolate.
  */
-DART_EXPORT void Dart_DeletePersistentHandle(Dart_Handle object);
+DART_EXPORT void Dart_DeletePersistentHandle(Dart_PersistentHandle object);
 
 /**
  * Allocates a weak persistent handle for an object.
@@ -394,17 +408,13 @@
  * \return Success if the weak persistent handle was
  *   created. Otherwise, returns an error.
  */
-DART_EXPORT Dart_Handle Dart_NewWeakPersistentHandle(
+DART_EXPORT Dart_WeakPersistentHandle Dart_NewWeakPersistentHandle(
     Dart_Handle object,
     void* peer,
     Dart_WeakPersistentHandleFinalizer callback);
 
-/**
- * Is this object a weak persistent handle?
- *
- * Requires there to be a current isolate.
- */
-DART_EXPORT bool Dart_IsWeakPersistentHandle(Dart_Handle object);
+DART_EXPORT void Dart_DeleteWeakPersistentHandle(
+    Dart_WeakPersistentHandle object);
 
 /**
  * Allocates a prologue weak persistent handle for an object.
@@ -432,7 +442,7 @@
  * \return Success if the prologue weak persistent handle was created.
  *   Otherwise, returns an error.
  */
-DART_EXPORT Dart_Handle Dart_NewPrologueWeakPersistentHandle(
+DART_EXPORT Dart_WeakPersistentHandle Dart_NewPrologueWeakPersistentHandle(
     Dart_Handle object,
     void* peer,
     Dart_WeakPersistentHandleFinalizer callback);
@@ -442,7 +452,8 @@
  *
  * Requires there to be a current isolate.
  */
-DART_EXPORT bool Dart_IsPrologueWeakPersistentHandle(Dart_Handle object);
+DART_EXPORT bool Dart_IsPrologueWeakPersistentHandle(
+    Dart_WeakPersistentHandle object);
 
 /**
  * Constructs a set of weak references from the Cartesian product of
@@ -459,10 +470,11 @@
  * \return Success if the weak reference set could be created.
  *   Otherwise, returns an error handle.
  */
-DART_EXPORT Dart_Handle Dart_NewWeakReferenceSet(Dart_Handle* keys,
-                                                 intptr_t num_keys,
-                                                 Dart_Handle* values,
-                                                 intptr_t num_values);
+DART_EXPORT Dart_Handle Dart_NewWeakReferenceSet(
+    Dart_WeakPersistentHandle* keys,
+    intptr_t num_keys,
+    Dart_WeakPersistentHandle* values,
+    intptr_t num_values);
 
 // --- Garbage Collection Callbacks ---
 
@@ -1766,18 +1778,9 @@
  *   WeakPersistentHandle which needs to be deleted in the specified callback
  *   using Dart_DeletePersistentHandle.
  */
-DART_EXPORT Dart_Handle Dart_NewExternalTypedData(
-    Dart_TypedData_Type type,
-    void* data,
-    intptr_t length,
-    void* peer,
-    Dart_WeakPersistentHandleFinalizer callback);
-
-/**
- * Retrieves the peer pointer associated with an external TypedData object.
- */
-DART_EXPORT Dart_Handle Dart_ExternalTypedDataGetPeer(Dart_Handle object,
-                                                      void** peer);
+DART_EXPORT Dart_Handle Dart_NewExternalTypedData(Dart_TypedData_Type type,
+                                                  void* data,
+                                                  intptr_t length);
 
 /**
  * Acquires access to the internal data address of a TypedData object.
diff --git a/runtime/lib/mirrors.cc b/runtime/lib/mirrors.cc
index 62c22e0..790f6f6 100644
--- a/runtime/lib/mirrors.cc
+++ b/runtime/lib/mirrors.cc
@@ -88,10 +88,11 @@
 }
 
 
-static void FreeVMReference(Dart_Handle weak_ref, void* data) {
-  Dart_Handle perm_handle = reinterpret_cast<Dart_Handle>(data);
+static void FreeVMReference(Dart_WeakPersistentHandle weak_ref, void* data) {
+  Dart_PersistentHandle perm_handle =
+      reinterpret_cast<Dart_PersistentHandle>(data);
   Dart_DeletePersistentHandle(perm_handle);
-  Dart_DeletePersistentHandle(weak_ref);
+  Dart_DeleteWeakPersistentHandle(weak_ref);
 }
 
 
@@ -108,10 +109,8 @@
   }
 
   // Allocate a persistent handle.
-  Dart_Handle perm_handle = Dart_NewPersistentHandle(handle);
-  if (Dart_IsError(perm_handle)) {
-    return perm_handle;
-  }
+  Dart_PersistentHandle perm_handle = Dart_NewPersistentHandle(handle);
+  ASSERT(perm_handle != NULL);
 
   // Store the persistent handle in the VMReference.
   intptr_t perm_handle_value = reinterpret_cast<intptr_t>(perm_handle);
@@ -126,12 +125,9 @@
   // the VMReference is collected, so we can release the persistent
   // handle.
   void* perm_handle_data = reinterpret_cast<void*>(perm_handle);
-  Dart_Handle weak_ref =
+  Dart_WeakPersistentHandle weak_ref =
       Dart_NewWeakPersistentHandle(vm_ref, perm_handle_data, FreeVMReference);
-  if (Dart_IsError(weak_ref)) {
-    Dart_DeletePersistentHandle(perm_handle);
-    return weak_ref;
-  }
+  ASSERT(weak_ref != NULL);
 
   // Success.
   return vm_ref;
@@ -146,9 +142,13 @@
   if (Dart_IsError(result)) {
     return result;
   }
-  Dart_Handle perm_handle = reinterpret_cast<Dart_Handle>(perm_handle_value);
-  ASSERT(!Dart_IsError(perm_handle));
-  return perm_handle;
+  Dart_PersistentHandle perm_handle =
+      reinterpret_cast<Dart_PersistentHandle>(perm_handle_value);
+  ASSERT(perm_handle != NULL);
+  Dart_Handle handle = Dart_HandleFromPersistent(perm_handle);
+  ASSERT(handle != NULL);
+  ASSERT(!Dart_IsError(handle));
+  return handle;
 }
 
 
diff --git a/runtime/lib/typed_data.cc b/runtime/lib/typed_data.cc
index a4f37b3..b1b2632 100644
--- a/runtime/lib/typed_data.cc
+++ b/runtime/lib/typed_data.cc
@@ -59,8 +59,8 @@
 }
 
 
-static void PeerFinalizer(Dart_Handle handle, void* peer) {
-  Dart_DeletePersistentHandle(handle);
+  static void PeerFinalizer(Dart_WeakPersistentHandle handle, void* peer) {
+  Dart_DeleteWeakPersistentHandle(handle);
   OS::AlignedFree(peer);
 }
 
diff --git a/runtime/lib/typed_data.dart b/runtime/lib/typed_data.dart
index 8cf462f..04f6fa9 100644
--- a/runtime/lib/typed_data.dart
+++ b/runtime/lib/typed_data.dart
@@ -282,14 +282,14 @@
   // Method(s) implementing the Collection interface.
   bool contains(element) => IterableMixinWorkaround.contains(this, element);
 
-  void forEach(void f(element)) {
+  void forEach(void f(num element)) {
     var len = this.length;
     for (var i = 0; i < len; i++) {
       f(this[i]);
     }
   }
 
-  Iterable map(f(int element)) {
+  Iterable map(f(num element)) {
     return IterableMixinWorkaround.mapList(this, f);
   }
 
@@ -297,20 +297,20 @@
     return IterableMixinWorkaround.join(this, separator);
   }
 
-  dynamic reduce(dynamic combine(value, element)) {
+  num reduce(dynamic combine(num value, num element)) {
     return IterableMixinWorkaround.reduce(this, combine);
   }
 
   dynamic fold(dynamic initialValue,
-                 dynamic combine(dynamic initialValue, element)) {
+               dynamic combine(dynamic initialValue, num element)) {
     return IterableMixinWorkaround.fold(this, initialValue, combine);
   }
 
-  Iterable where(bool f(int element)) {
+  Iterable where(bool f(num element)) {
     return IterableMixinWorkaround.where(this, f);
   }
 
-  Iterable expand(Iterable f(int element)) {
+  Iterable expand(Iterable f(num element)) {
     return IterableMixinWorkaround.expand(this, f);
   }
 
@@ -318,7 +318,7 @@
     return IterableMixinWorkaround.takeList(this, n);
   }
 
-  Iterable takeWhile(bool test(int value)) {
+  Iterable takeWhile(bool test(num element)) {
     return IterableMixinWorkaround.takeWhile(this, test);
   }
 
@@ -326,31 +326,31 @@
     return IterableMixinWorkaround.skipList(this, n);
   }
 
-  Iterable skipWhile(bool test(int value)) {
+  Iterable skipWhile(bool test(num element)) {
     return IterableMixinWorkaround.skipWhile(this, test);
   }
 
-  bool every(bool f(element)) {
+  bool every(bool f(num element)) {
     return IterableMixinWorkaround.every(this, f);
   }
 
-  bool any(bool f(element)) {
+  bool any(bool f(num element)) {
     return IterableMixinWorkaround.any(this, f);
   }
 
-  int firstWhere(bool test(int value), {int orElse()}) {
+  num firstWhere(bool test(num element), {orElse()}) {
     return IterableMixinWorkaround.firstWhere(this, test, orElse);
   }
 
-  int lastWhere(bool test(int value), {int orElse()}) {
+  num lastWhere(bool test(num element), {orElse()}) {
     return IterableMixinWorkaround.lastWhereList(this, test, orElse);
   }
 
-  int singleWhere(bool test(int value)) {
+  num singleWhere(bool test(num element)) {
     return IterableMixinWorkaround.singleWhere(this, test);
   }
 
-  int elementAt(int index) {
+  num elementAt(int index) {
     return this[index];
   }
 
@@ -387,7 +387,7 @@
         "Cannot insert into a non-extendable array");
   }
 
-  void sort([int compare(var a, var b)]) {
+  void sort([int compare(num a, num b)]) {
     return IterableMixinWorkaround.sortList(this, compare);
   }
 
@@ -429,27 +429,27 @@
         "Cannot remove from a non-extendable array");
   }
 
-  void removeWhere(bool test(int element)) {
+  void removeWhere(bool test(element)) {
     throw new UnsupportedError(
         "Cannot remove from a non-extendable array");
   }
 
-  void retainWhere(bool test(int element)) {
+  void retainWhere(bool test(element)) {
     throw new UnsupportedError(
         "Cannot remove from a non-extendable array");
   }
 
-  int get first {
+  num get first {
     if (length > 0) return this[0];
     throw new StateError("No elements");
   }
 
-  int get last {
+  num get last {
     if (length > 0) return this[length - 1];
     throw new StateError("No elements");
   }
 
-  int get single {
+  num get single {
     if (length == 1) return this[0];
     if (length == 0) throw new StateError("No elements");
     throw new StateError("More than one element");
@@ -497,7 +497,7 @@
     IterableMixinWorkaround.setAllList(this, index, iterable);
   }
 
-  void fillRange(int start, int end, [fillValue]) {
+  void fillRange(int start, int end, [num fillValue]) {
     IterableMixinWorkaround.fillRangeList(this, start, end, fillValue);
   }
 
diff --git a/runtime/tests/vm/vm.status b/runtime/tests/vm/vm.status
index 4fe49fc..b849809 100644
--- a/runtime/tests/vm/vm.status
+++ b/runtime/tests/vm/vm.status
@@ -54,13 +54,13 @@
 # Skip until we stabilize language tests.
 *: Skip
 
+[ $arch == arm ]
+*: Skip
+
 [ $arch == simarm ]
-# Tests missing code generation support.
-cc/Dart2JSCompileAll: Skip
-cc/CorelibCompileAll: Skip
-cc/ParsePatchLibrary: Skip
-dart/byte_array_test: Skip
-dart/byte_array_optimized_test: Skip
+# Bug in optimized code generation.
+dart/byte_array_test: Fail
+dart/byte_array_optimized_test: Fail
 
 [ $arch == mips ]
 *: Skip
diff --git a/runtime/vm/assembler_arm.cc b/runtime/vm/assembler_arm.cc
index b84ff57..c1803e2 100644
--- a/runtime/vm/assembler_arm.cc
+++ b/runtime/vm/assembler_arm.cc
@@ -1243,29 +1243,6 @@
 }
 
 
-void Assembler::mrc(Register rd, int32_t coproc, int32_t opc1,
-                    int32_t crn, int32_t crm, int32_t opc2, Condition cond) {
-  ASSERT(rd != kNoRegister);
-  ASSERT(cond != kNoCondition);
-
-  // This is all the simulator and disassembler know about.
-  ASSERT(coproc == 15);
-  ASSERT(opc1 == 0);
-  ASSERT(crn == 0);
-  ASSERT(crm == 2);
-  ASSERT(opc2 == 0);
-  int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
-                     B27 | B26 | B25 | B20 | B4 |
-                     ((opc1 & 0x7) << kOpc1Shift) |
-                     ((crn & 0xf) << kCRnShift) |
-                     ((coproc & 0xf) << kCoprocShift) |
-                     ((opc2 & 0x7) << kOpc2Shift) |
-                     ((crm & 0xf) << kCRmShift) |
-                     (static_cast<int32_t>(rd) << kRdShift);
-  Emit(encoding);
-}
-
-
 void Assembler::MarkExceptionHandler(Label* label) {
   EmitType01(AL, 1, TST, 1, PC, R0, ShifterOperand(0));
   Label l;
@@ -1504,8 +1481,9 @@
     }
     case kLoadSWord:
     case kLoadDWord: {
-      *offset_mask = 0x3ff;
-      return Utils::IsAbsoluteUint(10, offset);  // VFP addressing mode.
+      *offset_mask = 0x3fc;  // Multiple of 4.
+      // VFP addressing mode.
+      return (Utils::IsAbsoluteUint(10, offset) && Utils::IsAligned(offset, 4));
     }
     default: {
       UNREACHABLE();
@@ -1531,8 +1509,9 @@
     }
     case kStoreSWord:
     case kStoreDWord: {
-      *offset_mask = 0x3ff;
-      return Utils::IsAbsoluteUint(10, offset);  // VFP addressing mode.
+      *offset_mask = 0x3fc;  // Multiple of 4.
+      // VFP addressing mode.
+      return (Utils::IsAbsoluteUint(10, offset) && Utils::IsAligned(offset, 4));
     }
     default: {
       UNREACHABLE();
@@ -1562,7 +1541,7 @@
 }
 
 
-void Assembler::Mov(Register rd, Register rm, Condition cond) {
+void Assembler::MoveRegister(Register rd, Register rm, Condition cond) {
   if (rd != rm) {
     mov(rd, ShifterOperand(rm), cond);
   }
@@ -1576,6 +1555,11 @@
 }
 
 
+void Assembler::Lsl(Register rd, Register rm, Register rs, Condition cond) {
+  mov(rd, ShifterOperand(rm, LSL, rs), cond);
+}
+
+
 void Assembler::Lsr(Register rd, Register rm, uint32_t shift_imm,
                     Condition cond) {
   ASSERT(shift_imm != 0);  // Do not use Lsr if no shift is wanted.
@@ -1584,6 +1568,11 @@
 }
 
 
+void Assembler::Lsr(Register rd, Register rm, Register rs, Condition cond) {
+  mov(rd, ShifterOperand(rm, LSR, rs), cond);
+}
+
+
 void Assembler::Asr(Register rd, Register rm, uint32_t shift_imm,
                     Condition cond) {
   ASSERT(shift_imm != 0);  // Do not use Asr if no shift is wanted.
@@ -1592,6 +1581,11 @@
 }
 
 
+void Assembler::Asr(Register rd, Register rm, Register rs, Condition cond) {
+  mov(rd, ShifterOperand(rm, ASR, rs), cond);
+}
+
+
 void Assembler::Ror(Register rd, Register rm, uint32_t shift_imm,
                     Condition cond) {
   ASSERT(shift_imm != 0);  // Use Rrx instruction.
@@ -1599,6 +1593,11 @@
 }
 
 
+void Assembler::Ror(Register rd, Register rm, Register rs, Condition cond) {
+  mov(rd, ShifterOperand(rm, ROR, rs), cond);
+}
+
+
 void Assembler::Rrx(Register rd, Register rm, Condition cond) {
   mov(rd, ShifterOperand(rm, ROR, 0), cond);
 }
diff --git a/runtime/vm/assembler_arm.h b/runtime/vm/assembler_arm.h
index 4ee373b..5cddcab 100644
--- a/runtime/vm/assembler_arm.h
+++ b/runtime/vm/assembler_arm.h
@@ -514,10 +514,6 @@
   void bx(Register rm, Condition cond = AL);
   void blx(Register rm, Condition cond = AL);
 
-  // Move to ARM core register from Coprocessor.
-  void mrc(Register rd, int32_t coproc, int32_t opc1,
-           int32_t crn, int32_t crm, int32_t opc2, Condition cond = AL);
-
   // Macros.
   // Branch to an entry address. Call sequence is never patched.
   void Branch(const ExternalLabel* label, Condition cond = AL);
@@ -617,14 +613,18 @@
   void PushList(RegList regs, Condition cond = AL);
   void PopList(RegList regs, Condition cond = AL);
 
-  void Mov(Register rd, Register rm, Condition cond = AL);
+  void MoveRegister(Register rd, Register rm, Condition cond = AL);
 
   // Convenience shift instructions. Use mov instruction with shifter operand
-  // for variants setting the status flags or using a register shift count.
+  // for variants setting the status flags.
   void Lsl(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL);
+  void Lsl(Register rd, Register rm, Register rs, Condition cond = AL);
   void Lsr(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL);
+  void Lsr(Register rd, Register rm, Register rs, Condition cond = AL);
   void Asr(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL);
+  void Asr(Register rd, Register rm, Register rs, Condition cond = AL);
   void Ror(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL);
+  void Ror(Register rd, Register rm, Register rs, Condition cond = AL);
   void Rrx(Register rd, Register rm, Condition cond = AL);
 
   void SmiTag(Register reg, Condition cond = AL) {
diff --git a/runtime/vm/assembler_arm_test.cc b/runtime/vm/assembler_arm_test.cc
index 838bb69..0c0296d 100644
--- a/runtime/vm/assembler_arm_test.cc
+++ b/runtime/vm/assembler_arm_test.cc
@@ -637,7 +637,7 @@
 
 ASSEMBLER_TEST_GENERATE(Multiply64To64, assembler) {
   __ Push(R4);
-  __ Mov(IP, R0);
+  __ mov(IP, ShifterOperand(R0));
   __ mul(R4, R2, R1);
   __ umull(R0, R1, R2, IP);
   __ mla(R2, IP, R3, R4);
@@ -936,7 +936,7 @@
 
 
 ASSEMBLER_TEST_GENERATE(Ldrd, assembler) {
-  __ Mov(IP, SP);
+  __ mov(IP, ShifterOperand(SP));
   __ strd(R2, Address(SP, (-kWordSize * 30), Address::PreIndex));
   __ strd(R0, Address(IP, (-kWordSize * 28)));
   __ ldrd(R2, Address(IP, (-kWordSize * 28)));
@@ -1418,76 +1418,12 @@
 }
 
 
-// Check that assembler mrc instruction encoding, and simulator decoding
-// are in agreement.
-#if defined(USING_SIMULATOR)
-ASSEMBLER_TEST_GENERATE(MrcHaveDiv, assembler) {
-  __ mrc(R0, 15, 0, 0, 2, 0);  // Accesses ID_ISAR0.
-  // Bits 24 - 27 describe the presence of integer division. Bit 24 is set if
-  // it is available in the Thumb instruction set. Bit 25 is set if it is
-  // available both in Thumb and in the ARM instruction set.
-  __ Lsr(R0, R0, 24);
-  __ and_(R0, R0, ShifterOperand(0xf));
-  __ bx(LR);
-}
-
-
-ASSEMBLER_TEST_RUN(MrcHaveDiv, test) {
-  EXPECT(test != NULL);
-  typedef int (*Tst)();
-  bool b = CPUFeatures::integer_division_supported();
-  CPUFeatures::set_integer_division_supported(true);
-  EXPECT_EQ(2, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
-  CPUFeatures::set_integer_division_supported(b);
-}
-
-
-ASSEMBLER_TEST_GENERATE(MrcNoDiv, assembler) {
-  __ mrc(R0, 15, 0, 0, 2, 0);
-  __ Lsr(R0, R0, 24);
-  __ and_(R0, R0, ShifterOperand(0xf));
-  __ bx(LR);
-}
-
-
-ASSEMBLER_TEST_RUN(MrcNoDiv, test) {
-  EXPECT(test != NULL);
-  typedef int (*Tst)();
-  bool b = CPUFeatures::integer_division_supported();
-  CPUFeatures::set_integer_division_supported(false);
-  EXPECT_EQ(0, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
-  CPUFeatures::set_integer_division_supported(b);
-}
-
-
-ASSEMBLER_TEST_GENERATE(MrcReal, assembler) {
-  __ mrc(R0, 15, 0, 0, 2, 0);
-  __ Lsr(R0, R0, 24);
-  __ and_(R0, R0, ShifterOperand(0xf));
-  __ bx(LR);
-}
-
-
-ASSEMBLER_TEST_RUN(MrcReal, test) {
-  EXPECT(test != NULL);
-  typedef int (*Tst)();
-  bool have_div = CPUFeatures::integer_division_supported();
-  int32_t r = EXECUTE_TEST_CODE_INT32(Tst, test->entry());
-  if (have_div) {
-    EXPECT_EQ(2, r);
-  } else {
-    EXPECT_EQ(0, r);
-  }
-}
-#endif  // defined(USING_SIMULATOR)
-
-
 ASSEMBLER_TEST_GENERATE(Udiv, assembler) {
   if (CPUFeatures::integer_division_supported()) {
     __ mov(R0, ShifterOperand(27));
     __ mov(R1, ShifterOperand(9));
     __ udiv(R2, R0, R1);
-    __ Mov(R0, R2);
+    __ mov(R0, ShifterOperand(R2));
   } else {
     __ mov(R0, ShifterOperand(3));
   }
@@ -1507,7 +1443,7 @@
     __ mov(R0, ShifterOperand(27));
     __ LoadImmediate(R1, -9);
     __ sdiv(R2, R0, R1);
-    __ Mov(R0, R2);
+    __ mov(R0, ShifterOperand(R2));
   } else {
     __ LoadImmediate(R0, -3);
   }
@@ -1527,7 +1463,7 @@
     __ mov(R0, ShifterOperand(27));
     __ mov(R1, ShifterOperand(0));
     __ udiv(R2, R0, R1);
-    __ Mov(R0, R2);
+    __ mov(R0, ShifterOperand(R2));
   } else {
     __ LoadImmediate(R0, 0);
   }
@@ -1547,7 +1483,7 @@
     __ mov(R0, ShifterOperand(27));
     __ mov(R1, ShifterOperand(0));
     __ udiv(R2, R0, R1);
-    __ Mov(R0, R2);
+    __ mov(R0, ShifterOperand(R2));
   } else {
     __ LoadImmediate(R0, 0);
   }
@@ -1567,7 +1503,7 @@
     __ LoadImmediate(R0, 0x80000000);
     __ LoadImmediate(R1, 0xffffffff);
     __ udiv(R2, R0, R1);
-    __ Mov(R0, R2);
+    __ mov(R0, ShifterOperand(R2));
   } else {
     __ LoadImmediate(R0, 0);
   }
@@ -1587,7 +1523,7 @@
     __ LoadImmediate(R0, 0x80000000);
     __ LoadImmediate(R1, 0xffffffff);
     __ sdiv(R2, R0, R1);
-    __ Mov(R0, R2);
+    __ mov(R0, ShifterOperand(R2));
   } else {
     __ LoadImmediate(R0, 0x80000000);
   }
diff --git a/runtime/vm/ast.cc b/runtime/vm/ast.cc
index 7f88189..77f14fd 100644
--- a/runtime/vm/ast.cc
+++ b/runtime/vm/ast.cc
@@ -73,6 +73,34 @@
 }
 
 
+LetNode::LetNode(intptr_t token_pos)
+  : AstNode(token_pos),
+    vars_(1),
+    initializers_(1),
+    body_(NULL) { }
+
+
+LocalVariable* LetNode::AddInitializer(AstNode* node) {
+  initializers_.Add(node);
+  char name[64];
+  OS::SNPrint(name, sizeof(name), ":lt%"Pd"_%d", token_pos(), vars_.length());
+  LocalVariable* temp_var =
+      new LocalVariable(token_pos(),
+                        String::ZoneHandle(Symbols::New(name)),
+                        Type::ZoneHandle(Type::DynamicType()));
+  vars_.Add(temp_var);
+  return temp_var;
+}
+
+
+void LetNode::VisitChildren(AstNodeVisitor* visitor) const {
+  for (intptr_t i = 0; i < num_temps(); ++i) {
+    initializers_[i]->Visit(visitor);
+  }
+  body_->Visit(visitor);
+}
+
+
 void ArrayNode::VisitChildren(AstNodeVisitor* visitor) const {
   for (intptr_t i = 0; i < this->length(); i++) {
     ElementAt(i)->Visit(visitor);
diff --git a/runtime/vm/ast.h b/runtime/vm/ast.h
index c65f991..43fe8b2 100644
--- a/runtime/vm/ast.h
+++ b/runtime/vm/ast.h
@@ -55,6 +55,7 @@
   V(LoadIndexedNode, "load indexed")                                           \
   V(StoreIndexedNode, "store indexed")                                         \
   V(SequenceNode, "seq")                                                       \
+  V(LetNode, "let")                                                            \
   V(CommaNode, "comma")                                                        \
   V(CatchClauseNode, "catch clause block")                                     \
   V(TryCatchNode, "try catch block")                                           \
@@ -293,24 +294,48 @@
 };
 
 
+class LetNode : public AstNode {
+ public:
+  explicit LetNode(intptr_t token_pos);
+
+  LocalVariable* TempAt(intptr_t i) const { return vars_[i]; }
+  AstNode* InitializerAt(intptr_t i) const { return initializers_[i]; }
+
+  LocalVariable* AddInitializer(AstNode* node);
+
+  intptr_t num_temps() const {
+    return vars_.length();
+  }
+
+  AstNode* body() const { return body_; }
+  void set_body(AstNode* node) { body_ = node; }
+
+  void VisitChildren(AstNodeVisitor* visitor) const;
+
+  DECLARE_COMMON_NODE_FUNCTIONS(LetNode);
+
+ private:
+  GrowableArray<LocalVariable*> vars_;
+  GrowableArray<AstNode*> initializers_;
+  AstNode* body_;
+
+  DISALLOW_COPY_AND_ASSIGN(LetNode);
+};
+
+
 class ArrayNode : public AstNode {
  public:
-  ArrayNode(intptr_t token_pos,
-            const AbstractType& type,
-            const LocalVariable& temp)
+  ArrayNode(intptr_t token_pos, const AbstractType& type)
       : AstNode(token_pos),
         type_(type),
-        temp_local_(temp),
         elements_() {
     CheckFields();
   }
   ArrayNode(intptr_t token_pos,
             const AbstractType& type,
-            const LocalVariable& temp,
             const GrowableArray<AstNode*>& elements)
       : AstNode(token_pos),
         type_(type),
-        temp_local_(temp),
         elements_(elements.length()) {
     CheckFields();
     for (intptr_t i = 0; i < elements.length(); i++) {
@@ -330,13 +355,10 @@
 
   const AbstractType& type() const { return type_; }
 
-  const LocalVariable& temp_local() const { return temp_local_; }
-
   DECLARE_COMMON_NODE_FUNCTIONS(ArrayNode);
 
  private:
   const AbstractType& type_;
-  const LocalVariable& temp_local_;  // Store allocated array while filling it.
   GrowableArray<AstNode*> elements_;
 
   void CheckFields() {
@@ -1507,25 +1529,19 @@
 // instantiator is the first parameter of this factory, which is already a
 // type argument vector. This case is identified by a null and unneeded
 // instantiator_class.
-//
-// A temporary local is needed to hold the allocated value while the
-// constructor is being called.
 class ConstructorCallNode : public AstNode {
  public:
   ConstructorCallNode(intptr_t token_pos,
                       const AbstractTypeArguments& type_arguments,
                       const Function& constructor,
-                      ArgumentListNode* arguments,
-                      const LocalVariable* allocated_object_var)
+                      ArgumentListNode* arguments)
       : AstNode(token_pos),
         type_arguments_(type_arguments),
         constructor_(constructor),
-        arguments_(arguments),
-        allocated_object_var_(*allocated_object_var) {
+        arguments_(arguments) {
     ASSERT(type_arguments_.IsZoneHandle());
     ASSERT(constructor_.IsZoneHandle());
     ASSERT(arguments_ != NULL);
-    ASSERT(allocated_object_var != NULL);
   }
 
   const AbstractTypeArguments& type_arguments() const {
@@ -1533,9 +1549,6 @@
   }
   const Function& constructor() const { return constructor_; }
   ArgumentListNode* arguments() const { return arguments_; }
-  const LocalVariable& allocated_object_var() const {
-    return allocated_object_var_;
-  }
 
   virtual void VisitChildren(AstNodeVisitor* visitor) const {
     arguments()->Visit(visitor);
@@ -1547,7 +1560,6 @@
   const AbstractTypeArguments& type_arguments_;
   const Function& constructor_;
   ArgumentListNode* arguments_;
-  const LocalVariable& allocated_object_var_;
 
   DISALLOW_IMPLICIT_CONSTRUCTORS(ConstructorCallNode);
 };
diff --git a/runtime/vm/ast_printer.cc b/runtime/vm/ast_printer.cc
index 32bd0af8..9bf4816 100644
--- a/runtime/vm/ast_printer.cc
+++ b/runtime/vm/ast_printer.cc
@@ -127,6 +127,11 @@
 }
 
 
+void AstPrinter::VisitLetNode(LetNode* node) {
+  VisitGenericAstNode(node);
+}
+
+
 void AstPrinter::VisitArrayNode(ArrayNode* node) {
   VisitGenericAstNode(node);
 }
diff --git a/runtime/vm/bit_vector.h b/runtime/vm/bit_vector.h
index 76f6450..09a0489 100644
--- a/runtime/vm/bit_vector.h
+++ b/runtime/vm/bit_vector.h
@@ -48,7 +48,6 @@
       : length_(length),
         data_length_(SizeFor(length)),
         data_(Isolate::Current()->current_zone()->Alloc<uword>(data_length_)) {
-    ASSERT(length > 0);
     Clear();
   }
 
diff --git a/runtime/vm/code_generator_test.cc b/runtime/vm/code_generator_test.cc
index c0d1172..bcd6bf7 100644
--- a/runtime/vm/code_generator_test.cc
+++ b/runtime/vm/code_generator_test.cc
@@ -350,11 +350,10 @@
   String& function_bar_name = String::ZoneHandle(Symbols::New("bar"));
   ArgumentListNode* no_arguments = new ArgumentListNode(kPos);
   const TypeArguments& no_type_arguments = TypeArguments::ZoneHandle();
-  const LocalVariable* allocated = test->CreateTempConstVariable("alloc");
   InstanceCallNode* call_bar = new InstanceCallNode(
       kPos,
       new ConstructorCallNode(
-          kPos, no_type_arguments, constructor, no_arguments, allocated),
+          kPos, no_type_arguments, constructor, no_arguments),
       function_bar_name,
       no_arguments);
 
@@ -535,9 +534,8 @@
 
   const TypeArguments& no_type_arguments = TypeArguments::ZoneHandle();
   ArgumentListNode* no_arguments = new ArgumentListNode(kPos);
-  const LocalVariable* allocated = test->CreateTempConstVariable("alloc");
   test->node_sequence()->Add(new ReturnNode(kPos, new ConstructorCallNode(
-      kPos, no_type_arguments, constructor, no_arguments, allocated)));
+      kPos, no_type_arguments, constructor, no_arguments)));
 }
 
 
diff --git a/runtime/vm/compiler.cc b/runtime/vm/compiler.cc
index c9b16a7..53bc843 100644
--- a/runtime/vm/compiler.cc
+++ b/runtime/vm/compiler.cc
@@ -242,6 +242,9 @@
 // Return false if bailed out.
 static bool CompileParsedFunctionHelper(const ParsedFunction& parsed_function,
                                         bool optimized) {
+  if (optimized && !parsed_function.function().is_optimizable()) {
+    return false;
+  }
   TimerScope timer(FLAG_compiler_stats, &CompilerStats::codegen_timer);
   bool is_compiled = false;
   Isolate* isolate = Isolate::Current();
@@ -281,6 +284,11 @@
       flow_graph = builder.BuildGraph();
     }
 
+    if (FLAG_print_flow_graph ||
+        (optimized && FLAG_print_flow_graph_optimized)) {
+      FlowGraphPrinter::PrintGraph("Before Optimizations", flow_graph);
+    }
+
     if (optimized) {
       TimerScope timer(FLAG_compiler_stats,
                        &CompilerStats::ssa_timer,
@@ -288,12 +296,11 @@
       // Transform to SSA (virtual register 0 and no inlining arguments).
       flow_graph->ComputeSSA(0, NULL);
       DEBUG_ASSERT(flow_graph->VerifyUseLists());
+      if (FLAG_print_flow_graph || FLAG_print_flow_graph_optimized) {
+        FlowGraphPrinter::PrintGraph("After SSA", flow_graph);
+      }
     }
 
-    if (FLAG_print_flow_graph ||
-        (optimized && FLAG_print_flow_graph_optimized)) {
-      FlowGraphPrinter::PrintGraph("Before Optimizations", flow_graph);
-    }
 
     // Collect all instance fields that are loaded in the graph and
     // have non-generic type feedback attached to them that can
@@ -847,9 +854,6 @@
     parsed_function->set_expression_temp_var(
         ParsedFunction::CreateExpressionTempVar(0));
     fragment->scope()->AddVariable(parsed_function->expression_temp_var());
-    parsed_function->set_array_literal_var(
-        ParsedFunction::CreateArrayLiteralVar(0));
-    fragment->scope()->AddVariable(parsed_function->array_literal_var());
     parsed_function->AllocateVariables();
 
     // Non-optimized code generator.
diff --git a/runtime/vm/constants_arm.h b/runtime/vm/constants_arm.h
index 8caf86d..0d69e3c 100644
--- a/runtime/vm/constants_arm.h
+++ b/runtime/vm/constants_arm.h
@@ -554,15 +554,6 @@
     return ((Bits(20, 5) & 0x12) == 0x10) && (Bits(9, 3) == 5);
   }
 
-  // Only handle mrc of the id_isar0 register.
-  inline bool IsMrcIdIsar0() const {
-    ASSERT(ConditionField() != kSpecialCondition);
-    ASSERT(TypeField() == 7);
-    return (Bits(21, 3) == 0) && (Bits(16, 4) == 0) &&
-           (Bits(8, 4) == 0xf) && (Bits(5, 3) == 0) &&
-           (Bits(0, 4) == 2);
-  }
-
   // Test for VFP multiple load and store instructions of type 6.
   inline bool IsVFPMultipleLoadStore() const {
     ASSERT(ConditionField() != kSpecialCondition);
diff --git a/runtime/vm/dart.cc b/runtime/vm/dart.cc
index 446aace..b68c88a 100644
--- a/runtime/vm/dart.cc
+++ b/runtime/vm/dart.cc
@@ -128,6 +128,12 @@
     vm_isolate_->heap()->IterateOldObjects(&premarker);
     vm_isolate_->heap()->WriteProtect(true);
   }
+  // There is a planned and known asymmetry here: We enter one scope for the VM
+  // isolate so that we can allocate the "persistent" scoped handles for the
+  // predefined API values (such as Dart_True, Dart_False and Dart_Null).
+  Dart_EnterScope();
+  Api::InitHandles();
+
   Isolate::SetCurrent(NULL);  // Unregister the VM isolate from this thread.
   Isolate::SetCreateCallback(create);
   Isolate::SetInterruptCallback(interrupt);
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index d493d4e..fd7f2da 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -36,6 +36,9 @@
 DECLARE_FLAG(bool, print_class_table);
 
 ThreadLocalKey Api::api_native_key_ = Thread::kUnsetThreadLocalKey;
+Dart_Handle Api::true_handle_ = NULL;
+Dart_Handle Api::false_handle_ = NULL;
+Dart_Handle Api::null_handle_ = NULL;
 
 
 const char* CanonicalFunction(const char* func) {
@@ -95,9 +98,7 @@
   ApiState* state = isolate->api_state();
   ASSERT(state != NULL);
   ASSERT(state->IsValidLocalHandle(object) ||
-         state->IsValidPersistentHandle(object) ||
-         state->IsValidWeakPersistentHandle(object) ||
-         state->IsValidPrologueWeakPersistentHandle(object));
+         Dart::vm_isolate()->api_state()->IsValidLocalHandle(object));
   ASSERT(FinalizablePersistentHandle::raw_offset() == 0 &&
          PersistentHandle::raw_offset() == 0 &&
          LocalHandle::raw_offset() == 0);
@@ -118,32 +119,23 @@
 #undef DEFINE_UNWRAP
 
 
-LocalHandle* Api::UnwrapAsLocalHandle(const ApiState& state,
-                                      Dart_Handle object) {
-  ASSERT(state.IsValidLocalHandle(object));
-  return reinterpret_cast<LocalHandle*>(object);
-}
-
-
-PersistentHandle* Api::UnwrapAsPersistentHandle(const ApiState& state,
-                                                Dart_Handle object) {
-  ASSERT(state.IsValidPersistentHandle(object));
+PersistentHandle* Api::UnwrapAsPersistentHandle(Dart_PersistentHandle object) {
+  ASSERT(Isolate::Current()->api_state()->IsValidPersistentHandle(object));
   return reinterpret_cast<PersistentHandle*>(object);
 }
 
 
 FinalizablePersistentHandle* Api::UnwrapAsWeakPersistentHandle(
-    const ApiState& state,
-    Dart_Handle object) {
-  ASSERT(state.IsValidWeakPersistentHandle(object));
+    Dart_WeakPersistentHandle object) {
+  ASSERT(Isolate::Current()->api_state()->IsValidWeakPersistentHandle(object));
   return reinterpret_cast<FinalizablePersistentHandle*>(object);
 }
 
 
 FinalizablePersistentHandle* Api::UnwrapAsPrologueWeakPersistentHandle(
-    const ApiState& state,
-    Dart_Handle object) {
-  ASSERT(state.IsValidPrologueWeakPersistentHandle(object));
+    Dart_WeakPersistentHandle object) {
+  ASSERT(Isolate::Current()->api_state()->IsValidPrologueWeakPersistentHandle(
+      object));
   return reinterpret_cast<FinalizablePersistentHandle*>(object);
 }
 
@@ -151,7 +143,7 @@
 Dart_Handle Api::CheckIsolateState(Isolate* isolate) {
   if (ClassFinalizer::FinalizePendingClasses() &&
       isolate->object_store()->PreallocateObjects()) {
-    return Api::Success(isolate);
+    return Api::Success();
   }
   ASSERT(isolate->object_store()->sticky_error() != Object::null());
   return Api::NewHandle(isolate, isolate->object_store()->sticky_error());
@@ -163,15 +155,6 @@
 }
 
 
-Dart_Handle Api::Success(Isolate* isolate) {
-  ASSERT(isolate != NULL);
-  ApiState* state = isolate->api_state();
-  ASSERT(state != NULL);
-  PersistentHandle* true_handle = state->True();
-  return reinterpret_cast<Dart_Handle>(true_handle);
-}
-
-
 Dart_Handle Api::NewError(const char* format, ...) {
   Isolate* isolate = Isolate::Current();
   DARTSCOPE(isolate);
@@ -210,30 +193,18 @@
 }
 
 
-Dart_Handle Api::Null(Isolate* isolate) {
-  ASSERT(isolate != NULL);
-  ApiState* state = isolate->api_state();
-  ASSERT(state != NULL);
-  PersistentHandle* null_handle = state->Null();
-  return reinterpret_cast<Dart_Handle>(null_handle);
+Dart_Handle Api::Null() {
+  return null_handle_;
 }
 
 
-Dart_Handle Api::True(Isolate* isolate) {
-  ASSERT(isolate != NULL);
-  ApiState* state = isolate->api_state();
-  ASSERT(state != NULL);
-  PersistentHandle* true_handle = state->True();
-  return reinterpret_cast<Dart_Handle>(true_handle);
+Dart_Handle Api::True() {
+  return true_handle_;
 }
 
 
-Dart_Handle Api::False(Isolate* isolate) {
-  ASSERT(isolate != NULL);
-  ApiState* state = isolate->api_state();
-  ASSERT(state != NULL);
-  PersistentHandle* false_handle = state->False();
-  return reinterpret_cast<Dart_Handle>(false_handle);
+Dart_Handle Api::False() {
+  return false_handle_;
 }
 
 
@@ -254,6 +225,23 @@
 }
 
 
+void Api::InitHandles() {
+  Isolate* isolate = Isolate::Current();
+  ASSERT(isolate != NULL);
+  ASSERT(isolate == Dart::vm_isolate());
+  ApiState* state = isolate->api_state();
+  ASSERT(state != NULL);
+  ASSERT(true_handle_ == NULL);
+  true_handle_ = Api::NewHandle(isolate, Bool::True().raw());
+
+  ASSERT(false_handle_ == NULL);
+  false_handle_ = Api::NewHandle(isolate, Bool::False().raw());
+
+  ASSERT(null_handle_ == NULL);
+  null_handle_ = Api::NewHandle(isolate, Object::null());
+}
+
+
 bool Api::ExternalStringGetPeerHelper(Dart_Handle object, void** peer) {
   NoGCScope no_gc_scope;
   RawObject* raw_obj = Api::UnwrapHandle(object);
@@ -524,7 +512,32 @@
 }
 
 
-DART_EXPORT Dart_Handle Dart_NewPersistentHandle(Dart_Handle object) {
+DART_EXPORT Dart_Handle Dart_HandleFromPersistent(
+    Dart_PersistentHandle object) {
+  Isolate* isolate = Isolate::Current();
+  DARTSCOPE(isolate);
+  ApiState* state = isolate->api_state();
+  ASSERT(state != NULL);
+  ASSERT(state->IsValidPersistentHandle(object));
+  return Api::NewHandle(isolate,
+                        reinterpret_cast<PersistentHandle*>(object)->raw());
+}
+
+
+DART_EXPORT Dart_Handle Dart_HandleFromWeakPersistent(
+    Dart_WeakPersistentHandle object) {
+  Isolate* isolate = Isolate::Current();
+  DARTSCOPE(isolate);
+  ApiState* state = isolate->api_state();
+  ASSERT(state != NULL);
+  ASSERT(state->IsValidWeakPersistentHandle(object) ||
+         state->IsValidPrologueWeakPersistentHandle(object));
+  return Api::NewHandle(
+      isolate, reinterpret_cast<FinalizablePersistentHandle*>(object)->raw());
+}
+
+
+DART_EXPORT Dart_PersistentHandle Dart_NewPersistentHandle(Dart_Handle object) {
   Isolate* isolate = Isolate::Current();
   DARTSCOPE(isolate);
   ApiState* state = isolate->api_state();
@@ -532,10 +545,10 @@
   const Object& old_ref = Object::Handle(isolate, Api::UnwrapHandle(object));
   PersistentHandle* new_ref = state->persistent_handles().AllocateHandle();
   new_ref->set_raw(old_ref);
-  return reinterpret_cast<Dart_Handle>(new_ref);
+  return reinterpret_cast<Dart_PersistentHandle>(new_ref);
 }
 
-static Dart_Handle AllocateFinalizableHandle(
+static Dart_WeakPersistentHandle AllocateFinalizableHandle(
     Isolate* isolate,
     FinalizablePersistentHandles* handles,
     Dart_Handle object,
@@ -546,11 +559,11 @@
   finalizable_ref->set_raw(ref);
   finalizable_ref->set_peer(peer);
   finalizable_ref->set_callback(callback);
-  return reinterpret_cast<Dart_Handle>(finalizable_ref);
+  return reinterpret_cast<Dart_WeakPersistentHandle>(finalizable_ref);
 }
 
 
-DART_EXPORT Dart_Handle Dart_NewWeakPersistentHandle(
+DART_EXPORT Dart_WeakPersistentHandle Dart_NewWeakPersistentHandle(
     Dart_Handle object,
     void* peer,
     Dart_WeakPersistentHandleFinalizer callback) {
@@ -566,7 +579,7 @@
 }
 
 
-DART_EXPORT Dart_Handle Dart_NewPrologueWeakPersistentHandle(
+DART_EXPORT Dart_WeakPersistentHandle Dart_NewPrologueWeakPersistentHandle(
     Dart_Handle object,
     void* peer,
     Dart_WeakPersistentHandleFinalizer callback) {
@@ -582,24 +595,12 @@
 }
 
 
-DART_EXPORT void Dart_DeletePersistentHandle(Dart_Handle object) {
+DART_EXPORT void Dart_DeletePersistentHandle(Dart_PersistentHandle object) {
   Isolate* isolate = Isolate::Current();
   CHECK_ISOLATE(isolate);
   ApiState* state = isolate->api_state();
   ASSERT(state != NULL);
-  if (state->IsValidPrologueWeakPersistentHandle(object)) {
-    FinalizablePersistentHandle* prologue_weak_ref =
-        Api::UnwrapAsPrologueWeakPersistentHandle(*state, object);
-    state->prologue_weak_persistent_handles().FreeHandle(prologue_weak_ref);
-    return;
-  }
-  if (state->IsValidWeakPersistentHandle(object)) {
-    FinalizablePersistentHandle* weak_ref =
-        Api::UnwrapAsWeakPersistentHandle(*state, object);
-    state->weak_persistent_handles().FreeHandle(weak_ref);
-    return;
-  }
-  PersistentHandle* ref = Api::UnwrapAsPersistentHandle(*state, object);
+  PersistentHandle* ref = Api::UnwrapAsPersistentHandle(object);
   ASSERT(!state->IsProtectedHandle(ref));
   if (!state->IsProtectedHandle(ref)) {
     state->persistent_handles().FreeHandle(ref);
@@ -607,16 +608,27 @@
 }
 
 
-DART_EXPORT bool Dart_IsWeakPersistentHandle(Dart_Handle object) {
+DART_EXPORT void Dart_DeleteWeakPersistentHandle(
+    Dart_WeakPersistentHandle object) {
   Isolate* isolate = Isolate::Current();
   CHECK_ISOLATE(isolate);
   ApiState* state = isolate->api_state();
   ASSERT(state != NULL);
-  return state->IsValidWeakPersistentHandle(object);
+  if (state->IsValidPrologueWeakPersistentHandle(object)) {
+    FinalizablePersistentHandle* prologue_weak_ref =
+        Api::UnwrapAsPrologueWeakPersistentHandle(object);
+    state->prologue_weak_persistent_handles().FreeHandle(prologue_weak_ref);
+    return;
+  }
+  FinalizablePersistentHandle* weak_ref =
+      Api::UnwrapAsWeakPersistentHandle(object);
+  state->weak_persistent_handles().FreeHandle(weak_ref);
+  return;
 }
 
 
-DART_EXPORT bool Dart_IsPrologueWeakPersistentHandle(Dart_Handle object) {
+DART_EXPORT bool Dart_IsPrologueWeakPersistentHandle(
+    Dart_WeakPersistentHandle object) {
   Isolate* isolate = Isolate::Current();
   CHECK_ISOLATE(isolate);
   ApiState* state = isolate->api_state();
@@ -625,10 +637,11 @@
 }
 
 
-DART_EXPORT Dart_Handle Dart_NewWeakReferenceSet(Dart_Handle* keys,
-                                                 intptr_t num_keys,
-                                                 Dart_Handle* values,
-                                                 intptr_t num_values) {
+DART_EXPORT Dart_Handle Dart_NewWeakReferenceSet(
+    Dart_WeakPersistentHandle* keys,
+    intptr_t num_keys,
+    Dart_WeakPersistentHandle* values,
+    intptr_t num_values) {
   Isolate* isolate = Isolate::Current();
   CHECK_ISOLATE(isolate);
   ApiState* state = isolate->api_state();
@@ -653,7 +666,7 @@
   WeakReferenceSet* reference_set = new WeakReferenceSet(keys, num_keys,
                                                          values, num_values);
   state->DelayWeakReferenceSet(reference_set);
-  return Api::Success(isolate);
+  return Api::Success();
 }
 
 
@@ -672,7 +685,7 @@
         CURRENT_FUNC);
   }
   callbacks.Add(callback);
-  return Api::Success(isolate);
+  return Api::Success();
 }
 
 
@@ -687,7 +700,7 @@
         CURRENT_FUNC);
   }
   callbacks.Remove(callback);
-  return Api::Success(isolate);
+  return Api::Success();
 }
 
 
@@ -703,7 +716,7 @@
         CURRENT_FUNC);
   }
   callbacks.Add(callback);
-  return Api::Success(isolate);
+  return Api::Success();
 }
 
 
@@ -718,7 +731,7 @@
         CURRENT_FUNC);
   }
   callbacks.Remove(callback);
-  return Api::Success(isolate);
+  return Api::Success();
 }
 
 
@@ -730,7 +743,7 @@
     RETURN_NULL_ERROR(callback);
   }
   isolate->heap()->Profile(callback, stream);
-  return Api::Success(isolate);
+  return Api::Success();
 }
 
 // --- Initialization and Globals ---
@@ -898,7 +911,7 @@
   FullSnapshotWriter writer(buffer, ApiReallocate);
   writer.WriteFullSnapshot();
   *size = writer.BytesWritten();
-  return Api::Success(isolate);
+  return Api::Success();
 }
 
 
@@ -927,7 +940,7 @@
   ScriptSnapshotWriter writer(buffer, ApiReallocate);
   writer.WriteScriptSnapshot(library);
   *size = writer.BytesWritten();
-  return Api::Success(isolate);
+  return Api::Success();
 }
 
 
@@ -1003,7 +1016,7 @@
   if (FLAG_print_class_table) {
     isolate->class_table()->Print();
   }
-  return Api::Success(isolate);
+  return Api::Success();
 }
 
 
@@ -1017,7 +1030,7 @@
     isolate->object_store()->clear_sticky_error();
     return error;
   }
-  return Api::Success(isolate);
+  return Api::Success();
 }
 
 
@@ -1198,7 +1211,7 @@
 DART_EXPORT Dart_Handle Dart_Null() {
   Isolate* isolate = Isolate::Current();
   CHECK_ISOLATE_SCOPE(isolate);
-  return Api::Null(isolate);
+  return Api::Null();
 }
 
 
@@ -1220,7 +1233,7 @@
       Object::Handle(isolate, DartLibraryCalls::Equals(expected, actual));
   if (result.IsBool()) {
     *value = Bool::Cast(result).value();
-    return Api::Success(isolate);
+    return Api::Success();
   } else if (result.IsError()) {
     return Api::NewHandle(isolate, result.raw());
   } else {
@@ -1267,7 +1280,7 @@
   } else {
     *value = false;
   }
-  return Api::Success(isolate);
+  return Api::Success();
 }
 
 
@@ -1318,7 +1331,7 @@
   intptr_t class_id = Api::ClassId(integer);
   if (class_id == kSmiCid || class_id == kMintCid) {
     *fits = true;
-    return Api::Success(isolate);
+    return Api::Success();
   }
   // Slow path for Mints and Bigints.
   DARTSCOPE(isolate);
@@ -1328,7 +1341,7 @@
   }
   ASSERT(!BigintOperations::FitsIntoInt64(Bigint::Cast(int_obj)));
   *fits = false;
-  return Api::Success(isolate);
+  return Api::Success();
 }
 
 
@@ -1339,7 +1352,7 @@
   CHECK_ISOLATE(isolate);
   if (Api::IsSmi(integer)) {
     *fits = (Api::SmiValue(integer) >= 0);
-    return Api::Success(isolate);
+    return Api::Success();
   }
   // Slow path for Mints and Bigints.
   DARTSCOPE(isolate);
@@ -1353,7 +1366,7 @@
   } else {
     *fits = BigintOperations::FitsIntoUint64(Bigint::Cast(int_obj));
   }
-  return Api::Success(isolate);
+  return Api::Success();
 }
 
 
@@ -1388,7 +1401,7 @@
   CHECK_ISOLATE(isolate);
   if (Api::IsSmi(integer)) {
     *value = Api::SmiValue(integer);
-    return Api::Success(isolate);
+    return Api::Success();
   }
   // Slow path for Mints and Bigints.
   DARTSCOPE(isolate);
@@ -1399,12 +1412,12 @@
   ASSERT(!int_obj.IsSmi());
   if (int_obj.IsMint()) {
     *value = int_obj.AsInt64Value();
-    return Api::Success(isolate);
+    return Api::Success();
   } else {
     const Bigint& bigint = Bigint::Cast(int_obj);
     if (BigintOperations::FitsIntoInt64(bigint)) {
       *value = BigintOperations::ToInt64(bigint);
-      return Api::Success(isolate);
+      return Api::Success();
     }
   }
   return Api::NewError("%s: Integer %s cannot be represented as an int64_t.",
@@ -1421,7 +1434,7 @@
     intptr_t smi_value = Api::SmiValue(integer);
     if (smi_value >= 0) {
       *value = smi_value;
-      return Api::Success(isolate);
+      return Api::Success();
     }
   }
   // Slow path for Mints and Bigints.
@@ -1433,12 +1446,12 @@
   ASSERT(!int_obj.IsSmi());
   if (int_obj.IsMint() && !int_obj.IsNegative()) {
     *value = int_obj.AsInt64Value();
-    return Api::Success(isolate);
+    return Api::Success();
   } else {
     const Bigint& bigint = Bigint::Cast(int_obj);
     if (BigintOperations::FitsIntoUint64(bigint)) {
       *value = BigintOperations::ToUint64(bigint);
-      return Api::Success(isolate);
+      return Api::Success();
     }
   }
   return Api::NewError("%s: Integer %s cannot be represented as a uint64_t.",
@@ -1467,7 +1480,7 @@
     *value = BigintOperations::ToHexCString(Bigint::Cast(int_obj),
                                             BigintAllocate);
   }
-  return Api::Success(isolate);
+  return Api::Success();
 }
 
 
@@ -1477,14 +1490,14 @@
 DART_EXPORT Dart_Handle Dart_True() {
   Isolate* isolate = Isolate::Current();
   CHECK_ISOLATE_SCOPE(isolate);
-  return Api::True(isolate);
+  return Api::True();
 }
 
 
 DART_EXPORT Dart_Handle Dart_False() {
   Isolate* isolate = Isolate::Current();
   CHECK_ISOLATE_SCOPE(isolate);
-  return Api::False(isolate);
+  return Api::False();
 }
 
 
@@ -1496,7 +1509,7 @@
 DART_EXPORT Dart_Handle Dart_NewBoolean(bool value) {
   Isolate* isolate = Isolate::Current();
   CHECK_ISOLATE_SCOPE(isolate);
-  return value ? Api::True(isolate) : Api::False(isolate);
+  return value ? Api::True() : Api::False();
 }
 
 
@@ -1509,7 +1522,7 @@
     RETURN_TYPE_ERROR(isolate, boolean_obj, Bool);
   }
   *value = obj.value();
-  return Api::Success(isolate);
+  return Api::Success();
 }
 
 
@@ -1538,7 +1551,7 @@
     RETURN_TYPE_ERROR(isolate, double_obj, Double);
   }
   *value = obj.value();
-  return Api::Success(isolate);
+  return Api::Success();
 }
 
 
@@ -1563,7 +1576,7 @@
     RETURN_TYPE_ERROR(isolate, str, String);
   }
   *len = str_obj.Length();
-  return Api::Success(isolate);
+  return Api::Success();
 }
 
 
@@ -1633,7 +1646,7 @@
   }
 
   if (Api::ExternalStringGetPeerHelper(object, peer)) {
-    return Api::Success(Isolate::Current());
+    return Api::Success();
   }
 
   // It's not an external string, return appropriate error.
@@ -1701,7 +1714,7 @@
   memmove(res, string_value, string_length + 1);
   ASSERT(res[string_length] == '\0');
   *cstr = res;
-  return Api::Success(isolate);
+  return Api::Success();
 }
 
 
@@ -1727,7 +1740,7 @@
   }
   str_obj.ToUTF8(*utf8_array, str_len);
   *length = str_len;
-  return Api::Success(isolate);
+  return Api::Success();
 }
 
 
@@ -1755,7 +1768,7 @@
     latin1_array[i] = str_obj.CharAt(i);
   }
   *length = copy_len;
-  return Api::Success(isolate);
+  return Api::Success();
 }
 
 
@@ -1774,7 +1787,7 @@
     utf16_array[i] = static_cast<uint16_t>(str_obj.CharAt(i));
   }
   *length = copy_len;
-  return Api::Success(isolate);
+  return Api::Success();
 }
 
 
@@ -1790,7 +1803,7 @@
     RETURN_NULL_ERROR(size);
   }
   *size = (str_obj.Length() * str_obj.CharSize());
-  return Api::Success(isolate);
+  return Api::Success();
 }
 
 
@@ -1839,7 +1852,7 @@
         utf16_array[i] = static_cast<uint16_t>(str_obj.CharAt(i));
       }
     }
-    return Api::Null(isolate);
+    return Api::Null();
   }
   return Api::NewHandle(isolate,
                         str_obj.MakeExternal(array, length, peer, cback));
@@ -1893,7 +1906,7 @@
   type& array = type::Handle(isolate);                                         \
   array ^= obj.raw();                                                          \
   *len = array.Length();                                                       \
-  return Api::Success(isolate);                                                \
+  return Api::Success();                                                       \
 
 
 DART_EXPORT Dart_Handle Dart_ListLength(Dart_Handle list, intptr_t* len) {
@@ -1938,7 +1951,7 @@
     Object::Handle(isolate, DartEntry::InvokeFunction(function, args));
   if (retval.IsSmi()) {
     *len = Smi::Cast(retval).Value();
-    return Api::Success(isolate);
+    return Api::Success();
   } else if (retval.IsMint() || retval.IsBigint()) {
     if (retval.IsMint()) {
       int64_t mint_value = Mint::Cast(retval).value();
@@ -2017,7 +2030,7 @@
   }                                                                            \
   if ((index >= 0) && (index < array.Length())) {                              \
     array.SetAt(index, value_obj);                                             \
-    return Api::Success(isolate);                                              \
+    return Api::Success();                                                     \
   }                                                                            \
   return Api::NewError("Invalid index passed in to set list element");         \
 
@@ -2166,7 +2179,7 @@
       native_array[i] = static_cast<uint8_t>(integer.AsInt64Value() & 0xff);   \
       ASSERT(integer.AsInt64Value() <= 0xff);                                  \
     }                                                                          \
-    return Api::Success(isolate);                                              \
+    return Api::Success();                                                     \
   }                                                                            \
   return Api::NewError("Invalid length passed in to access array elements");   \
 
@@ -2186,7 +2199,7 @@
         memmove(native_array,
                 reinterpret_cast<uint8_t*>(array.DataAddr(offset)),
                 length);
-        return Api::Success(isolate);
+        return Api::Success();
       }
       return Api::NewError("Invalid length passed in to access list elements");
     }
@@ -2243,7 +2256,7 @@
         native_array[i] =
             static_cast<uint8_t>(integer_result.AsInt64Value() & 0xff);
       }
-      return Api::Success(isolate);
+      return Api::Success();
     }
   }
   return Api::NewError("Object does not implement the 'List' interface");
@@ -2259,7 +2272,7 @@
       integer = Integer::New(native_array[i]);                                 \
       array.SetAt(offset + i, integer);                                        \
     }                                                                          \
-    return Api::Success(isolate);                                              \
+    return Api::Success();                                                     \
   }                                                                            \
   return Api::NewError("Invalid length passed in to set array elements");      \
 
@@ -2279,7 +2292,7 @@
         memmove(reinterpret_cast<uint8_t*>(array.DataAddr(offset)),
                 native_array,
                 length);
-        return Api::Success(isolate);
+        return Api::Success();
       }
       return Api::NewError("Invalid length passed in to access list elements");
     }
@@ -2334,7 +2347,7 @@
           return Api::NewHandle(isolate, result.raw());
         }
       }
-      return Api::Success(isolate);
+      return Api::Success();
     }
   }
   return Api::NewError("Object does not implement the 'List' interface");
@@ -2488,32 +2501,19 @@
 
 
 static Dart_Handle NewExternalTypedData(
-    Isolate* isolate,
-    intptr_t cid,
-    void* data,
-    intptr_t length,
-    void* peer,
-    Dart_WeakPersistentHandleFinalizer callback) {
+    Isolate* isolate, intptr_t cid, void* data, intptr_t length) {
   CHECK_LENGTH(length, ExternalTypedData::MaxElements(cid));
   const ExternalTypedData& result = ExternalTypedData::Handle(
       isolate,
       ExternalTypedData::New(cid, reinterpret_cast<uint8_t*>(data), length));
-  result.AddFinalizer(peer, callback);
   return Api::NewHandle(isolate, result.raw());
 }
 
 
-static Dart_Handle NewExternalByteData(Isolate* isolate,
-                                       void* data,
-                                       intptr_t length,
-                                       void* peer,
-                                       Dart_WeakPersistentHandleFinalizer cb) {
-  Dart_Handle ext_data = NewExternalTypedData(isolate,
-                                              kExternalTypedDataUint8ArrayCid,
-                                              data,
-                                              length,
-                                              peer,
-                                              cb);
+static Dart_Handle NewExternalByteData(
+    Isolate* isolate, void* data, intptr_t length) {
+  Dart_Handle ext_data = NewExternalTypedData(
+      isolate, kExternalTypedDataUint8ArrayCid, data, length);
   if (::Dart_IsError(ext_data)) {
     return ext_data;
   }
@@ -2582,16 +2582,14 @@
                            CURRENT_FUNC);
   }
   UNREACHABLE();
-  return Api::Null(isolate);
+  return Api::Null();
 }
 
 
 DART_EXPORT Dart_Handle Dart_NewExternalTypedData(
     Dart_TypedData_Type type,
     void* data,
-    intptr_t length,
-    void* peer,
-    Dart_WeakPersistentHandleFinalizer callback) {
+    intptr_t length) {
   Isolate* isolate = Isolate::Current();
   DARTSCOPE(isolate);
   if (data == NULL && length != 0) {
@@ -2600,114 +2598,73 @@
   CHECK_CALLBACK_STATE(isolate);
   switch (type) {
     case kByteData:
-      return NewExternalByteData(isolate, data, length, peer, callback);
+      return NewExternalByteData(isolate, data, length);
     case kInt8:
       return NewExternalTypedData(isolate,
                                   kExternalTypedDataInt8ArrayCid,
                                   data,
-                                  length,
-                                  peer,
-                                  callback);
+                                  length);
     case kUint8:
       return NewExternalTypedData(isolate,
                                   kExternalTypedDataUint8ArrayCid,
                                   data,
-                                  length,
-                                  peer,
-                                  callback);
+                                  length);
     case kUint8Clamped:
       return NewExternalTypedData(isolate,
                                   kExternalTypedDataUint8ClampedArrayCid,
                                   data,
-                                  length,
-                                  peer,
-                                  callback);
+                                  length);
     case kInt16:
       return NewExternalTypedData(isolate,
                                   kExternalTypedDataInt16ArrayCid,
                                   data,
-                                  length,
-                                  peer,
-                                  callback);
+                                  length);
     case kUint16:
       return NewExternalTypedData(isolate,
                                   kExternalTypedDataUint16ArrayCid,
                                   data,
-                                  length,
-                                  peer,
-                                  callback);
+                                  length);
     case kInt32:
       return NewExternalTypedData(isolate,
                                   kExternalTypedDataInt32ArrayCid,
                                   data,
-                                  length,
-                                  peer,
-                                  callback);
+                                  length);
     case kUint32:
       return NewExternalTypedData(isolate,
                                   kExternalTypedDataUint32ArrayCid,
                                   data,
-                                  length,
-                                  peer,
-                                  callback);
+                                  length);
     case kInt64:
       return NewExternalTypedData(isolate,
                                   kExternalTypedDataInt64ArrayCid,
                                   data,
-                                  length,
-                                  peer,
-                                  callback);
+                                  length);
     case kUint64:
       return NewExternalTypedData(isolate,
                                   kExternalTypedDataUint64ArrayCid,
                                   data,
-                                  length,
-                                  peer,
-                                  callback);
+                                  length);
     case kFloat32:
       return NewExternalTypedData(isolate,
                                   kExternalTypedDataFloat32ArrayCid,
                                   data,
-                                  length,
-                                  peer,
-                                  callback);
+                                  length);
     case kFloat64:
       return NewExternalTypedData(isolate,
                                   kExternalTypedDataFloat64ArrayCid,
                                   data,
-                                  length,
-                                  peer,
-                                  callback);
+                                  length);
     case kFloat32x4:
       return NewExternalTypedData(isolate,
                                   kExternalTypedDataFloat32x4ArrayCid,
                                   data,
-                                  length,
-                                  peer,
-                                  callback);
+                                  length);
     default:
       return Api::NewError("%s expects argument 'type' to be of"
                            " 'external TypedData'", CURRENT_FUNC);
   }
   UNREACHABLE();
-  return Api::Null(isolate);
-}
-
-
-DART_EXPORT Dart_Handle Dart_ExternalTypedDataGetPeer(Dart_Handle object,
-                                                      void** peer) {
-  Isolate* isolate = Isolate::Current();
-  DARTSCOPE(isolate);
-  const ExternalTypedData& array =
-      Api::UnwrapExternalTypedDataHandle(isolate, object);
-  if (array.IsNull()) {
-    RETURN_TYPE_ERROR(isolate, object, ExternalTypedData);
-  }
-  if (peer == NULL) {
-    RETURN_NULL_ERROR(peer);
-  }
-  *peer = array.GetPeer();
-  return Api::Success(isolate);
+  return Api::Null();
 }
 
 
@@ -2770,7 +2727,7 @@
       *data = data_obj.DataAddr(offset_in_bytes);
     }
   }
-  return Api::Success(isolate);
+  return Api::Success();
 }
 
 
@@ -2787,7 +2744,7 @@
     isolate->DecrementNoGCScopeDepth();
     END_NO_CALLBACK_SCOPE(isolate);
   }
-  return Api::Success(isolate);
+  return Api::Success();
 }
 
 
@@ -2923,7 +2880,7 @@
   } else {
     *count = interface_types.Length();
   }
-  return Api::Success(isolate);
+  return Api::Success();
 }
 
 
@@ -3234,7 +3191,7 @@
     RETURN_TYPE_ERROR(isolate, function, Function);
   }
   *is_abstract = func.is_abstract();
-  return Api::Success(isolate);
+  return Api::Success();
 }
 
 
@@ -3250,7 +3207,7 @@
     RETURN_TYPE_ERROR(isolate, function, Function);
   }
   *is_static = func.is_static();
-  return Api::Success(isolate);
+  return Api::Success();
 }
 
 
@@ -3266,7 +3223,7 @@
     RETURN_TYPE_ERROR(isolate, function, Function);
   }
   *is_constructor = func.kind() == RawFunction::kConstructor;
-  return Api::Success(isolate);
+  return Api::Success();
 }
 
 
@@ -3282,7 +3239,7 @@
     RETURN_TYPE_ERROR(isolate, function, Function);
   }
   *is_getter = func.IsGetterFunction();
-  return Api::Success(isolate);
+  return Api::Success();
 }
 
 
@@ -3298,7 +3255,7 @@
     RETURN_TYPE_ERROR(isolate, function, Function);
   }
   *is_setter = (func.kind() == RawFunction::kSetterFunction);
-  return Api::Success(isolate);
+  return Api::Success();
 }
 
 
@@ -3352,7 +3309,7 @@
   ASSERT(*fixed_param_count >= 0);
   ASSERT(*opt_param_count >= 0);
 
-  return Api::Success(isolate);
+  return Api::Success();
 }
 
 
@@ -3488,7 +3445,7 @@
     RETURN_TYPE_ERROR(isolate, variable, Field);
   }
   *is_static = var.is_static();
-  return Api::Success(isolate);
+  return Api::Success();
 }
 
 
@@ -3504,7 +3461,7 @@
     RETURN_TYPE_ERROR(isolate, variable, Field);
   }
   *is_final = var.is_final();
-  return Api::Success(isolate);
+  return Api::Success();
 }
 
 
@@ -4135,7 +4092,7 @@
       if (result.IsError()) {
         return Api::NewHandle(isolate, result.raw());
       } else {
-        return Api::Success(isolate);
+        return Api::Success();
       }
     } else if (!field.IsNull()) {
       if (field.is_final()) {
@@ -4143,7 +4100,7 @@
                              CURRENT_FUNC, field_name.ToCString());
       } else {
         field.set_value(value_instance);
-        return Api::Success(isolate);
+        return Api::Success();
       }
     } else {
       return Api::NewError("%s: did not find static field '%s'.",
@@ -4172,7 +4129,7 @@
       if (result.IsError()) {
         return Api::NewHandle(isolate, result.raw());
       } else {
-        return Api::Success(isolate);
+        return Api::Success();
       }
     } else if (!field.IsNull()) {
       if (field.is_final()) {
@@ -4180,7 +4137,7 @@
                              CURRENT_FUNC, field_name.ToCString());
       } else {
         field.set_value(value_instance);
-        return Api::Success(isolate);
+        return Api::Success();
       }
     } else {
       return Api::NewError("%s: did not find top-level variable '%s'.",
@@ -4237,7 +4194,7 @@
   }
   const Class& cls = Class::Handle(isolate, instance.clazz());
   *count = cls.num_native_fields();
-  return Api::Success(isolate);
+  return Api::Success();
 }
 
 
@@ -4256,7 +4213,7 @@
         CURRENT_FUNC, index);
   }
   *value = instance.GetNativeField(isolate, index);
-  return Api::Success(isolate);
+  return Api::Success();
 }
 
 
@@ -4275,7 +4232,7 @@
         CURRENT_FUNC, index);
   }
   instance.SetNativeField(index, value);
-  return Api::Success(isolate);
+  return Api::Success();
 }
 
 
@@ -4399,7 +4356,7 @@
   Isolate* isolate = Isolate::Current();
   CHECK_ISOLATE(isolate);
   isolate->set_library_tag_handler(handler);
-  return Api::Success(isolate);
+  return Api::Success();
 }
 
 
@@ -4535,7 +4492,7 @@
   ASSERT(isolate != NULL);
   const Error& error = Error::Handle(isolate, Library::CompileAll());
   if (error.IsNull()) {
-    *result = Api::Success(isolate);
+    *result = Api::Success();
   } else {
     *result = Api::NewHandle(isolate, error.raw());
   }
@@ -4758,7 +4715,7 @@
       library_vm.AddObject(library_prefix, prefix_symbol);
     }
   }
-  return Api::Success(isolate);
+  return Api::Success();
 }
 
 
@@ -4828,7 +4785,7 @@
     RETURN_TYPE_ERROR(isolate, library, Library);
   }
   lib.set_native_entry_resolver(resolver);
-  return Api::Success(isolate);
+  return Api::Success();
 }
 
 
@@ -4865,7 +4822,7 @@
     RawObject* raw_obj = obj.raw();
     *peer = isolate->heap()->GetPeer(raw_obj);
   }
-  return Api::Success(isolate);
+  return Api::Success();
 }
 
 
@@ -4883,7 +4840,7 @@
     RawObject* raw_obj = obj.raw();
     isolate->heap()->SetPeer(raw_obj, peer);
   }
-  return Api::Success(isolate);
+  return Api::Success();
 }
 
 }  // namespace dart
diff --git a/runtime/vm/dart_api_impl.h b/runtime/vm/dart_api_impl.h
index b913df8..3959611 100644
--- a/runtime/vm/dart_api_impl.h
+++ b/runtime/vm/dart_api_impl.h
@@ -74,24 +74,18 @@
   CLASS_LIST_FOR_HANDLES(DECLARE_UNWRAP)
 #undef DECLARE_UNWRAP
 
-  // Validates and converts the passed in handle as a local handle.
-  static LocalHandle* UnwrapAsLocalHandle(const ApiState& state,
-                                          Dart_Handle object);
-
   // Validates and converts the passed in handle as a persistent handle.
-  static PersistentHandle* UnwrapAsPersistentHandle(const ApiState& state,
-                                                    Dart_Handle object);
+  static PersistentHandle* UnwrapAsPersistentHandle(
+      Dart_PersistentHandle object);
 
   // Validates and converts the passed in handle as a weak persistent handle.
   static FinalizablePersistentHandle* UnwrapAsWeakPersistentHandle(
-      const ApiState& state,
-      Dart_Handle object);
+      Dart_WeakPersistentHandle object);
 
   // Validates and converts the passed in handle as a prologue weak
   // persistent handle.
   static FinalizablePersistentHandle* UnwrapAsPrologueWeakPersistentHandle(
-      const ApiState& state,
-      Dart_Handle object);
+      Dart_WeakPersistentHandle object);
 
   // Returns an Error handle if isolate is in an inconsistent state.
   // Returns a Success handle when no error condition exists.
@@ -101,7 +95,7 @@
   static Dart_Isolate CastIsolate(Isolate* isolate);
 
   // Gets the handle used to designate successful return.
-  static Dart_Handle Success(Isolate* isolate);
+  static Dart_Handle Success() { return Api::True(); }
 
   // Sets up the acquired error object after initializing an Isolate. This
   // object is pre-created because we will not be able to allocate this
@@ -140,13 +134,13 @@
   static Dart_Handle NewError(const char* format, ...) PRINTF_ATTRIBUTE(1, 2);
 
   // Gets a handle to Null.
-  static Dart_Handle Null(Isolate* isolate);
+  static Dart_Handle Null();
 
   // Gets a handle to True.
-  static Dart_Handle True(Isolate* isolate);
+  static Dart_Handle True();
 
   // Gets a handle to False
-  static Dart_Handle False(Isolate* isolate);
+  static Dart_Handle False();
 
   // Retrieves the top ApiLocalScope.
   static ApiLocalScope* TopScope(Isolate* isolate);
@@ -154,6 +148,9 @@
   // Performs one-time initialization needed by the API.
   static void InitOnce();
 
+  // Allocates handles for objects in the VM isolate.
+  static void InitHandles();
+
   // Helper function to get the peer value of an external string object.
   static bool ExternalStringGetPeerHelper(Dart_Handle object, void** peer);
 
@@ -161,6 +158,9 @@
   // Thread local key used by the API. Currently holds the current
   // ApiNativeScope if any.
   static ThreadLocalKey api_native_key_;
+  static Dart_Handle true_handle_;
+  static Dart_Handle false_handle_;
+  static Dart_Handle null_handle_;
 
   friend class ApiNativeScope;
 };
diff --git a/runtime/vm/dart_api_impl_test.cc b/runtime/vm/dart_api_impl_test.cc
index 76bdc4c..9368382 100644
--- a/runtime/vm/dart_api_impl_test.cc
+++ b/runtime/vm/dart_api_impl_test.cc
@@ -931,8 +931,7 @@
   Dart_EnterScope();
   Dart_Handle external_byte_data = Dart_NewExternalTypedData(kByteData,
                                                              data,
-                                                             16,
-                                                             NULL, NULL);
+                                                             16);
   EXPECT_VALID(external_byte_data);
   EXPECT_EQ(kByteData, Dart_GetTypeOfTypedData(external_byte_data));
   Dart_SetReturnValue(args, external_byte_data);
@@ -1106,9 +1105,7 @@
   intptr_t data_length = ARRAY_SIZE(data);
   Dart_Handle ext_list_access_test_obj;
   ext_list_access_test_obj = Dart_NewExternalTypedData(kUint8,
-                                                       data,
-                                                       data_length,
-                                                       NULL, NULL);
+                                                       data, data_length);
   EXPECT_VALID(ext_list_access_test_obj);
   TestDirectAccess(lib, ext_list_access_test_obj, kUint8);
 }
@@ -1209,10 +1206,6 @@
   EXPECT_EQ(expected_type, type);
   EXPECT_VALID(Dart_TypedDataReleaseData(obj));
 
-  void* peer = &data;  // just a non-NULL value
-  EXPECT_VALID(Dart_ExternalTypedDataGetPeer(obj, &peer));
-  EXPECT(peer == NULL);
-
   intptr_t list_length = 0;
   EXPECT_VALID(Dart_ListLength(obj, &list_length));
   EXPECT_EQ(data_length, list_length);
@@ -1257,9 +1250,7 @@
   uint8_t data[] = { 0, 11, 22, 33, 44, 55, 66, 77 };
   intptr_t data_length = ARRAY_SIZE(data);
 
-  Dart_Handle obj = Dart_NewExternalTypedData(kUint8,
-                                              data, data_length,
-                                              NULL, NULL);
+  Dart_Handle obj = Dart_NewExternalTypedData(kUint8, data, data_length);
   ExternalTypedDataAccessTests(obj, kUint8, data, data_length);
 }
 
@@ -1268,9 +1259,7 @@
   uint8_t data[] = { 0, 11, 22, 33, 44, 55, 66, 77 };
   intptr_t data_length = ARRAY_SIZE(data);
 
-  Dart_Handle obj = Dart_NewExternalTypedData(kUint8Clamped,
-                                              data, data_length,
-                                              NULL, NULL);
+  Dart_Handle obj = Dart_NewExternalTypedData(kUint8Clamped, data, data_length);
   ExternalTypedDataAccessTests(obj, kUint8Clamped, data, data_length);
 }
 
@@ -1291,8 +1280,7 @@
   uint8_t data[] = { 0, 11, 22, 33, 44, 55, 66, 77 };
   intptr_t data_length = ARRAY_SIZE(data);
   Dart_Handle obj = Dart_NewExternalTypedData(kUint8Clamped,
-                                              data, data_length,
-                                              NULL, NULL);
+                                              data, data_length);
   EXPECT_VALID(obj);
   Dart_Handle result;
   // Create a test library and Load up a test script in it.
@@ -1311,9 +1299,9 @@
 }
 
 
-static void ExternalTypedDataCallbackFinalizer(Dart_Handle handle,
+static void ExternalTypedDataFinalizer(Dart_WeakPersistentHandle handle,
                                                void* peer) {
-  Dart_DeletePersistentHandle(handle);
+  Dart_DeleteWeakPersistentHandle(handle);
   *static_cast<int*>(peer) = 42;
 }
 
@@ -1326,13 +1314,9 @@
     Dart_Handle obj = Dart_NewExternalTypedData(
         kUint8,
         data,
-        ARRAY_SIZE(data),
-        &peer,
-        ExternalTypedDataCallbackFinalizer);
+        ARRAY_SIZE(data));
+    Dart_NewWeakPersistentHandle(obj, &peer, ExternalTypedDataFinalizer);
     EXPECT_VALID(obj);
-    void* api_peer = NULL;
-    EXPECT_VALID(Dart_ExternalTypedDataGetPeer(obj, &api_peer));
-    EXPECT_EQ(api_peer, &peer);
     Dart_ExitScope();
   }
   EXPECT(peer == 0);
@@ -1384,8 +1368,8 @@
   // Dart_NewExternalTypedData.
   Dart_EnterScope();
   {
-    Dart_Handle lcl = Dart_NewExternalTypedData(
-        kFloat32x4, data, 10, &peer, ExternalTypedDataCallbackFinalizer);
+    Dart_Handle lcl = Dart_NewExternalTypedData(kFloat32x4, data, 10);
+    Dart_NewWeakPersistentHandle(lcl, &peer, ExternalTypedDataFinalizer);
     CheckFloat32x4Data(lcl);
   }
   Dart_ExitScope();
@@ -1429,7 +1413,7 @@
   ApiState* state = isolate->api_state();
   EXPECT(state != NULL);
   ApiLocalScope* scope = state->top_scope();
-  Dart_Handle handles[2000];
+  Dart_PersistentHandle handles[2000];
   Dart_EnterScope();
   {
     DARTSCOPE(isolate);
@@ -1460,22 +1444,22 @@
     HANDLESCOPE(isolate);
     for (int i = 0; i < 500; i++) {
       String& str = String::Handle();
-      str ^= Api::UnwrapHandle(handles[i]);
+      str ^= Api::UnwrapAsPersistentHandle(handles[i])->raw();
       EXPECT(str.Equals(kTestString1));
     }
     for (int i = 500; i < 1000; i++) {
       String& str = String::Handle();
-      str ^= Api::UnwrapHandle(handles[i]);
+      str ^= Api::UnwrapAsPersistentHandle(handles[i])->raw();
       EXPECT(str.Equals(kTestString2));
     }
     for (int i = 1000; i < 1500; i++) {
       String& str = String::Handle();
-      str ^= Api::UnwrapHandle(handles[i]);
+      str ^= Api::UnwrapAsPersistentHandle(handles[i])->raw();
       EXPECT(str.Equals(kTestString1));
     }
     for (int i = 1500; i < 2000; i++) {
       String& str = String::Handle();
-      str ^= Api::UnwrapHandle(handles[i]);
+      str ^= Api::UnwrapAsPersistentHandle(handles[i])->raw();
       EXPECT(str.Equals(kTestString2));
     }
   }
@@ -1497,17 +1481,19 @@
   DARTSCOPE(isolate);
 
   // Start with a known persistent handle.
-  Dart_Handle obj1 = Dart_True();
+  Dart_PersistentHandle obj1 = Dart_NewPersistentHandle(Dart_True());
   EXPECT(state->IsValidPersistentHandle(obj1));
 
   // And use it to allocate a second persistent handle.
-  Dart_Handle obj2 = Dart_NewPersistentHandle(obj1);
-  EXPECT(state->IsValidPersistentHandle(obj2));
+  Dart_Handle obj2 = Dart_HandleFromPersistent(obj1);
+  Dart_PersistentHandle obj3 = Dart_NewPersistentHandle(obj2);
+  EXPECT(state->IsValidPersistentHandle(obj3));
 
   // Make sure that the value transferred.
-  EXPECT(Dart_IsBoolean(obj2));
+  Dart_Handle obj4 = Dart_HandleFromPersistent(obj3);
+  EXPECT(Dart_IsBoolean(obj4));
   bool value = false;
-  Dart_Handle result = Dart_BooleanValue(obj2, &value);
+  Dart_Handle result = Dart_BooleanValue(obj4, &value);
   EXPECT_VALID(result);
   EXPECT(value);
 }
@@ -1526,12 +1512,24 @@
 };
 
 
-TEST_CASE(WeakPersistentHandle) {
-  Dart_Handle weak_new_ref = Dart_Null();
-  EXPECT(Dart_IsNull(weak_new_ref));
+static Dart_Handle AsHandle(Dart_PersistentHandle weak) {
+  return Dart_HandleFromPersistent(weak);
+}
 
-  Dart_Handle weak_old_ref = Dart_Null();
-  EXPECT(Dart_IsNull(weak_old_ref));
+
+static Dart_Handle AsHandle(Dart_WeakPersistentHandle weak) {
+  return Dart_HandleFromWeakPersistent(weak);
+}
+
+
+TEST_CASE(WeakPersistentHandle) {
+  Dart_Handle local_new_ref = Dart_Null();
+  Dart_WeakPersistentHandle weak_new_ref = Dart_NewWeakPersistentHandle(
+      local_new_ref, NULL, NULL);
+
+  Dart_Handle local_old_ref = Dart_Null();
+  Dart_WeakPersistentHandle weak_old_ref = Dart_NewWeakPersistentHandle(
+      local_old_ref, NULL, NULL);
 
   {
     Dart_EnterScope();
@@ -1551,13 +1549,13 @@
 
     // Create a weak ref to the new space object.
     weak_new_ref = Dart_NewWeakPersistentHandle(new_ref, NULL, NULL);
-    EXPECT_VALID(weak_new_ref);
-    EXPECT(!Dart_IsNull(weak_new_ref));
+    EXPECT_VALID(AsHandle(weak_new_ref));
+    EXPECT(!Dart_IsNull(AsHandle(weak_new_ref)));
 
     // Create a weak ref to the old space object.
     weak_old_ref = Dart_NewWeakPersistentHandle(old_ref, NULL, NULL);
-    EXPECT_VALID(weak_old_ref);
-    EXPECT(!Dart_IsNull(weak_old_ref));
+    EXPECT_VALID(AsHandle(weak_old_ref));
+    EXPECT(!Dart_IsNull(AsHandle(weak_old_ref)));
 
     // Garbage collect new space.
     GCTestHelper::CollectNewSpace(Heap::kIgnoreApiCallbacks);
@@ -1568,13 +1566,13 @@
     EXPECT_VALID(old_ref);
     EXPECT(!Dart_IsNull(old_ref));
 
-    EXPECT_VALID(weak_new_ref);
-    EXPECT(!Dart_IsNull(weak_new_ref));
-    EXPECT(Dart_IdentityEquals(new_ref, weak_new_ref));
+    EXPECT_VALID(AsHandle(weak_new_ref));
+    EXPECT(!Dart_IsNull(AsHandle(weak_new_ref)));
+    EXPECT(Dart_IdentityEquals(new_ref, AsHandle(weak_new_ref)));
 
-    EXPECT_VALID(weak_old_ref);
-    EXPECT(!Dart_IsNull(weak_old_ref));
-    EXPECT(Dart_IdentityEquals(old_ref, weak_old_ref));
+    EXPECT_VALID(AsHandle(weak_old_ref));
+    EXPECT(!Dart_IsNull(AsHandle(weak_old_ref)));
+    EXPECT(Dart_IdentityEquals(old_ref, AsHandle(weak_old_ref)));
 
     // Garbage collect old space.
     Isolate::Current()->heap()->CollectGarbage(Heap::kOld);
@@ -1585,13 +1583,13 @@
     EXPECT_VALID(old_ref);
     EXPECT(!Dart_IsNull(old_ref));
 
-    EXPECT_VALID(weak_new_ref);
-    EXPECT(!Dart_IsNull(weak_new_ref));
-    EXPECT(Dart_IdentityEquals(new_ref, weak_new_ref));
+    EXPECT_VALID(AsHandle(weak_new_ref));
+    EXPECT(!Dart_IsNull(AsHandle(weak_new_ref)));
+    EXPECT(Dart_IdentityEquals(new_ref, AsHandle(weak_new_ref)));
 
-    EXPECT_VALID(weak_old_ref);
-    EXPECT(!Dart_IsNull(weak_old_ref));
-    EXPECT(Dart_IdentityEquals(old_ref, weak_old_ref));
+    EXPECT_VALID(AsHandle(weak_old_ref));
+    EXPECT(!Dart_IsNull(AsHandle(weak_old_ref)));
+    EXPECT(Dart_IdentityEquals(old_ref, AsHandle(weak_old_ref)));
 
     // Delete local (strong) references.
     Dart_ExitScope();
@@ -1600,23 +1598,31 @@
   // Garbage collect new space again.
   GCTestHelper::CollectNewSpace(Heap::kIgnoreApiCallbacks);
 
-  // Weak ref to new space object should now be cleared.
-  EXPECT_VALID(weak_new_ref);
-  EXPECT(Dart_IsNull(weak_new_ref));
-  EXPECT_VALID(weak_old_ref);
-  EXPECT(!Dart_IsNull(weak_old_ref));
+  {
+    Dart_EnterScope();
+    // Weak ref to new space object should now be cleared.
+    EXPECT_VALID(AsHandle(weak_new_ref));
+    EXPECT(Dart_IsNull(AsHandle(weak_new_ref)));
+    EXPECT_VALID(AsHandle(weak_old_ref));
+    EXPECT(!Dart_IsNull(AsHandle(weak_old_ref)));
+    Dart_ExitScope();
+  }
 
   // Garbage collect old space again.
   Isolate::Current()->heap()->CollectGarbage(Heap::kOld);
 
-  // Weak ref to old space object should now be cleared.
-  EXPECT_VALID(weak_new_ref);
-  EXPECT(Dart_IsNull(weak_new_ref));
-  EXPECT_VALID(weak_old_ref);
-  EXPECT(Dart_IsNull(weak_old_ref));
+  {
+    Dart_EnterScope();
+    // Weak ref to old space object should now be cleared.
+    EXPECT_VALID(AsHandle(weak_new_ref));
+    EXPECT(Dart_IsNull(AsHandle(weak_new_ref)));
+    EXPECT_VALID(AsHandle(weak_old_ref));
+    EXPECT(Dart_IsNull(AsHandle(weak_old_ref)));
+    Dart_ExitScope();
+  }
 
-  Dart_DeletePersistentHandle(weak_new_ref);
-  Dart_DeletePersistentHandle(weak_old_ref);
+  Dart_DeleteWeakPersistentHandle(weak_new_ref);
+  Dart_DeleteWeakPersistentHandle(weak_old_ref);
 
   // Garbage collect one last time to revisit deleted handles.
   Isolate::Current()->heap()->CollectGarbage(Heap::kNew);
@@ -1624,14 +1630,14 @@
 }
 
 
-static void WeakPersistentHandlePeerFinalizer(Dart_Handle handle, void* peer) {
+static void WeakPersistentHandlePeerFinalizer(
+    Dart_WeakPersistentHandle handle, void* peer) {
   *static_cast<int*>(peer) = 42;
 }
 
 
 TEST_CASE(WeakPersistentHandleCallback) {
-  Dart_Handle weak_ref = Dart_Null();
-  EXPECT(Dart_IsNull(weak_ref));
+  Dart_WeakPersistentHandle weak_ref = NULL;
   int peer = 0;
   {
     Dart_EnterScope();
@@ -1639,21 +1645,20 @@
     EXPECT_VALID(obj);
     weak_ref = Dart_NewWeakPersistentHandle(obj, &peer,
                                             WeakPersistentHandlePeerFinalizer);
+    EXPECT_VALID(AsHandle(weak_ref));
+    EXPECT(peer == 0);
     Dart_ExitScope();
   }
-  EXPECT_VALID(weak_ref);
-  EXPECT(peer == 0);
   Isolate::Current()->heap()->CollectGarbage(Heap::kOld);
   EXPECT(peer == 0);
   GCTestHelper::CollectNewSpace(Heap::kIgnoreApiCallbacks);
   EXPECT(peer == 42);
-  Dart_DeletePersistentHandle(weak_ref);
+  Dart_DeleteWeakPersistentHandle(weak_ref);
 }
 
 
 TEST_CASE(WeakPersistentHandleNoCallback) {
-  Dart_Handle weak_ref = Dart_Null();
-  EXPECT(Dart_IsNull(weak_ref));
+  Dart_WeakPersistentHandle weak_ref = NULL;
   int peer = 0;
   {
     Dart_EnterScope();
@@ -1665,8 +1670,7 @@
   }
   // A finalizer is not invoked on a deleted handle.  Therefore, the
   // peer value should not change after the referent is collected.
-  Dart_DeletePersistentHandle(weak_ref);
-  EXPECT_VALID(weak_ref);
+  Dart_DeleteWeakPersistentHandle(weak_ref);
   EXPECT(peer == 0);
   Isolate::Current()->heap()->CollectGarbage(Heap::kOld);
   EXPECT(peer == 0);
@@ -1689,116 +1693,125 @@
 
 
 TEST_CASE(ObjectGroups) {
-  Dart_Handle strong = Dart_Null();
-  EXPECT(Dart_IsNull(strong));
+  Dart_PersistentHandle strong = NULL;
+  Dart_WeakPersistentHandle strong_weak = NULL;
 
-  Dart_Handle weak1 = Dart_Null();
-  EXPECT(Dart_IsNull(weak1));
-
-  Dart_Handle weak2 = Dart_Null();
-  EXPECT(Dart_IsNull(weak2));
-
-  Dart_Handle weak3 = Dart_Null();
-  EXPECT(Dart_IsNull(weak3));
-
-  Dart_Handle weak4 = Dart_Null();
-  EXPECT(Dart_IsNull(weak4));
+  Dart_WeakPersistentHandle weak1 = NULL;
+  Dart_WeakPersistentHandle weak2 = NULL;
+  Dart_WeakPersistentHandle weak3 = NULL;
+  Dart_WeakPersistentHandle weak4 = NULL;
 
   Dart_EnterScope();
   {
     Isolate* isolate = Isolate::Current();
     DARTSCOPE(isolate);
 
-    strong = Dart_NewPersistentHandle(
-        Api::NewHandle(isolate, String::New("strongly reachable", Heap::kOld)));
-    EXPECT_VALID(strong);
-    EXPECT(!Dart_IsNull(strong));
+    Dart_Handle local = Api::NewHandle(
+        isolate, String::New("strongly reachable", Heap::kOld));
+    strong = Dart_NewPersistentHandle(local);
+    strong_weak = Dart_NewWeakPersistentHandle(local, NULL, NULL);
+    EXPECT_VALID(AsHandle(strong));
+    EXPECT(!Dart_IsNull(AsHandle(strong)));
 
     weak1 = Dart_NewWeakPersistentHandle(
         Api::NewHandle(isolate, String::New("weakly reachable 1", Heap::kOld)),
         NULL, NULL);
-    EXPECT_VALID(weak1);
-    EXPECT(!Dart_IsNull(weak1));
+    EXPECT_VALID(AsHandle(weak1));
+    EXPECT(!Dart_IsNull(AsHandle(weak1)));
 
     weak2 = Dart_NewWeakPersistentHandle(
         Api::NewHandle(isolate, String::New("weakly reachable 2", Heap::kOld)),
         NULL, NULL);
-    EXPECT_VALID(weak2);
-    EXPECT(!Dart_IsNull(weak2));
+    EXPECT_VALID(AsHandle(weak2));
+    EXPECT(!Dart_IsNull(AsHandle(weak2)));
 
     weak3 = Dart_NewWeakPersistentHandle(
         Api::NewHandle(isolate, String::New("weakly reachable 3", Heap::kOld)),
         NULL, NULL);
-    EXPECT_VALID(weak3);
-    EXPECT(!Dart_IsNull(weak3));
+    EXPECT_VALID(AsHandle(weak3));
+    EXPECT(!Dart_IsNull(AsHandle(weak3)));
 
     weak4 = Dart_NewWeakPersistentHandle(
         Api::NewHandle(isolate, String::New("weakly reachable 4", Heap::kOld)),
         NULL, NULL);
-    EXPECT_VALID(weak4);
-    EXPECT(!Dart_IsNull(weak4));
+    EXPECT_VALID(AsHandle(weak4));
+    EXPECT(!Dart_IsNull(AsHandle(weak4)));
   }
   Dart_ExitScope();
 
-  EXPECT_VALID(strong);
-
-  EXPECT_VALID(weak1);
-  EXPECT_VALID(weak2);
-  EXPECT_VALID(weak3);
-  EXPECT_VALID(weak4);
+  {
+    Dart_EnterScope();
+    EXPECT_VALID(AsHandle(strong));
+    EXPECT_VALID(AsHandle(weak1));
+    EXPECT_VALID(AsHandle(weak2));
+    EXPECT_VALID(AsHandle(weak3));
+    EXPECT_VALID(AsHandle(weak4));
+    Dart_ExitScope();
+  }
 
   GCTestHelper::CollectNewSpace(Heap::kIgnoreApiCallbacks);
 
-  // New space collection should not affect old space objects
-  EXPECT(!Dart_IsNull(weak1));
-  EXPECT(!Dart_IsNull(weak2));
-  EXPECT(!Dart_IsNull(weak3));
-  EXPECT(!Dart_IsNull(weak4));
+  {
+    Dart_EnterScope();
+    // New space collection should not affect old space objects
+    EXPECT(!Dart_IsNull(AsHandle(weak1)));
+    EXPECT(!Dart_IsNull(AsHandle(weak2)));
+    EXPECT(!Dart_IsNull(AsHandle(weak3)));
+    EXPECT(!Dart_IsNull(AsHandle(weak4)));
+    Dart_ExitScope();
+  }
 
   {
-    Dart_Handle array1[] = { weak1, strong };
+    Dart_WeakPersistentHandle array1[] = { weak1, strong_weak };
     EXPECT_VALID(Dart_NewWeakReferenceSet(array1, ARRAY_SIZE(array1),
                                           array1, ARRAY_SIZE(array1)));
 
-    Dart_Handle array2[] = { weak2, weak1 };
+    Dart_WeakPersistentHandle array2[] = { weak2, weak1 };
     EXPECT_VALID(Dart_NewWeakReferenceSet(array2, ARRAY_SIZE(array2),
                                           array2, ARRAY_SIZE(array2)));
 
-    Dart_Handle array3[] = { weak3, weak2 };
+    Dart_WeakPersistentHandle array3[] = { weak3, weak2 };
     EXPECT_VALID(Dart_NewWeakReferenceSet(array3, ARRAY_SIZE(array3),
                                           array3, ARRAY_SIZE(array3)));
 
-    Dart_Handle array4[] = { weak4, weak3 };
+    Dart_WeakPersistentHandle array4[] = { weak4, weak3 };
     EXPECT_VALID(Dart_NewWeakReferenceSet(array4, ARRAY_SIZE(array4),
                                           array4, ARRAY_SIZE(array4)));
 
     Isolate::Current()->heap()->CollectGarbage(Heap::kOld);
   }
 
-  // All weak references should be preserved.
-  EXPECT(!Dart_IsNull(weak1));
-  EXPECT(!Dart_IsNull(weak2));
-  EXPECT(!Dart_IsNull(weak3));
-  EXPECT(!Dart_IsNull(weak4));
+  {
+    Dart_EnterScope();
+    // All weak references should be preserved.
+    EXPECT(!Dart_IsNull(AsHandle(strong_weak)));
+    EXPECT(!Dart_IsNull(AsHandle(weak1)));
+    EXPECT(!Dart_IsNull(AsHandle(weak2)));
+    EXPECT(!Dart_IsNull(AsHandle(weak3)));
+    EXPECT(!Dart_IsNull(AsHandle(weak4)));
+    Dart_ExitScope();
+  }
 
   {
-    Dart_Handle array1[] = { weak1, strong };
+    Dart_EnterScope();
+    Dart_WeakPersistentHandle array1[] = { weak1, strong_weak };
     EXPECT_VALID(Dart_NewWeakReferenceSet(array1, ARRAY_SIZE(array1),
                                           array1, ARRAY_SIZE(array1)));
 
-    Dart_Handle array2[] = { weak2, weak1 };
+    Dart_WeakPersistentHandle array2[] = { weak2, weak1 };
     EXPECT_VALID(Dart_NewWeakReferenceSet(array2, ARRAY_SIZE(array2),
                                           array2, ARRAY_SIZE(array2)));
 
-    Dart_Handle array3[] = { weak2 };
+    Dart_WeakPersistentHandle array3[] = { weak2 };
     EXPECT_VALID(Dart_NewWeakReferenceSet(array3, ARRAY_SIZE(array3),
                                           array3, ARRAY_SIZE(array3)));
 
     // Strong reference to weak3 to retain weak3 and weak4.
-    Dart_Handle weak3_strong_ref = Dart_NewPersistentHandle(weak3);
-    EXPECT_VALID(weak3_strong_ref);
+    Dart_PersistentHandle weak3_strong_ref =
+        Dart_NewPersistentHandle(AsHandle(weak3));
+    EXPECT_VALID(AsHandle(weak3_strong_ref));
 
-    Dart_Handle array4[] = { weak4, weak3 };
+    Dart_WeakPersistentHandle array4[] = { weak4, weak3 };
     EXPECT_VALID(Dart_NewWeakReferenceSet(array4, ARRAY_SIZE(array4),
                                           array4, ARRAY_SIZE(array4)));
 
@@ -1806,86 +1819,106 @@
 
     // Delete strong reference to weak3.
     Dart_DeletePersistentHandle(weak3_strong_ref);
+    Dart_ExitScope();
   }
 
-  // All weak references should be preserved.
-  EXPECT(!Dart_IsNull(weak1));
-  EXPECT(!Dart_IsNull(weak2));
-  EXPECT(!Dart_IsNull(weak3));
-  EXPECT(!Dart_IsNull(weak4));
+  {
+    Dart_EnterScope();
+    // All weak references should be preserved.
+    EXPECT(!Dart_IsNull(AsHandle(strong_weak)));
+    EXPECT(!Dart_IsNull(AsHandle(weak1)));
+    EXPECT(!Dart_IsNull(AsHandle(weak2)));
+    EXPECT(!Dart_IsNull(AsHandle(weak3)));
+    EXPECT(!Dart_IsNull(AsHandle(weak4)));
+    Dart_ExitScope();
+  }
 
   {
-    Dart_Handle array1[] = { weak1, strong };
+    Dart_WeakPersistentHandle array1[] = { weak1, strong_weak };
     EXPECT_VALID(Dart_NewWeakReferenceSet(array1, ARRAY_SIZE(array1),
                                           array1, ARRAY_SIZE(array1)));
 
-    Dart_Handle array2[] = { weak2, weak1 };
+    Dart_WeakPersistentHandle array2[] = { weak2, weak1 };
     EXPECT_VALID(Dart_NewWeakReferenceSet(array2, ARRAY_SIZE(array2),
                                           array2, ARRAY_SIZE(array2)));
 
-    Dart_Handle array3[] = { weak2 };
+    Dart_WeakPersistentHandle array3[] = { weak2 };
     EXPECT_VALID(Dart_NewWeakReferenceSet(array3, ARRAY_SIZE(array3),
                                           array3, ARRAY_SIZE(array3)));
 
-    Dart_Handle array4[] = { weak4, weak3 };
+    Dart_WeakPersistentHandle array4[] = { weak4, weak3 };
     EXPECT_VALID(Dart_NewWeakReferenceSet(array4, ARRAY_SIZE(array4),
                                           array4, ARRAY_SIZE(array4)));
 
     Isolate::Current()->heap()->CollectGarbage(Heap::kOld);
   }
 
-  // Only weak1 and weak2 should be preserved.
-  EXPECT(!Dart_IsNull(weak1));
-  EXPECT(!Dart_IsNull(weak2));
-  EXPECT(Dart_IsNull(weak3));
-  EXPECT(Dart_IsNull(weak4));
+  {
+    Dart_EnterScope();
+    // Only weak1 and weak2 should be preserved.
+    EXPECT(!Dart_IsNull(AsHandle(strong_weak)));
+    EXPECT(!Dart_IsNull(AsHandle(weak1)));
+    EXPECT(!Dart_IsNull(AsHandle(weak2)));
+    EXPECT(Dart_IsNull(AsHandle(weak3)));
+    EXPECT(Dart_IsNull(AsHandle(weak4)));
+    Dart_ExitScope();
+  }
 
   {
-    Dart_Handle array1[] = { weak1, strong };
+    Dart_WeakPersistentHandle array1[] = { weak1, strong_weak };
     EXPECT_VALID(Dart_NewWeakReferenceSet(array1, ARRAY_SIZE(array1),
                                           array1, ARRAY_SIZE(array1)));
 
     // weak3 is cleared so weak2 is unreferenced and should be cleared
-    Dart_Handle array2[] = { weak2, weak3 };
+    Dart_WeakPersistentHandle array2[] = { weak2, weak3 };
     EXPECT_VALID(Dart_NewWeakReferenceSet(array2, ARRAY_SIZE(array2),
                                           array2, ARRAY_SIZE(array2)));
 
     Isolate::Current()->heap()->CollectGarbage(Heap::kOld);
   }
 
-  // Only weak1 should be preserved, weak3 should not preserve weak2.
-  EXPECT(!Dart_IsNull(weak1));
-  EXPECT(Dart_IsNull(weak2));
-  EXPECT(Dart_IsNull(weak3));  // was cleared, should remain cleared
-  EXPECT(Dart_IsNull(weak4));  // was cleared, should remain cleared
+  {
+    Dart_EnterScope();
+    // Only weak1 should be preserved, weak3 should not preserve weak2.
+    EXPECT(!Dart_IsNull(AsHandle(strong_weak)));
+    EXPECT(!Dart_IsNull(AsHandle(weak1)));
+    EXPECT(Dart_IsNull(AsHandle(weak2)));
+    EXPECT(Dart_IsNull(AsHandle(weak3)));  // was cleared, should remain cleared
+    EXPECT(Dart_IsNull(AsHandle(weak4)));  // was cleared, should remain cleared
+    Dart_ExitScope();
+  }
 
   {
     // weak{2,3,4} are cleared and should have no effect on weak1
-    Dart_Handle array1[] = { strong, weak2, weak3, weak4 };
+    Dart_WeakPersistentHandle array1[] = { strong_weak, weak2, weak3, weak4 };
     EXPECT_VALID(Dart_NewWeakReferenceSet(array1, ARRAY_SIZE(array1),
                                           array1, ARRAY_SIZE(array1)));
 
     // weak1 is weakly reachable and should be cleared
-    Dart_Handle array2[] = { weak1 };
+    Dart_WeakPersistentHandle array2[] = { weak1 };
     EXPECT_VALID(Dart_NewWeakReferenceSet(array2, ARRAY_SIZE(array2),
                                           array2, ARRAY_SIZE(array2)));
 
     Isolate::Current()->heap()->CollectGarbage(Heap::kOld);
   }
 
-  // All weak references should now be cleared.
-  EXPECT(Dart_IsNull(weak1));
-  EXPECT(Dart_IsNull(weak2));
-  EXPECT(Dart_IsNull(weak3));
-  EXPECT(Dart_IsNull(weak4));
+  {
+    Dart_EnterScope();
+    // All weak references should now be cleared.
+    EXPECT(!Dart_IsNull(AsHandle(strong_weak)));
+    EXPECT(Dart_IsNull(AsHandle(weak1)));
+    EXPECT(Dart_IsNull(AsHandle(weak2)));
+    EXPECT(Dart_IsNull(AsHandle(weak3)));
+    EXPECT(Dart_IsNull(AsHandle(weak4)));
+    Dart_ExitScope();
+  }
 }
 
 
 TEST_CASE(PrologueWeakPersistentHandles) {
-  Dart_Handle old_pwph = Dart_Null();
-  EXPECT(Dart_IsNull(old_pwph));
-  Dart_Handle new_pwph = Dart_Null();
-  EXPECT(Dart_IsNull(new_pwph));
+  Dart_WeakPersistentHandle old_pwph = NULL;
+  Dart_WeakPersistentHandle new_pwph = NULL;
+
   Dart_EnterScope();
   {
     Isolate* isolate = Isolate::Current();
@@ -1894,215 +1927,276 @@
         Api::NewHandle(isolate,
                        String::New("new space prologue weak", Heap::kNew)),
         NULL, NULL);
-    EXPECT_VALID(new_pwph);
-    EXPECT(!Dart_IsNull(new_pwph));
+    EXPECT_VALID(AsHandle(new_pwph));
+    EXPECT(!Dart_IsNull(AsHandle(new_pwph)));
     old_pwph = Dart_NewPrologueWeakPersistentHandle(
         Api::NewHandle(isolate,
                        String::New("old space prologue weak", Heap::kOld)),
         NULL, NULL);
-    EXPECT_VALID(old_pwph);
-    EXPECT(!Dart_IsNull(old_pwph));
+    EXPECT_VALID(AsHandle(old_pwph));
+    EXPECT(!Dart_IsNull(AsHandle(old_pwph)));
   }
   Dart_ExitScope();
-  EXPECT_VALID(new_pwph);
-  EXPECT(!Dart_IsNull(new_pwph));
-  EXPECT(Dart_IsPrologueWeakPersistentHandle(new_pwph));
-  EXPECT_VALID(old_pwph);
-  EXPECT(!Dart_IsNull(old_pwph));
-  EXPECT(Dart_IsPrologueWeakPersistentHandle(old_pwph));
+
+  {
+    Dart_EnterScope();
+    EXPECT_VALID(AsHandle(new_pwph));
+    EXPECT(!Dart_IsNull(AsHandle(new_pwph)));
+    EXPECT(Dart_IsPrologueWeakPersistentHandle(new_pwph));
+    EXPECT_VALID(AsHandle(old_pwph));
+    EXPECT(!Dart_IsNull(AsHandle(old_pwph)));
+    EXPECT(Dart_IsPrologueWeakPersistentHandle(old_pwph));
+    Dart_ExitScope();
+  }
+
   // Garbage collect new space without invoking API callbacks.
   GCTestHelper::CollectNewSpace(Heap::kIgnoreApiCallbacks);
 
-  // Both prologue weak handles should be preserved.
-  EXPECT(!Dart_IsNull(new_pwph));
-  EXPECT(!Dart_IsNull(old_pwph));
+  {
+    Dart_EnterScope();
+    // Both prologue weak handles should be preserved.
+    EXPECT(!Dart_IsNull(AsHandle(new_pwph)));
+    EXPECT(!Dart_IsNull(AsHandle(old_pwph)));
+    Dart_ExitScope();
+  }
+
   // Garbage collect old space without invoking API callbacks.
   Isolate::Current()->heap()->CollectGarbage(Heap::kOld,
                                              Heap::kIgnoreApiCallbacks);
-  // Both prologue weak handles should be preserved.
-  EXPECT(!Dart_IsNull(new_pwph));
-  EXPECT(!Dart_IsNull(old_pwph));
+
+  {
+    Dart_EnterScope();
+    // Both prologue weak handles should be preserved.
+    EXPECT(!Dart_IsNull(AsHandle(new_pwph)));
+    EXPECT(!Dart_IsNull(AsHandle(old_pwph)));
+    Dart_ExitScope();
+  }
+
   // Garbage collect new space invoking API callbacks.
   GCTestHelper::CollectNewSpace(Heap::kInvokeApiCallbacks);
 
-  // The prologue weak handle with a new space referent should now be
-  // cleared.  The old space referent should be preserved.
-  EXPECT(Dart_IsNull(new_pwph));
-  EXPECT(!Dart_IsNull(old_pwph));
+  {
+    Dart_EnterScope();
+    // The prologue weak handle with a new space referent should now be
+    // cleared.  The old space referent should be preserved.
+    EXPECT(Dart_IsNull(AsHandle(new_pwph)));
+    EXPECT(!Dart_IsNull(AsHandle(old_pwph)));
+    Dart_ExitScope();
+  }
+
   Isolate::Current()->heap()->CollectGarbage(Heap::kOld,
                                              Heap::kInvokeApiCallbacks);
-  // The prologue weak handle with an old space referent should now be
-  // cleared.  The new space referent should remain cleared.
-  EXPECT(Dart_IsNull(new_pwph));
-  EXPECT(Dart_IsNull(old_pwph));
+
+  {
+    Dart_EnterScope();
+    // The prologue weak handle with an old space referent should now be
+    // cleared.  The new space referent should remain cleared.
+    EXPECT(Dart_IsNull(AsHandle(new_pwph)));
+    EXPECT(Dart_IsNull(AsHandle(old_pwph)));
+    Dart_ExitScope();
+  }
 }
 
 
 TEST_CASE(ImplicitReferencesOldSpace) {
-  Dart_Handle strong = Dart_Null();
-  EXPECT(Dart_IsNull(strong));
+  Dart_PersistentHandle strong = NULL;
+  Dart_WeakPersistentHandle strong_weak = NULL;
 
-  Dart_Handle weak1 = Dart_Null();
-  EXPECT(Dart_IsNull(weak1));
-
-  Dart_Handle weak2 = Dart_Null();
-  EXPECT(Dart_IsNull(weak2));
-
-  Dart_Handle weak3 = Dart_Null();
-  EXPECT(Dart_IsNull(weak3));
+  Dart_WeakPersistentHandle weak1 = NULL;
+  Dart_WeakPersistentHandle weak2 = NULL;
+  Dart_WeakPersistentHandle weak3 = NULL;
 
   Dart_EnterScope();
   {
     Isolate* isolate = Isolate::Current();
     DARTSCOPE(isolate);
 
-    strong = Dart_NewPersistentHandle(
-        Api::NewHandle(isolate, String::New("strongly reachable", Heap::kOld)));
-    EXPECT(!Dart_IsNull(strong));
-    EXPECT_VALID(strong);
+    Dart_Handle local = Api::NewHandle(
+        isolate, String::New("strongly reachable", Heap::kOld));
+    strong = Dart_NewPersistentHandle(local);
+    strong_weak = Dart_NewWeakPersistentHandle(local, NULL, NULL);
+
+    EXPECT(!Dart_IsNull(AsHandle(strong)));
+    EXPECT_VALID(AsHandle(strong));
+    EXPECT(!Dart_IsNull(AsHandle(strong_weak)));
+    EXPECT_VALID(AsHandle(strong_weak));
+    EXPECT(Dart_IdentityEquals(AsHandle(strong), AsHandle(strong_weak)))
 
     weak1 = Dart_NewWeakPersistentHandle(
         Api::NewHandle(isolate, String::New("weakly reachable 1", Heap::kOld)),
         NULL, NULL);
-    EXPECT(!Dart_IsNull(weak1));
-    EXPECT_VALID(weak1);
+    EXPECT(!Dart_IsNull(AsHandle(weak1)));
+    EXPECT_VALID(AsHandle(weak1));
 
     weak2 = Dart_NewWeakPersistentHandle(
         Api::NewHandle(isolate, String::New("weakly reachable 2", Heap::kOld)),
         NULL, NULL);
-    EXPECT(!Dart_IsNull(weak2));
-    EXPECT_VALID(weak2);
+    EXPECT(!Dart_IsNull(AsHandle(weak2)));
+    EXPECT_VALID(AsHandle(weak2));
 
     weak3 = Dart_NewWeakPersistentHandle(
         Api::NewHandle(isolate, String::New("weakly reachable 3", Heap::kOld)),
         NULL, NULL);
-    EXPECT(!Dart_IsNull(weak3));
-    EXPECT_VALID(weak3);
+    EXPECT(!Dart_IsNull(AsHandle(weak3)));
+    EXPECT_VALID(AsHandle(weak3));
   }
   Dart_ExitScope();
 
-  EXPECT_VALID(strong);
-
-  EXPECT_VALID(weak1);
-  EXPECT_VALID(weak2);
-  EXPECT_VALID(weak3);
+  {
+    Dart_EnterScope();
+    EXPECT_VALID(AsHandle(strong_weak));
+    EXPECT_VALID(AsHandle(weak1));
+    EXPECT_VALID(AsHandle(weak2));
+    EXPECT_VALID(AsHandle(weak3));
+    Dart_ExitScope();
+  }
 
   GCTestHelper::CollectNewSpace(Heap::kIgnoreApiCallbacks);
 
-  // New space collection should not affect old space objects
-  EXPECT(!Dart_IsNull(weak1));
-  EXPECT(!Dart_IsNull(weak2));
-  EXPECT(!Dart_IsNull(weak3));
+  {
+    Dart_EnterScope();
+    // New space collection should not affect old space objects
+    EXPECT_VALID(AsHandle(strong_weak));
+    EXPECT(!Dart_IsNull(AsHandle(weak1)));
+    EXPECT(!Dart_IsNull(AsHandle(weak2)));
+    EXPECT(!Dart_IsNull(AsHandle(weak3)));
+    Dart_ExitScope();
+  }
 
   // A strongly referenced key should preserve all the values.
   {
-    Dart_Handle keys[] = { strong };
-    Dart_Handle values[] = { weak1, weak2, weak3 };
+    Dart_WeakPersistentHandle keys[] = { strong_weak };
+    Dart_WeakPersistentHandle values[] = { weak1, weak2, weak3 };
     EXPECT_VALID(Dart_NewWeakReferenceSet(keys, ARRAY_SIZE(keys),
                                           values, ARRAY_SIZE(values)));
 
     Isolate::Current()->heap()->CollectGarbage(Heap::kOld);
   }
 
-  // All weak references should be preserved.
-  EXPECT(!Dart_IsNull(weak1));
-  EXPECT(!Dart_IsNull(weak2));
-  EXPECT(!Dart_IsNull(weak3));
+  {
+    Dart_EnterScope();
+    // All weak references should be preserved.
+    EXPECT_VALID(AsHandle(strong_weak));
+    EXPECT(!Dart_IsNull(AsHandle(weak1)));
+    EXPECT(!Dart_IsNull(AsHandle(weak2)));
+    EXPECT(!Dart_IsNull(AsHandle(weak3)));
+    Dart_ExitScope();
+  }
 
   // Key membership does not imply a strong reference.
   {
-    Dart_Handle keys[] = { strong, weak3 };
-    Dart_Handle values[] = { weak1, weak2 };
+    Dart_WeakPersistentHandle keys[] = { strong_weak, weak3 };
+    Dart_WeakPersistentHandle values[] = { weak1, weak2 };
     EXPECT_VALID(Dart_NewWeakReferenceSet(keys, ARRAY_SIZE(keys),
                                           values, ARRAY_SIZE(values)));
 
     Isolate::Current()->heap()->CollectGarbage(Heap::kOld);
   }
 
-  // All weak references except weak3 should be preserved.
-  EXPECT(!Dart_IsNull(weak1));
-  EXPECT(!Dart_IsNull(weak2));
-  EXPECT(Dart_IsNull(weak3));
+  {
+    Dart_EnterScope();
+    // All weak references except weak3 should be preserved.
+    EXPECT(!Dart_IsNull(AsHandle(weak1)));
+    EXPECT(!Dart_IsNull(AsHandle(weak2)));
+    EXPECT(Dart_IsNull(AsHandle(weak3)));
+    Dart_ExitScope();
+  }
 }
 
 
 TEST_CASE(ImplicitReferencesNewSpace) {
-  Dart_Handle strong = Dart_Null();
-  EXPECT(Dart_IsNull(strong));
+  Dart_PersistentHandle strong = NULL;
+  Dart_WeakPersistentHandle strong_weak = NULL;
 
-  Dart_Handle weak1 = Dart_Null();
-  EXPECT(Dart_IsNull(weak1));
-
-  Dart_Handle weak2 = Dart_Null();
-  EXPECT(Dart_IsNull(weak2));
-
-  Dart_Handle weak3 = Dart_Null();
-  EXPECT(Dart_IsNull(weak3));
+  Dart_WeakPersistentHandle weak1 = NULL;
+  Dart_WeakPersistentHandle weak2 = NULL;
+  Dart_WeakPersistentHandle weak3 = NULL;
 
   Dart_EnterScope();
   {
     Isolate* isolate = Isolate::Current();
     DARTSCOPE(isolate);
 
-    strong = Dart_NewPersistentHandle(
-        Api::NewHandle(isolate, String::New("strongly reachable", Heap::kNew)));
-    EXPECT(!Dart_IsNull(strong));
-    EXPECT_VALID(strong);
+    Dart_Handle local = Api::NewHandle(
+        isolate, String::New("strongly reachable", Heap::kOld));
+    strong = Dart_NewPersistentHandle(local);
+    strong_weak = Dart_NewWeakPersistentHandle(local, NULL, NULL);
+
+    EXPECT(!Dart_IsNull(AsHandle(strong)));
+    EXPECT_VALID(AsHandle(strong));
+    EXPECT(!Dart_IsNull(AsHandle(strong_weak)));
+    EXPECT_VALID(AsHandle(strong_weak));
+    EXPECT(Dart_IdentityEquals(AsHandle(strong), AsHandle(strong_weak)))
 
     weak1 = Dart_NewWeakPersistentHandle(
         Api::NewHandle(isolate, String::New("weakly reachable 1", Heap::kNew)),
         NULL, NULL);
-    EXPECT(!Dart_IsNull(weak1));
-    EXPECT_VALID(weak1);
+    EXPECT(!Dart_IsNull(AsHandle(weak1)));
+    EXPECT_VALID(AsHandle(weak1));
 
     weak2 = Dart_NewWeakPersistentHandle(
         Api::NewHandle(isolate, String::New("weakly reachable 2", Heap::kNew)),
         NULL, NULL);
-    EXPECT(!Dart_IsNull(weak2));
-    EXPECT_VALID(weak2);
+    EXPECT(!Dart_IsNull(AsHandle(weak2)));
+    EXPECT_VALID(AsHandle(weak2));
 
     weak3 = Dart_NewWeakPersistentHandle(
         Api::NewHandle(isolate, String::New("weakly reachable 3", Heap::kNew)),
         NULL, NULL);
-    EXPECT(!Dart_IsNull(weak3));
-    EXPECT_VALID(weak3);
+    EXPECT(!Dart_IsNull(AsHandle(weak3)));
+    EXPECT_VALID(AsHandle(weak3));
   }
   Dart_ExitScope();
 
-  EXPECT_VALID(strong);
-
-  EXPECT_VALID(weak1);
-  EXPECT_VALID(weak2);
-  EXPECT_VALID(weak3);
+  {
+    Dart_EnterScope();
+    EXPECT_VALID(AsHandle(strong_weak));
+    EXPECT_VALID(AsHandle(weak1));
+    EXPECT_VALID(AsHandle(weak2));
+    EXPECT_VALID(AsHandle(weak3));
+    Dart_ExitScope();
+  }
 
   Isolate::Current()->heap()->CollectGarbage(Heap::kOld);
 
-  // Old space collection should not affect old space objects.
-  EXPECT(!Dart_IsNull(weak1));
-  EXPECT(!Dart_IsNull(weak2));
-  EXPECT(!Dart_IsNull(weak3));
+  {
+    Dart_EnterScope();
+    // Old space collection should not affect old space objects.
+    EXPECT(!Dart_IsNull(AsHandle(weak1)));
+    EXPECT(!Dart_IsNull(AsHandle(weak2)));
+    EXPECT(!Dart_IsNull(AsHandle(weak3)));
+    Dart_ExitScope();
+  }
 
   // A strongly referenced key should preserve all the values.
   {
-    Dart_Handle keys[] = { strong };
-    Dart_Handle values[] = { weak1, weak2, weak3 };
+    Dart_WeakPersistentHandle keys[] = { strong_weak };
+    Dart_WeakPersistentHandle values[] = { weak1, weak2, weak3 };
     EXPECT_VALID(Dart_NewWeakReferenceSet(keys, ARRAY_SIZE(keys),
                                           values, ARRAY_SIZE(values)));
 
     GCTestHelper::CollectNewSpace(Heap::kInvokeApiCallbacks);
   }
 
-  // All weak references should be preserved.
-  EXPECT(!Dart_IsNull(weak1));
-  EXPECT(!Dart_IsNull(weak2));
-  EXPECT(!Dart_IsNull(weak3));
+  {
+    Dart_EnterScope();
+    // All weak references should be preserved.
+    EXPECT(!Dart_IsNull(AsHandle(weak1)));
+    EXPECT(!Dart_IsNull(AsHandle(weak2)));
+    EXPECT(!Dart_IsNull(AsHandle(weak3)));
+    Dart_ExitScope();
+  }
 
   GCTestHelper::CollectNewSpace(Heap::kIgnoreApiCallbacks);
 
-  // No weak references should be preserved.
-  EXPECT(Dart_IsNull(weak1));
-  EXPECT(Dart_IsNull(weak2));
-  EXPECT(Dart_IsNull(weak3));
+  {
+    Dart_EnterScope();
+    // No weak references should be preserved.
+    EXPECT(Dart_IsNull(AsHandle(weak1)));
+    EXPECT(Dart_IsNull(AsHandle(weak2)));
+    EXPECT(Dart_IsNull(AsHandle(weak3)));
+    Dart_ExitScope();
+  }
 }
 
 
@@ -5177,7 +5271,7 @@
   if (tag == kCanonicalizeUrl) {
     return url;
   }
-  return Api::Success(Isolate::Current());
+  return Api::Success();
 }
 
 
@@ -5301,7 +5395,7 @@
       return Api::NewError("invalid callback");
   }
   index += 1;
-  return Api::Success(Isolate::Current());
+  return Api::Success();
 }
 
 
diff --git a/runtime/vm/dart_api_state.h b/runtime/vm/dart_api_state.h
index e1ac24e..4b58d4f 100644
--- a/runtime/vm/dart_api_state.h
+++ b/runtime/vm/dart_api_state.h
@@ -187,7 +187,7 @@
     if (callback != NULL) {
       void* peer = handle->peer();
       handle->Clear();
-      (*callback)(reinterpret_cast<Dart_Handle>(handle), peer);
+      (*callback)(reinterpret_cast<Dart_WeakPersistentHandle>(handle), peer);
     } else {
       handle->Clear();
     }
@@ -351,7 +351,7 @@
   }
 
   // Validate if passed in handle is a Persistent Handle.
-  bool IsValidHandle(Dart_Handle object) const {
+  bool IsValidHandle(Dart_PersistentHandle object) const {
     return IsValidScopedHandle(reinterpret_cast<uword>(object));
   }
 
@@ -425,7 +425,7 @@
   }
 
   // Validate if passed in handle is a Persistent Handle.
-  bool IsValidHandle(Dart_Handle object) const {
+  bool IsValidHandle(Dart_WeakPersistentHandle object) const {
     return IsValidScopedHandle(reinterpret_cast<uword>(object));
   }
 
@@ -442,8 +442,8 @@
 
 class WeakReferenceSet {
  public:
-  WeakReferenceSet(Dart_Handle* keys, intptr_t keys_length,
-                   Dart_Handle* values, intptr_t values_length)
+  WeakReferenceSet(Dart_WeakPersistentHandle* keys, intptr_t keys_length,
+                   Dart_WeakPersistentHandle* values, intptr_t values_length)
       : next_(NULL),
         keys_(keys), num_keys_(keys_length),
         values_(values), num_values_(values_length) {
@@ -456,14 +456,16 @@
   RawObject** get_key(intptr_t i) {
     ASSERT(i >= 0);
     ASSERT(i < num_keys_);
-    return (reinterpret_cast<PersistentHandle*>(keys_[i]))->raw_addr();
+    return (reinterpret_cast<FinalizablePersistentHandle*>(keys_[i]))->
+        raw_addr();
   }
 
   intptr_t num_values() const { return num_values_; }
   RawObject** get_value(intptr_t i) {
     ASSERT(i >= 0);
     ASSERT(i < num_values_);
-    return (reinterpret_cast<PersistentHandle*>(values_[i]))->raw_addr();
+    return (reinterpret_cast<FinalizablePersistentHandle*>(values_[i]))->
+        raw_addr();
   }
 
   static WeakReferenceSet* Pop(WeakReferenceSet** queue) {
@@ -485,9 +487,9 @@
 
  private:
   WeakReferenceSet* next_;
-  Dart_Handle* keys_;
+  Dart_WeakPersistentHandle* keys_;
   intptr_t num_keys_;
-  Dart_Handle* values_;
+  Dart_WeakPersistentHandle* values_;
   intptr_t num_values_;
   DISALLOW_COPY_AND_ASSIGN(WeakReferenceSet);
 };
@@ -617,15 +619,16 @@
     return false;
   }
 
-  bool IsValidPersistentHandle(Dart_Handle object) const {
+  bool IsValidPersistentHandle(Dart_PersistentHandle object) const {
     return persistent_handles_.IsValidHandle(object);
   }
 
-  bool IsValidWeakPersistentHandle(Dart_Handle object) const {
+  bool IsValidWeakPersistentHandle(Dart_WeakPersistentHandle object) const {
     return weak_persistent_handles_.IsValidHandle(object);
   }
 
-  bool IsValidPrologueWeakPersistentHandle(Dart_Handle object) const {
+  bool IsValidPrologueWeakPersistentHandle(
+      Dart_WeakPersistentHandle object) const {
     return prologue_weak_persistent_handles_.IsValidHandle(object);
   }
 
@@ -655,27 +658,6 @@
     }
     return total;
   }
-  PersistentHandle* Null() {
-    if (null_ == NULL) {
-      null_ = persistent_handles().AllocateHandle();
-      null_->set_raw(Object::null());
-    }
-    return null_;
-  }
-  PersistentHandle* True() {
-    if (true_ == NULL) {
-      true_ = persistent_handles().AllocateHandle();
-      true_->set_raw(Bool::True());
-    }
-    return true_;
-  }
-  PersistentHandle* False() {
-    if (false_ == NULL) {
-      false_ = persistent_handles().AllocateHandle();
-      false_->set_raw(Bool::False());
-    }
-    return false_;
-  }
 
   void SetupAcquiredError() {
     ASSERT(acquired_error_ == NULL);
diff --git a/runtime/vm/debugger_api_impl.cc b/runtime/vm/debugger_api_impl.cc
index 123db7c..133df5b 100644
--- a/runtime/vm/debugger_api_impl.cc
+++ b/runtime/vm/debugger_api_impl.cc
@@ -78,7 +78,7 @@
   CHECK_NOT_NULL(length);
   CHECK_AND_CAST(DebuggerStackTrace, stack_trace, trace);
   *length = stack_trace->Length();
-  return Api::True(isolate);
+  return Api::Success();
 }
 
 
@@ -96,7 +96,7 @@
   }
   *frame = reinterpret_cast<Dart_ActivationFrame>(
        stack_trace->ActivationFrameAt(frame_index));
-  return Api::True(isolate);
+  return Api::Success();
 }
 
 static Dart_PausedEventHandler* paused_event_handler = NULL;
@@ -204,7 +204,7 @@
   Isolate* isolate = Isolate::Current();
   DARTSCOPE(isolate);
   isolate->debugger()->SetExceptionPauseInfo(pause_info);
-  return Api::True(isolate);
+  return Api::Success();
 }
 
 
@@ -220,7 +220,7 @@
   DARTSCOPE(isolate);
   CHECK_NOT_NULL(trace);
   *trace = reinterpret_cast<Dart_StackTrace>(isolate->debugger()->StackTrace());
-  return Api::True(isolate);
+  return Api::Success();
 }
 
 
@@ -246,7 +246,7 @@
     const Library& lib = Library::Handle(frame->Library());
     *library_id = lib.index();
   }
-  return Api::True(isolate);
+  return Api::Success();
 }
 
 
@@ -269,7 +269,7 @@
     location->library_id = lib.index();
     location->token_pos = frame->TokenPos();
   }
-  return Api::True(isolate);
+  return Api::Success();
 }
 
 
@@ -397,7 +397,7 @@
   }
 
   debugger->OneTimeBreakAtEntry(bp_target);
-  return Api::True(isolate);
+  return Api::Success();
 }
 
 
@@ -408,7 +408,7 @@
   ASSERT(debugger != NULL);
 
   isolate->debugger()->RemoveBreakpoint(bp_id);
-  return Api::True(isolate);
+  return Api::Success();
 }
 
 
@@ -416,7 +416,7 @@
   Isolate* isolate = Isolate::Current();
   DARTSCOPE(isolate);
   isolate->debugger()->SetStepOver();
-  return Api::True(isolate);
+  return Api::Success();
 }
 
 
@@ -424,7 +424,7 @@
   Isolate* isolate = Isolate::Current();
   DARTSCOPE(isolate);
   isolate->debugger()->SetStepInto();
-  return Api::True(isolate);
+  return Api::Success();
 }
 
 
@@ -432,7 +432,7 @@
   Isolate* isolate = Isolate::Current();
   DARTSCOPE(isolate);
   isolate->debugger()->SetStepOut();
-  return Api::True(isolate);
+  return Api::Success();
 }
 
 
@@ -493,7 +493,7 @@
   UNWRAP_AND_CHECK_PARAM(Instance, obj, object_in);
   CHECK_NOT_NULL(class_id);
   *class_id = obj.GetClassId();
-  return Api::True(isolate);
+  return Api::Success();
 }
 
 
@@ -536,7 +536,7 @@
     *static_fields =
         Api::NewHandle(isolate, isolate->debugger()->GetStaticFields(cls));
   }
-  return Api::True(isolate);
+  return Api::Success();
 }
 
 
@@ -747,7 +747,7 @@
                          CURRENT_FUNC, library_id);
   }
   *is_debuggable = lib.IsDebuggable();
-  return Api::True(isolate);
+  return Api::Success();
 }
 
 
@@ -762,7 +762,7 @@
                          CURRENT_FUNC, library_id);
   }
   lib.set_debuggable(is_debuggable);
-  return Api::True(isolate);
+  return Api::Success();
 }
 
 
diff --git a/runtime/vm/disassembler_arm.cc b/runtime/vm/disassembler_arm.cc
index dc1258e..ea92980 100644
--- a/runtime/vm/disassembler_arm.cc
+++ b/runtime/vm/disassembler_arm.cc
@@ -1212,8 +1212,6 @@
         Unknown(instr);
       }
     }
-  } else if (instr->IsMrcIdIsar0()) {
-    Format(instr, "mrc'cond p15, 0, 'rd, c0, c2, 0");
   } else {
     Unknown(instr);
   }
diff --git a/runtime/vm/flow_graph.cc b/runtime/vm/flow_graph.cc
index 8ebce64..d78ff5b 100644
--- a/runtime/vm/flow_graph.cc
+++ b/runtime/vm/flow_graph.cc
@@ -418,6 +418,7 @@
       LoadLocalInstr* load = current->AsLoadLocal();
       if (load != NULL) {
         const intptr_t index = load->local().BitIndexIn(num_non_copied_params_);
+        if (index >= live_in->length()) continue;  // Skip tmp_locals.
         live_in->Add(index);
         if (!last_loads->Contains(index)) {
           last_loads->Add(index);
@@ -774,6 +775,8 @@
       Definition* input_defn = v->definition();
       if (input_defn->IsLoadLocal() ||
           input_defn->IsStoreLocal() ||
+          input_defn->IsPushTemp() ||
+          input_defn->IsDropTemps() ||
           input_defn->IsConstant()) {
         // Remove the load/store from the graph.
         input_defn->RemoveFromGraph();
@@ -795,8 +798,14 @@
     if (definition != NULL) {
       LoadLocalInstr* load = definition->AsLoadLocal();
       StoreLocalInstr* store = definition->AsStoreLocal();
+      PushTempInstr* push = definition->AsPushTemp();
+      DropTempsInstr* drop = definition->AsDropTemps();
       ConstantInstr* constant = definition->AsConstant();
-      if ((load != NULL) || (store != NULL) || (constant != NULL)) {
+      if ((load != NULL) ||
+          (store != NULL) ||
+          (push != NULL) ||
+          (drop != NULL) ||
+          (constant != NULL)) {
         intptr_t index;
         Definition* result;
         if (store != NULL) {
@@ -825,6 +834,17 @@
           if (variable_liveness->IsLastLoad(block_entry, load)) {
             (*env)[index] = constant_null();
           }
+        } else if (push != NULL) {
+          result = push->value()->definition();
+          env->Add(result);
+          it.RemoveCurrentFromGraph();
+          continue;
+        } else if (drop != NULL) {
+          // Drop temps from the environment.
+          for (intptr_t j = 0; j < drop->num_temps(); j++) {
+            env->RemoveLast();
+          }
+          result = drop->value()->definition();
         } else {
           ASSERT(definition->is_used());
           result = GetConstant(constant->value());
diff --git a/runtime/vm/flow_graph_builder.cc b/runtime/vm/flow_graph_builder.cc
index 0773a4f..42cd547 100644
--- a/runtime/vm/flow_graph_builder.cc
+++ b/runtime/vm/flow_graph_builder.cc
@@ -57,7 +57,8 @@
     context_level_(0),
     last_used_try_index_(CatchClauseNode::kInvalidTryIndex),
     try_index_(CatchClauseNode::kInvalidTryIndex),
-    graph_entry_(NULL) { }
+    graph_entry_(NULL),
+    args_pushed_(0) { }
 
 
 void FlowGraphBuilder::AddCatchEntry(CatchBlockEntryInstr* entry) {
@@ -356,6 +357,7 @@
   DeallocateTempIndex(definition->InputCount());
   definition->set_use_kind(Definition::kValue);
   definition->set_temp_index(AllocateTempIndex());
+  owner_->add_args_pushed(-definition->ArgumentCount());
   if (is_empty()) {
     entry_ = definition;
   } else {
@@ -370,6 +372,7 @@
   ASSERT(is_open());
   DeallocateTempIndex(definition->InputCount());
   definition->set_use_kind(Definition::kEffect);
+  owner_->add_args_pushed(-definition->ArgumentCount());
   if (is_empty()) {
     entry_ = definition;
   } else {
@@ -384,6 +387,7 @@
   ASSERT(instruction->IsPushArgument() || !instruction->IsDefinition());
   ASSERT(!instruction->IsBlockEntry());
   DeallocateTempIndex(instruction->InputCount());
+  owner_->add_args_pushed(-instruction->ArgumentCount());
   if (is_empty()) {
     entry_ = exit_ = instruction;
   } else {
@@ -503,6 +507,7 @@
 
 
 PushArgumentInstr* EffectGraphVisitor::PushArgument(Value* value) {
+  owner_->add_args_pushed(1);
   PushArgumentInstr* result = new PushArgumentInstr(value);
   AddInstruction(result);
   return result;
@@ -1824,6 +1829,92 @@
 }
 
 
+intptr_t EffectGraphVisitor::GetCurrentTempLocalIndex() const {
+  return kFirstLocalSlotFromFp
+      - owner()->num_stack_locals()
+      - owner()->num_copied_params()
+      - owner()->args_pushed()
+      - temp_index() + 1;
+}
+
+
+class TempLocalScope : public ValueObject {
+ public:
+  TempLocalScope(EffectGraphVisitor* visitor, Value* value)
+      : visitor_(visitor) {
+    ASSERT(value->definition()->temp_index() == visitor->temp_index() - 1);
+    intptr_t index = visitor->GetCurrentTempLocalIndex();
+    char name[64];
+    OS::SNPrint(name, 64, ":tmp_local%"Pd, index);
+    var_ = new LocalVariable(0, String::ZoneHandle(Symbols::New(name)),
+                             Type::ZoneHandle(Type::DynamicType()));
+    var_->set_index(index);
+    visitor->Do(new PushTempInstr(value));
+    visitor->AllocateTempIndex();
+  }
+
+  LocalVariable* var() const { return var_; }
+
+  ~TempLocalScope() {
+    Value* result = visitor_->Bind(new LoadLocalInstr(*var_));
+    visitor_->DeallocateTempIndex(1);
+    visitor_->ReturnDefinition(new DropTempsInstr(1, result));
+  }
+
+ private:
+  EffectGraphVisitor* visitor_;
+  LocalVariable* var_;
+};
+
+
+void EffectGraphVisitor::BuildLetTempExpressions(LetNode* node) {
+  intptr_t num_temps = node->num_temps();
+  for (intptr_t i = 0; i < num_temps; ++i) {
+    ValueGraphVisitor for_value(owner(), temp_index());
+    node->InitializerAt(i)->Visit(&for_value);
+    Append(for_value);
+    Value* temp_val = for_value.value();
+    node->TempAt(i)->set_index(GetCurrentTempLocalIndex());
+    Do(new PushTempInstr(temp_val));
+    AllocateTempIndex();
+  }
+}
+
+
+void EffectGraphVisitor::VisitLetNode(LetNode* node) {
+  BuildLetTempExpressions(node);
+  intptr_t num_temps = node->num_temps();
+
+  // TODO(fschneider): Generate better code for effect context by visiting the
+  // body for effect. Currently, the value of the body expression is
+  // materialized and then dropped. This also requires changing DropTempsInstr
+  // to have zero or one inputs.
+  ValueGraphVisitor for_value(owner(), temp_index());
+  node->body()->Visit(&for_value);
+  Append(for_value);
+  Value* result_value = for_value.value();
+  DeallocateTempIndex(num_temps);
+  Do(new DropTempsInstr(num_temps, result_value));
+}
+
+
+void ValueGraphVisitor::VisitLetNode(LetNode* node) {
+  BuildLetTempExpressions(node);
+
+  ValueGraphVisitor for_value(owner(), temp_index());
+  node->body()->Visit(&for_value);
+  Append(for_value);
+  Value* result_value = for_value.value();
+  intptr_t num_temps = node->num_temps();
+  if (num_temps > 0) {
+    DeallocateTempIndex(num_temps);
+    ReturnDefinition(new DropTempsInstr(num_temps, result_value));
+  } else {
+    ReturnValue(result_value);
+  }
+}
+
+
 void EffectGraphVisitor::VisitArrayNode(ArrayNode* node) {
   const AbstractTypeArguments& type_args =
       AbstractTypeArguments::ZoneHandle(node->type().arguments());
@@ -1834,31 +1925,28 @@
                                                   node->type(),
                                                   element_type);
   Value* array_val = Bind(create);
-  Definition* store = BuildStoreTemp(node->temp_local(), array_val);
-  Do(store);
 
-  const intptr_t class_id = create->Type()->ToCid();
-  const intptr_t deopt_id = Isolate::kNoDeoptId;
-  for (int i = 0; i < node->length(); ++i) {
-    Value* array = Bind(
-        new LoadLocalInstr(node->temp_local()));
-    Value* index = Bind(new ConstantInstr(Smi::ZoneHandle(Smi::New(i))));
-    ValueGraphVisitor for_value(owner(), temp_index());
-    node->ElementAt(i)->Visit(&for_value);
-    Append(for_value);
-    // No store barrier needed for constants.
-    const StoreBarrierType emit_store_barrier =
-        for_value.value()->BindsToConstant()
-            ? kNoStoreBarrier
-            : kEmitStoreBarrier;
-    intptr_t index_scale = FlowGraphCompiler::ElementSizeFor(class_id);
-    StoreIndexedInstr* store = new StoreIndexedInstr(
-        array, index, for_value.value(),
-        emit_store_barrier, index_scale, class_id, deopt_id);
-    Do(store);
+  { TempLocalScope tmp(this, array_val);
+    const intptr_t class_id = create->Type()->ToCid();
+    const intptr_t deopt_id = Isolate::kNoDeoptId;
+    for (int i = 0; i < node->length(); ++i) {
+      Value* array = Bind(new LoadLocalInstr(*tmp.var()));
+      Value* index = Bind(new ConstantInstr(Smi::ZoneHandle(Smi::New(i))));
+      ValueGraphVisitor for_value(owner(), temp_index());
+      node->ElementAt(i)->Visit(&for_value);
+      Append(for_value);
+      // No store barrier needed for constants.
+      const StoreBarrierType emit_store_barrier =
+          for_value.value()->BindsToConstant()
+              ? kNoStoreBarrier
+              : kEmitStoreBarrier;
+      intptr_t index_scale = FlowGraphCompiler::ElementSizeFor(class_id);
+      StoreIndexedInstr* store = new StoreIndexedInstr(
+          array, index, for_value.value(),
+          emit_store_barrier, index_scale, class_id, deopt_id);
+      Do(store);
+    }
   }
-
-  ReturnDefinition(new LoadLocalInstr(node->temp_local()));
 }
 
 
@@ -2332,7 +2420,6 @@
   // The type arguments are uninstantiated. We use expression_temp_var to save
   // the instantiator type arguments because they have two uses.
   ASSERT(owner()->parsed_function().expression_temp_var() != NULL);
-  const LocalVariable& temp = *owner()->parsed_function().expression_temp_var();
   const Class& instantiator_class = Class::Handle(
       owner()->parsed_function().function().Owner());
   Value* type_arguments_val = BuildInstantiatorTypeArguments(
@@ -2347,7 +2434,7 @@
     const intptr_t len = node->type_arguments().Length();
     if (node->type_arguments().IsRawInstantiatedRaw(len)) {
       type_arguments_val =
-          Bind(BuildStoreTemp(temp, type_arguments_val));
+          Bind(BuildStoreExprTemp(type_arguments_val));
       type_arguments_val = Bind(
           new ExtractConstructorTypeArgumentsInstr(
               node->token_pos(),
@@ -2355,7 +2442,7 @@
               instantiator_class,
               type_arguments_val));
     } else {
-      Do(BuildStoreTemp(temp, type_arguments_val));
+      Do(BuildStoreExprTemp(type_arguments_val));
       type_arguments_val = Bind(new ConstantInstr(node->type_arguments()));
     }
   }
@@ -2363,7 +2450,7 @@
 
   Value* instantiator_val = NULL;
   if (!use_instantiator_type_args) {
-    instantiator_val = Bind(BuildLoadLocal(temp));
+    instantiator_val = Bind(BuildLoadExprTemp());
     const intptr_t len = node->type_arguments().Length();
     if (node->type_arguments().IsRawInstantiatedRaw(len)) {
       instantiator_val =
@@ -2395,15 +2482,11 @@
   //   tn       <- LoadLocal(temp)
 
   Value* allocate = BuildObjectAllocation(node);
-  Value* allocated_value = Bind(BuildStoreTemp(
-      node->allocated_object_var(),
-      allocate));
-  PushArgumentInstr* push_allocated_value = PushArgument(allocated_value);
-  BuildConstructorCall(node, push_allocated_value);
-  Definition* load_allocated = BuildLoadLocal(
-      node->allocated_object_var());
-  allocated_value = Bind(load_allocated);
-  ReturnValue(allocated_value);
+  { TempLocalScope tmp(this, allocate);
+    Value* allocated_tmp = Bind(new LoadLocalInstr(*tmp.var()));
+    PushArgumentInstr* push_allocated_value = PushArgument(allocated_tmp);
+    BuildConstructorCall(node, push_allocated_value);
+  }
 }
 
 
@@ -3270,8 +3353,7 @@
   // including the receiver.
   ArrayNode* args_array = new ArrayNode(
       args_pos,
-      Type::ZoneHandle(Type::ArrayType()),
-      *owner()->parsed_function().array_literal_var());
+      Type::ZoneHandle(Type::ArrayType()));
   for (intptr_t i = 0; i < method_arguments->length(); i++) {
     args_array->AddElement(method_arguments->NodeAt(i));
   }
diff --git a/runtime/vm/flow_graph_builder.h b/runtime/vm/flow_graph_builder.h
index 9f613eb..a24a3d2 100644
--- a/runtime/vm/flow_graph_builder.h
+++ b/runtime/vm/flow_graph_builder.h
@@ -140,6 +140,9 @@
   bool IsInlining() const { return (exit_collector_ != NULL); }
   InlineExitCollector* exit_collector() const { return exit_collector_; }
 
+  intptr_t args_pushed() const { return args_pushed_; }
+  void add_args_pushed(intptr_t n) { args_pushed_ += n; }
+
  private:
   intptr_t parameter_count() const {
     return num_copied_params_ + num_non_copied_params_;
@@ -162,6 +165,9 @@
   intptr_t try_index_;
   GraphEntryInstr* graph_entry_;
 
+  // Outgoing argument stack height.
+  intptr_t args_pushed_;
+
   DISALLOW_IMPLICIT_CONSTRUCTORS(FlowGraphBuilder);
 };
 
@@ -318,6 +324,10 @@
     temp_index_ -= n;
   }
 
+  // Returns a local variable index for a temporary local that is
+  // on top of the current expression stack.
+  intptr_t GetCurrentTempLocalIndex() const;
+
   Value* BuildObjectAllocation(ConstructorCallNode* node);
   void BuildConstructorCall(ConstructorCallNode* node,
                             PushArgumentInstr* alloc_value);
@@ -346,21 +356,23 @@
 
   Value* BuildNullValue();
 
- private:
-  // Specify a definition of the final result.  Adds the definition to
-  // the graph, but normally overridden in subclasses.
-  virtual void ReturnDefinition(Definition* definition) {
-    Do(definition);
-  }
-
- protected:
   // Returns true if the run-time type check can be eliminated.
   bool CanSkipTypeCheck(intptr_t token_pos,
                         Value* value,
                         const AbstractType& dst_type,
                         const String& dst_name);
 
+  void BuildLetTempExpressions(LetNode* node);
+
  private:
+  friend class TempLocalScope;  // For ReturnDefinition.
+
+  // Specify a definition of the final result.  Adds the definition to
+  // the graph, but normally overridden in subclasses.
+  virtual void ReturnDefinition(Definition* definition) {
+    Do(definition);
+  }
+
   // Shared global state.
   FlowGraphBuilder* owner_;
 
@@ -401,6 +413,7 @@
   virtual void VisitStoreStaticFieldNode(StoreStaticFieldNode* node);
   virtual void VisitTypeNode(TypeNode* node);
   virtual void VisitCommaNode(CommaNode* node);
+  virtual void VisitLetNode(LetNode* node);
 
   Value* value() const { return value_; }
 
diff --git a/runtime/vm/flow_graph_compiler.cc b/runtime/vm/flow_graph_compiler.cc
index a5d50b1..d56842f 100644
--- a/runtime/vm/flow_graph_compiler.cc
+++ b/runtime/vm/flow_graph_compiler.cc
@@ -738,7 +738,7 @@
   }
 
   // Allocate all unallocated input locations.
-  const bool should_pop = !instr->IsPushArgument();
+  const bool should_pop = !instr->IsPushArgument() && !instr->IsPushTemp();
   for (intptr_t i = locs->input_count() - 1; i >= 0; i--) {
     Location loc = locs->in(i);
     Register reg = kNoRegister;
diff --git a/runtime/vm/flow_graph_compiler_arm.cc b/runtime/vm/flow_graph_compiler_arm.cc
index c4317a9..07981a1 100644
--- a/runtime/vm/flow_graph_compiler_arm.cc
+++ b/runtime/vm/flow_graph_compiler_arm.cc
@@ -1408,17 +1408,47 @@
 }
 
 
+// Implement equality spec: if any of the arguments is null do identity check.
+// Fallthrough calls super equality.
 void FlowGraphCompiler::EmitSuperEqualityCallPrologue(Register result,
                                                       Label* skip_call) {
-  UNIMPLEMENTED();
+  Label check_identity, fall_through;
+  __ LoadImmediate(IP, reinterpret_cast<intptr_t>(Object::null()));
+  __ ldr(result, Address(SP, 0 * kWordSize));  // Load right operand.
+  __ cmp(result, ShifterOperand(IP));  // Is right null?
+  __ ldr(result, Address(SP, 1 * kWordSize));  // Load left operand.
+  __ b(&check_identity, EQ);  // Branch if right (IP) is null; left in result.
+  __ cmp(result, ShifterOperand(IP));  // Right is non-null; is left null?
+  __ b(&fall_through, NE);
+  // Right is non-null, left is null. We could return false, but we save code
+  // by falling through with an IP different than null.
+  __ mov(IP, ShifterOperand(0));
+  __ Bind(&check_identity);
+  __ cmp(result, ShifterOperand(IP));
+  __ LoadObject(result, Bool::True(), EQ);
+  __ LoadObject(result, Bool::False(), NE);
+  __ Drop(2);
+  __ b(skip_call);
+  __ Bind(&fall_through);
 }
 
 
 void FlowGraphCompiler::SaveLiveRegisters(LocationSummary* locs) {
   // TODO(vegorov): consider saving only caller save (volatile) registers.
-  const intptr_t fpu_registers = locs->live_registers()->fpu_registers();
-  if (fpu_registers > 0) {
-    UNIMPLEMENTED();
+  const intptr_t fpu_regs_count = locs->live_registers()->fpu_regs_count();
+  if (fpu_regs_count > 0) {
+    __ AddImmediate(SP, -(fpu_regs_count * kFpuRegisterSize));
+    // Store fpu registers with the lowest register number at the lowest
+    // address.
+    intptr_t offset = 0;
+    for (intptr_t reg_idx = 0; reg_idx < kNumberOfFpuRegisters; ++reg_idx) {
+      DRegister fpu_reg = static_cast<DRegister>(reg_idx);
+      if (locs->live_registers()->ContainsFpuRegister(fpu_reg)) {
+        __ vstrd(fpu_reg, Address(SP, offset));
+        offset += kFpuRegisterSize;
+      }
+    }
+    ASSERT(offset == (fpu_regs_count * kFpuRegisterSize));
   }
 
   // Store general purpose registers with the lowest register number at the
@@ -1440,9 +1470,19 @@
     __ PopList(cpu_registers);
   }
 
-  const intptr_t fpu_registers = locs->live_registers()->fpu_registers();
-  if (fpu_registers > 0) {
-    UNIMPLEMENTED();
+  const intptr_t fpu_regs_count = locs->live_registers()->fpu_regs_count();
+  if (fpu_regs_count > 0) {
+    // Fpu registers have the lowest register number at the lowest address.
+    intptr_t offset = 0;
+    for (intptr_t reg_idx = 0; reg_idx < kNumberOfFpuRegisters; ++reg_idx) {
+      DRegister fpu_reg = static_cast<DRegister>(reg_idx);
+      if (locs->live_registers()->ContainsFpuRegister(fpu_reg)) {
+        __ vldrd(fpu_reg, Address(SP, offset));
+        offset += kFpuRegisterSize;
+      }
+    }
+    ASSERT(offset == (fpu_regs_count * kFpuRegisterSize));
+    __ AddImmediate(SP, offset);
   }
 }
 
@@ -1498,7 +1538,13 @@
                                                 FpuRegister left,
                                                 FpuRegister right,
                                                 BranchInstr* branch) {
-  UNIMPLEMENTED();
+  ASSERT(branch != NULL);
+  assembler()->vcmpd(left, right);
+  assembler()->vmstat();
+  BlockEntryInstr* nan_result = (true_condition == NE) ?
+      branch->true_successor() : branch->false_successor();
+  assembler()->b(GetJumpLabel(nan_result), VS);
+  branch->EmitBranchOnCondition(this, true_condition);
 }
 
 
@@ -1506,7 +1552,13 @@
                                               FpuRegister left,
                                               FpuRegister right,
                                               Register result) {
-  UNIMPLEMENTED();
+  assembler()->vcmpd(left, right);
+  assembler()->vmstat();
+  assembler()->LoadObject(result, Bool::False());
+  Label done;
+  assembler()->b(&done, VS);  // NaN -> false.
+  assembler()->LoadObject(result, Bool::True(), true_condition);
+  assembler()->Bind(&done);
 }
 
 
diff --git a/runtime/vm/flow_graph_inliner.cc b/runtime/vm/flow_graph_inliner.cc
index 4788723..80a93ee 100644
--- a/runtime/vm/flow_graph_inliner.cc
+++ b/runtime/vm/flow_graph_inliner.cc
@@ -990,6 +990,9 @@
 
 
 bool PolymorphicInliner::TryInlining(const Function& target) {
+  if (!target.is_optimizable()) {
+    return false;
+  }
   GrowableArray<Value*> arguments(call_->ArgumentCount());
   for (int i = 0; i < call_->ArgumentCount(); ++i) {
     arguments.Add(call_->PushArgumentAt(i)->value());
diff --git a/runtime/vm/flow_graph_optimizer.cc b/runtime/vm/flow_graph_optimizer.cc
index 81ebad6..f22e386 100644
--- a/runtime/vm/flow_graph_optimizer.cc
+++ b/runtime/vm/flow_graph_optimizer.cc
@@ -5061,6 +5061,18 @@
 }
 
 
+void ConstantPropagator::VisitPushTemp(PushTempInstr* instr) {
+  // Instruction is eliminated when translating to SSA.
+  UNREACHABLE();
+}
+
+
+void ConstantPropagator::VisitDropTemps(DropTempsInstr* instr) {
+  // Instruction is eliminated when translating to SSA.
+  UNREACHABLE();
+}
+
+
 void ConstantPropagator::VisitStoreLocal(StoreLocalInstr* instr) {
   // Instruction is eliminated when translating to SSA.
   UNREACHABLE();
diff --git a/runtime/vm/flow_graph_type_propagator.cc b/runtime/vm/flow_graph_type_propagator.cc
index d096872..7dc47d2 100644
--- a/runtime/vm/flow_graph_type_propagator.cc
+++ b/runtime/vm/flow_graph_type_propagator.cc
@@ -857,6 +857,16 @@
 }
 
 
+CompileType PushTempInstr::ComputeType() const {
+  return CompileType::Dynamic();
+}
+
+
+CompileType DropTempsInstr::ComputeType() const {
+  return CompileType::Dynamic();
+}
+
+
 CompileType* StoreLocalInstr::ComputeInitialType() const {
   // Returns stored value.
   return value()->Type();
diff --git a/runtime/vm/intermediate_language.cc b/runtime/vm/intermediate_language.cc
index e5d855b..3fd1a11 100644
--- a/runtime/vm/intermediate_language.cc
+++ b/runtime/vm/intermediate_language.cc
@@ -1579,6 +1579,35 @@
 }
 
 
+LocationSummary* PushTempInstr::MakeLocationSummary() const {
+  return LocationSummary::Make(1,
+                               Location::NoLocation(),
+                               LocationSummary::kNoCall);
+}
+
+
+void PushTempInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  ASSERT(!compiler->is_optimizing());
+  // Nothing to do.
+}
+
+
+LocationSummary* DropTempsInstr::MakeLocationSummary() const {
+  return LocationSummary::Make(1,
+                               Location::SameAsFirstInput(),
+                               LocationSummary::kNoCall);
+}
+
+
+void DropTempsInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  ASSERT(!compiler->is_optimizing());
+  Register value = locs()->in(0).reg();
+  Register result = locs()->out().reg();
+  ASSERT(result == value);  // Assert that register assignment is correct.
+  __ Drop(num_temps());
+}
+
+
 void StoreContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   // Nothing to do.  Context register was loaded by the register allocator.
   ASSERT(locs()->in(0).reg() == CTX);
diff --git a/runtime/vm/intermediate_language.h b/runtime/vm/intermediate_language.h
index 19976f6..d998fec 100644
--- a/runtime/vm/intermediate_language.h
+++ b/runtime/vm/intermediate_language.h
@@ -529,6 +529,8 @@
   M(PolymorphicInstanceCall)                                                   \
   M(StaticCall)                                                                \
   M(LoadLocal)                                                                 \
+  M(PushTemp)                                                                  \
+  M(DropTemps)                                                                 \
   M(StoreLocal)                                                                \
   M(StrictCompare)                                                             \
   M(EqualityCompare)                                                           \
@@ -3145,6 +3147,69 @@
 };
 
 
+class PushTempInstr : public TemplateDefinition<1> {
+ public:
+  explicit PushTempInstr(Value* value) {
+    SetInputAt(0, value);
+  }
+
+  DECLARE_INSTRUCTION(PushTemp)
+
+  Value* value() const { return inputs_[0]; }
+
+  virtual CompileType ComputeType() const;
+
+  virtual bool CanDeoptimize() const { return false; }
+
+  virtual EffectSet Effects() const {
+    UNREACHABLE();  // Eliminated by SSA construction.
+    return EffectSet::None();
+  }
+
+  virtual bool MayThrow() const {
+    UNREACHABLE();
+    return false;
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(PushTempInstr);
+};
+
+
+class DropTempsInstr : public TemplateDefinition<1> {
+ public:
+  explicit DropTempsInstr(intptr_t num_temps, Value* value)
+      : num_temps_(num_temps) {
+    SetInputAt(0, value);
+  }
+
+  DECLARE_INSTRUCTION(DropTemps)
+
+  Value* value() const { return inputs_[0]; }
+
+  intptr_t num_temps() const { return num_temps_; }
+
+  virtual CompileType ComputeType() const;
+
+  virtual bool CanDeoptimize() const { return false; }
+
+  virtual EffectSet Effects() const {
+    UNREACHABLE();  // Eliminated by SSA construction.
+    return EffectSet::None();
+  }
+
+  virtual bool MayThrow() const {
+    UNREACHABLE();
+    return false;
+  }
+
+ private:
+  intptr_t num_temps_;
+
+  DISALLOW_COPY_AND_ASSIGN(DropTempsInstr);
+};
+
+
 class StoreLocalInstr : public TemplateDefinition<1> {
  public:
   StoreLocalInstr(const LocalVariable& local, Value* value)
diff --git a/runtime/vm/intermediate_language_arm.cc b/runtime/vm/intermediate_language_arm.cc
index 7e3c96b..0f9444a 100644
--- a/runtime/vm/intermediate_language_arm.cc
+++ b/runtime/vm/intermediate_language_arm.cc
@@ -264,13 +264,32 @@
 
 
 LocationSummary* ArgumentDefinitionTestInstr::MakeLocationSummary() const {
-  UNIMPLEMENTED();
-  return NULL;
+  const intptr_t kNumInputs = 1;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* locs =
+      new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
+  locs->set_in(0, Location::RegisterLocation(R0));
+  locs->set_out(Location::RegisterLocation(R0));
+  return locs;
 }
 
 
 void ArgumentDefinitionTestInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  UNIMPLEMENTED();
+  Register saved_args_desc = locs()->in(0).reg();
+  Register result = locs()->out().reg();
+
+  // Push the result place holder initialized to NULL.
+  __ PushObject(Object::ZoneHandle());
+  __ LoadImmediate(IP, Smi::RawValue(formal_parameter_index()));
+  __ Push(IP);
+  __ PushObject(formal_parameter_name());
+  __ Push(saved_args_desc);
+  compiler->GenerateCallRuntime(token_pos(),
+                                deopt_id(),
+                                kArgumentDefinitionTestRuntimeEntry,
+                                locs());
+  __ Drop(3);
+  __ Pop(result);  // Pop bool result.
 }
 
 
@@ -565,7 +584,43 @@
                                    Token::Kind kind,
                                    BranchInstr* branch,
                                    intptr_t deopt_id) {
-  UNIMPLEMENTED();
+  ASSERT((kind == Token::kEQ) || (kind == Token::kNE));
+  Register left = locs.in(0).reg();
+  Register right = locs.in(1).reg();
+  Register temp = locs.temp(0).reg();
+  Label* deopt = compiler->AddDeoptStub(deopt_id, kDeoptEquality);
+  __ tst(left, ShifterOperand(kSmiTagMask));
+  __ b(deopt, EQ);
+  // 'left' is not Smi.
+  Label identity_compare;
+  __ LoadImmediate(IP, reinterpret_cast<intptr_t>(Object::null()));
+  __ cmp(right, ShifterOperand(IP));
+  __ b(&identity_compare, EQ);
+  __ cmp(left, ShifterOperand(IP));
+  __ b(&identity_compare, EQ);
+
+  __ LoadClassId(temp, left);
+  const intptr_t len = ic_data.NumberOfChecks();
+  for (intptr_t i = 0; i < len; i++) {
+    __ CompareImmediate(temp, ic_data.GetReceiverClassIdAt(i));
+    if (i == (len - 1)) {
+      __ b(deopt, NE);
+    } else {
+      __ b(&identity_compare, EQ);
+    }
+  }
+  __ Bind(&identity_compare);
+  __ cmp(left, ShifterOperand(right));
+  if (branch == NULL) {
+    Register result = locs.out().reg();
+    __ LoadObject(result,
+                  (kind == Token::kEQ) ? Bool::True() : Bool::False(), EQ);
+    __ LoadObject(result,
+                  (kind == Token::kEQ) ? Bool::False() : Bool::True(), NE);
+  } else {
+    Condition cond = TokenKindToSmiCondition(kind);
+    branch->EmitBranchOnCondition(compiler, cond);
+  }
 }
 
 
@@ -679,11 +734,36 @@
 }
 
 
+static Condition TokenKindToDoubleCondition(Token::Kind kind) {
+  switch (kind) {
+    case Token::kEQ: return EQ;
+    case Token::kNE: return NE;
+    case Token::kLT: return LT;
+    case Token::kGT: return GT;
+    case Token::kLTE: return LE;
+    case Token::kGTE: return GE;
+    default:
+      UNREACHABLE();
+      return VS;
+  }
+}
+
+
 static void EmitDoubleComparisonOp(FlowGraphCompiler* compiler,
                                    const LocationSummary& locs,
                                    Token::Kind kind,
                                    BranchInstr* branch) {
-  UNIMPLEMENTED();
+  DRegister left = locs.in(0).fpu_reg();
+  DRegister right = locs.in(1).fpu_reg();
+
+  Condition true_condition = TokenKindToDoubleCondition(kind);
+  if (branch != NULL) {
+    compiler->EmitDoubleCompareBranch(
+        true_condition, left, right, branch);
+  } else {
+    compiler->EmitDoubleCompareBool(
+        true_condition, left, right, locs.out().reg());
+  }
 }
 
 
@@ -958,13 +1038,21 @@
 
 
 LocationSummary* StringFromCharCodeInstr::MakeLocationSummary() const {
-  UNIMPLEMENTED();
-  return NULL;
+  const intptr_t kNumInputs = 1;
+  // TODO(fschneider): Allow immediate operands for the char code.
+  return LocationSummary::Make(kNumInputs,
+                               Location::RequiresRegister(),
+                               LocationSummary::kNoCall);
 }
 
 
 void StringFromCharCodeInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  UNIMPLEMENTED();
+  Register char_code = locs()->in(0).reg();
+  Register result = locs()->out().reg();
+  __ LoadImmediate(result,
+                   reinterpret_cast<uword>(Symbols::PredefinedAddress()));
+  __ AddImmediate(result, Symbols::kNullCharCodeSymbolOffset * kWordSize);
+  __ ldr(result, Address(result, char_code, LSL, 1));  // Char code is a smi.
 }
 
 
@@ -1135,7 +1223,33 @@
   if ((representation() == kUnboxedDouble) ||
       (representation() == kUnboxedMint) ||
       (representation() == kUnboxedFloat32x4)) {
-    UNIMPLEMENTED();
+    DRegister result = locs()->out().fpu_reg();
+    switch (class_id()) {
+      case kTypedDataInt32ArrayCid:
+        UNIMPLEMENTED();
+        break;
+      case kTypedDataUint32ArrayCid:
+        UNIMPLEMENTED();
+        break;
+      case kTypedDataFloat32ArrayCid:
+        // Load single precision float and promote to double.
+        // vldrs does not support indexed addressing.
+        __ add(index.reg(), index.reg(), ShifterOperand(array));
+        element_address = Address(index.reg(), 0);
+        __ vldrs(S0, element_address);
+        __ vcvtds(result, S0);
+        break;
+      case kTypedDataFloat64ArrayCid:
+        // vldrd does not support indexed addressing.
+        __ add(index.reg(), index.reg(), ShifterOperand(array));
+        element_address = Address(index.reg(), 0);
+        __ vldrd(result, element_address);
+        break;
+      case kTypedDataFloat32x4ArrayCid:
+        UNIMPLEMENTED();
+        break;
+    }
+    return;
   }
 
   Register result = locs()->out().reg();
@@ -1674,14 +1788,19 @@
 
 LocationSummary*
 AllocateObjectWithBoundsCheckInstr::MakeLocationSummary() const {
-  UNIMPLEMENTED();
-  return NULL;
+  return MakeCallSummary();
 }
 
 
 void AllocateObjectWithBoundsCheckInstr::EmitNativeCode(
     FlowGraphCompiler* compiler) {
-  UNIMPLEMENTED();
+  compiler->GenerateCallRuntime(token_pos(),
+                                deopt_id(),
+                                kAllocateObjectWithBoundsCheckRuntimeEntry,
+                                locs());
+  __ Drop(3);
+  ASSERT(locs()->out().reg() == R0);
+  __ Pop(R0);  // Pop new instance.
 }
 
 
@@ -1856,13 +1975,28 @@
 
 
 LocationSummary* CloneContextInstr::MakeLocationSummary() const {
-  UNIMPLEMENTED();
-  return NULL;
+  const intptr_t kNumInputs = 1;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* locs =
+      new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
+  locs->set_in(0, Location::RegisterLocation(R0));
+  locs->set_out(Location::RegisterLocation(R0));
+  return locs;
 }
 
 
 void CloneContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  UNIMPLEMENTED();
+  Register context_value = locs()->in(0).reg();
+  Register result = locs()->out().reg();
+
+  __ PushObject(Object::ZoneHandle());  // Make room for the result.
+  __ Push(context_value);
+  compiler->GenerateCallRuntime(token_pos(),
+                                deopt_id(),
+                                kCloneContextRuntimeEntry,
+                                locs());
+  __ Drop(1);  // Remove argument.
+  __ Pop(result);  // Get result (cloned context).
 }
 
 
@@ -2056,20 +2190,29 @@
 
 LocationSummary* BinarySmiOpInstr::MakeLocationSummary() const {
   const intptr_t kNumInputs = 2;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* summary =
+      new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
   if (op_kind() == Token::kTRUNCDIV) {
-    UNIMPLEMENTED();
-    return NULL;
-  } else {
-    const intptr_t kNumTemps = 0;
-    LocationSummary* summary =
-        new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
-    summary->set_in(0, Location::RequiresRegister());
-    summary->set_in(1, Location::RegisterOrSmiConstant(right()));
-    // We make use of 3-operand instructions by not requiring result register
-    // to be identical to first input register as on Intel.
-    summary->set_out(Location::RequiresRegister());
+    if (RightIsPowerOfTwoConstant()) {
+      summary->set_in(0, Location::RequiresRegister());
+      ConstantInstr* right_constant = right()->definition()->AsConstant();
+      summary->set_in(1, Location::Constant(right_constant->value()));
+      summary->set_out(Location::RequiresRegister());
+    } else {
+      // Both inputs must be writable because they will be untagged.
+      summary->set_in(0, Location::WritableRegister());
+      summary->set_in(1, Location::WritableRegister());
+      summary->set_out(Location::RequiresRegister());
+    }
     return summary;
   }
+  summary->set_in(0, Location::RequiresRegister());
+  summary->set_in(1, Location::RegisterOrSmiConstant(right()));
+  // We make use of 3-operand instructions by not requiring result register
+  // to be identical to first input register as on Intel.
+  summary->set_out(Location::RequiresRegister());
+  return summary;
 }
 
 
@@ -2130,7 +2273,31 @@
         break;
       }
       case Token::kTRUNCDIV: {
-        UNIMPLEMENTED();
+        const intptr_t value = Smi::Cast(constant).Value();
+        if (value == 1) {
+          // Do nothing.
+          break;
+        } else if (value == -1) {
+          // Check the corner case of dividing the 'MIN_SMI' with -1, in which
+          // case we cannot negate the result.
+          __ CompareImmediate(left, 0x80000000);
+          __ b(deopt, EQ);
+          __ rsb(result, left, ShifterOperand(0));
+          break;
+        }
+        ASSERT((value != 0) && Utils::IsPowerOfTwo(Utils::Abs(value)));
+        const intptr_t shift_count =
+            Utils::ShiftForPowerOfTwo(Utils::Abs(value)) + kSmiTagSize;
+        ASSERT(kSmiTagSize == 1);
+        __ mov(IP, ShifterOperand(left, ASR, 31));
+        ASSERT(shift_count > 1);  // 1, -1 case handled above.
+        __ add(left, left, ShifterOperand(IP, LSR, 32 - shift_count));
+        ASSERT(shift_count > 0);
+        __ mov(result, ShifterOperand(left, ASR, shift_count));
+        if (value < 0) {
+          __ rsb(result, result, ShifterOperand(0));
+        }
+        __ SmiTag(result);
         break;
       }
       case Token::kBIT_AND: {
@@ -2245,7 +2412,20 @@
       break;
     }
     case Token::kTRUNCDIV: {
-      UNIMPLEMENTED();
+      // Handle divide by zero in runtime.
+      __ cmp(right, ShifterOperand(0));
+      __ b(deopt, EQ);
+      __ SmiUntag(left);
+      __ SmiUntag(right);
+      if (!CPUFeatures::integer_division_supported()) {
+        UNIMPLEMENTED();
+      }
+      __ sdiv(result, left, right);
+      // Check the corner case of dividing the 'MIN_SMI' with -1, in which
+      // case we cannot tag the result.
+      __ CompareImmediate(result, 0x40000000);
+      __ b(deopt, EQ);
+      __ SmiTag(result);
       break;
     }
     case Token::kSHR: {
@@ -2278,35 +2458,142 @@
 
 
 LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary() const {
-  UNIMPLEMENTED();
-  return NULL;
+  intptr_t left_cid = left()->Type()->ToCid();
+  intptr_t right_cid = right()->Type()->ToCid();
+  ASSERT((left_cid != kDoubleCid) && (right_cid != kDoubleCid));
+  const intptr_t kNumInputs = 2;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* summary =
+    new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  summary->set_in(0, Location::RequiresRegister());
+  summary->set_in(1, Location::RequiresRegister());
+  return summary;
 }
 
 
 void CheckEitherNonSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  UNIMPLEMENTED();
+  Label* deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinaryDoubleOp);
+  intptr_t left_cid = left()->Type()->ToCid();
+  intptr_t right_cid = right()->Type()->ToCid();
+  Register left = locs()->in(0).reg();
+  Register right = locs()->in(1).reg();
+  if (left_cid == kSmiCid) {
+    __ tst(right, ShifterOperand(kSmiTagMask));
+  } else if (right_cid == kSmiCid) {
+    __ tst(left, ShifterOperand(kSmiTagMask));
+  } else {
+    __ orr(IP, left, ShifterOperand(right));
+    __ tst(IP, ShifterOperand(kSmiTagMask));
+  }
+  __ b(deopt, EQ);
 }
 
 
 LocationSummary* BoxDoubleInstr::MakeLocationSummary() const {
-  UNIMPLEMENTED();
-  return NULL;
+  const intptr_t kNumInputs = 1;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* summary =
+      new LocationSummary(kNumInputs,
+                          kNumTemps,
+                          LocationSummary::kCallOnSlowPath);
+  summary->set_in(0, Location::RequiresFpuRegister());
+  summary->set_out(Location::RequiresRegister());
+  return summary;
 }
 
 
+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) {
-  UNIMPLEMENTED();
+  BoxDoubleSlowPath* slow_path = new BoxDoubleSlowPath(this);
+  compiler->AddSlowPathCode(slow_path);
+
+  Register out_reg = locs()->out().reg();
+  DRegister value = locs()->in(0).fpu_reg();
+
+  __ TryAllocate(compiler->double_class(),
+                 slow_path->entry_label(),
+                 out_reg);
+  __ Bind(slow_path->exit_label());
+  __ StoreDToOffset(value, out_reg, Double::value_offset() - kHeapObjectTag);
 }
 
 
 LocationSummary* UnboxDoubleInstr::MakeLocationSummary() const {
-  UNIMPLEMENTED();
-  return NULL;
+  const intptr_t kNumInputs = 1;
+  const intptr_t value_cid = value()->Type()->ToCid();
+  const bool needs_temp = ((value_cid != kSmiCid) && (value_cid != kDoubleCid));
+  const bool needs_writable_input = (value_cid == kSmiCid);
+  const intptr_t kNumTemps = needs_temp ? 1 : 0;
+  LocationSummary* summary =
+      new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  summary->set_in(0, needs_writable_input
+                     ? Location::WritableRegister()
+                     : Location::RequiresRegister());
+  if (needs_temp) summary->set_temp(0, Location::RequiresRegister());
+  summary->set_out(Location::RequiresFpuRegister());
+  return summary;
 }
 
 
 void UnboxDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  UNIMPLEMENTED();
+  const intptr_t value_cid = value()->Type()->ToCid();
+  const Register value = locs()->in(0).reg();
+  const DRegister result = locs()->out().fpu_reg();
+
+  if (value_cid == kDoubleCid) {
+    __ LoadDFromOffset(result, value, Double::value_offset() - kHeapObjectTag);
+  } else if (value_cid == kSmiCid) {
+    __ SmiUntag(value);  // Untag input before conversion.
+    __ vmovsr(S0, value);
+    __ vcvtdi(result, S0);
+  } else {
+    Label* deopt = compiler->AddDeoptStub(deopt_id_, kDeoptBinaryDoubleOp);
+    Register temp = locs()->temp(0).reg();
+    Label is_smi, done;
+    __ tst(value, ShifterOperand(kSmiTagMask));
+    __ b(&is_smi, EQ);
+    __ CompareClassId(value, kDoubleCid, temp);
+    __ b(deopt, NE);
+    __ LoadDFromOffset(result, value, Double::value_offset() - kHeapObjectTag);
+    __ b(&done);
+    __ Bind(&is_smi);
+    // TODO(regis): Why do we preserve value here but not above?
+    __ mov(IP, ShifterOperand(value, ASR, 1));  // Copy and untag.
+    __ vmovsr(S0, IP);
+    __ vcvtdi(result, S0);
+    __ Bind(&done);
+  }
 }
 
 
@@ -2355,13 +2642,28 @@
 
 
 LocationSummary* BinaryDoubleOpInstr::MakeLocationSummary() const {
-  UNIMPLEMENTED();
-  return NULL;
+  const intptr_t kNumInputs = 2;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* summary =
+      new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  summary->set_in(0, Location::RequiresFpuRegister());
+  summary->set_in(1, Location::RequiresFpuRegister());
+  summary->set_out(Location::RequiresFpuRegister());
+  return summary;
 }
 
 
 void BinaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  UNIMPLEMENTED();
+  DRegister left = locs()->in(0).fpu_reg();
+  DRegister right = locs()->in(1).fpu_reg();
+  DRegister result = locs()->out().fpu_reg();
+  switch (op_kind()) {
+    case Token::kADD: __ vaddd(result, left, right); break;
+    case Token::kSUB: __ vsubd(result, left, right); break;
+    case Token::kMUL: __ vmuld(result, left, right); break;
+    case Token::kDIV: __ vdivd(result, left, right); break;
+    default: UNREACHABLE();
+  }
 }
 
 
@@ -2574,79 +2876,213 @@
 
 
 LocationSummary* MathSqrtInstr::MakeLocationSummary() const {
-  UNIMPLEMENTED();
-  return NULL;
+  const intptr_t kNumInputs = 1;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* summary =
+      new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  summary->set_in(0, Location::RequiresFpuRegister());
+  summary->set_out(Location::RequiresFpuRegister());
+  return summary;
 }
 
 
 void MathSqrtInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  UNIMPLEMENTED();
+  __ vsqrtd(locs()->out().fpu_reg(), locs()->in(0).fpu_reg());
 }
 
 
 LocationSummary* UnarySmiOpInstr::MakeLocationSummary() const {
-  UNIMPLEMENTED();
-  return NULL;
+  const intptr_t kNumInputs = 1;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* summary =
+      new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  summary->set_in(0, Location::RequiresRegister());
+  // We make use of 3-operand instructions by not requiring result register
+  // to be identical to first input register as on Intel.
+  summary->set_out(Location::RequiresRegister());
+  return summary;
 }
 
 
 void UnarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  UNIMPLEMENTED();
+  Register value = locs()->in(0).reg();
+  Register result = locs()->out().reg();
+  switch (op_kind()) {
+    case Token::kNEGATE: {
+      Label* deopt = compiler->AddDeoptStub(deopt_id(),
+                                            kDeoptUnaryOp);
+      __ rsbs(result, value, ShifterOperand(0));
+      __ b(deopt, VS);
+      break;
+    }
+    case Token::kBIT_NOT:
+      __ mvn(result, ShifterOperand(value));
+      // Remove inverted smi-tag.
+      __ bic(result, result, ShifterOperand(kSmiTagMask));
+      break;
+    default:
+      UNREACHABLE();
+  }
 }
 
 
 LocationSummary* SmiToDoubleInstr::MakeLocationSummary() const {
-  UNIMPLEMENTED();
-  return NULL;
+  const intptr_t kNumInputs = 1;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* result =
+      new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  result->set_in(0, Location::WritableRegister());
+  result->set_out(Location::RequiresFpuRegister());
+  return result;
 }
 
 
 void SmiToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  UNIMPLEMENTED();
+  Register value = locs()->in(0).reg();
+  FpuRegister result = locs()->out().fpu_reg();
+  __ SmiUntag(value);
+  __ vmovsr(S0, value);
+  __ vcvtdi(result, S0);
 }
 
 
 LocationSummary* DoubleToIntegerInstr::MakeLocationSummary() const {
-  UNIMPLEMENTED();
-  return NULL;
+  const intptr_t kNumInputs = 1;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* result =
+      new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
+  result->set_in(0, Location::RegisterLocation(R1));
+  result->set_out(Location::RegisterLocation(R0));
+  return result;
 }
 
 
 void DoubleToIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  UNIMPLEMENTED();
+  Register result = locs()->out().reg();
+  Register value_obj = locs()->in(0).reg();
+  ASSERT(result == R0);
+  ASSERT(result != value_obj);
+  __ LoadDFromOffset(D0, value_obj, Double::value_offset() - kHeapObjectTag);
+  __ vcvtid(S0, D0);
+  __ vmovrs(result, S0);
+  // Overflow is signaled with minint.
+  Label do_call, done;
+  // Check for overflow and that it fits into Smi.
+  __ CompareImmediate(result, 0xC0000000);
+  __ b(&do_call, MI);
+  __ SmiTag(result);
+  __ b(&done);
+  __ Bind(&do_call);
+  __ Push(value_obj);
+  ASSERT(instance_call()->HasICData());
+  const ICData& ic_data = *instance_call()->ic_data();
+  ASSERT((ic_data.NumberOfChecks() == 1));
+  const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(0));
+
+  const intptr_t kNumberOfArguments = 1;
+  compiler->GenerateStaticCall(deopt_id(),
+                               instance_call()->token_pos(),
+                               target,
+                               kNumberOfArguments,
+                               Array::Handle(),  // No argument names.,
+                               locs());
+  __ Bind(&done);
 }
 
 
 LocationSummary* DoubleToSmiInstr::MakeLocationSummary() const {
-  UNIMPLEMENTED();
-  return NULL;
+  const intptr_t kNumInputs = 1;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* result = new LocationSummary(
+      kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  result->set_in(0, Location::RequiresFpuRegister());
+  result->set_out(Location::RequiresRegister());
+  return result;
 }
 
 
 void DoubleToSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  UNIMPLEMENTED();
+  Label* deopt = compiler->AddDeoptStub(deopt_id(), kDeoptDoubleToSmi);
+  Register result = locs()->out().reg();
+  DRegister value = locs()->in(0).fpu_reg();
+  __ vcvtid(S0, value);
+  __ vmovrs(result, S0);
+  // Check for overflow and that it fits into Smi.
+  __ CompareImmediate(result, 0xC0000000);
+  __ b(deopt, MI);
+  __ SmiTag(result);
 }
 
 
 LocationSummary* DoubleToDoubleInstr::MakeLocationSummary() const {
-  UNIMPLEMENTED();
-  return NULL;
+  const intptr_t kNumInputs = 1;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* result =
+      new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  result->set_in(0, Location::RequiresFpuRegister());
+  result->set_out(Location::RequiresFpuRegister());
+  return result;
 }
 
 
 void DoubleToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  UNIMPLEMENTED();
+  // DRegister value = locs()->in(0).fpu_reg();
+  // DRegister result = locs()->out().fpu_reg();
+  switch (recognized_kind()) {
+    case MethodRecognizer::kDoubleTruncate:
+      UNIMPLEMENTED();
+      // __ roundsd(result, value,  Assembler::kRoundToZero);
+      break;
+    case MethodRecognizer::kDoubleFloor:
+      UNIMPLEMENTED();
+      // __ roundsd(result, value,  Assembler::kRoundDown);
+      break;
+    case MethodRecognizer::kDoubleCeil:
+      UNIMPLEMENTED();
+      // __ roundsd(result, value,  Assembler::kRoundUp);
+      break;
+    default:
+      UNREACHABLE();
+  }
 }
 
 
 LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary() const {
-  UNIMPLEMENTED();
-  return NULL;
+  ASSERT((InputCount() == 1) || (InputCount() == 2));
+  const intptr_t kNumTemps = 0;
+  LocationSummary* result =
+      new LocationSummary(InputCount(), kNumTemps, LocationSummary::kCall);
+  result->set_in(0, Location::FpuRegisterLocation(D1));
+  if (InputCount() == 2) {
+    result->set_in(1, Location::FpuRegisterLocation(D2));
+  }
+  result->set_out(Location::FpuRegisterLocation(D1));
+  return result;
 }
 
 
 void InvokeMathCFunctionInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  UNIMPLEMENTED();
+  // For pow-function return NAN if exponent is NAN.
+  Label do_call, skip_call;
+  if (recognized_kind() == MethodRecognizer::kDoublePow) {
+    DRegister exp = locs()->in(1).fpu_reg();
+    __ vcmpd(exp, exp);
+    __ vmstat();
+    __ b(&do_call, VC);  // NaN -> false;
+    // Exponent is NaN, return NaN.
+    __ vmovd(locs()->out().fpu_reg(), exp);
+    __ b(&skip_call);
+  }
+  __ Bind(&do_call);
+  // TODO(regis): Using D0 as the reserved scratch value is not a good idea.
+  __ vmovd(D0, locs()->in(0).fpu_reg());
+  if (InputCount() == 2) {
+    __ vmovd(D1, locs()->in(1).fpu_reg());
+  }
+  UNIMPLEMENTED();  // TODO(regis): We need to support double type leaf calls.
+  __ CallRuntime(TargetFunction());
+  __ vmovd(locs()->out().fpu_reg(), D0);
+  __ Bind(&skip_call);
 }
 
 
diff --git a/runtime/vm/intrinsifier_arm.cc b/runtime/vm/intrinsifier_arm.cc
index 694f64b..2e551ab 100644
--- a/runtime/vm/intrinsifier_arm.cc
+++ b/runtime/vm/intrinsifier_arm.cc
@@ -833,7 +833,6 @@
 
 bool Intrinsifier::Integer_bitXorFromInteger(Assembler* assembler) {
   Label fall_through;
-  __ Untested("Intrinsifier::Integer_bitXorFromInteger");
 
   TestBothArgumentsSmis(assembler, &fall_through);  // checks two smis
   __ eor(R0, R0, ShifterOperand(R1));
@@ -1126,12 +1125,10 @@
   TestLastArgumentIsDouble(assembler, &is_smi, &fall_through);
   // Both arguments are double, right operand is in R0.
 
-  __ AddImmediate(R0, Double::value_offset() - kHeapObjectTag);
-  __ vldrd(D1, Address(R0));
+  __ LoadDFromOffset(D1, R0, Double::value_offset() - kHeapObjectTag);
   __ Bind(&double_op);
   __ ldr(R0, Address(SP, 1 * kWordSize));  // Left argument.
-  __ AddImmediate(R0, Double::value_offset() - kHeapObjectTag);
-  __ vldrd(D0, Address(R0));
+  __ LoadDFromOffset(D0, R0, Double::value_offset() - kHeapObjectTag);
 
   __ vcmpd(D0, D1);
   __ vmstat();
@@ -1183,13 +1180,9 @@
 
   TestLastArgumentIsDouble(assembler, &fall_through, &fall_through);
   // Both arguments are double, right operand is in R0.
-  // Can't use FieldAddress here. R0 is heap-object-tagged, so the offset will
-  // not be 4-byte aligned.
-  __ AddImmediate(R0, Double::value_offset() - kHeapObjectTag);
-  __ vldrd(D1, Address(R0));
+  __ LoadDFromOffset(D1, R0, Double::value_offset() - kHeapObjectTag);
   __ ldr(R0, Address(SP, 1 * kWordSize));  // Left argument.
-  __ AddImmediate(R0, Double::value_offset() - kHeapObjectTag);
-  __ vldrd(D0, Address(R0));
+  __ LoadDFromOffset(D0, R0, Double::value_offset() - kHeapObjectTag);
   switch (kind) {
     case Token::kADD: __ vaddd(D0, D0, D1); break;
     case Token::kSUB: __ vsubd(D0, D0, D1); break;
@@ -1200,8 +1193,7 @@
   const Class& double_class = Class::Handle(
       Isolate::Current()->object_store()->double_class());
   __ TryAllocate(double_class, &fall_through, R0);  // Result register.
-  __ AddImmediate(R1, R0, Double::value_offset() - kHeapObjectTag);
-  __ vstrd(D0, Address(R1));
+  __ StoreDToOffset(D0, R0, Double::value_offset() - kHeapObjectTag);
   __ Ret();
   __ Bind(&fall_through);
   return false;
@@ -1231,7 +1223,6 @@
 // Left is double right is integer (Bigint, Mint or Smi)
 bool Intrinsifier::Double_mulFromInteger(Assembler* assembler) {
   Label fall_through;
-  __ Untested("Intrinsifier::Double_mulFromInteger");
   // Only Smi-s allowed.
   __ ldr(R0, Address(SP, 0 * kWordSize));
   __ tst(R0, ShifterOperand(kSmiTagMask));
@@ -1241,14 +1232,12 @@
   __ vmovsr(S0, R0);
   __ vcvtdi(D1, S0);
   __ ldr(R0, Address(SP, 1 * kWordSize));
-  __ AddImmediate(R0, Double::value_offset() - kHeapObjectTag);
-  __ vldrd(D0, Address(R0));
+  __ LoadDFromOffset(D0, R0, Double::value_offset() - kHeapObjectTag);
   __ vmuld(D0, D0, D1);
   const Class& double_class = Class::Handle(
       Isolate::Current()->object_store()->double_class());
   __ TryAllocate(double_class, &fall_through, R0);  // Result register.
-  __ AddImmediate(R1, R0, Double::value_offset() - kHeapObjectTag);
-  __ vstrd(D0, Address(R1));
+  __ StoreDToOffset(D0, R0, Double::value_offset() - kHeapObjectTag);
   __ Ret();
   __ Bind(&fall_through);
   return false;
@@ -1268,8 +1257,7 @@
   const Class& double_class = Class::Handle(
       Isolate::Current()->object_store()->double_class());
   __ TryAllocate(double_class, &fall_through, R0);  // Result register.
-  __ AddImmediate(R1, R0, Double::value_offset() - kHeapObjectTag);
-  __ vstrd(D0, Address(R1));
+  __ StoreDToOffset(D0, R0, Double::value_offset() - kHeapObjectTag);
   __ Ret();
   __ Bind(&fall_through);
   return false;
@@ -1278,14 +1266,12 @@
 
 bool Intrinsifier::Double_getIsNaN(Assembler* assembler) {
   Label is_true;
-  __ Untested("Intrinsifier::Double_getIsNaN");
   __ ldr(R0, Address(SP, 0 * kWordSize));
-  __ AddImmediate(R0, Double::value_offset() - kHeapObjectTag);
-  __ vldrd(D0, Address(R0));
+  __ LoadDFromOffset(D0, R0, Double::value_offset() - kHeapObjectTag);
   __ vcmpd(D0, D0);
   __ vmstat();
-  __ LoadObject(R0, Bool::False(), VS);
-  __ LoadObject(R0, Bool::True(), VC);
+  __ LoadObject(R0, Bool::False(), VC);
+  __ LoadObject(R0, Bool::True(), VS);
   __ Ret();
   return true;
 }
@@ -1293,10 +1279,8 @@
 
 bool Intrinsifier::Double_getIsNegative(Assembler* assembler) {
   Label is_false, is_true, is_zero;
-  __ Untested("Intrinsifier::Double_getIsNegative");
   __ ldr(R0, Address(SP, 0 * kWordSize));
-  __ AddImmediate(R0, Double::value_offset() - kHeapObjectTag);
-  __ vldrd(D0, Address(R0));
+  __ LoadDFromOffset(D0, R0, Double::value_offset() - kHeapObjectTag);
   __ LoadDImmediate(D1, 0.0, R1);
   __ vcmpd(D0, D1);
   __ vmstat();
@@ -1325,8 +1309,7 @@
 
 bool Intrinsifier::Double_toInt(Assembler* assembler) {
   __ ldr(R0, Address(SP, 0 * kWordSize));
-  __ AddImmediate(R0, Double::value_offset() - kHeapObjectTag);
-  __ vldrd(D0, Address(R0));
+  __ LoadDFromOffset(D0, R0, Double::value_offset() - kHeapObjectTag);
   __ vcvtid(S0, D0);
   __ vmovrs(R0, S0);
   // Overflow is signaled with minint.
@@ -1343,18 +1326,15 @@
 
 bool Intrinsifier::Math_sqrt(Assembler* assembler) {
   Label fall_through, is_smi, double_op;
-  __ Untested("Intrinsifier::Math_sqrt");
   TestLastArgumentIsDouble(assembler, &is_smi, &fall_through);
   // Argument is double and is in R0.
-  __ AddImmediate(R0, Double::value_offset() - kHeapObjectTag);
-  __ vldrd(D1, Address(R0));
+  __ LoadDFromOffset(D1, R0, Double::value_offset() - kHeapObjectTag);
   __ Bind(&double_op);
   __ vsqrtd(D0, D1);
   const Class& double_class = Class::Handle(
       Isolate::Current()->object_store()->double_class());
   __ TryAllocate(double_class, &fall_through, R0);  // Result register.
-  __ AddImmediate(R1, R0, Double::value_offset() - kHeapObjectTag);
-  __ vstrd(D0, Address(R1));
+  __ StoreDToOffset(D0, R0, Double::value_offset() - kHeapObjectTag);
   __ Ret();
   __ Bind(&is_smi);
   __ SmiUntag(R0);
@@ -1398,8 +1378,6 @@
   ASSERT(Utils::IsUint(32, a_int_value));
   int32_t a_int32_value = static_cast<int32_t>(a_int_value);
 
-  __ Untested("Random_nextState");
-
   __ ldr(R0, Address(SP, 0 * kWordSize));  // Receiver.
   __ ldr(R1, FieldAddress(R0, state_field.Offset()));  // Field '_state'.
   // Addresses of _state[0] and _state[1].
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 4c1a93b..ec65512 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -297,7 +297,7 @@
 }
 
 
-static void DeleteWeakPersistentHandle(Dart_Handle handle) {
+static void DeleteWeakPersistentHandle(Dart_WeakPersistentHandle handle) {
   ApiState* state = Isolate::Current()->api_state();
   ASSERT(state != NULL);
   FinalizablePersistentHandle* weak_ref =
@@ -322,14 +322,14 @@
   Heap* heap = isolate->heap();
 
   // Allocate the read only object handles here.
-  empty_array_ = Array::ReadOnlyHandle(isolate);
-  sentinel_ = Instance::ReadOnlyHandle(isolate);
-  transition_sentinel_ = Instance::ReadOnlyHandle(isolate);
-  unknown_constant_ =  Instance::ReadOnlyHandle(isolate);
-  non_constant_ =  Instance::ReadOnlyHandle(isolate);
-  bool_true_ = Bool::ReadOnlyHandle(isolate);
-  bool_false_ = Bool::ReadOnlyHandle(isolate);
-  snapshot_writer_error_ = LanguageError::ReadOnlyHandle(isolate);
+  empty_array_ = Array::ReadOnlyHandle();
+  sentinel_ = Instance::ReadOnlyHandle();
+  transition_sentinel_ = Instance::ReadOnlyHandle();
+  unknown_constant_ =  Instance::ReadOnlyHandle();
+  non_constant_ =  Instance::ReadOnlyHandle();
+  bool_true_ = Bool::ReadOnlyHandle();
+  bool_false_ = Bool::ReadOnlyHandle();
+  snapshot_writer_error_ = LanguageError::ReadOnlyHandle();
 
   // Allocate and initialize the null instance.
   // 'null_' must be the first object allocated as it is used in allocation to
@@ -1578,19 +1578,24 @@
   // To work properly, this call requires the super class of this class to be
   // resolved, which is checked by the SuperClass() call.
   Class& cls = Class::Handle(raw());
-  if (IsSignatureClass()) {
-    const Function& signature_fun = Function::Handle(signature_function());
-    if (!signature_fun.is_static() &&
-        !signature_fun.HasInstantiatedSignature()) {
-      cls = signature_fun.Owner();
+  intptr_t num_type_args = 0;
+
+  do {
+    if (cls.IsSignatureClass()) {
+      const Function& signature_fun =
+          Function::Handle(cls.signature_function());
+      if (!signature_fun.is_static() &&
+          !signature_fun.HasInstantiatedSignature()) {
+        cls = signature_fun.Owner();
+      }
     }
-  }
-  intptr_t num_type_args = NumTypeParameters();
-  cls = cls.SuperClass();
-  // Object is its own super class during bootstrap.
-  if (!cls.IsNull() && (cls.raw() != raw())) {
-    num_type_args += cls.NumTypeArguments();
-  }
+    num_type_args += cls.NumTypeParameters();
+    // Object is its own super class during bootstrap.
+    if (cls.SuperClass() == Class::null() || cls.SuperClass() == cls.raw()) {
+      break;
+    }
+    cls = cls.SuperClass();
+  } while (true);
   return num_type_args;
 }
 
@@ -5118,7 +5123,7 @@
 }
 
 
-void TokenStream::DataFinalizer(Dart_Handle handle, void *peer) {
+void TokenStream::DataFinalizer(Dart_WeakPersistentHandle handle, void *peer) {
   ASSERT(peer != NULL);
   ::free(peer);
   DeleteWeakPersistentHandle(handle);
@@ -5300,15 +5305,10 @@
 
 RawTokenStream* TokenStream::New() {
   ASSERT(Object::token_stream_class() != Class::null());
-  TokenStream& result = TokenStream::Handle();
-  {
-    RawObject* raw = Object::Allocate(TokenStream::kClassId,
-                                      TokenStream::InstanceSize(),
-                                      Heap::kOld);
-    NoGCScope no_gc;
-    result ^= raw;
-  }
-  return result.raw();
+  RawObject* raw = Object::Allocate(TokenStream::kClassId,
+                                    TokenStream::InstanceSize(),
+                                    Heap::kOld);
+  return reinterpret_cast<RawTokenStream*>(raw);
 }
 
 
@@ -9234,15 +9234,10 @@
   if (cls.EnsureIsFinalized(isolate) != Error::null()) {
     return Instance::null();
   }
-  Instance& result = Instance::Handle(isolate);
-  {
-    intptr_t instance_size = cls.instance_size();
-    ASSERT(instance_size > 0);
-    RawObject* raw = Object::Allocate(cls.id(), instance_size, space);
-    NoGCScope no_gc;
-    result ^= raw;
-  }
-  return result.raw();
+  intptr_t instance_size = cls.instance_size();
+  ASSERT(instance_size > 0);
+  RawObject* raw = Object::Allocate(cls.id(), instance_size, space);
+  return reinterpret_cast<RawInstance*>(raw);
 }
 
 
@@ -12337,7 +12332,8 @@
 }
 
 
-void ExternalOneByteString::Finalize(Dart_Handle handle, void* peer) {
+void ExternalOneByteString::Finalize(Dart_WeakPersistentHandle handle,
+                                     void* peer) {
   delete reinterpret_cast<ExternalStringData<uint8_t>*>(peer);
   DeleteWeakPersistentHandle(handle);
 }
@@ -12374,7 +12370,8 @@
 }
 
 
-void ExternalTwoByteString::Finalize(Dart_Handle handle, void* peer) {
+void ExternalTwoByteString::Finalize(Dart_WeakPersistentHandle handle,
+                                     void* peer) {
   delete reinterpret_cast<ExternalStringData<uint16_t>*>(peer);
   DeleteWeakPersistentHandle(handle);
 }
@@ -13320,15 +13317,10 @@
 RawWeakProperty* WeakProperty::New(Heap::Space space) {
   ASSERT(Isolate::Current()->object_store()->weak_property_class()
          != Class::null());
-  WeakProperty& result = WeakProperty::Handle();
-  {
-    RawObject* raw = Object::Allocate(WeakProperty::kClassId,
-                                      WeakProperty::InstanceSize(),
-                                      space);
-    NoGCScope no_gc;
-    result ^= raw;
-  }
-  return result.raw();
+  RawObject* raw = Object::Allocate(WeakProperty::kClassId,
+                                    WeakProperty::InstanceSize(),
+                                    space);
+  return reinterpret_cast<RawWeakProperty*>(raw);
 }
 
 
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 01b8c78..349542f 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -78,7 +78,7 @@
     initializeHandle(obj, raw_ptr);                                            \
     return *obj;                                                               \
   }                                                                            \
-  static object* ReadOnlyHandle(Isolate* isolate) {                            \
+  static object* ReadOnlyHandle() {                                            \
     object* obj = reinterpret_cast<object*>(                                   \
         Dart::AllocateReadOnlyHandle());                                       \
     initializeHandle(obj, object::null());                                     \
@@ -2052,7 +2052,7 @@
   void SetPrivateKey(const String& value) const;
 
   static RawTokenStream* New();
-  static void DataFinalizer(Dart_Handle handle, void *peer);
+  static void DataFinalizer(Dart_WeakPersistentHandle handle, void *peer);
 
   FINAL_HEAP_OBJECT_IMPLEMENTATION(TokenStream, Object);
   friend class Class;
@@ -4753,7 +4753,7 @@
     raw_ptr(str)->external_data_ = data;
   }
 
-  static void Finalize(Dart_Handle handle, void* peer);
+  static void Finalize(Dart_WeakPersistentHandle handle, void* peer);
 
   static RawExternalOneByteString* ReadFrom(SnapshotReader* reader,
                                             intptr_t object_id,
@@ -4819,7 +4819,7 @@
     raw_ptr(str)->external_data_ = data;
   }
 
-  static void Finalize(Dart_Handle handle, void* peer);
+  static void Finalize(Dart_WeakPersistentHandle handle, void* peer);
 
   static RawExternalTwoByteString* ReadFrom(SnapshotReader* reader,
                                             intptr_t object_id,
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
index 303bd75..7659c44 100644
--- a/runtime/vm/parser.cc
+++ b/runtime/vm/parser.cc
@@ -116,13 +116,6 @@
 }
 
 
-LocalVariable* ParsedFunction::CreateArrayLiteralVar(intptr_t token_pos) {
-  return new LocalVariable(token_pos,
-                           Symbols::ArrayLiteralVar(),
-                           Type::ZoneHandle(Type::ArrayType()));
-}
-
-
 void ParsedFunction::SetNodeSequence(SequenceNode* node_sequence) {
   ASSERT(node_sequence_ == NULL);
   ASSERT(node_sequence != NULL);
@@ -788,10 +781,6 @@
       UNREACHABLE();
   }
 
-  parsed_function->set_array_literal_var(
-      ParsedFunction::CreateArrayLiteralVar(func.token_pos()));
-  node_sequence->scope()->AddVariable(parsed_function->array_literal_var());
-
   if (!HasReturnNode(node_sequence)) {
     // Add implicit return node.
     node_sequence->Add(new ReturnNode(func.end_token_pos()));
@@ -1409,18 +1398,6 @@
 }
 
 
-LocalVariable* Parser::BuildArrayTempLocal(intptr_t token_pos) {
-  char name[64];
-  OS::SNPrint(name, 64, ":arrlit%"Pd, token_pos);
-  LocalVariable* temp =
-      new LocalVariable(token_pos,
-                        String::ZoneHandle(Symbols::New(name)),
-                        Type::ZoneHandle(Type::ArrayType()));
-  current_block_->scope->AddVariable(temp);
-  return temp;
-}
-
-
 StaticCallNode* Parser::BuildInvocationMirrorAllocation(
     intptr_t call_pos,
     const String& function_name,
@@ -1438,9 +1415,8 @@
   arguments->Add(new LiteralNode(args_pos, args_descriptor));
   // The third argument is an array containing the original function arguments,
   // including the receiver.
-  ArrayNode* args_array = new ArrayNode(
-      args_pos, Type::ZoneHandle(Type::ArrayType()),
-      *BuildArrayTempLocal(call_pos));
+  ArrayNode* args_array =
+      new ArrayNode(args_pos, Type::ZoneHandle(Type::ArrayType()));
   for (intptr_t i = 0; i < function_args.length(); i++) {
     args_array->AddElement(function_args.NodeAt(i));
   }
@@ -7028,71 +7004,42 @@
 }
 
 
-// A compound assignment consists of a store and a load part. In order
-// to control inputs with potential side effects, the store part stores any
-// side effect creating inputs into locals. The load part reads then from
-// those locals. If expr may have side effects, it will be split into two new
-// left and right nodes. 'expr' becomes the right node, left node is returned as
-// result.
-AstNode* Parser::PrepareCompoundAssignmentNodes(AstNode** expr) {
+LetNode* Parser::PrepareCompoundAssignmentNodes(AstNode** expr) {
   AstNode* node = *expr;
+  intptr_t token_pos = node->token_pos();
+  LetNode* result = new LetNode(token_pos);
   if (node->IsLoadIndexedNode()) {
-    LoadIndexedNode* left_node = node->AsLoadIndexedNode();
-    LoadIndexedNode* right_node = left_node;
-    intptr_t token_pos = node->token_pos();
-    node = NULL;  // Do not use it.
-    if (!IsSimpleLocalOrLiteralNode(left_node->array())) {
-      LocalVariable* temp =
-          CreateTempConstVariable(token_pos, "lia");
-      StoreLocalNode* save =
-          new StoreLocalNode(token_pos, temp, left_node->array());
-      left_node = new LoadIndexedNode(token_pos,
-                                      save,
-                                      left_node->index_expr(),
-                                      left_node->super_class());
-      right_node = new LoadIndexedNode(token_pos,
-                                       new LoadLocalNode(token_pos, temp),
-                                       right_node->index_expr(),
-                                       right_node->super_class());
+    LoadIndexedNode* load_indexed = node->AsLoadIndexedNode();
+    AstNode* array = load_indexed->array();
+    AstNode* index = load_indexed->index_expr();
+    if (!IsSimpleLocalOrLiteralNode(load_indexed->array())) {
+      LocalVariable* t0 = result->AddInitializer(load_indexed->array());
+      array = new LoadLocalNode(token_pos, t0);
     }
-    if (!IsSimpleLocalOrLiteralNode(left_node->index_expr())) {
-      LocalVariable* temp =
-          CreateTempConstVariable(token_pos, "lix");
-      StoreLocalNode* save =
-          new StoreLocalNode(token_pos, temp, left_node->index_expr());
-      left_node = new LoadIndexedNode(token_pos,
-                                      left_node->array(),
-                                      save,
-                                      left_node->super_class());
-      right_node = new LoadIndexedNode(token_pos,
-                                       right_node->array(),
-                                       new LoadLocalNode(token_pos, temp),
-                                       right_node->super_class());
+    if (!IsSimpleLocalOrLiteralNode(load_indexed->index_expr())) {
+      LocalVariable* t1 = result->AddInitializer(
+          load_indexed->index_expr());
+      index = new LoadLocalNode(token_pos, t1);
     }
-    *expr = right_node;
-    return left_node;
+    *expr = new LoadIndexedNode(token_pos,
+                                array,
+                                index,
+                                load_indexed->super_class());
+    return result;
   }
   if (node->IsInstanceGetterNode()) {
-    InstanceGetterNode* left_node = node->AsInstanceGetterNode();
-    InstanceGetterNode* right_node = left_node;
-    intptr_t token_pos = node->token_pos();
-    node = NULL;  // Do not use it.
-    if (!IsSimpleLocalOrLiteralNode(left_node->receiver())) {
-      LocalVariable* temp =
-          CreateTempConstVariable(token_pos, "igr");
-      StoreLocalNode* save =
-          new StoreLocalNode(token_pos, temp, left_node->receiver());
-      left_node = new InstanceGetterNode(token_pos,
-                                         save,
-                                         left_node->field_name());
-      right_node = new InstanceGetterNode(token_pos,
-                                          new LoadLocalNode(token_pos, temp),
-                                          right_node->field_name());
+    InstanceGetterNode* getter = node->AsInstanceGetterNode();
+    AstNode* receiver = getter->receiver();
+    if (!IsSimpleLocalOrLiteralNode(getter->receiver())) {
+      LocalVariable* t0 = result->AddInitializer(getter->receiver());
+      receiver = new LoadLocalNode(token_pos, t0);
     }
-    *expr = right_node;
-    return left_node;
+    *expr = new InstanceGetterNode(token_pos,
+                                   receiver,
+                                   getter->field_name());
+    return result;
   }
-  return *expr;
+  return result;
 }
 
 
@@ -7123,12 +7070,12 @@
 
 AstNode* Parser::ParseCascades(AstNode* expr) {
   intptr_t cascade_pos = TokenPos();
-  LocalVariable* cascade_receiver_var =
-      CreateTempConstVariable(cascade_pos, "casc");
+  LetNode* result = new LetNode(cascade_pos);
+  LocalVariable* cascade_receiver_var = result->AddInitializer(expr);
+  // TODO(fschneider): Make LetNode support more than one body node and
+  // replace the SequenceNode here and CommaNode here and in postfix
+  // expressions.
   SequenceNode* cascade = new SequenceNode(cascade_pos, NULL);
-  StoreLocalNode* save_cascade =
-      new StoreLocalNode(cascade_pos, cascade_receiver_var, expr);
-  cascade->Add(save_cascade);
   while (CurrentToken() == Token::kCASCADE) {
     cascade_pos = TokenPos();
     LoadLocalNode* load_cascade_receiver =
@@ -7150,30 +7097,42 @@
       const intptr_t assignment_pos = TokenPos();
       ConsumeToken();
       AstNode* right_expr = ParseExpr(kAllowConst, kNoCascades);
-      AstNode* left_expr = expr;
       if (assignment_op != Token::kASSIGN) {
         // Compound assignment: store inputs with side effects into
         // temporary locals.
-        left_expr = PrepareCompoundAssignmentNodes(&expr);
+        LetNode* let_expr = PrepareCompoundAssignmentNodes(&expr);
+        right_expr =
+            ExpandAssignableOp(assignment_pos, assignment_op, expr, right_expr);
+        AstNode* assign_expr = CreateAssignmentNode(expr, right_expr);
+        if (assign_expr == NULL) {
+          ErrorMsg(assignment_pos,
+                   "left hand side of '%s' is not assignable",
+                   Token::Str(assignment_op));
+        }
+        let_expr->set_body(assign_expr);
+        expr = let_expr;
+      } else {
+        right_expr =
+            ExpandAssignableOp(assignment_pos, assignment_op, expr, right_expr);
+        AstNode* assign_expr = CreateAssignmentNode(expr, right_expr);
+        if (assign_expr == NULL) {
+          ErrorMsg(assignment_pos,
+                   "left hand side of '%s' is not assignable",
+                   Token::Str(assignment_op));
+        }
+        expr = assign_expr;
       }
-      right_expr =
-          ExpandAssignableOp(assignment_pos, assignment_op, expr, right_expr);
-      AstNode* assign_expr = CreateAssignmentNode(left_expr, right_expr);
-      if (assign_expr == NULL) {
-        ErrorMsg(assignment_pos,
-                 "left hand side of '%s' is not assignable",
-                 Token::Str(assignment_op));
-      }
-      expr = assign_expr;
     }
     cascade->Add(expr);
   }
   // The result is a pair of the (side effects of the) cascade sequence
   // followed by the (value of the) receiver temp variable load.
-  return new CommaNode(
+  CommaNode* body = new CommaNode(
       cascade_pos,
       cascade,
       new LoadLocalNode(cascade_pos, cascade_receiver_var));
+  result->set_body(body);
+  return result;
 }
 
 
@@ -7207,20 +7166,30 @@
     ErrorMsg(right_expr_pos, "expression must be a compile-time constant");
   }
   AstNode* right_expr = ParseExpr(require_compiletime_const, consume_cascades);
-  AstNode* left_expr = expr;
   if (assignment_op != Token::kASSIGN) {
     // Compound assignment: store inputs with side effects into temp. locals.
-    left_expr = PrepareCompoundAssignmentNodes(&expr);
+    LetNode* let_expr = PrepareCompoundAssignmentNodes(&expr);
+    AstNode* assigned_value =
+        ExpandAssignableOp(assignment_pos, assignment_op, expr, right_expr);
+    AstNode* assign_expr = CreateAssignmentNode(expr, assigned_value);
+    if (assign_expr == NULL) {
+      ErrorMsg(assignment_pos,
+               "left hand side of '%s' is not assignable",
+               Token::Str(assignment_op));
+    }
+    let_expr->set_body(assign_expr);
+    return let_expr;
+  } else {
+    AstNode* assigned_value =
+        ExpandAssignableOp(assignment_pos, assignment_op, expr, right_expr);
+    AstNode* assign_expr = CreateAssignmentNode(expr, assigned_value);
+    if (assign_expr == NULL) {
+      ErrorMsg(assignment_pos,
+               "left hand side of '%s' is not assignable",
+               Token::Str(assignment_op));
+    }
+    return assign_expr;
   }
-  right_expr =
-      ExpandAssignableOp(assignment_pos, assignment_op, expr, right_expr);
-  AstNode* assign_expr = CreateAssignmentNode(left_expr, right_expr);
-  if (assign_expr == NULL) {
-    ErrorMsg(assignment_pos,
-             "left hand side of '%s' is not assignable",
-             Token::Str(assignment_op));
-  }
-  return assign_expr;
 }
 
 
@@ -7278,7 +7247,7 @@
       ErrorMsg("expression is not assignable");
     }
     // Is prefix.
-    AstNode* left_expr = PrepareCompoundAssignmentNodes(&expr);
+    LetNode* let_expr = PrepareCompoundAssignmentNodes(&expr);
     Token::Kind binary_op =
         (incr_op == Token::kINCR) ? Token::kADD : Token::kSUB;
     BinaryOpNode* add = new BinaryOpNode(
@@ -7286,9 +7255,10 @@
         binary_op,
         expr,
         new LiteralNode(op_pos, Smi::ZoneHandle(Smi::New(1))));
-    AstNode* store = CreateAssignmentNode(left_expr, add);
+    AstNode* store = CreateAssignmentNode(expr, add);
     ASSERT(store != NULL);
-    expr = store;
+    let_expr->set_body(store);
+    expr = let_expr;
   } else {
     expr = ParsePostfixExpr();
   }
@@ -7770,24 +7740,24 @@
     }
     ConsumeToken();
     // Not prefix.
-    AstNode* left_expr = PrepareCompoundAssignmentNodes(&postfix_expr);
-    const LocalVariable* temp = GetIncrementTempLocal();
-    AstNode* save =
-        new StoreLocalNode(postfix_expr_pos, temp, postfix_expr);
+    LetNode* let_expr = PrepareCompoundAssignmentNodes(&postfix_expr);
+    LocalVariable* temp = let_expr->AddInitializer(postfix_expr);
     Token::Kind binary_op =
         (incr_op == Token::kINCR) ? Token::kADD : Token::kSUB;
     BinaryOpNode* add = new BinaryOpNode(
         postfix_expr_pos,
         binary_op,
-        save,
+        new LoadLocalNode(postfix_expr_pos, temp),
         new LiteralNode(postfix_expr_pos, Smi::ZoneHandle(Smi::New(1))));
-    AstNode* store = CreateAssignmentNode(left_expr, add);
+    AstNode* store = CreateAssignmentNode(postfix_expr, add);
+    ASSERT(store != NULL);
     // The result is a pair of the (side effects of the) store followed by
     // the (value of the) initial value temp variable load.
-    return new CommaNode(
+    let_expr->set_body(new CommaNode(
         postfix_expr_pos,
         store,
-        new LoadLocalNode(postfix_expr_pos, temp));
+        new LoadLocalNode(postfix_expr_pos, temp)));
+    return let_expr;
   }
   return postfix_expr;
 }
@@ -8118,6 +8088,10 @@
       if (const_value.IsError()) {
         const Error& error = Error::Cast(const_value);
         if (error.IsUnhandledException()) {
+          // 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);
           field.set_value(Instance::Handle());
           // It is a compile-time error if evaluation of a compile-time constant
           // would raise an exception.
@@ -8181,6 +8155,10 @@
                                                arg_values,
                                                arg_descriptor));
   if (result.IsError()) {
+      // 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);
       if (result.IsUnhandledException()) {
         return result.raw();
       } else {
@@ -8862,9 +8840,7 @@
           new LiteralNode(TokenPos(), empty_array);
       factory_param->Add(empty_array_literal);
     } else {
-      const LocalVariable& temp_local = *BuildArrayTempLocal(type_pos);
-      ArrayNode* list =
-          new ArrayNode(TokenPos(), type, temp_local, element_list);
+      ArrayNode* list = new ArrayNode(TokenPos(), type, element_list);
       factory_param->Add(list);
     }
     return CreateConstructorCallNode(literal_pos,
@@ -8883,13 +8859,10 @@
   if (!type_arguments.IsNull() && !type_arguments.IsInstantiated()) {
     EnsureExpressionTemp();
   }
-  LocalVariable* allocated =
-      CreateTempConstVariable(token_pos, "alloc");
   return new ConstructorCallNode(token_pos,
                                  type_arguments,
                                  constructor,
-                                 arguments,
-                                 allocated);
+                                 arguments);
 }
 
 
@@ -9087,7 +9060,6 @@
     ArrayNode* kv_pairs = new ArrayNode(
         TokenPos(),
         Type::ZoneHandle(Type::ArrayType()),
-        *BuildArrayTempLocal(type_pos),
         kv_pairs_list);
     factory_param->Add(kv_pairs);
     return CreateConstructorCallNode(literal_pos,
@@ -9474,7 +9446,6 @@
     ArrayNode* values = new ArrayNode(
         TokenPos(),
         Type::ZoneHandle(Type::ArrayType()),
-        *BuildArrayTempLocal(TokenPos()),
         values_list);
     interpolate_arg->Add(values);
     primary = MakeStaticCall(Symbols::StringBase(),
diff --git a/runtime/vm/parser.h b/runtime/vm/parser.h
index b7310eb..e7431a1 100644
--- a/runtime/vm/parser.h
+++ b/runtime/vm/parser.h
@@ -39,7 +39,6 @@
         saved_current_context_var_(NULL),
         saved_entry_context_var_(NULL),
         expression_temp_var_(NULL),
-        array_literal_var_(NULL),
         first_parameter_index_(0),
         first_stack_local_index_(0),
         num_copied_params_(0),
@@ -102,17 +101,6 @@
   }
   static LocalVariable* CreateExpressionTempVar(intptr_t token_pos);
 
-  void set_array_literal_var(LocalVariable* local) {
-    ASSERT((local != NULL) &&  (array_literal_var_ == NULL));
-    array_literal_var_ = local;
-  }
-  LocalVariable* array_literal_var() const {
-    ASSERT(array_literal_var_ != NULL);
-    return array_literal_var_;
-  }
-
-  static LocalVariable* CreateArrayLiteralVar(intptr_t token_pos);
-
   int first_parameter_index() const { return first_parameter_index_; }
   int first_stack_local_index() const { return first_stack_local_index_; }
   int num_copied_params() const { return num_copied_params_; }
@@ -128,9 +116,6 @@
   LocalVariable* saved_current_context_var_;
   LocalVariable* saved_entry_context_var_;
   LocalVariable* expression_temp_var_;
-  // TODO(hausner): Remove once ArrayNode creation is removed from flow
-  // graph builder.
-  LocalVariable* array_literal_var_;
 
   int first_parameter_index_;
   int first_stack_local_index_;
@@ -600,7 +585,7 @@
                               Token::Kind assignment_op,
                               AstNode* lhs,
                               AstNode* rhs);
-  AstNode* PrepareCompoundAssignmentNodes(AstNode** expr);
+  LetNode* PrepareCompoundAssignmentNodes(AstNode** expr);
   LocalVariable* CreateTempConstVariable(intptr_t token_pos, const char* s);
 
   static bool IsAssignableExpr(AstNode* expr);
@@ -636,8 +621,6 @@
       const Function& constructor,
       ArgumentListNode* arguments);
 
-  LocalVariable* BuildArrayTempLocal(intptr_t token_pos);
-
   Script& script_;
   TokenStream::Iterator tokens_iterator_;
   Token::Kind token_kind_;  // Cached token kind for current token.
diff --git a/runtime/vm/scopes.h b/runtime/vm/scopes.h
index 4b0fd2a..fa95e9d 100644
--- a/runtime/vm/scopes.h
+++ b/runtime/vm/scopes.h
@@ -32,7 +32,7 @@
       is_final_(false),
       is_captured_(false),
       is_invisible_(false),
-      index_(LocalVariable::kUnitializedIndex) {
+      index_(LocalVariable::kUninitializedIndex) {
     ASSERT(type.IsZoneHandle());
     ASSERT(type.IsFinalized());
   }
@@ -54,7 +54,7 @@
   void set_is_captured() { is_captured_ = true; }
 
   bool HasIndex() const {
-    return index_ != kUnitializedIndex;
+    return index_ != kUninitializedIndex;
   }
   int index() const {
     ASSERT(HasIndex());
@@ -63,8 +63,7 @@
 
   // Assign an index to a local.
   void set_index(int index) {
-    ASSERT(!HasIndex());
-    ASSERT(index != kUnitializedIndex);
+    ASSERT(index != kUninitializedIndex);
     index_ = index;
   }
 
@@ -95,7 +94,7 @@
   int BitIndexIn(intptr_t var_count) const;
 
  private:
-  static const int kUnitializedIndex = INT_MIN;
+  static const int kUninitializedIndex = INT_MIN;
 
   const intptr_t token_pos_;
   const String& name_;
diff --git a/runtime/vm/simulator_arm.cc b/runtime/vm/simulator_arm.cc
index 3542587..14442b8 100644
--- a/runtime/vm/simulator_arm.cc
+++ b/runtime/vm/simulator_arm.cc
@@ -2826,14 +2826,6 @@
         UnimplementedInstruction(instr);
       }
     }
-  } else if (instr->IsMrcIdIsar0()) {
-    // mrc of ID_ISAR0.
-    Register rd = instr->RdField();
-    if (CPUFeatures::integer_division_supported()) {
-      set_register(rd, 0x02100010);  // sim has sdiv, udiv, bkpt and clz.
-    } else {
-      set_register(rd, 0x00100010);  // simulator has only bkpt and clz.
-    }
   } else {
     UnimplementedInstruction(instr);
   }
diff --git a/runtime/vm/symbols.cc b/runtime/vm/symbols.cc
index a8d4cae..d35b1c1 100644
--- a/runtime/vm/symbols.cc
+++ b/runtime/vm/symbols.cc
@@ -65,7 +65,7 @@
     // The symbol_table needs to be reloaded as it might have grown in the
     // previous iteration.
     symbol_table = object_store->symbol_table();
-    String* str = String::ReadOnlyHandle(isolate);
+    String* str = String::ReadOnlyHandle();
     *str = OneByteString::New(names[i], Heap::kOld);
     Add(symbol_table, *str);
     symbol_handles_[i] = str;
@@ -81,7 +81,7 @@
     ASSERT(idx < kMaxPredefinedId);
     ASSERT(Utf::IsLatin1(c));
     uint8_t ch = static_cast<uint8_t>(c);
-    String* str = String::ReadOnlyHandle(isolate);
+    String* str = String::ReadOnlyHandle();
     *str = OneByteString::New(&ch, 1, Heap::kOld);
     Add(symbol_table, *str);
     predefined_[c] = str->raw();
diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h
index 6bc6f34..741a96f 100644
--- a/runtime/vm/symbols.h
+++ b/runtime/vm/symbols.h
@@ -58,7 +58,6 @@
   V(SavedTryContextVar, ":saved_try_context_var")                              \
   V(ExceptionVar, ":exception_var")                                            \
   V(StacktraceVar, ":stacktrace_var")                                          \
-  V(ArrayLiteralVar, ":array_literal_var")                                     \
   V(ListLiteralElement, "list literal element")                                \
   V(ForInIter, ":for-in-iter")                                                 \
   V(Library, "library")                                                        \
diff --git a/runtime/vm/unit_test.cc b/runtime/vm/unit_test.cc
index bbde54f..a91a7e1 100644
--- a/runtime/vm/unit_test.cc
+++ b/runtime/vm/unit_test.cc
@@ -139,7 +139,7 @@
   if (tag == kCanonicalizeUrl) {
     return url;
   }
-  return Api::Success(Isolate::Current());
+  return Api::Success();
 }
 
 
diff --git a/sdk/bin/dart b/sdk/bin/dart
index 22abed8..43855cb 100755
--- a/sdk/bin/dart
+++ b/sdk/bin/dart
@@ -12,11 +12,11 @@
   DART_CONFIGURATION="ReleaseIA32"
 fi
 
-if [[ `uname` == 'Darwin' ]]; 
+if [[ `uname` == 'Darwin' ]];
 then
-  BIN_DIR="$CUR_DIR"/../../xcodebuild/$DART_CONFIGURATION
+  BIN_DIR="$CUR_DIR"/../../xcodebuild/$DART_CONFIGURATION/dart-sdk/bin
 else
-  BIN_DIR="$CUR_DIR"/../../out/$DART_CONFIGURATION
-fi 
+  BIN_DIR="$CUR_DIR"/../../out/$DART_CONFIGURATION/dart-sdk/bin
+fi
 
 exec "$BIN_DIR"/dart "$@"
diff --git a/sdk/bin/dart2js b/sdk/bin/dart2js
index 96354ca..2baaba7 100755
--- a/sdk/bin/dart2js
+++ b/sdk/bin/dart2js
@@ -41,9 +41,6 @@
 declare -a EXTRA_VM_OPTIONS
 
 if test -f "$SNAPSHOT"; then
-  # TODO(ahe): Remove the following line when we are relatively sure it works.
-  echo Using snapshot "$SNAPSHOT" 1>&2
-
   EXTRA_OPTIONS[${#EXTRA_OPTIONS[@]}]="--library-root=$SDK_DIR"
 fi
 
diff --git a/sdk/bin/dart2js.bat b/sdk/bin/dart2js.bat
index be0219f..aa6efb7 100644
--- a/sdk/bin/dart2js.bat
+++ b/sdk/bin/dart2js.bat
@@ -29,7 +29,6 @@
 )
 
 if exist "%SNAPSHOT%" (
-  echo Using snapshot "%SNAPSHOT%" >&2
   set EXTRA_OPTIONS=%EXTRA_OPTIONS% "--library-root=%SDK_DIR%"
 )
 
diff --git a/sdk/bin/pub b/sdk/bin/pub
index 76085ab..19acaa3 100755
--- a/sdk/bin/pub
+++ b/sdk/bin/pub
@@ -1,11 +1,46 @@
 #!/bin/bash
-# Run pub.dart on the Dart VM. This script assumes the Dart SDK's directory
-# structure.
+# 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.
 
-# Setting BIN_DIR this way is ugly, but is needed to handle the case where
-# dart-sdk/bin has been symlinked to. On MacOS, readlink doesn't work
-# with this case.
-BIN_DIR="$(cd "${0%/*}" ; pwd -P)"
-DART_SDK="$(cd "${BIN_DIR%/*}" ; pwd -P)"
+function follow_links() {
+  while [ -h "$1" ]; do
+    # On Mac OS, readlink -f doesn't work.
+    1="$(readlink "$1")"
+  done
+  echo "$1"
+}
 
-exec "$BIN_DIR"/dart "$DART_SDK"/bin/snapshots/pub.dart.snapshot $@
+# Unlike $0, $BASH_SOURCE points to the absolute path of this file.
+PROG_NAME="$(follow_links "$BASH_SOURCE")"
+
+# Handle the case where dart-sdk/bin has been symlinked to.
+BIN_DIR="$(follow_links "$(cd "${PROG_NAME%/*}" ; pwd -P)")"
+
+SDK_DIR="$(cd "${BIN_DIR}/.." ; pwd -P)"
+
+DART="$BIN_DIR/dart"
+
+SNAPSHOT="$BIN_DIR/snapshots/pub.dart.snapshot"
+
+if test -f "$SNAPSHOT"; then
+  # We are running the snapshot in the built SDK.
+  exec "$DART" "--checked" "$SNAPSHOT" "$@"
+else
+  # We are running pub from source in the development repo.
+  if [ -z "$DART_CONFIGURATION" ];
+  then
+    DART_CONFIGURATION="ReleaseIA32"
+  fi
+
+  if [[ `uname` == 'Darwin' ]];
+  then
+    PACKAGES_DIR="$SDK_DIR"/../xcodebuild/$DART_CONFIGURATION/packages/
+  else
+    PACKAGES_DIR="$SDK_DIR"/../out/$DART_CONFIGURATION/packages/
+  fi
+
+  PUB="$SDK_DIR/lib/_internal/pub/bin/pub.dart"
+
+  exec "$DART" "--checked" "--package-root=$PACKAGES_DIR" "$PUB" "$@"
+fi
diff --git a/sdk/lib/_internal/compiler/implementation/apiimpl.dart b/sdk/lib/_internal/compiler/implementation/apiimpl.dart
index c582bc0..067417a 100644
--- a/sdk/lib/_internal/compiler/implementation/apiimpl.dart
+++ b/sdk/lib/_internal/compiler/implementation/apiimpl.dart
@@ -59,6 +59,8 @@
             preserveComments: hasOption(options, '--preserve-comments'),
             verbose: hasOption(options, '--verbose'),
             sourceMapUri: extractSourceMapUri(options),
+            globalJsName: extractStringOption(
+                options, '--global-js-name=', r'$'),
             buildId: extractStringOption(
                 options, '--build-id=',
                 "build number could not be determined")) {
diff --git a/sdk/lib/_internal/compiler/implementation/closure.dart b/sdk/lib/_internal/compiler/implementation/closure.dart
index b1d62ca..35b227e 100644
--- a/sdk/lib/_internal/compiler/implementation/closure.dart
+++ b/sdk/lib/_internal/compiler/implementation/closure.dart
@@ -112,8 +112,11 @@
               // classes (since the emitter sorts classes by their id).
               compiler.getNextFreeClassId(),
               STATE_DONE) {
-    compiler.closureClass.ensureResolved(compiler);
-    supertype = compiler.closureClass.computeType(compiler);
+    ClassElement superclass = methodElement.isInstanceMember()
+        ? compiler.boundClosureClass
+        : compiler.closureClass;
+    superclass.ensureResolved(compiler);
+    supertype = superclass.computeType(compiler);
     interfaces = const Link<DartType>();
     allSupertypes = const Link<DartType>().prepend(supertype);
     thisType = rawType = new InterfaceType(this);
diff --git a/sdk/lib/_internal/compiler/implementation/compile_time_constants.dart b/sdk/lib/_internal/compiler/implementation/compile_time_constants.dart
index 47b66c2..7a31f2e 100644
--- a/sdk/lib/_internal/compiler/implementation/compile_time_constants.dart
+++ b/sdk/lib/_internal/compiler/implementation/compile_time_constants.dart
@@ -62,11 +62,13 @@
 
   void registerStaticUse(Element element) {
     if (isMetadata) return;
+    compiler.analyzeElement(element.declaration);
     compiler.enqueuer.codegen.registerStaticUse(element);
   }
 
   void registerGetOfStaticFunction(FunctionElement element) {
     if (isMetadata) return;
+    compiler.analyzeElement(element.declaration);
     compiler.enqueuer.codegen.registerGetOfStaticFunction(element);
   }
 
@@ -124,7 +126,7 @@
         return result;
       }
       return compiler.withCurrentElement(element, () {
-        TreeElements definitions = compiler.analyzeElement(element);
+        TreeElements definitions = compiler.analyzeElement(element.declaration);
         Constant constant = compileVariableWithDefinitions(
             element, definitions, isConst: isConst);
         return constant;
@@ -645,6 +647,10 @@
 
     Send send = node.send;
     FunctionElement constructor = elements[send];
+    // TODO(ahe): This is nasty: we must eagerly analyze the
+    // constructor to ensure the redirectionTarget has been computed
+    // correctly.  Find a way to avoid this.
+    compiler.analyzeElement(constructor.declaration);
     constructor = constructor.redirectionTarget;
     ClassElement classElement = constructor.getEnclosingClass();
     // The constructor must be an implementation to ensure that field
diff --git a/sdk/lib/_internal/compiler/implementation/compiler.dart b/sdk/lib/_internal/compiler/implementation/compiler.dart
index f14543f..be0fc84 100644
--- a/sdk/lib/_internal/compiler/implementation/compiler.dart
+++ b/sdk/lib/_internal/compiler/implementation/compiler.dart
@@ -286,6 +286,12 @@
    */
   final Uri sourceMapUri;
 
+  /**
+   * The name to use for the global JS object in JS output.  Default
+   * value is "$".
+   */
+  final String globalJsName;
+
   final api.CompilerOutputProvider outputProvider;
 
   bool disableInlining = false;
@@ -306,6 +312,7 @@
 
   ClassElement objectClass;
   ClassElement closureClass;
+  ClassElement boundClosureClass;
   ClassElement dynamicClass;
   ClassElement boolClass;
   ClassElement numClass;
@@ -412,6 +419,9 @@
   static const SourceString START_ROOT_ISOLATE =
       const SourceString('startRootIsolate');
 
+  static const String UNDETERMINED_BUILD_ID =
+      "build number could not be determined";
+
   final Selector iteratorSelector =
       new Selector.getter(const SourceString('iterator'), null);
   final Selector currentSelector =
@@ -459,15 +469,15 @@
             this.preserveComments: false,
             this.verbose: false,
             this.sourceMapUri: null,
-            this.buildId: "build number could not be determined",
+            this.buildId: UNDETERMINED_BUILD_ID,
+            this.globalJsName: r'$',
             outputProvider,
             List<String> strips: const []})
       : this.analyzeOnly = analyzeOnly || analyzeSignaturesOnly,
         this.analyzeSignaturesOnly = analyzeSignaturesOnly,
-        this.outputProvider =
-            (outputProvider == null) ? NullSink.outputProvider : outputProvider
-
-  {
+        this.outputProvider = (outputProvider == null)
+            ? NullSink.outputProvider
+            : outputProvider {
     world = new World(this);
 
     closureMapping.ClosureNamer closureNamer;
@@ -508,6 +518,8 @@
   Universe get resolverWorld => enqueuer.resolution.universe;
   Universe get codegenWorld => enqueuer.codegen.universe;
 
+  bool get hasBuildId => buildId != UNDETERMINED_BUILD_ID;
+
   int getNextFreeClassId() => nextFreeClassId++;
 
   void ensure(bool condition) {
@@ -643,6 +655,7 @@
     }
     if (uri == Uri.parse('dart:mirrors')) {
       mirrorSystemClass = library.find(const SourceString('MirrorSystem'));
+      metadataHandler = constantHandler;
     } else if (uri == Uri.parse('dart:_collection-dev')) {
       symbolImplementationClass = library.find(const SourceString('Symbol'));
     }
@@ -702,6 +715,7 @@
       return result;
     }
     jsInvocationMirrorClass = lookupHelperClass('JSInvocationMirror');
+    boundClosureClass = lookupHelperClass('BoundClosure');
     closureClass = lookupHelperClass('Closure');
     dynamicClass = lookupHelperClass('Dynamic_');
     nullClass = lookupHelperClass('Null');
@@ -822,6 +836,7 @@
     // Elements required by enqueueHelpers are global dependencies
     // that are not pulled in by a particular element.
     backend.enqueueHelpers(enqueuer.resolution, globalDependencies);
+    resolveReflectiveDataIfNeeded();
     processQueue(enqueuer.resolution, main);
     enqueuer.resolution.logSummary(log);
 
@@ -864,8 +879,19 @@
     checkQueues();
   }
 
+  void resolveReflectiveDataIfNeeded() {
+    // Only need reflective data when dart:mirrors is loaded.
+    if (mirrorSystemClass == null) return;
+
+    for (LibraryElement library in libraries.values) {
+      for (Link link = library.metadata; !link.isEmpty; link = link.tail) {
+        link.head.ensureResolved(this);
+      }
+    }
+  }
+
   void fullyEnqueueLibrary(LibraryElement library) {
-    library.forEachLocalMember(fullyEnqueueTopLevelElement);
+    library.implementation.forEachLocalMember(fullyEnqueueTopLevelElement);
   }
 
   void fullyEnqueueTopLevelElement(Element element) {
@@ -948,7 +974,8 @@
   TreeElements analyzeElement(Element element) {
     assert(invariant(element, element.isDeclaration));
     assert(!element.isForwardingConstructor);
-    TreeElements elements = enqueuer.resolution.getCachedElements(element);
+    ResolutionEnqueuer world = enqueuer.resolution;
+    TreeElements elements = world.getCachedElements(element);
     if (elements != null) return elements;
     assert(parser != null);
     Node tree = parser.parse(element);
@@ -956,8 +983,9 @@
     elements = resolver.resolve(element);
     if (elements != null && !analyzeSignaturesOnly) {
       // Only analyze nodes with a corresponding [TreeElements].
-      checker.check(tree, elements);
+      checker.check(elements);
     }
+    world.resolvedElements[element] = elements;
     return elements;
   }
 
@@ -978,8 +1006,6 @@
     TreeElements result = world.getCachedElements(element);
     if (result != null) return result;
     result = analyzeElement(element);
-    assert(invariant(element, element.isDeclaration));
-    world.resolvedElements[element] = result;
     return result;
   }
 
diff --git a/sdk/lib/_internal/compiler/implementation/dart2js.dart b/sdk/lib/_internal/compiler/implementation/dart2js.dart
index 8d3c7da..96c5ff1 100644
--- a/sdk/lib/_internal/compiler/implementation/dart2js.dart
+++ b/sdk/lib/_internal/compiler/implementation/dart2js.dart
@@ -29,13 +29,19 @@
  */
 String BUILD_ID = null;
 
-typedef void HandleOption(String option);
+/**
+ * The data passed to the [HandleOption] callback is either a single
+ * string argument, or the arguments iterator for multiple arguments
+ * handlers.
+ */
+typedef void HandleOption(data);
 
 class OptionHandler {
-  String pattern;
-  HandleOption handle;
+  final String pattern;
+  final HandleOption handle;
+  final bool multipleArguments;
 
-  OptionHandler(this.pattern, this.handle);
+  OptionHandler(this.pattern, this.handle, {this.multipleArguments: false});
 }
 
 /**
@@ -64,12 +70,20 @@
     patterns.add(handler.pattern);
   }
   var pattern = new RegExp('^(${patterns.join(")\$|(")})\$');
-  OUTER: for (String argument in argv) {
+
+  Iterator<String> arguments = argv.iterator;
+  OUTER: while (arguments.moveNext()) {
+    String argument = arguments.current;
     Match match = pattern.firstMatch(argument);
     assert(match.groupCount == handlers.length);
     for (int i = 0; i < handlers.length; i++) {
       if (match[i + 1] != null) {
-        handlers[i].handle(argument);
+        OptionHandler handler = handlers[i];
+        if (handler.multipleArguments) {
+          handler.handle(arguments);
+        } else {
+          handler.handle(argument);
+        }
         continue OUTER;
       }
     }
@@ -86,6 +100,7 @@
   List<String> options = new List<String>();
   bool explicitOut = false;
   bool wantHelp = false;
+  bool wantVersion = false;
   String outputLanguage = 'JavaScript';
   bool stripArgumentSet = false;
   bool analyzeOnly = false;
@@ -107,9 +122,18 @@
     packageRoot = currentDirectory.resolve(extractPath(argument));
   }
 
-  setOutput(String argument) {
+  setOutput(Iterator<String> arguments) {
+    String path;
+    if (arguments.current == '-o') {
+      if (!arguments.moveNext()) {
+        helpAndFail('Error: Missing file after -o option.');
+      }
+      path = arguments.current;
+    } else {
+      path = extractParameter(arguments.current);
+    }
     explicitOut = true;
-    out = currentDirectory.resolve(nativeToUriPath(extractParameter(argument)));
+    out = currentDirectory.resolve(nativeToUriPath(path));
     sourceMapOut = Uri.parse('$out.map');
   }
 
@@ -165,7 +189,15 @@
         }
       }
     }
-    return passThrough('--categories=${categories.join(",")}');
+    passThrough('--categories=${categories.join(",")}');
+  }
+
+  checkGlobalName(String argument) {
+    String globalName = extractParameter(argument);
+    if (!new RegExp(r'^\$[a-z]*$').hasMatch(globalName)) {
+      fail('Error: "$globalName" must match "\\\$[a-z]*"');
+    }
+    passThrough(argument);
   }
 
   handleShortOptions(String argument) {
@@ -197,8 +229,9 @@
                       (_) => diagnosticHandler.showWarnings = false),
     new OptionHandler('--output-type=dart|--output-type=js', setOutputType),
     new OptionHandler('--verbose', setVerbose),
+    new OptionHandler('--version', (_) => wantVersion = true),
     new OptionHandler('--library-root=.+', setLibraryRoot),
-    new OptionHandler('--out=.+|-o.+', setOutput),
+    new OptionHandler('--out=.+|-o.*', setOutput, multipleArguments: true),
     new OptionHandler('--allow-mock-compilation', passThrough),
     new OptionHandler('--minify', passThrough),
     new OptionHandler('--force-strip=.*', setStrip),
@@ -224,6 +257,7 @@
     new OptionHandler('--report-sdk-use-of-deprecated-language-features',
                       passThrough),
     new OptionHandler('--categories=.*', setCategories),
+    new OptionHandler('--global-js-name=.*', checkGlobalName),
 
     // The following two options must come last.
     new OptionHandler('-.*', (String argument) {
@@ -235,7 +269,9 @@
   ];
 
   parseCommandLine(handlers, argv);
-  if (wantHelp) helpAndExit(diagnosticHandler.verbose);
+  if (wantHelp || wantVersion) {
+    helpAndExit(wantHelp, wantVersion, diagnosticHandler.verbose);
+  }
 
   if (outputLanguage != OUTPUT_LANGUAGE_DART && stripArgumentSet) {
     helpAndFail('Error: --force-strip may only be used with '
@@ -322,7 +358,7 @@
       }
     }
 
-    var controller = new StreamController<String>();
+    var controller = new StreamController<String>(sync: true);
     controller.stream.listen(output.write, onDone: onDone);
     sink = new CountingSink(controller);
     return sink;
@@ -389,19 +425,19 @@
 Compiles Dart to JavaScript.
 
 Common options:
-  -o<file> Generate the output into <file>.
-  -c       Insert runtime type checks and enable assertions (checked mode).
-  -h       Display this message (add -v for information about all options).''');
+  -o <file> Generate the output into <file>.
+  -c        Insert runtime type checks and enable assertions (checked mode).
+  -h        Display this message (add -v for information about all options).''');
 }
 
 void verboseHelp() {
-  print('''
+  print(r'''
 Usage: dart2js [options] dartfile
 
 Compiles Dart to JavaScript.
 
 Supported options:
-  -o<file>, --out=<file>
+  -o <file>, --out=<file>
     Generate the output into <file>.
 
   -c, --enable-checked-mode, --checked
@@ -413,6 +449,9 @@
   -v, --verbose
     Display verbose information.
 
+  --version
+    Display version information.
+
   -p<path>, --package-root=<path>
     Where to find packages, that is, "package:..." imports.
 
@@ -484,14 +523,27 @@
     unsupported category, for example, --categories=help.  To enable
     all categories, use --categories=all.
 
+  --global-js-name=<name>
+    By default, dart2js generates JavaScript output that uses a global
+    variable named "$".  The name of this global can be overridden
+    with this option.  The name must match the regular expression "\$[a-z]*".
+
 '''.trim());
 }
 
-void helpAndExit(bool verbose) {
-  if (verbose) {
-    verboseHelp();
-  } else {
-    help();
+void helpAndExit(bool wantHelp, bool wantVersion, bool verbose) {
+  if (wantVersion) {
+    var version = (BUILD_ID == null)
+        ? '<non-SDK build>'
+        : BUILD_ID;
+    print('Dart-to-JavaScript compiler (dart2js) version: $version');
+  }
+  if (wantHelp) {
+    if (verbose) {
+      verboseHelp();
+    } else {
+      help();
+    }
   }
   exit(0);
 }
diff --git a/sdk/lib/_internal/compiler/implementation/dart_backend/placeholder_collector.dart b/sdk/lib/_internal/compiler/implementation/dart_backend/placeholder_collector.dart
index 2d67ace..83a067fe 100644
--- a/sdk/lib/_internal/compiler/implementation/dart_backend/placeholder_collector.dart
+++ b/sdk/lib/_internal/compiler/implementation/dart_backend/placeholder_collector.dart
@@ -48,7 +48,15 @@
 
   SendVisitor(this.collector, TreeElements elements) : super(elements);
 
-  visitOperatorSend(Send node) {}
+  visitOperatorSend(Send node) {
+    if (node.isParameterCheck) {
+      final element = elements[node.receiver];
+      if (element != null) {
+        collector.tryMakeLocalPlaceholder(element, node.receiver);
+      }
+    }
+  }
+
   visitForeignSend(Send node) {}
 
   visitSuperSend(Send node) {
@@ -236,9 +244,11 @@
   }
 
   void tryMakeLocalPlaceholder(Element element, Identifier node) {
-    bool isOptionalParameter() {
+    bool isNamedOptionalParameter() {
       FunctionElement function = element.enclosingElement;
-      for (Element parameter in function.functionSignature.optionalParameters) {
+      FunctionSignature signature = function.functionSignature;
+      if (!signature.optionalParametersAreNamed) return false;
+      for (Element parameter in signature.optionalParameters) {
         if (identical(parameter, element)) return true;
       }
       return false;
@@ -247,7 +257,7 @@
     // TODO(smok): Maybe we should rename privates as well, their privacy
     // should not matter if they are local vars.
     if (node.source.isPrivate()) return;
-    if (element.isParameter() && isOptionalParameter()) {
+    if (element.isParameter() && isNamedOptionalParameter()) {
       currentFunctionScope.registerParameter(node);
     } else if (Elements.isLocal(element)) {
       makeLocalPlaceholder(node);
diff --git a/sdk/lib/_internal/compiler/implementation/dart_backend/renamer.dart b/sdk/lib/_internal/compiler/implementation/dart_backend/renamer.dart
index 5ad2230..a936b7d 100644
--- a/sdk/lib/_internal/compiler/implementation/dart_backend/renamer.dart
+++ b/sdk/lib/_internal/compiler/implementation/dart_backend/renamer.dart
@@ -167,20 +167,24 @@
   // A function that takes original identifier name and generates a new unique
   // identifier.
   Function generateUniqueName;
+
+  Set<String> allNamedParameterIdentifiers = new Set<String>();
+  for (var functionScope in placeholderCollector.functionScopes.values) {
+    allNamedParameterIdentifiers.addAll(functionScope.parameterIdentifiers);
+  }
+
   if (compiler.enableMinification) {
     MinifyingGenerator generator = new MinifyingGenerator();
     Set<String> forbiddenIdentifiers = new Set<String>.from(['main']);
     forbiddenIdentifiers.addAll(Keyword.keywords.keys);
     forbiddenIdentifiers.addAll(fixedMemberNames);
     generateUniqueName = (_) =>
-        generator.generate(forbiddenIdentifiers.contains);
+        generator.generate((name) =>
+            forbiddenIdentifiers.contains(name)
+            || allNamedParameterIdentifiers.contains(name));
     rename = makeRenamer(generateUniqueName);
     renameElement = makeElementRenamer(rename, generateUniqueName);
 
-    Set<String> allParameterIdentifiers = new Set<String>();
-    for (var functionScope in placeholderCollector.functionScopes.values) {
-      allParameterIdentifiers.addAll(functionScope.parameterIdentifiers);
-    }
     // Build a sorted (by usage) list of local nodes that will be renamed to
     // the same identifier. So the top-used local variables in all functions
     // will be renamed first and will all share the same new identifier.
@@ -209,10 +213,7 @@
         renameElement(elementRenamable.element);
     String memberRenamer(MemberRenamable memberRenamable) =>
         generator.generate(forbiddenIdentifiers.contains);
-    String localRenamer(LocalRenamable localRenamable) =>
-        generator.generate((name) =>
-            allParameterIdentifiers.contains(name)
-            || forbiddenIdentifiers.contains(name));
+    Function localRenamer = generateUniqueName;
     List<Renamable> renamables = [];
     placeholderCollector.elementNodes.forEach(
         (Element element, Set<Node> nodes) {
@@ -239,7 +240,9 @@
     usedTopLevelOrMemberIdentifiers.addAll(fixedMemberNames);
     generateUniqueName = (originalName) {
       String newName = conservativeGenerator(
-          originalName, usedTopLevelOrMemberIdentifiers.contains);
+          originalName, (name) =>
+              usedTopLevelOrMemberIdentifiers.contains(name)
+              || allNamedParameterIdentifiers.contains(name));
       usedTopLevelOrMemberIdentifiers.add(newName);
       return newName;
     };
diff --git a/sdk/lib/_internal/compiler/implementation/elements/elements.dart b/sdk/lib/_internal/compiler/implementation/elements/elements.dart
index bd1fac2..3d7982b 100644
--- a/sdk/lib/_internal/compiler/implementation/elements/elements.dart
+++ b/sdk/lib/_internal/compiler/implementation/elements/elements.dart
@@ -721,6 +721,8 @@
   void forEachOptionalParameter(void function(Element parameter));
 
   void orderedForEachParameter(void function(Element parameter));
+
+  bool isCompatibleWith(FunctionSignature constructorSignature);
 }
 
 abstract class FunctionElement extends Element {
@@ -733,6 +735,8 @@
   FunctionElement get patch;
   FunctionElement get origin;
 
+  bool get isRedirectingFactory;
+
   // TODO(kasperl): These are bit fishy. Do we really need them?
   void set patch(FunctionElement value);
   void set origin(FunctionElement value);
diff --git a/sdk/lib/_internal/compiler/implementation/elements/modelx.dart b/sdk/lib/_internal/compiler/implementation/elements/modelx.dart
index 1ea7a23..27b8fa6 100644
--- a/sdk/lib/_internal/compiler/implementation/elements/modelx.dart
+++ b/sdk/lib/_internal/compiler/implementation/elements/modelx.dart
@@ -317,6 +317,7 @@
   get origin => unsupported();
   get defaultImplementation => unsupported();
 
+  bool get isRedirectingFactory => unsupported();
   bool get isPatched => unsupported();
   bool get isPatch => unsupported();
 
@@ -594,6 +595,15 @@
   LibraryElement get declaration => super.declaration;
   LibraryElement get implementation => super.implementation;
 
+  Link<MetadataAnnotation> get metadata {
+    return (libraryTag == null) ? super.metadata : libraryTag.metadata;
+  }
+
+  set metadata(value) {
+    // The metadata is stored on [libraryTag].
+    throw new SpannableAssertionFailure(this, 'Cannot set metadata on Library');
+  }
+
   CompilationUnitElement getCompilationUnit() => entryCompilationUnit;
 
   void addCompilationUnit(CompilationUnitElement element) {
@@ -1093,6 +1103,38 @@
   }
 
   int get parameterCount => requiredParameterCount + optionalParameterCount;
+
+  /**
+   * Check whether a function with this signature can be used instead of a
+   * function with signature [signature] without causing a `noSuchMethod`
+   * exception/call.
+   */
+  bool isCompatibleWith(FunctionSignature signature) {
+    if (optionalParametersAreNamed != signature.optionalParametersAreNamed) {
+      return false;
+    }
+    if (optionalParametersAreNamed) {
+      if (requiredParameterCount != signature.requiredParameterCount) {
+        return false;
+      }
+      for (Element namedParameter in signature.optionalParameters) {
+        if (!optionalParameters.contains(namedParameter)) {
+          return false;
+        }
+      }
+    } else {
+      // There must be at least as many arguments as in the other signature, but
+      // this signature must not have more required parameters.  Having more
+      // optional parameters is not a problem, they simply are never provided
+      // by call sites of a call to a method with the other signature.
+      if (requiredParameterCount > signature.requiredParameterCount ||
+          requiredParameterCount < signature.parameterCount ||
+          parameterCount < signature.parameterCount) {
+        return false;
+      }
+    }
+    return true;
+  }
 }
 
 class FunctionElementX extends ElementX implements FunctionElement {
@@ -1152,6 +1194,8 @@
   bool get isPatched => patch != null;
   bool get isPatch => origin != null;
 
+  bool get isRedirectingFactory => defaultImplementation != this;
+
   FunctionElement get redirectionTarget {
     if (this == defaultImplementation) return this;
     var target = defaultImplementation;
diff --git a/sdk/lib/_internal/compiler/implementation/enqueue.dart b/sdk/lib/_internal/compiler/implementation/enqueue.dart
index 18bf774..7397b2f 100644
--- a/sdk/lib/_internal/compiler/implementation/enqueue.dart
+++ b/sdk/lib/_internal/compiler/implementation/enqueue.dart
@@ -87,6 +87,8 @@
   final Function itemCompilationContextCreator;
   final Map<String, Link<Element>> instanceMembersByName
       = new Map<String, Link<Element>>();
+  final Map<String, Link<Element>> instanceFunctionsByName
+      = new Map<String, Link<Element>>();
   final Set<ClassElement> seenClasses = new Set<ClassElement>();
   final Universe universe = new Universe();
 
@@ -193,36 +195,71 @@
     assert(invariant(member, member.isDeclaration));
     if (isProcessed(member)) return;
     if (!member.isInstanceMember()) return;
-    if (member.isField()) {
-      // Fields are implicitly used by the constructor of the
-      // instantiated class they are part of.
-      compiler.world.registerUsedElement(member);
-      // Native fields need to go into instanceMembersByName as they
-      // are virtual instantiation points and escape points. Test the
-      // enclosing class, since the metadata has not been parsed yet.
-      if (!member.enclosingElement.isNative()) return;
-    }
 
     String memberName = member.name.slowToString();
 
-    if (member.kind == ElementKind.FUNCTION) {
+    if (member.kind == ElementKind.FIELD) {
+      // The obvious thing to test here would be "member.isNative()",
+      // however, that only works after metadata has been parsed/analyzed,
+      // and that may not have happened yet.
+      // So instead we use the enclosing class, which we know have had
+      // its metadata parsed and analyzed.
+      // Note: this assumes that there are no non-native fields on native
+      // classes, which may not be the case when a native class is subclassed.
+      if (cls.isNative()) {
+        compiler.world.registerUsedElement(member);
+        nativeEnqueuer.handleFieldAnnotations(member);
+        if (universe.hasInvokedGetter(member, compiler) ||
+            universe.hasInvocation(member, compiler)) {
+          nativeEnqueuer.registerFieldLoad(member);
+          // In handleUnseenSelector we can't tell if the field is loaded or
+          // stored.  We need the basic algorithm to be Church-Rosser, since the
+          // resolution 'reduction' order is different to the codegen order. So
+          // register that the field is also stored.  In other words: if we
+          // don't register the store here during resolution, the store could be
+          // registered during codegen on the handleUnseenSelector path, and
+          // cause the set of codegen elements to include unresolved elements.
+          nativeEnqueuer.registerFieldStore(member);
+          return;
+        }
+        if (universe.hasInvokedSetter(member, compiler)) {
+          nativeEnqueuer.registerFieldStore(member);
+          // See comment after registerFieldLoad above.
+          nativeEnqueuer.registerFieldLoad(member);
+          return;
+        }
+        // Native fields need to go into instanceMembersByName as they
+        // are virtual instantiation points and escape points.
+      } else {
+        // The codegen inlines instance fields initialization, so it
+        // does not need to add individual fields in the work list.
+        if (isResolutionQueue) {
+          addToWorkList(member);
+        }
+        return;
+      }
+    } else if (member.kind == ElementKind.FUNCTION) {
       if (member.name == Compiler.NO_SUCH_METHOD) {
         enableNoSuchMethod(member);
       }
-      if (universe.hasInvocation(member, compiler)) {
-        return addToWorkList(member);
-      }
       // If there is a property access with the same name as a method we
       // need to emit the method.
       if (universe.hasInvokedGetter(member, compiler)) {
-        // We will emit a closure, so make sure the closure class is
+        // We will emit a closure, so make sure the bound closure class is
         // generated.
-        compiler.closureClass.ensureResolved(compiler);
-        registerInstantiatedClass(compiler.closureClass,
+        registerInstantiatedClass(compiler.boundClosureClass,
                                   // Precise dependency is not important here.
                                   compiler.globalDependencies);
         return addToWorkList(member);
       }
+      // Store the member in [instanceFunctionsByName] to catch
+      // getters on the function.
+      Link<Element> members = instanceFunctionsByName.putIfAbsent(
+          memberName, () => const Link<Element>());
+      instanceFunctionsByName[memberName] = members.prepend(member);
+      if (universe.hasInvocation(member, compiler)) {
+        return addToWorkList(member);
+      }
     } else if (member.kind == ElementKind.GETTER) {
       if (universe.hasInvokedGetter(member, compiler)) {
         return addToWorkList(member);
@@ -236,28 +273,6 @@
       if (universe.hasInvokedSetter(member, compiler)) {
         return addToWorkList(member);
       }
-    } else if (member.kind == ElementKind.FIELD &&
-               member.enclosingElement.isNative()) {
-      nativeEnqueuer.handleFieldAnnotations(member);
-      if (universe.hasInvokedGetter(member, compiler) ||
-          universe.hasInvocation(member, compiler)) {
-        nativeEnqueuer.registerFieldLoad(member);
-        // In handleUnseenSelector we can't tell if the field is loaded or
-        // stored.  We need the basic algorithm to be Church-Rosser, since the
-        // resolution 'reduction' order is different to the codegen order. So
-        // register that the field is also stored.  In other words: if we don't
-        // register the store here during resolution, the store could be
-        // registered during codegen on the handleUnseenSelector path, and cause
-        // the set of codegen elements to include unresolved elements.
-        nativeEnqueuer.registerFieldStore(member);
-        return;
-      }
-      if (universe.hasInvokedSetter(member, compiler)) {
-        nativeEnqueuer.registerFieldStore(member);
-        // See comment after registerFieldLoad above.
-        nativeEnqueuer.registerFieldLoad(member);
-        return;
-      }
     }
 
     // The element is not yet used. Add it to the list of instance
@@ -282,12 +297,6 @@
         cls.ensureResolved(compiler);
         cls.implementation.forEachMember(processInstantiatedClassMember);
         if (isResolutionQueue) {
-          // Only the resolution queue needs to operate on individual
-          // fields. The codegen enqueuer inlines the potential field
-          // intializations in the constructor.
-          cls.implementation.forEachInstanceField((_, Element field) {
-            addToWorkList(field);
-          }, includeSuperAndInjectedMembers: true);
           compiler.resolver.checkClass(cls);
         }
       }
@@ -386,22 +395,32 @@
   void registerNewSymbol(TreeElements elements) {
   }
 
-  processInstanceMembers(SourceString n, bool f(Element e)) {
+  processLink(Map<String, Link<Element>> map,
+              SourceString n,
+              bool f(Element e)) {
     String memberName = n.slowToString();
-    Link<Element> members = instanceMembersByName[memberName];
+    Link<Element> members = map[memberName];
     if (members != null) {
       LinkBuilder<Element> remaining = new LinkBuilder<Element>();
       for (; !members.isEmpty; members = members.tail) {
         if (!f(members.head)) remaining.addLast(members.head);
       }
-      instanceMembersByName[memberName] = remaining.toLink();
+      map[memberName] = remaining.toLink();
     }
   }
 
+  processInstanceMembers(SourceString n, bool f(Element e)) {
+    processLink(instanceMembersByName, n, f);
+  }
+
+  processInstanceFunctions(SourceString n, bool f(Element e)) {
+    processLink(instanceFunctionsByName, n, f);
+  }
+
   void handleUnseenSelector(SourceString methodName, Selector selector) {
     processInstanceMembers(methodName, (Element member) {
       if (selector.appliesUnnamed(member, compiler)) {
-        if (member.isField() && member.enclosingElement.isNative()) {
+        if (member.isField() && member.getEnclosingClass().isNative()) {
           if (selector.isGetter() || selector.isCall()) {
             nativeEnqueuer.registerFieldLoad(member);
             // We have to also handle storing to the field because we only get
@@ -410,6 +429,7 @@
             // TODO(sra): Process fields for storing separately.
             nativeEnqueuer.registerFieldStore(member);
           } else {
+            assert(selector.isSetter());
             nativeEnqueuer.registerFieldStore(member);
             // We have to also handle loading from the field because we only get
             // one look at each member and there might be a load we have not
@@ -424,6 +444,19 @@
       }
       return false;
     });
+    if (selector.isGetter()) {
+      processInstanceFunctions(methodName, (Element member) {
+        if (selector.appliesUnnamed(member, compiler)) {
+          // We will emit a closure, so make sure the bound closure class is
+          // generated.
+          registerInstantiatedClass(compiler.boundClosureClass,
+                                    // Precise dependency is not important here.
+                                    compiler.globalDependencies);
+          return true;
+        }
+        return false;
+      });
+    }
   }
 
   /**
@@ -439,6 +472,8 @@
 
   void registerGetOfStaticFunction(FunctionElement element) {
     registerStaticUse(element);
+    registerInstantiatedClass(compiler.closureClass,
+                              compiler.globalDependencies);
     universe.staticFunctionsNeedingGetter.add(element);
   }
 
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart b/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart
index 6ecbfd5..417dca9 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart
@@ -58,7 +58,6 @@
   bool needsInheritFunction = false;
   bool needsDefineClass = false;
   bool needsMixinSupport = false;
-  bool needsClosureClass = false;
   bool needsLazyInitializer = false;
   final Namer namer;
   ConstantEmitter constantEmitter;
@@ -1558,6 +1557,10 @@
     emitSuper(superName, builder);
     emitRuntimeName(runtimeName, builder);
     emitClassFields(classElement, builder, superName);
+    var metadata = buildMetadataFunction(classElement);
+    if (metadata != null) {
+      builder.addProperty("@", metadata);
+    }
     emitClassGettersSetters(classElement, builder);
     if (!classElement.isMixinApplication) {
       emitInstanceMembers(classElement, builder);
@@ -1756,19 +1759,6 @@
     return (ClassElement cls) => !unneededClasses.contains(cls);
   }
 
-  void emitClosureClassIfNeeded(CodeBuffer buffer) {
-    // The closure class could have become necessary because of the generation
-    // of stubs.
-    ClassElement closureClass = compiler.closureClass;
-    if (needsClosureClass && !instantiatedClasses.contains(closureClass)) {
-      ClassElement objectClass = compiler.objectClass;
-      if (!instantiatedClasses.contains(objectClass)) {
-        generateClass(objectClass, bufferForElement(objectClass, buffer));
-      }
-      generateClass(closureClass, bufferForElement(closureClass, buffer));
-    }
-  }
-
   void emitFinishClassesInvocationIfNecessary(CodeBuffer buffer) {
     if (needsDefineClass) {
       buffer.write('$finishClassesName($classesCollector,'
@@ -1855,7 +1845,7 @@
       String staticName = namer.getName(element);
       String superName = namer.getName(compiler.closureClass);
       String name = 'Closure\$${element.name.slowToString()}';
-      needsClosureClass = true;
+      assert(instantiatedClasses.contains(compiler.closureClass));
 
       ClassElement closureClassElement = new ClosureClassElement(
           null, new SourceString(name), compiler, element,
@@ -1877,7 +1867,7 @@
       // If a static function is used as a closure we need to add its name
       // in case it is used in spawnFunction.
       String methodName = namer.STATIC_CLOSURE_NAME_NAME;
-      emitBoundClosureClassHeader(
+      emitClosureClassHeader(
           mangledName, superName, <String>[invocationName, methodName],
           closureBuilder);
 
@@ -1889,7 +1879,7 @@
         closureBuilder.addProperty(operator, js('true'));
       });
 
-      // TODO(ngeoffray): Cache common base classes for clsures, bound
+      // TODO(ngeoffray): Cache common base classes for closures, bound
       // closures, and static closures that have common type checks.
       boundClosures.add(
           js('$classesCollector.$mangledName = #',
@@ -1899,10 +1889,10 @@
     }
   }
 
-  void emitBoundClosureClassHeader(String mangledName,
-                                   String superName,
-                                   List<String> fieldNames,
-                                   ClassBuilder builder) {
+  void emitClosureClassHeader(String mangledName,
+                              String superName,
+                              List<String> fieldNames,
+                              ClassBuilder builder) {
     builder.addProperty('',
         js.string("$superName;${fieldNames.join(',')}"));
   }
@@ -1915,6 +1905,7 @@
   void emitDynamicFunctionGetter(FunctionElement member,
                                  DefineStubFunction defineStub) {
     assert(invariant(member, member.isDeclaration));
+    assert(instantiatedClasses.contains(compiler.boundClosureClass));
     // For every method that has the same name as a property-get we create a
     // getter that returns a bound closure. Say we have a class 'A' with method
     // 'foo' and somewhere in the code there is a dynamic property get of
@@ -1924,8 +1915,7 @@
     //    foo(x, y, z) { ... } // Original function.
     //    get foo { return new BoundClosure499(this, "foo"); }
     // }
-    // class BoundClosure499 extends Closure {
-    //   var self;
+    // class BoundClosure499 extends BoundClosure {
     //   BoundClosure499(this.self, this.name);
     //   $call3(x, y, z) { return self[name](x, y, z); }
     // }
@@ -1940,21 +1930,18 @@
     int parameterCount = member.parameterCount(compiler);
 
     Map<int, String> cache;
-    String extraArg = null;
     // Intercepted methods take an extra parameter, which is the
     // receiver of the call.
     bool inInterceptor = backend.isInterceptedMethod(member);
     if (inInterceptor) {
       cache = interceptorClosureCache;
-      extraArg = 'receiver';
     } else {
       cache = boundClosureCache;
     }
-    List<String> fieldNames = compiler.enableMinification
-        ? inInterceptor ? const ['a', 'b', 'c']
-                        : const ['a', 'b']
-        : inInterceptor ? const ['self', 'target', 'receiver']
-                        : const ['self', 'target'];
+    List<String> fieldNames = <String>[];
+    compiler.boundClosureClass.forEachInstanceField((_, Element field) {
+      fieldNames.add(namer.getName(field));
+    });
 
     Iterable<Element> typedefChecks =
         getTypedefChecksOn(member.computeType(compiler));
@@ -1983,12 +1970,11 @@
           member.getCompilationUnit());
       String mangledName = namer.getName(closureClassElement);
       String superName = namer.getName(closureClassElement.superclass);
-      needsClosureClass = true;
 
       // Define the constructor with a name so that Object.toString can
       // find the class name of the closure class.
       ClassBuilder boundClosureBuilder = new ClassBuilder();
-      emitBoundClosureClassHeader(
+      emitClosureClassHeader(
           mangledName, superName, fieldNames, boundClosureBuilder);
       // Now add the methods on the closure class. The instance method does not
       // have the correct name. Since [addParameterStubs] use the name to create
@@ -2044,8 +2030,12 @@
     arguments.add(js('this'));
     arguments.add(js.string(targetName));
     if (inInterceptor) {
-      parameters.add(extraArg);
-      arguments.add(js(extraArg));
+      String receiverArg = fieldNames[2];
+      parameters.add(receiverArg);
+      arguments.add(js(receiverArg));
+    } else {
+      // Put null in the intercepted receiver field.
+      arguments.add(new jsAst.LiteralNull());
     }
 
     jsAst.Expression getterFunction = js.fun(
@@ -2940,6 +2930,26 @@
     if (compiler.enableMinification) buffer.write('\n');
   }
 
+  /// The metadata function returns the metadata associated with
+  /// [element] in generated code.  The metadata needs to be wrapped
+  /// in a function as it refers to constants that may not have been
+  /// constructed yet.  For example, a class is allowed to be
+  /// annotated with itself.  The metadata function is used by
+  /// mirrors_patch to implement DeclarationMirror.metadata.
+  jsAst.Fun buildMetadataFunction(Element element) {
+    if (compiler.mirrorSystemClass == null) return null;
+    var metadata = [];
+    Link link = element.metadata;
+    // TODO(ahe): Why is metadata sometimes null?
+    if (link != null) {
+      for (; !link.isEmpty; link = link.tail) {
+        metadata.add(constantReference(link.head.value));
+      }
+    }
+    if (metadata.isEmpty) return null;
+    return js.fun([], [js.return_(new jsAst.ArrayInitializer.from(metadata))]);
+  }
+
   String assembleProgram() {
     measure(() {
       // Compute the required type checks to know which classes need a
@@ -2948,7 +2958,7 @@
 
       computeNeededClasses();
 
-      mainBuffer.add(GENERATED_BY);
+      mainBuffer.add(buildGeneratedBy());
       addComment(HOOKS_API_USAGE, mainBuffer);
       mainBuffer.add('function ${namer.isolateName}()$_{}\n');
       mainBuffer.add('init()$N$n');
@@ -2997,7 +3007,6 @@
       }
 
       emitStaticFunctionClosures();
-      emitClosureClassIfNeeded(mainBuffer);
 
       addComment('Bound closures', mainBuffer);
       // Now that we have emitted all classes, we know all the bound
@@ -3021,13 +3030,13 @@
           mainBuffer.write(';');
         }
         mainBuffer
-            ..write(REFLECTION_DATA_PARSER)
+            ..write(getReflectionDataParser())
             ..write('([$n');
         emitDeferredPreambleWhenEmpty(deferredBuffer);
         deferredBuffer.add('\$\$$_=$_{};$n');
 
         deferredBuffer
-            ..write(REFLECTION_DATA_PARSER)
+            ..write(getReflectionDataParser())
             ..write('([$n');
         var sortedLibraries = Elements.sortedByPosition(libraryBuffers.keys);
         for (LibraryElement library in sortedLibraries) {
@@ -3042,9 +3051,13 @@
                 compiler.sourceMapUri, library.canonicalUri, false);
           }
           if (buffer != null) {
+            var metadata = buildMetadataFunction(library);
             mainBuffer
                 ..write('["${library.getLibraryOrScriptName()}",$_')
                 ..write('"${uri}",$_')
+                ..write(metadata == null
+                        ? "" : jsAst.prettyPrint(metadata, compiler))
+                ..write(',$_')
                 ..write('{$n')
                 ..addBuffer(buffer)
                 ..write('}],$n');
@@ -3054,6 +3067,7 @@
             deferredBuffer
                 ..write('["${library.getLibraryOrScriptName()}",$_')
                 ..write('"${uri}",$_')
+                ..write('[],$_')
                 ..write('{$n')
                 ..addBuffer(buffer)
                 ..write('}],$n');
@@ -3173,7 +3187,7 @@
   void emitDeferredPreambleWhenEmpty(CodeBuffer buffer) {
     if (!buffer.isEmpty) return;
 
-    buffer.write(GENERATED_BY);
+    buffer.write(buildGeneratedBy());
 
     buffer.write('var old${namer.CURRENT_ISOLATE}$_='
                  '$_${namer.CURRENT_ISOLATE}$N');
@@ -3186,6 +3200,12 @@
                  '$_${namer.isolateName}.prototype$N$n');
   }
 
+  String buildGeneratedBy() {
+    var suffix = '';
+    if (compiler.hasBuildId) suffix = ' version: ${compiler.buildId}';
+    return '// Generated by dart2js, the Dart to JavaScript compiler$suffix.\n';
+  }
+
   String buildSourceMap(CodeBuffer buffer, SourceFile compiledFile) {
     SourceMapBuilder sourceMapBuilder =
         new SourceMapBuilder(compiler.sourceMapUri);
@@ -3212,6 +3232,39 @@
                            MessageKind.GENERIC.error({'text': message}),
                            api.Diagnostic.WARNING);
   }
+
+  // TODO(ahe): This code should be integrated in finishClasses.
+  String getReflectionDataParser() {
+    return '''
+(function (reflectionData) {
+  if (!init.libraries) init.libraries = [];
+  var libraries = init.libraries;
+  var hasOwnProperty = Object.prototype.hasOwnProperty;
+  var length = reflectionData.length;
+  for (var i = 0; i < length; i++) {
+    var data = reflectionData[i];
+    var name = data[0];
+    var uri = data[1];
+    var metadata = data[2];
+    var descriptor = data[3];
+    var classes = [];
+    var functions = [];
+    for (var property in descriptor) {
+      if (!hasOwnProperty.call(descriptor, property)) continue;
+      var element = descriptor[property];
+      if (typeof element === "function") {
+        ${namer.CURRENT_ISOLATE}[property] = element;
+        functions.push(property);
+      } else {
+        $classesCollector[property] = element;
+        classes.push(property);
+        classes.push(element[""]);
+      }
+    }
+    libraries.push([name, uri, classes, functions, metadata]);
+  }
+})''';
+  }
 }
 
 const String GENERATED_BY = """
@@ -3227,34 +3280,3 @@
 //                        Instead, a closure that will invoke [main] is
 //                        passed to [dartMainRunner].
 """;
-
-// TODO(ahe): This code should be integrated in finishClasses.
-// TODO(ahe): The uri field below is fake.
-const String REFLECTION_DATA_PARSER = r'''
-(function (reflectionData) {
-  if (!init.libraries) init.libraries = [];
-  var libraries = init.libraries;
-  var hasOwnProperty = Object.prototype.hasOwnProperty;
-  var length = reflectionData.length;
-  for (var i = 0; i < length; i++) {
-    var data = reflectionData[i];
-    var name = data[0];
-    var uri = data[1];
-    var descriptor = data[2];
-    var classes = [];
-    var functions = [];
-    for (var property in descriptor) {
-      if (!hasOwnProperty.call(descriptor, property)) continue;
-      var element = descriptor[property];
-      if (typeof element === "function") {
-        $[property] = element;
-        functions.push(property);
-      } else {
-        $$[property] = element;
-        classes.push(property);
-        classes.push(element[""]);
-      }
-    }
-    libraries.push([name, uri, classes, functions]);
-  }
-})''';
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/emitter_no_eval.dart b/sdk/lib/_internal/compiler/implementation/js_backend/emitter_no_eval.dart
index e739b58..ebdb9fd 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/emitter_no_eval.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/emitter_no_eval.dart
@@ -25,10 +25,10 @@
     }
   }
 
-  void emitBoundClosureClassHeader(String mangledName,
-                                   String superName,
-                                   List<String> fieldNames,
-                                   ClassBuilder builder) {
+  void emitClosureClassHeader(String mangledName,
+                              String superName,
+                              List<String> fieldNames,
+                              ClassBuilder builder) {
     builder.addProperty('', buildConstructor(mangledName, fieldNames));
     emitSuper(superName, builder);
   }
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/namer.dart b/sdk/lib/_internal/compiler/implementation/js_backend/namer.dart
index 3f43bc6..c83e714 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/namer.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/namer.dart
@@ -172,7 +172,7 @@
     return _jsVariableReserved;
   }
 
-  final String CURRENT_ISOLATE = r'$';
+  final String CURRENT_ISOLATE;
 
   final String getterPrefix = r'get$';
   final String setterPrefix = r'set$';
@@ -204,6 +204,7 @@
 
   Namer(Compiler compiler)
       : compiler = compiler,
+        CURRENT_ISOLATE = compiler.globalJsName,
         globals = new Map<Element, String>(),
         shortPrivateNameOwners = new Map<String, LibraryElement>(),
         bailoutNames = new Map<Element, String>(),
diff --git a/sdk/lib/_internal/compiler/implementation/lib/foreign_helper.dart b/sdk/lib/_internal/compiler/implementation/lib/foreign_helper.dart
index fb06bf3..3cfe86a 100644
--- a/sdk/lib/_internal/compiler/implementation/lib/foreign_helper.dart
+++ b/sdk/lib/_internal/compiler/implementation/lib/foreign_helper.dart
@@ -90,14 +90,14 @@
  */
 // Add additional optional arguments if needed. The method is treated internally
 // as a variable argument method.
-dynamic JS(String typeDescription, String codeTemplate,
-    [var arg0, var arg1, var arg2, var arg3, var arg4, var arg5, var arg6,
-     var arg7, var arg8, var arg9, var arg10, var arg11]) {}
+JS(String typeDescription, String codeTemplate,
+    [arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11])
+{}
 
 /**
  * Returns the isolate in which this code is running.
  */
-IsolateContext JS_CURRENT_ISOLATE() {}
+IsolateContext JS_CURRENT_ISOLATE_CONTEXT() {}
 
 abstract class IsolateContext {
   /// Holds a (native) JavaScript instance of Isolate, see
@@ -108,12 +108,12 @@
 /**
  * Invokes [function] in the context of [isolate].
  */
-dynamic JS_CALL_IN_ISOLATE(var isolate, Function function) {}
+JS_CALL_IN_ISOLATE(isolate, Function function) {}
 
 /**
  * Converts the Dart closure [function] into a JavaScript closure.
  */
-dynamic DART_CLOSURE_TO_JS(Function function) {}
+DART_CLOSURE_TO_JS(Function function) {}
 
 /**
  * Returns a raw reference to the JavaScript function which implements
@@ -127,17 +127,17 @@
  * to V8's Error.captureStackTrace. See
  * https://code.google.com/p/v8/wiki/JavaScriptStackTraceApi.
  */
-dynamic RAW_DART_FUNCTION_REF(Function function) {}
+RAW_DART_FUNCTION_REF(Function function) {}
 
 /**
  * Sets the current isolate to [isolate].
  */
-void JS_SET_CURRENT_ISOLATE(var isolate) {}
+void JS_SET_CURRENT_ISOLATE(isolate) {}
 
 /**
  * Creates an isolate and returns it.
  */
-dynamic JS_CREATE_ISOLATE() {}
+JS_CREATE_ISOLATE() {}
 
 /**
  * Returns the JavaScript constructor function for Dart's Object class.
@@ -146,7 +146,7 @@
  *     if (JS('bool', '# instanceof #', obj, JS_DART_OBJECT_CONSTRUCTOR()))
  *       ...
  */
-dynamic JS_DART_OBJECT_CONSTRUCTOR() {}
+JS_DART_OBJECT_CONSTRUCTOR() {}
 
 /**
  * Returns the prefix used for generated is checks on classes.
@@ -158,8 +158,16 @@
  */
 String JS_OPERATOR_AS_PREFIX() {}
 
+/// Returns the name of the class `Object` in the generated code.
+String JS_OBJECT_CLASS_NAME() {}
+
 /**
  * Returns the field name used for determining if an object or its
  * interceptor has JavaScript indexing behavior.
  */
 String JS_IS_INDEXABLE_FIELD_NAME() {}
+
+/**
+ * Returns the object corresponding to Namer.CURRENT_ISOLATE.
+ */
+JS_CURRENT_ISOLATE() {}
diff --git a/sdk/lib/_internal/compiler/implementation/lib/io_patch.dart b/sdk/lib/_internal/compiler/implementation/lib/io_patch.dart
index feb7009..37dc6b8 100644
--- a/sdk/lib/_internal/compiler/implementation/lib/io_patch.dart
+++ b/sdk/lib/_internal/compiler/implementation/lib/io_patch.dart
@@ -90,9 +90,6 @@
   patch static _deleteLink(String path) {
     throw new UnsupportedError("File._deleteLink");
   }
-  patch static _directory(String path) {
-    throw new UnsupportedError("File._directory");
-  }
   patch static _lengthFromPath(String path) {
     throw new UnsupportedError("File._lengthFromPath");
   }
diff --git a/sdk/lib/_internal/compiler/implementation/lib/isolate_helper.dart b/sdk/lib/_internal/compiler/implementation/lib/isolate_helper.dart
index 3c79299..2f85b44 100644
--- a/sdk/lib/_internal/compiler/implementation/lib/isolate_helper.dart
+++ b/sdk/lib/_internal/compiler/implementation/lib/isolate_helper.dart
@@ -12,6 +12,7 @@
 import 'dart:_foreign_helper' show DART_CLOSURE_TO_JS,
                                    JS,
                                    JS_CREATE_ISOLATE,
+                                   JS_CURRENT_ISOLATE_CONTEXT,
                                    JS_CURRENT_ISOLATE,
                                    JS_SET_CURRENT_ISOLATE,
                                    IsolateContext;
@@ -425,7 +426,7 @@
    * JavaScript workers.
    */
   static String computeThisScript() {
-    var currentScript = JS('', r'$.$currentScript');
+    var currentScript = JS('', r'#.$currentScript', JS_CURRENT_ISOLATE());
     if (currentScript != null) {
       return JS('String', 'String(#.src)', currentScript);
     }
@@ -555,11 +556,11 @@
 
   /** Find a constructor given its name. */
   static dynamic _getJSConstructorFromName(String factoryName) {
-    return JS("", r"$[#]", factoryName);
+    return JS("", "#[#]", JS_CURRENT_ISOLATE(), factoryName);
   }
 
   static dynamic _getJSFunctionFromName(String functionName) {
-    return JS("", r"$[#]", functionName);
+    return JS("", "#[#]", JS_CURRENT_ISOLATE(), functionName);
   }
 
   /**
diff --git a/sdk/lib/_internal/compiler/implementation/lib/js_helper.dart b/sdk/lib/_internal/compiler/implementation/lib/js_helper.dart
index 17507a2..2cbd650 100644
--- a/sdk/lib/_internal/compiler/implementation/lib/js_helper.dart
+++ b/sdk/lib/_internal/compiler/implementation/lib/js_helper.dart
@@ -9,10 +9,12 @@
                                    JS,
                                    JS_CALL_IN_ISOLATE,
                                    JS_CURRENT_ISOLATE,
+                                   JS_CURRENT_ISOLATE_CONTEXT,
                                    JS_DART_OBJECT_CONSTRUCTOR,
-                                   JS_OPERATOR_IS_PREFIX,
-                                   JS_OPERATOR_AS_PREFIX,
                                    JS_IS_INDEXABLE_FIELD_NAME,
+                                   JS_OBJECT_CLASS_NAME,
+                                   JS_OPERATOR_AS_PREFIX,
+                                   JS_OPERATOR_IS_PREFIX,
                                    RAW_DART_FUNCTION_REF;
 import 'dart:_interceptors';
 import "dart:_collection-dev" as _symbol_dev;
@@ -145,13 +147,13 @@
   static int hashCodeSeed = 0;
 
   static int objectHashCode(object) {
-    int hash = JS('var', r'#.$identityHash', object);
+    int hash = JS('int|Null', r'#.$identityHash', object);
     if (hash == null) {
       // TOOD(ahe): We should probably randomize this somehow.
       hash = ++hashCodeSeed;
       JS('void', r'#.$identityHash = #', object, hash);
     }
-    return hash;
+    return JS('int', '#', hash);
   }
 
   /**
@@ -576,8 +578,7 @@
     if (JS('bool', '# == "num"', int)) return const JSNumber();
     if (JS('bool', '# == "bool"', int)) return const JSBool();
     if (JS('bool', '# == "List"', int)) return const JSArray();
-    // TODO(ahe): How to safely access $?
-    return JS('var', r'$[#]', className);
+    return JS('var', '#[#]', JS_CURRENT_ISOLATE(), className);
   }
 
   static bool identicalImplementation(a, b) {
@@ -932,7 +933,7 @@
                 // Capture the current isolate now.  Remember that "#"
                 // in JS is simply textual substitution of compiled
                 // expressions.
-                JS_CURRENT_ISOLATE(),
+                JS_CURRENT_ISOLATE_CONTEXT(),
                 DART_CLOSURE_TO_JS(invokeClosure));
 
   JS('void', r'#.$identity = #', closure, function);
@@ -946,6 +947,28 @@
   String toString() => "Closure";
 }
 
+class BoundClosure extends Closure {
+  var self;
+  var target;
+  var receiver;
+
+  bool operator==(other) {
+    if (identical(this, other)) return true;
+    if (other is! BoundClosure) return false;
+    return JS('bool', '# === # && # === # && # === #',
+        self, other.self,
+        target, other.target,
+        receiver, other.receiver);
+  }
+
+  int get hashCode {
+    return JS('int', '(# + # + #) & 0x3ffffff',
+        self.hashCode,
+        target.hashCode,
+        receiver.hashCode);
+  }
+}
+
 bool jsHasOwnProperty(var jsObject, String property) {
   return JS('bool', r'#.hasOwnProperty(#)', jsObject, property);
 }
diff --git a/sdk/lib/_internal/compiler/implementation/lib/js_mirrors.dart b/sdk/lib/_internal/compiler/implementation/lib/js_mirrors.dart
new file mode 100644
index 0000000..d1f93ed
--- /dev/null
+++ b/sdk/lib/_internal/compiler/implementation/lib/js_mirrors.dart
@@ -0,0 +1,486 @@
+// 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 dart._js_mirrors;
+
+import 'dart:async';
+import 'dart:mirrors';
+
+import 'dart:_foreign_helper' show JS, JS_CURRENT_ISOLATE;
+import 'dart:_collection-dev' as _symbol_dev;
+import 'dart:_js_helper' show
+    Closure,
+    JSInvocationMirror,
+    Null,
+    Primitives,
+    createInvocationMirror;
+import 'dart:_interceptors' show Interceptor;
+
+String getName(Symbol symbol) => n(symbol);
+
+class JsMirrorSystem implements MirrorSystem {
+  TypeMirror get dynamicType => _dynamicType;
+  TypeMirror get voidType => _voidType;
+
+  final static TypeMirror _dynamicType =
+      new JsTypeMirror(const Symbol('dynamic'));
+  final static TypeMirror _voidType = new JsTypeMirror(const Symbol('void'));
+
+  static final Map<String, List<LibraryMirror>> librariesByName =
+      computeLibrariesByName();
+
+  Iterable<LibraryMirror> findLibrary(Symbol libraryName) {
+    return new List<LibraryMirror>.from(librariesByName[n(libraryName)]);
+  }
+
+  static Map<String, List<LibraryMirror>> computeLibrariesByName() {
+    var result = new Map<String, List<LibraryMirror>>();
+    var jsLibraries = JS('=List|Null', 'init.libraries');
+    if (jsLibraries == null) return result;
+    for (List data in jsLibraries) {
+      String name = data[0];
+      Uri uri = Uri.parse(data[1]);
+      List<String> classes = data[2];
+      List<String> functions = data[3];
+      var metadataFunction = data[4];
+      List metadata = (metadataFunction == null)
+          ? null : JS('List', '#()', metadataFunction);
+      var libraries = result.putIfAbsent(name, () => <LibraryMirror>[]);
+      libraries.add(
+          new JsLibraryMirror(s(name), uri, classes, functions, metadata));
+    }
+    return result;
+  }
+}
+
+class JsTypeMirror implements TypeMirror {
+  final Symbol simpleName;
+  JsTypeMirror(this.simpleName);
+}
+
+class JsLibraryMirror extends JsObjectMirror implements LibraryMirror {
+  final Symbol simpleName;
+  final Uri uri;
+  final List<String> _classes;
+  final List<String> _functions;
+  final List _metadata;
+
+  JsLibraryMirror(this.simpleName,
+                 this.uri,
+                 this._classes,
+                 this._functions,
+                 this._metadata);
+
+  Symbol get qualifiedName => simpleName;
+
+  Map<Symbol, ClassMirror> get classes {
+    var result = new Map<Symbol, ClassMirror>();
+    for (int i = 0; i < _classes.length; i += 2) {
+      Symbol symbol = s(_classes[i]);
+      JsClassMirror cls = reflectClassByName(symbol, _classes[i + 1]);
+      result[symbol] = cls;
+      cls._owner = this;
+    }
+    return result;
+  }
+
+  InstanceMirror setField(Symbol fieldName, Object arg) {
+    // TODO(ahe): This is extremely dangerous!!!
+    JS('void', '#[#] = #', JS_CURRENT_ISOLATE(), n(fieldName), arg);
+    return reflect(arg);
+  }
+
+  InstanceMirror getField(Symbol fieldName) {
+    // TODO(ahe): This is extremely dangerous!!!
+    return reflect(JS('', '#[#]', JS_CURRENT_ISOLATE(), n(fieldName)));
+  }
+
+  Map<Symbol, MethodMirror> get functions {
+    var result = new Map<Symbol, MethodMirror>();
+    for (int i = 0; i < _functions.length; i++) {
+      String name = _functions[i];
+      Symbol symbol = s(name);
+      int parameterCount = null; // TODO(ahe): Compute this.
+      JsMethodMirror mirror =
+          // TODO(ahe): Create accessor for accessing $.  It is also
+          // used in js_helper.
+          new JsMethodMirror(
+              symbol, JS('', '#[#]', JS_CURRENT_ISOLATE(), name), parameterCount);
+      // TODO(ahe): Cache mirrors.
+      result[symbol] = mirror;
+      mirror._owner = this;
+    }
+    return result;
+  }
+
+  Map<Symbol, MethodMirror> get getters {
+    var result = new Map<Symbol, MethodMirror>();
+    // TODO(ahe): Implement this.
+    return result;
+  }
+
+  Map<Symbol, MethodMirror> get setters {
+    var result = new Map<Symbol, MethodMirror>();
+    // TODO(ahe): Implement this.
+    return result;
+  }
+
+  Map<Symbol, VariableMirror> get variables {
+    var result = new Map<Symbol, VariableMirror>();
+    // TODO(ahe): Implement this.
+    return result;
+  }
+
+  Map<Symbol, Mirror> get members {
+    Map<Symbol, Mirror> result = new Map<Symbol, Mirror>.from(classes);
+    addToResult(Symbol key, Mirror value) {
+      result[key] = value;
+    }
+    functions.forEach(addToResult);
+    getters.forEach(addToResult);
+    setters.forEach(addToResult);
+    variables.forEach(addToResult);
+    return result;
+  }
+
+  List<InstanceMirror> get metadata => _metadata.map(reflect).toList();
+}
+
+String n(Symbol symbol) => _symbol_dev.Symbol.getName(symbol);
+
+Symbol s(String name) {
+  if (name == null) return null;
+  return new _symbol_dev.Symbol.unvalidated(name);
+}
+
+final JsMirrorSystem currentJsMirrorSystem = new JsMirrorSystem();
+
+InstanceMirror reflect(Object reflectee) {
+  if (reflectee is Closure) {
+    return new JsClosureMirror(reflectee);
+  } else {
+    return new JsInstanceMirror(reflectee);
+  }
+}
+
+final Expando<ClassMirror> classMirrors = new Expando<ClassMirror>();
+
+ClassMirror reflectType(Type key) => reflectClassByName(s('$key'), null);
+
+ClassMirror reflectClassByName(Symbol symbol, String fields) {
+  String className = n(symbol);
+  var constructor = Primitives.getConstructor(className);
+  if (constructor == null) {
+    // Probably an intercepted class.
+    // TODO(ahe): How to handle intercepted classes?
+    throw new UnsupportedError('Cannot find class for: $className');
+  }
+  var mirror = classMirrors[constructor];
+  if (mirror == null) {
+    mirror = new JsClassMirror(symbol, constructor, fields);
+    classMirrors[constructor] = mirror;
+  }
+  return mirror;
+}
+
+abstract class JsObjectMirror implements ObjectMirror {
+  Future<InstanceMirror> setFieldAsync(Symbol fieldName, Object value) {
+    return new Future<InstanceMirror>(() => this.setField(fieldName, value));
+  }
+
+  Future<InstanceMirror> getFieldAsync(Symbol fieldName) {
+    return new Future<InstanceMirror>(() => this.getField(fieldName));
+  }
+}
+
+class JsInstanceMirror extends JsObjectMirror implements InstanceMirror {
+  final reflectee;
+
+  JsInstanceMirror(this.reflectee);
+
+  bool get hasReflectee => true;
+
+  ClassMirror get type => reflectType(reflectee.runtimeType);
+
+  Future<InstanceMirror> invokeAsync(Symbol memberName,
+                                     List<Object> positionalArguments,
+                                     [Map<Symbol, dynamic> namedArguments]) {
+    if (namedArguments != null && !namedArguments.isEmpty) {
+      throw new UnsupportedError('Named arguments are not implemented');
+    }
+    return
+        new Future<InstanceMirror>(
+            () => invoke(memberName, positionalArguments, namedArguments));
+  }
+
+  InstanceMirror invoke(Symbol memberName,
+                        List positionalArguments,
+                        [Map<Symbol,dynamic> namedArguments]) {
+    if (namedArguments != null && !namedArguments.isEmpty) {
+      throw new UnsupportedError('Named arguments are not implemented');
+    }
+    // Copy the list to ensure that it can safely be passed to
+    // JavaScript.
+    var jsList = new List.from(positionalArguments);
+    return _invoke(
+        memberName, JSInvocationMirror.METHOD,
+        '${n(memberName)}\$${positionalArguments.length}', jsList);
+  }
+
+  InstanceMirror _invoke(Symbol name,
+                         int type,
+                         String mangledName,
+                         List arguments) {
+    // TODO(ahe): Get the argument names.
+    List<String> argumentNames = [];
+    Invocation invocation = createInvocationMirror(
+        n(name), mangledName, type, arguments, argumentNames);
+
+    return reflect(delegate(invocation));
+  }
+
+  InstanceMirror setField(Symbol fieldName, Object arg) {
+    _invoke(
+        fieldName, JSInvocationMirror.SETTER, 'set\$${n(fieldName)}', [arg]);
+    return reflect(arg);
+  }
+
+  InstanceMirror getField(Symbol fieldName) {
+    return _invoke(
+        fieldName, JSInvocationMirror.GETTER, 'get\$${n(fieldName)}', []);
+  }
+
+  delegate(Invocation invocation) {
+    return JSInvocationMirror.invokeFromMirror(invocation, reflectee);
+  }
+
+  String toString() => 'InstanceMirror($reflectee)';
+}
+
+class JsClassMirror extends JsObjectMirror implements ClassMirror {
+  final Symbol simpleName;
+  final _jsConstructor;
+  final String _fields;
+  List _metadata;
+  // Set as side-effect of accessing JsLibraryMirror.classes.
+  JsLibraryMirror _owner;
+
+  JsClassMirror(this.simpleName, this._jsConstructor, this._fields);
+
+  Symbol get qualifiedName => computeQualifiedName(owner, simpleName);
+
+  Map<Symbol, MethodMirror> get functions {
+    var result = new Map<Symbol, MethodMirror>();
+    // TODO(ahe): Implement this.
+    return result;
+  }
+
+  Map<Symbol, MethodMirror> get getters {
+    var result = new Map<Symbol, MethodMirror>();
+    // TODO(ahe): Implement this.
+    return result;
+  }
+
+  Map<Symbol, MethodMirror> get setters {
+    var result = new Map<Symbol, MethodMirror>();
+    // TODO(ahe): Implement this.
+    return result;
+  }
+
+  Map<Symbol, VariableMirror> get variables {
+    var result = new Map<Symbol, VariableMirror>();
+    var s = _fields.split(";");
+    var fields = s[1] == "" ? [] : s[1].split(",");
+    for (String field in fields) {
+      JsVariableMirror mirror = new JsVariableMirror.from(field);
+      result[mirror.simpleName] = mirror;
+      mirror._owner = this;
+    }
+    return result;
+  }
+
+  Map<Symbol, Mirror> get members {
+    Map<Symbol, Mirror> result = new Map<Symbol, Mirror>.from(functions);
+    addToResult(Symbol key, Mirror value) {
+      result[key] = value;
+    }
+    getters.forEach(addToResult);
+    setters.forEach(addToResult);
+    variables.forEach(addToResult);
+    return result;
+  }
+
+  InstanceMirror setField(Symbol fieldName, Object arg) {
+    // TODO(ahe): This is extremely dangerous!!!
+    JS('void', '#[#] = #', JS_CURRENT_ISOLATE(),
+       '${n(simpleName)}_${n(fieldName)}', arg);
+    return reflect(arg);
+  }
+
+  InstanceMirror getField(Symbol fieldName) {
+    // TODO(ahe): This is extremely dangerous!!!
+    return reflect(
+        JS('', '#[#]', JS_CURRENT_ISOLATE(),
+           '${n(simpleName)}_${n(fieldName)}'));
+  }
+
+  InstanceMirror newInstance(Symbol constructorName,
+                             List positionalArguments,
+                             [Map<Symbol,dynamic> namedArguments]) {
+    if (namedArguments != null && !namedArguments.isEmpty) {
+      throw new UnsupportedError('Named arguments are not implemented');
+    }
+    String constructorName = '${n(simpleName)}\$${n(constructorName)}';
+    return reflect(JS('', r'#[#].apply(#, #)', JS_CURRENT_ISOLATE(),
+                       constructorName,
+                       JS_CURRENT_ISOLATE(),
+                       new List.from(positionalArguments)));
+  }
+
+  Future<InstanceMirror> newInstanceAsync(
+      Symbol constructorName,
+      List positionalArguments,
+      [Map<Symbol, dynamic> namedArguments]) {
+    if (namedArguments != null && !namedArguments.isEmpty) {
+      throw new UnsupportedError('Named arguments are not implemented');
+    }
+    return new Future<InstanceMirror>(
+        () => newInstance(
+            constructorName, positionalArguments, namedArguments));
+  }
+
+  DeclarationMirror get owner {
+    if (_owner == null) {
+      if (_jsConstructor is Interceptor) {
+        _owner = reflectType(Object).owner;
+      } else {
+        for (var list in JsMirrorSystem.librariesByName.values) {
+          for (JsLibraryMirror library in list) {
+            // This will set _owner field on all clasess as a side
+            // effect.  This gives us a fast path to reflect on a
+            // class without parsing reflection data.
+            library.classes;
+          }
+        }
+      }
+      if (_owner == null) {
+        throw new StateError('Class "${n(simpleName)}" has no owner');
+      }
+    }
+    return _owner;
+  }
+
+  List<InstanceMirror> get metadata {
+    if (_metadata == null) {
+      var metadataFunction = JS('', '#.prototype["@"]', _jsConstructor);
+      _metadata = (metadataFunction == null)
+          ? const [] : JS('', '#()', metadataFunction);
+    }
+    return _metadata.map(reflect).toList();
+  }
+
+  String toString() => 'ClassMirror(${n(simpleName)})';
+}
+
+class JsVariableMirror implements VariableMirror {
+  // TODO(ahe): The values in these fields are virtually untested.
+  final Symbol simpleName;
+  final String _jsName;
+  final bool _readOnly;
+  DeclarationMirror _owner;
+
+  JsVariableMirror(this.simpleName, this._jsName, this._readOnly);
+
+  factory JsVariableMirror.from(String descriptor) {
+    int length = descriptor.length;
+    var code = fieldCode(descriptor.codeUnitAt(length - 1));
+    if (code == 0) {
+      throw new RuntimeError('Bad field descriptor: $descriptor');
+    }
+    bool hasGetter = (code & 3) != 0;
+    bool hasSetter = (code >> 2) != 0;
+    String jsName;
+    String accessorName = jsName = descriptor.substring(0, length - 1);
+    int divider = descriptor.indexOf(":");
+    if (divider > 0) {
+      accessorName = accessorName.substring(0, divider);
+      jsName = accessorName.substring(divider + 1);
+    }
+    bool readOnly = !hasSetter;
+    return new JsVariableMirror(s(accessorName), jsName, readOnly);
+  }
+
+  TypeMirror get type => JsMirrorSystem._dynamicType;
+
+  DeclarationMirror get owner => _owner;
+
+  Symbol get qualifiedName => computeQualifiedName(owner, simpleName);
+
+  static int fieldCode(int code) {
+    if (code >= 60 && code <= 64) return code - 59;
+    if (code >= 123 && code <= 126) return code - 117;
+    if (code >= 37 && code <= 43) return code - 27;
+    return 0;
+  }
+}
+
+class JsClosureMirror extends JsInstanceMirror implements ClosureMirror {
+  JsClosureMirror(reflectee) : super(reflectee);
+
+  MethodMirror get function {
+    // TODO(ahe): What about optional parameters (named or not).
+    var extractCallName = JS('', r'''
+function(reflectee) {
+  for (var property in reflectee) {
+    if ("call$" == property.substring(0, 5)) return property;
+  }
+  return null;
+}
+''');
+    String callName = JS('String|Null', '#(#)', extractCallName, reflectee);
+    if (callName == null) {
+      throw new RuntimeError('Cannot find callName on "$reflectee"');
+    }
+    var jsFunction = JS('', '#[#]', reflectee, callName);
+    int parameterCount = int.parse(callName.split(r'$')[1]);
+    return new JsMethodMirror(s(callName), jsFunction, parameterCount);
+  }
+
+  InstanceMirror apply(List positionalArguments,
+                       [Map<Symbol, dynamic> namedArguments]) {
+    return reflect(
+        Function.apply(reflectee, positionalArguments, namedArguments));
+  }
+
+  Future<InstanceMirror> applyAsync(List positionalArguments,
+                                    [Map<Symbol, dynamic> namedArguments]) {
+    return new Future<InstanceMirror>(
+        () => apply(positionalArguments, namedArguments));
+  }
+}
+
+class JsMethodMirror implements MethodMirror {
+  final Symbol simpleName;
+  final _jsFunction;
+  final int _parameterCount;
+  DeclarationMirror _owner;
+
+  JsMethodMirror(this.simpleName, this._jsFunction, this._parameterCount);
+
+  List<ParameterMirror> get parameters {
+    // TODO(ahe): Fill the list with parameter mirrors.
+    return new List<ParameterMirror>(_parameterCount);
+  }
+
+  DeclarationMirror get owner => _owner;
+
+  Symbol get qualifiedName => computeQualifiedName(owner, simpleName);
+}
+
+Symbol computeQualifiedName(DeclarationMirror owner, Symbol simpleName) {
+  if (owner == null) return simpleName;
+  String ownerName = n(owner.qualifiedName);
+  if (ownerName == '') return simpleName;
+  return s('$ownerName.${n(simpleName)}');
+}
diff --git a/sdk/lib/_internal/compiler/implementation/lib/js_rti.dart b/sdk/lib/_internal/compiler/implementation/lib/js_rti.dart
index 721f38f..0cd37e1 100644
--- a/sdk/lib/_internal/compiler/implementation/lib/js_rti.dart
+++ b/sdk/lib/_internal/compiler/implementation/lib/js_rti.dart
@@ -119,7 +119,7 @@
  *   against.
  */
 bool checkSubtype(Object object, String isField, List checks, String asField) {
-  if (object == null) return true;
+  if (object == null) return false;
   var arguments = getRuntimeTypeInfo(object);
   // Interceptor is needed for JSArray and native classes.
   // TODO(sra): It could be a more specialized interceptor since [object] is not
@@ -143,7 +143,7 @@
 }
 
 Object subtypeCast(Object object, String isField, List checks, String asField) {
-  if (!checkSubtype(object, isField, checks, asField)) {
+  if (object != null && !checkSubtype(object, isField, checks, asField)) {
     String actualType = Primitives.objectTypeName(object);
     String typeName = computeTypeName(isField, checks);
     throw new CastErrorImplementation(object, typeName);
@@ -153,7 +153,7 @@
 
 Object assertSubtype(Object object, String isField, List checks,
                      String asField) {
-  if (!checkSubtype(object, isField, checks, asField)) {
+  if (object != null && !checkSubtype(object, isField, checks, asField)) {
     String typeName = computeTypeName(isField, checks);
     throw new TypeErrorImplementation(object, typeName);
   }
@@ -195,13 +195,19 @@
 
 getField(var object, var name) => JS('var', r'#[#]', object, name);
 
+bool isSubtypeOfNull(type) {
+  // `null` means `dynamic`.
+  return type == null || getConstructorName(type) == JS_OBJECT_CLASS_NAME();
+}
+
 /**
  * Tests whether the Dart object [o] is a subtype of the runtime type
  * representation [t], which is a type representation as described in the
  * comment on [isSubtype].
  */
 bool checkSubtypeOfRuntimeType(Object o, var t) {
-  if (JS('bool', '# == null', o) || JS('bool', '# == null', t)) return true;
+  if (JS('bool', '# == null', o)) return isSubtypeOfNull(t);
+  if (JS('bool', '# == null', t)) return true;
   // Get the runtime type information from the object here, because we may
   // overwrite o with the interceptor below.
   var rti = getRuntimeTypeInfo(o);
@@ -224,7 +230,7 @@
 }
 
 Object subtypeOfRuntimeTypeCast(Object object, var type) {
-  if (!checkSubtypeOfRuntimeType(object, type)) {
+  if (object != null && !checkSubtypeOfRuntimeType(object, type)) {
     String actualType = Primitives.objectTypeName(object);
     throw new CastErrorImplementation(actualType, runtimeTypeToString(type));
   }
@@ -232,7 +238,7 @@
 }
 
 Object assertSubtypeOfRuntimeType(Object object, var type) {
-  if (!checkSubtypeOfRuntimeType(object, type)) {
+  if (object != null && !checkSubtypeOfRuntimeType(object, type)) {
     throw new TypeErrorImplementation(object, runtimeTypeToString(type));
   }
   return object;
diff --git a/sdk/lib/_internal/compiler/implementation/lib/mirrors_patch.dart b/sdk/lib/_internal/compiler/implementation/lib/mirrors_patch.dart
index ffcef0a..2fddaef 100644
--- a/sdk/lib/_internal/compiler/implementation/lib/mirrors_patch.dart
+++ b/sdk/lib/_internal/compiler/implementation/lib/mirrors_patch.dart
@@ -4,463 +4,18 @@
 
 // Patch library for dart:mirrors.
 
-import 'dart:_foreign_helper' show JS;
-import 'dart:_collection-dev' as _symbol_dev;
-import 'dart:_js_helper' show createInvocationMirror;
-import 'dart:_interceptors' show Interceptor;
+import 'dart:_js_mirrors' as js;
 
 patch class MirrorSystem {
-  patch static String getName(Symbol symbol) => _n(symbol);
+  patch static String getName(Symbol symbol) => js.getName(symbol);
 }
 
-class _MirrorSystem implements MirrorSystem {
-  TypeMirror get dynamicType => _dynamicType;
-  TypeMirror get voidType => _voidType;
-
-  final static TypeMirror _dynamicType =
-      new _TypeMirror(const Symbol('dynamic'));
-  final static TypeMirror _voidType = new _TypeMirror(const Symbol('void'));
-
-  static final Map<String, List<LibraryMirror>> librariesByName =
-      computeLibrariesByName();
-
-  Iterable<LibraryMirror> findLibrary(Symbol libraryName) {
-    return new List<LibraryMirror>.from(librariesByName[_n(libraryName)]);
-  }
-
-  static Map<String, List<LibraryMirror>> computeLibrariesByName() {
-    var result = new Map<String, List<LibraryMirror>>();
-    var jsLibraries = JS('=List|Null', 'init.libraries');
-    if (jsLibraries == null) return result;
-    for (List data in jsLibraries) {
-      String name = data[0];
-      Uri uri = Uri.parse(data[1]);
-      List<String> classes = data[2];
-      List<String> functions = data[3];
-      var libraries = result.putIfAbsent(name, () => <LibraryMirror>[]);
-      libraries.add(new _LibraryMirror(_s(name), uri, classes, functions));
-    }
-    return result;
-  }
-}
-
-class _TypeMirror implements TypeMirror {
-  final Symbol simpleName;
-  _TypeMirror(this.simpleName);
-}
-
-class _LibraryMirror extends _ObjectMirror implements LibraryMirror {
-  final Symbol simpleName;
-  final Uri uri;
-  final List<String> _classes;
-  final List<String> _functions;
-
-  _LibraryMirror(this.simpleName, this.uri, this._classes, this._functions);
-
-  Symbol get qualifiedName => simpleName;
-
-  Map<Symbol, ClassMirror> get classes {
-    var result = new Map<Symbol, ClassMirror>();
-    for (int i = 0; i < _classes.length; i += 2) {
-      Symbol symbol = _s(_classes[i]);
-      _ClassMirror cls = _reflectClass(symbol, _classes[i + 1]);
-      result[symbol] = cls;
-      cls._owner = this;
-    }
-    return result;
-  }
-
-  InstanceMirror setField(Symbol fieldName, Object arg) {
-    // TODO(ahe): This is extremely dangerous!!!
-    JS('void', r'$[#] = #', _n(fieldName), arg);
-    return _reflect(arg);
-  }
-
-  InstanceMirror getField(Symbol fieldName) {
-    // TODO(ahe): This is extremely dangerous!!!
-    return _reflect(JS('', r'$[#]', _n(fieldName)));
-  }
-
-  Map<Symbol, MethodMirror> get functions {
-    var result = new Map<Symbol, MethodMirror>();
-    for (int i = 0; i < _functions.length; i++) {
-      String name = _functions[i];
-      Symbol symbol = _s(name);
-      int parameterCount = null; // TODO(ahe): Compute this.
-      _MethodMirror mirror =
-          // TODO(ahe): Create accessor for accessing $.  It is also
-          // used in js_helper.
-          new _MethodMirror(symbol, JS('', r'$[#]', name), parameterCount);
-      // TODO(ahe): Cache mirrors.
-      result[symbol] = mirror;
-      mirror._owner = this;
-    }
-    return result;
-  }
-
-  Map<Symbol, MethodMirror> get getters {
-    var result = new Map<Symbol, MethodMirror>();
-    // TODO(ahe): Implement this.
-    return result;
-  }
-
-  Map<Symbol, MethodMirror> get setters {
-    var result = new Map<Symbol, MethodMirror>();
-    // TODO(ahe): Implement this.
-    return result;
-  }
-
-  Map<Symbol, VariableMirror> get variables {
-    var result = new Map<Symbol, VariableMirror>();
-    // TODO(ahe): Implement this.
-    return result;
-  }
-
-  Map<Symbol, Mirror> get members {
-    Map<Symbol, Mirror> result = new Map<Symbol, Mirror>.from(classes);
-    addToResult(Symbol key, Mirror value) {
-      result[key] = value;
-    }
-    functions.forEach(addToResult);
-    getters.forEach(addToResult);
-    setters.forEach(addToResult);
-    variables.forEach(addToResult);
-    return result;
-  }
-}
-
-String _n(Symbol symbol) => _symbol_dev.Symbol.getName(symbol);
-
-Symbol _s(String name) {
-  if (name == null) return null;
-  return new _symbol_dev.Symbol.unvalidated(name);
-}
-
-patch MirrorSystem currentMirrorSystem() => _currentMirrorSystem;
-
-final _MirrorSystem _currentMirrorSystem = new _MirrorSystem();
+patch MirrorSystem currentMirrorSystem() => js.currentJsMirrorSystem;
 
 patch Future<MirrorSystem> mirrorSystemOf(SendPort port) {
   throw new UnsupportedError("MirrorSystem not implemented");
 }
 
-// TODO(ahe): This is a workaround for http://dartbug.com/10543
-patch InstanceMirror reflect(Object reflectee) => _reflect(reflectee);
+patch InstanceMirror reflect(Object reflectee) => js.reflect(reflectee);
 
-InstanceMirror _reflect(Object reflectee) {
-  if (reflectee is Closure) {
-    return new _ClosureMirror(reflectee);
-  } else {
-    return new _InstanceMirror(reflectee);
-  }
-}
-
-final Expando<ClassMirror> _classMirrors = new Expando<ClassMirror>();
-
-patch ClassMirror reflectClass(Type key) => __reflectClass(key);
-
-// TODO(ahe): This is a workaround for http://dartbug.com/10543
-ClassMirror __reflectClass(Type key) => _reflectClass(_s('$key'), null);
-
-ClassMirror _reflectClass(Symbol symbol, String fields) {
-  String className = _n(symbol);
-  var constructor = Primitives.getConstructor(className);
-  if (constructor == null) {
-    // Probably an intercepted class.
-    // TODO(ahe): How to handle intercepted classes?
-    throw new UnsupportedError('Cannot find class for: $className');
-  }
-  var mirror = _classMirrors[constructor];
-  if (mirror == null) {
-    mirror = new _ClassMirror(symbol, constructor, fields);
-    _classMirrors[constructor] = mirror;
-  }
-  return mirror;
-}
-
-abstract class _ObjectMirror implements ObjectMirror {
-  Future<InstanceMirror> setFieldAsync(Symbol fieldName, Object value) {
-    return new Future<InstanceMirror>(() => this.setField(fieldName, value));
-  }
-
-  Future<InstanceMirror> getFieldAsync(Symbol fieldName) {
-    return new Future<InstanceMirror>(() => this.getField(fieldName));
-  }
-}
-
-class _InstanceMirror extends _ObjectMirror implements InstanceMirror {
-  final reflectee;
-
-  _InstanceMirror(this.reflectee);
-
-  bool get hasReflectee => true;
-
-  ClassMirror get type => __reflectClass(reflectee.runtimeType);
-
-  Future<InstanceMirror> invokeAsync(Symbol memberName,
-                                     List<Object> positionalArguments,
-                                     [Map<String,Object> namedArguments]) {
-    if (namedArguments != null && !namedArguments.isEmpty) {
-      throw new UnsupportedError('Named arguments are not implemented');
-    }
-    return
-        new Future<InstanceMirror>(
-            () => invoke(memberName, positionalArguments, namedArguments));
-  }
-
-  InstanceMirror invoke(Symbol memberName,
-                        List positionalArguments,
-                        [Map<Symbol,dynamic> namedArguments]) {
-    if (namedArguments != null && !namedArguments.isEmpty) {
-      throw new UnsupportedError('Named arguments are not implemented');
-    }
-    // Copy the list to ensure that it can safely be passed to
-    // JavaScript.
-    var jsList = new List.from(positionalArguments);
-    return _invoke(
-        memberName, JSInvocationMirror.METHOD,
-        '${_n(memberName)}\$${positionalArguments.length}', jsList);
-  }
-
-  InstanceMirror _invoke(Symbol name,
-                         int type,
-                         String mangledName,
-                         List arguments) {
-    // TODO(ahe): Get the argument names.
-    List<String> argumentNames = [];
-    Invocation invocation = createInvocationMirror(
-        _n(name), mangledName, type, arguments, argumentNames);
-
-    return _reflect(delegate(invocation));
-  }
-
-  InstanceMirror setField(Symbol fieldName, Object arg) {
-    _invoke(
-        fieldName, JSInvocationMirror.SETTER, 'set\$${_n(fieldName)}', [arg]);
-    return _reflect(arg);
-  }
-
-  InstanceMirror getField(Symbol fieldName) {
-    return _invoke(
-        fieldName, JSInvocationMirror.GETTER, 'get\$${_n(fieldName)}', []);
-  }
-
-  delegate(Invocation invocation) {
-    return JSInvocationMirror.invokeFromMirror(invocation, reflectee);
-  }
-
-  String toString() => 'InstanceMirror($reflectee)';
-}
-
-class _ClassMirror extends _ObjectMirror implements ClassMirror {
-  final Symbol simpleName;
-  final _jsConstructor;
-  final String _fields;
-  // Set as side-effect of accessing _LibraryMirror.classes.
-  _LibraryMirror _owner;
-
-  _ClassMirror(this.simpleName, this._jsConstructor, this._fields);
-
-  Symbol get qualifiedName => _computeQualifiedName(owner, simpleName);
-
-  Map<Symbol, MethodMirror> get functions {
-    var result = new Map<Symbol, MethodMirror>();
-    // TODO(ahe): Implement this.
-    return result;
-  }
-
-  Map<Symbol, MethodMirror> get getters {
-    var result = new Map<Symbol, MethodMirror>();
-    // TODO(ahe): Implement this.
-    return result;
-  }
-
-  Map<Symbol, MethodMirror> get setters {
-    var result = new Map<Symbol, MethodMirror>();
-    // TODO(ahe): Implement this.
-    return result;
-  }
-
-  Map<Symbol, VariableMirror> get variables {
-    var result = new Map<Symbol, VariableMirror>();
-    var s = _fields.split(";");
-    var fields = s[1] == "" ? [] : s[1].split(",");
-    for (String field in fields) {
-      _VariableMirror mirror = new _VariableMirror.from(field);
-      result[mirror.simpleName] = mirror;
-      mirror._owner = this;
-    }
-    return result;
-  }
-
-  Map<Symbol, Mirror> get members {
-    Map<Symbol, Mirror> result = new Map<Symbol, Mirror>.from(functions);
-    addToResult(Symbol key, Mirror value) {
-      result[key] = value;
-    }
-    getters.forEach(addToResult);
-    setters.forEach(addToResult);
-    variables.forEach(addToResult);
-    return result;
-  }
-
-  InstanceMirror setField(Symbol fieldName, Object arg) {
-    // TODO(ahe): This is extremely dangerous!!!
-    JS('void', r'$[#] = #', '${_n(simpleName)}_${_n(fieldName)}', arg);
-    return _reflect(arg);
-  }
-
-  InstanceMirror getField(Symbol fieldName) {
-    // TODO(ahe): This is extremely dangerous!!!
-    return _reflect(
-        JS('', r'$[#]', '${_n(simpleName)}_${_n(fieldName)}'));
-  }
-
-  InstanceMirror newInstance(Symbol constructorName,
-                             List positionalArguments,
-                             [Map<Symbol,dynamic> namedArguments]) {
-    if (namedArguments != null && !namedArguments.isEmpty) {
-      throw new UnsupportedError('Named arguments are not implemented');
-    }
-    String constructorName = '${_n(simpleName)}\$${_n(constructorName)}';
-    return _reflect(JS('', r'$[#].apply($, #)', constructorName,
-                       new List.from(positionalArguments)));
-  }
-
-  Future<InstanceMirror> newInstanceAsync(
-      Symbol constructorName,
-      List positionalArguments,
-      [Map<Symbol, dynamic> namedArguments]) {
-    if (namedArguments != null && !namedArguments.isEmpty) {
-      throw new UnsupportedError('Named arguments are not implemented');
-    }
-    return new Future<InstanceMirror>(
-        () => newInstance(
-            constructorName, positionalArguments, namedArguments));
-  }
-
-  DeclarationMirror get owner {
-    if (_owner == null) {
-      if (_jsConstructor is Interceptor) {
-        _owner = __reflectClass(Object).owner;
-      } else {
-        for (var list in _MirrorSystem.librariesByName.values) {
-          for (_LibraryMirror library in list) {
-            // This will set _owner field on all clasess as a side
-            // effect.  This gives us a fast path to reflect on a
-            // class without parsing reflection data.
-            library.classes;
-          }
-        }
-      }
-      if (_owner == null) {
-        throw new StateError('Class "${_n(simpleName)}" has no owner');
-      }
-    }
-    return _owner;
-  }
-
-  String toString() => 'ClassMirror(${_n(simpleName)})';
-}
-
-class _VariableMirror implements VariableMirror {
-  // TODO(ahe): The values in these fields are virtually untested.
-  final Symbol simpleName;
-  final String _jsName;
-  final bool _readOnly;
-  DeclarationMirror _owner;
-
-  _VariableMirror(this.simpleName, this._jsName, this._readOnly);
-
-  factory _VariableMirror.from(String descriptor) {
-    int length = descriptor.length;
-    var code = fieldCode(descriptor.codeUnitAt(length - 1));
-    if (code == 0) {
-      throw new RuntimeError('Bad field descriptor: $descriptor');
-    }
-    bool hasGetter = (code & 3) != 0;
-    bool hasSetter = (code >> 2) != 0;
-    String jsName;
-    String accessorName = jsName = descriptor.substring(0, length - 1);
-    int divider = descriptor.indexOf(":");
-    if (divider > 0) {
-      accessorName = accessorName.substring(0, divider);
-      jsName = accessorName.substring(divider + 1);
-    }
-    bool readOnly = !hasSetter;
-    return new _VariableMirror(_s(accessorName), jsName, readOnly);
-  }
-
-  TypeMirror get type => _MirrorSystem._dynamicType;
-
-  DeclarationMirror get owner => _owner;
-
-  Symbol get qualifiedName => _computeQualifiedName(owner, simpleName);
-
-  static int fieldCode(int code) {
-    if (code >= 60 && code <= 64) return code - 59;
-    if (code >= 123 && code <= 126) return code - 117;
-    if (code >= 37 && code <= 43) return code - 27;
-    return 0;
-  }
-}
-
-class _ClosureMirror extends _InstanceMirror implements ClosureMirror {
-  _ClosureMirror(reflectee) : super(reflectee);
-
-  MethodMirror get function {
-    // TODO(ahe): What about optional parameters (named or not).
-    var extractCallName = JS('', r'''
-function(reflectee) {
-  for (var property in reflectee) {
-    if ("call$" == property.substring(0, 5)) return property;
-  }
-  return null;
-}
-''');
-    String callName = JS('String|Null', '#(#)', extractCallName, reflectee);
-    if (callName == null) {
-      throw new RuntimeError('Cannot find callName on "$reflectee"');
-    }
-    var jsFunction = JS('', '#[#]', reflectee, callName);
-    int parameterCount = int.parse(callName.split(r'$')[1]);
-    return new _MethodMirror(_s(callName), jsFunction, parameterCount);
-  }
-
-  InstanceMirror apply(List positionalArguments,
-                       [Map<Symbol, dynamic> namedArguments]) {
-    return _reflect(
-        Function.apply(reflectee, positionalArguments, namedArguments));
-  }
-
-  Future<InstanceMirror> applyAsync(List positionalArguments,
-                                    [Map<Symbol, dynamic> namedArguments]) {
-    return new Future<InstanceMirror>(
-        () => apply(positionalArguments, namedArguments));
-  }
-}
-
-class _MethodMirror implements MethodMirror {
-  final Symbol simpleName;
-  final _jsFunction;
-  final int _parameterCount;
-  DeclarationMirror _owner;
-
-  _MethodMirror(this.simpleName, this._jsFunction, this._parameterCount);
-
-  List<ParameterMirror> get parameters {
-    // TODO(ahe): Fill the list with parameter mirrors.
-    return new List<ParameterMirror>(_parameterCount);
-  }
-
-  DeclarationMirror get owner => _owner;
-
-  Symbol get qualifiedName => _computeQualifiedName(owner, simpleName);
-}
-
-Symbol _computeQualifiedName(DeclarationMirror owner, Symbol simpleName) {
-  if (owner == null) return simpleName;
-  String ownerName = _n(owner.qualifiedName);
-  if (ownerName == '') return simpleName;
-  return _s('$ownerName.${_n(simpleName)}');
-}
+patch ClassMirror reflectClass(Type key) => js.reflectType(key);
diff --git a/sdk/lib/_internal/compiler/implementation/resolution/members.dart b/sdk/lib/_internal/compiler/implementation/resolution/members.dart
index ae787be..6e2eb36 100644
--- a/sdk/lib/_internal/compiler/implementation/resolution/members.dart
+++ b/sdk/lib/_internal/compiler/implementation/resolution/members.dart
@@ -106,10 +106,10 @@
     return selectors[node.assignmentOperator];
   }
 
-  // The following methods set selectors on the "for in" node. Since	
-  // we're using three selectors, we need to use children of the node,	
-  // and we arbitrarily choose which ones.	
- 
+  // The following methods set selectors on the "for in" node. Since
+  // we're using three selectors, we need to use children of the node,
+  // and we arbitrarily choose which ones.
+
   Selector setIteratorSelector(ForIn node, Selector selector) {
     selectors[node] = selector;
   }
@@ -121,7 +121,7 @@
   Selector setMoveNextSelector(ForIn node, Selector selector) {
     selectors[node.forToken] = selector;
   }
-	
+
   Selector getMoveNextSelector(ForIn node) {
     return selectors[node.forToken];
   }
@@ -602,6 +602,14 @@
     ClassElement mixin = mixinApplication.mixin;
     if (mixin == null) return;
 
+    // Check that we're not trying to use Object as a mixin.
+    if (mixin.superclass == null) {
+      compiler.reportErrorCode(mixinApplication,
+                               MessageKind.ILLEGAL_MIXIN_OBJECT);
+      // Avoid reporting additional errors for the Object class.
+      return;
+    }
+
     // Check that the mixed in class has Object as its superclass.
     if (!mixin.superclass.isObject(compiler)) {
       compiler.reportErrorCode(mixin, MessageKind.ILLEGAL_MIXIN_SUPERCLASS);
@@ -962,8 +970,12 @@
       annotation.resolutionState = STATE_STARTED;
 
       Node node = annotation.parseNode(compiler);
-      ResolverVisitor visitor =
-          visitorFor(annotation.annotatedElement.enclosingElement);
+      Element annotatedElement = annotation.annotatedElement;
+      Element context = annotatedElement.enclosingElement;
+      if (context == null) {
+        context = annotatedElement;
+      }
+      ResolverVisitor visitor = visitorFor(context);
       node.accept(visitor);
       annotation.value = compiler.metadataHandler.compileNodeWithDefinitions(
           node, visitor.mapping, isConst: true);
@@ -2307,9 +2319,8 @@
     // unqualified.
     useElement(node, target);
     registerSend(selector, target);
-    if (node.isPropertyAccess) {
-      // It might be the closurization of a method.
-      world.registerInstantiatedClass(compiler.functionClass, mapping);
+    if (node.isPropertyAccess && Elements.isStaticOrTopLevelFunction(target)) {
+      world.registerGetOfStaticFunction(target.declaration);
     }
     return node.isPropertyAccess ? target : null;
   }
@@ -2491,11 +2502,7 @@
       compiler.reportErrorCode(
           enclosingElement, MessageKind.MISSING_FACTORY_KEYWORD);
     }
-    Element redirectionTarget = resolveRedirectingFactory(node);
-    var type = mapping.getType(node.expression);
-    if (type is InterfaceType && !type.isRaw) {
-      unimplemented(node.expression, 'type arguments on redirecting factory');
-    }
+    FunctionElement redirectionTarget = resolveRedirectingFactory(node);
     useElement(node.expression, redirectionTarget);
     FunctionElement constructor = enclosingElement;
     if (constructor.modifiers.isConst() &&
@@ -2503,7 +2510,36 @@
       error(node, MessageKind.CONSTRUCTOR_IS_NOT_CONST);
     }
     constructor.defaultImplementation = redirectionTarget;
-    if (Elements.isUnresolved(redirectionTarget)) return;
+    if (Elements.isUnresolved(redirectionTarget)) {
+      compiler.backend.registerThrowNoSuchMethod(mapping);
+      return;
+    }
+
+    // Compute the signature of the target method taking into account the
+    // type arguments that are specified in the redirection, and store it on
+    // the return node.
+    ClassElement targetClass = redirectionTarget.getEnclosingClass();
+    InterfaceType type = mapping.getType(node.expression)
+        .subst(currentClass.typeVariables, targetClass.typeVariables);
+    mapping.setType(node, type);
+
+    // Check that the target constructor is type compatible with the
+    // redirecting constructor.
+    FunctionType targetType = redirectionTarget.computeType(compiler)
+        .subst(type.typeArguments, targetClass.typeVariables);
+    FunctionType constructorType = constructor.computeType(compiler);
+    if (!compiler.types.isSubtype(targetType, constructorType)) {
+      warning(node, MessageKind.NOT_ASSIGNABLE,
+              {'fromType': targetType, 'toType': constructorType});
+    }
+
+    FunctionSignature targetSignature =
+        redirectionTarget.computeSignature(compiler);
+    FunctionSignature constructorSignature =
+        constructor.computeSignature(compiler);
+    if (!targetSignature.isCompatibleWith(constructorSignature)) {
+      compiler.backend.registerThrowNoSuchMethod(mapping);
+    }
 
     // TODO(ahe): Check that this doesn't lead to a cycle.  For now,
     // just make sure that the redirection target isn't itself a
@@ -2513,7 +2549,7 @@
       FunctionExpression function = targetImplementation.parseNode(compiler);
       if (function.body != null && function.body.asReturn() != null
           && function.body.asReturn().isRedirectingFactoryBody) {
-        unimplemented(node.expression, 'redirecing to redirecting factory');
+        unimplemented(node.expression, 'redirecting to redirecting factory');
       }
     }
     world.registerStaticUse(redirectionTarget);
diff --git a/sdk/lib/_internal/compiler/implementation/scanner/listener.dart b/sdk/lib/_internal/compiler/implementation/scanner/listener.dart
index 5c3243a..17f790c 100644
--- a/sdk/lib/_internal/compiler/implementation/scanner/listener.dart
+++ b/sdk/lib/_internal/compiler/implementation/scanner/listener.dart
@@ -1033,9 +1033,11 @@
   }
 
   Link<MetadataAnnotation> popMetadata(Element element) {
-    var result = metadata;
+    var result = const Link<MetadataAnnotation>();
     for (Link link = metadata; !link.isEmpty; link = link.tail) {
       element.addMetadata(link.head);
+      // Reverse the list as is implicitly done by addMetadata.
+      result = result.prepend(link.head);
     }
     metadata = const Link<MetadataAnnotation>();
     return result;
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/bailout.dart b/sdk/lib/_internal/compiler/implementation/ssa/bailout.dart
index c22a52c..b9db4c4 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/bailout.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/bailout.dart
@@ -181,7 +181,7 @@
     bool isIndexOperatorOnIndexablePrimitive(instruction) {
       return instruction is HIndex
           || (instruction is HInvokeDynamicMethod
-              && instruction.isIndexOperatorOnIndexablePrimitive());
+              && instruction.isIndexOperatorOnIndexablePrimitive(compiler));
     }
 
     // To speed up computations on values loaded from arrays, we
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/builder.dart b/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
index 6f4cd16..76e92c0 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
@@ -67,8 +67,7 @@
             index++;
           });
         } else {
-          // TODO(ahe): I have disabled type optimizations for
-          // optional arguments as the types are stored in the wrong
+          // BUG(10938): the types are stored in the wrong order.
           // order.
           HTypeList parameterTypes =
               backend.optimisticParameterTypes(element.declaration,
@@ -2632,7 +2631,8 @@
       // creating an [HStatic].
       push(new HStatic(element.declaration));
       // TODO(ahe): This should be registered in codegen.
-      compiler.enqueuer.codegen.registerGetOfStaticFunction(element);
+      compiler.enqueuer.codegen.registerGetOfStaticFunction(
+          element.declaration);
     } else if (Elements.isErroneousElement(element)) {
       // An erroneous element indicates an unresolved static getter.
       generateThrowNoSuchMethod(send,
@@ -2973,10 +2973,10 @@
     return;
   }
 
-  void handleForeignJsCurrentIsolate(Send node) {
+  void handleForeignJsCurrentIsolateContext(Send node) {
     if (!node.arguments.isEmpty) {
       compiler.cancel(
-          'Too many arguments to JS_CURRENT_ISOLATE', node: node);
+          'Too many arguments to JS_CURRENT_ISOLATE_CONTEXT', node: node);
     }
 
     if (!compiler.hasIsolateSupport()) {
@@ -3095,13 +3095,22 @@
                       <HInstruction>[]));
   }
 
+  void handleForeignJsCurrentIsolate(Send node) {
+    if (!node.arguments.isEmpty) {
+      compiler.cancel('Too many arguments', node: node.argumentsNode);
+    }
+    push(new HForeign(new js.LiteralString(backend.namer.CURRENT_ISOLATE),
+                      HType.UNKNOWN,
+                      <HInstruction>[]));
+  }
+
   visitForeignSend(Send node) {
     Selector selector = elements.getSelector(node);
     SourceString name = selector.name;
     if (name == const SourceString('JS')) {
       handleForeignJs(node);
-    } else if (name == const SourceString('JS_CURRENT_ISOLATE')) {
-      handleForeignJsCurrentIsolate(node);
+    } else if (name == const SourceString('JS_CURRENT_ISOLATE_CONTEXT')) {
+      handleForeignJsCurrentIsolateContext(node);
     } else if (name == const SourceString('JS_CALL_IN_ISOLATE')) {
       handleForeignJsCallInIsolate(node);
     } else if (name == const SourceString('DART_CLOSURE_TO_JS')) {
@@ -3114,6 +3123,9 @@
       handleForeignCreateIsolate(node);
     } else if (name == const SourceString('JS_OPERATOR_IS_PREFIX')) {
       stack.add(addConstantString(node, backend.namer.operatorIsPrefix()));
+    } else if (name == const SourceString('JS_OBJECT_CLASS_NAME')) {
+      String name = backend.namer.getRuntimeTypeName(compiler.objectClass);
+      stack.add(addConstantString(node, name));
     } else if (name == const SourceString('JS_OPERATOR_AS_PREFIX')) {
       stack.add(addConstantString(node, backend.namer.operatorAsPrefix()));
     } else if (name == const SourceString('JS_DART_OBJECT_CONSTRUCTOR')) {
@@ -3122,6 +3134,8 @@
       Element element = compiler.findHelper(
           const SourceString('JavaScriptIndexingBehavior'));
       stack.add(addConstantString(node, backend.namer.operatorIs(element)));
+    } else if (name == const SourceString('JS_CURRENT_ISOLATE')) {
+      handleForeignJsCurrentIsolate(node);
     } else {
       throw "Unknown foreign: ${selector}";
     }
@@ -3376,6 +3390,7 @@
     }
     FunctionElement functionElement = constructor;
     constructor = functionElement.redirectionTarget;
+
     final bool isSymbolConstructor =
         functionElement == compiler.symbolConstructor;
 
@@ -3388,6 +3403,23 @@
                        message: 'Constructor Symbol.validated is missing'));
     }
 
+    bool isRedirected = functionElement.isRedirectingFactory;
+    DartType expectedType = type;
+    if (isRedirected) {
+      FunctionExpression functionNode = functionElement.parseNode(compiler);
+      if (functionNode.isRedirectingFactory) {
+        // Lookup the type used in the redirection.
+        Return redirectionNode = functionNode.body;
+        TreeElements treeElements =
+            compiler.enqueuer.resolution.getCachedElements(
+                functionElement.declaration);
+        ClassElement targetClass = functionElement.getEnclosingClass();
+        type = treeElements.getType(redirectionNode)
+            .subst(type.typeArguments, targetClass.typeVariables);
+      }
+      functionElement = functionElement.redirectionTarget;
+    }
+
     var inputs = <HInstruction>[];
     // TODO(5347): Try to avoid the need for calling [implementation] before
     // calling [addStaticSendArgumentsToList].
@@ -3432,6 +3464,15 @@
     if (isListConstructor && backend.needsRti(compiler.listClass)) {
       handleListConstructor(type, send, newInstance);
     }
+
+    // Finally, if we called a redirecting factory constructor, check the type.
+    if (isRedirected) {
+      HInstruction checked = potentiallyCheckType(newInstance, expectedType);
+      if (checked != newInstance) {
+        pop();
+        stack.add(checked);
+      }
+    }
   }
 
   visitStaticSend(Send node) {
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart b/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart
index 120f91c..797bc85 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart
@@ -2462,7 +2462,7 @@
       // input is !string
       checkString(input, '!==');
       test = pop();
-    } else if (node.isExtendableArray()) {
+    } else if (node.isExtendableArray(compiler)) {
       // input is !Object || input is !Array || input.isFixed
       checkObject(input, '!==');
       js.Expression objectTest = pop();
@@ -2471,7 +2471,7 @@
       checkFixedArray(input);
       test = new js.Binary('||', objectTest, arrayTest);
       test = new js.Binary('||', test, pop());
-    } else if (node.isMutableArray()) {
+    } else if (node.isMutableArray(compiler)) {
       // input is !Object
       // || ((input is !Array || input.isImmutable)
       //     && input is !JsIndexingBehavior)
@@ -2484,7 +2484,7 @@
       checkIndexingBehavior(input, negative: true);
       js.Binary notIndexing = new js.Binary('&&', notArrayOrImmutable, pop());
       test = new js.Binary('||', objectTest, notIndexing);
-    } else if (node.isReadableArray()) {
+    } else if (node.isReadableArray(compiler)) {
       // input is !Object
       // || (input is !Array && input is !JsIndexingBehavior)
       checkObject(input, '!==');
@@ -2494,7 +2494,7 @@
       checkIndexingBehavior(input, negative: true);
       js.Expression notIndexing = new js.Binary('&&', arrayTest, pop());
       test = new js.Binary('||', objectTest, notIndexing);
-    } else if (node.isIndexablePrimitive()) {
+    } else if (node.isIndexablePrimitive(compiler)) {
       // input is !String
       // && (input is !Object
       //     || (input is !Array && input is !JsIndexingBehavior))
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/interceptor_simplifier.dart b/sdk/lib/_internal/compiler/implementation/ssa/interceptor_simplifier.dart
index e3f7a46..9c7de35 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/interceptor_simplifier.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/interceptor_simplifier.dart
@@ -99,7 +99,7 @@
       constantInterceptor = backend.jsBoolClass;
     } else if (type.isString()) {
       constantInterceptor = backend.jsStringClass;
-    } else if (type.isArray()) {
+    } else if (type.isArray(compiler)) {
       constantInterceptor = backend.jsArrayClass;
     } else if (type.isNull()) {
       constantInterceptor = backend.jsNullClass;
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 426332e..e27ae59 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/invoke_dynamic_specializers.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/invoke_dynamic_specializers.dart
@@ -21,7 +21,18 @@
 
   HType computeTypeFromInputTypes(HInvokeDynamic instruction,
                                   Compiler compiler) {
-    return HType.UNKNOWN;
+    HType receiverType = instruction.getDartReceiver(compiler).instructionType;
+    Selector refined = receiverType.refine(instruction.selector, compiler);
+    HType type = new HType.inferredTypeForSelector(refined, compiler);
+    // TODO(ngeoffray): Because we don't know yet the side effects of
+    // a JS call, we sometimes know more in the compiler about the
+    // side effects of an element (for example operator% on the int
+    // class). We should remove this check once we analyze JS calls.
+    if (!instruction.useGvn()) {
+      instruction.sideEffects =
+          compiler.world.getSideEffectsOfSelector(refined);
+    }
+    return type;
   }
 
   HInstruction tryConvertToBuiltin(HInvokeDynamic instruction,
@@ -171,8 +182,8 @@
                                   Compiler compiler) {
     // All bitwise operations on primitive types either produce an
     // integer or throw an error.
-    if (instruction.inputs[1].isPrimitive()) return HType.INTEGER;
-    return HType.UNKNOWN;
+    if (instruction.inputs[1].isPrimitiveOrNull()) return HType.INTEGER;
+    return super.computeTypeFromInputTypes(instruction, compiler);
   }
 
   HInstruction tryConvertToBuiltin(HInvokeDynamic instruction,
@@ -207,8 +218,8 @@
   HType computeTypeFromInputTypes(HInvokeDynamic instruction,
                                   Compiler compiler) {
     HType operandType = instruction.inputs[1].instructionType;
-    if (operandType.isNumber()) return operandType;
-    return HType.UNKNOWN;
+    if (operandType.isNumberOrNull()) return operandType;
+    return super.computeTypeFromInputTypes(instruction, compiler);
   }
 
   HInstruction tryConvertToBuiltin(HInvokeDynamic instruction,
@@ -226,12 +237,12 @@
                                   Compiler compiler) {
     HInstruction left = instruction.inputs[1];
     HInstruction right = instruction.inputs[2];
-    if (left.isInteger() && right.isInteger()) return HType.INTEGER;
-    if (left.isNumber()) {
-      if (left.isDouble() || right.isDouble()) return HType.DOUBLE;
+    if (left.isIntegerOrNull() && right.isIntegerOrNull()) return HType.INTEGER;
+    if (left.isNumberOrNull()) {
+      if (left.isDoubleOrNull() || right.isDoubleOrNull()) return HType.DOUBLE;
       return HType.NUMBER;
     }
-    return HType.UNKNOWN;
+    return super.computeTypeFromInputTypes(instruction, compiler);
   }
 
   HType computeDesiredTypeForInput(HInvokeDynamic instruction,
@@ -308,8 +319,8 @@
   HType computeTypeFromInputTypes(HInstruction instruction,
                                   Compiler compiler) {
     HInstruction left = instruction.inputs[1];
-    if (left.isNumber()) return HType.DOUBLE;
-    return HType.UNKNOWN;
+    if (left.isNumberOrNull()) return HType.DOUBLE;
+    return super.computeTypeFromInputTypes(instruction, compiler);
   }
 
   HType computeDesiredTypeForInput(HInstruction instruction,
@@ -388,8 +399,8 @@
     // All bitwise operations on primitive types either produce an
     // integer or throw an error.
     HInstruction left = instruction.inputs[1];
-    if (left.isPrimitive()) return HType.INTEGER;
-    return HType.UNKNOWN;
+    if (left.isPrimitiveOrNull()) return HType.INTEGER;
+    return super.computeTypeFromInputTypes(instruction, compiler);
   }
 
   HType computeDesiredTypeForInput(HInvokeDynamic instruction,
@@ -494,7 +505,7 @@
     if (instruction.inputs[1].instructionType.isPrimitiveOrNull()) {
       return HType.BOOLEAN;
     }
-    return HType.UNKNOWN;
+    return super.computeTypeFromInputTypes(instruction, compiler);
   }
 
   HType computeDesiredTypeForInput(HInvokeDynamic instruction,
@@ -546,11 +557,11 @@
       return right.instructionType;
     }
     // String equality testing is much more common than array equality testing.
-    if (input == left && left.isIndexablePrimitive()) {
+    if (input == left && left.isIndexablePrimitive(compiler)) {
       return HType.READABLE_ARRAY;
     }
     // String equality testing is much more common than array equality testing.
-    if (input == right && right.isIndexablePrimitive()) {
+    if (input == right && right.isIndexablePrimitive(compiler)) {
       return HType.STRING;
     }
     return HType.UNKNOWN;
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart b/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart
index 757230d..4236ba1 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart
@@ -826,18 +826,26 @@
   bool isControlFlow() => false;
 
   // All isFunctions work on the propagated types.
-  bool isArray() => instructionType.isArray();
-  bool isReadableArray() => instructionType.isReadableArray();
-  bool isMutableArray() => instructionType.isMutableArray();
-  bool isExtendableArray() => instructionType.isExtendableArray();
-  bool isFixedArray() => instructionType.isFixedArray();
+  bool isArray(Compiler compiler) =>
+      instructionType.isArray(compiler);
+  bool isReadableArray(Compiler compiler) =>
+      instructionType.isReadableArray(compiler);
+  bool isMutableArray(Compiler compiler) =>
+      instructionType.isMutableArray(compiler);
+  bool isExtendableArray(Compiler compiler) =>
+      instructionType.isExtendableArray(compiler);
+  bool isFixedArray(Compiler compiler) =>
+      instructionType.isFixedArray(compiler);
   bool isBoolean() => instructionType.isBoolean();
   bool isInteger() => instructionType.isInteger();
+  bool isIntegerOrNull() => instructionType.isIntegerOrNull();
   bool isDouble() => instructionType.isDouble();
+  bool isDoubleOrNull() => instructionType.isDoubleOrNull();
   bool isNumber() => instructionType.isNumber();
   bool isNumberOrNull() => instructionType.isNumberOrNull();
   bool isString() => instructionType.isString();
   bool isPrimitive() => instructionType.isPrimitive();
+  bool isPrimitiveOrNull() => instructionType.isPrimitiveOrNull();
   bool isNull() => instructionType.isNull();
   bool canBeNull() => instructionType.canBeNull();
   bool canBePrimitive(Compiler compiler) =>
@@ -851,7 +859,8 @@
       instructionType.isMutableIndexable(compiler);
 
   // TODO(kasperl): Get rid of this one.
-  bool isIndexablePrimitive() => instructionType.isIndexablePrimitive();
+  bool isIndexablePrimitive(Compiler compiler) =>
+      instructionType.isIndexablePrimitive(compiler);
 
   /**
    * Type of the unstruction.
@@ -1332,11 +1341,11 @@
   String toString() => 'invoke dynamic method: $selector';
   accept(HVisitor visitor) => visitor.visitInvokeDynamicMethod(this);
 
-  bool isIndexOperatorOnIndexablePrimitive() {
+  bool isIndexOperatorOnIndexablePrimitive(Compiler compiler) {
     return isInterceptedCall
         && selector.kind == SelectorKind.INDEX
         && selector.name == const SourceString('[]')
-        && inputs[1].isIndexablePrimitive();
+        && inputs[1].isIndexablePrimitive(compiler);
   }
 }
 
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart b/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart
index c803976..ffcab4d 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart
@@ -245,7 +245,7 @@
         return graph.addConstantInt(constant.length, constantSystem);
       }
       Element element = backend.jsIndexableLength;
-      bool isAssignable = !actualReceiver.isFixedArray() &&
+      bool isAssignable = !actualReceiver.isFixedArray(compiler) &&
           !actualReceiver.isString();
       HFieldGet result = new HFieldGet(
           element, actualReceiver, isAssignable: isAssignable);
@@ -279,7 +279,7 @@
 
     if (selector.isCall()) {
       Element target;
-      if (input.isExtendableArray()) {
+      if (input.isExtendableArray(compiler)) {
         if (selector.applies(backend.jsArrayRemoveLast, compiler)) {
           target = backend.jsArrayRemoveLast;
         } else if (selector.applies(backend.jsArrayAdd, compiler)) {
@@ -826,7 +826,8 @@
   HBoundsCheck insertBoundsCheck(HInstruction indexNode,
                                  HInstruction array,
                                  HInstruction indexArgument) {
-    bool isAssignable = !array.isFixedArray() && !array.isString();
+    bool isAssignable =
+        !array.isFixedArray(backend.compiler) && !array.isString();
     HFieldGet length = new HFieldGet(
         backend.jsIndexableLength, array, isAssignable: isAssignable);
     length.instructionType = HType.INTEGER;
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/types.dart b/sdk/lib/_internal/compiler/implementation/ssa/types.dart
index d1d22bf..faf1f08 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/types.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/types.dart
@@ -180,12 +180,13 @@
   bool isInteger() => false;
   bool isDouble() => false;
   bool isString() => false;
-  bool isFixedArray() => false;
-  bool isReadableArray() => false;
-  bool isMutableArray() => false;
-  bool isExtendableArray() => false;
-  bool isPrimitive() => false;
 
+  bool isFixedArray(Compiler compiler) => false;
+  bool isReadableArray(Compiler compiler) => false;
+  bool isMutableArray(Compiler compiler) => false;
+  bool isExtendableArray(Compiler compiler) => false;
+
+  bool isPrimitive() => false;
   bool isBooleanOrNull() => false;
   bool isNumberOrNull() => false;
   bool isIntegerOrNull() => false;
@@ -194,7 +195,7 @@
   bool isPrimitiveOrNull() => false;
 
   // TODO(kasperl): Get rid of this one.
-  bool isIndexablePrimitive() => false;
+  bool isIndexablePrimitive(Compiler compiler) => false;
 
   bool isIndexable(Compiler compiler) {
     JavaScriptBackend backend = compiler.backend;
@@ -222,7 +223,7 @@
   /** A type is useful it is not unknown, not conflicting, and not null. */
   bool isUseful() => !isUnknown() && !isConflicting() && !isNull();
   /** Alias for isReadableArray. */
-  bool isArray() => isReadableArray();
+  bool isArray(Compiler compiler) => isReadableArray(compiler);
 
   TypeMask computeMask(Compiler compiler);
 
@@ -457,7 +458,7 @@
 
 class HIndexablePrimitiveType extends HPrimitiveType {
   const HIndexablePrimitiveType();
-  bool isIndexablePrimitive() => true;
+  bool isIndexablePrimitive(Compiler compiler) => true;
   String toString() => "indexable";
 
   TypeMask computeMask(Compiler compiler) {
@@ -497,7 +498,7 @@
 
 class HReadableArrayType extends HIndexablePrimitiveType {
   const HReadableArrayType();
-  bool isReadableArray() => true;
+  bool isReadableArray(Compiler compiler) => true;
   String toString() => "readable array";
   bool canBePrimitiveArray(Compiler compiler) => true;
 
@@ -510,7 +511,7 @@
 
 class HMutableArrayType extends HReadableArrayType {
   const HMutableArrayType();
-  bool isMutableArray() => true;
+  bool isMutableArray(Compiler compiler) => true;
   String toString() => "mutable array";
 
   TypeMask computeMask(Compiler compiler) {
@@ -522,7 +523,7 @@
 
 class HFixedArrayType extends HMutableArrayType {
   const HFixedArrayType();
-  bool isFixedArray() => true;
+  bool isFixedArray(Compiler compiler) => true;
   String toString() => "fixed array";
   bool isExact() => true;
 
@@ -535,7 +536,7 @@
 
 class HExtendableArrayType extends HMutableArrayType {
   const HExtendableArrayType();
-  bool isExtendableArray() => true;
+  bool isExtendableArray(Compiler compiler) => true;
   String toString() => "extendable array";
   bool isExact() => true;
 
@@ -587,6 +588,32 @@
         || mask.contains(jsExtendableArrayType, compiler);
   }
 
+  bool isIndexablePrimitive(Compiler compiler) {
+    JavaScriptBackend backend = compiler.backend;
+    return mask.containsOnlyString(compiler)
+        || mask.satisfies(backend.jsIndexableClass, compiler);
+  }
+
+  bool isFixedArray(Compiler compiler) {
+    JavaScriptBackend backend = compiler.backend;
+    return mask.containsOnly(backend.jsFixedArrayClass);
+  }
+
+  bool isExtendableArray(Compiler compiler) {
+    JavaScriptBackend backend = compiler.backend;
+    return mask.containsOnly(backend.jsExtendableArrayClass);
+  }
+
+  bool isMutableArray(Compiler compiler) {
+    JavaScriptBackend backend = compiler.backend;
+    return mask.satisfies(backend.jsMutableArrayClass, compiler);
+  }
+
+  bool isReadableArray(Compiler compiler) {
+    JavaScriptBackend backend = compiler.backend;
+    return mask.satisfies(backend.jsArrayClass, compiler);
+  }
+
   bool canBePrimitiveString(Compiler compiler) {
     JavaScriptBackend backend = compiler.backend;
     DartType jsStringType = backend.jsStringClass.computeType(compiler);
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/types_propagation.dart b/sdk/lib/_internal/compiler/implementation/ssa/types_propagation.dart
index 9e85957..ab3ec41 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/types_propagation.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/types_propagation.dart
@@ -126,18 +126,6 @@
   }
 
   HType visitInvokeDynamic(HInvokeDynamic instruction) {
-    HType receiverType = instruction.getDartReceiver(compiler).instructionType;
-    Selector refined = receiverType.refine(instruction.selector, compiler);
-    HType type = new HType.inferredTypeForSelector(refined, compiler);
-    // TODO(ngeoffray): Because we don't know yet the side effects of
-    // a JS call, we sometimes know more in the compiler about the
-    // side effects of an element (for example operator% on the int
-    // class). We should remove this check once we analyze JS calls.
-    if (!instruction.useGvn()) {
-      instruction.sideEffects =
-          compiler.world.getSideEffectsOfSelector(refined);
-    }
-    if (type.isUseful()) return type;
     return instruction.specializer.computeTypeFromInputTypes(
         instruction, compiler);
   }
diff --git a/sdk/lib/_internal/compiler/implementation/tree/nodes.dart b/sdk/lib/_internal/compiler/implementation/tree/nodes.dart
index a2216cd..9a3c43c 100644
--- a/sdk/lib/_internal/compiler/implementation/tree/nodes.dart
+++ b/sdk/lib/_internal/compiler/implementation/tree/nodes.dart
@@ -702,6 +702,11 @@
 
   accept(Visitor visitor) => visitor.visitFunctionExpression(this);
 
+  bool get isRedirectingFactory {
+    return body != null && body.asReturn() != null &&
+        body.asReturn().isRedirectingFactoryBody;
+  }
+
   visitChildren(Visitor visitor) {
     if (modifiers != null) modifiers.accept(visitor);
     if (returnType != null) returnType.accept(visitor);
diff --git a/sdk/lib/_internal/compiler/implementation/typechecker.dart b/sdk/lib/_internal/compiler/implementation/typechecker.dart
index 6ab80fd..cdd5f8c 100644
--- a/sdk/lib/_internal/compiler/implementation/typechecker.dart
+++ b/sdk/lib/_internal/compiler/implementation/typechecker.dart
@@ -8,11 +8,15 @@
   TypeCheckerTask(Compiler compiler) : super(compiler);
   String get name => "Type checker";
 
-  void check(Node tree, TreeElements elements) {
-    measure(() {
-      Visitor visitor =
-          new TypeCheckerVisitor(compiler, elements, compiler.types);
-      tree.accept(visitor);
+  void check(TreeElements elements) {
+    Element element = elements.currentElement;
+    compiler.withCurrentElement(element, () {
+      measure(() {
+        Node tree = element.parseNode(compiler);
+        Visitor visitor =
+            new TypeCheckerVisitor(compiler, elements, compiler.types);
+        tree.accept(visitor);
+      });
     });
   }
 }
@@ -140,7 +144,7 @@
   String toString() => 'TypeLiteralAccess($element)';
 }
 
-class TypeCheckerVisitor implements Visitor<DartType> {
+class TypeCheckerVisitor extends Visitor<DartType> {
   final Compiler compiler;
   final TreeElements elements;
   final Types types;
@@ -170,6 +174,8 @@
     listType = compiler.listClass.computeType(compiler);
   }
 
+  LibraryElement get currentLibrary => elements.currentElement.getLibrary();
+
   reportTypeWarning(Node node, MessageKind kind, [Map arguments = const {}]) {
     compiler.reportWarning(node, new TypeWarning(kind, arguments));
   }
@@ -260,18 +266,6 @@
     return type;
   }
 
-  DartType visitClassNode(ClassNode node) {
-    compiler.internalError('unexpected node type', node: node);
-  }
-
-  DartType visitMixinApplication(MixinApplication node) {
-    compiler.internalError('unexpected node type', node: node);
-  }
-
-  DartType visitNamedMixinApplication(NamedMixinApplication node) {
-    compiler.internalError('unexpected node type', node: node);
-  }
-
   DartType visitDoWhile(DoWhile node) {
     StatementType bodyType = analyze(node.body);
     checkCondition(node.condition);
@@ -337,8 +331,19 @@
   DartType visitIdentifier(Identifier node) {
     if (node.isThis()) {
       return currentClass.computeType(compiler);
+    } else if (node.isSuper()) {
+      return currentClass.supertype;
     } else {
-      // This is an identifier of a formal parameter.
+      Element element = elements[node];
+      if (element != null) {
+        assert(invariant(node, element.isVariable() || element.isParameter(),
+            message: 'Unexpected context element ${element}'));
+        return element.computeType(compiler);
+      }
+
+      assert(invariant(node, elements.currentElement.isField(),
+          message: 'Unexpected context element ${elements.currentElement}'));
+      // This is an identifier of a field declaration.
       return types.dynamicType;
     }
   }
@@ -351,8 +356,17 @@
     return thenType.join(elseType);
   }
 
-  DartType visitLoop(Loop node) {
-    return unhandledStatement();
+  void checkPrivateAccess(Node node, Element element, SourceString name) {
+    if (name != null &&
+        name.isPrivate() &&
+        element.getLibrary() != currentLibrary) {
+      reportTypeWarning(
+          node,
+          MessageKind.PRIVATE_ACCESS,
+          {'name': name,
+           'libraryName': element.getLibrary().getLibraryOrScriptName()});
+    }
+
   }
 
   ElementAccess lookupMember(Node node, DartType type, SourceString name,
@@ -362,6 +376,7 @@
     }
     Member member = type.lookupMember(name);
     if (member != null) {
+      checkPrivateAccess(node, member.element, name);
       return new MemberAccess(member);
     }
     switch (memberKind) {
@@ -547,12 +562,12 @@
           name, memberKind);
     } else if (element.isFunction()) {
       // foo() where foo is a method in the same class.
-      return new ResolvedAccess(element);
+      return createResolvedAccess(node, name, element);
     } else if (element.isVariable() ||
         element.isParameter() ||
         element.isField()) {
       // foo() where foo is a field in the same class.
-      return new ResolvedAccess(element);
+      return createResolvedAccess(node, name, element);
     } else if (element.impliesType()) {
       // The literal `Foo` where Foo is a class, a typedef, or a type variable.
       if (elements.getType(node) != null) {
@@ -562,15 +577,21 @@
               '${elements.getType(node)}'));
         return new TypeLiteralAccess(element);
       }
-      return new ResolvedAccess(element);
+      return createResolvedAccess(node, name, element);
     } else if (element.isGetter() || element.isSetter()) {
-      return new ResolvedAccess(element);
+      return createResolvedAccess(node, name, element);
     } else {
       compiler.internalErrorOnElement(
           element, 'unexpected element kind ${element.kind}');
     }
   }
 
+  ElementAccess createResolvedAccess(Send node, SourceString name,
+                                     Element element) {
+    checkPrivateAccess(node, element, name);
+    return new ResolvedAccess(element);
+  }
+
   /**
    * Computes the type of the access of [name] on the [node] possibly using the
    * [element] provided for [node] by the resolver.
@@ -896,6 +917,12 @@
 
   DartType visitNewExpression(NewExpression node) {
     Element element = elements[node.send];
+    if (Elements.isUnresolved(element)) return types.dynamicType;
+
+    ClassElement enclosingClass = element.getEnclosingClass();
+    SourceString name = Elements.deconstructConstructorName(
+        element.name, enclosingClass);
+    checkPrivateAccess(node, element, name);
     DartType constructorType = computeType(element);
     DartType newType = elements.getType(node);
     // TODO(johnniwinther): Use [:lookupMember:] to account for type variable
@@ -944,10 +971,6 @@
     return type;
   }
 
-  DartType visitOperator(Operator node) {
-    compiler.internalError('unexpected node type', node: node);
-  }
-
   DartType visitRethrow(Rethrow node) {
     return StatementType.RETURNING;
   }
@@ -991,6 +1014,7 @@
   }
 
   DartType visitThrow(Throw node) {
+    // TODO(johnniwinther): Handle reachability.
     analyze(node.expression);
     return types.dynamicType;
   }
@@ -1006,10 +1030,6 @@
     return elements.getType(node);
   }
 
-  visitTypeVariable(TypeVariable node) {
-    return types.dynamicType;
-  }
-
   DartType visitVariableDefinitions(VariableDefinitions node) {
     DartType type = analyzeWithDefault(node.type, types.dynamicType);
     if (type == types.voidType) {
@@ -1020,7 +1040,7 @@
          link = link.tail) {
       Node definition = link.head;
       compiler.ensure(definition is Identifier || definition is SendSet);
-      if (definition is Send) {
+      if (definition is SendSet) {
         SendSet initialization = definition;
         DartType initializer = analyzeNonVoid(initialization.arguments.head);
         checkAssignable(initialization.assignmentOperator, initializer, type);
@@ -1062,8 +1082,6 @@
     }
   }
 
-  DartType visitModifiers(Modifiers node) {}
-
   visitStringInterpolation(StringInterpolation node) {
     node.visitChildren(this);
     return stringType;
@@ -1092,10 +1110,8 @@
     return bodyType.join(StatementType.NOT_RETURNING);
   }
 
-  visitLabel(Label node) { }
-
   visitLabeledStatement(LabeledStatement node) {
-    return node.statement.accept(this);
+    return analyze(node.statement);
   }
 
   visitLiteralMap(LiteralMap node) {
@@ -1114,10 +1130,6 @@
     return mapType;
   }
 
-  visitLiteralMapEntry(LiteralMapEntry node) {
-    return unhandledExpression();
-  }
-
   visitNamedArgument(NamedArgument node) {
     // Named arguments are visited as part of analyzing invocations of
     // unresolved methods. For instance [: foo(a: 42); :] where 'foo' is neither
@@ -1128,15 +1140,25 @@
   }
 
   visitSwitchStatement(SwitchStatement node) {
-    return unhandledStatement();
+    // TODO(johnniwinther): Handle reachability based on reachability of
+    // switch cases.
+    // TODO(johnniwinther): Check assignability to constants.
+    DartType expressionType = analyze(node.expression);
+    for (SwitchCase switchCase in node.cases) {
+      for (Node labelOrCase in switchCase.labelsAndCases) {
+        CaseMatch caseMatch = labelOrCase.asCaseMatch();
+        if (caseMatch == null) continue;
+
+        DartType caseType = analyze(caseMatch.expression);
+        checkAssignable(caseMatch, expressionType, caseType);
+      }
+      analyze(switchCase);
+    }
+    return StatementType.NOT_RETURNING;
   }
 
   visitSwitchCase(SwitchCase node) {
-    return unhandledStatement();
-  }
-
-  visitCaseMatch(CaseMatch node) {
-    return unhandledStatement();
+    return analyze(node.statements);
   }
 
   visitTryStatement(TryStatement node) {
@@ -1151,79 +1173,17 @@
     return StatementType.NOT_RETURNING;
   }
 
-  visitScriptTag(ScriptTag node) {
-    return unhandledExpression();
-  }
-
   visitCatchBlock(CatchBlock node) {
     return analyze(node.block);
   }
 
   visitTypedef(Typedef node) {
-    return unhandledStatement();
+    // Do not typecheck [Typedef] nodes.
   }
 
-  DartType visitNode(Node node) {
-    compiler.unimplemented('visitNode', node: node);
-  }
-
-  DartType visitCombinator(Combinator node) {
-    compiler.unimplemented('visitNode', node: node);
-  }
-
-  DartType visitExport(Export node) {
-    compiler.unimplemented('visitNode', node: node);
-  }
-
-  DartType visitExpression(Expression node) {
-    compiler.unimplemented('visitNode', node: node);
-  }
-
-  DartType visitGotoStatement(GotoStatement node) {
-    compiler.unimplemented('visitNode', node: node);
-  }
-
-  DartType visitImport(Import node) {
-    compiler.unimplemented('visitNode', node: node);
-  }
-
-  DartType visitLibraryName(LibraryName node) {
-    compiler.unimplemented('visitNode', node: node);
-  }
-
-  DartType visitLibraryTag(LibraryTag node) {
-    compiler.unimplemented('visitNode', node: node);
-  }
-
-  DartType visitLiteral(Literal node) {
-    compiler.unimplemented('visitNode', node: node);
-  }
-
-  DartType visitPart(Part node) {
-    compiler.unimplemented('visitNode', node: node);
-  }
-
-  DartType visitPartOf(PartOf node) {
-    compiler.unimplemented('visitNode', node: node);
-  }
-
-  DartType visitPostfix(Postfix node) {
-    compiler.unimplemented('visitNode', node: node);
-  }
-
-  DartType visitPrefix(Prefix node) {
-    compiler.unimplemented('visitNode', node: node);
-  }
-
-  DartType visitStatement(Statement node) {
-    compiler.unimplemented('visitNode', node: node);
-  }
-
-  DartType visitStringNode(StringNode node) {
-    compiler.unimplemented('visitNode', node: node);
-  }
-
-  DartType visitLibraryDependency(LibraryDependency node) {
-    compiler.unimplemented('visitNode', node: node);
+  visitNode(Node node) {
+    compiler.internalError(
+        'Unexpected node ${node.getObjectDescription()} in the type checker.',
+        node: node);
   }
 }
diff --git a/sdk/lib/_internal/compiler/implementation/types/simple_types_inferrer.dart b/sdk/lib/_internal/compiler/implementation/types/simple_types_inferrer.dart
index 9241edc..accc506 100644
--- a/sdk/lib/_internal/compiler/implementation/types/simple_types_inferrer.dart
+++ b/sdk/lib/_internal/compiler/implementation/types/simple_types_inferrer.dart
@@ -2053,7 +2053,8 @@
       sideEffects.add(nativeBehavior.sideEffects);
       return inferrer.typeOfNativeBehavior(nativeBehavior);
     } else if (name == const SourceString('JS_OPERATOR_IS_PREFIX')
-               || name == const SourceString('JS_OPERATOR_AS_PREFIX')) {
+               || name == const SourceString('JS_OPERATOR_AS_PREFIX')
+               || name == const SourceString('JS_OBJECT_CLASS_NAME')) {
       return inferrer.stringType;
     } else {
       sideEffects.setAllSideEffects();
diff --git a/sdk/lib/_internal/compiler/implementation/warnings.dart b/sdk/lib/_internal/compiler/implementation/warnings.dart
index c609c17..97b7cfa 100644
--- a/sdk/lib/_internal/compiler/implementation/warnings.dart
+++ b/sdk/lib/_internal/compiler/implementation/warnings.dart
@@ -38,6 +38,9 @@
       '#{className}.#{memberName} is not static');
   static const NO_INSTANCE_AVAILABLE = const MessageKind(
       '#{name} is only available in instance methods');
+  static const PRIVATE_ACCESS = const MessageKind(
+      "'#{name}' is declared private within library #{libraryName} and "
+      "is therefore not accessible.");
 
   static const THIS_IS_THE_METHOD = const MessageKind(
       "This is the method declaration.");
@@ -327,6 +330,9 @@
   static const ILLEGAL_MIXIN_SUPERCLASS = const MessageKind(
       "Error: class used as mixin must have Object as superclass.");
 
+  static const ILLEGAL_MIXIN_OBJECT = const MessageKind(
+      "Error: cannot use Object as mixin.");
+
   static const ILLEGAL_MIXIN_CONSTRUCTOR = const MessageKind(
       "Error: class used as mixin cannot have non-factory constructor.");
 
diff --git a/sdk/lib/_internal/libraries.dart b/sdk/lib/_internal/libraries.dart
index 2e8efef..5c20d17 100644
--- a/sdk/lib/_internal/libraries.dart
+++ b/sdk/lib/_internal/libraries.dart
@@ -146,6 +146,12 @@
       category: "Internal",
       documented: false,
       platforms: DART2JS_PLATFORM),
+
+  "_js_mirrors": const LibraryInfo(
+      "_internal/compiler/implementation/lib/js_mirrors.dart",
+      category: "Internal",
+      documented: false,
+      platforms: DART2JS_PLATFORM),
 };
 
 /**
diff --git a/sdk/lib/_internal/pub/lib/src/error_group.dart b/sdk/lib/_internal/pub/lib/src/error_group.dart
index a6f9e86..51fb27d 100644
--- a/sdk/lib/_internal/pub/lib/src/error_group.dart
+++ b/sdk/lib/_internal/pub/lib/src/error_group.dart
@@ -239,7 +239,7 @@
   /// Creates a new [_ErrorGroupFuture] that's a child of [_group] and wraps
   /// [inner].
   _ErrorGroupStream(this._group, Stream inner)
-    : _controller = new StreamController() {
+    : _controller = new StreamController(sync: true) {
     this._stream = inner.isBroadcast
         ? _controller.stream.asBroadcastStream()
         : _controller.stream;
diff --git a/sdk/lib/_internal/pub/lib/src/io.dart b/sdk/lib/_internal/pub/lib/src/io.dart
index e9a1316..e9d803b 100644
--- a/sdk/lib/_internal/pub/lib/src/io.dart
+++ b/sdk/lib/_internal/pub/lib/src/io.dart
@@ -422,7 +422,7 @@
 /// will succeed when [EventSink] is closed or fail with any errors that occur
 /// while writing.
 Pair<EventSink, Future> consumerToSink(StreamConsumer consumer) {
-  var controller = new StreamController();
+  var controller = new StreamController(sync: true);
   var done = controller.stream.pipe(consumer);
   return new Pair<EventSink, Future>(controller.sink, done);
 }
@@ -739,7 +739,7 @@
   contents.forEach((file) => buffer.write('$file\n'));
   log.fine(buffer.toString());
 
-  var controller = new StreamController<List<int>>();
+  var controller = new StreamController<List<int>>(sync: true);
 
   if (baseDir == null) baseDir = path.current;
   baseDir = path.absolute(baseDir);
diff --git a/sdk/lib/_internal/pub/lib/src/safe_http_server.dart b/sdk/lib/_internal/pub/lib/src/safe_http_server.dart
index c9885f1..a580770b 100644
--- a/sdk/lib/_internal/pub/lib/src/safe_http_server.dart
+++ b/sdk/lib/_internal/pub/lib/src/safe_http_server.dart
@@ -76,7 +76,6 @@
   int get contentLength => _inner.contentLength;
   String get method => _inner.method;
   Uri get uri => _inner.uri;
-  Map<String, String> get queryParameters => _inner.queryParameters;
   HttpHeaders get headers => _inner.headers;
   List<Cookie> get cookies => _inner.cookies;
   bool get persistentConnection => _inner.persistentConnection;
diff --git a/sdk/lib/_internal/pub/lib/src/utils.dart b/sdk/lib/_internal/pub/lib/src/utils.dart
index b3ae863..aceec1c 100644
--- a/sdk/lib/_internal/pub/lib/src/utils.dart
+++ b/sdk/lib/_internal/pub/lib/src/utils.dart
@@ -183,7 +183,7 @@
 /// Returns a wrapped version of [stream] along with a [StreamSubscription] that
 /// can be used to control the wrapped stream.
 Pair<Stream, StreamSubscription> streamWithSubscription(Stream stream) {
-  var controller = new StreamController();
+  var controller = new StreamController(sync: true);
   var controllerStream = stream.isBroadcast ?
       controller.stream.asBroadcastStream() :
       controller.stream;
@@ -198,8 +198,8 @@
 /// errors from [stream]. This is useful if [stream] is single-subscription but
 /// multiple subscribers are necessary.
 Pair<Stream, Stream> tee(Stream stream) {
-  var controller1 = new StreamController();
-  var controller2 = new StreamController();
+  var controller1 = new StreamController(sync: true);
+  var controller2 = new StreamController(sync: true);
   stream.listen((value) {
     controller1.add(value);
     controller2.add(value);
@@ -217,7 +217,7 @@
 /// both sources.
 Stream mergeStreams(Stream stream1, Stream stream2) {
   var doneCount = 0;
-  var controller = new StreamController();
+  var controller = new StreamController(sync: true);
 
   for (var stream in [stream1, stream2]) {
     stream.listen((value) {
diff --git a/sdk/lib/_internal/pub/test/error_group_test.dart b/sdk/lib/_internal/pub/test/error_group_test.dart
index d22f12c..7cad9be 100644
--- a/sdk/lib/_internal/pub/test/error_group_test.dart
+++ b/sdk/lib/_internal/pub/test/error_group_test.dart
@@ -38,7 +38,8 @@
 
       expect(() => errorGroup.registerFuture(new Future.value()),
           throwsStateError);
-      expect(() => errorGroup.registerStream(new StreamController().stream),
+      expect(() => errorGroup.registerStream(
+          new StreamController(sync: true).stream),
           throwsStateError);
     });
   });
@@ -66,7 +67,8 @@
       completer.future.then(expectAsync1((_) {
         expect(() => errorGroup.registerFuture(new Future.value()),
             throwsStateError);
-        expect(() => errorGroup.registerStream(new StreamController().stream),
+        expect(() => errorGroup.registerStream(
+            new StreamController(sync: true).stream),
             throwsStateError);
       }));
     });
@@ -205,7 +207,7 @@
 
     setUp(() {
       errorGroup = new ErrorGroup();
-      controller = new StreamController();
+      controller = new StreamController(sync: true);
       stream = errorGroup.registerStream(controller.stream.asBroadcastStream());
     });
 
@@ -277,7 +279,7 @@
 
     setUp(() {
       errorGroup = new ErrorGroup();
-      controller = new StreamController();
+      controller = new StreamController(sync: true);
       stream = errorGroup.registerStream(controller.stream);
     });
 
@@ -326,8 +328,8 @@
 
     setUp(() {
       errorGroup = new ErrorGroup();
-      controller1 = new StreamController();
-      controller2 = new StreamController();
+      controller1 = new StreamController(sync: true);
+      controller2 = new StreamController(sync: true);
       stream1 = errorGroup.registerStream(controller1.stream.asBroadcastStream());
       stream2 = errorGroup.registerStream(controller2.stream.asBroadcastStream());
     });
@@ -385,7 +387,7 @@
 
     setUp(() {
       errorGroup = new ErrorGroup();
-      controller = new StreamController();
+      controller = new StreamController(sync: true);
       stream = errorGroup.registerStream(controller.stream.asBroadcastStream());
       completer = new Completer();
       future = errorGroup.registerFuture(completer.future);
diff --git a/sdk/lib/async/stream.dart b/sdk/lib/async/stream.dart
index 07378b5..43697ec 100644
--- a/sdk/lib/async/stream.dart
+++ b/sdk/lib/async/stream.dart
@@ -62,7 +62,7 @@
    * data or error, and then close with a done-event.
    */
   factory Stream.fromFuture(Future<T> future) {
-    StreamController<T> controller = new StreamController<T>();
+    StreamController<T> controller = new StreamController<T>(sync: true);
     future.then((value) {
         controller.add(value);
         controller.close();
@@ -114,7 +114,7 @@
       });
     }
 
-    controller = new StreamController<T>(
+    controller = new StreamController<T>(sync: true,
         onListen: () {
           watch.start();
           startPeriodicTimer();
diff --git a/sdk/lib/async/stream_controller.dart b/sdk/lib/async/stream_controller.dart
index b057565..abfd648 100644
--- a/sdk/lib/async/stream_controller.dart
+++ b/sdk/lib/async/stream_controller.dart
@@ -53,6 +53,11 @@
   /**
    * A controller with a [stream] that supports only one single subscriber.
    *
+   * If [sync] is true, events may be passed directly to the stream's listener
+   * during an [add], [addError] or [close] call. If [sync] is false, the event
+   * will be passed to the listener at a later time, after the code creating
+   * the event has returned.
+   *
    * The controller will buffer all incoming events until the subscriber is
    * registered.
    *
@@ -69,8 +74,11 @@
   factory StreamController({void onListen(),
                             void onPause(),
                             void onResume(),
-                            void onCancel()})
-      => new _StreamControllerImpl<T>(onListen, onPause, onResume, onCancel);
+                            void onCancel(),
+                            bool sync: false})
+      => sync
+         ? new _SyncStreamController<T>(onListen, onPause, onResume, onCancel)
+         : new _AsyncStreamController<T>(onListen, onPause, onResume, onCancel);
 
   /**
    * A controller where [stream] can be listened to more than once.
@@ -83,17 +91,35 @@
    * It is not allowed to call [add], [addError], or [close] before a previous
    * call has returned.
    *
+   * If [sync] is true, events may be passed directly to the stream's listener
+   * during an [add], [addError] or [close] call. If [sync] is false, the event
+   * will be passed to the listener at a later time, after the code creating
+   * the event has returned.
+   *
    * Each listener is handled independently, and if they pause, only the pausing
    * listener is affected. A paused listener will buffer events internally until
    * unpaused or canceled.
    *
+   * If [sync] is false, no guarantees are given with regard to when
+   * multiple listeners get the events, except that each listener will get
+   * all events in the correct order. If two events are sent on an async
+   * controller with two listeners, one of the listeners may get both events
+   * before the other listener gets any.
+   * A listener must be subscribed both when the event is initiated (that is,
+   * when [add] is called) and when the event is later delivered, in order to
+   * get the event.
+   *
    * The [onListen] callback is called when the first listener is subscribed,
    * and the [onCancel] is called when there are no longer any active listeners.
    * If a listener is added again later, after the [onCancel] was called,
    * the [onListen] will be called again.
    */
-  factory StreamController.broadcast({void onListen(), void onCancel()}) {
-    return new _MultiplexStreamController<T>(onListen, onCancel);
+  factory StreamController.broadcast({void onListen(),
+                                      void onCancel(),
+                                      bool sync: false}) {
+    return sync
+        ? new _SyncBroadcastStreamController<T>(onListen, onCancel)
+        : new _AsyncBroadcastStreamController<T>(onListen, onCancel);
   }
 
   /**
@@ -147,8 +173,9 @@
  *
  * Controls a stream that only supports a single controller.
  */
-class _StreamControllerImpl<T> implements StreamController<T>,
-                                          _StreamControllerLifecycle<T> {
+abstract class _StreamController<T> implements StreamController<T>,
+                                               _StreamControllerLifecycle<T>,
+                                               _EventDispatch<T> {
   static const int _STATE_OPEN = 0;
   static const int _STATE_CANCELLED = 1;
   static const int _STATE_CLOSED = 2;
@@ -168,10 +195,10 @@
   // Events added to the stream before it has an active subscription.
   _PendingEvents _pendingEvents = null;
 
-  _StreamControllerImpl(this._onListen,
-                        this._onPause,
-                        this._onResume,
-                        this._onCancel) {
+  _StreamController(this._onListen,
+                    this._onPause,
+                    this._onResume,
+                    this._onCancel) {
     _stream = new _ControllerStream<T>(this);
   }
 
@@ -202,7 +229,7 @@
   void add(T value) {
     if (isClosed) throw new StateError("Adding event after close");
     if (_subscription != null) {
-      _subscription._add(value);
+      _sendData(value);
     } else if (!_isCancelled) {
       _addPendingEvent(new _DelayedData<T>(value));
     }
@@ -219,7 +246,7 @@
       _attachStackTrace(error, stackTrace);
     }
     if (_subscription != null) {
-      _subscription._addError(error);
+      _sendError(error);
     } else if (!_isCancelled) {
       _addPendingEvent(new _DelayedError(error));
     }
@@ -240,12 +267,14 @@
     if (isClosed) return;
     _state |= _STATE_CLOSED;
     if (_subscription != null) {
-      _subscription._close();
+      _sendDone();
     } else if (!_isCancelled) {
       _addPendingEvent(const _DelayedDone());
     }
   }
 
+  // EventDispatch interface
+
   void _addPendingEvent(_DelayedEvent event) {
     if (_isCancelled) return;
     _StreamImplEvents events = _pendingEvents;
@@ -281,6 +310,46 @@
   }
 }
 
+class _SyncStreamController<T> extends _StreamController<T> {
+  _SyncStreamController(void onListen(),
+                        void onPause(),
+                        void onResume(),
+                        void onCancel())
+      : super(onListen, onPause, onResume, onCancel);
+
+  void _sendData(T data) {
+    _subscription._add(data);
+  }
+
+  void _sendError(Object error) {
+    _subscription._addError(error);
+  }
+
+  void _sendDone() {
+    _subscription._close();
+  }
+}
+
+class _AsyncStreamController<T> extends _StreamController<T> {
+  _AsyncStreamController(void onListen(),
+                         void onPause(),
+                         void onResume(),
+                         void onCancel())
+      : super(onListen, onPause, onResume, onCancel);
+
+  void _sendData(T data) {
+    _subscription._addPending(new _DelayedData(data));
+  }
+
+  void _sendError(Object error) {
+    _subscription._addPending(new _DelayedError(error));
+  }
+
+  void _sendDone() {
+    _subscription._addPending(const _DelayedDone());
+  }
+}
+
 typedef void _NotificationHandler();
 
 void _runGuarded(_NotificationHandler notificationHandler) {
@@ -339,10 +408,10 @@
   }
 }
 
-class _MultiplexStream<T> extends _StreamImpl<T> {
-  _MultiplexStreamController _controller;
+class _BroadcastStream<T> extends _StreamImpl<T> {
+  _BroadcastStreamController _controller;
 
-  _MultiplexStream(this._controller);
+  _BroadcastStream(this._controller);
 
   bool get isBroadcast => true;
 
@@ -351,7 +420,7 @@
       void onError(Object error),
       void onDone(),
       bool cancelOnError) {
-    return new _MultiplexSubscription<T>(
+    return new _BroadcastSubscription<T>(
         _controller, onData, onError, onDone, cancelOnError);
   }
 
@@ -360,22 +429,22 @@
   }
 }
 
-abstract class _MultiplexSubscriptionLink {
-  _MultiplexSubscriptionLink _next;
-  _MultiplexSubscriptionLink _previous;
+abstract class _BroadcastSubscriptionLink {
+  _BroadcastSubscriptionLink _next;
+  _BroadcastSubscriptionLink _previous;
 }
 
-class _MultiplexSubscription<T> extends _ControllerSubscription<T>
-                                implements _MultiplexSubscriptionLink {
+class _BroadcastSubscription<T> extends _ControllerSubscription<T>
+                                implements _BroadcastSubscriptionLink {
   static const int _STATE_EVENT_ID = 1;
   static const int _STATE_FIRING = 2;
   static const int _STATE_REMOVE_AFTER_FIRING = 4;
   int _eventState;
 
-  _MultiplexSubscriptionLink _next;
-  _MultiplexSubscriptionLink _previous;
+  _BroadcastSubscriptionLink _next;
+  _BroadcastSubscriptionLink _previous;
 
-  _MultiplexSubscription(_StreamControllerLifecycle controller,
+  _BroadcastSubscription(_StreamControllerLifecycle controller,
                          void onData(T data),
                          void onError(Object error),
                          void onDone(),
@@ -384,7 +453,7 @@
     _next = _previous = this;
   }
 
-  _MultiplexStreamController get _controller => super._controller;
+  _BroadcastStreamController get _controller => super._controller;
 
   bool _expectsEvent(int eventId) {
     return (_eventState & _STATE_EVENT_ID) == eventId;
@@ -406,9 +475,11 @@
 }
 
 
-class _MultiplexStreamController<T> implements StreamController<T>,
-                                               _StreamControllerLifecycle<T>,
-                                               _MultiplexSubscriptionLink {
+abstract class _BroadcastStreamController<T>
+    implements StreamController<T>,
+               _StreamControllerLifecycle<T>,
+               _BroadcastSubscriptionLink,
+               _EventDispatch<T> {
   static const int _STATE_INITIAL = 0;
   static const int _STATE_EVENT_ID = 1;
   static const int _STATE_FIRING = 2;
@@ -421,24 +492,24 @@
   int _state;
 
   // Double-linked list of active listeners.
-  _MultiplexSubscriptionLink _next;
-  _MultiplexSubscriptionLink _previous;
+  _BroadcastSubscriptionLink _next;
+  _BroadcastSubscriptionLink _previous;
 
-  _MultiplexStreamController(this._onListen, this._onCancel)
+  _BroadcastStreamController(this._onListen, this._onCancel)
       : _state = _STATE_INITIAL {
     _next = _previous = this;
   }
 
   // StreamController interface.
 
-  Stream<T> get stream => new _MultiplexStream<T>(this);
+  Stream<T> get stream => new _BroadcastStream<T>(this);
 
   EventSink<T> get sink => new _EventSinkView<T>(this);
 
   bool get isClosed => (_state & _STATE_CLOSED) != 0;
 
   /**
-   * A multiplex controller is never paused.
+   * A broadcast controller is never paused.
    *
    * Each receiving stream may be paused individually, and they handle their
    * own buffering.
@@ -456,8 +527,8 @@
   bool get _isEmpty => identical(_next, this);
 
   /** Adds subscription to linked list of active listeners. */
-  void _addListener(_MultiplexSubscription<T> subscription) {
-    _MultiplexSubscriptionLink previous = _previous;
+  void _addListener(_BroadcastSubscription<T> subscription) {
+    _BroadcastSubscriptionLink previous = _previous;
     previous._next = subscription;
     _previous = subscription._previous;
     subscription._previous._next = this;
@@ -465,7 +536,7 @@
     subscription._eventState = (_state & _STATE_EVENT_ID);
   }
 
-  void _removeListener(_MultiplexSubscription<T> subscription) {
+  void _removeListener(_BroadcastSubscription<T> subscription) {
     assert(identical(subscription._controller, this));
     assert(!identical(subscription._next, subscription));
     subscription._previous._next = subscription._next;
@@ -475,7 +546,7 @@
 
   // _StreamControllerLifecycle interface.
 
-  void _recordListen(_MultiplexSubscription<T> subscription) {
+  void _recordListen(_BroadcastSubscription<T> subscription) {
     _addListener(subscription);
     if (identical(_next, _previous)) {
       // Only one listener, so it must be the first listener.
@@ -483,7 +554,7 @@
     }
   }
 
-  void _recordCancel(_MultiplexSubscription<T> subscription) {
+  void _recordCancel(_BroadcastSubscription<T> subscription) {
     if (subscription._isFiring) {
       subscription._setRemoveAfterFiring();
     } else {
@@ -524,6 +595,55 @@
     _sendDone();
   }
 
+  void _forEachListener(
+      void action(_BufferingStreamSubscription<T> subscription)) {
+    if (_isFiring) {
+      throw new StateError(
+          "Cannot fire new event. Controller is already firing an event");
+    }
+    if (_isEmpty) return;
+
+    // Get event id of this event.
+    int id = (_state & _STATE_EVENT_ID);
+    // Start firing (set the _STATE_FIRING bit). We don't do [_onCancel]
+    // callbacks while firing, and we prevent reentrancy of this function.
+    //
+    // Set [_state]'s event id to the next event's id.
+    // Any listeners added while firing this event will expect the next event,
+    // not this one, and won't get notified.
+    _state ^= _STATE_EVENT_ID | _STATE_FIRING;
+    _BroadcastSubscriptionLink link = _next;
+    while (!identical(link, this)) {
+      _BroadcastSubscription<T> subscription = link;
+      if (subscription._expectsEvent(id)) {
+        subscription._eventState |= _BroadcastSubscription._STATE_FIRING;
+        action(subscription);
+        subscription._toggleEventId();
+        link = subscription._next;
+        if (subscription._removeAfterFiring) {
+          _removeListener(subscription);
+        }
+        subscription._eventState &= ~_BroadcastSubscription._STATE_FIRING;
+      } else {
+        link = subscription._next;
+      }
+    }
+    _state &= ~_STATE_FIRING;
+
+    if (_isEmpty) {
+      _callOnCancel();
+    }
+  }
+
+  void _callOnCancel() {
+    _runGuarded(_onCancel);
+  }
+}
+
+class _SyncBroadcastStreamController<T> extends _BroadcastStreamController<T> {
+  _SyncBroadcastStreamController(void onListen(), void onCancel())
+      : super(onListen, onCancel);
+
   // EventDispatch interface.
 
   void _sendData(T data) {
@@ -542,64 +662,65 @@
 
   void _sendDone() {
     if (_isEmpty) return;
-    _forEachListener((_MultiplexSubscription<T> subscription) {
+    _forEachListener((_BroadcastSubscription<T> subscription) {
       subscription._close();
       subscription._eventState |=
-          _MultiplexSubscription._STATE_REMOVE_AFTER_FIRING;
+          _BroadcastSubscription._STATE_REMOVE_AFTER_FIRING;
     });
   }
-
-  void _forEachListener(
-      void action(_BufferingStreamSubscription<T> subscription)) {
-    if (_isFiring) {
-      throw new StateError(
-          "Cannot fire new event. Controller is already firing an event");
-    }
-    if (_isEmpty) return;
-
-    // Get event id of this event.
-    int id = (_state & _STATE_EVENT_ID);
-    // Start firing (set the _STATE_FIRING bit). We don't do [_onCancel]
-    // callbacks while firing, and we prevent reentrancy of this function.
-    //
-    // Set [_state]'s event id to the next event's id.
-    // Any listeners added while firing this event will expect the next event,
-    // not this one, and won't get notified.
-    _state ^= _STATE_EVENT_ID | _STATE_FIRING;
-    _MultiplexSubscriptionLink link = _next;
-    while (!identical(link, this)) {
-      _MultiplexSubscription<T> subscription = link;
-      if (subscription._expectsEvent(id)) {
-        subscription._eventState |= _MultiplexSubscription._STATE_FIRING;
-        action(subscription);
-        subscription._toggleEventId();
-        link = subscription._next;
-        if (subscription._removeAfterFiring) {
-          _removeListener(subscription);
-        }
-        subscription._eventState &= ~_MultiplexSubscription._STATE_FIRING;
-      } else {
-        link = subscription._next;
-      }
-    }
-    _state &= ~_STATE_FIRING;
-
-    if (_isEmpty) {
-      _callOnCancel();
-    }
-  }
-
-  void _callOnCancel() {
-    _runGuarded(_onCancel);
-  }
 }
 
-class _BufferingMultiplexStreamController<T>
-    extends _MultiplexStreamController<T>
+class _AsyncBroadcastStreamController<T> extends _BroadcastStreamController<T> {
+  _AsyncBroadcastStreamController(void onListen(), void onCancel())
+      : super(onListen, onCancel);
+
+  // EventDispatch interface.
+
+  void _sendData(T data) {
+    for (_BroadcastSubscriptionLink link = _next;
+         !identical(link, this);
+         link = link._next) {
+      _BroadcastSubscription<T> subscription = link;
+      subscription._addPending(new _DelayedData(data));
+    }
+  }
+
+  void _sendError(Object error) {
+    for (_BroadcastSubscriptionLink link = _next;
+         !identical(link, this);
+         link = link._next) {
+      _BroadcastSubscription<T> subscription = link;
+      subscription._addPending(new _DelayedError(error));
+    }
+  }
+
+  void _sendDone() {
+    for (_BroadcastSubscriptionLink link = _next;
+         !identical(link, this);
+         link = link._next) {
+      _BroadcastSubscription<T> subscription = link;
+      subscription._addPending(const _DelayedDone());
+    }
+  }
+}
+
+/**
+ * Stream controller that is used by [Stream.asBroadcastStream].
+ *
+ * This stream controller allows incoming events while it is firing
+ * other events. This is handled by delaying the events until the
+ * current event is done firing, and then fire the pending events.
+ *
+ * This class extends [_SyncBroadcastStreamController]. Events of
+ * an "asBroadcastStream" stream are always initiated by events
+ * on another stream, and it is fine to forward them synchronously.
+ */
+class _AsBroadcastStreamController<T>
+    extends _SyncBroadcastStreamController<T>
     implements _EventDispatch<T> {
   _StreamImplEvents _pending;
 
-  _BufferingMultiplexStreamController(void onListen(), void onCancel())
+  _AsBroadcastStreamController(void onListen(), void onCancel())
       : super(onListen, onCancel);
 
   bool get _hasPending => _pending != null && ! _pending.isEmpty;
@@ -649,6 +770,5 @@
       _pending = null;
     }
     super._callOnCancel();
-
   }
 }
diff --git a/sdk/lib/async/stream_impl.dart b/sdk/lib/async/stream_impl.dart
index 375844c..e46ba50 100644
--- a/sdk/lib/async/stream_impl.dart
+++ b/sdk/lib/async/stream_impl.dart
@@ -694,9 +694,9 @@
   }
 }
 
-class _MultiplexerLinkedList {
-  _MultiplexerLinkedList _next;
-  _MultiplexerLinkedList _previous;
+class _BroadcastLinkedList {
+  _BroadcastLinkedList _next;
+  _BroadcastLinkedList _previous;
 
   void _unlink() {
     _previous._next = _next;
@@ -704,8 +704,8 @@
     _next = _previous = this;
   }
 
-  void _insertBefore(_MultiplexerLinkedList newNext) {
-    _MultiplexerLinkedList newPrevious = newNext._previous;
+  void _insertBefore(_BroadcastLinkedList newNext) {
+    _BroadcastLinkedList newPrevious = newNext._previous;
     newPrevious._next = this;
     newNext._previous = _previous;
     _previous._next = newNext;
@@ -715,11 +715,11 @@
 
 class _AsBroadcastStream<T> extends Stream<T> {
   final Stream<T> _source;
-  _BufferingMultiplexStreamController<T> _controller;
+  _AsBroadcastStreamController<T> _controller;
   StreamSubscription<T> _subscription;
 
   _AsBroadcastStream(this._source) {
-    _controller = new _BufferingMultiplexStreamController<T>(null, _onCancel);
+    _controller = new _AsBroadcastStreamController<T>(null, _onCancel);
   }
 
   bool get isBroadcast => true;
diff --git a/sdk/lib/core/iterable.dart b/sdk/lib/core/iterable.dart
index 03127c8..41972b9 100644
--- a/sdk/lib/core/iterable.dart
+++ b/sdk/lib/core/iterable.dart
@@ -198,13 +198,13 @@
    * Returns an [Iterable] that skips elements while [test] is satisfied.
    *
    * The filtering happens lazily. Every new [Iterator] of the returned
-   * [Iterable] will iterate over all elements of `this`.
+   * [Iterable] iterates over all elements of `this`.
    *
-   * As long as the iterator's elements do not satisfy [test] they are
-   * discarded. Once an element satisfies the [test] the iterator stops testing
-   * and uses every element unconditionally. That is, the elements of the
-   * returned [Iterable] are the elements of `this` starting from the first
-   * element that doesn't satisfy [test].
+   * As long as the iterator's elements satisfy [test] they are
+   * discarded. Once an element does not satisfy the [test] the iterator stops
+   * testing and uses every later element unconditionally. That is, the elements
+   * of the returned [Iterable] are the elements of `this` starting from the
+   * first element that does not satisfy [test].
    */
   Iterable<E> skipWhile(bool test(E value));
 
diff --git a/sdk/lib/html/dart2js/html_dart2js.dart b/sdk/lib/html/dart2js/html_dart2js.dart
index 021a3ca..084abb2 100644
--- a/sdk/lib/html/dart2js/html_dart2js.dart
+++ b/sdk/lib/html/dart2js/html_dart2js.dart
@@ -249,7 +249,7 @@
 
   @DomName('DOMApplicationCache.progressEvent')
   @DocsEditable
-  static const EventStreamProvider<Event> progressEvent = const EventStreamProvider<Event>('progress');
+  static const EventStreamProvider<ProgressEvent> progressEvent = const EventStreamProvider<ProgressEvent>('progress');
 
   @DomName('DOMApplicationCache.updatereadyEvent')
   @DocsEditable
@@ -338,7 +338,7 @@
 
   @DomName('DOMApplicationCache.onprogress')
   @DocsEditable
-  Stream<Event> get onProgress => progressEvent.forTarget(this);
+  Stream<ProgressEvent> get onProgress => progressEvent.forTarget(this);
 
   @DomName('DOMApplicationCache.onupdateready')
   @DocsEditable
@@ -427,15 +427,6 @@
 
 
 @DocsEditable
-@DomName('Attr')
-class Attr extends Node native "Attr" {
-}
-// 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.
-
-
-@DocsEditable
 @DomName('HTMLAudioElement')
 class AudioElement extends MediaElement native "HTMLAudioElement" {
 
@@ -5573,7 +5564,7 @@
 @DocsEditable
 @DomName('CustomElementConstructor')
 // https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/custom/index.html#dfn-custom-element-constructor-generation
-@Experimental
+@deprecated // experimental
 class CustomElementConstructor native "CustomElementConstructor" {
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -7251,6 +7242,24 @@
     throw new UnsupportedError('Cannot sort element lists');
   }
 
+  void removeWhere(bool test(Element element)) {
+    _filter(test, false);
+  }
+
+  void retainWhere(bool test(Element element)) {
+    _filter(test, true);
+  }
+
+  void _filter(bool test(var element), bool retainMatching) {
+    var removed;
+    if (retainMatching) {
+      removed = _element.children.where((e) => !test(e));
+    } else {
+      removed = _element.children.where(test);
+    }
+    for (var e in removed) e.remove();
+  }
+
   void setRange(int start, int end, Iterable<Element> iterable,
                 [int skipCount = 0]) {
     throw new UnimplementedError();
@@ -7642,6 +7651,16 @@
     _xtag = value;
   }
 
+  @DomName('Element.localName')
+  @DocsEditable
+  String get localName => $dom_localName;
+
+  @DomName('Element.namespaceUri')
+  @DocsEditable
+  String get namespaceUri => $dom_namespaceUri;
+
+  String toString() => localName;
+
   /**
    * Scrolls this element into view.
    *
@@ -7696,7 +7715,7 @@
     }
   }
 
-  @DomName('Element.webkitTransitionEndEvent')
+  @DomName('Element.transitionEndEvent')
   static const EventStreamProvider<TransitionEvent> transitionEndEvent =
       const _CustomEventStreamProvider<TransitionEvent>(
         Element._determineTransitionEventType);
@@ -8854,13 +8873,12 @@
   @Experimental
   Stream<TouchEvent> get onTouchStart => touchStartEvent.forTarget(this);
 
-  @DomName('Element.onwebkitTransitionEnd')
+  @DomName('Element.ontransitionend')
   @DocsEditable
   @SupportedBrowser(SupportedBrowser.CHROME)
   @SupportedBrowser(SupportedBrowser.FIREFOX)
   @SupportedBrowser(SupportedBrowser.IE, '10')
   @SupportedBrowser(SupportedBrowser.SAFARI)
-  @deprecated
   Stream<TransitionEvent> get onTransitionEnd => transitionEndEvent.forTarget(this);
 
   @DomName('Element.onwebkitfullscreenchange')
@@ -10630,7 +10648,7 @@
 
     int watchId;
     var controller;
-    controller = new StreamController<Geoposition>(
+    controller = new StreamController<Geoposition>(sync: true,
       onListen: () {
         assert(watchId == null);
         watchId = $dom_watchPosition(
@@ -15810,14 +15828,15 @@
    */
   Node insertAllBefore(Iterable<Node> newNodes, Node refChild) {
     if (newNodes is _ChildNodeListLazy) {
-      if (identical(newNodes._this, this)) {
+      _ChildNodeListLazy otherList = newNodes;
+      if (identical(otherList._this, this)) {
         throw new ArgumentError(newNodes);
       }
 
       // Optimized route for copying between nodes.
-      for (var i = 0, len = newNodes.length; i < len; ++i) {
+      for (var i = 0, len = otherList.length; i < len; ++i) {
         // Should use $dom_firstChild, Bug 8886.
-        this.insertBefore(newNodes[0], refChild);
+        this.insertBefore(otherList[0], refChild);
       }
     } else {
       for (var node in newNodes) {
@@ -15829,8 +15848,7 @@
   /**
    * Print out a String representation of this Node.
    */
-  String toString() => localName == null ?
-      (nodeValue == null ? super.toString() : nodeValue) : localName;
+  String toString() => nodeValue == null ? super.toString() : nodeValue;
 
   /**
    * Binds the attribute [name] to the [path] of the [model].
@@ -15925,11 +15943,12 @@
   @DocsEditable
   final Node $dom_lastChild;
 
+  @JSName('localName')
   @DomName('Node.localName')
   @DocsEditable
   // http://dom.spec.whatwg.org/#dom-node-localname
   @deprecated // deprecated
-  final String localName;
+  final String $dom_localName;
 
   @JSName('namespaceURI')
   @DomName('Node.namespaceURI')
@@ -20367,7 +20386,7 @@
   @Experimental
   static Stream<DocumentFragment> get instanceCreated {
     if (_instanceCreated == null) {
-      _instanceCreated = new StreamController<DocumentFragment>();
+      _instanceCreated = new StreamController<DocumentFragment>(sync: true);
     }
     return _instanceCreated.stream;
   }
@@ -22027,7 +22046,7 @@
       var axis = 0;
       var detail = 0;
       if (deltaX != 0 && deltaY != 0) {
-        throw UnsupportedError(
+        throw new UnsupportedError(
             'Cannot modify deltaX and deltaY simultaneously');
       }
       if (deltaY != 0) {
@@ -23220,6 +23239,10 @@
   @Experimental
   Stream<TouchEvent> get onTouchStart => Element.touchStartEvent.forTarget(this);
 
+  @DomName('Window.ontransitionend')
+  @DocsEditable
+  Stream<TransitionEvent> get onTransitionEnd => Element.transitionEndEvent.forTarget(this);
+
   @DomName('Window.onunload')
   @DocsEditable
   Stream<Event> get onUnload => unloadEvent.forTarget(this);
@@ -23239,11 +23262,6 @@
   @Experimental // untriaged
   Stream<AnimationEvent> get onAnimationStart => animationStartEvent.forTarget(this);
 
-  @DomName('Window.onwebkitTransitionEnd')
-  @DocsEditable
-  @deprecated
-  Stream<TransitionEvent> get onTransitionEnd => Element.transitionEndEvent.forTarget(this);
-
 
   @DomName('DOMWindow.beforeunloadEvent')
   @DocsEditable
@@ -23294,7 +23312,7 @@
   const _BeforeUnloadEventStreamProvider(this._eventType);
 
   Stream<BeforeUnloadEvent> forTarget(EventTarget e, {bool useCapture: false}) {
-    var controller = new StreamController();
+    var controller = new StreamController(sync: true);
     var stream = new _EventStream(e, _eventType, useCapture);
     stream.listen((event) {
       var wrapped = new _BeforeUnloadEvent(event);
@@ -23618,6 +23636,37 @@
 
 
 @DocsEditable
+@DomName('Attr')
+class _Attr extends Node native "Attr" {
+
+  @DomName('Attr.isId')
+  @DocsEditable
+  final bool isId;
+
+  @DomName('Attr.name')
+  @DocsEditable
+  final String name;
+
+  @DomName('Attr.ownerElement')
+  @DocsEditable
+  @deprecated // deprecated
+  final Element ownerElement;
+
+  @DomName('Attr.specified')
+  @DocsEditable
+  @deprecated // deprecated
+  final bool specified;
+
+  @DomName('Attr.value')
+  @DocsEditable
+  String value;
+}
+// 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.
+
+
+@DocsEditable
 @DomName('CSSPrimitiveValue')
 // http://dev.w3.org/csswg/cssom/#the-cssstyledeclaration-interface
 @deprecated // deprecated
@@ -24857,7 +24906,7 @@
     var keys = new List<String>();
     for (int i = 0, len = attributes.length; i < len; i++) {
       if (_matches(attributes[i])) {
-        keys.add(attributes[i].localName);
+        keys.add(attributes[i].name);
       }
     }
     return keys;
@@ -25635,7 +25684,7 @@
   static final int _ROMAN_ALPHABET_OFFSET = "a".codeUnits[0] - "A".codeUnits[0];
 
   /** Controller to produce KeyEvents for the stream. */
-  final StreamController _controller = new StreamController();
+  final StreamController _controller = new StreamController(sync: true);
 
   static const _EVENT_TYPE = 'KeyEvent';
 
@@ -25704,7 +25753,7 @@
    * Hook up all event listeners under the covers so we can estimate keycodes
    * and charcodes when they are not provided.
    */
-  _KeyboardEventHandler.initializeAllEventListeners(this._type, this._target) : 
+  _KeyboardEventHandler.initializeAllEventListeners(this._type, this._target) :
     super(_EVENT_TYPE) {
     Element.keyDownEvent.forTarget(_target, useCapture: true).listen(
         processKeyDown);
@@ -26849,7 +26898,8 @@
     // TODO(jmesserly): if the path is empty, or the object is! Observable, we
     // can optimize the PathObserver to be more lightweight.
 
-    _values = new StreamController.broadcast(onListen: _observe,
+    _values = new StreamController.broadcast(sync: true,
+                                             onListen: _observe,
                                              onCancel: _unobserve);
 
     if (_isValid) {
@@ -27896,11 +27946,12 @@
   static void _removeChild(Node parent, Node child) {
     child._templateInstance = null;
     if (child is Element && (child as Element).isTemplate) {
+      Element childElement = child;
       // Make sure we stop observing when we remove an element.
-      var templateIterator = child._templateIterator;
+      var templateIterator = childElement._templateIterator;
       if (templateIterator != null) {
         templateIterator.abandon();
-        child._templateIterator = null;
+        childElement._templateIterator = null;
       }
     }
     child.remove();
diff --git a/sdk/lib/html/dartium/html_dartium.dart b/sdk/lib/html/dartium/html_dartium.dart
index 0d36c93..0821628 100644
--- a/sdk/lib/html/dartium/html_dartium.dart
+++ b/sdk/lib/html/dartium/html_dartium.dart
@@ -332,7 +332,7 @@
 
   @DomName('DOMApplicationCache.progressEvent')
   @DocsEditable
-  static const EventStreamProvider<Event> progressEvent = const EventStreamProvider<Event>('progress');
+  static const EventStreamProvider<ProgressEvent> progressEvent = const EventStreamProvider<ProgressEvent>('progress');
 
   @DomName('DOMApplicationCache.updatereadyEvent')
   @DocsEditable
@@ -419,7 +419,7 @@
 
   @DomName('DOMApplicationCache.onprogress')
   @DocsEditable
-  Stream<Event> get onProgress => progressEvent.forTarget(this);
+  Stream<ProgressEvent> get onProgress => progressEvent.forTarget(this);
 
   @DomName('DOMApplicationCache.onupdateready')
   @DocsEditable
@@ -541,19 +541,6 @@
 
 
 @DocsEditable
-@DomName('Attr')
-class Attr extends Node {
-  Attr.internal() : super.internal();
-
-}
-// 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.
-
-// WARNING: Do not edit - generated code.
-
-
-@DocsEditable
 @DomName('HTMLAudioElement')
 class AudioElement extends MediaElement {
   AudioElement.internal() : super.internal();
@@ -6060,7 +6047,7 @@
 @DocsEditable
 @DomName('CustomElementConstructor')
 // https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/custom/index.html#dfn-custom-element-constructor-generation
-@Experimental
+@deprecated // experimental
 class CustomElementConstructor extends NativeFieldWrapperClass1 {
   CustomElementConstructor.internal();
 
@@ -7725,6 +7712,24 @@
     throw new UnsupportedError('Cannot sort element lists');
   }
 
+  void removeWhere(bool test(Element element)) {
+    _filter(test, false);
+  }
+
+  void retainWhere(bool test(Element element)) {
+    _filter(test, true);
+  }
+
+  void _filter(bool test(var element), bool retainMatching) {
+    var removed;
+    if (retainMatching) {
+      removed = _element.children.where((e) => !test(e));
+    } else {
+      removed = _element.children.where(test);
+    }
+    for (var e in removed) e.remove();
+  }
+
   void setRange(int start, int end, Iterable<Element> iterable,
                 [int skipCount = 0]) {
     throw new UnimplementedError();
@@ -8115,6 +8120,16 @@
     _xtag = value;
   }
 
+  @DomName('Element.localName')
+  @DocsEditable
+  String get localName => $dom_localName;
+
+  @DomName('Element.namespaceUri')
+  @DocsEditable
+  String get namespaceUri => $dom_namespaceUri;
+
+  String toString() => localName;
+
   /**
    * Scrolls this element into view.
    *
@@ -8594,13 +8609,9 @@
   @Experimental
   static const EventStreamProvider<TouchEvent> touchStartEvent = const EventStreamProvider<TouchEvent>('touchstart');
 
-  @DomName('Element.webkitTransitionEndEvent')
+  @DomName('Element.transitionendEvent')
   @DocsEditable
-  @SupportedBrowser(SupportedBrowser.CHROME)
-  @SupportedBrowser(SupportedBrowser.SAFARI)
-  @Experimental
-  @deprecated
-  static const EventStreamProvider<TransitionEvent> transitionEndEvent = const EventStreamProvider<TransitionEvent>('webkitTransitionEnd');
+  static const EventStreamProvider<TransitionEvent> transitionEndEvent = const EventStreamProvider<TransitionEvent>('transitionend');
 
   @DomName('Element.webkitfullscreenchangeEvent')
   @DocsEditable
@@ -9165,13 +9176,12 @@
   @Experimental
   Stream<TouchEvent> get onTouchStart => touchStartEvent.forTarget(this);
 
-  @DomName('Element.onwebkitTransitionEnd')
+  @DomName('Element.ontransitionend')
   @DocsEditable
   @SupportedBrowser(SupportedBrowser.CHROME)
   @SupportedBrowser(SupportedBrowser.FIREFOX)
   @SupportedBrowser(SupportedBrowser.IE, '10')
   @SupportedBrowser(SupportedBrowser.SAFARI)
-  @deprecated
   Stream<TransitionEvent> get onTransitionEnd => transitionEndEvent.forTarget(this);
 
   @DomName('Element.onwebkitfullscreenchange')
@@ -11067,7 +11077,7 @@
 
     int watchId;
     var controller;
-    controller = new StreamController<Geoposition>(
+    controller = new StreamController<Geoposition>(sync: true,
       onListen: () {
         assert(watchId == null);
         watchId = $dom_watchPosition(
@@ -16863,14 +16873,15 @@
    */
   Node insertAllBefore(Iterable<Node> newNodes, Node refChild) {
     if (newNodes is _ChildNodeListLazy) {
-      if (identical(newNodes._this, this)) {
+      _ChildNodeListLazy otherList = newNodes;
+      if (identical(otherList._this, this)) {
         throw new ArgumentError(newNodes);
       }
 
       // Optimized route for copying between nodes.
-      for (var i = 0, len = newNodes.length; i < len; ++i) {
+      for (var i = 0, len = otherList.length; i < len; ++i) {
         // Should use $dom_firstChild, Bug 8886.
-        this.insertBefore(newNodes[0], refChild);
+        this.insertBefore(otherList[0], refChild);
       }
     } else {
       for (var node in newNodes) {
@@ -16882,8 +16893,7 @@
   /**
    * Print out a String representation of this Node.
    */
-  String toString() => localName == null ?
-      (nodeValue == null ? super.toString() : nodeValue) : localName;
+  String toString() => nodeValue == null ? super.toString() : nodeValue;
 
   /**
    * Binds the attribute [name] to the [path] of the [model].
@@ -16978,7 +16988,7 @@
   @DocsEditable
   // http://dom.spec.whatwg.org/#dom-node-localname
   @deprecated // deprecated
-  String get localName native "Node_localName_Getter";
+  String get $dom_localName native "Node_localName_Getter";
 
   @DomName('Node.namespaceURI')
   @DocsEditable
@@ -21916,7 +21926,7 @@
   @Experimental
   static Stream<DocumentFragment> get instanceCreated {
     if (_instanceCreated == null) {
-      _instanceCreated = new StreamController<DocumentFragment>();
+      _instanceCreated = new StreamController<DocumentFragment>(sync: true);
     }
     return _instanceCreated.stream;
   }
@@ -24719,6 +24729,10 @@
   @Experimental
   Stream<TouchEvent> get onTouchStart => Element.touchStartEvent.forTarget(this);
 
+  @DomName('Window.ontransitionend')
+  @DocsEditable
+  Stream<TransitionEvent> get onTransitionEnd => Element.transitionEndEvent.forTarget(this);
+
   @DomName('Window.onunload')
   @DocsEditable
   Stream<Event> get onUnload => unloadEvent.forTarget(this);
@@ -24738,11 +24752,6 @@
   @Experimental // untriaged
   Stream<AnimationEvent> get onAnimationStart => animationStartEvent.forTarget(this);
 
-  @DomName('Window.onwebkitTransitionEnd')
-  @DocsEditable
-  @deprecated
-  Stream<TransitionEvent> get onTransitionEnd => Element.transitionEndEvent.forTarget(this);
-
 
   @DomName('DOMWindow.beforeunloadEvent')
   @DocsEditable
@@ -24788,7 +24797,7 @@
   const _BeforeUnloadEventStreamProvider(this._eventType);
 
   Stream<BeforeUnloadEvent> forTarget(EventTarget e, {bool useCapture: false}) {
-    var controller = new StreamController();
+    var controller = new StreamController(sync: true);
     var stream = new _EventStream(e, _eventType, useCapture);
     stream.listen((event) {
       var wrapped = new _BeforeUnloadEvent(event);
@@ -25153,6 +25162,45 @@
 
 
 @DocsEditable
+@DomName('Attr')
+class _Attr extends Node {
+  _Attr.internal() : super.internal();
+
+  @DomName('Attr.isId')
+  @DocsEditable
+  bool get isId native "Attr_isId_Getter";
+
+  @DomName('Attr.name')
+  @DocsEditable
+  String get name native "Attr_name_Getter";
+
+  @DomName('Attr.ownerElement')
+  @DocsEditable
+  @deprecated // deprecated
+  Element get ownerElement native "Attr_ownerElement_Getter";
+
+  @DomName('Attr.specified')
+  @DocsEditable
+  @deprecated // deprecated
+  bool get specified native "Attr_specified_Getter";
+
+  @DomName('Attr.value')
+  @DocsEditable
+  String get value native "Attr_value_Getter";
+
+  @DomName('Attr.value')
+  @DocsEditable
+  void set value(String value) native "Attr_value_Setter";
+
+}
+// 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.
+
+// WARNING: Do not edit - generated code.
+
+
+@DocsEditable
 @DomName('CSSPrimitiveValue')
 // http://dev.w3.org/csswg/cssom/#the-cssstyledeclaration-interface
 @deprecated // deprecated
@@ -26731,7 +26779,7 @@
     var keys = new List<String>();
     for (int i = 0, len = attributes.length; i < len; i++) {
       if (_matches(attributes[i])) {
-        keys.add(attributes[i].localName);
+        keys.add(attributes[i].name);
       }
     }
     return keys;
@@ -27509,7 +27557,7 @@
   static final int _ROMAN_ALPHABET_OFFSET = "a".codeUnits[0] - "A".codeUnits[0];
 
   /** Controller to produce KeyEvents for the stream. */
-  final StreamController _controller = new StreamController();
+  final StreamController _controller = new StreamController(sync: true);
 
   static const _EVENT_TYPE = 'KeyEvent';
 
@@ -27578,7 +27626,7 @@
    * Hook up all event listeners under the covers so we can estimate keycodes
    * and charcodes when they are not provided.
    */
-  _KeyboardEventHandler.initializeAllEventListeners(this._type, this._target) : 
+  _KeyboardEventHandler.initializeAllEventListeners(this._type, this._target) :
     super(_EVENT_TYPE) {
     Element.keyDownEvent.forTarget(_target, useCapture: true).listen(
         processKeyDown);
@@ -28723,7 +28771,8 @@
     // TODO(jmesserly): if the path is empty, or the object is! Observable, we
     // can optimize the PathObserver to be more lightweight.
 
-    _values = new StreamController.broadcast(onListen: _observe,
+    _values = new StreamController.broadcast(sync: true,
+                                             onListen: _observe,
                                              onCancel: _unobserve);
 
     if (_isValid) {
@@ -29770,11 +29819,12 @@
   static void _removeChild(Node parent, Node child) {
     child._templateInstance = null;
     if (child is Element && (child as Element).isTemplate) {
+      Element childElement = child;
       // Make sure we stop observing when we remove an element.
-      var templateIterator = child._templateIterator;
+      var templateIterator = childElement._templateIterator;
       if (templateIterator != null) {
         templateIterator.abandon();
-        child._templateIterator = null;
+        childElement._templateIterator = null;
       }
     }
     child.remove();
diff --git a/sdk/lib/indexed_db/dart2js/indexed_db_dart2js.dart b/sdk/lib/indexed_db/dart2js/indexed_db_dart2js.dart
index 99346e1..22634d5 100644
--- a/sdk/lib/indexed_db/dart2js/indexed_db_dart2js.dart
+++ b/sdk/lib/indexed_db/dart2js/indexed_db_dart2js.dart
@@ -1016,7 +1016,7 @@
     // TODO: need to guarantee that the controller provides the values
     // immediately as waiting until the next tick will cause the transaction to
     // close.
-    var controller = new StreamController();
+    var controller = new StreamController(sync: true);
 
     request.onError.listen((e) {
       //TODO: Report stacktrace once issue 4061 is resolved.
diff --git a/sdk/lib/indexed_db/dartium/indexed_db_dartium.dart b/sdk/lib/indexed_db/dartium/indexed_db_dartium.dart
index 1a539d9..745303e 100644
--- a/sdk/lib/indexed_db/dartium/indexed_db_dartium.dart
+++ b/sdk/lib/indexed_db/dartium/indexed_db_dartium.dart
@@ -877,7 +877,7 @@
     // TODO: need to guarantee that the controller provides the values
     // immediately as waiting until the next tick will cause the transaction to
     // close.
-    var controller = new StreamController();
+    var controller = new StreamController(sync: true);
 
     request.onError.listen((e) {
       //TODO: Report stacktrace once issue 4061 is resolved.
diff --git a/sdk/lib/io/directory.dart b/sdk/lib/io/directory.dart
index 59dc529..cd77600 100644
--- a/sdk/lib/io/directory.dart
+++ b/sdk/lib/io/directory.dart
@@ -51,17 +51,6 @@
   }
 
   /**
-   * Check whether a directory with this name already exists. Returns
-   * a [:Future<bool>:] that completes with the result.
-   */
-  Future<bool> exists();
-
-  /**
-   * Synchronously check whether a directory with this name already exists.
-   */
-  bool existsSync();
-
-  /**
    * Creates the directory with this name.
    *
    * If [recursive] is false, only the last directory in the path is
diff --git a/sdk/lib/io/directory_impl.dart b/sdk/lib/io/directory_impl.dart
index 0157a19..b9935ca 100644
--- a/sdk/lib/io/directory_impl.dart
+++ b/sdk/lib/io/directory_impl.dart
@@ -247,7 +247,7 @@
     const int RESPONSE_COMPLETE = 1;
     const int RESPONSE_ERROR = 2;
 
-    var controller = new StreamController<FileSystemEntity>();
+    var controller = new StreamController<FileSystemEntity>(sync: true);
 
     List request = [ _Directory.LIST_REQUEST, path, recursive, followLinks ];
     ReceivePort responsePort = new ReceivePort();
diff --git a/sdk/lib/io/file.dart b/sdk/lib/io/file.dart
index eb3dcd7..2eea723 100644
--- a/sdk/lib/io/file.dart
+++ b/sdk/lib/io/file.dart
@@ -46,19 +46,6 @@
   factory File.fromPath(Path path) => new _File.fromPath(path);
 
   /**
-   * Check if the file exists. Returns a
-   * [:Future<bool>:] that completes when the answer is known.
-   */
-  Future<bool> exists();
-
-  /**
-   * Synchronously check if the file exists.
-   *
-   * Throws a [FileIOException] if the operation fails.
-   */
-  bool existsSync();
-
-  /**
    * Create the file. Returns a [:Future<File>:] that completes with
    * the file when it has been created.
    *
@@ -94,18 +81,9 @@
 
   /**
    * Get a [Directory] object for the directory containing this
-   * file. Returns a [:Future<Directory>:] that completes with the
-   * directory.
+   * file.
    */
-  Future<Directory> directory();
-
-  /**
-   * Synchronously get a [Directory] object for the directory containing
-   * this file.
-   *
-   * Throws a [FileIOException] if the operation fails.
-   */
-  Directory directorySync();
+  Directory get directory;
 
   /**
    * Get the length of the file. Returns a [:Future<int>:] that
diff --git a/sdk/lib/io/file_impl.dart b/sdk/lib/io/file_impl.dart
index 29b93dc..53a0f50 100644
--- a/sdk/lib/io/file_impl.dart
+++ b/sdk/lib/io/file_impl.dart
@@ -47,7 +47,7 @@
   }
 
   void _setupController() {
-    _controller = new StreamController<List<int>>(
+    _controller = new StreamController<List<int>>(sync: true,
         onListen: _start,
         onPause: () => _paused = true,
         onResume: _resume,
@@ -204,26 +204,25 @@
 const int _DELETE_REQUEST = 2;
 const int _OPEN_REQUEST = 3;
 const int _FULL_PATH_REQUEST = 4;
-const int _DIRECTORY_REQUEST = 5;
-const int _CLOSE_REQUEST = 6;
-const int _POSITION_REQUEST = 7;
-const int _SET_POSITION_REQUEST = 8;
-const int _TRUNCATE_REQUEST = 9;
-const int _LENGTH_REQUEST = 10;
-const int _LENGTH_FROM_PATH_REQUEST = 11;
-const int _LAST_MODIFIED_REQUEST = 12;
-const int _FLUSH_REQUEST = 13;
-const int _READ_BYTE_REQUEST = 14;
-const int _WRITE_BYTE_REQUEST = 15;
-const int _READ_REQUEST = 16;
-const int _READ_LIST_REQUEST = 17;
-const int _WRITE_LIST_REQUEST = 18;
-const int _CREATE_LINK_REQUEST = 19;
-const int _DELETE_LINK_REQUEST = 20;
-const int _LINK_TARGET_REQUEST = 21;
-const int _TYPE_REQUEST = 22;
-const int _IDENTICAL_REQUEST = 23;
-const int _STAT_REQUEST = 24;
+const int _CLOSE_REQUEST = 5;
+const int _POSITION_REQUEST = 6;
+const int _SET_POSITION_REQUEST = 7;
+const int _TRUNCATE_REQUEST = 8;
+const int _LENGTH_REQUEST = 9;
+const int _LENGTH_FROM_PATH_REQUEST = 10;
+const int _LAST_MODIFIED_REQUEST = 11;
+const int _FLUSH_REQUEST = 12;
+const int _READ_BYTE_REQUEST = 13;
+const int _WRITE_BYTE_REQUEST = 14;
+const int _READ_REQUEST = 15;
+const int _READ_LIST_REQUEST = 16;
+const int _WRITE_LIST_REQUEST = 17;
+const int _CREATE_LINK_REQUEST = 18;
+const int _DELETE_LINK_REQUEST = 19;
+const int _LINK_TARGET_REQUEST = 20;
+const int _TYPE_REQUEST = 21;
+const int _IDENTICAL_REQUEST = 22;
+const int _STAT_REQUEST = 23;
 
 // TODO(ager): The only reason for this class is that the patching
 // mechanism doesn't seem to like patching a private top level
@@ -313,27 +312,9 @@
     throwIfError(result, "Cannot delete file '$_path'");
   }
 
-  Future<Directory> directory() {
-    _ensureFileService();
-    List request = new List(2);
-    request[0] = _DIRECTORY_REQUEST;
-    request[1] = _path;
-    return _fileService.call(request).then((response) {
-      if (_isErrorResponse(response)) {
-        throw _exceptionFromResponse(response,
-                                     "Cannot retrieve directory for "
-                                     "file '$_path'");
-      }
-      return new Directory(response);
-    });
-  }
-
-  external static _directory(String path);
-
-  Directory directorySync() {
-    var result = _directory(path);
-    throwIfError(result, "Cannot retrieve directory for file '$_path'");
-    return new Directory(result);
+  Directory get directory {
+    Path path = new Path(_path).directoryPath;
+    return new Directory.fromPath(path);
   }
 
   Future<RandomAccessFile> open({FileMode mode: FileMode.READ}) {
@@ -507,7 +488,7 @@
   static List<String> _decodeLines(List<int> bytes, Encoding encoding) {
     if (bytes.length == 0) return [];
     var list = [];
-    var controller = new StreamController();
+    var controller = new StreamController(sync: true);
     controller.stream
         .transform(new StringDecoder(encoding))
         .transform(new LineTransformer())
diff --git a/sdk/lib/io/file_system_entity.dart b/sdk/lib/io/file_system_entity.dart
index 4347f2c..ce84e35 100644
--- a/sdk/lib/io/file_system_entity.dart
+++ b/sdk/lib/io/file_system_entity.dart
@@ -235,6 +235,37 @@
     return result;
   }
 
+  /**
+   * Check whether the file system entity with this path exists. Returns
+   * a [:Future<bool>:] that completes with the result.
+   *
+   * Since FileSystemEntity is abstract, every FileSystemEntity object
+   * is actually an instance of one of the subclasses [File],
+   * [Directory], and [Link].  Calling [exists] on an instance of one
+   * of these subclasses checks whether the object exists in the file
+   * system object exists and is of the correct type (file, directory,
+   * or link).  To check whether a path points to an object on the
+   * file system, regardless of the object's type, use the [type]
+   * static method.
+   *
+   */
+  Future<bool> exists();
+
+  /**
+   * Synchronously check whether the file system entity with this path
+   * exists.
+   *
+   * Since FileSystemEntity is abstract, every FileSystemEntity object
+   * is actually an instance of one of the subclasses [File],
+   * [Directory], and [Link].  Calling [existsSync] on an instance of
+   * one of these subclasses checks whether the object exists in the
+   * file system object exists and is of the correct type (file,
+   * directory, or link).  To check whether a path points to an object
+   * on the file system, regardless of the object's type, use the
+   * [typeSync] static method.
+   */
+  bool existsSync();
+
   static Future<FileSystemEntityType> type(String path,
                                            {bool followLinks: true})
       => _getTypeAsync(path, followLinks).then(FileSystemEntityType._lookup);
diff --git a/sdk/lib/io/http.dart b/sdk/lib/io/http.dart
index 913ab8f..4ea77f7 100644
--- a/sdk/lib/io/http.dart
+++ b/sdk/lib/io/http.dart
@@ -666,16 +666,12 @@
   String get method;
 
   /**
-   * Returns the URI for the request.
+   * Returns the URI for the request. This provides access to the
+   * path, query string and fragment identifier for the request.
    */
   Uri get uri;
 
   /**
-   * Returns the parsed query string.
-   */
-  Map<String, String> get queryParameters;
-
-  /**
    * Returns the request headers.
    */
   HttpHeaders get headers;
diff --git a/sdk/lib/io/http_impl.dart b/sdk/lib/io/http_impl.dart
index b27441b..0a16be9 100644
--- a/sdk/lib/io/http_impl.dart
+++ b/sdk/lib/io/http_impl.dart
@@ -78,9 +78,6 @@
 class _HttpRequest extends _HttpInboundMessage implements HttpRequest {
   final HttpResponse response;
 
-  // Lazy initialized parsed query parameters.
-  Map<String, String> _queryParameters;
-
   final _HttpServer _httpServer;
 
   final _HttpConnection _httpConnection;
@@ -119,13 +116,6 @@
                             cancelOnError: cancelOnError);
   }
 
-  Map<String, String> get queryParameters {
-    if (_queryParameters == null) {
-      _queryParameters = _HttpUtils.splitQueryString(uri.query);
-    }
-    return _queryParameters;
-  }
-
   Uri get uri => _incoming.uri;
 
   String get method => _incoming.method;
@@ -570,7 +560,8 @@
 
   _ensureController() {
     if (_controller != null) return;
-    _controller = new StreamController(onPause: () => _subscription.pause(),
+    _controller = new StreamController(sync: true,
+                                       onPause: () => _subscription.pause(),
                                        onResume: () => _subscription.resume(),
                                        onListen: () => _subscription.resume(),
                                        onCancel: _cancel);
@@ -1939,7 +1930,7 @@
   // Set of currently connected clients.
   final Set<_HttpConnection> _connections = new Set<_HttpConnection>();
   final StreamController<HttpRequest> _controller
-      = new StreamController<HttpRequest>();
+      = new StreamController<HttpRequest>(sync: true);
 
   // TODO(ajohnsen): Use close queue?
 }
diff --git a/sdk/lib/io/http_parser.dart b/sdk/lib/io/http_parser.dart
index b7aabd2..8edaa0c 100644
--- a/sdk/lib/io/http_parser.dart
+++ b/sdk/lib/io/http_parser.dart
@@ -107,6 +107,7 @@
   _HttpDetachedIncoming(StreamSubscription this.subscription,
                         List<int> this.carryOverData) {
     controller = new StreamController<List<int>>(
+        sync: true,
         onListen: resume,
         onPause: pause,
         onResume: resume,
@@ -195,24 +196,25 @@
 
   _HttpParser._(this._requestParser) {
     _controller = new StreamController<_HttpIncoming>(
-          onListen: () {
-            _socketSubscription.resume();
-            _paused = false;
-          },
-          onPause: () {
-            _paused = true;
-            _pauseStateChanged();
-          },
-          onResume: () {
-            _paused = false;
-            _pauseStateChanged();
-          },
-          onCancel: () {
-            try {
-              _socketSubscription.cancel();
-            } catch (e) {
-            }
-          });
+        sync: true,
+        onListen: () {
+          _socketSubscription.resume();
+          _paused = false;
+        },
+        onPause: () {
+          _paused = true;
+          _pauseStateChanged();
+        },
+        onResume: () {
+          _paused = false;
+          _pauseStateChanged();
+        },
+        onCancel: () {
+          try {
+            _socketSubscription.cancel();
+          } catch (e) {
+          }
+        });
     _reset();
   }
 
@@ -883,6 +885,7 @@
     assert(!_bodyPaused);
     var incoming;
     _bodyController = new StreamController<List<int>>(
+        sync: true,
         onListen: () {
           if (incoming != _incoming) return;
           assert(_bodyPaused);
diff --git a/sdk/lib/io/io_sink.dart b/sdk/lib/io/io_sink.dart
index 8e8b71f..4dab40f 100644
--- a/sdk/lib/io/io_sink.dart
+++ b/sdk/lib/io/io_sink.dart
@@ -132,7 +132,7 @@
       throw new StateError("StreamSink is closed");
     }
     if (_controllerInstance == null) {
-      _controllerInstance = new StreamController<T>();
+      _controllerInstance = new StreamController<T>(sync: true);
       _controllerCompleter = new Completer();
       _target.addStream(_controller.stream)
           .then(
diff --git a/sdk/lib/io/link.dart b/sdk/lib/io/link.dart
index bb64fe9..a179f66 100644
--- a/sdk/lib/io/link.dart
+++ b/sdk/lib/io/link.dart
@@ -20,19 +20,6 @@
   factory Link.fromPath(Path path) => new _Link.fromPath(path);
 
   /**
-   * Checks if the link exists. The link may exist, even if its target
-   * is missing or deleted.
-   * Returns a [:Future<bool>:] that completes when the answer is known.
-   */
-  Future<bool> exists();
-
-  /**
-   * Synchronously checks if the link exists. The link may exist, even if
-   * its target is missing or deleted.
-   */
-  bool existsSync();
-
-  /**
    * Creates a symbolic link. Returns a [:Future<Link>:] that completes with
    * the link when it has been created. If the link exists,
    * the future will complete with an error.
diff --git a/sdk/lib/io/mime_multipart_parser.dart b/sdk/lib/io/mime_multipart_parser.dart
index dc3f206..1e3c548 100644
--- a/sdk/lib/io/mime_multipart_parser.dart
+++ b/sdk/lib/io/mime_multipart_parser.dart
@@ -101,6 +101,7 @@
 
   Stream<MimeMultipart> bind(Stream<List<int>> stream) {
     _controller = new StreamController(
+        sync: true,
         onPause: _pauseStream,
         onResume:_resumeStream,
         onCancel: () {
@@ -293,6 +294,7 @@
         case _HEADER_ENDING:
           _expect(byte, _CharCode.LF);
           _multipartController = new StreamController(
+              sync: true,
               onPause: () {
                 _pauseStream();
               },
diff --git a/sdk/lib/io/secure_server_socket.dart b/sdk/lib/io/secure_server_socket.dart
index 7d7dfd1..18966a3 100644
--- a/sdk/lib/io/secure_server_socket.dart
+++ b/sdk/lib/io/secure_server_socket.dart
@@ -122,6 +122,7 @@
                           bool this.requireClientCertificate) {
     _socket = serverSocket;
     _controller = new StreamController<RawSecureSocket>(
+        sync: true,
         onListen: _onSubscriptionStateChange,
         onPause: _onPauseStateChange,
         onResume: _onPauseStateChange,
diff --git a/sdk/lib/io/secure_socket.dart b/sdk/lib/io/secure_socket.dart
index 4ed4da4..0db4e46 100644
--- a/sdk/lib/io/secure_socket.dart
+++ b/sdk/lib/io/secure_socket.dart
@@ -149,23 +149,30 @@
    * arguments.
    *
    * The optional argument [database] is the path to a certificate database
-   * containing root certificates for verifying certificate paths on
+   * directory containing root certificates for verifying certificate paths on
    * client connections, and server certificates to provide on server
    * connections.  The argument [password] should be used when creating
    * secure server sockets, to allow the private key of the server
    * certificate to be fetched.  If [useBuiltinRoots] is true (the default),
    * then a built-in set of root certificates for trusted certificate
    * authorities is merged with the certificates in the database.
+   * The list of built-in root certificates, and documentation about this
+   * default database, is available at
+   * http://www.mozilla.org/projects/security/certs/included/ .
+   *
+   * If the [database] argument is omitted, then only the
+   * builtin root certificates are used.  If [useBuiltinRoots] is also false,
+   * then no certificates are available.
    *
    * Examples:
    *   1) Use only the builtin root certificates:
    *     SecureSocket.initialize(); or
    *
-   *   2) Use a specified database and the builtin roots:
+   *   2) Use a specified database directory and the builtin roots:
    *     SecureSocket.initialize(database: 'path/to/my/database',
    *                             password: 'my_password');
    *
-   *   3) Use a specified database, without builtin roots:
+   *   3) Use a specified database directory, without builtin roots:
    *     SecureSocket.initialize(database: 'path/to/my/database',
    *                             password: 'my_password'.
    *                             useBuiltinRoots: false);
@@ -424,6 +431,7 @@
       bool this.sendClientCertificate,
       bool this.onBadCertificate(X509Certificate certificate)) {
     _controller = new StreamController<RawSocketEvent>(
+        sync: true,
         onListen: _onSubscriptionStateChange,
         onPause: _onPauseStateChange,
         onResume: _onPauseStateChange,
diff --git a/sdk/lib/io/string_transformer.dart b/sdk/lib/io/string_transformer.dart
index ec6d0e2..f127b38 100644
--- a/sdk/lib/io/string_transformer.dart
+++ b/sdk/lib/io/string_transformer.dart
@@ -186,7 +186,7 @@
   if (bytes.length == 0) return "";
   var string;
   var error;
-  var controller = new StreamController();
+  var controller = new StreamController(sync: true);
   controller.stream
     .transform(new StringDecoder(encoding))
     .listen((data) => string = data,
@@ -205,7 +205,7 @@
   if (bytes.length == 0) return "";
   var string;
   var error;
-  var controller = new StreamController();
+  var controller = new StreamController(sync: true);
   controller.stream
     .transform(new Utf8DecoderTransformer(null))
     .listen((data) => string = data,
@@ -223,7 +223,7 @@
 List<int> _encodeString(String string, [Encoding encoding = Encoding.UTF_8]) {
   if (string.length == 0) return [];
   var bytes;
-  var controller = new StreamController();
+  var controller = new StreamController(sync: true);
   controller.stream
     .transform(new StringEncoder(encoding))
     .listen((data) => bytes = data);
diff --git a/sdk/lib/io/websocket_impl.dart b/sdk/lib/io/websocket_impl.dart
index 77c3456..8108084 100644
--- a/sdk/lib/io/websocket_impl.dart
+++ b/sdk/lib/io/websocket_impl.dart
@@ -93,7 +93,7 @@
                 throw new WebSocketException("Protocol error");
               }
               _currentMessageType = _WebSocketMessageType.TEXT;
-              _controller = new StreamController();
+              _controller = new StreamController(sync: true);
               _controller.stream
                   .transform(new Utf8DecoderTransformer(null))
                   .fold(new StringBuffer(), (buffer, str) => buffer..write(str))
@@ -109,7 +109,7 @@
                 throw new WebSocketException("Protocol error");
               }
               _currentMessageType = _WebSocketMessageType.BINARY;
-              _controller = new StreamController();
+              _controller = new StreamController(sync: true);
               _controller.stream
                   .fold(new _BufferList(), (buffer, data) => buffer..add(data))
                   .then((buffer) {
@@ -376,7 +376,7 @@
 
 class _WebSocketTransformerImpl implements WebSocketTransformer {
   final StreamController<WebSocket> _controller =
-      new StreamController<WebSocket>();
+      new StreamController<WebSocket>(sync: true);
 
   Stream<WebSocket> bind(Stream<HttpRequest> stream) {
     stream.listen((request) {
@@ -566,7 +566,8 @@
 
   _ensureController() {
     if (_controller != null) return;
-    _controller = new StreamController(onPause: () => _subscription.pause(),
+    _controller = new StreamController(sync: true,
+                                       onPause: () => _subscription.pause(),
                                        onResume: () => _subscription.resume(),
                                        onCancel: _onListen);
     var stream = _controller.stream.transform(
@@ -628,7 +629,7 @@
 
 
 class _WebSocketImpl extends Stream implements WebSocket {
-  final StreamController _controller = new StreamController();
+  final StreamController _controller = new StreamController(sync: true);
   StreamSink _sink;
 
   final Socket _socket;
diff --git a/sdk/lib/isolate/isolate_stream.dart b/sdk/lib/isolate/isolate_stream.dart
index 0f0f63f..f16271e 100644
--- a/sdk/lib/isolate/isolate_stream.dart
+++ b/sdk/lib/isolate/isolate_stream.dart
@@ -38,7 +38,7 @@
 class IsolateStream extends Stream<dynamic> {
   bool _isClosed = false;
   final ReceivePort _port;
-  StreamController _controller = new StreamController();
+  StreamController _controller = new StreamController(sync: true);
 
   IsolateStream._fromOriginalReceivePort(this._port) {
     _port.receive((message, replyTo) {
diff --git a/sdk/lib/mdv_observe_impl/mdv_observe_impl.dart b/sdk/lib/mdv_observe_impl/mdv_observe_impl.dart
index 577f0b8..e83a15d 100644
--- a/sdk/lib/mdv_observe_impl/mdv_observe_impl.dart
+++ b/sdk/lib/mdv_observe_impl/mdv_observe_impl.dart
@@ -63,15 +63,15 @@
  * call [notifyPropertyChange]. See that method for an example.
  */
 abstract class ObservableMixin implements Observable {
-  StreamController _multiplexController;
+  StreamController _broadcastController;
   List<ChangeRecord> _changes;
 
   Stream<List<ChangeRecord>> get changes {
-    if (_multiplexController == null) {
-      _multiplexController =
-          new StreamController<List<ChangeRecord>>.broadcast();
+    if (_broadcastController == null) {
+      _broadcastController =
+          new StreamController<List<ChangeRecord>>.broadcast(sync: true);
     }
-    return _multiplexController.stream;
+    return _broadcastController.stream;
   }
 
   void _deliverChanges() {
@@ -79,7 +79,7 @@
     _changes = null;
     if (hasObservers && changes != null) {
       // TODO(jmesserly): make "changes" immutable
-      _multiplexController.add(changes);
+      _broadcastController.add(changes);
     }
   }
 
@@ -87,8 +87,8 @@
    * True if this object has any observers, and should call
    * [notifyPropertyChange] for changes.
    */
-  bool get hasObservers => _multiplexController != null &&
-                           _multiplexController.hasListener;
+  bool get hasObservers => _broadcastController != null &&
+                           _broadcastController.hasListener;
 
   /**
    * Notify that the field [name] of this object has been changed.
diff --git a/sdk/lib/mirrors/mirrors.dart b/sdk/lib/mirrors/mirrors.dart
index 1e9377e..722be26 100644
--- a/sdk/lib/mirrors/mirrors.dart
+++ b/sdk/lib/mirrors/mirrors.dart
@@ -176,6 +176,11 @@
    * The source location of this Dart language entity.
    */
   SourceLocation get location;
+
+  /**
+   * A list of the metadata associated with this declaration.
+   */
+  List<InstanceMirror> get metadata;
 }
 
 /**
diff --git a/sdk/lib/typed_data/dart2js/typed_data_dart2js.dart b/sdk/lib/typed_data/dart2js/typed_data_dart2js.dart
index d7afeed..1fcecdb 100644
--- a/sdk/lib/typed_data/dart2js/typed_data_dart2js.dart
+++ b/sdk/lib/typed_data/dart2js/typed_data_dart2js.dart
@@ -123,22 +123,12 @@
 }
 
 class ByteData extends TypedData native "DataView" {
-  factory ByteData(int length) => JS('ByteData', 'new DataView(#)', length);
+  factory ByteData(int length) =>
+      _TypedArrayFactoryProvider.createByteData(length);
 
-  factory ByteData.view(ByteBuffer buffer, [int byteOffset, int byteLength]) {
-    if (?byteLength) {
-      return ByteData._create_1(buffer, byteOffset, byteLength);
-    }
-    if (?byteOffset) {
-      return ByteData._create_2(buffer, byteOffset);
-    }
-    return ByteData._create_3(buffer);
-  }
-
-  static ByteData _create_1(buffer, byteOffset, byteLength) =>
-    JS('ByteData', 'new DataView(#,#,#)', buffer, byteOffset, byteLength);
-  static ByteData _create_2(buffer, byteOffset) => JS('ByteData', 'new DataView(#,#)', buffer, byteOffset);
-  static ByteData _create_3(buffer) => JS('ByteData', 'new DataView(#)', buffer);
+  factory ByteData.view(ByteBuffer buffer, [int byteOffset, int byteLength]) =>
+      _TypedArrayFactoryProvider.createByteData_fromBuffer(
+          buffer, byteOffset, byteLength);
 
   num getFloat32(int byteOffset, [Endianness endian=Endianness.BIG_ENDIAN]) =>
       _getFloat32(byteOffset, endian._littleEndian);
@@ -2280,7 +2270,7 @@
   }
 
   factory Float32x4List.view(ByteBuffer buffer,
-			     [int offsetInBytes = 0, int length]) {
+                             [int offsetInBytes = 0, int length]) {
     throw new UnsupportedError("Float32x4List not supported by dart2js.");
   }
 
diff --git a/sdk/lib/typed_data/typed_data.dart b/sdk/lib/typed_data/typed_data.dart
index 55274b2..043a61e 100644
--- a/sdk/lib/typed_data/typed_data.dart
+++ b/sdk/lib/typed_data/typed_data.dart
@@ -430,7 +430,7 @@
  * more space- and time-efficient than the default [List] implementation.
  * Indexed store clamps the value to range 0..0xFF.
  */
-abstract class Uint8ClampedList implements List<int>, TypedData {
+abstract class Uint8ClampedList implements Uint8List {
   /**
    * Creates a [Uint8ClampedList] of the specified length (in elements), all of
    * whose elements are initially zero.
diff --git a/sdk/lib/web_audio/dart2js/web_audio_dart2js.dart b/sdk/lib/web_audio/dart2js/web_audio_dart2js.dart
index 83732db..30413ba 100644
--- a/sdk/lib/web_audio/dart2js/web_audio_dart2js.dart
+++ b/sdk/lib/web_audio/dart2js/web_audio_dart2js.dart
@@ -1001,8 +1001,8 @@
    */
   Stream<AudioProcessingEvent> get onAudioProcess {
     if (_eventStream == null) {
-      var controller = new StreamController();
-      var callback = (audioData) { 
+      var controller = new StreamController(sync: true);
+      var callback = (audioData) {
           if (controller.hasListener) {
             // This stream is a strange combination of broadcast and single
             // subscriber streams. We only allow one listener, but if there is
diff --git a/sdk/lib/web_audio/dartium/web_audio_dartium.dart b/sdk/lib/web_audio/dartium/web_audio_dartium.dart
index 786b08d..2eefb8c 100644
--- a/sdk/lib/web_audio/dartium/web_audio_dartium.dart
+++ b/sdk/lib/web_audio/dartium/web_audio_dartium.dart
@@ -1258,8 +1258,8 @@
    */
   Stream<AudioProcessingEvent> get onAudioProcess {
     if (_eventStream == null) {
-      var controller = new StreamController();
-      var callback = (audioData) { 
+      var controller = new StreamController(sync: true);
+      var callback = (audioData) {
           if (controller.hasListener) {
             // This stream is a strange combination of broadcast and single
             // subscriber streams. We only allow one listener, but if there is
diff --git a/tests/co19/co19-analyzer.status b/tests/co19/co19-analyzer.status
index f037e57..ba2d15e 100644
--- a/tests/co19/co19-analyzer.status
+++ b/tests/co19/co19-analyzer.status
@@ -38,11 +38,6 @@
 Language/07_Classes/6_Constructors/3_Constant_Constructors_A05_t02: fail
 Language/07_Classes/6_Constructors/3_Constant_Constructors_A05_t03: fail
 Language/07_Classes/7_Static_Methods_A01_t01: fail
-Language/07_Classes/9_Superclasses_A03_t01: fail
-Language/07_Classes/9_Superclasses_A03_t02: fail
-Language/08_Interfaces/5_Superinterfaces_A01_t03: fail
-Language/08_Interfaces/5_Superinterfaces_A01_t04: fail
-Language/08_Interfaces/5_Superinterfaces_A04_t03: fail
 Language/09_Generics/09_Generics_A04_t07: fail
 Language/11_Expressions/01_Constants_A01_t01: fail
 Language/11_Expressions/01_Constants_A08_t02: fail
@@ -70,7 +65,6 @@
 Language/11_Expressions/07_Maps_A02_t02: fail
 Language/11_Expressions/11_Instance_Creation/1_New_A13_t02: fail
 Language/11_Expressions/11_Instance_Creation/2_Const_A06_t01: fail
-Language/11_Expressions/11_Instance_Creation/2_Const_A06_t02: fail
 Language/11_Expressions/11_Instance_Creation/2_Const_A10_t01: fail
 Language/11_Expressions/11_Instance_Creation_A05_t02: fail
 Language/11_Expressions/14_Function_Invocation/1_Actual_Argument_List_Evaluation_A02_t01: fail
diff --git a/tests/co19/co19-dart2dart.status b/tests/co19/co19-dart2dart.status
index e639cac..69035a4 100644
--- a/tests/co19/co19-dart2dart.status
+++ b/tests/co19/co19-dart2dart.status
@@ -9,7 +9,6 @@
 Language/11_Expressions/11_Instance_Creation/2_Const_A03_t01: Fail # TODO(dart2dart-team): Please triage this failure.
 Language/11_Expressions/11_Instance_Creation_A05_t02: Fail # TODO(dart2dart-team): Please triage this failure.
 Language/11_Expressions/14_Function_Invocation/3_Unqualified_Invocation_A01_t10: Fail # TODO(dart2dart-team): Please triage this failure.
-Language/11_Expressions/33_Argument_Definition_Test_A02_t01: Fail # TODO(dart2dart-team): Please triage this failure.
 Language/11_Expressions/33_Argument_Definition_Test_A02_t02: Fail # TODO(dart2dart-team): Please triage this failure.
 Language/12_Statements/03_Variable_Declaration_A04_t07: Fail # TODO(dart2dart-team): Please triage this failure.
 Language/12_Statements/03_Variable_Declaration_A04_t08: Fail # TODO(dart2dart-team): Please triage this failure.
@@ -405,9 +404,6 @@
 
 
 [ $compiler == dart2dart && $minified ]
-Language/11_Expressions/33_Argument_Definition_Test_A03_t01: Fail # TODO(dart2dart-team): Please triage this failure.
-Language/11_Expressions/33_Argument_Definition_Test_A03_t02: Fail # TODO(dart2dart-team): Please triage this failure.
-
 Language/11_Expressions/14_Function_Invocation/4_Function_Expression_Invocation_A01_t02: Fail, OK # co19 issue 396
 Language/11_Expressions/17_Getter_Invocation_A02_t01: Fail, OK # co19 issue 396
 Language/11_Expressions/18_Assignment_A05_t02: Fail, OK # co19 issue 396
diff --git a/tests/co19/co19-runtime.status b/tests/co19/co19-runtime.status
index 79111bd..544150d 100644
--- a/tests/co19/co19-runtime.status
+++ b/tests/co19/co19-runtime.status
@@ -510,13 +510,29 @@
 [ $compiler == none && $runtime == vm && $unchecked ]
 LibTest/core/List/setRange_A05_t01: Fail # setRange now takes end-argument. Issue 402
 
-[ $compiler == none && $arch == simarm ]
+[ $compiler == none && $runtime == vm && $arch == arm ]
 *: Skip
 
+[ $compiler == none && $runtime == vm && $arch == simarm]
+LibTest/math/tan_A01_t01: Fail
+LibTest/math/Random/nextDouble_A01_t01.dart: Pass, Fail
+LibTest/core/int/operator_left_shift_A01_t02: Fail
+LibTest/core/int/operator_unary_minus_A01_t01: Fail
 
-[ $compiler == none && $arch == simmips ]
+[ $compiler == none && $runtime == vm && $arch == simarm && $mode == debug]
+LibTest/core/Expect/throws_A01_t04: Crash
+LibTest/core/List/sort_A01_t04: Crash
+LibTest/core/List/sort_A01_t05: Crash
+LibTest/core/List/sort_A01_t06: Crash
+LibTest/core/double/ceil_A01_t02: Fail
+LibTest/core/double/floor_A01_t02: Fail
+LibTest/core/double/truncate_A01_t01: Fail
+LibTest/core/int/operator_left_shift_A01_t02: Fail
+LibTest/core/int/operator_unary_minus_A01_t01: Fail
+
+[ $compiler == none && $runtime == vm && $arch == mips ]
 *: Skip
 
-
-[ $compiler == none && $arch == mips ]
+[ $compiler == none && $runtime == vm && $arch == simmips ]
 *: Skip
+
diff --git a/tests/compiler/dart2js/analyze_api_test.dart b/tests/compiler/dart2js/analyze_api_test.dart
index a4cca28..29ad0ef 100644
--- a/tests/compiler/dart2js/analyze_api_test.dart
+++ b/tests/compiler/dart2js/analyze_api_test.dart
@@ -22,10 +22,7 @@
 const Map<String, List<String>> WHITE_LIST = const {
   'html_dart2js.dart':
       const ['Warning: Using "new Symbol"', // Issue 10565.
-             // Issue 10688:
-             'Warning: no property named',
-             "Warning: 'UnsupportedError' is not callable",
-             "Warning: no operator [] in class Iterable"],
+            ],
 };
 
 void main() {
diff --git a/tests/compiler/dart2js/class_codegen_test.dart b/tests/compiler/dart2js/class_codegen_test.dart
index 3380a43..24d8c63 100644
--- a/tests/compiler/dart2js/class_codegen_test.dart
+++ b/tests/compiler/dart2js/class_codegen_test.dart
@@ -86,7 +86,7 @@
 
 constructor1() {
   String generated = compileAll(TEST_FIVE);
-  Expect.isTrue(generated.contains(r"new $.A(a);"));
+  Expect.isTrue(generated.contains(new RegExp(r"new [$a-z]+\.A\(a\);")));
 }
 
 main() {
diff --git a/tests/compiler/dart2js/dart_backend_test.dart b/tests/compiler/dart2js/dart_backend_test.dart
index 59fe13f..112f0fa 100644
--- a/tests/compiler/dart2js/dart_backend_test.dart
+++ b/tests/compiler/dart2js/dart_backend_test.dart
@@ -23,6 +23,7 @@
 class Function {}
 class List<T> {}
 class Map<K,V> {}
+class BoundClosure {}
 class Closure {}
 class Dynamic_ {}
 class Null {}
@@ -611,7 +612,7 @@
   }
 }
 
-fooglobal(arg,[optionalarg = 7]) {
+fooglobal(arg,{optionalarg: 7}) {
   arg = 6;
 }
 
@@ -622,7 +623,7 @@
 }
 ''';
   var expectedResult =
-      'class B{var E;static C(A){A=5;}}D(A,[optionalarg=7]){A=6;}'
+      'class B{var E;static C(A){A=5;}}D(A,{optionalarg: 7}){A=6;}'
       'main(){new B().E;B.C(8);D(8);}';
   testDart2Dart(src, continuation:
       (String result) { Expect.equals(expectedResult, result); }, minify: true);
diff --git a/tests/compiler/dart2js/interceptor_test.dart b/tests/compiler/dart2js/interceptor_test.dart
index 5f7caa6..e0f544d 100644
--- a/tests/compiler/dart2js/interceptor_test.dart
+++ b/tests/compiler/dart2js/interceptor_test.dart
@@ -42,7 +42,7 @@
   // Check that one-shot interceptors preserve variable names, see
   // https://code.google.com/p/dart/issues/detail?id=8106.
   generated = compile(TEST_TWO, entry: 'foo');
-  Expect.isTrue(generated.contains(r'$.$add$n(a, 42)'));
+  Expect.isTrue(generated.contains(new RegExp(r'[$a-z]+\.\$add\$n\(a, 42\)')));
   Expect.isTrue(generated.contains('myVariableName'));
 
   // Check that an intercepted getter that does not need to be
@@ -50,6 +50,7 @@
   // access.
   generated = compile(TEST_THREE, entry: 'foo');
   Expect.isFalse(generated.contains(r'a.get$length()'));
-  Expect.isTrue(generated.contains(r'$.A$().length'));
-  Expect.isTrue(generated.contains(r'$.get$length$a(a)'));
+  Expect.isTrue(generated.contains(new RegExp(r'[$a-z]+\.A\$\(\)\.length')));
+  Expect.isTrue(
+      generated.contains(new RegExp(r'[$a-z]+\.get\$length\$a\(a\)')));
 }
diff --git a/tests/compiler/dart2js/mock_compiler.dart b/tests/compiler/dart2js/mock_compiler.dart
index d0c1089..a9fa9de 100644
--- a/tests/compiler/dart2js/mock_compiler.dart
+++ b/tests/compiler/dart2js/mock_compiler.dart
@@ -53,6 +53,11 @@
   boolConversionCheck(x) {}
   abstract class JavaScriptIndexingBehavior {}
   class JSInvocationMirror {}
+  class BoundClosure {
+    var self;
+    var target;
+    var receiver;
+  }
   class Closure {}
   class Null {}
   class Dynamic_ {}
diff --git a/tests/compiler/dart2js/patch_test.dart b/tests/compiler/dart2js/patch_test.dart
index 3cf4b46..b0cec7d 100644
--- a/tests/compiler/dart2js/patch_test.dart
+++ b/tests/compiler/dart2js/patch_test.dart
@@ -10,9 +10,12 @@
 import "mock_compiler.dart";
 import "parser_helper.dart";
 
-Compiler applyPatch(String script, String patch) {
+Compiler applyPatch(String script, String patch,
+                    {bool analyzeAll: false, bool analyzeOnly: false}) {
   String core = "$DEFAULT_CORELIB\n$script";
-  MockCompiler compiler = new MockCompiler(coreSource: core);
+  MockCompiler compiler = new MockCompiler(coreSource: core,
+                                           analyzeAll: analyzeAll,
+                                           analyzeOnly: analyzeOnly);
   var uri = Uri.parse("core.dartp");
   compiler.sourceFiles[uri.toString()] = new MockFile(patch);
   var handler = new LibraryDependencyHandler(compiler);
@@ -715,6 +718,34 @@
   Expect.isTrue(typedSelector.applies(method, compiler));
 }
 
+void testAnalyzeAllInjectedMembers() {
+  String patchText = """
+                     void method() {
+                       String s = 0;
+                     }
+                     """;
+  var compiler = applyPatch('', patchText, analyzeAll: true, analyzeOnly: true);
+  compiler.librariesToAnalyzeWhenRun = [Uri.parse('dart:core')];
+  compiler.runCompiler(null);
+  compareWarningKinds(patchText,
+      [MessageKind.NOT_ASSIGNABLE], compiler.warnings);
+}
+
+void testTypecheckPatchedMembers() {
+  String originText = "external void method();";
+  String patchText = """
+                     patch void method() {
+                       String s = 0;
+                     }
+                     """;
+  var compiler = applyPatch(originText, patchText,
+                            analyzeAll: true, analyzeOnly: true);
+  compiler.librariesToAnalyzeWhenRun = [Uri.parse('dart:core')];
+  compiler.runCompiler(null);
+  compareWarningKinds(patchText,
+      [MessageKind.NOT_ASSIGNABLE], compiler.warnings);
+}
+
 main() {
   testPatchConstructor();
   testPatchFunction();
@@ -744,4 +775,7 @@
   testPatchNonFunction();
 
   testPatchAndSelector();
+
+  testAnalyzeAllInjectedMembers();
+  testTypecheckPatchedMembers();
 }
diff --git a/tests/compiler/dart2js/private_test.dart b/tests/compiler/dart2js/private_test.dart
new file mode 100644
index 0000000..3390c9f
--- /dev/null
+++ b/tests/compiler/dart2js/private_test.dart
@@ -0,0 +1,165 @@
+// 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.
+
+import "package:expect/expect.dart";
+import 'mock_compiler.dart';
+
+import '../../../sdk/lib/_internal/compiler/implementation/source_file.dart';
+import '../../../sdk/lib/_internal/compiler/implementation/dart2jslib.dart'
+    hide SourceString;
+
+const String PRIVATE_SOURCE_URI = 'src:private';
+const String PRIVATE_SOURCE = '''
+
+var _privateVariable;
+void _privateFunction() {}
+
+class _PrivateClass {
+  _PrivateClass();
+  _PrivateClass.publicConstructor();
+  _PrivateClass._privateConstructor();
+
+  var _privateField;
+  get _privateGetter => null;
+  void set _privateSetter(var value) {}
+  void _privateMethod() {}
+
+  var publicField;
+  get publicGetter => null;
+  void set publicSetter(var value) {}
+  void publicMethod() {}
+}
+
+class PublicClass extends _PrivateClass {
+  PublicClass() : super();
+  PublicClass.publicConstructor() : super.publicConstructor();
+  PublicClass._privateConstructor() : super._privateConstructor();
+
+  _PrivateClass get private => this;
+}
+''';
+
+
+void analyze(String text, [expectedWarnings]) {
+  if (expectedWarnings == null) expectedWarnings = [];
+  if (expectedWarnings is !List) expectedWarnings = [expectedWarnings];
+
+  MockCompiler compiler = new MockCompiler(analyzeOnly: true);
+  compiler.registerSource(Uri.parse(PRIVATE_SOURCE_URI), PRIVATE_SOURCE);
+  compiler.diagnosticHandler = (uri, int begin, int end, String message, kind) {
+    SourceFile sourceFile = compiler.sourceFiles[uri.toString()];
+    if (sourceFile != null) {
+      print(sourceFile.getLocationMessage(message, begin, end, true, (x) => x));
+    } else {
+      print(message);
+    }
+  };
+
+  String source = '''
+                  library public;
+
+                  import '$PRIVATE_SOURCE_URI';
+
+                  void main() {
+                    PublicClass publicClass;
+                    $text
+                  }
+                  ''';
+  Uri uri = Uri.parse('src:public');
+  compiler.registerSource(uri, source);
+  compiler.runCompiler(uri);
+  compareWarningKinds(text, expectedWarnings, compiler.warnings);
+}
+
+void main() {
+  // Read from private variable.
+  analyze('var value = _privateVariable;', MessageKind.CANNOT_RESOLVE);
+  // Write to private variable.
+  analyze('_privateVariable = 0;', MessageKind.CANNOT_RESOLVE);
+  // Access private function.
+  analyze('var value = _privateFunction;', MessageKind.CANNOT_RESOLVE);
+  // Call private function.
+  analyze('_privateFunction();', MessageKind.CANNOT_RESOLVE);
+
+  // Call unnamed (public) constructor on private class.
+  analyze('new _PrivateClass();', MessageKind.CANNOT_RESOLVE);
+  // Call public constructor on private class.
+  analyze('new _PrivateClass.publicConstructor();', MessageKind.CANNOT_RESOLVE);
+  // Call private constructor on private class.
+  analyze('new _PrivateClass._privateConstructor();',
+      MessageKind.CANNOT_RESOLVE);
+  // Call public getter of private type.
+  analyze('var value = publicClass.private;');
+  // Read from private field on private class.
+  analyze('var value = publicClass.private._privateField;',
+      MessageKind.PRIVATE_ACCESS);
+  // Write to private field on private class.
+  analyze('publicClass.private._privateField = 0;',
+      MessageKind.PRIVATE_ACCESS);
+  // Call private getter on private class.
+  analyze('var value = publicClass.private._privateGetter;',
+      MessageKind.PRIVATE_ACCESS);
+  // Call private setter on private class.
+  analyze('publicClass.private._privateSetter = 0;',
+      MessageKind.PRIVATE_ACCESS);
+  // Access private method on private class.
+  analyze('var value = publicClass.private._privateMethod;',
+      MessageKind.PRIVATE_ACCESS);
+  // Call private method on private class.
+  analyze('publicClass.private._privateMethod();',
+      MessageKind.PRIVATE_ACCESS);
+
+  // Read from public field on private class.
+  analyze('var value = publicClass.private.publicField;');
+  // Write to public field on private class.
+  analyze('publicClass.private.publicField = 0;');
+  // Call public getter on private class.
+  analyze('var value = publicClass.private.publicGetter;');
+  // Call public setter on private class.
+  analyze('publicClass.private.publicSetter = 0;');
+  // Access public method on private class.
+  analyze('var value = publicClass.private.publicMethod;');
+  // Call public method on private class.
+  analyze('publicClass.private.publicMethod();');
+
+  // Call unnamed (public) constructor on public class.
+  analyze('publicClass = new PublicClass();');
+  // Call public constructor on public class.
+  analyze('publicClass = new PublicClass.publicConstructor();');
+  // Call private constructor on public class.
+  analyze('publicClass = new PublicClass._privateConstructor();',
+      MessageKind.CANNOT_FIND_CONSTRUCTOR);
+  // Read from private field on public class.
+  analyze('var value = publicClass._privateField;',
+      MessageKind.PRIVATE_ACCESS);
+  // Write to private field on public class.
+  analyze('publicClass._privateField = 0;',
+      MessageKind.PRIVATE_ACCESS);
+  // Call private getter on public class.
+  analyze('var value = publicClass._privateGetter;',
+      MessageKind.PRIVATE_ACCESS);
+  // Call private setter on public class.
+  analyze('publicClass._privateSetter = 0;',
+      MessageKind.PRIVATE_ACCESS);
+  // Access private method on public class.
+  analyze('var value = publicClass._privateMethod;',
+      MessageKind.PRIVATE_ACCESS);
+  // Call private method on public class.
+  analyze('publicClass._privateMethod();',
+      MessageKind.PRIVATE_ACCESS);
+
+  // Read from public field on public class.
+  analyze('var value = publicClass.publicField;');
+  // Write to public field on public class.
+  analyze('publicClass.publicField = 0;');
+  // Call public getter on public class.
+  analyze('var value = publicClass.publicGetter;');
+  // Call public setter on public class.
+  analyze('publicClass.publicSetter = 0;');
+  // Access public method on public class.
+  analyze('var value = publicClass.publicMethod;');
+  // Call public method on public class.
+  analyze('publicClass.publicMethod();');
+}
+
diff --git a/tests/compiler/dart2js/simple_inferrer_test.dart b/tests/compiler/dart2js/simple_inferrer_test.dart
index c9776bb..19be754 100644
--- a/tests/compiler/dart2js/simple_inferrer_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_test.dart
@@ -386,6 +386,8 @@
 }
 
 main() {
+  // Ensure a function class is being instantiated.
+  () => 42;
   returnNum1(true);
   returnNum2(true);
   returnInt1(true);
diff --git a/tests/compiler/dart2js/static_closure_test.dart b/tests/compiler/dart2js/static_closure_test.dart
index e6aff7a..4003c61 100644
--- a/tests/compiler/dart2js/static_closure_test.dart
+++ b/tests/compiler/dart2js/static_closure_test.dart
@@ -17,5 +17,5 @@
 
   // If this test fail, please take a look at the use of
   // toStringWrapper in captureStackTrace in js_helper.dart.
-  Expect.isTrue(code.contains(r'print($.main$closure);'));
+  Expect.isTrue(code.contains(new RegExp(r'print\([$a-z]+\.main\$closure\);')));
 }
diff --git a/tests/compiler/dart2js/type_checker_test.dart b/tests/compiler/dart2js/type_checker_test.dart
index 1a6bc16..c9c0221 100644
--- a/tests/compiler/dart2js/type_checker_test.dart
+++ b/tests/compiler/dart2js/type_checker_test.dart
@@ -32,6 +32,7 @@
                 testFor,
                 testWhile,
                 testTry,
+                testSwitch,
                 testOperators,
                 testConstructorInvocationArgumentCount,
                 testConstructorInvocationArgumentTypes,
@@ -42,6 +43,7 @@
                 testConditionalExpression,
                 testIfStatement,
                 testThis,
+                testSuper,
                 testOperatorsAssignability];
   for (Function test in tests) {
     setup();
@@ -123,6 +125,17 @@
       [MessageKind.NOT_ASSIGNABLE, MessageKind.NOT_ASSIGNABLE]);
 }
 
+
+testSwitch() {
+  analyze("switch (0) { case 1: break; case 2: break; }");
+  analyze("switch (0) { case 1: int i = ''; break; case 2: break; }",
+      MessageKind.NOT_ASSIGNABLE);
+  analyze("switch (0) { case '': break; case 2: break; }",
+      MessageKind.NOT_ASSIGNABLE);
+  analyze("switch ('') { case 1: break; case 2: break; }",
+      [MessageKind.NOT_ASSIGNABLE, MessageKind.NOT_ASSIGNABLE]);
+}
+
 testOperators() {
   // TODO(karlklose): add the DartC tests for operators when we can parse
   // classes with operators.
@@ -540,6 +553,24 @@
   analyzeIn(foo, "{ Foo f = this; }");
 }
 
+testSuper() {
+  String script = r'''
+    class A {
+      String field = "42";
+    }
+    
+    class B extends A {
+      Object field = 42;
+    }
+    ''';
+  LibraryElement library = mockLibrary(compiler, script);
+  compiler.parseScript(script, library);
+  ClassElement B = library.find(const SourceString("B"));
+  analyzeIn(B, "{ int i = super.field; }", MessageKind.NOT_ASSIGNABLE);
+  analyzeIn(B, "{ Object o = super.field; }");
+  analyzeIn(B, "{ String s = super.field; }");
+}
+
 const String CLASSES_WITH_OPERATORS = '''
 class Operators {
   Operators operator +(Operators other) => this;
diff --git a/tests/compiler/dart2js/type_guard_unuser_test.dart b/tests/compiler/dart2js/type_guard_unuser_test.dart
index d26d8c6..4cad5fd 100644
--- a/tests/compiler/dart2js/type_guard_unuser_test.dart
+++ b/tests/compiler/dart2js/type_guard_unuser_test.dart
@@ -45,7 +45,9 @@
   RegExp regexp = new RegExp(getIntTypeCheck(anyIdentifier));
   Iterator<Match> matches = regexp.allMatches(generated).iterator;
   checkNumberOfMatches(matches, 0);
-  Expect.isTrue(generated.contains(r'return a === true ? $.foo(2) : b;'));
+  Expect.isTrue(
+      generated.contains(
+          new RegExp(r'return a === true \? [$a-z]+\.foo\(2\) : b;')));
 
   generated = compile(TEST_TWO, entry: 'foo');
   regexp = new RegExp("foo\\(1\\)");
diff --git a/tests/corelib/corelib.status b/tests/corelib/corelib.status
index 7e3010d..3008f2e 100644
--- a/tests/corelib/corelib.status
+++ b/tests/corelib/corelib.status
@@ -4,9 +4,6 @@
 
 reg_exp_unicode_2_test: Fail # Bug 6592
 
-[ $compiler == dart2js && $checked ]
-list_test: Fail, OK # dartbug.com/10708
-
 [ $compiler == none ]
 unicode_test: Fail        # Bug 6706
 *dartc_test: Skip
@@ -97,6 +94,9 @@
 list_insert_test: fail
 list_removeat_test: fail
 
+[ $arch == arm ]
+*: Skip
+
 [ $arch == simarm ]
 *: Skip
 
diff --git a/tests/corelib/list_test.dart b/tests/corelib/list_test.dart
index 395cc57..8883e49 100644
--- a/tests/corelib/list_test.dart
+++ b/tests/corelib/list_test.dart
@@ -14,6 +14,12 @@
   testTypedList(new Int16List(4));
   testTypedList(new Uint32List(4));
   testTypedList(new Int32List(4));
+  testTypedList(new Uint8List(4).toList(growable: false));
+  testTypedList(new Int8List(4).toList(growable: false));
+  testTypedList(new Uint16List(4).toList(growable: false));
+  testTypedList(new Int16List(4).toList(growable: false));
+  testTypedList(new Uint32List(4).toList(growable: false));
+  testTypedList(new Int32List(4).toList(growable: false));
 
   // Fixed length lists, length 4.
   testFixedLengthList(new List(4));
@@ -23,13 +29,6 @@
   testFixedLengthList(new MyFixedList(new List(4)));
   testFixedLengthList(new MyFixedList(new List(4)).toList(growable: false));
 
-  testFixedLengthList(new Uint8List(4).toList(growable: false));
-  testFixedLengthList(new Int8List(4).toList(growable: false));
-  testFixedLengthList(new Uint16List(4).toList(growable: false));
-  testFixedLengthList(new Int16List(4).toList(growable: false));
-  testFixedLengthList(new Uint32List(4).toList(growable: false));
-  testFixedLengthList(new Int32List(4).toList(growable: false));
-
   // Growable lists. Initial length 0.
   testGrowableList(new List());
   testGrowableList(new List().toList());
@@ -38,12 +37,13 @@
   testGrowableList((const []).toList());
   testGrowableList(new MyList([]));
   testGrowableList(new MyList([]).toList());
-  testGrowableList(new Uint8List(0).toList());
-  testGrowableList(new Int8List(0).toList());
-  testGrowableList(new Uint16List(0).toList());
-  testGrowableList(new Int16List(0).toList());
-  testGrowableList(new Uint32List(0).toList());
-  testGrowableList(new Int32List(0).toList());
+
+  testTypedGrowableList(new Uint8List(0).toList());
+  testTypedGrowableList(new Int8List(0).toList());
+  testTypedGrowableList(new Uint16List(0).toList());
+  testTypedGrowableList(new Int16List(0).toList());
+  testTypedGrowableList(new Uint32List(0).toList());
+  testTypedGrowableList(new Int32List(0).toList());
 }
 
 void testLength(int length, List list) {
@@ -237,6 +237,17 @@
   isUnsupported(() => list.replaceRange(0, 1, []));
 }
 
+void testTypedGrowableList(List list) {
+  testLength(0, list);
+  // set length.
+  list.length = 4;
+  testLength(4, list);
+
+  testTypedLengthInvariantOperations(list);
+
+  testGrowableListOperations(list);
+}
+
 void testGrowableList(List list) {
   testLength(0, list);
   // set length.
@@ -245,6 +256,10 @@
 
   testLengthInvariantOperations(list);
 
+  testGrowableListOperations(list);
+}
+
+void testGrowableListOperations(List list) {
   // add, removeLast.
   list.clear();
   testLength(0, list);
diff --git a/tests/html/element_test.dart b/tests/html/element_test.dart
index aae4dda..3537335 100644
--- a/tests/html/element_test.dart
+++ b/tests/html/element_test.dart
@@ -500,6 +500,50 @@
       expect(el.children.getRange(1, 2).length, 1);
     });
 
+    test('retainWhere', () {
+      var el = makeElementWithChildren();
+      expect(el.children.length, 3);
+      el.children.retainWhere((e) => true);
+      expect(el.children.length, 3);
+
+      el = makeElementWithChildren();
+      expect(el.children.length, 3);
+      el.children.retainWhere((e) => false);
+      expect(el.children.length, 0);
+
+      el = makeElementWithChildren();
+      expect(el.children.length, 3);
+      el.children.retainWhere((e) => e.localName == 'input');
+      expect(el.children.length, 1);
+
+      el = makeElementWithChildren();
+      expect(el.children.length, 3);
+      el.children.retainWhere((e) => e.localName == 'br');
+      expect(el.children.length, 1);
+    });
+
+    test('removeWhere', () {
+      var el = makeElementWithChildren();
+      expect(el.children.length, 3);
+      el.children.removeWhere((e) => true);
+      expect(el.children.length, 0);
+
+      el = makeElementWithChildren();
+      expect(el.children.length, 3);
+      el.children.removeWhere((e) => false);
+      expect(el.children.length, 3);
+
+      el = makeElementWithChildren();
+      expect(el.children.length, 3);
+      el.children.removeWhere((e) => e.localName == 'input');
+      expect(el.children.length, 2);
+
+      el = makeElementWithChildren();
+      expect(el.children.length, 3);
+      el.children.removeWhere((e) => e.localName == 'br');
+      expect(el.children.length, 2);
+    });
+
     testUnsupported('sort', () {
       var l = makeElementWithChildren().children;
       l.sort();
diff --git a/tests/html/html.status b/tests/html/html.status
index 40625a0..5e34364 100644
--- a/tests/html/html.status
+++ b/tests/html/html.status
@@ -41,7 +41,7 @@
 [ $runtime == chrome ]
 touchevent_test/supported: Fail
 
-[ $runtime == chrome || $runtime == chromeOnAndroid || $runtime == drt ]
+[ $runtime == chrome || $runtime == chromeOnAndroid || $runtime == drt || $runtime == safari ]
 audiocontext_test: Skip # Issue 9322
 
 [$runtime == drt || $runtime == dartium || $runtime == chrome || $runtime == chromeOnAndroid]
diff --git a/tests/html/shadow_dom_test.dart b/tests/html/shadow_dom_test.dart
index 78b62b5..d9ec86a 100644
--- a/tests/html/shadow_dom_test.dart
+++ b/tests/html/shadow_dom_test.dart
@@ -66,5 +66,30 @@
         expect(shadowRoot.queryAll('.foo'), equals([paragraph1]));
       }, expectation);
     });
+
+    if (ShadowRoot.supported) {
+      test('Shadowroot contents are distributed', () {
+
+        var div = new DivElement();
+
+        var box1 = new DivElement()
+          ..classes.add('foo');
+        div.append(box1);
+
+        var box2 = new DivElement();
+        div.append(box2);
+
+        var sRoot = div.createShadowRoot();
+        var content1 = new ContentElement()
+          ..select = ".foo";
+        sRoot.append(content1);
+
+        var content2 = new ContentElement();
+        sRoot.append(content2);
+
+        expect(content1.getDistributedNodes(), [box1]);
+        expect(content2.getDistributedNodes(), [box2]);
+      });
+    }
   });
 }
diff --git a/tests/isolate/isolate.status b/tests/isolate/isolate.status
index 1937b48..b5f430c 100644
--- a/tests/isolate/isolate.status
+++ b/tests/isolate/isolate.status
@@ -129,6 +129,9 @@
 [ $compiler == dart2js && ( $runtime == ff || $runtime == safari ) ]
 isolate_stress_test: Pass, Timeout # http://dartbug.com/10697
 
+[ $arch == arm ]
+*: Skip
+
 [ $arch == simarm ]
 *: Skip
 
diff --git a/tests/language/bound_closure_equality_test.dart b/tests/language/bound_closure_equality_test.dart
new file mode 100644
index 0000000..fc645ce
--- /dev/null
+++ b/tests/language/bound_closure_equality_test.dart
@@ -0,0 +1,76 @@
+// 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";
+
+class A {
+  const A();
+  foo() => 42;
+}
+
+class B {
+  foo() => 42;
+}
+
+main() {
+  // Use an array to defeat type inferencing.
+  var array = [new A(), new A(), new B(), new B()];
+  var set = new Set.from(array.map((a) => a.foo));
+  Expect.equals(array.length, set.length);
+  set.addAll(array.map((a) => a.foo));
+  Expect.equals(array.length, set.length);
+
+  for (int i = 0; i < array.length; i += 2) {
+    Expect.isTrue(set.contains(array[i].foo));
+    Expect.equals(array[i], array[i]);
+    Expect.equals(array[i].foo, array[i].foo);
+    Expect.equals(array[i].foo.hashCode, array[i].foo.hashCode);
+    for (int j = 0; j < array.length; j++) {
+      if (i == j) continue;
+      Expect.notEquals(array[i].foo, array[j].foo);
+    }
+  }
+
+  // Try with dart2js intercepted types.
+  array =  ['foo', 'bar', [], [], const []];
+  set = new Set.from(array.map((a) => a.indexOf));
+  Expect.equals(array.length, set.length);
+  set.addAll(array.map((a) => a.indexOf));
+  Expect.equals(array.length, set.length);
+
+  for (int i = 0; i < array.length; i += 2) {
+    Expect.isTrue(set.contains(array[i].indexOf));
+    Expect.equals(array[i], array[i]);
+    Expect.equals(array[i].indexOf, array[i].indexOf);
+    Expect.equals(array[i].indexOf.hashCode, array[i].indexOf.hashCode);
+    for (int j = 0; j < array.length; j++) {
+      if (i == j) continue;
+      Expect.notEquals(array[i].indexOf, array[j].indexOf);
+    }
+  }
+
+  array = [const A(), const A()];
+  set = new Set.from(array.map((a) => a.foo));
+  Expect.equals(1, set.length);
+  set.addAll(array.map((a) => a.foo));
+  Expect.equals(1, set.length);
+
+  Expect.isTrue(set.contains(array[0].foo));
+  Expect.equals(array[0].foo, array[0].foo);
+  Expect.equals(array[0].foo.hashCode, array[0].foo.hashCode);
+  Expect.equals(array[0].foo, array[1].foo);
+  Expect.equals(array[0].foo.hashCode, array[1].foo.hashCode);
+
+  array = [const [], const []];
+  set = new Set.from(array.map((a) => a.indexOf));
+  Expect.equals(1, set.length);
+  set.addAll(array.map((a) => a.indexOf));
+  Expect.equals(1, set.length);
+
+  Expect.isTrue(set.contains(array[0].indexOf));
+  Expect.equals(array[0].indexOf, array[0].indexOf);
+  Expect.equals(array[0].indexOf.hashCode, array[0].indexOf.hashCode);
+  Expect.equals(array[0].indexOf, array[1].indexOf);
+  Expect.equals(array[0].indexOf.hashCode, array[1].indexOf.hashCode);
+}
diff --git a/tests/language/bound_closure_primitives_test.dart b/tests/language/bound_closure_primitives_test.dart
new file mode 100644
index 0000000..83ffe79
--- /dev/null
+++ b/tests/language/bound_closure_primitives_test.dart
@@ -0,0 +1,27 @@
+// 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 dart2js does not try to use the same
+// BoundClosureClass between an intercepted method and a
+// non-intercepted method.
+
+import "package:expect/expect.dart";
+
+class A {
+  // Make dart2js try to share a bound closure for [foo] with a bound
+  // closure for [List.add], by having same number of arguments.
+  foo(a) => a;
+}
+
+main() {
+  var array = [[], new A()];
+  var method = array[0].add;
+  method(42);
+
+  method = array[1].foo;
+  Expect.equals(42, method(42));
+
+  Expect.equals(1, array[0].length);
+  Expect.isTrue(array[0].contains(42));
+}
diff --git a/tests/language/language.status b/tests/language/language.status
index bd59fc9..1b35b74 100644
--- a/tests/language/language.status
+++ b/tests/language/language.status
@@ -38,6 +38,7 @@
 method_override2_test/00: Fail # Issue 7076.
 method_override2_test/02: Fail # Issue 7076.
 method_override2_test/03: Fail # Issue 7076.
+bound_closure_equality_test: Fail # Issue 10849
 
 # These bugs refer currently ongoing language discussions.
 constructor5_test: Fail           # (Discussion ongoing)
@@ -77,11 +78,12 @@
 
 mixin_mixin_test: Fail
 mixin_issue10216_2_test: Fail
+mixin_illegal_object_test/01: Crash # Issue 10952
+mixin_illegal_object_test/02: Crash # Issue 10952
 
 type_variable_field_initializer_closure_test: Crash # issue 8847
 
 super_getter_setter_test: Fail # Issue 8917
-super_operator_index7_test: Fail # Issue 8918
 
 execute_finally10_test: Fail # Issue 430
 execute_finally11_test: Fail # Issue 430
@@ -330,16 +332,8 @@
 built_in_identifier_prefix_test: Fail # Inherited from dart2js.
 constructor_redirect2_test/03: Fail
 constructor_initializer_test: Fail # VM issue
-factory2_test: Fail
 factory3_test: Fail
-factory5_test/none: Fail
-factory5_test/00: Fail
 type_checks_in_factory_method_test: Fail
-default_factory2_test/01: Fail # type arguments on redirecting factory not implemented
-default_factory3_test: Fail # type arguments on redirecting factory not implemented
-non_parameterized_factory_test: Fail # type arguments on redirecting factory not implemented
-non_parameterized_factory2_test: Fail # type arguments on redirecting factory not implemented
-type_variable_scope_test: Fail # type arguments on redirecting factory not implemented
 
 many_overridden_no_such_method_test: Fail, Pass, OK # Fails in minified mode, test depends on method names.
 overridden_no_such_method_test: Fail, Pass, OK # Fails in minified mode, test depends on method names.
@@ -515,11 +509,12 @@
 type_variable_field_initializer_closure_test: Crash # VM bug: issue 8847
 
 super_getter_setter_test: Fail # VM bug: issue 8917
-super_operator_index7_test: Fail # VM bug: issue 8918
 
 execute_finally10_test: Fail # VM bug: issue 430
 execute_finally11_test: Fail # VM bug: issue 430
 
+bound_closure_equality_test: Fail # Issue 10849
+
 [ $compiler == dart2dart && $minified ]
 
 # TODO(tball): Assign proper bug numbers.
@@ -557,18 +552,10 @@
 callable_test/none: fail
 cast_test/04: fail
 cast_test/05: fail
-class_cycle_negative_test: fail
-class_cycle_test/00: fail
-class_cycle_test/01: fail
 class_cycle_test/03: fail
 closure_call_wrong_argument_count_negative_test: fail
 compile_time_constant10_test/none: fail
 compile_time_constant8_test: fail
-compile_time_constant_arguments_test/01: fail
-compile_time_constant_arguments_test/02: fail
-compile_time_constant_arguments_test/03: fail
-compile_time_constant_arguments_test/05: fail
-compile_time_constant_arguments_test/06: fail
 compile_time_constant_b_test: fail
 compile_time_constant_c_test/01: fail
 compile_time_constant_c_test/02: fail
@@ -606,7 +593,6 @@
 factory5_test/00: fail
 factory_implementation_test/none: fail
 factory_redirection2_test/01: fail
-factory_redirection_test/07: fail
 fauxverride_test/03: fail
 fauxverride_test/05: fail
 field_method4_negative_test: fail
@@ -633,13 +619,11 @@
 implicit_this_test/04: fail
 implicit_this_test/none: fail
 import_combinators_negative_test: fail
-infinite_switch_label_test: fail
 inst_field_initializer1_negative_test: fail
 instance_call_wrong_argument_count_negative_test: fail
 instance_method2_negative_test: fail
 instance_method_negative_test: fail
 instantiate_type_variable_negative_test: fail
-interface_cycle_negative_test: fail
 interface_inherit_field_test: fail
 interface_static_non_final_fields_negative_test: fail
 interface_test/00: fail
@@ -673,7 +657,6 @@
 new_expression_type_args_test/00: fail
 new_expression_type_args_test/01: fail
 new_expression_type_args_test/02: fail
-nested_switch_label_test: fail
 no_such_method_negative_test: fail
 non_const_super_negative_test: fail
 number_identifier_negative_test: fail
@@ -717,7 +700,6 @@
 static_field_test/03: fail
 static_final_field2_negative_test: fail
 static_final_field_negative_test: fail
-switch_label2_test: fail
 syntax_test/28: fail
 syntax_test/29: fail
 syntax_test/30: fail
@@ -817,9 +799,25 @@
 type_variable_scope_test/05: fail
 
 
-[ $arch == simarm ]
+[ $arch == arm ]
 *: Skip
 
+[ $arch == simarm ]
+arithmetic_test: Crash
+bit_operations_test: Crash
+char_escape_test: Pass, Crash
+deopt_smi_op_test: Fail
+div_with_power_of_two_test: Fail
+double_modulo_test: Crash
+gc_test: Crash
+invocation_mirror_test: Fail
+large_implicit_getter_test: Crash
+load_to_load_forwarding_test: Fail
+math_vm_test: Crash
+named_parameters_with_conversions_test: Pass, Crash
+stack_overflow_stacktrace_test: Crash
+stack_overflow_test: Crash
+
 [ $arch == mips ]
 *: Skip
 
diff --git a/tests/language/language_dart2js.status b/tests/language/language_dart2js.status
index 0b6a3c9..cab3e41 100644
--- a/tests/language/language_dart2js.status
+++ b/tests/language/language_dart2js.status
@@ -42,9 +42,7 @@
 function_type_alias6_test: Crash # dartbug.com/9792
 
 prefix16_test: Fail # dartbug.com/7354
-default_factory2_test/01: Pass # For the wrong reasons.
-type_variable_scope_test/none: Fail
-redirecting_factory_infinite_steps_test/01: Fail
+default_factory2_test/01: Fail
 type_variable_bounds_test/01: Fail
 type_variable_bounds_test/02: Fail
 type_variable_bounds_test/04: Fail
@@ -62,17 +60,11 @@
 local_function2_test: Fail # Issue 5022
 
 [ $compiler == dart2js && $unchecked ]
-default_factory2_test/01: Fail # type arguments on redirecting factory not implemented
-type_variable_scope_test: Fail # type arguments on redirecting factory not implemented
+factory_redirection_test/14: Fail # redirecting to redirecting factory
+type_checks_in_factory_method_test: Fail # Expect.equals(expected: <true>, actual: <false>) fails. -- checked mode test.
+
 assertion_test: Fail
 type_variable_bounds_test/07: Fail # Wrongly reports compile-time error.
-factory_redirection_test/08: Fail
-factory_redirection_test/09: Fail
-factory_redirection_test/10: Fail
-factory_redirection_test/11: Fail
-factory_redirection_test/12: Fail
-factory_redirection_test/13: Fail
-factory_redirection_test/14: Fail
 
 double_to_string_as_exponential2_test: Fail # toStringAsExponential doesn't check if argument is an integer.
 double_to_string_as_fixed2_test: Fail # toStringAsFixed doesn't check if argument is an integer.
@@ -108,7 +100,6 @@
 mint_arithmetic_test: Fail # Issue 1533 (big integer arithmetic).
 left_shift_test: Fail # Issue 1533
 factory_redirection_test/01: Fail
-factory_redirection_test/05: Fail
 factory_redirection_test/07: Fail
 final_variable_assignment_test/01: Fail
 final_variable_assignment_test/02: Fail
@@ -141,17 +132,12 @@
 positional_parameters_type_test: Fail
 
 # Compilation errors.
-default_factory3_test: Fail # type arguments on redirecting factory not implemented
-non_parameterized_factory_test: Fail # type arguments on redirecting factory not implemented
-non_parameterized_factory2_test: Fail # type arguments on redirecting factory not implemented
 const_var_test: Fail # Map literals take 2 type arguments.
 map_literal3_test: Fail # Map literals take 2 type arguments.
 ct_const_test: Fail # We don't take the generic type into account yet.
 dynamic_test: Fail # cannot resolve type F1
 constructor_redirect2_test/03: Fail # redirecting ctor with initializing formal
-factory2_test: Fail # internal error: visitIs for type variables not implemented
 factory3_test: Fail # internal error: visitIs for type variables not implemented
-factory5_test: Fail # internal error: visitIs for type variables not implemented
 function_type_alias2_test: Fail # cannot resolve type f1
 function_type_alias3_test: Fail # cannot resolve type F
 function_type_alias4_test: Fail # cannot resolve type F
@@ -221,7 +207,6 @@
 list_literal4_test: Fail # Illegal argument(s): 0 -- checked mode test.
 map_literal4_test: Fail # Attempt to modify an immutable object -- checked mode test.
 named_parameters_type_test: Fail # Expect.equals(expected: <111>, actual: <0>) fails. -- checked mode test.
-type_checks_in_factory_method_test: Fail # Expect.equals(expected: <true>, actual: <false>) fails. -- checked mode test.
 type_dartc_test: Fail # Expect.equals(expected: <1>, actual: <0>) -- checked mode test.
 
 class_cycle_negative_test: Fail, OK # Bad test: assumes eager loading.
@@ -321,7 +306,6 @@
 factory3_test: Fail
 stack_overflow_test: Fail
 stack_overflow_stacktrace_test: Fail
-type_checks_in_factory_method_test: Fail
 
 
 [ $compiler == dart2js && $runtime == safari ]
diff --git a/tests/language/local_function_non_equal_test.dart b/tests/language/local_function_non_equal_test.dart
new file mode 100644
index 0000000..a64b2cc
--- /dev/null
+++ b/tests/language/local_function_non_equal_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.
+
+import "package:expect/expect.dart";
+
+foo() => () => 42;
+bar() {
+  var c = () => 54;
+  return c;
+}
+baz() {
+  c() => 68;
+  return c;
+}
+
+main() {
+  var first = foo();
+  var second = foo();
+  Expect.isFalse(identical(first, second));
+  Expect.notEquals(first, second);
+
+  first = bar();
+  second = bar();
+  Expect.isFalse(identical(first, second));
+  Expect.notEquals(first, second);
+
+  first = baz();
+  second = baz();
+  Expect.isFalse(identical(first, second));
+  Expect.notEquals(first, second);
+}
diff --git a/tests/language/mixin_illegal_object_test.dart b/tests/language/mixin_illegal_object_test.dart
new file mode 100644
index 0000000..ef11ef1
--- /dev/null
+++ b/tests/language/mixin_illegal_object_test.dart
@@ -0,0 +1,14 @@
+// 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 C0 extends Object
+with Object                       /// 01: compile-time error
+{ }
+
+typedef C1 = Object with Object;  /// 02: compile-time error
+
+main() {
+  new C0();
+  new C1();                       /// 02: continued
+}
diff --git a/tests/language/null_is2_test.dart b/tests/language/null_is2_test.dart
new file mode 100644
index 0000000..1edf139
--- /dev/null
+++ b/tests/language/null_is2_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.
+
+import "package:expect/expect.dart";
+
+class Test<T> {
+  foo(a) => a is T;
+}
+
+main() {
+  Expect.isTrue(new Test<Object>().foo(null));
+  Expect.isTrue(new Test<dynamic>().foo(null));
+  Expect.isFalse(new Test<int>().foo(null));
+  Expect.isFalse(null is List<Object>);
+}
diff --git a/tests/language/regress_10996_lib.dart b/tests/language/regress_10996_lib.dart
new file mode 100644
index 0000000..77071a2
--- /dev/null
+++ b/tests/language/regress_10996_lib.dart
@@ -0,0 +1,10 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library regress_10996_lib;
+
+var a = 3;
+var b = 4;
+var c = 5;
+var d = 6;
diff --git a/tests/language/regress_10996_test.dart b/tests/language/regress_10996_test.dart
new file mode 100644
index 0000000..4aefa94
--- /dev/null
+++ b/tests/language/regress_10996_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 "package:expect/expect.dart";
+import "regress_10996_lib.dart" as lib;
+
+foo(a, [b]) {
+  return a + b + lib.a + lib.b;
+}
+
+bar(c, {d}) {
+  return c + d + lib.c + lib.d;
+}
+
+main() {
+  Expect.equals(1 + 2 + 3 + 4, foo(1, 2));
+  Expect.equals(7 + 8 + 3 + 4, foo(7, 8));
+  Expect.equals(3 + 4 + 5 + 6, bar(3, d: 4));
+  Expect.equals(7 + 8 + 5 + 6, bar(7, d: 8));
+}
diff --git a/tests/language/static_closure_identical_test.dart b/tests/language/static_closure_identical_test.dart
new file mode 100644
index 0000000..aa176a4
--- /dev/null
+++ b/tests/language/static_closure_identical_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.
+
+import "package:expect/expect.dart";
+
+var foo = main;
+
+main() {
+  Expect.equals(main, main);
+  Expect.identical(main, main);
+  Expect.equals(main.hashCode, main.hashCode);
+
+  Expect.equals(main, foo);
+  Expect.identical(main, foo);
+  Expect.equals(main.hashCode, foo.hashCode);
+}
diff --git a/tests/lib/async/slow_consumer2_test.dart b/tests/lib/async/slow_consumer2_test.dart
index 2108870..0c56f4a 100644
--- a/tests/lib/async/slow_consumer2_test.dart
+++ b/tests/lib/async/slow_consumer2_test.dart
@@ -71,6 +71,7 @@
 
   DataProvider(int this.bytesPerSecond, int this.targetCount, this.chunkSize) {
     controller = new StreamController(
+      sync: true,
       onPause: onPauseStateChange,
       onResume: onPauseStateChange);
     Timer.run(send);
diff --git a/tests/lib/async/slow_consumer_test.dart b/tests/lib/async/slow_consumer_test.dart
index a20ad6d..f4f6ef5 100644
--- a/tests/lib/async/slow_consumer_test.dart
+++ b/tests/lib/async/slow_consumer_test.dart
@@ -69,6 +69,7 @@
 
   DataProvider(int this.bytesPerSecond, int this.targetCount, this.chunkSize) {
     controller = new StreamController(
+      sync: true,
       onPause: onPauseStateChange,
       onResume: onPauseStateChange);
     Timer.run(send);
diff --git a/tests/lib/async/stream_controller_async_test.dart b/tests/lib/async/stream_controller_async_test.dart
index 65e658f..7c13405 100644
--- a/tests/lib/async/stream_controller_async_test.dart
+++ b/tests/lib/async/stream_controller_async_test.dart
@@ -10,6 +10,7 @@
 import 'dart:isolate';
 import '../../../pkg/unittest/lib/unittest.dart';
 import 'event_helper.dart';
+import 'stream_state_helper.dart';
 
 testController() {
   // Test fold
@@ -266,111 +267,91 @@
 
 testPause() {
   test("pause event-unpause", () {
-    StreamController c = new StreamController();
-    Events actualEvents = new Events.capture(c.stream);
-    Events expectedEvents = new Events();
-    expectedEvents.add(42);
-    c.add(42);
-    Expect.listEquals(expectedEvents.events, actualEvents.events);
+    StreamProtocolTest test = new StreamProtocolTest();
     Completer completer = new Completer();
-    actualEvents.pause(completer.future);
-    c..add(43)..add(44)..close();
-    Expect.listEquals(expectedEvents.events, actualEvents.events);
-    completer.complete();
-    expectedEvents..add(43)..add(44)..close();
-    actualEvents.onDone(expectAsync0(() {
-      Expect.listEquals(expectedEvents.events, actualEvents.events);
-    }));
+    test..expectListen()
+        ..expectData(42, () { test.pause(completer.future); })
+        ..expectPause(() {
+            completer.complete(null);
+          })
+        ..expectData(43)
+        ..expectData(44)
+        ..expectDone()
+        ..expectCancel();
+    test.listen();
+    test.add(42);
+    test.add(43);
+    test.add(44);
+    test.close();
   });
 
   test("pause twice event-unpause", () {
-    StreamController c = new StreamController();
-    Events actualEvents = new Events.capture(c.stream);
-    Events expectedEvents = new Events();
-    expectedEvents.add(42);
-    c.add(42);
-    Expect.listEquals(expectedEvents.events, actualEvents.events);
+    StreamProtocolTest test = new StreamProtocolTest();
     Completer completer = new Completer();
     Completer completer2 = new Completer();
-    actualEvents.pause(completer.future);
-    actualEvents.pause(completer2.future);
-    c..add(43)..add(44)..close();
-    Expect.listEquals(expectedEvents.events, actualEvents.events);
-    completer.complete();
-    Expect.listEquals(expectedEvents.events, actualEvents.events);
-    completer2.complete();
-    expectedEvents..add(43)..add(44)..close();
-    actualEvents.onDone(expectAsync0((){
-      Expect.listEquals(expectedEvents.events, actualEvents.events);
-    }));
+    test..expectListen()
+        ..expectData(42, () {
+            test.pause(completer.future);
+            test.pause(completer2.future);
+          })
+        ..expectPause(() {
+            completer.future.then(completer2.complete);
+            completer.complete(null);
+          })
+        ..expectData(43)
+        ..expectData(44)
+        ..expectDone()
+        ..expectCancel();
+    test..listen()
+        ..add(42)
+        ..add(43)
+        ..add(44)
+        ..close();
   });
 
   test("pause twice direct-unpause", () {
-    StreamController c = new StreamController();
-    Events actualEvents = new Events.capture(c.stream);
-    Events expectedEvents = new Events();
-    expectedEvents.add(42);
-    c.add(42);
-    Expect.listEquals(expectedEvents.events, actualEvents.events);
-    actualEvents.pause();
-    actualEvents.pause();
-    c.add(43);
-    c.add(44);
-    c.close();
-    Expect.listEquals(expectedEvents.events, actualEvents.events);
-    actualEvents.resume();
-    Expect.listEquals(expectedEvents.events, actualEvents.events);
-    expectedEvents..add(43)..add(44)..close();
-    actualEvents.onDone(expectAsync0(() {
-      Expect.listEquals(expectedEvents.events, actualEvents.events);
-    }));
-    actualEvents.resume();
+    StreamProtocolTest test = new StreamProtocolTest();
+    test..expectListen()
+        ..expectData(42, () {
+            test.pause();
+            test.pause();
+          })
+        ..expectPause(() {
+            test.resume();
+            test.resume();
+          })
+        ..expectData(43)
+        ..expectData(44)
+        ..expectDone()
+        ..expectCancel();
+    test..listen()
+        ..add(42)
+        ..add(43)
+        ..add(44)
+        ..close();
   });
 
   test("pause twice direct-event-unpause", () {
-    StreamController c = new StreamController();
-    Events actualEvents = new Events.capture(c.stream);
-    Events expectedEvents = new Events();
-    expectedEvents.add(42);
-    c.add(42);
-    Expect.listEquals(expectedEvents.events, actualEvents.events);
+    StreamProtocolTest test = new StreamProtocolTest();
     Completer completer = new Completer();
-    actualEvents.pause(completer.future);
-    actualEvents.pause();
-    c.add(43);
-    c.add(44);
-    c.close();
-    Expect.listEquals(expectedEvents.events, actualEvents.events);
-    actualEvents.resume();
-    Expect.listEquals(expectedEvents.events, actualEvents.events);
-    expectedEvents..add(43)..add(44)..close();
-    actualEvents.onDone(expectAsync0(() {
-      Expect.listEquals(expectedEvents.events, actualEvents.events);
-    }));
-    completer.complete();
-  });
-
-  test("pause twice direct-unpause", () {
-    StreamController c = new StreamController();
-    Events actualEvents = new Events.capture(c.stream);
-    Events expectedEvents = new Events();
-    expectedEvents.add(42);
-    c.add(42);
-    Expect.listEquals(expectedEvents.events, actualEvents.events);
-    Completer completer = new Completer();
-    actualEvents.pause(completer.future);
-    actualEvents.pause();
-    c.add(43);
-    c.add(44);
-    c.close();
-    Expect.listEquals(expectedEvents.events, actualEvents.events);
-    completer.complete();
-    Expect.listEquals(expectedEvents.events, actualEvents.events);
-    expectedEvents..add(43)..add(44)..close();
-    actualEvents.onDone(expectAsync0(() {
-      Expect.listEquals(expectedEvents.events, actualEvents.events);
-    }));
-    actualEvents.resume();
+    test..expectListen()
+        ..expectData(42, () {
+            test.pause();
+            test.pause(completer.future);
+            test.add(43);
+            test.add(44);
+            test.close();
+          })
+        ..expectPause(() {
+            completer.future.then((v) => test.resume());
+            completer.complete(null);
+          })
+        ..expectData(43)
+        ..expectData(44)
+        ..expectDone()
+        ..expectCancel();
+    test..listen()
+        ..add(42);
   });
 }
 
@@ -431,75 +412,89 @@
 
 void testBroadcastController() {
   test("broadcast-controller-basic", () {
-    StreamController<int> c = new StreamController.broadcast(
-      onListen: expectAsync0(() {}),
-      onCancel: expectAsync0(() {})
-    );
-    Stream<int> s = c.stream;
-    s.listen(expectAsync1((x) { expect(x, equals(42)); }));
-    c.add(42);
-    c.close();
+    StreamProtocolTest test = new StreamProtocolTest.broadcast();
+    test..expectListen()
+        ..expectData(42)
+        ..expectDone()
+        ..expectCancel(test.terminate);
+    test..listen()
+        ..add(42)
+        ..close();
   });
 
   test("broadcast-controller-listen-twice", () {
-    StreamController<int> c = new StreamController.broadcast(
-      onListen: expectAsync0(() {}),
-      onCancel: expectAsync0(() {})
-    );
-    c.stream.listen(expectAsync1((x) { expect(x, equals(42)); }, count: 2));
-    c.add(42);
-    c.stream.listen(expectAsync1((x) { expect(x, equals(42)); }));
-    c.add(42);
-    c.close();
+    StreamProtocolTest test = new StreamProtocolTest.broadcast();
+    test..expectListen()
+        ..expectData(42, () {
+            test.listen();
+            test.add(37);
+            test.close();
+          })
+      // Order is not guaranteed between subscriptions if not sync.
+        ..expectData(37)
+        ..expectData(37)
+        ..expectDone()
+        ..expectDone()
+        ..expectCancel(test.terminate);
+    test.listen();
+    test.add(42);
   });
 
   test("broadcast-controller-listen-twice-non-overlap", () {
-    StreamController<int> c = new StreamController.broadcast(
-      onListen: expectAsync0(() {}, count: 2),
-      onCancel: expectAsync0(() {}, count: 2)
-    );
-    var sub = c.stream.listen(expectAsync1((x) { expect(x, equals(42)); }));
-    c.add(42);
-    sub.cancel();
-    c.stream.listen(expectAsync1((x) { expect(x, equals(42)); }));
-    c.add(42);
-    c.close();
+    StreamProtocolTest test = new StreamProtocolTest.broadcast();
+    test
+    ..expectListen(() {
+      test.add(42);
+    })
+    ..expectData(42, () {
+      test.cancel();
+    })
+    ..expectCancel(() {
+      test.listen();
+    })..expectListen(() {
+      test.add(37);
+    })
+    ..expectData(37, () {
+      test.close();
+    })
+    ..expectDone()
+    ..expectCancel(test.terminate);
+    test.listen();
   });
 
   test("broadcast-controller-individual-pause", () {
-    StreamController<int> c = new StreamController.broadcast(
-      onListen: expectAsync0(() {}),
-      onCancel: expectAsync0(() {})
-    );
-    var sub1 = c.stream.listen(expectAsync1((x) { expect(x, equals(42)); }));
-    var sub2 = c.stream.listen(expectAsync1((x) { expect(x, equals(42)); },
-                                            count: 3));
-    c.add(42);
-    sub1.pause();
-    c.add(42);
-    sub1.cancel();
-    var sub3 = c.stream.listen(expectAsync1((x) { expect(x, equals(42)); }));
-    c.add(42);
-    c.close();
+    StreamProtocolTest test = new StreamProtocolTest.broadcast();
+    test.trace = true;
+    var sub1;
+    test..expectListen()
+        ..expectData(42)
+        ..expectData(42, () { sub1.pause(); })
+        ..expectData(43, () {
+      sub1.cancel();
+      test.listen();
+      test.add(44);
+      test.expectData(44);
+      test.expectData(44, test.terminate);
+    });
+    sub1 = test.listen();
+    test.listen();
+    test.add(42);
+    test.add(43);
   });
 
   test("broadcast-controller-add-in-callback", () {
-    StreamController<int> c;
-    c = new StreamController(
-      onListen: expectAsync0(() {}),
-      onCancel: expectAsync0(() {
-        c.add(42);
-      })
-    );
-    var sub;
-    sub = c.stream.asBroadcastStream().listen(expectAsync1((v) {
-      Expect.equals(37, v);
-      c.add(21);
+    StreamProtocolTest test = new StreamProtocolTest.broadcast();
+    test.expectListen();
+    var sub = test.listen();
+    test.add(42);
+    sub.expectData(42, () {
+      test.add(87);
       sub.cancel();
-    }));
-    c.add(37);  // Triggers listener, which adds 21 and removes itself.
-    // Removing listener triggers onCancel which adds another 42.
-    // Both 21 and 42 are lost because there are no listeners.
+    });
+    test.expectCancel(() {
+      test.add(37);
+      test.terminate();
+    });
   });
 }
 
diff --git a/tests/lib/async/stream_controller_test.dart b/tests/lib/async/stream_controller_test.dart
index 9990f44..b4aa6aa 100644
--- a/tests/lib/async/stream_controller_test.dart
+++ b/tests/lib/async/stream_controller_test.dart
@@ -11,7 +11,7 @@
 
 testMultiController() {
   // Test normal flow.
-  var c = new StreamController();
+  var c = new StreamController(sync: true);
   Events expectedEvents = new Events()
       ..add(42)
       ..add("dibs")
@@ -23,7 +23,7 @@
   Expect.listEquals(expectedEvents.events, actualEvents.events);
 
   // Test automatic unsubscription on error.
-  c = new StreamController();
+  c = new StreamController(sync: true);
   expectedEvents = new Events()..add(42)..error("error");
   actualEvents = new Events.capture(c.stream.asBroadcastStream(),
                                     cancelOnError: true);
@@ -33,7 +33,7 @@
   Expect.listEquals(expectedEvents.events, actualEvents.events);
 
   // Test manual unsubscription.
-  c = new StreamController();
+  c = new StreamController(sync: true);
   expectedEvents = new Events()..add(42)..error("error")..add(37);
   actualEvents = new Events.capture(c.stream.asBroadcastStream(),
                                     cancelOnError: false);
@@ -43,7 +43,7 @@
   Expect.listEquals(expectedEvents.events, actualEvents.events);
 
   // Test filter.
-  c = new StreamController();
+  c = new StreamController(sync: true);
   expectedEvents = new Events()
     ..add("a string")..add("another string")..close();
   sentEvents = new Events()
@@ -55,7 +55,7 @@
   Expect.listEquals(expectedEvents.events, actualEvents.events);
 
   // Test map.
-  c = new StreamController();
+  c = new StreamController(sync: true);
   expectedEvents = new Events()..add("abab")..error("error")..close();
   sentEvents = new Events()..add("ab")..error("error")..close();
   actualEvents = new Events.capture(c.stream
@@ -65,7 +65,7 @@
   Expect.listEquals(expectedEvents.events, actualEvents.events);
 
   // Test handleError.
-  c = new StreamController();
+  c = new StreamController(sync: true);
   expectedEvents = new Events()..add("ab")..error("[foo]");
   sentEvents = new Events()..add("ab")..error("foo")..add("ab")..close();
   actualEvents = new Events.capture(c.stream
@@ -82,7 +82,7 @@
   // reduce is tested asynchronously and therefore not in this file.
 
   // Test expand
-  c = new StreamController();
+  c = new StreamController(sync: true);
   sentEvents = new Events()..add(3)..add(2)..add(4)..close();
   expectedEvents = new Events()..add(1)..add(2)..add(3)
                                ..add(1)..add(2)
@@ -97,7 +97,7 @@
   Expect.listEquals(expectedEvents.events, actualEvents.events);
 
   // Test transform.
-  c = new StreamController();
+  c = new StreamController(sync: true);
   sentEvents = new Events()..add("a")..error(42)..add("b")..close();
   expectedEvents =
       new Events()..error("a")..add(42)..error("b")..add("foo")..close();
@@ -116,7 +116,7 @@
   Expect.listEquals(expectedEvents.events, actualEvents.events);
 
   // Test multiple filters.
-  c = new StreamController();
+  c = new StreamController(sync: true);
   sentEvents = new Events()..add(42)
                            ..add("snugglefluffy")
                            ..add(7)
@@ -136,7 +136,7 @@
   Expect.listEquals(expectedEvents.events, actualEvents.events);
 
   // Test subscription changes while firing.
-  c = new StreamController();
+  c = new StreamController(sync: true);
   var sink = c.sink;
   var stream = c.stream.asBroadcastStream();
   var counter = 0;
@@ -163,7 +163,7 @@
 
 testSingleController() {
   // Test normal flow.
-  var c = new StreamController();
+  var c = new StreamController(sync: true);
   Events expectedEvents = new Events()
       ..add(42)
       ..add("dibs")
@@ -175,7 +175,7 @@
   Expect.listEquals(expectedEvents.events, actualEvents.events);
 
   // Test automatic unsubscription on error.
-  c = new StreamController();
+  c = new StreamController(sync: true);
   expectedEvents = new Events()..add(42)..error("error");
   actualEvents = new Events.capture(c.stream, cancelOnError: true);
   Events sentEvents =
@@ -184,7 +184,7 @@
   Expect.listEquals(expectedEvents.events, actualEvents.events);
 
   // Test manual unsubscription.
-  c = new StreamController();
+  c = new StreamController(sync: true);
   expectedEvents = new Events()..add(42)..error("error")..add(37);
   actualEvents = new Events.capture(c.stream, cancelOnError: false);
   expectedEvents.replay(c);
@@ -193,7 +193,7 @@
   Expect.listEquals(expectedEvents.events, actualEvents.events);
 
   // Test filter.
-  c = new StreamController();
+  c = new StreamController(sync: true);
   expectedEvents = new Events()
     ..add("a string")..add("another string")..close();
   sentEvents = new Events()
@@ -203,7 +203,7 @@
   Expect.listEquals(expectedEvents.events, actualEvents.events);
 
   // Test map.
-  c = new StreamController();
+  c = new StreamController(sync: true);
   expectedEvents = new Events()..add("abab")..error("error")..close();
   sentEvents = new Events()..add("ab")..error("error")..close();
   actualEvents = new Events.capture(c.stream.map((v) => "$v$v"));
@@ -211,7 +211,7 @@
   Expect.listEquals(expectedEvents.events, actualEvents.events);
 
   // Test handleError.
-  c = new StreamController();
+  c = new StreamController(sync: true);
   expectedEvents = new Events()..add("ab")..error("[foo]");
   sentEvents = new Events()..add("ab")..error("foo")..add("ab")..close();
   actualEvents = new Events.capture(c.stream.handleError((error) {
@@ -226,7 +226,7 @@
   // reduce is tested asynchronously and therefore not in this file.
 
   // Test expand
-  c = new StreamController();
+  c = new StreamController(sync: true);
   sentEvents = new Events()..add(3)..add(2)..add(4)..close();
   expectedEvents = new Events()..add(1)..add(2)..add(3)
                                ..add(1)..add(2)
@@ -242,7 +242,7 @@
 
   // test contains.
   {
-    c = new StreamController();
+    c = new StreamController(sync: true);
     // Error after match is not important.
     sentEvents = new Events()..add("a")..add("x")..error("FAIL")..close();
     Future<bool> contains = c.stream.contains("x");
@@ -253,7 +253,7 @@
   }
 
   {
-    c = new StreamController();
+    c = new StreamController(sync: true);
     // Not matching is ok.
     sentEvents = new Events()..add("a")..add("x")..add("b")..close();
     Future<bool> contains = c.stream.contains("y");
@@ -264,7 +264,7 @@
   }
 
   {
-    c = new StreamController();
+    c = new StreamController(sync: true);
     // Error before match makes future err.
     sentEvents = new Events()..add("a")..error("FAIL")..add("b")..close();
     Future<bool> contains = c.stream.contains("b");
@@ -277,7 +277,7 @@
   }
 
   // Test transform.
-  c = new StreamController();
+  c = new StreamController(sync: true);
   sentEvents = new Events()..add("a")..error(42)..add("b")..close();
   expectedEvents =
       new Events()..error("a")..add(42)..error("b")..add("foo")..close();
@@ -293,7 +293,7 @@
   Expect.listEquals(expectedEvents.events, actualEvents.events);
 
   // Test multiple filters.
-  c = new StreamController();
+  c = new StreamController(sync: true);
   sentEvents = new Events()..add(42)
                            ..add("snugglefluffy")
                            ..add(7)
@@ -313,7 +313,7 @@
   Expect.listEquals(expectedEvents.events, actualEvents.events);
 
   // Test that only one subscription is allowed.
-  c = new StreamController();
+  c = new StreamController(sync: true);
   var sink = c.sink;
   var stream = c.stream;
   var counter = 0;
@@ -327,67 +327,67 @@
 testExtraMethods() {
   Events sentEvents = new Events()..add(1)..add(2)..add(3)..close();
 
-  var c = new StreamController();
+  var c = new StreamController(sync: true);
   Events expectedEvents = new Events()..add(3)..close();
   Events actualEvents = new Events.capture(c.stream.skip(2));
   sentEvents.replay(c);
   Expect.listEquals(expectedEvents.events, actualEvents.events);
 
-  c = new StreamController();
+  c = new StreamController(sync: true);
   expectedEvents = new Events()..close();
   actualEvents = new Events.capture(c.stream.skip(3));
   sentEvents.replay(c);
   Expect.listEquals(expectedEvents.events, actualEvents.events);
 
-  c = new StreamController();
+  c = new StreamController(sync: true);
   expectedEvents = new Events()..close();
   actualEvents = new Events.capture(c.stream.skip(7));
   sentEvents.replay(c);
   Expect.listEquals(expectedEvents.events, actualEvents.events);
 
-  c = new StreamController();
+  c = new StreamController(sync: true);
   expectedEvents = sentEvents;
   actualEvents = new Events.capture(c.stream.skip(0));
   sentEvents.replay(c);
   Expect.listEquals(expectedEvents.events, actualEvents.events);
 
 
-  c = new StreamController();
+  c = new StreamController(sync: true);
   expectedEvents = new Events()..add(3)..close();
   actualEvents = new Events.capture(c.stream.skipWhile((x) => x <= 2));
   sentEvents.replay(c);
   Expect.listEquals(expectedEvents.events, actualEvents.events);
 
 
-  c = new StreamController();
+  c = new StreamController(sync: true);
   expectedEvents = new Events()..add(2)..add(3)..close();
   actualEvents = new Events.capture(c.stream.skipWhile((x) => x <= 1));
   sentEvents.replay(c);
   Expect.listEquals(expectedEvents.events, actualEvents.events);
 
 
-  c = new StreamController();
+  c = new StreamController(sync: true);
   expectedEvents = new Events()..add(1)..add(2)..add(3)..close();
   actualEvents = new Events.capture(c.stream.skipWhile((x) => false));
   sentEvents.replay(c);
   Expect.listEquals(expectedEvents.events, actualEvents.events);
 
 
-  c = new StreamController();
+  c = new StreamController(sync: true);
   expectedEvents = new Events()..add(1)..add(2)..close();
   actualEvents = new Events.capture(c.stream.take(2));
   sentEvents.replay(c);
   Expect.listEquals(expectedEvents.events, actualEvents.events);
 
 
-  c = new StreamController();
+  c = new StreamController(sync: true);
   expectedEvents = new Events()..add(1)..add(2)..close();
   actualEvents = new Events.capture(c.stream.takeWhile((x) => x <= 2));
   sentEvents.replay(c);
   Expect.listEquals(expectedEvents.events, actualEvents.events);
 
 
-  c = new StreamController();
+  c = new StreamController(sync: true);
   sentEvents = new Events()
       ..add(1)..add(1)..add(2)..add(1)..add(2)..add(2)..add(2)..close();
   expectedEvents = new Events()
@@ -397,7 +397,7 @@
   Expect.listEquals(expectedEvents.events, actualEvents.events);
 
 
-  c = new StreamController();
+  c = new StreamController(sync: true);
   sentEvents = new Events()
       ..add(5)..add(6)..add(4)..add(6)..add(8)..add(3)..add(4)..add(1)..close();
   expectedEvents = new Events()
@@ -409,7 +409,7 @@
 }
 
 testClosed() {
-  StreamController c = new StreamController();
+  StreamController c = new StreamController(sync: true);
   Expect.isFalse(c.isClosed);
   c.add(42);
   Expect.isFalse(c.isClosed);
diff --git a/tests/lib/async/stream_event_transform_test.dart b/tests/lib/async/stream_event_transform_test.dart
index 87f114c..c10b8f5 100644
--- a/tests/lib/async/stream_event_transform_test.dart
+++ b/tests/lib/async/stream_event_transform_test.dart
@@ -46,7 +46,7 @@
 
 main() {
   {
-    StreamController c = new StreamController();
+    StreamController c = new StreamController(sync: true);
     Events expected = new Events()..error("0")..add(1)
                                   ..error("1")..add(2)
                                   ..add(3)..error("4")
@@ -61,7 +61,7 @@
   }
 
   {
-    StreamController c = new StreamController();
+    StreamController c = new StreamController(sync: true);
     Events expected = new Events()..error("0")..add(1)
                                   ..error("1")..add(2)
                                   ..add(3)..error("4")
diff --git a/tests/lib/async/stream_single_test.dart b/tests/lib/async/stream_single_test.dart
index fe0b384..4c3c486 100644
--- a/tests/lib/async/stream_single_test.dart
+++ b/tests/lib/async/stream_single_test.dart
@@ -13,21 +13,21 @@
 
 main() {
   test("single", () {
-    StreamController c = new StreamController();
+    StreamController c = new StreamController(sync: true);
     Future f = c.stream.single;
     f.then(expectAsync1((v) { Expect.equals(42, v);}));
     new Events.fromIterable([42]).replay(c);
   });
 
   test("single empty", () {
-    StreamController c = new StreamController();
+    StreamController c = new StreamController(sync: true);
     Future f = c.stream.single;
     f.catchError(expectAsync1((error) { Expect.isTrue(error is StateError); }));
     new Events.fromIterable([]).replay(c);
   });
 
   test("single error", () {
-    StreamController c = new StreamController();
+    StreamController c = new StreamController(sync: true);
     Future f = c.stream.single;
     f.catchError(expectAsync1((error) { Expect.equals("error", error); }));
     Events errorEvents = new Events()..error("error")..close();
@@ -35,7 +35,7 @@
   });
 
   test("single error 2", () {
-    StreamController c = new StreamController();
+    StreamController c = new StreamController(sync: true);
     Future f = c.stream.single;
     f.catchError(expectAsync1((error) { Expect.equals("error", error); }));
     Events errorEvents = new Events()..error("error")..error("error2")..close();
@@ -43,7 +43,7 @@
   });
 
   test("single error 3", () {
-    StreamController c = new StreamController();
+    StreamController c = new StreamController(sync: true);
     Future f = c.stream.single;
     f.catchError(expectAsync1((error) { Expect.equals("error", error); }));
     Events errorEvents = new Events()..add(499)..error("error")..close();
diff --git a/tests/lib/async/stream_single_to_multi_subscriber_test.dart b/tests/lib/async/stream_single_to_multi_subscriber_test.dart
index 1f4d693..8fd37e1 100644
--- a/tests/lib/async/stream_single_to_multi_subscriber_test.dart
+++ b/tests/lib/async/stream_single_to_multi_subscriber_test.dart
@@ -13,7 +13,7 @@
 
 main() {
   test("tomulti 1", () {
-    StreamController c = new StreamController<int>();
+    StreamController c = new StreamController<int>(sync: true);
     Stream<int> multi = c.stream.asBroadcastStream();
     // Listen twice.
     multi.listen(expectAsync1((v) => Expect.equals(42, v)));
@@ -22,7 +22,7 @@
   });
 
   test("tomulti 2", () {
-    StreamController c = new StreamController<int>();
+    StreamController c = new StreamController<int>(sync: true);
     Stream<int> multi = c.stream.asBroadcastStream();
     Events expected = new Events.fromIterable([1, 2, 3, 4, 5]);
     Events actual1 = new Events.capture(multi);
@@ -37,7 +37,7 @@
   });
 
   test("tomulti no-op", () {
-    StreamController c = new StreamController<int>();
+    StreamController c = new StreamController<int>(sync: true);
     Stream<int> multi = c.stream.asBroadcastStream();
     Events expected = new Events.fromIterable([1, 2, 3, 4, 5]);
     Events actual1 = new Events.capture(multi);
diff --git a/tests/lib/async/stream_state_helper.dart b/tests/lib/async/stream_state_helper.dart
index c433e39..1ab5a4c 100644
--- a/tests/lib/async/stream_state_helper.dart
+++ b/tests/lib/async/stream_state_helper.dart
@@ -8,46 +8,12 @@
 import "dart:async";
 import "dart:collection";
 
-class StreamProtocolTest {
-  bool trace = false;
-  StreamController _controller;
-  Stream _controllerStream;
+class SubscriptionProtocolTest {
+  final StreamProtocolTest _streamTest;
+  final int id;
   StreamSubscription _subscription;
-  List<Event> _expectations = new List<Event>();
-  int _nextExpectationIndex = 0;
-  Function _onComplete;
 
-  StreamProtocolTest([bool broadcast = false]) {
-    _controller = new StreamController(
-          onListen: _onSubcription,
-          onPause: _onPause,
-          onResume: _onResume,
-          onCancel: _onCancel);
-    if (broadcast) {
-      _controllerStream = _controller.stream.asBroadcastStream();
-    } else {
-      _controllerStream = _controller.stream;
-    }
-    _onComplete = expectAsync0((){
-      _onComplete = null;  // Being null marks the test to be complete.
-    });
-  }
-
-  // Actions on the stream and controller.
-  void add(var data) { _controller.add(data); }
-  void error(var error) { _controller.addError(error); }
-  void close() { _controller.close(); }
-
-  void subscribe({bool cancelOnError : false}) {
-    // TODO(lrn): Handle more subscriptions (e.g., a subscription-id
-    // per subscription, and an id on event _expectations).
-    if (_subscription != null) throw new StateError("Already subscribed");
-    _subscription = _controllerStream.listen(_onData,
-                                             onError: _onError,
-                                             onDone: _onDone,
-                                             cancelOnError:
-                                                 cancelOnError);
-  }
+  SubscriptionProtocolTest(this.id, this._subscription, this._streamTest);
 
   void pause([Future resumeSignal]) {
     if (_subscription == null) throw new StateError("Not subscribed");
@@ -65,34 +31,138 @@
     _subscription = null;
   }
 
+  void expectData(var data, [void action()]) {
+    _streamTest._expectData(this, data, action);
+  }
+
+  void expectError(var error, [void action()]) {
+    _streamTest._expectError(this, error, action);
+  }
+
+  void expectDone([void action()]) {
+    _streamTest._expectDone(this, action);
+  }
+}
+
+class StreamProtocolTest {
+  bool trace = false;
+  // If not a broadcast stream, the onComplete is called automatically by
+  // the first onCancel.
+  bool isBroadcast;
+  StreamController _controller;
+  Stream _controllerStream;
+  // Most recent subscription created. Used as default for pause/resume.
+  SubscriptionProtocolTest _latestSubscription;
+  List<Event> _expectations = new List<Event>();
+  int _nextExpectationIndex = 0;
+  int _subscriptionIdCounter = 0;
+  Function _onComplete;
+
+  StreamProtocolTest.broadcast({ bool sync: false })
+      : isBroadcast = true {
+    _controller = new StreamController.broadcast(
+        sync: sync,
+        onListen: _onListen,
+        onCancel: _onCancel);
+    _controllerStream = _controller.stream;
+    _onComplete = expectAsync0((){
+      _onComplete = null;  // Being null marks the test as being complete.
+    });
+  }
+
+  StreamProtocolTest({ bool broadcast: false, bool sync: false })
+      : isBroadcast = false {
+    _controller = new StreamController(
+        sync: sync,
+        onListen: _onListen,
+        onPause: _onPause,
+        onResume: _onResume,
+        onCancel: _onCancel);
+    if (broadcast) {
+      _controllerStream = _controller.stream.asBroadcastStream();
+    } else {
+      _controllerStream = _controller.stream;
+    }
+    _onComplete = expectAsync0((){
+      _onComplete = null;  // Being null marks the test as being complete.
+    });
+  }
+
+  // Actions on the stream and controller.
+  void add(var data) { _controller.add(data); }
+  void error(var error) { _controller.addError(error); }
+  void close() { _controller.close(); }
+
+  SubscriptionProtocolTest listen({bool cancelOnError : false}) {
+    int subscriptionId = _subscriptionIdCounter++;
+
+    StreamSubscription subscription = _controllerStream.listen(
+        (var data) { _onData(subscriptionId, data); },
+        onError: (Object error) { _onError(subscriptionId, error); },
+        onDone: () { _onDone(subscriptionId); },
+        cancelOnError: cancelOnError);
+    _latestSubscription =
+        new SubscriptionProtocolTest(subscriptionId, subscription, this);
+    if (trace) {
+      print("[Listen #$subscriptionId(#${_latestSubscription.hashCode})]");
+    }
+    return _latestSubscription;
+  }
+
+  // Actions on the most recently created subscription.
+  void pause([Future resumeSignal]) {
+    _latestSubscription.pause(resumeSignal);
+  }
+
+  void resume() {
+    _latestSubscription.resume();
+  }
+
+  void cancel() {
+    _latestSubscription.cancel();
+    _latestSubscription = null;
+  }
+
+  // End the test now. There must be no open expectations, and no furter
+  // expectations will be allowed.
+  // Called automatically by an onCancel event on a non-broadcast stream.
+  void terminate() {
+    if (_nextExpectationIndex != _expectations.length) {
+      _withNextExpectation((Event expect) {
+        _fail("Expected: $expect\n"
+              "Found   : Early termination.\n${expect._stackTrace}");
+      });
+    }
+    _onComplete();
+  }
+
   // Handling of stream events.
-  void _onData(var data) {
-    if (trace) print("[Data : $data]");
+  void _onData(int id, var data) {
+    if (trace) print("[Data#$id : $data]");
     _withNextExpectation((Event expect) {
-      if (!expect.matchData(data)) {
+      if (!expect.matchData(id, data)) {
         _fail("Expected: $expect\n"
-              "Found   : [Data: $data]");
+              "Found   : [Data#$id: $data]\n${expect._stackTrace}");
       }
     });
   }
 
-  void _onError(error) {
-    if (trace) print("[Error : $error]");
+  void _onError(int id, Object error) {
+    if (trace) print("[Error#$id : $error]");
     _withNextExpectation((Event expect) {
-      if (!expect.matchError(error)) {
+      if (!expect.matchError(id, error)) {
         _fail("Expected: $expect\n"
-              "Found   : [Error: ${error}]");
+              "Found   : [Error#$id: ${error}]\n${expect._stackTrace}");
       }
     });
   }
 
-  void _onDone() {
-    if (trace) print("[Done]");
-    _subscription = null;
+  void _onDone(int id) {
+    if (trace) print("[Done#$id]");
     _withNextExpectation((Event expect) {
-      if (!expect.matchDone()) {
+      if (!expect.matchDone(id)) {
         _fail("Expected: $expect\n"
-              "Found   : [Done]");
+              "Found   : [Done#$id]\n${expect._stackTrace}");
       }
     });
   }
@@ -102,7 +172,7 @@
     _withNextExpectation((Event expect) {
       if (!expect.matchPause()) {
         _fail("Expected: $expect\n"
-              "Found   : [Paused]");
+              "Found   : [Paused]\n${expect._stackTrace}");
       }
     });
   }
@@ -112,17 +182,17 @@
     _withNextExpectation((Event expect) {
       if (!expect.matchResume()) {
         _fail("Expected: $expect\n"
-              "Found   : [Resumed]");
+              "Found   : [Resumed]\n${expect._stackTrace}");
       }
     });
   }
 
-  void _onSubcription() {
+  void _onListen() {
     if (trace) print("[Subscribed]");
     _withNextExpectation((Event expect) {
       if (!expect.matchSubscribe()) {
         _fail("Expected: $expect\n"
-              "Found: [Subscribed]");
+              "Found: [Subscribed]\n${expect._stackTrace}");
       }
     });
   }
@@ -132,29 +202,22 @@
     _withNextExpectation((Event expect) {
       if (!expect.matchCancel()) {
         _fail("Expected: $expect\n"
-              "Found: [Cancelled]");
+              "Found: [Cancelled]\n${expect._stackTrace}");
       }
     });
+    if (!isBroadcast) terminate();
   }
 
   void _withNextExpectation(void action(Event expect)) {
     if (_nextExpectationIndex == _expectations.length) {
+      _nextExpectationIndex++;
       action(new MismatchEvent());
     } else {
-      Event next = _expectations[_nextExpectationIndex];
+      Event next = _expectations[_nextExpectationIndex++];
       action(next);
     }
-    _nextExpectationIndex++;
-    _checkDone();
   }
 
-  void _checkDone() {
-    if (_nextExpectationIndex == _expectations.length) {
-      _onComplete();
-    }
-  }
-
-
   // Adds _expectations.
   void expectAny([void action()]) {
     if (_onComplete == null) {
@@ -162,43 +225,62 @@
     }
     _expectations.add(new LogAnyEvent(action));
   }
+
   void expectData(var data, [void action()]) {
+    _expectData(null, data, action);
+  }
+
+  void _expectData(SubscriptionProtocolTest sub, var data, void action()) {
     if (_onComplete == null) {
       _fail("Adding expectation after completing");
     }
-    _expectations.add(new DataEvent(data, action));
+    _expectations.add(new DataEvent(sub, data, action));
   }
+
   void expectError(var error, [void action()]) {
+    _expectError(null, error, action);
+  }
+
+  void _expectError(SubscriptionProtocolTest sub, var error, void action()) {
     if (_onComplete == null) {
       _fail("Adding expectation after completing");
     }
-    _expectations.add(new ErrorEvent(error, action));
+    _expectations.add(new ErrorEvent(sub, error, action));
   }
+
   void expectDone([void action()]) {
+    _expectDone(null, action);
+  }
+
+  void _expectDone(SubscriptionProtocolTest sub, [void action()]) {
     if (_onComplete == null) {
       _fail("Adding expectation after completing");
     }
-    _expectations.add(new DoneEvent(action));
+    _expectations.add(new DoneEvent(sub, action));
   }
+
   void expectPause([void action()]) {
     if (_onComplete == null) {
       _fail("Adding expectation after completing");
     }
     _expectations.add(new PauseCallbackEvent(action));
   }
+
   void expectResume([void action()]) {
     if (_onComplete == null) {
       _fail("Adding expectation after completing");
     }
     _expectations.add(new ResumeCallbackEvent(action));
   }
-  void expectSubscription([void action()]) {
+
+  void expectListen([void action()]) {
     if (_onComplete == null) {
       _fail("Adding expectation after completing");
     }
     _expectations.add(
           new SubscriptionCallbackEvent(action));
   }
+
   void expectCancel([void action()]) {
     if (_onComplete == null) {
       _fail("Adding expectation after completing");
@@ -211,45 +293,58 @@
     if (_nextExpectationIndex == 0) {
       throw "Unexpected event:\n$message\nNo earlier events matched.";
     }
-    throw "Unexpected event:\n$message\nMatched so far:\n"
-          " ${_expectations.take(_nextExpectationIndex).join("\n ")}";
+    StringBuffer buf = new StringBuffer();
+    for (int i = 0; i < _expectations.length; i++) {
+      if (i == _nextExpectationIndex - 1) {
+        buf.write("->");
+      } else {
+        buf.write("  ");
+      }
+      buf.write(_expectations[i]);
+      buf.write("\n");
+    }
+    throw "Unexpected event:\n$message\nAll expectations:\n$buf";
   }
 }
 
 class Event {
   Function _action;
-  Event(void this._action());
+  StackTrace _stackTrace;
+  Event(void action())
+      : _action = (action == null) ? null : expectAsync0(action) {
+    try { throw 0; } catch (_, s) { _stackTrace = s; }
+  }
 
-  bool matchData(var data) {
-    if (!_testData(data)) return false;
-    if (_action != null) _action();
-    return true;
+  bool matchData(int id, var data) {
+    return false;
   }
-  bool matchError(e) {
-    if (!_testError(e)) return false;
-    if (_action != null) _action();
-    return true;
+
+  bool matchError(int id, e) {
+    return false;
   }
-  bool matchDone() {
-    if (!_testDone()) return false;
-    if (_action != null) _action();
-    return true;
+
+  bool matchDone(int id) {
+    return false;
   }
+
   bool matchPause() {
     if (!_testPause()) return false;
     if (_action != null) _action();
     return true;
   }
+
   bool matchResume() {
     if (!_testResume()) return false;
     if (_action != null) _action();
     return true;
   }
+
   bool matchSubscribe() {
     if (!_testSubscribe()) return false;
     if (_action != null) _action();
     return true;
   }
+
   bool matchCancel() {
     if (!_testCancel()) return false;
     if (_action != null) _action();
@@ -265,29 +360,59 @@
   bool _testCancel() => false;
 }
 
+class SubscriptionEvent extends Event {
+  SubscriptionProtocolTest subscription;
+  SubscriptionEvent(this.subscription, void action()) : super(action);
+
+  bool matchData(int id, var data) {
+    if (subscription != null && subscription.id != id) return false;
+    if (!_testData(data)) return false;
+    if (_action != null) _action();
+    return true;
+  }
+
+  bool matchError(int id, e) {
+    if (subscription != null && subscription.id != id) return false;
+    if (!_testError(e)) return false;
+    if (_action != null) _action();
+    return true;
+  }
+
+  bool matchDone(int id) {
+    if (subscription != null && subscription.id != id) return false;
+    if (!_testDone()) return false;
+    if (_action != null) _action();
+    return true;
+  }
+
+  String get _id => (subscription == null) ? "" : "#${subscription.id}";
+}
+
 class MismatchEvent extends Event {
   MismatchEvent() : super(null);
   toString() => "[No event expected]";
 }
 
-class DataEvent extends Event {
+class DataEvent extends SubscriptionEvent {
   final data;
-  DataEvent(this.data, void action()) : super(action);
+  DataEvent(SubscriptionProtocolTest sub, this.data, void action())
+      : super(sub, action);
   bool _testData(var data) => this.data == data;
-  String toString() => "[Data: $data]";
+  String toString() => "[Data$_id: $data]";
 }
 
-class ErrorEvent extends Event {
+class ErrorEvent extends SubscriptionEvent {
   final error;
-  ErrorEvent(this.error, void action()) : super(action);
+  ErrorEvent(SubscriptionProtocolTest sub, this.error, void action())
+      : super(sub, action);
   bool _testError(error) => this.error == error;
-  String toString() => "[Error: $error]";
+  String toString() => "[Error$_id: $error]";
 }
 
-class DoneEvent extends Event {
-  DoneEvent(void action()) : super(action);
+class DoneEvent extends SubscriptionEvent {
+  DoneEvent(SubscriptionProtocolTest sub, void action()) : super(sub, action);
   bool _testDone() => true;
-  String toString() => "[Done]";
+  String toString() => "[Done$_id]";
 }
 
 class PauseCallbackEvent extends Event {
@@ -314,38 +439,47 @@
   String toString() => "[Cancelled]";
 }
 
-
+/** Event matcher that matches any other event. */
 class LogAnyEvent extends Event {
   String _actual = "*Not matched yet*";
+
   LogAnyEvent(void action()) : super(action);
+
   bool _testData(var data) {
     _actual = "*[Data $data]";
     return true;
   }
+
   bool _testError(error) {
     _actual = "*[Error ${error}]";
     return true;
   }
+
   bool _testDone() {
     _actual = "*[Done]";
     return true;
   }
+
   bool _testPause() {
     _actual = "*[Paused]";
     return true;
   }
+
   bool _testResume() {
     _actual = "*[Resumed]";
     return true;
   }
+
   bool _testSubcribe() {
     _actual = "*[Subscribed]";
     return true;
   }
+
   bool _testCancel() {
     _actual = "*[Cancelled]";
     return true;
   }
 
+  /** Returns a representation of the event it was tested against. */
   String toString() => _actual;
 }
diff --git a/tests/lib/async/stream_state_nonzero_timer_test.dart b/tests/lib/async/stream_state_nonzero_timer_test.dart
index 0beff6f..38c14a6 100644
--- a/tests/lib/async/stream_state_nonzero_timer_test.dart
+++ b/tests/lib/async/stream_state_nonzero_timer_test.dart
@@ -23,8 +23,8 @@
   var p = broadcast ? "BC" : "SC";
 
   test("$p-sub-data/pause/resume/pause/resume-done", () {
-    var t = new StreamProtocolTest(broadcast);
-    t..expectSubscription()
+    var t = new StreamProtocolTest(broadcast: broadcast);
+    t..expectListen()
      ..expectData(42, () {
          t.pause();
        })
@@ -34,12 +34,12 @@
      ..expectResume(() { t.close(); })
      ..expectDone()
      ..expectCancel();
-    t..subscribe()..add(42);
+    t..listen()..add(42);
   });
 
   test("$p-sub-data/pause-done", () {
-    var t = new StreamProtocolTest(broadcast);
-    t..expectSubscription()
+    var t = new StreamProtocolTest(broadcast: broadcast);
+    t..expectListen()
      ..expectData(42, () {
          t.pause(new Future.delayed(ms5, () => null));
        })
@@ -48,12 +48,12 @@
      ..expectCancel();
      // We are calling "close" while the controller is actually paused,
      // and it will stay paused until the pending events are sent.
-    t..subscribe()..add(42)..close();
+    t..listen()..add(42)..close();
   });
 
   test("$p-sub-data/pause-resume/done", () {
-    var t = new StreamProtocolTest(broadcast);
-    t..expectSubscription()
+    var t = new StreamProtocolTest(broadcast: broadcast);
+    t..expectListen()
      ..expectData(42, () {
          t.pause(new Future.delayed(ms5, () => null));
        })
@@ -61,12 +61,12 @@
      ..expectResume(t.close)
      ..expectDone()
      ..expectCancel();
-    t..subscribe()..add(42);
+    t..listen()..add(42);
   });
 
   test("$p-sub-data/data+pause-data-resume-done", () {
-    var t = new StreamProtocolTest(broadcast);
-    t..expectSubscription()
+    var t = new StreamProtocolTest(broadcast: broadcast);
+    t..expectListen()
      ..expectData(42, () {
          t.add(43);
          t.pause(new Future.delayed(ms5, () => null));
@@ -79,12 +79,12 @@
      ..expectResume(t.close)
      ..expectDone()
      ..expectCancel();
-    t..subscribe()..add(42);
+    t..listen()..add(42);
   });
-return;
+
   test("$p-pause-during-callback", () {
-    var t = new StreamProtocolTest(broadcast);
-    t..expectSubscription()
+    var t = new StreamProtocolTest(broadcast: broadcast);
+    t..expectListen()
      ..expectData(42, () {
        t.pause();
      })
@@ -98,7 +98,7 @@
      })
      ..expectDone()
      ..expectCancel();
-    t..subscribe()
+    t..listen()
      ..add(42);
   });
 }
diff --git a/tests/lib/async/stream_state_test.dart b/tests/lib/async/stream_state_test.dart
index 08cb7a1..bee7f9b 100644
--- a/tests/lib/async/stream_state_test.dart
+++ b/tests/lib/async/stream_state_test.dart
@@ -11,38 +11,44 @@
 const ms5 = const Duration(milliseconds: 5);
 
 main() {
-  mainTest(false);
-  // TODO(floitsch): reenable?
-  // mainTest(true);
+  mainTest(sync: true, broadcast: false);
+  mainTest(sync: true, broadcast: true);
+  mainTest(sync: false, broadcast: false);
+  mainTest(sync: false, broadcast: true);
 }
 
-mainTest(bool broadcast) {
-  var p = broadcast ? "BC" : "SC";
+mainTest({bool sync, bool broadcast}) {
+  var p = (sync ? "S" : "AS") + (broadcast ? "BC" : "SC");
   test("$p-sub-data-done", () {
-    var t = new StreamProtocolTest(broadcast);
-    t..expectSubscription()
+    var t = new StreamProtocolTest(sync: sync, broadcast: broadcast);
+    t..expectListen()
      ..expectData(42)
      ..expectDone()
      ..expectCancel();
-    t..subscribe()..add(42)..close();
+    t..listen()..add(42)..close();
   });
 
-  test("$p-data-done-sub", () {
-    var t = new StreamProtocolTest(broadcast);
-    if (broadcast) {
-      t..expectDone();
-    } else {
-      t..expectSubscription()
-       ..expectData(42)
-       ..expectDone()
-       ..expectCancel();
-    }
-    t..add(42)..close()..subscribe();
+  test("$p-data-done-sub-sync", () {
+    var t = new StreamProtocolTest(sync: sync, broadcast: broadcast);
+    t..expectListen()
+     ..expectData(42)
+     ..expectDone()
+     ..expectCancel();
+    t..add(42)..close()..listen();
+  });
+
+  test("$p-data-done-sub-async", () {
+    var t = new StreamProtocolTest(sync: sync, broadcast: broadcast);
+    t..expectListen()
+     ..expectData(42)
+     ..expectDone()
+     ..expectCancel();
+    t..add(42)..close()..listen();
   });
 
   test("$p-sub-data/pause+resume-done", () {
-    var t = new StreamProtocolTest(broadcast);
-    t..expectSubscription()
+    var t = new StreamProtocolTest(sync: sync, broadcast: broadcast);
+    t..expectListen()
      ..expectData(42, () {
          t.pause();
          t.resume();
@@ -50,16 +56,16 @@
        })
      ..expectDone()
      ..expectCancel();
-    t..subscribe()..add(42);
+    t..listen()..add(42);
   });
 
   test("$p-sub-data-unsubonerror", () {
-    var t = new StreamProtocolTest(broadcast);
-    t..expectSubscription()
+    var t = new StreamProtocolTest(sync: sync, broadcast: broadcast);
+    t..expectListen()
      ..expectData(42)
      ..expectError("bad")
      ..expectCancel();
-    t..subscribe(cancelOnError: true)
+    t..listen(cancelOnError: true)
      ..add(42)
      ..error("bad")
      ..add(43)
@@ -67,14 +73,14 @@
   });
 
   test("$p-sub-data-no-unsubonerror", () {
-    var t = new StreamProtocolTest(broadcast);
-    t..expectSubscription()
+    var t = new StreamProtocolTest(sync: sync, broadcast: broadcast);
+    t..expectListen()
      ..expectData(42)
      ..expectError("bad")
      ..expectData(43)
      ..expectDone()
      ..expectCancel();
-    t..subscribe(cancelOnError: false)
+    t..listen(cancelOnError: false)
      ..add(42)
      ..error("bad")
      ..add(43)
@@ -82,15 +88,18 @@
   });
 
   test("$p-pause-resume-during-event", () {
-    var t = new StreamProtocolTest(broadcast);
-    t..expectSubscription()
+    var t = new StreamProtocolTest(sync: sync, broadcast: broadcast);
+    t..expectListen()
      ..expectData(42, () {
        t.pause();
        t.resume();
-     })
-     ..expectDone()
+     });
+    if (!broadcast && !sync) {
+      t..expectPause();
+    }
+    t..expectDone()
      ..expectCancel();
-    t..subscribe()
+    t..listen()
      ..add(42)
      ..close();
   });
diff --git a/tests/lib/async/stream_subscription_as_future_test.dart b/tests/lib/async/stream_subscription_as_future_test.dart
index 5be8f79..3c2c082 100644
--- a/tests/lib/async/stream_subscription_as_future_test.dart
+++ b/tests/lib/async/stream_subscription_as_future_test.dart
@@ -20,7 +20,7 @@
   });
 
   test("subscription.asStream success2", () {
-    StreamController controller = new StreamController();
+    StreamController controller = new StreamController(sync: true);
     [1, 2, 3].forEach(controller.add);
     controller.close();
     Stream stream = controller.stream;
@@ -41,7 +41,7 @@
   });
 
   test("subscription.asStream failure", () {
-    StreamController controller = new StreamController();
+    StreamController controller = new StreamController(sync: true);
     [1, 2, 3].forEach(controller.add);
     controller.addError("foo");
     controller.close();
diff --git a/tests/lib/async/stream_transform_test.dart b/tests/lib/async/stream_transform_test.dart
index 414c02c..fc6a3cf 100644
--- a/tests/lib/async/stream_transform_test.dart
+++ b/tests/lib/async/stream_transform_test.dart
@@ -14,7 +14,7 @@
   // Regression tests for http://dartbug.com/8310 and 8311
 
   test("simpleDone", () {
-    StreamController c = new StreamController();
+    StreamController c = new StreamController(sync: true);
     Stream out = c.stream.handleError((x){}).handleError((x){});
     out.listen((v){}, onDone: expectAsync0(() {}));
     // Should not throw.
@@ -22,7 +22,7 @@
   });
 
   test("with events", () {
-    StreamController c = new StreamController();
+    StreamController c = new StreamController(sync: true);
     Events expected = new Events.fromIterable([10, 12]);
     Events input = new Events.fromIterable([1, 2, 3, 4, 5, 6, 7]);
     Events actual = new Events.capture(
@@ -34,7 +34,7 @@
   });
 
   test("paused events", () {
-    StreamController c = new StreamController();
+    StreamController c = new StreamController(sync: true);
     Events expected = new Events.fromIterable([10, 12]);
     Events input = new Events.fromIterable([1, 2, 3, 4, 5, 6, 7]);
     Events actual = new Events.capture(
@@ -48,7 +48,7 @@
   });
 
   test("closing after done", () {
-    var controller = new StreamController();
+    var controller = new StreamController(sync: true);
     controller.stream.map((e) => e).transform(new StreamTransformer(
         handleData: (element, sink) { sink.add(element); },
         handleDone: (sink) { sink.close(); })
diff --git a/tests/lib/lib.status b/tests/lib/lib.status
index f905060..a1bd9e0 100644
--- a/tests/lib/lib.status
+++ b/tests/lib/lib.status
@@ -2,16 +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.
 
-# The typed_data library is not supported by dart2js or dart2dart yet.
-[ $compiler == dart2js  || $compiler == dart2dart ]
-typed_data/*: Fail
-
-
-# The typed_data library is not supported by dart2js or dart2dart yet.
-[ $compiler == dart2js  || $compiler == dart2dart ]
-typed_data/*: Skip
-
-
 [ $compiler == dart2js ]
 math/*: Skip
 mirrors/mirrors_test: Fail # TODO(ahe): I'm working on fixing this.
@@ -20,6 +10,15 @@
 async/run_async4_test: Pass, Fail # no global exception handler in isolates. http://dartbug.com/9012
 async/run_async6_test: Fail # global error handling is not supported. http://dartbug.com/5958
 
+# SIMD is unsupported on dart2js.
+typed_data/float32x4_test: Fail, OK
+typed_data/float32x4_list_test: Fail, OK
+typed_data/float32x4_unbox_phi_test: Fail, OK
+typed_data/float32x4_unbox_regress_test: Fail, OK
+
+[ $compiler == dart2js && ($runtime == d8 || $runtime == ie9) ]
+typed_data/byte_data_test: Fail, OK # d8/ie9 doesn't support DataView
+
 [ $compiler == dart2js && $minified ]
 mirrors/mirrors_resolve_fields_test: Fail # Issue 6490
 
@@ -61,8 +60,16 @@
                                          # implement timer (currently only in d8)
 
 [ $compiler == dart2dart ]
-# Skip until we stabilize language tests.
-*: Skip
+mirrors/mirrors_test: Fail              # Issue 10957
+mirrors/library_uri_package_test: Fail  # Issue 10957
+async/run_async6_test: Fail             # Issue 10957 - may be related to issue 10910
+
+[ $compiler == dart2dart && $minified ]
+json/json_test: Fail                           # Issue 10961
+typed_data/float32x4_test: Fail                # Issue 10961
+typed_data/float32x4_list_test: Fail           # Issue 10961
+typed_data/float32x4_unbox_phi_test: Fail      # Issue 10961
+typed_data/float32x4_unbox_regress_test: Fail  # Issue 10961
 
 [ $runtime == safari]
  # Bug in JSC: the test only passes when being debugged.
@@ -88,6 +95,7 @@
 
 [ $runtime == vm || ($compiler == none && $runtime == drt) ]
 async/run_async3_test: Fail # _enqueueImmediate runs after Timer. http://dartbug.com/9001.
+mirrors/metadata_test: Fail # http://dartbug.com/10906
 
 [ $compiler == none && $runtime == drt ]
 async/timer_isolate_test: Skip # See Issue 4997
@@ -96,6 +104,13 @@
 mirrors/library_uri_io_test: Skip # Not intended for drt as it uses dart:io.
 async/run_async6_test: Fail # Issue 10910
 
+[ $compiler == none && $runtime == drt && $system == windows ]
+async/multiple_timer_test: Fail # See Issue 10982
+async/timer_test: Fail # See Issue 10982
+
+[ $arch == arm ]
+*: Skip
+
 [ $arch == simarm ]
 *: Skip
 
diff --git a/tests/lib/mirrors/metadata_test.dart b/tests/lib/mirrors/metadata_test.dart
new file mode 100644
index 0000000..973bf34
--- /dev/null
+++ b/tests/lib/mirrors/metadata_test.dart
@@ -0,0 +1,48 @@
+// 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.
+
+@fisk @symbol
+library test.metadata_test;
+
+import 'dart:mirrors';
+
+const fisk = 'a metadata string';
+
+const symbol = const Symbol('fisk');
+
+@symbol @fisk
+class MyClass {
+}
+
+checkMetadata(DeclarationMirror mirror, List expectedMetadata) {
+  List metadata = mirror.metadata.map((m) => m.reflectee).toList();
+  if (metadata == null) {
+    throw 'Null metadata on $mirror';
+  }
+  int expectedLength = expectedMetadata.length;
+  int actualLength = metadata.length;
+  if (expectedLength != actualLength) {
+    throw 'Expected length = $expectedLength, but got length = $actualLength.';
+  }
+  for (int i = 0; i < expectedLength; i++) {
+    if (metadata[i] != expectedMetadata[i]) {
+      throw '${metadata[i]} is not "${expectedMetadata[i]}"'
+          ' in $mirror at index $i';
+    }
+  }
+  print(metadata);
+}
+
+main() {
+  if (MirrorSystem.getName(symbol) != 'fisk') {
+    // This happened in dart2js due to how early library metadata is
+    // computed.
+    throw 'Bad constant: $symbol';
+  }
+
+  MirrorSystem mirrors = currentMirrorSystem();
+  checkMetadata(mirrors.findLibrary(const Symbol('test.metadata_test')).first,
+                [fisk, symbol]);
+  checkMetadata(reflect(new MyClass()).type, [symbol, fisk]);
+}
diff --git a/tests/lib/typed_data/byte_data_test.dart b/tests/lib/typed_data/byte_data_test.dart
new file mode 100644
index 0000000..cffa631
--- /dev/null
+++ b/tests/lib/typed_data/byte_data_test.dart
@@ -0,0 +1,40 @@
+// 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 'dart:typed_data';
+
+main() {
+  testRegress10898();
+}
+
+testRegress10898() {
+  ByteData data = new ByteData(16);
+  Expect.equals(16, data.lengthInBytes);
+  for (int i = 0; i < data.lengthInBytes; i++) {
+    Expect.equals(0, data.getInt8(i));
+    data.setInt8(i, 42 + i);
+    Expect.equals(42 + i, data.getInt8(i));
+  }
+
+  ByteData backing = new ByteData(16);
+  ByteData view = new ByteData.view(backing.buffer);
+  for (int i = 0; i < view.lengthInBytes; i++) {
+    Expect.equals(0, view.getInt8(i));
+    view.setInt8(i, 87 + i);
+    Expect.equals(87 + i, view.getInt8(i));
+  }
+
+  view = new ByteData.view(backing.buffer, 4);
+  Expect.equals(12, view.lengthInBytes);
+  for (int i = 0; i < view.lengthInBytes; i++) {
+    Expect.equals(87 + i + 4, view.getInt8(i));
+  }
+
+  view = new ByteData.view(backing.buffer, 8, 4);
+  Expect.equals(4, view.lengthInBytes);
+  for (int i = 0; i < view.lengthInBytes; i++) {
+    Expect.equals(87 + i + 8, view.getInt8(i));
+  }
+}
diff --git a/tests/lib/typed_data/typed_list_iterable_test.dart b/tests/lib/typed_data/typed_list_iterable_test.dart
new file mode 100644
index 0000000..4d4a3db
--- /dev/null
+++ b/tests/lib/typed_data/typed_list_iterable_test.dart
@@ -0,0 +1,180 @@
+// 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 'dart:typed_data';
+
+void testIterableFunctions(list, first, last) {
+  assert(list.length > 0);
+
+  Expect.equals(first, list.first);
+  Expect.equals(last, list.last);
+  Expect.equals(first, list.firstWhere((x) => x == first));
+  Expect.equals(last, list.lastWhere((x) => x == last));
+  if (list.length == 1) {
+    Expect.equals(first, list.single);
+    Expect.equals(first, list.singleWhere((x) => x == last));
+  } else {
+    Expect.throws(() => list.single, (e) => e is StateError);
+    bool isFirst = true;
+    Expect.equals(first, list.singleWhere((x) {
+      if (isFirst) {
+        isFirst = false;
+        return true;
+      }
+      return false;
+    }));
+  }
+  Expect.isFalse(list.isEmpty);
+
+  int i = 0;
+  for (var x in list) {
+    Expect.equals(list[i++], x);
+  }
+  Expect.isTrue(list.any((x) => x == last));
+  Expect.isFalse(list.any((x) => false));
+  Expect.isTrue(list.contains(last));
+  Expect.equals(first, list.elementAt(0));
+  Expect.isTrue(list.every((x) => true));
+  Expect.isFalse(list.every((x) => x != last));
+  Expect.listEquals([], list.expand((x) => []).toList());
+  var expand2 = list.expand((x) => [x, x]);
+  i = 0;
+  for (var x in expand2) {
+    Expect.equals(list[i ~/ 2], x);
+    i++;
+  }
+  Expect.equals(2 * list.length, i);
+  Expect.listEquals(list, list.fold([], (result, x) => result..add(x)));
+  i = 0;
+  list.forEach((x) {
+    Expect.equals(list[i++], x);
+  });
+  Expect.equals(list.toList().join("*"), list.join("*"));
+  Expect.listEquals(list, list.map((x) => x).toList());
+  int mapCount = 0;
+  var mappedList = list.map((x) {
+    mapCount++;
+    return x;
+  });
+  Expect.equals(0, mapCount);
+  Expect.equals(list.length, mappedList.length);
+  Expect.equals(0, mapCount);
+  mappedList.join();
+  Expect.equals(list.length, mapCount);
+
+  Expect.listEquals(list, list.where((x) => true).toList());
+  int whereCount = 0;
+  var whereList = list.where((x) {
+    whereCount++;
+    return true;
+  });
+  Expect.equals(0, whereCount);
+  Expect.equals(list.length, whereList.length);
+  Expect.equals(list.length, whereCount);
+
+  if (list.length > 1) {
+    int reduceResult = 1;
+    Expect.equals(list.length, list.reduce((x, y) => ++reduceResult));
+  } else {
+    Expect.equals(first, list.reduce((x, y) { throw "should not be called"; }));
+  }
+
+  Expect.isTrue(list.skip(list.length).isEmpty);
+  Expect.listEquals(list, list.skip(0).toList());
+  Expect.isTrue(list.skipWhile((x) => true).isEmpty);
+  Expect.listEquals(list, list.skipWhile((x) => false).toList());
+  Expect.listEquals(list, list.take(list.length).toList());
+  Expect.isTrue(list.take(0).isEmpty);
+  Expect.isTrue(list.takeWhile((x) => false).isEmpty);
+  Expect.listEquals(list, list.takeWhile((x) => true).toList());
+  Expect.listEquals(list, list.toList().toList());
+  var l2 = list.toList();
+  l2.add(first);
+  Expect.equals(first, l2.last);
+  var l3 = list.toList(growable: false);
+  Expect.throws(() => l3.add(last), (e) => e is UnsupportedError);
+}
+
+void emptyChecks(list) {
+  assert(list.length == 0);
+
+  Expect.isTrue(list.isEmpty);
+
+  Expect.throws(() => list.first, (e) => e is StateError);
+  Expect.throws(() => list.last, (e) => e is StateError);
+  Expect.throws(() => list.single, (e) => e is StateError);
+  Expect.throws(() => list.firstWhere((x) => true), (e) => e is StateError);
+  Expect.throws(() => list.lastWhere((x) => true), (e) => e is StateError);
+  Expect.throws(() => list.singleWhere((x) => true), (e) => e is StateError);
+
+  Expect.isFalse(list.any((x) => true));
+  Expect.isFalse(list.contains(null));
+  Expect.throws(() => list.elementAt(0), (e) => e is RangeError);
+  Expect.isTrue(list.every((x) => false));
+  Expect.listEquals([], list.expand((x) => []).toList());
+  Expect.listEquals([], list.expand((x) => [x, x]).toList());
+  Expect.listEquals(
+      [], list.expand((x) { throw "should not be reached"; }).toList());
+  Expect.listEquals([], list.fold([], (result, x) => result..add(x)));
+  Expect.equals(list.toList().join("*"), list.join("*"));
+  Expect.listEquals(list, list.map((x) => x).toList());
+  int mapCount = 0;
+  var mappedList = list.map((x) {
+    mapCount++;
+    return x;
+  });
+  Expect.equals(0, mapCount);
+  Expect.equals(list.length, mappedList.length);
+  Expect.equals(0, mapCount);
+  mappedList.join();
+  Expect.equals(list.length, mapCount);
+
+  Expect.listEquals(list, list.where((x) => true).toList());
+  int whereCount = 0;
+  var whereList = list.where((x) {
+    whereCount++;
+    return true;
+  });
+  Expect.equals(0, whereCount);
+  Expect.equals(list.length, whereList.length);
+  Expect.equals(list.length, whereCount);
+
+  Expect.throws(() => list.reduce((x, y) => x), (e) => e is StateError);
+
+  Expect.isTrue(list.skip(list.length).isEmpty);
+  Expect.isTrue(list.skip(0).isEmpty);
+  Expect.isTrue(list.skipWhile((x) => true).isEmpty);
+  Expect.isTrue(list.skipWhile((x) => false).isEmpty);
+  Expect.isTrue(list.take(list.length).isEmpty);
+  Expect.isTrue(list.take(0).isEmpty);
+  Expect.isTrue(list.takeWhile((x) => false).isEmpty);
+  Expect.isTrue(list.takeWhile((x) => true).isEmpty);
+  Expect.isTrue(list.toList().isEmpty);
+  var l2 = list.toList();
+  l2.add(0);
+  Expect.equals(0, l2.last);
+  var l3 = list.toList(growable: false);
+  Expect.throws(() => l3.add(0), (e) => e is UnsupportedError);
+}
+
+main() {
+  testIterableFunctions(new Float32List.fromList([1.5, 9.5]), 1.5, 9.5);
+  testIterableFunctions(new Float64List.fromList([1.5, 9.5]), 1.5, 9.5);
+  testIterableFunctions(new Int8List.fromList([3, 9]), 3, 9);
+  testIterableFunctions(new Int16List.fromList([3, 9]), 3, 9);
+  testIterableFunctions(new Int32List.fromList([3, 9]), 3, 9);
+  testIterableFunctions(new Uint8List.fromList([3, 9]), 3, 9);
+  testIterableFunctions(new Uint16List.fromList([3, 9]), 3, 9);
+  testIterableFunctions(new Uint32List.fromList([3, 9]), 3, 9);
+
+  emptyChecks(new Float32List(0));
+  emptyChecks(new Float64List(0));
+  emptyChecks(new Int8List(0));
+  emptyChecks(new Int16List(0));
+  emptyChecks(new Int32List(0));
+  emptyChecks(new Uint8List(0));
+  emptyChecks(new Uint16List(0));
+  emptyChecks(new Uint32List(0));
+}
diff --git a/tests/standalone/io/file_error_test.dart b/tests/standalone/io/file_error_test.dart
index 16c0e24..8af6f1f 100644
--- a/tests/standalone/io/file_error_test.dart
+++ b/tests/standalone/io/file_error_test.dart
@@ -171,38 +171,6 @@
   });
 }
 
-bool checkDirectoryInNonExistentDirectoryException(e) {
-  Expect.isTrue(e is FileIOException);
-  Expect.isTrue(e.osError != null);
-  Expect.isTrue(
-      e.toString().indexOf("Cannot retrieve directory for file") != -1);
-  // File not not found has error code 2 on all supported platforms.
-  Expect.equals(2, e.osError.errorCode);
-
-  return true;
-}
-
-void testDirectoryInNonExistentDirectory() {
-  Directory temp = tempDir();
-  ReceivePort p = new ReceivePort();
-  p.receive((x, y) {
-    p.close();
-    temp.deleteSync(recursive: true);
-  });
-  var file = new File("${temp.path}/nonExistentDirectory/newFile");
-
-  // Create in non-existent directory should throw exception.
-  Expect.throws(() => file.directorySync(),
-                (e) => checkDirectoryInNonExistentDirectoryException(e));
-
-  var dirFuture = file.directory();
-  dirFuture.then((directory) => Expect.fail("Unreachable code"))
-  .catchError((error) {
-    checkDirectoryInNonExistentDirectoryException(error);
-    p.toSendPort().send(null);
-  });
-}
-
 void testReadAsBytesNonExistent() {
   Directory temp = tempDir();
   ReceivePort p = new ReceivePort();
@@ -481,7 +449,6 @@
   testLengthNonExistent();
   testCreateInNonExistentDirectory();
   testFullPathOnNonExistentDirectory();
-  testDirectoryInNonExistentDirectory();
   testReadAsBytesNonExistent();
   testReadAsTextNonExistent();
   testReadAsLinesNonExistent();
diff --git a/tests/standalone/io/file_fuzz_test.dart b/tests/standalone/io/file_fuzz_test.dart
index 3013a01..81d9d4e 100644
--- a/tests/standalone/io/file_fuzz_test.dart
+++ b/tests/standalone/io/file_fuzz_test.dart
@@ -18,7 +18,6 @@
       doItSync(f.existsSync);
       doItSync(f.createSync);
       doItSync(f.deleteSync);
-      doItSync(f.directorySync);
       doItSync(f.lengthSync);
       doItSync(f.modifiedSync);
       doItSync(f.fullPathSync);
diff --git a/tests/standalone/io/file_non_ascii_sync_test.dart b/tests/standalone/io/file_non_ascii_sync_test.dart
index 23290e3..c5004f6 100644
--- a/tests/standalone/io/file_non_ascii_sync_test.dart
+++ b/tests/standalone/io/file_non_ascii_sync_test.dart
@@ -20,7 +20,7 @@
   // The contents of the file is precomposed utf8.
   Expect.equals(precomposed, nonAsciiFile.readAsStringSync());
   nonAsciiFile.createSync();
-  var path = nonAsciiFile.directorySync().path;
+  var path = nonAsciiFile.directory.path;
   Expect.isTrue(path.endsWith(precomposed) || path.endsWith(decomposed));
   Expect.equals(6, nonAsciiFile.lengthSync());
   nonAsciiFile.lastModifiedSync();
diff --git a/tests/standalone/io/file_non_ascii_test.dart b/tests/standalone/io/file_non_ascii_test.dart
index 3bdc939..3aa0a3a 100644
--- a/tests/standalone/io/file_non_ascii_test.dart
+++ b/tests/standalone/io/file_non_ascii_test.dart
@@ -27,7 +27,7 @@
                 // The contents of the file is precomposed utf8.
                 Expect.equals(precomposed, contents);
                 nonAsciiFile.create().then((_) {
-                  nonAsciiFile.directory().then((d) {
+                  var d = nonAsciiFile.directory;
                   Expect.isTrue(d.path.endsWith(precomposed) ||
                                 d.path.endsWith(decomposed));
                   nonAsciiFile.length().then((length) {
@@ -37,8 +37,7 @@
                         Expect.isTrue(path.endsWith('${precomposed}.txt') ||
                                       path.endsWith('${decomposed}.txt'));
                         tempDir.delete(recursive: true).then((_) {
-                          port.close();
-                        });
+                        port.close();
                       });
                     });
                   });
diff --git a/tests/standalone/io/file_test.dart b/tests/standalone/io/file_test.dart
index a94185c..64cedd8 100644
--- a/tests/standalone/io/file_test.dart
+++ b/tests/standalone/io/file_test.dart
@@ -568,50 +568,36 @@
 
     var tempDir = tempDirectory.path;
     var file = new File("${tempDir}/testDirectory");
-    var errors = 0;
-    var dirFuture = file.directory();
-    dirFuture.then((d) => Expect.fail("non-existing file"))
-    .catchError((e) {
       file.create().then((ignore) {
-        file.directory().then((Directory d) {
-          d.exists().then((exists) {
-            Expect.isTrue(exists);
-            Expect.isTrue(d.path.endsWith(tempDir));
-            file.delete().then((ignore) {
-              var fileDir = new File(".");
-              var dirFuture2 = fileDir.directory();
-              dirFuture2.then((d) => Expect.fail("non-existing file"))
-              .catchError((e) {
-                var fileDir = new File(tempDir);
-                var dirFuture3 = fileDir.directory();
-                dirFuture3.then((d) => Expect.fail("non-existing file"))
-                .catchError((e) {
-                  port.toSendPort().send(1);
-                });
-              });
-            });
+          Directory d = file.directory;
+          d.exists().then((xexists) {
+          Expect.isTrue(xexists);
+          Expect.isTrue(d.path.endsWith(tempDir));
+          file.delete().then((ignore) {
+                port.toSendPort().send(1);
           });
         });
       });
-    });
   }
 
   static void testDirectorySync() {
     var tempDir = tempDirectory.path;
     var file = new File("${tempDir}/testDirectorySync");
-    // Non-existing file should throw exception.
-    Expect.throws(file.directorySync, (e) { return e is FileIOException; });
+    // Non-existing file still provides the directory.
+    Expect.equals("${tempDir}", file.directory.path);
     file.createSync();
     // Check that the path of the returned directory is the temp directory.
-    Directory d = file.directorySync();
+    Directory d = file.directory;
     Expect.isTrue(d.existsSync());
     Expect.isTrue(d.path.endsWith(tempDir));
     file.deleteSync();
-    // Directories should throw exception.
-    var file_dir = new File(".");
-    Expect.throws(file_dir.directorySync, (e) { return e is FileIOException; });
-    file_dir = new File(tempDir);
-    Expect.throws(file_dir.directorySync, (e) { return e is FileIOException; });
+    // The directory getter does not care about file or type of file
+    // system entity.
+    Expect.equals("${tempDir}", file.directory.path);
+    file = new File("foo");
+    Expect.equals(".", file.directory.path);
+    file = new File(".");
+    Expect.equals(".", file.directory.path);
   }
 
   // Test for file length functionality.
diff --git a/tests/standalone/io/http_keep_alive_test.dart b/tests/standalone/io/http_keep_alive_test.dart
index b2d821a..3e5d198 100644
--- a/tests/standalone/io/http_keep_alive_test.dart
+++ b/tests/standalone/io/http_keep_alive_test.dart
@@ -25,8 +25,8 @@
 Future<HttpServer> startServer() {
   return HttpServer.bind("127.0.0.1", 0).then((server) {
     server.listen((request) {
-      bool chunked = request.queryParameters["chunked"] == "true";
-      int length = int.parse(request.queryParameters["length"]);
+      bool chunked = request.uri.queryParameters["chunked"] == "true";
+      int length = int.parse(request.uri.queryParameters["length"]);
       var buffer = new List<int>.filled(length, 0);
       if (!chunked) request.response.contentLength = length;
       request.response.add(buffer);
diff --git a/tests/standalone/io/http_parser_test.dart b/tests/standalone/io/http_parser_test.dart
index dbd9564..a2ebc78 100644
--- a/tests/standalone/io/http_parser_test.dart
+++ b/tests/standalone/io/http_parser_test.dart
@@ -37,7 +37,7 @@
     StreamController controller;
     void reset() {
       _HttpParser httpParser = new _HttpParser.requestParser();
-      controller = new StreamController();
+      controller = new StreamController(sync: true);
       var port1 = new ReceivePort();
       var port2 = new ReceivePort();
 
@@ -135,7 +135,7 @@
 
     void reset() {
       httpParser = new _HttpParser.requestParser();
-      controller = new StreamController();
+      controller = new StreamController(sync: true);
       var port = new ReceivePort();
       controller.stream.pipe(httpParser);
       var subscription = httpParser.listen((incoming) {
@@ -198,7 +198,7 @@
       int contentLength;
       int bytesReceived;
       httpParser = new _HttpParser.responseParser();
-      controller = new StreamController();
+      controller = new StreamController(sync: true);
       var port = new ReceivePort();
       controller.stream.pipe(httpParser);
       int doneCallCount = 0;
@@ -280,7 +280,7 @@
   static void _testParseInvalidResponse(String response, [bool close = false]) {
     void testWrite(List<int> requestData, [int chunkSize = -1]) {
       _HttpParser httpParser = new _HttpParser.responseParser();
-      StreamController controller = new StreamController();
+      StreamController controller = new StreamController(sync: true);
       bool errorCalled = false;;
 
       if (chunkSize == -1) chunkSize = requestData.length;
diff --git a/tests/standalone/io/http_server_response_test.dart b/tests/standalone/io/http_server_response_test.dart
index 5b0a525..f31d183 100644
--- a/tests/standalone/io/http_server_response_test.dart
+++ b/tests/standalone/io/http_server_response_test.dart
@@ -102,7 +102,7 @@
   }, bytes: bytes * 2);
 
   testServerRequest((server, request) {
-    var controller = new StreamController();
+    var controller = new StreamController(sync: true);
     request.response.addStream(controller.stream)
         .then((response) {
           response.close();
diff --git a/tests/standalone/io/io_sink_test.dart b/tests/standalone/io/io_sink_test.dart
index 1c96448..de83044 100644
--- a/tests/standalone/io/io_sink_test.dart
+++ b/tests/standalone/io/io_sink_test.dart
@@ -65,7 +65,7 @@
 void testAddStreamClose() {
   {
     var sink = new IOSink(new TestConsumer([0]));
-    var controller = new StreamController();
+    var controller = new StreamController(sync: true);
     sink.addStream(controller.stream)
         .then((_) {
           sink.close();
@@ -75,7 +75,7 @@
   }
   {
     var sink = new IOSink(new TestConsumer([0, 1, 2]));
-    var controller = new StreamController();
+    var controller = new StreamController(sync: true);
     sink.addStream(controller.stream)
         .then((_) {
           sink.close();
@@ -90,7 +90,7 @@
 void testAddStreamAddClose() {
   {
     var sink = new IOSink(new TestConsumer([0, 1]));
-    var controller = new StreamController();
+    var controller = new StreamController(sync: true);
     sink.addStream(controller.stream)
         .then((_) {
           sink.add([1]);
diff --git a/tests/standalone/io/mime_multipart_parser_test.dart b/tests/standalone/io/mime_multipart_parser_test.dart
index 5a81df7..49e5b6a 100644
--- a/tests/standalone/io/mime_multipart_parser_test.dart
+++ b/tests/standalone/io/mime_multipart_parser_test.dart
@@ -14,7 +14,7 @@
                List expectedParts,
                bool expectError = false]) {
   void testWrite(List<int> data, [int chunkSize = -1]) {
-    StreamController controller = new StreamController();
+    StreamController controller = new StreamController(sync: true);
 
     var stream = controller.stream.transform(
         new MimeMultipartTransformer(boundary));
diff --git a/tests/standalone/io/regress_10026_test.dart b/tests/standalone/io/regress_10026_test.dart
index 44f2e54..444c145 100644
--- a/tests/standalone/io/regress_10026_test.dart
+++ b/tests/standalone/io/regress_10026_test.dart
@@ -10,7 +10,7 @@
 void testZLibInflate_regress10026() {
   test(data, expect) {
     var port = new ReceivePort();
-    var controller = new StreamController();
+    var controller = new StreamController(sync: true);
     controller.stream
         .transform(new ZLibInflater())
         .transform(new StringDecoder())
@@ -25,46 +25,61 @@
     controller.add(data);
     controller.close();
   }
+  // Generated by using 'gzip -c | od -v -tu1 -An -w12' and adding commas.
   test([
-      31, 139, 8, 0, 140, 39, 113, 81, 2, 255, 125, 84, 205, 142, 211, 48, 16,
-      62, 55, 79, 49, 132, 11, 72, 77, 211, 101, 1, 85, 217, 52, 2, 1, 18, 23,
-      224, 0, 23, 142, 211, 120, 210, 142, 54, 177, 131, 237, 164, 173, 16, 239,
-      206, 216, 105, 187, 133, 21, 168, 145, 26, 207, 196, 223, 159, 39, 41,
-      159, 40, 83, 251, 99, 79, 176, 243, 93, 91, 37, 229, 249, 143, 80, 85,
-      201, 172, 244, 236, 91, 170, 62, 28, 176, 235, 91, 130, 247, 166, 67, 214,
-      101, 62, 85, 19, 233, 119, 228, 17, 234, 29, 90, 71, 126, 157, 14, 190,
-      201, 86, 41, 228, 213, 185, 179, 243, 190, 207, 232, 199, 192, 227, 58,
-      125, 103, 180, 39, 237, 179, 192, 150, 66, 61, 173, 214, 169, 167, 131,
-      207, 3, 235, 221, 5, 231, 17, 140, 198, 142, 214, 233, 200, 180, 239, 141,
-      245, 87, 155, 247, 172, 252, 110, 173, 104, 228, 154, 178, 184, 152, 3,
-      107, 246, 140, 109, 230, 106, 108, 105, 125, 115, 194, 113, 254, 40, 6, 2,
-      247, 137, 178, 118, 46, 149, 198, 198, 168, 35, 252, 76, 102, 179, 13,
-      214, 247, 91, 107, 6, 173, 178, 218, 180, 198, 22, 240, 180, 89, 202, 239,
-      197, 157, 52, 59, 180, 91, 214, 5, 44, 195, 162, 71, 165, 88, 111, 79,
-      171, 70, 180, 100, 13, 118, 220, 30, 11, 72, 191, 244, 164, 225, 43, 106,
-      151, 206, 33, 253, 72, 237, 72, 158, 107, 132, 207, 52, 144, 84, 46, 133,
-      57, 188, 181, 162, 113, 14, 78, 30, 205, 28, 89, 110, 2, 86, 50, 251, 149,
-      204, 20, 143, 81, 80, 180, 83, 192, 235, 229, 178, 63, 92, 107, 120, 69,
-      29, 224, 224, 205, 31, 82, 110, 169, 187, 251, 135, 137, 38, 66, 111, 140,
-      85, 100, 51, 139, 138, 7, 87, 192, 77, 124, 94, 216, 176, 104, 89, 223,
-      207, 1, 139, 145, 29, 123, 82, 145, 251, 188, 249, 118, 245, 114, 181,
-      138, 251, 67, 102, 153, 162, 218, 88, 244, 108, 68, 134, 54, 154, 38, 136,
-      55, 29, 41, 70, 120, 214, 225, 33, 187, 22, 253, 124, 202, 245, 28, 240,
-      127, 196, 9, 200, 197, 246, 217, 247, 217, 226, 67, 246, 15, 165, 191,
-      204, 196, 115, 120, 200, 98, 242, 22, 64, 229, 42, 243, 120, 242, 213, 44,
-      41, 243, 105, 168, 147, 50, 72, 146, 25, 23, 198, 48, 25, 187, 155, 71,
-      243, 45, 37, 105, 244, 213, 183, 29, 59, 80, 177, 8, 114, 71, 206, 227,
-      166, 101, 183, 147, 148, 188, 129, 13, 193, 224, 228, 182, 49, 22, 184,
-      109, 7, 231, 67, 54, 35, 1, 77, 112, 78, 70, 81, 118, 215, 67, 39, 179,
-      234, 22, 240, 221, 12, 178, 148, 224, 60, 104, 138, 16, 49, 105, 241, 194,
-      26, 61, 129, 192, 160, 187, 143, 112, 61, 217, 142, 157, 147, 160, 3, 145,
-      176, 128, 191, 150, 162, 47, 20, 114, 112, 90, 1, 251, 32, 47, 0, 227,
-      136, 220, 138, 72, 10, 48, 2, 111, 105, 203, 147, 46, 163, 23, 101, 222,
-      79, 190, 74, 121, 51, 45, 53, 235, 52, 188, 159, 69, 158, 239, 247, 251,
-      5, 163, 198, 133, 177, 219, 124, 34, 113, 185, 235, 169, 150, 25, 77, 171,
-      79, 198, 146, 112, 10, 96, 55, 225, 44, 4, 9, 171, 136, 86, 230, 49, 197,
-      50, 63, 101, 154, 79, 223, 143, 223, 163, 237, 129, 168, 87, 4, 0, 0],
-      '''<!doctype html>
+     31, 139,   8,   8, 238,  42, 167,  81,   0,   3, 116, 101,
+    120, 116,  46, 116, 120, 116,   0, 125,  84,  79, 175, 147,
+     64,  16,  63, 183, 159,  98, 196, 139,  38, 165, 244, 249,
+    212,  52,  20, 136,  70,  77, 188, 168,   7, 189, 120, 156,
+    178,  67, 153,  20, 118, 113, 119, 161, 109, 140, 223, 221,
+     97, 105, 251, 170,  47, 154,  54,  41,  51, 195, 254, 254,
+     49,  52, 123, 162,  76, 233,  79,  29,  65, 237, 219, 166,
+    152, 103, 151,  31,  66,  85, 204, 103, 153, 103, 223,  80,
+    241, 225, 136, 109, 215,  16, 188,  55,  45, 178, 206, 146,
+    169,  59, 151, 121,  75,  30, 161, 172, 209,  58, 242, 121,
+    212, 251,  42,  94,  71, 144,  20, 151,  73, 237, 125,  23,
+    211, 143, 158, 135,  60, 122, 103, 180,  39, 237, 227, 145,
+     45, 130, 114, 170, 242, 200, 211, 209,  39,  35, 235, 230,
+    138, 243,   8,  70,  99,  75, 121,  52,  48,  29,  58,  99,
+    253, 205, 225,   3,  43,  95, 231, 138,   6,  46,  41,  14,
+    197,   2,  88, 179, 103, 108,  98,  87,  98,  67, 249, 221,
+     25, 199, 249, 147,  24,  24, 185, 207, 148, 165, 115, 145,
+     12, 182,  70, 157, 224, 231, 124,  54, 219,  98, 185, 223,
+     89, 211, 107,  21, 151, 166,  49,  54, 133, 167, 213,  74,
+     62,  47,  54,  50, 108, 209, 238,  88, 167, 176,  26, 139,
+     14, 149,  98, 189,  59,  87, 149, 104, 137,  43, 108, 185,
+     57, 165,  16, 125, 233,  72, 195,  87, 212,  46,  90,  64,
+    244, 145, 154, 129,  60, 151,   8, 159, 169,  39, 233,  92,
+     27,  11, 120, 107,  69, 227,   2, 156, 220,  26,  59, 178,
+     92, 109,  36, 206,  95, 243, 153, 226,  33, 200,   9, 102,
+     82, 120, 189,  90, 117, 199,  91,   5, 175, 168,   5, 236,
+    189, 249,  67, 200,  61, 181, 155, 127,  88, 168, 170,  48,
+     49,  86, 145, 141,  45,  42, 238,  93,  10, 119, 225, 126,
+     97, 195, 180,  97, 189,  95,   0, 166,   3,  59, 246, 164,
+      2, 247, 229, 240, 253, 250, 229, 122,  29, 206, 143, 137,
+    197, 138,  74,  99, 209, 179,  17,  25, 218, 104, 154,  32,
+    222, 180, 164,  24, 225,  89, 139, 199, 248,  86, 244, 243,
+     41, 213,  75, 188, 255,  17,  39,  32,  87, 219,  23, 223,
+     23, 139,  15, 201,  63, 180, 254,  50,  19, 158, 194,  67,
+     22, 147, 183,  17,  84, 190,  89,  18, 158, 187,  44, 116,
+     50, 109, 244,  60,  27,  21,  73,  45, 132, 227,  90, 212,
+    119, 143, 150,  91,  90,  50, 232, 138, 111,  53,  59,  80,
+    161,   9, 114,  69, 206, 227, 182,  97,  87,  75,  72, 222,
+    192, 150, 160, 119, 114,  89,  25,  11, 220,  52, 189, 243,
+     99,  52,   3,   1,  77, 112,  78, 246,  80,  78, 151, 125,
+     43, 139, 234, 150, 240, 221, 244,  82,  74, 110,  30,  52,
+      5, 136,  16, 180,  88,  97, 141, 158,  64,  96, 208, 237,
+      3,  92,  71, 182, 101, 231,  36, 231, 145,  72,  88, 192,
+    223,  74, 209,  87,  10, 121, 110,  90,   1, 251,  81, 222,
+      8, 140,   3, 114,  35,  34, 105, 132,  17, 120,  75,  59,
+    158, 116,  25, 189, 204, 146, 110, 242, 149, 201, 107, 105,
+    169, 202, 163, 241, 229,  76, 147, 228, 112,  56,  44,  25,
+     53,  46, 141, 221,  37,  19, 137,  75,  92,  71, 165,  44,
+    104,  84, 124,  50, 150, 132,  83,   0, 219,   9, 103,  41,
+     72,  88,   4, 180,  44,   9,  41, 102, 201,  57, 211, 100,
+    250, 243, 248,  13, 215,  32, 235, 247,  84,   4,   0,   0
+  ], '''
+<!doctype html>
 <html>
 <head>
 	<title>Example Domain</title>
@@ -78,7 +93,7 @@
 		margin: 0;
 		padding: 0;
 		font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
-		
+
 	}
 	div {
 		width: 600px;
@@ -102,7 +117,7 @@
 			padding: 1em;
 		}
 	}
-	</style>	
+	</style>
 </head>
 
 <body>
diff --git a/tests/standalone/io/stdout_stderr_test.dart b/tests/standalone/io/stdout_stderr_test.dart
index ccd1550..1f7ac91 100644
--- a/tests/standalone/io/stdout_stderr_test.dart
+++ b/tests/standalone/io/stdout_stderr_test.dart
@@ -16,14 +16,14 @@
   sink.writeCharCode(72);
   sink.add([101, 108, 108, 111, 10]);
 
-  var controller = new StreamController();
+  var controller = new StreamController(sync: true);
   var future = sink.addStream(controller.stream);
   controller.add([72, 101, 108]);
   controller.add([108, 111, 10]);
   controller.close();
 
   future.then((_) {
-    controller = new StreamController();
+    controller = new StreamController(sync: true);
     controller.stream.pipe(sink);
     controller.add([72, 101, 108]);
     controller.add([108, 111, 10]);
diff --git a/tests/standalone/io/string_decoder_test.dart b/tests/standalone/io/string_decoder_test.dart
index 975e1cc..df808ae 100644
--- a/tests/standalone/io/string_decoder_test.dart
+++ b/tests/standalone/io/string_decoder_test.dart
@@ -8,7 +8,7 @@
 
 void test() {
   // Code point U+10FFFF is the largest code point supported by Dart.
-  var controller = new StreamController();
+  var controller = new StreamController(sync: true);
   controller.add([0xf0, 0x90, 0x80, 0x80]);  // U+10000
   controller.add([0xf4, 0x8f, 0xbf, 0xbf]);  // U+10FFFF
   controller.add([0xf4, 0x90, 0x80, 0x80]);  // U+110000
@@ -42,7 +42,7 @@
 
 void testInvalid() {
   void invalid(var bytes, var outputLength) {
-    var controller = new StreamController();
+    var controller = new StreamController(sync: true);
     controller.add(bytes);
     controller.close();
     controller.stream.transform(new StringDecoder()).listen((string) {
diff --git a/tests/standalone/io/string_transformer_test.dart b/tests/standalone/io/string_transformer_test.dart
index a7dd544..e9e11b5 100644
--- a/tests/standalone/io/string_transformer_test.dart
+++ b/tests/standalone/io/string_transformer_test.dart
@@ -17,7 +17,7 @@
                     0xef, 0xbf, 0xbf,
                     0xf0, 0x9d, 0x84, 0x9e,
                     0x100, -0x1, -0xFF];
-  var controller = new StreamController();
+  var controller = new StreamController(sync: true);
   controller.add(data);
   controller.close();
   var stringStream = controller.stream
@@ -52,7 +52,7 @@
                     0x80,
                     0xff,
                     0x100, -0x1, -0xff];
-  var controller = new StreamController();
+  var controller = new StreamController(sync: true);
   controller.add(data);
   controller.close();
   var stream = controller.stream
@@ -73,7 +73,7 @@
                     0x44, 0x61, 0x72, 0x74,
                     0x7f,
                     0xf4, 0x100, -0x1, -0xff];
-  var controller = new StreamController();
+  var controller = new StreamController(sync: true);
   controller.add(data);
   controller.close();
   var stream = controller.stream
@@ -88,7 +88,7 @@
 }
 
 void testReadLine1() {
-  var controller = new StreamController();
+  var controller = new StreamController(sync: true);
   var stream = controller.stream
       .transform(new StringDecoder())
       .transform(new LineTransformer());
@@ -119,7 +119,7 @@
 }
 
 void testReadLine2() {
-  var controller = new StreamController();
+  var controller = new StreamController(sync: true);
 
   var stream = controller.stream
     .transform(new StringDecoder())
@@ -187,7 +187,7 @@
 }
 
 testErrorHandler() {
-  var controller = new StreamController();
+  var controller = new StreamController(sync: true);
   var errors = 0;
   var stream = controller.stream
     .transform(new StringDecoder())
@@ -212,7 +212,7 @@
                     0x80,
                     0xff,
                     0x100];
-  var controller = new StreamController();
+  var controller = new StreamController(sync: true);
   controller.add(new String.fromCharCodes(data));
   controller.close();
   var stream = controller.stream
diff --git a/tests/standalone/io/web_socket_protocol_processor_test.dart b/tests/standalone/io/web_socket_protocol_processor_test.dart
index b655b13..2aa9fb9 100644
--- a/tests/standalone/io/web_socket_protocol_processor_test.dart
+++ b/tests/standalone/io/web_socket_protocol_processor_test.dart
@@ -101,7 +101,7 @@
     int messageCount = 0;
     // Use the same web socket protocol transformer for all frames.
     var transformer = new _WebSocketProtocolTransformer();
-    var controller = new StreamController();
+    var controller = new StreamController(sync: true);
     WebSocketMessageCollector mc = new WebSocketMessageCollector(
         controller.stream.transform(transformer),
         message);
@@ -165,7 +165,7 @@
 void testFragmentedMessages() {
   // Use the same web socket protocol transformer for all frames.
   var transformer = new _WebSocketProtocolTransformer();
-  var controller = new StreamController();
+  var controller = new StreamController(sync: true);
   WebSocketMessageCollector mc = new WebSocketMessageCollector(
       controller.stream.transform(transformer));
 
@@ -230,7 +230,7 @@
 
 void testUnmaskedMessage() {
   var transformer = new _WebSocketProtocolTransformer(true);
-  var controller = new StreamController();
+  var controller = new StreamController(sync: true);
   var port = new ReceivePort();
   controller.stream.transform(transformer).listen((_) {}, onError: (e) {
     port.close();
diff --git a/tests/standalone/io/zlib_test.dart b/tests/standalone/io/zlib_test.dart
index 6cfa46f..d1214ae 100644
--- a/tests/standalone/io/zlib_test.dart
+++ b/tests/standalone/io/zlib_test.dart
@@ -11,7 +11,7 @@
   test(int level, List<int> expected) {
     var port = new ReceivePort();
     var data = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
-    var controller = new StreamController();
+    var controller = new StreamController(sync: true);
     controller.stream.transform(new ZLibDeflater(gzip: false, level: level))
         .fold([], (buffer, data) {
           buffer.addAll(data);
@@ -31,7 +31,7 @@
 
 void testZLibDeflateEmpty() {
   var port = new ReceivePort();
-  var controller = new StreamController();
+  var controller = new StreamController(sync: true);
   controller.stream.transform(new ZLibDeflater(gzip: false, level: 6))
       .fold([], (buffer, data) {
         buffer.addAll(data);
@@ -48,7 +48,7 @@
 void testZLibDeflateGZip() {
   var port = new ReceivePort();
   var data = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
-  var controller = new StreamController();
+  var controller = new StreamController(sync: true);
   controller.stream.transform(new ZLibDeflater())
       .fold([], (buffer, data) {
         buffer.addAll(data);
@@ -92,7 +92,7 @@
   test2(bool gzip, int level) {
     var port = new ReceivePort();
     var data = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
-    var controller = new StreamController();
+    var controller = new StreamController(sync: true);
     controller.stream
       .transform(new ZLibDeflater(gzip: gzip, level: level))
       .transform(new ZLibInflater())
diff --git a/tests/standalone/standalone.status b/tests/standalone/standalone.status
index 6027974..3b328ab 100644
--- a/tests/standalone/standalone.status
+++ b/tests/standalone/standalone.status
@@ -88,6 +88,10 @@
 io/url_encoding_test: fail
 io/web_socket_protocol_processor_test: fail
 
+# Fails because checked-in dart executable is not up to date.
+io/test_runner_test: fail, OK
+io/skipping_dart2js_compilations_test: fail, OK
+
 
 [ $compiler == dart2js ]
 number_identity_test: Skip # Bigints and int/double diff. not supported.
@@ -133,6 +137,9 @@
 # Skip until we stabilize language tests.
 *: Skip
 
+[ $arch == arm ]
+*: Skip
+
 [ $arch == simarm ]
 *: Skip
 
diff --git a/tests/standalone/typed_data_test.dart b/tests/standalone/typed_data_test.dart
index 21f17a5b..f8f28aa 100644
--- a/tests/standalone/typed_data_test.dart
+++ b/tests/standalone/typed_data_test.dart
@@ -30,7 +30,7 @@
 
   typed_data = new Uint8ClampedList(0);
   Expect.isTrue(typed_data is Uint8ClampedList);
-  Expect.isFalse(typed_data is Uint8List);
+  Expect.isTrue(typed_data is Uint8List);
   Expect.equals(0, typed_data.length);
   Expect.equals(0, typed_data.lengthInBytes);
 
diff --git a/tests/utils/dummy_compiler_test.dart b/tests/utils/dummy_compiler_test.dart
index 50ab451..59d3ee9 100644
--- a/tests/utils/dummy_compiler_test.dart
+++ b/tests/utils/dummy_compiler_test.dart
@@ -29,6 +29,7 @@
                   class List {}
                   class Map {}
                   class Closure {}
+                  class BoundClosure {}
                   class Dynamic_ {}
                   class Null {}
                   class StackTrace {}
diff --git a/tests/utils/recursive_import_test.dart b/tests/utils/recursive_import_test.dart
index 59aade0..a21c5a9 100644
--- a/tests/utils/recursive_import_test.dart
+++ b/tests/utils/recursive_import_test.dart
@@ -21,6 +21,7 @@
 class Function{}
 class List {}
 class Map {}
+class BoundClosure {}
 class Closure {}
 class Dynamic_ {}
 class Type {}
diff --git a/tests/utils/utils.status b/tests/utils/utils.status
index d8a3a34..79344f3 100644
--- a/tests/utils/utils.status
+++ b/tests/utils/utils.status
@@ -9,6 +9,7 @@
 [ $compiler == none && $runtime == drt ]
 dummy_compiler_test: Skip # http://dartbug.com/7233
 dart2js_test: Skip # Uses dart:io.
+txt_layout_test: Skip # Might just go away.
 
 [ $compiler == dart2js && $browser ]
 *: Skip
@@ -23,6 +24,9 @@
 # Skip until we stabilize language tests.
 *: Skip
 
+[ $arch == arm ]
+*: Skip
+
 [ $arch == simarm ]
 *: Skip
 
diff --git a/tools/VERSION b/tools/VERSION
index 0a54219..b6d74d9 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -1,4 +1,4 @@
 MAJOR 0
 MINOR 5
-BUILD 12
+BUILD 13
 PATCH 0
diff --git a/tools/bots/compiler.py b/tools/bots/compiler.py
index 38c116b..9dab287 100644
--- a/tools/bots/compiler.py
+++ b/tools/bots/compiler.py
@@ -114,13 +114,13 @@
 def UseBrowserController(runtime, system):
   supported_platforms = {
     'linux': ['ff', 'chromeOnAndroid', 'chrome'],
-    'mac': [],
+    'mac': ['safari'],
     'windows': []
   }
   # Platforms that we run on the fyi waterfall only.
   fyi_supported_platforms = {
     'linux': [],
-    'mac': ['safari'],
+    'mac': [],
     'windows': []
   }
 
diff --git a/tools/bots/cross-vm.py b/tools/bots/cross-vm.py
index 54d43c1..3671f20 100644
--- a/tools/bots/cross-vm.py
+++ b/tools/bots/cross-vm.py
@@ -50,14 +50,18 @@
     num_run = int(os.environ['BUILDBOT_ANNOTATED_STEPS_RUN'])
     if num_run == 1:
       with bot.BuildStep('Build %s %s' % (arch, mode)):
-        args = [sys.executable, build_py,
-                '-m%s' % mode, '--arch=%s' % arch, 'runtime']
+        run([sys.executable, build_py,
+             '-m%s' % mode, '--arch=%s' % arch, 'runtime'])
+        # We need to build 'run_vm_tests.host' as well to enable
+        # test.py to list the VM tests.
+        run([sys.executable, build_py,
+             '-m%s' % mode, '--arch=%s' % arch, 'run_vm_tests.host'])
 
-        run(args)
       with bot.BuildStep('Create build tarball'):
         run(['tar', '-cjf', tarball, '--exclude=**/obj',
              '--exclude=**/obj.host', '--exclude=**/obj.target',
-             '--exclude=**/*analyzer*', '--exclude=**/*IA32', 'out/'])
+             '--exclude=**/*analyzer*', '--exclude=**/run_vm_tests.host',
+             'out/'])
 
       with bot.BuildStep('Upload build tarball'):
         uri = "%s/%s" % (GCS_BUCKET, tarball)
diff --git a/tools/coverage.dart b/tools/coverage.dart
new file mode 100644
index 0000000..1c9519e
--- /dev/null
+++ b/tools/coverage.dart
@@ -0,0 +1,492 @@
+// 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 test forks a second vm process that runs a dart script as
+// a debug target, single stepping through the entire program, and
+// recording each breakpoint. At the end, a coverage map of the source
+// is printed.
+//
+// Usage: dart coverage.dart [--wire] [--verbose] target_script.dart
+//
+//   --wire      see json messages sent between the processes.
+//   --verbose   see the stdout and stderr output of the debug
+//               target process.
+
+import "dart:io";
+import "dart:utf";
+import "dart:json" as JSON;
+
+
+// Whether or not to print debug target process on the console.
+var showDebuggeeOutput = false;
+
+// Whether or not to print the debugger wire messages on the console.
+var verboseWire = false;
+
+
+class Program {
+  static int numBps = 0;
+
+  // Maps source code url to source.
+  static var sources = new Map<String, Source>();
+
+  // Takes a JSON Debugger response and increments the count for
+  // the source position.
+  static void recordBp(Debugger debugger, Map<String,dynamic> msg) {
+    // Progress indicator.
+    if (++numBps % 100 == 0) print(numBps);
+    var location = msg["params"]["location"];
+    if (location == null) return;
+    String url = location["url"];
+    assert(url != null);
+    int tokenPos = location["tokenOffset"];;
+    Source s = sources[url];
+    if (s == null) {
+      debugger.GetLineNumberTable(url);
+      s = new Source(url);
+      sources[url] = s;
+    }
+    s.recordBp(tokenPos);
+  }
+
+  // Prints the annotated source code.
+  static void printCoverage() {
+    print("Coverage info collected from $numBps breakpoints:");
+    for(Source s in sources.values) s.printCoverage();
+  }
+}
+
+
+class Source {
+  final String url;
+
+  // Maps token position to breakpoint count.
+  final tokenCounts = new Map<int,int>();
+
+  // Maps token position to line number.
+  final tokenPosToLine = new Map<int,int>();
+
+  Source(this.url);
+
+  void recordBp(int tokenPos) {
+    var count = tokenCounts[tokenPos];
+    tokenCounts[tokenPos] = count == null ? 1 : count + 1;
+  }
+
+  void SetLineInfo(List lineInfoTable) {
+    // Each line is encoded as an array with first element being the line
+    // number, followed by pairs of (tokenPosition, textOffset).
+    lineInfoTable.forEach((List<int> line) {
+      int lineNumber = line[0];
+      for (int t = 1; t < line.length; t += 2) {
+        assert(tokenPosToLine[line[t]] == null);
+        tokenPosToLine[line[t]] = lineNumber;
+      }
+    });
+  }
+
+  // Print out the annotated source code. For each line that has seen
+  // a breakpoint, print out the maximum breakpoint count for all
+  // tokens in the line.
+  void printCoverage() {
+    var lineCounts = new Map<int,int>();  // BP counts for each line.
+    print(url);
+    tokenCounts.forEach((tp, bpCount) {
+      int lineNumber = tokenPosToLine[tp];
+      var lineCount = lineCounts[lineNumber];
+      // Remember maximum breakpoint count of all tokens in this line.
+      if (lineCount == null || lineCount < bpCount) {
+        lineCounts[lineNumber] = bpCount;
+      }
+    });
+
+    List lines = new File(Uri.parse(url).path).readAsLinesSync();
+    for (int line = 1; line <= lines.length; line++) {
+      String prefix = "      ";
+      if (lineCounts.containsKey(line)) {
+        prefix = lineCounts[line].toString();
+        StringBuffer b = new StringBuffer();
+        for (int i = prefix.length; i < 6; i++) b.write(" ");
+        b.write(prefix);
+        prefix = b.toString();
+      }
+      print("${prefix}|${lines[line-1]}");
+    }
+  }
+}
+
+
+class StepCmd {
+  Map msg;
+  StepCmd(int isolateId) {
+    msg = {"id": 0, "command": "stepInto", "params": {"isolateId": isolateId}};
+  }
+  void handleResponse(Map response) {}
+}
+
+
+class GetLineTableCmd {
+  Map msg;
+  GetLineTableCmd(int isolateId, int libraryId, String url) {
+    msg = { "id": 0,
+            "command":  "getLineNumberTable",
+            "params": { "isolateId" : isolateId,
+                        "libraryId": libraryId,
+                        "url": url } };
+  }
+
+  void handleResponse(Map response) {
+    var url = msg["params"]["url"];
+    Source s = Program.sources[url];
+    assert(s != null);
+    s.SetLineInfo(response["result"]["lines"]);
+  }
+}
+
+
+class Debugger {
+  // Debug target process properties.
+  Process targetProcess;
+  Socket socket;
+  bool cleanupDone = false;
+  JsonBuffer responses = new JsonBuffer();
+  List<String> errors = new List();
+
+  // Data collected from debug target.
+  Map currentMessage = null;  // Currently handled message sent by target.
+  var outstandingCommand = null;
+  var queuedCommand = null;
+  String scriptUrl = null;
+  bool shutdownEventSeen = false;
+  int isolateId = 0;
+  int libraryId = null;
+
+  int nextMessageId = 0;
+  bool isPaused = false;
+  bool pendingAck = false;
+
+  Debugger(this.targetProcess) {
+    var stdoutStringStream = targetProcess.stdout
+        .transform(new StringDecoder())
+        .transform(new LineTransformer());
+    stdoutStringStream.listen((line) {
+      if (showDebuggeeOutput) {
+        print("TARG: $line");
+      }
+      if (line.startsWith("Debugger listening")) {
+        RegExp portExpr = new RegExp(r"\d+");
+        var port = portExpr.stringMatch(line);
+        print("Debug target found listening at port '$port'");
+        openConnection(int.parse(port));
+      }
+    });
+
+    var stderrStringStream = targetProcess.stderr
+        .transform(new StringDecoder())
+        .transform(new LineTransformer());
+    stderrStringStream.listen((line) {
+      if (showDebuggeeOutput) {
+        print("TARG: $line");
+      }
+    });
+  }
+
+  // Handle debugger events, updating the debugger state.
+  void handleEvent(Map<String,dynamic> msg) {
+    if (msg["event"] == "isolate") {
+      if (msg["params"]["reason"] == "created") {
+        isolateId = msg["params"]["id"];
+        assert(isolateId != null);
+        print("Debuggee isolate id $isolateId created.");
+      } else if (msg["params"]["reason"] == "shutdown") {
+        print("Debuggee isolate id ${msg["params"]["id"]} shut down.");
+        shutdownEventSeen = true;
+      }
+    } else if (msg["event"] == "breakpointResolved") {
+      var bpId = msg["params"]["breakpointId"];
+      assert(bpId != null);
+      var isolateId = msg["params"]["isolateId"];
+      assert(isolateId != null);
+      var location = msg["params"]["location"];
+      assert(location != null);
+      print("Isolate $isolateId: breakpoint $bpId resolved"
+            " at location $location");
+      // We may want to maintain a table of breakpoints in the future.
+    } else if (msg["event"] == "paused") {
+      isPaused = true;
+      if (libraryId == null) {
+        libraryId = msg["params"]["location"]["libraryId"];
+        assert(libraryId != null);
+      }
+      if (msg["params"]["reason"] == "breakpoint") {
+        Program.recordBp(this, msg);
+      }
+    } else {
+      error("Error: unknown debugger event received");
+    }
+  }
+
+  // Handle one JSON message object and match it to the
+  // expected events and responses in the debugging script.
+  void handleMessage(Map<String,dynamic> receivedMsg) {
+    currentMessage = receivedMsg;
+    if (receivedMsg["event"] != null) {
+      handleEvent(receivedMsg);
+      if (errorsDetected) {
+        error("Error while handling debugger event");
+        error("Event received from debug target: $receivedMsg");
+      }
+    } else if (receivedMsg["id"] != null) {
+      // This is a response to the last command we sent.
+      int id = receivedMsg["id"];
+      assert(outstandingCommand != null);
+      assert(outstandingCommand.msg["id"] == id);
+      outstandingCommand.handleResponse(receivedMsg);
+      outstandingCommand = null;
+    } else {
+      error("Unexpected message from target");
+    }
+  }
+
+  // Handle data received over the wire from the debug target
+  // process. Split input from JSON wire format into individual
+  // message objects (maps).
+  void handleMessages() {
+    var msg = responses.getNextMessage();
+    while (msg != null) {
+      if (verboseWire) print("RECV: $msg");
+      if (responses.haveGarbage()) {
+        error("Error: leftover text after message: '${responses.buffer}'");
+        error("Previous message may be malformed, was: '$msg'");
+        cleanup();
+        return;
+      }
+      var msgObj = JSON.parse(msg);
+      handleMessage(msgObj);
+      if (errorsDetected) {
+        error("Error while handling message from debug target");
+        error("Message received from debug target: $msg");
+        cleanup();
+        return;
+      }
+      if (shutdownEventSeen) {
+        if (outstandingCommand != null) {
+          error("Error: outstanding command when shutdown received");
+        }
+        cleanup();
+        return;
+      }
+      if (isPaused && (outstandingCommand == null)) {
+        var cmd = queuedCommand;
+        queuedCommand = null;
+        if (cmd == null) {
+          cmd = new StepCmd(isolateId);
+          isPaused = false;
+        }
+        sendMessage(cmd.msg);
+        outstandingCommand = cmd;
+      }
+      msg = responses.getNextMessage();
+    }
+  }
+
+  // Send a debugger command to the target VM.
+  void sendMessage(Map<String,dynamic> msg) {
+    assert(msg["id"] != null);
+    msg["id"] = nextMessageId++;
+    String jsonMsg = JSON.stringify(msg);
+    if (verboseWire) print("SEND: $jsonMsg");
+    socket.write(jsonMsg);
+  }
+
+  void GetLineNumberTable(String url) {
+    assert(queuedCommand == null);
+    queuedCommand = new GetLineTableCmd(isolateId, libraryId, url);
+  }
+  
+  bool get errorsDetected => errors.length > 0;
+
+  // Record error message.
+  void error(String s) {
+    errors.add(s);
+  }
+
+  void openConnection(int portNumber) {
+    Socket.connect("127.0.0.1", portNumber).then((s) {
+      socket = s;
+      var stringStream = socket.transform(new StringDecoder());
+      stringStream.listen(
+          (str) {
+            try {
+              responses.append(str);
+              handleMessages();
+            } catch(e, trace) {
+              print("Unexpected exception:\n$e\n$trace");
+              cleanup();
+            }
+          },
+          onDone: () {
+            print("Connection closed by debug target");
+            cleanup();
+          },
+          onError: (e) {
+            print("Error '$e' detected in input stream from debug target");
+            cleanup();
+          });
+      },
+      onError: (e) {
+        String msg = "Error while connecting to debugee: $e";
+        var trace = getAttachedStackTrace(e);
+        if (trace != null) msg += "\nStackTrace: $trace";
+        error(msg);
+        cleanup();
+     });
+  }
+
+  void cleanup() {
+    if (cleanupDone) return;
+    if (socket != null) {
+      socket.close().catchError((error) {
+        // Print this directly in addition to adding it to the
+        // error message queue, in case the error message queue
+        // gets printed before this error handler is called.
+        print("Error occurred while closing socket: $error");
+        error("Error while closing socket: $error");
+      });
+    }
+    var targetPid = targetProcess.pid;
+    print("Sending kill signal to process $targetPid...");
+    targetProcess.kill();
+    // If the process was already dead exitCode is already
+    // available and we call exit() in the next event loop cycle.
+    // Otherwise this will wait for the process to exit.
+
+    targetProcess.exitCode.then((exitCode) {
+      print("process $targetPid terminated with exit code $exitCode.");
+      if (errorsDetected) {
+        print("\n===== Errors detected: =====");
+        for (int i = 0; i < errors.length; i++) print(errors[i]);
+        print("============================\n");
+      }
+      Program.printCoverage();
+      exit(errors.length);
+    });
+    cleanupDone = true;
+  }
+}
+
+
+// Class to buffer wire protocol data from debug target and
+// break it down to individual json messages.
+class JsonBuffer {
+  String buffer = null;
+
+  append(String s) {
+    if (buffer == null || buffer.length == 0) {
+      buffer = s;
+    } else {
+      buffer = buffer.concat(s);
+    }
+  }
+
+  String getNextMessage() {
+    if (buffer == null) return null;
+    int msgLen = objectLength();
+    if (msgLen == 0) return null;
+    String msg = null;
+    if (msgLen == buffer.length) {
+      msg = buffer;
+      buffer = null;
+    } else {
+      assert(msgLen < buffer.length);
+      msg = buffer.substring(0, msgLen);
+      buffer = buffer.substring(msgLen);
+    }
+    return msg;
+  }
+
+  bool haveGarbage() {
+    if (buffer == null || buffer.length == 0) return false;
+    var i = 0, char = " ";
+    while (i < buffer.length) {
+      char = buffer[i];
+      if (char != " " && char != "\n" && char != "\r" && char != "\t") break;
+      i++;
+    }
+    if (i >= buffer.length) {
+      return false;
+    } else { 
+      return char != "{";
+    }
+  }
+
+  // Returns the character length of the next json message in the
+  // buffer, or 0 if there is only a partial message in the buffer.
+  // The object value must start with '{' and continues to the
+  // matching '}'. No attempt is made to otherwise validate the contents
+  // as JSON. If it is invalid, a later JSON.parse() will fail.
+  int objectLength() {
+    int skipWhitespace(int index) {
+      while (index < buffer.length) {
+        String char = buffer[index];
+        if (char != " " && char != "\n" && char != "\r" && char != "\t") break;
+        index++;
+      }
+      return index;
+    }
+    int skipString(int index) {
+      assert(buffer[index - 1] == '"');
+      while (index < buffer.length) {
+        String char = buffer[index];
+        if (char == '"') return index + 1;
+        if (char == r'\') index++;
+        if (index == buffer.length) return index;
+        index++;
+      }
+      return index;
+    }
+    int index = 0;
+    index = skipWhitespace(index);
+    // Bail out if the first non-whitespace character isn't '{'.
+    if (index == buffer.length || buffer[index] != '{') return 0;
+    int nesting = 0;
+    while (index < buffer.length) {
+      String char = buffer[index++];
+      if (char == '{') {
+        nesting++;
+      } else if (char == '}') {
+        nesting--;
+        if (nesting == 0) return index;
+      } else if (char == '"') {
+        // Strings can contain braces. Skip their content.
+        index = skipString(index);
+      }
+    }
+    return 0;
+  }
+}
+
+
+void main() {
+  var options = new Options();
+  var targetOpts = [ "--debug:0" ];
+  for (String str in options.arguments) {
+    switch (str) {
+      case "--verbose":
+        showDebuggeeOutput = true;
+        break;
+      case "--wire":
+        verboseWire = true;
+        break;
+      default:
+        targetOpts.add(str);
+        break;
+    }
+  }
+
+  Process.start(options.executable, targetOpts).then((Process process) {
+    process.stdin.close();
+    var debugger = new Debugger(process);
+  });
+}
diff --git a/tools/dom/dom.json b/tools/dom/dom.json
index c01a78f..f773ca9 100644
--- a/tools/dom/dom.json
+++ b/tools/dom/dom.json
@@ -883,6 +883,7 @@
   },
   "CustomElementConstructor": {
     "comment": "https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/custom/index.html#dfn-custom-element-constructor-generation",
+    "dart_action": "suppress",
     "members": {},
     "support_level": "experimental"
   },
@@ -2354,6 +2355,7 @@
         "comment": "http://www.w3.org/TR/touch-events/, http://www.chromestatus.com/features",
         "support_level": "experimental"
       },
+      "ontransitionend": {},
       "onwebkitTransitionEnd": {
         "support_level": "deprecated"
       },
diff --git a/tools/dom/scripts/dartmetadata.py b/tools/dom/scripts/dartmetadata.py
index 9daed68..3cbd995 100644
--- a/tools/dom/scripts/dartmetadata.py
+++ b/tools/dom/scripts/dartmetadata.py
@@ -279,7 +279,7 @@
   'DOMWindow.webkitNotifications': _webkit_experimental_annotations,
   'DOMWindow.webkitRequestFileSystem': _file_system_annotations,
   'DOMWindow.webkitResolveLocalFileSystemURL': _file_system_annotations,
-  'Element.onwebkitTransitionEnd': _all_but_ie9_annotations,
+  'Element.ontransitionend': _all_but_ie9_annotations,
   # Placeholder to add experimental flag, implementation for this is
   # pending in a separate CL.
   'Element.webkitMatchesSelector': ['@Experimental()'],
diff --git a/tools/dom/scripts/htmleventgenerator.py b/tools/dom/scripts/htmleventgenerator.py
index 3ed4393..c2ead7c 100644
--- a/tools/dom/scripts/htmleventgenerator.py
+++ b/tools/dom/scripts/htmleventgenerator.py
@@ -15,7 +15,7 @@
 # onEventName methods in the IDL but some events aren't listed so we need
 # to manually add them here so that they are easy for users to find.
 _html_manual_events = monitored.Dict('htmleventgenerator._html_manual_events', {
-  'Element': ['touchleave', 'touchenter', 'webkitTransitionEnd'],
+  'Element': ['touchleave', 'touchenter', 'transitionend'],
   'Window': ['DOMContentLoaded']
 })
 
@@ -28,7 +28,6 @@
   'webkitanimationiteration': 'webkitAnimationIteration',
   'webkitanimationstart': 'webkitAnimationStart',
   'webkitspeechchange': 'webkitSpeechChange',
-  'webkittransitionend': 'webkitTransitionEnd',
 })
 
 _html_event_types = monitored.Dict('htmleventgenerator._html_event_types', {
@@ -108,7 +107,7 @@
   '*.webkitAnimationEnd': ('animationEnd', 'AnimationEvent'),
   '*.webkitAnimationIteration': ('animationIteration', 'AnimationEvent'),
   '*.webkitAnimationStart': ('animationStart', 'AnimationEvent'),
-  '*.webkitTransitionEnd': ('transitionEnd', 'TransitionEvent'),
+  '*.transitionend': ('transitionEnd', 'TransitionEvent'),
   '*.webkitfullscreenchange': ('fullscreenChange', 'Event'),
   '*.webkitfullscreenerror': ('fullscreenError', 'Event'),
   'AbstractWorker.error': ('error', 'ErrorEvent'),
@@ -118,7 +117,7 @@
   'DOMApplicationCache.downloading': ('downloading', 'Event'),
   'DOMApplicationCache.noupdate': ('noUpdate', 'Event'),
   'DOMApplicationCache.obsolete': ('obsolete', 'Event'),
-  'DOMApplicationCache.progress': ('progress', 'Event'),
+  'DOMApplicationCache.progress': ('progress', 'ProgressEvent'),
   'DOMApplicationCache.updateready': ('updateReady', 'Event'),
   'Document.readystatechange': ('readyStateChange', 'Event'),
   'Document.securitypolicyviolation': ('securityPolicyViolation', 'SecurityPolicyViolationEvent'),
diff --git a/tools/dom/scripts/htmlrenamer.py b/tools/dom/scripts/htmlrenamer.py
index 7262ee1..b3d7354 100644
--- a/tools/dom/scripts/htmlrenamer.py
+++ b/tools/dom/scripts/htmlrenamer.py
@@ -23,6 +23,7 @@
 
 html_interface_renames = monitored.Dict('htmlrenamer.html_interface_renames',
                                         dict({
+    'Attr': '_Attr',
     'CDATASection': 'CDataSection',
     'Clipboard': 'DataTransfer',
     'Database': 'SqlDatabase', # Avoid conflict with Index DB's Database.
@@ -270,6 +271,7 @@
   'Node.childNodes',
   'Node.firstChild',
   'Node.lastChild',
+  'Node.localName',
   'Node.namespaceURI',
   'Node.removeChild',
   'Node.replaceChild',
@@ -363,7 +365,6 @@
 # to be suppressed but not the setter, etc.
 # TODO(jacobr): cleanup and augment this list.
 _removed_html_members = monitored.Set('htmlrenamer._removed_html_members', [
-    'Attr.*',
     'AudioBufferSourceNode.looping', # TODO(vsm): Use deprecated IDL annotation
     'CSSStyleDeclaration.getPropertyCSSValue',
     'CanvasRenderingContext2D.clearShadow',
diff --git a/tools/dom/src/AttributeMap.dart b/tools/dom/src/AttributeMap.dart
index b0cb0cc..76a9064 100644
--- a/tools/dom/src/AttributeMap.dart
+++ b/tools/dom/src/AttributeMap.dart
@@ -44,7 +44,7 @@
     var keys = new List<String>();
     for (int i = 0, len = attributes.length; i < len; i++) {
       if (_matches(attributes[i])) {
-        keys.add(attributes[i].localName);
+        keys.add(attributes[i].name);
       }
     }
     return keys;
diff --git a/tools/dom/src/KeyboardEventStream.dart b/tools/dom/src/KeyboardEventStream.dart
index 6f08c70..2e838d1 100644
--- a/tools/dom/src/KeyboardEventStream.dart
+++ b/tools/dom/src/KeyboardEventStream.dart
@@ -28,7 +28,7 @@
   static final int _ROMAN_ALPHABET_OFFSET = "a".codeUnits[0] - "A".codeUnits[0];
 
   /** Controller to produce KeyEvents for the stream. */
-  final StreamController _controller = new StreamController();
+  final StreamController _controller = new StreamController(sync: true);
 
   static const _EVENT_TYPE = 'KeyEvent';
 
@@ -97,7 +97,7 @@
    * Hook up all event listeners under the covers so we can estimate keycodes
    * and charcodes when they are not provided.
    */
-  _KeyboardEventHandler.initializeAllEventListeners(this._type, this._target) : 
+  _KeyboardEventHandler.initializeAllEventListeners(this._type, this._target) :
     super(_EVENT_TYPE) {
     Element.keyDownEvent.forTarget(_target, useCapture: true).listen(
         processKeyDown);
diff --git a/tools/dom/src/PathObserver.dart b/tools/dom/src/PathObserver.dart
index b0eda5f..bc07ac1 100644
--- a/tools/dom/src/PathObserver.dart
+++ b/tools/dom/src/PathObserver.dart
@@ -72,7 +72,8 @@
     // TODO(jmesserly): if the path is empty, or the object is! Observable, we
     // can optimize the PathObserver to be more lightweight.
 
-    _values = new StreamController.broadcast(onListen: _observe,
+    _values = new StreamController.broadcast(sync: true,
+                                             onListen: _observe,
                                              onCancel: _unobserve);
 
     if (_isValid) {
diff --git a/tools/dom/src/TemplateBindings.dart b/tools/dom/src/TemplateBindings.dart
index 81cebd3..5f379da 100644
--- a/tools/dom/src/TemplateBindings.dart
+++ b/tools/dom/src/TemplateBindings.dart
@@ -611,11 +611,12 @@
   static void _removeChild(Node parent, Node child) {
     child._templateInstance = null;
     if (child is Element && (child as Element).isTemplate) {
+      Element childElement = child;
       // Make sure we stop observing when we remove an element.
-      var templateIterator = child._templateIterator;
+      var templateIterator = childElement._templateIterator;
       if (templateIterator != null) {
         templateIterator.abandon();
-        child._templateIterator = null;
+        childElement._templateIterator = null;
       }
     }
     child.remove();
diff --git a/tools/dom/templates/html/impl/impl_Element.darttemplate b/tools/dom/templates/html/impl/impl_Element.darttemplate
index 188759e..7b8a594 100644
--- a/tools/dom/templates/html/impl/impl_Element.darttemplate
+++ b/tools/dom/templates/html/impl/impl_Element.darttemplate
@@ -58,6 +58,24 @@
     throw new UnsupportedError('Cannot sort element lists');
   }
 
+  void removeWhere(bool test(Element element)) {
+    _filter(test, false);
+  }
+
+  void retainWhere(bool test(Element element)) {
+    _filter(test, true);
+  }
+
+  void _filter(bool test(var element), bool retainMatching) {
+    var removed;
+    if (retainMatching) {
+      removed = _element.children.where((e) => !test(e));
+    } else {
+      removed = _element.children.where(test);
+    }
+    for (var e in removed) e.remove();
+  }
+
   void setRange(int start, int end, Iterable<Element> iterable,
                 [int skipCount = 0]) {
     throw new UnimplementedError();
@@ -450,6 +468,16 @@
     _xtag = value;
   }
 
+  @DomName('Element.localName')
+  @DocsEditable
+  String get localName => $dom_localName;
+
+  @DomName('Element.namespaceUri')
+  @DocsEditable
+  String get namespaceUri => $dom_namespaceUri;
+
+  String toString() => localName;
+
   /**
    * Scrolls this element into view.
    *
@@ -507,7 +535,7 @@
     }
   }
 
-  @DomName('Element.webkitTransitionEndEvent')
+  @DomName('Element.transitionEndEvent')
   static const EventStreamProvider<TransitionEvent> transitionEndEvent =
       const _CustomEventStreamProvider<TransitionEvent>(
         Element._determineTransitionEventType);
diff --git a/tools/dom/templates/html/impl/impl_Geolocation.darttemplate b/tools/dom/templates/html/impl/impl_Geolocation.darttemplate
index c4fec21..5049d4b 100644
--- a/tools/dom/templates/html/impl/impl_Geolocation.darttemplate
+++ b/tools/dom/templates/html/impl/impl_Geolocation.darttemplate
@@ -53,7 +53,7 @@
 
     int watchId;
     var controller;
-    controller = new StreamController<Geoposition>(
+    controller = new StreamController<Geoposition>(sync: true,
       onListen: () {
         assert(watchId == null);
         watchId = $dom_watchPosition(
diff --git a/tools/dom/templates/html/impl/impl_HTMLTemplateElement.darttemplate b/tools/dom/templates/html/impl/impl_HTMLTemplateElement.darttemplate
index 42f8d38..3ee3646 100644
--- a/tools/dom/templates/html/impl/impl_HTMLTemplateElement.darttemplate
+++ b/tools/dom/templates/html/impl/impl_HTMLTemplateElement.darttemplate
@@ -29,7 +29,7 @@
   @Experimental
   static Stream<DocumentFragment> get instanceCreated {
     if (_instanceCreated == null) {
-      _instanceCreated = new StreamController<DocumentFragment>();
+      _instanceCreated = new StreamController<DocumentFragment>(sync: true);
     }
     return _instanceCreated.stream;
   }
diff --git a/tools/dom/templates/html/impl/impl_IDBObjectStore.darttemplate b/tools/dom/templates/html/impl/impl_IDBObjectStore.darttemplate
index 4251ff5..3d9aa48 100644
--- a/tools/dom/templates/html/impl/impl_IDBObjectStore.darttemplate
+++ b/tools/dom/templates/html/impl/impl_IDBObjectStore.darttemplate
@@ -147,7 +147,7 @@
     // TODO: need to guarantee that the controller provides the values
     // immediately as waiting until the next tick will cause the transaction to
     // close.
-    var controller = new StreamController();
+    var controller = new StreamController(sync: true);
 
     request.onError.listen((e) {
       //TODO: Report stacktrace once issue 4061 is resolved.
diff --git a/tools/dom/templates/html/impl/impl_Node.darttemplate b/tools/dom/templates/html/impl/impl_Node.darttemplate
index 287151f..02edf51 100644
--- a/tools/dom/templates/html/impl/impl_Node.darttemplate
+++ b/tools/dom/templates/html/impl/impl_Node.darttemplate
@@ -230,14 +230,15 @@
    */
   Node insertAllBefore(Iterable<Node> newNodes, Node refChild) {
     if (newNodes is _ChildNodeListLazy) {
-      if (identical(newNodes._this, this)) {
+      _ChildNodeListLazy otherList = newNodes;
+      if (identical(otherList._this, this)) {
         throw new ArgumentError(newNodes);
       }
 
       // Optimized route for copying between nodes.
-      for (var i = 0, len = newNodes.length; i < len; ++i) {
+      for (var i = 0, len = otherList.length; i < len; ++i) {
         // Should use $dom_firstChild, Bug 8886.
-        this.insertBefore(newNodes[0], refChild);
+        this.insertBefore(otherList[0], refChild);
       }
     } else {
       for (var node in newNodes) {
@@ -249,8 +250,7 @@
   /**
    * Print out a String representation of this Node.
    */
-  String toString() => localName == null ?
-      (nodeValue == null ? super.toString() : nodeValue) : localName;
+  String toString() => nodeValue == null ? super.toString() : nodeValue;
 
   /**
    * Binds the attribute [name] to the [path] of the [model].
diff --git a/tools/dom/templates/html/impl/impl_ScriptProcessorNode.darttemplate b/tools/dom/templates/html/impl/impl_ScriptProcessorNode.darttemplate
index d6f813f..2c9a2eb 100644
--- a/tools/dom/templates/html/impl/impl_ScriptProcessorNode.darttemplate
+++ b/tools/dom/templates/html/impl/impl_ScriptProcessorNode.darttemplate
@@ -16,8 +16,8 @@
    */
   Stream<AudioProcessingEvent> get onAudioProcess {
     if (_eventStream == null) {
-      var controller = new StreamController();
-      var callback = (audioData) { 
+      var controller = new StreamController(sync: true);
+      var callback = (audioData) {
           if (controller.hasListener) {
             // This stream is a strange combination of broadcast and single
             // subscriber streams. We only allow one listener, but if there is
diff --git a/tools/dom/templates/html/impl/impl_WheelEvent.darttemplate b/tools/dom/templates/html/impl/impl_WheelEvent.darttemplate
index dcad713..dce1f69 100644
--- a/tools/dom/templates/html/impl/impl_WheelEvent.darttemplate
+++ b/tools/dom/templates/html/impl/impl_WheelEvent.darttemplate
@@ -50,7 +50,7 @@
       var axis = 0;
       var detail = 0;
       if (deltaX != 0 && deltaY != 0) {
-        throw UnsupportedError(
+        throw new UnsupportedError(
             'Cannot modify deltaX and deltaY simultaneously');
       }
       if (deltaY != 0) {
diff --git a/tools/dom/templates/html/impl/impl_Window.darttemplate b/tools/dom/templates/html/impl/impl_Window.darttemplate
index 9c8f8ce..cce9a48 100644
--- a/tools/dom/templates/html/impl/impl_Window.darttemplate
+++ b/tools/dom/templates/html/impl/impl_Window.darttemplate
@@ -315,7 +315,7 @@
   const _BeforeUnloadEventStreamProvider(this._eventType);
 
   Stream<BeforeUnloadEvent> forTarget(EventTarget e, {bool useCapture: false}) {
-    var controller = new StreamController();
+    var controller = new StreamController(sync: true);
     var stream = new _EventStream(e, _eventType, useCapture);
     stream.listen((event) {
       var wrapped = new _BeforeUnloadEvent(event);
diff --git a/tools/test.dart b/tools/test.dart
index 781ae2c..b1c587a 100755
--- a/tools/test.dart
+++ b/tools/test.dart
@@ -167,16 +167,9 @@
       if (key == 'co19') {
         testSuites.add(new Co19TestSuite(conf));
       } else if (conf['runtime'] == 'vm' && key == 'vm') {
-        // TODO(kustermann): Currently we don't support running VM unittest
-        // tests (i.e. run_vm_tests) on ARM because:
-        //   a) we currently use record&replay [test.dart cannot be used on ARM]
-        //   b) we cannot easily determine all the VM test names
-        //      [we would need to run 'run_vm_tests --list' on ARM]
-        if (!['arm', 'mips'].contains(conf['arch'])) {
-          // vm tests contain both cc tests (added here) and dart tests (added
-          // in [TEST_SUITE_DIRECTORIES]).
-          testSuites.add(new VMTestSuite(conf));
-        }
+        // vm tests contain both cc tests (added here) and dart tests (added
+        // in [TEST_SUITE_DIRECTORIES]).
+        testSuites.add(new VMTestSuite(conf));
       } else if (conf['analyzer']) {
         if (key == 'dartc' && conf['compiler'] == 'dartc') {
           testSuites.add(new JUnitDartcTestSuite(conf));
diff --git a/tools/testing/dart/browser_controller.dart b/tools/testing/dart/browser_controller.dart
index 9b5e966..8570f35 100644
--- a/tools/testing/dart/browser_controller.dart
+++ b/tools/testing/dart/browser_controller.dart
@@ -53,6 +53,31 @@
   // We use this to gracefully handle double calls to close.
   bool underTermination = false;
 
+  Browser();
+
+  factory Browser.byName(String name) {
+    if (name == 'ff' || name == 'firefox') {
+      return new Firefox();
+    } else if (name == 'chrome') {
+      return new Chrome();
+    } else if (name == 'safari') {
+      return new Safari();
+    } else {
+      throw "Non supported browser";
+    }
+  }
+
+  static const List<String> SUPPORTED_BROWSERS =
+      const ['safari', 'ff', 'firefox', 'chrome'];
+
+  static const List<String> BROWSERS_WITH_WINDOW_SUPPORT =
+      const ['safari', 'ff', 'firefox', 'chrome'];
+
+  // TODO(kustermann): add standard support for chrome on android
+  static bool supportedBrowser(String name) {
+    return SUPPORTED_BROWSERS.contains(name);
+  }
+
   void _logEvent(String event) {
     String toLog = "$this ($id) - ${new DateTime.now()}: $event \n";
     if (debugPrint) print("usageLog: $toLog");
@@ -510,7 +535,11 @@
   BrowserTestRunner(this.local_ip, this.browserName, this.maxNumBrowsers);
 
   Future<bool> start() {
-    testingServer = new BrowserTestingServer(local_ip);
+    // If [browserName] doesn't support opening new windows, we use new iframes
+    // instead.
+    bool useIframe =
+        !Browser.BROWSERS_WITH_WINDOW_SUPPORT.contains(browserName);
+    testingServer = new BrowserTestingServer(local_ip, useIframe);
     return testingServer.start().then((_) {
       testingServer.testDoneCallBack = handleResults;
       testingServer.nextTestCallBack = getNextTest;
@@ -709,16 +738,7 @@
   }
 
   Browser getInstance() {
-    var browser;
-    if (browserName == "chrome") {
-      browser = new Chrome();
-    } else if (browserName == "ff") {
-      browser = new Firefox();
-    } else if (browserName == "safari") {
-      browser = new Safari();
-    } else {
-      throw "Non supported browser for browser controller";
-    }
+    var browser = new Browser.byName(browserName);
     browser.logger = logger;
     return browser;
   }
@@ -748,11 +768,12 @@
   var testCount = 0;
   var httpServer;
   bool underTermination = false;
+  bool useIframe = false;
 
   Function testDoneCallBack;
   Function nextTestCallBack;
 
-  BrowserTestingServer(this.local_ip);
+  BrowserTestingServer(this.local_ip, this.useIframe);
 
   Future start() {
     return HttpServer.bind(local_ip, 0).then((createdServer) {
@@ -837,98 +858,109 @@
 <head>
   <title>Driving page</title>
   <script type='text/javascript'>
-    var number_of_tests = 0;
-    var current_id;
-    var last_reported_id;
-    var testing_window;
-    // We use this to determine if we did actually get back a start event
-    // from the test we just loaded.
-    var did_start = false;
 
-    function newTaskHandler() {
-      if (this.readyState == this.DONE) {
-        if (this.status == 200) {
-          if (this.responseText == '$waitSignal') {
-            setTimeout(getNextTask, 500);
-          } else if (this.responseText == '$terminateSignal') {
-            // Don't do anything, we will be killed shortly.
-          } else {
-            // TODO(ricow): Do something more clever here.
-            if (nextTask != undefined) alert('This is really bad');
-            // The task is send to us as:
-            // URL#ID
-            var split = this.responseText.split('#');
-            var nextTask = split[0];
-            current_id = split[1];
-            did_start = false;
-            run(nextTask);
-          }
-        } else {
-          // We are basically in trouble - do something clever.
-        }
-      }
-    }
+    function startTesting() {
+      var number_of_tests = 0;
+      var current_id;
+      var last_reported_id;
+      var testing_window;
+      // We use this to determine if we did actually get back a start event
+      // from the test we just loaded.
+      var did_start = false;
 
-    function getNextTask() {
-      var client = new XMLHttpRequest();
-      client.onreadystatechange = newTaskHandler;
-      client.open('GET', '$nextTestPath/$browserId');
-      client.send();
-    }
+      var embedded_iframe = document.getElementById('embedded_iframe');
+      var use_iframe = ${useIframe};
 
-    function run(url) {
-      number_of_tests++;
-      document.getElementById('number').innerHTML = number_of_tests;
-      if (testing_window == undefined) {
-        testing_window = window.open(url);
-      } else {
-        testing_window.location = url;
-      }
-    }
-
-    function reportMessage(msg) {
-      if (msg == 'STARTING') {
-        did_start = true;
-        return;
-      }
-      var client = new XMLHttpRequest();
-      function handleReady() {
+      function newTaskHandler() {
         if (this.readyState == this.DONE) {
-          if (last_reported_id != current_id && did_start) {
-            getNextTask();
-            last_reported_id = current_id;
+          if (this.status == 200) {
+            if (this.responseText == '$waitSignal') {
+              setTimeout(getNextTask, 500);
+            } else if (this.responseText == '$terminateSignal') {
+              // Don't do anything, we will be killed shortly.
+            } else {
+              // TODO(ricow): Do something more clever here.
+              if (nextTask != undefined) alert('This is really bad');
+              // The task is send to us as:
+              // URL#ID
+              var split = this.responseText.split('#');
+              var nextTask = split[0];
+              current_id = split[1];
+              did_start = false;
+              run(nextTask);
+            }
+          } else {
+            // We are basically in trouble - do something clever.
           }
         }
       }
-      client.onreadystatechange = handleReady;
-      // If did_start is false it means that we did actually set the url on
-      // the testing_window, but this is a report left in the event loop or
-      // a callback because the page did not load yet.
-      // In both cases this is a double report from the last test.
-      var posting_id = did_start ? current_id : last_reported_id;
-      client.open('POST', '$reportPath/${browserId}?id=' + posting_id);
-      client.setRequestHeader('Content-type',
-                              'application/x-www-form-urlencoded');
-      client.send(msg);
-      // TODO(ricow) add error handling to somehow report the fact that
-      // we could not send back a result.
+
+      function getNextTask() {
+        var client = new XMLHttpRequest();
+        client.onreadystatechange = newTaskHandler;
+        client.open('GET', '$nextTestPath/$browserId');
+        client.send();
+      }
+
+      function run(url) {
+        number_of_tests++;
+        document.getElementById('number').innerHTML = number_of_tests;
+        if (use_iframe) {
+          embedded_iframe.src = url;
+        } else {
+          if (testing_window == undefined) {
+            testing_window = window.open(url);
+          } else {
+            testing_window.location = url;
+          }
+        }
+      }
+
+      function reportMessage(msg) {
+        if (msg == 'STARTING') {
+          did_start = true;
+          return;
+        }
+        var client = new XMLHttpRequest();
+        function handleReady() {
+          if (this.readyState == this.DONE) {
+            if (last_reported_id != current_id && did_start) {
+              getNextTask();
+              last_reported_id = current_id;
+            }
+          }
+        }
+        client.onreadystatechange = handleReady;
+        // If did_start is false it means that we did actually set the url on
+        // the testing_window, but this is a report left in the event loop or
+        // a callback because the page did not load yet.
+        // In both cases this is a double report from the last test.
+        var posting_id = did_start ? current_id : last_reported_id;
+        client.open('POST', '$reportPath/${browserId}?id=' + posting_id);
+        client.setRequestHeader('Content-type',
+                                'application/x-www-form-urlencoded');
+        client.send(msg);
+        // TODO(ricow) add error handling to somehow report the fact that
+        // we could not send back a result.
+      }
+
+      function messageHandler(e) {
+        var msg = e.data;
+        if (typeof msg != 'string') return;
+        reportMessage(msg);
+      }
+
+      window.addEventListener('message', messageHandler, false);
+      waitForDone = false;
+
+      getNextTask();
     }
 
-    function messageHandler(e) {
-      var msg = e.data;
-      if (typeof msg != 'string') return;
-      reportMessage(msg);
-    }
-
-    window.addEventListener('message', messageHandler, false);
-    waitForDone = false;
-
-    getNextTask();
-
   </script>
 </head>
-  <body>
+  <body onload="startTesting()">
     Dart test driver, number of tests: <div id="number"></div>
+    <iframe id="embedded_iframe"></iframe>
   </body>
 </html>
 """;
diff --git a/tools/testing/dart/launch_browser.dart b/tools/testing/dart/launch_browser.dart
new file mode 100644
index 0000000..3637906
--- /dev/null
+++ b/tools/testing/dart/launch_browser.dart
@@ -0,0 +1,39 @@
+// 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.
+
+/**
+ * Simple command line interface to launching browsers.
+ * Uses the browser_controller framework.
+ * The usage is:
+ *   DARTBIN launch_browser.dart BROWSER_NAME URL
+ * DARTBIN should be the checked in stable binary.
+ */
+
+import "dart:io";
+import "browser_controller.dart";
+
+void printHelp() {
+  print("Usage pattern:");
+  print("launch_browser.dart browser url");
+  print("Supported browsers: ${Browser.SUPPORTED_BROWSERS}");
+}
+
+void main() {
+  var args = new Options().arguments;
+  if (args.length != 2) {
+    print("Wrong number of arguments, please pass in exactly two arguments");
+    printHelp();
+    return;
+  }
+
+  if (!Browser.supportedBrowser(args[0])) {
+    print("Specified browser not supported");
+    printHelp();
+    return;
+  }
+
+  var browser = new Browser.byName(args[0]);
+  browser.start(args[1]);
+
+}
diff --git a/tools/testing/dart/test_progress.dart b/tools/testing/dart/test_progress.dart
index b9ce10b..f105505 100644
--- a/tools/testing/dart/test_progress.dart
+++ b/tools/testing/dart/test_progress.dart
@@ -90,40 +90,46 @@
       }
     }
   }
-  if (!test.lastCommandOutput.diagnostics.isEmpty) {
-    String prefix = 'diagnostics:';
-    for (var s in test.lastCommandOutput.diagnostics) {
-      output.add('$prefix ${s}');
-      prefix = '   ';
+  for (var i = 0; i < test.commands.length; i++) {
+    var command = test.commands[i];
+    var commandOutput = test.commandOutputs[command];
+    if (commandOutput != null) {
+      output.add("CommandOutput[$i]:");
+      if (!commandOutput.diagnostics.isEmpty) {
+        String prefix = 'diagnostics:';
+        for (var s in commandOutput.diagnostics) {
+          output.add('$prefix ${s}');
+          prefix = '   ';
+        }
+      }
+      if (!commandOutput.stdout.isEmpty) {
+        output.add('');
+        output.add('stdout:');
+        if (command.isPixelTest) {
+          output.add('DRT pixel test failed! stdout is not printed because it '
+                     'contains binary data!');
+        } else {
+          output.addAll(getLinesWithoutCarriageReturn(commandOutput.stdout));
+        }
+      }
+      if (!commandOutput.stderr.isEmpty) {
+        output.add('');
+        output.add('stderr:');
+        output.addAll(getLinesWithoutCarriageReturn(commandOutput.stderr));
+      }
     }
   }
-  if (!test.lastCommandOutput.stdout.isEmpty) {
-    output.add('');
-    output.add('stdout:');
-    if (test.lastCommandOutput.command.isPixelTest) {
-      output.add('DRT pixel test failed! stdout is not printed because it '
-                 'contains binary data!');
-    } else {
-      output.addAll(
-          getLinesWithoutCarriageReturn(test.lastCommandOutput.stdout));
-    }
-  }
-  if (!test.lastCommandOutput.stderr.isEmpty) {
-    output.add('');
-    output.add('stderr:');
-    output.addAll(getLinesWithoutCarriageReturn(test.lastCommandOutput.stderr));
-  }
   if (test is BrowserTestCase) {
     // Additional command for rerunning the steps locally after the fact.
     var command =
       test.configuration["_servers_"].httpServerCommandline();
+    output.add('');
     output.add('To retest, run:  $command');
   }
-  for (Command c in test.commands) {
+  for (var i = 0; i < test.commands.length; i++) {
+    var command = test.commands[i];
     output.add('');
-    String message = (c == test.commands.last
-        ? "Command line" : "Compilation command");
-    output.add('$message: $c');
+    output.add('Command[$i]: $command');
   }
   return output;
 }
diff --git a/tools/testing/dart/test_runner.dart b/tools/testing/dart/test_runner.dart
index 9169a83..0b3b454 100644
--- a/tools/testing/dart/test_runner.dart
+++ b/tools/testing/dart/test_runner.dart
@@ -117,7 +117,7 @@
     }
     var quotedArguments = [];
     arguments.forEach((argument) => quotedArguments.add('"$argument"'));
-    commandLine = "$executable ${quotedArguments.join(' ')}";
+    commandLine = "\"$executable\" ${quotedArguments.join(' ')}";
   }
 
   String toString() => commandLine;
@@ -1649,7 +1649,7 @@
   Future<BrowserTestRunner> _getBrowserTestRunner(TestCase test) {
     var local_ip = test.configuration['local_ip'];
     var runtime = test.configuration['runtime'];
-    var num_browsers = 1;//test.configuration['tasks'];
+    var num_browsers = test.configuration['tasks'];
     if (_browserTestRunners[runtime] == null) {
       var testRunner =
         new BrowserTestRunner(local_ip, runtime, num_browsers);
diff --git a/tools/testing/dart/test_suite.dart b/tools/testing/dart/test_suite.dart
index 2a6fa18..843bb8c 100644
--- a/tools/testing/dart/test_suite.dart
+++ b/tools/testing/dart/test_suite.dart
@@ -304,7 +304,8 @@
  */
 class CCTestSuite extends TestSuite {
   final String testPrefix;
-  String runnerPath;
+  String targetRunnerPath;
+  String hostRunnerPath;
   final String dartDir;
   List<String> statusFilePaths;
   TestCaseEvent doTest;
@@ -319,7 +320,18 @@
               {this.testPrefix: ''})
       : super(configuration, suiteName),
         dartDir = TestUtils.dartDir().toNativePath() {
-    runnerPath = '$buildDir/$runnerName';
+    // For running the tests we use the given '$runnerName' binary
+    targetRunnerPath = '$buildDir/$runnerName';
+
+    // For listing the tests we use the '$runnerName.host' binary if it exists
+    // and use '$runnerName' if it doesn't.
+    var binarySuffix = Platform.operatingSystem == 'windows' ? '.exe' : '';
+    var hostBinary = '$targetRunnerPath.host$binarySuffix';
+    if (new File(hostBinary).existsSync()) {
+      hostRunnerPath = hostBinary;
+    } else {
+      hostRunnerPath = targetRunnerPath;
+    }
   }
 
   void testNameHandler(String testName, ignore) {
@@ -347,7 +359,7 @@
       args.add(testName);
 
       doTest(new TestCase(constructedName,
-                          [new Command(runnerPath, args)],
+                          [new Command(targetRunnerPath, args)],
                           configuration,
                           completeHandler,
                           expectations));
@@ -364,7 +376,7 @@
       if (filesRead == statusFilePaths.length) {
         receiveTestName = new ReceivePort();
         var port = spawnFunction(ccTestLister);
-        port.send(runnerPath, receiveTestName.toSendPort());
+        port.send(hostRunnerPath, receiveTestName.toSendPort());
         receiveTestName.receive(testNameHandler);
       }
     }
@@ -1181,8 +1193,9 @@
       return configuration['drt'];
     }
     if (Platform.operatingSystem == 'macos') {
-      return dartDir.append('/client/tests/drt/Content Shell.app/Contents/'
-                            'MacOS/Content Shell').toNativePath();
+      final path = dartDir.append(
+          '/client/tests/drt/Content Shell.app/Contents/MacOS/Content Shell');
+      return path.toNativePath();
     }
     return dartDir.append('client/tests/drt/content_shell').toNativePath();
   }
diff --git a/utils/compiler/create_snapshot.dart b/utils/compiler/create_snapshot.dart
index f1bc9db..c5a8af4 100644
--- a/utils/compiler/create_snapshot.dart
+++ b/utils/compiler/create_snapshot.dart
@@ -82,10 +82,9 @@
   if (!args.containsKey("dart2js_main")) throw "Please specify dart2js_main";
   if (!args.containsKey("output_dir")) throw "Please specify output_dir";
 
-  var scriptFile = new File(options.script);
-  var path = new Path(scriptFile.directorySync().path);
+  var scriptFile = new File(new File(options.script).fullPathSync());
+  var path = new Path(scriptFile.directory.path);
   var rootPath = path.directoryPath.directoryPath;
-
   getSnapshotGenerationFile(options, args, rootPath).then((result) {
     var wrapper = "${args['output_dir']}/utils_wrapper.dart";
     writeSnapshotFile(wrapper, result);
diff --git a/utils/tests/css/css.status b/utils/tests/css/css.status
index e857409..6b7ba1c 100644
--- a/utils/tests/css/css.status
+++ b/utils/tests/css/css.status
@@ -8,8 +8,14 @@
 [ $arch == x64 ]
 *: Skip
 
+[ $arch == arm ]
+*: Skip
+
 [ $arch == simarm ]
 *: Skip
 
-[ $arch == arm ]
+[ $arch == mips ]
+*: Skip
+
+[ $arch == simmips ]
 *: Skip
diff --git a/utils/tests/peg/peg.status b/utils/tests/peg/peg.status
index d933e20..ba6061c 100644
--- a/utils/tests/peg/peg.status
+++ b/utils/tests/peg/peg.status
@@ -8,8 +8,14 @@
 [ $arch == x64 ]
 *: Skip
 
+[ $arch == arm ]
+*: Skip
+
 [ $arch == simarm ]
 *: Skip
 
-[ $arch == arm ]
+[ $arch == mips ]
+*: Skip
+
+[ $arch == simmips ]
 *: Skip