Version 0.5.12.0

svn merge -r 23167:23342  https://dart.googlecode.com/svn/branches/bleeding_edge trunk

git-svn-id: http://dart.googlecode.com/svn/trunk@23346 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/dart.gyp b/dart.gyp
index c4b0ddc..0be9a49 100644
--- a/dart.gyp
+++ b/dart.gyp
@@ -38,9 +38,15 @@
         'runtime/dart-runtime.gyp:dart_no_snapshot',
         'runtime/dart-runtime.gyp:run_vm_tests',
         'runtime/dart-runtime.gyp:process_test',
-        'runtime/dart-runtime.gyp:test_extension',
         'packages',
       ],
+      'conditions': [
+        ['OS!="android"', {
+          'dependencies': [
+            'runtime/dart-runtime.gyp:test_extension',
+          ],
+        }],
+      ],
     },
     {
       # Build the SDK. This target is separate from upload_sdk as the
diff --git a/pkg/analyzer_experimental/example/resolver_driver.dart b/pkg/analyzer_experimental/example/resolver_driver.dart
index c3a9ef7..883816e 100644
--- a/pkg/analyzer_experimental/example/resolver_driver.dart
+++ b/pkg/analyzer_experimental/example/resolver_driver.dart
@@ -28,7 +28,7 @@
 
   AnalysisContext context = AnalysisEngine.instance.createAnalysisContext();
   context.sourceFactory = new SourceFactory.con2([new DartUriResolver(sdk), new FileUriResolver()]);
-  Source source = new FileBasedSource.con1(context.sourceFactory, new JavaFile(args[1]));
+  Source source = new FileBasedSource.con1(context.sourceFactory.contentCache, new JavaFile(args[1]));
   //
   ChangeSet changeSet = new ChangeSet();
   changeSet.added(source);
diff --git a/pkg/analyzer_experimental/lib/options.dart b/pkg/analyzer_experimental/lib/options.dart
index d26060b..c6fd30d 100644
--- a/pkg/analyzer_experimental/lib/options.dart
+++ b/pkg/analyzer_experimental/lib/options.dart
@@ -37,6 +37,9 @@
   /** The path to the dart SDK */
   final String dartSdkPath;
 
+  /** The path to the package root */
+  final String packageRootPath;
+
   /** The source files to analyze */
   final List<String> sourceFiles;
 
@@ -45,12 +48,13 @@
    */
   CommandLineOptions._fromArgs(ArgResults args)
     : shouldBatch = args['batch'],
-      machineFormat = args['machine_format'],
-      ignoreUnrecognizedFlags = args['ignore_unrecognized_flags'],
-      showPackageWarnings = args['show_package_warnings'],
-      showSdkWarnings = args['show_sdk_warnings'],
-      warningsAreFatal = args['fatal_warnings'],
-      dartSdkPath = args['dart_sdk'],
+      machineFormat = args['machine-format'],
+      ignoreUnrecognizedFlags = args['ignore-unrecognized-flags'],
+      showPackageWarnings = args['show-package-warnings'],
+      showSdkWarnings = args['show-sdk-warnings'],
+      warningsAreFatal = args['fatal-warnings'],
+      dartSdkPath = args['dart-sdk'],
+      packageRootPath = args['package-root'],
       sourceFiles = args.rest;
 
   /**
@@ -81,18 +85,19 @@
     var parser = new _CommandLineParser()
       ..addFlag('batch', abbr: 'b', help: 'Run in batch mode',
           defaultsTo: false, negatable: false)
-      ..addOption('dart_sdk', help: 'Specify path to the Dart sdk')
-      ..addFlag('machine_format', help: 'Specify whether errors '
+      ..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',
           defaultsTo: false, negatable: false)
-      ..addFlag('ignore_unrecognized_flags',
+      ..addFlag('ignore-unrecognized-flags',
           help: 'Ignore unrecognized command line flags',
           defaultsTo: false, negatable: false)
-      ..addFlag('fatal_warnings', help: 'Treat non-type warnings as fatal',
+      ..addFlag('fatal-warnings', help: 'Treat non-type warnings as fatal',
           defaultsTo: false, negatable: false)
-      ..addFlag('show_package_warnings', help: 'Show warnings from package: imports',
+      ..addFlag('show-package-warnings', help: 'Show warnings from package: imports',
          defaultsTo: false, negatable: false)
-      ..addFlag('show_sdk_warnings', help: 'Show warnings from SDK imports',
+      ..addFlag('show-sdk-warnings', help: 'Show warnings from SDK imports',
          defaultsTo: false, negatable: false)
       ..addFlag('help', abbr: 'h', help: 'Display this help message',
          defaultsTo: false, negatable: false);
diff --git a/pkg/analyzer_experimental/lib/src/analyzer_impl.dart b/pkg/analyzer_experimental/lib/src/analyzer_impl.dart
index 40b8deb..84cfb8d 100644
--- a/pkg/analyzer_experimental/lib/src/analyzer_impl.dart
+++ b/pkg/analyzer_experimental/lib/src/analyzer_impl.dart
@@ -71,7 +71,12 @@
     List<UriResolver> resolvers = [new DartUriResolver(sdk), new FileUriResolver()];
     // may be add package resolver
     {
-      var packageDirectory = getPackageDirectoryFor(sourceFile);
+      JavaFile packageDirectory;
+      if (options.packageRootPath != null) {
+        packageDirectory = new JavaFile(options.packageRootPath);
+      } else {
+        packageDirectory = getPackageDirectoryFor(sourceFile);
+      }
       if (packageDirectory != null) {
         resolvers.add(new PackageUriResolver([packageDirectory]));
       }
@@ -138,11 +143,18 @@
   }
 
   static JavaFile getPackageDirectoryFor(JavaFile sourceFile) {
-    JavaFile sourceFolder = sourceFile.getParentFile();
-    JavaFile packagesFolder = new JavaFile.relative(sourceFolder, "packages");
-    if (packagesFolder.exists()) {
-      return packagesFolder;
+    // we are going to ask parent file, so get absolute path
+    sourceFile = sourceFile.getAbsoluteFile();
+    // look in the containing directories
+    JavaFile dir = sourceFile.getParentFile();
+    while (dir != null) {
+      JavaFile packagesDir = new JavaFile.relative(dir, "packages");
+      if (packagesDir.exists()) {
+        return packagesDir;
+      }
+      dir = dir.getParentFile();
     }
+    // not found
     return null;
   }
 }
diff --git a/pkg/analyzer_experimental/lib/src/error.dart b/pkg/analyzer_experimental/lib/src/error.dart
index 5485a0f..d3df0e1 100644
--- a/pkg/analyzer_experimental/lib/src/error.dart
+++ b/pkg/analyzer_experimental/lib/src/error.dart
@@ -98,8 +98,8 @@
 
   String get result => _buffer.toString();
 
-  void accept1(CharBuffer contents, _) =>
-    _buffer.write(contents.subSequence(0, contents.length));
+  void accept(CharBuffer contents, _) =>
+    _buffer.write(contents.subSequence(0, contents.length()));
 
   void accept2(String contents, _) => _buffer.write(contents);
 }
diff --git a/pkg/analyzer_experimental/lib/src/generated/engine.dart b/pkg/analyzer_experimental/lib/src/generated/engine.dart
index fca4fef..e9390f7 100644
--- a/pkg/analyzer_experimental/lib/src/generated/engine.dart
+++ b/pkg/analyzer_experimental/lib/src/generated/engine.dart
@@ -4,7 +4,6 @@
 library engine;
 
 import 'dart:collection' show HasNextIterator;
-import 'dart:uri' show Uri;
 import 'java_core.dart';
 import 'java_engine.dart';
 import 'instrumentation.dart';
@@ -2828,7 +2827,7 @@
       for (XmlAttributeNode attribute in node.attributes) {
         if (javaStringEqualsIgnoreCase(attribute.name.lexeme, AnalysisContextImpl._ATTRIBUTE_SRC)) {
           try {
-            Uri uri = new Uri.fromComponents(path: attribute.text);
+            Uri uri = new Uri(path: attribute.text);
             String fileName = uri.path;
             if (AnalysisEngine.isDartFileName(fileName)) {
               Source librarySource = AnalysisContextImpl_this._sourceFactory.resolveUri(htmlSource, fileName);
diff --git a/pkg/analyzer_experimental/lib/src/generated/error.dart b/pkg/analyzer_experimental/lib/src/generated/error.dart
index 1f684c9..152ea76 100644
--- a/pkg/analyzer_experimental/lib/src/generated/error.dart
+++ b/pkg/analyzer_experimental/lib/src/generated/error.dart
@@ -1395,7 +1395,7 @@
   /**
    * An error listener that ignores errors that are reported to it.
    */
-  AnalysisErrorListener _NULL_LISTENER = new AnalysisErrorListener_4();
+  static AnalysisErrorListener _NULL_LISTENER = new AnalysisErrorListener_4();
   /**
    * This method is invoked when an error has been found by the analysis engine.
    * @param error the error that was just found (not {@code null})
diff --git a/pkg/analyzer_experimental/lib/src/generated/java_core.dart b/pkg/analyzer_experimental/lib/src/generated/java_core.dart
index 3bf99ccc..445d6d7 100644
--- a/pkg/analyzer_experimental/lib/src/generated/java_core.dart
+++ b/pkg/analyzer_experimental/lib/src/generated/java_core.dart
@@ -1,7 +1,6 @@
 library java.core;
 
 import "dart:math" as math;
-import "dart:uri";
 import "dart:collection" show ListBase;
 
 class JavaSystem {
@@ -319,7 +318,7 @@
   }
 
   void setAll(int index, Iterable<E> iterable) {
-    elements.setAll(iterable);
+    elements.setAll(index, iterable);
   }
 
   void sort([int compare(E a, E b)]) {
@@ -462,11 +461,13 @@
 class JavaStringBuilder {
   StringBuffer sb = new StringBuffer();
   String toString() => sb.toString();
-  void append(x) {
+  JavaStringBuilder append(x) {
     sb.write(x);
+    return this;
   }
-  void appendChar(int c) {
+  JavaStringBuilder appendChar(int c) {
     sb.writeCharCode(c);
+    return this;
   }
   int get length => sb.length;
   void set length(int newLength) {
diff --git a/pkg/analyzer_experimental/lib/src/generated/java_io.dart b/pkg/analyzer_experimental/lib/src/generated/java_io.dart
index b5ac6d9..f818d57 100644
--- a/pkg/analyzer_experimental/lib/src/generated/java_io.dart
+++ b/pkg/analyzer_experimental/lib/src/generated/java_io.dart
@@ -1,7 +1,6 @@
 library java.io;
 
 import "dart:io";
-import "dart:uri";
 
 class JavaSystemIO {
   static Map<String, String> _properties = new Map();
@@ -84,7 +83,7 @@
   bool isDirectory() {
     return _newDirectory().existsSync();
   }
-  Uri toURI() => new Uri.fromComponents(path: _path.toString());
+  Uri toURI() => new Uri(path: _path.toString());
   String readAsStringSync() => _newFile().readAsStringSync();
   int lastModified() => _newFile().lastModifiedSync().millisecondsSinceEpoch;
   File _newFile() => new File.fromPath(_path);
diff --git a/pkg/analyzer_experimental/lib/src/generated/resolver.dart b/pkg/analyzer_experimental/lib/src/generated/resolver.dart
index fc7b84d..42147fa 100644
--- a/pkg/analyzer_experimental/lib/src/generated/resolver.dart
+++ b/pkg/analyzer_experimental/lib/src/generated/resolver.dart
@@ -4,7 +4,6 @@
 library engine.resolver;
 
 import 'dart:collection';
-import 'dart:uri' show Uri;
 import 'java_core.dart';
 import 'java_engine.dart';
 import 'instrumentation.dart';
@@ -880,7 +879,7 @@
         ExternalHtmlScriptElementImpl script = new ExternalHtmlScriptElementImpl(node);
         if (scriptSourcePath != null) {
           try {
-            new Uri(scriptSourcePath);
+            Uri.parse(scriptSourcePath);
             Source scriptSource = _context.sourceFactory.resolveUri(htmlSource, scriptSourcePath);
             script.scriptSource = scriptSource;
             if (!scriptSource.exists()) {
@@ -1994,7 +1993,7 @@
         } else if (identifier.inGetterContext()) {
           _resolver.reportError(StaticWarningCode.UNDEFINED_GETTER, identifier, [identifier.name, targetType.name]);
         } else {
-          System.out.println("two ${identifier.name}");
+          print("two ${identifier.name}");
           _resolver.reportError(StaticWarningCode.UNDEFINED_IDENTIFIER, identifier, [identifier.name]);
         }
       }
@@ -8417,4 +8416,4 @@
   bool needsRecompilation() => true;
   int compareTo(ResolverErrorCode other) => __ordinal - other.__ordinal;
   String toString() => __name;
-}
\ No newline at end of file
+}
diff --git a/pkg/analyzer_experimental/lib/src/generated/sdk.dart b/pkg/analyzer_experimental/lib/src/generated/sdk.dart
index 64bc958..9825059 100644
--- a/pkg/analyzer_experimental/lib/src/generated/sdk.dart
+++ b/pkg/analyzer_experimental/lib/src/generated/sdk.dart
@@ -3,7 +3,6 @@
 
 library engine.sdk;
 
-import 'dart:uri';
 import 'java_core.dart';
 import 'java_engine.dart';
 import 'source.dart' show ContentCache, Source, UriKind;
diff --git a/pkg/analyzer_experimental/lib/src/generated/sdk_io.dart b/pkg/analyzer_experimental/lib/src/generated/sdk_io.dart
index cb9c473..47abce7 100644
--- a/pkg/analyzer_experimental/lib/src/generated/sdk_io.dart
+++ b/pkg/analyzer_experimental/lib/src/generated/sdk_io.dart
@@ -4,7 +4,6 @@
 library engine.sdk.io;
 
 import 'dart:io';
-import 'dart:uri';
 import 'java_core.dart';
 import 'java_io.dart';
 import 'java_engine.dart';
diff --git a/pkg/analyzer_experimental/lib/src/generated/source.dart b/pkg/analyzer_experimental/lib/src/generated/source.dart
index 83c24d0..1be6594 100644
--- a/pkg/analyzer_experimental/lib/src/generated/source.dart
+++ b/pkg/analyzer_experimental/lib/src/generated/source.dart
@@ -3,7 +3,6 @@
 
 library engine.source;
 
-import 'dart:uri';
 import 'java_core.dart';
 import 'sdk.dart' show DartSdk;
 import 'engine.dart' show AnalysisContext;
@@ -55,7 +54,7 @@
    */
   Source forUri(String absoluteUri) {
     try {
-      Uri uri = new Uri(absoluteUri);
+      Uri uri = Uri.parse(absoluteUri);
       if (uri.isAbsolute) {
         return resolveUri2(null, uri);
       }
@@ -79,7 +78,7 @@
       throw new IllegalArgumentException("Invalid source kind in encoding: ${kind}");
     }
     try {
-      Uri uri = new Uri(encoding.substring(1));
+      Uri uri = Uri.parse(encoding.substring(1));
       for (UriResolver resolver in _resolvers) {
         Source result = resolver.fromEncoding(_contentCache, kind, uri);
         if (result != null) {
@@ -126,7 +125,7 @@
    */
   Source resolveUri(Source containingSource, String containedUri) {
     try {
-      return resolveUri2(containingSource, new Uri(containedUri));
+      return resolveUri2(containingSource, Uri.parse(containedUri));
     } on URISyntaxException catch (exception) {
       return null;
     }
@@ -729,4 +728,4 @@
       _stampMap[source] = JavaSystem.currentTimeMillis();
     }
   }
-}
\ No newline at end of file
+}
diff --git a/pkg/analyzer_experimental/lib/src/generated/source_io.dart b/pkg/analyzer_experimental/lib/src/generated/source_io.dart
index f016564..5d5a49f 100644
--- a/pkg/analyzer_experimental/lib/src/generated/source_io.dart
+++ b/pkg/analyzer_experimental/lib/src/generated/source_io.dart
@@ -5,7 +5,6 @@
 
 import 'source.dart';
 import 'dart:io';
-import 'dart:uri';
 import 'java_core.dart';
 import 'java_io.dart';
 import 'sdk.dart' show DartSdk;
@@ -195,7 +194,7 @@
     } on IOException catch (e) {
       AnalysisEngine.instance.logger.logError2("Canonical failed: ${pkgDir}", e);
     }
-    return new JavaFile.relative(pkgDir, relPath.replaceAll(0x2F, JavaFile.separatorChar));
+    return new JavaFile.relative(pkgDir, relPath.replaceAll('/', JavaFile.separatorChar));
   }
 }
 /**
diff --git a/pkg/analyzer_experimental/lib/src/utils.dart b/pkg/analyzer_experimental/lib/src/utils.dart
index 4ff702f..2b5053e 100644
--- a/pkg/analyzer_experimental/lib/src/utils.dart
+++ b/pkg/analyzer_experimental/lib/src/utils.dart
@@ -4,7 +4,6 @@
 library utils;
 
 import 'dart:io';
-import 'dart:uri';
 
 import 'package:pathos/path.dart' as pathos;
 
diff --git a/pkg/analyzer_experimental/test/generated/resolver_test.dart b/pkg/analyzer_experimental/test/generated/resolver_test.dart
index 829f7ff..fd28a66 100644
--- a/pkg/analyzer_experimental/test/generated/resolver_test.dart
+++ b/pkg/analyzer_experimental/test/generated/resolver_test.dart
@@ -2230,7 +2230,7 @@
     verify([source]);
   }
   void fail_prefixCollidesWithTopLevelMembers() {
-    Source source = addSource(EngineTestCase.createSource(["import 'dart:uri' as uri;", "var uri = null;"]));
+    Source source = addSource(EngineTestCase.createSource(["import 'dart:uft' as utf;", "var utf = null;"]));
     resolve(source, []);
     assertErrors([CompileTimeErrorCode.PREFIX_COLLIDES_WITH_TOP_LEVEL_MEMBER]);
     verify([source]);
@@ -6765,4 +6765,4 @@
 //  StaticTypeWarningCodeTest.dartSuite();
 //  StaticWarningCodeTest.dartSuite();
 //  TypePropagationTest.dartSuite();
-}
\ No newline at end of file
+}
diff --git a/pkg/analyzer_experimental/test/generated/test_support.dart b/pkg/analyzer_experimental/test/generated/test_support.dart
index c666db1..df7f862 100644
--- a/pkg/analyzer_experimental/test/generated/test_support.dart
+++ b/pkg/analyzer_experimental/test/generated/test_support.dart
@@ -4,7 +4,6 @@
 library engine.test_support;
 
 import 'dart:collection';
-import 'dart:uri';
 import 'package:analyzer_experimental/src/generated/java_core.dart';
 import 'package:analyzer_experimental/src/generated/java_engine.dart';
 import 'package:analyzer_experimental/src/generated/java_junit.dart';
@@ -669,6 +668,9 @@
   Source resolveRelative(Uri uri) {
     throw new UnsupportedOperationException();
   }
+  UriKind get uriKind {
+    throw new UnsupportedOperationException();
+  }
 }
 
 /**
diff --git a/pkg/args/example/test_runner.dart b/pkg/args/example/test_runner.dart
index d0a6ed8..74750ae 100644
--- a/pkg/args/example/test_runner.dart
+++ b/pkg/args/example/test_runner.dart
@@ -40,8 +40,9 @@
       allowedHelp: {
         'vm': 'Run Dart code on the standalone dart vm.',
         'd8': 'Run JavaScript from the command line using v8.',
+        // TODO(antonm): rename flag.
         'drt': 'Run Dart or JavaScript in the headless version of Chrome,\n'
-          'DumpRenderTree.',
+          'content shell.',
         'dartium': 'Run Dart or JavaScript in Dartium.',
         'ff': 'Run JavaScript in Firefox',
         'chrome': 'Run JavaScript in Chrome',
@@ -116,7 +117,8 @@
       defaultsTo: false);
 
   parser.addOption('dart',    help: 'Path to dart executable');
-  parser.addOption('drt',     help: 'Path to DumpRenderTree executable');
+  // TODO(antonm): rename the option.
+  parser.addOption('drt',     help: 'Path to content shell executable');
   parser.addOption('dartium', help: 'Path to Dartium Chrome executable');
 
   parser.addFlag('batch', abbr: 'b',
diff --git a/sdk/lib/crypto/crypto.dart b/pkg/crypto/lib/crypto.dart
similarity index 96%
rename from sdk/lib/crypto/crypto.dart
rename to pkg/crypto/lib/crypto.dart
index a34ce53..1b764ae 100644
--- a/sdk/lib/crypto/crypto.dart
+++ b/pkg/crypto/lib/crypto.dart
@@ -6,12 +6,12 @@
 
 import 'dart:math';
 
-part 'crypto_utils.dart';
-part 'hash_utils.dart';
-part 'hmac.dart';
-part 'md5.dart';
-part 'sha1.dart';
-part 'sha256.dart';
+part 'src/crypto_utils.dart';
+part 'src/hash_utils.dart';
+part 'src/hmac.dart';
+part 'src/md5.dart';
+part 'src/sha1.dart';
+part 'src/sha256.dart';
 
 /**
  * Interface for cryptographic hash functions.
diff --git a/sdk/lib/crypto/crypto_utils.dart b/pkg/crypto/lib/src/crypto_utils.dart
similarity index 100%
rename from sdk/lib/crypto/crypto_utils.dart
rename to pkg/crypto/lib/src/crypto_utils.dart
diff --git a/sdk/lib/crypto/hash_utils.dart b/pkg/crypto/lib/src/hash_utils.dart
similarity index 100%
rename from sdk/lib/crypto/hash_utils.dart
rename to pkg/crypto/lib/src/hash_utils.dart
diff --git a/sdk/lib/crypto/hmac.dart b/pkg/crypto/lib/src/hmac.dart
similarity index 100%
rename from sdk/lib/crypto/hmac.dart
rename to pkg/crypto/lib/src/hmac.dart
diff --git a/sdk/lib/crypto/md5.dart b/pkg/crypto/lib/src/md5.dart
similarity index 100%
rename from sdk/lib/crypto/md5.dart
rename to pkg/crypto/lib/src/md5.dart
diff --git a/sdk/lib/crypto/sha1.dart b/pkg/crypto/lib/src/sha1.dart
similarity index 100%
rename from sdk/lib/crypto/sha1.dart
rename to pkg/crypto/lib/src/sha1.dart
diff --git a/sdk/lib/crypto/sha256.dart b/pkg/crypto/lib/src/sha256.dart
similarity index 100%
rename from sdk/lib/crypto/sha256.dart
rename to pkg/crypto/lib/src/sha256.dart
diff --git a/pkg/crypto/pubspec.yaml b/pkg/crypto/pubspec.yaml
new file mode 100644
index 0000000..cc3c47d
--- /dev/null
+++ b/pkg/crypto/pubspec.yaml
@@ -0,0 +1,5 @@
+name: crypto
+author: "Dart Team <misc@dartlang.org>"
+homepage: http://www.dartlang.org
+description: >
+ Library of cryptographic functions.
diff --git a/pkg/http/lib/http.dart b/pkg/http/lib/http.dart
index dda24f24..752a53b 100644
--- a/pkg/http/lib/http.dart
+++ b/pkg/http/lib/http.dart
@@ -69,7 +69,6 @@
 
 import 'dart:async';
 import 'dart:typed_data';
-import 'dart:uri';
 
 import 'src/client.dart';
 import 'src/response.dart';
diff --git a/pkg/http/lib/src/base_client.dart b/pkg/http/lib/src/base_client.dart
index df6e730..2526a62 100644
--- a/pkg/http/lib/src/base_client.dart
+++ b/pkg/http/lib/src/base_client.dart
@@ -7,7 +7,6 @@
 import 'dart:async';
 import 'dart:io';
 import 'dart:typed_data';
-import 'dart:uri';
 
 import 'base_request.dart';
 import 'client.dart';
diff --git a/pkg/http/lib/src/base_request.dart b/pkg/http/lib/src/base_request.dart
index ffff471..415e27a 100644
--- a/pkg/http/lib/src/base_request.dart
+++ b/pkg/http/lib/src/base_request.dart
@@ -7,7 +7,6 @@
 import 'dart:async';
 import 'dart:io';
 import 'dart:isolate';
-import 'dart:uri';
 
 import 'byte_stream.dart';
 import 'client.dart';
diff --git a/pkg/http/lib/src/multipart_request.dart b/pkg/http/lib/src/multipart_request.dart
index ab66bbd..6d8f03b 100644
--- a/pkg/http/lib/src/multipart_request.dart
+++ b/pkg/http/lib/src/multipart_request.dart
@@ -7,7 +7,6 @@
 import 'dart:async';
 import 'dart:io';
 import 'dart:math';
-import 'dart:uri';
 import 'dart:utf';
 
 import 'base_request.dart';
@@ -138,7 +137,8 @@
     // http://tools.ietf.org/html/rfc2388 mandates some complex encodings for
     // field names and file names, but in practice user agents seem to just
     // URL-encode them so we do the same.
-    var header = 'content-disposition: form-data; name="${encodeUri(name)}"';
+    var header =
+        'content-disposition: form-data; name="${Uri.encodeFull(name)}"';
     if (!isPlainAscii(value)) {
       header = '$header\r\ncontent-type: text/plain; charset=utf-8';
     }
@@ -149,10 +149,10 @@
   /// contain only ASCII characters.
   String _headerForFile(MultipartFile file) {
     var header = 'content-type: ${file.contentType}\r\n'
-      'content-disposition: form-data; name="${encodeUri(file.field)}"';
+      'content-disposition: form-data; name="${Uri.encodeFull(file.field)}"';
 
     if (file.filename != null) {
-      header = '$header; filename="${encodeUri(file.filename)}"';
+      header = '$header; filename="${Uri.encodeFull(file.filename)}"';
     }
     return '$header\r\n\r\n';
   }
diff --git a/pkg/http/lib/src/request.dart b/pkg/http/lib/src/request.dart
index 2520b2a..982d2fb 100644
--- a/pkg/http/lib/src/request.dart
+++ b/pkg/http/lib/src/request.dart
@@ -7,7 +7,6 @@
 import 'dart:async';
 import 'dart:io';
 import 'dart:typed_data';
-import 'dart:uri';
 
 import 'base_request.dart';
 import 'byte_stream.dart';
diff --git a/pkg/http/lib/src/streamed_request.dart b/pkg/http/lib/src/streamed_request.dart
index eb20758..1b72eab 100644
--- a/pkg/http/lib/src/streamed_request.dart
+++ b/pkg/http/lib/src/streamed_request.dart
@@ -6,7 +6,6 @@
 
 import 'dart:async';
 import 'dart:io';
-import 'dart:uri';
 
 import 'byte_stream.dart';
 import 'base_request.dart';
diff --git a/pkg/http/lib/src/utils.dart b/pkg/http/lib/src/utils.dart
index ba5c968..4a3b84c 100644
--- a/pkg/http/lib/src/utils.dart
+++ b/pkg/http/lib/src/utils.dart
@@ -5,12 +5,12 @@
 library utils;
 
 import 'dart:async';
-import 'dart:crypto';
 import 'dart:io';
 import 'dart:typed_data';
-import 'dart:uri';
 import 'dart:utf';
 
+import "package:crypto/crypto.dart";
+
 import 'byte_stream.dart';
 
 /// Converts a URL query string (or `application/x-www-form-urlencoded` body)
@@ -37,7 +37,8 @@
 String mapToQuery(Map<String, String> map) {
   var pairs = <List<String>>[];
   map.forEach((key, value) =>
-      pairs.add([encodeUriComponent(key), encodeUriComponent(value)]));
+      pairs.add([Uri.encodeQueryComponent(key),
+                 Uri.encodeQueryComponent(value)]));
   return pairs.map((pair) => "${pair[0]}=${pair[1]}").join("&");
 }
 
@@ -50,10 +51,10 @@
 void mapAddAll(Map destination, Map source) =>
   source.forEach((key, value) => destination[key] = value);
 
-/// Decodes a URL-encoded string. Unlike [decodeUriComponent], this includes
+/// Decodes a URL-encoded string. Unlike [Uri.decodeComponent], this includes
 /// replacing `+` with ` `.
 String urlDecode(String encoded) =>
-  decodeUriComponent(encoded.replaceAll("+", " "));
+  Uri.decodeComponent(encoded.replaceAll("+", " "));
 
 /// Like [String.split], but only splits on the first occurrence of the pattern.
 /// This will always return an array of two elements or fewer.
diff --git a/pkg/http/test/client_test.dart b/pkg/http/test/client_test.dart
index e898426..aa7781f 100644
--- a/pkg/http/test/client_test.dart
+++ b/pkg/http/test/client_test.dart
@@ -5,7 +5,6 @@
 library client_test;
 
 import 'dart:io';
-import 'dart:uri';
 
 import 'package:http/http.dart' as http;
 import 'package:http/src/utils.dart';
diff --git a/pkg/http/test/mock_client_test.dart b/pkg/http/test/mock_client_test.dart
index a77d965..8e46ccc 100644
--- a/pkg/http/test/mock_client_test.dart
+++ b/pkg/http/test/mock_client_test.dart
@@ -7,7 +7,6 @@
 import 'dart:async';
 import 'dart:io';
 import 'dart:json' as json;
-import 'dart:uri';
 
 import 'package:http/http.dart' as http;
 import 'package:http/src/utils.dart';
diff --git a/pkg/http/test/safe_http_server.dart b/pkg/http/test/safe_http_server.dart
index 25d57ee..c9885f1 100644
--- a/pkg/http/test/safe_http_server.dart
+++ b/pkg/http/test/safe_http_server.dart
@@ -6,7 +6,6 @@
 
 import 'dart:async';
 import 'dart:io';
-import 'dart:uri';
 
 // TODO(nweiz): remove this when issue 9140 is fixed.
 /// A wrapper around [HttpServer] that swallows errors caused by requests
diff --git a/pkg/http/test/utils.dart b/pkg/http/test/utils.dart
index 25bb92e..786bb84 100644
--- a/pkg/http/test/utils.dart
+++ b/pkg/http/test/utils.dart
@@ -7,7 +7,6 @@
 import 'dart:async';
 import 'dart:io';
 import 'dart:json' as json;
-import 'dart:uri';
 
 import 'package:http/http.dart' as http;
 import 'package:http/src/byte_stream.dart';
diff --git a/pkg/intl/lib/src/lazy_locale_data.dart b/pkg/intl/lib/src/lazy_locale_data.dart
index a7ec331..90ff3a1 100644
--- a/pkg/intl/lib/src/lazy_locale_data.dart
+++ b/pkg/intl/lib/src/lazy_locale_data.dart
@@ -10,7 +10,6 @@
 
 library lazy_locale_data;
 import 'dart:async';
-import 'dart:uri';
 import 'intl_helpers.dart';
 import 'dart:json' as json;
 
diff --git a/pkg/mdv_observe/lib/src/observable_list.dart b/pkg/mdv_observe/lib/src/observable_list.dart
index c3ae880..66ca771 100644
--- a/pkg/mdv_observe/lib/src/observable_list.dart
+++ b/pkg/mdv_observe/lib/src/observable_list.dart
@@ -70,7 +70,8 @@
   void operator []=(int index, E value) {
     var oldValue = _list[index];
     if (hasObservers) {
-      _recordChange(new ListChangeRecord(index, addedCount: 1, removedCount: 1));
+      _recordChange(new ListChangeRecord(index, addedCount: 1,
+                                                removedCount: 1));
     }
     _list[index] = value;
   }
diff --git a/pkg/mdv_observe/lib/src/observable_map.dart b/pkg/mdv_observe/lib/src/observable_map.dart
index 009d692..ce1e48f 100644
--- a/pkg/mdv_observe/lib/src/observable_map.dart
+++ b/pkg/mdv_observe/lib/src/observable_map.dart
@@ -92,6 +92,8 @@
 
   bool get isEmpty => length == 0;
 
+  bool get isNotEmpty => !isEmpty;
+
   bool containsValue(V value) => _map.containsValue(value);
 
   bool containsKey(K key) => _map.containsKey(key);
diff --git a/pkg/oauth2/lib/oauth2.dart b/pkg/oauth2/lib/oauth2.dart
index 592589d..96bffcf 100644
--- a/pkg/oauth2/lib/oauth2.dart
+++ b/pkg/oauth2/lib/oauth2.dart
@@ -34,7 +34,6 @@
 /// that the library is being used by a server-side application.
 ///
 ///     import 'dart:io'
-///     import 'dart:uri'
 ///     import 'package:oauth2/oauth2.dart' as oauth2;
 ///
 ///     // These URLs are endpoints that are provided by the authorization
diff --git a/pkg/oauth2/lib/src/authorization_code_grant.dart b/pkg/oauth2/lib/src/authorization_code_grant.dart
index 900dfc5..266812e 100644
--- a/pkg/oauth2/lib/src/authorization_code_grant.dart
+++ b/pkg/oauth2/lib/src/authorization_code_grant.dart
@@ -5,7 +5,6 @@
 library authorization_code_grant;
 
 import 'dart:async';
-import 'dart:uri';
 
 import 'package:http/http.dart' as http;
 
diff --git a/pkg/oauth2/lib/src/authorization_exception.dart b/pkg/oauth2/lib/src/authorization_exception.dart
index 1062aa9..d48c3b1 100644
--- a/pkg/oauth2/lib/src/authorization_exception.dart
+++ b/pkg/oauth2/lib/src/authorization_exception.dart
@@ -5,7 +5,6 @@
 library authorization_exception;
 
 import 'dart:io';
-import 'dart:uri';
 
 /// An exception raised when OAuth2 authorization fails.
 class AuthorizationException implements Exception {
diff --git a/pkg/oauth2/lib/src/client.dart b/pkg/oauth2/lib/src/client.dart
index 62e2288..d473be19 100644
--- a/pkg/oauth2/lib/src/client.dart
+++ b/pkg/oauth2/lib/src/client.dart
@@ -5,7 +5,6 @@
 library oauth2_client;
 
 import 'dart:async';
-import 'dart:uri';
 
 import 'package:http/http.dart' as http;
 
diff --git a/pkg/oauth2/lib/src/credentials.dart b/pkg/oauth2/lib/src/credentials.dart
index 420dc49..b02f470 100644
--- a/pkg/oauth2/lib/src/credentials.dart
+++ b/pkg/oauth2/lib/src/credentials.dart
@@ -6,7 +6,6 @@
 
 import 'dart:async';
 import 'dart:json' as JSON;
-import 'dart:uri';
 
 import 'package:http/http.dart' as http;
 
diff --git a/pkg/oauth2/lib/src/handle_access_token_response.dart b/pkg/oauth2/lib/src/handle_access_token_response.dart
index c82c818..5e5f6e2 100644
--- a/pkg/oauth2/lib/src/handle_access_token_response.dart
+++ b/pkg/oauth2/lib/src/handle_access_token_response.dart
@@ -6,7 +6,6 @@
 
 import 'dart:io';
 import 'dart:json' as JSON;
-import 'dart:uri';
 
 import 'package:http/http.dart' as http;
 
diff --git a/pkg/oauth2/lib/src/utils.dart b/pkg/oauth2/lib/src/utils.dart
index f69ac8b..d0e5f11 100644
--- a/pkg/oauth2/lib/src/utils.dart
+++ b/pkg/oauth2/lib/src/utils.dart
@@ -5,9 +5,9 @@
 library utils;
 
 import 'dart:async';
-import 'dart:uri';
 import 'dart:isolate';
-import 'dart:crypto';
+
+import "package:crypto/crypto.dart";
 
 /// Adds additional query parameters to [url], overwriting the original
 /// parameters if a name conflict occurs.
@@ -35,8 +35,10 @@
 String mapToQuery(Map<String, String> map) {
   var pairs = <List<String>>[];
   map.forEach((key, value) {
-    key = encodeUriComponent(key);
-    value = (value == null || value.isEmpty) ? null : encodeUriComponent(value);
+    key = Uri.encodeQueryComponent(key);
+    value = (value == null || value.isEmpty)
+            ? null
+            : Uri.encodeQueryComponent(value);
     pairs.add([key, value]);
   });
   return pairs.map((pair) {
@@ -50,10 +52,10 @@
 void mapAddAll(Map destination, Map source) =>
   source.forEach((key, value) => destination[key] = value);
 
-/// Decode a URL-encoded string. Unlike [decodeUriComponent], this includes
+/// Decode a URL-encoded string. Unlike [Uri.decodeComponent], this includes
 /// replacing `+` with ` `.
 String urlDecode(String encoded) =>
-  decodeUriComponent(encoded.replaceAll("+", " "));
+  Uri.decodeComponent(encoded.replaceAll("+", " "));
 
 /// Like [String.split], but only splits on the first occurrence of the pattern.
 /// This will always return a list of two elements or fewer.
diff --git a/pkg/oauth2/test/authorization_code_grant_test.dart b/pkg/oauth2/test/authorization_code_grant_test.dart
index 22be3cfa7..0d4a5fc 100644
--- a/pkg/oauth2/test/authorization_code_grant_test.dart
+++ b/pkg/oauth2/test/authorization_code_grant_test.dart
@@ -7,7 +7,6 @@
 import 'dart:async';
 import 'dart:io';
 import 'dart:json' as JSON;
-import 'dart:uri';
 
 import 'package:unittest/unittest.dart';
 import 'package:http/http.dart' as http;
diff --git a/pkg/oauth2/test/client_test.dart b/pkg/oauth2/test/client_test.dart
index 7a05e99..d55eef7 100644
--- a/pkg/oauth2/test/client_test.dart
+++ b/pkg/oauth2/test/client_test.dart
@@ -7,7 +7,6 @@
 import 'dart:async';
 import 'dart:io';
 import 'dart:json' as JSON;
-import 'dart:uri';
 
 import 'package:http/http.dart' as http;
 import 'package:oauth2/oauth2.dart' as oauth2;
diff --git a/pkg/oauth2/test/credentials_test.dart b/pkg/oauth2/test/credentials_test.dart
index 652d394..768b85a 100644
--- a/pkg/oauth2/test/credentials_test.dart
+++ b/pkg/oauth2/test/credentials_test.dart
@@ -7,7 +7,6 @@
 import 'dart:async';
 import 'dart:io';
 import 'dart:json' as JSON;
-import 'dart:uri';
 
 import 'package:http/http.dart' as http;
 import 'package:oauth2/oauth2.dart' as oauth2;
diff --git a/pkg/oauth2/test/handle_access_token_response_test.dart b/pkg/oauth2/test/handle_access_token_response_test.dart
index 772f263..45860ab 100644
--- a/pkg/oauth2/test/handle_access_token_response_test.dart
+++ b/pkg/oauth2/test/handle_access_token_response_test.dart
@@ -6,7 +6,6 @@
 
 import 'dart:io';
 import 'dart:json' as JSON;
-import 'dart:uri';
 
 import 'package:http/http.dart' as http;
 import 'package:oauth2/oauth2.dart' as oauth2;
diff --git a/pkg/pkg.status b/pkg/pkg.status
index c752bfb..161a54b 100644
--- a/pkg/pkg.status
+++ b/pkg/pkg.status
@@ -119,6 +119,9 @@
 [ $compiler == dart2js ]
 unittest/test/instance_test: Skip
 
+[ $compiler == dart2js && $csp ]
+unittest/test/unittest_test: Pass, Crash # Issue 10935
+
 [ $compiler == dart2js && $minified ]
 # The unittest package relies on getting the original (non-minified) method
 # names in Invocation.  You can't get that when minifying.
@@ -140,9 +143,6 @@
 [ $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/scheduled_process.dart b/pkg/scheduled_test/lib/scheduled_process.dart
index 75891a9..3ff903c 100644
--- a/pkg/scheduled_test/lib/scheduled_process.dart
+++ b/pkg/scheduled_test/lib/scheduled_process.dart
@@ -39,7 +39,7 @@
   Stream<String> _stdoutLog;
 
   /// A line-by-line view of the standard output stream of the process.
-  Stream<String> _stdout;
+  StreamIterator<String> _stdout;
 
   /// A canceller that controls both [_stdout] and [_stdoutLog].
   StreamCanceller _stdoutCanceller;
@@ -49,7 +49,7 @@
   Stream<String> _stderrLog;
 
   /// A line-by-line view of the standard error stream of the process.
-  Stream<String> _stderr;
+  StreamIterator<String> _stderr;
 
   /// A canceller that controls both [_stderr] and [_stderrLog].
   StreamCanceller _stderrCanceller;
@@ -103,8 +103,8 @@
     _stderrCanceller = stderrWithCanceller.last;
     _stderrLog = stderrWithCanceller.first;
 
-    _stdout = stdoutStream();
-    _stderr = stderrStream();
+    _stdout = new StreamIterator<String>(stdoutStream());
+    _stderr = new StreamIterator<String>(stderrStream());
   }
 
   /// Updates [_description] to reflect [executable] and [arguments], which are
@@ -151,8 +151,7 @@
                              arguments,
                              workingDirectory: workingDirectory,
                              environment: environment).then((process) {
-          // TODO(nweiz): enable this when issue 9020 is fixed.
-          // process.stdin.encoding = Encoding.UTF_8;
+          process.stdin.encoding = Encoding.UTF_8;
           return process;
         });
       });
@@ -249,11 +248,11 @@
   }
 
   /// Reads the next line of stdout from the process.
-  Future<String> nextLine() => schedule(() => streamFirst(_stdout),
+  Future<String> nextLine() => schedule(() => streamIteratorFirst(_stdout),
       "reading the next stdout line from process '$description'");
 
   /// Reads the next line of stderr from the process.
-  Future<String> nextErrLine() => schedule(() => streamFirst(_stderr),
+  Future<String> nextErrLine() => schedule(() => streamIteratorFirst(_stderr),
       "reading the next stderr line from process '$description'");
 
   /// Reads the remaining stdout from the process. This should only be called
@@ -263,8 +262,7 @@
       throw new StateError("remainingStdout() should only be called after "
           "kill() or shouldExit().");
     }
-
-    return schedule(() => _stdout.toList().then((lines) => lines.join("\n")),
+    return schedule(() => concatRest(_stdout),
         "reading the remaining stdout from process '$description'");
   }
 
@@ -276,7 +274,7 @@
           "kill() or shouldExit().");
     }
 
-    return schedule(() => _stderr.toList().then((lines) => lines.join("\n")),
+    return schedule(() => concatRest(_stderr),
         "reading the remaining stderr from process '$description'");
   }
 
diff --git a/pkg/scheduled_test/lib/scheduled_server.dart b/pkg/scheduled_test/lib/scheduled_server.dart
index 1e4e633..293545b 100644
--- a/pkg/scheduled_test/lib/scheduled_server.dart
+++ b/pkg/scheduled_test/lib/scheduled_server.dart
@@ -7,7 +7,6 @@
 import 'dart:async';
 import 'dart:collection';
 import 'dart:io';
-import 'dart:uri';
 
 import 'scheduled_test.dart';
 import 'src/utils.dart';
diff --git a/pkg/scheduled_test/lib/src/mock_clock.dart b/pkg/scheduled_test/lib/src/mock_clock.dart
index 6abe81f..0d77e5a 100644
--- a/pkg/scheduled_test/lib/src/mock_clock.dart
+++ b/pkg/scheduled_test/lib/src/mock_clock.dart
@@ -44,27 +44,25 @@
   int get time => _time;
   int _time = 0;
 
-  /// The stream of millisecond ticks of the clock.
-  Stream<int> get onTick {
-    if (_onTickControllerStream == null) {
-      _onTickControllerStream = _onTickController.stream.asBroadcastStream();
-    }
-    return _onTickControllerStream;
-  }
-
-  final _onTickController = new StreamController<int>();
-  Stream<int> _onTickControllerStream;
+  /// Controller providing streams for listening.
+  StreamController<int> _multiplexController =
+      new StreamController<int>.broadcast();
 
   Clock._();
 
+  /// The stream of millisecond ticks of the clock.
+  Stream<int> get onTick => _multiplexController.stream;
+
   /// Advances the clock forward by [milliseconds]. This works like synchronous
   /// code that takes [milliseconds] to execute; any [Timer]s that are scheduled
   /// to fire during the interval will do so asynchronously once control returns
   /// to the event loop.
-  void tick([int milliseconds=1]) {
+  void tick([int milliseconds = 1]) {
     for (var i = 0; i < milliseconds; i++) {
       var tickTime = ++_time;
-      new Future.value().then((_) => _onTickController.add(tickTime));
+      runAsync(() {
+        _multiplexController.add(tickTime);
+      });
     }
   }
 
@@ -74,7 +72,7 @@
   /// code runs before the next tick.
   void run() {
     pumpEventQueue().then((_) {
-      if (!_onTickController.hasListener) return;
+      if (!_multiplexController.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 25d57ee..c9885f1 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
@@ -6,7 +6,6 @@
 
 import 'dart:async';
 import 'dart:io';
-import 'dart:uri';
 
 // TODO(nweiz): remove this when issue 9140 is fixed.
 /// A wrapper around [HttpServer] that swallows errors caused by requests
diff --git a/pkg/scheduled_test/lib/src/utils.dart b/pkg/scheduled_test/lib/src/utils.dart
index d686ef9..62461a6 100644
--- a/pkg/scheduled_test/lib/src/utils.dart
+++ b/pkg/scheduled_test/lib/src/utils.dart
@@ -94,27 +94,38 @@
   return controller.stream;
 }
 
-// TODO(nweiz): remove this when issue 7964 is fixed.
-/// Returns a [Future] that will complete to the first element of [stream].
-/// Unlike [Stream.first], this is safe to use with single-subscription streams.
-Future streamFirst(Stream stream) {
-  var stackTrace;
-  try {
-    throw '';
-  } catch (_, thrownStackTrace) {
-    stackTrace = thrownStackTrace;
-  }
+/// Returns the first element of a [StreamIterator].
+///
+/// If the [StreamIterator] has no elements, the result is a state error.
+Future<String> streamIteratorFirst(StreamIterator<String> streamIterator) {
+  StackTrace stackTrace = new Trace.current();
+  return streamIterator.moveNext().then((hasNext) {
+    if (hasNext) {
+      return streamIterator.current;
+    } else {
+      return new Future.error(new StateError("No elements"), stackTrace);
+    }
+  });
+}
 
-  var completer = new Completer();
-  var subscription;
-  subscription = stream.listen((value) {
-    subscription.cancel();
-    completer.complete(value);
-  }, onError: (e) {
-    completer.completeError(e);
-  }, onDone: () {
-    completer.completeError(new StateError("No elements"), stackTrace);
-  }, cancelOnError: true);
+/// Collects all remaining lines from a [StreamIterator] of lines.
+///
+/// Returns the concatenation of the collected lines joined by newlines.
+Future<String> concatRest(StreamIterator<String> streamIterator) {
+  var completer = new Completer<String>();
+  var buffer = new StringBuffer();
+  void collectAll() {
+    streamIterator.moveNext().then((hasNext) {
+      if (hasNext) {
+        if (!buffer.isEmpty) buffer.write('\n');
+        buffer.write(streamIterator.current);
+        collectAll();
+      } else {
+        completer.complete(buffer.toString());
+      }
+    }, onError: completer.completeError);
+  }
+  collectAll();
   return completer.future;
 }
 
diff --git a/pkg/serialization/lib/serialization.dart b/pkg/serialization/lib/serialization.dart
index a95ee3f..522a7d1 100644
--- a/pkg/serialization/lib/serialization.dart
+++ b/pkg/serialization/lib/serialization.dart
@@ -210,7 +210,6 @@
 import 'dart:async';
 import 'dart:json' as json;
 import 'dart:collection';
-import 'dart:uri';
 
 part 'src/reader_writer.dart';
 part 'src/serialization_rule.dart';
diff --git a/pkg/serialization/lib/src/serialization_helpers.dart b/pkg/serialization/lib/src/serialization_helpers.dart
index 9568c24..1f86a97 100644
--- a/pkg/serialization/lib/src/serialization_helpers.dart
+++ b/pkg/serialization/lib/src/serialization_helpers.dart
@@ -248,6 +248,7 @@
     values.clear();
   }
   bool get isEmpty => keys.isEmpty;
+  bool get isNotEmpty => !isEmpty;
 
   // Note that this is doing an equality comparison.
   bool containsValue(x) => values.contains(x);
diff --git a/pkg/serialization/lib/src/serialization_rule.dart b/pkg/serialization/lib/src/serialization_rule.dart
index 4ffe966..aad0aaf 100644
--- a/pkg/serialization/lib/src/serialization_rule.dart
+++ b/pkg/serialization/lib/src/serialization_rule.dart
@@ -408,7 +408,7 @@
     // So follow one or the other path depending if it has a colon, which we
     // assume is in any URI and can't be in a Symbol.
     if (name.contains(":")) {
-      var uri = new Uri(name);
+      var uri = Uri.parse(name);
       var libMirror = currentMirrorSystem().libraries[uri];
       return libMirror.classes[new Symbol(type)];
     } else {
@@ -529,6 +529,7 @@
 
   int get length => _raw.length;
   bool get isEmpty => _raw.isEmpty;
+  bool get isNotEmpty => _raw.isNotEmpty;
   Iterable get keys => _raw.keys;
   bool containsKey(x) => _raw.containsKey(x);
 
diff --git a/pkg/stack_trace/lib/src/frame.dart b/pkg/stack_trace/lib/src/frame.dart
index cb7d656..335bfba 100644
--- a/pkg/stack_trace/lib/src/frame.dart
+++ b/pkg/stack_trace/lib/src/frame.dart
@@ -4,7 +4,6 @@
 
 library frame;
 
-import 'dart:uri';
 
 import 'package:pathos/path.dart' as path;
 
diff --git a/pkg/stack_trace/lib/src/trace.dart b/pkg/stack_trace/lib/src/trace.dart
index ffea498..4ed1563 100644
--- a/pkg/stack_trace/lib/src/trace.dart
+++ b/pkg/stack_trace/lib/src/trace.dart
@@ -5,7 +5,6 @@
 library trace;
 
 import 'dart:collection';
-import 'dart:uri';
 import 'dart:math' as math;
 
 import 'frame.dart';
diff --git a/pkg/stack_trace/lib/src/utils.dart b/pkg/stack_trace/lib/src/utils.dart
index 50ccab3..30a43bcc 100644
--- a/pkg/stack_trace/lib/src/utils.dart
+++ b/pkg/stack_trace/lib/src/utils.dart
@@ -5,7 +5,6 @@
 library utils;
 
 import 'dart:io';
-import 'dart:uri';
 
 import 'package:pathos/path.dart' as path;
 
diff --git a/pkg/stack_trace/test/frame_test.dart b/pkg/stack_trace/test/frame_test.dart
index 826bad7..512f6d0 100644
--- a/pkg/stack_trace/test/frame_test.dart
+++ b/pkg/stack_trace/test/frame_test.dart
@@ -5,7 +5,6 @@
 library frame_test;
 
 import 'dart:io';
-import 'dart:uri';
 
 import 'package:pathos/path.dart' as path;
 import 'package:stack_trace/src/utils.dart';
@@ -42,7 +41,7 @@
     // TODO(nweiz): use URL-style paths when such a thing exists.
     var builder = new path.Builder(style: path.Style.posix);
     expect(builder.basename(frame.uri.path), equals('frame_test.dart'));
-    expect(frame.line, equals(17));
+    expect(frame.line, equals(16));
     expect(frame.column, equals(5));
     expect(frame.member, equals('getStackFrame'));
   });
diff --git a/pkg/stack_trace/test/trace_test.dart b/pkg/stack_trace/test/trace_test.dart
index d3fa56e..afd5700 100644
--- a/pkg/stack_trace/test/trace_test.dart
+++ b/pkg/stack_trace/test/trace_test.dart
@@ -5,7 +5,6 @@
 library trace_test;
 
 import 'dart:io';
-import 'dart:uri';
 
 import 'package:pathos/path.dart' as path;
 import 'package:stack_trace/src/utils.dart';
diff --git a/pkg/unittest/lib/coverage_controller.js b/pkg/unittest/lib/coverage_controller.js
index 78ddb9d..1cf21ae 100644
--- a/pkg/unittest/lib/coverage_controller.js
+++ b/pkg/unittest/lib/coverage_controller.js
@@ -4,7 +4,7 @@
 
 /**
  * Coverage controller logic - used by coverage test harness to embed tests in
- * DumpRenderTree and extract coverage information.
+ * content shell and extract coverage information.
  */
 
 var LONG_LINE = 60000;
@@ -13,7 +13,7 @@
   if (e.data == 'unittest-suite-done') {
     var s = JSON.stringify(top._$jscoverage);
     var res = '';
-    // DumpRenderTree has a bug on lines longer than 2^16, so we split them
+    // conent shell has a bug on lines longer than 2^16, so we split them
     while (s.length > LONG_LINE) {
       res += s.substr(0, LONG_LINE) + '<br>\n';
       s = s.substr(LONG_LINE);
diff --git a/pkg/unittest/lib/test_controller.js b/pkg/unittest/lib/test_controller.js
index dd9bba3..d8ef908 100644
--- a/pkg/unittest/lib/test_controller.js
+++ b/pkg/unittest/lib/test_controller.js
@@ -4,7 +4,7 @@
 
 /**
  * Test controller logic - used by unit test harness to embed tests in
- * DumpRenderTree.
+ * conent shell.
  */
 
 // Clear the console before every test run - this is Firebug specific code.
@@ -27,7 +27,7 @@
   navigator.webkitStartDart();
 }
 
-// testRunner is provided by DRT or WebKit's layout tests.
+// testRunner is provided by content shell.
 // It is not available in selenium tests.
 var testRunner = window.testRunner || window.layoutTestController;
 
diff --git a/pkg/webdriver/lib/webdriver.dart b/pkg/webdriver/lib/webdriver.dart
index e257bd6..0119c68 100644
--- a/pkg/webdriver/lib/webdriver.dart
+++ b/pkg/webdriver/lib/webdriver.dart
@@ -7,7 +7,6 @@
 import 'dart:async';
 import 'dart:io';
 import 'dart:json' as json;
-import 'dart:uri';
 
 part 'src/base64decoder.dart';
 
diff --git a/pkg/yaml/lib/src/yaml_map.dart b/pkg/yaml/lib/src/yaml_map.dart
index 29fec75..303d8ed 100644
--- a/pkg/yaml/lib/src/yaml_map.dart
+++ b/pkg/yaml/lib/src/yaml_map.dart
@@ -36,6 +36,7 @@
   Iterable get values => _map.values;
   int get length => _map.length;
   bool get isEmpty => _map.isEmpty;
+  bool get isNotEmpty => map.isNotEmpty;
   String toString() => _map.toString();
 
   int get hashCode => hashCodeFor(_map);
diff --git a/runtime/bin/bin.gypi b/runtime/bin/bin.gypi
index 8cc5866..033539e 100644
--- a/runtime/bin/bin.gypi
+++ b/runtime/bin/bin.gypi
@@ -180,6 +180,7 @@
     {
       'target_name': 'libdart_io',
       'type': 'static_library',
+      'toolsets':['target', 'host'],
       'include_dirs': [
         '..',
       ],
@@ -187,14 +188,19 @@
         'io_natives.h',
         'io_natives.cc',
       ],
-      'includes': [
-        'io_impl_sources.gypi',
-      ],
       'conditions': [
         [ 'dart_io_support==1', {
           'dependencies': [
             'bin/net/ssl.gyp:libssl_dart',
           ],
+          'includes': [
+            'io_impl_sources.gypi',
+          ],
+        },
+        {
+          'includes': [
+            'io_impl_sources_no_nss.gypi',
+          ],
         }],
         ['OS=="win"', {
           # TODO(antonm): fix the implementation.
@@ -336,6 +342,7 @@
     {
       'target_name': 'generate_resources_cc_file',
       'type': 'none',
+      'toolsets':['target', 'host'],
       'includes': [
         'vmstats_sources.gypi',
       ],
@@ -364,12 +371,13 @@
       # dart binary with a snapshot of corelibs built in.
       'target_name': 'dart',
       'type': 'executable',
+      'toolsets':['target'],
       'dependencies': [
         'libdart',
         'libdart_builtin',
         'libdart_io',
         'generate_snapshot_file#host',
-        'generate_resources_cc_file',
+        'generate_resources_cc_file#host',
       ],
       'include_dirs': [
         '..',
@@ -411,17 +419,34 @@
             '-rdynamic',
           ],
         }],
+        ['OS=="android"', {
+          'link_settings': {
+            'ldflags': [
+              '-z',
+              'muldefs',
+            ],
+            'ldflags!': [
+              '-Wl,--exclude-libs=ALL,-shared',
+            ],
+            'libraries': [
+              '-llog',
+              '-lc',
+              '-lz',
+            ],
+          },
+        }],
       ],
     },
     {
       # dart binary without any snapshot built in.
       'target_name': 'dart_no_snapshot',
       'type': 'executable',
+      'toolsets':['target'],
       'dependencies': [
         'libdart_withcore',
         'libdart_builtin',
         'libdart_io',
-        'generate_resources_cc_file',
+        'generate_resources_cc_file#host',
       ],
       'include_dirs': [
         '..',
@@ -467,6 +492,23 @@
             '-rdynamic',
           ],
         }],
+
+        ['OS=="android"', {
+          'link_settings': {
+            'ldflags': [
+              '-z',
+              'muldefs',
+            ],
+            'ldflags!': [
+              '-Wl,--exclude-libs=ALL,-shared',
+            ],
+            'libraries': [
+              '-llog',
+              '-lc',
+              '-lz',
+            ],
+          },
+        }],
       ],
     },
     {
@@ -479,6 +521,78 @@
     {
       'target_name': 'run_vm_tests',
       'type': 'executable',
+      'toolsets':['target'],
+      'dependencies': [
+        'libdart_withcore',
+        'libdart_builtin',
+        'libdart_io',
+        'generate_snapshot_file#host',
+        'generate_snapshot_test_dat_file',
+      ],
+      'include_dirs': [
+        '..',
+        '<(gen_source_dir)',
+      ],
+      'sources': [
+        'run_vm_tests.cc',
+        'builtin_natives.cc',
+        'builtin_nolib.cc',
+        'builtin.h',
+        'io_natives.h',
+        # Include generated source files.
+        '<(snapshot_cc_file)',
+        '<(builtin_cc_file)',
+        '<(io_cc_file)',
+        '<(io_patch_cc_file)',
+      ],
+      'includes': [
+        'builtin_impl_sources.gypi',
+        '../platform/platform_sources.gypi',
+        '../vm/vm_sources.gypi',
+      ],
+      'defines': [
+        'TESTING',
+      ],
+      # Only include _test.[cc|h] files.
+      'sources/': [
+        ['exclude', '\\.(cc|h)$'],
+        ['include', 'run_vm_tests.cc'],
+        ['include', 'builtin_nolib.cc'],
+        ['include', 'builtin_natives.cc'],
+        ['include', '_gen\\.cc$'],
+        ['include', '_test\\.(cc|h)$'],
+      ],
+      'conditions': [
+        ['OS=="win"', {
+          'link_settings': {
+            'libraries': [ '-lws2_32.lib', '-lRpcrt4.lib', '-lwinmm.lib' ],
+          },
+        }],
+        ['OS=="android"', {
+
+          'link_settings': {
+            'ldflags': [
+              '-z',
+              'muldefs',
+            ],
+            'ldflags!': [
+              '-Wl,--exclude-libs=ALL,-shared',
+            ],
+            'libraries': [
+              '-Wl,--start-group',
+              '-Wl,--end-group',
+              '-llog',
+              '-lc',
+              '-lz',
+            ],
+          },
+        }],
+      ],
+    },
+    {
+      'target_name': 'run_vm_tests.host',
+      'type': 'executable',
+      'toolsets':['host'],
       'dependencies': [
         'libdart_withcore',
         'libdart_builtin',
@@ -527,44 +641,50 @@
         }],
       ],
     },
-    {
-      'target_name': 'test_extension',
-      'type': 'shared_library',
-      'dependencies': [
-        'dart',
-      ],
-      'include_dirs': [
-        '..',
-      ],
-      'sources': [
-        'test_extension.cc',
-        'test_extension_dllmain_win.cc',
-      ],
-      'defines': [
-        # The only effect of DART_SHARED_LIB is to export the Dart API entries.
-        'DART_SHARED_LIB',
-      ],
-      'conditions': [
-        ['OS=="win"', {
-          'msvs_settings': {
-            'VCLinkerTool': {
-              'AdditionalDependencies': [ 'dart.lib' ],
-              'AdditionalLibraryDirectories': [ '<(PRODUCT_DIR)' ],
-            },
-          },
-        }],
-        ['OS=="mac"', {
-          'xcode_settings': {
-            'OTHER_LDFLAGS': [ '-undefined', 'dynamic_lookup' ],
-          },
-        }],
-        ['OS=="linux"', {
-          'cflags': [
-            '-fPIC',
+  ],
+  'conditions': [
+    ['OS!="android"', {
+      'targets': [
+        {
+          'target_name': 'test_extension',
+          'type': 'shared_library',
+          'dependencies': [
+            'dart',
           ],
-        }],
+          'include_dirs': [
+            '..',
+          ],
+          'sources': [
+            'test_extension.cc',
+            'test_extension_dllmain_win.cc',
+          ],
+          'defines': [
+            # The only effect of DART_SHARED_LIB is to export the Dart API.
+            'DART_SHARED_LIB',
+          ],
+          'conditions': [
+            ['OS=="win"', {
+              'msvs_settings': {
+                'VCLinkerTool': {
+                  'AdditionalDependencies': [ 'dart.lib' ],
+                  'AdditionalLibraryDirectories': [ '<(PRODUCT_DIR)' ],
+                },
+              },
+            }],
+            ['OS=="mac"', {
+              'xcode_settings': {
+                'OTHER_LDFLAGS': [ '-undefined', 'dynamic_lookup' ],
+              },
+            }],
+            ['OS=="linux"', {
+              'cflags': [
+                '-fPIC',
+              ],
+            }],
+          ],
+        },
       ],
-    },
+    }],
   ],
 }
 
diff --git a/runtime/bin/builtin.dart b/runtime/bin/builtin.dart
index 5eb32ad..808124a 100644
--- a/runtime/bin/builtin.dart
+++ b/runtime/bin/builtin.dart
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 
 library builtin;
-import 'dart:uri';
 
 // Corelib 'print' implementation.
 void _print(arg) {
@@ -58,9 +57,8 @@
     _logResolution("## scriptName: $scriptName");
   }
   var base =
-      new Uri.fromComponents(
-          scheme: "file",
-          path: cwd.endsWith("/") ? cwd : "$cwd/");
+      new Uri(scheme: "file",
+              path: cwd.endsWith("/") ? cwd : "$cwd/");
   _entrypoint = base.resolve(scriptName);
   _logResolution("# Resolved script to: $_entrypoint");
 
@@ -84,7 +82,7 @@
       // package URI path part.
       path = _filePathFromPackageUri(resolved);
     }
-    resolved = new Uri.fromComponents(scheme: "dart-ext", path: path);
+    resolved = new Uri(scheme: "dart-ext", path: path);
   } else {
     resolved = baseUri.resolve(userString);
   }
@@ -127,8 +125,8 @@
 }
 
 String _filePathFromFileUri(Uri uri) {
-  if (uri.domain != '') {
-    throw "URIs using the 'file:' scheme may not contain a domain.";
+  if (!uri.host.isEmpty) {
+    throw "URIs using the 'file:' scheme may not contain a host.";
   }
 
   _logResolution("# Path: ${uri.path}");
@@ -136,8 +134,8 @@
 }
 
 String _filePathFromOtherUri(Uri uri) {
-  if (uri.domain != '') {
-    throw "URIs whose paths are used as file paths may not contain a domain.";
+  if (!uri.host.isEmpty) {
+    throw "URIs whose paths are used as file paths may not contain a host.";
   }
 
   _logResolution("# Path: ${uri.path}");
@@ -145,8 +143,8 @@
 }
 
 String _filePathFromPackageUri(Uri uri) {
-  if (uri.domain != '') {
-    var path = (uri.path != '') ? '${uri.domain}${uri.path}' : uri.domain;
+  if (!uri.host.isEmpty) {
+    var path = (uri.path != '') ? '${uri.host}${uri.path}' : uri.host;
     var right = 'package:$path';
     var wrong = 'package://$path';
 
diff --git a/runtime/bin/dartutils.cc b/runtime/bin/dartutils.cc
index e113927..89a84c4 100644
--- a/runtime/bin/dartutils.cc
+++ b/runtime/bin/dartutils.cc
@@ -26,7 +26,6 @@
 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::kIdFieldName = "_id";
 
diff --git a/runtime/bin/dbg_message.cc b/runtime/bin/dbg_message.cc
index 5713657..caec295 100644
--- a/runtime/bin/dbg_message.cc
+++ b/runtime/bin/dbg_message.cc
@@ -1053,7 +1053,7 @@
 
 
 DbgMsgQueue* DbgMsgQueueList::list_ = NULL;
-dart::Mutex DbgMsgQueueList::msg_queue_list_lock_;
+dart::Mutex* DbgMsgQueueList::msg_queue_list_lock_ = new dart::Mutex();
 
 
 void DbgMsgQueueList::Initialize() {
@@ -1085,7 +1085,7 @@
                                         const char* start,
                                         const char* end,
                                         int debug_fd) {
-  MutexLocker ml(&msg_queue_list_lock_);
+  MutexLocker ml(msg_queue_list_lock_);
   DbgMsgQueue* queue = DbgMsgQueueList::GetIsolateMsgQueueLocked(isolate_id);
   if (queue != NULL) {
     queue->AddMessage(cmd_idx, start, end, debug_fd);
@@ -1096,7 +1096,7 @@
 
 
 bool DbgMsgQueueList::InterruptIsolate(Dart_IsolateId isolate_id) {
-  MutexLocker ml(&msg_queue_list_lock_);
+  MutexLocker ml(msg_queue_list_lock_);
   DbgMsgQueue* queue = DbgMsgQueueList::GetIsolateMsgQueueLocked(isolate_id);
   if (queue != NULL) {
     queue->InterruptIsolate();
@@ -1107,7 +1107,7 @@
 
 
 DbgMsgQueue* DbgMsgQueueList::AddIsolateMsgQueue(Dart_IsolateId isolate_id) {
-  MutexLocker ml(&msg_queue_list_lock_);
+  MutexLocker ml(msg_queue_list_lock_);
 
   DbgMsgQueue* queue = new DbgMsgQueue(isolate_id, list_);
   ASSERT(queue != NULL);
@@ -1117,7 +1117,7 @@
 
 
 DbgMsgQueue* DbgMsgQueueList::GetIsolateMsgQueue(Dart_IsolateId isolate_id) {
-  MutexLocker ml(&msg_queue_list_lock_);
+  MutexLocker ml(msg_queue_list_lock_);
   ASSERT(Dart_GetIsolate(isolate_id) == Dart_CurrentIsolate());
   return GetIsolateMsgQueueLocked(isolate_id);
 }
@@ -1138,7 +1138,7 @@
 
 
 void DbgMsgQueueList::RemoveIsolateMsgQueue(Dart_IsolateId isolate_id) {
-  MutexLocker ml(&msg_queue_list_lock_);
+  MutexLocker ml(msg_queue_list_lock_);
   if (list_ == NULL) {
     return;  // No items in the list.
   }
@@ -1165,7 +1165,7 @@
 
 
 void DbgMsgQueueList::ListIsolateIds(dart::TextBuffer* msg) {
-  MutexLocker ml(&msg_queue_list_lock_);
+  MutexLocker ml(msg_queue_list_lock_);
   if (list_ == NULL) {
     return;  // No items in the list.
   }
diff --git a/runtime/bin/dbg_message.h b/runtime/bin/dbg_message.h
index 85be1a5..ca05255 100644
--- a/runtime/bin/dbg_message.h
+++ b/runtime/bin/dbg_message.h
@@ -255,7 +255,7 @@
   static DbgMsgQueue* GetIsolateMsgQueueLocked(Dart_IsolateId isolate_id);
 
   static DbgMsgQueue* list_;
-  static dart::Mutex msg_queue_list_lock_;
+  static dart::Mutex* msg_queue_list_lock_;
 
   DISALLOW_ALLOCATION();
   DISALLOW_IMPLICIT_CONSTRUCTORS(DbgMsgQueueList);
diff --git a/runtime/bin/directory_android.cc b/runtime/bin/directory_android.cc
index f3ea9e6..dc5bad2 100644
--- a/runtime/bin/directory_android.cc
+++ b/runtime/bin/directory_android.cc
@@ -478,7 +478,7 @@
     if (stat(ANDROID_TEMP_DIR, &st) != 0) {
       mkdir(ANDROID_TEMP_DIR, 0777);
     }
-    path.Add(ANDROID_TEMP_DIR "/tmp/temp_dir1_");
+    path.Add(ANDROID_TEMP_DIR "/temp_dir1_");
   } else if ((path.data)[path.length - 1] == '/') {
     path.Add("temp_dir_");
   }
diff --git a/runtime/bin/file_android.cc b/runtime/bin/file_android.cc
index e8a1fa9..b166aad 100644
--- a/runtime/bin/file_android.cc
+++ b/runtime/bin/file_android.cc
@@ -265,10 +265,17 @@
 char* File::GetCanonicalPath(const char* pathname) {
   char* abs_path = NULL;
   if (pathname != NULL) {
+    // A null second argument to realpath crashes Android.  Fixed in Mar 2013,
+    // but not in earlier releases of Android.
+    char* resolved = reinterpret_cast<char*>(malloc(PATH_MAX));
+    if (resolved == NULL) return NULL;
     do {
-      abs_path = realpath(pathname, NULL);
+      abs_path = realpath(pathname, resolved);
     } while (abs_path == NULL && errno == EINTR);
     ASSERT(abs_path == NULL || IsAbsolutePath(abs_path));
+    if (abs_path != resolved) {
+      free(resolved);
+    }
   }
   return abs_path;
 }
diff --git a/runtime/bin/filter_dummy.cc b/runtime/bin/filter_dummy.cc
new file mode 100644
index 0000000..617e1c9
--- /dev/null
+++ b/runtime/bin/filter_dummy.cc
@@ -0,0 +1,44 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#include "bin/builtin.h"
+#include "bin/dartutils.h"
+
+#include "include/dart_api.h"
+
+
+namespace dart {
+namespace bin {
+
+void FUNCTION_NAME(Filter_CreateZLibInflate)(Dart_NativeArguments args) {
+  Dart_EnterScope();
+  Dart_ThrowException(DartUtils::NewInternalError(
+        "ZLibInflater and Deflater not supported on this platform"));
+  Dart_ExitScope();
+}
+
+void FUNCTION_NAME(Filter_CreateZLibDeflate)(Dart_NativeArguments args) {
+  Dart_EnterScope();
+  Dart_ExitScope();
+}
+
+void FUNCTION_NAME(Filter_Process)(Dart_NativeArguments args) {
+  Dart_EnterScope();
+  Dart_ExitScope();
+}
+
+
+void FUNCTION_NAME(Filter_Processed)(Dart_NativeArguments args) {
+  Dart_EnterScope();
+  Dart_ExitScope();
+}
+
+
+void FUNCTION_NAME(Filter_End)(Dart_NativeArguments args) {
+  Dart_EnterScope();
+  Dart_ExitScope();
+}
+
+}  // namespace bin
+}  // namespace dart
diff --git a/runtime/bin/io_impl_sources_no_nss.gypi b/runtime/bin/io_impl_sources_no_nss.gypi
new file mode 100644
index 0000000..3222272
--- /dev/null
+++ b/runtime/bin/io_impl_sources_no_nss.gypi
@@ -0,0 +1,45 @@
+# 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.
+
+# This file contains some C++ sources for the dart:io library.  The other
+# implementation files are in builtin_impl_sources.gypi.
+{
+  'sources': [
+    'common.cc',
+    'crypto.cc',
+    'crypto_android.cc',
+    'crypto_linux.cc',
+    'crypto_macos.cc',
+    'crypto_win.cc',
+    'eventhandler.cc',
+    'eventhandler.h',
+    'eventhandler_android.cc',
+    'eventhandler_linux.cc',
+    'eventhandler_linux.h',
+    'eventhandler_macos.cc',
+    'eventhandler_macos.h',
+    'eventhandler_win.cc',
+    'eventhandler_win.h',
+    'filter_dummy.cc',
+    'platform.cc',
+    'platform.h',
+    'platform_android.cc',
+    'platform_linux.cc',
+    'platform_macos.cc',
+    'platform_win.cc',
+    'process.cc',
+    'process.h',
+    'process_android.cc',
+    'process_linux.cc',
+    'process_macos.cc',
+    'process_win.cc',
+    'socket.cc',
+    'socket.h',
+    'socket_android.cc',
+    'socket_linux.cc',
+    'socket_macos.cc',
+    'socket_win.cc',
+    'secure_socket_dummy.cc',
+  ],
+}
diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc
index 5bfc079..6f139b7 100644
--- a/runtime/bin/main.cc
+++ b/runtime/bin/main.cc
@@ -454,9 +454,6 @@
   // Prepare builtin and its dependent libraries for use to resolve URIs.
   // The builtin library is part of the core snapshot and would already be
   // available here in the case of script snapshot loading.
-  Dart_Handle uri_url = DartUtils::NewString(DartUtils::kUriLibURL);
-  Dart_Handle uri_lib = Dart_LookupLibrary(uri_url);
-  CHECK_RESULT(uri_lib);
   Dart_Handle builtin_lib =
       Builtin::LoadAndCheckLibrary(Builtin::kBuiltinLibrary);
   CHECK_RESULT(builtin_lib);
diff --git a/runtime/bin/net/nss.gyp b/runtime/bin/net/nss.gyp
index 53d3d6f..e1c64e1 100644
--- a/runtime/bin/net/nss.gyp
+++ b/runtime/bin/net/nss.gyp
@@ -91,6 +91,7 @@
       'target_name': 'nspr_dart',  # Added by Dart (the _dart postfix)
       'product_name': 'crnspr',
       'type': '<(component)',
+      'toolsets':['host','target'],
       # Changed by Dart: '<(nss_directory)/' added to all paths.
       'sources': [
         # Added by Dart.
@@ -458,6 +459,7 @@
       'target_name': 'nss_dart',  # Added by Dart (the _dart postfix)
       'product_name': 'crnss',
       'type': '<(component)',
+      'toolsets':['host','target'],
       'dependencies': [
         'nss_static_dart',  # Added by Dart (the _dart postfix)
       ],
@@ -509,6 +511,7 @@
       'target_name': 'nssckbi_dart',  # Added by Dart (the _dart postfix)
       'product_name': 'crnssckbi',
       'type': 'static_library',
+      'toolsets':['host','target'],
       # This target is an implementation detail - the public dependencies
       # should be on 'nss'.
       'suppress_wildcard': 1,
@@ -571,6 +574,7 @@
     {
       'target_name': 'nss_static_dart',  # Added by Dart (the _dart postfix)
       'type': 'static_library',
+      'toolsets':['host','target'],
       # This target is an implementation detail - the public dependencies
       # should be on 'nss'.
       'suppress_wildcard': 1,
diff --git a/runtime/bin/net/sqlite.gyp b/runtime/bin/net/sqlite.gyp
index 14dedb2..f194bdc 100644
--- a/runtime/bin/net/sqlite.gyp
+++ b/runtime/bin/net/sqlite.gyp
@@ -39,6 +39,7 @@
   'targets': [
     {
       'target_name': 'sqlite_dart',  # Added by Dart (the _dart postfix)
+      'toolsets':['host','target'],
       'conditions': [
         [ 'chromeos==1' , {
             'defines': [
diff --git a/runtime/bin/net/ssl.gyp b/runtime/bin/net/ssl.gyp
index b8fbf8f..a7744df 100644
--- a/runtime/bin/net/ssl.gyp
+++ b/runtime/bin/net/ssl.gyp
@@ -44,6 +44,7 @@
     {
       'target_name': 'libssl_dart',  # Added by Dart (the _dart postfix)
       'type': 'static_library',
+      'toolsets':['host','target'],
       # Changed by Dart: '<(ssl_directory)/' added to all paths.
       'sources': [
         '<(ssl_directory)/ssl/authcert.c',
diff --git a/runtime/bin/net/zlib.gyp b/runtime/bin/net/zlib.gyp
index 41c5c62..f3e7bca 100644
--- a/runtime/bin/net/zlib.gyp
+++ b/runtime/bin/net/zlib.gyp
@@ -24,6 +24,7 @@
     {
       'target_name': 'zlib_dart',  # Added by Dart (the _dart postfix)
       'type': 'static_library',
+      'toolsets':['host','target'],
       # Changed by Dart: '<(zlib_directory)/' added to all paths.
       'sources': [
         '<(zlib_path)/adler32.c',
diff --git a/runtime/bin/secure_socket_dummy.cc b/runtime/bin/secure_socket_dummy.cc
new file mode 100644
index 0000000..a571c85
--- /dev/null
+++ b/runtime/bin/secure_socket_dummy.cc
@@ -0,0 +1,90 @@
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#include "bin/builtin.h"
+#include "bin/dartutils.h"
+
+#include "include/dart_api.h"
+
+
+namespace dart {
+namespace bin {
+
+void FUNCTION_NAME(SecureSocket_Init)(Dart_NativeArguments args) {
+  Dart_EnterScope();
+  Dart_ThrowException(DartUtils::NewDartArgumentError(
+      "Secure Sockets unsupported on this platform"));
+  Dart_ExitScope();
+}
+
+
+void FUNCTION_NAME(SecureSocket_Connect)(Dart_NativeArguments args) {
+  Dart_EnterScope();
+  Dart_ThrowException(DartUtils::NewDartArgumentError(
+      "Secure Sockets unsupported on this platform"));
+  Dart_ExitScope();
+}
+
+
+void FUNCTION_NAME(SecureSocket_Destroy)(Dart_NativeArguments args) {
+  Dart_EnterScope();
+  Dart_ThrowException(DartUtils::NewDartArgumentError(
+      "Secure Sockets unsupported on this platform"));
+  Dart_ExitScope();
+}
+
+
+void FUNCTION_NAME(SecureSocket_Handshake)(Dart_NativeArguments args) {
+  Dart_EnterScope();
+  Dart_ThrowException(DartUtils::NewDartArgumentError(
+      "Secure Sockets unsupported on this platform"));
+  Dart_ExitScope();
+}
+
+
+void FUNCTION_NAME(SecureSocket_RegisterHandshakeCompleteCallback)(
+    Dart_NativeArguments args) {
+  Dart_EnterScope();
+  Dart_ThrowException(DartUtils::NewDartArgumentError(
+      "Secure Sockets unsupported on this platform"));
+  Dart_ExitScope();
+}
+
+
+void FUNCTION_NAME(SecureSocket_RegisterBadCertificateCallback)(
+    Dart_NativeArguments args) {
+  Dart_EnterScope();
+  Dart_ThrowException(DartUtils::NewDartArgumentError(
+      "Secure Sockets unsupported on this platform"));
+  Dart_ExitScope();
+}
+
+
+void FUNCTION_NAME(SecureSocket_ProcessBuffer)(Dart_NativeArguments args) {
+  Dart_EnterScope();
+  Dart_ThrowException(DartUtils::NewDartArgumentError(
+      "Secure Sockets unsupported on this platform"));
+  Dart_ExitScope();
+}
+
+
+void FUNCTION_NAME(SecureSocket_InitializeLibrary)
+    (Dart_NativeArguments args) {
+  Dart_EnterScope();
+  Dart_ThrowException(DartUtils::NewDartArgumentError(
+      "Secure Sockets unsupported on this platform"));
+  Dart_ExitScope();
+}
+
+
+void FUNCTION_NAME(SecureSocket_PeerCertificate)
+    (Dart_NativeArguments args) {
+  Dart_EnterScope();
+  Dart_ThrowException(DartUtils::NewDartArgumentError(
+      "Secure Sockets unsupported on this platform"));
+  Dart_ExitScope();
+}
+
+}  // namespace bin
+}  // namespace dart
diff --git a/runtime/bin/socket_android.cc b/runtime/bin/socket_android.cc
index 8bb8f07..20715a3 100644
--- a/runtime/bin/socket_android.cc
+++ b/runtime/bin/socket_android.cc
@@ -9,12 +9,14 @@
 #include <stdio.h>  // NOLINT
 #include <stdlib.h>  // NOLINT
 #include <string.h>  // NOLINT
+#include <sys/stat.h>  // NOLINT
 #include <unistd.h>  // NOLINT
 #include <netinet/tcp.h>  // NOLINT
 
-#include "bin/socket.h"
 #include "bin/fdutils.h"
+#include "bin/file.h"
 #include "bin/log.h"
+#include "bin/socket.h"
 
 
 namespace dart {
@@ -152,6 +154,17 @@
 }
 
 
+int Socket::GetType(intptr_t fd) {
+  struct stat buf;
+  int result = fstat(fd, &buf);
+  if (result == -1) return -1;
+  if (S_ISCHR(buf.st_mode)) return File::kTerminal;
+  if (S_ISFIFO(buf.st_mode)) return File::kPipe;
+  if (S_ISREG(buf.st_mode)) return File::kFile;
+  return File::kOther;
+}
+
+
 intptr_t Socket::GetStdioHandle(int num) {
   return static_cast<intptr_t>(num);
 }
diff --git a/runtime/bin/socket_patch.dart b/runtime/bin/socket_patch.dart
index f233a98..d86a17c 100644
--- a/runtime/bin/socket_patch.dart
+++ b/runtime/bin/socket_patch.dart
@@ -837,11 +837,6 @@
       if (offset < buffer.length) {
         if (!paused) {
           paused = true;
-          // TODO(ajohnsen): It would be nice to avoid this check.
-          // Some info: socket._write can emit an event, if it fails to write.
-          // If the user closes the socket in that event, stop() will be called
-          // before we get a change to pause.
-          if (subscription == null) return;
           subscription.pause();
         }
         socket._enableWriteEvent();
@@ -874,6 +869,7 @@
     if (subscription == null) return;
     subscription.cancel();
     subscription = null;
+    paused = false;
     socket._disableWriteEvent();
   }
 }
diff --git a/runtime/lib/array.dart b/runtime/lib/array.dart
index b26f098..cfb640b 100644
--- a/runtime/lib/array.dart
+++ b/runtime/lib/array.dart
@@ -194,6 +194,8 @@
     return this.length == 0;
   }
 
+  bool get isNotEmpty => !isEmpty;
+
   Iterable<E> get reversed => IterableMixinWorkaround.reversedList(this);
 
   void sort([int compare(E a, E b)]) {
@@ -445,6 +447,8 @@
     return this.length == 0;
   }
 
+  bool get isNotEmpty => !isEmpty;
+
   Iterable<E> get reversed => IterableMixinWorkaround.reversedList(this);
 
   void sort([int compare(E a, E b)]) {
diff --git a/runtime/lib/collection_patch.dart b/runtime/lib/collection_patch.dart
index 1ddd5d9..6479ba2 100644
--- a/runtime/lib/collection_patch.dart
+++ b/runtime/lib/collection_patch.dart
@@ -109,6 +109,8 @@
   /* patch */ int get length => _hashTable._elementCount;
 
   /* patch */ bool get isEmpty => _hashTable._elementCount == 0;
+
+  /* patch */ bool get isNotEmpty => !isEmpty;
 }
 
 patch class HashSet<E> {
@@ -130,6 +132,8 @@
 
   /* patch */ bool get isEmpty => _table._elementCount == 0;
 
+  /* patch */ bool get isNotEmpty => !isEmpty;
+
   /* patch */ bool contains(Object object) => _table._get(object) >= 0;
 
   // Collection.
@@ -300,6 +304,8 @@
   /* patch */ int get length => _hashTable._elementCount;
 
   /* patch */ bool get isEmpty => _hashTable._elementCount == 0;
+
+  /* patch */ bool get isNotEmpty => !isEmpty;
 }
 
 patch class LinkedHashSet<E> extends _HashSetBase<E> {
@@ -320,6 +326,8 @@
 
   /* patch */ bool get isEmpty => _table._elementCount == 0;
 
+  /* patch */ bool get isNotEmpty => !isEmpty;
+
   /* patch */ bool contains(Object object) => _table._get(object) >= 0;
 
   /* patch */ void forEach(void action(E element)) {
diff --git a/runtime/lib/growable_array.dart b/runtime/lib/growable_array.dart
index 1e69b65..6dfb6f6 100644
--- a/runtime/lib/growable_array.dart
+++ b/runtime/lib/growable_array.dart
@@ -324,6 +324,8 @@
     return this.length == 0;
   }
 
+  bool get isNotEmpty => !isEmpty;
+
   void clear() {
     this.length = 0;
   }
diff --git a/runtime/lib/immutable_map.dart b/runtime/lib/immutable_map.dart
index 3ca9ed5..3c5c72e 100644
--- a/runtime/lib/immutable_map.dart
+++ b/runtime/lib/immutable_map.dart
@@ -25,6 +25,8 @@
     return kvPairs_.length == 0;
   }
 
+  bool get isNotEmpty => !isEmpty;
+
   int get length {
     return kvPairs_.length ~/ 2;
   }
diff --git a/runtime/lib/integers_patch.dart b/runtime/lib/integers_patch.dart
index 05d47cf..fb749d7 100644
--- a/runtime/lib/integers_patch.dart
+++ b/runtime/lib/integers_patch.dart
@@ -13,6 +13,8 @@
       ((9 <= codePoint) && (codePoint <= 13)); // CR, LF, TAB, etc.
   }
 
+  static bool is64Bit() => 1 << 32 is _Smi;
+
   static int _tryParseSmi(String str) {
     if (str.isEmpty) return null;
     var ix = 0;
@@ -40,7 +42,8 @@
         return null;  // Empty.
       }
     }
-    if ((endIx - ix) >= 9) {
+    int smiLimit = is64Bit() ? 18 : 9;
+    if ((endIx - ix) >= smiLimit) {
       return null;  // May not fit into a Smi.
     }
     var result = 0;
diff --git a/runtime/lib/math_patch.dart b/runtime/lib/math_patch.dart
index c279c19..d5110da 100644
--- a/runtime/lib/math_patch.dart
+++ b/runtime/lib/math_patch.dart
@@ -49,7 +49,11 @@
     do {
       seed = (seed + 0x5A17) & _Random._MASK_64;
     } while (seed == 0);
-    return new _Random._internal(seed);
+    // Crank a couple of times to distribute the seed bits a bit further.
+    return new _Random._internal(seed).._nextState()
+                                      .._nextState()
+                                      .._nextState()
+                                      .._nextState();
   }
 }
 
diff --git a/runtime/lib/string_patch.dart b/runtime/lib/string_patch.dart
index dbe8dc0..0707a5f 100644
--- a/runtime/lib/string_patch.dart
+++ b/runtime/lib/string_patch.dart
@@ -70,6 +70,8 @@
     return this.length == 0;
   }
 
+  bool get isNotEmpty => !isEmpty;
+
   String operator +(String other) native "String_concat";
 
   String concat(String other) => this + other;
diff --git a/runtime/lib/typed_data.dart b/runtime/lib/typed_data.dart
index 8e5bcaa..8cf462f 100644
--- a/runtime/lib/typed_data.dart
+++ b/runtime/lib/typed_data.dart
@@ -358,6 +358,7 @@
     return this.length == 0;
   }
 
+  bool get isNotEmpty => !isEmpty;
 
   // Method(s) implementing the List interface.
 
diff --git a/runtime/tests/vm/dart/isolate_mirror_local_test.dart b/runtime/tests/vm/dart/isolate_mirror_local_test.dart
index e7927c2..39f5948 100644
--- a/runtime/tests/vm/dart/isolate_mirror_local_test.dart
+++ b/runtime/tests/vm/dart/isolate_mirror_local_test.dart
@@ -13,7 +13,6 @@
 import 'dart:async';
 import 'dart:isolate';
 import 'dart:mirrors';
-import 'dart:uri';
 
 ReceivePort exit_port;
 Set expectedTests;
diff --git a/runtime/tests/vm/vm.status b/runtime/tests/vm/vm.status
index 63e214c..4fe49fc 100644
--- a/runtime/tests/vm/vm.status
+++ b/runtime/tests/vm/vm.status
@@ -54,9 +54,6 @@
 # Skip until we stabilize language tests.
 *: Skip
 
-[ $arch == arm ]
-*: Skip
-
 [ $arch == simarm ]
 # Tests missing code generation support.
 cc/Dart2JSCompileAll: Skip
@@ -65,11 +62,6 @@
 dart/byte_array_test: Skip
 dart/byte_array_optimized_test: Skip
 
-# Bug in optimized code generation.
-cc/ExternalStringDeoptimize: Skip
-dart/inline_stack_frame_test: Skip
-dart/isolate_mirror_local_test: Skip
-
 [ $arch == mips ]
 *: Skip
 
@@ -82,6 +74,11 @@
 dart/byte_array_optimized_test: Skip
 dart/inline_stack_frame_test: Skip
 
+# Bug in optimized code generation.
+cc/ExternalStringDeoptimize: Skip
+dart/inline_stack_frame_test: Skip
+dart/isolate_mirror_local_test: Skip
+
 # TODO(ajohnsen): Fix this as part of library changes.
 [ $compiler == none ]
 cc/CustomIsolates: Skip # Bug 6890
diff --git a/runtime/tools/create_snapshot_bin.py b/runtime/tools/create_snapshot_bin.py
index c80df4d..db948a1 100755
--- a/runtime/tools/create_snapshot_bin.py
+++ b/runtime/tools/create_snapshot_bin.py
@@ -59,83 +59,6 @@
   return True
 
 
-def RunAdb(device, command):
-  """Run a raw adb command."""
-  return utils.RunCommand(["adb", "-s", device] + command)
-
-
-def RunAdbShell(device, command):
-  RunAdb(device, ['shell'] + command)
-
-
-def RunOnAndroid(options):
-  outputBin = options.output_bin
-
-  android_workspace = os.getenv("ANDROID_DART", "/data/local/dart")
-  android_outputBin = join(android_workspace, basename(outputBin))
-
-  executable = options.executable
-  android_executable = join(android_workspace, basename(executable))
-
-  filesToPush = [] # (src, dest)
-  filesToPull = [] # (src, dest)
-
-  # Setup arguments to the snapshot generator binary.
-  script_args = [android_executable]
-
-  # First setup the snapshot output filename.
-  filesToPull.append((android_outputBin, outputBin))
-  script_args.append(''.join([ "--snapshot=", android_outputBin]))
-
-  # We don't know what source files are needed to fully satisfy a dart script,
-  # so we can't support the general case of url mapping or script inclusion.
-  if options.url_mapping:
-    raise Exception("--url_mapping is not supported when building for Android")
-
-  if options.script:
-    raise Exception("--script is not supported when building for Android")
-
-  filesToPush.append((executable, android_executable))
-
-  abi = options.abi or 'x86'
-  # We know we're run in the runtime directory, and we know the relative path
-  # to the tools we want to execute:
-  command = ["tools/android_finder.py", "--bootstrap", "--abi", abi]
-  if VERBOSE:
-    command += ['--verbose']
-  device = utils.RunCommand(command, errStream=sys.stderr)
-
-  if device == None:
-    raise Exception("Could not find Android device for abi %s" % abi)
-
-  device = device.strip()
-
-  if VERBOSE:
-    sys.write.stderr('Using Android device %s for abi %s' % (device, abi))
-
-  RunAdbShell(device, ["mkdir", android_workspace])
-
-  try:
-    if VERBOSE:
-      sys.write.stderr('pushing files to %s' % device)
-    for src, dest in filesToPush:
-      RunAdb(device, ["push", src, dest])
-    if VERBOSE:
-      sys.write.stderr('running snapshot generator')
-    RunAdbShell(device, script_args)
-    if VERBOSE:
-      sys.write.stderr('retrieving snapshot')
-    for src, dest in filesToPull:
-      RunAdb(device, ["pull", src, dest])
-  finally:
-    if VERBOSE:
-      sys.write.stderr('cleaning intermediate files')
-    for src, dest in filesToPush:
-      RunAdbShell(device, ["rm", dest])
-    for src, dest in filesToPull:
-      RunAdbShell(device, ["rm", src])
-
-
 def Main():
   # Parse options.
   parser = BuildOptions()
@@ -165,15 +88,12 @@
     script_args.append(options.script)
 
   # Construct command line to execute the snapshot generator binary and invoke.
-  if options.target_os == 'android':
-    RunOnAndroid(options)
-  else:
-    command = [ options.executable ] + script_args
-    try:
-      utils.RunCommand(command, outStream=sys.stderr, errStream=sys.stderr,
-                       verbose=options.verbose, printErrorInfo=True)
-    except Exception as e:
-      return -1
+  command = [ options.executable ] + script_args
+  try:
+    utils.RunCommand(command, outStream=sys.stderr, errStream=sys.stderr,
+                     verbose=options.verbose, printErrorInfo=True)
+  except Exception as e:
+    return -1
 
   return 0
 
diff --git a/runtime/tools/gyp/runtime_configurations_android.gypi b/runtime/tools/gyp/runtime_configurations_android.gypi
index 15eafa5..6de2aee 100644
--- a/runtime/tools/gyp/runtime_configurations_android.gypi
+++ b/runtime/tools/gyp/runtime_configurations_android.gypi
@@ -7,6 +7,9 @@
 # http://src.chromium.org/viewvc/chrome/trunk/src/build/common.gypi
 
 {
+  'variables': {
+    'dart_io_support': 0,
+  },
   'target_defaults': {
     'cflags': [
       '-Wno-abi',
diff --git a/runtime/vm/assembler_arm.cc b/runtime/vm/assembler_arm.cc
index dffa50b..b84ff57 100644
--- a/runtime/vm/assembler_arm.cc
+++ b/runtime/vm/assembler_arm.cc
@@ -18,7 +18,7 @@
 namespace dart {
 
 DEFINE_FLAG(bool, print_stop_message, true, "Print stop message.");
-
+DECLARE_FLAG(bool, inline_alloc);
 
 bool CPUFeatures::integer_division_supported_ = false;
 #if defined(DEBUG)
@@ -414,6 +414,12 @@
 }
 
 
+void Assembler::bics(Register rd, Register rn, ShifterOperand so,
+                     Condition cond) {
+  EmitType01(cond, so.type(), BIC, 1, rn, rd, so);
+}
+
+
 void Assembler::mvn(Register rd, ShifterOperand so, Condition cond) {
   EmitType01(cond, so.type(), MVN, 0, R0, rd, so);
 }
@@ -517,6 +523,13 @@
 }
 
 
+void Assembler::smlal(Register rd_lo, Register rd_hi,
+                      Register rn, Register rm, Condition cond) {
+  // Assembler registers rd_lo, rd_hi, rn, rm are encoded as rd, rn, rm, rs.
+  EmitMulOp(cond, B23 | B22 | B21, rd_lo, rd_hi, rn, rm);
+}
+
+
 void Assembler::EmitDivOp(Condition cond, int32_t opcode,
                           Register rd, Register rn, Register rm) {
   ASSERT(CPUFeatures::integer_division_supported());
@@ -2060,9 +2073,39 @@
 
 void Assembler::TryAllocate(const Class& cls,
                             Label* failure,
-                            bool near_jump,
                             Register instance_reg) {
-  UNIMPLEMENTED();
+  ASSERT(failure != NULL);
+  if (FLAG_inline_alloc) {
+    Heap* heap = Isolate::Current()->heap();
+    const intptr_t instance_size = cls.instance_size();
+    LoadImmediate(instance_reg, heap->TopAddress());
+    ldr(instance_reg, Address(instance_reg, 0));
+    AddImmediate(instance_reg, instance_size);
+
+    // instance_reg: potential next object start.
+    LoadImmediate(TMP, heap->EndAddress());
+    ldr(TMP, Address(TMP, 0));
+    cmp(TMP, ShifterOperand(instance_reg));
+    // fail if heap end unsigned less than or equal to instance_reg.
+    b(failure, LS);
+
+    // Successfully allocated the object, now update top to point to
+    // next object start and store the class in the class field of object.
+    LoadImmediate(TMP, heap->TopAddress());
+    str(instance_reg, Address(TMP, 0));
+
+    ASSERT(instance_size >= kHeapObjectTag);
+    AddImmediate(instance_reg, -instance_size + kHeapObjectTag);
+
+    uword tags = 0;
+    tags = RawObject::SizeTag::update(instance_size, tags);
+    ASSERT(cls.id() != kIllegalCid);
+    tags = RawObject::ClassIdTag::update(cls.id(), tags);
+    LoadImmediate(TMP, tags);
+    str(TMP, FieldAddress(instance_reg, Object::tags_offset()));
+  } else {
+    b(failure);
+  }
 }
 
 
diff --git a/runtime/vm/assembler_arm.h b/runtime/vm/assembler_arm.h
index 6195664..4ee373b 100644
--- a/runtime/vm/assembler_arm.h
+++ b/runtime/vm/assembler_arm.h
@@ -382,6 +382,7 @@
   void movs(Register rd, ShifterOperand so, Condition cond = AL);
 
   void bic(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
+  void bics(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
 
   void mvn(Register rd, ShifterOperand so, Condition cond = AL);
   void mvns(Register rd, ShifterOperand so, Condition cond = AL);
@@ -402,6 +403,8 @@
              Condition cond = AL);
   void umull(Register rd_lo, Register rd_hi, Register rn, Register rm,
              Condition cond = AL);
+  void smlal(Register rd_lo, Register rd_hi, Register rn, Register rm,
+             Condition cond = AL);
 
   // Division instructions.
   void sdiv(Register rd, Register rn, Register rm, Condition cond = AL);
@@ -668,7 +671,6 @@
   // Only the tags field of the object is initialized.
   void TryAllocate(const Class& cls,
                    Label* failure,
-                   bool near_jump,
                    Register instance_reg);
 
   // Emit data (e.g encoded instruction or immediate) in instruction stream.
diff --git a/runtime/vm/assembler_arm_test.cc b/runtime/vm/assembler_arm_test.cc
index 52de670..838bb69 100644
--- a/runtime/vm/assembler_arm_test.cc
+++ b/runtime/vm/assembler_arm_test.cc
@@ -17,7 +17,7 @@
 
 ASSEMBLER_TEST_GENERATE(Simple, assembler) {
   __ mov(R0, ShifterOperand(42));
-  __ mov(PC, ShifterOperand(LR));
+  __ bx(LR);
 }
 
 
@@ -29,7 +29,7 @@
 
 ASSEMBLER_TEST_GENERATE(MoveNegated, assembler) {
   __ mvn(R0, ShifterOperand(42));
-  __ mov(PC, ShifterOperand(LR));
+  __ bx(LR);
 }
 
 
@@ -46,7 +46,7 @@
   __ mov(R0, shifter_op);
   EXPECT(ShifterOperand::CanHold(0x30000003, &shifter_op));
   __ add(R0, R0, shifter_op);
-  __ mov(PC, ShifterOperand(LR));
+  __ bx(LR);
 }
 
 
@@ -60,7 +60,7 @@
 ASSEMBLER_TEST_GENERATE(MovImm16, assembler) {
   __ movw(R0, 0x5678);
   __ movt(R0, 0x1234);
-  __ mov(PC, ShifterOperand(LR));
+  __ bx(LR);
 }
 
 
@@ -76,7 +76,7 @@
   __ cmp(R0, ShifterOperand(0));
   __ LoadImmediate(R0, 0x12345678, EQ);
   __ LoadImmediate(R0, 0x87654321, NE);
-  __ mov(PC, ShifterOperand(LR));
+  __ bx(LR);
 }
 
 
@@ -99,7 +99,7 @@
   __ vmovsr(S7, R1);  // S7 = R1, S6:S7 == 41:43
   __ vmovrrd(R0, R1, D3);  // R0:R1 = D3, R0:R1 == 41:43
   __ sub(R0, R1, ShifterOperand(R0));  // 43-41
-  __ mov(PC, ShifterOperand(LR));
+  __ bx(LR);
 }
 
 
@@ -118,7 +118,7 @@
   __ vadds(S0, S0, S0);
   __ vstrs(S0, Address(R2, (-kWordSize * 30)));
   __ ldr(R0, Address(SP, (kWordSize * 30), Address::PostIndex));
-  __ mov(PC, ShifterOperand(LR));
+  __ bx(LR);
 }
 
 
@@ -143,7 +143,7 @@
   // Expressing __ldr(R0, Address(SP, (kWordSize * 32), Address::PostIndex));
   // as:
   __ ldr(R0, Address(SP, R1, LSL, 5, Address::PostIndex));
-  __ mov(PC, ShifterOperand(LR));
+  __ bx(LR);
 }
 
 
@@ -167,7 +167,7 @@
   __ vstrd(D0, Address(R2, (-kWordSize * 30)));
   __ ldr(R1, Address(R2, (-kWordSize * 29)));
   __ ldr(R0, Address(SP, (kWordSize * 30), Address::PostIndex));
-  __ mov(PC, ShifterOperand(LR));
+  __ bx(LR);
 }
 
 
@@ -190,7 +190,7 @@
   __ vdivs(S0, S0, S1);  // 14.7f
   __ vsqrts(S0, S0);  // 3.8340579f
   __ vmovrs(R0, S0);
-  __ mov(PC, ShifterOperand(LR));
+  __ bx(LR);
 }
 
 
@@ -213,7 +213,7 @@
   __ vdivd(D0, D0, D1);  // 14.7
   __ vsqrtd(D0, D0);  // 3.8340579
   __ vmovrrd(R0, R1, D0);
-  __ mov(PC, ShifterOperand(LR));
+  __ bx(LR);
 }
 
 
@@ -225,12 +225,31 @@
 }
 
 
+ASSEMBLER_TEST_GENERATE(DoubleSqrtNeg, assembler) {
+  // Check that sqrt of a negative double gives NaN.
+  __ LoadDImmediate(D1, -1.0, R0);
+  __ vsqrtd(D0, D1);
+  __ vcmpd(D0, D0);
+  __ vmstat();
+  __ mov(R0, ShifterOperand(1), VS);
+  __ mov(R0, ShifterOperand(0), VC);
+  __ Ret();
+}
+
+
+ASSEMBLER_TEST_RUN(DoubleSqrtNeg, test) {
+  EXPECT(test != NULL);
+  typedef double (*DoubleFPOperations)();
+  EXPECT_EQ(1, EXECUTE_TEST_CODE_INT32(DoubleFPOperations, test->entry()));
+}
+
+
 ASSEMBLER_TEST_GENERATE(IntToDoubleConversion, assembler) {
   __ mov(R3, ShifterOperand(6));
   __ vmovsr(S3, R3);
   __ vcvtdi(D1, S3);
   __ vmovrrd(R0, R1, D1);
-  __ mov(PC, ShifterOperand(LR));
+  __ bx(LR);
 }
 
 
@@ -254,7 +273,7 @@
   __ LoadDImmediate(D2, 1.0 * (1LL << 32), R0);
   __ vmlad(D0, D1, D2);
   __ vmovrrd(R0, R1, D0);
-  __ mov(PC, ShifterOperand(LR));
+  __ bx(LR);
 }
 
 
@@ -272,7 +291,7 @@
   __ vmovsr(S3, R3);
   __ vcvtsi(S1, S3);
   __ vmovrs(R0, S1);
-  __ mov(PC, ShifterOperand(LR));
+  __ bx(LR);
 }
 
 
@@ -288,7 +307,7 @@
   __ vmovsr(S1, R0);
   __ vcvtis(S0, S1);
   __ vmovrs(R0, S0);
-  __ mov(PC, ShifterOperand(LR));
+  __ bx(LR);
 }
 
 
@@ -311,7 +330,7 @@
   __ vmovdrr(D1, R0, R1);
   __ vcvtid(S0, D1);
   __ vmovrs(R0, S0);
-  __ mov(PC, ShifterOperand(LR));
+  __ bx(LR);
 }
 
 
@@ -334,7 +353,7 @@
   __ LoadSImmediate(S1, 12.8f);
   __ vcvtds(D2, S1);
   __ vmovrrd(R0, R1, D2);
-  __ mov(PC, ShifterOperand(LR));
+  __ bx(LR);
 }
 
 
@@ -351,7 +370,7 @@
   __ LoadDImmediate(D1, 12.8, R0);
   __ vcvtsd(S3, D1);
   __ vmovrs(R0, S3);
-  __ mov(PC, ShifterOperand(LR));
+  __ bx(LR);
 }
 
 
@@ -387,7 +406,7 @@
   __ add(R0, R0, ShifterOperand(16), VC);  // Error if not unordered (not Nan).
 
   // R0 is 0 if all tests passed.
-  __ mov(PC, ShifterOperand(LR));
+  __ bx(LR);
 }
 
 
@@ -421,7 +440,7 @@
   __ add(R0, R0, ShifterOperand(16), VC);  // Error if not unordered (not Nan).
 
   // R0 is 0 if all tests passed.
-  __ mov(PC, ShifterOperand(LR));
+  __ bx(LR);
 }
 
 
@@ -440,7 +459,7 @@
   __ mov(R0, ShifterOperand(R0, LSL, 1));
   __ movs(R1, ShifterOperand(R1, LSR, 1));
   __ b(&loop_entry, NE);
-  __ mov(PC, ShifterOperand(LR));
+  __ bx(LR);
 }
 
 
@@ -457,7 +476,7 @@
   __ b(&skip);
   __ mov(R0, ShifterOperand(11));
   __ Bind(&skip);
-  __ mov(PC, ShifterOperand(LR));
+  __ bx(LR);
 }
 
 
@@ -472,7 +491,7 @@
   __ mov(R1, ShifterOperand(123));
   __ Push(R1);
   __ Pop(R0);
-  __ mov(PC, ShifterOperand(LR));
+  __ bx(LR);
 }
 
 
@@ -489,7 +508,7 @@
   __ add(R0, R1, ShifterOperand(4));
   __ rsbs(R0, R0, ShifterOperand(100));
   __ rsc(R0, R0, ShifterOperand(100));
-  __ mov(PC, ShifterOperand(LR));
+  __ bx(LR);
 }
 
 
@@ -511,7 +530,7 @@
   __ tst(IP, ShifterOperand(0));
   __ b(&retry, NE);  // NE if context switch occurred between ldrex and strex.
   __ Pop(R0);  // 42
-  __ mov(PC, ShifterOperand(LR));
+  __ bx(LR);
 }
 
 
@@ -531,7 +550,7 @@
   __ strex(IP, R1, SP);  // IP == 1, failure
   __ Pop(R0);  // 40
   __ add(R0, R0, ShifterOperand(IP));
-  __ mov(PC, ShifterOperand(LR));
+  __ bx(LR);
 }
 
 
@@ -548,7 +567,7 @@
   __ and_(R1, R2, ShifterOperand(R1));
   __ mov(R3, ShifterOperand(42));
   __ orr(R0, R1, ShifterOperand(R3));
-  __ mov(PC, ShifterOperand(LR));
+  __ bx(LR);
 }
 
 
@@ -563,11 +582,11 @@
   __ mov(R0, ShifterOperand(0));
   __ tst(R0, ShifterOperand(R1));  // Set zero-flag.
   __ orrs(R0, R0, ShifterOperand(1));  // Clear zero-flag.
-  __ mov(PC, ShifterOperand(LR), EQ);
+  __ bx(LR, EQ);
   __ mov(R0, ShifterOperand(42));
-  __ mov(PC, ShifterOperand(LR), NE);  // Only this return should fire.
+  __ bx(LR, NE);  // Only this return should fire.
   __ mov(R0, ShifterOperand(2));
-  __ mov(PC, ShifterOperand(LR));
+  __ bx(LR);
 }
 
 
@@ -583,7 +602,7 @@
   __ mov(R2, ShifterOperand(40));
   __ mul(R3, R2, R1);
   __ mov(R0, ShifterOperand(R3));
-  __ mov(PC, ShifterOperand(LR));
+  __ bx(LR);
 }
 
 
@@ -603,7 +622,7 @@
   __ vcvtid(S0, D0);
   __ vmovrs(R1, S0);  // r1 = r0/r2
   __ mls(R0, R1, R2, R0);  // r0 = r0 - r1*r2
-  __ mov(PC, ShifterOperand(LR));
+  __ bx(LR);
 }
 
 
@@ -624,7 +643,7 @@
   __ mla(R2, IP, R3, R4);
   __ add(R1, R2, ShifterOperand(R1));
   __ Pop(R4);
-  __ mov(PC, ShifterOperand(LR));
+  __ bx(LR);
 }
 
 
@@ -638,7 +657,7 @@
 
 ASSEMBLER_TEST_GENERATE(Multiply32To64, assembler) {
   __ smull(R0, R1, R0, R2);
-  __ mov(PC, ShifterOperand(LR));
+  __ bx(LR);
 }
 
 
@@ -650,6 +669,20 @@
 }
 
 
+ASSEMBLER_TEST_GENERATE(MultiplyAccum32To64, assembler) {
+  __ smlal(R0, R1, R0, R2);
+  __ bx(LR);
+}
+
+
+ASSEMBLER_TEST_RUN(MultiplyAccum32To64, test) {
+  EXPECT(test != NULL);
+  typedef int64_t (*Multiply32To64)(int64_t operand0, int64_t operand1);
+  EXPECT_EQ(3,
+            EXECUTE_TEST_CODE_INT64_LL(Multiply32To64, test->entry(), -3, -2));
+}
+
+
 ASSEMBLER_TEST_GENERATE(Clz, assembler) {
   Label error;
 
@@ -670,10 +703,10 @@
   __ cmp(R1, ShifterOperand(3));
   __ b(&error, NE);
   __ mov(R0, ShifterOperand(0));
-  __ mov(PC, ShifterOperand(LR));
+  __ bx(LR);
   __ Bind(&error);
   __ mov(R0, ShifterOperand(1));
-  __ mov(PC, ShifterOperand(LR));
+  __ bx(LR);
 }
 
 
@@ -693,7 +726,7 @@
   __ b(&skip, NE);
   __ mov(R0, ShifterOperand(0));
   __ Bind(&skip);
-  __ mov(PC, ShifterOperand(LR));
+  __ bx(LR);
 }
 
 
@@ -711,7 +744,7 @@
   __ mov(R0, ShifterOperand(R0, LSL, 1));
   __ mov(R1, ShifterOperand(1));
   __ mov(R0, ShifterOperand(R0, LSL, R1));
-  __ mov(PC, ShifterOperand(LR));
+  __ bx(LR);
 }
 
 
@@ -729,7 +762,7 @@
   __ mov(R0, ShifterOperand(R0, LSR, 1));
   __ mov(R1, ShifterOperand(1));
   __ mov(R0, ShifterOperand(R0, LSR, R1));
-  __ mov(PC, ShifterOperand(LR));
+  __ bx(LR);
 }
 
 
@@ -746,7 +779,7 @@
   __ mov(R0, ShifterOperand(1));
   __ Lsl(R0, R0, 31);
   __ Lsr(R0, R0, 31);
-  __ mov(PC, ShifterOperand(LR));
+  __ bx(LR);
 }
 
 
@@ -763,7 +796,7 @@
   __ mov(R0, ShifterOperand(1));
   __ Lsl(R0, R0, 31);
   __ Asr(R0, R0, 31);
-  __ mov(PC, ShifterOperand(LR));
+  __ bx(LR);
 }
 
 
@@ -777,7 +810,7 @@
 ASSEMBLER_TEST_GENERATE(Rsb, assembler) {
   __ mov(R3, ShifterOperand(10));
   __ rsb(R0, R3, ShifterOperand(42));
-  __ mov(PC, ShifterOperand(LR));
+  __ bx(LR);
 }
 
 
@@ -823,7 +856,7 @@
   __ mov(R0, ShifterOperand(0));
   __ Bind(&Done);
   __ ldr(R1, Address(SP, (kWordSize * 30), Address::PostIndex));
-  __ mov(PC, ShifterOperand(LR));
+  __ bx(LR);
 }
 
 
@@ -840,7 +873,7 @@
   __ str(R1, Address(SP, (-kWordSize * 30), Address::PreIndex));
   __ ldrsb(R0, Address(R2, (-kWordSize * 30)));
   __ ldr(R1, Address(SP, (kWordSize * 30), Address::PostIndex));
-  __ mov(PC, ShifterOperand(LR));
+  __ bx(LR);
 }
 
 
@@ -857,7 +890,7 @@
   __ str(R1, Address(SP, (-kWordSize * 30), Address::PreIndex));
   __ ldrb(R0, Address(R2, (-kWordSize * 30)));
   __ ldr(R1, Address(SP, (kWordSize * 30), Address::PostIndex));
-  __ mov(PC, ShifterOperand(LR));
+  __ bx(LR);
 }
 
 
@@ -874,7 +907,7 @@
   __ str(R1, Address(SP, (-kWordSize * 30), Address::PreIndex));
   __ ldrsh(R0, Address(R2, (-kWordSize * 30)));
   __ ldr(R1, Address(SP, (kWordSize * 30), Address::PostIndex));
-  __ mov(PC, ShifterOperand(LR));
+  __ bx(LR);
 }
 
 
@@ -891,7 +924,7 @@
   __ str(R1, Address(SP, (-kWordSize * 30), Address::PreIndex));
   __ ldrh(R0, Address(R2, (-kWordSize * 30)));
   __ ldr(R1, Address(SP, (kWordSize * 30), Address::PostIndex));
-  __ mov(PC, ShifterOperand(LR));
+  __ bx(LR);
 }
 
 
@@ -910,7 +943,7 @@
   __ ldrd(R0, Address(SP, (kWordSize * 30), Address::PostIndex));
   __ sub(R0, R0, ShifterOperand(R2));
   __ add(R1, R1, ShifterOperand(R3));
-  __ mov(PC, ShifterOperand(LR));
+  __ bx(LR);
 }
 
 
@@ -954,7 +987,7 @@
   __ Pop(R5);  // Restore R5.
   __ Pop(R5);  // Restore R5.
   __ Pop(R5);  // Restore R5.
-  __ mov(PC, ShifterOperand(LR));
+  __ bx(LR);
 }
 
 
@@ -970,7 +1003,7 @@
   __ mov(R1, ShifterOperand(kWordSize));
   __ str(R2, Address(SP, R1, LSL, 1, Address::NegOffset));
   __ ldr(R0, Address(SP, (-kWordSize * 2), Address::Offset));
-  __ mov(PC, ShifterOperand(LR));
+  __ bx(LR);
 }
 
 
@@ -986,7 +1019,7 @@
   __ mov(R1, ShifterOperand(kWordSize));
   __ str(R2, Address(SP, (-kWordSize * 32), Address::Offset));
   __ ldr(R0, Address(SP, R1, LSL, 5, Address::NegOffset));
-  __ mov(PC, ShifterOperand(LR));
+  __ bx(LR);
 }
 
 
@@ -1002,7 +1035,7 @@
   __ mov(R1, ShifterOperand(kWordSize * 2));
   __ str(R2, Address(SP, R1, LSR, 1, Address::NegOffset));
   __ ldr(R0, Address(SP, -kWordSize, Address::Offset));
-  __ mov(PC, ShifterOperand(LR));
+  __ bx(LR);
 }
 
 
@@ -1018,7 +1051,7 @@
   __ mov(R1, ShifterOperand(kWordSize * 2));
   __ str(R2, Address(SP, -kWordSize, Address::Offset));
   __ ldr(R0, Address(SP, R1, LSR, 1, Address::NegOffset));
-  __ mov(PC, ShifterOperand(LR));
+  __ bx(LR);
 }
 
 
@@ -1036,7 +1069,7 @@
   __ str(R2, Address(SP, R1, LSL, 5, Address::NegPreIndex));
   __ ldr(R0, Address(R3, (-kWordSize * 32), Address::Offset));
   __ mov(SP, ShifterOperand(R3));
-  __ mov(PC, ShifterOperand(LR));
+  __ bx(LR);
 }
 
 
@@ -1052,7 +1085,7 @@
   __ mov(R1, ShifterOperand(kWordSize));
   __ str(R2, Address(SP, (-kWordSize * 32), Address::PreIndex));
   __ ldr(R0, Address(SP, R1, LSL, 5, Address::PostIndex));
-  __ mov(PC, ShifterOperand(LR));
+  __ bx(LR);
 }
 
 
@@ -1106,7 +1139,7 @@
   __ vmstat();
   __ mov(R0, ShifterOperand(0), NE);  // Put failure into R0 if NE
 
-  __ mov(PC, ShifterOperand(LR));
+  __ bx(LR);
 }
 
 
@@ -1159,7 +1192,7 @@
   __ vmstat();
   __ mov(R0, ShifterOperand(0), NE);  // Put failure value into R0 if NE
 
-  __ mov(PC, ShifterOperand(LR));
+  __ bx(LR);
 }
 
 
@@ -1211,7 +1244,7 @@
   __ vmstat();
   __ mov(R0, ShifterOperand(0), NE);  // Put failure into R0 if NE
 
-  __ mov(PC, ShifterOperand(LR));
+  __ bx(LR);
 }
 
 
@@ -1262,7 +1295,7 @@
   __ vmstat();
   __ mov(R0, ShifterOperand(0), NE);  // Put failure value into R0 if NE
 
-  __ mov(PC, ShifterOperand(LR));
+  __ bx(LR);
 }
 
 
@@ -1319,7 +1352,7 @@
   __ vmstat();
   __ mov(R0, ShifterOperand(0), NE);  // Put failure into R0 if NE
 
-  __ mov(PC, ShifterOperand(LR));
+  __ bx(LR);
 }
 
 
@@ -1374,7 +1407,7 @@
   __ vmstat();
   __ mov(R0, ShifterOperand(0), NE);  // Put failure value into R0 if NE
 
-  __ mov(PC, ShifterOperand(LR));
+  __ bx(LR);
 }
 
 
@@ -1395,7 +1428,7 @@
   // available both in Thumb and in the ARM instruction set.
   __ Lsr(R0, R0, 24);
   __ and_(R0, R0, ShifterOperand(0xf));
-  __ mov(PC, ShifterOperand(LR));
+  __ bx(LR);
 }
 
 
@@ -1413,7 +1446,7 @@
   __ mrc(R0, 15, 0, 0, 2, 0);
   __ Lsr(R0, R0, 24);
   __ and_(R0, R0, ShifterOperand(0xf));
-  __ mov(PC, ShifterOperand(LR));
+  __ bx(LR);
 }
 
 
@@ -1431,7 +1464,7 @@
   __ mrc(R0, 15, 0, 0, 2, 0);
   __ Lsr(R0, R0, 24);
   __ and_(R0, R0, ShifterOperand(0xf));
-  __ mov(PC, ShifterOperand(LR));
+  __ bx(LR);
 }
 
 
@@ -1458,7 +1491,7 @@
   } else {
     __ mov(R0, ShifterOperand(3));
   }
-  __ mov(PC, ShifterOperand(LR));
+  __ bx(LR);
 }
 
 
@@ -1478,7 +1511,7 @@
   } else {
     __ LoadImmediate(R0, -3);
   }
-  __ mov(PC, ShifterOperand(LR));
+  __ bx(LR);
 }
 
 
@@ -1498,7 +1531,7 @@
   } else {
     __ LoadImmediate(R0, 0);
   }
-  __ mov(PC, ShifterOperand(LR));
+  __ bx(LR);
 }
 
 
@@ -1518,7 +1551,7 @@
   } else {
     __ LoadImmediate(R0, 0);
   }
-  __ mov(PC, ShifterOperand(LR));
+  __ bx(LR);
 }
 
 
@@ -1538,7 +1571,7 @@
   } else {
     __ LoadImmediate(R0, 0);
   }
-  __ mov(PC, ShifterOperand(LR));
+  __ bx(LR);
 }
 
 
@@ -1558,7 +1591,7 @@
   } else {
     __ LoadImmediate(R0, 0x80000000);
   }
-  __ mov(PC, ShifterOperand(LR));
+  __ bx(LR);
 }
 
 
@@ -1575,7 +1608,7 @@
   __ LoadImmediate(R1, -9);
   __ muls(R2, R0, R1);
   __ mov(R0, ShifterOperand(42), MI);
-  __ mov(PC, ShifterOperand(LR));
+  __ bx(LR);
 }
 
 
diff --git a/runtime/vm/assembler_ia32.cc b/runtime/vm/assembler_ia32.cc
index 7442edc..3b35560 100644
--- a/runtime/vm/assembler_ia32.cc
+++ b/runtime/vm/assembler_ia32.cc
@@ -1271,6 +1271,13 @@
 }
 
 
+void Assembler::andl(Register dst, const Address& address) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0x23);
+  EmitOperand(dst, address);
+}
+
+
 void Assembler::orl(Register dst, Register src) {
   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
   EmitUint8(0x0B);
@@ -1284,6 +1291,13 @@
 }
 
 
+void Assembler::orl(Register dst, const Address& address) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0x0B);
+  EmitOperand(dst, address);
+}
+
+
 void Assembler::xorl(Register dst, Register src) {
   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
   EmitUint8(0x33);
@@ -1297,6 +1311,13 @@
 }
 
 
+void Assembler::xorl(Register dst, const Address& address) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0x33);
+  EmitOperand(dst, address);
+}
+
+
 void Assembler::addl(Register reg, const Immediate& imm) {
   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
   EmitComplex(0, Operand(reg), imm);
diff --git a/runtime/vm/assembler_ia32.h b/runtime/vm/assembler_ia32.h
index e9c6148..7ed62a8 100644
--- a/runtime/vm/assembler_ia32.h
+++ b/runtime/vm/assembler_ia32.h
@@ -514,12 +514,15 @@
 
   void andl(Register dst, const Immediate& imm);
   void andl(Register dst, Register src);
+  void andl(Register dst, const Address& address);
 
   void orl(Register dst, const Immediate& imm);
   void orl(Register dst, Register src);
+  void orl(Register dst, const Address& address);
 
   void xorl(Register dst, const Immediate& imm);
   void xorl(Register dst, Register src);
+  void xorl(Register dst, const Address& address);
 
   void addl(Register dst, Register src);
   void addl(Register reg, const Immediate& imm);
diff --git a/runtime/vm/assembler_ia32_test.cc b/runtime/vm/assembler_ia32_test.cc
index bada450..cfc7981 100644
--- a/runtime/vm/assembler_ia32_test.cc
+++ b/runtime/vm/assembler_ia32_test.cc
@@ -340,14 +340,23 @@
 ASSEMBLER_TEST_GENERATE(Bitwise, assembler) {
   __ movl(ECX, Immediate(42));
   __ xorl(ECX, ECX);
-  __ orl(ECX, Immediate(256));
-  __ movl(EAX, Immediate(4));
-  __ orl(ECX, EAX);
+  __ orl(ECX, Immediate(0x100));
+  __ movl(EAX, Immediate(0x648));
+  __ orl(ECX, EAX);  // 0x748.
   __ movl(EAX, Immediate(0xfff0));
-  __ andl(ECX, EAX);
+  __ andl(ECX, EAX);  // 0x740.
+  __ pushl(Immediate(0xF6FF));
+  __ andl(ECX, Address(ESP, 0));  // 0x640.
+  __ popl(EAX);  // Discard.
   __ movl(EAX, Immediate(1));
-  __ orl(ECX, EAX);
-  __ xorl(ECX, Immediate(0));
+  __ orl(ECX, EAX);  // 0x641.
+  __ pushl(Immediate(0x7));
+  __ orl(ECX, Address(ESP, 0));  // 0x647.
+  __ popl(EAX);  // Discard.
+  __ xorl(ECX, Immediate(0));  // 0x647.
+  __ pushl(Immediate(0x1C));
+  __ xorl(ECX, Address(ESP, 0));  // 0x65B.
+  __ popl(EAX);  // Discard.
   __ movl(EAX, ECX);
   __ ret();
 }
@@ -355,7 +364,7 @@
 
 ASSEMBLER_TEST_RUN(Bitwise, test) {
   typedef int (*Bitwise)();
-  EXPECT_EQ(256 + 1, reinterpret_cast<Bitwise>(test->entry())());
+  EXPECT_EQ(0x65B, reinterpret_cast<Bitwise>(test->entry())());
 }
 
 
diff --git a/runtime/vm/assembler_mips.cc b/runtime/vm/assembler_mips.cc
index 3f496db..200e777 100644
--- a/runtime/vm/assembler_mips.cc
+++ b/runtime/vm/assembler_mips.cc
@@ -204,10 +204,14 @@
 }
 
 
-void Assembler::CompareObject(Register rd, Register rn, const Object& object) {
+void Assembler::CompareObject(Register rd1, Register rd2,
+                              Register rn, const Object& object) {
   ASSERT(rn != TMP1);
+  ASSERT(rd1 != TMP1);
+  ASSERT(rd1 != rd2);
   LoadObject(TMP1, object);
-  subu(rd, rn, TMP1);
+  slt(rd1, rn, TMP1);
+  slt(rd2, TMP1, rn);
 }
 
 
diff --git a/runtime/vm/assembler_mips.h b/runtime/vm/assembler_mips.h
index d496837..c48f1bd 100644
--- a/runtime/vm/assembler_mips.h
+++ b/runtime/vm/assembler_mips.h
@@ -230,10 +230,11 @@
   }
 
   // CPU instructions in alphabetical order.
-  void addd(FRegister fd, FRegister fs, FRegister ft) {
-    ASSERT(EvenFPURegister(fd));
-    ASSERT(EvenFPURegister(fs));
-    ASSERT(EvenFPURegister(ft));
+  void addd(DRegister dd, DRegister ds, DRegister dt) {
+    // DRegisters start at the even FRegisters.
+    FRegister fd = static_cast<FRegister>(dd * 2);
+    FRegister fs = static_cast<FRegister>(ds * 2);
+    FRegister ft = static_cast<FRegister>(dt * 2);
     EmitFpuRType(COP1, FMT_D, ft, fs, fd, COP1_ADD);
   }
 
@@ -378,58 +379,58 @@
   }
 
   // FPU compare, always false.
-  void cfd(FRegister fs, FRegister ft) {
-    ASSERT(EvenFPURegister(fs));
-    ASSERT(EvenFPURegister(ft));
+  void cfd(DRegister ds, DRegister dt) {
+    FRegister fs = static_cast<FRegister>(ds * 2);
+    FRegister ft = static_cast<FRegister>(dt * 2);
     EmitFpuRType(COP1, FMT_D, ft, fs, F0, COP1_C_F);
   }
 
   // FPU compare, true if unordered, i.e. one is NaN.
-  void cund(FRegister fs, FRegister ft) {
-    ASSERT(EvenFPURegister(fs));
-    ASSERT(EvenFPURegister(ft));
+  void cund(DRegister ds, DRegister dt) {
+    FRegister fs = static_cast<FRegister>(ds * 2);
+    FRegister ft = static_cast<FRegister>(dt * 2);
     EmitFpuRType(COP1, FMT_D, ft, fs, F0, COP1_C_UN);
   }
 
   // FPU compare, true if equal.
-  void ceqd(FRegister fs, FRegister ft) {
-    ASSERT(EvenFPURegister(fs));
-    ASSERT(EvenFPURegister(ft));
+  void ceqd(DRegister ds, DRegister dt) {
+    FRegister fs = static_cast<FRegister>(ds * 2);
+    FRegister ft = static_cast<FRegister>(dt * 2);
     EmitFpuRType(COP1, FMT_D, ft, fs, F0, COP1_C_EQ);
   }
 
   // FPU compare, true if unordered or equal.
-  void cueqd(FRegister fs, FRegister ft) {
-    ASSERT(EvenFPURegister(fs));
-    ASSERT(EvenFPURegister(ft));
+  void cueqd(DRegister ds, DRegister dt) {
+    FRegister fs = static_cast<FRegister>(ds * 2);
+    FRegister ft = static_cast<FRegister>(dt * 2);
     EmitFpuRType(COP1, FMT_D, ft, fs, F0, COP1_C_UEQ);
   }
 
   // FPU compare, true if less than.
-  void coltd(FRegister fs, FRegister ft) {
-    ASSERT(EvenFPURegister(fs));
-    ASSERT(EvenFPURegister(ft));
+  void coltd(DRegister ds, DRegister dt) {
+    FRegister fs = static_cast<FRegister>(ds * 2);
+    FRegister ft = static_cast<FRegister>(dt * 2);
     EmitFpuRType(COP1, FMT_D, ft, fs, F0, COP1_C_OLT);
   }
 
   // FPU compare, true if unordered or less than.
-  void cultd(FRegister fs, FRegister ft) {
-    ASSERT(EvenFPURegister(fs));
-    ASSERT(EvenFPURegister(ft));
+  void cultd(DRegister ds, DRegister dt) {
+    FRegister fs = static_cast<FRegister>(ds * 2);
+    FRegister ft = static_cast<FRegister>(dt * 2);
     EmitFpuRType(COP1, FMT_D, ft, fs, F0, COP1_C_ULT);
   }
 
   // FPU compare, true if less or equal.
-  void coled(FRegister fs, FRegister ft) {
-    ASSERT(EvenFPURegister(fs));
-    ASSERT(EvenFPURegister(ft));
+  void coled(DRegister ds, DRegister dt) {
+    FRegister fs = static_cast<FRegister>(ds * 2);
+    FRegister ft = static_cast<FRegister>(dt * 2);
     EmitFpuRType(COP1, FMT_D, ft, fs, F0, COP1_C_OLE);
   }
 
   // FPU compare, true if unordered or less or equal.
-  void culed(FRegister fs, FRegister ft) {
-    ASSERT(EvenFPURegister(fs));
-    ASSERT(EvenFPURegister(ft));
+  void culed(DRegister ds, DRegister dt) {
+    FRegister fs = static_cast<FRegister>(ds * 2);
+    FRegister ft = static_cast<FRegister>(dt * 2);
     EmitFpuRType(COP1, FMT_D, ft, fs, F0, COP1_C_ULE);
   }
 
@@ -442,21 +443,20 @@
   }
 
   // Converts a 32-bit signed int in fs to a double in fd.
-  void cvtdw(FRegister fd, FRegister fs) {
-    ASSERT(EvenFPURegister(fd));
+  void cvtdw(DRegister dd, FRegister fs) {
+    FRegister fd = static_cast<FRegister>(dd * 2);
     EmitFpuRType(COP1, FMT_W, F0, fs, fd, COP1_CVT_D);
   }
 
   // Converts a 64-bit signed int in fs to a double in fd.
-  void cvtdl(FRegister fd, FRegister fs) {
-    ASSERT(EvenFPURegister(fs));
-    ASSERT(EvenFPURegister(fd));
+  void cvtdl(DRegister dd, DRegister ds) {
+    FRegister fs = static_cast<FRegister>(ds * 2);
+    FRegister fd = static_cast<FRegister>(dd * 2);
     EmitFpuRType(COP1, FMT_L, F0, fs, fd, COP1_CVT_D);
   }
 
-  void cvtwd(FRegister fd, FRegister fs) {
-    ASSERT(EvenFPURegister(fs));
-    ASSERT(EvenFPURegister(fd));
+  void cvtwd(FRegister fd, DRegister ds) {
+    FRegister fs = static_cast<FRegister>(ds * 2);
     EmitFpuRType(COP1, FMT_D, F0, fs, fd, COP1_CVT_W);
   }
 
@@ -464,10 +464,10 @@
     EmitRType(SPECIAL, rs, rt, R0, 0, DIV);
   }
 
-  void divd(FRegister fd, FRegister fs, FRegister ft) {
-    ASSERT(EvenFPURegister(fd));
-    ASSERT(EvenFPURegister(fs));
-    ASSERT(EvenFPURegister(ft));
+  void divd(DRegister dd, DRegister ds, DRegister dt) {
+    FRegister fd = static_cast<FRegister>(dd * 2);
+    FRegister fs = static_cast<FRegister>(ds * 2);
+    FRegister ft = static_cast<FRegister>(dt * 2);
     EmitFpuRType(COP1, FMT_D, ft, fs, fd, COP1_DIV);
   }
 
@@ -496,8 +496,8 @@
     EmitLoadStore(LBU, rt, addr);
   }
 
-  void ldc1(FRegister ft, const Address& addr) {
-    ASSERT(EvenFPURegister(ft));
+  void ldc1(DRegister dt, const Address& addr) {
+    FRegister ft = static_cast<FRegister>(dt * 2);
     EmitFpuLoadStore(LDC1, ft, addr);
   }
 
@@ -542,9 +542,9 @@
     or_(rd, rs, ZR);
   }
 
-  void movd(FRegister fd, FRegister fs) {
-    ASSERT(EvenFPURegister(fd));
-    ASSERT(EvenFPURegister(fs));
+  void movd(DRegister dd, DRegister ds) {
+    FRegister fd = static_cast<FRegister>(dd * 2);
+    FRegister fs = static_cast<FRegister>(ds * 2);
     EmitFpuRType(COP1, FMT_D, F0, fs, fd, COP1_MOV);
   }
 
@@ -567,10 +567,10 @@
          fs << kFsShift);
   }
 
-  void muld(FRegister fd, FRegister fs, FRegister ft) {
-    ASSERT(EvenFPURegister(fd));
-    ASSERT(EvenFPURegister(fs));
-    ASSERT(EvenFPURegister(ft));
+  void muld(DRegister dd, DRegister ds, DRegister dt) {
+    FRegister fd = static_cast<FRegister>(dd * 2);
+    FRegister fs = static_cast<FRegister>(ds * 2);
+    FRegister ft = static_cast<FRegister>(dt * 2);
     EmitFpuRType(COP1, FMT_D, ft, fs, fd, COP1_MUL);
   }
 
@@ -604,8 +604,8 @@
     EmitLoadStore(SB, rt, addr);
   }
 
-  void sdc1(FRegister ft, const Address& addr) {
-    ASSERT(EvenFPURegister(ft));
+  void sdc1(DRegister dt, const Address& addr) {
+    FRegister ft = static_cast<FRegister>(dt * 2);
     EmitFpuLoadStore(SDC1, ft, addr);
   }
 
@@ -625,13 +625,25 @@
     EmitRType(SPECIAL, rs, rt, rd, 0, SLT);
   }
 
+  void slti(Register rt, Register rs, const Immediate& imm) {
+    ASSERT(Utils::IsInt(kImmBits, imm.value()));
+    int16_t imm_value = static_cast<int16_t>(imm.value());
+    EmitIType(SLTI, rs, rt, imm_value);
+  }
+
+  void sltiu(Register rt, Register rs, const Immediate& imm) {
+    ASSERT(Utils::IsUint(kImmBits, imm.value()));
+    uint16_t imm_value = static_cast<uint16_t>(imm.value());
+    EmitIType(SLTIU, rs, rt, imm_value);
+  }
+
   void sltu(Register rd, Register rs, Register rt) {
     EmitRType(SPECIAL, rs, rt, rd, 0, SLTU);
   }
 
-  void sqrtd(FRegister fd, FRegister fs) {
-    ASSERT(EvenFPURegister(fd));
-    ASSERT(EvenFPURegister(fs));
+  void sqrtd(DRegister dd, DRegister ds) {
+    FRegister fd = static_cast<FRegister>(dd * 2);
+    FRegister fs = static_cast<FRegister>(ds * 2);
     EmitFpuRType(COP1, FMT_D, F0, fs, fd, COP1_SQRT);
   }
 
@@ -651,10 +663,10 @@
     EmitRType(SPECIAL, rs, rt, rd, 0, SRLV);
   }
 
-  void subd(FRegister fd, FRegister fs, FRegister ft) {
-    ASSERT(EvenFPURegister(fd));
-    ASSERT(EvenFPURegister(fs));
-    ASSERT(EvenFPURegister(ft));
+  void subd(DRegister dd, DRegister ds, DRegister dt) {
+    FRegister fd = static_cast<FRegister>(dd * 2);
+    FRegister fs = static_cast<FRegister>(ds * 2);
+    FRegister ft = static_cast<FRegister>(dt * 2);
     EmitFpuRType(COP1, FMT_D, ft, fs, fd, COP1_SUB);
   }
 
@@ -760,23 +772,23 @@
     }
   }
 
-  void LoadImmediate(FRegister rd, double value) {
-    ASSERT(EvenFPURegister(rd));
+  void LoadImmediate(DRegister rd, double value) {
+    FRegister frd = static_cast<FRegister>(rd * 2);
     const int64_t ival = bit_cast<uint64_t, double>(value);
     const int32_t low = Utils::Low32Bits(ival);
     const int32_t high = Utils::High32Bits(ival);
     if (low != 0) {
       LoadImmediate(TMP1, low);
-      mtc1(TMP1, rd);
+      mtc1(TMP1, frd);
     } else {
-      mtc1(ZR, rd);
+      mtc1(ZR, frd);
     }
 
     if (high != 0) {
       LoadImmediate(TMP1, high);
-      mtc1(TMP1, static_cast<FRegister>(rd + 1));
+      mtc1(TMP1, static_cast<FRegister>(frd + 1));
     } else {
-      mtc1(ZR, static_cast<FRegister>(rd + 1));
+      mtc1(ZR, static_cast<FRegister>(frd + 1));
     }
   }
 
@@ -853,8 +865,13 @@
   }
 
   void BranchSignedGreaterEqual(Register rd, int32_t value, Label* l) {
-    LoadImmediate(CMPRES, value);
-    BranchSignedGreaterEqual(rd, CMPRES, l);
+    if (Utils::IsInt(kImmBits, value)) {
+      slti(CMPRES, rd, Immediate(value));
+      beq(CMPRES, ZR, l);
+    } else {
+      LoadImmediate(CMPRES, value);
+      BranchSignedGreaterEqual(rd, CMPRES, l);
+    }
   }
 
   void BranchUnsignedGreaterEqual(Register rd, Register rs, Label* l) {
@@ -863,8 +880,13 @@
   }
 
   void BranchUnsignedGreaterEqual(Register rd, int32_t value, Label* l) {
-    LoadImmediate(CMPRES, value);
-    BranchUnsignedGreaterEqual(rd, CMPRES, l);
+    if (Utils::IsUint(kImmBits, value)) {
+      sltiu(CMPRES, rd, Immediate(value));
+      beq(CMPRES, ZR, l);
+    } else {
+      LoadImmediate(CMPRES, value);
+      BranchUnsignedGreaterEqual(rd, CMPRES, l);
+    }
   }
 
   void BranchSignedLess(Register rd, Register rs, Label* l) {
@@ -872,8 +894,13 @@
   }
 
   void BranchSignedLess(Register rd, int32_t value, Label* l) {
-    LoadImmediate(CMPRES, value);
-    BranchSignedGreater(CMPRES, rd, l);
+    if (Utils::IsInt(kImmBits, value)) {
+      slti(CMPRES, rd, Immediate(value));
+      bne(CMPRES, ZR, l);
+    } else {
+      LoadImmediate(CMPRES, value);
+      BranchSignedGreater(CMPRES, rd, l);
+    }
   }
 
   void BranchUnsignedLess(Register rd, Register rs, Label* l) {
@@ -881,8 +908,13 @@
   }
 
   void BranchUnsignedLess(Register rd, int32_t value, Label* l) {
-    LoadImmediate(CMPRES, value);
-    BranchUnsignedGreater(CMPRES, rd, l);
+    if (Utils::IsUint(kImmBits, value)) {
+      sltiu(CMPRES, rd, Immediate(value));
+      bne(CMPRES, ZR, l);
+    } else {
+      LoadImmediate(CMPRES, value);
+      BranchUnsignedGreater(CMPRES, rd, l);
+    }
   }
 
   void BranchSignedLessEqual(Register rd, Register rs, Label* l) {
@@ -937,9 +969,11 @@
   void LoadObject(Register rd, const Object& object);
   void PushObject(const Object& object);
 
-  // Sets register rd to zero if the object is equal to register rn,
-  // sets it to non-zero otherwise.
-  void CompareObject(Register rd, Register rn, const Object& object);
+  // Compares rn with the object. Returns results in rd1 and rd2.
+  // rd1 is 1 if rn < object. rd2 is 1 if object < rn. Since both cannot be
+  // 1, rd1 == rd2 (== 0) iff rn == object.
+  void CompareObject(Register rd1, Register rd2,
+                     Register rn, const Object& object);
 
   void LoadClassId(Register result, Register object);
   void LoadClassById(Register result, Register class_id);
@@ -993,10 +1027,6 @@
 
   GrowableArray<CodeComment*> comments_;
 
-  bool EvenFPURegister(FRegister reg) {
-    return (static_cast<int>(reg) & 1) == 0;
-  }
-
   void Emit(int32_t value) {
     // Emitting an instruction clears the delay slot state.
     in_delay_slot_ = false;
diff --git a/runtime/vm/assembler_mips_test.cc b/runtime/vm/assembler_mips_test.cc
index 1dc7d33..445ab8e 100644
--- a/runtime/vm/assembler_mips_test.cc
+++ b/runtime/vm/assembler_mips_test.cc
@@ -1186,9 +1186,9 @@
 
 
 ASSEMBLER_TEST_GENERATE(Addd, assembler) {
-  __ LoadImmediate(F0, 1.0);
-  __ LoadImmediate(F2, 2.0);
-  __ addd(F4, F0, F2);
+  __ LoadImmediate(D0, 1.0);
+  __ LoadImmediate(D1, 2.0);
+  __ addd(D2, D0, D1);
   __ mfc1(V0, F4);
   __ mfc1(V1, F5);
   __ Ret();
@@ -1204,8 +1204,8 @@
 
 
 ASSEMBLER_TEST_GENERATE(Movd, assembler) {
-  __ LoadImmediate(F0, 1.0);
-  __ movd(F2, F0);
+  __ LoadImmediate(D0, 1.0);
+  __ movd(D1, D0);
   __ mfc1(V0, F2);
   __ mfc1(V1, F3);
   __ Ret();
@@ -1224,9 +1224,9 @@
   __ AddImmediate(SP, -8 * kWordSize);
   __ LoadImmediate(T1, ~(8 - 1));
   __ and_(T0, SP, T1);  // Need 8 byte alignment.
-  __ LoadImmediate(F0, 1.0);
-  __ sdc1(F0, Address(T0));
-  __ ldc1(F2, Address(T0));
+  __ LoadImmediate(D0, 1.0);
+  __ sdc1(D0, Address(T0));
+  __ ldc1(D1, Address(T0));
   __ mfc1(V0, F2);
   __ mfc1(V1, F3);
   __ Ret();
@@ -1242,12 +1242,12 @@
 
 
 ASSEMBLER_TEST_GENERATE(Addd_NaN, assembler) {
-  __ LoadImmediate(F0, 1.0);
+  __ LoadImmediate(D0, 1.0);
   // Double non-signaling NaN is 0x7FF8000000000000.
   __ LoadImmediate(T0, 0x7FF80000);
   __ mtc1(ZR, F2);  // Load upper bits of NaN.
   __ mtc1(T0, F3);  // Load lower bits of NaN.
-  __ addd(F4, F0, F2);
+  __ addd(D2, D0, D1);
   __ mfc1(V0, F4);
   __ mfc1(V1, F5);
   __ Ret();
@@ -1263,11 +1263,11 @@
 
 
 ASSEMBLER_TEST_GENERATE(Addd_Inf, assembler) {
-  __ LoadImmediate(F0, 1.0f);
+  __ LoadImmediate(D0, 1.0);
   __ LoadImmediate(T0, 0x7FF00000);  // +inf
   __ mtc1(ZR, F2);
   __ mtc1(T0, F3);
-  __ addd(F4, F0, F2);
+  __ addd(D2, D0, D1);
   __ mfc1(V0, F4);
   __ mfc1(V1, F5);
   __ Ret();
@@ -1283,9 +1283,9 @@
 
 
 ASSEMBLER_TEST_GENERATE(Subd, assembler) {
-  __ LoadImmediate(F0, 2.5);
-  __ LoadImmediate(F2, 1.5);
-  __ subd(F4, F0, F2);
+  __ LoadImmediate(D0, 2.5);
+  __ LoadImmediate(D1, 1.5);
+  __ subd(D2, D0, D1);
   __ mfc1(V0, F4);
   __ mfc1(V1, F5);
   __ Ret();
@@ -1301,9 +1301,9 @@
 
 
 ASSEMBLER_TEST_GENERATE(Muld, assembler) {
-  __ LoadImmediate(F0, 6.0);
-  __ LoadImmediate(F2, 7.0);
-  __ muld(F4, F0, F2);
+  __ LoadImmediate(D0, 6.0);
+  __ LoadImmediate(D1, 7.0);
+  __ muld(D2, D0, D1);
   __ mfc1(V0, F4);
   __ mfc1(V1, F5);
   __ Ret();
@@ -1319,9 +1319,9 @@
 
 
 ASSEMBLER_TEST_GENERATE(Divd, assembler) {
-  __ LoadImmediate(F0, 42.0);
-  __ LoadImmediate(F2, 7.0);
-  __ divd(F4, F0, F2);
+  __ LoadImmediate(D0, 42.0);
+  __ LoadImmediate(D1, 7.0);
+  __ divd(D2, D0, D1);
   __ mfc1(V0, F4);
   __ mfc1(V1, F5);
   __ Ret();
@@ -1337,8 +1337,8 @@
 
 
 ASSEMBLER_TEST_GENERATE(Sqrtd, assembler) {
-  __ LoadImmediate(F0, 36.0);
-  __ sqrtd(F4, F0);
+  __ LoadImmediate(D0, 36.0);
+  __ sqrtd(D2, D0);
   __ mfc1(V0, F4);
   __ mfc1(V1, F5);
   __ Ret();
@@ -1356,12 +1356,12 @@
 ASSEMBLER_TEST_GENERATE(Cop1CUN, assembler) {
   Label is_true;
 
-  __ LoadImmediate(F0, 42.0);
+  __ LoadImmediate(D0, 42.0);
   __ LoadImmediate(T0, 0x7FF80000);
   __ mtc1(ZR, F2);
   __ mtc1(T0, F3);
   __ LoadImmediate(V0, 42);
-  __ cund(F0, F2);
+  __ cund(D0, D1);
   __ bc1t(&is_true);
   __ mov(V0, ZR);
   __ Bind(&is_true);
@@ -1378,10 +1378,10 @@
 ASSEMBLER_TEST_GENERATE(Cop1CUN_not_taken, assembler) {
   Label is_true;
 
-  __ LoadImmediate(F0, 42.0);
-  __ LoadImmediate(F2, 42.0);
+  __ LoadImmediate(D0, 42.0);
+  __ LoadImmediate(D1, 42.0);
   __ LoadImmediate(V0, 42);
-  __ cund(F0, F2);
+  __ cund(D0, D1);
   __ bc1t(&is_true);
   __ mov(V0, ZR);
   __ Bind(&is_true);
@@ -1398,10 +1398,10 @@
 ASSEMBLER_TEST_GENERATE(Cop1CEq, assembler) {
   Label is_true;
 
-  __ LoadImmediate(F0, 42.5);
-  __ LoadImmediate(F2, 42.5);
+  __ LoadImmediate(D0, 42.5);
+  __ LoadImmediate(D1, 42.5);
   __ LoadImmediate(V0, 42);
-  __ ceqd(F0, F2);
+  __ ceqd(D0, D1);
   __ bc1t(&is_true);
   __ mov(V0, ZR);
   __ Bind(&is_true);
@@ -1418,10 +1418,10 @@
 ASSEMBLER_TEST_GENERATE(Cop1CEq_not_taken, assembler) {
   Label is_true;
 
-  __ LoadImmediate(F0, 42.0);
-  __ LoadImmediate(F2, 42.5);
+  __ LoadImmediate(D0, 42.0);
+  __ LoadImmediate(D1, 42.5);
   __ LoadImmediate(V0, 42);
-  __ ceqd(F0, F2);
+  __ ceqd(D0, D1);
   __ bc1t(&is_true);
   __ mov(V0, ZR);
   __ Bind(&is_true);
@@ -1438,10 +1438,10 @@
 ASSEMBLER_TEST_GENERATE(Cop1CEq_false, assembler) {
   Label is_true;
 
-  __ LoadImmediate(F0, 42.0);
-  __ LoadImmediate(F2, 42.5);
+  __ LoadImmediate(D0, 42.0);
+  __ LoadImmediate(D1, 42.5);
   __ LoadImmediate(V0, 42);
-  __ ceqd(F0, F2);
+  __ ceqd(D0, D1);
   __ bc1f(&is_true);
   __ mov(V0, ZR);
   __ Bind(&is_true);
@@ -1458,10 +1458,10 @@
 ASSEMBLER_TEST_GENERATE(Cop1CEq_false_not_taken, assembler) {
   Label is_true;
 
-  __ LoadImmediate(F0, 42.5);
-  __ LoadImmediate(F2, 42.5);
+  __ LoadImmediate(D0, 42.5);
+  __ LoadImmediate(D1, 42.5);
   __ LoadImmediate(V0, 42);
-  __ ceqd(F0, F2);
+  __ ceqd(D0, D1);
   __ bc1f(&is_true);
   __ mov(V0, ZR);
   __ Bind(&is_true);
@@ -1478,10 +1478,10 @@
 ASSEMBLER_TEST_GENERATE(Cop1COLT, assembler) {
   Label is_true;
 
-  __ LoadImmediate(F0, 42.0);
-  __ LoadImmediate(F2, 42.5);
+  __ LoadImmediate(D0, 42.0);
+  __ LoadImmediate(D1, 42.5);
   __ LoadImmediate(V0, 42);
-  __ coltd(F0, F2);
+  __ coltd(D0, D1);
   __ bc1t(&is_true);
   __ mov(V0, ZR);
   __ Bind(&is_true);
@@ -1498,10 +1498,10 @@
 ASSEMBLER_TEST_GENERATE(Cop1COLT_not_taken, assembler) {
   Label is_true;
 
-  __ LoadImmediate(F0, 42.5);
-  __ LoadImmediate(F2, 42.0);
+  __ LoadImmediate(D0, 42.5);
+  __ LoadImmediate(D1, 42.0);
   __ LoadImmediate(V0, 42);
-  __ coltd(F0, F2);
+  __ coltd(D0, D1);
   __ bc1t(&is_true);
   __ mov(V0, ZR);
   __ Bind(&is_true);
@@ -1518,10 +1518,10 @@
 ASSEMBLER_TEST_GENERATE(Cop1COLE, assembler) {
   Label is_true;
 
-  __ LoadImmediate(F0, 42.0);
-  __ LoadImmediate(F2, 42.0);
+  __ LoadImmediate(D0, 42.0);
+  __ LoadImmediate(D1, 42.0);
   __ LoadImmediate(V0, 42);
-  __ coled(F0, F2);
+  __ coled(D0, D1);
   __ bc1t(&is_true);
   __ mov(V0, ZR);
   __ Bind(&is_true);
@@ -1538,10 +1538,10 @@
 ASSEMBLER_TEST_GENERATE(Cop1COLE_not_taken, assembler) {
   Label is_true;
 
-  __ LoadImmediate(F0, 42.5);
-  __ LoadImmediate(F2, 42.0);
+  __ LoadImmediate(D0, 42.5);
+  __ LoadImmediate(D1, 42.0);
   __ LoadImmediate(V0, 42);
-  __ coled(F0, F2);
+  __ coled(D0, D1);
   __ bc1t(&is_true);
   __ mov(V0, ZR);
   __ Bind(&is_true);
@@ -1558,7 +1558,7 @@
 ASSEMBLER_TEST_GENERATE(Cop1CvtDW, assembler) {
   __ LoadImmediate(T0, 42);
   __ mtc1(T0, F0);
-  __ cvtdw(F2, F0);
+  __ cvtdw(D1, F0);
   __ mfc1(V0, F2);
   __ mfc1(V1, F3);
   __ Ret();
@@ -1576,7 +1576,7 @@
 ASSEMBLER_TEST_GENERATE(Cop1CvtDW_neg, assembler) {
   __ LoadImmediate(T0, -42);
   __ mtc1(T0, F0);
-  __ cvtdw(F2, F0);
+  __ cvtdw(D1, F0);
   __ mfc1(V0, F2);
   __ mfc1(V1, F3);
   __ Ret();
@@ -1595,7 +1595,7 @@
   __ LoadImmediate(T0, 0x1);
   __ mtc1(ZR, F0);
   __ mtc1(T0, F1);  // D0 <- 0x100000000 = 4294967296
-  __ cvtdl(F2, F0);
+  __ cvtdl(D1, D0);
   __ mfc1(V0, F2);
   __ mfc1(V1, F3);
   __ Ret();
@@ -1614,7 +1614,7 @@
   __ LoadImmediate(T0, 0xffffffff);
   __ mtc1(T0, F0);
   __ mtc1(T0, F1);  // D0 <- 0xffffffffffffffff = -1
-  __ cvtdl(F2, F0);
+  __ cvtdl(D1, D0);
   __ mfc1(V0, F2);
   __ mfc1(V1, F3);
   __ Ret();
@@ -1630,8 +1630,8 @@
 
 
 ASSEMBLER_TEST_GENERATE(Cop1CvtWD, assembler) {
-  __ LoadImmediate(F0, 42.0);
-  __ cvtwd(F2, F0);
+  __ LoadImmediate(D0, 42.0);
+  __ cvtwd(F2, D0);
   __ mfc1(V0, F2);
   __ Ret();
 }
@@ -1645,8 +1645,8 @@
 
 
 ASSEMBLER_TEST_GENERATE(Cop1CvtWD_neg, assembler) {
-  __ LoadImmediate(F0, -42.0);
-  __ cvtwd(F2, F0);
+  __ LoadImmediate(D0, -42.0);
+  __ cvtwd(F2, D0);
   __ mfc1(V0, F2);
   __ Ret();
 }
diff --git a/runtime/vm/ast.cc b/runtime/vm/ast.cc
index 4ac570b..7f88189 100644
--- a/runtime/vm/ast.cc
+++ b/runtime/vm/ast.cc
@@ -329,9 +329,6 @@
   if (local().is_final()) {
     return NULL;
   }
-  if (HasPseudo()) {
-    return NULL;
-  }
   return new StoreLocalNode(token_pos(), &local(), rhs);
 }
 
diff --git a/runtime/vm/ast.h b/runtime/vm/ast.h
index 07e2314..c65f991 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(CommaNode, "comma")                                                        \
   V(CatchClauseNode, "catch clause block")                                     \
   V(TryCatchNode, "try catch block")                                           \
   V(ThrowNode, "throw")                                                        \
@@ -180,6 +181,35 @@
 };
 
 
+// Comma node represents a pair of expressions evaluated in sequence
+// and return the value of the second expression.
+class CommaNode : public AstNode {
+ public:
+  CommaNode(intptr_t token_pos,
+            AstNode* first,
+            AstNode* second)
+      : AstNode(token_pos),
+        first_(first),
+        second_(second) { }
+
+  AstNode* first() const { return first_; }
+  AstNode* second() const { return second_; }
+
+  void VisitChildren(AstNodeVisitor* visitor) const {
+    first_->Visit(visitor);
+    second_->Visit(visitor);
+  }
+
+  DECLARE_COMMON_NODE_FUNCTIONS(CommaNode);
+
+ private:
+  AstNode* first_;
+  AstNode* second_;
+
+  DISALLOW_COPY_AND_ASSIGN(CommaNode);
+};
+
+
 class CloneContextNode : public AstNode {
  public:
   explicit CloneContextNode(intptr_t token_pos)
@@ -962,29 +992,13 @@
 class LoadLocalNode : public AstNode {
  public:
   LoadLocalNode(intptr_t token_pos, const LocalVariable* local)
-      : AstNode(token_pos), local_(*local), pseudo_(NULL) {
-    ASSERT(local != NULL);
-  }
-
-  // A local variable load can optionally be a pair of an arbitrary 'pseudo'
-  // AST node followed by the load.  The pseudo node is evaluated for its
-  // side-effects and the value of the expression is the value of the local
-  // load after evaluating the pseudo node.  Pseudo nodes are used, e.g., in
-  // the desugaring of postincrement and cascade expressions.
-  LoadLocalNode(intptr_t token_pos, const LocalVariable* local, AstNode* pseudo)
-      : AstNode(token_pos), local_(*local), pseudo_(pseudo) {
+      : AstNode(token_pos), local_(*local) {
     ASSERT(local != NULL);
   }
 
   const LocalVariable& local() const { return local_; }
-  AstNode* pseudo() const { return pseudo_; }  // Can be NULL.
-  bool HasPseudo() const { return pseudo_ != NULL; }
 
-  virtual void VisitChildren(AstNodeVisitor* visitor) const {
-    if (HasPseudo()) {
-      pseudo()->Visit(visitor);
-    }
-  }
+  virtual void VisitChildren(AstNodeVisitor* visitor) const { }
 
   virtual const Instance* EvalConstExpr() const;
   virtual AstNode* MakeAssignmentNode(AstNode* rhs);
@@ -993,7 +1007,6 @@
 
  private:
   const LocalVariable& local_;
-  AstNode* pseudo_;
 
   DISALLOW_IMPLICIT_CONSTRUCTORS(LoadLocalNode);
 };
diff --git a/runtime/vm/ast_printer.cc b/runtime/vm/ast_printer.cc
index 0224c25..32bd0af8 100644
--- a/runtime/vm/ast_printer.cc
+++ b/runtime/vm/ast_printer.cc
@@ -38,6 +38,11 @@
 }
 
 
+void AstPrinter::VisitCommaNode(CommaNode* node) {
+  VisitGenericAstNode(node);
+}
+
+
 void AstPrinter::VisitCloneContextNode(CloneContextNode* node) {
   VisitGenericAstNode(node);
 }
diff --git a/runtime/vm/benchmark_test.cc b/runtime/vm/benchmark_test.cc
index 2b19ef5..3badf77 100644
--- a/runtime/vm/benchmark_test.cc
+++ b/runtime/vm/benchmark_test.cc
@@ -434,10 +434,8 @@
       "import 'dart:isolate';\n"
       "import 'dart:mirrors';\n"
       "import 'dart:typed_data';\n"
-      "import 'dart:uri';\n"
       "import 'dart:utf';\n"
       "import 'dart:json';\n"
-      "import 'dart:crypto';\n"
       "import 'dart:builtin';\n"
       "import 'dart:io';\n"
       "\n";
diff --git a/runtime/vm/bootstrap.cc b/runtime/vm/bootstrap.cc
index bdc5054..e174416 100644
--- a/runtime/vm/bootstrap.cc
+++ b/runtime/vm/bootstrap.cc
@@ -46,10 +46,6 @@
                _collection-dev,
                Bootstrap::collection_dev_source_paths_,
                Bootstrap::collection_dev_patch_paths_),
-  INIT_LIBRARY(ObjectStore::kCrypto,
-               crypto,
-               Bootstrap::crypto_source_paths_,
-               NULL),
   INIT_LIBRARY(ObjectStore::kIsolate,
                isolate,
                Bootstrap::isolate_source_paths_,
@@ -74,10 +70,6 @@
                utf,
                Bootstrap::utf_source_paths_,
                NULL),
-  INIT_LIBRARY(ObjectStore::kUri,
-               uri,
-               Bootstrap::uri_source_paths_,
-               NULL),
 
   { ObjectStore::kNone, NULL, NULL, NULL, NULL }
 };
diff --git a/runtime/vm/bootstrap.h b/runtime/vm/bootstrap.h
index d873541..843cf72 100644
--- a/runtime/vm/bootstrap.h
+++ b/runtime/vm/bootstrap.h
@@ -22,13 +22,11 @@
   static const char* corelib_source_paths_[];
   static const char* collection_source_paths_[];
   static const char* collection_dev_source_paths_[];
-  static const char* crypto_source_paths_[];
   static const char* isolate_source_paths_[];
   static const char* json_source_paths_[];
   static const char* math_source_paths_[];
   static const char* mirrors_source_paths_[];
   static const char* typed_data_source_paths_[];
-  static const char* uri_source_paths_[];
   static const char* utf_source_paths_[];
 
   // Source path mapping for patch URI and 'parts'.
diff --git a/runtime/vm/code_generator.cc b/runtime/vm/code_generator.cc
index ffc41a1..86ca5af 100644
--- a/runtime/vm/code_generator.cc
+++ b/runtime/vm/code_generator.cc
@@ -38,16 +38,8 @@
     "Trace IC miss in optimized code");
 DEFINE_FLAG(bool, trace_patching, false, "Trace patching of code.");
 DEFINE_FLAG(bool, trace_runtime_calls, false, "Trace runtime calls");
-#if defined(TARGET_ARCH_IA32) ||                                               \
-    defined(TARGET_ARCH_X64) ||                                                \
-    defined(TARGET_ARCH_ARM)
 DEFINE_FLAG(int, optimization_counter_threshold, 3000,
     "Function's usage-counter value before it is optimized, -1 means never");
-#else
-// TODO(regis): Enable optimization on MIPS.
-DEFINE_FLAG(int, optimization_counter_threshold, -1,
-    "Function's usage-counter value before it is optimized, -1 means never");
-#endif
 DECLARE_FLAG(bool, enable_type_checks);
 DECLARE_FLAG(bool, trace_type_checks);
 DECLARE_FLAG(bool, report_usage_count);
@@ -1548,7 +1540,7 @@
   ASSERT(!deopt_info.IsNull());
 
   CopyFrame(optimized_code, *caller_frame);
-  if (FLAG_trace_deoptimization) {
+  if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) {
     Function& function = Function::Handle(optimized_code.function());
     OS::PrintErr(
         "Deoptimizing (reason %"Pd" '%s') at pc %#"Px" '%s' (count %d)\n",
@@ -1714,7 +1706,7 @@
 
   // Since this is the only step where GC can occur during deoptimization,
   // use it to report the source line where deoptimization occured.
-  if (FLAG_trace_deoptimization) {
+  if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) {
     DartFrameIterator iterator;
     StackFrame* top_frame = iterator.NextFrame();
     ASSERT(top_frame != NULL);
diff --git a/runtime/vm/compiler.cc b/runtime/vm/compiler.cc
index 9785e38..c9b16a7 100644
--- a/runtime/vm/compiler.cc
+++ b/runtime/vm/compiler.cc
@@ -499,11 +499,7 @@
         }
 
         // If not yet present, allocate deoptimization history array.
-        Array& deopt_history = Array::Handle(function.deopt_history());
-        if (deopt_history.IsNull()) {
-          deopt_history = Array::New(FLAG_deoptimization_counter_threshold);
-          function.set_deopt_history(deopt_history);
-        }
+        function.EnsureDeoptHistory();
 
         for (intptr_t i = 0; i < guarded_fields.length(); i++) {
           const Field& field = *guarded_fields[i];
diff --git a/runtime/vm/constants_mips.h b/runtime/vm/constants_mips.h
index 32f608b..64a92c3 100644
--- a/runtime/vm/constants_mips.h
+++ b/runtime/vm/constants_mips.h
@@ -129,12 +129,38 @@
   kNoFRegister = -1,
 };
 
+// The double precision floating point registers are concatenated pairs of the
+// single precision registers, e.g. D0 is F1:F0, D1 is F3:F2, etc.. We only
+// tell the architecture generic code about the double precision registers, then
+// convert to the single precision registers when needed in the mips-specific
+// code.
+enum DRegister {
+  D0  =  0,
+  D1  =  1,
+  D2  =  2,
+  D3  =  3,
+  D4  =  4,
+  D5  =  5,
+  D6  =  6,
+  D7  =  7,
+  D8  =  8,
+  D9  =  9,
+  D10 = 10,
+  D11 = 11,
+  D12 = 12,
+  D13 = 13,
+  D14 = 14,
+  D15 = 15,
+  D16 = 16,
+  kNumberOfDRegisters = 16,
+  kNoDRegister = -1,
+};
 
 // Architecture independent aliases.
-typedef FRegister FpuRegister;
-const FpuRegister FpuTMP = F0;
-const int kNumberOfFpuRegisters = kNumberOfFRegisters;
-const FpuRegister kNoFpuRegister = kNoFRegister;
+typedef DRegister FpuRegister;
+const FpuRegister FpuTMP = D0;
+const int kNumberOfFpuRegisters = kNumberOfDRegisters;
+const FpuRegister kNoFpuRegister = kNoDRegister;
 
 
 // Register aliases.
diff --git a/runtime/vm/deopt_instructions.cc b/runtime/vm/deopt_instructions.cc
index 9c9dd24..8b37613 100644
--- a/runtime/vm/deopt_instructions.cc
+++ b/runtime/vm/deopt_instructions.cc
@@ -73,7 +73,8 @@
 // Deoptimization instruction moving value from optimized frame at
 // 'from_index' to specified slots in the unoptimized frame.
 // 'from_index' represents the slot index of the frame (0 being first argument)
-// and accounts for saved return address, frame pointer and pc marker.
+// and accounts for saved return address, frame pointer, pool pointer and pc
+// marker.
 class DeoptStackSlotInstr : public DeoptInstr {
  public:
   explicit DeoptStackSlotInstr(intptr_t from_index)
@@ -515,7 +516,7 @@
     // Increment the deoptimization counter. This effectively increments each
     // function occurring in the optimized frame.
     function.set_deoptimization_counter(function.deoptimization_counter() + 1);
-    if (FLAG_trace_deoptimization) {
+    if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) {
       OS::PrintErr("Deoptimizing %s (count %d)\n",
           function.ToFullyQualifiedCString(),
           function.deoptimization_counter());
@@ -863,7 +864,7 @@
 intptr_t DeoptInfoBuilder::CalculateStackIndex(const Location& from_loc) const {
   return from_loc.stack_index() < 0 ?
             from_loc.stack_index() + num_args_ :
-            from_loc.stack_index() + num_args_ - kFirstLocalSlotFromFp + 1;
+            from_loc.stack_index() + num_args_ + kDartFrameFixedSize;
 }
 
 
diff --git a/runtime/vm/disassembler_arm.cc b/runtime/vm/disassembler_arm.cc
index 8a7b5ea..dc1258e 100644
--- a/runtime/vm/disassembler_arm.cc
+++ b/runtime/vm/disassembler_arm.cc
@@ -643,6 +643,11 @@
             Format(instr, "smull'cond's 'rd, 'rn, 'rm, 'rs");
             break;
           }
+          case 7: {
+            // Registers rd_lo, rd_hi, rn, rm are encoded as rd, rn, rm, rs.
+            Format(instr, "smlal'cond's 'rd, 'rn, 'rm, 'rs");
+            break;
+          }
           default: {
             Unknown(instr);  // Not used.
             break;
diff --git a/runtime/vm/disassembler_mips.cc b/runtime/vm/disassembler_mips.cc
index 8c672b3..f6d7051 100644
--- a/runtime/vm/disassembler_mips.cc
+++ b/runtime/vm/disassembler_mips.cc
@@ -685,6 +685,14 @@
       Format(instr, "sb 'rt, 'imms('rs)");
       break;
     }
+    case SLTI: {
+      Format(instr, "slti 'rt, 'rs, 'imms");
+      break;
+    }
+    case SLTIU: {
+      Format(instr, "sltu 'rt, 'rs, 'immu");
+      break;
+    }
     case SH: {
       Format(instr, "sh 'rt, 'imms('rs)");
       break;
diff --git a/runtime/vm/flow_graph_builder.cc b/runtime/vm/flow_graph_builder.cc
index f0343db..0773a4f 100644
--- a/runtime/vm/flow_graph_builder.cc
+++ b/runtime/vm/flow_graph_builder.cc
@@ -2299,10 +2299,16 @@
       owner()->parsed_function().function().Owner());
   Value* instantiator_value =
       BuildInstantiatorTypeArguments(token_pos, instantiator_class, NULL);
-  return Bind(new InstantiateTypeArgumentsInstr(token_pos,
-                                                type_arguments,
-                                                instantiator_class,
-                                                instantiator_value));
+  const bool use_instantiator_type_args =
+      type_arguments.IsUninstantiatedIdentity() ||
+      type_arguments.CanShareInstantiatorTypeArguments(
+          instantiator_class);
+  return use_instantiator_type_args
+      ? instantiator_value
+      : Bind(new InstantiateTypeArgumentsInstr(token_pos,
+                                               type_arguments,
+                                               instantiator_class,
+                                               instantiator_value));
 }
 
 
@@ -2641,16 +2647,11 @@
 
 // <Expression> ::= LoadLocal { local: LocalVariable }
 void EffectGraphVisitor::VisitLoadLocalNode(LoadLocalNode* node) {
-  if (node->HasPseudo()) {
-    EffectGraphVisitor for_pseudo(owner(), temp_index());
-    node->pseudo()->Visit(&for_pseudo);
-    Append(for_pseudo);
-  }
+  // Nothing to do.
 }
 
 
 void ValueGraphVisitor::VisitLoadLocalNode(LoadLocalNode* node) {
-  EffectGraphVisitor::VisitLoadLocalNode(node);
   Definition* load = BuildLoadLocal(node->local());
   ReturnDefinition(load);
 }
@@ -3141,6 +3142,29 @@
 }
 
 
+void EffectGraphVisitor::VisitCommaNode(CommaNode* node) {
+  EffectGraphVisitor for_effect_first(owner(), temp_index());
+  node->first()->Visit(&for_effect_first);
+  Append(for_effect_first);
+
+  EffectGraphVisitor for_effect_second(owner(), temp_index());
+  node->second()->Visit(&for_effect_second);
+  Append(for_effect_second);
+}
+
+
+void ValueGraphVisitor::VisitCommaNode(CommaNode* node) {
+  EffectGraphVisitor for_effect(owner(), temp_index());
+  node->first()->Visit(&for_effect);
+  Append(for_effect);
+
+  ValueGraphVisitor for_value(owner(), temp_index());
+  node->second()->Visit(&for_value);
+  Append(for_value);
+  ReturnValue(for_value.value());
+}
+
+
 void EffectGraphVisitor::VisitTryCatchNode(TryCatchNode* node) {
   InlineBailout("EffectGraphVisitor::VisitTryCatchNode (exception)");
   intptr_t old_try_index = owner()->try_index();
diff --git a/runtime/vm/flow_graph_builder.h b/runtime/vm/flow_graph_builder.h
index 59a752d..9f613eb 100644
--- a/runtime/vm/flow_graph_builder.h
+++ b/runtime/vm/flow_graph_builder.h
@@ -400,6 +400,7 @@
   virtual void VisitStaticSetterNode(StaticSetterNode* node);
   virtual void VisitStoreStaticFieldNode(StoreStaticFieldNode* node);
   virtual void VisitTypeNode(TypeNode* node);
+  virtual void VisitCommaNode(CommaNode* node);
 
   Value* value() const { return value_; }
 
diff --git a/runtime/vm/flow_graph_compiler.h b/runtime/vm/flow_graph_compiler.h
index a5672d4..6dbcaa4 100644
--- a/runtime/vm/flow_graph_compiler.h
+++ b/runtime/vm/flow_graph_compiler.h
@@ -442,10 +442,6 @@
 
   bool may_reoptimize() const { return may_reoptimize_; }
 
-  static Condition FlipCondition(Condition condition);
-
-  static bool EvaluateCondition(Condition condition, intptr_t l, intptr_t r);
-
   // Array/list element address computations.
   static intptr_t DataOffsetFor(intptr_t cid);
   static intptr_t ElementSizeFor(intptr_t cid);
diff --git a/runtime/vm/flow_graph_compiler_arm.cc b/runtime/vm/flow_graph_compiler_arm.cc
index 686c7e0..c4317a9 100644
--- a/runtime/vm/flow_graph_compiler_arm.cc
+++ b/runtime/vm/flow_graph_compiler_arm.cc
@@ -708,12 +708,8 @@
       AddCurrentDescriptor(PcDescriptors::kDeopt,
                            assert->deopt_id(),
                            assert->token_pos());
-    } else if (instr->IsGuardField()) {
-      GuardFieldInstr* guard = instr->AsGuardField();
-      AddCurrentDescriptor(PcDescriptors::kDeopt,
-                           guard->deopt_id(),
-                           Scanner::kDummyTokenIndex);
-    } else if (instr->CanBeDeoptimizationTarget()) {
+    } else if (instr->IsGuardField() ||
+               instr->CanBecomeDeoptimizationTarget()) {
       AddCurrentDescriptor(PcDescriptors::kDeopt,
                            instr->deopt_id(),
                            Scanner::kDummyTokenIndex);
@@ -1290,7 +1286,65 @@
     intptr_t deopt_id,
     intptr_t token_pos,
     LocationSummary* locs) {
-  UNIMPLEMENTED();
+  MegamorphicCacheTable* table = Isolate::Current()->megamorphic_cache_table();
+  const String& name = String::Handle(ic_data.target_name());
+  const MegamorphicCache& cache =
+      MegamorphicCache::ZoneHandle(table->Lookup(name, arguments_descriptor));
+  Label not_smi, load_cache;
+  __ LoadFromOffset(kLoadWord, R0, SP, (argument_count - 1) * kWordSize);
+  __ tst(R0, ShifterOperand(kSmiTagMask));
+  __ b(&not_smi, NE);
+  __ mov(R0, ShifterOperand(Smi::RawValue(kSmiCid)));
+  __ b(&load_cache);
+
+  __ Bind(&not_smi);
+  __ LoadClassId(R0, R0);
+  __ SmiTag(R0);
+
+  // R0: class ID of the receiver (smi).
+  __ Bind(&load_cache);
+  __ LoadObject(R1, cache);
+  __ ldr(R2, FieldAddress(R1, MegamorphicCache::buckets_offset()));
+  __ ldr(R1, FieldAddress(R1, MegamorphicCache::mask_offset()));
+  // R2: cache buckets array.
+  // R1: mask.
+  __ mov(R3, ShifterOperand(R0));
+
+  Label loop, update, call_target_function;
+  __ b(&loop);
+
+  __ Bind(&update);
+  __ add(R3, R3, ShifterOperand(Smi::RawValue(1)));
+  __ Bind(&loop);
+  __ and_(R3, R3, ShifterOperand(R1));
+  const intptr_t base = Array::data_offset();
+  // R3 is smi tagged, but table entries are two words, so LSL 2.
+  __ add(IP, R2, ShifterOperand(R3, LSL, 2));
+  __ ldr(R4, FieldAddress(IP, base));
+
+  ASSERT(kIllegalCid == 0);
+  __ tst(R4, ShifterOperand(R4));
+  __ b(&call_target_function, EQ);
+  __ cmp(R4, ShifterOperand(R0));
+  __ b(&update, NE);
+
+  __ Bind(&call_target_function);
+  // Call the target found in the cache.  For a class id match, this is a
+  // proper target for the given name and arguments descriptor.  If the
+  // illegal class id was found, the target is a cache miss handler that can
+  // be invoked as a normal Dart function.
+  __ add(IP, R2, ShifterOperand(R3, LSL, 2));
+  __ ldr(R0, FieldAddress(IP, base + kWordSize));
+  __ ldr(R0, FieldAddress(R0, Function::code_offset()));
+  __ ldr(R0, FieldAddress(R0, Code::instructions_offset()));
+  __ LoadObject(R5, ic_data);
+  __ LoadObject(R4, arguments_descriptor);
+  __ AddImmediate(R0, Instructions::HeaderSize() - kHeapObjectTag);
+  __ blx(R0);
+  AddCurrentDescriptor(PcDescriptors::kOther, Isolate::kNoDeoptId, token_pos);
+  RecordSafepoint(locs);
+  AddDeoptIndexAtCall(Isolate::ToDeoptAfter(deopt_id), token_pos);
+  __ Drop(argument_count);
 }
 
 
@@ -1456,29 +1510,17 @@
 }
 
 
-Condition FlowGraphCompiler::FlipCondition(Condition condition) {
-  UNIMPLEMENTED();
-  return condition;
-}
-
-
-bool FlowGraphCompiler::EvaluateCondition(Condition condition,
-                                          intptr_t left,
-                                          intptr_t right) {
-  UNIMPLEMENTED();
-  return false;
-}
-
-
+// Do not impelement or use this function.
 FieldAddress FlowGraphCompiler::ElementAddressForIntIndex(intptr_t cid,
                                                           intptr_t index_scale,
                                                           Register array,
                                                           intptr_t index) {
-  UNIMPLEMENTED();
+  UNREACHABLE();
   return FieldAddress(array, index);
 }
 
 
+// Do not implement or use this function.
 FieldAddress FlowGraphCompiler::ElementAddressForRegIndex(intptr_t cid,
                                                           intptr_t index_scale,
                                                           Register array,
diff --git a/runtime/vm/flow_graph_compiler_ia32.cc b/runtime/vm/flow_graph_compiler_ia32.cc
index 593b42d..a42ed3b 100644
--- a/runtime/vm/flow_graph_compiler_ia32.cc
+++ b/runtime/vm/flow_graph_compiler_ia32.cc
@@ -727,12 +727,8 @@
       AddCurrentDescriptor(PcDescriptors::kDeopt,
                            assert->deopt_id(),
                            assert->token_pos());
-    } else if (instr->IsGuardField()) {
-      GuardFieldInstr* guard = instr->AsGuardField();
-      AddCurrentDescriptor(PcDescriptors::kDeopt,
-                           guard->deopt_id(),
-                           Scanner::kDummyTokenIndex);
-    } else if (instr->CanBeDeoptimizationTarget()) {
+    } else if (instr->IsGuardField() ||
+               instr->CanBecomeDeoptimizationTarget()) {
       AddCurrentDescriptor(PcDescriptors::kDeopt,
                            instr->deopt_id(),
                            Scanner::kDummyTokenIndex);
@@ -1653,48 +1649,6 @@
 }
 
 
-Condition FlowGraphCompiler::FlipCondition(Condition condition) {
-  switch (condition) {
-    case EQUAL:         return EQUAL;
-    case NOT_EQUAL:     return NOT_EQUAL;
-    case LESS:          return GREATER;
-    case LESS_EQUAL:    return GREATER_EQUAL;
-    case GREATER:       return LESS;
-    case GREATER_EQUAL: return LESS_EQUAL;
-    case BELOW:         return ABOVE;
-    case BELOW_EQUAL:   return ABOVE_EQUAL;
-    case ABOVE:         return BELOW;
-    case ABOVE_EQUAL:   return BELOW_EQUAL;
-    default:
-      UNIMPLEMENTED();
-      return EQUAL;
-  }
-}
-
-
-bool FlowGraphCompiler::EvaluateCondition(Condition condition,
-                                          intptr_t left,
-                                          intptr_t right) {
-  const uintptr_t unsigned_left = static_cast<uintptr_t>(left);
-  const uintptr_t unsigned_right = static_cast<uintptr_t>(right);
-  switch (condition) {
-    case EQUAL:         return left == right;
-    case NOT_EQUAL:     return left != right;
-    case LESS:          return left < right;
-    case LESS_EQUAL:    return left <= right;
-    case GREATER:       return left > right;
-    case GREATER_EQUAL: return left >= right;
-    case BELOW:         return unsigned_left < unsigned_right;
-    case BELOW_EQUAL:   return unsigned_left <= unsigned_right;
-    case ABOVE:         return unsigned_left > unsigned_right;
-    case ABOVE_EQUAL:   return unsigned_left >= unsigned_right;
-    default:
-      UNIMPLEMENTED();
-      return false;
-  }
-}
-
-
 FieldAddress FlowGraphCompiler::ElementAddressForIntIndex(intptr_t cid,
                                                           intptr_t index_scale,
                                                           Register array,
diff --git a/runtime/vm/flow_graph_compiler_mips.cc b/runtime/vm/flow_graph_compiler_mips.cc
index efcd64c..42d34aa 100644
--- a/runtime/vm/flow_graph_compiler_mips.cc
+++ b/runtime/vm/flow_graph_compiler_mips.cc
@@ -45,8 +45,96 @@
 
 RawDeoptInfo* CompilerDeoptInfo::CreateDeoptInfo(FlowGraphCompiler* compiler,
                                                  DeoptInfoBuilder* builder) {
-  UNIMPLEMENTED();  // TODO(regis): Copy ARM version.
-  return NULL;
+  if (deopt_env_ == NULL) return DeoptInfo::null();
+
+  intptr_t stack_height = compiler->StackSize();
+  AllocateIncomingParametersRecursive(deopt_env_, &stack_height);
+
+  intptr_t slot_ix = 0;
+  Environment* current = deopt_env_;
+
+  // Emit all kMaterializeObject instructions describing objects to be
+  // materialized on the deoptimization as a prefix to the deoptimization info.
+  EmitMaterializations(deopt_env_, builder);
+
+  // The real frame starts here.
+  builder->MarkFrameStart();
+
+  // Current PP, FP, and PC.
+  builder->AddPp(current->function(), slot_ix++);
+  builder->AddCallerFp(slot_ix++);
+  builder->AddReturnAddress(current->function(), deopt_id(), slot_ix++);
+
+  // Callee's PC marker is not used anymore. Pass Function::null() to set to 0.
+  builder->AddPcMarker(Function::Handle(), slot_ix++);
+
+  // Emit all values that are needed for materialization as a part of the
+  // expression stack for the bottom-most frame. This guarantees that GC
+  // will be able to find them during materialization.
+  slot_ix = builder->EmitMaterializationArguments(slot_ix);
+
+  // For the innermost environment, set outgoing arguments and the locals.
+  for (intptr_t i = current->Length() - 1;
+       i >= current->fixed_parameter_count();
+       i--) {
+    builder->AddCopy(current->ValueAt(i), current->LocationAt(i), slot_ix++);
+  }
+
+  Environment* previous = current;
+  current = current->outer();
+  while (current != NULL) {
+    // PP, FP, and PC.
+    builder->AddPp(current->function(), slot_ix++);
+    builder->AddCallerFp(slot_ix++);
+
+    // For any outer environment the deopt id is that of the call instruction
+    // which is recorded in the outer environment.
+    builder->AddReturnAddress(current->function(),
+                              Isolate::ToDeoptAfter(current->deopt_id()),
+                              slot_ix++);
+
+    // PC marker.
+    builder->AddPcMarker(previous->function(), slot_ix++);
+
+    // The values of outgoing arguments can be changed from the inlined call so
+    // we must read them from the previous environment.
+    for (intptr_t i = previous->fixed_parameter_count() - 1; i >= 0; i--) {
+      builder->AddCopy(previous->ValueAt(i),
+                       previous->LocationAt(i),
+                       slot_ix++);
+    }
+
+    // Set the locals, note that outgoing arguments are not in the environment.
+    for (intptr_t i = current->Length() - 1;
+         i >= current->fixed_parameter_count();
+         i--) {
+      builder->AddCopy(current->ValueAt(i),
+                       current->LocationAt(i),
+                       slot_ix++);
+    }
+
+    // Iterate on the outer environment.
+    previous = current;
+    current = current->outer();
+  }
+  // The previous pointer is now the outermost environment.
+  ASSERT(previous != NULL);
+
+  // For the outermost environment, set caller PC, caller PP, and caller FP.
+  builder->AddCallerPp(slot_ix++);
+  builder->AddCallerFp(slot_ix++);
+  builder->AddCallerPc(slot_ix++);
+
+  // PC marker.
+  builder->AddPcMarker(previous->function(), slot_ix++);
+
+  // For the outermost environment, set the incoming arguments.
+  for (intptr_t i = previous->fixed_parameter_count() - 1; i >= 0; i--) {
+    builder->AddCopy(previous->ValueAt(i), previous->LocationAt(i), slot_ix++);
+  }
+
+  const DeoptInfo& deopt_info = DeoptInfo::Handle(builder->CreateDeoptInfo());
+  return deopt_info.raw();
 }
 
 
@@ -78,8 +166,7 @@
                                            Label* is_false) {
   __ TraceSimMsg("BoolToJump");
   Label fall_through;
-  __ BranchEqual(bool_register, reinterpret_cast<intptr_t>(Object::null()),
-                 &fall_through);
+  __ beq(bool_register, NULLREG, &fall_through);
   __ BranchEqual(bool_register, Bool::True(), is_true);
   __ b(is_false);
   __ Bind(&fall_through);
@@ -101,19 +188,14 @@
   const SubtypeTestCache& type_test_cache =
       SubtypeTestCache::ZoneHandle(SubtypeTestCache::New());
   __ LoadObject(A2, type_test_cache);
-  intptr_t null = reinterpret_cast<intptr_t>(Object::null());
-  uint16_t null_lo = Utils::Low16Bits(null);
-  uint16_t null_hi = Utils::High16Bits(null);
   if (test_kind == kTestTypeOneArg) {
     ASSERT(type_arguments_reg == kNoRegister);
-    __ lui(A1, Immediate(null_hi));
     __ BranchLink(&StubCode::Subtype1TestCacheLabel());
-    __ delay_slot()->ori(A1, A1, Immediate(null_lo));
+    __ delay_slot()->mov(A1, NULLREG);
   } else if (test_kind == kTestTypeTwoArgs) {
     ASSERT(type_arguments_reg == kNoRegister);
-    __ lui(A1, Immediate(null_hi));
     __ BranchLink(&StubCode::Subtype2TestCacheLabel());
-    __ delay_slot()->ori(A1, A1, Immediate(null_lo));
+    __ delay_slot()->mov(A1, NULLREG);
   } else if (test_kind == kTestTypeThreeArgs) {
     ASSERT(type_arguments_reg == A1);
     __ BranchLink(&StubCode::Subtype3TestCacheLabel());
@@ -247,8 +329,7 @@
     // Check if instance is a closure.
     __ LoadClassById(T1, kClassIdReg);
     __ lw(T1, FieldAddress(T1, Class::signature_function_offset()));
-    __ BranchNotEqual(T1, reinterpret_cast<int32_t>(Object::null()),
-                      is_instance_lbl);
+    __ bne(T1, NULLREG, is_instance_lbl);
   }
   // Custom checking for numbers (Smi, Mint, Bigint and Double).
   // Note that instance is not Smi (checked above).
@@ -315,8 +396,7 @@
     __ lw(A1, Address(SP, 0));  // Get instantiator type arguments.
     // A1: instantiator type arguments.
     // Check if type argument is dynamic.
-    __ BranchEqual(A1, reinterpret_cast<intptr_t>(Object::null()),
-                   is_instance_lbl);
+    __ beq(A1, NULLREG, is_instance_lbl);
     // Can handle only type arguments that are instances of TypeArguments.
     // (runtime checks canonicalize type arguments).
     Label fall_through;
@@ -327,8 +407,7 @@
     // R2: concrete type of type.
     // Check if type argument is dynamic.
     __ BranchEqual(T2, Type::ZoneHandle(Type::DynamicType()), is_instance_lbl);
-    __ BranchEqual(T2, reinterpret_cast<intptr_t>(Object::null()),
-                   is_instance_lbl);
+    __ beq(T2, NULLREG, is_instance_lbl);
     const Type& object_type = Type::ZoneHandle(Type::ObjectType());
     __ BranchEqual(T2, object_type, is_instance_lbl);
 
@@ -487,7 +566,7 @@
 
   // A null object is always assignable and is returned as result.
   Label is_assignable, runtime_call;
-  __ BranchEqual(A0, reinterpret_cast<int32_t>(Object::null()), &is_assignable);
+  __ beq(A0, NULLREG, &is_assignable);
   __ delay_slot()->sw(A1, Address(SP, 0 * kWordSize));
 
   if (!FLAG_eliminate_type_checks) {
@@ -570,12 +649,8 @@
       AddCurrentDescriptor(PcDescriptors::kDeopt,
                            assert->deopt_id(),
                            assert->token_pos());
-    } else if (instr->IsGuardField()) {
-      GuardFieldInstr* guard = instr->AsGuardField();
-      AddCurrentDescriptor(PcDescriptors::kDeopt,
-                           guard->deopt_id(),
-                           Scanner::kDummyTokenIndex);
-    } else if (instr->CanBeDeoptimizationTarget()) {
+    } else if (instr->IsGuardField() ||
+               instr->CanBecomeDeoptimizationTarget()) {
       AddCurrentDescriptor(PcDescriptors::kDeopt,
                            instr->deopt_id(),
                            Scanner::kDummyTokenIndex);
@@ -726,8 +801,7 @@
     delete[] opt_param_position;
     // Check that T0 now points to the null terminator in the array descriptor.
     __ lw(T3, Address(T0));
-    __ BranchEqual(T3, reinterpret_cast<int32_t>(Object::null()),
-                   &all_arguments_processed);
+    __ beq(T3, NULLREG, &all_arguments_processed);
   } else {
     ASSERT(num_opt_pos_params > 0);
     __ lw(T2,
@@ -804,8 +878,6 @@
   // implicitly final, since garbage collecting the unmodified value is not
   // an issue anymore.
 
-  __ LoadImmediate(T0, reinterpret_cast<intptr_t>(Object::null()));
-
   // S4 : arguments descriptor array.
   __ lw(T2, FieldAddress(S4, ArgumentsDescriptor::count_offset()));
   __ sll(T2, T2, 1);  // T2 is a Smi.
@@ -818,7 +890,7 @@
   __ addiu(T2, T2, Immediate(-kWordSize));
   __ addu(T3, T1, T2);
   __ bgtz(T2, &null_args_loop);
-  __ delay_slot()->sw(T0, Address(T3));
+  __ delay_slot()->sw(NULLREG, Address(T3));
   __ Bind(&null_args_loop_exit);
 }
 
@@ -841,12 +913,8 @@
   __ lw(T0, Address(SP, 1 * kWordSize));  // Receiver.
   __ lw(T1, Address(SP, 0 * kWordSize));  // Value.
   __ StoreIntoObject(T0, FieldAddress(T0, offset), T1);
-  intptr_t null = reinterpret_cast<intptr_t>(Object::null());
-  uint16_t null_lo = Utils::Low16Bits(null);
-  uint16_t null_hi = Utils::High16Bits(null);
-  __ lui(V0, Immediate(null_hi));
   __ Ret();
-  __ delay_slot()->ori(V0, V0, Immediate(null_lo));
+  __ delay_slot()->mov(V0, NULLREG);
 }
 
 
@@ -1039,10 +1107,9 @@
     __ TraceSimMsg("Initialize spill slots");
     __ Comment("Initialize spill slots");
     const intptr_t slot_base = parsed_function().first_stack_local_index();
-    __ LoadImmediate(T0, reinterpret_cast<intptr_t>(Object::null()));
     for (intptr_t i = 0; i < num_locals; ++i) {
       // Subtract index i (locals lie at lower addresses than FP).
-      __ sw(T0, Address(FP, (slot_base - i) * kWordSize));
+      __ sw(NULLREG, Address(FP, (slot_base - i) * kWordSize));
     }
   }
 
@@ -1065,7 +1132,7 @@
   AddCurrentDescriptor(PcDescriptors::kPatchCode,
                        Isolate::kNoDeoptId,
                        0);  // No token position.
-  __ Branch(&StubCode::FixCallersTargetLabel());
+  __ BranchPatchable(&StubCode::FixCallersTargetLabel());
   AddCurrentDescriptor(PcDescriptors::kLazyDeoptJump,
                        Isolate::kNoDeoptId,
                        0);  // No token position.
@@ -1229,7 +1296,7 @@
     __ addiu(SP, SP, Immediate(2 * kWordSize));  // Discard constant.
     return;
   }
-  __ CompareObject(CMPRES, reg, obj);
+  __ CompareObject(CMPRES, TMP1, reg, obj);
 }
 
 
@@ -1252,7 +1319,8 @@
     __ lw(left, Address(SP, 1 * kWordSize));
     __ addiu(SP, SP, Immediate(2 * kWordSize));
   } else {
-    __ subu(CMPRES, left, right);
+    __ slt(CMPRES, left, right);
+    __ slt(TMP1, right, left);
   }
 }
 
@@ -1342,20 +1410,6 @@
 }
 
 
-Condition FlowGraphCompiler::FlipCondition(Condition condition) {
-  UNIMPLEMENTED();
-  return condition;
-}
-
-
-bool FlowGraphCompiler::EvaluateCondition(Condition condition,
-                                          intptr_t left,
-                                          intptr_t right) {
-  UNIMPLEMENTED();
-  return false;
-}
-
-
 FieldAddress FlowGraphCompiler::ElementAddressForIntIndex(intptr_t cid,
                                                           intptr_t index_scale,
                                                           Register array,
@@ -1482,7 +1536,7 @@
            source.IsQuadStackSlot());
     bool double_width = destination.IsDoubleStackSlot() ||
                         source.IsDoubleStackSlot();
-    FRegister reg = source.IsFpuRegister() ? source.fpu_reg()
+    DRegister reg = source.IsFpuRegister() ? source.fpu_reg()
                                            : destination.fpu_reg();
     const Address& slot_address = source.IsFpuRegister()
         ? destination.ToStackSlotAddress()
diff --git a/runtime/vm/flow_graph_compiler_x64.cc b/runtime/vm/flow_graph_compiler_x64.cc
index 8c9e874..d15ecea 100644
--- a/runtime/vm/flow_graph_compiler_x64.cc
+++ b/runtime/vm/flow_graph_compiler_x64.cc
@@ -722,12 +722,8 @@
       AddCurrentDescriptor(PcDescriptors::kDeopt,
                            assert->deopt_id(),
                            assert->token_pos());
-    } else if (instr->IsGuardField()) {
-      GuardFieldInstr* guard = instr->AsGuardField();
-      AddCurrentDescriptor(PcDescriptors::kDeopt,
-                           guard->deopt_id(),
-                           Scanner::kDummyTokenIndex);
-    } else if (instr->CanBeDeoptimizationTarget()) {
+    } else if (instr->IsGuardField() ||
+               instr->CanBecomeDeoptimizationTarget()) {
       AddCurrentDescriptor(PcDescriptors::kDeopt,
                            instr->deopt_id(),
                            Scanner::kDummyTokenIndex);
@@ -1650,48 +1646,6 @@
 }
 
 
-Condition FlowGraphCompiler::FlipCondition(Condition condition) {
-  switch (condition) {
-    case EQUAL:         return EQUAL;
-    case NOT_EQUAL:     return NOT_EQUAL;
-    case LESS:          return GREATER;
-    case LESS_EQUAL:    return GREATER_EQUAL;
-    case GREATER:       return LESS;
-    case GREATER_EQUAL: return LESS_EQUAL;
-    case BELOW:         return ABOVE;
-    case BELOW_EQUAL:   return ABOVE_EQUAL;
-    case ABOVE:         return BELOW;
-    case ABOVE_EQUAL:   return BELOW_EQUAL;
-    default:
-      UNIMPLEMENTED();
-      return EQUAL;
-  }
-}
-
-
-bool FlowGraphCompiler::EvaluateCondition(Condition condition,
-                                          intptr_t left,
-                                          intptr_t right) {
-  const uintptr_t unsigned_left = static_cast<uintptr_t>(left);
-  const uintptr_t unsigned_right = static_cast<uintptr_t>(right);
-  switch (condition) {
-    case EQUAL:         return left == right;
-    case NOT_EQUAL:     return left != right;
-    case LESS:          return left < right;
-    case LESS_EQUAL:    return left <= right;
-    case GREATER:       return left > right;
-    case GREATER_EQUAL: return left >= right;
-    case BELOW:         return unsigned_left < unsigned_right;
-    case BELOW_EQUAL:   return unsigned_left <= unsigned_right;
-    case ABOVE:         return unsigned_left > unsigned_right;
-    case ABOVE_EQUAL:   return unsigned_left >= unsigned_right;
-    default:
-      UNIMPLEMENTED();
-      return false;
-  }
-}
-
-
 FieldAddress FlowGraphCompiler::ElementAddressForIntIndex(intptr_t cid,
                                                           intptr_t index_scale,
                                                           Register array,
diff --git a/runtime/vm/flow_graph_inliner.cc b/runtime/vm/flow_graph_inliner.cc
index 0c0a38d..4788723 100644
--- a/runtime/vm/flow_graph_inliner.cc
+++ b/runtime/vm/flow_graph_inliner.cc
@@ -614,11 +614,7 @@
 
       // Functions can be inlined before they are optimized.
       // If not yet present, allocate deoptimization history array.
-      Array& deopt_history = Array::Handle(function.deopt_history());
-      if (deopt_history.IsNull()) {
-        deopt_history = Array::New(FLAG_deoptimization_counter_threshold);
-        function.set_deopt_history(deopt_history);
-      }
+      function.EnsureDeoptHistory();
 
       // Build succeeded so we restore the bailout jump.
       inlined_ = true;
diff --git a/runtime/vm/instructions_mips.h b/runtime/vm/instructions_mips.h
index ed16b16..5567ae6 100644
--- a/runtime/vm/instructions_mips.h
+++ b/runtime/vm/instructions_mips.h
@@ -25,6 +25,10 @@
   uword TargetAddress() const;
   void SetTargetAddress(uword target_address) const;
 
+  // This constant length is only valid for inserted call patterns used for
+  // lazy deoptimization. Regular call pattern may vary in length.
+  static const int kFixedLengthInBytes = 3 * Instr::kInstrSize;
+
  private:
   uword Back(int n) const;
   int DecodeLoadObject(int end, Register* reg, Object* obj);
diff --git a/runtime/vm/intermediate_language.cc b/runtime/vm/intermediate_language.cc
index ce76be5..e5d855b 100644
--- a/runtime/vm/intermediate_language.cc
+++ b/runtime/vm/intermediate_language.cc
@@ -1455,12 +1455,12 @@
 
 
 void JoinEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  __ Bind(compiler->GetJumpLabel(this));
   if (!compiler->is_optimizing()) {
     compiler->AddCurrentDescriptor(PcDescriptors::kDeopt,
                                    deopt_id_,
                                    Scanner::kDummyTokenIndex);
   }
-  __ Bind(compiler->GetJumpLabel(this));
   if (HasParallelMove()) {
     compiler->parallel_move_resolver()->EmitNativeCode(parallel_move());
   }
@@ -1474,12 +1474,12 @@
 
 
 void TargetEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  __ Bind(compiler->GetJumpLabel(this));
   if (!compiler->is_optimizing()) {
     compiler->AddCurrentDescriptor(PcDescriptors::kDeopt,
                                    deopt_id_,
                                    Scanner::kDummyTokenIndex);
   }
-  __ Bind(compiler->GetJumpLabel(this));
   if (HasParallelMove()) {
     compiler->parallel_move_resolver()->EmitNativeCode(parallel_move());
   }
diff --git a/runtime/vm/intermediate_language.h b/runtime/vm/intermediate_language.h
index 683642f..19976f6 100644
--- a/runtime/vm/intermediate_language.h
+++ b/runtime/vm/intermediate_language.h
@@ -642,7 +642,7 @@
   virtual Tag tag() const = 0;
 
   intptr_t deopt_id() const {
-    ASSERT(CanDeoptimize() || CanBeDeoptimizationTarget());
+    ASSERT(CanDeoptimize() || CanBecomeDeoptimizationTarget());
     return deopt_id_;
   }
 
@@ -846,10 +846,10 @@
   virtual void InheritDeoptTarget(Instruction* other);
 
   bool NeedsEnvironment() const {
-    return CanDeoptimize() || CanBeDeoptimizationTarget();
+    return CanDeoptimize() || CanBecomeDeoptimizationTarget();
   }
 
-  virtual bool CanBeDeoptimizationTarget() const {
+  virtual bool CanBecomeDeoptimizationTarget() const {
     return false;
   }
 
@@ -1152,7 +1152,7 @@
 
   virtual intptr_t ArgumentCount() const { return 0; }
 
-  virtual bool CanBeDeoptimizationTarget() const {
+  virtual bool CanBecomeDeoptimizationTarget() const {
     // BlockEntry environment is copied to Goto and Branch instructions
     // when we insert new blocks targeting this block.
     return true;
@@ -1860,7 +1860,7 @@
   intptr_t token_pos() const { return token_pos_; }
   Value* value() const { return inputs_[0]; }
 
-  virtual bool CanBeDeoptimizationTarget() const {
+  virtual bool CanBecomeDeoptimizationTarget() const {
     // Return instruction might turn into a Goto instruction after inlining.
     // Every Goto must have an environment.
     return true;
@@ -1940,7 +1940,7 @@
   virtual intptr_t SuccessorCount() const;
   virtual BlockEntryInstr* SuccessorAt(intptr_t index) const;
 
-  virtual bool CanBeDeoptimizationTarget() const {
+  virtual bool CanBecomeDeoptimizationTarget() const {
     // Goto instruction can be used as a deoptimization target when LICM
     // hoists instructions out of the loop.
     return true;
@@ -2016,7 +2016,7 @@
   intptr_t InputCount() const;
   Value* InputAt(intptr_t i) const;
   virtual bool CanDeoptimize() const;
-  virtual bool CanBeDeoptimizationTarget() const;
+  virtual bool CanBecomeDeoptimizationTarget() const;
 
   virtual EffectSet Effects() const;
 
@@ -2762,8 +2762,8 @@
 }
 
 
-inline bool BranchInstr::CanBeDeoptimizationTarget() const {
-  return comparison()->CanBeDeoptimizationTarget();
+inline bool BranchInstr::CanBecomeDeoptimizationTarget() const {
+  return comparison()->CanBecomeDeoptimizationTarget();
 }
 
 
@@ -2811,7 +2811,7 @@
 
   virtual void PrintOperandsTo(BufferFormatter* f) const;
 
-  virtual bool CanBeDeoptimizationTarget() const {
+  virtual bool CanBecomeDeoptimizationTarget() const {
     // StrictCompare can be merged into Branch and thus needs an environment.
     return true;
   }
diff --git a/runtime/vm/intermediate_language_arm.cc b/runtime/vm/intermediate_language_arm.cc
index d07ab4d..7e3c96b 100644
--- a/runtime/vm/intermediate_language_arm.cc
+++ b/runtime/vm/intermediate_language_arm.cc
@@ -356,9 +356,6 @@
 }
 
 
-// R1: left.
-// R0: right.
-// Uses R5 to load ic_call_data.
 static void EmitEqualityAsInstanceCall(FlowGraphCompiler* compiler,
                                        intptr_t deopt_id,
                                        intptr_t token_pos,
@@ -376,6 +373,7 @@
 
   Label check_identity;
   __ LoadImmediate(IP, reinterpret_cast<intptr_t>(Object::null()));
+  __ ldm(IA, SP, (1 << R0) | (1 << R1));
   __ cmp(R1, ShifterOperand(IP));
   __ b(&check_identity, EQ);
   __ cmp(R0, ShifterOperand(IP));
@@ -397,7 +395,6 @@
                                    deopt_id,
                                    kNumArgumentsChecked);
   }
-  __ PushList((1 << R0) | (1 << R1));
   compiler->GenerateInstanceCall(deopt_id,
                                  token_pos,
                                  kNumberOfArguments,
@@ -411,6 +408,7 @@
   Label equality_done;
   if (compiler->is_optimizing()) {
     // No need to update IC data.
+    __ PopList((1 << R0) | (1 << R1));
     __ cmp(R0, ShifterOperand(R1));
     __ LoadObject(R0, (kind == Token::kEQ) ? Bool::False() : Bool::True(), NE);
     __ LoadObject(R0, (kind == Token::kEQ) ? Bool::True() : Bool::False(), EQ);
@@ -429,6 +427,7 @@
                            &StubCode::EqualityWithNullArgLabel(),
                            PcDescriptors::kRuntimeCall,
                            locs);
+    __ Drop(2);
   }
   __ Bind(&check_ne);
   if (kind == Token::kNE) {
@@ -479,8 +478,8 @@
 }
 
 
-// R1: left.
-// R0: right.
+// R1: left, also on stack.
+// R0: right, also on stack.
 static void EmitEqualityAsPolymorphicCall(FlowGraphCompiler* compiler,
                                           const ICData& orig_ic_data,
                                           LocationSummary* locs,
@@ -518,6 +517,7 @@
     const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(i));
     if (target.Owner() == object_store->object_class()) {
       // Object.== is same as ===.
+      __ Drop(2);
       __ cmp(left, ShifterOperand(right));
       if (branch != NULL) {
         branch->EmitBranchOnCondition(compiler, cond);
@@ -608,12 +608,32 @@
   __ Bind(&non_null_compare);  // Receiver is not null.
   ASSERT(left == R1);
   ASSERT(right == R0);
+  __ PushList((1 << R0) | (1 << R1));
   EmitEqualityAsPolymorphicCall(compiler, ic_data, locs, branch, kind,
                                 deopt_id, token_pos);
   __ Bind(&done);
 }
 
 
+static Condition FlipCondition(Condition condition) {
+  switch (condition) {
+    case EQ: return EQ;
+    case NE: return NE;
+    case LT: return GT;
+    case LE: return GE;
+    case GT: return LT;
+    case GE: return LE;
+    case CC: return HI;
+    case LS: return CS;
+    case HI: return CC;
+    case CS: return LS;
+    default:
+      UNIMPLEMENTED();
+      return EQ;
+  }
+}
+
+
 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler,
                                 const LocationSummary& locs,
                                 Token::Kind kind,
@@ -626,7 +646,7 @@
 
   if (left.IsConstant()) {
     __ CompareObject(right.reg(), left.constant());
-    true_condition = FlowGraphCompiler::FlipCondition(true_condition);
+    true_condition = FlipCondition(true_condition);
   } else if (right.IsConstant()) {
     __ CompareObject(left.reg(), right.constant());
   } else {
@@ -698,6 +718,7 @@
   Register right = locs()->in(1).reg();
   ASSERT(left == R1);
   ASSERT(right == R0);
+  __ PushList((1 << R0) | (1 << R1));
   EmitEqualityAsInstanceCall(compiler,
                              deopt_id(),
                              token_pos(),
@@ -740,6 +761,7 @@
   Register right = locs()->in(1).reg();
   ASSERT(left == R1);
   ASSERT(right == R0);
+  __ PushList((1 << R0) | (1 << R1));
   EmitEqualityAsInstanceCall(compiler,
                              deopt_id(),
                              token_pos(),
@@ -1697,34 +1719,32 @@
 
   // 'instantiator_reg' is the instantiator AbstractTypeArguments object
   // (or null).
-  if (!type_arguments().IsUninstantiatedIdentity() &&
-      !type_arguments().CanShareInstantiatorTypeArguments(
-          instantiator_class())) {
-    // If the instantiator is null and if the type argument vector
-    // instantiated from null becomes a vector of dynamic, then use null as
-    // the type arguments.
-    Label type_arguments_instantiated;
-    const intptr_t len = type_arguments().Length();
-    if (type_arguments().IsRawInstantiatedRaw(len)) {
-      __ LoadImmediate(IP, reinterpret_cast<intptr_t>(Object::null()));
-      __ cmp(instantiator_reg, ShifterOperand(IP));
-      __ b(&type_arguments_instantiated, EQ);
-    }
-    // Instantiate non-null type arguments.
-    // A runtime call to instantiate the type arguments is required.
-    __ PushObject(Object::ZoneHandle());  // Make room for the result.
-    __ PushObject(type_arguments());
-    __ Push(instantiator_reg);  // Push instantiator type arguments.
-    compiler->GenerateCallRuntime(token_pos(),
-                                  deopt_id(),
-                                  kInstantiateTypeArgumentsRuntimeEntry,
-                                  locs());
-    __ Drop(2);  // Drop instantiator and uninstantiated type arguments.
-    __ Pop(result_reg);  // Pop instantiated type arguments.
-    __ Bind(&type_arguments_instantiated);
+  ASSERT(!type_arguments().IsUninstantiatedIdentity() &&
+         !type_arguments().CanShareInstantiatorTypeArguments(
+             instantiator_class()));
+  // If the instantiator is null and if the type argument vector
+  // instantiated from null becomes a vector of dynamic, then use null as
+  // the type arguments.
+  Label type_arguments_instantiated;
+  const intptr_t len = type_arguments().Length();
+  if (type_arguments().IsRawInstantiatedRaw(len)) {
+    __ LoadImmediate(IP, reinterpret_cast<intptr_t>(Object::null()));
+    __ cmp(instantiator_reg, ShifterOperand(IP));
+    __ b(&type_arguments_instantiated, EQ);
   }
+  // Instantiate non-null type arguments.
+  // A runtime call to instantiate the type arguments is required.
+  __ PushObject(Object::ZoneHandle());  // Make room for the result.
+  __ PushObject(type_arguments());
+  __ Push(instantiator_reg);  // Push instantiator type arguments.
+  compiler->GenerateCallRuntime(token_pos(),
+                                deopt_id(),
+                                kInstantiateTypeArgumentsRuntimeEntry,
+                                locs());
+  __ Drop(2);  // Drop instantiator and uninstantiated type arguments.
+  __ Pop(result_reg);  // Pop instantiated type arguments.
+  __ Bind(&type_arguments_instantiated);
   ASSERT(instantiator_reg == result_reg);
-  // 'result_reg': Instantiated type arguments.
 }
 
 
@@ -1925,6 +1945,115 @@
 }
 
 
+static void EmitSmiShiftLeft(FlowGraphCompiler* compiler,
+                             BinarySmiOpInstr* shift_left) {
+  const bool is_truncating = shift_left->is_truncating();
+  const LocationSummary& locs = *shift_left->locs();
+  Register left = locs.in(0).reg();
+  Register result = locs.out().reg();
+  Label* deopt = shift_left->CanDeoptimize() ?
+      compiler->AddDeoptStub(shift_left->deopt_id(), kDeoptBinarySmiOp) : NULL;
+  if (locs.in(1).IsConstant()) {
+    const Object& constant = locs.in(1).constant();
+    ASSERT(constant.IsSmi());
+    // Immediate shift operation takes 5 bits for the count.
+    const intptr_t kCountLimit = 0x1F;
+    const intptr_t value = Smi::Cast(constant).Value();
+    if (value == 0) {
+      // No code needed.
+    } else if ((value < 0) || (value >= kCountLimit)) {
+      // This condition may not be known earlier in some cases because
+      // of constant propagation, inlining, etc.
+      if ((value >=kCountLimit) && is_truncating) {
+        __ mov(result, ShifterOperand(0));
+      } else {
+        // Result is Mint or exception.
+        __ b(deopt);
+      }
+    } else {
+      if (!is_truncating) {
+        // Check for overflow (preserve left).
+        __ Lsl(IP, left, value);
+        __ cmp(left, ShifterOperand(IP, ASR, value));
+        __ b(deopt, NE);  // Overflow.
+      }
+      // Shift for result now we know there is no overflow.
+      __ Lsl(result, left, value);
+    }
+    return;
+  }
+
+  // Right (locs.in(1)) is not constant.
+  Register right = locs.in(1).reg();
+  Range* right_range = shift_left->right()->definition()->range();
+  if (shift_left->left()->BindsToConstant() && !is_truncating) {
+    // TODO(srdjan): Implement code below for is_truncating().
+    // If left is constant, we know the maximal allowed size for right.
+    const Object& obj = shift_left->left()->BoundConstant();
+    if (obj.IsSmi()) {
+      const intptr_t left_int = Smi::Cast(obj).Value();
+      if (left_int == 0) {
+        __ cmp(right, ShifterOperand(0));
+        __ b(deopt, MI);
+        return;
+      }
+      const intptr_t max_right = kSmiBits - Utils::HighestBit(left_int);
+      const bool right_needs_check =
+          (right_range == NULL) ||
+          !right_range->IsWithin(0, max_right - 1);
+      if (right_needs_check) {
+        __ cmp(right,
+               ShifterOperand(reinterpret_cast<int32_t>(Smi::New(max_right))));
+        __ b(deopt, CS);
+      }
+      __ SmiUntag(right);
+      __ Lsl(result, left, right);
+    }
+    return;
+  }
+
+  const bool right_needs_check =
+      (right_range == NULL) || !right_range->IsWithin(0, (Smi::kBits - 1));
+  if (is_truncating) {
+    if (right_needs_check) {
+      const bool right_may_be_negative =
+          (right_range == NULL) ||
+          !right_range->IsWithin(0, RangeBoundary::kPlusInfinity);
+      if (right_may_be_negative) {
+        ASSERT(shift_left->CanDeoptimize());
+        __ cmp(right, ShifterOperand(0));
+        __ b(deopt, MI);
+      }
+      Label done, is_not_zero;
+      __ cmp(right,
+             ShifterOperand(reinterpret_cast<int32_t>(Smi::New(Smi::kBits))));
+      __ mov(result, ShifterOperand(0), CS);
+      __ SmiUntag(right, CC);
+      __ Lsl(result, left, right, CC);
+    } else {
+      __ SmiUntag(right);
+      __ Lsl(result, left, right);
+    }
+  } else {
+    if (right_needs_check) {
+      ASSERT(shift_left->CanDeoptimize());
+      __ cmp(right,
+             ShifterOperand(reinterpret_cast<int32_t>(Smi::New(Smi::kBits))));
+      __ b(deopt, CS);
+    }
+    // Left is not a constant.
+    // Check if count too large for handling it inlined.
+    __ SmiUntag(right);
+    // Overflow test (preserve left and right);
+    __ Lsl(IP, left, right);
+    __ cmp(left, ShifterOperand(IP, ASR, right));
+    __ b(deopt, NE);  // Overflow.
+    // Shift for result now we know there is no overflow.
+    __ Lsl(result, left, right);
+  }
+}
+
+
 LocationSummary* BinarySmiOpInstr::MakeLocationSummary() const {
   const intptr_t kNumInputs = 2;
   if (op_kind() == Token::kTRUNCDIV) {
@@ -1946,7 +2075,7 @@
 
 void BinarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   if (op_kind() == Token::kSHL) {
-    UNIMPLEMENTED();
+    EmitSmiShiftLeft(compiler, this);
     return;
   }
 
@@ -2040,7 +2169,24 @@
         break;
       }
       case Token::kSHR: {
-        UNIMPLEMENTED();
+        // sarl operation masks the count to 5 bits.
+        const intptr_t kCountLimit = 0x1F;
+        intptr_t value = Smi::Cast(constant).Value();
+
+        if (value == 0) {
+          // TODO(vegorov): should be handled outside.
+          break;
+        } else if (value < 0) {
+          // TODO(vegorov): should be handled outside.
+          __ b(deopt);
+          break;
+        }
+
+        value = value + kSmiTagSize;
+        if (value >= kCountLimit) value = kCountLimit;
+
+        __ Asr(result, left, value);
+        __ SmiTag(result);
         break;
       }
 
@@ -2530,7 +2676,8 @@
   }
 
   // Load receiver into R0.
-  __ ldr(R0, Address(SP, (instance_call()->ArgumentCount() - 1) * kWordSize));
+  __ LoadFromOffset(kLoadWord, R0, SP,
+                    (instance_call()->ArgumentCount() - 1) * kWordSize);
 
   LoadValueCid(compiler, R2, R0,
                (ic_data().GetReceiverClassIdAt(0) == kSmiCid) ? NULL : deopt);
@@ -2772,14 +2919,6 @@
 
 
 void GotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  if (!compiler->is_optimizing()) {
-    // Add deoptimization descriptor for deoptimizing instructions that may
-    // be inserted before this instruction.
-    compiler->AddCurrentDescriptor(PcDescriptors::kDeopt,
-                                   GetDeoptId(),
-                                   0);  // No token position.
-  }
-
   if (HasParallelMove()) {
     compiler->parallel_move_resolver()->EmitNativeCode(parallel_move());
   }
diff --git a/runtime/vm/intermediate_language_ia32.cc b/runtime/vm/intermediate_language_ia32.cc
index 23b6241..1d1ad45 100644
--- a/runtime/vm/intermediate_language_ia32.cc
+++ b/runtime/vm/intermediate_language_ia32.cc
@@ -629,6 +629,25 @@
 }
 
 
+static Condition FlipCondition(Condition condition) {
+  switch (condition) {
+    case EQUAL:         return EQUAL;
+    case NOT_EQUAL:     return NOT_EQUAL;
+    case LESS:          return GREATER;
+    case LESS_EQUAL:    return GREATER_EQUAL;
+    case GREATER:       return LESS;
+    case GREATER_EQUAL: return LESS_EQUAL;
+    case BELOW:         return ABOVE;
+    case BELOW_EQUAL:   return ABOVE_EQUAL;
+    case ABOVE:         return BELOW;
+    case ABOVE_EQUAL:   return BELOW_EQUAL;
+    default:
+      UNIMPLEMENTED();
+      return EQUAL;
+  }
+}
+
+
 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler,
                                 const LocationSummary& locs,
                                 Token::Kind kind,
@@ -641,7 +660,7 @@
 
   if (left.IsConstant()) {
     __ CompareObject(right.reg(), left.constant());
-    true_condition = FlowGraphCompiler::FlipCondition(true_condition);
+    true_condition = FlipCondition(true_condition);
   } else if (right.IsConstant()) {
     __ CompareObject(left.reg(), right.constant());
   } else if (right.IsStackSlot()) {
@@ -749,11 +768,11 @@
   __ cmpl(left_tmp, right_tmp);
   if (branch != NULL) {
     __ j(hi_cond, compiler->GetJumpLabel(branch->true_successor()));
-    __ j(FlowGraphCompiler::FlipCondition(hi_cond),
+    __ j(FlipCondition(hi_cond),
          compiler->GetJumpLabel(branch->false_successor()));
   } else {
     __ j(hi_cond, &is_true);
-    __ j(FlowGraphCompiler::FlipCondition(hi_cond), &is_false);
+    __ j(FlipCondition(hi_cond), &is_false);
   }
 
   // If upper is equal, compare lower half.
@@ -1883,35 +1902,33 @@
 
   // 'instantiator_reg' is the instantiator AbstractTypeArguments object
   // (or null).
-  if (!type_arguments().IsUninstantiatedIdentity() &&
-      !type_arguments().CanShareInstantiatorTypeArguments(
-          instantiator_class())) {
-    // If the instantiator is null and if the type argument vector
-    // instantiated from null becomes a vector of dynamic, then use null as
-    // the type arguments.
-    Label type_arguments_instantiated;
-    const intptr_t len = type_arguments().Length();
-    if (type_arguments().IsRawInstantiatedRaw(len)) {
-      const Immediate& raw_null =
-          Immediate(reinterpret_cast<intptr_t>(Object::null()));
-      __ cmpl(instantiator_reg, raw_null);
-      __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump);
-    }
-    // Instantiate non-null type arguments.
-    // A runtime call to instantiate the type arguments is required.
-    __ PushObject(Object::ZoneHandle());  // Make room for the result.
-    __ PushObject(type_arguments());
-    __ pushl(instantiator_reg);  // Push instantiator type arguments.
-    compiler->GenerateCallRuntime(token_pos(),
-                                  deopt_id(),
-                                  kInstantiateTypeArgumentsRuntimeEntry,
-                                  locs());
-    __ Drop(2);  // Drop instantiator and uninstantiated type arguments.
-    __ popl(result_reg);  // Pop instantiated type arguments.
-    __ Bind(&type_arguments_instantiated);
+  ASSERT(!type_arguments().IsUninstantiatedIdentity() &&
+         !type_arguments().CanShareInstantiatorTypeArguments(
+             instantiator_class()));
+  // If the instantiator is null and if the type argument vector
+  // instantiated from null becomes a vector of dynamic, then use null as
+  // the type arguments.
+  Label type_arguments_instantiated;
+  const intptr_t len = type_arguments().Length();
+  if (type_arguments().IsRawInstantiatedRaw(len)) {
+    const Immediate& raw_null =
+        Immediate(reinterpret_cast<intptr_t>(Object::null()));
+    __ cmpl(instantiator_reg, raw_null);
+    __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump);
   }
+  // Instantiate non-null type arguments.
+  // A runtime call to instantiate the type arguments is required.
+  __ PushObject(Object::ZoneHandle());  // Make room for the result.
+  __ PushObject(type_arguments());
+  __ pushl(instantiator_reg);  // Push instantiator type arguments.
+  compiler->GenerateCallRuntime(token_pos(),
+                                deopt_id(),
+                                kInstantiateTypeArgumentsRuntimeEntry,
+                                locs());
+  __ Drop(2);  // Drop instantiator and uninstantiated type arguments.
+  __ popl(result_reg);  // Pop instantiated type arguments.
+  __ Bind(&type_arguments_instantiated);
   ASSERT(instantiator_reg == result_reg);
-  // 'result_reg': Instantiated type arguments.
 }
 
 
@@ -2181,11 +2198,7 @@
         __ j(NEGATIVE, deopt);
         return;
       }
-      intptr_t tmp = (left_int > 0) ? left_int : ~left_int;
-      intptr_t max_right = kSmiBits;
-      while ((tmp >>= 1) != 0) {
-        max_right--;
-      }
+      const intptr_t max_right = kSmiBits - Utils::HighestBit(left_int);
       const bool right_needs_check =
           (right_range == NULL) ||
           !right_range->IsWithin(0, max_right - 1);
@@ -2295,7 +2308,12 @@
     LocationSummary* summary =
         new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
     summary->set_in(0, Location::RequiresRegister());
-    summary->set_in(1, Location::RegisterOrSmiConstant(right()));
+    ConstantInstr* constant = right()->definition()->AsConstant();
+    if (constant != NULL) {
+      summary->set_in(1, Location::RegisterOrSmiConstant(right()));
+    } else {
+      summary->set_in(1, Location::PrefersRegister());
+    }
     summary->set_out(Location::SameAsFirstInput());
     return summary;
   }
@@ -2416,8 +2434,49 @@
         break;
     }
     return;
-  }
+  }  // if locs()->in(1).IsConstant()
 
+  if (locs()->in(1).IsStackSlot()) {
+    const Address& right = locs()->in(1).ToStackSlotAddress();
+    switch (op_kind()) {
+      case Token::kADD: {
+        __ addl(left, right);
+        if (deopt != NULL) __ j(OVERFLOW, deopt);
+        break;
+      }
+      case Token::kSUB: {
+        __ subl(left, right);
+        if (deopt != NULL) __ j(OVERFLOW, deopt);
+        break;
+      }
+      case Token::kMUL: {
+        __ SmiUntag(left);
+        __ imull(left, right);
+        if (deopt != NULL) __ j(OVERFLOW, deopt);
+        break;
+      }
+      case Token::kBIT_AND: {
+        // No overflow check.
+        __ andl(left, right);
+        break;
+      }
+      case Token::kBIT_OR: {
+        // No overflow check.
+        __ orl(left, right);
+        break;
+      }
+      case Token::kBIT_XOR: {
+        // No overflow check.
+        __ xorl(left, right);
+        break;
+      }
+      default:
+        UNREACHABLE();
+    }
+    return;
+  }  // if locs()->in(1).IsStackSlot.
+
+  // if locs()->in(1).IsRegister.
   Register right = locs()->in(1).reg();
   switch (op_kind()) {
     case Token::kADD: {
@@ -4268,14 +4327,6 @@
 
 
 void GotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  if (!compiler->is_optimizing()) {
-    // Add deoptimization descriptor for deoptimizing instructions that may
-    // be inserted before this instruction.
-    compiler->AddCurrentDescriptor(PcDescriptors::kDeopt,
-                                   GetDeoptId(),
-                                   0);  // No token position.
-  }
-
   if (HasParallelMove()) {
     compiler->parallel_move_resolver()->EmitNativeCode(parallel_move());
   }
diff --git a/runtime/vm/intermediate_language_mips.cc b/runtime/vm/intermediate_language_mips.cc
index 5107f34..5610b8b 100644
--- a/runtime/vm/intermediate_language_mips.cc
+++ b/runtime/vm/intermediate_language_mips.cc
@@ -92,9 +92,9 @@
     const intptr_t fp_sp_dist =
         (kFirstLocalSlotFromFp + 1 - compiler->StackSize()) * kWordSize;
     ASSERT(fp_sp_dist <= 0);
-    __ subu(T2, SP, FP);
+    __ subu(TMP1, SP, FP);
 
-    __ BranchEqual(T2, fp_sp_dist, &stack_ok);
+    __ BranchEqual(TMP1, fp_sp_dist, &stack_ok);
     __ break_(0);
 
     __ Bind(&stack_ok);
@@ -328,7 +328,10 @@
     const intptr_t kNumTemps = 1;
     LocationSummary* locs =
         new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
-    UNIMPLEMENTED();  // TODO(regis): Verify register allocation.
+    locs->set_in(0, Location::RegisterLocation(A1));
+    locs->set_in(1, Location::RegisterLocation(A0));
+    locs->set_temp(0, Location::RegisterLocation(T0));
+    locs->set_out(Location::RegisterLocation(V0));
     return locs;
   }
   const intptr_t kNumTemps = 1;
@@ -363,9 +366,8 @@
   const int kNumArgumentsChecked = 2;
 
   Label check_identity;
-  __ LoadImmediate(TMP1, reinterpret_cast<intptr_t>(Object::null()));
-  __ beq(A1, TMP1, &check_identity);
-  __ beq(A0, TMP1, &check_identity);
+  __ beq(A1, NULLREG, &check_identity);
+  __ beq(A0, NULLREG, &check_identity);
 
   ICData& equality_ic_data = ICData::ZoneHandle();
   if (compiler->is_optimizing() && FLAG_propagate_ic_data) {
@@ -496,6 +498,29 @@
 }
 
 
+// Branches on condition c assuming comparison results in CMPRES and TMP1.
+static void EmitBranchAfterCompare(
+    FlowGraphCompiler* compiler, Condition c, Label* is_true) {
+    switch (c) {
+      case EQ: __ beq(CMPRES, TMP1, is_true); break;
+      case NE: __ bne(CMPRES, TMP1, is_true); break;
+      case GT: __ bne(TMP1, ZR, is_true); break;
+      case GE: __ beq(CMPRES, ZR, is_true); break;
+      case LT: __ bne(CMPRES, ZR, is_true); break;
+      case LE: __ beq(TMP1, ZR, is_true); break;
+      default:
+        UNREACHABLE();
+        break;
+    }
+}
+
+
+static Condition FlipCondition(Condition condition) {
+  UNIMPLEMENTED();
+  return condition;
+}
+
+
 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler,
                                 const LocationSummary& locs,
                                 Token::Kind kind,
@@ -508,12 +533,13 @@
   Condition true_condition = TokenKindToSmiCondition(kind);
 
   if (left.IsConstant()) {
-    __ CompareObject(CMPRES, right.reg(), left.constant());
-    true_condition = FlowGraphCompiler::FlipCondition(true_condition);
+    __ CompareObject(CMPRES, TMP1, right.reg(), left.constant());
+    true_condition = FlipCondition(true_condition);
   } else if (right.IsConstant()) {
-    __ CompareObject(CMPRES, left.reg(), right.constant());
+    __ CompareObject(CMPRES, TMP1, left.reg(), right.constant());
   } else {
-    __ subu(CMPRES, left.reg(), right.reg());
+    __ slt(CMPRES, left.reg(), right.reg());
+    __ slt(TMP1, right.reg(), left.reg());
   }
 
   if (branch != NULL) {
@@ -521,17 +547,7 @@
   } else {
     Register result = locs.out().reg();
     Label done, is_true;
-    switch (true_condition) {
-      case EQ: __ beq(CMPRES, ZR, &is_true); break;
-      case NE: __ bne(CMPRES, ZR, &is_true); break;
-      case GT: __ bgtz(CMPRES, &is_true); break;
-      case GE: __ bgez(CMPRES, &is_true); break;
-      case LT: __ bltz(CMPRES, &is_true); break;
-      case LE: __ blez(CMPRES, &is_true); break;
-      default:
-        UNREACHABLE();
-        break;
-    }
+    EmitBranchAfterCompare(compiler, true_condition, &is_true);
     __ LoadObject(result, Bool::False());
     __ b(&done);
     __ Bind(&is_true);
@@ -649,7 +665,7 @@
     EmitAssertBoolean(V0, token_pos(), deopt_id(), locs(), compiler);
   }
   Condition branch_condition = (kind() == Token::kNE) ? NE : EQ;
-  __ CompareObject(CMPRES, V0, Bool::True());
+  __ CompareObject(CMPRES, TMP1, V0, Bool::True());
   branch->EmitBranchOnCondition(compiler, branch_condition);
 }
 
@@ -785,7 +801,7 @@
     return;
   }
   EmitNativeCode(compiler);
-  __ CompareObject(CMPRES, V0, Bool::True());
+  __ CompareObject(CMPRES, TMP1, V0, Bool::True());
   branch->EmitBranchOnCondition(compiler, EQ);
 }
 
@@ -859,13 +875,25 @@
 
 
 LocationSummary* LoadClassIdInstr::MakeLocationSummary() const {
-  UNIMPLEMENTED();
-  return NULL;
+  const intptr_t kNumInputs = 1;
+  return LocationSummary::Make(kNumInputs,
+                               Location::RequiresRegister(),
+                               LocationSummary::kNoCall);
 }
 
 
 void LoadClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  UNIMPLEMENTED();
+  Register object = locs()->in(0).reg();
+  Register result = locs()->out().reg();
+  Label load, done;
+  __ andi(CMPRES, object, Immediate(kSmiTagMask));
+  __ bne(CMPRES, ZR, &load);
+  __ LoadImmediate(result, Smi::RawValue(kSmiCid));
+  __ b(&done);
+  __ Bind(&load);
+  __ LoadClassId(result, object);
+  __ SmiTag(result);
+  __ Bind(&done);
 }
 
 
@@ -994,9 +1022,9 @@
       default:
         UNREACHABLE();
     }
-    __ AddImmediate(index.reg(),
+    __ addu(index.reg(), array, index.reg());
+    element_address = Address(index.reg(),
         FlowGraphCompiler::DataOffsetFor(class_id()) - kHeapObjectTag);
-    element_address = Address(array, index.reg());
   }
 
   if ((representation() == kUnboxedDouble) ||
@@ -1006,9 +1034,6 @@
   }
 
   Register result = locs()->out().reg();
-  if ((index_scale() == 1) && index.IsRegister()) {
-    __ SmiUntag(index.reg());
-  }
   switch (class_id()) {
     case kTypedDataInt8ArrayCid:
       ASSERT(index_scale() == 1);
@@ -1061,8 +1086,33 @@
 
 Representation StoreIndexedInstr::RequiredInputRepresentation(
     intptr_t idx) const {
-  UNIMPLEMENTED();
-  return kTagged;
+  // Array can be a Dart object or a pointer to external data.
+  if (idx == 0)  return kNoRepresentation;  // Flexible input representation.
+  if (idx == 1) return kTagged;  // Index is a smi.
+  ASSERT(idx == 2);
+  switch (class_id_) {
+    case kArrayCid:
+    case kOneByteStringCid:
+    case kTypedDataInt8ArrayCid:
+    case kTypedDataUint8ArrayCid:
+    case kExternalTypedDataUint8ArrayCid:
+    case kTypedDataUint8ClampedArrayCid:
+    case kExternalTypedDataUint8ClampedArrayCid:
+    case kTypedDataInt16ArrayCid:
+    case kTypedDataUint16ArrayCid:
+      return kTagged;
+    case kTypedDataInt32ArrayCid:
+    case kTypedDataUint32ArrayCid:
+      return value()->IsSmiValue() ? kTagged : kUnboxedMint;
+    case kTypedDataFloat32ArrayCid:
+    case kTypedDataFloat64ArrayCid:
+      return kUnboxedDouble;
+    case kTypedDataFloat32x4ArrayCid:
+      return kUnboxedFloat32x4;
+    default:
+      UNIMPLEMENTED();
+      return kTagged;
+  }
 }
 
 
@@ -1088,14 +1138,22 @@
     case kTypedDataUint8ArrayCid:
     case kTypedDataUint8ClampedArrayCid:
     case kOneByteStringCid:
+      locs->set_in(2, Location::RegisterOrSmiConstant(value()));
+      break;
     case kTypedDataInt16ArrayCid:
     case kTypedDataUint16ArrayCid:
     case kTypedDataInt32ArrayCid:
     case kTypedDataUint32ArrayCid:
+      locs->set_in(2, Location::WritableRegister());
+      break;
     case kTypedDataFloat32ArrayCid:
-    case kTypedDataFloat64ArrayCid:
+      // TODO(regis): Verify.
+      // Need temp register for float-to-double conversion.
+      locs->AddTemp(Location::RequiresFpuRegister());
+      // Fall through.
+    case kTypedDataFloat64ArrayCid:  // TODO(srdjan): Support Float64 constants.
     case kTypedDataFloat32x4ArrayCid:
-      UNIMPLEMENTED();
+      locs->set_in(2, Location::RequiresFpuRegister());
       break;
     default:
       UNREACHABLE();
@@ -1143,10 +1201,9 @@
       default:
         UNREACHABLE();
     }
-    __ AddImmediate(index.reg(),
+    __ addu(index.reg(), array, index.reg());
+    element_address = Address(index.reg(),
         FlowGraphCompiler::DataOffsetFor(class_id()) - kHeapObjectTag);
-    __ addu(TMP1, array, index.reg());
-    element_address = Address(TMP1);
   }
 
   switch (class_id()) {
@@ -1165,13 +1222,64 @@
     case kTypedDataInt8ArrayCid:
     case kTypedDataUint8ArrayCid:
     case kExternalTypedDataUint8ArrayCid:
+    case kOneByteStringCid: {
+      if (locs()->in(2).IsConstant()) {
+        const Smi& constant = Smi::Cast(locs()->in(2).constant());
+        __ LoadImmediate(TMP, static_cast<int8_t>(constant.Value()));
+        __ sb(TMP, element_address);
+      } else {
+        Register value = locs()->in(2).reg();
+        __ SmiUntag(value);
+        __ sb(value, element_address);
+      }
+      break;
+    }
     case kTypedDataUint8ClampedArrayCid:
-    case kExternalTypedDataUint8ClampedArrayCid:
-    case kOneByteStringCid:
+    case kExternalTypedDataUint8ClampedArrayCid: {
+      if (locs()->in(2).IsConstant()) {
+        const Smi& constant = Smi::Cast(locs()->in(2).constant());
+        intptr_t value = constant.Value();
+        // Clamp to 0x0 or 0xFF respectively.
+        if (value > 0xFF) {
+          value = 0xFF;
+        } else if (value < 0) {
+          value = 0;
+        }
+        __ LoadImmediate(TMP, static_cast<int8_t>(value));
+        __ sb(TMP, element_address);
+      } else {
+        Register value = locs()->in(2).reg();
+        Label store_value, bigger, smaller;
+        __ SmiUntag(value);
+        __ BranchUnsignedLess(value, 0xFF + 1, &store_value);
+        __ LoadImmediate(TMP, 0xFF);
+        __ slti(CMPRES, value, Immediate(1));
+        __ movn(TMP, ZR, CMPRES);
+        __ mov(value, TMP);
+        __ Bind(&store_value);
+        __ sb(value, element_address);
+      }
+      break;
+    }
     case kTypedDataInt16ArrayCid:
-    case kTypedDataUint16ArrayCid:
+    case kTypedDataUint16ArrayCid: {
+      Register value = locs()->in(2).reg();
+      __ SmiUntag(value);
+      __ sh(value, element_address);
+      break;
+    }
     case kTypedDataInt32ArrayCid:
-    case kTypedDataUint32ArrayCid:
+    case kTypedDataUint32ArrayCid: {
+      if (value()->IsSmiValue()) {
+        ASSERT(RequiredInputRepresentation(2) == kTagged);
+        Register value = locs()->in(2).reg();
+        __ SmiUntag(value);
+        __ sw(value, element_address);
+      } else {
+        UNIMPLEMENTED();
+      }
+      break;
+    }
     case kTypedDataFloat32ArrayCid:
     case kTypedDataFloat64ArrayCid:
     case kTypedDataFloat32x4ArrayCid:
@@ -1299,8 +1407,7 @@
 
       if (field().is_nullable() && (field_cid != kNullCid)) {
         __ beq(CMPRES, ZR, &ok);
-        __ LoadImmediate(TMP1, reinterpret_cast<intptr_t>(Object::null()));
-        __ subu(CMPRES, value_reg, TMP1);
+        __ subu(CMPRES, value_reg, NULLREG);
       }
 
       if (ok_is_fall_through) {
@@ -1498,41 +1605,37 @@
 
   // 'instantiator_reg' is the instantiator AbstractTypeArguments object
   // (or null).
-  if (!type_arguments().IsUninstantiatedIdentity() &&
-      !type_arguments().CanShareInstantiatorTypeArguments(
-          instantiator_class())) {
-    // If the instantiator is null and if the type argument vector
-    // instantiated from null becomes a vector of dynamic, then use null as
-    // the type arguments.
-    Label type_arguments_instantiated;
-    const intptr_t len = type_arguments().Length();
-    if (type_arguments().IsRawInstantiatedRaw(len)) {
-      __ BranchEqual(instantiator_reg,
-                     reinterpret_cast<intptr_t>(Object::null()),
-                     &type_arguments_instantiated);
-    }
-    // Instantiate non-null type arguments.
-    // A runtime call to instantiate the type arguments is required.
-    __ addiu(SP, SP, Immediate(-3 * kWordSize));
-    __ LoadObject(TMP1, Object::ZoneHandle());
-    __ sw(TMP1, Address(SP, 2 * kWordSize));  // Make room for the result.
-    __ LoadObject(TMP1, type_arguments());
-    __ sw(TMP1, Address(SP, 1 * kWordSize));
-    // Push instantiator type arguments.
-    __ sw(instantiator_reg, Address(SP, 0 * kWordSize));
-
-    compiler->GenerateCallRuntime(token_pos(),
-                                  deopt_id(),
-                                  kInstantiateTypeArgumentsRuntimeEntry,
-                                  locs());
-    // Pop instantiated type arguments.
-    __ lw(result_reg, Address(SP, 2 * kWordSize));
-    // Drop instantiator and uninstantiated type arguments.
-    __ addiu(SP, SP, Immediate(3 * kWordSize));
-    __ Bind(&type_arguments_instantiated);
+  ASSERT(!type_arguments().IsUninstantiatedIdentity() &&
+         !type_arguments().CanShareInstantiatorTypeArguments(
+             instantiator_class()));
+  // If the instantiator is null and if the type argument vector
+  // instantiated from null becomes a vector of dynamic, then use null as
+  // the type arguments.
+  Label type_arguments_instantiated;
+  const intptr_t len = type_arguments().Length();
+  if (type_arguments().IsRawInstantiatedRaw(len)) {
+    __ beq(instantiator_reg, NULLREG, &type_arguments_instantiated);
   }
+  // Instantiate non-null type arguments.
+  // A runtime call to instantiate the type arguments is required.
+  __ addiu(SP, SP, Immediate(-3 * kWordSize));
+  __ LoadObject(TMP1, Object::ZoneHandle());
+  __ sw(TMP1, Address(SP, 2 * kWordSize));  // Make room for the result.
+  __ LoadObject(TMP1, type_arguments());
+  __ sw(TMP1, Address(SP, 1 * kWordSize));
+  // Push instantiator type arguments.
+  __ sw(instantiator_reg, Address(SP, 0 * kWordSize));
+
+  compiler->GenerateCallRuntime(token_pos(),
+                                deopt_id(),
+                                kInstantiateTypeArgumentsRuntimeEntry,
+                                locs());
+  // Pop instantiated type arguments.
+  __ lw(result_reg, Address(SP, 2 * kWordSize));
+  // Drop instantiator and uninstantiated type arguments.
+  __ addiu(SP, SP, Immediate(3 * kWordSize));
+  __ Bind(&type_arguments_instantiated);
   ASSERT(instantiator_reg == result_reg);
-  // 'result_reg': Instantiated type arguments.
 }
 
 
@@ -1564,9 +1667,7 @@
   // the type arguments.
   Label type_arguments_instantiated;
   ASSERT(type_arguments().IsRawInstantiatedRaw(type_arguments().Length()));
-  __ BranchEqual(instantiator_reg,
-                 reinterpret_cast<intptr_t>(Object::null()),
-                 &type_arguments_instantiated);
+  __ beq(instantiator_reg, NULLREG, &type_arguments_instantiated);
   // Instantiate non-null type arguments.
   // In the non-factory case, we rely on the allocation stub to
   // instantiate the type arguments.
@@ -1606,8 +1707,7 @@
   // the type arguments and do not pass the instantiator.
   ASSERT(type_arguments().IsRawInstantiatedRaw(type_arguments().Length()));
   Label instantiator_not_null;
-  __ BranchNotEqual(instantiator_reg,
-      reinterpret_cast<intptr_t>(Object::null()), &instantiator_not_null);
+  __ bne(instantiator_reg, NULLREG, &instantiator_not_null);
   // Null was used in VisitExtractConstructorTypeArguments as the
   // instantiated type arguments, no proper instantiator needed.
   __ LoadImmediate(instantiator_reg,
@@ -1681,10 +1781,10 @@
         Address(FP, stacktrace_var().index() * kWordSize));
 
   Label next;
-  __ mov(T0, RA);  // Save return adress.
+  __ mov(TMP, RA);  // Save return adress.
   // Restore the pool pointer.
   __ bal(&next);  // Branch and link to next instruction to get PC in RA.
-  __ delay_slot()->mov(T1, RA);  // Save PC of the following mov.
+  __ delay_slot()->mov(CMPRES, RA);  // Save PC of the following mov.
 
   // Calculate offset of pool pointer from the PC.
   const intptr_t object_pool_pc_dist =
@@ -1692,8 +1792,8 @@
      compiler->assembler()->CodeSize();
 
   __ Bind(&next);
-  __ mov(RA, T0);  // Restore return address.
-  __ lw(PP, Address(T1, -object_pool_pc_dist));
+  __ mov(RA, TMP);  // Restore return address.
+  __ lw(PP, Address(CMPRES, -object_pool_pc_dist));
 }
 
 
@@ -1756,7 +1856,7 @@
     UNIMPLEMENTED();
     return NULL;
   } else {
-    const intptr_t kNumTemps = 0;
+    const intptr_t kNumTemps = op_kind() == Token::kADD ? 1 : 0;
     LocationSummary* summary =
         new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
     summary->set_in(0, Location::RequiresRegister());
@@ -2408,8 +2508,7 @@
   if (null_check()) {
     Label* deopt = compiler->AddDeoptStub(deopt_id(),
                                           kDeoptCheckClass);
-    __ BranchEqual(locs()->in(0).reg(),
-                  reinterpret_cast<intptr_t>(Object::null()), deopt);
+    __ beq(locs()->in(0).reg(), NULLREG, deopt);
     return;
   }
 
@@ -2608,14 +2707,6 @@
 
 void GotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   __ TraceSimMsg("GotoInstr");
-  if (!compiler->is_optimizing()) {
-    // Add deoptimization descriptor for deoptimizing instructions that may
-    // be inserted before this instruction.
-    compiler->AddCurrentDescriptor(PcDescriptors::kDeopt,
-                                   GetDeoptId(),
-                                   0);  // No token position.
-  }
-
   if (HasParallelMove()) {
     compiler->parallel_move_resolver()->EmitNativeCode(parallel_move());
   }
@@ -2662,33 +2753,13 @@
   if (compiler->CanFallThroughTo(false_successor())) {
     // If the next block is the false successor we will fall through to it.
     Label* label = compiler->GetJumpLabel(true_successor());
-    switch (true_condition) {
-      case EQ: __ beq(CMPRES, ZR, label); break;
-      case NE: __ bne(CMPRES, ZR, label); break;
-      case GT: __ bgtz(CMPRES, label); break;
-      case GE: __ bgez(CMPRES, label); break;
-      case LT: __ bltz(CMPRES, label); break;
-      case LE: __ blez(CMPRES, label); break;
-      default:
-        UNREACHABLE();
-        break;
-    }
+    EmitBranchAfterCompare(compiler, true_condition, label);
   } else {
     // If the next block is the true successor we negate comparison and fall
     // through to it.
     Condition false_condition = NegateCondition(true_condition);
     Label* label = compiler->GetJumpLabel(false_successor());
-    switch (false_condition) {
-      case EQ: __ beq(CMPRES, ZR, label); break;
-      case NE: __ bne(CMPRES, ZR, label); break;
-      case GT: __ bgtz(CMPRES, label); break;
-      case GE: __ bgez(CMPRES, label); break;
-      case LT: __ bltz(CMPRES, label); break;
-      case LE: __ blez(CMPRES, label); break;
-      default:
-        UNREACHABLE();
-        break;
-    }
+    EmitBranchAfterCompare(compiler, false_condition, label);
     // Fall through or jump to the true successor.
     if (!compiler->CanFallThroughTo(true_successor())) {
       __ b(compiler->GetJumpLabel(true_successor()));
@@ -2858,11 +2929,11 @@
   Register dest_reg = locs()->in(1).reg();
 
   if (value()->NeedsStoreBuffer()) {
-    __ StoreIntoObject(dest_reg, FieldAddress(dest_reg, offset_in_bytes()),
-                       value_reg);
+    __ StoreIntoObject(dest_reg,
+        FieldAddress(dest_reg, offset_in_bytes()), value_reg);
   } else {
-    __ StoreIntoObjectNoBarrier(
-        dest_reg, FieldAddress(dest_reg, offset_in_bytes()), value_reg);
+    __ StoreIntoObjectNoBarrier(dest_reg,
+        FieldAddress(dest_reg, offset_in_bytes()), value_reg);
   }
 }
 
diff --git a/runtime/vm/intermediate_language_x64.cc b/runtime/vm/intermediate_language_x64.cc
index 6cb751f..6318124 100644
--- a/runtime/vm/intermediate_language_x64.cc
+++ b/runtime/vm/intermediate_language_x64.cc
@@ -785,6 +785,25 @@
 }
 
 
+static Condition FlipCondition(Condition condition) {
+  switch (condition) {
+    case EQUAL:         return EQUAL;
+    case NOT_EQUAL:     return NOT_EQUAL;
+    case LESS:          return GREATER;
+    case LESS_EQUAL:    return GREATER_EQUAL;
+    case GREATER:       return LESS;
+    case GREATER_EQUAL: return LESS_EQUAL;
+    case BELOW:         return ABOVE;
+    case BELOW_EQUAL:   return ABOVE_EQUAL;
+    case ABOVE:         return BELOW;
+    case ABOVE_EQUAL:   return BELOW_EQUAL;
+    default:
+      UNIMPLEMENTED();
+      return EQUAL;
+  }
+}
+
+
 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler,
                                 const LocationSummary& locs,
                                 Token::Kind kind,
@@ -797,7 +816,7 @@
 
   if (left.IsConstant()) {
     __ CompareObject(right.reg(), left.constant());
-    true_condition = FlowGraphCompiler::FlipCondition(true_condition);
+    true_condition = FlipCondition(true_condition);
   } else if (right.IsConstant()) {
     __ CompareObject(left.reg(), right.constant());
   } else if (right.IsStackSlot()) {
@@ -1866,35 +1885,33 @@
 
   // 'instantiator_reg' is the instantiator AbstractTypeArguments object
   // (or null).
-  if (!type_arguments().IsUninstantiatedIdentity() &&
-      !type_arguments().CanShareInstantiatorTypeArguments(
-          instantiator_class())) {
-    // If the instantiator is null and if the type argument vector
-    // instantiated from null becomes a vector of dynamic, then use null as
-    // the type arguments.
-    Label type_arguments_instantiated;
-    const intptr_t len = type_arguments().Length();
-    if (type_arguments().IsRawInstantiatedRaw(len)) {
-      const Immediate& raw_null =
-          Immediate(reinterpret_cast<intptr_t>(Object::null()));
-      __ cmpq(instantiator_reg, raw_null);
-      __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump);
-    }
-    // Instantiate non-null type arguments.
-    // A runtime call to instantiate the type arguments is required.
-    __ PushObject(Object::ZoneHandle());  // Make room for the result.
-    __ PushObject(type_arguments());
-    __ pushq(instantiator_reg);  // Push instantiator type arguments.
-    compiler->GenerateCallRuntime(token_pos(),
-                                  deopt_id(),
-                                  kInstantiateTypeArgumentsRuntimeEntry,
-                                  locs());
-    __ Drop(2);  // Drop instantiator and uninstantiated type arguments.
-    __ popq(result_reg);  // Pop instantiated type arguments.
-    __ Bind(&type_arguments_instantiated);
+  ASSERT(!type_arguments().IsUninstantiatedIdentity() &&
+         !type_arguments().CanShareInstantiatorTypeArguments(
+             instantiator_class()));
+  // If the instantiator is null and if the type argument vector
+  // instantiated from null becomes a vector of dynamic, then use null as
+  // the type arguments.
+  Label type_arguments_instantiated;
+  const intptr_t len = type_arguments().Length();
+  if (type_arguments().IsRawInstantiatedRaw(len)) {
+    const Immediate& raw_null =
+        Immediate(reinterpret_cast<intptr_t>(Object::null()));
+    __ cmpq(instantiator_reg, raw_null);
+    __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump);
   }
+  // Instantiate non-null type arguments.
+  // A runtime call to instantiate the type arguments is required.
+  __ PushObject(Object::ZoneHandle());  // Make room for the result.
+  __ PushObject(type_arguments());
+  __ pushq(instantiator_reg);  // Push instantiator type arguments.
+  compiler->GenerateCallRuntime(token_pos(),
+                                deopt_id(),
+                                kInstantiateTypeArgumentsRuntimeEntry,
+                                locs());
+  __ Drop(2);  // Drop instantiator and uninstantiated type arguments.
+  __ popq(result_reg);  // Pop instantiated type arguments.
+  __ Bind(&type_arguments_instantiated);
   ASSERT(instantiator_reg == result_reg);
-  // 'result_reg': Instantiated type arguments.
 }
 
 
@@ -2167,11 +2184,7 @@
         __ j(NEGATIVE, deopt);
         return;
       }
-      intptr_t tmp = (left_int > 0) ? left_int : ~left_int;
-      intptr_t max_right = kSmiBits;
-      while ((tmp >>= 1) != 0) {
-        max_right--;
-      }
+      const intptr_t max_right = kSmiBits - Utils::HighestBit(left_int);
       const bool right_needs_check =
           (right_range == NULL) ||
           !right_range->IsWithin(0, max_right - 1);
@@ -2303,7 +2316,12 @@
     LocationSummary* summary =
         new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
     summary->set_in(0, Location::RequiresRegister());
-    summary->set_in(1, Location::RegisterOrSmiConstant(right()));
+    ConstantInstr* constant = right()->definition()->AsConstant();
+    if (constant != NULL) {
+      summary->set_in(1, Location::RegisterOrSmiConstant(right()));
+    } else {
+      summary->set_in(1, Location::PrefersRegister());
+    }
     summary->set_out(Location::SameAsFirstInput());
     return summary;
   }
@@ -2427,8 +2445,51 @@
         break;
     }
     return;
-  }
+  }  // locs()->in(1).IsConstant().
 
+
+  if (locs()->in(1).IsStackSlot()) {
+    const Address& right = locs()->in(1).ToStackSlotAddress();
+    switch (op_kind()) {
+      case Token::kADD: {
+        __ addq(left, right);
+        if (deopt != NULL) __ j(OVERFLOW, deopt);
+        break;
+      }
+      case Token::kSUB: {
+        __ subq(left, right);
+        if (deopt != NULL) __ j(OVERFLOW, deopt);
+        break;
+      }
+      case Token::kMUL: {
+        __ SmiUntag(left);
+        __ imulq(left, right);
+        if (deopt != NULL) __ j(OVERFLOW, deopt);
+        break;
+      }
+      case Token::kBIT_AND: {
+        // No overflow check.
+        __ andq(left, right);
+        break;
+      }
+      case Token::kBIT_OR: {
+        // No overflow check.
+        __ orq(left, right);
+        break;
+      }
+      case Token::kBIT_XOR: {
+        // No overflow check.
+        __ xorq(left, right);
+        break;
+      }
+      default:
+        UNREACHABLE();
+        break;
+    }
+    return;
+  }  // locs()->in(1).IsStackSlot().
+
+  // if locs()->in(1).IsRegister.
   Register right = locs()->in(1).reg();
   switch (op_kind()) {
     case Token::kADD: {
@@ -4069,14 +4130,6 @@
 
 
 void GotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  if (!compiler->is_optimizing()) {
-    // Add deoptimization descriptor for deoptimizing instructions that may
-    // be inserted before this instruction.
-    compiler->AddCurrentDescriptor(PcDescriptors::kDeopt,
-                                   GetDeoptId(),
-                                   0);  // No token position.
-  }
-
   if (HasParallelMove()) {
     compiler->parallel_move_resolver()->EmitNativeCode(parallel_move());
   }
diff --git a/runtime/vm/intrinsifier_arm.cc b/runtime/vm/intrinsifier_arm.cc
index 49d87c0..694f64b 100644
--- a/runtime/vm/intrinsifier_arm.cc
+++ b/runtime/vm/intrinsifier_arm.cc
@@ -6,297 +6,1362 @@
 #if defined(TARGET_ARCH_ARM)
 
 #include "vm/intrinsifier.h"
+
+#include "vm/assembler.h"
+#include "vm/flow_graph_compiler.h"
 #include "vm/object.h"
+#include "vm/object_store.h"
+#include "vm/symbols.h"
 
 namespace dart {
 
+DECLARE_FLAG(bool, enable_type_checks);
+
+
+#define __ assembler->
+
 bool Intrinsifier::ObjectArray_Allocate(Assembler* assembler) {
+  const intptr_t kTypeArgumentsOffset = 1 * kWordSize;
+  const intptr_t kArrayLengthOffset = 0 * kWordSize;
+  Label fall_through;
+
+  // Compute the size to be allocated, it is based on the array length
+  // and is computed as:
+  // RoundedAllocationSize((array_length * kwordSize) + sizeof(RawArray)).
+  __ ldr(R3, Address(SP, kArrayLengthOffset));  // Array length.
+
+  // Check that length is a positive Smi.
+  __ tst(R3, ShifterOperand(kSmiTagMask));
+  __ b(&fall_through, NE);
+  __ cmp(R3, ShifterOperand(0));
+  __ b(&fall_through, LT);
+
+  // Check for maximum allowed length.
+  const intptr_t max_len =
+      reinterpret_cast<int32_t>(Smi::New(Array::kMaxElements));
+  __ CompareImmediate(R3, max_len);
+  __ b(&fall_through, GT);
+
+  const intptr_t fixed_size = sizeof(RawArray) + kObjectAlignment - 1;
+  __ LoadImmediate(R2, fixed_size);
+  __ add(R2, R2, ShifterOperand(R3, LSL, 1));  // R3 is  a Smi.
+  ASSERT(kSmiTagShift == 1);
+  __ bic(R2, R2, ShifterOperand(kObjectAlignment - 1));
+
+  // R2: Allocation size.
+
+  Isolate* isolate = Isolate::Current();
+  Heap* heap = isolate->heap();
+
+  __ LoadImmediate(R6, heap->TopAddress());
+  __ ldr(R0, Address(R6, 0));  // Potential new object start.
+  __ adds(R1, R0, ShifterOperand(R2));  // Potential next object start.
+  __ b(&fall_through, VS);
+
+  // Check if the allocation fits into the remaining space.
+  // R0: potential new object start.
+  // R1: potential next object start.
+  // R2: allocation size.
+  __ LoadImmediate(R3, heap->EndAddress());
+  __ ldr(R3, Address(R3, 0));
+  __ cmp(R1, ShifterOperand(R3));
+  __ b(&fall_through, CS);
+
+  // Successfully allocated the object(s), now update top to point to
+  // next object start and initialize the object.
+  __ str(R1, Address(R6, 0));
+  __ add(R0, R0, ShifterOperand(kHeapObjectTag));
+
+  // Initialize the tags.
+  // R0: new object start as a tagged pointer.
+  // R1: new object end address.
+  // R2: allocation size.
+  {
+    const intptr_t shift = RawObject::kSizeTagBit - kObjectAlignmentLog2;
+    const Class& cls = Class::Handle(isolate->object_store()->array_class());
+
+    __ CompareImmediate(R2, RawObject::SizeTag::kMaxSizeTag);
+    __ mov(R2, ShifterOperand(R2, LSL, shift), LS);
+    __ mov(R2, ShifterOperand(0), HI);
+
+    // Get the class index and insert it into the tags.
+    // R2: size and bit tags.
+    __ LoadImmediate(TMP, RawObject::ClassIdTag::encode(cls.id()));
+    __ orr(R2, R2, ShifterOperand(TMP));
+    __ str(R2, FieldAddress(R0, Array::tags_offset()));  // Store tags.
+  }
+
+  // R0: new object start as a tagged pointer.
+  // R1: new object end address.
+  // Store the type argument field.
+  __ ldr(R2, Address(SP, kTypeArgumentsOffset));  // Type argument.
+  __ StoreIntoObjectNoBarrier(R0,
+                              FieldAddress(R0, Array::type_arguments_offset()),
+                              R2);
+
+  // Set the length field.
+  __ ldr(R2, Address(SP, kArrayLengthOffset));  // Array Length.
+  __ StoreIntoObjectNoBarrier(R0,
+                              FieldAddress(R0, Array::length_offset()),
+                              R2);
+
+  // Initialize all array elements to raw_null.
+  // R0: new object start as a tagged pointer.
+  // R1: new object end address.
+  // R2: iterator which initially points to the start of the variable
+  // data area to be initialized.
+  // R3: null
+  __ LoadImmediate(R3, reinterpret_cast<intptr_t>(Object::null()));
+  __ AddImmediate(R2, R0, sizeof(RawArray) - kHeapObjectTag);
+
+  Label init_loop;
+  __ Bind(&init_loop);
+  __ cmp(R2, ShifterOperand(R1));
+  __ str(R3, Address(R2, 0), CC);
+  __ AddImmediate(R2, kWordSize, CC);
+  __ b(&init_loop, CC);
+
+  __ Ret();  // Returns the newly allocated object in R0.
+  __ Bind(&fall_through);
   return false;
 }
 
 
 bool Intrinsifier::Array_getLength(Assembler* assembler) {
-  return false;
+  __ ldr(R0, Address(SP, 0 * kWordSize));
+  __ ldr(R0, FieldAddress(R0, Array::length_offset()));
+  __ Ret();
+  return true;
 }
 
 
 bool Intrinsifier::ImmutableArray_getLength(Assembler* assembler) {
-  return false;
+  return Array_getLength(assembler);
 }
 
 
 bool Intrinsifier::Array_getIndexed(Assembler* assembler) {
+  Label fall_through;
+
+  __ ldr(R0, Address(SP, + 0 * kWordSize));  // Index
+  __ ldr(R1, Address(SP, + 1 * kWordSize));  // Array
+
+  __ tst(R0, ShifterOperand(kSmiTagMask));
+  __ b(&fall_through, NE);  // Index is not an smi, fall through
+
+  // range check
+  __ ldr(R6, FieldAddress(R1, Array::length_offset()));
+  __ cmp(R0, ShifterOperand(R6));
+
+  ASSERT(kSmiTagShift == 1);
+  // array element at R1 + R0*2 + Array::data_offset - 1
+  __ add(R6, R1, ShifterOperand(R0, LSL, 1), CC);
+  __ ldr(R0, FieldAddress(R6, Array::data_offset()), CC);
+  __ bx(LR, CC);
+  __ Bind(&fall_through);
   return false;
 }
 
 
 bool Intrinsifier::ImmutableArray_getIndexed(Assembler* assembler) {
-  return false;
+  return Array_getIndexed(assembler);
 }
 
 
+static intptr_t ComputeObjectArrayTypeArgumentsOffset() {
+  const Library& core_lib = Library::Handle(Library::CoreLibrary());
+  const Class& cls =
+      Class::Handle(core_lib.LookupClassAllowPrivate(Symbols::ObjectArray()));
+  ASSERT(!cls.IsNull());
+  ASSERT(cls.HasTypeArguments());
+  ASSERT(cls.NumTypeArguments() == 1);
+  const intptr_t field_offset = cls.type_arguments_field_offset();
+  ASSERT(field_offset != Class::kNoTypeArguments);
+  return field_offset;
+}
+
+
+// Intrinsify only for Smi value and index. Non-smi values need a store buffer
+// update. Array length is always a Smi.
 bool Intrinsifier::Array_setIndexed(Assembler* assembler) {
+  Label fall_through;
+
+  if (FLAG_enable_type_checks) {
+    const intptr_t type_args_field_offset =
+        ComputeObjectArrayTypeArgumentsOffset();
+    // Inline simple tests (Smi, null), fallthrough if not positive.
+    const int32_t raw_null = reinterpret_cast<intptr_t>(Object::null());
+    Label checked_ok;
+    __ ldr(R2, Address(SP, 0 * kWordSize));  // Value.
+
+    // Null value is valid for any type.
+    __ CompareImmediate(R2, raw_null);
+    __ b(&checked_ok, EQ);
+
+    __ ldr(R1, Address(SP, 2 * kWordSize));  // Array.
+    __ ldr(R1, FieldAddress(R1, type_args_field_offset));
+
+    // R1: Type arguments of array.
+    __ CompareImmediate(R1, raw_null);
+    __ b(&checked_ok, EQ);
+
+    // Check if it's dynamic.
+    // For now handle only TypeArguments and bail out if InstantiatedTypeArgs.
+    __ CompareClassId(R1, kTypeArgumentsCid, R0);
+    __ b(&fall_through, NE);
+    // Get type at index 0.
+    __ ldr(R0, FieldAddress(R1, TypeArguments::type_at_offset(0)));
+    __ CompareObject(R0, Type::ZoneHandle(Type::DynamicType()));
+    __ b(&checked_ok, EQ);
+
+    // Check for int and num.
+    __ tst(R2, ShifterOperand(kSmiTagMask));  // Value is Smi?
+    __ b(&fall_through, NE);  // Non-smi value.
+    __ CompareObject(R0, Type::ZoneHandle(Type::IntType()));
+    __ b(&checked_ok, EQ);
+    __ CompareObject(R0, Type::ZoneHandle(Type::Number()));
+    __ b(&fall_through, NE);
+    __ Bind(&checked_ok);
+  }
+  __ ldr(R1, Address(SP, 1 * kWordSize));  // Index.
+  __ tst(R1, ShifterOperand(kSmiTagMask));
+  // Index not Smi.
+  __ b(&fall_through, NE);
+  __ ldr(R0, Address(SP, 2 * kWordSize));  // Array.
+
+  // Range check.
+  __ ldr(R3, FieldAddress(R0, Array::length_offset()));  // Array length.
+  __ cmp(R1, ShifterOperand(R3));
+  // Runtime throws exception.
+  __ b(&fall_through, CS);
+
+  // Note that R1 is Smi, i.e, times 2.
+  ASSERT(kSmiTagShift == 1);
+  // Destroy R2 as we will not continue in the function.
+  __ ldr(R2, Address(SP, 0 * kWordSize));  // Value.
+  __ add(R1, R0, ShifterOperand(R1, LSL, 1));  // R1 is Smi.
+  __ StoreIntoObject(R0,
+                     FieldAddress(R1, Array::data_offset()),
+                     R2);
+  // Caller is responsible of preserving the value if necessary.
+  __ Ret();
+  __ Bind(&fall_through);
   return false;
 }
 
 
+// Allocate a GrowableObjectArray using the backing array specified.
+// On stack: type argument (+1), data (+0).
 bool Intrinsifier::GrowableArray_Allocate(Assembler* assembler) {
+  // The newly allocated object is returned in R0.
+  const intptr_t kTypeArgumentsOffset = 1 * kWordSize;
+  const intptr_t kArrayOffset = 0 * kWordSize;
+  Label fall_through;
+
+  // Compute the size to be allocated, it is based on the array length
+  // and is computed as:
+  // RoundedAllocationSize(sizeof(RawGrowableObjectArray)) +
+  intptr_t fixed_size = GrowableObjectArray::InstanceSize();
+
+  Isolate* isolate = Isolate::Current();
+  Heap* heap = isolate->heap();
+
+  __ LoadImmediate(R2, heap->TopAddress());
+  __ ldr(R0, Address(R2, 0));
+  __ AddImmediate(R1, R0, fixed_size);
+
+  // Check if the allocation fits into the remaining space.
+  // R0: potential new backing array object start.
+  // R1: potential next object start.
+  __ LoadImmediate(R3, heap->EndAddress());
+  __ ldr(R3, Address(R3, 0));
+  __ cmp(R1, ShifterOperand(R3));
+  __ b(&fall_through, CS);
+
+  // Successfully allocated the object(s), now update top to point to
+  // next object start and initialize the object.
+  __ str(R1, Address(R2, 0));
+  __ AddImmediate(R0, kHeapObjectTag);
+
+  // Initialize the tags.
+  // R0: new growable array object start as a tagged pointer.
+  const Class& cls = Class::Handle(
+      isolate->object_store()->growable_object_array_class());
+  uword tags = 0;
+  tags = RawObject::SizeTag::update(fixed_size, tags);
+  tags = RawObject::ClassIdTag::update(cls.id(), tags);
+  __ LoadImmediate(R1, tags);
+  __ str(R1, FieldAddress(R0, GrowableObjectArray::tags_offset()));
+
+  // Store backing array object in growable array object.
+  __ ldr(R1, Address(SP, kArrayOffset));  // Data argument.
+  // R0 is new, no barrier needed.
+  __ StoreIntoObjectNoBarrier(
+      R0,
+      FieldAddress(R0, GrowableObjectArray::data_offset()),
+      R1);
+
+  // R0: new growable array object start as a tagged pointer.
+  // Store the type argument field in the growable array object.
+  __ ldr(R1, Address(SP, kTypeArgumentsOffset));  // Type argument.
+  __ StoreIntoObjectNoBarrier(
+      R0,
+      FieldAddress(R0, GrowableObjectArray::type_arguments_offset()),
+      R1);
+
+  // Set the length field in the growable array object to 0.
+  __ LoadImmediate(R1, 0);
+  __ str(R1, FieldAddress(R0, GrowableObjectArray::length_offset()));
+  __ Ret();  // Returns the newly allocated object in R0.
+
+  __ Bind(&fall_through);
   return false;
 }
 
 
 bool Intrinsifier::GrowableArray_getLength(Assembler* assembler) {
-  return false;
+  __ ldr(R0, Address(SP, 0 * kWordSize));
+  __ ldr(R0, FieldAddress(R0, GrowableObjectArray::length_offset()));
+  __ Ret();
+  return true;
 }
 
 
 bool Intrinsifier::GrowableArray_getCapacity(Assembler* assembler) {
-  return false;
+  __ ldr(R0, Address(SP, 0 * kWordSize));
+  __ ldr(R0, FieldAddress(R0, GrowableObjectArray::data_offset()));
+  __ ldr(R0, FieldAddress(R0, Array::length_offset()));
+  __ Ret();
+  return true;
 }
 
 
 bool Intrinsifier::GrowableArray_getIndexed(Assembler* assembler) {
+  Label fall_through;
+
+  __ ldr(R0, Address(SP, + 0 * kWordSize));  // Index
+  __ ldr(R1, Address(SP, + 1 * kWordSize));  // Array
+
+  __ tst(R0, ShifterOperand(kSmiTagMask));
+  __ b(&fall_through, NE);  // Index is not an smi, fall through
+
+  // range check
+  __ ldr(R6, FieldAddress(R1, GrowableObjectArray::length_offset()));
+  __ cmp(R0, ShifterOperand(R6));
+
+  ASSERT(kSmiTagShift == 1);
+  // array element at R6 + R0 * 2 + Array::data_offset - 1
+  __ ldr(R6, FieldAddress(R1, GrowableObjectArray::data_offset()), CC);  // data
+  __ add(R6, R6, ShifterOperand(R0, LSL, 1), CC);
+  __ ldr(R0, FieldAddress(R6, Array::data_offset()), CC);
+  __ bx(LR, CC);
+  __ Bind(&fall_through);
   return false;
 }
 
 
+// Set value into growable object array at specified index.
+// On stack: growable array (+2), index (+1), value (+0).
 bool Intrinsifier::GrowableArray_setIndexed(Assembler* assembler) {
+  if (FLAG_enable_type_checks) {
+    return false;
+  }
+  Label fall_through;
+  __ ldr(R1, Address(SP, 1 * kWordSize));  // Index.
+  __ ldr(R0, Address(SP, 2 * kWordSize));  // GrowableArray.
+  __ tst(R1, ShifterOperand(kSmiTagMask));
+  __ b(&fall_through, NE);  // Non-smi index.
+  // Range check using _length field.
+  __ ldr(R2, FieldAddress(R0, GrowableObjectArray::length_offset()));
+  __ cmp(R1, ShifterOperand(R2));
+  // Runtime throws exception.
+  __ b(&fall_through, CS);
+  __ ldr(R0, FieldAddress(R0, GrowableObjectArray::data_offset()));  // data.
+  __ ldr(R2, Address(SP, 0 * kWordSize));  // Value.
+  // Note that R1 is Smi, i.e, times 2.
+  ASSERT(kSmiTagShift == 1);
+  __ add(R1, R0, ShifterOperand(R1, LSL, 1));
+  __ StoreIntoObject(R0,
+                     FieldAddress(R1, Array::data_offset()),
+                     R2);
+  __ Ret();
+  __ Bind(&fall_through);
   return false;
 }
 
 
+// Set length of growable object array. The length cannot
+// be greater than the length of the data container.
+// On stack: growable array (+1), length (+0).
 bool Intrinsifier::GrowableArray_setLength(Assembler* assembler) {
+  __ ldr(R0, Address(SP, 1 * kWordSize));  // Growable array.
+  __ ldr(R1, Address(SP, 0 * kWordSize));  // Length value.
+  __ tst(R1, ShifterOperand(kSmiTagMask));  // Check for Smi.
+  __ str(R1, FieldAddress(R0, GrowableObjectArray::length_offset()), EQ);
+  __ bx(LR, EQ);
+  // Fall through on non-Smi.
   return false;
 }
 
 
+// Set data of growable object array.
+// On stack: growable array (+1), data (+0).
 bool Intrinsifier::GrowableArray_setData(Assembler* assembler) {
+  if (FLAG_enable_type_checks) {
+    return false;
+  }
+  Label fall_through;
+  __ ldr(R1, Address(SP, 0 * kWordSize));  // Data.
+  // Check that data is an ObjectArray.
+  __ tst(R1, ShifterOperand(kSmiTagMask));
+  __ b(&fall_through, EQ);  // Data is Smi.
+  __ CompareClassId(R1, kArrayCid, R0);
+  __ b(&fall_through, NE);
+  __ ldr(R0, Address(SP, 1 * kWordSize));  // Growable array.
+  __ StoreIntoObject(R0,
+                     FieldAddress(R0, GrowableObjectArray::data_offset()),
+                     R1);
+  __ Ret();
+  __ Bind(&fall_through);
   return false;
 }
 
 
+// Add an element to growable array if it doesn't need to grow, otherwise
+// call into regular code.
+// On stack: growable array (+1), value (+0).
 bool Intrinsifier::GrowableArray_add(Assembler* assembler) {
+  // In checked mode we need to type-check the incoming argument.
+  if (FLAG_enable_type_checks) return false;
+  Label fall_through;
+  // R0: Array.
+  __ ldr(R0, Address(SP, 1 * kWordSize));
+  // R1: length.
+  __ ldr(R1, FieldAddress(R0, GrowableObjectArray::length_offset()));
+  // R2: data.
+  __ ldr(R2, FieldAddress(R0, GrowableObjectArray::data_offset()));
+  // R3: capacity.
+  __ ldr(R3, FieldAddress(R2, Array::length_offset()));
+  // Compare length with capacity.
+  __ cmp(R1, ShifterOperand(R3));
+  __ b(&fall_through, EQ);  // Must grow data.
+  const int32_t value_one = reinterpret_cast<int32_t>(Smi::New(1));
+  // len = len + 1;
+  __ add(R3, R1, ShifterOperand(value_one));
+  __ str(R3, FieldAddress(R0, GrowableObjectArray::length_offset()));
+  __ ldr(R0, Address(SP, 0 * kWordSize));  // Value.
+  ASSERT(kSmiTagShift == 1);
+  __ add(R1, R2, ShifterOperand(R1, LSL, 1));
+  __ StoreIntoObject(R2,
+                     FieldAddress(R1, Array::data_offset()),
+                     R0);
+  const int32_t raw_null = reinterpret_cast<int32_t>(Object::null());
+  __ LoadImmediate(R0, raw_null);
+  __ Ret();
+  __ Bind(&fall_through);
   return false;
 }
 
 
+#define TYPED_ARRAY_ALLOCATION(type_name, cid, max_len, scale_shift)           \
+  Label fall_through;                                                          \
+  const intptr_t kArrayLengthStackOffset = 0 * kWordSize;                      \
+  __ ldr(R2, Address(SP, kArrayLengthStackOffset));  /* Array length. */       \
+  /* Check that length is a positive Smi. */                                   \
+  /* R2: requested array length argument. */                                   \
+  __ tst(R2, ShifterOperand(kSmiTagMask));                                     \
+  __ b(&fall_through, NE);                                                     \
+  __ CompareImmediate(R2, 0);                                                  \
+  __ b(&fall_through, LT);                                                     \
+  __ SmiUntag(R2);                                                             \
+  /* Check for maximum allowed length. */                                      \
+  /* R2: untagged array length. */                                             \
+  __ CompareImmediate(R2, max_len);                                            \
+  __ b(&fall_through, GT);                                                     \
+  __ mov(R2, ShifterOperand(R2, LSL, scale_shift));                            \
+  const intptr_t fixed_size = sizeof(Raw##type_name) + kObjectAlignment - 1;   \
+  __ AddImmediate(R2, fixed_size);                                             \
+  __ bic(R2, R2, ShifterOperand(kObjectAlignment - 1));                        \
+  Heap* heap = Isolate::Current()->heap();                                     \
+                                                                               \
+  __ LoadImmediate(R0, heap->TopAddress());                                    \
+  __ ldr(R0, Address(R0, 0));                                                  \
+                                                                               \
+  /* R2: allocation size. */                                                   \
+  __ add(R1, R0, ShifterOperand(R2));                                          \
+  __ b(&fall_through, VS);                                                     \
+                                                                               \
+  /* Check if the allocation fits into the remaining space. */                 \
+  /* R0: potential new object start. */                                        \
+  /* R1: potential next object start. */                                       \
+  /* R2: allocation size. */                                                   \
+  __ LoadImmediate(R3, heap->EndAddress());                                    \
+  __ ldr(R3, Address(R3, 0));                                                  \
+  __ cmp(R1, ShifterOperand(R3));                                              \
+  __ b(&fall_through, CS);                                                     \
+                                                                               \
+  /* Successfully allocated the object(s), now update top to point to */       \
+  /* next object start and initialize the object. */                           \
+  __ LoadImmediate(R3, heap->TopAddress());                                    \
+  __ str(R1, Address(R3, 0));                                                  \
+  __ AddImmediate(R0, kHeapObjectTag);                                         \
+                                                                               \
+  /* Initialize the tags. */                                                   \
+  /* R0: new object start as a tagged pointer. */                              \
+  /* R1: new object end address. */                                            \
+  /* R2: allocation size. */                                                   \
+  {                                                                            \
+    __ CompareImmediate(R2, RawObject::SizeTag::kMaxSizeTag);                  \
+    __ mov(R2, ShifterOperand(R2, LSL,                                         \
+        RawObject::kSizeTagBit - kObjectAlignmentLog2), LS);                   \
+    __ mov(R2, ShifterOperand(0), HI);                                         \
+                                                                               \
+    /* Get the class index and insert it into the tags. */                     \
+    __ LoadImmediate(TMP, RawObject::ClassIdTag::encode(cid));                 \
+    __ orr(R2, R2, ShifterOperand(TMP));                                       \
+    __ str(R2, FieldAddress(R0, type_name::tags_offset()));  /* Tags. */       \
+  }                                                                            \
+  /* Set the length field. */                                                  \
+  /* R0: new object start as a tagged pointer. */                              \
+  /* R1: new object end address. */                                            \
+  __ ldr(R2, Address(SP, kArrayLengthStackOffset));  /* Array length. */       \
+  __ StoreIntoObjectNoBarrier(R0,                                              \
+                              FieldAddress(R0, type_name::length_offset()),    \
+                              R2);                                             \
+  /* Initialize all array elements to 0. */                                    \
+  /* R0: new object start as a tagged pointer. */                              \
+  /* R1: new object end address. */                                            \
+  /* R2: iterator which initially points to the start of the variable */       \
+  /* R3: scratch register. */                                                  \
+  /* data area to be initialized. */                                           \
+  __ LoadImmediate(R3, 0);                                                     \
+  __ AddImmediate(R2, R0, sizeof(Raw##type_name) - 1);                         \
+  Label init_loop;                                                             \
+  __ Bind(&init_loop);                                                         \
+  __ cmp(R2, ShifterOperand(R1));                                              \
+  __ str(R3, Address(R2, 0), CC);                                              \
+  __ add(R2, R2, ShifterOperand(kWordSize), CC);                               \
+  __ b(&init_loop, CC);                                                        \
+                                                                               \
+  __ Ret();                                                                    \
+  __ Bind(&fall_through);                                                      \
+
+
+// Gets the length of a TypedData.
 bool Intrinsifier::TypedData_getLength(Assembler* assembler) {
-  return false;
+  __ ldr(R0, Address(SP, 0 * kWordSize));
+  __ ldr(R0, FieldAddress(R0, TypedData::length_offset()));
+  __ Ret();
+  return true;
 }
 
 
+static int GetScaleFactor(intptr_t size) {
+  switch (size) {
+    case 1: return 0;
+    case 2: return 1;
+    case 4: return 2;
+    case 8: return 3;
+    case 16: return 4;
+  }
+  UNREACHABLE();
+  return -1;
+};
+
+
 #define TYPED_DATA_ALLOCATOR(clazz)                                            \
 bool Intrinsifier::TypedData_##clazz##_new(Assembler* assembler) {             \
+  intptr_t size = TypedData::ElementSizeInBytes(kTypedData##clazz##Cid);       \
+  intptr_t max_len = TypedData::MaxElements(kTypedData##clazz##Cid);           \
+  int shift = GetScaleFactor(size);                                            \
+  TYPED_ARRAY_ALLOCATION(TypedData, kTypedData##clazz##Cid, max_len, shift);   \
   return false;                                                                \
 }                                                                              \
 bool Intrinsifier::TypedData_##clazz##_factory(Assembler* assembler) {         \
+  intptr_t size = TypedData::ElementSizeInBytes(kTypedData##clazz##Cid);       \
+  intptr_t max_len = TypedData::MaxElements(kTypedData##clazz##Cid);           \
+  int shift = GetScaleFactor(size);                                            \
+  TYPED_ARRAY_ALLOCATION(TypedData, kTypedData##clazz##Cid, max_len, shift);   \
   return false;                                                                \
 }
 CLASS_LIST_TYPED_DATA(TYPED_DATA_ALLOCATOR)
 #undef TYPED_DATA_ALLOCATOR
 
 
+// Loads args from stack into R0 and R1
+// Tests if they are smis, jumps to label not_smi if not.
+static void TestBothArgumentsSmis(Assembler* assembler, Label* not_smi) {
+  __ ldr(R0, Address(SP, + 0 * kWordSize));
+  __ ldr(R1, Address(SP, + 1 * kWordSize));
+  __ orr(TMP, R0, ShifterOperand(R1));
+  __ tst(TMP, ShifterOperand(kSmiTagMask));
+  __ b(not_smi, NE);
+  return;
+}
+
+
 bool Intrinsifier::Integer_addFromInteger(Assembler* assembler) {
+  Label fall_through;
+  TestBothArgumentsSmis(assembler, &fall_through);  // Checks two smis.
+  __ adds(R0, R0, ShifterOperand(R1));  // Adds.
+  __ bx(LR, VC);  // Return if no overflow.
+  // Otherwise fall through.
+  __ Bind(&fall_through);
   return false;
 }
 
 
 bool Intrinsifier::Integer_add(Assembler* assembler) {
-  return false;
+  return Integer_addFromInteger(assembler);
 }
 
 
 bool Intrinsifier::Integer_subFromInteger(Assembler* assembler) {
+  Label fall_through;
+  TestBothArgumentsSmis(assembler, &fall_through);
+  __ subs(R0, R0, ShifterOperand(R1));  // Subtract.
+  __ bx(LR, VC);  // Return if no overflow.
+  // Otherwise fall through.
+  __ Bind(&fall_through);
   return false;
 }
 
 
 bool Intrinsifier::Integer_sub(Assembler* assembler) {
+  Label fall_through;
+  TestBothArgumentsSmis(assembler, &fall_through);
+  __ subs(R0, R1, ShifterOperand(R0));  // Subtract.
+  __ bx(LR, VC);  // Return if no overflow.
+  // Otherwise fall through.
+  __ Bind(&fall_through);
   return false;
 }
 
 
 bool Intrinsifier::Integer_mulFromInteger(Assembler* assembler) {
+  Label fall_through;
+
+  TestBothArgumentsSmis(assembler, &fall_through);  // checks two smis
+  __ SmiUntag(R0);  // untags R6. only want result shifted by one
+
+  __ smull(R0, IP, R0, R1);  // IP:R0 <- R0 * R1.
+  __ cmp(IP, ShifterOperand(R0, ASR, 31));
+  __ bx(LR, EQ);
+  __ Bind(&fall_through);  // Fall through on overflow.
   return false;
 }
 
 
 bool Intrinsifier::Integer_mul(Assembler* assembler) {
-  return false;
+  return Integer_mulFromInteger(assembler);
 }
 
 
+// Optimizations:
+// - result is 0 if:
+//   - left is 0
+//   - left equals right
+// - result is left if
+//   - left > 0 && left < right
+// R1: Tagged left (dividend).
+// R0: Tagged right (divisor).
+// Returns with result in R0, OR:
+//   R1: Untagged result (remainder).
+static void EmitRemainderOperation(Assembler* assembler) {
+  Label modulo;
+  const Register left = R1;
+  const Register right = R0;
+  const Register result = R1;
+  ASSERT(left == result);
+
+  // Check for quick zero results.
+  __ cmp(left, ShifterOperand(0));
+  __ mov(R0, ShifterOperand(0), EQ);
+  __ bx(LR, EQ);  // left is 0? Return 0.
+  __ cmp(left, ShifterOperand(right));
+  __ mov(R0, ShifterOperand(0), EQ);
+  __ bx(LR, EQ);  // left == right? Return 0.
+
+  // Check if result should be left.
+  __ cmp(left, ShifterOperand(0));
+  __ b(&modulo, LT);
+  // left is positive.
+  __ cmp(left, ShifterOperand(right));
+  // left is less than right, result is left.
+  __ mov(R0, ShifterOperand(left), LT);
+  __ bx(LR, LT);
+
+  __ Bind(&modulo);
+  // result <- left - right * (left / right)
+  __ SmiUntag(left);
+  __ SmiUntag(right);
+  __ sdiv(TMP, left, right);  // TMP <- left / right
+  __ mls(result, right, TMP, left);  // result <- left - right * TMP
+  return;
+}
+
+
+// Implementation:
+//  res = left % right;
+//  if (res < 0) {
+//    if (right < 0) {
+//      res = res - right;
+//    } else {
+//      res = res + right;
+//    }
+//  }
 bool Intrinsifier::Integer_modulo(Assembler* assembler) {
+  // Check to see if we have integer division
+  if (!CPUFeatures::integer_division_supported())
+    return false;
+
+  Label fall_through, subtract;
+  TestBothArgumentsSmis(assembler, &fall_through);
+  // R1: Tagged left (dividend).
+  // R0: Tagged right (divisor).
+  // Check if modulo by zero -> exception thrown in main function.
+  __ cmp(R0, ShifterOperand(0));
+  __ b(&fall_through, EQ);
+  EmitRemainderOperation(assembler);
+  // Untagged right in R0. Untagged remainder result in R1.
+
+  __ cmp(R1, ShifterOperand(0));
+  __ mov(R0, ShifterOperand(R1, LSL, 1), GE);  // Tag and move result to R0.
+  __ bx(LR, GE);
+
+  // Result is negative, adjust it.
+  __ cmp(R0, ShifterOperand(0));
+  __ sub(R0, R1, ShifterOperand(R0), LT);
+  __ add(R0, R1, ShifterOperand(R0), GE);
+  __ SmiTag(R0);
+  __ Ret();
+
+  __ Bind(&fall_through);
   return false;
 }
 
 
 bool Intrinsifier::Integer_remainder(Assembler* assembler) {
+  // Check to see if we have integer division
+  if (!CPUFeatures::integer_division_supported())
+    return false;
+
+  Label fall_through;
+  TestBothArgumentsSmis(assembler, &fall_through);
+  // R1: Tagged left (dividend).
+  // R0: Tagged right (divisor).
+  // Check if modulo by zero -> exception thrown in main function.
+  __ cmp(R0, ShifterOperand(0));
+  __ b(&fall_through, EQ);
+  EmitRemainderOperation(assembler);
+  // Untagged remainder result in R1.
+  __ mov(R0, ShifterOperand(R1, LSL, 1));  // Tag result and return.
+  __ Ret();
+
+  __ Bind(&fall_through);
   return false;
 }
 
 
 bool Intrinsifier::Integer_truncDivide(Assembler* assembler) {
+  // Check to see if we have integer division
+  if (!CPUFeatures::integer_division_supported())
+    return false;
+
+  Label fall_through;
+
+  TestBothArgumentsSmis(assembler, &fall_through);
+  __ cmp(R0, ShifterOperand(0));
+  __ b(&fall_through, EQ);  // If b is 0, fall through.
+
+  __ SmiUntag(R0);
+  __ SmiUntag(R1);
+  __ sdiv(R0, R1, R0);
+  // Check the corner case of dividing the 'MIN_SMI' with -1, in which case we
+  // cannot tag the result.
+  __ CompareImmediate(R0, 0x40000000);
+  __ SmiTag(R0, NE);  // Not equal. Okay to tag and return.
+  __ bx(LR, NE);  // Return.
+  __ Bind(&fall_through);
   return false;
 }
 
 
 bool Intrinsifier::Integer_negate(Assembler* assembler) {
+  __ ldr(R0, Address(SP, + 0 * kWordSize));  // Grab first argument.
+  __ tst(R0, ShifterOperand(kSmiTagMask));  // Test for Smi.
+  __ rsb(R0, R0, ShifterOperand(0), EQ);  // R0 is a Smi. R0 <- 0 - R0.
+  __ bx(LR, EQ);  // Return.
+  // R0 is not a Smi. Fall through.
   return false;
 }
 
 
 bool Intrinsifier::Integer_bitAndFromInteger(Assembler* assembler) {
+  Label fall_through;
+
+  TestBothArgumentsSmis(assembler, &fall_through);  // checks two smis
+  __ and_(R0, R0, ShifterOperand(R1));
+
+  __ Ret();
+  __ Bind(&fall_through);
   return false;
 }
 
 
 bool Intrinsifier::Integer_bitAnd(Assembler* assembler) {
-  return false;
+  return Integer_bitAndFromInteger(assembler);
 }
 
 
 bool Intrinsifier::Integer_bitOrFromInteger(Assembler* assembler) {
+  Label fall_through;
+
+  TestBothArgumentsSmis(assembler, &fall_through);  // checks two smis
+  __ orr(R0, R0, ShifterOperand(R1));
+
+  __ Ret();
+  __ Bind(&fall_through);
   return false;
 }
 
 
 bool Intrinsifier::Integer_bitOr(Assembler* assembler) {
-  return false;
+  return Integer_bitOrFromInteger(assembler);
 }
 
 
 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));
+
+  __ Ret();
+  __ Bind(&fall_through);
   return false;
 }
 
 
 bool Intrinsifier::Integer_bitXor(Assembler* assembler) {
-  return false;
+  return Integer_bitXorFromInteger(assembler);
 }
 
 
 bool Intrinsifier::Integer_shl(Assembler* assembler) {
+  ASSERT(kSmiTagShift == 1);
+  ASSERT(kSmiTag == 0);
+  Label fall_through;
+
+  TestBothArgumentsSmis(assembler, &fall_through);
+  __ CompareImmediate(R0, Smi::RawValue(Smi::kBits));
+  __ b(&fall_through, HI);
+
+  __ SmiUntag(R0);
+
+  // Check for overflow by shifting left and shifting back arithmetically.
+  // If the result is different from the original, there was overflow.
+  __ mov(IP, ShifterOperand(R1, LSL, R0));
+  __ cmp(R1, ShifterOperand(IP, ASR, R0));
+
+  // No overflow, result in R0.
+  __ mov(R0, ShifterOperand(R1, LSL, R0), EQ);
+  __ bx(LR, EQ);
+
+  // Arguments are Smi but the shift produced an overflow to Mint.
+  __ CompareImmediate(R6, 0);
+  __ b(&fall_through, LT);
+  __ SmiUntag(R6);
+
+  // Pull off high bits that will be shifted off of R6 by making a mask
+  // ((1 << R0) - 1), shifting it to the left, masking R6, then shifting back.
+  // high bits = (((1 << R0) - 1) << (32 - R0)) & R6) >> (32 - R0)
+  // lo bits = R6 << R0
+  __ LoadImmediate(R7, 1);
+  __ mov(R7, ShifterOperand(R7, LSL, R0));  // R7 <- 1 << R0
+  __ sub(R7, R7, ShifterOperand(1));  // R7 <- R7 - 1
+  __ rsb(R8, R0, ShifterOperand(32));  // R8 <- 32 - R0
+  __ mov(R7, ShifterOperand(R7, LSL, R8));  // R7 <- R7 << R8
+  __ and_(R7, R6, ShifterOperand(R7));  // R7 <- R7 & R6
+  __ mov(R7, ShifterOperand(R7, LSR, R8));  // R7 <- R7 >> R8
+  // Now R7 has the bits that fall off of R6 on a left shift.
+  __ mov(R1, ShifterOperand(R6, LSL, R0));  // R1 gets the low bits.
+
+  const Class& mint_class = Class::Handle(
+      Isolate::Current()->object_store()->mint_class());
+  __ TryAllocate(mint_class, &fall_through, R0);
+
+
+  __ str(R1, FieldAddress(R0, Mint::value_offset()));
+  __ str(R7, FieldAddress(R0, Mint::value_offset() + kWordSize));
+  __ Ret();
+  __ Bind(&fall_through);
+  return false;
+}
+
+
+static void Get64SmiOrMint(Assembler* assembler,
+                           Register res_hi,
+                           Register res_lo,
+                           Register reg,
+                           Label* not_smi_or_mint) {
+  Label not_smi, done;
+  __ tst(reg, ShifterOperand(kSmiTagMask));
+  __ b(&not_smi, NE);
+  __ SmiUntag(reg);
+
+  // Sign extend to 64 bit
+  __ mov(res_lo, ShifterOperand(reg));
+  __ mov(res_hi, ShifterOperand(res_lo, ASR, 31));
+  __ b(&done);
+
+  __ Bind(&not_smi);
+  __ CompareClassId(reg, kMintCid, res_lo);
+  __ b(not_smi_or_mint, NE);
+
+  // Mint.
+  __ ldr(res_lo, FieldAddress(reg, Mint::value_offset()));
+  __ ldr(res_hi, FieldAddress(reg, Mint::value_offset() + kWordSize));
+  __ Bind(&done);
+  return;
+}
+
+
+static bool CompareIntegers(Assembler* assembler, Condition true_condition) {
+  Label try_mint_smi, is_true, is_false, drop_two_fall_through, fall_through;
+  TestBothArgumentsSmis(assembler, &try_mint_smi);
+  // R0 contains the right argument. R1 contains left argument
+
+  __ cmp(R1, ShifterOperand(R0));
+  __ b(&is_true, true_condition);
+  __ Bind(&is_false);
+  __ LoadObject(R0, Bool::False());
+  __ Ret();
+  __ Bind(&is_true);
+  __ LoadObject(R0, Bool::True());
+  __ Ret();
+
+  // 64-bit comparison
+  Condition hi_true_cond, hi_false_cond, lo_false_cond;
+  switch (true_condition) {
+    case LT:
+    case LE:
+      hi_true_cond = LT;
+      hi_false_cond = GT;
+      lo_false_cond = (true_condition == LT) ? CS : HI;
+      break;
+    case GT:
+    case GE:
+      hi_true_cond = GT;
+      hi_false_cond = LT;
+      lo_false_cond = (true_condition == GT) ? LS : CC;
+      break;
+    default:
+      UNREACHABLE();
+      hi_true_cond = hi_false_cond = lo_false_cond = VS;
+  }
+
+  __ Bind(&try_mint_smi);
+  // Get left as 64 bit integer.
+  Get64SmiOrMint(assembler, R3, R2, R1, &fall_through);
+  // Get right as 64 bit integer.
+  Get64SmiOrMint(assembler, R7, R6, R0, &fall_through);
+  // R3: left high.
+  // R2: left low.
+  // R7: right high.
+  // R6: right low.
+
+  __ cmp(R3, ShifterOperand(R7));  // Compare left hi, right high.
+  __ b(&is_false, hi_false_cond);
+  __ b(&is_true, hi_true_cond);
+  __ cmp(R2, ShifterOperand(R6));  // Compare left lo, right lo.
+  __ b(&is_false, lo_false_cond);
+  // Else is true.
+  __ b(&is_true);
+
+  __ Bind(&fall_through);
   return false;
 }
 
 
 bool Intrinsifier::Integer_greaterThanFromInt(Assembler* assembler) {
-  return false;
+  return CompareIntegers(assembler, LT);
 }
 
 
 bool Intrinsifier::Integer_lessThan(Assembler* assembler) {
-  return false;
+  return Integer_greaterThanFromInt(assembler);
 }
 
 
 bool Intrinsifier::Integer_greaterThan(Assembler* assembler) {
-  return false;
+  return CompareIntegers(assembler, GT);
 }
 
 
 bool Intrinsifier::Integer_lessEqualThan(Assembler* assembler) {
-  return false;
+  return CompareIntegers(assembler, LE);
 }
 
 
 bool Intrinsifier::Integer_greaterEqualThan(Assembler* assembler) {
-  return false;
+  return CompareIntegers(assembler, GE);
 }
 
 
+// This is called for Smi, Mint and Bigint receivers. The right argument
+// can be Smi, Mint, Bigint or double.
 bool Intrinsifier::Integer_equalToInteger(Assembler* assembler) {
+  Label fall_through, true_label, check_for_mint;
+  // For integer receiver '===' check first.
+  __ ldr(R0, Address(SP, 0 * kWordSize));
+  __ ldr(R1, Address(SP, 1 * kWordSize));
+  __ cmp(R0, ShifterOperand(R1));
+  __ b(&true_label, EQ);
+
+  __ orr(R2, R0, ShifterOperand(R1));
+  __ tst(R2, ShifterOperand(kSmiTagMask));
+  __ b(&check_for_mint, NE);  // If R0 or R1 is not a smi do Mint checks.
+
+  // Both arguments are smi, '===' is good enough.
+  __ LoadObject(R0, Bool::False());
+  __ Ret();
+  __ Bind(&true_label);
+  __ LoadObject(R0, Bool::True());
+  __ Ret();
+
+  // At least one of the arguments was not Smi.
+  Label receiver_not_smi;
+  __ Bind(&check_for_mint);
+
+  __ tst(R1, ShifterOperand(kSmiTagMask));  // Check receiver.
+  __ b(&receiver_not_smi, NE);
+
+  // Left (receiver) is Smi, return false if right is not Double.
+  // Note that an instance of Mint or Bigint never contains a value that can be
+  // represented by Smi.
+
+  __ CompareClassId(R0, kDoubleCid, R2);
+  __ b(&fall_through, EQ);
+  __ LoadObject(R0, Bool::False());  // Smi == Mint -> false.
+  __ Ret();
+
+  __ Bind(&receiver_not_smi);
+  // R1:: receiver.
+
+  __ CompareClassId(R1, kMintCid, R2);
+  __ b(&fall_through, NE);
+  // Receiver is Mint, return false if right is Smi.
+  __ tst(R0, ShifterOperand(kSmiTagMask));
+  __ b(&fall_through, NE);
+  __ LoadObject(R0, Bool::False());
+  __ Ret();
+  // TODO(srdjan): Implement Mint == Mint comparison.
+
+  __ Bind(&fall_through);
   return false;
 }
 
 
 bool Intrinsifier::Integer_equal(Assembler* assembler) {
-  return false;
+  return Integer_equalToInteger(assembler);
 }
 
 
 bool Intrinsifier::Integer_sar(Assembler* assembler) {
+  Label fall_through;
+
+  TestBothArgumentsSmis(assembler, &fall_through);
+  // Shift amount in R0. Value to shift in R1.
+
+  // Fall through if shift amount is negative.
+  __ SmiUntag(R0);
+  __ CompareImmediate(R0, 0);
+  __ b(&fall_through, LT);
+
+  // If shift amount is bigger than 31, set to 31.
+  __ CompareImmediate(R0, 0x1F);
+  __ LoadImmediate(R0, 0x1F, GT);
+  __ SmiUntag(R1);
+  __ mov(R0, ShifterOperand(R1, ASR, R0));
+  __ SmiTag(R0);
+  __ Ret();
+  __ Bind(&fall_through);
   return false;
 }
 
 
 bool Intrinsifier::Smi_bitNegate(Assembler* assembler) {
+  __ ldr(R0, Address(SP, 0 * kWordSize));
+  __ mvn(R0, ShifterOperand(R0));
+  __ bic(R0, R0, ShifterOperand(kSmiTagMask));  // Remove inverted smi-tag.
+  __ Ret();
+  return false;
+}
+
+
+// Check if the last argument is a double, jump to label 'is_smi' if smi
+// (easy to convert to double), otherwise jump to label 'not_double_smi',
+// Returns the last argument in R0.
+static void TestLastArgumentIsDouble(Assembler* assembler,
+                                     Label* is_smi,
+                                     Label* not_double_smi) {
+  __ ldr(R0, Address(SP, 0 * kWordSize));
+  __ tst(R0, ShifterOperand(kSmiTagMask));
+  __ b(is_smi, EQ);
+  __ CompareClassId(R0, kDoubleCid, R1);
+  __ b(not_double_smi, NE);
+  // Fall through with Double in R0.
+}
+
+
+// Both arguments on stack, arg0 (left) is a double, arg1 (right) is of unknown
+// type. Return true or false object in the register R0. Any NaN argument
+// returns false. Any non-double arg1 causes control flow to fall through to the
+// slow case (compiled method body).
+static bool CompareDoubles(Assembler* assembler, Condition true_condition) {
+  Label fall_through, is_smi, double_op;
+
+  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));
+  __ Bind(&double_op);
+  __ ldr(R0, Address(SP, 1 * kWordSize));  // Left argument.
+  __ AddImmediate(R0, Double::value_offset() - kHeapObjectTag);
+  __ vldrd(D0, Address(R0));
+
+  __ vcmpd(D0, D1);
+  __ vmstat();
+  __ LoadObject(R0, Bool::False());
+  // Return false if D0 or D1 was NaN before checking true condition.
+  __ bx(LR, VS);
+  __ LoadObject(R0, Bool::True(), true_condition);
+  __ Ret();
+
+  __ Bind(&is_smi);  // Convert R0 to a double.
+  __ SmiUntag(R0);
+  __ vmovsr(S0, R0);
+  __ vcvtdi(D1, S0);
+  __ b(&double_op);  // Then do the comparison.
+  __ Bind(&fall_through);
   return false;
 }
 
 
 bool Intrinsifier::Double_greaterThan(Assembler* assembler) {
-  return false;
+  return CompareDoubles(assembler, HI);
 }
 
 
 bool Intrinsifier::Double_greaterEqualThan(Assembler* assembler) {
-  return false;
+  return CompareDoubles(assembler, CS);
 }
 
 
 bool Intrinsifier::Double_lessThan(Assembler* assembler) {
-  return false;
+  return CompareDoubles(assembler, CC);
 }
 
 
 bool Intrinsifier::Double_equal(Assembler* assembler) {
-  return false;
+  return CompareDoubles(assembler, EQ);
 }
 
 
 bool Intrinsifier::Double_lessEqualThan(Assembler* assembler) {
+  return CompareDoubles(assembler, LS);
+}
+
+
+// Expects left argument to be double (receiver). Right argument is unknown.
+// Both arguments are on stack.
+static bool DoubleArithmeticOperations(Assembler* assembler, Token::Kind kind) {
+  Label fall_through;
+
+  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));
+  __ ldr(R0, Address(SP, 1 * kWordSize));  // Left argument.
+  __ AddImmediate(R0, Double::value_offset() - kHeapObjectTag);
+  __ vldrd(D0, Address(R0));
+  switch (kind) {
+    case Token::kADD: __ vaddd(D0, D0, D1); break;
+    case Token::kSUB: __ vsubd(D0, D0, D1); break;
+    case Token::kMUL: __ vmuld(D0, D0, D1); break;
+    case Token::kDIV: __ vdivd(D0, D0, D1); break;
+    default: UNREACHABLE();
+  }
+  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));
+  __ Ret();
+  __ Bind(&fall_through);
   return false;
 }
 
 
 bool Intrinsifier::Double_add(Assembler* assembler) {
-  return false;
+  return DoubleArithmeticOperations(assembler, Token::kADD);
 }
 
 
 bool Intrinsifier::Double_mul(Assembler* assembler) {
-  return false;
+  return DoubleArithmeticOperations(assembler, Token::kMUL);
 }
 
 
 bool Intrinsifier::Double_sub(Assembler* assembler) {
-  return false;
+  return DoubleArithmeticOperations(assembler, Token::kSUB);
 }
 
 
 bool Intrinsifier::Double_div(Assembler* assembler) {
-  return false;
+  return DoubleArithmeticOperations(assembler, Token::kDIV);
 }
 
 
+// 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));
+  __ b(&fall_through, NE);
+  // Is Smi.
+  __ SmiUntag(R0);
+  __ vmovsr(S0, R0);
+  __ vcvtdi(D1, S0);
+  __ ldr(R0, Address(SP, 1 * kWordSize));
+  __ AddImmediate(R0, Double::value_offset() - kHeapObjectTag);
+  __ vldrd(D0, Address(R0));
+  __ 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));
+  __ Ret();
+  __ Bind(&fall_through);
   return false;
 }
 
 
 bool Intrinsifier::Double_fromInteger(Assembler* assembler) {
+  Label fall_through;
+
+  __ ldr(R0, Address(SP, 0 * kWordSize));
+  __ tst(R0, ShifterOperand(kSmiTagMask));
+  __ b(&fall_through, NE);
+  // Is Smi.
+  __ SmiUntag(R0);
+  __ vmovsr(S0, R0);
+  __ vcvtdi(D0, S0);
+  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));
+  __ Ret();
+  __ Bind(&fall_through);
   return false;
 }
 
 
 bool Intrinsifier::Double_getIsNaN(Assembler* assembler) {
-  return false;
+  Label is_true;
+  __ Untested("Intrinsifier::Double_getIsNaN");
+  __ ldr(R0, Address(SP, 0 * kWordSize));
+  __ AddImmediate(R0, Double::value_offset() - kHeapObjectTag);
+  __ vldrd(D0, Address(R0));
+  __ vcmpd(D0, D0);
+  __ vmstat();
+  __ LoadObject(R0, Bool::False(), VS);
+  __ LoadObject(R0, Bool::True(), VC);
+  __ Ret();
+  return true;
 }
 
 
 bool Intrinsifier::Double_getIsNegative(Assembler* assembler) {
-  return false;
+  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));
+  __ LoadDImmediate(D1, 0.0, R1);
+  __ vcmpd(D0, D1);
+  __ vmstat();
+  __ b(&is_false, VS);  // NaN -> false.
+  __ b(&is_zero, EQ);  // Check for negative zero.
+  __ b(&is_false, CS);  // >= 0 -> false.
+
+  __ Bind(&is_true);
+  __ LoadObject(R0, Bool::True());
+  __ Ret();
+
+  __ Bind(&is_false);
+  __ LoadObject(R0, Bool::False());
+  __ Ret();
+
+  __ Bind(&is_zero);
+  // Check for negative zero by looking at the sign bit.
+  __ vmovrrd(R0, R1, D0);  // R1:R0 <- D0, so sign bit is in bit 31 of R1.
+  __ mov(R1, ShifterOperand(R1, LSR, 31));
+  __ tst(R1, ShifterOperand(1));
+  __ b(&is_true, NE);  // Sign bit set.
+  __ b(&is_false);
+  return true;
 }
 
 
 bool Intrinsifier::Double_toInt(Assembler* assembler) {
+  __ ldr(R0, Address(SP, 0 * kWordSize));
+  __ AddImmediate(R0, Double::value_offset() - kHeapObjectTag);
+  __ vldrd(D0, Address(R0));
+  __ vcvtid(S0, D0);
+  __ vmovrs(R0, S0);
+  // Overflow is signaled with minint.
+  Label fall_through;
+  // Check for overflow and that it fits into Smi.
+  __ CompareImmediate(R0, 0xC0000000);
+  __ b(&fall_through, MI);
+  __ SmiTag(R0);
+  __ Ret();
+  __ Bind(&fall_through);
   return false;
 }
 
 
 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));
+  __ 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));
+  __ Ret();
+  __ Bind(&is_smi);
+  __ SmiUntag(R0);
+  __ vmovsr(S0, R0);
+  __ vcvtdi(D1, S0);
+  __ b(&double_op);
+  __ Bind(&fall_through);
   return false;
 }
 
@@ -311,52 +1376,332 @@
 }
 
 
+//    var state = ((_A * (_state[kSTATE_LO])) + _state[kSTATE_HI]) & _MASK_64;
+//    _state[kSTATE_LO] = state & _MASK_32;
+//    _state[kSTATE_HI] = state >> 32;
 bool Intrinsifier::Random_nextState(Assembler* assembler) {
-  return false;
+  const Library& math_lib = Library::Handle(Library::MathLibrary());
+  ASSERT(!math_lib.IsNull());
+  const Class& random_class =
+      Class::Handle(math_lib.LookupClassAllowPrivate(Symbols::_Random()));
+  ASSERT(!random_class.IsNull());
+  const Field& state_field = Field::ZoneHandle(
+      random_class.LookupInstanceField(Symbols::_state()));
+  ASSERT(!state_field.IsNull());
+  const Field& random_A_field = Field::ZoneHandle(
+      random_class.LookupStaticField(Symbols::_A()));
+  ASSERT(!random_A_field.IsNull());
+  ASSERT(random_A_field.is_const());
+  const Instance& a_value = Instance::Handle(random_A_field.value());
+  const int64_t a_int_value = Integer::Cast(a_value).AsInt64Value();
+  // 'a_int_value' is a mask.
+  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].
+
+  const int64_t disp_0 =
+      FlowGraphCompiler::DataOffsetFor(kTypedDataUint32ArrayCid);
+
+  const int64_t disp_1 =
+      FlowGraphCompiler::ElementSizeFor(kTypedDataUint32ArrayCid) +
+      FlowGraphCompiler::DataOffsetFor(kTypedDataUint32ArrayCid);
+
+  __ LoadImmediate(R0, a_int32_value);
+  __ LoadFromOffset(kLoadWord, R2, R1, disp_0 - 1);
+  __ LoadFromOffset(kLoadWord, R3, R1, disp_1 - 1);
+  __ mov(R6, ShifterOperand(R3, ASR, 31));  // Sign extend into R6.
+  // 64-bit multiply and accumulate into R6:R3.
+  __ smlal(R3, R6, R0, R2);  // R6:R3 <- R6:R3 + R0 * R2.
+  __ StoreToOffset(kStoreWord, R3, R1, disp_0 - 1);
+  __ StoreToOffset(kStoreWord, R6, R1, disp_1 - 1);
+  __ Ret();
+  return true;
 }
 
 
 bool Intrinsifier::Object_equal(Assembler* assembler) {
-  return false;
+  __ ldr(R0, Address(SP, 0 * kWordSize));
+  __ ldr(R1, Address(SP, 1 * kWordSize));
+  __ cmp(R0, ShifterOperand(R1));
+  __ LoadObject(R0, Bool::False(), NE);
+  __ LoadObject(R0, Bool::True(), EQ);
+  __ Ret();
+  return true;
 }
 
 
 bool Intrinsifier::String_getHashCode(Assembler* assembler) {
+  __ Untested("Intrinsifier::String_getHashCode");
+  __ ldr(R0, Address(SP, 0 * kWordSize));
+  __ ldr(R0, FieldAddress(R0, String::hash_offset()));
+  __ cmp(R0, ShifterOperand(0));
+  __ bx(LR, NE);  // Hash not yet computed.
   return false;
 }
 
 
 bool Intrinsifier::String_getLength(Assembler* assembler) {
-  return false;
+  __ ldr(R0, Address(SP, 0 * kWordSize));
+  __ ldr(R0, FieldAddress(R0, String::length_offset()));
+  __ Ret();
+  return true;
 }
 
 
+// TODO(srdjan): Implement for two and four byte strings as well.
 bool Intrinsifier::String_codeUnitAt(Assembler* assembler) {
+  Label fall_through;
+
+  __ ldr(R1, Address(SP, 0 * kWordSize));  // Index.
+  __ ldr(R0, Address(SP, 1 * kWordSize));  // String.
+  __ tst(R1, ShifterOperand(kSmiTagMask));
+  __ b(&fall_through, NE);  // Index is not a Smi.
+  // Range check.
+  __ ldr(R2, FieldAddress(R0, String::length_offset()));
+  __ cmp(R1, ShifterOperand(R2));
+  __ b(&fall_through, CS);  // Runtime throws exception.
+  __ CompareClassId(R0, kOneByteStringCid, R3);
+  __ b(&fall_through, NE);
+  __ SmiUntag(R1);
+  __ AddImmediate(R0, OneByteString::data_offset() - kHeapObjectTag);
+  __ ldrb(R0, Address(R0, R1));
+  __ SmiTag(R0);
+  __ Ret();
+  __ Bind(&fall_through);
   return false;
 }
 
 
 bool Intrinsifier::String_getIsEmpty(Assembler* assembler) {
-  return false;
+  __ ldr(R0, Address(SP, 0 * kWordSize));
+  __ ldr(R0, FieldAddress(R0, String::length_offset()));
+  __ cmp(R0, ShifterOperand(Smi::RawValue(0)));
+  __ LoadObject(R0, Bool::True(), EQ);
+  __ LoadObject(R0, Bool::False(), NE);
+  __ Ret();
+  return true;
 }
 
 
 bool Intrinsifier::OneByteString_getHashCode(Assembler* assembler) {
+  __ ldr(R1, Address(SP, 0 * kWordSize));
+  __ ldr(R0, FieldAddress(R1, String::hash_offset()));
+  __ cmp(R0, ShifterOperand(0));
+  __ bx(LR, NE);  // Return if already computed.
+
+  __ ldr(R2, FieldAddress(R1, String::length_offset()));
+
+  Label done;
+  // If the string is empty, set the hash to 1, and return.
+  __ cmp(R2, ShifterOperand(Smi::RawValue(0)));
+  __ b(&done, EQ);
+
+  __ SmiUntag(R2);
+  __ mov(R3, ShifterOperand(0));
+  __ AddImmediate(R6, R1, OneByteString::data_offset() - kHeapObjectTag);
+  // R1: Instance of OneByteString.
+  // R2: String length, untagged integer.
+  // R3: Loop counter, untagged integer.
+  // R6: String data.
+  // R0: Hash code, untagged integer.
+
+  Label loop;
+  // Add to hash code: (hash_ is uint32)
+  // hash_ += ch;
+  // hash_ += hash_ << 10;
+  // hash_ ^= hash_ >> 6;
+  // Get one characters (ch).
+  __ Bind(&loop);
+  __ ldrb(R7, Address(R6, 0));
+  // R7: ch.
+  __ add(R3, R3, ShifterOperand(1));
+  __ add(R6, R6, ShifterOperand(1));
+  __ add(R0, R0, ShifterOperand(R7));
+  __ add(R0, R0, ShifterOperand(R0, LSL, 10));
+  __ eor(R0, R0, ShifterOperand(R0, LSR, 6));
+  __ cmp(R3, ShifterOperand(R2));
+  __ b(&loop, NE);
+
+  // Finalize.
+  // hash_ += hash_ << 3;
+  // hash_ ^= hash_ >> 11;
+  // hash_ += hash_ << 15;
+  __ add(R0, R0, ShifterOperand(R0, LSL, 3));
+  __ eor(R0, R0, ShifterOperand(R0, LSR, 11));
+  __ add(R0, R0, ShifterOperand(R0, LSL, 15));
+  // hash_ = hash_ & ((static_cast<intptr_t>(1) << bits) - 1);
+  __ LoadImmediate(R2, (static_cast<intptr_t>(1) << String::kHashBits) - 1);
+  __ and_(R0, R0, ShifterOperand(R2));
+  __ cmp(R0, ShifterOperand(0));
+  // return hash_ == 0 ? 1 : hash_;
+  __ Bind(&done);
+  __ mov(R0, ShifterOperand(1), EQ);
+  __ SmiTag(R0);
+  __ str(R0, FieldAddress(R1, String::hash_offset()));
+  __ Ret();
   return false;
 }
 
 
+// Allocates one-byte string of length 'end - start'. The content is not
+// initialized.
+// 'length-reg' (R2) contains tagged length.
+// Returns new string as tagged pointer in R0.
+static void TryAllocateOnebyteString(Assembler* assembler,
+                                     Label* ok,
+                                     Label* failure) {
+  const Register length_reg = R2;
+  Label fail;
+
+  __ mov(R6, ShifterOperand(length_reg));  // Save the length register.
+  __ SmiUntag(length_reg);
+  const intptr_t fixed_size = sizeof(RawString) + kObjectAlignment - 1;
+  __ AddImmediate(length_reg, fixed_size);
+  __ bic(length_reg, length_reg, ShifterOperand(kObjectAlignment - 1));
+
+  Isolate* isolate = Isolate::Current();
+  Heap* heap = isolate->heap();
+
+  __ LoadImmediate(R3, heap->TopAddress());
+  __ ldr(R0, Address(R3, 0));
+
+  // length_reg: allocation size.
+  __ adds(R1, R0, ShifterOperand(length_reg));
+  __ b(&fail, VS);  // Fail on overflow.
+
+  // Check if the allocation fits into the remaining space.
+  // R0: potential new object start.
+  // R1: potential next object start.
+  // R2: allocation size.
+  // R3: heap->Top->Address().
+  __ LoadImmediate(R7, heap->EndAddress());
+  __ ldr(R7, Address(R7, 0));
+  __ cmp(R1, ShifterOperand(R7));
+  __ b(&fail, CS);
+
+  // Successfully allocated the object(s), now update top to point to
+  // next object start and initialize the object.
+  __ str(R1, Address(R3, 0));
+  __ AddImmediate(R0, kHeapObjectTag);
+
+  // Initialize the tags.
+  // R0: new object start as a tagged pointer.
+  // R1: new object end address.
+  // R2: allocation size.
+  {
+    const intptr_t shift = RawObject::kSizeTagBit - kObjectAlignmentLog2;
+    const Class& cls =
+        Class::Handle(isolate->object_store()->one_byte_string_class());
+
+    __ CompareImmediate(R2, RawObject::SizeTag::kMaxSizeTag);
+    __ mov(R2, ShifterOperand(R2, LSL, shift), LS);
+    __ mov(R2, ShifterOperand(0), HI);
+
+    // Get the class index and insert it into the tags.
+    // R2: size and bit tags.
+    __ LoadImmediate(TMP, RawObject::ClassIdTag::encode(cls.id()));
+    __ orr(R2, R2, ShifterOperand(TMP));
+    __ str(R2, FieldAddress(R0, String::tags_offset()));  // Store tags.
+  }
+
+  // Set the length field using the saved length (R6).
+  __ StoreIntoObjectNoBarrier(R0,
+                              FieldAddress(R0, String::length_offset()),
+                              R6);
+  // Clear hash.
+  __ LoadImmediate(TMP, 0);
+  __ str(TMP, FieldAddress(R0, String::hash_offset()));
+  __ b(ok);
+
+  __ Bind(&fail);
+  __ b(failure);
+}
+
+
+// Arg0: Onebyte String
+// Arg1: Start index as Smi.
+// Arg2: End index as Smi.
+// The indexes must be valid.
 bool Intrinsifier::OneByteString_substringUnchecked(Assembler* assembler) {
+  const intptr_t kStringOffset = 2 * kWordSize;
+  const intptr_t kStartIndexOffset = 1 * kWordSize;
+  const intptr_t kEndIndexOffset = 0 * kWordSize;
+  Label fall_through, ok;
+
+  __ ldr(R2, Address(SP, kEndIndexOffset));
+  __ ldr(TMP, Address(SP, kStartIndexOffset));
+  __ sub(R2, R2, ShifterOperand(TMP));
+  TryAllocateOnebyteString(assembler, &ok, &fall_through);
+  __ Bind(&ok);
+  // R0: new string as tagged pointer.
+  // Copy string.
+  __ ldr(R3, Address(SP, kStringOffset));
+  __ ldr(R1, Address(SP, kStartIndexOffset));
+  __ SmiUntag(R1);
+  __ add(R3, R3, ShifterOperand(R1));
+  // Calculate start address and untag (- 1).
+  __ AddImmediate(R3, OneByteString::data_offset() - 1);
+
+  // R3: Start address to copy from (untagged).
+  // R1: Untagged start index.
+  __ ldr(R2, Address(SP, kEndIndexOffset));
+  __ SmiUntag(R2);
+  __ sub(R2, R2, ShifterOperand(R1));
+
+  // R3: Start address to copy from (untagged).
+  // R2: Untagged number of bytes to copy.
+  // R0: Tagged result string.
+  // R6: Pointer into R3.
+  // R7: Pointer into R0.
+  // R1: Scratch register.
+  Label loop, done;
+  __ cmp(R2, ShifterOperand(0));
+  __ b(&done, LE);
+  __ mov(R6, ShifterOperand(R3));
+  __ mov(R7, ShifterOperand(R0));
+  __ Bind(&loop);
+  __ ldrb(R1, Address(R6, 0));
+  __ AddImmediate(R6, 1);
+  __ sub(R2, R2, ShifterOperand(1));
+  __ cmp(R2, ShifterOperand(0));
+  __ strb(R1, FieldAddress(R7, OneByteString::data_offset()));
+  __ AddImmediate(R7, 1);
+  __ b(&loop, GT);
+
+  __ Bind(&done);
+  __ Ret();
+  __ Bind(&fall_through);
   return false;
 }
 
 
 bool Intrinsifier::OneByteString_setAt(Assembler* assembler) {
-  return false;
+  __ ldr(R2, Address(SP, 0 * kWordSize));  // Value.
+  __ ldr(R1, Address(SP, 1 * kWordSize));  // Index.
+  __ ldr(R0, Address(SP, 2 * kWordSize));  // OneByteString.
+  __ SmiUntag(R1);
+  __ SmiUntag(R2);
+  __ AddImmediate(R3, R0, OneByteString::data_offset() - kHeapObjectTag);
+  __ strb(R2, Address(R3, R1));
+  __ Ret();
+  return true;
 }
 
 
 bool Intrinsifier::OneByteString_allocate(Assembler* assembler) {
+  __ ldr(R2, Address(SP, 0 * kWordSize));  // Length.
+  Label fall_through, ok;
+  TryAllocateOnebyteString(assembler, &ok, &fall_through);
+
+  __ Bind(&ok);
+  __ Ret();
+
+  __ Bind(&fall_through);
   return false;
 }
 
diff --git a/runtime/vm/intrinsifier_ia32.cc b/runtime/vm/intrinsifier_ia32.cc
index 8d5ff5a..5b704ce 100644
--- a/runtime/vm/intrinsifier_ia32.cc
+++ b/runtime/vm/intrinsifier_ia32.cc
@@ -677,7 +677,7 @@
 // EAX: Tagged left (dividend).
 // EBX: Tagged right (divisor).
 // EDX: Untagged result (remainder).
-void EmitRemainderOperation(Assembler* assembler) {
+static void EmitRemainderOperation(Assembler* assembler) {
   Label return_zero, modulo;
   // Check for quick zero results.
   __ cmpl(EAX, Immediate(0));
@@ -1632,7 +1632,7 @@
   __ pushl(EDI);  // Preserve length.
   __ SmiUntag(EDI);
   const intptr_t fixed_size = sizeof(RawString) + kObjectAlignment - 1;
-  __ leal(EDI, Address(EDI, TIMES_1, fixed_size));  // EDI is a Smi.
+  __ leal(EDI, Address(EDI, TIMES_1, fixed_size));  // EDI is untagged.
   __ andl(EDI, Immediate(-kObjectAlignment));
 
   Isolate* isolate = Isolate::Current();
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index f455a0a..4c1a93b 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -53,6 +53,7 @@
 DECLARE_FLAG(bool, trace_compiler);
 DECLARE_FLAG(bool, eliminate_type_checks);
 DECLARE_FLAG(bool, enable_type_checks);
+DECLARE_FLAG(int, deoptimization_counter_threshold);
 
 static const char* kGetterPrefix = "get:";
 static const intptr_t kGetterPrefixLength = strlen(kGetterPrefix);
@@ -2299,74 +2300,53 @@
 
 
 bool Class::IsTopLevel() const {
-  return String::Handle(Name()).Equals("::");
+  return Name() == Symbols::TopLevel().raw();
 }
 
 
 RawFunction* Class::LookupDynamicFunction(const String& name) const {
-  Function& function = Function::Handle(LookupFunction(name));
-  if (function.IsNull() || !function.IsDynamicFunction()) {
-    return Function::null();
-  }
-  return function.raw();
+  return LookupFunction(name, kInstance);
 }
 
 
 RawFunction* Class::LookupDynamicFunctionAllowPrivate(
     const String& name) const {
-  Function& function = Function::Handle(LookupFunctionAllowPrivate(name));
-  if (function.IsNull() || !function.IsDynamicFunction()) {
-    return Function::null();
-  }
-  return function.raw();
+  return LookupFunctionAllowPrivate(name, kInstance);
 }
 
 
 RawFunction* Class::LookupStaticFunction(const String& name) const {
-  Function& function = Function::Handle(LookupFunction(name));
-  if (function.IsNull() || !function.IsStaticFunction()) {
-    return Function::null();
-  }
-  return function.raw();
+  return LookupFunction(name, kStatic);
 }
 
 
 RawFunction* Class::LookupStaticFunctionAllowPrivate(const String& name) const {
-  Function& function = Function::Handle(LookupFunctionAllowPrivate(name));
-  if (function.IsNull() || !function.IsStaticFunction()) {
-    return Function::null();
-  }
-  return function.raw();
+  return LookupFunctionAllowPrivate(name, kStatic);
 }
 
 
 RawFunction* Class::LookupConstructor(const String& name) const {
-  Function& function = Function::Handle(LookupFunction(name));
-  if (function.IsNull() || !function.IsConstructor()) {
-    return Function::null();
-  }
-  ASSERT(!function.is_static());
-  return function.raw();
+  return LookupFunction(name, kConstructor);
 }
 
 
 RawFunction* Class::LookupConstructorAllowPrivate(const String& name) const {
-  Function& function = Function::Handle(LookupFunctionAllowPrivate(name));
-  if (function.IsNull() || !function.IsConstructor()) {
-    return Function::null();
-  }
-  ASSERT(!function.is_static());
-  return function.raw();
+  return LookupFunctionAllowPrivate(name, kConstructor);
 }
 
 
 RawFunction* Class::LookupFactory(const String& name) const {
-  Function& function = Function::Handle(LookupFunction(name));
-  if (function.IsNull() || !function.IsFactory()) {
-    return Function::null();
-  }
-  ASSERT(function.is_static());
-  return function.raw();
+  return LookupFunction(name, kFactory);
+}
+
+
+RawFunction* Class::LookupFunction(const String& name) const {
+  return LookupFunction(name, kAny);
+}
+
+
+RawFunction* Class::LookupFunctionAllowPrivate(const String& name) const {
+  return LookupFunctionAllowPrivate(name, kAny);
 }
 
 
@@ -2395,7 +2375,33 @@
 }
 
 
-RawFunction* Class::LookupFunction(const String& name) const {
+RawFunction* Class::CheckFunctionType(const Function& func, intptr_t type) {
+  if (type == kInstance) {
+    if (func.IsDynamicFunction()) {
+      return func.raw();
+    }
+  } else if (type == kStatic) {
+    if (func.IsStaticFunction()) {
+      return func.raw();
+    }
+  } else if (type == kConstructor) {
+    if (func.IsConstructor()) {
+      ASSERT(!func.is_static());
+      return func.raw();
+    }
+  } else if (type == kFactory) {
+    if (func.IsFactory()) {
+      ASSERT(func.is_static());
+      return func.raw();
+    }
+  } else if (type == kAny) {
+    return func.raw();
+  }
+  return Function::null();
+}
+
+
+RawFunction* Class::LookupFunction(const String& name, intptr_t type) const {
   Isolate* isolate = Isolate::Current();
   if (EnsureIsFinalized(isolate) != Error::null()) {
     return Function::null();
@@ -2405,7 +2411,7 @@
     // This can occur, e.g., for Null classes.
     return Function::null();
   }
-  Function& function = Function::Handle(isolate, Function::null());
+  Function& function = Function::Handle(isolate);
   const intptr_t len = funcs.Length();
   if (name.IsSymbol()) {
     // Quick Symbol compare.
@@ -2413,16 +2419,16 @@
     for (intptr_t i = 0; i < len; i++) {
       function ^= funcs.At(i);
       if (function.name() == name.raw()) {
-        return function.raw();
+        return CheckFunctionType(function, type);
       }
     }
   } else {
-    String& function_name = String::Handle(isolate, String::null());
+    String& function_name = String::Handle(isolate);
     for (intptr_t i = 0; i < len; i++) {
       function ^= funcs.At(i);
       function_name ^= function.name();
       if (function_name.Equals(name)) {
-        return function.raw();
+        return CheckFunctionType(function, type);
       }
     }
   }
@@ -2431,7 +2437,8 @@
 }
 
 
-RawFunction* Class::LookupFunctionAllowPrivate(const String& name) const {
+RawFunction* Class::LookupFunctionAllowPrivate(const String& name,
+                                               intptr_t type) const {
   Isolate* isolate = Isolate::Current();
   if (EnsureIsFinalized(isolate) != Error::null()) {
     return Function::null();
@@ -2441,14 +2448,14 @@
     // This can occur, e.g., for Null classes.
     return Function::null();
   }
-  Function& function = Function::Handle(isolate, Function::null());
-  String& function_name = String::Handle(isolate, String::null());
+  Function& function = Function::Handle(isolate);
+  String& function_name = String::Handle(isolate);
   intptr_t len = funcs.Length();
   for (intptr_t i = 0; i < len; i++) {
     function ^= funcs.At(i);
     function_name ^= function.name();
     if (String::EqualsIgnoringPrivateKey(function_name, name)) {
-        return function.raw();
+      return CheckFunctionType(function, type);
     }
   }
   // No function found.
@@ -2517,44 +2524,21 @@
 
 
 RawField* Class::LookupInstanceField(const String& name) const {
-  Isolate* isolate = Isolate::Current();
-  if (EnsureIsFinalized(isolate) != Error::null()) {
-    return Field::null();
-  }
-  ASSERT(is_finalized());
-  const Field& field = Field::Handle(isolate, LookupField(name));
-  if (!field.IsNull()) {
-    if (field.is_static()) {
-      // Name matches but it is not of the correct kind, return NULL.
-      return Field::null();
-    }
-    return field.raw();
-  }
-  // No field found.
-  return Field::null();
+  return LookupField(name, kInstance);
 }
 
 
 RawField* Class::LookupStaticField(const String& name) const {
-  Isolate* isolate = Isolate::Current();
-  if (EnsureIsFinalized(isolate) != Error::null()) {
-    return Field::null();
-  }
-  ASSERT(is_finalized());
-  const Field& field = Field::Handle(isolate, LookupField(name));
-  if (!field.IsNull()) {
-    if (!field.is_static()) {
-      // Name matches but it is not of the correct kind, return NULL.
-      return Field::null();
-    }
-    return field.raw();
-  }
-  // No field found.
-  return Field::null();
+  return LookupField(name, kStatic);
 }
 
 
 RawField* Class::LookupField(const String& name) const {
+  return LookupField(name, kAny);
+}
+
+
+RawField* Class::LookupField(const String& name, intptr_t type) const {
   Isolate* isolate = Isolate::Current();
   if (EnsureIsFinalized(isolate) != Error::null()) {
     return Field::null();
@@ -2567,7 +2551,18 @@
     field ^= flds.At(i);
     field_name ^= field.name();
     if (String::EqualsIgnoringPrivateKey(field_name, name)) {
-      return field.raw();
+      if (type == kInstance) {
+        if (!field.is_static()) {
+          return field.raw();
+        }
+      } else if (type == kStatic) {
+        if (field.is_static()) {
+          return field.raw();
+        }
+      } else if (type == kAny) {
+        return field.raw();
+      }
+      return Field::null();
     }
   }
   // No field found.
@@ -3424,6 +3419,15 @@
 }
 
 
+void Function::EnsureDeoptHistory() const {
+  Array& array = Array::Handle(deopt_history());
+  if (array.IsNull()) {
+    array = Array::New(FLAG_deoptimization_counter_threshold);
+    set_deopt_history(array);
+  }
+}
+
+
 RawContextScope* Function::context_scope() const {
   if (IsClosureFunction()) {
     const Object& obj = Object::Handle(raw_ptr()->data_);
@@ -6688,11 +6692,6 @@
 }
 
 
-RawLibrary* Library::CryptoLibrary() {
-  return Isolate::Current()->object_store()->crypto_library();
-}
-
-
 RawLibrary* Library::IsolateLibrary() {
   return Isolate::Current()->object_store()->isolate_library();
 }
@@ -6723,11 +6722,6 @@
 }
 
 
-RawLibrary* Library::UriLibrary() {
-  return Isolate::Current()->object_store()->uri_library();
-}
-
-
 RawLibrary* Library::UtfLibrary() {
   return Isolate::Current()->object_store()->utf_library();
 }
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 480ce5b..01b8c78 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -917,6 +917,13 @@
 
  private:
   enum {
+    kAny = 0,
+    kStatic,
+    kInstance,
+    kConstructor,
+    kFactory,
+  };
+  enum {
     kConstBit = 0,
     kImplementedBit = 1,
     kAbstractBit = 2,
@@ -953,6 +960,12 @@
   // Assigns empty array to all raw class array fields.
   void InitEmptyFields();
 
+  static RawFunction* CheckFunctionType(const Function& func, intptr_t type);
+  RawFunction* LookupFunction(const String& name, intptr_t type) const;
+  RawFunction* LookupFunctionAllowPrivate(const String& name,
+                                          intptr_t type) const;
+  RawField* LookupField(const String& name, intptr_t type) const;
+
   RawFunction* LookupAccessorFunction(const char* prefix,
                                       intptr_t prefix_length,
                                       const String& name) const;
@@ -1316,6 +1329,8 @@
 
   RawArray* deopt_history() const { return raw_ptr()->deopt_history_; }
   void set_deopt_history(const Array& value) const;
+  // If not yet present, allocate deoptimization history array.
+  void EnsureDeoptHistory() const;
 
   // Returns true if there is at least one debugger breakpoint
   // set in this function.
diff --git a/runtime/vm/object_store.cc b/runtime/vm/object_store.cc
index 1f8a131..67c588c 100644
--- a/runtime/vm/object_store.cc
+++ b/runtime/vm/object_store.cc
@@ -50,7 +50,6 @@
     async_library_(Library::null()),
     builtin_library_(Library::null()),
     core_library_(Library::null()),
-    crypto_library_(Library::null()),
     isolate_library_(Library::null()),
     json_library_(Library::null()),
     math_library_(Library::null()),
@@ -58,7 +57,6 @@
     native_wrappers_library_(Library::null()),
     root_library_(Library::null()),
     typed_data_library_(Library::null()),
-    uri_library_(Library::null()),
     utf_library_(Library::null()),
     libraries_(GrowableObjectArray::null()),
     pending_classes_(GrowableObjectArray::null()),
diff --git a/runtime/vm/object_store.h b/runtime/vm/object_store.h
index f7fce5d..ffe1419 100644
--- a/runtime/vm/object_store.h
+++ b/runtime/vm/object_store.h
@@ -25,14 +25,12 @@
     kCore,
     kCollection,
     kCollectionDev,
-    kCrypto,
     kIsolate,
     kJson,
     kMath,
     kMirrors,
     kTypedData,
     kUtf,
-    kUri,
   };
 
   ~ObjectStore();
@@ -261,13 +259,11 @@
   RawLibrary* collection_dev_library() const {
     return collection_dev_library_;
   }
-  RawLibrary* crypto_library() const { return crypto_library_; }
   RawLibrary* isolate_library() const { return isolate_library_; }
   RawLibrary* json_library() const { return json_library_; }
   RawLibrary* math_library() const { return math_library_; }
   RawLibrary* mirrors_library() const { return mirrors_library_; }
   RawLibrary* typed_data_library() const { return typed_data_library_; }
-  RawLibrary* uri_library() const { return uri_library_; }
   RawLibrary* utf_library() const { return utf_library_; }
   void set_bootstrap_library(intptr_t index, const Library& value) {
     switch (index) {
@@ -283,9 +279,6 @@
       case kCollectionDev:
         collection_dev_library_ = value.raw();
         break;
-      case kCrypto:
-        crypto_library_ = value.raw();
-        break;
       case kIsolate:
         isolate_library_ = value.raw();
         break;
@@ -304,9 +297,6 @@
       case kUtf:
         utf_library_ = value.raw();
         break;
-      case kUri:
-        uri_library_ = value.raw();
-        break;
       default:
         UNREACHABLE();
     }
@@ -463,7 +453,6 @@
   RawLibrary* core_library_;
   RawLibrary* collection_library_;
   RawLibrary* collection_dev_library_;
-  RawLibrary* crypto_library_;
   RawLibrary* isolate_library_;
   RawLibrary* json_library_;
   RawLibrary* math_library_;
@@ -471,7 +460,6 @@
   RawLibrary* native_wrappers_library_;
   RawLibrary* root_library_;
   RawLibrary* typed_data_library_;
-  RawLibrary* uri_library_;
   RawLibrary* utf_library_;
   RawGrowableObjectArray* libraries_;
   RawGrowableObjectArray* pending_classes_;
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
index f396f3b..303bd75 100644
--- a/runtime/vm/parser.cc
+++ b/runtime/vm/parser.cc
@@ -1517,13 +1517,7 @@
 
 // Simple test if a node is side effect free.
 static bool IsSimpleLocalOrLiteralNode(AstNode* node) {
-  if (node->IsLiteralNode()) {
-    return true;
-  }
-  if (node->IsLoadLocalNode() && !node->AsLoadLocalNode()->HasPseudo()) {
-    return true;
-  }
-  return false;
+  return node->IsLiteralNode() || node->IsLoadLocalNode();
 }
 
 
@@ -1573,8 +1567,9 @@
     ASSERT(!super_class.IsNull());
     super_op =
         new LoadIndexedNode(operator_pos, receiver, index_expr, super_class);
-  } else if (Token::CanBeOverloaded(CurrentToken()) ||
-             (CurrentToken() == Token::kNE)) {
+  } else {
+    ASSERT(Token::CanBeOverloaded(CurrentToken()) ||
+           (CurrentToken() == Token::kNE));
     Token::Kind op = CurrentToken();
     ConsumeToken();
 
@@ -1656,28 +1651,24 @@
         String::ZoneHandle(Field::SetterName(field_name));
     const Function& super_setter = Function::ZoneHandle(
         Resolver::ResolveDynamicAnyArgs(super_class, setter_name));
-    if (!super_setter.IsNull()) {
-      return new StaticGetterNode(
-          field_pos, implicit_argument, true, super_class, field_name);
+    if (super_setter.IsNull()) {
+      // Check if this is an access to an implicit closure using 'super'.
+      // If a function exists of the specified field_name then try
+      // accessing it as a getter, at runtime we will handle this by
+      // creating an implicit closure of the function and returning it.
+      const Function& super_function = Function::ZoneHandle(
+          Resolver::ResolveDynamicAnyArgs(super_class, field_name));
+      if (!super_function.IsNull()) {
+        // In case CreateAssignmentNode is called later on this
+        // CreateImplicitClosureNode, it will be replaced by a StaticSetterNode.
+        return CreateImplicitClosureNode(super_function,
+                                         field_pos,
+                                         implicit_argument);
+      }
+      // No function or field exists of the specified field_name.
+      // Emit a StaticGetterNode anyway, so that noSuchMethod gets called.
     }
   }
-  if (super_getter.IsNull()) {
-    // Check if this is an access to an implicit closure using 'super'.
-    // If a function exists of the specified field_name then try
-    // accessing it as a getter, at runtime we will handle this by
-    // creating an implicit closure of the function and returning it.
-    const Function& super_function = Function::ZoneHandle(
-        Resolver::ResolveDynamicAnyArgs(super_class, field_name));
-    if (!super_function.IsNull()) {
-      // In case CreateAssignmentNode is called later on this
-      // CreateImplicitClosureNode, it will be replaced by a StaticSetterNode.
-      return CreateImplicitClosureNode(super_function,
-                                       field_pos,
-                                       implicit_argument);
-    }
-    // No function or field exists of the specified field_name.
-    // Emit a StaticGetterNode anyway, so that noSuchMethod gets called.
-  }
   return new StaticGetterNode(
       field_pos, implicit_argument, true, super_class, field_name);
 }
@@ -5420,7 +5411,7 @@
     // Do not add statements with no effect (e.g., LoadLocalNode).
     if ((statement != NULL) && statement->IsLoadLocalNode()) {
       // Skip load local.
-      statement = statement->AsLoadLocalNode()->pseudo();
+      continue;
     }
     if (statement != NULL) {
       if (!dead_code_allowed && abrupt_completing_seen) {
@@ -6886,7 +6877,7 @@
 
 
 bool Parser::IsAssignableExpr(AstNode* expr) {
-  return (expr->IsLoadLocalNode() && !expr->AsLoadLocalNode()->HasPseudo()
+  return (expr->IsLoadLocalNode()
           && (!expr->AsLoadLocalNode()->local().is_final()))
       || expr->IsLoadStaticFieldNode()
       || expr->IsStaticGetterNode()
@@ -7179,7 +7170,10 @@
   }
   // 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 LoadLocalNode(cascade_pos, cascade_receiver_var, cascade);
+  return new CommaNode(
+      cascade_pos,
+      cascade,
+      new LoadLocalNode(cascade_pos, cascade_receiver_var));
 }
 
 
@@ -7790,9 +7784,10 @@
     AstNode* store = CreateAssignmentNode(left_expr, add);
     // The result is a pair of the (side effects of the) store followed by
     // the (value of the) initial value temp variable load.
-    LoadLocalNode* load_res =
-        new LoadLocalNode(postfix_expr_pos, temp, store);
-    return load_res;
+    return new CommaNode(
+        postfix_expr_pos,
+        store,
+        new LoadLocalNode(postfix_expr_pos, temp));
   }
   return postfix_expr;
 }
diff --git a/runtime/vm/simulator_arm.cc b/runtime/vm/simulator_arm.cc
index 4e161c6..3542587 100644
--- a/runtime/vm/simulator_arm.cc
+++ b/runtime/vm/simulator_arm.cc
@@ -114,11 +114,13 @@
   bool GetFValue(char* desc, float* value);
   bool GetDValue(char* desc, double* value);
 
-  void PrintDartFrame(uword pc, uword fp, uword sp,
-                      const Function& function,
-                      intptr_t token_pos,
-                      bool is_optimized,
-                      bool is_inlined);
+  static intptr_t GetApproximateTokenIndex(const Code& code, uword pc);
+
+  static void PrintDartFrame(uword pc, uword fp, uword sp,
+                             const Function& function,
+                             intptr_t token_pos,
+                             bool is_optimized,
+                             bool is_inlined);
   void PrintBacktrace();
 
   // Set or delete a breakpoint. Returns true if successful.
@@ -262,6 +264,23 @@
 }
 
 
+intptr_t SimulatorDebugger::GetApproximateTokenIndex(const Code& code,
+                                                     uword pc) {
+  intptr_t token_pos = -1;
+  const PcDescriptors& descriptors =
+      PcDescriptors::Handle(code.pc_descriptors());
+  for (intptr_t i = 0; i < descriptors.Length(); i++) {
+    if (descriptors.PC(i) == pc) {
+      token_pos = descriptors.TokenPos(i);
+      break;
+    } else if ((token_pos <= 0) && (descriptors.PC(i) > pc)) {
+      token_pos = descriptors.TokenPos(i);
+    }
+  }
+  return token_pos;
+}
+
+
 void SimulatorDebugger::PrintDartFrame(uword pc, uword fp, uword sp,
                                        const Function& function,
                                        intptr_t token_pos,
@@ -313,7 +332,8 @@
           if (!it.Done()) {
             PrintDartFrame(unoptimized_pc, frame->fp(), frame->sp(),
                            inlined_function,
-                           unoptimized_code.GetTokenIndexOfPC(unoptimized_pc),
+                           GetApproximateTokenIndex(unoptimized_code,
+                                                    unoptimized_pc),
                            true, true);
           }
         }
@@ -321,7 +341,7 @@
       }
       PrintDartFrame(frame->pc(), frame->fp(), frame->sp(),
                      function,
-                     code.GetTokenIndexOfPC(frame->pc()),
+                     GetApproximateTokenIndex(code, frame->pc()),
                      code.is_optimized(), false);
     } else {
       OS::Print("pc=0x%"Px" fp=0x%"Px" sp=0x%"Px" %s frame\n",
@@ -1664,6 +1684,32 @@
             }
             break;
           }
+          case 7: {
+            // Registers rd_lo, rd_hi, rn, rm are encoded as rd, rn, rm, rs.
+            // Format(instr, "smlal'cond's 'rd, 'rn, 'rm, 'rs");
+            int32_t rd_lo_val = get_register(rd);
+            int32_t rd_hi_val = get_register(rn);
+            int64_t left_op  = static_cast<int32_t>(rm_val);
+            int64_t right_op = static_cast<int32_t>(rs_val);
+            uint32_t accum_lo = static_cast<uint32_t>(rd_lo_val);
+            int32_t accum_hi = static_cast<int32_t>(rd_hi_val);
+            int64_t accum = Utils::LowHighTo64Bits(accum_lo, accum_hi);
+            int64_t result = accum + left_op * right_op;
+            int32_t hi_res = Utils::High32Bits(result);
+            int32_t lo_res = Utils::Low32Bits(result);
+            set_register(rd, lo_res);
+            set_register(rn, hi_res);
+            if (instr->HasS()) {
+              if (lo_res != 0) {
+                // Collapse bits 0..31 into bit 32 so that 32-bit Z check works.
+                hi_res |= 1;
+              }
+              ASSERT((result == 0) == (hi_res == 0));  // Z bit
+              ASSERT(((result & (1LL << 63)) != 0) == (hi_res < 0));  // N bit
+              SetNZFlags(hi_res);
+            }
+            break;
+          }
           default: {
             UnimplementedInstruction(instr);
             break;
diff --git a/runtime/vm/simulator_mips.cc b/runtime/vm/simulator_mips.cc
index 393e261..0da94b0 100644
--- a/runtime/vm/simulator_mips.cc
+++ b/runtime/vm/simulator_mips.cc
@@ -1762,6 +1762,20 @@
       }
       break;
     }
+    case SLTI: {
+      // Format(instr, "slti 'rt, 'rs, 'imms");
+      int32_t rs_val = get_register(instr->RsField());
+      int32_t imm_val = instr->SImmField();
+      set_register(instr->RtField(), rs_val < imm_val ? 1 : 0);
+      break;
+    }
+    case SLTIU: {
+      // Format(instr, "slti 'rt, 'rs, 'immu");
+      uint32_t rs_val = get_register(instr->RsField());
+      uint32_t imm_val = instr->UImmField();
+      set_register(instr->RtField(), rs_val < imm_val ? 1 : 0);
+      break;
+    }
     case SDC1: {
       // Format(instr, "sdc1 'ft, 'imms('rs)");
       int32_t base_val = get_register(instr->RsField());
diff --git a/runtime/vm/stub_code_arm.cc b/runtime/vm/stub_code_arm.cc
index 0b8a041..1491ec3 100644
--- a/runtime/vm/stub_code_arm.cc
+++ b/runtime/vm/stub_code_arm.cc
@@ -437,13 +437,9 @@
   // Push arguments descriptor array.
   __ LoadImmediate(IP, reinterpret_cast<intptr_t>(Object::null()));
   __ PushList((1 << R4) | (1 << R5) | (1 << R6) | (1 << IP));
-
-  // R2: Smi-tagged arguments array length.
-  PushArgumentsArray(assembler);
-
   __ CallRuntime(kMegamorphicCacheMissHandlerRuntimeEntry);
   // Remove arguments.
-  __ Drop(4);
+  __ Drop(3);
   __ Pop(R0);  // Get result into R0.
 
   // Restore IC data and arguments descriptor.
diff --git a/runtime/vm/stub_code_ia32.cc b/runtime/vm/stub_code_ia32.cc
index 0657984..1acfc81 100644
--- a/runtime/vm/stub_code_ia32.cc
+++ b/runtime/vm/stub_code_ia32.cc
@@ -448,7 +448,7 @@
   __ pushl(raw_null);  // Space for the result of the runtime call.
   __ pushl(EAX);  // Pass receiver.
   __ pushl(ECX);  // Pass IC data.
-  __ pushl(EDX);  // Pass rguments descriptor.
+  __ pushl(EDX);  // Pass arguments descriptor.
   __ CallRuntime(kMegamorphicCacheMissHandlerRuntimeEntry);
   // Discard arguments.
   __ popl(EAX);
diff --git a/runtime/vm/stub_code_mips.cc b/runtime/vm/stub_code_mips.cc
index 5881403..39d3357 100644
--- a/runtime/vm/stub_code_mips.cc
+++ b/runtime/vm/stub_code_mips.cc
@@ -111,8 +111,22 @@
 }
 
 
+// Print the stop message.
+DEFINE_LEAF_RUNTIME_ENTRY(void, PrintStopMessage, const char* message) {
+  OS::Print("Stop message: %s\n", message);
+}
+END_LEAF_RUNTIME_ENTRY
+
+
+// Input parameters:
+//   A0 : stop message (const char*).
+// Must preserve all registers.
 void StubCode::GeneratePrintStopMessageStub(Assembler* assembler) {
-  __ Unimplemented("PrintStopMessage stub");
+  __ EnterCallRuntimeFrame(0);
+  // Call the runtime leaf function. A0 already contains the parameter.
+  __ CallRuntime(kPrintStopMessageRuntimeEntry);
+  __ LeaveCallRuntimeFrame();
+  __ Ret();
 }
 
 
@@ -239,6 +253,7 @@
 void StubCode::GenerateFixCallersTargetStub(Assembler* assembler) {
   // Create a stub frame as we are pushing some objects on the stack before
   // calling into the runtime.
+  __ TraceSimMsg("FixCallersTarget");
   __ EnterStubFrame();
   // Setup space on stack for return value and preserve arguments descriptor.
   __ addiu(SP, SP, Immediate(-2 * kWordSize));
@@ -324,17 +339,6 @@
   PushArgumentsArray(assembler);
   __ TraceSimMsg("InstanceFunctionLookupStub return");
 
-  // Stack:
-  // TOS + 0: argument array.
-  // TOS + 1: arguments descriptor array.
-  // TOS + 2: IC data object.
-  // TOS + 3: Receiver.
-  // TOS + 4: place for result from the call.
-  // TOS + 5: saved FP of previous frame.
-  // TOS + 6: dart code return address
-  // TOS + 7: pc marker (0 for stub).
-  // TOS + 8: last argument of caller.
-  // ....
   __ CallRuntime(kInstanceFunctionLookupRuntimeEntry);
 
   __ lw(V0, Address(SP, 4 * kWordSize));  // Get result into V0.
@@ -351,6 +355,8 @@
 DECLARE_LEAF_RUNTIME_ENTRY(void, DeoptimizeFillFrame, uword last_fp);
 
 
+
+
 // Used by eager and lazy deoptimization. Preserve result in V0 if necessary.
 // This stub translates optimized frame into unoptimized frame. The optimized
 // frame can contain values in registers and on stack, the unoptimized
@@ -364,42 +370,53 @@
 // GC can occur only after frame is fully rewritten.
 // Stack after EnterFrame(...) below:
 //   +------------------+
-//   | Saved FP         | <- TOS
+//   | Saved PP         | <- TOS
 //   +------------------+
-//   | return-address   |  (deoptimization point)
+//   | Saved FP         | <- FP of stub
 //   +------------------+
-//   | optimized frame  |
-//   |  ...             |
+//   | Saved LR         |  (deoptimization point)
+//   +------------------+
+//   | PC marker        |
+//   +------------------+
+//   | ...              | <- SP of optimized frame
 //
 // Parts of the code cannot GC, part of the code can GC.
 static void GenerateDeoptimizationSequence(Assembler* assembler,
                                            bool preserve_result) {
+  __ TraceSimMsg("GenerateDeoptimizationSequence");
   const intptr_t kPushedRegistersSize =
       kNumberOfCpuRegisters * kWordSize +
-      2 * kWordSize +  // FP and RA.
+      4 * kWordSize +  // PP, FP, RA, PC marker.
       kNumberOfFRegisters * kWordSize;
 
+  // DeoptimizeCopyFrame expects a Dart frame, i.e. EnterDartFrame(0), but there
+  // is no need to set the correct PC marker or load PP, since they get patched.
   __ addiu(SP, SP, Immediate(-kPushedRegistersSize * kWordSize));
-  __ sw(RA, Address(SP, kPushedRegistersSize - 1 * kWordSize));
-  __ sw(FP, Address(SP, kPushedRegistersSize - 2 * kWordSize));
-  __ addiu(FP, SP, Immediate(kPushedRegistersSize - 2 * kWordSize));
-
+  __ sw(ZR, Address(SP, kPushedRegistersSize - 1 * kWordSize));
+  __ sw(RA, Address(SP, kPushedRegistersSize - 2 * kWordSize));
+  __ sw(FP, Address(SP, kPushedRegistersSize - 3 * kWordSize));
+  __ sw(PP, Address(SP, kPushedRegistersSize - 4 * kWordSize));
+  __ addiu(FP, SP, Immediate(kPushedRegistersSize - 3 * kWordSize));
 
   // The code in this frame may not cause GC. kDeoptimizeCopyFrameRuntimeEntry
   // and kDeoptimizeFillFrameRuntimeEntry are leaf runtime calls.
-  const intptr_t saved_v0_offset_from_fp = -(kNumberOfCpuRegisters - V0);
+  const intptr_t saved_result_slot_from_fp =
+      kFirstLocalSlotFromFp + 1 - (kNumberOfCpuRegisters - V0);
   // Result in V0 is preserved as part of pushing all registers below.
 
+  // TODO(regis): Should we align the stack before pushing the fpu registers?
+  // If we do, saved_result_slot_from_fp is not constant anymore.
+
   // Push registers in their enumeration order: lowest register number at
   // lowest address.
   for (int i = 0; i < kNumberOfCpuRegisters; i++) {
-    const int slot = 2 + kNumberOfCpuRegisters - i;
+    const int slot = 4 + kNumberOfCpuRegisters - i;
     Register reg = static_cast<Register>(i);
     __ sw(reg, Address(SP, kPushedRegistersSize - slot * kWordSize));
   }
   for (int i = 0; i < kNumberOfFRegisters; i++) {
     // These go below the CPU registers.
-    const int slot = 2 + kNumberOfCpuRegisters + kNumberOfFRegisters - i;
+    const int slot = 4 + kNumberOfCpuRegisters + kNumberOfFRegisters - i;
     FRegister reg = static_cast<FRegister>(i);
     __ swc1(reg, Address(SP, kPushedRegistersSize - slot * kWordSize));
   }
@@ -411,38 +428,40 @@
 
   if (preserve_result) {
     // Restore result into T1 temporarily.
-    __ lw(T1, Address(FP, saved_v0_offset_from_fp * kWordSize));
+    __ lw(T1, Address(FP, saved_result_slot_from_fp * kWordSize));
   }
 
-  __ mov(SP, FP);
-  __ lw(FP, Address(SP, 0 * kWordSize));
-  __ lw(RA, Address(SP, 1 * kWordSize));
-  __ addiu(SP, SP, Immediate(2 * kWordSize));
-
+  __ addiu(SP, FP, Immediate(-kWordSize));
+  __ lw(RA, Address(SP, 2 * kWordSize));
+  __ lw(FP, Address(SP, 1 * kWordSize));
+  __ lw(PP, Address(SP, 0 * kWordSize));
   __ subu(SP, FP, V0);
 
-  __ addiu(SP, SP, Immediate(-2 * kWordSize));
-  __ sw(RA, Address(SP, 1 * kWordSize));
-  __ sw(FP, Address(SP, 0 * kWordSize));
-  __ mov(FP, SP);
+  // DeoptimizeFillFrame expects a Dart frame, i.e. EnterDartFrame(0), but there
+  // is no need to set the correct PC marker or load PP, since they get patched.
+  __ addiu(SP, SP, Immediate(-4 * kWordSize));
+  __ sw(ZR, Address(SP, 3 * kWordSize));
+  __ sw(RA, Address(SP, 2 * kWordSize));
+  __ sw(FP, Address(SP, 1 * kWordSize));
+  __ sw(PP, Address(SP, 0 * kWordSize));
+  __ addiu(FP, SP, Immediate(kWordSize));
 
-  __ mov(A0, SP);  // Get last FP address.
+  __ mov(A0, FP);  // Get last FP address.
   if (preserve_result) {
-    __ Push(T1);  // Preserve result.
+    __ Push(T1);  // Preserve result as first local.
   }
   __ ReserveAlignedFrameSpace(0);
   __ CallRuntime(kDeoptimizeFillFrameRuntimeEntry);  // Pass last FP in A0.
-  // Result (V0) is our FP.
   if (preserve_result) {
     // Restore result into T1.
-    __ lw(T1, Address(FP, -1 * kWordSize));
+    __ lw(T1, Address(FP, kFirstLocalSlotFromFp * kWordSize));
   }
   // Code above cannot cause GC.
-  __ mov(SP, FP);
-  __ lw(FP, Address(SP, 0 * kWordSize));
-  __ lw(RA, Address(SP, 1 * kWordSize));
-  __ addiu(SP, SP, Immediate(2 * kWordSize));
-  __ mov(FP, V0);
+  __ addiu(SP, FP, Immediate(-kWordSize));
+  __ lw(RA, Address(SP, 2 * kWordSize));
+  __ lw(FP, Address(SP, 1 * kWordSize));
+  __ lw(PP, Address(SP, 0 * kWordSize));
+  __ addiu(SP, SP, Immediate(4 * kWordSize));
 
   // Frame is fully rewritten at this point and it is safe to perform a GC.
   // Materialize any objects that were deferred by FillFrame because they
@@ -456,20 +475,22 @@
   // Result tells stub how many bytes to remove from the expression stack
   // of the bottom-most frame. They were used as materialization arguments.
   __ Pop(T1);
-  __ SmiUntag(T1);
   if (preserve_result) {
     __ Pop(V0);  // Restore result.
   }
   __ LeaveStubFrame();
-
-  // Return.
-  __ jr(RA);
-  __ delay_slot()->addu(SP, SP, T1);  // Remove materialization arguments.
+  // Remove materialization arguments.
+  __ SmiUntag(T1);
+  __ addu(SP, SP, T1);
+  __ Ret();
 }
 
 
 void StubCode::GenerateDeoptimizeLazyStub(Assembler* assembler) {
-  __ Unimplemented("DeoptimizeLazy stub");
+  // Correct return address to point just after the call that is being
+  // deoptimized.
+  __ AddImmediate(RA, -CallPattern::kFixedLengthInBytes);
+  GenerateDeoptimizationSequence(assembler, true);  // Preserve V0.
 }
 
 
@@ -480,6 +501,7 @@
 
 void StubCode::GenerateMegamorphicMissStub(Assembler* assembler) {
   __ Unimplemented("MegamorphicMiss stub");
+  return;
 }
 
 
@@ -866,6 +888,7 @@
 // Output:
 //   V0: new allocated RawContext object.
 void StubCode::GenerateAllocateContextStub(Assembler* assembler) {
+  __ TraceSimMsg("AllocateContext");
   if (FLAG_inline_alloc) {
     const Class& context_class = Class::ZoneHandle(Object::context_class());
     Label slow_case;
@@ -1757,6 +1780,7 @@
 void StubCode::GenerateBreakpointDynamicStub(Assembler* assembler) {
   // Create a stub frame as we are pushing some objects on the stack before
   // calling into the runtime.
+  __ TraceSimMsg("BreakpointDynamicStub");
   __ EnterStubFrame();
   __ addiu(SP, SP, Immediate(-2 * kWordSize));
   __ sw(S5, Address(SP, 1 * kWordSize));
@@ -2137,6 +2161,8 @@
   __ Bind(&reference_compare);
   __ subu(ret, left, right);
   __ Bind(&done);
+  // A branch or test after this comparison will check CMPRES == TMP1.
+  __ mov(TMP1, ZR);
   __ lw(T0, Address(SP, 0 * kWordSize));
   __ lw(T1, Address(SP, 1 * kWordSize));
   __ Ret();
diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h
index 8a4b2c9..6bc6f34 100644
--- a/runtime/vm/symbols.h
+++ b/runtime/vm/symbols.h
@@ -251,13 +251,11 @@
   V(DartCore, "dart:core")                                                     \
   V(DartCollection, "dart:collection")                                         \
   V(DartCollectionDev, "dart:_collection-dev")                                 \
-  V(DartCrypto, "dart:crypto")                                                 \
   V(DartIsolate, "dart:isolate")                                               \
   V(DartJson, "dart:json")                                                     \
   V(DartMath, "dart:math")                                                     \
   V(DartMirrors, "dart:mirrors")                                               \
   V(DartTypedData, "dart:typed_data")                                          \
-  V(DartUri, "dart:uri")                                                       \
   V(DartUtf, "dart:utf")                                                       \
   V(_Random, "_Random")                                                        \
   V(_state, "_state")                                                          \
diff --git a/runtime/vm/vm.gypi b/runtime/vm/vm.gypi
index 058f5ce..1e1da59 100644
--- a/runtime/vm/vm.gypi
+++ b/runtime/vm/vm.gypi
@@ -15,7 +15,6 @@
     'collection_patch_cc_file': '<(gen_source_dir)/collection_patch_gen.cc',
     'collection_dev_cc_file': '<(gen_source_dir)/collection_dev_gen.cc',
     'collection_dev_patch_cc_file': '<(gen_source_dir)/collection_dev_patch_gen.cc',
-    'crypto_cc_file': '<(gen_source_dir)/crypto_gen.cc',
     'math_cc_file': '<(gen_source_dir)/math_gen.cc',
     'math_patch_cc_file': '<(gen_source_dir)/math_patch_gen.cc',
     'mirrors_cc_file': '<(gen_source_dir)/mirrors_gen.cc',
@@ -26,7 +25,6 @@
     'json_patch_cc_file': '<(gen_source_dir)/json_patch_gen.cc',
     'typed_data_cc_file': '<(gen_source_dir)/typed_data_gen.cc',
     'typed_data_patch_cc_file': '<(gen_source_dir)/typed_data_patch_gen.cc',
-    'uri_cc_file': '<(gen_source_dir)/uri_gen.cc',
     'utf_cc_file': '<(gen_source_dir)/utf_gen.cc',
     'snapshot_test_dat_file': '<(gen_source_dir)/snapshot_test.dat',
     'snapshot_test_in_dat_file': 'snapshot_test_in.dat',
@@ -103,7 +101,6 @@
         'generate_collection_patch_cc_file',
         'generate_collection_dev_cc_file',
         'generate_collection_dev_patch_cc_file',
-        'generate_crypto_cc_file',
         'generate_math_cc_file',
         'generate_math_patch_cc_file',
         'generate_isolate_cc_file',
@@ -114,7 +111,6 @@
         'generate_mirrors_patch_cc_file',
         'generate_typed_data_cc_file',
         'generate_typed_data_patch_cc_file',
-        'generate_uri_cc_file',
         'generate_utf_cc_file',
       ],
       'includes': [
@@ -137,7 +133,6 @@
         '<(collection_patch_cc_file)',
         '<(collection_dev_cc_file)',
         '<(collection_dev_patch_cc_file)',
-        '<(crypto_cc_file)',
         '<(math_cc_file)',
         '<(math_patch_cc_file)',
         '<(isolate_cc_file)',
@@ -148,7 +143,6 @@
         '<(mirrors_patch_cc_file)',
         '<(typed_data_cc_file)',
         '<(typed_data_patch_cc_file)',
-        '<(uri_cc_file)',
         '<(utf_cc_file)',
       ],
       'include_dirs': [
@@ -415,39 +409,6 @@
       ]
     },
     {
-      'target_name': 'generate_crypto_cc_file',
-      'type': 'none',
-      'toolsets':['host', 'target'],
-      'includes': [
-        # Load the shared crypto sources.
-        '../../sdk/lib/crypto/crypto_sources.gypi',
-      ],
-      'actions': [
-        {
-          'action_name': 'generate_crypto_cc',
-          'inputs': [
-            '../tools/gen_library_src_paths.py',
-            '<(libgen_in_cc_file)',
-            '<@(_sources)',
-          ],
-          'outputs': [
-            '<(crypto_cc_file)',
-          ],
-          'action': [
-            'python',
-            'tools/gen_library_src_paths.py',
-            '--output', '<(crypto_cc_file)',
-            '--input_cc', '<(libgen_in_cc_file)',
-            '--include', 'vm/bootstrap.h',
-            '--var_name', 'dart::Bootstrap::crypto_source_paths_',
-            '--library_name', 'dart:crypto',
-            '<@(_sources)',
-          ],
-          'message': 'Generating ''<(crypto_cc_file)'' file.'
-        },
-      ]
-    },
-    {
       'target_name': 'generate_math_cc_file',
       'type': 'none',
       'toolsets':['host', 'target'],
@@ -921,39 +882,6 @@
       ]
     },
     {
-      'target_name': 'generate_uri_cc_file',
-      'type': 'none',
-      'toolsets':['host', 'target'],
-      'includes': [
-        # Load the shared uri sources.
-        '../../sdk/lib/uri/uri_sources.gypi',
-      ],
-      'actions': [
-        {
-          'action_name': 'generate_uri_cc',
-          'inputs': [
-            '../tools/gen_library_src_paths.py',
-            '<(libgen_in_cc_file)',
-            '<@(_sources)',
-          ],
-          'outputs': [
-            '<(uri_cc_file)',
-          ],
-          'action': [
-            'python',
-            'tools/gen_library_src_paths.py',
-            '--output', '<(uri_cc_file)',
-            '--input_cc', '<(libgen_in_cc_file)',
-            '--include', 'vm/bootstrap.h',
-            '--var_name', 'dart::Bootstrap::uri_source_paths_',
-            '--library_name', 'dart:uri',
-            '<@(_sources)',
-          ],
-          'message': 'Generating ''<(uri_cc_file)'' file.'
-        },
-      ]
-    },
-    {
       'target_name': 'generate_utf_cc_file',
       'type': 'none',
       'toolsets':['host', 'target'],
diff --git a/sdk/bin/dartanalyzer b/sdk/bin/dartanalyzer
index 3f0f947..cc33e5c 100755
--- a/sdk/bin/dartanalyzer
+++ b/sdk/bin/dartanalyzer
@@ -29,16 +29,16 @@
 
 DART_SDK=""
 if [ $FOUND_SDK = 0 ] ; then
-  if [ -f $DART_ANALYZER_HOME/lib/core/core.dart ] ; then
-    DART_SDK="--dart-sdk $DART_ANALYZER_HOME"
+  if [ -f "$DART_ANALYZER_HOME/lib/core/core.dart" ] ; then
+    DART_SDK=(--dart-sdk "$DART_ANALYZER_HOME")
   else
-    DART_SDK_HOME=$(dirname $DART_ANALYZER_HOME)/dart-sdk
-    if [ -d $DART_SDK_HOME ] ; then
-      DART_SDK="--dart-sdk $DART_SDK_HOME"
+    DART_SDK_HOME=$(dirname "$DART_ANALYZER_HOME")/dart-sdk
+    if [ -d "$DART_SDK_HOME" ] ; then
+      DART_SDK=(--dart-sdk "$DART_SDK_HOME")
     else
-      DART_SDK_HOME=$(dirname $DART_SDK_HOME)/dart-sdk
-      if [ -d $DART_SDK_HOME ] ; then
-        DART_SDK="--dart-sdk $DART_SDK_HOME"
+      DART_SDK_HOME=$(dirname "$DART_SDK_HOME")/dart-sdk
+      if [ -d "$DART_SDK_HOME" ] ; then
+        DART_SDK=(--dart-sdk "$DART_SDK_HOME")
       else
         echo "Couldn't find Dart SDK. Specify with --dart-sdk cmdline argument"
       fi
@@ -46,9 +46,9 @@
   fi
 fi
 
-if [ -f $DART_SDK_HOME/util/dartanalyzer/dartanalyzer.jar ] ; then
+if [ -f "$DART_SDK_HOME/util/dartanalyzer/dartanalyzer.jar" ] ; then
   DART_ANALYZER_LIBS=$DART_SDK_HOME/util/dartanalyzer
-elif [ -f $DART_ANALYZER_HOME/util/dartanalyzer/dartanalyzer.jar ] ; then
+elif [ -f "$DART_ANALYZER_HOME/util/dartanalyzer/dartanalyzer.jar" ] ; then
   DART_ANALYZER_LIBS=$DART_ANALYZER_HOME/util/dartanalyzer
 else
   echo "Configuration problem. Couldn't find dartanalyzer.jar."
@@ -76,4 +76,4 @@
 fi
 
 exec java $EXTRA_JVMARGS $DART_JVMARGS -ea -jar \
-  "$DART_ANALYZER_LIBS/dartanalyzer.jar" ${DART_SDK} $@
+  "$DART_ANALYZER_LIBS/dartanalyzer.jar" "${DART_SDK[@]}" $@
diff --git a/sdk/bin/dartanalyzer.bat b/sdk/bin/dartanalyzer.bat
index d3ed53b..4905124 100644
--- a/sdk/bin/dartanalyzer.bat
+++ b/sdk/bin/dartanalyzer.bat
@@ -36,12 +36,12 @@
     )

   )

 )

-endlocal & set "DART_SDK=%DART_SDK%" & set "DART_SDK_HOME=%DART_SDK_HOME%"

+endlocal & set DART_SDK=%DART_SDK% & set DART_SDK_HOME=%DART_SDK_HOME%

 

 if exist "%DART_SDK_HOME%\util\dartanalyzer\dartanalyzer.jar" (

-  set DART_ANALYZER_LIBS="%DART_SDK_HOME%\util\dartanalyzer"

+  set DART_ANALYZER_LIBS=%DART_SDK_HOME%\util\dartanalyzer

 ) else if exist "%DART_ANALYZER_HOME%\util\dartanalyzer\dartanalyzer.jar" (

-  set DART_ANALYZER_LIBS="%DART_ANALYZER_HOME%\util\dartanalyzer"

+  set DART_ANALYZER_LIBS=%DART_ANALYZER_HOME%\util\dartanalyzer

 ) else (

   echo Configuration problem. Couldn't find dartanalyzer.jar.

   exit /b 1

diff --git a/sdk/lib/_collection_dev/list.dart b/sdk/lib/_collection_dev/list.dart
index c14cb50..90a1d16 100644
--- a/sdk/lib/_collection_dev/list.dart
+++ b/sdk/lib/_collection_dev/list.dart
@@ -238,6 +238,7 @@
   Iterable<int> get keys => new _ListIndicesIterable(_values);
 
   bool get isEmpty => _values.isEmpty;
+  bool get isNotEmpty => _values.isNotEmpty;
   bool containsValue(E value) => _values.contains(value);
   bool containsKey(int key) => key is int && key >= 0 && key < length;
 
diff --git a/sdk/lib/_internal/compiler/compiler.dart b/sdk/lib/_internal/compiler/compiler.dart
index 41c5ac1..e0be239 100644
--- a/sdk/lib/_internal/compiler/compiler.dart
+++ b/sdk/lib/_internal/compiler/compiler.dart
@@ -5,7 +5,6 @@
 library compiler;
 
 import 'dart:async';
-import 'dart:uri';
 import 'implementation/apiimpl.dart';
 
 // Unless explicitly allowed, passing [:null:] for any argument to the
diff --git a/sdk/lib/_internal/compiler/implementation/apiimpl.dart b/sdk/lib/_internal/compiler/implementation/apiimpl.dart
index 69d3cfa..c582bc0 100644
--- a/sdk/lib/_internal/compiler/implementation/apiimpl.dart
+++ b/sdk/lib/_internal/compiler/implementation/apiimpl.dart
@@ -4,7 +4,6 @@
 
 library leg_apiimpl;
 
-import 'dart:uri';
 import 'dart:async';
 
 import '../compiler.dart' as api;
@@ -136,7 +135,7 @@
 
   elements.LibraryElement scanBuiltinLibrary(String path) {
     Uri uri = libraryRoot.resolve(lookupLibraryPath(path));
-    Uri canonicalUri = new Uri.fromComponents(scheme: "dart", path: path);
+    Uri canonicalUri = new Uri(scheme: "dart", path: path);
     elements.LibraryElement library =
         libraryLoader.loadLibrary(uri, null, canonicalUri);
     return library;
diff --git a/sdk/lib/_internal/compiler/implementation/code_buffer.dart b/sdk/lib/_internal/compiler/implementation/code_buffer.dart
index 1d58b9b..4934ea3 100644
--- a/sdk/lib/_internal/compiler/implementation/code_buffer.dart
+++ b/sdk/lib/_internal/compiler/implementation/code_buffer.dart
@@ -20,6 +20,8 @@
     return buffer.isEmpty;
   }
 
+  bool get isNotEmpty => !isEmpty;
+
   CodeBuffer add(var object) {
     write(object);
     return this;
diff --git a/sdk/lib/_internal/compiler/implementation/compiler.dart b/sdk/lib/_internal/compiler/implementation/compiler.dart
index a292e28..f14543f 100644
--- a/sdk/lib/_internal/compiler/implementation/compiler.dart
+++ b/sdk/lib/_internal/compiler/implementation/compiler.dart
@@ -318,6 +318,7 @@
   ClassElement typeClass;
   ClassElement mapClass;
   ClassElement symbolClass;
+  ClassElement stackTraceClass;
 
   // Initialized after mirrorSystemClass has been resolved.
   FunctionElement symbolConstructor;
@@ -579,7 +580,8 @@
     } else if (node is Element) {
       return spanFromElement(node);
     } else if (node is MetadataAnnotation) {
-      return spanFromTokens(node.beginToken, node.endToken);
+      MetadataAnnotation annotation = node;
+      return spanFromTokens(annotation.beginToken, annotation.endToken);
     } else {
       throw 'No error location.';
     }
@@ -679,6 +681,7 @@
     listClass = lookupCoreClass('List');
     typeClass = lookupCoreClass('Type');
     mapClass = lookupCoreClass('Map');
+    stackTraceClass = lookupCoreClass('StackTrace');
     if (!missingCoreClasses.isEmpty) {
       internalErrorOnElement(coreLibrary,
           'dart:core library does not contain required classes: '
@@ -741,7 +744,7 @@
     invokeOnMethod = jsInvocationMirrorClass.lookupLocalMember(INVOKE_ON);
 
     if (preserveComments) {
-      var uri = new Uri.fromComponents(scheme: 'dart', path: 'mirrors');
+      var uri = new Uri(scheme: 'dart', path: 'mirrors');
       LibraryElement libraryElement =
           libraryLoader.loadLibrary(uri, null, uri);
       documentClass = libraryElement.find(const SourceString('Comment'));
@@ -1108,7 +1111,9 @@
     if (Elements.isErroneousElement(element)) {
       element = element.enclosingElement;
     }
-    if (element.position() == null && !element.isCompilationUnit()) {
+    if (element.position() == null &&
+        !element.isLibrary() &&
+        !element.isCompilationUnit()) {
       // Sometimes, the backend fakes up elements that have no
       // position. So we use the enclosing element instead. It is
       // not a good error location, but cancel really is "internal
diff --git a/sdk/lib/_internal/compiler/implementation/dart2js.dart b/sdk/lib/_internal/compiler/implementation/dart2js.dart
index 20856b7..8d3c7da 100644
--- a/sdk/lib/_internal/compiler/implementation/dart2js.dart
+++ b/sdk/lib/_internal/compiler/implementation/dart2js.dart
@@ -7,7 +7,6 @@
 import 'dart:async';
 import 'dart:collection' show Queue, LinkedHashMap;
 import 'dart:io';
-import 'dart:uri';
 import 'dart:utf';
 
 import '../compiler.dart' as api;
diff --git a/sdk/lib/_internal/compiler/implementation/dart2jslib.dart b/sdk/lib/_internal/compiler/implementation/dart2jslib.dart
index 6dd95ef..c006c95 100644
--- a/sdk/lib/_internal/compiler/implementation/dart2jslib.dart
+++ b/sdk/lib/_internal/compiler/implementation/dart2jslib.dart
@@ -5,7 +5,6 @@
 library dart2js;
 
 import 'dart:async';
-import 'dart:uri';
 import 'dart:collection' show Queue, LinkedHashMap;
 
 import 'closure.dart' as closureMapping;
diff --git a/sdk/lib/_internal/compiler/implementation/dart_backend/backend.dart b/sdk/lib/_internal/compiler/implementation/dart_backend/backend.dart
index 26b930d..5bc30cd 100644
--- a/sdk/lib/_internal/compiler/implementation/dart_backend/backend.dart
+++ b/sdk/lib/_internal/compiler/implementation/dart_backend/backend.dart
@@ -77,8 +77,10 @@
   visitBlock(Block block) {
     shouldOmit(Statement statement) {
       if (statement is EmptyStatement) return true;
-      if (statement is ExpressionStatement) {
-        Send send = statement.expression.asSend();
+      ExpressionStatement expressionStatement =
+          statement.asExpressionStatement();
+      if (expressionStatement != null) {
+        Send send = expressionStatement.expression.asSend();
         if (send != null) {
           Element element = originalTreeElements[send];
           if (stripAsserts && identical(element, compiler.assertMethod)) {
@@ -90,8 +92,9 @@
     }
 
     rewriteStatement(Statement statement) {
-      if (statement is Block) {
-        Link statements = statement.statements.nodes;
+      Block block = statement.asBlock();
+      if (block != null) {
+        Link statements = block.statements.nodes;
         if (!statements.isEmpty && statements.tail.isEmpty) {
           Statement single = statements.head;
           bool isDeclaration =
@@ -150,7 +153,8 @@
       if (typeArguments == null) return;
       for (Node typeArgument in typeArguments.nodes) {
         if (typeArgument is TypeVariable) {
-          typeArgument = typeArgument.bound;
+          TypeVariable typeVariable = typeArgument;
+          typeArgument = typeVariable.bound;
         }
         if (typeArgument == null) continue;
         assert(typeArgument is TypeAnnotation);
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 e5ecbf3..2d67ace 100644
--- a/sdk/lib/_internal/compiler/implementation/dart_backend/placeholder_collector.dart
+++ b/sdk/lib/_internal/compiler/implementation/dart_backend/placeholder_collector.dart
@@ -265,12 +265,13 @@
   }
 
   void makeTypePlaceholder(Node node, DartType type) {
-    if (node is Send) {
+    Send send = node.asSend();
+    if (send != null) {
       // Prefix.
-      assert(node.receiver is Identifier);
-      assert(node.selector is Identifier);
-      makeNullPlaceholder(node.receiver);
-      node = node.selector;
+      assert(send.receiver is Identifier);
+      assert(send.selector is Identifier);
+      makeNullPlaceholder(send.receiver);
+      node = send.selector;
     }
     makeElementPlaceholder(node, type.element);
   }
@@ -497,20 +498,21 @@
       // TODO(smok): Fix this when resolver correctly deals with
       // such cases.
       if (definitionElement == null) continue;
-      if (definition is Send) {
+      Send send = definition.asSend();
+      if (send != null) {
         // May get FunctionExpression here in definition.selector
         // in case of A(int this.f());
-        if (definition.selector is Identifier) {
+        if (send.selector is Identifier) {
           if (identical(definitionElement.kind, ElementKind.FIELD_PARAMETER)) {
-            tryMakeMemberPlaceholder(definition.selector);
+            tryMakeMemberPlaceholder(send.selector);
           } else {
-            tryMakeLocalPlaceholder(definitionElement, definition.selector);
+            tryMakeLocalPlaceholder(definitionElement, send.selector);
           }
         } else {
-          assert(definition.selector is FunctionExpression);
+          assert(send.selector is FunctionExpression);
           if (identical(definitionElement.kind, ElementKind.FIELD_PARAMETER)) {
             tryMakeMemberPlaceholder(
-                definition.selector.asFunctionExpression().name);
+                send.selector.asFunctionExpression().name);
           }
         }
       } else if (definition is Identifier) {
diff --git a/sdk/lib/_internal/compiler/implementation/dart_backend/renamer.dart b/sdk/lib/_internal/compiler/implementation/dart_backend/renamer.dart
index 83531c7..5ad2230 100644
--- a/sdk/lib/_internal/compiler/implementation/dart_backend/renamer.dart
+++ b/sdk/lib/_internal/compiler/implementation/dart_backend/renamer.dart
@@ -88,9 +88,10 @@
     // js-helpers.
     StringBuffer result = new StringBuffer(renameElement(type.element));
     if (type is InterfaceType) {
-      if (!type.isRaw) {
+      InterfaceType interfaceType = type;
+      if (!interfaceType.isRaw) {
         result.write('<');
-        Link<DartType> argumentsLink = type.typeArguments;
+        Link<DartType> argumentsLink = interfaceType.typeArguments;
         result.write(renameType(argumentsLink.head, renameElement));
         for (Link<DartType> link = argumentsLink.tail; !link.isEmpty;
              link = link.tail) {
diff --git a/sdk/lib/_internal/compiler/implementation/deferred_load.dart b/sdk/lib/_internal/compiler/implementation/deferred_load.dart
index abcf627..1a8d770 100644
--- a/sdk/lib/_internal/compiler/implementation/deferred_load.dart
+++ b/sdk/lib/_internal/compiler/implementation/deferred_load.dart
@@ -4,9 +4,6 @@
 
 library deferred_load;
 
-import 'dart:uri'
-       show Uri;
-
 import 'dart:collection'
        show LinkedHashMap,
             LinkedHashSet;
@@ -65,7 +62,7 @@
   }
 
   ClassElement findDeferredLibraryClass() {
-    var uri = new Uri.fromComponents(scheme: 'dart', path: 'async');
+    var uri = new Uri(scheme: 'dart', path: 'async');
     LibraryElement asyncLibrary =
         compiler.libraryLoader.loadLibrary(uri, null, uri);
     var element = asyncLibrary.find(const SourceString('DeferredLibrary'));
diff --git a/sdk/lib/_internal/compiler/implementation/elements/elements.dart b/sdk/lib/_internal/compiler/implementation/elements/elements.dart
index c0bc01e4..bd1fac2 100644
--- a/sdk/lib/_internal/compiler/implementation/elements/elements.dart
+++ b/sdk/lib/_internal/compiler/implementation/elements/elements.dart
@@ -4,7 +4,6 @@
 
 library elements;
 
-import 'dart:uri';
 
 import 'modelx.dart';
 import '../tree/tree.dart';
@@ -827,8 +826,8 @@
   void reverseBackendMembers();
 
   Element lookupMember(SourceString memberName);
-  Element lookupSelector(Selector selector);
-  Element lookupSuperSelector(Selector selector);
+  Element lookupSelector(Selector selector, Compiler compiler);
+  Element lookupSuperSelector(Selector selector, Compiler compiler);
 
   Element lookupLocalMember(SourceString memberName);
   Element lookupBackendMember(SourceString memberName);
diff --git a/sdk/lib/_internal/compiler/implementation/elements/modelx.dart b/sdk/lib/_internal/compiler/implementation/elements/modelx.dart
index 5762744..1ea7a23 100644
--- a/sdk/lib/_internal/compiler/implementation/elements/modelx.dart
+++ b/sdk/lib/_internal/compiler/implementation/elements/modelx.dart
@@ -4,7 +4,6 @@
 
 library elements.modelx;
 
-import 'dart:uri';
 import 'dart:collection' show LinkedHashMap;
 
 import 'elements.dart';
@@ -1582,15 +1581,17 @@
    * When called on the implementation element both members declared in the
    * origin and the patch class are returned.
    */
-  Element lookupSelector(Selector selector) {
-    return internalLookupSelector(selector, false);
+  Element lookupSelector(Selector selector, Compiler compiler) {
+    return internalLookupSelector(selector, compiler, false);
   }
 
-  Element lookupSuperSelector(Selector selector) {
-    return internalLookupSelector(selector, true);
+  Element lookupSuperSelector(Selector selector, Compiler compiler) {
+    return internalLookupSelector(selector, compiler, true);
   }
 
-  Element internalLookupSelector(Selector selector, bool isSuperLookup) {
+  Element internalLookupSelector(Selector selector,
+                                 Compiler compiler,
+                                 bool isSuperLookup) {
     SourceString name = selector.name;
     bool isPrivate = name.isPrivate();
     LibraryElement library = selector.library;
@@ -1616,12 +1617,14 @@
         FunctionElement getter = field.getter;
         FunctionElement setter = field.setter;
         if (selector.isSetter()) {
-          if (setter != null) return setter;
+          // Abstract members can be defined in a super class.
+          if (setter != null && !setter.isAbstract(compiler)) return setter;
         } else {
           assert(selector.isGetter() || selector.isCall());
-          if (getter != null) return getter;
+          if (getter != null && !getter.isAbstract(compiler)) return getter;
         }
-      } else {
+      // Abstract members can be defined in a super class.
+      } else if (!member.isAbstract(compiler)) {
         return member;
       }
     }
diff --git a/sdk/lib/_internal/compiler/implementation/enqueue.dart b/sdk/lib/_internal/compiler/implementation/enqueue.dart
index ca6d2d6..18bf774 100644
--- a/sdk/lib/_internal/compiler/implementation/enqueue.dart
+++ b/sdk/lib/_internal/compiler/implementation/enqueue.dart
@@ -23,7 +23,11 @@
       if (element.isLibrary()) {
         LibraryElementX library = element;
         Uri uri = library.canonicalUri;
-        if (uri.scheme != 'dart' && !uri.path.startsWith('_')) {
+        // Don't include private implementation libraries.  These
+        // libraries contain special classes that cause problems
+        // in other parts of the resolver (in particular Null and Void).
+        // TODO(ahe): Consider lifting this restriction.
+        if (uri.scheme != 'dart' || !uri.path.startsWith('_')) {
           members = library.localMembers;
           // TODO(ahe): Is this right?  Is this necessary?
           name = library.getLibraryOrScriptName();
@@ -278,6 +282,12 @@
         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);
         }
       }
diff --git a/sdk/lib/_internal/compiler/implementation/filenames.dart b/sdk/lib/_internal/compiler/implementation/filenames.dart
index 46bc421..c5cc4e9 100644
--- a/sdk/lib/_internal/compiler/implementation/filenames.dart
+++ b/sdk/lib/_internal/compiler/implementation/filenames.dart
@@ -5,7 +5,6 @@
 library filenames;
 
 import 'dart:io';
-import 'dart:uri';
 
 // TODO(ahe): This library should be replaced by a general
 // path-munging library.
@@ -21,7 +20,7 @@
   return new Path(path).toNativePath();
 }
 
-final Uri currentDirectory = new Uri.fromComponents(
+final Uri currentDirectory = new Uri(
     scheme: 'file',
     path: appendSlash(nativeToUriPath(new File('.').fullPathSync())));
 
diff --git a/sdk/lib/_internal/compiler/implementation/js/printer.dart b/sdk/lib/_internal/compiler/implementation/js/printer.dart
index 2645362..f7d65c1 100644
--- a/sdk/lib/_internal/compiler/implementation/js/printer.dart
+++ b/sdk/lib/_internal/compiler/implementation/js/printer.dart
@@ -161,7 +161,8 @@
 
   void blockOutWithoutBraces(Node node) {
     if (node is Block) {
-      node.statements.forEach(blockOutWithoutBraces);
+      Block block = node;
+      block.statements.forEach(blockOutWithoutBraces);
     } else {
       visit(node);
     }
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart b/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart
index d2584bc..fde02b4 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart
@@ -828,6 +828,10 @@
     return interceptedElements[name] != null;
   }
 
+  bool isInterceptedSelector(Selector selector) {
+    return interceptedElements[selector.name] != null;
+  }
+
   final Map<SourceString, Set<ClassElement>> interceptedClassesCache =
       new Map<SourceString, Set<ClassElement>>();
 
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart b/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart
index 54ded9c..6ecbfd5 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart
@@ -1254,7 +1254,6 @@
       String holder = namer.isolateAccess(backend.getImplementationClass(cls));
       for (TypeCheck check in typeChecks[cls]) {
         ClassElement cls = check.cls;
-        buffer.write('$holder.${namer.operatorIs(check.cls)}$_=${_}true$N');
         buffer.write('$holder.${namer.operatorIs(cls)}$_=${_}true$N');
         Substitution substitution = check.substitution;
         if (substitution != null) {
@@ -1741,7 +1740,8 @@
     List<Constant> constants = handler.getConstantsForEmission();
     for (Constant constant in constants) {
       if (constant is InterceptorConstant) {
-        needed.add(constant.dispatchedType.element);
+        InterceptorConstant inceptorConstant = constant;
+        needed.add(inceptorConstant.dispatchedType.element);
       }
     }
 
@@ -3033,16 +3033,28 @@
         for (LibraryElement library in sortedLibraries) {
           List<CodeBuffer> buffers = libraryBuffers[library];
           var buffer = buffers[0];
+          var uri = library.canonicalUri;
+          if (uri.scheme == 'file' && compiler.sourceMapUri != null) {
+            // TODO(ahe): It is a hack to use compiler.sourceMapUri
+            // here.  It should be relative to the main JavaScript
+            // output file.
+            uri = relativize(
+                compiler.sourceMapUri, library.canonicalUri, false);
+          }
           if (buffer != null) {
             mainBuffer
-                ..write('["${library.getLibraryOrScriptName()}",$_{$n')
+                ..write('["${library.getLibraryOrScriptName()}",$_')
+                ..write('"${uri}",$_')
+                ..write('{$n')
                 ..addBuffer(buffer)
                 ..write('}],$n');
           }
           buffer = buffers[1];
           if (buffer != null) {
             deferredBuffer
-                ..write('["${library.getLibraryOrScriptName()}",$_{$n')
+                ..write('["${library.getLibraryOrScriptName()}",$_')
+                ..write('"${uri}",$_')
+                ..write('{$n')
                 ..addBuffer(buffer)
                 ..write('}],$n');
           }
@@ -3227,7 +3239,8 @@
   for (var i = 0; i < length; i++) {
     var data = reflectionData[i];
     var name = data[0];
-    var descriptor = data[1];
+    var uri = data[1];
+    var descriptor = data[2];
     var classes = [];
     var functions = [];
     for (var property in descriptor) {
@@ -3242,7 +3255,6 @@
         classes.push(element[""]);
       }
     }
-    var uri = ".../library" + i + ".dart";
     libraries.push([name, uri, classes, functions]);
   }
 })''';
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/js_backend.dart b/sdk/lib/_internal/compiler/implementation/js_backend/js_backend.dart
index fae1efc..4f7b499 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/js_backend.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/js_backend.dart
@@ -25,6 +25,7 @@
 import '../universe/universe.dart' hide js; // TODO(ahe): VM bug, see above.
 import '../util/characters.dart';
 import '../util/util.dart';
+import '../util/uri_extras.dart' show relativize;
 
 part 'backend.dart';
 part 'constant_emitter.dart';
diff --git a/sdk/lib/_internal/compiler/implementation/lib/collection_patch.dart b/sdk/lib/_internal/compiler/implementation/lib/collection_patch.dart
index a5a7b89..803c97e 100644
--- a/sdk/lib/_internal/compiler/implementation/lib/collection_patch.dart
+++ b/sdk/lib/_internal/compiler/implementation/lib/collection_patch.dart
@@ -30,6 +30,7 @@
 
   patch int get length => _length;
   patch bool get isEmpty => _length == 0;
+  patch bool get isNotEmpty => !isEmpty;
 
   patch Iterable<K> get keys {
     return new HashMapKeyIterable<K>(this);
@@ -391,6 +392,8 @@
 
   patch int get length => _length;
   patch bool get isEmpty => _length == 0;
+  patch bool get isNotEmpty => !isEmpty;
+
 
   patch Iterable<K> get keys {
     return new LinkedHashMapKeyIterable<K>(this);
@@ -744,6 +747,7 @@
 
   patch int get length => _length;
   patch bool get isEmpty => _length == 0;
+  patch bool get isNotEmpty => !isEmpty;
 
   patch bool contains(Object object) {
     if (_isStringElement(object)) {
@@ -1038,6 +1042,7 @@
 
   patch int get length => _length;
   patch bool get isEmpty => _length == 0;
+  patch bool get isNotEmpty => !isEmpty;
 
   patch bool contains(Object object) {
     if (_isStringElement(object)) {
diff --git a/sdk/lib/_internal/compiler/implementation/lib/constant_map.dart b/sdk/lib/_internal/compiler/implementation/lib/constant_map.dart
index d84b4a5..1647f32 100644
--- a/sdk/lib/_internal/compiler/implementation/lib/constant_map.dart
+++ b/sdk/lib/_internal/compiler/implementation/lib/constant_map.dart
@@ -40,6 +40,8 @@
 
   bool get isEmpty => length == 0;
 
+  bool get isNotEmpty => !isEmpty;
+
   String toString() => Maps.mapToString(this);
 
   _throwUnmodifiable() {
diff --git a/sdk/lib/_internal/compiler/implementation/lib/core_patch.dart b/sdk/lib/_internal/compiler/implementation/lib/core_patch.dart
index 4d6d4c1..dec98f1 100644
--- a/sdk/lib/_internal/compiler/implementation/lib/core_patch.dart
+++ b/sdk/lib/_internal/compiler/implementation/lib/core_patch.dart
@@ -6,7 +6,6 @@
 import 'dart:_interceptors';
 import 'dart:_js_helper' show checkNull,
                               getRuntimeType,
-                              isJsArray,
                               JSSyntaxRegExp,
                               Primitives,
                               stringJoinUnchecked;
@@ -213,7 +212,7 @@
 
 patch class String {
   patch factory String.fromCharCodes(Iterable<int> charCodes) {
-    if (!isJsArray(charCodes)) {
+    if (charCodes is! JSArray) {
       charCodes = new List.from(charCodes);
     }
     return Primitives.stringFromCharCodes(charCodes);
diff --git a/sdk/lib/_internal/compiler/implementation/lib/foreign_helper.dart b/sdk/lib/_internal/compiler/implementation/lib/foreign_helper.dart
index 0e72750..fb06bf3 100644
--- a/sdk/lib/_internal/compiler/implementation/lib/foreign_helper.dart
+++ b/sdk/lib/_internal/compiler/implementation/lib/foreign_helper.dart
@@ -157,3 +157,9 @@
  * Returns the prefix used for generated type argument substitutions on classes.
  */
 String JS_OPERATOR_AS_PREFIX() {}
+
+/**
+ * Returns the field name used for determining if an object or its
+ * interceptor has JavaScript indexing behavior.
+ */
+String JS_IS_INDEXABLE_FIELD_NAME() {}
diff --git a/sdk/lib/_internal/compiler/implementation/lib/interceptors.dart b/sdk/lib/_internal/compiler/implementation/lib/interceptors.dart
index 67e6a0c..b144a30 100644
--- a/sdk/lib/_internal/compiler/implementation/lib/interceptors.dart
+++ b/sdk/lib/_internal/compiler/implementation/lib/interceptors.dart
@@ -11,8 +11,6 @@
                               Null,
                               JSSyntaxRegExp,
                               Primitives,
-                              checkGrowable,
-                              checkMutable,
                               checkNull,
                               checkNum,
                               checkString,
@@ -51,6 +49,9 @@
   // This is a magic method: the compiler does specialization of it
   // depending on the uses of intercepted methods and instantiated
   // primitive types.
+  // This method is recursive to prevent the type analyzer from thinking that
+  // the method returns `null`.
+  return getInterceptor(object);
 }
 
 /**
@@ -79,7 +80,7 @@
   defineProperty(object, dispatchPropertyName, value);
 }
 
-makeDispatchRecord(interceptor, proto, extension) {
+makeDispatchRecord(interceptor, proto, extension, indexability) {
   // Dispatch records are stored in the prototype chain, and in some cases, on
   // instances.
   //
@@ -108,21 +109,18 @@
   //     P      I                     if object's prototype is P, use I
   //     F      -           P         if object's prototype is P, call F
 
-  // TODO(kasperl): Remove this hack. It is needed to avoid inlining
-  // this method because inlining gives us multiple allocation points
-  // for records which is bad because it leads to polymorphic access.
+  // BUG(10903): Remove this hack. It is needed to avoid inlining this
+  // method because inlining gives us multiple allocation points for
+  // records which is bad because it leads to polymorphic access.
   if (false) return null;
-  return JS('', '{i: #, p: #, e: #, x: null}', interceptor, proto, extension);
+  return JS('', '{i: #, p: #, e: #, x: #}',
+            interceptor, proto, extension, indexability);
 }
 
 dispatchRecordInterceptor(record) => JS('', '#.i', record);
 dispatchRecordProto(record) => JS('', '#.p', record);
 dispatchRecordExtension(record) => JS('', '#.e', record);
-
 dispatchRecordIndexability(record) => JS('bool|Null', '#.x', record);
-setDispatchRecordIndexability(record, bool value) {
-  JS('void', '#.x = #', record, value);
-}
 
 /**
  * Returns the interceptor for a native class instance. Used by
@@ -201,7 +199,7 @@
       JS('void', '#(#)', setGetDispatchPropertyFn, getter);
       setDispatchProperty(
           objectProto,
-          makeDispatchRecord(jsObjectInterceptor, objectProto, null));
+          makeDispatchRecord(jsObjectInterceptor, objectProto, null, null));
       return;
     }
   }
@@ -233,7 +231,7 @@
       }
       setDispatchProperty(
           objectProto,
-          makeDispatchRecord(jsObjectInterceptor, objectProto, null));
+          makeDispatchRecord(jsObjectInterceptor, objectProto, null, null));
       return;
     }
   }
diff --git a/sdk/lib/_internal/compiler/implementation/lib/js_array.dart b/sdk/lib/_internal/compiler/implementation/lib/js_array.dart
index 30e0a39..40ce9fa 100644
--- a/sdk/lib/_internal/compiler/implementation/lib/js_array.dart
+++ b/sdk/lib/_internal/compiler/implementation/lib/js_array.dart
@@ -13,8 +13,20 @@
 class JSArray<E> extends Interceptor implements List<E>, JSIndexable {
   const JSArray();
 
+  checkMutable(reason) {
+    if (this is !JSMutableArray) { 
+      throw new UnsupportedError(reason);
+    }
+  }
+
+  checkGrowable(reason) {
+    if (this is !JSExtendableArray) {
+      throw new UnsupportedError(reason);
+    }
+  }
+
   void add(E value) {
-    checkGrowable(this, 'add');
+    checkGrowable('add');
     JS('void', r'#.push(#)', this, value);
   }
 
@@ -23,7 +35,7 @@
     if (index < 0 || index >= length) {
       throw new RangeError.value(index);
     }
-    checkGrowable(this, 'removeAt');
+    checkGrowable('removeAt');
     return JS('var', r'#.splice(#, 1)[0]', this, index);
   }
 
@@ -32,28 +44,28 @@
     if (index < 0 || index > length) {
       throw new RangeError.value(index);
     }
-    checkGrowable(this, 'insert');
+    checkGrowable('insert');
     JS('void', r'#.splice(#, 0, #)', this, index, value);
   }
 
   void insertAll(int index, Iterable<E> iterable) {
-    checkGrowable(this, 'insertAll');
+    checkGrowable('insertAll');
     IterableMixinWorkaround.insertAllList(this, index, iterable);
   }
 
   void setAll(int index, Iterable<E> iterable) {
-    checkMutable(this, 'setAll');
+    checkMutable('setAll');
     IterableMixinWorkaround.setAllList(this, index, iterable);
   }
 
   E removeLast() {
-    checkGrowable(this, 'removeLast');
+    checkGrowable('removeLast');
     if (length == 0) throw new RangeError.value(-1);
     return JS('var', r'#.pop()', this);
   }
 
   bool remove(Object element) {
-    checkGrowable(this, 'remove');
+    checkGrowable('remove');
     for (int i = 0; i < this.length; i++) {
       if (this[i] == element) {
         JS('var', r'#.splice(#, 1)', this, i);
@@ -188,7 +200,7 @@
   }
 
   void removeRange(int start, int end) {
-    checkGrowable(this, 'removeRange');
+    checkGrowable('removeRange');
     int receiverLength = this.length;
     if (start < 0 || start > receiverLength) {
       throw new RangeError.range(start, 0, receiverLength);
@@ -205,17 +217,17 @@
   }
 
   void setRange(int start, int end, Iterable<E> iterable, [int skipCount = 0]) {
-    checkMutable(this, 'set range');
+    checkMutable('set range');
     IterableMixinWorkaround.setRangeList(this, start, end, iterable, skipCount);
   }
 
   void fillRange(int start, int end, [E fillValue]) {
-    checkMutable(this, 'fill range');
+    checkMutable('fill range');
     IterableMixinWorkaround.fillRangeList(this, start, end, fillValue);
   }
 
   void replaceRange(int start, int end, Iterable<E> iterable) {
-    checkGrowable(this, 'removeRange');
+    checkGrowable('removeRange');
     IterableMixinWorkaround.replaceRangeList(this, start, end, iterable);
   }
 
@@ -226,7 +238,7 @@
   Iterable<E> get reversed => IterableMixinWorkaround.reversedList(this);
 
   void sort([int compare(E a, E b)]) {
-    checkMutable(this, 'sort');
+    checkMutable('sort');
     IterableMixinWorkaround.sortList(this, compare);
   }
 
@@ -247,6 +259,8 @@
 
   bool get isEmpty => length == 0;
 
+  bool get isNotEmpty => !isEmpty;
+
   String toString() => ToString.iterableToString(this);
 
   List<E> toList({ bool growable: true }) =>
@@ -263,7 +277,7 @@
   void set length(int newLength) {
     if (newLength is !int) throw new ArgumentError(newLength);
     if (newLength < 0) throw new RangeError.value(newLength);
-    checkGrowable(this, 'set length');
+    checkGrowable('set length');
     JS('void', r'#.length = #', this, newLength);
   }
 
@@ -274,7 +288,7 @@
   }
 
   void operator []=(int index, E value) {
-    checkMutable(this, 'indexed set');
+    checkMutable('indexed set');
     if (index is !int) throw new ArgumentError(index);
     if (index >= length || index < 0) throw new RangeError.value(index);
     JS('void', r'#[#] = #', this, index, value);
diff --git a/sdk/lib/_internal/compiler/implementation/lib/js_helper.dart b/sdk/lib/_internal/compiler/implementation/lib/js_helper.dart
index 3b5371c..17507a2 100644
--- a/sdk/lib/_internal/compiler/implementation/lib/js_helper.dart
+++ b/sdk/lib/_internal/compiler/implementation/lib/js_helper.dart
@@ -12,16 +12,9 @@
                                    JS_DART_OBJECT_CONSTRUCTOR,
                                    JS_OPERATOR_IS_PREFIX,
                                    JS_OPERATOR_AS_PREFIX,
+                                   JS_IS_INDEXABLE_FIELD_NAME,
                                    RAW_DART_FUNCTION_REF;
-import 'dart:_interceptors' show getInterceptor,
-                                 interceptedNames,
-                                 makeDispatchRecord,
-                                 getDispatchProperty,
-                                 dispatchRecordIndexability,
-                                 setDispatchRecordIndexability,
-                                 Interceptor,
-                                 JSMutableIndexable,
-                                 JSUnknown;
+import 'dart:_interceptors';
 import "dart:_collection-dev" as _symbol_dev;
 
 part 'constant_map.dart';
@@ -39,32 +32,7 @@
     var result = dispatchRecordIndexability(record);
     if (result != null) return result;
   }
-  return isJsIndexableSlow(object);
-}
-
-// We keep the slow path of the indexability check in a separate method
-// to get better code generated for the fast path and to increase the
-// chance of having it inlined.
-bool isJsIndexableSlow(var object) {
-  bool result = object is JavaScriptIndexingBehavior;
-  var record = getDispatchProperty(object);
-  if (record == null) return result;
-  // This is intentionally written to have two return points, so we
-  // will not inline the slow path function into the fast one.
-  setDispatchRecordIndexability(record, result);
-  return result;
-}
-
-checkMutable(list, reason) {
-  if (JS('bool', r'!!(#.immutable$list)', list)) {
-    throw new UnsupportedError(reason);
-  }
-}
-
-checkGrowable(list, reason) {
-  if (JS('bool', r'!!(#.fixed$length)', list)) {
-    throw new UnsupportedError(reason);
-  }
+  return object is JavaScriptIndexingBehavior;
 }
 
 String S(value) {
@@ -329,7 +297,7 @@
 
   /// Returns the type of [object] as a string (including type arguments).
   static String objectTypeName(Object object) {
-    String name = constructorNameFallback(object);
+    String name = constructorNameFallback(getInterceptor(object));
     if (name == 'Object') {
       // Try to decompile the constructor by turning it into a string
       // and get the name out of that. If the decompiled name is a
@@ -600,6 +568,14 @@
   }
 
   static getConstructor(String className) {
+    // TODO(ahe): Generalize this and improve test coverage of
+    // reflecting on intercepted classes.
+    if (JS('bool', '# == "String"', className)) return const JSString();
+    if (JS('bool', '# == "int"', int)) return const JSInt();
+    if (JS('bool', '# == "double"', int)) return const JSDouble();
+    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);
   }
diff --git a/sdk/lib/_internal/compiler/implementation/lib/js_number.dart b/sdk/lib/_internal/compiler/implementation/lib/js_number.dart
index b6219e7..445e927 100644
--- a/sdk/lib/_internal/compiler/implementation/lib/js_number.dart
+++ b/sdk/lib/_internal/compiler/implementation/lib/js_number.dart
@@ -264,7 +264,14 @@
   }
 }
 
-class JSInt extends JSNumber implements int {
+/**
+ * The interceptor class for [int]s.
+ *
+ * This class implements double since in JavaScript all numbers are doubles, so
+ * while we want to treat `2.0` as an integer for some operations, its
+ * interceptor should answer `true` to `is double`.
+ */
+class JSInt extends JSNumber implements int, double {
   const JSInt();
 
   bool get isEven => (this & 1) == 0;
diff --git a/sdk/lib/_internal/compiler/implementation/lib/js_rti.dart b/sdk/lib/_internal/compiler/implementation/lib/js_rti.dart
index 21be9af..721f38f 100644
--- a/sdk/lib/_internal/compiler/implementation/lib/js_rti.dart
+++ b/sdk/lib/_internal/compiler/implementation/lib/js_rti.dart
@@ -5,7 +5,7 @@
 part of _js_helper;
 
 setRuntimeTypeInfo(target, typeInfo) {
-  assert(typeInfo == null || isJsArray(typeInfo));
+  assert(typeInfo == null || typeInfo is JSArray);
   // We have to check for null because factories may return null.
   if (target != null) JS('var', r'#.$builtinTypeInfo = #', target, typeInfo);
 }
@@ -49,7 +49,7 @@
 String runtimeTypeToString(type) {
   if (type == null) {
     return 'dynamic';
-  } else if (isJsArray(type)) {
+  } else if (type is JSArray) {
     // A list representing a type with arguments.
     return getRuntimeTypeAsString(type);
   } else {
@@ -79,7 +79,7 @@
 }
 
 String getRuntimeTypeString(var object) {
-  String className = isJsArray(object) ? 'List' : getClassName(object);
+  String className = object is JSArray ? 'List' : getClassName(object);
   var typeInfo = JS('var', r'#.$builtinTypeInfo', object);
   return "$className${joinArguments(typeInfo, 0)}";
 }
@@ -98,7 +98,7 @@
 Object call(target, name) => JS('var', r'#[#]()', target, name);
 
 substitute(var substitution, var arguments) {
-  if (isJsArray(substitution)) {
+  if (substitution is JSArray) {
     arguments = substitution;
   } else if (isJsFunction(substitution)) {
     arguments = invoke(substitution, arguments);
@@ -176,8 +176,8 @@
   // [:null:] means a raw type.
   if (s == null || t == null) return true;
 
-  assert(isJsArray(s));
-  assert(isJsArray(t));
+  assert(s is JSArray);
+  assert(t is JSArray);
   assert(s.length == t.length);
 
   int len = s.length;
@@ -190,7 +190,7 @@
 }
 
 getArguments(var type) {
-  return isJsArray(type) ? JS('var', r'#.slice(1)', type) : null;
+  return type is JSArray ? JS('var', r'#.slice(1)', type) : null;
 }
 
 getField(var object, var name) => JS('var', r'#[#]', object, name);
@@ -205,9 +205,7 @@
   // Get the runtime type information from the object here, because we may
   // overwrite o with the interceptor below.
   var rti = getRuntimeTypeInfo(o);
-  // Check for native objects and use the interceptor instead of the object.
-  // TODO(9586): Move type info for static functions onto an interceptor.
-  o = isJsFunction(o) ? o : getInterceptor(o);
+  o = getInterceptor(o);
   // We can use the object as its own type representation because we install
   // the subtype flags and the substitution on the prototype, so they are
   // properties of the object in JS.
@@ -263,8 +261,8 @@
   if (JS('bool', '# === #', s, t)) return true;
   // Get the object describing the class and check for the subtyping flag
   // constructed from the type of [t].
-  var typeOfS = isJsArray(s) ? s[0] : s;
-  var typeOfT = isJsArray(t) ? t[0] : t;
+  var typeOfS = s is JSArray ? s[0] : s;
+  var typeOfT = t is JSArray ? t[0] : t;
   // TODO(johnniwinther): replace this with the real function subtype test.
   if (JS('bool', '#.func', s) == true || JS('bool', '#.func', t) == true ) {
     return true;
@@ -282,8 +280,8 @@
   // arguments and no substitution, it is used as raw type.  If [t] has no
   // type arguments, it used as a raw type.  In both cases, [s] is a subtype
   // of [t].
-  if ((!isJsArray(s) && JS('bool', '# == null', substitution)) ||
-      !isJsArray(t)) {
+  if ((s is! JSArray && JS('bool', '# == null', substitution)) ||
+      t is! JSArray) {
     return true;
   }
   // Recursively check the type arguments.
diff --git a/sdk/lib/_internal/compiler/implementation/lib/js_string.dart b/sdk/lib/_internal/compiler/implementation/lib/js_string.dart
index 04cfa7d..610f7f8 100644
--- a/sdk/lib/_internal/compiler/implementation/lib/js_string.dart
+++ b/sdk/lib/_internal/compiler/implementation/lib/js_string.dart
@@ -227,6 +227,8 @@
 
   bool get isEmpty => length == 0;
 
+  bool get isNotEmpty => !isEmpty;
+
   int compareTo(String other) {
     if (other is !String) throw new ArgumentError(other);
     return this == other ? 0
diff --git a/sdk/lib/_internal/compiler/implementation/lib/mirrors_patch.dart b/sdk/lib/_internal/compiler/implementation/lib/mirrors_patch.dart
index 88e9bba..ffcef0a 100644
--- a/sdk/lib/_internal/compiler/implementation/lib/mirrors_patch.dart
+++ b/sdk/lib/_internal/compiler/implementation/lib/mirrors_patch.dart
@@ -7,7 +7,7 @@
 import 'dart:_foreign_helper' show JS;
 import 'dart:_collection-dev' as _symbol_dev;
 import 'dart:_js_helper' show createInvocationMirror;
-import 'dart:_interceptors' show getInterceptor;
+import 'dart:_interceptors' show Interceptor;
 
 patch class MirrorSystem {
   patch static String getName(Symbol symbol) => _n(symbol);
@@ -38,7 +38,7 @@
       List<String> classes = data[2];
       List<String> functions = data[3];
       var libraries = result.putIfAbsent(name, () => <LibraryMirror>[]);
-      libraries.add(new _LibraryMirror(name, uri, classes, functions));
+      libraries.add(new _LibraryMirror(_s(name), uri, classes, functions));
     }
     return result;
   }
@@ -50,18 +50,22 @@
 }
 
 class _LibraryMirror extends _ObjectMirror implements LibraryMirror {
-  final String _name;
+  final Symbol simpleName;
   final Uri uri;
   final List<String> _classes;
   final List<String> _functions;
 
-  _LibraryMirror(this._name, this.uri, this._classes, this._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]);
-      result[symbol] = _reflectClass(symbol, _classes[i + 1]);
+      _ClassMirror cls = _reflectClass(symbol, _classes[i + 1]);
+      result[symbol] = cls;
+      cls._owner = this;
     }
     return result;
   }
@@ -76,6 +80,53 @@
     // 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);
@@ -205,20 +256,54 @@
   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);
 
-  Map<Symbol, Mirror> get members {
-    var result = new Map<Symbol, Mirror>();
+  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);
@@ -254,6 +339,26 @@
             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)})';
 }
@@ -263,6 +368,7 @@
   final Symbol simpleName;
   final String _jsName;
   final bool _readOnly;
+  DeclarationMirror _owner;
 
   _VariableMirror(this.simpleName, this._jsName, this._readOnly);
 
@@ -287,6 +393,10 @@
 
   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;
@@ -314,7 +424,7 @@
     }
     var jsFunction = JS('', '#[#]', reflectee, callName);
     int parameterCount = int.parse(callName.split(r'$')[1]);
-    return new _MethodMirror(jsFunction, parameterCount);
+    return new _MethodMirror(_s(callName), jsFunction, parameterCount);
   }
 
   InstanceMirror apply(List positionalArguments,
@@ -331,13 +441,26 @@
 }
 
 class _MethodMirror implements MethodMirror {
+  final Symbol simpleName;
   final _jsFunction;
   final int _parameterCount;
+  DeclarationMirror _owner;
 
-  _MethodMirror(this._jsFunction, this._parameterCount);
+  _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)}');
 }
diff --git a/sdk/lib/_internal/compiler/implementation/lib/native_helper.dart b/sdk/lib/_internal/compiler/implementation/lib/native_helper.dart
index b7a1f44..f4c1fe2 100644
--- a/sdk/lib/_internal/compiler/implementation/lib/native_helper.dart
+++ b/sdk/lib/_internal/compiler/implementation/lib/native_helper.dart
@@ -163,6 +163,7 @@
   if (!identical(JS('String', 'typeof(navigator)'), 'object')) return typeNameInChrome;
 
   String userAgent = JS('String', "navigator.userAgent");
+  // TODO(antonm): remove a reference to DumpRenderTree.
   if (contains(userAgent, 'Chrome') || contains(userAgent, 'DumpRenderTree')) {
     return typeNameInChrome;
   } else if (contains(userAgent, 'Firefox')) {
@@ -302,9 +303,11 @@
   var isLeaf =
       (leafTags != null) && JS('bool', '(#[#]) === true', leafTags, tag);
   if (isLeaf) {
-    return makeDispatchRecord(interceptor, false, null);
+    var fieldName = JS_IS_INDEXABLE_FIELD_NAME();
+    bool indexability = JS('bool', r'!!#[#]', interceptor, fieldName);
+    return makeDispatchRecord(interceptor, false, null, indexability);
   } else {
     var proto = JS('', 'Object.getPrototypeOf(#)', obj);
-    return makeDispatchRecord(interceptor, proto, null);
+    return makeDispatchRecord(interceptor, proto, null, null);
   }
 }
diff --git a/sdk/lib/_internal/compiler/implementation/library_loader.dart b/sdk/lib/_internal/compiler/implementation/library_loader.dart
index b0784da..872aa58 100644
--- a/sdk/lib/_internal/compiler/implementation/library_loader.dart
+++ b/sdk/lib/_internal/compiler/implementation/library_loader.dart
@@ -337,7 +337,7 @@
    */
   LibraryElement loadCoreLibrary(LibraryDependencyHandler handler) {
     if (compiler.coreLibrary == null) {
-      Uri coreUri = new Uri.fromComponents(scheme: 'dart', path: 'core');
+      Uri coreUri = new Uri(scheme: 'dart', path: 'core');
       compiler.coreLibrary
           = createLibrary(handler, null, coreUri, null, coreUri);
     }
diff --git a/sdk/lib/_internal/compiler/implementation/mirrors/dart2js_mirror.dart b/sdk/lib/_internal/compiler/implementation/mirrors/dart2js_mirror.dart
index 9be802d..1493438 100644
--- a/sdk/lib/_internal/compiler/implementation/mirrors/dart2js_mirror.dart
+++ b/sdk/lib/_internal/compiler/implementation/mirrors/dart2js_mirror.dart
@@ -6,7 +6,6 @@
 
 import 'dart:async';
 import 'dart:collection' show LinkedHashMap;
-import 'dart:uri';
 
 import '../../compiler.dart' as api;
 import '../elements/elements.dart';
diff --git a/sdk/lib/_internal/compiler/implementation/mirrors/mirrors.dart b/sdk/lib/_internal/compiler/implementation/mirrors/mirrors.dart
index 4b2ad1b..54e71ad 100644
--- a/sdk/lib/_internal/compiler/implementation/mirrors/mirrors.dart
+++ b/sdk/lib/_internal/compiler/implementation/mirrors/mirrors.dart
@@ -5,7 +5,6 @@
 library mirrors;
 
 import 'dart:async';
-import 'dart:uri';
 
 /**
  * The main interface for the whole mirror system.
diff --git a/sdk/lib/_internal/compiler/implementation/mirrors/util.dart b/sdk/lib/_internal/compiler/implementation/mirrors/util.dart
index 7760da1..72b05b9 100644
--- a/sdk/lib/_internal/compiler/implementation/mirrors/util.dart
+++ b/sdk/lib/_internal/compiler/implementation/mirrors/util.dart
@@ -58,6 +58,7 @@
   }
 
   bool get isEmpty => length == 0;
+  bool get isNotEmpty => !isEmpty;
   V putIfAbsent(K key, V ifAbsent()) {
     if (!containsKey(key)) {
       V value = this[key];
diff --git a/sdk/lib/_internal/compiler/implementation/native_handler.dart b/sdk/lib/_internal/compiler/implementation/native_handler.dart
index 4dc4f9c..6a70a51b 100644
--- a/sdk/lib/_internal/compiler/implementation/native_handler.dart
+++ b/sdk/lib/_internal/compiler/implementation/native_handler.dart
@@ -5,7 +5,6 @@
 library native;
 
 import 'dart:collection' show Queue;
-import 'dart:uri';
 import 'dart2jslib.dart' hide SourceString;
 import 'dart_types.dart';
 import 'elements/elements.dart';
@@ -286,7 +285,8 @@
     return compiler.withCurrentElement(element, () {
       Node node = element.parseNode(compiler);
       if (node is! FunctionExpression) return false;
-      node = node.body;
+      FunctionExpression functionExpression = node;
+      node = functionExpression.body;
       Token token = node.getBeginToken();
       if (identical(token.stringValue, 'native')) return true;
       return false;
@@ -783,10 +783,11 @@
   void _escape(DartType type, Compiler compiler) {
     type = type.unalias(compiler);
     if (type is FunctionType) {
+      FunctionType functionType = type;
       // A function might be called from native code, passing us novel
       // parameters.
-      _escape(type.returnType, compiler);
-      for (Link<DartType> parameters = type.parameterTypes;
+      _escape(functionType.returnType, compiler);
+      for (Link<DartType> parameters = functionType.parameterTypes;
            !parameters.isEmpty;
            parameters = parameters.tail) {
         _capture(parameters.head, compiler);
@@ -800,8 +801,9 @@
   void _capture(DartType type, Compiler compiler) {
     type = type.unalias(compiler);
     if (type is FunctionType) {
-      _capture(type.returnType, compiler);
-      for (Link<DartType> parameters = type.parameterTypes;
+      FunctionType functionType = type;
+      _capture(functionType.returnType, compiler);
+      for (Link<DartType> parameters = functionType.parameterTypes;
            !parameters.isEmpty;
            parameters = parameters.tail) {
         _escape(parameters.head, compiler);
diff --git a/sdk/lib/_internal/compiler/implementation/patch_parser.dart b/sdk/lib/_internal/compiler/implementation/patch_parser.dart
index 128ba88..02c4ecc 100644
--- a/sdk/lib/_internal/compiler/implementation/patch_parser.dart
+++ b/sdk/lib/_internal/compiler/implementation/patch_parser.dart
@@ -114,7 +114,6 @@
 
 library patchparser;
 
-import "dart:uri";
 import "tree/tree.dart" as tree;
 import "dart2jslib.dart" as leg;  // CompilerTask, Compiler.
 import "apiimpl.dart";
diff --git a/sdk/lib/_internal/compiler/implementation/resolution/members.dart b/sdk/lib/_internal/compiler/implementation/resolution/members.dart
index b4fe9d9..ae787be 100644
--- a/sdk/lib/_internal/compiler/implementation/resolution/members.dart
+++ b/sdk/lib/_internal/compiler/implementation/resolution/members.dart
@@ -20,6 +20,12 @@
   void setSelector(Node node, Selector selector);
   void setGetterSelectorInComplexSendSet(SendSet node, Selector selector);
   void setOperatorSelectorInComplexSendSet(SendSet node, Selector selector);
+  Selector getIteratorSelector(ForIn node);
+  Selector getMoveNextSelector(ForIn node);
+  Selector getCurrentSelector(ForIn node);
+  Selector setIteratorSelector(ForIn node, Selector selector);
+  Selector setMoveNextSelector(ForIn node, Selector selector);
+  Selector setCurrentSelector(ForIn node, Selector selector);
 
   /// Register additional dependencies required by [currentElement].
   /// For example, elements that are used by a backend.
@@ -41,8 +47,9 @@
 
   operator []=(Node node, Element element) {
     assert(invariant(node, () {
-      if (node is FunctionExpression) {
-        return !node.modifiers.isExternal();
+      FunctionExpression functionExpression = node.asFunctionExpression();
+      if (functionExpression != null) {
+        return !functionExpression.modifiers.isExternal();
       }
       return true;
     }));
@@ -99,6 +106,34 @@
     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.	
+ 
+  Selector setIteratorSelector(ForIn node, Selector selector) {
+    selectors[node] = selector;
+  }
+
+  Selector getIteratorSelector(ForIn node) {
+    return selectors[node];
+  }
+
+  Selector setMoveNextSelector(ForIn node, Selector selector) {
+    selectors[node.forToken] = selector;
+  }
+	
+  Selector getMoveNextSelector(ForIn node) {
+    return selectors[node.forToken];
+  }
+
+  Selector setCurrentSelector(ForIn node, Selector selector) {
+    selectors[node.inToken] = selector;
+  }
+
+  Selector getCurrentSelector(ForIn node) {
+    return selectors[node.inToken];
+  }
+
   bool isParameterChecked(Element element) {
     return checkedParameters.contains(element);
   }
@@ -1953,8 +1988,8 @@
 
   visitIf(If node) {
     visit(node.condition);
-    visit(node.thenPart);
-    visit(node.elsePart);
+    visitIn(node.thenPart, new BlockScope(scope));
+    visitIn(node.elsePart, new BlockScope(scope));
   }
 
   static bool isLogicalOperator(Identifier op) {
@@ -2016,7 +2051,7 @@
       }
       // TODO(johnniwinther): Ensure correct behavior if currentClass is a
       // patch.
-      target = currentClass.lookupSuperSelector(selector);
+      target = currentClass.lookupSuperSelector(selector, compiler);
       // [target] may be null which means invoking noSuchMethod on
       // super.
       if (target == null) {
@@ -2349,7 +2384,7 @@
       registerSend(getterSelector, getter);
       mapping.setGetterSelectorInComplexSendSet(node, getterSelector);
       if (node.isSuperCall) {
-        getter = currentClass.lookupSuperSelector(getterSelector);
+        getter = currentClass.lookupSuperSelector(getterSelector, compiler);
         if (getter == null) {
           target = warnAndCreateErroneousElement(
               node, selector.name, MessageKind.NO_SUCH_SUPER_MEMBER,
@@ -2554,13 +2589,6 @@
     if (cls.isAbstract(compiler)) {
       compiler.backend.registerAbstractClassInstantiation(mapping);
     }
-    // [cls] might be the declaration element and we want to include injected
-    // members.
-    cls.implementation.forEachInstanceField(
-        (ClassElement enclosingClass, Element member) {
-          world.addToWorkList(member);
-        },
-        includeSuperAndInjectedMembers: true);
 
     if (isSymbolConstructor) {
       if (node.isConst()) {
@@ -2754,10 +2782,13 @@
 
   visitForIn(ForIn node) {
     LibraryElement library = enclosingElement.getLibrary();
+    mapping.setIteratorSelector(node, compiler.iteratorSelector);
     world.registerDynamicGetter(compiler.iteratorSelector.name,
                                 compiler.iteratorSelector);
+    mapping.setCurrentSelector(node, compiler.currentSelector);
     world.registerDynamicGetter(compiler.currentSelector.name,
                                 compiler.currentSelector);
+    mapping.setMoveNextSelector(node, compiler.moveNextSelector);
     world.registerDynamicInvocation(compiler.moveNextSelector.name,
                                     compiler.moveNextSelector);
 
@@ -2974,17 +3005,25 @@
     compiler.backend.registerCatchStatement(world, mapping);
     // Check that if catch part is present, then
     // it has one or two formal parameters.
+    VariableDefinitions exceptionDefinition;
+    VariableDefinitions stackTraceDefinition;
     if (node.formals != null) {
-      if (node.formals.isEmpty) {
+      Link<Node> formalsToProcess = node.formals.nodes;
+      if (formalsToProcess.isEmpty) {
         error(node, MessageKind.EMPTY_CATCH_DECLARATION);
-      }
-      if (!node.formals.nodes.tail.isEmpty) {
-        if (!node.formals.nodes.tail.tail.isEmpty) {
-          for (Node extra in node.formals.nodes.tail.tail) {
-            error(extra, MessageKind.EXTRA_CATCH_DECLARATION);
+      } else {
+        exceptionDefinition = formalsToProcess.head.asVariableDefinitions();
+        formalsToProcess = formalsToProcess.tail;
+        if (!formalsToProcess.isEmpty) {
+          stackTraceDefinition = formalsToProcess.head.asVariableDefinitions();
+          formalsToProcess = formalsToProcess.tail;
+          if (!formalsToProcess.isEmpty) {
+            for (Node extra in formalsToProcess) {
+              error(extra, MessageKind.EXTRA_CATCH_DECLARATION);
+            }
           }
+          compiler.backend.registerStackTraceInCatch(mapping);
         }
-        compiler.backend.registerStackTraceInCatch(mapping);
       }
 
       // Check that the formals aren't optional and that they have no
@@ -3020,6 +3059,19 @@
     inCatchBlock = true;
     visitIn(node.block, blockScope);
     inCatchBlock = oldInCatchBlock;
+
+    if (node.type != null && exceptionDefinition != null) {
+      DartType exceptionType = mapping.getType(node.type);
+      Node exceptionVariable = exceptionDefinition.definitions.nodes.head;
+      VariableElementX exceptionElement = mapping[exceptionVariable];
+      exceptionElement.variables.type = exceptionType;
+    }
+    if (stackTraceDefinition != null) {
+      Node stackTraceVariable = stackTraceDefinition.definitions.nodes.head;
+      VariableElementX stackTraceElement = mapping[stackTraceVariable];
+      world.registerInstantiatedClass(compiler.stackTraceClass, mapping);
+      stackTraceElement.variables.type = compiler.stackTraceClass.rawType;
+    }
   }
 
   visitTypedef(Typedef node) {
diff --git a/sdk/lib/_internal/compiler/implementation/resolution/secret_tree_element.dart b/sdk/lib/_internal/compiler/implementation/resolution/secret_tree_element.dart
index c9a67a6..665938e 100644
--- a/sdk/lib/_internal/compiler/implementation/resolution/secret_tree_element.dart
+++ b/sdk/lib/_internal/compiler/implementation/resolution/secret_tree_element.dart
@@ -10,7 +10,7 @@
  * testing.
  *
  * We have taken great care to ensure AST nodes can be cached between
- * compiler instances.  Part of this is requires that we always access
+ * compiler instances.  Part of this requires that we always access
  * resolution results through TreeElements.
  *
  * So please, do not add additional elements to this library, and do
diff --git a/sdk/lib/_internal/compiler/implementation/scanner/scannerlib.dart b/sdk/lib/_internal/compiler/implementation/scanner/scannerlib.dart
index 8bdf120..f9a175f 100644
--- a/sdk/lib/_internal/compiler/implementation/scanner/scannerlib.dart
+++ b/sdk/lib/_internal/compiler/implementation/scanner/scannerlib.dart
@@ -5,7 +5,6 @@
 library scanner;
 
 import 'dart:collection' show LinkedHashMap, IterableBase;
-import 'dart:uri';
 
 import 'scanner_implementation.dart';
 import '../elements/elements.dart';
diff --git a/sdk/lib/_internal/compiler/implementation/source_file_provider.dart b/sdk/lib/_internal/compiler/implementation/source_file_provider.dart
index 874300b..e10a4bd 100644
--- a/sdk/lib/_internal/compiler/implementation/source_file_provider.dart
+++ b/sdk/lib/_internal/compiler/implementation/source_file_provider.dart
@@ -5,7 +5,6 @@
 library source_file_provider;
 
 import 'dart:async';
-import 'dart:uri';
 import 'dart:io';
 import 'dart:utf';
 
diff --git a/sdk/lib/_internal/compiler/implementation/source_map_builder.dart b/sdk/lib/_internal/compiler/implementation/source_map_builder.dart
index 2f732d3..dd07af6 100644
--- a/sdk/lib/_internal/compiler/implementation/source_map_builder.dart
+++ b/sdk/lib/_internal/compiler/implementation/source_map_builder.dart
@@ -4,7 +4,6 @@
 
 library source_map_builder;
 
-import 'dart:uri';
 
 import 'util/util.dart';
 import 'scanner/scannerlib.dart' show Token;
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/bailout.dart b/sdk/lib/_internal/compiler/implementation/ssa/bailout.dart
index 0ef2257..c22a52c 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/bailout.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/bailout.dart
@@ -37,7 +37,8 @@
     // for parameters that are not 'this', which is always passed as
     // the receiver.
     if (instruction is HCheck) {
-      add(instruction.checkedInput);
+      HCheck check = instruction;
+      add(check.checkedInput);
     } else if (!instruction.isCodeMotionInvariant()
                || (instruction is HParameterValue && instruction is !HThis)) {
       lives.add(instruction);
@@ -294,7 +295,10 @@
         receiverSelectorOnThrow = selector;
         willThrow = true;
       }
-    } else if (willThrowArgumentError(selector, receiver, speculativeType)) {
+    // We need to call the actual method in checked mode to get
+    // the right type error.
+    } else if (!compiler.enableTypeAssertions
+               && willThrowArgumentError(selector, receiver, speculativeType)) {
       willThrow = true;
     }
 
@@ -730,7 +734,10 @@
     }
 
     if (blocks.isEmpty) {
-      if (firstBailoutTarget == null) {
+      // If [currentBlockInformation] is not null, we are in the
+      // middle of a loop/labeled block and this is too complex to handle for
+      // now.
+      if (firstBailoutTarget == null && currentBlockInformation == null) {
         firstBailoutTarget = target;
       } else {
         hasComplexBailoutTargets = true;
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/builder.dart b/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
index cb5b362..6f4cd16 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
@@ -44,6 +44,7 @@
                  kind == ElementKind.SETTER) {
         graph = builder.buildMethod(element);
       } else if (kind == ElementKind.FIELD) {
+        assert(!element.isInstanceMember());
         graph = builder.buildLazyInitializer(element);
       } else {
         compiler.internalErrorOnElement(element,
@@ -1105,8 +1106,11 @@
         bodyElement.origin.patch = bodyElement;
         classElement.origin.addBackendMember(bodyElement.origin);
       }
-      compiler.enqueuer.codegen.addToWorkList(bodyElement.declaration,
-                                              treeElements);
+      // Set the [TreeElements] of the generative constructor body to
+      // be the same as the generative constructor.
+      compiler.enqueuer.resolution.ensureCachedElements(
+          bodyElement.declaration,
+          treeElements);
     }
     assert(bodyElement.isGenerativeConstructorBody());
     return bodyElement;
@@ -1131,7 +1135,6 @@
    */
   InliningState enterInlinedMethod(FunctionElement function,
                                    Selector selector,
-                                   Link<Node> argumentsNodes,
                                    List<HInstruction> providedArguments,
                                    Node currentNode) {
     assert(invariant(function, function.isImplementation));
@@ -1139,7 +1142,16 @@
     List<HInstruction> compiledArguments;
     bool isInstanceMember = function.isInstanceMember();
 
-    if (isInstanceMember && !function.isGenerativeConstructorBody()) {
+    if (currentNode == null
+        || currentNode.asForIn() != null
+        || !isInstanceMember
+        || function.isGenerativeConstructorBody()) {
+      // For these cases, the provided arguments must match the
+      // expected parameters.
+      assert(providedArguments != null);
+      compiledArguments = providedArguments;
+    } else {
+      Send send = currentNode.asSend();
       assert(providedArguments != null);
       compiledArguments = new List<HInstruction>();
       compiledArguments.add(providedArguments[0]);
@@ -1148,7 +1160,7 @@
       // call [Selector.addArgumentsToList] only for getting the
       // default values of the optional parameters.
       bool succeeded = selector.addArgumentsToList(
-          argumentsNodes,
+          send.isPropertyAccess ? null : send.arguments,
           compiledArguments,
           function,
           (node) => null,
@@ -1167,9 +1179,6 @@
       // The caller of [enterInlinedMethod] has ensured the selector
       // matches the element.
       assert(succeeded);
-    } else {
-      assert(providedArguments != null);
-      compiledArguments = providedArguments;
     }
 
     // Create the inlining state after evaluating the arguments, that
@@ -1236,7 +1245,6 @@
    */
   bool tryInlineMethod(Element element,
                        Selector selector,
-                       Link<Node> argumentsNodes,
                        List<HInstruction> providedArguments,
                        Node currentNode) {
     // We cannot inline a method from a deferred library into a method
@@ -1244,26 +1252,11 @@
     // TODO(ahe): But we should still inline into the same
     // connected-component of the deferred library.
     if (compiler.deferredLoadTask.isDeferred(element)) return false;
-
     if (compiler.disableInlining) return false;
+    if (inliningStack.length > MAX_INLINING_DEPTH) return false;
+
     // Ensure that [element] is an implementation element.
     element = element.implementation;
-    // TODO(floitsch): find a cleaner way to know if the element is a function
-    // containing nodes.
-    // [PartialFunctionElement]s are [FunctionElement]s that have [Node]s.
-    if (element is !PartialFunctionElement
-        && !element.isGenerativeConstructorBody()) {
-      return false;
-    }
-    if (inliningStack.length > MAX_INLINING_DEPTH) return false;
-    // Don't inline recursive calls. We use the same elements for the inlined
-    // functions and would thus clobber our local variables.
-    // Use [:element.declaration:] since [work.element] is always a declaration.
-    if (currentElement == element.declaration) return false;
-    for (int i = 0; i < inliningStack.length; i++) {
-      if (inliningStack[i].function == element) return false;
-    }
-
     FunctionElement function = element;
     bool canBeInlined = backend.canBeInlined[function];
     if (canBeInlined == false) return false;
@@ -1304,7 +1297,7 @@
           new HFieldGet(element, providedArguments[0]), currentNode);
     }
     InliningState state = enterInlinedMethod(
-        function, selector, argumentsNodes, providedArguments, currentNode);
+        function, selector, providedArguments, currentNode);
 
     inlinedFrom(element, () {
       FunctionElement function = element;
@@ -1673,11 +1666,11 @@
         bodyCallInputs.add(localsHandler.readLocal(scopeData.boxElement));
       }
 
-      if (tryInlineMethod(body, null, null, bodyCallInputs, function)) {
+      if (tryInlineMethod(body, null, bodyCallInputs, function)) {
         pop();
       } else {
         HInvokeConstructorBody invoke =
-            new HInvokeConstructorBody(body, bodyCallInputs);
+            new HInvokeConstructorBody(body.declaration, bodyCallInputs);
         invoke.sideEffects =
             compiler.world.getSideEffectsOfElement(constructor);
         add(invoke);
@@ -2711,9 +2704,8 @@
     }
   }
 
-  HInstruction invokeInterceptor(Set<ClassElement> intercepted,
-                                 HInstruction receiver) {
-    HInterceptor interceptor = new HInterceptor(intercepted, receiver);
+  HInstruction invokeInterceptor(HInstruction receiver) {
+    HInterceptor interceptor = new HInterceptor(receiver);
     add(interceptor);
     return interceptor;
   }
@@ -3126,6 +3118,10 @@
       stack.add(addConstantString(node, backend.namer.operatorAsPrefix()));
     } else if (name == const SourceString('JS_DART_OBJECT_CONSTRUCTOR')) {
       handleForeignDartObjectJsConstructorFunction(node);
+    } else if (name == const SourceString('JS_IS_INDEXABLE_FIELD_NAME')) {
+      Element element = compiler.findHelper(
+          const SourceString('JavaScriptIndexingBehavior'));
+      stack.add(addConstantString(node, backend.namer.operatorIs(element)));
     } else {
       throw "Unknown foreign: ${selector}";
     }
@@ -3686,7 +3682,7 @@
       }
     }
 
-    bool isOptimizableOperation(Send node, Selector selector, Element element) {
+    bool isOptimizableOperation(Selector selector, Element element) {
       ClassElement cls = element.getEnclosingClass();
       if (isOptimizableOperationOnIndexable(selector, element)) return true;
       if (!backend.interceptedClasses.contains(cls)) return false;
@@ -3704,26 +3700,20 @@
 
     Element element = compiler.world.locateSingleElement(selector);
     if (element != null
-        // TODO(ngeoffray): Handle non-send nodes.
-        && (node.asSend() != null)
+        && !element.isField()
         && !(element.isGetter() && selector.isCall())
         && !(element.isFunction() && selector.isGetter())
-        && !isOptimizableOperation(node, selector, element)) {
-      Send send = node.asSend();
-      Link<Node> nodes = send.isPropertyAccess ? null : send.arguments;
-      if (tryInlineMethod(element, selector, nodes, arguments, node)) {
+        && !isOptimizableOperation(selector, element)) {
+      if (tryInlineMethod(element, selector, arguments, node)) {
         return;
       }
     }
 
     HInstruction receiver = arguments[0];
-    Set<ClassElement> interceptedClasses =
-        backend.getInterceptedClassesOn(selector.name);
     List<HInstruction> inputs = <HInstruction>[];
-    bool isIntercepted = interceptedClasses != null;
+    bool isIntercepted = backend.isInterceptedSelector(selector);
     if (isIntercepted) {
-      assert(!interceptedClasses.isEmpty);
-      inputs.add(invokeInterceptor(interceptedClasses, receiver));
+      inputs.add(invokeInterceptor(receiver));
     }
     inputs.addAll(arguments);
     if (selector.isGetter()) {
@@ -3747,7 +3737,7 @@
                         Element element,
                         List<HInstruction> arguments,
                         [HType type = null]) {
-    if (tryInlineMethod(element, null, null, arguments, location)) {
+    if (tryInlineMethod(element, null, arguments, location)) {
       return;
     }
 
@@ -3781,10 +3771,8 @@
     // TODO(5346): Try to avoid the need for calling [declaration] before
     // creating an [HStatic].
     List<HInstruction> inputs = <HInstruction>[];
-    Set<ClassElement> interceptedClasses =
-        backend.getInterceptedClassesOn(selector.name);
-    if (interceptedClasses != null) {
-      inputs.add(invokeInterceptor(interceptedClasses, receiver));
+    if (backend.isInterceptedSelector(selector)) {
+      inputs.add(invokeInterceptor(receiver));
     }
     inputs.add(receiver);
     inputs.addAll(arguments);
@@ -4040,9 +4028,11 @@
       native.handleSsaNative(this, node.expression);
       return;
     }
-    assert(invariant(node, !node.isRedirectingFactoryBody));
     HInstruction value;
-    if (node.expression == null) {
+    if (node.isRedirectingFactoryBody) {
+      // TODO(ahe): This is only for reflection, and it is not correct yet.
+      value = graph.addConstantNull(constantSystem);
+    } else if (node.expression == null) {
       value = graph.addConstantNull(constantSystem);
     } else {
       visit(node.expression);
@@ -4199,19 +4189,19 @@
     // The iterator is shared between initializer, condition and body.
     HInstruction iterator;
     void buildInitializer() {
-      Selector selector = compiler.iteratorSelector;
+      Selector selector = elements.getIteratorSelector(node);
       visit(node.expression);
       HInstruction receiver = pop();
       pushInvokeDynamic(node, selector, [receiver]);
       iterator = pop();
     }
     HInstruction buildCondition() {
-      Selector selector = compiler.moveNextSelector;
+      Selector selector = elements.getMoveNextSelector(node);
       pushInvokeDynamic(node, selector, [iterator]);
       return popBoolified();
     }
     void buildBody() {
-      Selector call = compiler.currentSelector;
+      Selector call = elements.getCurrentSelector(node);
       pushInvokeDynamic(node, call, [iterator]);
 
       Node identifier = node.declaredIdentifier;
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart b/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart
index 76b6bff..120f91c 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart
@@ -604,7 +604,8 @@
     // argument.
     bool needsAssignment = true;
     if (instruction is HTypeConversion) {
-      String inputName = variableNames.getName(instruction.checkedInput);
+      HTypeConversion typeConversion = instruction;
+      String inputName = variableNames.getName(typeConversion.checkedInput);
       if (variableNames.getName(instruction) == inputName) {
         needsAssignment = false;
       }
@@ -805,7 +806,8 @@
               // go away.
               List<js.Expression> expressions;
               if (jsInitialization is js.Sequence) {
-                expressions = jsInitialization.expressions;
+                js.Sequence sequence = jsInitialization;
+                expressions = sequence.expressions;
               } else {
                 expressions = <js.Expression>[jsInitialization];
               }
@@ -1523,6 +1525,7 @@
     String methodName = backend.namer.getName(node.element);
     List<js.Expression> arguments = visitArguments(node.inputs);
     push(jsPropertyCall(object, methodName, arguments), node);
+    world.registerStaticUse(node.element);
   }
 
   void visitOneShotInterceptor(HOneShotInterceptor node) {
@@ -1760,13 +1763,7 @@
 
   visitForeignNew(HForeignNew node) {
     String jsClassReference = backend.namer.isolateAccess(node.element);
-    List<HInstruction> inputs = node.inputs;
-    // We can't use 'visitArguments', since our arguments start at input[0].
-    List<js.Expression> arguments = <js.Expression>[];
-    for (int i = 0; i < inputs.length; i++) {
-      use(inputs[i]);
-      arguments.add(pop());
-    }
+    List<js.Expression> arguments = visitArguments(node.inputs, start: 0);
     // TODO(floitsch): jsClassReference is an Access. We shouldn't treat it
     // as if it was a string.
     push(new js.New(new js.VariableUse(jsClassReference), arguments), node);
@@ -1848,7 +1845,8 @@
     if (input is HIs) {
       emitIs(input, '!==');
     } else if (input is HIdentity && generateAtUseSite) {
-      emitIdentityComparison(input.left, input.right, true);
+      HIdentity identity = input;
+      emitIdentityComparison(identity.left, identity.right, true);
     } else if (input is HBoolify && generateAtUseSite) {
       use(input.inputs[0]);
       push(new js.Binary("!==", pop(), newLiteralBool(true)), input);
@@ -1993,7 +1991,8 @@
     world.registerStaticUse(helper);
     js.VariableUse jsHelper =
         new js.VariableUse(backend.namer.isolateAccess(helper));
-    js.Call value = new js.Call(jsHelper, visitArguments([null, argument]));
+    use(argument);
+    js.Call value = new js.Call(jsHelper, [pop()]);
     attachLocation(value, argument);
     // BUG(4906): Using throw here adds to the size of the generated code
     // but it has the advantage of explicitly telling the JS engine that
@@ -2044,10 +2043,14 @@
 
   void visitStaticStore(HStaticStore node) {
     world.registerStaticUse(node.element);
-    js.VariableUse variableUse =
-        new js.VariableUse(backend.namer.isolateAccess(node.element));
+    js.VariableUse isolate = new js.VariableUse(backend.namer.CURRENT_ISOLATE);
+    // Create a property access to make sure expressions and variable
+    // declarations recognizers don't see this assignment as a local
+    // assignment.
+    js.Node variable = new js.PropertyAccess.field(
+        isolate, backend.namer.getName(node.element));
     use(node.inputs[0]);
-    push(new js.Assignment(variableUse, pop()), node);
+    push(new js.Assignment(variable, pop()), node);
   }
 
   void visitStringConcat(HStringConcat node) {
@@ -2182,12 +2185,22 @@
     push(new js.Prefix('!', new js.Prefix('!', field)));
   }
 
+  void checkFieldDoesNotExist(HInstruction input, String fieldName) {
+    use(input);
+    js.PropertyAccess field = new js.PropertyAccess.field(pop(), fieldName);
+    push(new js.Prefix('!', field));
+  }
+
   void checkImmutableArray(HInstruction input) {
     checkFieldExists(input, 'immutable\$list');
   }
 
+  void checkMutableArray(HInstruction input) {
+    checkFieldDoesNotExist(input, 'immutable\$list');
+  }
+
   void checkExtendableArray(HInstruction input) {
-    checkFieldExists(input, 'fixed\$length');
+    checkFieldDoesNotExist(input, 'fixed\$length');
   }
 
   void checkFixedArray(HInstruction input) {
@@ -2233,8 +2246,33 @@
   void checkType(HInstruction input, DartType type, {bool negative: false}) {
     assert(invariant(input, !type.isMalformed,
                      message: 'Attempt to check malformed type $type'));
-    world.registerIsCheck(type, work.resolutionTree);
     Element element = type.element;
+
+    if (element == backend.jsArrayClass) {
+      checkArray(input, negative ? '!==': '===');
+      return;
+    } else if (element == backend.jsMutableArrayClass) {
+      if (negative) {
+        checkImmutableArray(input);
+      } else {
+        checkMutableArray(input);
+      }
+      return;
+    } else if (element == backend.jsExtendableArrayClass) {
+      if (negative) {
+        checkFixedArray(input);
+      } else {
+        checkExtendableArray(input);
+      }
+      return;
+    } else if (element == backend.jsFixedArrayClass) {
+      if (negative) {
+        checkExtendableArray(input);
+      } else {
+        checkFixedArray(input);
+      }
+      return;
+    }
     use(input);
 
     // Hack in interceptor.  Ideally the interceptor would occur at the
@@ -2247,24 +2285,7 @@
     List<js.Expression> arguments = <js.Expression>[pop()];
     push(jsPropertyCall(isolate, interceptorName, arguments));
     backend.registerUseInterceptor(world);
-
-    // TODO(9586): If a static function can have the type, the type info is
-    // sitting on the function.  So generate:
-    //
-    //   (typeof x == "function" ? x : getInterceptor(x)).$isFoo
-    //
-    if (type.unalias(compiler) is FunctionType) {
-      js.Expression whenNotFunction = pop();
-      use(input);
-      js.Expression whenFunction = pop();
-      use(input);
-      push(new js.Conditional(
-          new js.Binary('==',
-              new js.Prefix("typeof", pop()),
-              js.string('function')),
-          whenFunction,
-          whenNotFunction));
-    }
+    world.registerIsCheck(type, work.resolutionTree);
 
     js.PropertyAccess field =
         new js.PropertyAccess.field(pop(), backend.namer.operatorIs(element));
@@ -2399,7 +2420,9 @@
         checkType(input, type, negative: negative);
         push(new js.Binary(negative ? '||' : '&&', nullTest, pop()));
         attachLocationToLast(node);
-      } else if (input.canBePrimitive(compiler) || input.canBeNull()) {
+      } else if ((input.canBePrimitive(compiler)
+                  && !input.canBePrimitiveArray(compiler))
+                 || input.canBeNull()) {
         checkObject(input, relation);
         js.Expression objectTest = pop();
         checkType(input, type, negative: negative);
@@ -2519,12 +2542,12 @@
 
     assert(node.isCheckedModeCheck || node.isCastTypeCheck);
     DartType type = node.typeExpression;
-      if (type.kind == TypeKind.FUNCTION) {
-        // TODO(5022): We currently generate $isFunction checks for
-        // function types.
-        world.registerIsCheck(
-            compiler.functionClass.computeType(compiler), work.resolutionTree);
-      }
+    if (type.kind == TypeKind.FUNCTION) {
+      // TODO(5022): We currently generate $isFunction checks for
+      // function types.
+      world.registerIsCheck(
+          compiler.functionClass.computeType(compiler), work.resolutionTree);
+    }
     world.registerIsCheck(type, work.resolutionTree);
 
     FunctionElement helperElement;
@@ -2724,7 +2747,7 @@
   // find the name of its checked input. Note that there must be a
   // name, otherwise the instruction would not be in the live
   // environment.
-  HInstruction unwrap(HInstruction argument) {
+  HInstruction unwrap(var argument) {
     while (argument is HCheck && !variableNames.hasName(argument)) {
       argument = argument.checkedInput;
     }
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/interceptor_simplifier.dart b/sdk/lib/_internal/compiler/implementation/ssa/interceptor_simplifier.dart
new file mode 100644
index 0000000..e3f7a46
--- /dev/null
+++ b/sdk/lib/_internal/compiler/implementation/ssa/interceptor_simplifier.dart
@@ -0,0 +1,282 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of ssa;
+
+/**
+ * This phase simplifies interceptors in multiple ways:
+ *
+ * 1) If the interceptor is for an object whose type is known, it
+ * tries to use a constant interceptor instead.
+ *
+ * 2) It specializes interceptors based on the selectors it is being
+ * called with.
+ *
+ * 3) If we know the object is not intercepted, we just use it
+ * instead.
+ *
+ * 4) It replaces all interceptors that are used only once with
+ * one-shot interceptors. It saves code size and makes the receiver of
+ * an intercepted call a candidate for being generated at use site.
+ *
+ */
+class SsaSimplifyInterceptors extends HBaseVisitor
+    implements OptimizationPhase {
+  final String name = "SsaSimplifyInterceptors";
+  final ConstantSystem constantSystem;
+  final Compiler compiler;
+  final CodegenWorkItem work;
+  HGraph graph;
+
+  SsaSimplifyInterceptors(this.compiler, this.constantSystem, this.work);
+
+  void visitGraph(HGraph graph) {
+    this.graph = graph;
+    visitDominatorTree(graph);
+  }
+
+  void visitBasicBlock(HBasicBlock node) {
+    currentBlock = node;
+
+    HInstruction instruction = node.first;
+    while (instruction != null) {
+      bool shouldRemove = instruction.accept(this);
+      HInstruction next = instruction.next;
+      if (shouldRemove) {
+        instruction.block.remove(instruction);
+      }
+      instruction = next;
+    }
+  }
+
+  bool visitInstruction(HInstruction instruction) => false;
+
+  bool canUseSelfForInterceptor(HType receiverType,
+                                Set<ClassElement> interceptedClasses) {
+    JavaScriptBackend backend = compiler.backend;
+    if (receiverType.canBePrimitive(compiler)) {
+      // Primitives always need interceptors.
+      return false;
+    }
+    if (receiverType.canBeNull()
+        && interceptedClasses.contains(backend.jsNullClass)) {
+      // Need the JSNull interceptor.
+      return false;
+    }
+
+    // [interceptedClasses] is sparse - it is just the classes that define some
+    // intercepted method.  Their subclasses (that inherit the method) are
+    // implicit, so we have to extend them.
+
+    TypeMask receiverMask = receiverType.computeMask(compiler);
+    return interceptedClasses
+        .where((cls) => cls != compiler.objectClass)
+        .map((cls) => backend.classesMixedIntoNativeClasses.contains(cls)
+            ? new TypeMask.subtype(cls.rawType)
+            : new TypeMask.subclass(cls.rawType))
+        .every((mask) => receiverMask.intersection(mask, compiler).isEmpty);
+  }
+
+  HInstruction tryComputeConstantInterceptor(
+      HInstruction input,
+      Set<ClassElement> interceptedClasses) {
+    if (input == graph.explicitReceiverParameter) {
+      // If `explicitReceiverParameter` is set it means the current method is an
+      // interceptor method, and `this` is the interceptor.  The caller just did
+      // `getInterceptor(foo).currentMethod(foo)` to enter the current method.
+      return graph.thisInstruction;
+    }
+
+    HType type = input.instructionType;
+    ClassElement constantInterceptor;
+    JavaScriptBackend backend = compiler.backend;
+    if (type.isInteger()) {
+      constantInterceptor = backend.jsIntClass;
+    } else if (type.isDouble()) {
+      constantInterceptor = backend.jsDoubleClass;
+    } else if (type.isBoolean()) {
+      constantInterceptor = backend.jsBoolClass;
+    } else if (type.isString()) {
+      constantInterceptor = backend.jsStringClass;
+    } else if (type.isArray()) {
+      constantInterceptor = backend.jsArrayClass;
+    } else if (type.isNull()) {
+      constantInterceptor = backend.jsNullClass;
+    } else if (type.isNumber()
+        && !interceptedClasses.contains(backend.jsIntClass)
+        && !interceptedClasses.contains(backend.jsDoubleClass)) {
+      // If the method being intercepted is not defined in [int] or [double] we
+      // can safely use the number interceptor.  This is because none of the
+      // [int] or [double] methods are called from a method defined on [num].
+      constantInterceptor = backend.jsNumberClass;
+    } else {
+      // Try to find constant interceptor for a native class.  If the receiver
+      // is constrained to a leaf native class, we can use the class's
+      // interceptor directly.
+
+      // TODO(sra): Key DOM classes like Node, Element and Event are not leaf
+      // classes.  When the receiver type is not a leaf class, we might still be
+      // able to use the receiver class as a constant interceptor.  It is
+      // usually the case that methods defined on a non-leaf class don't test
+      // for a subclass or call methods defined on a subclass.  Provided the
+      // code is completely insensitive to the specific instance subclasses, we
+      // can use the non-leaf class directly.
+
+      if (!type.canBeNull()) {
+        ClassElement element = type.computeMask(compiler).singleClass(compiler);
+        if (element != null && element.isNative()) {
+          constantInterceptor = element;
+        }
+      }
+    }
+
+    if (constantInterceptor == null) return null;
+    if (constantInterceptor == work.element.getEnclosingClass()) {
+      return graph.thisInstruction;
+    }
+
+    Constant constant = new InterceptorConstant(
+        constantInterceptor.computeType(compiler));
+    return graph.addConstant(constant);
+  }
+
+  HInstruction findDominator(Iterable<HInstruction> instructions) {
+    HInstruction result;
+    L1: for (HInstruction candidate in instructions) {
+      for (HInstruction current in instructions) {
+        if (current != candidate && !candidate.dominates(current)) continue L1;
+      }
+      result = candidate;
+      break;
+    }
+    return result;
+  }
+
+  bool visitInterceptor(HInterceptor node) {
+    if (node.isConstant()) return false;
+
+    // If the interceptor is used by multiple instructions, specialize
+    // it with a set of classes it intercepts.
+    Set<ClassElement> interceptedClasses;
+    JavaScriptBackend backend = compiler.backend;
+    HInstruction dominator =
+        findDominator(node.usedBy.where((i) => i is HInvokeDynamic));
+    // If there is an instruction that dominates all others, we can
+    // use only the selector of that instruction.
+    if (dominator != null) {
+      interceptedClasses = 
+            backend.getInterceptedClassesOn(dominator.selector.name);
+
+      // If we found that we need number, we must still go through all
+      // uses to check if they require int, or double.
+      if (interceptedClasses.contains(backend.jsNumberClass)
+          && !(interceptedClasses.contains(backend.jsDoubleClass)
+               || interceptedClasses.contains(backend.jsIntClass))) {
+        for (var user in node.usedBy) {
+          if (user is! HInvoke) continue;
+          Set<ClassElement> intercepted =
+              backend.getInterceptedClassesOn(user.selector.name);
+          if (intercepted.contains(backend.jsIntClass)) {
+            interceptedClasses.add(backend.jsIntClass);
+          }
+          if (intercepted.contains(backend.jsDoubleClass)) {
+            interceptedClasses.add(backend.jsDoubleClass);
+          }
+        }
+      }
+    } else {
+      interceptedClasses = new Set<ClassElement>();
+      for (var user in node.usedBy) {
+        if (user is! HInvoke) continue;
+        // We don't handle escaping interceptors yet.
+        interceptedClasses.addAll(
+            backend.getInterceptedClassesOn(user.selector.name));
+      }
+    }
+
+    HInstruction receiver = node.receiver;
+    HType instructionType = receiver.instructionType;
+    if (canUseSelfForInterceptor(instructionType, interceptedClasses)) {
+      node.block.rewrite(node, receiver);
+      return false;
+    }
+
+    // Try computing a constant interceptor.
+    HInstruction constantInterceptor =
+        tryComputeConstantInterceptor(receiver, interceptedClasses);
+    if (constantInterceptor != null) {
+      node.block.rewrite(node, constantInterceptor);
+      return false;
+    }
+
+    if (node.usedBy.every((e) => e is HBailoutTarget || e is HTypeGuard)) {
+      // The interceptor is only used by the bailout version. We don't
+      // remove it because the bailout version will use it.
+      node.interceptedClasses = backend.interceptedClasses;
+      return false;
+    }
+
+    node.interceptedClasses = interceptedClasses;
+
+    // Try creating a one-shot interceptor.
+    if (node.usedBy.length != 1) return false;
+    if (node.usedBy[0] is !HInvokeDynamic) return false;
+
+    HInvokeDynamic user = node.usedBy[0];
+
+    // If [node] was loop hoisted, we keep the interceptor.
+    if (!user.hasSameLoopHeaderAs(node)) return false;
+
+    // Replace the user with a [HOneShotInterceptor].
+    HConstant nullConstant = graph.addConstantNull(constantSystem);
+    List<HInstruction> inputs = new List<HInstruction>.from(user.inputs);
+    inputs[0] = nullConstant;
+    HOneShotInterceptor interceptor = new HOneShotInterceptor(
+        user.selector, inputs, node.interceptedClasses);
+    interceptor.sourcePosition = user.sourcePosition;
+    interceptor.sourceElement = user.sourceElement;
+    interceptor.instructionType = user.instructionType;
+
+    HBasicBlock block = user.block;
+    block.addAfter(user, interceptor);
+    block.rewrite(user, interceptor);
+    block.remove(user);
+    return true;
+  }
+
+  
+  bool visitOneShotInterceptor(HOneShotInterceptor node) {
+    HInstruction constant = tryComputeConstantInterceptor(
+        node.inputs[1], node.interceptedClasses);
+
+    if (constant == null) return false;
+
+    Selector selector = node.selector;
+    // TODO(ngeoffray): make one shot interceptors know whether
+    // they have side effects.
+    HInstruction instruction;
+    if (selector.isGetter()) {
+      instruction= new HInvokeDynamicGetter(
+          selector,
+          node.element,
+          <HInstruction>[constant, node.inputs[1]],
+          false);
+    } else if (node.selector.isSetter()) {
+      instruction = new HInvokeDynamicSetter(
+          selector,
+          node.element,
+          <HInstruction>[constant, node.inputs[1], node.inputs[2]],
+          false);
+    } else {
+      List<HInstruction> inputs = new List<HInstruction>.from(node.inputs);
+      inputs[0] = constant;
+      instruction = new HInvokeDynamicMethod(selector, inputs, true);
+    }
+
+    HBasicBlock block = node.block;
+    block.addAfter(node, instruction);
+    block.rewrite(node, instruction);
+    return true;
+  }
+}
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 d1f80ec..426332e 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/invoke_dynamic_specializers.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/invoke_dynamic_specializers.dart
@@ -100,6 +100,10 @@
   HInstruction tryConvertToBuiltin(HInvokeDynamic instruction,
                                    Compiler compiler) {
     if (instruction.inputs[1].isMutableIndexable(compiler)) {
+      if (!instruction.inputs[2].isInteger() && compiler.enableTypeAssertions) {
+        // We want the right checked mode error.
+        return null;
+      }
       return new HIndexAssign(instruction.inputs[1],
                               instruction.inputs[2],
                               instruction.inputs[3],
@@ -130,6 +134,10 @@
   HInstruction tryConvertToBuiltin(HInvokeDynamic instruction,
                                    Compiler compiler) {
     if (instruction.inputs[1].isIndexable(compiler)) {
+      if (!instruction.inputs[2].isInteger() && compiler.enableTypeAssertions) {
+        // We want the right checked mode error.
+        return null;
+      }
       HInstruction index = new HIndex(
           instruction.inputs[1], instruction.inputs[2], instruction.selector);
       index.instructionType =
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart b/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart
index 088fe6e..757230d 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart
@@ -838,9 +838,12 @@
   bool isNumberOrNull() => instructionType.isNumberOrNull();
   bool isString() => instructionType.isString();
   bool isPrimitive() => instructionType.isPrimitive();
+  bool isNull() => instructionType.isNull();
   bool canBeNull() => instructionType.canBeNull();
   bool canBePrimitive(Compiler compiler) =>
       instructionType.canBePrimitive(compiler);
+  bool canBePrimitiveArray(Compiler compiler) =>
+      instructionType.canBePrimitiveArray(compiler);
 
   bool isIndexable(Compiler compiler) =>
       instructionType.isIndexable(compiler);
@@ -2044,9 +2047,10 @@
 }
 
 class HInterceptor extends HInstruction {
+  // This field should originally be null to allow GVN'ing all
+  // [HInterceptor] on the same input.
   Set<ClassElement> interceptedClasses;
-  HInterceptor(this.interceptedClasses, HInstruction receiver)
-      : super(<HInstruction>[receiver]) {
+  HInterceptor(HInstruction receiver) : super(<HInstruction>[receiver]) {
     sideEffects.clearAllSideEffects();
     setUseGvn();
   }
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart b/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart
index 26523a5..c803976 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart
@@ -50,14 +50,13 @@
           new SsaDeadPhiEliminator(),
           new SsaConstantFolder(constantSystem, backend, work),
           new SsaNonSpeculativeTypePropagator(compiler),
-          new SsaReceiverSpecialization(compiler),
           new SsaGlobalValueNumberer(compiler),
           new SsaCodeMotion(),
           new SsaValueRangeAnalyzer(compiler, constantSystem, work),
           // Previous optimizations may have generated new
           // opportunities for constant folding.
           new SsaConstantFolder(constantSystem, backend, work),
-          new SsaSimplifyInterceptors(constantSystem),
+          new SsaSimplifyInterceptors(compiler, constantSystem, work),
           new SsaDeadCodeEliminator()];
       runPhases(graph, phases);
       if (!speculative) {
@@ -72,6 +71,7 @@
       return false;
     }
     JavaScriptItemCompilationContext context = work.compilationContext;
+    ConstantSystem constantSystem = compiler.backend.constantSystem;
     return measure(() {
       SsaTypeGuardInserter inserter = new SsaTypeGuardInserter(compiler, work);
 
@@ -488,6 +488,10 @@
       return graph.addConstantBool(false, constantSystem);
     }
 
+    if (left.isNull() && right.isNull()) {
+      return graph.addConstantBool(true, constantSystem);
+    }
+
     if (left.isConstantBoolean() && right.isBoolean()) {
       HConstant constant = left;
       if (constant.constant.isTrue()) {
@@ -580,13 +584,6 @@
       } else {
         return graph.addConstantBool(false, constantSystem);
       }
-    } else if (expressionType.isArray()) {
-      if (identical(element, compiler.listClass)
-          || Elements.isListSupertype(element, compiler)) {
-        return graph.addConstantBool(true, constantSystem);
-      } else {
-        return graph.addConstantBool(false, constantSystem);
-      }
     // We need the [:hasTypeArguments:] check because we don't have
     // the notion of generics in the backend. For example, [:this:] in
     // a class [:A<T>:], is currently always considered to have the
@@ -796,140 +793,8 @@
     return node;
   }
 
-  HInstruction visitInterceptor(HInterceptor node) {
-    if (node.isConstant()) return node;
-    // If the intercepted object does not need to be intercepted, just
-    // return the object (the [:getInterceptor:] method would have
-    // returned the object).
-    HType type = node.receiver.instructionType;
-    if (canUseSelfForInterceptor(type, node.interceptedClasses)) {
-      return node.receiver;
-    }
-    HInstruction constant = tryComputeConstantInterceptor(
-        node.inputs[0], node.interceptedClasses);
-    if (constant == null) return node;
-
-    return constant;
-  }
-
-  bool canUseSelfForInterceptor(HType receiverType,
-                                Set<ClassElement> interceptedClasses) {
-    if (receiverType.canBePrimitive(compiler)) {
-      // Primitives always need interceptors.
-      return false;
-    }
-    if (receiverType.canBeNull()
-        && interceptedClasses.contains(backend.jsNullClass)) {
-      // Need the JSNull interceptor.
-      return false;
-    }
-
-    // [interceptedClasses] is sparse - it is just the classes that define some
-    // intercepted method.  Their subclasses (that inherit the method) are
-    // implicit, so we have to extend them.
-
-    TypeMask receiverMask = receiverType.computeMask(compiler);
-    return interceptedClasses
-        .where((cls) => cls != compiler.objectClass)
-        .map((cls) => backend.classesMixedIntoNativeClasses.contains(cls)
-            ? new TypeMask.subtype(cls.rawType)
-            : new TypeMask.subclass(cls.rawType))
-        .every((mask) => receiverMask.intersection(mask, compiler).isEmpty);
-  }
-
-  HInstruction tryComputeConstantInterceptor(HInstruction input,
-                                             Set<ClassElement> intercepted) {
-    if (input == graph.explicitReceiverParameter) {
-      // If `explicitReceiverParameter` is set it means the current method is an
-      // interceptor method, and `this` is the interceptor.  The caller just did
-      // `getInterceptor(foo).currentMethod(foo)` to enter the current method.
-      return graph.thisInstruction;
-    }
-
-    HType type = input.instructionType;
-    ClassElement constantInterceptor;
-    if (type.isInteger()) {
-      constantInterceptor = backend.jsIntClass;
-    } else if (type.isDouble()) {
-      constantInterceptor = backend.jsDoubleClass;
-    } else if (type.isBoolean()) {
-      constantInterceptor = backend.jsBoolClass;
-    } else if (type.isString()) {
-      constantInterceptor = backend.jsStringClass;
-    } else if (type.isArray()) {
-      constantInterceptor = backend.jsArrayClass;
-    } else if (type.isNull()) {
-      constantInterceptor = backend.jsNullClass;
-    } else if (type.isNumber()) {
-      // If the method being intercepted is not defined in [int] or [double] we
-      // can safely use the number interceptor.  This is because none of the
-      // [int] or [double] methods are called from a method defined on [num].
-      if (!intercepted.contains(backend.jsIntClass)
-          && !intercepted.contains(backend.jsDoubleClass)) {
-        constantInterceptor = backend.jsNumberClass;
-      }
-    } else {
-      // Try to find constant interceptor for a native class.  If the receiver
-      // is constrained to a leaf native class, we can use the class's
-      // interceptor directly.
-
-      // TODO(sra): Key DOM classes like Node, Element and Event are not leaf
-      // classes.  When the receiver type is not a leaf class, we might still be
-      // able to use the receiver class as a constant interceptor.  It is
-      // usually the case that methods defined on a non-leaf class don't test
-      // for a subclass or call methods defined on a subclass.  Provided the
-      // code is completely insensitive to the specific instance subclasses, we
-      // can use the non-leaf class directly.
-
-      if (!type.canBeNull()) {
-        ClassElement element = type.computeMask(compiler).singleClass(compiler);
-        if (element != null && element.isNative()) {
-          constantInterceptor = element;
-        }
-      }
-    }
-
-    if (constantInterceptor == null) return null;
-    if (constantInterceptor == work.element.getEnclosingClass()) {
-      return graph.thisInstruction;
-    }
-
-    Constant constant = new InterceptorConstant(
-        constantInterceptor.computeType(compiler));
-    return graph.addConstant(constant);
-  }
-
   HInstruction visitOneShotInterceptor(HOneShotInterceptor node) {
-    HInstruction newInstruction = handleInterceptedCall(node);
-    if (newInstruction != node) return newInstruction;
-
-    HInstruction constant = tryComputeConstantInterceptor(
-        node.inputs[1], node.interceptedClasses);
-
-    if (constant == null) return node;
-
-    Selector selector = node.selector;
-    // TODO(ngeoffray): make one shot interceptors know whether
-    // they have side effects.
-    if (selector.isGetter()) {
-      HInstruction res = new HInvokeDynamicGetter(
-          selector,
-          node.element,
-          <HInstruction>[constant, node.inputs[1]],
-          false);
-      return res;
-    } else if (node.selector.isSetter()) {
-      HInstruction res = new HInvokeDynamicSetter(
-          selector,
-          node.element,
-          <HInstruction>[constant, node.inputs[1], node.inputs[2]],
-          false);
-      return res;
-    } else {
-      List<HInstruction> inputs = new List<HInstruction>.from(node.inputs);
-      inputs[0] = constant;
-      return new HInvokeDynamicMethod(selector, inputs, true);
-    }
+    return handleInterceptedCall(node);
   }
 }
 
@@ -1572,6 +1437,11 @@
   }
 
   visitForeignNew(HForeignNew node) {
+    if (!work.element.isGenerativeConstructor()) return;
+    // Check if this is the new object allocated by this generative
+    // constructor. Inlining might add other [HForeignNew]
+    // instructions in the graph.
+    if (!node.usedBy.any((user) => user is HReturn)) return;
     // The HForeignNew instruction is used in the generative constructor to
     // initialize all fields in newly created objects. The fields are
     // initialized to the value present in the initializer list or set to null
@@ -1623,100 +1493,3 @@
     });
   }
 }
-
-/**
- * This phase specializes dominated uses of a call, where the call
- * can give us some type information of what the receiver might be.
- * For example, after a call to [:a.foo():], if [:foo:] is only
- * in class [:A:], a can be of type [:A:].
- */
-class SsaReceiverSpecialization extends HBaseVisitor
-    implements OptimizationPhase {
-  final String name = "SsaReceiverSpecialization";
-  final Compiler compiler;
-
-  SsaReceiverSpecialization(this.compiler);
-
-  void visitGraph(HGraph graph) {
-    visitDominatorTree(graph);
-  }
-
-  void visitInterceptor(HInterceptor interceptor) {
-    HInstruction receiver = interceptor.receiver;
-    JavaScriptBackend backend = compiler.backend;
-    for (var user in receiver.usedBy) {
-      if (user is HInterceptor && interceptor.dominates(user)) {
-        Set<ClassElement> otherIntercepted = user.interceptedClasses;
-        // If the dominated interceptor intercepts the int class or
-        // the double class, we make sure these classes are also being
-        // intercepted by the dominating interceptor. Otherwise, the
-        // dominating interceptor could just intercept the number
-        // class and therefore not implement the methods in the int or
-        // double class.
-        if (otherIntercepted.contains(backend.jsIntClass)
-            || otherIntercepted.contains(backend.jsDoubleClass)) {
-          // We cannot modify the intercepted classes set without
-          // copying because it may be shared by multiple interceptors
-          // because of caching in the backend.
-          Set<ClassElement> copy = interceptor.interceptedClasses.toSet();
-          copy.addAll(user.interceptedClasses);
-          interceptor.interceptedClasses = copy;
-        }
-        user.interceptedClasses = interceptor.interceptedClasses;
-      }
-    }
-  }
-
-  // TODO(ngeoffray): Also implement it for non-intercepted calls.
-}
-
-/**
- * This phase replaces all interceptors that are used only once with
- * one-shot interceptors. It saves code size and makes the receiver of
- * an intercepted call a candidate for being generated at use site.
- */
-class SsaSimplifyInterceptors extends HBaseVisitor
-    implements OptimizationPhase {
-  final String name = "SsaSimplifyInterceptors";
-  final ConstantSystem constantSystem;
-  HGraph graph;
-
-  SsaSimplifyInterceptors(this.constantSystem);
-
-  void visitGraph(HGraph graph) {
-    this.graph = graph;
-    visitDominatorTree(graph);
-  }
-
-  void visitInterceptor(HInterceptor node) {
-    if (node.usedBy.length != 1) return;
-    // [HBailoutTarget] instructions might have the interceptor as
-    // input. In such situation we let the dead code analyzer find out
-    // the interceptor is not needed.
-    if (node.usedBy[0] is !HInvokeDynamic) return;
-
-    HInvokeDynamic user = node.usedBy[0];
-
-    // If [node] was loop hoisted, we keep the interceptor.
-    if (!user.hasSameLoopHeaderAs(node)) return;
-
-    // Replace the user with a [HOneShotInterceptor].
-    HConstant nullConstant = graph.addConstantNull(constantSystem);
-    List<HInstruction> inputs = new List<HInstruction>.from(user.inputs);
-    inputs[0] = nullConstant;
-    HOneShotInterceptor interceptor = new HOneShotInterceptor(
-        user.selector, inputs, node.interceptedClasses);
-    interceptor.sourcePosition = user.sourcePosition;
-    interceptor.sourceElement = user.sourceElement;
-    interceptor.instructionType = user.instructionType;
-
-    HBasicBlock block = user.block;
-    block.addAfter(user, interceptor);
-    block.rewrite(user, interceptor);
-    block.remove(user);
-
-    // The interceptor will be removed in the dead code elimination
-    // phase. Note that removing it here would not work because of how
-    // the [visitBasicBlock] is implemented.
-  }
-}
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/ssa.dart b/sdk/lib/_internal/compiler/implementation/ssa/ssa.dart
index fe79732..c62f67e 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/ssa.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/ssa.dart
@@ -32,6 +32,7 @@
 part 'builder.dart';
 part 'codegen.dart';
 part 'codegen_helpers.dart';
+part 'interceptor_simplifier.dart';
 part 'invoke_dynamic_specializers.dart';
 part 'nodes.dart';
 part 'optimize.dart';
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/tracer.dart b/sdk/lib/_internal/compiler/implementation/ssa/tracer.dart
index 02d7cfe..c603386 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/tracer.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/tracer.dart
@@ -367,9 +367,7 @@
 
   String visitInvokeConstructorBody(HInvokeConstructorBody invoke) {
     String target = invoke.element.name.slowToString();
-    int offset = HInvoke.ARGUMENTS_OFFSET + 1;
-    List arguments = invoke.inputs.sublist(offset);
-    return visitGenericInvoke("Invoke constructor body", target, arguments);
+    return visitGenericInvoke("Invoke constructor body", target, invoke.inputs);
   }
 
   String visitForeign(HForeign foreign) {
@@ -553,8 +551,12 @@
   }
 
   String visitTypeConversion(HTypeConversion node) {
+    assert(node.inputs.length <= 2);
+    String otherInput = (node.inputs.length == 2)
+        ? temporaryId(node.inputs[1])
+        : '';
     return "TypeConversion: ${temporaryId(node.checkedInput)} to "
-      "${node.instructionType}";
+      "${node.instructionType} $otherInput";
   }
 
   String visitRangeConversion(HRangeConversion node) {
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/types_propagation.dart b/sdk/lib/_internal/compiler/implementation/ssa/types_propagation.dart
index 5e1eb2a..9e85957 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/types_propagation.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/types_propagation.dart
@@ -190,14 +190,18 @@
     }
   }
 
-  HType visitInvokeDynamicMethod(HInvokeDynamicMethod instruction) {
+  HType visitInvokeDynamic(HInvokeDynamic instruction) {
     // Update the pending optimizations map based on the potentially
     // new types of the operands. If the operand types no longer allow
     // us to optimize, we remove the pending optimization.
     if (instruction.specializer is BinaryArithmeticSpecializer) {
       HInstruction left = instruction.inputs[1];
       HInstruction right = instruction.inputs[2];
-      if (left.isNumber() && !right.isNumber()) {
+      if (left.isNumber()
+          && !right.isNumber()
+          // We need to call the actual method in checked mode to get
+          // the right type error.
+          && !compiler.enableTypeAssertions) {
         pendingOptimizations[instruction] = () {
           // This callback function is invoked after we're done
           // propagating types. The types shouldn't have changed.
@@ -208,7 +212,7 @@
         pendingOptimizations.remove(instruction);
       }
     }
-    return super.visitInvokeDynamicMethod(instruction);
+    return super.visitInvokeDynamic(instruction);
   }
 }
 
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/validate.dart b/sdk/lib/_internal/compiler/implementation/ssa/validate.dart
index 16de943..e751b4d 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/validate.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/validate.dart
@@ -150,7 +150,8 @@
       bool inBasicBlock = instruction.isInBasicBlock();
       return everyInstruction(instruction.inputs, (input, count) {
         if (inBasicBlock) {
-          return countInstruction(input.usedBy, instruction) == count;
+          return input.isInBasicBlock()
+              && countInstruction(input.usedBy, instruction) == count;
         } else {
           return countInstruction(input.usedBy, instruction) == 0;
         }
@@ -161,7 +162,8 @@
     bool hasCorrectUses() {
       if (!instruction.isInBasicBlock()) return true;
       return everyInstruction(instruction.usedBy, (use, count) {
-        return countInstruction(use.inputs, instruction) == count;
+        return use.isInBasicBlock()
+            && countInstruction(use.inputs, instruction) == count;
       });
     }
 
diff --git a/sdk/lib/_internal/compiler/implementation/typechecker.dart b/sdk/lib/_internal/compiler/implementation/typechecker.dart
index b58a0eb..6ab80fd 100644
--- a/sdk/lib/_internal/compiler/implementation/typechecker.dart
+++ b/sdk/lib/_internal/compiler/implementation/typechecker.dart
@@ -680,6 +680,20 @@
     }
   }
 
+  /// Returns the first type in the list or [:dynamic:] if the list is empty.
+  DartType firstType(Link<DartType> link) {
+    return link.isEmpty ? types.dynamicType : link.head;
+  }
+
+  /**
+   * Returns the second type in the list or [:dynamic:] if the list is too
+   * short.
+   */
+  DartType secondType(Link<DartType> link) {
+    return link.isEmpty || link.tail.isEmpty
+        ? types.dynamicType : link.tail.head;
+  }
+
   /**
    * Checks [: target o= value :] for some operator o, and returns the type
    * of the result. This method also handles increment/decrement expressions
@@ -701,7 +715,7 @@
       FunctionType operatorType = operator;
       // [result] is the type of target o value.
       DartType result = operatorType.returnType;
-      DartType operatorArgument = operatorType.parameterTypes.head;
+      DartType operatorArgument = firstType(operatorType.parameterTypes);
       // Check target o value.
       bool validValue = checkAssignable(valueNode, value, operatorArgument);
       if (validValue || !(node.isPrefix || node.isPostfix)) {
@@ -732,7 +746,7 @@
         node, base, const SourceString('[]'), MemberKind.OPERATOR);
     if (indexGet is FunctionType) {
       FunctionType indexGetType = indexGet;
-      DartType indexGetKey = indexGetType.parameterTypes.head;
+      DartType indexGetKey = firstType(indexGetType.parameterTypes);
       // Check base[key].
       bool validKey = checkAssignable(keyNode, key, indexGetKey);
 
@@ -745,7 +759,7 @@
         FunctionType operatorType = operator;
 
         // Check base[key] o value.
-        DartType operatorArgument = operatorType.parameterTypes.head;
+        DartType operatorArgument = firstType(operatorType.parameterTypes);
         bool validValue = checkAssignable(valueNode, value, operatorArgument);
 
         // [result] is the type of base[key] o value.
@@ -756,9 +770,8 @@
             node, base, const SourceString('[]='), MemberKind.OPERATOR);
         if (indexSet is FunctionType) {
           FunctionType indexSetType = indexSet;
-          DartType indexSetKey = indexSetType.parameterTypes.head;
-          DartType indexSetValue =
-              indexSetType.parameterTypes.tail.head;
+          DartType indexSetKey = firstType(indexSetType.parameterTypes);
+          DartType indexSetValue = secondType(indexSetType.parameterTypes);
 
           if (validKey || indexGetKey != indexSetKey) {
             // Only check base[key] on []= if base[key] was valid for [] or
@@ -793,9 +806,9 @@
             node, base, const SourceString('[]='), MemberKind.OPERATOR);
         if (indexSet is FunctionType) {
           FunctionType indexSetType = indexSet;
-          DartType indexSetKey = indexSetType.parameterTypes.head;
+          DartType indexSetKey = firstType(indexSetType.parameterTypes);
           checkAssignable(keyNode, key, indexSetKey);
-          DartType indexSetValue = indexSetType.parameterTypes.tail.head;
+          DartType indexSetValue = secondType(indexSetType.parameterTypes);
           checkAssignable(node.assignmentOperator, value, indexSetValue);
         }
         return value;
@@ -899,7 +912,7 @@
 
   DartType visitLiteralList(LiteralList node) {
     InterfaceType listType = elements.getType(node);
-    DartType listElementType = listType.typeArguments.head;
+    DartType listElementType = firstType(listType.typeArguments);
     for (Link<Node> link = node.elements.nodes;
          !link.isEmpty;
          link = link.tail) {
@@ -1087,8 +1100,8 @@
 
   visitLiteralMap(LiteralMap node) {
     InterfaceType mapType = elements.getType(node);
-    DartType mapKeyType = mapType.typeArguments.head;
-    DartType mapValueType = mapType.typeArguments.tail.head;
+    DartType mapKeyType = firstType(mapType.typeArguments);
+    DartType mapValueType = secondType(mapType.typeArguments);
     for (Link<Node> link = node.entries.nodes;
          !link.isEmpty;
          link = link.tail) {
@@ -1106,7 +1119,12 @@
   }
 
   visitNamedArgument(NamedArgument node) {
-    return unhandledExpression();
+    // Named arguments are visited as part of analyzing invocations of
+    // unresolved methods. For instance [: foo(a: 42); :] where 'foo' is neither
+    // found in the enclosing scope nor through lookup on 'this' or
+    // [: x.foo(b: 42); :] where 'foo' cannot be not found through lookup on
+    // the static type of 'x'.
+    return analyze(node.expression);
   }
 
   visitSwitchStatement(SwitchStatement node) {
@@ -1122,7 +1140,15 @@
   }
 
   visitTryStatement(TryStatement node) {
-    return unhandledStatement();
+    // TODO(johnniwinther): Use reachability information of try-block,
+    // catch-blocks and finally-block to compute the whether the try statement
+    // is returning.
+    analyze(node.tryBlock);
+    for (CatchBlock catchBlock in node.catchBlocks) {
+      analyze(catchBlock);
+    }
+    analyzeWithDefault(node.finallyBlock, null);
+    return StatementType.NOT_RETURNING;
   }
 
   visitScriptTag(ScriptTag node) {
@@ -1130,7 +1156,7 @@
   }
 
   visitCatchBlock(CatchBlock node) {
-    return unhandledStatement();
+    return analyze(node.block);
   }
 
   visitTypedef(Typedef node) {
diff --git a/sdk/lib/_internal/compiler/implementation/types/concrete_types_inferrer.dart b/sdk/lib/_internal/compiler/implementation/types/concrete_types_inferrer.dart
index 6ad589e..f1e5291 100644
--- a/sdk/lib/_internal/compiler/implementation/types/concrete_types_inferrer.dart
+++ b/sdk/lib/_internal/compiler/implementation/types/concrete_types_inferrer.dart
@@ -33,7 +33,7 @@
 
   ClassBaseType(this.element);
 
-  bool operator ==(BaseType other) {
+  bool operator ==(var other) {
     if (identical(this, other)) return true;
     if (other is! ClassBaseType) return false;
     return element == other.element;
diff --git a/sdk/lib/_internal/compiler/implementation/types/flat_type_mask.dart b/sdk/lib/_internal/compiler/implementation/types/flat_type_mask.dart
index 0f0ee58..59f6874 100644
--- a/sdk/lib/_internal/compiler/implementation/types/flat_type_mask.dart
+++ b/sdk/lib/_internal/compiler/implementation/types/flat_type_mask.dart
@@ -383,19 +383,22 @@
    */
   static bool hasElementIn(ClassElement cls,
                            Selector selector,
-                           Element element) {
+                           Element element,
+                           Compiler compiler) {
     // Use [:implementation:] of [element]
     // because our function set only stores declarations.
-    Element result = findMatchIn(cls, selector);
+    Element result = findMatchIn(cls, selector, compiler);
     return result == null
         ? false
         : result.implementation == element.implementation;
   }
 
-  static Element findMatchIn(ClassElement cls, Selector selector) {
+  static Element findMatchIn(ClassElement cls,
+                             Selector selector,
+                             Compiler compiler) {
     // Use the [:implementation] of [cls] in case the found [element]
     // is in the patch class.
-    return cls.implementation.lookupSelector(selector);
+    return cls.implementation.lookupSelector(selector, compiler);
   }
 
   /**
@@ -408,7 +411,7 @@
     if (isEmpty) {
       if (!isNullable) return false;
       return hasElementIn(
-          compiler.backend.nullImplementation, selector, element);
+          compiler.backend.nullImplementation, selector, element, compiler);
     }
 
     // TODO(kasperl): Can't we just avoid creating typed selectors
@@ -424,14 +427,14 @@
     if (compiler.backend.isNullImplementation(other)) {
       return isNullable;
     } else if (isExact) {
-      return hasElementIn(self, selector, element);
+      return hasElementIn(self, selector, element, compiler);
     } else if (isSubclass) {
-      return hasElementIn(self, selector, element)
+      return hasElementIn(self, selector, element, compiler)
           || other.isSubclassOf(self)
           || compiler.world.hasAnySubclassThatMixes(self, other);
     } else {
       assert(isSubtype);
-      return hasElementIn(self, selector, element)
+      return hasElementIn(self, selector, element, compiler)
           || other.implementsInterface(self)
           || other.isSubclassOf(self)
           || compiler.world.hasAnySubclassThatMixes(self, other)
@@ -446,7 +449,7 @@
   static bool hasConcreteMatch(ClassElement cls,
                                Selector selector,
                                Compiler compiler) {
-    Element element = findMatchIn(cls, selector);
+    Element element = findMatchIn(cls, selector, compiler);
     if (element == null) return false;
 
     if (element.isAbstract(compiler)) {
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 c6c2e26..9241edc 100644
--- a/sdk/lib/_internal/compiler/implementation/types/simple_types_inferrer.dart
+++ b/sdk/lib/_internal/compiler/implementation/types/simple_types_inferrer.dart
@@ -961,23 +961,23 @@
     }
   }
 
-  void unregisterCalledElement(Send send,
+  void unregisterCalledElement(Node node,
                                Selector selector,
                                Element caller,
                                Element callee) {
     if (callee.isField()) {
       if (selector.isSetter()) {
         Map<Node, TypeMask> types = typeOfFields[callee];
-        if (types == null || !types.containsKey(send)) return;
-        types.remove(send);
+        if (types == null || !types.containsKey(node)) return;
+        types.remove(node);
         if (hasAnalyzedAll) updateNonFinalFieldType(callee);
       }
     } else if (callee.isGetter()) {
       return;
     } else {
       Map<Node, ArgumentsTypes> types = typeOfArguments[callee];
-      if (types == null || !types.containsKey(send)) return;
-      types.remove(send);
+      if (types == null || !types.containsKey(node)) return;
+      types.remove(node);
       if (hasAnalyzedAll) enqueueAgain(callee);
     }
   }
@@ -2224,9 +2224,18 @@
         assert(selector.isOperator());
         elements.setOperatorSelectorInComplexSendSet(node, selector);
       }
-    } else {
-      assert(node.asSend() != null);
+    } else if (node.asSend() != null) {
       elements.setSelector(node, selector);
+    } else {
+      assert(node.asForIn() != null);
+      if (selector.asUntyped == compiler.iteratorSelector) {
+        elements.setIteratorSelector(node, selector);
+      } else if (selector.asUntyped == compiler.currentSelector) {
+        elements.setCurrentSelector(node, selector);
+      } else {
+        assert(selector.asUntyped == compiler.moveNextSelector);
+        elements.setMoveNextSelector(node, selector);
+      }
     }
   }
 
@@ -2447,22 +2456,41 @@
 
   TypeMask visitForIn(ForIn node) {
     bool changed = false;
-    visit(node.expression);
-    if (!isThisExposed && node.expression.isThis()) {
-      Selector iteratorSelector = compiler.iteratorSelector;
-      checkIfExposesThis(new TypedSelector(thisType, iteratorSelector));
-      TypeMask iteratorType = inferrer.typeOfSelector(iteratorSelector);
+    TypeMask expressionType = visit(node.expression);
+    Selector iteratorSelector = elements.getIteratorSelector(node);
+    Selector currentSelector = elements.getCurrentSelector(node);
+    Selector moveNextSelector = elements.getMoveNextSelector(node);
 
-      checkIfExposesThis(
-          new TypedSelector(iteratorType, compiler.moveNextSelector));
-      checkIfExposesThis(
-          new TypedSelector(iteratorType, compiler.currentSelector));
+    TypeMask iteratorType =
+        handleDynamicSend(node, iteratorSelector, expressionType, null);
+    handleDynamicSend(node, moveNextSelector,
+                      iteratorType, new ArgumentsTypes([], null));
+    TypeMask currentType =
+        handleDynamicSend(node, currentSelector, iteratorType, null);
+
+    // We nullify the type in case there is no element in the
+    // iterable.
+    currentType = currentType.nullable();
+
+    if (node.expression.isThis()) {
+      // Any reasonable implementation of an iterator would expose
+      // this, so we play it safe and assume it will.
+      isThisExposed = true;
     }
+
     Node identifier = node.declaredIdentifier;
-    Element variable = elements[identifier];
+    Element element = elements[identifier];
     Selector selector = elements.getSelector(identifier);
-    handlePlainAssignment(identifier, variable, selector,
-                          inferrer.dynamicType, inferrer.dynamicType,
+
+    TypeMask receiverType;
+    if (element != null && element.isInstanceMember()) {
+      receiverType = thisType;
+    } else {
+      receiverType = inferrer.dynamicType;
+    }
+
+    handlePlainAssignment(identifier, element, selector,
+                          receiverType, currentType,
                           node.expression);
     return handleLoop(node, () {
       visit(node.body);
diff --git a/sdk/lib/_internal/compiler/implementation/util/uri_extras.dart b/sdk/lib/_internal/compiler/implementation/util/uri_extras.dart
index f43e826..654341d 100644
--- a/sdk/lib/_internal/compiler/implementation/util/uri_extras.dart
+++ b/sdk/lib/_internal/compiler/implementation/util/uri_extras.dart
@@ -5,7 +5,6 @@
 library uri_extras;
 
 import 'dart:math';
-import 'dart:uri';
 
 String relativize(Uri base, Uri uri, bool isWindows) {
   if (!base.path.startsWith('/')) {
@@ -31,7 +30,7 @@
   if (equalsNCS(base.scheme, 'file') &&
       equalsNCS(base.scheme, uri.scheme) &&
       base.userInfo == uri.userInfo &&
-      equalsNCS(base.domain, uri.domain) &&
+      equalsNCS(base.host, uri.host) &&
       base.port == uri.port &&
       uri.query == "" && uri.fragment == "") {
     if (normalize(uri.path).startsWith(normalize(base.path))) {
diff --git a/sdk/lib/_internal/compiler/samples/compile_loop/compile_loop.dart b/sdk/lib/_internal/compiler/samples/compile_loop/compile_loop.dart
index cb0e64b..df3f21a 100644
--- a/sdk/lib/_internal/compiler/samples/compile_loop/compile_loop.dart
+++ b/sdk/lib/_internal/compiler/samples/compile_loop/compile_loop.dart
@@ -7,7 +7,6 @@
 library sample.compile_loop;
 
 import 'dart:async';
-import 'dart:uri';
 
 import '../../compiler.dart' as compiler;
 
diff --git a/sdk/lib/_internal/compiler/samples/darttags/darttags.dart b/sdk/lib/_internal/compiler/samples/darttags/darttags.dart
index f600188..347b230 100644
--- a/sdk/lib/_internal/compiler/samples/darttags/darttags.dart
+++ b/sdk/lib/_internal/compiler/samples/darttags/darttags.dart
@@ -24,7 +24,6 @@
 // Where DART_LOCATION is the gclient directory where you found .gclient.
 
 import 'dart:io';
-import 'dart:uri';
 
 // TODO(ahe): Should be dart:mirrors.
 import '../../implementation/mirrors/mirrors.dart';
diff --git a/sdk/lib/_internal/compiler/samples/jsonify/jsonify.dart b/sdk/lib/_internal/compiler/samples/jsonify/jsonify.dart
index 891f505..82232c9 100644
--- a/sdk/lib/_internal/compiler/samples/jsonify/jsonify.dart
+++ b/sdk/lib/_internal/compiler/samples/jsonify/jsonify.dart
@@ -4,7 +4,6 @@
 
 import 'dart:io';
 import 'dart:json';
-import 'dart:uri';
 
 // TODO(ahe): Should be dart:mirrors.
 import '../../implementation/mirrors/mirrors.dart';
diff --git a/sdk/lib/_internal/compiler/samples/leap/leap.dart b/sdk/lib/_internal/compiler/samples/leap/leap.dart
index 3dba298..f352287 100644
--- a/sdk/lib/_internal/compiler/samples/leap/leap.dart
+++ b/sdk/lib/_internal/compiler/samples/leap/leap.dart
@@ -5,7 +5,6 @@
 library leap;
 
 import 'dart:isolate';
-import 'dart:uri';
 
 import 'dart:html' as html;
 import 'request_cache.dart';
diff --git a/sdk/lib/_internal/dartdoc/bin/dartdoc.dart b/sdk/lib/_internal/dartdoc/bin/dartdoc.dart
index 47eb828..d9fe3d9 100644
--- a/sdk/lib/_internal/dartdoc/bin/dartdoc.dart
+++ b/sdk/lib/_internal/dartdoc/bin/dartdoc.dart
@@ -18,7 +18,6 @@
 
 import 'dart:async';
 import 'dart:io';
-import 'dart:uri';
 
 // TODO(rnystrom): Use "package:" URL (#4968).
 import '../lib/dartdoc.dart';
diff --git a/sdk/lib/_internal/dartdoc/lib/dartdoc.dart b/sdk/lib/_internal/dartdoc/lib/dartdoc.dart
index 152f32c..dfc0f45 100644
--- a/sdk/lib/_internal/dartdoc/lib/dartdoc.dart
+++ b/sdk/lib/_internal/dartdoc/lib/dartdoc.dart
@@ -21,7 +21,6 @@
 import 'dart:isolate';
 import 'dart:json' as json;
 import 'dart:math';
-import 'dart:uri';
 
 import 'package:pathos/path.dart' as pathos;
 
diff --git a/sdk/lib/_internal/dartdoc/lib/src/dart2js_mirrors.dart b/sdk/lib/_internal/dartdoc/lib/src/dart2js_mirrors.dart
index 8ce26c0..7e421f8 100644
--- a/sdk/lib/_internal/dartdoc/lib/src/dart2js_mirrors.dart
+++ b/sdk/lib/_internal/dartdoc/lib/src/dart2js_mirrors.dart
@@ -6,7 +6,6 @@
 
 import 'dart:async' show Future;
 import 'dart:io' show Path;
-import 'dart:uri';
 
 import '../../../compiler/compiler.dart' as api;
 import '../../../compiler/implementation/mirrors/dart2js_mirror.dart' as dart2js
diff --git a/sdk/lib/_internal/dartdoc/lib/src/dartdoc/utils.dart b/sdk/lib/_internal/dartdoc/lib/src/dartdoc/utils.dart
index 016a354..4b95669 100644
--- a/sdk/lib/_internal/dartdoc/lib/src/dartdoc/utils.dart
+++ b/sdk/lib/_internal/dartdoc/lib/src/dartdoc/utils.dart
@@ -6,7 +6,6 @@
 library utils;
 
 import 'dart:io';
-import 'dart:uri';
 import 'dart:math' as math;
 
 import 'package:pathos/path.dart' as pathos;
diff --git a/sdk/lib/_internal/dartdoc/lib/src/export_map.dart b/sdk/lib/_internal/dartdoc/lib/src/export_map.dart
index 512991d..0173009 100644
--- a/sdk/lib/_internal/dartdoc/lib/src/export_map.dart
+++ b/sdk/lib/_internal/dartdoc/lib/src/export_map.dart
@@ -9,7 +9,6 @@
 library export_map;
 
 import 'dart:io';
-import 'dart:uri';
 
 import 'package:analyzer_experimental/analyzer.dart';
 import 'package:pathos/path.dart' as pathos;
diff --git a/sdk/lib/_internal/dartdoc/test/export_map_test.dart b/sdk/lib/_internal/dartdoc/test/export_map_test.dart
index 9ac4288..7d271d8 100644
--- a/sdk/lib/_internal/dartdoc/test/export_map_test.dart
+++ b/sdk/lib/_internal/dartdoc/test/export_map_test.dart
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:io';
-import 'dart:uri';
 
 import 'package:pathos/path.dart' as pathos;
 import 'package:unittest/unittest.dart';
diff --git a/sdk/lib/_internal/libraries.dart b/sdk/lib/_internal/libraries.dart
index ea69f77..2e8efef 100644
--- a/sdk/lib/_internal/libraries.dart
+++ b/sdk/lib/_internal/libraries.dart
@@ -38,9 +38,6 @@
       "core/core.dart",
       dart2jsPatchPath: "_internal/compiler/implementation/lib/core_patch.dart"),
 
-  "crypto": const LibraryInfo(
-      "crypto/crypto.dart"),
-
   "html": const LibraryInfo(
       "html/dartium/html_dartium.dart",
       category: "Client",
@@ -101,9 +98,6 @@
         category: "Client",
         dart2jsPath: "svg/dart2js/svg_dart2js.dart"),
 
-  "uri": const LibraryInfo(
-      "uri/uri.dart"),
-
   "utf": const LibraryInfo(
       "utf/utf.dart"),
 
diff --git a/sdk/lib/_internal/pub/lib/src/command.dart b/sdk/lib/_internal/pub/lib/src/command.dart
index d1f8516..abc2468 100644
--- a/sdk/lib/_internal/pub/lib/src/command.dart
+++ b/sdk/lib/_internal/pub/lib/src/command.dart
@@ -134,11 +134,11 @@
       return commandFuture;
     }).whenComplete(() => cache.deleteTempDir()).catchError((e) {
       if (e is PubspecNotFoundException && e.name == null) {
-        e = 'Could not find a file named "pubspec.yaml" in the directory '
-          '${path.current}.';
+        e = new ApplicationException('Could not find a file named '
+            '"pubspec.yaml" in the directory ${path.current}.');
       } else if (e is PubspecHasNoNameException && e.name == null) {
-        e = 'pubspec.yaml is missing the required "name" field (e.g. "name: '
-          '${path.basename(path.current)}").';
+        e = new ApplicationException('pubspec.yaml is missing the required '
+            '"name" field (e.g. "name: ${path.basename(path.current)}").');
       }
 
       handleError(e);
diff --git a/sdk/lib/_internal/pub/lib/src/command_lish.dart b/sdk/lib/_internal/pub/lib/src/command_lish.dart
index 9fc723c..20bbdd8 100644
--- a/sdk/lib/_internal/pub/lib/src/command_lish.dart
+++ b/sdk/lib/_internal/pub/lib/src/command_lish.dart
@@ -7,7 +7,6 @@
 import 'dart:async';
 import 'dart:io';
 import 'dart:json';
-import 'dart:uri';
 
 import 'package:args/args.dart';
 import 'package:http/http.dart' as http;
@@ -52,34 +51,36 @@
   Future _publish(packageBytes) {
     var cloudStorageUrl;
     return oauth2.withClient(cache, (client) {
-      // TODO(nweiz): Cloud Storage can provide an XML-formatted error. We
-      // should report that error and exit.
-      var newUri = server.resolve("/packages/versions/new.json");
-      return client.get(newUri).then((response) {
-        var parameters = parseJsonResponse(response);
+      return log.progress('Uploading', () {
+        // TODO(nweiz): Cloud Storage can provide an XML-formatted error. We
+        // should report that error and exit.
+        var newUri = server.resolve("/packages/versions/new.json");
+        return client.get(newUri).then((response) {
+          var parameters = parseJsonResponse(response);
 
-        var url = _expectField(parameters, 'url', response);
-        if (url is! String) invalidServerResponse(response);
-        cloudStorageUrl = Uri.parse(url);
-        var request = new http.MultipartRequest('POST', cloudStorageUrl);
+          var url = _expectField(parameters, 'url', response);
+          if (url is! String) invalidServerResponse(response);
+          cloudStorageUrl = Uri.parse(url);
+          var request = new http.MultipartRequest('POST', cloudStorageUrl);
 
-        var fields = _expectField(parameters, 'fields', response);
-        if (fields is! Map) invalidServerResponse(response);
-        fields.forEach((key, value) {
-          if (value is! String) invalidServerResponse(response);
-          request.fields[key] = value;
-        });
+          var fields = _expectField(parameters, 'fields', response);
+          if (fields is! Map) invalidServerResponse(response);
+          fields.forEach((key, value) {
+            if (value is! String) invalidServerResponse(response);
+            request.fields[key] = value;
+          });
 
-        request.followRedirects = false;
-        request.files.add(new http.MultipartFile.fromBytes(
-            'file', packageBytes, filename: 'package.tar.gz'));
-        return client.send(request);
-      }).then(http.Response.fromStream).then((response) {
-        var location = response.headers['location'];
-        if (location == null) throw new PubHttpException(response);
-        return location;
-      }).then((location) => client.get(location))
-        .then(handleJsonSuccess);
+          request.followRedirects = false;
+          request.files.add(new http.MultipartFile.fromBytes(
+              'file', packageBytes, filename: 'package.tar.gz'));
+          return client.send(request);
+        }).then(http.Response.fromStream).then((response) {
+          var location = response.headers['location'];
+          if (location == null) throw new PubHttpException(response);
+          return location;
+        }).then((location) => client.get(location))
+          .then(handleJsonSuccess);
+      });
     }).catchError((error) {
       if (error is! PubHttpException) throw error;
       var url = error.response.request.url;
@@ -87,7 +88,7 @@
         // TODO(nweiz): the response may have XML-formatted information about
         // the error. Try to parse that out once we have an easily-accessible
         // XML parser.
-        throw new Exception('Failed to upload the package.');
+        throw new ApplicationException('Failed to upload the package.');
       } else if (urisEqual(Uri.parse(url.origin), Uri.parse(server.origin))) {
         handleJsonError(error.response);
       } else {
diff --git a/sdk/lib/_internal/pub/lib/src/command_uploader.dart b/sdk/lib/_internal/pub/lib/src/command_uploader.dart
index 2f4208d..c3b9be8 100644
--- a/sdk/lib/_internal/pub/lib/src/command_uploader.dart
+++ b/sdk/lib/_internal/pub/lib/src/command_uploader.dart
@@ -6,7 +6,6 @@
 
 import 'dart:async';
 import 'dart:io';
-import 'dart:uri';
 
 import 'package:args/args.dart';
 import 'package:pathos/path.dart' as path;
@@ -64,12 +63,12 @@
       var uploader = commandOptions.rest[0];
       return oauth2.withClient(cache, (client) {
         if (command == 'add') {
-          var url = server.resolve("/packages/${encodeUriComponent(package)}"
+          var url = server.resolve("/packages/${Uri.encodeComponent(package)}"
               "/uploaders.json");
           return client.post(url, fields: {"email": uploader});
         } else { // command == 'remove'
-          var url = server.resolve("/packages/${encodeUriComponent(package)}"
-              "/uploaders/${encodeUriComponent(uploader)}.json");
+          var url = server.resolve("/packages/${Uri.encodeComponent(package)}"
+              "/uploaders/${Uri.encodeComponent(uploader)}.json");
           return client.delete(url);
         }
       });
diff --git a/sdk/lib/_internal/pub/lib/src/error_group.dart b/sdk/lib/_internal/pub/lib/src/error_group.dart
index 694638c..a6f9e86 100644
--- a/sdk/lib/_internal/pub/lib/src/error_group.dart
+++ b/sdk/lib/_internal/pub/lib/src/error_group.dart
@@ -129,7 +129,7 @@
 
     _isDone = true;
     _done._signalError(error);
-    if (!caught && !_done._hasListeners) error.throwDelayed();
+    if (!caught && !_done._hasListeners) runAsync((){ throw error; });
   }
 
   /// Notifies [this] that one of its member [Future]s is complete.
diff --git a/sdk/lib/_internal/pub/lib/src/hosted_source.dart b/sdk/lib/_internal/pub/lib/src/hosted_source.dart
index a793f65..a5c9992 100644
--- a/sdk/lib/_internal/pub/lib/src/hosted_source.dart
+++ b/sdk/lib/_internal/pub/lib/src/hosted_source.dart
@@ -7,7 +7,6 @@
 import 'dart:async';
 import 'dart:io' as io;
 import 'dart:json' as json;
-import 'dart:uri';
 
 import 'package:http/http.dart' as http;
 import 'package:pathos/path.dart' as path;
@@ -214,8 +213,8 @@
 Uri _makeUrl(description, String pattern(String server, String package)) {
   var parsed = _parseDescription(description);
   var server = parsed.last;
-  var package = encodeUriComponent(parsed.first);
-  return new Uri(pattern(server, package));
+  var package = Uri.encodeComponent(parsed.first);
+  return Uri.parse(pattern(server, package));
 }
 
 /// Parses [id] into its server, package name, and version components, then
@@ -225,9 +224,9 @@
     String pattern(String server, String package, String version)) {
   var parsed = _parseDescription(id.description);
   var server = parsed.last;
-  var package = encodeUriComponent(parsed.first);
-  var version = encodeUriComponent(id.version.toString());
-  return new Uri(pattern(server, package, version));
+  var package = Uri.encodeComponent(parsed.first);
+  var version = Uri.encodeComponent(id.version.toString());
+  return Uri.parse(pattern(server, package, version));
 }
 
 /// Parses the description for a package.
diff --git a/sdk/lib/_internal/pub/lib/src/io.dart b/sdk/lib/_internal/pub/lib/src/io.dart
index 659661f..e9a1316 100644
--- a/sdk/lib/_internal/pub/lib/src/io.dart
+++ b/sdk/lib/_internal/pub/lib/src/io.dart
@@ -10,7 +10,6 @@
 import 'dart:io';
 import 'dart:isolate';
 import 'dart:json';
-import 'dart:uri';
 
 import 'package:pathos/path.dart' as path;
 import 'package:http/http.dart' show ByteStream;
diff --git a/sdk/lib/_internal/pub/lib/src/log.dart b/sdk/lib/_internal/pub/lib/src/log.dart
index e01425b..047f621 100644
--- a/sdk/lib/_internal/pub/lib/src/log.dart
+++ b/sdk/lib/_internal/pub/lib/src/log.dart
@@ -18,6 +18,13 @@
 /// [recordTranscript()] is called.
 List<Entry> _transcript;
 
+/// The timer used to write "..." during a progress log.
+Timer _progressTimer;
+
+/// The progress message as it's being incrementally appended. When the
+/// progress is done, a single entry will be added to the log for it.
+String _progressMessage;
+
 /// An enum type for defining the different logging levels. By default, [ERROR]
 /// and [WARNING] messages are printed to sterr. [MESSAGE] messages are printed
 /// to stdout, and others are ignored.
@@ -178,6 +185,40 @@
   stderr.writeln('---- End log transcript ----');
 }
 
+/// Prints [message] then slowly prints additional "..." after it until the
+/// future returned by [callback] completes. If anything else is logged during
+/// this, it cancels the progress.
+Future progress(String message, Future callback()) {
+  if (_progressTimer != null) throw new StateError("Already in progress.");
+
+  _progressMessage = '$message...';
+  stdout.write(_progressMessage);
+
+  _progressTimer = new Timer.periodic(new Duration(milliseconds: 500), (_) {
+    stdout.write('.');
+    _progressMessage += '.';
+  });
+
+  return callback().whenComplete(_stopProgress);
+}
+
+/// Stops the running progress indicator, if currently running.
+_stopProgress() {
+  if (_progressTimer == null) return;
+
+  // Stop the timer.
+  _progressTimer.cancel();
+  _progressTimer = null;
+  stdout.writeln();
+
+  // Add the progress message to the transcript.
+  if (_transcript != null) {
+    _transcript.add(new Entry(Level.MESSAGE, [_progressMessage]));
+  }
+
+  _progressMessage = null;
+}
+
 /// Sets the verbosity to "normal", which shows errors, warnings, and messages.
 void showNormal() {
   _loggers[Level.ERROR]   = _logToStderr;
@@ -241,6 +282,8 @@
 }
 
 void _logToStream(IOSink sink, Entry entry, {bool showLabel}) {
+  _stopProgress();
+
   bool firstLine = true;
   for (var line in entry.lines) {
     if (showLabel) {
diff --git a/sdk/lib/_internal/pub/lib/src/oauth2.dart b/sdk/lib/_internal/pub/lib/src/oauth2.dart
index 56b1494..dd2c7b6 100644
--- a/sdk/lib/_internal/pub/lib/src/oauth2.dart
+++ b/sdk/lib/_internal/pub/lib/src/oauth2.dart
@@ -6,7 +6,6 @@
 
 import 'dart:async';
 import 'dart:io';
-import 'dart:uri';
 
 import 'package:oauth2/oauth2.dart';
 import 'package:pathos/path.dart' as path;
diff --git a/sdk/lib/_internal/pub/lib/src/package.dart b/sdk/lib/_internal/pub/lib/src/package.dart
index a2a1b12..22d3bee 100644
--- a/sdk/lib/_internal/pub/lib/src/package.dart
+++ b/sdk/lib/_internal/pub/lib/src/package.dart
@@ -11,6 +11,7 @@
 import 'io.dart';
 import 'pubspec.dart';
 import 'source_registry.dart';
+import 'utils.dart';
 import 'version.dart';
 
 final _README_REGEXP = new RegExp(r"^README($|\.)", caseSensitive: false);
@@ -190,29 +191,30 @@
   }
 }
 
-class PubspecNotFoundException implements Exception {
+class PubspecNotFoundException extends ApplicationException {
   final String name;
 
-  PubspecNotFoundException(this.name);
-
-  String toString() => 'Package "$name" doesn\'t have a pubspec.yaml file.';
+  PubspecNotFoundException(String name)
+      : name = name,
+        super('Package "$name" doesn\'t have a pubspec.yaml file.');
 }
 
-class PubspecHasNoNameException implements Exception {
+class PubspecHasNoNameException extends ApplicationException {
   final String name;
 
-  PubspecHasNoNameException(this.name);
-
-  String toString() => 'Package "$name"\'s pubspec.yaml file is missing the '
-    'required "name" field (e.g. "name: $name").';
+  PubspecHasNoNameException(String name)
+      : name = name,
+        super('Package "$name"\'s pubspec.yaml file is missing the '
+              'required "name" field (e.g. "name: $name").');
 }
 
-class PubspecNameMismatchException implements Exception {
+class PubspecNameMismatchException extends ApplicationException {
   final String expectedName;
   final String actualName;
 
-  PubspecNameMismatchException(this.expectedName, this.actualName);
-
-  String toString() => 'The name you specified for your dependency, '
-    '"$expectedName", doesn\'t match the name "$actualName" in its pubspec.';
+  PubspecNameMismatchException(String expectedName, String actualName)
+      : expectedName = expectedName,
+        actualName = actualName,
+        super('The name you specified for your dependency, "$expectedName", '
+              'doesn\'t match the name "$actualName" in its pubspec.');
 }
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 25d57ee..c9885f1 100644
--- a/sdk/lib/_internal/pub/lib/src/safe_http_server.dart
+++ b/sdk/lib/_internal/pub/lib/src/safe_http_server.dart
@@ -6,7 +6,6 @@
 
 import 'dart:async';
 import 'dart:io';
-import 'dart:uri';
 
 // TODO(nweiz): remove this when issue 9140 is fixed.
 /// A wrapper around [HttpServer] that swallows errors caused by requests
diff --git a/sdk/lib/_internal/pub/lib/src/solver/version_solver.dart b/sdk/lib/_internal/pub/lib/src/solver/version_solver.dart
index 7b6713b..9a98698 100644
--- a/sdk/lib/_internal/pub/lib/src/solver/version_solver.dart
+++ b/sdk/lib/_internal/pub/lib/src/solver/version_solver.dart
@@ -27,12 +27,12 @@
 /// packages.
 Future<SolveResult> resolveVersions(SourceRegistry sources, Package root,
     {LockFile lockFile, List<String> useLatest}) {
-  log.message('Resolving dependencies...');
-
   if (lockFile == null) lockFile = new LockFile.empty();
   if (useLatest == null) useLatest = [];
 
-  return new BacktrackingSolver(sources, root, lockFile, useLatest).solve();
+  return log.progress('Resolving dependencies', () {
+    return new BacktrackingSolver(sources, root, lockFile, useLatest).solve();
+  });
 }
 
 /// The result of a version resolution.
@@ -176,29 +176,6 @@
   SolveFailure(this.package, Iterable<Dependency> dependencies)
       : dependencies = dependencies != null ? dependencies : <Dependency>[];
 
-  /// Writes [dependencies] to [buffer] as a bullet list. If [describe] is
-  /// passed, it will be called for each dependency and the result will be
-  /// written next to the dependency.
-  void writeDependencies(StringBuffer buffer,
-      [String describe(PackageDep dep)]) {
-    var map = {};
-    for (var dep in dependencies) {
-      map[dep.depender] = dep.dep;
-    }
-
-    var names = map.keys.toList();
-    names.sort();
-
-    for (var name in names) {
-      buffer.writeln("- '$name' ");
-      if (describe != null) {
-        buffer.writeln(describe(map[name]));
-      } else {
-        buffer.writeln("depends on version ${map[name].constraint}");
-      }
-    }
-  }
-
   String toString() {
     if (dependencies.isEmpty) return _message;
 
@@ -213,9 +190,8 @@
     var names = map.keys.toList();
     names.sort();
 
-    for (var name in names) {
-      buffer.writeln("- '$name' ${_describeDependency(map[name])}");
-    }
+    buffer.writeAll(names.map(
+        (name) => "- '$name' ${_describeDependency(map[name])}"), '\n');
 
     return buffer.toString();
   }
diff --git a/sdk/lib/_internal/pub/lib/src/utils.dart b/sdk/lib/_internal/pub/lib/src/utils.dart
index 0311c9d..b3ae863 100644
--- a/sdk/lib/_internal/pub/lib/src/utils.dart
+++ b/sdk/lib/_internal/pub/lib/src/utils.dart
@@ -6,13 +6,12 @@
 library utils;
 
 import 'dart:async';
-import 'dart:crypto';
 import 'dart:io';
 import 'dart:isolate';
 import 'dart:json' as json;
 import 'dart:mirrors';
-import 'dart:uri';
 
+import "package:crypto/crypto.dart";
 import 'package:pathos/path.dart' as path;
 
 /// A pair of values.
@@ -321,8 +320,9 @@
 String mapToQuery(Map<String, String> map) {
   var pairs = <List<String>>[];
   map.forEach((key, value) {
-    key = encodeUriComponent(key);
-    value = (value == null || value.isEmpty) ? null : encodeUriComponent(value);
+    key = Uri.encodeQueryComponent(key);
+    value = (value == null || value.isEmpty)
+       ? null : Uri.encodeQueryComponent(value);
     pairs.add([key, value]);
   });
   return pairs.map((pair) {
@@ -339,13 +339,6 @@
 
 /// Return [uri] with redundant port information removed.
 Uri canonicalizeUri(Uri uri) {
-  if (uri == null) return null;
-
-  var sansPort = new Uri.fromComponents(
-      scheme: uri.scheme, userInfo: uri.userInfo, domain: uri.domain,
-      path: uri.path, query: uri.query, fragment: uri.fragment);
-  if (uri.scheme == 'http' && uri.port == 80) return sansPort;
-  if (uri.scheme == 'https' && uri.port == 443) return sansPort;
   return uri;
 }
 
@@ -354,10 +347,10 @@
 void mapAddAll(Map destination, Map source) =>
   source.forEach((key, value) => destination[key] = value);
 
-/// Decodes a URL-encoded string. Unlike [decodeUriComponent], this includes
+/// Decodes a URL-encoded string. Unlike [Uri.decodeComponent], this includes
 /// replacing `+` with ` `.
 String urlDecode(String encoded) =>
-  decodeUriComponent(encoded.replaceAll("+", " "));
+  Uri.decodeComponent(encoded.replaceAll("+", " "));
 
 /// Takes a simple data structure (composed of [Map]s, [Iterable]s, scalar
 /// objects, and [Future]s) and recursively resolves all the [Future]s contained
@@ -472,8 +465,8 @@
     // TODO(nweiz): Serialize using the YAML library once it supports
     // serialization.
 
-    // Use indentation for maps.
-    if (data is Map) {
+    // Use indentation for (non-empty) maps.
+    if (data is Map && !data.isEmpty) {
       if (isMapValue) {
         buffer.writeln();
         indent += '  ';
diff --git a/sdk/lib/_internal/pub/test/deploy/copies_dart_js_next_to_entrypoints_test.dart b/sdk/lib/_internal/pub/test/deploy/copies_dart_js_next_to_entrypoints_test.dart
index d95b3d9..7eecff3 100644
--- a/sdk/lib/_internal/pub/test/deploy/copies_dart_js_next_to_entrypoints_test.dart
+++ b/sdk/lib/_internal/pub/test/deploy/copies_dart_js_next_to_entrypoints_test.dart
@@ -45,8 +45,7 @@
       ])
     ]).create();
 
-    schedulePub(args: ["install"],
-        output: new RegExp(r"Dependencies installed!$"));
+    pubInstall();
 
     schedulePub(args: ["deploy"],
         output: '''
diff --git a/sdk/lib/_internal/pub/test/dev_dependency_test.dart b/sdk/lib/_internal/pub/test/dev_dependency_test.dart
index 1e37807..88df801 100644
--- a/sdk/lib/_internal/pub/test/dev_dependency_test.dart
+++ b/sdk/lib/_internal/pub/test/dev_dependency_test.dart
@@ -30,8 +30,7 @@
       })
     ]).create();
 
-    schedulePub(args: ["install"],
-        output: new RegExp(r"Dependencies installed!$"));
+    pubInstall();
 
     d.dir(packagesPath, [
       d.dir("foo", [
@@ -65,8 +64,7 @@
       })
     ]).create();
 
-    schedulePub(args: ["install"],
-        output: new RegExp(r"Dependencies installed!$"));
+    pubInstall();
 
     d.dir(packagesPath, [
       d.dir("foo", [
@@ -104,8 +102,7 @@
       })
     ]).create();
 
-    schedulePub(args: ["install"],
-        output: new RegExp(r"Dependencies installed!$"));
+    pubInstall();
 
     d.dir(packagesPath, [
       d.dir("foo", [
diff --git a/sdk/lib/_internal/pub/test/error_group_test.dart b/sdk/lib/_internal/pub/test/error_group_test.dart
index ff2f699..d22f12c 100644
--- a/sdk/lib/_internal/pub/test/error_group_test.dart
+++ b/sdk/lib/_internal/pub/test/error_group_test.dart
@@ -210,8 +210,16 @@
     });
 
     test('should pass through values from the stream', () {
-      expect(stream.elementAt(0), completion(equals(1)));
-      expect(stream.elementAt(1), completion(equals(2)));
+      StreamIterator iter = new StreamIterator(stream);
+      iter.moveNext().then((hasNext) {
+        expect(hasNext, isTrue);
+        expect(iter.current, equals(1));
+        iter.moveNext().then((hasNext) {
+          expect(hasNext, isTrue);
+          expect(iter.current, equals(2));
+          expect(iter.moveNext(), completion(isFalse));
+        });
+      });
       expect(errorGroup.done, completes);
 
       controller..add(1)..add(2)..close();
@@ -232,15 +240,14 @@
     });
 
     test('should pass a signaled exception to the stream if it has a listener '
-        'and should unsubscribe that stream', () {
-      expect(stream.first, throwsFormatException);
+         'and should unsubscribe that stream', () {
       // errorGroup shouldn't top-level the exception
+      expect(stream.first, throwsFormatException);
       errorGroup.signalError(new FormatException());
 
-      expect(stream.first.catchError((_) {
+      expect(new Future(() {
         controller.add('value');
-        return stream.isEmpty;
-      }), completion(isTrue));
+      }), completes);
     });
 
     test('should notify the error group of a signaled exception even if the '
@@ -345,10 +352,12 @@
 
     test("shouldn't throw a top-level exception if a stream receives an error "
         "after the other listened stream completes", () {
-      expect(stream1.toList(), completion(equals(['value1', 'value2'])));
+      var signal = new Completer();
+      expect(stream1.toList().whenComplete(signal.complete),
+             completion(equals(['value1', 'value2'])));
       controller1..add('value1')..add('value2')..close();
 
-      expect(stream1.toList().then((_) {
+      expect(signal.future.then((_) {
         // shouldn't cause a top-level exception
         controller2.addError(new FormatException());
       }), completes);
@@ -356,10 +365,12 @@
 
     test("shouldn't throw a top-level exception if an error is signaled after "
         "one listened stream completes", () {
-      expect(stream1.toList(), completion(equals(['value1', 'value2'])));
+      var signal = new Completer();
+      expect(stream1.toList().whenComplete(signal.complete),
+             completion(equals(['value1', 'value2'])));
       controller1..add('value1')..add('value2')..close();
 
-      expect(stream1.toList().then((_) {
+      expect(signal.future.then((_) {
         // shouldn't cause a top-level exception
         errorGroup.signalError(new FormatException());
       }), completes);
@@ -419,10 +430,12 @@
 
     test("shouldn't throw a top-level exception if the future receives an "
         "error after the listened stream completes", () {
-      expect(stream.toList(), completion(equals(['value1', 'value2'])));
+      var signal = new Completer();
+      expect(stream.toList().whenComplete(signal.complete),
+             completion(equals(['value1', 'value2'])));
       controller..add('value1')..add('value2')..close();
 
-      expect(stream.toList().then((_) {
+      expect(signal.future.then((_) {
         // shouldn't cause a top-level exception
         completer.completeError(new FormatException());
       }), completes);
diff --git a/sdk/lib/_internal/pub/test/hosted/fail_gracefully_on_missing_package_test.dart b/sdk/lib/_internal/pub/test/hosted/fail_gracefully_on_missing_package_test.dart
index 675e52e..5d79470 100644
--- a/sdk/lib/_internal/pub/test/hosted/fail_gracefully_on_missing_package_test.dart
+++ b/sdk/lib/_internal/pub/test/hosted/fail_gracefully_on_missing_package_test.dart
@@ -18,8 +18,8 @@
 
       d.appDir([dependencyMap("foo", "1.2.3")]).create();
 
-      pubCommand(command, error:
-          new RegExp('Could not find package "foo" at http://localhost:'));
+      pubCommand(command, error: new RegExp(
+          r'Could not find package "foo" at http://localhost:\d+\.$'));
     });
   });
 }
diff --git a/sdk/lib/_internal/pub/test/hosted/fail_gracefully_on_url_resolve_test.dart b/sdk/lib/_internal/pub/test/hosted/fail_gracefully_on_url_resolve_test.dart
index 49742d3..f6f4628 100644
--- a/sdk/lib/_internal/pub/test/hosted/fail_gracefully_on_url_resolve_test.dart
+++ b/sdk/lib/_internal/pub/test/hosted/fail_gracefully_on_url_resolve_test.dart
@@ -28,8 +28,7 @@
         })
       ]).create();
 
-      pubCommand(command, error:
-        new RegExp('Could not resolve URL "http://pub.invalid".'));
+      pubCommand(command, error: 'Could not resolve URL "http://pub.invalid".');
     });
   });
 }
diff --git a/sdk/lib/_internal/pub/test/hosted/offline_test.dart b/sdk/lib/_internal/pub/test/hosted/offline_test.dart
index eaca7f2..3019a6b 100644
--- a/sdk/lib/_internal/pub/test/hosted/offline_test.dart
+++ b/sdk/lib/_internal/pub/test/hosted/offline_test.dart
@@ -50,7 +50,7 @@
       ]).create();
 
       pubCommand(command, args: ['--offline'],
-          error: new RegExp('Could not find package "foo" in cache'));
+          error: 'Could not find package "foo" in cache.');
     });
 
     integration('fails gracefully no cached versions match', () {
@@ -65,8 +65,9 @@
         dependencyMap("foo", ">2.0.0")
       ]).create();
 
-      pubCommand(command, args: ['--offline'],
-          error: new RegExp("Package 'foo' has no versions that match >2.0.0"));
+      pubCommand(command, args: ['--offline'], error:
+          "Package 'foo' has no versions that match >2.0.0 derived from:\n"
+          "- 'myapp' depends on version >2.0.0");
     });
   });
 }
diff --git a/sdk/lib/_internal/pub/test/install/broken_symlink_test.dart b/sdk/lib/_internal/pub/test/install/broken_symlink_test.dart
index 7b627b2..2d9e551 100644
--- a/sdk/lib/_internal/pub/test/install/broken_symlink_test.dart
+++ b/sdk/lib/_internal/pub/test/install/broken_symlink_test.dart
@@ -23,8 +23,7 @@
     // Create a broken "packages" symlink in "bin".
     scheduleSymlink("nonexistent", path.join(appPath, "packages"));
 
-    schedulePub(args: ['install'],
-        output: new RegExp(r"Dependencies installed!$"));
+    pubInstall();
 
     d.dir(appPath, [
       d.dir("bin", [
@@ -47,8 +46,7 @@
     // Create a broken "packages" symlink in "bin".
     scheduleSymlink("nonexistent", path.join(appPath, "bin", "packages"));
 
-    schedulePub(args: ['install'],
-        output: new RegExp(r"Dependencies installed!$"));
+    pubInstall();
 
     d.dir(appPath, [
       d.dir("bin", [
diff --git a/sdk/lib/_internal/pub/test/install/git/check_out_and_update_test.dart b/sdk/lib/_internal/pub/test/install/git/check_out_and_update_test.dart
index 3af7fb7..b606972 100644
--- a/sdk/lib/_internal/pub/test/install/git/check_out_and_update_test.dart
+++ b/sdk/lib/_internal/pub/test/install/git/check_out_and_update_test.dart
@@ -21,8 +21,7 @@
 
     d.appDir([{"git": "../foo.git"}]).create();
 
-    schedulePub(args: ['install'],
-        output: new RegExp(r"Dependencies installed!$"));
+    pubInstall();
 
     d.dir(cachePath, [
       d.dir('git', [
@@ -42,8 +41,7 @@
       d.libPubspec('foo', '1.0.0')
     ]).commit();
 
-    schedulePub(args: ['update'],
-        output: new RegExp(r"Dependencies updated!$"));
+    pubUpdate();
 
     // When we download a new version of the git package, we should re-use the
     // git/cache directory but create a new git/ directory.
diff --git a/sdk/lib/_internal/pub/test/install/git/check_out_branch_test.dart b/sdk/lib/_internal/pub/test/install/git/check_out_branch_test.dart
index 2df0198..3e5aef0 100644
--- a/sdk/lib/_internal/pub/test/install/git/check_out_branch_test.dart
+++ b/sdk/lib/_internal/pub/test/install/git/check_out_branch_test.dart
@@ -28,8 +28,7 @@
 
     d.appDir([{"git": {"url": "../foo.git", "ref": "old"}}]).create();
 
-    schedulePub(args: ['install'],
-        output: new RegExp(r"Dependencies installed!$"));
+    pubInstall();
 
     d.dir(packagesPath, [
       d.dir('foo', [
diff --git a/sdk/lib/_internal/pub/test/install/git/check_out_revision_test.dart b/sdk/lib/_internal/pub/test/install/git/check_out_revision_test.dart
index b763dd4..cd1587a 100644
--- a/sdk/lib/_internal/pub/test/install/git/check_out_revision_test.dart
+++ b/sdk/lib/_internal/pub/test/install/git/check_out_revision_test.dart
@@ -28,8 +28,7 @@
 
     d.appDir([{"git": {"url": "../foo.git", "ref": commit}}]).create();
 
-    schedulePub(args: ['install'],
-        output: new RegExp(r"Dependencies installed!$"));
+    pubInstall();
 
     d.dir(packagesPath, [
       d.dir('foo', [
diff --git a/sdk/lib/_internal/pub/test/install/git/check_out_test.dart b/sdk/lib/_internal/pub/test/install/git/check_out_test.dart
index c2a4f68..9c36368 100644
--- a/sdk/lib/_internal/pub/test/install/git/check_out_test.dart
+++ b/sdk/lib/_internal/pub/test/install/git/check_out_test.dart
@@ -21,8 +21,7 @@
 
     d.appDir([{"git": "../foo.git"}]).create();
 
-    schedulePub(args: ['install'],
-        output: new RegExp(r"Dependencies installed!$"));
+    pubInstall();
 
     d.dir(cachePath, [
       d.dir('git', [
diff --git a/sdk/lib/_internal/pub/test/install/git/check_out_transitive_test.dart b/sdk/lib/_internal/pub/test/install/git/check_out_transitive_test.dart
index d68763c..d07b3e2 100644
--- a/sdk/lib/_internal/pub/test/install/git/check_out_transitive_test.dart
+++ b/sdk/lib/_internal/pub/test/install/git/check_out_transitive_test.dart
@@ -26,8 +26,7 @@
 
     d.appDir([{"git": "../foo.git"}]).create();
 
-    schedulePub(args: ['install'],
-        output: new RegExp("Dependencies installed!\$"));
+    pubInstall();
 
     d.dir(cachePath, [
       d.dir('git', [
diff --git a/sdk/lib/_internal/pub/test/install/git/check_out_twice_test.dart b/sdk/lib/_internal/pub/test/install/git/check_out_twice_test.dart
index 87d9a94..2aef954 100644
--- a/sdk/lib/_internal/pub/test/install/git/check_out_twice_test.dart
+++ b/sdk/lib/_internal/pub/test/install/git/check_out_twice_test.dart
@@ -21,8 +21,7 @@
 
     d.appDir([{"git": "../foo.git"}]).create();
 
-    schedulePub(args: ['install'],
-        output: new RegExp(r"Dependencies installed!$"));
+    pubInstall();
 
     d.dir(cachePath, [
       d.dir('git', [
@@ -39,7 +38,6 @@
 
     // Verify that nothing breaks if we install a Git revision that's already
     // in the cache.
-    schedulePub(args: ['update'],
-        output: new RegExp(r"Dependencies updated!$"));
+    pubUpdate();
   });
 }
diff --git a/sdk/lib/_internal/pub/test/install/git/check_out_with_trailing_slash_test.dart b/sdk/lib/_internal/pub/test/install/git/check_out_with_trailing_slash_test.dart
index e414483..5162b2f 100644
--- a/sdk/lib/_internal/pub/test/install/git/check_out_with_trailing_slash_test.dart
+++ b/sdk/lib/_internal/pub/test/install/git/check_out_with_trailing_slash_test.dart
@@ -24,8 +24,7 @@
 
       d.appDir([{"git": "../foo.git/"}]).create();
 
-      schedulePub(args: ['install'],
-          output: new RegExp(r"Dependencies installed!$"));
+      pubInstall();
 
       d.dir(cachePath, [
         d.dir('git', [
diff --git a/sdk/lib/_internal/pub/test/install/git/dependency_name_match_pubspec_test.dart b/sdk/lib/_internal/pub/test/install/git/dependency_name_match_pubspec_test.dart
index c1e5572..c6f89ee 100644
--- a/sdk/lib/_internal/pub/test/install/git/dependency_name_match_pubspec_test.dart
+++ b/sdk/lib/_internal/pub/test/install/git/dependency_name_match_pubspec_test.dart
@@ -29,12 +29,8 @@
       })
     ]).create();
 
-    // TODO(nweiz): clean up this RegExp when either issue 4706 or 4707 is
-    // fixed.
-    schedulePub(args: ['install'],
-        error: new RegExp(r'^The name you specified for your dependency, '
-            '"weirdname", doesn\'t match the name "foo" in its '
-            r'pubspec\.'),
-        exitCode: 1);
+    pubInstall(error:
+        'The name you specified for your dependency, "weirdname", doesn\'t '
+        'match the name "foo" in its pubspec.');
   });
 }
diff --git a/sdk/lib/_internal/pub/test/install/git/different_repo_name_test.dart b/sdk/lib/_internal/pub/test/install/git/different_repo_name_test.dart
index 3e5378c..0203f9b 100644
--- a/sdk/lib/_internal/pub/test/install/git/different_repo_name_test.dart
+++ b/sdk/lib/_internal/pub/test/install/git/different_repo_name_test.dart
@@ -29,8 +29,7 @@
       })
     ]).create();
 
-    schedulePub(args: ['install'],
-        output: new RegExp(r"Dependencies installed!$"));
+    pubInstall();
 
     d.dir(packagesPath, [
       d.dir('weirdname', [
diff --git a/sdk/lib/_internal/pub/test/install/git/lock_version_test.dart b/sdk/lib/_internal/pub/test/install/git/lock_version_test.dart
index ed4994b..8eb7087 100644
--- a/sdk/lib/_internal/pub/test/install/git/lock_version_test.dart
+++ b/sdk/lib/_internal/pub/test/install/git/lock_version_test.dart
@@ -26,8 +26,7 @@
     d.appDir([{"git": "../foo.git"}]).create();
 
     // This install should lock the foo.git dependency to the current revision.
-    schedulePub(args: ['install'],
-        output: new RegExp(r"Dependencies installed!$"));
+    pubInstall();
 
     d.dir(packagesPath, [
       d.dir('foo', [
@@ -44,8 +43,7 @@
     ]).commit();
 
     // This install shouldn't update the foo.git dependency due to the lockfile.
-    schedulePub(args: ['install'],
-        output: new RegExp(r"Dependencies installed!$"));
+    pubInstall();
 
     d.dir(packagesPath, [
       d.dir('foo', [
diff --git a/sdk/lib/_internal/pub/test/install/git/require_pubspec_name_test.dart b/sdk/lib/_internal/pub/test/install/git/require_pubspec_name_test.dart
index aad6a52..eafd067 100644
--- a/sdk/lib/_internal/pub/test/install/git/require_pubspec_name_test.dart
+++ b/sdk/lib/_internal/pub/test/install/git/require_pubspec_name_test.dart
@@ -24,9 +24,8 @@
 
     // TODO(nweiz): clean up this RegExp when either issue 4706 or 4707 is
     // fixed.
-    schedulePub(args: ['install'],
-        error: new RegExp(r'^Package "foo"' "'" 's pubspec.yaml file is '
-            r'missing the required "name" field \(e\.g\. "name: foo"\)\.'),
-        exitCode: 1);
+    pubInstall(error:
+        'Package "foo"\'s pubspec.yaml file is '
+        'missing the required "name" field (e.g. "name: foo").');
   });
 }
diff --git a/sdk/lib/_internal/pub/test/install/git/require_pubspec_test.dart b/sdk/lib/_internal/pub/test/install/git/require_pubspec_test.dart
index ad1a22d..ba2b5c6 100644
--- a/sdk/lib/_internal/pub/test/install/git/require_pubspec_test.dart
+++ b/sdk/lib/_internal/pub/test/install/git/require_pubspec_test.dart
@@ -22,9 +22,6 @@
 
     // TODO(nweiz): clean up this RegExp when either issue 4706 or 4707 is
     // fixed.
-    schedulePub(args: ['install'],
-        error: new RegExp('^Package "foo" doesn\'t have a '
-            'pubspec.yaml file.'),
-        exitCode: 1);
+    pubInstall(error: 'Package "foo" doesn\'t have a pubspec.yaml file.');
   });
 }
diff --git a/sdk/lib/_internal/pub/test/install/git/stay_locked_if_compatible_test.dart b/sdk/lib/_internal/pub/test/install/git/stay_locked_if_compatible_test.dart
index 8bc5025..f59b93b 100644
--- a/sdk/lib/_internal/pub/test/install/git/stay_locked_if_compatible_test.dart
+++ b/sdk/lib/_internal/pub/test/install/git/stay_locked_if_compatible_test.dart
@@ -22,8 +22,7 @@
 
     d.appDir([{"git": "../foo.git"}]).create();
 
-    schedulePub(args: ['install'],
-        output: new RegExp(r"Dependencies installed!$"));
+    pubInstall();
 
     d.dir(packagesPath, [
       d.dir('foo', [
@@ -38,8 +37,7 @@
 
     d.appDir([{"git": "../foo.git", "version": ">=1.0.0"}]).create();
 
-    schedulePub(args: ['install'],
-        output: new RegExp(r"Dependencies installed!$"));
+    pubInstall();
 
     d.dir(packagesPath, [
       d.dir('foo', [
diff --git a/sdk/lib/_internal/pub/test/install/git/unlock_if_incompatible_test.dart b/sdk/lib/_internal/pub/test/install/git/unlock_if_incompatible_test.dart
index 1b23fba..644650b 100644
--- a/sdk/lib/_internal/pub/test/install/git/unlock_if_incompatible_test.dart
+++ b/sdk/lib/_internal/pub/test/install/git/unlock_if_incompatible_test.dart
@@ -22,8 +22,7 @@
 
     d.appDir([{"git": "../foo.git"}]).create();
 
-    schedulePub(args: ['install'],
-        output: new RegExp(r"Dependencies installed!$"));
+    pubInstall();
 
     d.dir(packagesPath, [
       d.dir('foo', [
@@ -38,8 +37,7 @@
 
     d.appDir([{"git": "../foo.git", "version": ">=1.0.0"}]).create();
 
-    schedulePub(args: ['install'],
-        output: new RegExp(r"Dependencies installed!$"));
+    pubInstall();
 
     d.dir(packagesPath, [
       d.dir('foo', [
diff --git a/sdk/lib/_internal/pub/test/install/hosted/cached_pubspec_test.dart b/sdk/lib/_internal/pub/test/install/hosted/cached_pubspec_test.dart
index 153431a..5949d4b 100644
--- a/sdk/lib/_internal/pub/test/install/hosted/cached_pubspec_test.dart
+++ b/sdk/lib/_internal/pub/test/install/hosted/cached_pubspec_test.dart
@@ -20,8 +20,7 @@
     d.appDir([dependencyMap("foo", "1.2.3")]).create();
 
     // Run install once so it gets cached.
-    schedulePub(args: ['install'],
-        output: new RegExp("Dependencies installed!\$"));
+    pubInstall();
 
     // Clear the cache. We don't care about anything that was served during
     // the initial install.
@@ -31,8 +30,7 @@
     d.packagesDir({"foo": "1.2.3"}).validate();
 
     // Run the solver again now that it's cached.
-    schedulePub(args: ['install'],
-        output: new RegExp("Dependencies installed!\$"));
+    pubInstall();
 
     // The update should not have requested the pubspec since it's installed
     // locally already.
diff --git a/sdk/lib/_internal/pub/test/install/hosted/do_not_update_on_removed_constraints_test.dart b/sdk/lib/_internal/pub/test/install/hosted/do_not_update_on_removed_constraints_test.dart
index 539d263..9184b83 100644
--- a/sdk/lib/_internal/pub/test/install/hosted/do_not_update_on_removed_constraints_test.dart
+++ b/sdk/lib/_internal/pub/test/install/hosted/do_not_update_on_removed_constraints_test.dart
@@ -22,8 +22,7 @@
 
     d.appDir([dependencyMap("foo"), dependencyMap("bar")]).create();
 
-    schedulePub(args: ['install'],
-        output: new RegExp(r"Dependencies installed!$"));
+    pubInstall();
 
     d.packagesDir({
       "foo": "1.0.0",
@@ -33,8 +32,7 @@
 
     d.appDir([dependencyMap("foo")]).create();
 
-    schedulePub(args: ['install'],
-        output: new RegExp(r"Dependencies installed!$"));
+    pubInstall();
 
     d.packagesDir({
       "foo": "1.0.0",
diff --git a/sdk/lib/_internal/pub/test/install/hosted/install_test.dart b/sdk/lib/_internal/pub/test/install/hosted/install_test.dart
index 5db5553..375860a 100644
--- a/sdk/lib/_internal/pub/test/install/hosted/install_test.dart
+++ b/sdk/lib/_internal/pub/test/install/hosted/install_test.dart
@@ -16,8 +16,7 @@
 
     d.appDir([dependencyMap("foo", "1.2.3")]).create();
 
-    schedulePub(args: ['install'],
-        output: new RegExp("Dependencies installed!\$"));
+    pubInstall();
 
     d.cacheDir({"foo": "1.2.3"}).validate();
     d.packagesDir({"foo": "1.2.3"}).validate();
@@ -28,9 +27,7 @@
 
     d.appDir([dependencyMap("bad name!", "1.2.3")]).create();
 
-    schedulePub(args: ['install'],
-        error: new RegExp('Could not find package "bad name!" at '
-                          'http://localhost:'),
-        exitCode: 1);
+    pubInstall(error: new RegExp(
+        r'Could not find package "bad name!" at http://localhost:\d+\.$'));
   });
 }
diff --git a/sdk/lib/_internal/pub/test/install/hosted/install_transitive_test.dart b/sdk/lib/_internal/pub/test/install/hosted/install_transitive_test.dart
index 7da990f5..e474897 100644
--- a/sdk/lib/_internal/pub/test/install/hosted/install_transitive_test.dart
+++ b/sdk/lib/_internal/pub/test/install/hosted/install_transitive_test.dart
@@ -21,8 +21,7 @@
 
     d.appDir([dependencyMap("foo", "1.2.3")]).create();
 
-    schedulePub(args: ['install'],
-        output: new RegExp("Dependencies installed!\$"));
+    pubInstall();
 
     d.cacheDir({"foo": "1.2.3", "bar": "2.0.4"}).validate();
     d.packagesDir({"foo": "1.2.3", "bar": "2.0.4"}).validate();
diff --git a/sdk/lib/_internal/pub/test/install/hosted/repair_cache_test.dart b/sdk/lib/_internal/pub/test/install/hosted/repair_cache_test.dart
index a343cc4..94874ad 100644
--- a/sdk/lib/_internal/pub/test/install/hosted/repair_cache_test.dart
+++ b/sdk/lib/_internal/pub/test/install/hosted/repair_cache_test.dart
@@ -30,8 +30,7 @@
 
     d.appDir([dependencyMap("foo", "1.2.3")]).create();
 
-    schedulePub(args: ['install'],
-        output: new RegExp("Dependencies installed!\$"));
+    pubInstall();
 
     d.cacheDir({"foo": "1.2.3"}).validate();
     d.packagesDir({"foo": "1.2.3"}).validate();
@@ -54,8 +53,7 @@
 
     d.appDir([dependencyMap("foo", "1.2.3")]).create();
 
-    schedulePub(args: ['install'],
-        output: new RegExp("Dependencies installed!\$"));
+    pubInstall();
 
     d.cacheDir({"foo": "1.2.3"}).validate();
     d.packagesDir({"foo": "1.2.3"}).validate();
diff --git a/sdk/lib/_internal/pub/test/install/hosted/resolve_constraints_test.dart b/sdk/lib/_internal/pub/test/install/hosted/resolve_constraints_test.dart
index 0da297a..522f21a 100644
--- a/sdk/lib/_internal/pub/test/install/hosted/resolve_constraints_test.dart
+++ b/sdk/lib/_internal/pub/test/install/hosted/resolve_constraints_test.dart
@@ -22,8 +22,7 @@
 
     d.appDir([dependencyMap("foo"), dependencyMap("bar")]).create();
 
-    schedulePub(args: ['install'],
-        output: new RegExp("Dependencies installed!\$"));
+    pubInstall();
 
     d.cacheDir({
       "foo": "1.2.3",
diff --git a/sdk/lib/_internal/pub/test/install/hosted/stay_locked_if_compatible_test.dart b/sdk/lib/_internal/pub/test/install/hosted/stay_locked_if_compatible_test.dart
index 7c08ab5..dfe1b50 100644
--- a/sdk/lib/_internal/pub/test/install/hosted/stay_locked_if_compatible_test.dart
+++ b/sdk/lib/_internal/pub/test/install/hosted/stay_locked_if_compatible_test.dart
@@ -17,8 +17,7 @@
 
     d.appDir([dependencyMap("foo")]).create();
 
-    schedulePub(args: ['install'],
-        output: new RegExp(r"Dependencies installed!$"));
+    pubInstall();
 
     d.packagesDir({"foo": "1.0.0"}).validate();
 
@@ -26,8 +25,7 @@
 
     d.appDir([dependencyMap("foo", ">=1.0.0")]).create();
 
-    schedulePub(args: ['install'],
-        output: new RegExp(r"Dependencies installed!$"));
+    pubInstall();
 
     d.packagesDir({"foo": "1.0.0"}).validate();
   });
diff --git a/sdk/lib/_internal/pub/test/install/hosted/stay_locked_if_new_is_satisfied_test.dart b/sdk/lib/_internal/pub/test/install/hosted/stay_locked_if_new_is_satisfied_test.dart
index fd2f244..1f57d92 100644
--- a/sdk/lib/_internal/pub/test/install/hosted/stay_locked_if_new_is_satisfied_test.dart
+++ b/sdk/lib/_internal/pub/test/install/hosted/stay_locked_if_new_is_satisfied_test.dart
@@ -21,8 +21,7 @@
 
     d.appDir([dependencyMap("foo")]).create();
 
-    schedulePub(args: ['install'],
-        output: new RegExp(r"Dependencies installed!$"));
+    pubInstall();
 
     d.packagesDir({
       "foo": "1.0.0",
@@ -39,8 +38,7 @@
 
     d.appDir([dependencyMap("foo"), dependencyMap("newdep")]).create();
 
-    schedulePub(args: ['install'],
-        output: new RegExp(r"Dependencies installed!$"));
+    pubInstall();
 
     d.packagesDir({
       "foo": "1.0.0",
diff --git a/sdk/lib/_internal/pub/test/install/hosted/stay_locked_test.dart b/sdk/lib/_internal/pub/test/install/hosted/stay_locked_test.dart
index 188012e..4cbafe3 100644
--- a/sdk/lib/_internal/pub/test/install/hosted/stay_locked_test.dart
+++ b/sdk/lib/_internal/pub/test/install/hosted/stay_locked_test.dart
@@ -22,8 +22,7 @@
     d.appDir([dependencyMap("foo")]).create();
 
     // This install should lock the foo dependency to version 1.0.0.
-    schedulePub(args: ['install'],
-        output: new RegExp(r"Dependencies installed!$"));
+    pubInstall();
 
     d.packagesDir({"foo": "1.0.0"}).validate();
 
@@ -34,8 +33,7 @@
     servePackages([packageMap("foo", "1.0.1")]);
 
     // This install shouldn't update the foo dependency due to the lockfile.
-    schedulePub(args: ['install'],
-        output: new RegExp(r"Dependencies installed!$"));
+    pubInstall();
 
     d.packagesDir({"foo": "1.0.0"}).validate();
   });
diff --git a/sdk/lib/_internal/pub/test/install/hosted/unlock_if_incompatible_test.dart b/sdk/lib/_internal/pub/test/install/hosted/unlock_if_incompatible_test.dart
index 082a36c..348a400 100644
--- a/sdk/lib/_internal/pub/test/install/hosted/unlock_if_incompatible_test.dart
+++ b/sdk/lib/_internal/pub/test/install/hosted/unlock_if_incompatible_test.dart
@@ -17,17 +17,13 @@
 
     d.appDir([dependencyMap("foo")]).create();
 
-    schedulePub(args: ['install'],
-        output: new RegExp(r"Dependencies installed!$"));
+    pubInstall();
 
     d.packagesDir({"foo": "1.0.0"}).validate();
-
     servePackages([packageMap("foo", "1.0.1")]);
-
     d.appDir([dependencyMap("foo", ">1.0.0")]).create();
 
-    schedulePub(args: ['install'],
-        output: new RegExp(r"Dependencies installed!$"));
+    pubInstall();
 
     d.packagesDir({"foo": "1.0.1"}).validate();
   });
diff --git a/sdk/lib/_internal/pub/test/install/hosted/unlock_if_new_is_unsatisfied_test.dart b/sdk/lib/_internal/pub/test/install/hosted/unlock_if_new_is_unsatisfied_test.dart
index 44ecb89..a80bc58 100644
--- a/sdk/lib/_internal/pub/test/install/hosted/unlock_if_new_is_unsatisfied_test.dart
+++ b/sdk/lib/_internal/pub/test/install/hosted/unlock_if_new_is_unsatisfied_test.dart
@@ -22,8 +22,7 @@
 
     d.appDir([dependencyMap("foo")]).create();
 
-    schedulePub(args: ['install'],
-        output: new RegExp(r"Dependencies installed!$"));
+    pubInstall();
 
     d.packagesDir({
       "foo": "1.0.0",
@@ -42,8 +41,7 @@
 
     d.appDir([dependencyMap("foo"), dependencyMap("newdep")]).create();
 
-    schedulePub(args: ['install'],
-        output: new RegExp(r"Dependencies installed!$"));
+    pubInstall();
 
     d.packagesDir({
       "foo": "2.0.0",
diff --git a/sdk/lib/_internal/pub/test/install/path/absolute_path_test.dart b/sdk/lib/_internal/pub/test/install/path/absolute_path_test.dart
index 9d12d16..42b2636 100644
--- a/sdk/lib/_internal/pub/test/install/path/absolute_path_test.dart
+++ b/sdk/lib/_internal/pub/test/install/path/absolute_path_test.dart
@@ -26,8 +26,7 @@
       })
     ]).create();
 
-    schedulePub(args: ["install"],
-        output: new RegExp(r"Dependencies installed!$"));
+    pubInstall();
 
     d.dir(packagesPath, [
       d.dir("foo", [
diff --git a/sdk/lib/_internal/pub/test/install/path/absolute_symlink_test.dart b/sdk/lib/_internal/pub/test/install/path/absolute_symlink_test.dart
index 4e4b196..83724c3 100644
--- a/sdk/lib/_internal/pub/test/install/path/absolute_symlink_test.dart
+++ b/sdk/lib/_internal/pub/test/install/path/absolute_symlink_test.dart
@@ -26,8 +26,7 @@
       })
     ]).create();
 
-    schedulePub(args: ["install"],
-        output: new RegExp(r"Dependencies installed!$"));
+    pubInstall();
 
     d.dir("moved").create();
 
diff --git a/sdk/lib/_internal/pub/test/install/path/no_pubspec_test.dart b/sdk/lib/_internal/pub/test/install/path/no_pubspec_test.dart
index 4553861..61789ad 100644
--- a/sdk/lib/_internal/pub/test/install/path/no_pubspec_test.dart
+++ b/sdk/lib/_internal/pub/test/install/path/no_pubspec_test.dart
@@ -26,8 +26,6 @@
       })
     ]).create();
 
-    schedulePub(args: ['install'],
-        error: new RegExp('Package "foo" doesn\'t have a pubspec.yaml file.'),
-        exitCode: 1);
+    pubInstall(error: 'Package "foo" doesn\'t have a pubspec.yaml file.');
   });
 }
\ No newline at end of file
diff --git a/sdk/lib/_internal/pub/test/install/path/nonexistent_dir_test.dart b/sdk/lib/_internal/pub/test/install/path/nonexistent_dir_test.dart
index 053c922..3564817 100644
--- a/sdk/lib/_internal/pub/test/install/path/nonexistent_dir_test.dart
+++ b/sdk/lib/_internal/pub/test/install/path/nonexistent_dir_test.dart
@@ -24,15 +24,6 @@
       })
     ]).create();
 
-    // TODO(rnystrom): The "\" in a Windows path gets treated like a regex
-    // character, so hack escape. A better fix is to use a literal string
-    // instead of a RegExp to validate, but that requires us to move the
-    // stack traces out of the stderr when we invoke pub. See also: #4706.
-    var escapePath = badPath.replaceAll(r"\", r"\\");
-
-    schedulePub(args: ['install'],
-        error:
-            new RegExp("Could not find package 'foo' at '$escapePath'."),
-        exitCode: 1);
+    pubInstall(error: "Could not find package 'foo' at '$badPath'.");
   });
 }
\ No newline at end of file
diff --git a/sdk/lib/_internal/pub/test/install/path/path_is_file_test.dart b/sdk/lib/_internal/pub/test/install/path/path_is_file_test.dart
index 7779467..dbbc0df 100644
--- a/sdk/lib/_internal/pub/test/install/path/path_is_file_test.dart
+++ b/sdk/lib/_internal/pub/test/install/path/path_is_file_test.dart
@@ -10,7 +10,7 @@
 
 main() {
   initConfig();
-  integration('path dependency when path is a d.file', () {
+  integration('path dependency when path is a file', () {
     d.dir('foo', [
       d.libDir('foo'),
       d.libPubspec('foo', '0.0.1')
@@ -28,15 +28,7 @@
       })
     ]).create();
 
-    // TODO(rnystrom): The "\" in a Windows path gets treated like a regex
-    // character, so hack escape. A better fix is to use a literal string
-    // instead of a RegExp to validate, but that requires us to move the
-    // stack traces out of the stderr when we invoke pub. See also: #4706.
-    var escapePath = dummyPath.replaceAll(r"\", r"\\");
-
-    schedulePub(args: ['install'],
-        error: new RegExp("Path dependency for package 'foo' must refer to a "
-                          "directory, not a file. Was '$escapePath'."),
-        exitCode: 1);
+    pubInstall(error: "Path dependency for package 'foo' must refer to a "
+                      "directory, not a file. Was '$dummyPath'.");
   });
 }
\ No newline at end of file
diff --git a/sdk/lib/_internal/pub/test/install/path/relative_path_test.dart b/sdk/lib/_internal/pub/test/install/path/relative_path_test.dart
index b9c9c31..5abaf09 100644
--- a/sdk/lib/_internal/pub/test/install/path/relative_path_test.dart
+++ b/sdk/lib/_internal/pub/test/install/path/relative_path_test.dart
@@ -25,8 +25,7 @@
       })
     ]).create();
 
-    schedulePub(args: ["install"],
-        output: new RegExp(r"Dependencies installed!$"));
+    pubInstall();
 
     d.dir(packagesPath, [
       d.dir("foo", [
@@ -58,8 +57,7 @@
       })
     ]).create();
 
-    schedulePub(args: ["install"],
-        output: new RegExp(r"Dependencies installed!$"));
+    pubInstall();
 
     d.dir(packagesPath, [
       d.dir("foo", [
diff --git a/sdk/lib/_internal/pub/test/install/path/relative_symlink_test.dart b/sdk/lib/_internal/pub/test/install/path/relative_symlink_test.dart
index 859f12c..97bd902 100644
--- a/sdk/lib/_internal/pub/test/install/path/relative_symlink_test.dart
+++ b/sdk/lib/_internal/pub/test/install/path/relative_symlink_test.dart
@@ -34,8 +34,7 @@
       })
     ]).create();
 
-    schedulePub(args: ["install"],
-        output: new RegExp(r"Dependencies installed!$"));
+    pubInstall();
 
     d.dir("moved").create();
 
diff --git a/sdk/lib/_internal/pub/test/install/path/shared_dependency_symlink_test.dart b/sdk/lib/_internal/pub/test/install/path/shared_dependency_symlink_test.dart
index d3b75da..bfb26dc 100644
--- a/sdk/lib/_internal/pub/test/install/path/shared_dependency_symlink_test.dart
+++ b/sdk/lib/_internal/pub/test/install/path/shared_dependency_symlink_test.dart
@@ -44,8 +44,7 @@
     d.dir("link").create();
     scheduleSymlink("shared", path.join("link", "shared"));
 
-    schedulePub(args: ["install"],
-        output: new RegExp(r"Dependencies installed!$"));
+    pubInstall();
 
     d.dir(packagesPath, [
       d.dir("foo", [d.file("foo.dart", 'main() => "foo";')]),
diff --git a/sdk/lib/_internal/pub/test/install/path/shared_dependency_test.dart b/sdk/lib/_internal/pub/test/install/path/shared_dependency_test.dart
index 65e7992..ee8a7c3 100644
--- a/sdk/lib/_internal/pub/test/install/path/shared_dependency_test.dart
+++ b/sdk/lib/_internal/pub/test/install/path/shared_dependency_test.dart
@@ -39,8 +39,7 @@
       })
     ]).create();
 
-    schedulePub(args: ["install"],
-        output: new RegExp(r"Dependencies installed!$"));
+    pubInstall();
 
     d.dir(packagesPath, [
       d.dir("foo", [d.file("foo.dart", 'main() => "foo";')]),
@@ -79,8 +78,7 @@
       })
     ]).create();
 
-    schedulePub(args: ["install"],
-        output: new RegExp(r"Dependencies installed!$"));
+    pubInstall();
 
     d.dir(packagesPath, [
       d.dir("foo", [d.file("foo.dart", 'main() => "foo";')]),
@@ -119,8 +117,7 @@
       })
     ]).create();
 
-    schedulePub(args: ["install"],
-        output: new RegExp(r"Dependencies installed!$"));
+    pubInstall();
 
     d.dir(packagesPath, [
       d.dir("foo", [d.file("foo.dart", 'main() => "foo";')]),
diff --git a/sdk/lib/_internal/pub/test/install/relative_symlink_test.dart b/sdk/lib/_internal/pub/test/install/relative_symlink_test.dart
index aeb0a2a..deb2254 100644
--- a/sdk/lib/_internal/pub/test/install/relative_symlink_test.dart
+++ b/sdk/lib/_internal/pub/test/install/relative_symlink_test.dart
@@ -25,8 +25,7 @@
       d.libDir('foo')
     ]).create();
 
-    schedulePub(args: ['install'],
-        output: new RegExp(r"Dependencies installed!$"));
+    pubInstall();
 
     scheduleRename(appPath, "moved");
 
@@ -46,8 +45,7 @@
       d.dir("bin")
     ]).create();
 
-    schedulePub(args: ['install'],
-        output: new RegExp(r"Dependencies installed!$"));
+    pubInstall();
 
     scheduleRename(appPath, "moved");
 
diff --git a/sdk/lib/_internal/pub/test/install/switch_source_test.dart b/sdk/lib/_internal/pub/test/install/switch_source_test.dart
index db8864e..428292e 100644
--- a/sdk/lib/_internal/pub/test/install/switch_source_test.dart
+++ b/sdk/lib/_internal/pub/test/install/switch_source_test.dart
@@ -19,17 +19,13 @@
 
     d.appDir([{"path": "../foo"}]).create();
 
-    schedulePub(args: ['install'],
-        output: new RegExp("Dependencies installed!\$"));
+    pubInstall();
 
     d.packagesDir({"foo": "0.0.1"}).validate();
-
     servePackages([packageMap("foo", "1.2.3")]);
-
     d.appDir([dependencyMap("foo", "any")]).create();
 
-    schedulePub(args: ['install'],
-        output: new RegExp("Dependencies installed!\$"));
+    pubInstall();
 
     d.packagesDir({"foo": "1.2.3"}).validate();
   });
diff --git a/sdk/lib/_internal/pub/test/lish/archives_and_uploads_a_package_test.dart b/sdk/lib/_internal/pub/test/lish/archives_and_uploads_a_package_test.dart
index 4e65965..f1460b5 100644
--- a/sdk/lib/_internal/pub/test/lish/archives_and_uploads_a_package_test.dart
+++ b/sdk/lib/_internal/pub/test/lish/archives_and_uploads_a_package_test.dart
@@ -31,6 +31,8 @@
       request.response.close();
     });
 
+    expect(pub.nextLine(), completion(matches(r'Uploading\.\.\.+')));
+
     expect(pub.nextLine(),
         completion(equals('Package test_pkg 1.0.0 uploaded!')));
     pub.shouldExit(0);
diff --git a/sdk/lib/_internal/pub/test/oauth2/utils.dart b/sdk/lib/_internal/pub/test/oauth2/utils.dart
index fa3ce98..7544506 100644
--- a/sdk/lib/_internal/pub/test/oauth2/utils.dart
+++ b/sdk/lib/_internal/pub/test/oauth2/utils.dart
@@ -6,7 +6,6 @@
 
 import 'dart:io';
 import 'dart:json' as json;
-import 'dart:uri';
 
 import 'package:http/http.dart' as http;
 import 'package:scheduled_test/scheduled_process.dart';
@@ -27,7 +26,7 @@
         .firstMatch(line);
     expect(match, isNotNull);
 
-    var redirectUrl = Uri.parse(decodeUriComponent(match.group(1)));
+    var redirectUrl = Uri.parse(Uri.decodeComponent(match.group(1)));
     redirectUrl = addQueryParameters(redirectUrl, {'code': 'access code'});
     return (new http.Request('GET', redirectUrl)..followRedirects = false)
       .send();
diff --git a/sdk/lib/_internal/pub/test/oauth2/with_a_server_rejected_refresh_token_authenticates_again_test.dart b/sdk/lib/_internal/pub/test/oauth2/with_a_server_rejected_refresh_token_authenticates_again_test.dart
index 154388b..1a103e9 100644
--- a/sdk/lib/_internal/pub/test/oauth2/with_a_server_rejected_refresh_token_authenticates_again_test.dart
+++ b/sdk/lib/_internal/pub/test/oauth2/with_a_server_rejected_refresh_token_authenticates_again_test.dart
@@ -28,6 +28,7 @@
         .create();
 
     var pub = startPublish(server);
+
     confirmPublish(pub);
 
     server.handle('POST', '/token', (request) {
@@ -41,6 +42,7 @@
       });
     });
 
+    expect(pub.nextLine(), completion(matches(r'Uploading\.\.\.+')));
     authorizePub(pub, server, 'new access token');
 
     server.handle('GET', '/packages/versions/new.json', (request) {
diff --git a/sdk/lib/_internal/pub/test/pub_install_and_update_test.dart b/sdk/lib/_internal/pub/test/pub_install_and_update_test.dart
index 1cbd5a3..d645071 100644
--- a/sdk/lib/_internal/pub/test/pub_install_and_update_test.dart
+++ b/sdk/lib/_internal/pub/test/pub_install_and_update_test.dart
@@ -20,7 +20,8 @@
         d.dir(appPath, []).create();
 
         pubCommand(command,
-            error: new RegExp(r'^Could not find a file named "pubspec.yaml"'));
+            error: new RegExp(r'^Could not find a file named "pubspec.yaml" '
+                r'in the directory .*\.$'));
       });
 
       integration('a pubspec with a "name" key', () {
@@ -28,9 +29,9 @@
           d.pubspec({"dependencies": {"foo": null}})
         ]).create();
 
-        pubCommand(command, error: new RegExp(
-            r'^pubspec.yaml is missing the required "name" field '
-            r'\(e\.g\. "name: myapp"\)\.'));
+        pubCommand(command, error:
+            'pubspec.yaml is missing the required "name" field '
+            '(e.g. "name: myapp").');
       });
     });
 
@@ -112,7 +113,7 @@
       ]).create();
 
       pubCommand(command,
-          error: new RegExp(r"^Incompatible dependencies on 'baz':"));
+          error: new RegExp("^Incompatible dependencies on 'baz':\n"));
     });
   });
 }
diff --git a/sdk/lib/_internal/pub/test/test_pub.dart b/sdk/lib/_internal/pub/test/test_pub.dart
index 50f6343..1a784e7 100644
--- a/sdk/lib/_internal/pub/test/test_pub.dart
+++ b/sdk/lib/_internal/pub/test/test_pub.dart
@@ -13,7 +13,6 @@
 import 'dart:io' hide sleep;
 import 'dart:json' as json;
 import 'dart:math';
-import 'dart:uri';
 import 'dart:utf';
 
 import 'package:http/testing.dart';
@@ -238,15 +237,13 @@
 /// Enum identifying a pub command that can be run with a well-defined success
 /// output.
 class RunCommand {
-  static final install = new RunCommand('install',
-      new RegExp("Dependencies installed!\$"));
-
-  static final update = new RunCommand('update',
-      new RegExp("Dependencies updated!\$"));
+  static final install = new RunCommand('install', 'installed');
+  static final update = new RunCommand('update', 'updated');
 
   final String name;
   final RegExp success;
-  RunCommand(this.name, this.success);
+  RunCommand(this.name, String verb)
+      : success = new RegExp("Dependencies $verb!\$");
 }
 
 /// Many tests validate behavior that is the same between pub install and
diff --git a/sdk/lib/_internal/pub/test/unknown_source_test.dart b/sdk/lib/_internal/pub/test/unknown_source_test.dart
index 6b0cde0..511b795 100644
--- a/sdk/lib/_internal/pub/test/unknown_source_test.dart
+++ b/sdk/lib/_internal/pub/test/unknown_source_test.dart
@@ -17,8 +17,8 @@
     integration('fails gracefully on a dependency from an unknown source', () {
       d.appDir([{"bad": "foo"}]).create();
 
-      pubCommand(command, error: new RegExp(
-          "Package 'myapp' depends on 'foo' from unknown source 'bad'.\$"));
+      pubCommand(command, error:
+          "Package 'myapp' depends on 'foo' from unknown source 'bad'.");
     });
 
     integration('fails gracefully on transitive dependency from an unknown '
@@ -30,8 +30,8 @@
 
       d.appDir([{"path": "../foo"}]).create();
 
-      pubCommand(command, error: new RegExp(
-          "Package 'foo' depends on 'bar' from unknown source 'bad'.\$"));
+      pubCommand(command, error:
+          "Package 'foo' depends on 'bar' from unknown source 'bad'.");
     });
 
     integration('ignores unknown source in lockfile', () {
diff --git a/sdk/lib/_internal/pub/test/update/git/do_not_update_if_unneeded_test.dart b/sdk/lib/_internal/pub/test/update/git/do_not_update_if_unneeded_test.dart
index 512b619..d48899a 100644
--- a/sdk/lib/_internal/pub/test/update/git/do_not_update_if_unneeded_test.dart
+++ b/sdk/lib/_internal/pub/test/update/git/do_not_update_if_unneeded_test.dart
@@ -27,8 +27,7 @@
 
     d.appDir([{"git": "../foo.git"}]).create();
 
-    schedulePub(args: ['install'],
-        output: new RegExp(r"Dependencies installed!$"));
+    pubInstall();
 
     d.dir(packagesPath, [
       d.dir('foo', [
@@ -49,8 +48,7 @@
       d.libPubspec('foo-dep', '1.0.0')
     ]).commit();
 
-    schedulePub(args: ['update', 'foo'],
-        output: new RegExp(r"Dependencies updated!$"));
+    pubUpdate(args: ['foo']);
 
     d.dir(packagesPath, [
       d.dir('foo', [
diff --git a/sdk/lib/_internal/pub/test/update/git/update_locked_test.dart b/sdk/lib/_internal/pub/test/update/git/update_locked_test.dart
index 3ed68c5..c17f641 100644
--- a/sdk/lib/_internal/pub/test/update/git/update_locked_test.dart
+++ b/sdk/lib/_internal/pub/test/update/git/update_locked_test.dart
@@ -26,8 +26,7 @@
 
     d.appDir([{"git": "../foo.git"}, {"git": "../bar.git"}]).create();
 
-    schedulePub(args: ['install'],
-        output: new RegExp(r"Dependencies installed!$"));
+    pubInstall();
 
     d.dir(packagesPath, [
       d.dir('foo', [
@@ -48,8 +47,7 @@
       d.libPubspec('bar', '1.0.0')
     ]).commit();
 
-    schedulePub(args: ['update'],
-        output: new RegExp(r"Dependencies updated!$"));
+    pubUpdate();
 
     d.dir(packagesPath, [
       d.dir('foo', [
diff --git a/sdk/lib/_internal/pub/test/update/git/update_one_locked_test.dart b/sdk/lib/_internal/pub/test/update/git/update_one_locked_test.dart
index 976553e..35370e7 100644
--- a/sdk/lib/_internal/pub/test/update/git/update_one_locked_test.dart
+++ b/sdk/lib/_internal/pub/test/update/git/update_one_locked_test.dart
@@ -26,8 +26,7 @@
 
     d.appDir([{"git": "../foo.git"}, {"git": "../bar.git"}]).create();
 
-    schedulePub(args: ['install'],
-        output: new RegExp(r"Dependencies installed!$"));
+    pubInstall();
 
     d.dir(packagesPath, [
       d.dir('foo', [
@@ -48,8 +47,7 @@
       d.libPubspec('bar', '1.0.0')
     ]).commit();
 
-    schedulePub(args: ['update', 'foo'],
-        output: new RegExp(r"Dependencies updated!$"));
+    pubUpdate(args: ['foo']);
 
     d.dir(packagesPath, [
       d.dir('foo', [
diff --git a/sdk/lib/_internal/pub/test/update/git/update_to_incompatible_pubspec_test.dart b/sdk/lib/_internal/pub/test/update/git/update_to_incompatible_pubspec_test.dart
index 09123f4..348d6db 100644
--- a/sdk/lib/_internal/pub/test/update/git/update_to_incompatible_pubspec_test.dart
+++ b/sdk/lib/_internal/pub/test/update/git/update_to_incompatible_pubspec_test.dart
@@ -21,8 +21,7 @@
 
     d.appDir([{"git": "../foo.git"}]).create();
 
-    schedulePub(args: ['install'],
-        output: new RegExp(r"Dependencies installed!$"));
+    pubInstall();
 
     d.dir(packagesPath, [
       d.dir('foo', [
@@ -35,10 +34,8 @@
       d.libPubspec('zoo', '1.0.0')
     ]).commit();
 
-    schedulePub(args: ['update'],
-        error: new RegExp(r'The name you specified for your dependency, '
-            r'"foo", doesn' "'" r't match the name "zoo" in its pubspec.'),
-        exitCode: 1);
+    pubUpdate(error: 'The name you specified for your dependency, '
+                     '"foo", doesn\'t match the name "zoo" in its pubspec.');
 
     d.dir(packagesPath, [
       d.dir('foo', [
diff --git a/sdk/lib/_internal/pub/test/update/git/update_to_nonexistent_pubspec_test.dart b/sdk/lib/_internal/pub/test/update/git/update_to_nonexistent_pubspec_test.dart
index 9e2e995..f746ee6 100644
--- a/sdk/lib/_internal/pub/test/update/git/update_to_nonexistent_pubspec_test.dart
+++ b/sdk/lib/_internal/pub/test/update/git/update_to_nonexistent_pubspec_test.dart
@@ -22,8 +22,7 @@
 
     d.appDir([{"git": "../foo.git"}]).create();
 
-    schedulePub(args: ['install'],
-        output: new RegExp(r"Dependencies installed!$"));
+    pubInstall();
 
     d.dir(packagesPath, [
       d.dir('foo', [
@@ -34,10 +33,7 @@
     repo.runGit(['rm', 'pubspec.yaml']);
     repo.runGit(['commit', '-m', 'delete']);
 
-    schedulePub(args: ['update'],
-        error: new RegExp(r'Package "foo" doesn' "'" r't have a '
-            r'pubspec.yaml file.'),
-        exitCode: 1);
+    pubUpdate(error: 'Package "foo" doesn\'t have a pubspec.yaml file.');
 
     d.dir(packagesPath, [
       d.dir('foo', [
diff --git a/sdk/lib/_internal/pub/test/update/hosted/unlock_dependers_test.dart b/sdk/lib/_internal/pub/test/update/hosted/unlock_dependers_test.dart
index f1b8e4d..b007e00 100644
--- a/sdk/lib/_internal/pub/test/update/hosted/unlock_dependers_test.dart
+++ b/sdk/lib/_internal/pub/test/update/hosted/unlock_dependers_test.dart
@@ -20,8 +20,7 @@
 
     d.appDir([dependencyMap("foo"), dependencyMap("bar")]).create();
 
-    schedulePub(args: ['install'],
-        output: new RegExp(r"Dependencies installed!$"));
+    pubInstall();
 
     d.packagesDir({
       "foo": "1.0.0",
@@ -33,8 +32,7 @@
       packageMap("bar", "2.0.0")
     ]);
 
-    schedulePub(args: ['update', 'bar'],
-        output: new RegExp(r"Dependencies updated!$"));
+    pubUpdate(args: ['bar']);
 
     d.packagesDir({
       "foo": "2.0.0",
diff --git a/sdk/lib/_internal/pub/test/update/hosted/unlock_if_necessary_test.dart b/sdk/lib/_internal/pub/test/update/hosted/unlock_if_necessary_test.dart
index 3115942..3f24c78 100644
--- a/sdk/lib/_internal/pub/test/update/hosted/unlock_if_necessary_test.dart
+++ b/sdk/lib/_internal/pub/test/update/hosted/unlock_if_necessary_test.dart
@@ -20,8 +20,7 @@
 
     d.appDir([dependencyMap("foo")]).create();
 
-    schedulePub(args: ['install'],
-        output: new RegExp(r"Dependencies installed!$"));
+    pubInstall();
 
     d.packagesDir({
       "foo": "1.0.0",
@@ -33,8 +32,7 @@
       packageMap("foo-dep", "2.0.0")
     ]);
 
-    schedulePub(args: ['update', 'foo'],
-        output: new RegExp(r"Dependencies updated!$"));
+    pubUpdate(args: ['foo']);
 
     d.packagesDir({
       "foo": "2.0.0",
diff --git a/sdk/lib/_internal/pub/test/update/hosted/update_removed_constraints_test.dart b/sdk/lib/_internal/pub/test/update/hosted/update_removed_constraints_test.dart
index dc20323..3ff3efc 100644
--- a/sdk/lib/_internal/pub/test/update/hosted/update_removed_constraints_test.dart
+++ b/sdk/lib/_internal/pub/test/update/hosted/update_removed_constraints_test.dart
@@ -21,8 +21,7 @@
 
     d.appDir([dependencyMap("foo"), dependencyMap("bar")]).create();
 
-    schedulePub(args: ['update'],
-        output: new RegExp(r"Dependencies updated!$"));
+    pubUpdate();
 
     d.packagesDir({
       "foo": "1.0.0",
@@ -32,8 +31,7 @@
 
     d.appDir([dependencyMap("foo")]).create();
 
-    schedulePub(args: ['update'],
-        output: new RegExp(r"Dependencies updated!$"));
+    pubUpdate();
 
     d.packagesDir({
       "foo": "1.0.0",
diff --git a/sdk/lib/_internal/pub/test/utils_test.dart b/sdk/lib/_internal/pub/test/utils_test.dart
index c1c29a8..a137d2d 100644
--- a/sdk/lib/_internal/pub/test/utils_test.dart
+++ b/sdk/lib/_internal/pub/test/utils_test.dart
@@ -80,5 +80,12 @@
 null: null
 true: bool"""));
     });
+
+    test('handles empty maps', () {
+      expect(yamlToString({}), equals("{}"));
+      expect(yamlToString({'a': {}, 'b': {}}), equals("""
+a: {}
+b: {}"""));
+    });
   });
 }
diff --git a/sdk/lib/async/async.dart b/sdk/lib/async/async.dart
index 7d22e8b..b028d80 100644
--- a/sdk/lib/async/async.dart
+++ b/sdk/lib/async/async.dart
@@ -4,6 +4,8 @@
 
 library dart.async;
 
+import "dart:collection";
+
 part 'async_error.dart';
 part 'deferred_load.dart';
 part 'event_loop.dart';
diff --git a/sdk/lib/async/event_loop.dart b/sdk/lib/async/event_loop.dart
index 3ceccd2..2802e40 100644
--- a/sdk/lib/async/event_loop.dart
+++ b/sdk/lib/async/event_loop.dart
@@ -7,31 +7,18 @@
 typedef void _AsyncCallback();
 
 bool _callbacksAreEnqueued = false;
-List<_AsyncCallback> _asyncCallbacks = <_AsyncCallback>[];
+Queue<_AsyncCallback> _asyncCallbacks = new Queue<_AsyncCallback>();
 
 void _asyncRunCallback() {
   // As long as we are iterating over the registered callbacks we don't
   // unset the [_callbacksAreEnqueued] boolean.
   while (!_asyncCallbacks.isEmpty) {
-    List callbacks = _asyncCallbacks;
-    // The callbacks we execute can register new callbacks. This means that
-    // the for-loop below could grow the list if we don't replace it here.
-    _asyncCallbacks = <_AsyncCallback>[];
-    for (int i = 0; i < callbacks.length; i++) {
-      Function callback = callbacks[i];
-      callbacks[i] = null;
-      try {
-        callback();
-      } catch (e) {
-        i++;  // Skip current callback.
-        List remainingCallbacks = callbacks.sublist(i);
-        List newCallbacks = _asyncCallbacks;
-        _asyncCallbacks = <_AsyncCallback>[];
-        _asyncCallbacks.addAll(remainingCallbacks);
-        _asyncCallbacks.addAll(newCallbacks);
-        _AsyncRun._enqueueImmediate(_asyncRunCallback);
-        throw;
-      }
+    Function callback = _asyncCallbacks.removeFirst();
+    try {
+      callback();
+    } catch (e) {
+      _AsyncRun._enqueueImmediate(_asyncRunCallback);
+      throw;
     }
   }
   // Any new callback must register a callback function now.
diff --git a/sdk/lib/async/stream.dart b/sdk/lib/async/stream.dart
index dbe3374..07378b5 100644
--- a/sdk/lib/async/stream.dart
+++ b/sdk/lib/async/stream.dart
@@ -62,24 +62,24 @@
    * data or error, and then close with a done-event.
    */
   factory Stream.fromFuture(Future<T> future) {
-    _StreamImpl<T> stream = new _SingleStreamImpl<T>();
+    StreamController<T> controller = new StreamController<T>();
     future.then((value) {
-        stream._add(value);
-        stream._close();
+        controller.add(value);
+        controller.close();
       },
       onError: (error) {
-        stream._addError(error);
-        stream._close();
+        controller.addError(error);
+        controller.close();
       });
-    return stream;
+    return controller.stream;
   }
 
   /**
    * Creates a single-subscription stream that gets its data from [data].
    */
   factory Stream.fromIterable(Iterable<T> data) {
-    _PendingEvents iterableEvents = new _IterablePendingEvents<T>(data);
-    return new _GeneratedSingleStreamImpl<T>(iterableEvents);
+    return new _GeneratedStreamImpl<T>(
+        () => new _IterablePendingEvents<T>(data));
   }
 
   /**
@@ -152,13 +152,13 @@
    * If this stream is single-subscription, return a new stream that allows
    * multiple subscribers. It will subscribe to this stream when its first
    * subscriber is added, and unsubscribe again when the last subscription is
-   * cancelled.
+   * canceled.
    *
    * If this stream is already a broadcast stream, it is returned unmodified.
    */
   Stream<T> asBroadcastStream() {
     if (isBroadcast) return this;
-    return new _SingleStreamMultiplexer<T>(this);
+    return new _AsBroadcastStream<T>(this);
   }
 
   /**
@@ -1049,22 +1049,7 @@
   const StreamEventTransformer();
 
   Stream<T> bind(Stream<S> source) {
-    // Hackish way of buffering data that goes out of the event-transformer.
-    // TODO(floitsch): replace this with a correct solution.
-    Stream transformingStream = new EventTransformStream<S, T>(source, this);
-    StreamController controller;
-    StreamSubscription subscription;
-    controller = new StreamController<T>(
-        onListen: () {
-          subscription = transformingStream.listen(
-              controller.add,
-              onError: controller.addError,
-              onDone: controller.close);
-        },
-        onPause: () => subscription.pause(),
-        onResume: () => subscription.resume(),
-        onCancel: () => subscription.cancel());
-    return controller.stream;
+    return new EventTransformStream<S, T>(source, this);
   }
 
   /**
@@ -1119,6 +1104,9 @@
                                { void onError(error),
                                  void onDone(),
                                  bool cancelOnError }) {
+    if (onData == null) onData = _nullDataHandler;
+    if (onError == null) onError = _nullErrorHandler;
+    if (onDone == null) onDone = _nullDoneHandler;
     cancelOnError = identical(true, cancelOnError);
     return new _EventTransformStreamSubscription(_source, _transformer,
                                                  onData, onError, onDone,
@@ -1127,16 +1115,16 @@
 }
 
 class _EventTransformStreamSubscription<S, T>
-    extends _BaseStreamSubscription<T>
-    implements _EventOutputSink<T> {
+    extends _BufferingStreamSubscription<T> {
   /** The transformer used to transform events. */
   final StreamEventTransformer<S, T> _transformer;
-  /** Whether to unsubscribe when emitting an error. */
-  final bool _cancelOnError;
+
   /** Whether this stream has sent a done event. */
   bool _isClosed = false;
+
   /** Source of incoming events. */
   StreamSubscription<S> _subscription;
+
   /** Cached EventSink wrapper for this class. */
   EventSink<T> _sink;
 
@@ -1145,9 +1133,9 @@
                                     void onData(T data),
                                     void onError(error),
                                     void onDone(),
-                                    this._cancelOnError)
-      : super(onData, onError, onDone) {
-    _sink = new _EventOutputSinkWrapper<T>(this);
+                                    bool cancelOnError)
+      : super(onData, onError, onDone, cancelOnError) {
+    _sink = new _EventSinkAdapter<T>(this);
     _subscription = source.listen(_handleData,
                                   onError: _handleError,
                                   onDone: _handleDone);
@@ -1156,17 +1144,15 @@
   /** Whether this subscription is still subscribed to its source. */
   bool get _isSubscribed => _subscription != null;
 
-  void pause([Future pauseSignal]) {
-    if (_isSubscribed) _subscription.pause(pauseSignal);
+  void _onPause() {
+    if (_isSubscribed) _subscription.pause();
   }
 
-  void resume() {
+  void _onResume() {
     if (_isSubscribed) _subscription.resume();
   }
 
-  bool get isPaused => _isSubscribed ? _subscription.isPaused : false;
-
-  void cancel() {
+  void _onCancel() {
     if (_isSubscribed) {
       StreamSubscription subscription = _subscription;
       _subscription = null;
@@ -1179,7 +1165,7 @@
     try {
       _transformer.handleData(data, _sink);
     } catch (e, s) {
-      _sendError(_asyncError(e, s));
+      _addError(_asyncError(e, s));
     }
   }
 
@@ -1187,7 +1173,7 @@
     try {
       _transformer.handleError(error, _sink);
     } catch (e, s) {
-      _sendError(_asyncError(e, s));
+      _addError(_asyncError(e, s));
     }
   }
 
@@ -1196,40 +1182,69 @@
       _subscription = null;
       _transformer.handleDone(_sink);
     } catch (e, s) {
-      _sendError(_asyncError(e, s));
+      _addError(_asyncError(e, s));
     }
   }
-
-  // EventOutputSink interface.
-  void _sendData(T data) {
-    if (_isClosed) return;
-    _onData(data);
-  }
-
-  void _sendError(error) {
-    if (_isClosed) return;
-    _onError(error);
-    if (_cancelOnError) {
-      cancel();
-    }
-  }
-
-  void _sendDone() {
-    if (_isClosed) throw new StateError("Already closed.");
-    _isClosed = true;
-    if (_isSubscribed) {
-      _subscription.cancel();
-      _subscription = null;
-    }
-    _onDone();
-  }
 }
 
-class _EventOutputSinkWrapper<T> extends EventSink<T> {
-  _EventOutputSink _sink;
-  _EventOutputSinkWrapper(this._sink);
+class _EventSinkAdapter<T> implements EventSink<T> {
+  _EventSink _sink;
+  _EventSinkAdapter(this._sink);
 
-  void add(T data) { _sink._sendData(data); }
-  void addError(error) { _sink._sendError(error); }
-  void close() { _sink._sendDone(); }
+  void add(T data) { _sink._add(data); }
+  void addError(error) { _sink._addError(error); }
+  void close() { _sink._close(); }
+}
+
+
+/**
+ * An [Iterable] like interface for the values of a [Stream].
+ *
+ * This wraps a [Stream] and a subscription on the stream. It listens
+ * on the stream, and completes the future returned by [moveNext] when the
+ * next value becomes available.
+ *
+ * NOTICE: This is a tentative design. This class may change.
+ */
+abstract class StreamIterator<T> {
+
+  /** Create a [StreamIterator] on [stream]. */
+  factory StreamIterator(Stream<T> stream)
+      // TODO(lrn): use redirecting factory constructor when type
+      // arguments are supported.
+      => new _StreamIteratorImpl<T>(stream);
+
+  /**
+   * Wait for the next stream value to be available.
+   *
+   * It is not allowed to call this function again until the future has
+   * completed. If the returned future completes with anything except `true`,
+   * the iterator is done, and no new value will ever be available.
+   *
+   * The future may complete with an error, if the stream produces an error.
+   */
+  Future<bool> moveNext();
+
+  /**
+   * The current value of the stream.
+   *
+   * Only valid when the future returned by [moveNext] completes with `true`
+   * as value, and only until the next call to [moveNext].
+   */
+  T get current;
+
+  /**
+   * Cancels the stream iterator (and the underlying stream subscription) early.
+   *
+   * The stream iterator is automatically canceled if the [moveNext] future
+   * completes with either `false` or an error.
+   *
+   * If a [moveNext] call has been made, it will complete with `false` as value,
+   * as will all further calls to [moveNext].
+   *
+   * If you need to stop listening for values before the stream iterator is
+   * automatically closed, you must call [cancel] to ensure that the stream
+   * is properly closed.
+   */
+  void cancel();
 }
diff --git a/sdk/lib/async/stream_controller.dart b/sdk/lib/async/stream_controller.dart
index 6ff3ee2..b057565 100644
--- a/sdk/lib/async/stream_controller.dart
+++ b/sdk/lib/async/stream_controller.dart
@@ -46,8 +46,9 @@
  * the stream at all, and won't trigger callbacks. From the controller's point
  * of view, the stream is completely inert when has completed.
  */
-class StreamController<T> extends EventSink<T> {
-  final _StreamImpl<T> stream;
+abstract class StreamController<T> implements EventSink<T> {
+  /** The stream that this controller is controlling. */
+  Stream<T> get stream;
 
   /**
    * A controller with a [stream] that supports only one single subscriber.
@@ -59,23 +60,46 @@
    * paused. [onResume] is called when the stream resumed.
    *
    * The [onListen] callback is called when the stream
-   * receives its listener. [onCancel] when the listener cancels
+   * receives its listener and [onCancel] when the listener ends
    * its subscription.
    *
    * If the stream is canceled before the controller needs new data the
    * [onResume] call might not be executed.
    */
-  StreamController({void onListen(),
-                    void onPause(),
-                    void onResume(),
-                    void onCancel()})
-      : stream = new _SingleControllerStream<T>(
-            onListen, onPause, onResume, onCancel);
+  factory StreamController({void onListen(),
+                            void onPause(),
+                            void onResume(),
+                            void onCancel()})
+      => new _StreamControllerImpl<T>(onListen, onPause, onResume, onCancel);
+
+  /**
+   * A controller where [stream] can be listened to more than once.
+   *
+   * The [Stream] returned by [stream] is a broadcast stream. It can be listened
+   * to more than once.
+   *
+   * The controller distributes any events to all currently subscribed
+   * listeners.
+   * It is not allowed to call [add], [addError], or [close] before a previous
+   * call 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.
+   *
+   * 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);
+  }
 
   /**
    * Returns a view of this object that only exposes the [EventSink] interface.
    */
-  EventSink<T> get sink => new _EventSinkView<T>(this);
+  EventSink<T> get sink;
 
   /**
    * Whether the stream is closed for adding more events.
@@ -83,71 +107,548 @@
    * If true, the "done" event might not have fired yet, but it has been
    * scheduled, and it is too late to add more events.
    */
-  bool get isClosed => stream._isClosed;
-
-  /** Whether one or more active subscribers have requested a pause. */
-  bool get isPaused => stream._isInputPaused;
-
-  /** Whether there are currently any subscribers on this [Stream]. */
-  bool get hasListener => stream._hasListener;
+  bool get isClosed;
 
   /**
-   * Send or queue a data event.
+   * Whether the subscription would need to buffer events.
+   *
+   * This is the case if the controller's stream has a listener and it is
+   * paused, or if it has not received a listener yet. In that case, the
+   * controller is considered paused as well.
+   *
+   * A broadcast stream controller is never considered paused. It always
+   * forwards its events to all uncanceled listeners, if any, and let them
+   * handle their own pausing.
    */
-  void add(T value) => stream._add(value);
+  bool get isPaused;
+
+  /** Whether there is a subscriber on the [Stream]. */
+  bool get hasListener;
 
   /**
    * Send or enqueue an error event.
    *
-   * If a subscription has requested to be unsubscribed on errors,
-   * it will be unsubscribed after receiving this event.
+   * Also allows an objection stack trace object, on top of what [EventSink]
+   * allows.
+   */
+  void addError(Object error, [Object stackTrace]);
+}
+
+
+abstract class _StreamControllerLifecycle<T> {
+  void _recordListen(StreamSubscription<T> subscription) {}
+  void _recordPause(StreamSubscription<T> subscription) {}
+  void _recordResume(StreamSubscription<T> subscription) {}
+  void _recordCancel(StreamSubscription<T> subscription) {}
+}
+
+/**
+ * Default implementation of [StreamController].
+ *
+ * Controls a stream that only supports a single controller.
+ */
+class _StreamControllerImpl<T> implements StreamController<T>,
+                                          _StreamControllerLifecycle<T> {
+  static const int _STATE_OPEN = 0;
+  static const int _STATE_CANCELLED = 1;
+  static const int _STATE_CLOSED = 2;
+
+  final _NotificationHandler _onListen;
+  final _NotificationHandler _onPause;
+  final _NotificationHandler _onResume;
+  final _NotificationHandler _onCancel;
+  _StreamImpl<T> _stream;
+
+  // An active subscription on the stream, or null if no subscripton is active.
+  _ControllerSubscription<T> _subscription;
+
+  // Whether we have sent a "done" event.
+  int _state = _STATE_OPEN;
+
+  // Events added to the stream before it has an active subscription.
+  _PendingEvents _pendingEvents = null;
+
+  _StreamControllerImpl(this._onListen,
+                        this._onPause,
+                        this._onResume,
+                        this._onCancel) {
+    _stream = new _ControllerStream<T>(this);
+  }
+
+  Stream<T> get stream => _stream;
+
+  /**
+   * Returns a view of this object that only exposes the [EventSink] interface.
+   */
+  EventSink<T> get sink => new _EventSinkView<T>(this);
+
+  /**
+   * Whether a listener has existed and been cancelled.
+   *
+   * After this, adding more events will be ignored.
+   */
+  bool get _isCancelled => (_state & _STATE_CANCELLED) != 0;
+
+  bool get isClosed => (_state & _STATE_CLOSED) != 0;
+
+  bool get isPaused => hasListener ? _subscription._isInputPaused
+                                   : !_isCancelled;
+
+  bool get hasListener => _subscription != null;
+
+  /**
+   * Send or queue a data event.
+   */
+  void add(T value) {
+    if (isClosed) throw new StateError("Adding event after close");
+    if (_subscription != null) {
+      _subscription._add(value);
+    } else if (!_isCancelled) {
+      _addPendingEvent(new _DelayedData<T>(value));
+    }
+  }
+
+  /**
+   * Send or enqueue an error event.
    */
   void addError(Object error, [Object stackTrace]) {
+    if (isClosed) throw new StateError("Adding event after close");
     if (stackTrace != null) {
       // Force stack trace overwrite. Even if the error already contained
       // a stack trace.
       _attachStackTrace(error, stackTrace);
     }
-    stream._addError(error);
+    if (_subscription != null) {
+      _subscription._addError(error);
+    } else if (!_isCancelled) {
+      _addPendingEvent(new _DelayedError(error));
+    }
   }
 
   /**
-   * Send or enqueue a "done" message.
+   * Closes this controller.
    *
-   * The "done" message should be sent at most once by a stream, and it
-   * should be the last message sent.
+   * After closing, no further events may be added using [add] or [addError].
+   *
+   * You are allowed to close the controller more than once, but only the first
+   * call has any effect.
+   *
+   * The first time a controller is closed, a "done" event is sent to its
+   * stream.
    */
-  void close() { stream._close(); }
+  void close() {
+    if (isClosed) return;
+    _state |= _STATE_CLOSED;
+    if (_subscription != null) {
+      _subscription._close();
+    } else if (!_isCancelled) {
+      _addPendingEvent(const _DelayedDone());
+    }
+  }
+
+  void _addPendingEvent(_DelayedEvent event) {
+    if (_isCancelled) return;
+    _StreamImplEvents events = _pendingEvents;
+    if (events == null) {
+      events = _pendingEvents = new _StreamImplEvents();
+    }
+    events.add(event);
+  }
+
+  void _recordListen(_BufferingStreamSubscription<T> subscription) {
+    assert(_subscription == null);
+    _subscription = subscription;
+    subscription._setPendingEvents(_pendingEvents);
+    _pendingEvents = null;
+    subscription._guardCallback(() {
+      _runGuarded(_onListen);
+    });
+  }
+
+  void _recordCancel(StreamSubscription<T> subscription) {
+    assert(identical(_subscription, subscription));
+    _subscription = null;
+    _state |= _STATE_CANCELLED;
+    _runGuarded(_onCancel);
+  }
+
+  void _recordPause(StreamSubscription<T> subscription) {
+    _runGuarded(_onPause);
+  }
+
+  void _recordResume(StreamSubscription<T> subscription) {
+    _runGuarded(_onResume);
+  }
 }
 
 typedef void _NotificationHandler();
 
-class _SingleControllerStream<T> extends _SingleStreamImpl<T> {
-  _NotificationHandler _onListen;
-  _NotificationHandler _onPause;
-  _NotificationHandler _onResume;
-  _NotificationHandler _onCancel;
+void _runGuarded(_NotificationHandler notificationHandler) {
+  if (notificationHandler == null) return;
+  try {
+    notificationHandler();
+  } catch (e, s) {
+    _throwDelayed(e, s);
+  }
+}
 
-  // TODO(floitsch): share this code with _MultiControllerStream.
-  _runGuarded(_NotificationHandler notificationHandler) {
-    if (notificationHandler == null) return;
-    try {
-      notificationHandler();
-    } catch (e, s) {
-      _throwDelayed(e, s);
+class _ControllerStream<T> extends _StreamImpl<T> {
+  _StreamControllerLifecycle<T> _controller;
+  bool _hasListener = false;
+
+  _ControllerStream(this._controller);
+
+  StreamSubscription<T> _createSubscription(
+      void onData(T data),
+      void onError(Object error),
+      void onDone(),
+      bool cancelOnError) {
+    if (_hasListener) {
+      throw new StateError("The stream has already been listened to.");
+    }
+    _hasListener = true;
+    return new _ControllerSubscription<T>(
+        _controller, onData, onError, onDone, cancelOnError);
+  }
+
+  void _onListen(_BufferingStreamSubscription subscription) {
+    _controller._recordListen(subscription);
+  }
+}
+
+class _ControllerSubscription<T> extends _BufferingStreamSubscription<T> {
+  final _StreamControllerLifecycle<T> _controller;
+
+  _ControllerSubscription(this._controller,
+                          void onData(T data),
+                          void onError(Object error),
+                          void onDone(),
+                          bool cancelOnError)
+      : super(onData, onError, onDone, cancelOnError);
+
+  void _onCancel() {
+    _controller._recordCancel(this);
+  }
+
+  void _onPause() {
+    _controller._recordPause(this);
+  }
+
+  void _onResume() {
+    _controller._recordResume(this);
+  }
+}
+
+class _MultiplexStream<T> extends _StreamImpl<T> {
+  _MultiplexStreamController _controller;
+
+  _MultiplexStream(this._controller);
+
+  bool get isBroadcast => true;
+
+  StreamSubscription<T> _createSubscription(
+      void onData(T data),
+      void onError(Object error),
+      void onDone(),
+      bool cancelOnError) {
+    return new _MultiplexSubscription<T>(
+        _controller, onData, onError, onDone, cancelOnError);
+  }
+
+  void _onListen(_BufferingStreamSubscription subscription) {
+    _controller._recordListen(subscription);
+  }
+}
+
+abstract class _MultiplexSubscriptionLink {
+  _MultiplexSubscriptionLink _next;
+  _MultiplexSubscriptionLink _previous;
+}
+
+class _MultiplexSubscription<T> extends _ControllerSubscription<T>
+                                implements _MultiplexSubscriptionLink {
+  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;
+
+  _MultiplexSubscription(_StreamControllerLifecycle controller,
+                         void onData(T data),
+                         void onError(Object error),
+                         void onDone(),
+                         bool cancelOnError)
+      : super(controller, onData, onError, onDone, cancelOnError) {
+    _next = _previous = this;
+  }
+
+  _MultiplexStreamController get _controller => super._controller;
+
+  bool _expectsEvent(int eventId) {
+    return (_eventState & _STATE_EVENT_ID) == eventId;
+  }
+
+  void _toggleEventId() {
+    _eventState ^= _STATE_EVENT_ID;
+  }
+
+  bool get _isFiring => (_eventState & _STATE_FIRING) != 0;
+
+  bool _setRemoveAfterFiring() {
+    assert(_isFiring);
+    _eventState |= _STATE_REMOVE_AFTER_FIRING;
+  }
+
+  bool get _removeAfterFiring =>
+      (_eventState & _STATE_REMOVE_AFTER_FIRING) != 0;
+}
+
+
+class _MultiplexStreamController<T> implements StreamController<T>,
+                                               _StreamControllerLifecycle<T>,
+                                               _MultiplexSubscriptionLink {
+  static const int _STATE_INITIAL = 0;
+  static const int _STATE_EVENT_ID = 1;
+  static const int _STATE_FIRING = 2;
+  static const int _STATE_CLOSED = 4;
+
+  final _NotificationHandler _onListen;
+  final _NotificationHandler _onCancel;
+
+  // State of the controller.
+  int _state;
+
+  // Double-linked list of active listeners.
+  _MultiplexSubscriptionLink _next;
+  _MultiplexSubscriptionLink _previous;
+
+  _MultiplexStreamController(this._onListen, this._onCancel)
+      : _state = _STATE_INITIAL {
+    _next = _previous = this;
+  }
+
+  // StreamController interface.
+
+  Stream<T> get stream => new _MultiplexStream<T>(this);
+
+  EventSink<T> get sink => new _EventSinkView<T>(this);
+
+  bool get isClosed => (_state & _STATE_CLOSED) != 0;
+
+  /**
+   * A multiplex controller is never paused.
+   *
+   * Each receiving stream may be paused individually, and they handle their
+   * own buffering.
+   */
+  bool get isPaused => false;
+
+  /** Whether there are currently a subscriber on the [Stream]. */
+  bool get hasListener => !_isEmpty;
+
+  /** Whether an event is being fired (sent to some, but not all, listeners). */
+  bool get _isFiring => (_state & _STATE_FIRING) != 0;
+
+  // Linked list helpers
+
+  bool get _isEmpty => identical(_next, this);
+
+  /** Adds subscription to linked list of active listeners. */
+  void _addListener(_MultiplexSubscription<T> subscription) {
+    _MultiplexSubscriptionLink previous = _previous;
+    previous._next = subscription;
+    _previous = subscription._previous;
+    subscription._previous._next = this;
+    subscription._previous = previous;
+    subscription._eventState = (_state & _STATE_EVENT_ID);
+  }
+
+  void _removeListener(_MultiplexSubscription<T> subscription) {
+    assert(identical(subscription._controller, this));
+    assert(!identical(subscription._next, subscription));
+    subscription._previous._next = subscription._next;
+    subscription._next._previous = subscription._previous;
+    subscription._next = subscription._previous = subscription;
+  }
+
+  // _StreamControllerLifecycle interface.
+
+  void _recordListen(_MultiplexSubscription<T> subscription) {
+    _addListener(subscription);
+    if (identical(_next, _previous)) {
+      // Only one listener, so it must be the first listener.
+      _runGuarded(_onListen);
     }
   }
 
-  _SingleControllerStream(this._onListen,
-                          this._onPause,
-                          this._onResume,
-                          this._onCancel);
-
-  void _onSubscriptionStateChange() {
-    _runGuarded(_hasListener ? _onListen : _onCancel);
+  void _recordCancel(_MultiplexSubscription<T> subscription) {
+    if (subscription._isFiring) {
+      subscription._setRemoveAfterFiring();
+    } else {
+      _removeListener(subscription);
+      // If we are currently firing an event, the empty-check is performed at
+      // the end of the listener loop instead of here.
+      if ((_state & _STATE_FIRING) == 0 && _isEmpty) {
+        _callOnCancel();
+      }
+    }
   }
 
-  void _onPauseStateChange() {
-    _runGuarded(_isPaused ? _onPause : _onResume);
+  void _recordPause(StreamSubscription<T> subscription) {}
+  void _recordResume(StreamSubscription<T> subscription) {}
+
+  // EventSink interface.
+
+  void add(T data) {
+    if (isClosed) {
+      throw new StateError("Cannot add new events after calling close()");
+    }
+    _sendData(data);
+  }
+
+  void addError(Object error, [Object stackTrace]) {
+    if (isClosed) {
+      throw new StateError("Cannot add new events after calling close()");
+    }
+    if (stackTrace != null) _attachStackTrace(error, stackTrace);
+    _sendError(error);
+  }
+
+  void close() {
+    if (isClosed) {
+      throw new StateError("Cannot add new events after calling close()");
+    }
+    _state |= _STATE_CLOSED;
+    _sendDone();
+  }
+
+  // EventDispatch interface.
+
+  void _sendData(T data) {
+    if (_isEmpty) return;
+    _forEachListener((_BufferingStreamSubscription<T> subscription) {
+      subscription._add(data);
+    });
+  }
+
+  void _sendError(Object error) {
+    if (_isEmpty) return;
+    _forEachListener((_BufferingStreamSubscription<T> subscription) {
+      subscription._addError(error);
+    });
+  }
+
+  void _sendDone() {
+    if (_isEmpty) return;
+    _forEachListener((_MultiplexSubscription<T> subscription) {
+      subscription._close();
+      subscription._eventState |=
+          _MultiplexSubscription._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>
+    implements _EventDispatch<T> {
+  _StreamImplEvents _pending;
+
+  _BufferingMultiplexStreamController(void onListen(), void onCancel())
+      : super(onListen, onCancel);
+
+  bool get _hasPending => _pending != null && ! _pending.isEmpty;
+
+  void _addPendingEvent(_DelayedEvent event) {
+    if (_pending == null) {
+      _pending = new _StreamImplEvents();
+    }
+    _pending.add(event);
+  }
+
+  void add(T data) {
+    if (_isFiring) {
+      _addPendingEvent(new _DelayedData<T>(data));
+      return;
+    }
+    super.add(data);
+    while (_hasPending) {
+      _pending.handleNext(this);
+    }
+  }
+
+  void addError(Object error, [StackTrace stackTrace]) {
+    if (_isFiring) {
+      _addPendingEvent(new _DelayedError(error));
+      return;
+    }
+    super.addError(error, stackTrace);
+    while (_hasPending) {
+      _pending.handleNext(this);
+    }
+  }
+
+  void close() {
+    if (_isFiring) {
+      _addPendingEvent(const _DelayedDone());
+      _state |= _STATE_CLOSED;
+      return;
+    }
+    super.close();
+    assert(!_hasPending);
+  }
+
+  void _callOnCancel() {
+    if (_hasPending) {
+      _pending.clear();
+      _pending = null;
+    }
+    super._callOnCancel();
+
   }
 }
diff --git a/sdk/lib/async/stream_impl.dart b/sdk/lib/async/stream_impl.dart
index 8fa1848..375844c 100644
--- a/sdk/lib/async/stream_impl.dart
+++ b/sdk/lib/async/stream_impl.dart
@@ -4,57 +4,6 @@
 
 part of dart.async;
 
-// States shared by single/multi stream implementations.
-
-// Completion state of the stream.
-/// Initial and default state where the stream can receive and send events.
-const int _STREAM_OPEN = 0;
-/// The stream has received a request to complete, but hasn't done so yet.
-/// No further events can be added to the stream.
-const int _STREAM_CLOSED = 1;
-/// The stream has completed and will no longer receive or send events.
-/// Also counts as closed. The stream must not be paused when it's completed.
-/// Always used in conjunction with [_STREAM_CLOSED].
-const int _STREAM_COMPLETE = 2;
-
-/// Bit that alternates between events, and listeners are updated to the
-/// current value when they are notified of the event.
-const int _STREAM_EVENT_ID = 4;
-const int _STREAM_EVENT_ID_SHIFT = 2;
-
-// The activity state of the stream: What is it currently doing.
-/// Bit set while firing and clear while not.
-const int _STREAM_FIRING = 8;
-/// Bit set while calling a pause-state or subscription-state change callback.
-const int _STREAM_CALLBACK = 16;
-
-// The pause state of the stream.
-/// Bit set when resuming with pending events. Cleared after all pending events
-/// have been transmitted. Means that the controller still considers the
-/// stream paused, even if the listener doesn't.
-const int _STREAM_PENDING_RESUME = 32;
-/// The count of times a stream has paused is stored in the
-/// state, shifted by this amount.
-const int _STREAM_PAUSE_COUNT_SHIFT = 6;
-
-// States for listeners.
-
-/// The listener is currently not subscribed to its source stream.
-const int _LISTENER_UNSUBSCRIBED = 0;
-/// The listener is actively subscribed to its source stream.
-const int _LISTENER_SUBSCRIBED = 1;
-/// The listener is subscribed until it has been notified of the current event.
-/// This flag bit is always used in conjuction with [_LISTENER_SUBSCRIBED].
-const int _LISTENER_PENDING_UNSUBSCRIBE = 2;
-
-/// Bit that contains the last sent event's "id bit".
-const int _LISTENER_EVENT_ID = 4;
-const int _LISTENER_EVENT_ID_SHIFT = 2;
-
-/// The count of times a listener has paused is stored in the
-/// state, shifted by this amount.
-const int _LISTENER_PAUSE_COUNT_SHIFT = 3;
-
 /** Throws the given error in the next cycle. */
 _throwDelayed(var error, [Object stackTrace]) {
   // We are going to reach the top-level here, but there might be a global
@@ -69,857 +18,135 @@
   });
 }
 
-
-// -------------------------------------------------------------------
-// Common base class for single and multi-subscription streams.
-// -------------------------------------------------------------------
-abstract class _StreamImpl<T> extends Stream<T> {
-  /** Current state of the stream. */
-  int _state = _STREAM_OPEN;
-
-  /**
-   * List of pending events.
-   *
-   * If events are added to the stream (using [_add], [_addError] or [_done])
-   * while the stream is paused, or while another event is firing, events will
-   * stored here.
-   * Also supports scheduling the events for later execution.
-   */
-  _PendingEvents _pendingEvents;
-
-  // ------------------------------------------------------------------
-  // Stream interface.
-
-  StreamSubscription<T> listen(void onData(T data),
-                               { void onError(error),
-                                 void onDone(),
-                                 bool cancelOnError }) {
-    if (_isComplete) {
-      return new _DoneSubscription(onDone);
-    }
-    if (onData == null) onData = _nullDataHandler;
-    if (onError == null) onError = _nullErrorHandler;
-    if (onDone == null) onDone = _nullDoneHandler;
-    cancelOnError = identical(true, cancelOnError);
-    _StreamSubscriptionImpl subscription =
-        _createSubscription(onData, onError, onDone, cancelOnError);
-    _addListener(subscription);
-    return subscription;
-  }
-
-  // ------------------------------------------------------------------
-  // EventSink interface-like methods for sending events into the stream.
-  // It's the responsibility of the caller to ensure that the stream is not
-  // paused when adding events. If the stream is paused, the events will be
-  // queued, but it's better to not send events at all.
-
-  /**
-   * Send or queue a data event.
-   */
-  void _add(T value) {
-    if (_isClosed) throw new StateError("Sending on closed stream");
-    if (!_mayFireState) {
-      // Not the time to send events.
-      _addPendingEvent(new _DelayedData<T>(value));
-      return;
-    }
-    if (_hasPendingEvent) {
-      _addPendingEvent(new _DelayedData<T>(value));
-    } else {
-      _sendData(value);
-    }
-    _handlePendingEvents();
-  }
-
-  /**
-   * Send or enqueue an error event.
-   *
-   * If a subscription has requested to be unsubscribed on errors,
-   * it will be unsubscribed after receiving this event.
-   */
-  void _addError(error) {
-    if (_isClosed) throw new StateError("Sending on closed stream");
-    if (!_mayFireState) {
-      // Not the time to send events.
-      _addPendingEvent(new _DelayedError(error));
-      return;
-    }
-    if (_hasPendingEvent) {
-      _addPendingEvent(new _DelayedError(error));
-    } else {
-      _sendError(error);
-    }
-    _handlePendingEvents();
-  }
-
-  /**
-   * Send or enqueue a "done" message.
-   *
-   * The "done" message should be sent at most once by a stream, and it
-   * should be the last message sent.
-   */
-  void _close() {
-    if (_isClosed) return;
-    _state |= _STREAM_CLOSED;
-    if (!_mayFireState) {
-      // Not the time to send events.
-      _addPendingEvent(const _DelayedDone());
-      return;
-    }
-    if (_hasPendingEvent) {
-      _addPendingEvent(new _DelayedDone());
-      _handlePendingEvents();
-    } else {
-      _sendDone();
-      assert(_isComplete);
-      assert(!_hasPendingEvent);
-    }
-  }
-
-  // -------------------------------------------------------------------
-  // Internal implementation.
-
-  // State predicates.
-
-  // Lifecycle state.
-  /** Whether the stream is in the default, open, state for events. */
-  bool get _isOpen => (_state & (_STREAM_CLOSED | _STREAM_COMPLETE)) == 0;
-
-  /** Whether the stream has been closed (a done event requested). */
-  bool get _isClosed => (_state & _STREAM_CLOSED) != 0;
-
-  /** Whether the stream is completed. */
-  bool get _isComplete => (_state & _STREAM_COMPLETE) != 0;
-
-  // Pause state.
-
-  /** Whether one or more active subscribers have requested a pause. */
-  bool get _isPaused => _state >= (1 << _STREAM_PAUSE_COUNT_SHIFT);
-
-  /** How many times the stream has been paused. */
-  int get _pauseCount => _state >> _STREAM_PAUSE_COUNT_SHIFT;
-
-  /**
-   * Whether a controller thinks the stream is paused.
-   *
-   * When this changes, a pause-state change callback is performed.
-   *
-   * It may differ from [_isPaused] if there are pending events
-   * in the queue when the listeners resume. The controller won't
-   * be informed until all queued events have been fired.
-   */
-  bool get _isInputPaused => _state >= (_STREAM_PENDING_RESUME);
-
-  /** Whether we have a pending resume scheduled. */
-  bool get _hasPendingResume => (_state & _STREAM_PENDING_RESUME) != 0;
-
-
-  // Action state. If the stream makes a call-out to external code,
-  // this state tracks it and avoids reentrancy problems.
-
-  /** Whether the stream is not currently firing or calling a callback. */
-  bool get _isInactive => (_state & (_STREAM_CALLBACK | _STREAM_FIRING)) == 0;
-
-  /** Whether we are currently executing a state-chance callback. */
-  bool get _isInCallback => (_state & _STREAM_CALLBACK) != 0;
-
-  /** Whether we are currently firing an event. */
-  bool get _isFiring => (_state & _STREAM_FIRING) != 0;
-
-  /** Check whether the pending event queue is non-empty */
-  bool get _hasPendingEvent =>
-      _pendingEvents != null && !_pendingEvents.isEmpty;
-
-  /**
-   * The bit representing the current or last event fired.
-   *
-   * This bit matches a bit on listeners that have received the corresponding
-   * event. It is toggled for each new event being fired.
-   */
-  int get _currentEventIdBit =>
-      (_state & _STREAM_EVENT_ID ) >> _STREAM_EVENT_ID_SHIFT;
-
-  /** Whether there is currently a subscriber on this [Stream]. */
-  bool get _hasListener;
-
-
-  /** Whether the state bits allow firing. */
-  bool get _mayFireState {
-    // The state allows firing unless:
-    // - it's currently firing
-    // - it's currently in a callback
-    // - it's paused
-    const int mask =
-        _STREAM_FIRING |
-        _STREAM_CALLBACK |
-        ~((1 << _STREAM_PAUSE_COUNT_SHIFT) - 1);
-    return (_state & mask) == 0;
-  }
-
-  // State modification.
-
-  /** Record an increases in the number of times the listener has paused. */
-  void _incrementPauseCount(_StreamListener<T> listener) {
-    listener._incrementPauseCount();
-    _state &= ~_STREAM_PENDING_RESUME;
-    _updatePauseCount(1);
-  }
-
-  /** Record a decrease in the number of times the listener has paused. */
-  void _decrementPauseCount(_StreamListener<T> listener) {
-    assert(_isPaused);
-    listener._decrementPauseCount();
-    _updatePauseCount(-1);
-  }
-
-  /** Update the stream's own pause count only. */
-  void _updatePauseCount(int by) {
-    int oldState = _state;
-    // We can't just _state += by << _STREAM_PAUSE_COUNT_SHIFT, since dart2js
-    // converts the result of the left-shift to a positive number.
-    if (by >= 0) {
-      _state = oldState + (by << _STREAM_PAUSE_COUNT_SHIFT);
-    } else {
-      _state = oldState - ((-by) << _STREAM_PAUSE_COUNT_SHIFT);
-    }
-    assert(_state >= 0);
-    assert((_state >> _STREAM_PAUSE_COUNT_SHIFT) ==
-        (oldState >> _STREAM_PAUSE_COUNT_SHIFT) + by);
-  }
-
-  void _setClosed() {
-    assert(!_isClosed);
-    _state |= _STREAM_CLOSED;
-  }
-
-  void _setComplete() {
-    assert(_isClosed);
-    _state = _state |_STREAM_COMPLETE;
-  }
-
-  void _startFiring() {
-    assert(!_isFiring);
-    assert(!_isInCallback);
-    assert(_hasListener);
-    assert(!_isPaused);
-    // This sets the _STREAM_FIRING bit and toggles the _STREAM_EVENT_ID
-    // bit. All current subscribers will now have a _LISTENER_EVENT_ID
-    // that doesn't match _STREAM_EVENT_ID, and they will receive the
-    // event being fired.
-    _state ^= _STREAM_FIRING | _STREAM_EVENT_ID;
-  }
-
-  void _endFiring(bool wasInputPaused) {
-    assert(_isFiring);
-    _state ^= _STREAM_FIRING;
-    // Had listeners, or we wouldn't have fired.
-    _checkCallbacks(true, wasInputPaused);
-  }
-
-  /**
-   * Record that a listener wants a pause from events.
-   *
-   * This methods is called from [_StreamListener.pause()].
-   * Subclasses can override this method, along with [isPaused] and
-   * [createSubscription], if they want to do a different handling of paused
-   * subscriptions, e.g., a filtering stream pausing its own source if all its
-   * subscribers are paused.
-   */
-  void _pause(_StreamListener<T> listener, Future resumeSignal) {
-    assert(identical(listener._source, this));
-    if (!listener._isSubscribed) {
-      throw new StateError("Subscription has been canceled.");
-    }
-    assert(!_isComplete);  // There can be no subscribers when complete.
-    bool wasInputPaused = _isInputPaused;
-    bool wasPaused = _isPaused;
-    _incrementPauseCount(listener);
-    if (resumeSignal != null) {
-      resumeSignal.whenComplete(() { this._resume(listener, true); });
-    }
-    if (!wasPaused && _hasPendingEvent && _pendingEvents.isScheduled) {
-      _pendingEvents.cancelSchedule();
-    }
-    if (_isInactive && !wasInputPaused) {
-      _checkCallbacks(true, false);
-      if (!_isPaused && _hasPendingEvent) {
-        _schedulePendingEvents();
-      }
-    }
-  }
-
-  /** Stops pausing due to one request from the given listener. */
-  void _resume(_StreamListener<T> listener, bool fromEvent) {
-    if (!listener.isPaused) return;
-    assert(listener._isSubscribed);
-    assert(_isPaused);
-    _decrementPauseCount(listener);
-    if (!_isPaused) {
-      if (_hasPendingEvent) {
-        _state |= _STREAM_PENDING_RESUME;
-        // Controller's pause state hasn't changed.
-        // If we can fire events now, fire any pending events right away.
-        if (_isInactive) {
-          if (fromEvent) {
-            _handlePendingEvents();
-          } else {
-            _schedulePendingEvents();
-          }
-        }
-      } else if (_isInactive) {
-        _checkCallbacks(true, true);
-        if (!_isPaused && _hasPendingEvent) {
-          if (fromEvent) {
-            _handlePendingEvents();
-          } else {
-            _schedulePendingEvents();
-          }
-        }
-      }
-    }
-  }
-
-  /** Schedule pending events to be executed. */
-  void _schedulePendingEvents() {
-    assert(_hasPendingEvent);
-    _pendingEvents.schedule(this);
-  }
-
-  /** Create a subscription object. Called by [subcribe]. */
-  _StreamSubscriptionImpl<T> _createSubscription(
-      void onData(T data),
-      void onError(error),
-      void onDone(),
-      bool cancelOnError);
-
-  /**
-   * Adds a listener to this stream.
-   */
-  void _addListener(_StreamSubscriptionImpl subscription);
-
-  /**
-   * Handle a cancel requested from a [_StreamSubscriptionImpl].
-   *
-   * This method is called from [_StreamSubscriptionImpl.cancel].
-   *
-   * If an event is currently firing, the cancel is delayed
-   * until after the subscribers have received the event.
-   */
-  void _cancel(_StreamSubscriptionImpl subscriber);
-
-  /**
-   * Iterate over all current subscribers and perform an action on each.
-   *
-   * Subscribers added during the iteration will not be visited.
-   * Subscribers unsubscribed during the iteration will only be removed
-   * after they have been acted on.
-   *
-   * Any change in the pause state is only reported after all subscribers have
-   * received the event.
-   *
-   * The [action] must not throw, or the controller will be left in an
-   * invalid state.
-   *
-   * This method must not be called while [isFiring] is true.
-   */
-  void _forEachSubscriber(void action(_StreamSubscriptionImpl<T> subscription));
-
-  /**
-   * Checks whether the subscription/pause state has changed.
-   *
-   * Calls the appropriate callback if the state has changed from the
-   * provided one. Repeats calling callbacks as long as the call changes
-   * the state.
-   */
-  void _checkCallbacks(bool hadListener, bool wasPaused) {
-    assert(!_isFiring);
-    // Will be handled after the current callback.
-    if (_isInCallback) return;
-    if (_hasPendingResume && !_hasPendingEvent) {
-      _state ^= _STREAM_PENDING_RESUME;
-    }
-    _state |= _STREAM_CALLBACK;
-    while (true) {
-      bool hasListener = _hasListener;
-      bool isPaused = _isInputPaused;
-      if (hadListener != hasListener) {
-        _onSubscriptionStateChange();
-      } else if (isPaused != wasPaused) {
-        _onPauseStateChange();
-      } else {
-        _state ^= _STREAM_CALLBACK;
-        return;
-      }
-      wasPaused = isPaused;
-      hadListener = hasListener;
-    }
-  }
-
-  /**
-   * Called when the first subscriber requests a pause or the last a resume.
-   *
-   * Read [isPaused] to see the new state.
-   */
-  void _onPauseStateChange() {}
-
-  /**
-   * Called when the first listener subscribes or the last unsubscribes.
-   *
-   * Read [hasListener] to see what the new state is.
-   */
-  void _onSubscriptionStateChange() {}
-
-  /**
-   * Add a pending event at the end of the pending event queue.
-   *
-   * Schedules events if currently not paused and inside a callback.
-   */
-  void _addPendingEvent(_DelayedEvent event) {
-    if (_pendingEvents == null) _pendingEvents = new _StreamImplEvents();
-    _StreamImplEvents events = _pendingEvents;
-    events.add(event);
-    if (_isPaused || _isFiring) return;
-    if (_isInCallback) {
-      _schedulePendingEvents();
-      return;
-    }
-  }
-
-  /** Fire any pending events until the pending event queue is empty. */
-  void _handlePendingEvents() {
-    assert(_isInactive);
-    if (!_hasPendingEvent) return;
-    _PendingEvents events = _pendingEvents;
-    do {
-      if (_isPaused) return;
-      if (events.isScheduled) events.cancelSchedule();
-      events.handleNext(this);
-    } while (!events.isEmpty);
-  }
-
-  /**
-   * Send a data event directly to each subscriber.
-   */
-  _sendData(T value) {
-    assert(!_isPaused);
-    assert(!_isComplete);
-    if (!_hasListener) return;
-    _forEachSubscriber((subscriber) {
-      try {
-        subscriber._sendData(value);
-      } catch (e, s) {
-        _throwDelayed(e, s);
-      }
-    });
-  }
-
-  /**
-   * Sends an error event directly to each subscriber.
-   */
-  void _sendError(error) {
-    assert(!_isPaused);
-    assert(!_isComplete);
-    if (!_hasListener) return;
-    _forEachSubscriber((subscriber) {
-      try {
-        subscriber._sendError(error);
-      } catch (e, s) {
-        _throwDelayed(e, s);
-      }
-    });
-  }
-
-  /**
-   * Sends the "done" message directly to each subscriber.
-   * This automatically stops further subscription and
-   * unsubscribes all subscribers.
-   */
-  void _sendDone() {
-    assert(!_isPaused);
-    assert(_isClosed);
-    _setComplete();
-    if (!_hasListener) return;
-    _forEachSubscriber((subscriber) {
-      _cancel(subscriber);
-      try {
-        subscriber._sendDone();
-      } catch (e, s) {
-        _throwDelayed(e, s);
-      }
-    });
-    assert(!_hasListener);
-  }
+/** Abstract and private interface for a place to put events. */
+abstract class _EventSink<T> {
+  void _add(T data);
+  void _addError(Object error);
+  void _close();
 }
 
-// -------------------------------------------------------------------
-// Default implementation of a stream with a single subscriber.
-// -------------------------------------------------------------------
 /**
- * Default implementation of stream capable of sending events to one subscriber.
+ * Abstract and private interface for a place to send events.
  *
- * Any class needing to implement [Stream] can either directly extend this
- * class, or extend [Stream] and delegate the subscribe method to an instance
- * of this class.
+ * Used by event buffering to finally dispatch the pending event, where
+ * [_EventSink] is where the event first enters the stream subscription,
+ * and may yet be buffered.
+ */
+abstract class _EventDispatch<T> {
+  void _sendData(T data);
+  void _sendError(Object error);
+  void _sendDone();
+}
+
+/**
+ * Default implementation of stream subscription of buffering events.
  *
- * The only public methods are those of [Stream], so instances of
- * [_SingleStreamImpl] can be returned directly as a [Stream] without exposing
- * internal functionality.
+ * The only public methods are those of [StreamSubscription], so instances of
+ * [_BufferingStreamSubscription] can be returned directly as a
+ * [StreamSubscription] without exposing internal functionality.
  *
- * The [StreamController] is a public facing version of this class, with
- * some methods made public.
+ * The [StreamController] is a public facing version of [Stream] and this class,
+ * with some methods made public.
  *
- * The user interface of [_SingleStreamImpl] are the following methods:
+ * The user interface of [_BufferingStreamSubscription] are the following
+ * methods:
  * * [_add]: Add a data event to the stream.
  * * [_addError]: Add an error event to the stream.
  * * [_close]: Request to close the stream.
- * * [_onSubscriberStateChange]: Called when receiving the first subscriber or
- *                               when losing the last subscriber.
- * * [_onPauseStateChange]: Called when entering or leaving paused mode.
- * * [_hasListener]: Test whether there are currently any subscribers.
- * * [_isInputPaused]: Test whether the stream is currently paused.
- * The user should not add new events while the stream is paused, but if it
- * happens anyway, the stream will enqueue the events just as when new events
- * arrive while still firing an old event.
+ * * [_onCancel]: Called when the subscription will provide no more events,
+ *     either due to being actively canceled, or after sending a done event.
+ * * [_onPause]: Called when the subscription wants the event source to pause.
+ * * [_onResume]: Called when allowing new events after a pause.
+ * The user should not add new events when the subscription requests a paused,
+ * but if it happens anyway, the subscription will enqueue the events just as
+ * when new events arrive while still firing an old event.
  */
-class _SingleStreamImpl<T> extends _StreamImpl<T> {
-  _StreamListener _subscriber = null;
-
-  /** Whether there is currently a subscriber on this [Stream]. */
-  bool get _hasListener => _subscriber != null;
-
-  // -------------------------------------------------------------------
-  // Internal implementation.
-
-  _SingleStreamImpl() {
-    // Start out paused.
-    _updatePauseCount(1);
-  }
-
+class _BufferingStreamSubscription<T> implements StreamSubscription<T>,
+                                                 _EventSink<T>,
+                                                 _EventDispatch<T> {
+  /** The `cancelOnError` flag from the `listen` call. */
+  static const int _STATE_CANCEL_ON_ERROR = 1;
   /**
-   * Create the new subscription object.
+   * Whether the "done" event has been received.
+   * No further events are accepted after this.
    */
-  _StreamSubscriptionImpl<T> _createSubscription(
-      void onData(T data),
-      void onError(error),
-      void onDone(),
-      bool cancelOnError) {
-    return new _StreamSubscriptionImpl<T>(
-        this, onData, onError, onDone, cancelOnError);
-  }
-
-  void _addListener(_StreamListener subscription) {
-    assert(!_isComplete);
-    if (_hasListener) {
-      throw new StateError("Stream already has subscriber.");
-    }
-    assert(_pauseCount == 1);
-    _updatePauseCount(-1);
-    _subscriber = subscription;
-    subscription._setSubscribed(0);
-    if (_isInactive) {
-      _checkCallbacks(false, true);
-      if (!_isPaused && _hasPendingEvent) {
-        _schedulePendingEvents();
-      }
-    }
-  }
-
+  static const int _STATE_CLOSED = 2;
   /**
-   * Handle a cancel requested from a [_StreamSubscriptionImpl].
+   * Set if the input has been asked not to send events.
    *
-   * This method is called from [_StreamSubscriptionImpl.cancel].
+   * This is not the same as being paused, since the input will remain paused
+   * after a call to [resume] if there are pending events.
    */
-  void _cancel(_StreamListener subscriber) {
-    assert(identical(subscriber._source, this));
-    // We allow unsubscribing the currently firing subscription during
-    // the event firing, because it is indistinguishable from delaying it since
-    // that event has already received the event.
-    if (!identical(_subscriber, subscriber)) {
-      // You may unsubscribe more than once, only the first one counts.
-      return;
-    }
-    _subscriber = null;
-    // Unsubscribing a paused subscription also cancels its pauses.
-    int resumeCount = subscriber._setUnsubscribed();
-    // Keep being paused while there is no subscriber and the stream is not
-    // complete.
-    _updatePauseCount(_isComplete ? -resumeCount : -resumeCount + 1);
-    if (_isInactive) {
-      _checkCallbacks(true, resumeCount > 0);
-      if (!_isPaused && _hasPendingEvent) {
-        _schedulePendingEvents();
-      }
-    }
-  }
-
-  void _forEachSubscriber(
-      void action(_StreamListener<T> subscription)) {
-    assert(!_isPaused);
-    bool wasInputPaused = _isInputPaused;
-    _StreamListener subscription = _subscriber;
-    assert(subscription != null);
-    _startFiring();
-    action(subscription);
-    _endFiring(wasInputPaused);
-  }
-}
-
-// -------------------------------------------------------------------
-// Default implementation of a stream with subscribers.
-// -------------------------------------------------------------------
-
-/**
- * Default implementation of stream capable of sending events to subscribers.
- *
- * Any class needing to implement [Stream] can either directly extend this
- * class, or extend [Stream] and delegate the subscribe method to an instance
- * of this class.
- *
- * The only public methods are those of [Stream], so instances of
- * [_MultiStreamImpl] can be returned directly as a [Stream] without exposing
- * internal functionality.
- *
- * The [StreamController] is a public facing version of this class, with
- * some methods made public.
- *
- * The user interface of [_MultiStreamImpl] are the following methods:
- * * [_add]: Add a data event to the stream.
- * * [_addError]: Add an error event to the stream.
- * * [_close]: Request to close the stream.
- * * [_onSubscriptionStateChange]: Called when receiving the first subscriber or
- *                                 when losing the last subscriber.
- * * [_onPauseStateChange]: Called when entering or leaving paused mode.
- * * [_hasListener]: Test whether there are currently any subscribers.
- * * [_isPaused]: Test whether the stream is currently paused.
- * The user should not add new events while the stream is paused, but if it
- * happens anyway, the stream will enqueue the events just as when new events
- * arrive while still firing an old event.
- */
-class _MultiStreamImpl<T> extends _StreamImpl<T>
-                          implements _InternalLinkList {
-  // Link list implementation (mixin when possible).
-  _InternalLink _nextLink;
-  _InternalLink _previousLink;
-
-  _MultiStreamImpl() {
-    _nextLink = _previousLink = this;
-  }
-
-  bool get isBroadcast => true;
-
-  Stream<T> asBroadcastStream() => this;
-
-  // ------------------------------------------------------------------
-  // Helper functions that can be overridden in subclasses.
-
-  /** Whether there are currently any subscribers on this [Stream]. */
-  bool get _hasListener => !_InternalLinkList.isEmpty(this);
-
+  static const int _STATE_INPUT_PAUSED = 4;
   /**
-   * Create the new subscription object.
+   * Whether the subscription has been canceled.
+   *
+   * Set by calling [cancel], or by handling a "done" event, or an "error" event
+   * when `cancelOnError` is true.
    */
-  _StreamListener<T> _createSubscription(
-      void onData(T data),
-      void onError(error),
-      void onDone(),
-      bool cancelOnError) {
-    return new _StreamSubscriptionImpl<T>(
-        this, onData, onError, onDone, cancelOnError);
-  }
+  static const int _STATE_CANCELED = 8;
+  static const int _STATE_IN_CALLBACK = 16;
+  static const int _STATE_HAS_PENDING = 32;
+  static const int _STATE_PAUSE_COUNT = 64;
+  static const int _STATE_PAUSE_COUNT_SHIFT = 6;
 
-  // -------------------------------------------------------------------
-  // Internal implementation.
-
-  /**
-   * Iterate over all current subscribers and perform an action on each.
-   *
-   * The set of subscribers cannot be modified during this iteration.
-   * All attempts to add or unsubscribe subscribers will be delayed until
-   * after the iteration is complete.
-   *
-   * The [action] must not throw, or the controller will be left in an
-   * invalid state.
-   *
-   * This method must not be called while [isFiring] is true.
-   */
-  void _forEachSubscriber(
-      void action(_StreamListener<T> subscription)) {
-    assert(!_isFiring);
-    if (!_hasListener) return;
-    bool wasInputPaused = _isInputPaused;
-    _startFiring();
-    _InternalLink cursor = this._nextLink;
-    while (!identical(cursor, this)) {
-      _StreamListener<T> current = cursor;
-      if (current._needsEvent(_currentEventIdBit)) {
-        action(current);
-        // Marks as having received the event.
-        current._toggleEventReceived();
-      }
-      cursor = current._nextLink;
-      if (current._isPendingUnsubscribe) {
-        _removeListener(current);
-      }
-    }
-    _endFiring(wasInputPaused);
-  }
-
-  void _addListener(_StreamListener listener) {
-    listener._setSubscribed(_currentEventIdBit);
-    bool hadListener = _hasListener;
-    _InternalLinkList.add(this, listener);
-    if (!hadListener && _isInactive) {
-      _checkCallbacks(false, false);
-      if (!_isPaused && _hasPendingEvent) {
-        _schedulePendingEvents();
-      }
-    }
-  }
-
-  /**
-   * Handle a cancel requested from a [_StreamListener].
-   *
-   * This method is called from [_StreamListener.cancel].
-   *
-   * If an event is currently firing, the cancel is delayed
-   * until after the subscribers have received the event.
-   */
-  void _cancel(_StreamListener listener) {
-    assert(identical(listener._source, this));
-    if (_InternalLink.isUnlinked(listener)) {
-      // You may unsubscribe more than once, only the first one counts.
-      return;
-    }
-    if (_isFiring) {
-      if (listener._needsEvent(_currentEventIdBit)) {
-        assert(listener._isSubscribed);
-        listener._setPendingUnsubscribe(_currentEventIdBit);
-      } else {
-        // The listener has been notified of the event (or don't need to,
-        // if it's still pending subscription) so it's safe to remove it.
-        _removeListener(listener);
-      }
-      // Pause and subscription state changes are reported when we end
-      // firing.
-    } else {
-      bool wasInputPaused = _isInputPaused;
-      _removeListener(listener);
-      if (_isInactive) {
-        _checkCallbacks(true, wasInputPaused);
-        if (!_isPaused && _hasPendingEvent) {
-          _schedulePendingEvents();
-        }
-      }
-    }
-  }
-
-  /**
-   * Removes a listener from this stream and cancels its pauses.
-   *
-   * This is a low-level action that doesn't call [_onSubscriptionStateChange].
-   * or [_callOnPauseStateChange].
-   */
-  void _removeListener(_StreamListener listener) {
-    int pauseCount = listener._setUnsubscribed();
-    _InternalLinkList.remove(listener);
-    if (pauseCount > 0) {
-      _updatePauseCount(-pauseCount);
-      if (!_isPaused && _hasPendingEvent) {
-        _state |= _STREAM_PENDING_RESUME;
-      }
-    }
-  }
-}
-
-
-/** Stream that generates its own events. */
-class _GeneratedSingleStreamImpl<T> extends _SingleStreamImpl<T> {
-  /**
-   * Initializes the stream to have only the events provided by [events].
-   *
-   * A [_PendingEvents] implementation provides events that are handled
-   * by calling [_PendingEvents.handleNext] with the [_StreamImpl].
-   */
-  _GeneratedSingleStreamImpl(_PendingEvents events) {
-    _pendingEvents = events;
-    _setClosed();  // Closed for input since all events are already pending.
-  }
-
-  void _add(T value) {
-    throw new UnsupportedError("Cannot inject events into generated stream");
-  }
-
-  void _addError(value) {
-    throw new UnsupportedError("Cannot inject events into generated stream");
-  }
-
-  void _close() {
-    throw new UnsupportedError("Cannot inject events into generated stream");
-  }
-}
-
-
-/** Pending events object that gets its events from an [Iterable]. */
-class _IterablePendingEvents<T> extends _PendingEvents {
-  final Iterator<T> _iterator;
-  /**
-   * Whether there are no more events to be sent.
-   *
-   * This starts out as [:false:] since there is always at least
-   * a 'done' event to be sent.
-   */
-  bool _isDone = false;
-
-  _IterablePendingEvents(Iterable<T> data) : _iterator = data.iterator;
-
-  bool get isEmpty => _isDone;
-
-  void handleNext(_StreamImpl<T> stream) {
-    if (_isDone) throw new StateError("No events pending.");
-    try {
-      _isDone = !_iterator.moveNext();
-      if (!_isDone) {
-        stream._sendData(_iterator.current);
-      } else {
-        stream._sendDone();
-      }
-    } catch (e, s) {
-      stream._sendError(_asyncError(e, s));
-      stream._sendDone();
-      _isDone = true;
-    }
-  }
-}
-
-
-/**
- * The subscription class that the [StreamController] uses.
- *
- * The [_StreamImpl.createSubscription] method should
- * create an object of this type, or another subclass of [_StreamListener].
- * A subclass of [_StreamImpl] can specify which subclass
- * of [_StreamSubscriptionImpl] it uses by overriding
- * [_StreamImpl.createSubscription].
- *
- * The subscription is in one of three states:
- * * Subscribed.
- * * Paused-and-subscribed.
- * * Unsubscribed.
- * Unsubscribing also resumes any pauses started by the subscription.
- */
-class _StreamSubscriptionImpl<T> extends _StreamListener<T>
-                                 implements StreamSubscription<T> {
-  final bool _cancelOnError;
-  // TODO(ahe): Restore type when feature is implemented in dart2js
-  // checked mode. http://dartbug.com/7733
-  var /* _DataHandler<T> */ _onData;
+  /* Event handlers provided in constructor. */
+  /* TODO(7733): Fix Function->_DataHandler<T> when dart2js understands
+   * parameterized function types. */
+  Function _onData;
   _ErrorHandler _onError;
   _DoneHandler _onDone;
-  _StreamSubscriptionImpl(_StreamImpl source,
-                          this._onData,
-                          this._onError,
-                          this._onDone,
-                          this._cancelOnError) : super(source);
+
+  /** Bit vector based on state-constants above. */
+  int _state;
+
+  /**
+   * Queue of pending events.
+   *
+   * Is created when necessary, or set in constructor for preconfigured events.
+   */
+  _PendingEvents _pending;
+
+  _BufferingStreamSubscription(this._onData,
+                               this._onError,
+                               this._onDone,
+                               bool cancelOnError)
+      : _state = (cancelOnError ? _STATE_CANCEL_ON_ERROR : 0) {
+    assert(_onData != null);
+    assert(_onError != null);
+    assert(_onDone != null);
+  }
+
+  /**
+   * Sets the subscription's pending events object.
+   *
+   * This can only be done once. The pending events object is used for the
+   * rest of the subscription's life cycle.
+   */
+  void _setPendingEvents(_PendingEvents pendingEvents) {
+    assert(_pending == null);
+    if (pendingEvents == null) return;
+    _pending = pendingEvents;
+    if (!pendingEvents.isEmpty) {
+      _state |= _STATE_HAS_PENDING;
+      _pending.schedule(this);
+    }
+  }
+
+  /**
+   * Extracts the pending events from a canceled stream.
+   *
+   * This can only be done during the [_onCancel] method call. After that,
+   * any remaining pending events will be cleared.
+   */
+  _PendingEvents _extractPending() {
+    assert(_isCanceled);
+    _PendingEvents events = _pending;
+    _pending = null;
+    return events;
+  }
+
+  // StreamSubscription interface.
 
   void onData(void handleData(T event)) {
     if (handleData == null) handleData = _nullDataHandler;
@@ -936,48 +163,381 @@
     _onDone = handleDone;
   }
 
-  void _sendData(T data) {
-    _onData(data);
-  }
-
-  void _sendError(error) {
-    _onError(error);
-    if (_cancelOnError) _source._cancel(this);
-  }
-
-  void _sendDone() {
-    _onDone();
-  }
-
-  void cancel() {
-    if (!_isSubscribed) return;
-    _source._cancel(this);
-  }
-
   void pause([Future resumeSignal]) {
-    if (!_isSubscribed) return;
-    _source._pause(this, resumeSignal);
+    if (_isCanceled) return;
+    bool wasPaused = _isPaused;
+    bool wasInputPaused = _isInputPaused;
+    // Increment pause count and mark input paused (if it isn't already).
+    _state = (_state + _STATE_PAUSE_COUNT) | _STATE_INPUT_PAUSED;
+    if (resumeSignal != null) resumeSignal.whenComplete(resume);
+    if (!wasPaused && _pending != null) _pending.cancelSchedule();
+    if (!wasInputPaused && !_inCallback) _guardCallback(_onPause);
   }
 
   void resume() {
-    if (!_isSubscribed || !isPaused) return;
-    _source._resume(this, false);
+    if (_isCanceled) return;
+    if (_isPaused) {
+      _decrementPauseCount();
+      if (!_isPaused) {
+        if (_hasPending && !_pending.isEmpty) {
+          // Input is still paused.
+          _pending.schedule(this);
+        } else {
+          assert(_mayResumeInput);
+          _state &= ~_STATE_INPUT_PAUSED;
+          if (!_inCallback) _guardCallback(_onResume);
+        }
+      }
+    }
+  }
+
+  void cancel() {
+    if (_isCanceled) return;
+    _cancel();
+    if (!_inCallback) {
+      // otherwise checkState will be called after firing or callback completes.
+      _state |= _STATE_IN_CALLBACK;
+      _onCancel();
+      _pending = null;
+      _state &= ~_STATE_IN_CALLBACK;
+    }
   }
 
   Future asFuture([var futureValue]) {
     _FutureImpl<T> result = new _FutureImpl<T>();
 
     // Overwrite the onDone and onError handlers.
-    onDone(() { result._setValue(futureValue); });
-    onError((error) {
+    _onDone = () { result._setValue(futureValue); };
+    _onError = (error) {
       cancel();
       result._setError(error);
-    });
+    };
 
     return result;
   }
+
+  // State management.
+
+  bool get _isInputPaused => (_state & _STATE_INPUT_PAUSED) != 0;
+  bool get _isClosed => (_state & _STATE_CLOSED) != 0;
+  bool get _isCanceled => (_state & _STATE_CANCELED) != 0;
+  bool get _inCallback => (_state & _STATE_IN_CALLBACK) != 0;
+  bool get _hasPending => (_state & _STATE_HAS_PENDING) != 0;
+  bool get _isPaused => _state >= _STATE_PAUSE_COUNT;
+  bool get _canFire => _state < _STATE_IN_CALLBACK;
+  bool get _mayResumeInput =>
+      !_isPaused && (_pending == null || _pending.isEmpty);
+  bool get _cancelOnError => (_state & _STATE_CANCEL_ON_ERROR) != 0;
+
+  bool get isPaused => _isPaused;
+
+  void _cancel() {
+    _state |= _STATE_CANCELED;
+    if (_hasPending) {
+      _pending.cancelSchedule();
+    }
+  }
+
+  /**
+   * Increment the pause count.
+   *
+   * Also marks input as paused.
+   */
+  void _incrementPauseCount() {
+    _state = (_state + _STATE_PAUSE_COUNT) | _STATE_INPUT_PAUSED;
+  }
+
+  /**
+   * Decrements the pause count.
+   *
+   * Does not automatically unpause the input (call [_onResume]) when
+   * the pause count reaches zero. This is handled elsewhere, and only
+   * if there are no pending events buffered.
+   */
+  void _decrementPauseCount() {
+    assert(_isPaused);
+    _state -= _STATE_PAUSE_COUNT;
+  }
+
+  // _EventSink interface.
+
+  void _add(T data) {
+    assert(!_isClosed);
+    if (_isCanceled) return;
+    if (_canFire) {
+      _sendData(data);
+    } else {
+      _addPending(new _DelayedData(data));
+    }
+  }
+
+  void _addError(Object error) {
+    if (_isCanceled) return;
+    if (_canFire) {
+      _sendError(error);  // Reports cancel after sending.
+    } else {
+      _addPending(new _DelayedError(error));
+    }
+  }
+
+  void _close() {
+    assert(!_isClosed);
+    if (_isCanceled) return;
+    _state |= _STATE_CLOSED;
+    if (_canFire) {
+      _sendDone();
+    } else {
+      _addPending(const _DelayedDone());
+    }
+  }
+
+  // Hooks called when the input is paused, unpaused or canceled.
+  // These must not throw. If overwritten to call user code, include suitable
+  // try/catch wrapping and send any errors to [_throwDelayed].
+  void _onPause() {
+    assert(_isInputPaused);
+  }
+
+  void _onResume() {
+    assert(!_isInputPaused);
+  }
+
+  void _onCancel() {
+    assert(_isCanceled);
+  }
+
+  // Handle pending events.
+
+  /**
+   * Add a pending event.
+   *
+   * If the subscription is not paused, this also schedules a firing
+   * of pending events later (if necessary).
+   */
+  void _addPending(_DelayedEvent event) {
+    _StreamImplEvents pending = _pending;
+    if (_pending == null) pending = _pending = new _StreamImplEvents();
+    pending.add(event);
+    if (!_hasPending) {
+      _state |= _STATE_HAS_PENDING;
+      if (!_isPaused) {
+        _pending.schedule(this);
+      }
+    }
+  }
+
+  /* _EventDispatch interface. */
+
+  void _sendData(T data) {
+    assert(!_isCanceled);
+    assert(!_isPaused);
+    assert(!_inCallback);
+    bool wasInputPaused = _isInputPaused;
+    _state |= _STATE_IN_CALLBACK;
+    try {
+      _onData(data);
+    } catch (e, s) {
+      _throwDelayed(e, s);
+    }
+    _state &= ~_STATE_IN_CALLBACK;
+    _checkState(wasInputPaused);
+  }
+
+  void _sendError(var error) {
+    assert(!_isCanceled);
+    assert(!_isPaused);
+    assert(!_inCallback);
+    bool wasInputPaused = _isInputPaused;
+    _state |= _STATE_IN_CALLBACK;
+    try {
+      _onError(error);
+    } catch (e, s) {
+      _throwDelayed(e, s);
+    }
+    _state &= ~_STATE_IN_CALLBACK;
+    if (_cancelOnError) {
+      _cancel();
+    }
+    _checkState(wasInputPaused);
+  }
+
+  void _sendDone() {
+    assert(!_isCanceled);
+    assert(!_isPaused);
+    assert(!_inCallback);
+    _state |= (_STATE_CANCELED | _STATE_CLOSED | _STATE_IN_CALLBACK);
+    try {
+      _onDone();
+    } catch (e, s) {
+      _throwDelayed(e, s);
+    }
+    _onCancel();  // No checkState after cancel, it is always the last event.
+    _state &= ~_STATE_IN_CALLBACK;
+  }
+
+  /**
+   * Call a hook function.
+   *
+   * The call is properly wrapped in code to avoid other callbacks
+   * during the call, and it checks for state changes after the call
+   * that should cause further callbacks.
+   */
+  void _guardCallback(callback) {
+    assert(!_inCallback);
+    bool wasInputPaused = _isInputPaused;
+    _state |= _STATE_IN_CALLBACK;
+    callback();
+    _state &= ~_STATE_IN_CALLBACK;
+    _checkState(wasInputPaused);
+  }
+
+  /**
+   * Check if the input needs to be informed of state changes.
+   *
+   * State changes are pausing, resuming and canceling.
+   *
+   * After canceling, no further callbacks will happen.
+   *
+   * The cancel callback is called after a user cancel, or after
+   * the final done event is sent.
+   */
+  void _checkState(bool wasInputPaused) {
+    assert(!_inCallback);
+    if (_hasPending && _pending.isEmpty) {
+      _state &= ~_STATE_HAS_PENDING;
+      if (_isInputPaused && _mayResumeInput) {
+        _state &= ~_STATE_INPUT_PAUSED;
+      }
+    }
+    // If the state changes during a callback, we immediately
+    // make a new state-change callback. Loop until the state didn't change.
+    while (true) {
+      if (_isCanceled) {
+        _onCancel();
+        _pending = null;
+        return;
+      }
+      bool isInputPaused = _isInputPaused;
+      if (wasInputPaused == isInputPaused) break;
+      _state ^= _STATE_IN_CALLBACK;
+      if (isInputPaused) {
+        _onPause();
+      } else {
+        _onResume();
+      }
+      _state &= ~_STATE_IN_CALLBACK;
+      wasInputPaused = isInputPaused;
+    }
+    if (_hasPending && !_isPaused) {
+      _pending.schedule(this);
+    }
+  }
 }
 
+// -------------------------------------------------------------------
+// Common base class for single and multi-subscription streams.
+// -------------------------------------------------------------------
+abstract class _StreamImpl<T> extends Stream<T> {
+  // ------------------------------------------------------------------
+  // Stream interface.
+
+  StreamSubscription<T> listen(void onData(T data),
+                               { void onError(error),
+                                 void onDone(),
+                                 bool cancelOnError }) {
+    if (onData == null) onData = _nullDataHandler;
+    if (onError == null) onError = _nullErrorHandler;
+    if (onDone == null) onDone = _nullDoneHandler;
+    cancelOnError = identical(true, cancelOnError);
+    StreamSubscription subscription =
+        _createSubscription(onData, onError, onDone, cancelOnError);
+    _onListen(subscription);
+    return subscription;
+  }
+
+  // -------------------------------------------------------------------
+  /** Create a subscription object. Called by [subcribe]. */
+  _BufferingStreamSubscription<T> _createSubscription(
+      void onData(T data),
+      void onError(error),
+      void onDone(),
+      bool cancelOnError) {
+    return new _BufferingStreamSubscription<T>(
+        onData, onError, onDone, cancelOnError);
+  }
+
+  /** Hook called when the subscription has been created. */
+  void _onListen(StreamSubscription subscription) {}
+}
+
+typedef _PendingEvents _EventGenerator();
+
+/** Stream that generates its own events. */
+class _GeneratedStreamImpl<T> extends _StreamImpl<T> {
+  final _EventGenerator _pending;
+  /**
+   * Initializes the stream to have only the events provided by a
+   * [_PendingEvents].
+   *
+   * A new [_PendingEvents] must be generated for each listen.
+   */
+  _GeneratedStreamImpl(this._pending);
+
+  StreamSubscription _createSubscription(void onData(T data),
+                                         void onError(Object error),
+                                         void onDone(),
+                                         bool cancelOnError) {
+    _BufferingStreamSubscription<T> subscription =
+         new _BufferingStreamSubscription(
+             onData, onError, onDone, cancelOnError);
+    subscription._setPendingEvents(_pending());
+    return subscription;
+  }
+}
+
+
+/** Pending events object that gets its events from an [Iterable]. */
+class _IterablePendingEvents<T> extends _PendingEvents {
+  // The iterator providing data for data events.
+  // Set to null when iteration has completed.
+  Iterator<T> _iterator;
+
+  _IterablePendingEvents(Iterable<T> data) : _iterator = data.iterator;
+
+  bool get isEmpty => _iterator == null;
+
+  void handleNext(_EventDispatch dispatch) {
+    if (_iterator == null) {
+      throw new StateError("No events pending.");
+    }
+    // Send one event per call to moveNext.
+    // If moveNext returns true, send the current element as data.
+    // If moveNext returns false, send a done event and clear the _iterator.
+    // If moveNext throws an error, send an error and clear the _iterator.
+    // After an error, no further events will be sent.
+    bool isDone;
+    try {
+      isDone = !_iterator.moveNext();
+    } catch (e, s) {
+      _iterator = null;
+      dispatch._sendError(_asyncError(e, s));
+      return;
+    }
+    if (!isDone) {
+      dispatch._sendData(_iterator.current);
+    } else {
+      _iterator = null;
+      dispatch._sendDone();
+    }
+  }
+
+  void clear() {
+    if (isScheduled) cancelSchedule();
+    _iterator = null;
+  }
+}
+
+
 // Internal helpers.
 
 // Types of the different handlers on a stream. Types used to type fields.
@@ -998,20 +558,20 @@
 void _nullDoneHandler() {}
 
 
-/** A delayed event on a stream implementation. */
+/** A delayed event on a buffering stream subscription. */
 abstract class _DelayedEvent {
   /** Added as a linked list on the [StreamController]. */
   _DelayedEvent next;
   /** Execute the delayed event on the [StreamController]. */
-  void perform(_StreamImpl stream);
+  void perform(_EventDispatch dispatch);
 }
 
 /** A delayed data event. */
 class _DelayedData<T> extends _DelayedEvent{
   final T value;
   _DelayedData(this.value);
-  void perform(_StreamImpl<T> stream) {
-    stream._sendData(value);
+  void perform(_EventDispatch<T> dispatch) {
+    dispatch._sendData(value);
   }
 }
 
@@ -1019,16 +579,16 @@
 class _DelayedError extends _DelayedEvent {
   final error;
   _DelayedError(this.error);
-  void perform(_StreamImpl stream) {
-    stream._sendError(error);
+  void perform(_EventDispatch dispatch) {
+    dispatch._sendError(error);
   }
 }
 
 /** A delayed done event. */
 class _DelayedDone implements _DelayedEvent {
   const _DelayedDone();
-  void perform(_StreamImpl stream) {
-    stream._sendDone();
+  void perform(_EventDispatch dispatch) {
+    dispatch._sendDone();
   }
 
   _DelayedEvent get next => null;
@@ -1038,198 +598,66 @@
   }
 }
 
-/**
- * Simple internal doubly-linked list implementation.
- *
- * In an internal linked list, the links are in the data objects themselves,
- * instead of in a separate object. That means each element can be in at most
- * one list at a time.
- *
- * All links are always members of an element cycle. At creation it's a
- * singleton cycle.
- */
-abstract class _InternalLink {
-  _InternalLink _nextLink;
-  _InternalLink _previousLink;
-
-  _InternalLink() {
-    this._previousLink = this._nextLink = this;
-  }
-
-  /* Removes a link from any list it may be part of, and links it to itself. */
-  static void unlink(_InternalLink element) {
-    _InternalLink next = element._nextLink;
-    _InternalLink previous = element._previousLink;
-    next._previousLink = previous;
-    previous._nextLink = next;
-    element._nextLink = element._previousLink = element;
-  }
-
-  /** Check whether an element is unattached to other elements. */
-  static bool isUnlinked(_InternalLink element) {
-    return identical(element, element._nextLink);
-  }
-}
-
-/**
- * Marker interface for "list" links.
- *
- * An "InternalLinkList" is an abstraction on top of a link cycle, where the
- * "list" object itself is not considered an element (it's just a header link
- * created to avoid edge cases).
- * An element is considered part of a list if it is in the list's cycle.
- * There should never be more than one "list" object in a cycle.
- */
-abstract class _InternalLinkList extends _InternalLink {
-  /**
-   * Adds an element to a list, just before the header link.
-   *
-   * This effectively adds it at the end of the list.
-   */
-  static void add(_InternalLinkList list, _InternalLink element) {
-    if (!_InternalLink.isUnlinked(element)) _InternalLink.unlink(element);
-    _InternalLink listEnd = list._previousLink;
-    listEnd._nextLink = element;
-    list._previousLink = element;
-    element._previousLink = listEnd;
-    element._nextLink = list;
-  }
-
-  /** Removes an element from its list. */
-  static void remove(_InternalLink element) {
-    _InternalLink.unlink(element);
-  }
-
-  /** Check whether a list contains no elements, only the header link. */
-  static bool isEmpty(_InternalLinkList list) => _InternalLink.isUnlinked(list);
-
-  /** Moves all elements from the list [other] to [list]. */
-  static void addAll(_InternalLinkList list, _InternalLinkList other) {
-    if (isEmpty(other)) return;
-    _InternalLink listLast = list._previousLink;
-    _InternalLink otherNext = other._nextLink;
-    listLast._nextLink = otherNext;
-    otherNext._previousLink = listLast;
-    _InternalLink otherLast = other._previousLink;
-    list._previousLink = otherLast;
-    otherLast._nextLink = list;
-    // Clean up [other].
-    other._nextLink = other._previousLink = other;
-  }
-}
-
-/** Abstract type for an internal interface for sending events. */
-abstract class _EventOutputSink<T> {
-  _sendData(T data);
-  _sendError(error);
-  _sendDone();
-}
-
-abstract class _StreamListener<T> extends _InternalLink
-                                  implements _EventOutputSink<T> {
-  final _StreamImpl _source;
-  int _state = _LISTENER_UNSUBSCRIBED;
-
-  _StreamListener(this._source);
-
-  bool get isPaused => _state >= (1 << _LISTENER_PAUSE_COUNT_SHIFT);
-
-  bool get _isPendingUnsubscribe =>
-      (_state & _LISTENER_PENDING_UNSUBSCRIBE) != 0;
-
-  bool get _isSubscribed => (_state & _LISTENER_SUBSCRIBED) != 0;
-
-  /**
-   * Whether the listener still needs to receive the currently firing event.
-   *
-   * The currently firing event is identified by a single bit, which alternates
-   * between events. The [_state] contains the previously sent event's bit in
-   * the [_LISTENER_EVENT_ID] bit. If the two don't match, this listener
-   * still need the current event.
-   */
-  bool _needsEvent(int currentEventIdBit) {
-    int lastEventIdBit =
-        (_state & _LISTENER_EVENT_ID) >> _LISTENER_EVENT_ID_SHIFT;
-    return lastEventIdBit != currentEventIdBit;
-  }
-
-  /// If a subscriber's "firing bit" doesn't match the stream's firing bit,
-  /// we are currently firing an event and the subscriber still need to receive
-  /// the event.
-  void _toggleEventReceived() {
-    _state ^= _LISTENER_EVENT_ID;
-  }
-
-  void _setSubscribed(int eventIdBit) {
-    assert(eventIdBit == 0 || eventIdBit == 1);
-    _state = _LISTENER_SUBSCRIBED | (eventIdBit << _LISTENER_EVENT_ID_SHIFT);
-  }
-
-  void _setPendingUnsubscribe(int currentEventIdBit) {
-    assert(_isSubscribed);
-    // Sets the pending unsubscribe, and ensures that the listener
-    // won't get the current event.
-    _state |= _LISTENER_PENDING_UNSUBSCRIBE | _LISTENER_EVENT_ID;
-    _state ^= (1 ^ currentEventIdBit) << _LISTENER_EVENT_ID_SHIFT;
-    assert(!_needsEvent(currentEventIdBit));
-  }
-
-  /**
-   * Marks the listener as unsubscibed.
-   *
-   * Returns the number of unresumed pauses for the listener.
-   */
-  int _setUnsubscribed() {
-    assert(_isSubscribed);
-    int timesPaused = _state >> _LISTENER_PAUSE_COUNT_SHIFT;
-    _state = _LISTENER_UNSUBSCRIBED;
-    return timesPaused;
-  }
-
-  void _incrementPauseCount() {
-    _state += 1 << _LISTENER_PAUSE_COUNT_SHIFT;
-  }
-
-  void _decrementPauseCount() {
-    assert(isPaused);
-    _state -= 1 << _LISTENER_PAUSE_COUNT_SHIFT;
-  }
-
-  _sendData(T data);
-  _sendError(error);
-  _sendDone();
-}
-
 /** Superclass for provider of pending events. */
 abstract class _PendingEvents {
+  // No async event has been scheduled.
+  static const int _STATE_UNSCHEDULED = 0;
+  // An async event has been scheduled to run a function.
+  static const int _STATE_SCHEDULED = 1;
+  // An async event has been scheduled, but it will do nothing when it runs.
+  // Async events can't be preempted.
+  static const int _STATE_CANCELED = 3;
+
   /**
-   * Timer set when pending events are scheduled for execution.
+   * State of being scheduled.
    *
-   * When scheduling pending events for execution in a later cycle, the timer
-   * is stored here. If pending events are executed earlier than that, e.g.,
-   * due to a second event in the current cycle, the timer is canceled again.
+   * Set to [_STATE_SCHEDULED] when pending events are scheduled for
+   * async dispatch. Since we can't cancel a [runAsync] call, if schduling
+   * is "canceled", the _state is simply set to [_STATE_CANCELED] which will
+   * make the async code do nothing except resetting [_state].
+   *
+   * If events are scheduled while the state is [_STATE_CANCELED], it is
+   * merely switched back to [_STATE_SCHEDULED], but no new call to [runAsync]
+   * is performed.
    */
-  Timer scheduleTimer = null;
+  int _state = _STATE_UNSCHEDULED;
 
   bool get isEmpty;
 
-  bool get isScheduled => scheduleTimer != null;
+  bool get isScheduled => _state == _STATE_SCHEDULED;
+  bool get _eventScheduled => _state >= _STATE_SCHEDULED;
 
-  void schedule(_StreamImpl stream) {
+  /**
+   * Schedule an event to run later.
+   *
+   * If called more than once, it should be called with the same dispatch as
+   * argument each time. It may reuse an earlier argument in some cases.
+   */
+  void schedule(_EventDispatch dispatch) {
     if (isScheduled) return;
-    scheduleTimer = new Timer(Duration.ZERO, () {
-      scheduleTimer = null;
-      stream._handlePendingEvents();
+    assert(!isEmpty);
+    if (_eventScheduled) {
+      assert(_state == _STATE_CANCELED);
+      _state = _STATE_SCHEDULED;
+      return;
+    }
+    runAsync(() {
+      int oldState = _state;
+      _state = _STATE_UNSCHEDULED;
+      if (oldState == _STATE_CANCELED) return;
+      handleNext(dispatch);
     });
+    _state = _STATE_SCHEDULED;
   }
 
   void cancelSchedule() {
-    assert(isScheduled);
-    scheduleTimer.cancel();
-    scheduleTimer = null;
+    if (isScheduled) _state = _STATE_CANCELED;
   }
 
-  void handleNext(_StreamImpl stream);
+  void handleNext(_EventDispatch dispatch);
+
+  /** Throw away any pending events and cancel scheduled events. */
+  void clear();
 }
 
 
@@ -1242,8 +670,6 @@
 
   bool get isEmpty => lastPendingEvent == null;
 
-  bool get isScheduled => scheduleTimer != null;
-
   void add(_DelayedEvent event) {
     if (lastPendingEvent == null) {
       firstPendingEvent = lastPendingEvent = event;
@@ -1252,122 +678,224 @@
     }
   }
 
-  void handleNext(_StreamImpl stream) {
+  void handleNext(_EventDispatch dispatch) {
     assert(!isScheduled);
     _DelayedEvent event = firstPendingEvent;
     firstPendingEvent = event.next;
     if (firstPendingEvent == null) {
       lastPendingEvent = null;
     }
-    event.perform(stream);
+    event.perform(dispatch);
+  }
+
+  void clear() {
+    if (isScheduled) cancelSchedule();
+    firstPendingEvent = lastPendingEvent = null;
   }
 }
 
+class _MultiplexerLinkedList {
+  _MultiplexerLinkedList _next;
+  _MultiplexerLinkedList _previous;
 
-class _DoneSubscription<T> implements StreamSubscription<T> {
-  _DoneHandler _handler;
-  Timer _timer;
-  int _pauseCount = 0;
-
-  _DoneSubscription(this._handler) {
-    _delayDone();
+  void _unlink() {
+    _previous._next = _next;
+    _next._previous = _previous;
+    _next = _previous = this;
   }
 
-  void _delayDone() {
-    assert(_timer == null && _pauseCount == 0);
-    _timer = new Timer(Duration.ZERO, () {
-      if (_handler != null) _handler();
-    });
-  }
-
-  bool get _isComplete => _timer == null && _pauseCount == 0;
-
-  void onData(void handleAction(T value)) {}
-
-  void onError(void handleError(error)) {}
-
-  void onDone(void handleDone()) {
-    _handler = handleDone;
-  }
-
-  void pause([Future signal]) {
-    if (_isComplete) return;
-    if (_timer != null) {
-      _timer.cancel();
-      _timer = null;
-    }
-    _pauseCount++;
-    if (signal != null) signal.whenComplete(resume);
-  }
-
-  void resume() {
-    if (_isComplete) return;
-    if (_pauseCount == 0) return;
-    _pauseCount--;
-    if (_pauseCount == 0) {
-      _delayDone();
-    }
-  }
-
-  bool get isPaused => _pauseCount > 0;
-
-  void cancel() {
-    if (_isComplete) return;
-    if (_timer != null) {
-      _timer.cancel();
-      _timer = null;
-    }
-    _pauseCount = 0;
-  }
-
-  Future asFuture([var futureValue]) {
-    // TODO(floitsch): share more code.
-    _FutureImpl<T> result = new _FutureImpl<T>();
-
-    // Overwrite the onDone and onError handlers.
-    onDone(() { result._setValue(futureValue); });
-    onError((error) {
-      cancel();
-      result._setError(error);
-    });
-
-    return result;
+  void _insertBefore(_MultiplexerLinkedList newNext) {
+    _MultiplexerLinkedList newPrevious = newNext._previous;
+    newPrevious._next = this;
+    newNext._previous = _previous;
+    _previous._next = newNext;
+    _previous = newPrevious;
   }
 }
 
-class _SingleStreamMultiplexer<T> extends _MultiStreamImpl<T> {
+class _AsBroadcastStream<T> extends Stream<T> {
   final Stream<T> _source;
+  _BufferingMultiplexStreamController<T> _controller;
   StreamSubscription<T> _subscription;
 
-  _SingleStreamMultiplexer(this._source);
+  _AsBroadcastStream(this._source) {
+    _controller = new _BufferingMultiplexStreamController<T>(null, _onCancel);
+  }
 
-  void _callOnPauseStateChange() {
-    if (_isPaused) {
-      if (_subscription != null) {
-        _subscription.pause();
-      }
+  bool get isBroadcast => true;
+
+  StreamSubscription<T> listen(void onData(T data),
+                               { void onError(Object error),
+                                 void onDone(),
+                                 bool cancelOnError}) {
+    if (_controller == null) {
+      throw new StateError("Source stream has been closed.");
+    }
+    if (_subscription == null) {
+      _subscription = _source.listen(_controller.add,
+                                     onError: _controller.addError,
+                                     onDone: _controller.close);
+    }
+    return _controller.stream.listen(onData, onError: onError, onDone: onDone,
+                                     cancelOnError: cancelOnError);
+  }
+
+  void _onCancel() {
+    // Called by [_controller] when it has no subscribers left.
+    StreamSubscription subscription = _subscription;
+    _subscription = null;
+    _controller = null;  // Marks the stream as no longer listenable.
+    subscription.cancel();
+  }
+}
+
+/**
+ * Simple implementation of [StreamIterator].
+ */
+class _StreamIteratorImpl<T> implements StreamIterator<T> {
+  // Internal state of the stream iterator.
+  // At any time, it is in one of these states.
+  // The interpretation of the [_futureOrPrefecth] field depends on the state.
+  // In _STATE_MOVING, the _data field holds the most recently returned
+  // future.
+  // When in one of the _STATE_EXTRA_* states, the it may hold the
+  // next data/error object, and the subscription is paused.
+
+  /// The simple state where [_data] holds the data to return, and [moveNext]
+  /// is allowed. The subscription is actively listening.
+  static const int _STATE_FOUND = 0;
+  /// State set after [moveNext] has returned false or an error,
+  /// or after calling [cancel]. The subscription is always canceled.
+  static const int _STATE_DONE = 1;
+  /// State set after calling [moveNext], but before its returned future has
+  /// completed. Calling [moveNext] again is not allowed in this state.
+  /// The subscription is actively listening.
+  static const int _STATE_MOVING = 2;
+  /// States set when another event occurs while in _STATE_FOUND.
+  /// This extra overflow event is cached until the next call to [moveNext],
+  /// which will complete as if it received the event normally.
+  /// The subscription is paused in these states, so we only ever get one
+  /// event too many.
+  static const int _STATE_EXTRA_DATA = 3;
+  static const int _STATE_EXTRA_ERROR = 4;
+  static const int _STATE_EXTRA_DONE = 5;
+
+  /// Subscription being listened to.
+  StreamSubscription _subscription;
+
+  /// The current element represented by the most recent call to moveNext.
+  ///
+  /// Is null between the time moveNext is called and its future completes.
+  T _current = null;
+
+  /// The future returned by the most recent call to [moveNext].
+  ///
+  /// Also used to store the next value/error in case the stream provides an
+  /// event before [moveNext] is called again. In that case, the stream will
+  /// be paused to prevent further events.
+  var _futureOrPrefetch = null;
+
+  /// The current state.
+  int _state = _STATE_FOUND;
+
+  _StreamIteratorImpl(final Stream<T> stream) {
+    _subscription = stream.listen(_onData,
+                                  onError: _onError,
+                                  onDone: _onDone,
+                                  cancelOnError: true);
+  }
+
+  T get current => _current;
+
+  Future<bool> moveNext() {
+    if (_state == _STATE_DONE) {
+      return new _FutureImpl<bool>.immediate(false);
+    }
+    if (_state == _STATE_MOVING) {
+      throw new StateError("Already waiting for next.");
+    }
+    if (_state == _STATE_FOUND) {
+      _state = _STATE_MOVING;
+      _futureOrPrefetch = new _FutureImpl<bool>();
+      return _futureOrPrefetch;
     } else {
-      if (_subscription != null) {
-        _subscription.resume();
+      assert(_state >= _STATE_EXTRA_DATA);
+      switch (_state) {
+        case _STATE_EXTRA_DATA:
+          _state = _STATE_FOUND;
+          _current = _futureOrPrefetch;
+          _futureOrPrefetch = null;
+          _subscription.resume();
+          return new _FutureImpl<bool>.immediate(true);
+        case _STATE_EXTRA_ERROR:
+          Object prefetch = _futureOrPrefetch;
+          _clear();
+          return new _FutureImpl<bool>.immediateError(prefetch);
+        case _STATE_EXTRA_DONE:
+          _clear();
+          return new _FutureImpl<bool>.immediate(false);
       }
     }
   }
 
-  /**
-    * Subscribe or unsubscribe on [_source] depending on whether
-    * [_stream] has subscribers.
-    */
-  void _onSubscriptionStateChange() {
-    if (_hasListener) {
-      assert(_subscription == null);
-      _subscription = _source.listen(this._add,
-                                     onError: this._addError,
-                                     onDone: this._close);
+  /** Clears up the internal state when the iterator ends. */
+  void _clear() {
+    _subscription = null;
+    _futureOrPrefetch = null;
+    _current = null;
+    _state = _STATE_DONE;
+  }
+
+  void cancel() {
+    StreamSubscription subscription = _subscription;
+    if (_state == _STATE_MOVING) {
+      _FutureImpl<bool> hasNext = _futureOrPrefetch;
+      _clear();
+      hasNext._setValue(false);
     } else {
-      // TODO(lrn): Check why this can happen.
-      if (_subscription == null) return;
-      _subscription.cancel();
-      _subscription = null;
+      _clear();
     }
+    subscription.cancel();
+  }
+
+  void _onData(T data) {
+    if (_state == _STATE_MOVING) {
+      _current = data;
+      _FutureImpl<bool> hasNext = _futureOrPrefetch;
+      _futureOrPrefetch = null;
+      _state = _STATE_FOUND;
+      hasNext._setValue(true);
+      return;
+    }
+    _subscription.pause();
+    assert(_futureOrPrefetch == null);
+    _futureOrPrefetch = data;
+    _state = _STATE_EXTRA_DATA;
+  }
+
+  void _onError(Object error) {
+    if (_state == _STATE_MOVING) {
+      _FutureImpl<bool> hasNext = _futureOrPrefetch;
+      // We have cancelOnError: true, so the subscription is canceled.
+      _clear();
+      hasNext._setError(error);
+      return;
+    }
+    _subscription.pause();
+    assert(_futureOrPrefetch == null);
+    _futureOrPrefetch = error;
+    _state = _STATE_EXTRA_ERROR;
+  }
+
+  void _onDone() {
+     if (_state == _STATE_MOVING) {
+      _FutureImpl<bool> hasNext = _futureOrPrefetch;
+      _clear();
+      hasNext._setValue(false);
+      return;
+    }
+    _subscription.pause();
+    _futureOrPrefetch = null;
+    _state = _STATE_EXTRA_DONE;
   }
 }
diff --git a/sdk/lib/async/stream_pipe.dart b/sdk/lib/async/stream_pipe.dart
index e089f6c..e5aca17 100644
--- a/sdk/lib/async/stream_pipe.dart
+++ b/sdk/lib/async/stream_pipe.dart
@@ -69,84 +69,26 @@
 
   // Override the following methods in subclasses to change the behavior.
 
-  void _handleData(S data, _EventOutputSink<T> sink) {
+  void _handleData(S data, _EventSink<T> sink) {
     var outputData = data;
-    sink._sendData(outputData);
+    sink._add(outputData);
   }
 
-  void _handleError(error, _EventOutputSink<T> sink) {
-    sink._sendError(error);
+  void _handleError(error, _EventSink<T> sink) {
+    sink._addError(error);
   }
 
-  void _handleDone(_EventOutputSink<T> sink) {
-    sink._sendDone();
+  void _handleDone(_EventSink<T> sink) {
+    sink._close();
   }
 }
 
 /**
- * Common behavior of [StreamSubscription] classes.
- *
- * Stores and allows updating of the event handlers of a [StreamSubscription].
- */
-abstract class _BaseStreamSubscription<T> implements StreamSubscription<T> {
-  // TODO(ahe): Restore type when feature is implemented in dart2js
-  // checked mode. http://dartbug.com/7733
-  var /* _DataHandler<T> */ _onData;
-  _ErrorHandler _onError;
-  _DoneHandler _onDone;
-
-  _BaseStreamSubscription(this._onData,
-                          this._onError,
-                          this._onDone) {
-    if (_onData == null) _onData = _nullDataHandler;
-    if (_onError == null) _onError = _nullErrorHandler;
-    if (_onDone == null) _onDone = _nullDoneHandler;
-  }
-
-  // StreamSubscription interface.
-  void onData(void handleData(T event)) {
-    if (handleData == null) handleData = _nullDataHandler;
-    _onData = handleData;
-  }
-
-  void onError(void handleError(error)) {
-    if (handleError == null) handleError = _nullErrorHandler;
-    _onError = handleError;
-  }
-
-  void onDone(void handleDone()) {
-    if (handleDone == null) handleDone = _nullDoneHandler;
-    _onDone = handleDone;
-  }
-
-  void pause([Future resumeSignal]);
-
-  void resume();
-
-  void cancel();
-
-  Future asFuture([var futureValue]) {
-    _FutureImpl<T> result = new _FutureImpl<T>();
-
-    // Overwrite the onDone and onError handlers.
-    onDone(() { result._setValue(futureValue); });
-    onError((error) {
-      cancel();
-      result._setError(error);
-    });
-
-    return result;
-  }
-}
-
-
-/**
  * Abstract superclass for subscriptions that forward to other subscriptions.
  */
 class _ForwardingStreamSubscription<S, T>
-    extends _BaseStreamSubscription<T> implements _EventOutputSink<T> {
+    extends _BufferingStreamSubscription<T> {
   final _ForwardingStream<S, T> _stream;
-  final bool _cancelOnError;
 
   StreamSubscription<S> _subscription;
 
@@ -154,62 +96,48 @@
                                 void onData(T data),
                                 void onError(error),
                                 void onDone(),
-                                this._cancelOnError)
-      : super(onData, onError, onDone) {
-    // Don't unsubscribe on incoming error, only if we send an error forwards.
+                                bool cancelOnError)
+      : super(onData, onError, onDone, cancelOnError) {
     _subscription =
         _stream._source.listen(_handleData,
                                onError: _handleError,
                                onDone: _handleDone);
   }
 
-  // StreamSubscription interface.
+  // _StreamSink interface.
+  // Transformers sending more than one event have no way to know if the stream
+  // is canceled or closed after the first, so we just ignore remaining events.
 
-  void pause([Future resumeSignal]) {
-    if (_subscription == null) return;
-    _subscription.pause(resumeSignal);
+  void _add(T data) {
+    if (_isClosed) return;
+    super._add(data);
   }
 
-  void resume() {
+  void _addError(Object error) {
+    if (_isClosed) return;
+    super._addError(error);
+  }
+
+  // StreamSubscription callbacks.
+
+  void _onPause() {
+    if (_subscription == null) return;
+    _subscription.pause();
+  }
+
+  void _onResume() {
     if (_subscription == null) return;
     _subscription.resume();
   }
 
-  bool get isPaused {
-    if (_subscription == null) return false;
-    return _subscription.isPaused;
-  }
-
-  void cancel() {
+  void _onCancel() {
     if (_subscription != null) {
-      _subscription.cancel();
+      StreamSubscription subscription = _subscription;
       _subscription = null;
+      subscription.cancel();
     }
   }
 
-  // _EventOutputSink interface. Sends data to this subscription.
-
-  void _sendData(T data) {
-    _onData(data);
-  }
-
-  void _sendError(error) {
-    _onError(error);
-    if (_cancelOnError) {
-      _subscription.cancel();
-      _subscription = null;
-    }
-  }
-
-  void _sendDone() {
-    // If the transformation sends a done signal, we stop the subscription.
-    if (_subscription != null) {
-      _subscription.cancel();
-      _subscription = null;
-    }
-    _onDone();
-  }
-
   // Methods used as listener on source subscription.
 
   // TODO(ahe): Restore type when feature is implemented in dart2js
@@ -241,16 +169,16 @@
   _WhereStream(Stream<T> source, bool test(T value))
       : _test = test, super(source);
 
-  void _handleData(T inputEvent, _EventOutputSink<T> sink) {
+  void _handleData(T inputEvent, _EventSink<T> sink) {
     bool satisfies;
     try {
       satisfies = _test(inputEvent);
     } catch (e, s) {
-      sink._sendError(_asyncError(e, s));
+      sink._addError(_asyncError(e, s));
       return;
     }
     if (satisfies) {
-      sink._sendData(inputEvent);
+      sink._add(inputEvent);
     }
   }
 }
@@ -267,15 +195,15 @@
   _MapStream(Stream<S> source, T transform(S event))
       : this._transform = transform, super(source);
 
-  void _handleData(S inputEvent, _EventOutputSink<T> sink) {
+  void _handleData(S inputEvent, _EventSink<T> sink) {
     T outputEvent;
     try {
       outputEvent = _transform(inputEvent);
     } catch (e, s) {
-      sink._sendError(_asyncError(e, s));
+      sink._addError(_asyncError(e, s));
       return;
     }
-    sink._sendData(outputEvent);
+    sink._add(outputEvent);
   }
 }
 
@@ -288,15 +216,15 @@
   _ExpandStream(Stream<S> source, Iterable<T> expand(S event))
       : this._expand = expand, super(source);
 
-  void _handleData(S inputEvent, _EventOutputSink<T> sink) {
+  void _handleData(S inputEvent, _EventSink<T> sink) {
     try {
       for (T value in _expand(inputEvent)) {
-        sink._sendData(value);
+        sink._add(value);
       }
     } catch (e, s) {
       // If either _expand or iterating the generated iterator throws,
       // we abort the iteration.
-      sink._sendError(_asyncError(e, s));
+      sink._addError(_asyncError(e, s));
     }
   }
 }
@@ -318,13 +246,13 @@
                     bool test(error))
       : this._transform = transform, this._test = test, super(source);
 
-  void _handleError(Object error, _EventOutputSink<T> sink) {
+  void _handleError(Object error, _EventSink<T> sink) {
     bool matches = true;
     if (_test != null) {
       try {
         matches = _test(error);
       } catch (e, s) {
-        sink._sendError(_asyncError(e, s));
+        sink._addError(_asyncError(e, s));
         return;
       }
     }
@@ -332,11 +260,11 @@
       try {
         _transform(error);
       } catch (e, s) {
-        sink._sendError(_asyncError(e, s));
+        sink._addError(_asyncError(e, s));
         return;
       }
     } else {
-      sink._sendError(error);
+      sink._addError(error);
     }
   }
 }
@@ -352,14 +280,14 @@
     if (count is! int) throw new ArgumentError(count);
   }
 
-  void _handleData(T inputEvent, _EventOutputSink<T> sink) {
+  void _handleData(T inputEvent, _EventSink<T> sink) {
     if (_remaining > 0) {
-      sink._sendData(inputEvent);
+      sink._add(inputEvent);
       _remaining -= 1;
       if (_remaining == 0) {
         // Closing also unsubscribes all subscribers, which unsubscribes
         // this from source.
-        sink._sendDone();
+        sink._close();
       }
     }
   }
@@ -372,20 +300,20 @@
   _TakeWhileStream(Stream<T> source, bool test(T value))
       : this._test = test, super(source);
 
-  void _handleData(T inputEvent, _EventOutputSink<T> sink) {
+  void _handleData(T inputEvent, _EventSink<T> sink) {
     bool satisfies;
     try {
       satisfies = _test(inputEvent);
     } catch (e, s) {
-      sink._sendError(_asyncError(e, s));
+      sink._addError(_asyncError(e, s));
       // The test didn't say true. Didn't say false either, but we stop anyway.
-      sink._sendDone();
+      sink._close();
       return;
     }
     if (satisfies) {
-      sink._sendData(inputEvent);
+      sink._add(inputEvent);
     } else {
-      sink._sendDone();
+      sink._close();
     }
   }
 }
@@ -400,12 +328,12 @@
     if (count is! int || count < 0) throw new ArgumentError(count);
   }
 
-  void _handleData(T inputEvent, _EventOutputSink<T> sink) {
+  void _handleData(T inputEvent, _EventSink<T> sink) {
     if (_remaining > 0) {
       _remaining--;
       return;
     }
-    return sink._sendData(inputEvent);
+    return sink._add(inputEvent);
   }
 }
 
@@ -416,23 +344,23 @@
   _SkipWhileStream(Stream<T> source, bool test(T value))
       : this._test = test, super(source);
 
-  void _handleData(T inputEvent, _EventOutputSink<T> sink) {
+  void _handleData(T inputEvent, _EventSink<T> sink) {
     if (_hasFailed) {
-      sink._sendData(inputEvent);
+      sink._add(inputEvent);
       return;
     }
     bool satisfies;
     try {
       satisfies = _test(inputEvent);
     } catch (e, s) {
-      sink._sendError(_asyncError(e, s));
+      sink._addError(_asyncError(e, s));
       // A failure to return a boolean is considered "not matching".
       _hasFailed = true;
       return;
     }
     if (!satisfies) {
       _hasFailed = true;
-      sink._sendData(inputEvent);
+      sink._add(inputEvent);
     }
   }
 }
@@ -448,10 +376,10 @@
   _DistinctStream(Stream<T> source, bool equals(T a, T b))
       : _equals = equals, super(source);
 
-  void _handleData(T inputEvent, _EventOutputSink<T> sink) {
+  void _handleData(T inputEvent, _EventSink<T> sink) {
     if (identical(_previous, _SENTINEL)) {
       _previous = inputEvent;
-      return sink._sendData(inputEvent);
+      return sink._add(inputEvent);
     } else {
       bool isEqual;
       try {
@@ -461,11 +389,11 @@
           isEqual = _equals(_previous, inputEvent);
         }
       } catch (e, s) {
-        sink._sendError(_asyncError(e, s));
+        sink._addError(_asyncError(e, s));
         return null;
       }
       if (!isEqual) {
-        sink._sendData(inputEvent);
+        sink._add(inputEvent);
         _previous = inputEvent;
       }
     }
diff --git a/sdk/lib/collection/hash_map.dart b/sdk/lib/collection/hash_map.dart
index f5fcd85..431c89f 100644
--- a/sdk/lib/collection/hash_map.dart
+++ b/sdk/lib/collection/hash_map.dart
@@ -13,6 +13,7 @@
 
   external int get length;
   external bool get isEmpty;
+  external bool get isNotEmpty;
 
   external Iterable<K> get keys;
   external Iterable<V> get values;
diff --git a/sdk/lib/collection/hash_set.dart b/sdk/lib/collection/hash_set.dart
index c459f99..8d484db 100644
--- a/sdk/lib/collection/hash_set.dart
+++ b/sdk/lib/collection/hash_set.dart
@@ -70,6 +70,8 @@
 
   external bool get isEmpty;
 
+  external bool get isNotEmpty;
+
   external bool contains(Object object);
 
   // Collection.
diff --git a/sdk/lib/collection/iterable.dart b/sdk/lib/collection/iterable.dart
index 2ec143b..a950543 100644
--- a/sdk/lib/collection/iterable.dart
+++ b/sdk/lib/collection/iterable.dart
@@ -95,6 +95,8 @@
 
   bool get isEmpty => !iterator.moveNext();
 
+  bool get isNotEmpty => !isEmpty;
+
   Iterable<E> take(int n) {
     return new TakeIterable<E>(this, n);
   }
@@ -287,6 +289,8 @@
 
   bool get isEmpty => !iterator.moveNext();
 
+  bool get isNotEmpty => !isEmpty;
+
   Iterable<E> take(int n) {
     return new TakeIterable<E>(this, n);
   }
diff --git a/sdk/lib/collection/linked_hash_map.dart b/sdk/lib/collection/linked_hash_map.dart
index 431f7fa..d41cb40 100644
--- a/sdk/lib/collection/linked_hash_map.dart
+++ b/sdk/lib/collection/linked_hash_map.dart
@@ -39,5 +39,7 @@
 
   external bool get isEmpty;
 
+  external bool get isNotEmpty;
+
   String toString() => Maps.mapToString(this);
 }
diff --git a/sdk/lib/collection/linked_hash_set.dart b/sdk/lib/collection/linked_hash_set.dart
index e866b63..ee9cdb1 100644
--- a/sdk/lib/collection/linked_hash_set.dart
+++ b/sdk/lib/collection/linked_hash_set.dart
@@ -19,6 +19,8 @@
 
   external bool get isEmpty;
 
+  external bool get isNotEmpty;
+
   external bool contains(Object object);
 
   external void forEach(void action(E element));
diff --git a/sdk/lib/collection/list.dart b/sdk/lib/collection/list.dart
index aab99d8..fa1bd50 100644
--- a/sdk/lib/collection/list.dart
+++ b/sdk/lib/collection/list.dart
@@ -45,6 +45,8 @@
 
   bool get isEmpty => length == 0;
 
+  bool get isNotEmpty => !isEmpty;
+
   E get first {
     if (length == 0) throw new StateError("No elements");
     return this[0];
diff --git a/sdk/lib/collection/maps.dart b/sdk/lib/collection/maps.dart
index b4eef3f..bd7d755 100644
--- a/sdk/lib/collection/maps.dart
+++ b/sdk/lib/collection/maps.dart
@@ -58,6 +58,8 @@
 
   static bool isEmpty(Map map) => map.keys.isEmpty;
 
+  static bool isNotEmpty(Map map) => map.keys.isNotEmpty;
+
   /**
    * Returns a string representing the specified map. The returned string
    * looks like this: [:'{key0: value0, key1: value1, ... keyN: valueN}':].
diff --git a/sdk/lib/collection/splay_tree.dart b/sdk/lib/collection/splay_tree.dart
index 1461cc6..b959a55 100644
--- a/sdk/lib/collection/splay_tree.dart
+++ b/sdk/lib/collection/splay_tree.dart
@@ -313,6 +313,8 @@
     return (_root == null);
   }
 
+  bool get isNotEmpty => !isEmpty;
+
   void forEach(void f(K key, V value)) {
     Iterator<_SplayTreeNode<K>> nodes =
         new _SplayTreeNodeIterator<K>(this);
diff --git a/sdk/lib/core/core.dart b/sdk/lib/core/core.dart
index 391000c..de7fc4a 100644
--- a/sdk/lib/core/core.dart
+++ b/sdk/lib/core/core.dart
@@ -7,6 +7,7 @@
 import "dart:collection";
 import "dart:_collection-dev" hide Symbol;
 import "dart:_collection-dev" as _collection_dev;
+import "dart:utf" show codepointsToUtf8, decodeUtf8;
 
 part "bool.dart";
 part "comparable.dart";
@@ -37,3 +38,4 @@
 part "string_sink.dart";
 part "symbol.dart";
 part "type.dart";
+part "uri.dart";
diff --git a/sdk/lib/core/corelib_sources.gypi b/sdk/lib/core/corelib_sources.gypi
index 9d6126fa..faafe0a 100644
--- a/sdk/lib/core/corelib_sources.gypi
+++ b/sdk/lib/core/corelib_sources.gypi
@@ -35,5 +35,6 @@
     'string_sink.dart',
     'symbol.dart',
     'type.dart',
+    'uri.dart',
   ],
 }
diff --git a/sdk/lib/core/iterable.dart b/sdk/lib/core/iterable.dart
index b802cfd..03127c8 100644
--- a/sdk/lib/core/iterable.dart
+++ b/sdk/lib/core/iterable.dart
@@ -162,6 +162,11 @@
   bool get isEmpty;
 
   /**
+   * Returns true if there is at least one element in this collection.
+   */
+  bool get isNotEmpty;
+
+  /**
    * Returns an [Iterable] with at most [n] elements.
    *
    * The returned [Iterable] may contain fewer than [n] elements, if `this`
diff --git a/sdk/lib/core/map.dart b/sdk/lib/core/map.dart
index de3807f..fe68fd8 100644
--- a/sdk/lib/core/map.dart
+++ b/sdk/lib/core/map.dart
@@ -93,4 +93,9 @@
    * Returns true if there is no {key, value} pair in the map.
    */
   bool get isEmpty;
+
+  /**
+   * Returns true if there is at least one {key, value} pair in the map.
+   */
+  bool get isNotEmpty;
 }
diff --git a/sdk/lib/core/string.dart b/sdk/lib/core/string.dart
index 7db20f3..3f0ad31 100644
--- a/sdk/lib/core/string.dart
+++ b/sdk/lib/core/string.dart
@@ -129,6 +129,11 @@
   bool get isEmpty;
 
   /**
+   * Returns whether this string is not empty.
+   */
+  bool get isNotEmpty;
+
+  /**
    * Creates a new string by concatenating this string with [other].
    *
    * A sequence of strings can be concatenated by using [Iterable.join]:
diff --git a/sdk/lib/core/string_buffer.dart b/sdk/lib/core/string_buffer.dart
index 8ea4bf1..59d1aa9 100644
--- a/sdk/lib/core/string_buffer.dart
+++ b/sdk/lib/core/string_buffer.dart
@@ -23,6 +23,12 @@
   /** Returns whether the buffer is empty. This is a constant-time operation. */
   bool get isEmpty => length == 0;
 
+  /**
+   * Returns whether the buffer is not empty. This is a constant-time
+   * operation.
+   */
+  bool get isNotEmpty => !isEmpty;
+
   /// Adds the contents of [obj], converted to a string, to the buffer.
   external void write(Object obj);
 
diff --git a/sdk/lib/core/uri.dart b/sdk/lib/core/uri.dart
new file mode 100644
index 0000000..c8277e7
--- /dev/null
+++ b/sdk/lib/core/uri.dart
@@ -0,0 +1,946 @@
+// 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.
+
+part of dart.core;
+
+/**
+ * A parsed URI, as specified by RFC-3986, http://tools.ietf.org/html/rfc3986.
+ */
+class Uri {
+  int _port;
+
+  /**
+   * Returns the scheme component.
+   *
+   * Returns the empty string if there is no scheme component.
+   */
+  final String scheme;
+
+  /**
+   * Returns the authority component.
+   *
+   * The authority is formatted from the [userInfo], [host] and [port]
+   * parts.
+   *
+   * Returns the empty string if there is no authority component.
+   */
+  String get authority {
+    if (!hasAuthority) return "";
+    var sb = new StringBuffer();
+    _writeAuthority(sb);
+    return sb.toString();
+  }
+
+  /**
+   * Returns the user info part of the authority component.
+   *
+   * Returns the empty string if there is no user info in the
+   * authority component.
+   */
+  final String userInfo;
+
+  /**
+   * Returns the host part of the authority component.
+   *
+   * Returns the empty string if there is no authority component and
+   * hence no host.
+   */
+  final String host;
+
+  /**
+   * Returns the port part of the authority component.
+   *
+   * Returns 0 if there is no port in the authority component.
+   */
+  int get port => _port;
+
+  /**
+   * Returns the path component.
+   *
+   * The returned path is encoded. To get direct access to the decoded
+   * path use [pathSegments].
+   *
+   * Returns the empty string if there is no path component.
+   */
+  final String path;
+
+  /**
+   * Returns the query component. The returned query is encoded. To get
+   * direct access to the decoded query use [queryParameters].
+   *
+   * Returns the empty string if there is no query component.
+   */
+  final String query;
+
+  /**
+   * Returns the fragment identifier component.
+   *
+   * Returns the empty string if there is no fragment identifier
+   * component.
+   */
+  final String fragment;
+
+  /**
+   * Creates a new URI object by parsing a URI string.
+   */
+  static Uri parse(String uri) => new Uri._fromMatch(_splitRe.firstMatch(uri));
+
+  Uri._fromMatch(Match m) :
+    this(scheme: _emptyIfNull(m[_COMPONENT_SCHEME]),
+         userInfo: _emptyIfNull(m[_COMPONENT_USER_INFO]),
+         host: _eitherOf(
+         m[_COMPONENT_HOST], m[_COMPONENT_HOST_IPV6]),
+         port: _parseIntOrZero(m[_COMPONENT_PORT]),
+         path: _emptyIfNull(m[_COMPONENT_PATH]),
+         query: _emptyIfNull(m[_COMPONENT_QUERY_DATA]),
+         fragment: _emptyIfNull(m[_COMPONENT_FRAGMENT]));
+
+  /*
+   * Create a new URI from its components.
+   *
+   * Each component is set through a named argument. Any number of
+   * components can be provided. The default value for the components
+   * not provided is the empry string, except for [port] which has a
+   * default value of 0. The [path] and [query] components can be set
+   * using two different named arguments.
+   *
+   * The scheme component is set through [scheme]. The scheme is
+   * normalized to all lowercase letters.
+   *
+   * The user info part of the authority component is set through
+   * [userInfo].
+   *
+   * The host part of the authority component is set through
+   * [host]. The host can either be a hostname, a IPv4 address or an
+   * IPv6 address, contained in '[' and ']'. If the host contains a
+   * ':' character, the '[' and ']' are added if not already provided.
+   *
+   * The port part of the authority component is set through
+   * [port]. The port is normalized for scheme http and https where
+   * port 80 and port 443 respectively is set.
+   *
+   * The path component is set through either [path] or
+   * [pathSegments]. When [path] is used, the provided string is
+   * expected to be fully percent-encoded, and is used in its literal
+   * form. When [pathSegments] is used, each of the provided segments
+   * is percent-encoded and joined using the forward slash
+   * separator. The percent-encoding of the path segments encodes all
+   * characters except for the unreserved characters and the following
+   * list of characters: `!$&'()*+,;=:@`.
+   *
+   * The query component is set through either [query] or
+   * [queryParameters]. When [query] is used the provided string is
+   * expected to be fully percent-encoded and is used in its literal
+   * form. When [queryParameters] is used the query is built from the
+   * provided map. Each key and value in the map is percent-encoded
+   * and joined using equal and ampersand characters. The
+   * percent-encoding of the keys and values encodes all characters
+   * except for the unreserved characters.
+   *
+   * The fragment component is set through [fragment].
+   */
+  Uri({scheme,
+       this.userInfo: "",
+       this.host: "",
+       port: 0,
+       String path,
+       List<String> pathSegments,
+       String query,
+       Map<String, String> queryParameters,
+       fragment: ""}) :
+      scheme = _makeScheme(scheme),
+      path = _makePath(path, pathSegments),
+      query = _makeQuery(query, queryParameters),
+      fragment = _makeFragment(fragment) {
+    // Perform scheme specific normalization.
+    if (scheme == "http" && port == 80) {
+      _port = 0;
+    } else if (scheme == "https" && port == 443) {
+      _port = 0;
+    } else {
+      _port = port;
+    }
+  }
+
+  /*
+   * Returns the URI path split into its segments. Each of the
+   * segments in the returned list have been decoded. If the path is
+   * empty the empty list will be returned.
+   */
+  List<String> get pathSegments {
+    if (path == "") return const<String>[];
+    return path.split("/").map(Uri.decodeComponent).toList(growable: false);
+  }
+
+  /*
+   * Returns the URI query split into a map according to the rules
+   * specified for FORM post in the HTML 4.01 specification. Each key
+   * and value in the returned map have been decoded. If there is no
+   * query the empty map will be returned.
+   */
+  Map<String, String> get queryParameters {
+    return query.split("&").fold({}, (map, element) {
+        int index = element.indexOf("=");
+        if (index == -1) {
+          if (!element.isEmpty) map[element] = "";
+        } else if (index != 0) {
+          var key = element.substring(0, index);
+          var value = element.substring(index + 1);
+          map[Uri.decodeQueryComponent(key)] = decodeQueryComponent(value);
+        }
+        return map;
+    });
+  }
+
+  static String _makeScheme(String scheme) {
+    bool isSchemeLowerCharacter(int ch) {
+      return ch < 128 &&
+             ((_schemeLowerTable[ch >> 4] & (1 << (ch & 0x0f))) != 0);
+    }
+
+    bool isSchemeCharacter(int ch) {
+      return ch < 128 && ((_schemeTable[ch >> 4] & (1 << (ch & 0x0f))) != 0);
+    }
+
+    if (scheme == null) return "";
+    bool allLowercase = true;
+    int length = scheme.length;
+    for (int i = 0; i < length; i++) {
+      int codeUnit = scheme.codeUnitAt(i);
+      if (!isSchemeLowerCharacter(codeUnit)) {
+        if (isSchemeCharacter(codeUnit)) {
+          allLowercase = false;
+        } else {
+          throw new ArgumentError('Illegal scheme: $scheme');
+        }
+      }
+    }
+
+    return allLowercase ? scheme : scheme.toLowerCase();
+  }
+
+  static String _makePath(String path, List<String> pathSegments) {
+    if (path == null && pathSegments == null) return "";
+    if (path != null && pathSegments != null) {
+      throw new ArgumentError('Both path and pathSegments specified');
+    }
+    if (path != null) return _normalize(path);
+
+    return pathSegments.map((s) => _uriEncode(_pathCharTable, s)).join("/");
+  }
+
+  static String _makeQuery(String query, Map<String, String> queryParameters) {
+    if (query == null && queryParameters == null) return "";
+    if (query != null && queryParameters != null) {
+      throw new ArgumentError('Both query and queryParameters specified');
+    }
+    if (query != null) return _normalize(query);
+
+    var result = new StringBuffer();
+    var first = true;
+    queryParameters.forEach((key, value) {
+      if (!first) {
+        result.write("&");
+      }
+      first = false;
+      result.write(Uri.encodeQueryComponent(key));
+      if (value != null && !value.isEmpty) {
+        result.write("=");
+        result.write(Uri.encodeQueryComponent(value));
+      }
+    });
+    return result.toString();
+  }
+
+  static String _makeFragment(String fragment) {
+    if (fragment == null) return "";
+    return _normalize(fragment);
+  }
+
+  static String _normalize(String component) {
+    bool isNormalizedHexDigit(int digit) {
+      return (_ZERO <= digit && digit <= _NINE) ||
+          (_UPPER_CASE_A <= digit && digit <= _UPPER_CASE_F);
+    }
+
+    bool isLowerCaseHexDigit(int digit) {
+      return _LOWER_CASE_A <= digit && digit <= _LOWER_CASE_F;
+    }
+
+    bool isUnreserved(int ch) {
+      return ch < 128 &&
+             ((_unreservedTable[ch >> 4] & (1 << (ch & 0x0f))) != 0);
+    }
+
+    int normalizeHexDigit(int index) {
+      var codeUnit = component.codeUnitAt(index);
+      if (isLowerCaseHexDigit(codeUnit)) {
+        return codeUnit - 0x20;
+      } else if (!isNormalizedHexDigit(codeUnit)) {
+        throw new ArgumentError("Invalid URI component: $component");
+      } else {
+        return codeUnit;
+      }
+    }
+
+    int decodeHexDigitPair(int index) {
+      int byte = 0;
+      for (int i = 0; i < 2; i++) {
+        var codeUnit = component.codeUnitAt(index + i);
+        if (_ZERO <= codeUnit && codeUnit <= _NINE) {
+          byte = byte * 16 + codeUnit - _ZERO;
+        } else {
+          // Check ranges A-F (0x41-0x46) and a-f (0x61-0x66).
+          codeUnit |= 0x20;
+          if (_LOWER_CASE_A <= codeUnit &&
+              codeUnit <= _LOWER_CASE_F) {
+            byte = byte * 16 + codeUnit - _LOWER_CASE_A + 10;
+          } else {
+            throw new ArgumentError(
+                "Invalid percent-encoding in URI component: $component");
+          }
+        }
+      }
+      return byte;
+    }
+
+    // Start building the normalized component string.
+    StringBuffer result;
+    int length = component.length;
+    int index = 0;
+    int prevIndex = 0;
+    while (index < length) {
+
+      // Copy a part of the component string to the result.
+      fillResult() {
+        if (result == null) {
+          assert(prevIndex == 0);
+          result = new StringBuffer(component.substring(prevIndex, index));
+        } else {
+          result.write(component.substring(prevIndex, index));
+        }
+      }
+
+      // Normalize percent encoding to uppercase and don't encode
+      // unreserved characters.
+      if (component.codeUnitAt(index) == _PERCENT) {
+        if (length < index + 2) {
+            throw new ArgumentError(
+                "Invalid percent-encoding in URI component: $component");
+        }
+
+        var codeUnit1 = component.codeUnitAt(index + 1);
+        var codeUnit2 = component.codeUnitAt(index + 2);
+        var decodedCodeUnit = decodeHexDigitPair(index + 1);
+        if (isNormalizedHexDigit(codeUnit1) &&
+            isNormalizedHexDigit(codeUnit2) &&
+            !isUnreserved(decodedCodeUnit)) {
+          index += 3;
+        } else {
+          fillResult();
+          if (isUnreserved(decodedCodeUnit)) {
+            result.writeCharCode(decodedCodeUnit);
+          } else {
+            result.write("%");
+            result.writeCharCode(normalizeHexDigit(index + 1));
+            result.writeCharCode(normalizeHexDigit(index + 2));
+          }
+          index += 3;
+          prevIndex = index;
+        }
+      } else {
+        index++;
+      }
+    }
+    assert(index == length);
+
+    if (result == null) return component;
+    return result.toString();
+  }
+
+  static String _emptyIfNull(String val) => val != null ? val : '';
+
+  static int _parseIntOrZero(String val) {
+    if (val != null && val != '') {
+      return int.parse(val);
+    } else {
+      return 0;
+    }
+  }
+
+  static String _eitherOf(String val1, String val2) {
+    if (val1 != null) return val1;
+    if (val2 != null) return val2;
+    return '';
+  }
+
+  // NOTE: This code was ported from: closure-library/closure/goog/uri/utils.js
+  static final RegExp _splitRe = new RegExp(
+      '^'
+      '(?:'
+        '([^:/?#.]+)'                   // scheme - ignore special characters
+                                        // used by other URL parts such as :,
+                                        // ?, /, #, and .
+      ':)?'
+      '(?://'
+        '(?:([^/?#]*)@)?'               // userInfo
+        '(?:'
+          r'([\w\d\-\u0100-\uffff.%]*)'
+                                        // host - restrict to letters,
+                                        // digits, dashes, dots, percent
+                                        // escapes, and unicode characters.
+          '|'
+          // TODO(ajohnsen): Only allow a max number of parts?
+          r'\[([A-Fa-f0-9:.]*)\])'
+                                        // IPv6 host - restrict to hex,
+                                        // dot and colon.
+        '(?::([0-9]+))?'                // port
+      ')?'
+      r'([^?#[]+)?'                     // path
+      r'(?:\?([^#]*))?'                 // query
+      '(?:#(.*))?'                      // fragment
+      r'$');
+
+  static const _COMPONENT_SCHEME = 1;
+  static const _COMPONENT_USER_INFO = 2;
+  static const _COMPONENT_HOST = 3;
+  static const _COMPONENT_HOST_IPV6 = 4;
+  static const _COMPONENT_PORT = 5;
+  static const _COMPONENT_PATH = 6;
+  static const _COMPONENT_QUERY_DATA = 7;
+  static const _COMPONENT_FRAGMENT = 8;
+
+  /**
+   * Returns whether the URI is absolute.
+   */
+  bool get isAbsolute => scheme != "" && fragment == "";
+
+  String _merge(String base, String reference) {
+    if (base == "") return "/$reference";
+    return "${base.substring(0, base.lastIndexOf("/") + 1)}$reference";
+  }
+
+  bool _hasDotSegments(String path) {
+    if (path.length > 0 && path.codeUnitAt(0) == _COLON) return true;
+    int index = path.indexOf("/.");
+    return index != -1;
+  }
+
+  String _removeDotSegments(String path) {
+    if (!_hasDotSegments(path)) return path;
+    List<String> output = [];
+    bool appendSlash = false;
+    for (String segment in path.split("/")) {
+      appendSlash = false;
+      if (segment == "..") {
+        if (!output.isEmpty &&
+            ((output.length != 1) || (output[0] != ""))) output.removeLast();
+        appendSlash = true;
+      } else if ("." == segment) {
+        appendSlash = true;
+      } else {
+        output.add(segment);
+      }
+    }
+    if (appendSlash) output.add("");
+    return output.join("/");
+  }
+
+  Uri resolve(String uri) {
+    return resolveUri(Uri.parse(uri));
+  }
+
+  Uri resolveUri(Uri reference) {
+    // From RFC 3986.
+    String targetScheme;
+    String targetUserInfo;
+    String targetHost;
+    int targetPort;
+    String targetPath;
+    String targetQuery;
+    if (reference.scheme != "") {
+      targetScheme = reference.scheme;
+      targetUserInfo = reference.userInfo;
+      targetHost = reference.host;
+      targetPort = reference.port;
+      targetPath = _removeDotSegments(reference.path);
+      targetQuery = reference.query;
+    } else {
+      if (reference.hasAuthority) {
+        targetUserInfo = reference.userInfo;
+        targetHost = reference.host;
+        targetPort = reference.port;
+        targetPath = _removeDotSegments(reference.path);
+        targetQuery = reference.query;
+      } else {
+        if (reference.path == "") {
+          targetPath = this.path;
+          if (reference.query != "") {
+            targetQuery = reference.query;
+          } else {
+            targetQuery = this.query;
+          }
+        } else {
+          if (reference.path.startsWith("/")) {
+            targetPath = _removeDotSegments(reference.path);
+          } else {
+            targetPath = _removeDotSegments(_merge(this.path, reference.path));
+          }
+          targetQuery = reference.query;
+        }
+        targetUserInfo = this.userInfo;
+        targetHost = this.host;
+        targetPort = this.port;
+      }
+      targetScheme = this.scheme;
+    }
+    return new Uri(scheme: targetScheme,
+                   userInfo: targetUserInfo,
+                   host: targetHost,
+                   port: targetPort,
+                   path: targetPath,
+                   query: targetQuery,
+                   fragment: reference.fragment);
+  }
+
+  bool get hasAuthority => host != "";
+
+  /**
+   * Returns the origin of the URI in the form scheme://host:port for the
+   * schemes http and https.
+   *
+   * It is an error if the scheme is not "http" or "https".
+   *
+   * See: http://www.w3.org/TR/2011/WD-html5-20110405/origin-0.html#origin
+   */
+  String get origin {
+    if (scheme == "" || host == null || host == "") {
+      throw new StateError("Cannot use origin without a scheme: $this");
+    }
+    if (scheme != "http" && scheme != "https") {
+      throw new StateError(
+        "Origin is only applicable schemes http and https: $this");
+    }
+    if (port == 0) return "$scheme://$host";
+    return "$scheme://$host:$port";
+  }
+
+  void _writeAuthority(StringSink ss) {
+    _addIfNonEmpty(ss, userInfo, userInfo, "@");
+    ss.write(host == null ? "null" :
+             host.contains(':') ? '[$host]' : host);
+    if (port != 0) {
+      ss.write(":");
+      ss.write(port.toString());
+    }
+  }
+
+  String toString() {
+    StringBuffer sb = new StringBuffer();
+    _addIfNonEmpty(sb, scheme, scheme, ':');
+    if (hasAuthority || (scheme == "file")) {
+      sb.write("//");
+      _writeAuthority(sb);
+    }
+    sb.write(path);
+    _addIfNonEmpty(sb, query, "?", query);
+    _addIfNonEmpty(sb, fragment, "#", fragment);
+    return sb.toString();
+  }
+
+  bool operator==(other) {
+    if (other is! Uri) return false;
+    Uri uri = other;
+    return scheme == uri.scheme &&
+        userInfo == uri.userInfo &&
+        host == uri.host &&
+        port == uri.port &&
+        path == uri.path &&
+        query == uri.query &&
+        fragment == uri.fragment;
+  }
+
+  int get hashCode {
+    int combine(part, current) {
+      // The sum is truncated to 30 bits to make sure it fits into a Smi.
+      return (current * 31 + part.hashCode) & 0x3FFFFFFF;
+    }
+    return combine(scheme, combine(userInfo, combine(host, combine(port,
+        combine(path, combine(query, combine(fragment, 1)))))));
+  }
+
+  static void _addIfNonEmpty(StringBuffer sb, String test,
+                             String first, String second) {
+    if ("" != test) {
+      sb.write(first);
+      sb.write(second);
+    }
+  }
+
+  /**
+   * Encode the string [component] using percent-encoding to make it
+   * safe for literal use as a URI component.
+   *
+   * All characters except uppercase and lowercase letters, digits and
+   * the characters `!$&'()*+,;=:@` are percent-encoded. This is the
+   * set of characters specified in RFC 2396 and the which is
+   * specified for the encodeUriComponent in ECMA-262 version 5.1.
+   *
+   * When manually encoding path segments or query components remember
+   * to encode each part separately before building the path or query
+   * string.
+   *
+   * For encoding the query part consider using
+   * [encodeQueryComponent].
+   *
+   * To avoid the need for explicitly encoding use the [pathSegments]
+   * and [queryParameters] optional named arguments when constructing
+   * a [Uri].
+   */
+  static String encodeComponent(String component) {
+    return _uriEncode(_unreserved2396Table, component);
+  }
+
+  /*
+   * Encode the string [component] according to the HTML 4.01 rules
+   * for encoding the posting of a HTML form as a query string
+   * component.
+   *
+   * Spaces will be replaced with plus and all characters except for
+   * uppercase and lowercase letters, decimal digits and the
+   * characters `-._~`. Note that the set of characters encoded is a
+   * superset of what HTML 4.01 says as it refers to RFC 1738 for
+   * reserved characters.
+   *
+   * When manually encoding query components remember to encode each
+   * part separately before building the query string.
+   *
+   * To avoid the need for explicitly encoding the query use the
+   * [queryParameters] optional named arguments when constructing a
+   * [Uri].
+   *
+   * See http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.2 for more
+   * details.
+   */
+  static String encodeQueryComponent(String component) {
+    return _uriEncode(_unreservedTable, component, spaceToPlus: true);
+  }
+
+  /**
+   * Decodes the percent-encoding in [encodedComponent].
+   *
+   * Note that decoding a URI component might change its meaning as
+   * some of the decoded characters could be characters with are
+   * delimiters for a given URI componene type. Always split a URI
+   * component using the delimiters for the component before decoding
+   * the individual parts.
+   *
+   * For handling the [path] and [query] components consider using
+   * [pathSegments] and [queryParameters] to get the separated and
+   * decoded component.
+   */
+  static String decodeComponent(String encodedComponent) {
+    return _uriDecode(encodedComponent);
+  }
+
+  static String decodeQueryComponent(String encodedComponent) {
+    return _uriDecode(encodedComponent, plusToSpace: true);
+  }
+
+  /**
+   * Encode the string [uri] using percent-encoding to make it
+   * safe for literal use as a full URI.
+   *
+   * All characters except uppercase and lowercase letters, digits and
+   * the characters `!#$&'()*+,-./:;=?@_~` are percent-encoded. This
+   * is the set of characters specified in in ECMA-262 version 5.1 for
+   * the encodeURI function .
+   */
+  static String encodeFull(String uri) {
+    return _uriEncode(_encodeFullTable, uri);
+  }
+
+  /**
+   * Decodes the percent-encoding in [uri].
+   *
+   * Note that decoding a full URI might change its meaning as some of
+   * the decoded characters could be reserved characters. In most
+   * cases an encoded URI should be parsed into components using
+   * [Uri.parse] before decoding the separate components.
+   */
+  static String decodeFull(String uri) {
+    return _uriDecode(uri);
+  }
+
+  // Frequently used character codes.
+  static const int _PERCENT = 0x25;
+  static const int _PLUS = 0x2B;
+  static const int _ZERO = 0x30;
+  static const int _NINE = 0x39;
+  static const int _COLON = 0x3A;
+  static const int _UPPER_CASE_A = 0x41;
+  static const int _UPPER_CASE_F = 0x46;
+  static const int _LOWER_CASE_A = 0x61;
+  static const int _LOWER_CASE_F = 0x66;
+
+  /**
+   * This is the internal implementation of JavaScript's encodeURI function.
+   * It encodes all characters in the string [text] except for those
+   * that appear in [canonicalTable], and returns the escaped string.
+   */
+  static String _uriEncode(List<int> canonicalTable,
+                    String text,
+                    {bool spaceToPlus: false}) {
+    byteToHex(int v) {
+      final String hex = '0123456789ABCDEF';
+      return '%${hex[v >> 4]}${hex[v & 0x0f]}';
+    }
+
+    StringBuffer result = new StringBuffer();
+    for (int i = 0; i < text.length; i++) {
+      int ch = text.codeUnitAt(i);
+      if (ch < 128 && ((canonicalTable[ch >> 4] & (1 << (ch & 0x0f))) != 0)) {
+        result.write(text[i]);
+      } else if (spaceToPlus && text[i] == " ") {
+        result.write("+");
+      } else {
+        if (ch >= 0xD800 && ch < 0xDC00) {
+          // Low surrogate. We expect a next char high surrogate.
+          ++i;
+          int nextCh = text.length == i ? 0 : text.codeUnitAt(i);
+          if (nextCh >= 0xDC00 && nextCh < 0xE000) {
+            // convert the pair to a U+10000 codepoint
+            ch = 0x10000 + ((ch - 0xD800) << 10) + (nextCh - 0xDC00);
+          } else {
+            throw new ArgumentError('Malformed URI');
+          }
+        }
+        for (int codepoint in codepointsToUtf8([ch])) {
+          result.write(byteToHex(codepoint));
+        }
+      }
+    }
+    return result.toString();
+  }
+
+  /**
+   * Convert a byte (2 character hex sequence) in string [s] starting
+   * at position [pos] to its ordinal value
+   */
+  static int _hexCharPairToByte(String s, int pos) {
+    int byte = 0;
+    for (int i = 0; i < 2; i++) {
+      var charCode = s.codeUnitAt(pos + i);
+      if (0x30 <= charCode && charCode <= 0x39) {
+        byte = byte * 16 + charCode - 0x30;
+      } else {
+        // Check ranges A-F (0x41-0x46) and a-f (0x61-0x66).
+        charCode |= 0x20;
+        if (0x61 <= charCode && charCode <= 0x66) {
+          byte = byte * 16 + charCode - 0x57;
+        } else {
+          throw new ArgumentError("Invalid URL encoding");
+        }
+      }
+    }
+    return byte;
+  }
+
+  /**
+   * A JavaScript-like decodeURI function. It unescapes the string [text] and
+   * returns the unescaped string.
+   */
+  static String _uriDecode(String text, {bool plusToSpace: false}) {
+    StringBuffer result = new StringBuffer();
+    List<int> codepoints = new List<int>();
+    for (int i = 0; i < text.length;) {
+      int ch = text.codeUnitAt(i);
+      if (ch != _PERCENT) {
+        if (plusToSpace && ch == _PLUS) {
+          result.write(" ");
+        } else {
+          result.writeCharCode(ch);
+        }
+        i++;
+      } else {
+        codepoints.clear();
+        while (ch == _PERCENT) {
+          if (++i > text.length - 2) {
+            throw new ArgumentError('Truncated URI');
+          }
+          codepoints.add(_hexCharPairToByte(text, i));
+          i += 2;
+          if (i == text.length) break;
+          ch = text.codeUnitAt(i);
+        }
+        result.write(decodeUtf8(codepoints));
+      }
+    }
+    return result.toString();
+  }
+
+  // Tables of char-codes organized as a bit vector of 128 bits where
+  // each bit indicate whether a character code on the 0-127 needs to
+  // be escaped or not.
+
+  // The unreserved characters of RFC 3986.
+  static const _unreservedTable = const [
+                //             LSB            MSB
+                //              |              |
+      0x0000,   // 0x00 - 0x0f  0000000000000000
+      0x0000,   // 0x10 - 0x1f  0000000000000000
+                //                           -.
+      0x6000,   // 0x20 - 0x2f  0000000000000110
+                //              0123456789
+      0x03ff,   // 0x30 - 0x3f  1111111111000000
+                //               ABCDEFGHIJKLMNO
+      0xfffe,   // 0x40 - 0x4f  0111111111111111
+                //              PQRSTUVWXYZ    _
+      0x87ff,   // 0x50 - 0x5f  1111111111100001
+                //               abcdefghijklmno
+      0xfffe,   // 0x60 - 0x6f  0111111111111111
+                //              pqrstuvwxyz   ~
+      0x47ff];  // 0x70 - 0x7f  1111111111100010
+
+  // The unreserved characters of RFC 2396.
+  static const _unreserved2396Table = const [
+                //             LSB            MSB
+                //              |              |
+      0x0000,   // 0x00 - 0x0f  0000000000000000
+      0x0000,   // 0x10 - 0x1f  0000000000000000
+                //               !     '()*  -.
+      0x6782,   // 0x20 - 0x2f  0100000111100110
+                //              0123456789
+      0x03ff,   // 0x30 - 0x3f  1111111111000000
+                //               ABCDEFGHIJKLMNO
+      0xfffe,   // 0x40 - 0x4f  0111111111111111
+                //              PQRSTUVWXYZ    _
+      0x87ff,   // 0x50 - 0x5f  1111111111100001
+                //               abcdefghijklmno
+      0xfffe,   // 0x60 - 0x6f  0111111111111111
+                //              pqrstuvwxyz   ~
+      0x47ff];  // 0x70 - 0x7f  1111111111100010
+
+  // Table of reserved characters specified by ECMAScript 5.
+  static const _encodeFullTable = const [
+                //             LSB            MSB
+                //              |              |
+      0x0000,   // 0x00 - 0x0f  0000000000000000
+      0x0000,   // 0x10 - 0x1f  0000000000000000
+                //               ! #$ &'()*+,-./
+      0xf7da,   // 0x20 - 0x2f  0101101111101111
+                //              0123456789:; = ?
+      0xafff,   // 0x30 - 0x3f  1111111111110101
+                //              @ABCDEFGHIJKLMNO
+      0xffff,   // 0x40 - 0x4f  1111111111111111
+                //              PQRSTUVWXYZ    _
+      0x87ff,   // 0x50 - 0x5f  1111111111100001
+                //               abcdefghijklmno
+      0xfffe,   // 0x60 - 0x6f  0111111111111111
+                //              pqrstuvwxyz   ~
+      0x47ff];  // 0x70 - 0x7f  1111111111100010
+
+  // Characters allowed in the scheme.
+  static const _schemeTable = const [
+                //             LSB            MSB
+                //              |              |
+      0x0000,   // 0x00 - 0x0f  0000000000000000
+      0x0000,   // 0x10 - 0x1f  0000000000000000
+                //                         + -.
+      0x6800,   // 0x20 - 0x2f  0000000000010110
+                //              0123456789
+      0x03ff,   // 0x30 - 0x3f  1111111111000000
+                //               ABCDEFGHIJKLMNO
+      0xfffe,   // 0x40 - 0x4f  0111111111111111
+                //              PQRSTUVWXYZ
+      0x07ff,   // 0x50 - 0x5f  1111111111100001
+                //               abcdefghijklmno
+      0xfffe,   // 0x60 - 0x6f  0111111111111111
+                //              pqrstuvwxyz
+      0x07ff];  // 0x70 - 0x7f  1111111111100010
+
+  // Characters allowed in scheme except for upper case letters.
+  static const _schemeLowerTable = const [
+                //             LSB            MSB
+                //              |              |
+      0x0000,   // 0x00 - 0x0f  0000000000000000
+      0x0000,   // 0x10 - 0x1f  0000000000000000
+                //                         + -.
+      0x6800,   // 0x20 - 0x2f  0000000000010110
+                //              0123456789
+      0x03ff,   // 0x30 - 0x3f  1111111111000000
+                //
+      0x0000,   // 0x40 - 0x4f  0111111111111111
+                //
+      0x0000,   // 0x50 - 0x5f  1111111111100001
+                //               abcdefghijklmno
+      0xfffe,   // 0x60 - 0x6f  0111111111111111
+                //              pqrstuvwxyz
+      0x07ff];  // 0x70 - 0x7f  1111111111100010
+
+  // Sub delimiter characters combined with unreserved as of 3986.
+  // sub-delims  = "!" / "$" / "&" / "'" / "(" / ")"
+  //             / "*" / "+" / "," / ";" / "="
+  // RFC 3986 section 2.3.
+  // unreserved  = ALPHA / DIGIT / "-" / "." / "_" / "~"
+  static const _subDelimitersTable = const [
+                //             LSB            MSB
+                //              |              |
+      0x0000,   // 0x00 - 0x0f  0000000000000000
+      0x0000,   // 0x10 - 0x1f  0000000000000000
+                //               !  $ &'()*+,-.
+      0x7fd2,   // 0x20 - 0x2f  0100101111111110
+                //              0123456789 ; =
+      0x2bff,   // 0x30 - 0x3f  1111111111010100
+                //               ABCDEFGHIJKLMNO
+      0xfffe,   // 0x40 - 0x4f  0111111111111111
+                //              PQRSTUVWXYZ    _
+      0x87ff,   // 0x50 - 0x5f  1111111111100001
+                //               abcdefghijklmno
+      0xfffe,   // 0x60 - 0x6f  0111111111111111
+                //              pqrstuvwxyz   ~
+      0x47ff];  // 0x70 - 0x7f  1111111111100010
+
+  // Characters allowed in the path as of RFC 3986.
+  // RFC 3986 section 3.3.
+  // pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
+  static const _pathCharTable = const [
+                //             LSB            MSB
+                //              |              |
+      0x0000,   // 0x00 - 0x0f  0000000000000000
+      0x0000,   // 0x10 - 0x1f  0000000000000000
+                //               !  $ &'()*+,-.
+      0x7fd2,   // 0x20 - 0x2f  0100101111111110
+                //              0123456789:; =
+      0x2fff,   // 0x30 - 0x3f  1111111111110100
+                //              @ABCDEFGHIJKLMNO
+      0xffff,   // 0x40 - 0x4f  1111111111111111
+                //              PQRSTUVWXYZ    _
+      0x87ff,   // 0x50 - 0x5f  1111111111100001
+                //               abcdefghijklmno
+      0xfffe,   // 0x60 - 0x6f  0111111111111111
+                //              pqrstuvwxyz   ~
+      0x47ff];  // 0x70 - 0x7f  1111111111100010
+
+  // Characters allowed in the query as of RFC 3986.
+  // RFC 3986 section 3.4.
+  // query = *( pchar / "/" / "?" )
+  static const _queryCharTable = const [
+                //             LSB            MSB
+                //              |              |
+      0x0000,   // 0x00 - 0x0f  0000000000000000
+      0x0000,   // 0x10 - 0x1f  0000000000000000
+                //               !  $ &'()*+,-./
+      0xffd2,   // 0x20 - 0x2f  0100101111111111
+                //              0123456789:; = ?
+      0xafff,   // 0x30 - 0x3f  1111111111110101
+                //              @ABCDEFGHIJKLMNO
+      0xffff,   // 0x40 - 0x4f  1111111111111111
+                //              PQRSTUVWXYZ    _
+      0x87ff,   // 0x50 - 0x5f  1111111111100001
+                //               abcdefghijklmno
+      0xfffe,   // 0x60 - 0x6f  0111111111111111
+                //              pqrstuvwxyz   ~
+      0x47ff];  // 0x70 - 0x7f  1111111111100010
+}
diff --git a/sdk/lib/html/dart2js/html_dart2js.dart b/sdk/lib/html/dart2js/html_dart2js.dart
index 8e53e7f..021a3ca 100644
--- a/sdk/lib/html/dart2js/html_dart2js.dart
+++ b/sdk/lib/html/dart2js/html_dart2js.dart
@@ -45,7 +45,7 @@
 HtmlDocument get document => JS('HtmlDocument', 'document');
 
 Element query(String selector) => document.query(selector);
-List<Element> queryAll(String selector) => document.queryAll(selector);
+ElementList queryAll(String selector) => document.queryAll(selector);
 
 // Workaround for tags like <cite> that lack their own Element subclass --
 // Dart issue 1990.
@@ -11415,12 +11415,12 @@
    *
    *     var request = new HttpRequest();
    *     request.open('GET', 'http://dartlang.org')
-   *     request.on.load.add((event) => print('Request complete'));
+   *     request.onLoad.add((event) => print('Request complete'));
    *
    * is the (more verbose) equivalent of
    *
-   *     var request = new HttpRequest.get('http://dartlang.org',
-   *         (event) => print('Request complete'));
+   *     HttpRequest.getString('http://dartlang.org').then(
+   *         (result) => print('Request complete: $result'));
    */
   @DomName('XMLHttpRequest.XMLHttpRequest')
   @DocsEditable
@@ -17864,9 +17864,15 @@
 @SupportedBrowser(SupportedBrowser.CHROME)
 @Experimental
 // http://dev.w3.org/2011/webrtc/editor/webrtc.html#idl-def-RTCIceCandidate
-class RtcIceCandidate native "RTCIceCandidate" {
+class RtcIceCandidate native "RTCIceCandidate,mozRTCIceCandidate" {
   factory RtcIceCandidate(Map dictionary) {
-    return JS('RtcIceCandidate', 'new RTCIceCandidate(#)',
+    // TODO(efortuna): Remove this check if when you can actually construct with
+    // the unprefixed RTCIceCandidate in Firefox (currently both are defined,
+    // but one can't be used as a constructor).
+    var constructorName = JS('', 'window[#]',
+        Device.isFirefox ? '${Device.propertyPrefix}RTCIceCandidate' : 
+        'RTCIceCandidate');
+    return JS('RtcIceCandidate', 'new #(#)', constructorName,
         convertDartToNative_SerializedScriptValue(dictionary));
   }
 
@@ -17907,7 +17913,7 @@
 @SupportedBrowser(SupportedBrowser.CHROME)
 @Experimental
 // http://dev.w3.org/2011/webrtc/editor/webrtc.html#idl-def-RTCPeerConnection
-class RtcPeerConnection extends EventTarget native "RTCPeerConnection" {
+class RtcPeerConnection extends EventTarget native "RTCPeerConnection,mozRTCPeerConnection" {
   factory RtcPeerConnection(Map rtcIceServers, [Map mediaConstraints]) {
     var constructorName = JS('RtcPeerConnection', 'window[#]',
         '${Device.propertyPrefix}RTCPeerConnection');
@@ -17929,11 +17935,12 @@
     // Currently in Firefox some of the RTC elements are defined but throw an
     // error unless the user has specifically enabled them in their
     // about:config. So we have to construct an element to actually test if RTC
-    // is supported at at the given time.
+    // is supported at the given time. 
     try {
-      var c = new RtcPeerConnection({"iceServers": [ {"url":"stun:foo.com"}]});
-      return c is RtcPeerConnection;
-    } catch (_) {}
+      new RtcPeerConnection(
+          {"iceServers": [ {"url":"stun:localhost"}]});
+      return true;
+    } catch (_) { return false;}
     return false;
   }
   Future<RtcSessionDescription> createOffer([Map mediaConstraints]) {
@@ -18216,8 +18223,6 @@
   Stream<Event> get onSignalingStateChange => signalingStateChangeEvent.forTarget(this);
 
 }
-
-
 // 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.
@@ -18227,9 +18232,16 @@
 @SupportedBrowser(SupportedBrowser.CHROME)
 @Experimental
 // http://dev.w3.org/2011/webrtc/editor/webrtc.html#idl-def-RTCSessionDescription
-class RtcSessionDescription native "RTCSessionDescription" {
+class RtcSessionDescription native "RTCSessionDescription,mozRTCSessionDescription" {
   factory RtcSessionDescription(Map dictionary) {
-    return JS('RtcSessionDescription', 'new RTCSessionDescription(#)',
+    // TODO(efortuna): Remove this check if when you can actually construct with
+    // the unprefixed RTCIceCandidate in Firefox (currently both are defined,
+    // but one can't be used as a constructor).
+    var constructorName = JS('', 'window[#]',
+        Device.isFirefox ? '${Device.propertyPrefix}RTCSessionDescription' : 
+       'RTCSessionDescription');
+    return JS('RtcSessionDescription', 
+        'new #(#)', constructorName,
         convertDartToNative_SerializedScriptValue(dictionary));
   }
 
@@ -19771,6 +19783,8 @@
 
   bool get isEmpty => $dom_key(0) == null;
 
+  bool get isNotEmpty => !isEmpty;
+
   @JSName('length')
   @DomName('Storage.length')
   @DocsEditable
@@ -24869,6 +24883,11 @@
   }
 
   /**
+   * Returns true if there is at least one {key, value} pair in the map.
+   */
+  bool get isNotEmpty => !isEmpty;
+
+  /**
    * Checks to see if the node should be included in this map.
    */
   bool _matches(Node node);
@@ -25015,6 +25034,8 @@
   // TODO: Use lazy iterator when it is available on Map.
   bool get isEmpty => length == 0;
 
+  bool get isNotEmpty => !isEmpty;
+
   // Helpers.
   String _attr(String key) => 'data-$key';
   bool _matches(String key) => key.startsWith('data-');
@@ -25460,6 +25481,9 @@
   /**
    * Gets a [Stream] for this event type, on the specified target.
    *
+   * This will always return a broadcast stream so multiple listeners can be
+   * used simultaneously.
+   *
    * This may be used to capture DOM events:
    *
    *     Element.keyDownEvent.forTarget(element, useCapture: true).listen(...);
@@ -26825,7 +26849,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(onListen: _observe, onCancel: _unobserve);
+    _values = new StreamController.broadcast(onListen: _observe,
+                                             onCancel: _unobserve);
 
     if (_isValid) {
       var segments = [];
diff --git a/sdk/lib/html/dartium/html_dartium.dart b/sdk/lib/html/dartium/html_dartium.dart
index a0b6278..0d36c93 100644
--- a/sdk/lib/html/dartium/html_dartium.dart
+++ b/sdk/lib/html/dartium/html_dartium.dart
@@ -52,7 +52,7 @@
 
 
 Element query(String selector) => document.query(selector);
-List<Element> queryAll(String selector) => document.queryAll(selector);
+ElementList queryAll(String selector) => document.queryAll(selector);
 
 int _getNewIsolateId() => _Utils._getNewIsolateId();
 
@@ -682,6 +682,9 @@
 @DomName('Blob')
 class Blob extends NativeFieldWrapperClass1 {
   Blob.internal();
+
+  @DomName('Blob.Blob')
+  @DocsEditable
   factory Blob(List blobParts, [String type, String endings]) => _create(blobParts, type, endings);
 
   @DocsEditable
@@ -10818,6 +10821,9 @@
 @SupportedBrowser(SupportedBrowser.SAFARI)
 class FormData extends NativeFieldWrapperClass1 {
   FormData.internal();
+
+  @DomName('FormData.DOMFormData')
+  @DocsEditable
   factory FormData([FormElement form]) => _create(form);
 
   @DocsEditable
@@ -11858,6 +11864,23 @@
   @DomName('XMLHttpRequest.readystatechangeEvent')
   @DocsEditable
   static const EventStreamProvider<ProgressEvent> readyStateChangeEvent = const EventStreamProvider<ProgressEvent>('readystatechange');
+
+  /**
+   * General constructor for any type of request (GET, POST, etc).
+   *
+   * This call is used in conjunction with [open]:
+   *
+   *     var request = new HttpRequest();
+   *     request.open('GET', 'http://dartlang.org')
+   *     request.onLoad.add((event) => print('Request complete'));
+   *
+   * is the (more verbose) equivalent of
+   *
+   *     HttpRequest.getString('http://dartlang.org').then(
+   *         (result) => print('Request complete: $result'));
+   */
+  @DomName('XMLHttpRequest.XMLHttpRequest')
+  @DocsEditable
   factory HttpRequest() => _create();
 
   @DocsEditable
@@ -15439,6 +15462,9 @@
 @Unstable
 class MessageChannel extends NativeFieldWrapperClass1 {
   MessageChannel.internal();
+
+  @DomName('MessageChannel.MessageChannel')
+  @DocsEditable
   factory MessageChannel() => _create();
 
   @DocsEditable
@@ -16181,6 +16207,9 @@
 @Experimental
 class MutationObserver extends NativeFieldWrapperClass1 {
   MutationObserver.internal();
+
+  @DomName('MutationObserver.MutationObserver')
+  @DocsEditable
   factory MutationObserver(MutationCallback callback) => _create(callback);
 
   @DocsEditable
@@ -19400,8 +19429,6 @@
   Stream<Event> get onSignalingStateChange => signalingStateChangeEvent.forTarget(this);
 
 }
-
-
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
@@ -21245,6 +21272,8 @@
   int get length => $dom_length;
 
   bool get isEmpty => $dom_key(0) == null;
+
+  bool get isNotEmpty => !isEmpty;
   Storage.internal();
 
   @DomName('Storage.length')
@@ -25582,6 +25611,9 @@
 @Experimental // non-standard
 class _DomPoint extends NativeFieldWrapperClass1 {
   _DomPoint.internal();
+
+  @DomName('WebKitPoint.DOMPoint')
+  @DocsEditable
   factory _DomPoint(num x, num y) => _create(x, y);
 
   @DocsEditable
@@ -26725,6 +26757,11 @@
   }
 
   /**
+   * Returns true if there is at least one {key, value} pair in the map.
+   */
+  bool get isNotEmpty => !isEmpty;
+
+  /**
    * Checks to see if the node should be included in this map.
    */
   bool _matches(Node node);
@@ -26871,6 +26908,8 @@
   // TODO: Use lazy iterator when it is available on Map.
   bool get isEmpty => length == 0;
 
+  bool get isNotEmpty => !isEmpty;
+
   // Helpers.
   String _attr(String key) => 'data-$key';
   bool _matches(String key) => key.startsWith('data-');
@@ -27316,6 +27355,9 @@
   /**
    * Gets a [Stream] for this event type, on the specified target.
    *
+   * This will always return a broadcast stream so multiple listeners can be
+   * used simultaneously.
+   *
    * This may be used to capture DOM events:
    *
    *     Element.keyDownEvent.forTarget(element, useCapture: true).listen(...);
@@ -28681,7 +28723,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(onListen: _observe, onCancel: _unobserve);
+    _values = new StreamController.broadcast(onListen: _observe,
+                                             onCancel: _unobserve);
 
     if (_isValid) {
       var segments = [];
@@ -31037,6 +31080,7 @@
   Iterable<String> get values => Maps.getValues(this);
   int get length => Maps.length(this);
   bool get isEmpty => Maps.isEmpty(this);
+  bool get isNotEmpty => Maps.isNotEmpty(this);
 }
 
 final Future<SendPort> __HELPER_ISOLATE_PORT =
diff --git a/sdk/lib/html/html_common/css_class_set.dart b/sdk/lib/html/html_common/css_class_set.dart
index df50d62..ab17d10 100644
--- a/sdk/lib/html/html_common/css_class_set.dart
+++ b/sdk/lib/html/html_common/css_class_set.dart
@@ -56,6 +56,8 @@
 
   bool get isEmpty => readClasses().isEmpty;
 
+  bool get isNotEmpty => readClasses().isNotEmpty;
+
   int get length => readClasses().length;
 
   String reduce(String combine(String value, String element)) {
diff --git a/sdk/lib/indexed_db/dart2js/indexed_db_dart2js.dart b/sdk/lib/indexed_db/dart2js/indexed_db_dart2js.dart
index b8427c5..99346e1 100644
--- a/sdk/lib/indexed_db/dart2js/indexed_db_dart2js.dart
+++ b/sdk/lib/indexed_db/dart2js/indexed_db_dart2js.dart
@@ -404,7 +404,14 @@
       if (onBlocked != null) {
         request.onBlocked.listen(onBlocked);
       }
-      return _completeRequest(request);
+      var completer = new Completer.sync();
+      request.onSuccess.listen((e) {
+        completer.complete(this);
+      });
+      request.onError.listen((e) {
+        completer.completeError(e);
+      });
+      return completer.future;
     } catch (e, stacktrace) {
       return new Future.error(e, stacktrace);
     }
@@ -911,7 +918,7 @@
       List keyPath_1 = convertDartToNative_StringArray(keyPath);
       return _$dom_createIndex_1(name, keyPath_1);
     }
-    if ((keyPath is List<String> || keyPath == null)) {
+    if ((keyPath is List<String> || keyPath == null) && ?options) {
       List keyPath_2 = convertDartToNative_StringArray(keyPath);
       var options_3 = convertDartToNative_Dictionary(options);
       return _$dom_createIndex_2(name, keyPath_2, options_3);
@@ -919,7 +926,7 @@
     if ((keyPath is String || keyPath == null) && !?options) {
       return _$dom_createIndex_3(name, keyPath);
     }
-    if ((keyPath is String || keyPath == null)) {
+    if ((keyPath is String || keyPath == null) && ?options) {
       var options_4 = convertDartToNative_Dictionary(options);
       return _$dom_createIndex_4(name, keyPath, options_4);
     }
diff --git a/sdk/lib/indexed_db/dartium/indexed_db_dartium.dart b/sdk/lib/indexed_db/dartium/indexed_db_dartium.dart
index 15076fb..1a539d9 100644
--- a/sdk/lib/indexed_db/dartium/indexed_db_dartium.dart
+++ b/sdk/lib/indexed_db/dartium/indexed_db_dartium.dart
@@ -279,7 +279,14 @@
       if (onBlocked != null) {
         request.onBlocked.listen(onBlocked);
       }
-      return _completeRequest(request);
+      var completer = new Completer.sync();
+      request.onSuccess.listen((e) {
+        completer.complete(this);
+      });
+      request.onError.listen((e) {
+        completer.completeError(e);
+      });
+      return completer.future;
     } catch (e, stacktrace) {
       return new Future.error(e, stacktrace);
     }
diff --git a/sdk/lib/io/buffer_list.dart b/sdk/lib/io/buffer_list.dart
index c61710f..eab260b 100644
--- a/sdk/lib/io/buffer_list.dart
+++ b/sdk/lib/io/buffer_list.dart
@@ -83,6 +83,11 @@
   bool get isEmpty => _length == 0;
 
   /**
+   * Returns whether the buffer list is not empty.
+   */
+  bool get isNotEmpty => !isEmpty;
+
+  /**
    * Clears the content of the buffer list.
    */
   void clear() {
diff --git a/sdk/lib/io/crypto.dart b/sdk/lib/io/crypto.dart
new file mode 100644
index 0000000..35bd01c
--- /dev/null
+++ b/sdk/lib/io/crypto.dart
@@ -0,0 +1,448 @@
+// 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.
+
+part of dart.io;
+
+class _CryptoUtils {
+  static String bytesToHex(List<int> bytes) {
+    var result = new StringBuffer();
+    for (var part in bytes) {
+      result.write('${part < 16 ? '0' : ''}${part.toRadixString(16)}');
+    }
+    return result.toString();
+  }
+
+  static const int PAD = 61; // '='
+  static const int CR = 13;  // '\r'
+  static const int LF = 10;  // '\n'
+  static const int LINE_LENGTH = 76;
+
+  static const String _encodeTable =
+      "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+  static const String _encodeTableUrlSafe =
+      "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
+
+  // Lookup table used for finding Base 64 alphabet index of a given byte.
+  // -2 : Outside Base 64 alphabet.
+  // -1 : '\r' or '\n'
+  //  0 : = (Padding character).
+  // >0 : Base 64 alphabet index of given byte.
+  static const List<int> _decodeTable =
+      const [ -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -1, -2, -2, -1, -2, -2,
+              -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
+              -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, 62, -2, 62, -2, 63,
+              52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -2, -2, -2,  0, -2, -2,
+              -2,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
+              15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -2, -2, -2, -2, 63,
+              -2, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+              41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -2, -2, -2, -2, -2,
+              -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
+              -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
+              -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
+              -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
+              -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
+              -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
+              -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
+              -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2 ];
+
+  static String bytesToBase64(List<int> bytes,
+                              [bool urlSafe = false,
+                               bool addLineSeparator = false]) {
+    int len = bytes.length;
+    if (len == 0) {
+      return "";
+    }
+    final String lookup = urlSafe ? _encodeTableUrlSafe : _encodeTable;
+    // Size of 24 bit chunks.
+    final int remainderLength = len.remainder(3);
+    final int chunkLength = len - remainderLength;
+    // Size of base output.
+    int outputLen = ((len ~/ 3) * 4) + ((remainderLength > 0) ? 4 : 0);
+    // Add extra for line separators.
+    if (addLineSeparator) {
+      outputLen += ((outputLen - 1) ~/ LINE_LENGTH) << 1;
+    }
+    List<int> out = new List<int>(outputLen);
+
+    // Encode 24 bit chunks.
+    int j = 0, i = 0, c = 0;
+    while (i < chunkLength) {
+      int x = ((bytes[i++] << 16) & 0xFFFFFF) |
+              ((bytes[i++] << 8) & 0xFFFFFF) |
+                bytes[i++];
+      out[j++] = lookup.codeUnitAt(x >> 18);
+      out[j++] = lookup.codeUnitAt((x >> 12) & 0x3F);
+      out[j++] = lookup.codeUnitAt((x >> 6)  & 0x3F);
+      out[j++] = lookup.codeUnitAt(x & 0x3f);
+      // Add optional line separator for each 76 char output.
+      if (addLineSeparator && ++c == 19 && j < outputLen - 2) {
+          out[j++] = CR;
+          out[j++] = LF;
+          c = 0;
+      }
+    }
+
+    // If input length if not a multiple of 3, encode remaining bytes and
+    // add padding.
+    if (remainderLength == 1) {
+      int x = bytes[i];
+      out[j++] = lookup.codeUnitAt(x >> 2);
+      out[j++] = lookup.codeUnitAt((x << 4) & 0x3F);
+      out[j++] = PAD;
+      out[j++] = PAD;
+    } else if (remainderLength == 2) {
+      int x = bytes[i];
+      int y = bytes[i + 1];
+      out[j++] = lookup.codeUnitAt(x >> 2);
+      out[j++] = lookup.codeUnitAt(((x << 4) | (y >> 4)) & 0x3F);
+      out[j++] = lookup.codeUnitAt((y << 2) & 0x3F);
+      out[j++] = PAD;
+    }
+
+    return new String.fromCharCodes(out);
+  }
+
+  static List<int> base64StringToBytes(String input,
+                                       [bool ignoreInvalidCharacters = true]) {
+    int len = input.length;
+    if (len == 0) {
+      return new List<int>(0);
+    }
+
+    // Count '\r', '\n' and illegal characters, For illegal characters,
+    // if [ignoreInvalidCharacters] is false, throw an exception.
+    int extrasLen = 0;
+    for (int i = 0; i < len; i++) {
+      int c = _decodeTable[input.codeUnitAt(i)];
+      if (c < 0) {
+        extrasLen++;
+        if(c == -2 && !ignoreInvalidCharacters) {
+          throw new FormatException('Invalid character: ${input[i]}');
+        }
+      }
+    }
+
+    if ((len - extrasLen) % 4 != 0) {
+      throw new FormatException('''Size of Base 64 characters in Input
+          must be a multiple of 4. Input: $input''');
+    }
+
+    // Count pad characters, ignore illegal characters at the end.
+    int padLength = 0;
+    for (int i = len - 1; i >= 0; i--) {
+      int currentCodeUnit = input.codeUnitAt(i);
+      if (_decodeTable[currentCodeUnit] > 0) break;
+      if (currentCodeUnit == PAD) padLength++;
+    }
+    int outputLen = (((len - extrasLen) * 6) >> 3) - padLength;
+    List<int> out = new List<int>(outputLen);
+
+    for (int i = 0, o = 0; o < outputLen;) {
+      // Accumulate 4 valid 6 bit Base 64 characters into an int.
+      int x = 0;
+      for (int j = 4; j > 0;) {
+        int c = _decodeTable[input.codeUnitAt(i++)];
+        if (c >= 0) {
+          x = ((x << 6) & 0xFFFFFF) | c;
+          j--;
+        }
+      }
+      out[o++] = x >> 16;
+      if (o < outputLen) {
+        out[o++] = (x >> 8) & 0xFF;
+        if (o < outputLen) out[o++] = x & 0xFF;
+      }
+    }
+    return out;
+  }
+
+}
+
+// Constants.
+const _MASK_8 = 0xff;
+const _MASK_32 = 0xffffffff;
+const _BITS_PER_BYTE = 8;
+const _BYTES_PER_WORD = 4;
+
+// Base class encapsulating common behavior for cryptographic hash
+// functions.
+abstract class _HashBase {
+  _HashBase(int this._chunkSizeInWords,
+            int this._digestSizeInWords,
+            bool this._bigEndianWords)
+      : _pendingData = [] {
+    _currentChunk = new List(_chunkSizeInWords);
+    _h = new List(_digestSizeInWords);
+  }
+
+  // Update the hasher with more data.
+  add(List<int> data) {
+    if (_digestCalled) {
+      throw new StateError(
+          'Hash update method called after digest was retrieved');
+    }
+    _lengthInBytes += data.length;
+    _pendingData.addAll(data);
+    _iterate();
+  }
+
+  // Finish the hash computation and return the digest string.
+  List<int> close() {
+    if (_digestCalled) {
+      return _resultAsBytes();
+    }
+    _digestCalled = true;
+    _finalizeData();
+    _iterate();
+    assert(_pendingData.length == 0);
+    return _resultAsBytes();
+  }
+
+  // Returns the block size of the hash in bytes.
+  int get blockSize {
+    return _chunkSizeInWords * _BYTES_PER_WORD;
+  }
+
+  // Create a fresh instance of this Hash.
+  newInstance();
+
+  // One round of the hash computation.
+  _updateHash(List<int> m);
+
+  // Helper methods.
+  _add32(x, y) => (x + y) & _MASK_32;
+  _roundUp(val, n) => (val + n - 1) & -n;
+
+  // Rotate left limiting to unsigned 32-bit values.
+  int _rotl32(int val, int shift) {
+    var mod_shift = shift & 31;
+    return ((val << mod_shift) & _MASK_32) |
+        ((val & _MASK_32) >> (32 - mod_shift));
+  }
+
+
+  // Compute the final result as a list of bytes from the hash words.
+  _resultAsBytes() {
+    var result = [];
+    for (var i = 0; i < _h.length; i++) {
+      result.addAll(_wordToBytes(_h[i]));
+    }
+    return result;
+  }
+
+  // Converts a list of bytes to a chunk of 32-bit words.
+  _bytesToChunk(List<int> data, int dataIndex) {
+    assert((data.length - dataIndex) >= (_chunkSizeInWords * _BYTES_PER_WORD));
+
+    for (var wordIndex = 0; wordIndex < _chunkSizeInWords; wordIndex++) {
+      var w3 = _bigEndianWords ? data[dataIndex] : data[dataIndex + 3];
+      var w2 = _bigEndianWords ? data[dataIndex + 1] : data[dataIndex + 2];
+      var w1 = _bigEndianWords ? data[dataIndex + 2] : data[dataIndex + 1];
+      var w0 = _bigEndianWords ? data[dataIndex + 3] : data[dataIndex];
+      dataIndex += 4;
+      var word = (w3 & 0xff) << 24;
+      word |= (w2 & _MASK_8) << 16;
+      word |= (w1 & _MASK_8) << 8;
+      word |= (w0 & _MASK_8);
+      _currentChunk[wordIndex] = word;
+    }
+  }
+
+  // Convert a 32-bit word to four bytes.
+  _wordToBytes(int word) {
+    List<int> bytes = new List(_BYTES_PER_WORD);
+    bytes[0] = (word >> (_bigEndianWords ? 24 : 0)) & _MASK_8;
+    bytes[1] = (word >> (_bigEndianWords ? 16 : 8)) & _MASK_8;
+    bytes[2] = (word >> (_bigEndianWords ? 8 : 16)) & _MASK_8;
+    bytes[3] = (word >> (_bigEndianWords ? 0 : 24)) & _MASK_8;
+    return bytes;
+  }
+
+  // Iterate through data updating the hash computation for each
+  // chunk.
+  _iterate() {
+    var len = _pendingData.length;
+    var chunkSizeInBytes = _chunkSizeInWords * _BYTES_PER_WORD;
+    if (len >= chunkSizeInBytes) {
+      var index = 0;
+      for (; (len - index) >= chunkSizeInBytes; index += chunkSizeInBytes) {
+        _bytesToChunk(_pendingData, index);
+        _updateHash(_currentChunk);
+      }
+      _pendingData = _pendingData.sublist(index, len);
+    }
+  }
+
+  // Finalize the data. Add a 1 bit to the end of the message. Expand with
+  // 0 bits and add the length of the message.
+  _finalizeData() {
+    _pendingData.add(0x80);
+    var contentsLength = _lengthInBytes + 9;
+    var chunkSizeInBytes = _chunkSizeInWords * _BYTES_PER_WORD;
+    var finalizedLength = _roundUp(contentsLength, chunkSizeInBytes);
+    var zeroPadding = finalizedLength - contentsLength;
+    for (var i = 0; i < zeroPadding; i++) {
+      _pendingData.add(0);
+    }
+    var lengthInBits = _lengthInBytes * _BITS_PER_BYTE;
+    assert(lengthInBits < pow(2, 32));
+    if (_bigEndianWords) {
+      _pendingData.addAll(_wordToBytes(0));
+      _pendingData.addAll(_wordToBytes(lengthInBits & _MASK_32));
+    } else {
+      _pendingData.addAll(_wordToBytes(lengthInBits & _MASK_32));
+      _pendingData.addAll(_wordToBytes(0));
+    }
+  }
+
+  // Hasher state.
+  final int _chunkSizeInWords;
+  final int _digestSizeInWords;
+  final bool _bigEndianWords;
+  int _lengthInBytes = 0;
+  List<int> _pendingData;
+  List<int> _currentChunk;
+  List<int> _h;
+  bool _digestCalled = false;
+}
+
+// The MD5 hasher is used to compute an MD5 message digest.
+class _MD5 extends _HashBase {
+  _MD5() : super(16, 4, false) {
+    _h[0] = 0x67452301;
+    _h[1] = 0xefcdab89;
+    _h[2] = 0x98badcfe;
+    _h[3] = 0x10325476;
+  }
+
+  // Returns a new instance of this Hash.
+  _MD5 newInstance() {
+    return new _MD5();
+  }
+
+  static const _k = const [
+    0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 0xf57c0faf, 0x4787c62a,
+    0xa8304613, 0xfd469501, 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
+    0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, 0xf61e2562, 0xc040b340,
+    0x265e5a51, 0xe9b6c7aa, 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
+    0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, 0xa9e3e905, 0xfcefa3f8,
+    0x676f02d9, 0x8d2a4c8a, 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
+    0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, 0x289b7ec6, 0xeaa127fa,
+    0xd4ef3085, 0x04881d05, 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
+    0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, 0x655b59c3, 0x8f0ccc92,
+    0xffeff47d, 0x85845dd1, 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
+    0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391 ];
+
+  static const _r = const [
+    7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 5,  9, 14,
+    20, 5,  9, 14, 20, 5,  9, 14, 20, 5,  9, 14, 20, 4, 11, 16, 23, 4, 11,
+    16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 6, 10, 15, 21, 6, 10, 15, 21, 6,
+    10, 15, 21, 6, 10, 15, 21 ];
+
+  // Compute one iteration of the MD5 algorithm with a chunk of
+  // 16 32-bit pieces.
+  void _updateHash(List<int> m) {
+    assert(m.length == 16);
+
+    var a = _h[0];
+    var b = _h[1];
+    var c = _h[2];
+    var d = _h[3];
+
+    var t0;
+    var t1;
+
+    for (var i = 0; i < 64; i++) {
+      if (i < 16) {
+        t0 = (b & c) | ((~b & _MASK_32) & d);
+        t1 = i;
+      } else if (i < 32) {
+        t0 = (d & b) | ((~d & _MASK_32) & c);
+        t1 = ((5 * i) + 1) % 16;
+      } else if (i < 48) {
+        t0 = b ^ c ^ d;
+        t1 = ((3 * i) + 5) % 16;
+      } else {
+        t0 = c ^ (b | (~d & _MASK_32));
+        t1 = (7 * i) % 16;
+      }
+
+      var temp = d;
+      d = c;
+      c = b;
+      b = _add32(b, _rotl32(_add32(_add32(a, t0),
+                                   _add32(_k[i], m[t1])),
+                            _r[i]));
+      a = temp;
+    }
+
+    _h[0] = _add32(a, _h[0]);
+    _h[1] = _add32(b, _h[1]);
+    _h[2] = _add32(c, _h[2]);
+    _h[3] = _add32(d, _h[3]);
+  }
+}
+
+// The SHA1 hasher is used to compute an SHA1 message digest.
+class _SHA1 extends _HashBase {
+  // Construct a SHA1 hasher object.
+  _SHA1() : _w = new List(80), super(16, 5, true) {
+    _h[0] = 0x67452301;
+    _h[1] = 0xEFCDAB89;
+    _h[2] = 0x98BADCFE;
+    _h[3] = 0x10325476;
+    _h[4] = 0xC3D2E1F0;
+  }
+
+  // Returns a new instance of this Hash.
+  _SHA1 newInstance() {
+    return new _SHA1();
+  }
+
+  // Compute one iteration of the SHA1 algorithm with a chunk of
+  // 16 32-bit pieces.
+  void _updateHash(List<int> m) {
+    assert(m.length == 16);
+
+    var a = _h[0];
+    var b = _h[1];
+    var c = _h[2];
+    var d = _h[3];
+    var e = _h[4];
+
+    for (var i = 0; i < 80; i++) {
+      if (i < 16) {
+        _w[i] = m[i];
+      } else {
+        var n = _w[i - 3] ^ _w[i - 8] ^ _w[i - 14] ^ _w[i - 16];
+        _w[i] = _rotl32(n, 1);
+      }
+      var t = _add32(_add32(_rotl32(a, 5), e), _w[i]);
+      if (i < 20) {
+        t = _add32(_add32(t, (b & c) | (~b & d)), 0x5A827999);
+      } else if (i < 40) {
+        t = _add32(_add32(t, (b ^ c ^ d)), 0x6ED9EBA1);
+      } else if (i < 60) {
+        t = _add32(_add32(t, (b & c) | (b & d) | (c & d)), 0x8F1BBCDC);
+      } else {
+        t = _add32(_add32(t, b ^ c ^ d), 0xCA62C1D6);
+      }
+
+      e = d;
+      d = c;
+      c = _rotl32(b, 30);
+      b = a;
+      a = t & _MASK_32;
+    }
+
+    _h[0] = _add32(a, _h[0]);
+    _h[1] = _add32(b, _h[1]);
+    _h[2] = _add32(c, _h[2]);
+    _h[3] = _add32(d, _h[3]);
+    _h[4] = _add32(e, _h[4]);
+  }
+
+  List<int> _w;
+}
diff --git a/sdk/lib/io/file_impl.dart b/sdk/lib/io/file_impl.dart
index fb6b272..29b93dc 100644
--- a/sdk/lib/io/file_impl.dart
+++ b/sdk/lib/io/file_impl.dart
@@ -534,7 +534,7 @@
       IOSink sink = openWrite(mode: mode);
       sink.add(bytes);
       sink.close();
-      return sink.done.then((_) => this);;
+      return sink.done.then((_) => this);
     } catch (e) {
       return new Future.error(e);
     }
diff --git a/sdk/lib/io/http.dart b/sdk/lib/io/http.dart
index 5dc5738..913ab8f 100644
--- a/sdk/lib/io/http.dart
+++ b/sdk/lib/io/http.dart
@@ -721,6 +721,10 @@
   /**
    * Gets the [HttpResponse] object, used for sending back the response to the
    * client.
+   *
+   * If the [contentLength] of the body isn't 0, and the body isn't being read,
+   * any write calls on the [HttpResponse] will automatically drain the request
+   * body.
    */
   HttpResponse get response;
 }
diff --git a/sdk/lib/io/http_impl.dart b/sdk/lib/io/http_impl.dart
index dec3633..b27441b 100644
--- a/sdk/lib/io/http_impl.dart
+++ b/sdk/lib/io/http_impl.dart
@@ -23,6 +23,8 @@
   String method;
   Uri uri;
 
+  bool hasSubscriber = false;
+
   // The transfer length if the length of the message body as it
   // appears in the message (RFC 2616 section 4.4). This can be -1 if
   // the length of the massage body is not known due to transfer
@@ -38,6 +40,7 @@
                                        {void onError(error),
                                         void onDone(),
                                         bool cancelOnError}) {
+    hasSubscriber = true;
     return _stream.listen(onData,
                           onError: onError,
                           onDone: onDone,
@@ -49,6 +52,7 @@
 
   void close(bool closing) {
     fullBodyRead = true;
+    hasSubscriber = true;
     _dataCompleter.complete(closing);
   }
 }
@@ -274,7 +278,7 @@
   Future<HttpClientResponse> _authenticate(bool proxyAuth) {
     Future<HttpClientResponse> retry() {
       // Drain body and retry.
-      return fold(null, (x, y) {}).then((_) {
+      return drain().then((_) {
           return _httpClient._openUrlFromRequest(_httpRequest.method,
                                                  _httpRequest.uri,
                                                  _httpRequest)
@@ -470,45 +474,56 @@
 
   Future<T> get done => _dataSink.done;
 
-  void _writeHeaders() {
-    if (_headersWritten) return;
+  Future _writeHeaders({drainRequest: true}) {
+    if (_headersWritten) return new Future.value();
     _headersWritten = true;
     headers._synchronize();  // Be sure the 'chunked' option is updated.
     bool isServerSide = this is _HttpResponse;
-    if (isServerSide && headers.chunkedTransferEncoding) {
+    if (isServerSide) {
       var response = this;
-      List acceptEncodings =
-          response._httpRequest.headers[HttpHeaders.ACCEPT_ENCODING];
-      List contentEncoding = headers[HttpHeaders.CONTENT_ENCODING];
-      if (acceptEncodings != null &&
-          acceptEncodings
-              .expand((list) => list.split(","))
-              .any((encoding) => encoding.trim().toLowerCase() == "gzip") &&
-          contentEncoding == null) {
-        headers.set(HttpHeaders.CONTENT_ENCODING, "gzip");
-        _asGZip = true;
+      if (headers.chunkedTransferEncoding) {
+        List acceptEncodings =
+            response._httpRequest.headers[HttpHeaders.ACCEPT_ENCODING];
+        List contentEncoding = headers[HttpHeaders.CONTENT_ENCODING];
+        if (acceptEncodings != null &&
+            acceptEncodings
+                .expand((list) => list.split(","))
+                .any((encoding) => encoding.trim().toLowerCase() == "gzip") &&
+            contentEncoding == null) {
+          headers.set(HttpHeaders.CONTENT_ENCODING, "gzip");
+          _asGZip = true;
+        }
+      }
+      if (drainRequest && !response._httpRequest._incoming.hasSubscriber) {
+        return response._httpRequest.drain()
+            // TODO(ajohnsen): Timeout on drain?
+            .catchError((_) {})  // Ignore errors.
+            .then((_) => _writeHeader());
       }
     }
-    _writeHeader();
+    return new Future.sync(_writeHeader);
   }
 
   Future _addStream(Stream<List<int>> stream) {
-    _writeHeaders();
-    int contentLength = headers.contentLength;
-    if (_ignoreBody) {
-      stream.fold(null, (x, y) {}).catchError((_) {});
-      return _headersSink.close();
-    }
-    stream = stream.transform(new _BufferTransformer());
-    if (headers.chunkedTransferEncoding) {
-      if (_asGZip) {
-        stream = stream.transform(new ZLibDeflater(gzip: true, level: 6));
-      }
-      stream = stream.transform(new _ChunkedTransformer());
-    } else if (contentLength >= 0) {
-      stream = stream.transform(new _ContentLengthValidator(contentLength));
-    }
-    return _headersSink.addStream(stream);
+    return _writeHeaders()
+        .then((_) {
+          int contentLength = headers.contentLength;
+          if (_ignoreBody) {
+            stream.drain().catchError((_) {});
+            return _headersSink.close();
+          }
+          stream = stream.transform(new _BufferTransformer());
+          if (headers.chunkedTransferEncoding) {
+            if (_asGZip) {
+              stream = stream.transform(new ZLibDeflater(gzip: true, level: 6));
+            }
+            stream = stream.transform(new _ChunkedTransformer());
+          } else if (contentLength >= 0) {
+            stream = stream.transform(
+                new _ContentLengthValidator(contentLength));
+          }
+          return _headersSink.addStream(stream);
+        });
   }
 
   Future _close() {
@@ -528,8 +543,7 @@
             " than 0: ${headers.contentLength}."));
       }
     }
-    _writeHeaders();
-    return _headersSink.close();
+    return _writeHeaders().then((_) => _headersSink.close());
   }
 
   void _writeHeader();  // TODO(ajohnsen): Better name.
@@ -548,7 +562,9 @@
 
   void _cancel() {
     if (_subscription != null) {
-      _subscription.cancel();
+      StreamSubscription subscription = _subscription;
+      _subscription = null;
+      subscription.cancel();
     }
   }
 
@@ -556,6 +572,7 @@
     if (_controller != null) return;
     _controller = new StreamController(onPause: () => _subscription.pause(),
                                        onResume: () => _subscription.resume(),
+                                       onListen: () => _subscription.resume(),
                                        onCancel: _cancel);
     _outbound._addStream(_controller.stream)
         .then((_) {
@@ -608,6 +625,8 @@
           _done(error);
         },
         cancelOnError: true);
+    // Pause the first request.
+    if (_controller == null) _subscription.pause();
     _ensureController();
     return _completer.future;
   }
@@ -682,8 +701,8 @@
 
   Future<Socket> detachSocket() {
     if (_headersWritten) throw new StateError("Headers already sent");
-    _writeHeaders();
     var future = _httpRequest._httpConnection.detachSocket();
+    _writeHeaders(drainRequest: false).then((_) => close());
     // Close connection so the socket is 'free'.
     close();
     done.catchError((_) {
@@ -878,11 +897,11 @@
     if (followRedirects && response.isRedirect) {
       if (response.redirects.length < maxRedirects) {
         // Redirect and drain response.
-        future = response.fold(null, (x, y) {})
+        future = response.drain()
           .then((_) => response.redirect());
       } else {
         // End with exception, too many redirects.
-        future = response.fold(null, (x, y) {})
+        future = response.drain()
             .then((_) => new Future.error(
                 new RedirectLimitExceededException(response.redirects)));
       }
@@ -927,7 +946,7 @@
         // For the connect method the request URI is the host:port of
         // the requested destination of the tunnel (see RFC 2817
         // section 5.2)
-        return "${uri.domain}:${uri.port}";
+        return "${uri.host}:${uri.port}";
       } else {
         if (_httpClientConnection._proxyTunnel) {
           return uriStartingFromPath();
@@ -1136,13 +1155,13 @@
                                          proxy,
                                          _httpClient,
                                          this);
-    request.headers.host = uri.domain;
+    request.headers.host = uri.host;
     request.headers.port = port;
     request.headers.set(HttpHeaders.ACCEPT_ENCODING, "gzip");
     if (proxy.isAuthenticated) {
       // If the proxy configuration contains user information use that
       // for proxy basic authorization.
-      String auth = CryptoUtils.bytesToBase64(
+      String auth = _CryptoUtils.bytesToBase64(
           _encodeString("${proxy.username}:${proxy.password}"));
       request.headers.set(HttpHeaders.PROXY_AUTHORIZATION, "Basic $auth");
     } else if (!proxy.isDirect && _httpClient._proxyCredentials.length > 0) {
@@ -1155,7 +1174,7 @@
       // If the URL contains user information use that for basic
       // authorization.
       String auth =
-          CryptoUtils.bytesToBase64(_encodeString(uri.userInfo));
+          _CryptoUtils.bytesToBase64(_encodeString(uri.userInfo));
       request.headers.set(HttpHeaders.AUTHORIZATION, "Basic $auth");
     } else {
       // Look for credentials.
@@ -1259,14 +1278,14 @@
 
   Future<_HttpClientConnection> createProxyTunnel(host, port, proxy) {
     _HttpClientRequest request =
-        send(new Uri.fromComponents(domain: host, port: port),
+        send(new Uri(host: host, port: port),
              port,
              "CONNECT",
              proxy);
     if (proxy.isAuthenticated) {
       // If the proxy configuration contains user information use that
       // for proxy basic authorization.
-      String auth = CryptoUtils.bytesToBase64(
+      String auth = _CryptoUtils.bytesToBase64(
           _encodeString("${proxy.username}:${proxy.password}"));
       request.headers.set(HttpHeaders.PROXY_AUTHORIZATION, "Basic $auth");
     }
@@ -1352,8 +1371,8 @@
                                  String path) {
     // TODO(sgjesse): The path set here can contain both query and
     // fragment. They should be cracked and set correctly.
-    return _openUrl(method, new Uri.fromComponents(
-        scheme: "http", domain: host, port: port, path: path));
+    return _openUrl(method, new Uri(
+        scheme: "http", host: host, port: port, path: path));
   }
 
   Future<HttpClientRequest> openUrl(String method, Uri url) {
@@ -1430,7 +1449,7 @@
       throw new ArgumentError(method);
     }
     if (method != "CONNECT") {
-      if (uri.domain.isEmpty ||
+      if (uri.host.isEmpty ||
           (uri.scheme != "http" && uri.scheme != "https")) {
         throw new ArgumentError("Unsupported scheme '${uri.scheme}' in $uri");
       }
@@ -1454,7 +1473,7 @@
         return new Future.error(error, stackTrace);
       }
     }
-    return _getConnection(uri.domain, port, proxyConf, isSecure)
+    return _getConnection(uri.host, port, proxyConf, isSecure)
         .then((info) {
           send(info) {
             return info.connection.send(uri,
@@ -1465,7 +1484,7 @@
           // If the connection was closed before the request was sent, create
           // and use another connection.
           if (info.connection.closed) {
-            return _getConnection(uri.domain, port, proxyConf, isSecure)
+            return _getConnection(uri.host, port, proxyConf, isSecure)
                 .then(send);
           }
           return send(info);
@@ -1478,19 +1497,19 @@
     // If the new URI is relative (to either '/' or some sub-path),
     // construct a full URI from the previous one.
     // See http://tools.ietf.org/html/rfc3986#section-4.2
-    replaceComponents({scheme, domain, port, path}) {
-      uri = new Uri.fromComponents(
+    replaceComponents({scheme, host, port, path}) {
+      uri = new Uri(
           scheme: scheme != null ? scheme : uri.scheme,
-          domain: domain != null ? domain : uri.domain,
+          host: host != null ? host : uri.host,
           port: port != null ? port : uri.port,
           path: path != null ? path : uri.path,
           query: uri.query,
           fragment: uri.fragment);
     }
-    if (uri.domain == '') {
-      replaceComponents(domain: previous.uri.domain, port: previous.uri.port);
+    if (uri.host.isEmpty) {
+      replaceComponents(host: previous.uri.host, port: previous.uri.port);
     }
-    if (uri.scheme == '') {
+    if (uri.scheme.isEmpty) {
       replaceComponents(scheme: previous.uri.scheme);
     }
     if (!uri.path.startsWith('/') && previous.uri.path.startsWith('/')) {
@@ -1657,7 +1676,7 @@
       if (option == null) return null;
       Iterator<String> names = option.split(",").map((s) => s.trim()).iterator;
       while (names.moveNext()) {
-        if (url.domain.endsWith(names.current)) {
+        if (url.host.endsWith(names.current)) {
           return "DIRECT";
         }
       }
@@ -2130,13 +2149,13 @@
       // http://tools.ietf.org/html/draft-reschke-basicauth-enc-06. For
       // now always use UTF-8 encoding.
       _HttpClientDigestCredentials creds = credentials;
-      var hasher = new MD5();
+      var hasher = new _MD5();
       hasher.add(_encodeString(creds.username));
       hasher.add([_CharCode.COLON]);
       hasher.add(realm.codeUnits);
       hasher.add([_CharCode.COLON]);
       hasher.add(_encodeString(creds.password));
-      ha1 = CryptoUtils.bytesToHex(hasher.close());
+      ha1 = _CryptoUtils.bytesToHex(hasher.close());
     }
   }
 
@@ -2153,7 +2172,7 @@
 
   bool applies(Uri uri, _AuthenticationScheme scheme) {
     if (scheme != null && credentials.scheme != scheme) return false;
-    if (uri.domain != this.uri.domain) return false;
+    if (uri.host != this.uri.host) return false;
     int thisPort =
         this.uri.port == 0 ? HttpClient.DEFAULT_HTTP_PORT : this.uri.port;
     int otherPort = uri.port == 0 ? HttpClient.DEFAULT_HTTP_PORT : uri.port;
@@ -2224,7 +2243,7 @@
     // http://tools.ietf.org/html/draft-reschke-basicauth-enc-06. For
     // now always use UTF-8 encoding.
     String auth =
-        CryptoUtils.bytesToBase64(_encodeString("$username:$password"));
+        _CryptoUtils.bytesToBase64(_encodeString("$username:$password"));
     return "Basic $auth";
   }
 
@@ -2251,22 +2270,22 @@
 
   String authorization(_Credentials credentials, _HttpClientRequest request) {
     String requestUri = request._requestUri();
-    MD5 hasher = new MD5();
+    _MD5 hasher = new _MD5();
     hasher.add(request.method.codeUnits);
     hasher.add([_CharCode.COLON]);
     hasher.add(requestUri.codeUnits);
-    var ha2 = CryptoUtils.bytesToHex(hasher.close());
+    var ha2 = _CryptoUtils.bytesToHex(hasher.close());
 
     String qop;
     String cnonce;
     String nc;
     var x;
-    hasher = new MD5();
+    hasher = new _MD5();
     hasher.add(credentials.ha1.codeUnits);
     hasher.add([_CharCode.COLON]);
     if (credentials.qop == "auth") {
       qop = credentials.qop;
-      cnonce = CryptoUtils.bytesToHex(_IOCrypto.getRandomBytes(4));
+      cnonce = _CryptoUtils.bytesToHex(_IOCrypto.getRandomBytes(4));
       ++credentials.nonceCount;
       nc = credentials.nonceCount.toRadixString(16);
       nc = "00000000".substring(0, 8 - nc.length + 1) + nc;
@@ -2284,7 +2303,7 @@
       hasher.add([_CharCode.COLON]);
       hasher.add(ha2.codeUnits);
     }
-    var response = CryptoUtils.bytesToHex(hasher.close());
+    var response = _CryptoUtils.bytesToHex(hasher.close());
 
     StringBuffer buffer = new StringBuffer();
     buffer.write('Digest ');
diff --git a/sdk/lib/io/http_parser.dart b/sdk/lib/io/http_parser.dart
index 58622cf..b7aabd2 100644
--- a/sdk/lib/io/http_parser.dart
+++ b/sdk/lib/io/http_parser.dart
@@ -578,7 +578,9 @@
           if (_connectionUpgrade) {
             _incoming.upgraded = true;
             _parserCalled = false;
-            _controller.add(_incoming);
+            var tmp = _incoming;
+            _closeIncoming();
+            _controller.add(tmp);
             return;
           }
           if (_transferLength == 0 ||
@@ -928,14 +930,6 @@
   }
 
   void _pauseStateChanged() {
-    void update(bool pause) {
-      if (pause && !_socketSubscription.isPaused) {
-        _socketSubscription.pause();
-      } else if (!pause && _socketSubscription.isPaused) {
-        _socketSubscription.resume();
-      }
-    }
-
     if (_incoming != null) {
       if (!_bodyPaused && !_parserCalled) {
         _parse();
diff --git a/sdk/lib/io/http_session.dart b/sdk/lib/io/http_session.dart
index 2b7e164..deeebd0 100644
--- a/sdk/lib/io/http_session.dart
+++ b/sdk/lib/io/http_session.dart
@@ -60,6 +60,7 @@
   Iterable get values => _data.values;
   int get length => _data.length;
   bool get isEmpty => _data.isEmpty;
+  bool get isNotEmpty => _data.isNotEmpty;
 }
 
 // Private class used to manage all the active sessions. The sessions are stored
@@ -73,7 +74,7 @@
   String createSessionId() {
     const int _KEY_LENGTH = 16;  // 128 bits.
     var data = _IOCrypto.getRandomBytes(_KEY_LENGTH);
-    return CryptoUtils.bytesToHex(data);
+    return _CryptoUtils.bytesToHex(data);
   }
 
   _HttpSession getSession(String id) {
diff --git a/sdk/lib/io/io.dart b/sdk/lib/io/io.dart
index c44f6ba..6c1d699 100644
--- a/sdk/lib/io/io.dart
+++ b/sdk/lib/io/io.dart
@@ -17,16 +17,15 @@
                               LinkedHashSet,
                               DoubleLinkedQueue,
                               DoubleLinkedQueueEntry;
-import 'dart:crypto';
 import 'dart:isolate';
 import 'dart:json' as JSON;
 import 'dart:math';
-import 'dart:uri';
 import 'dart:utf';
 import 'dart:typed_data';
 
 part 'buffer_list.dart';
 part 'common.dart';
+part 'crypto.dart';
 part 'data_transformer.dart';
 part 'directory.dart';
 part 'directory_impl.dart';
diff --git a/sdk/lib/io/iolib_sources.gypi b/sdk/lib/io/iolib_sources.gypi
index 5225dc1..b10f218 100644
--- a/sdk/lib/io/iolib_sources.gypi
+++ b/sdk/lib/io/iolib_sources.gypi
@@ -6,6 +6,7 @@
   'sources': [
     'buffer_list.dart',
     'common.dart',
+    'crypto.dart',
     'data_transformer.dart',
     'directory.dart',
     'directory_impl.dart',
diff --git a/sdk/lib/io/mime_multipart_parser.dart b/sdk/lib/io/mime_multipart_parser.dart
index 4bfbebe..dc3f206 100644
--- a/sdk/lib/io/mime_multipart_parser.dart
+++ b/sdk/lib/io/mime_multipart_parser.dart
@@ -101,11 +101,10 @@
 
   Stream<MimeMultipart> bind(Stream<List<int>> stream) {
     _controller = new StreamController(
-        onPause: () {
-          _pauseStream();
-        },
-        onResume: () {
-          _resumeStream();
+        onPause: _pauseStream,
+        onResume:_resumeStream,
+        onCancel: () {
+          _subscription.cancel();
         },
         onListen: () {
           _subscription = stream.listen(
@@ -126,9 +125,6 @@
               onError: (error) {
                 _controller.addError(error);
               });
-        },
-        onCancel: () {
-          _subscription.cancel();
         });
     return _controller.stream;
   }
diff --git a/sdk/lib/io/platform_impl.dart b/sdk/lib/io/platform_impl.dart
index 8b858c9..cee4e38 100644
--- a/sdk/lib/io/platform_impl.dart
+++ b/sdk/lib/io/platform_impl.dart
@@ -87,6 +87,7 @@
   Iterable<V> get values => _map.values;
   int get length => _map.length;
   bool get isEmpty => _map.isEmpty;
+  bool get isNotEmpty => _map.isNotEmpty;
 
   Map<String, V> _map;
 }
diff --git a/sdk/lib/io/timer_impl.dart b/sdk/lib/io/timer_impl.dart
index 107daba..3072f5c 100644
--- a/sdk/lib/io/timer_impl.dart
+++ b/sdk/lib/io/timer_impl.dart
@@ -158,8 +158,8 @@
         }
       } finally {
         _handling_callbacks = false;
+        _notifyEventHandler();
       }
-      _notifyEventHandler();
     }
 
     if(_receivePort == null) {
diff --git a/sdk/lib/io/websocket_impl.dart b/sdk/lib/io/websocket_impl.dart
index 3cef0ad..77c3456 100644
--- a/sdk/lib/io/websocket_impl.dart
+++ b/sdk/lib/io/websocket_impl.dart
@@ -406,9 +406,9 @@
     response.headers.add(HttpHeaders.CONNECTION, "Upgrade");
     response.headers.add(HttpHeaders.UPGRADE, "websocket");
     String key = request.headers.value("Sec-WebSocket-Key");
-    SHA1 sha1 = new SHA1();
+    _SHA1 sha1 = new _SHA1();
     sha1.add("$key$_webSocketGUID".codeUnits);
-    String accept = CryptoUtils.bytesToBase64(sha1.close());
+    String accept = _CryptoUtils.bytesToBase64(sha1.close());
     response.headers.add("Sec-WebSocket-Accept", accept);
     response.headers.contentLength = 0;
     return response.detachSocket()
@@ -658,15 +658,15 @@
     for (int i = 0; i < 16; i++) {
       nonceData[i] = random.nextInt(256);
     }
-    String nonce = CryptoUtils.bytesToBase64(nonceData);
+    String nonce = _CryptoUtils.bytesToBase64(nonceData);
 
-    uri = new Uri.fromComponents(scheme: uri.scheme == "wss" ? "https" : "http",
-                                 userInfo: uri.userInfo,
-                                 domain: uri.domain,
-                                 port: uri.port,
-                                 path: uri.path,
-                                 query: uri.query,
-                                 fragment: uri.fragment);
+    uri = new Uri(scheme: uri.scheme == "wss" ? "https" : "http",
+                  userInfo: uri.userInfo,
+                  host: uri.host,
+                  port: uri.port,
+                  path: uri.path,
+                  query: uri.query,
+                  fragment: uri.fragment);
     return _httpClient.openUrl("GET", uri)
       .then((request) {
         // Setup the initial handshake.
@@ -696,10 +696,10 @@
         if (accept == null) {
           error("Response did not contain a 'Sec-WebSocket-Accept' header");
         }
-        SHA1 sha1 = new SHA1();
+        _SHA1 sha1 = new _SHA1();
         sha1.add("$nonce$_webSocketGUID".codeUnits);
         List<int> expectedAccept = sha1.close();
-        List<int> receivedAccept = CryptoUtils.base64StringToBytes(accept);
+        List<int> receivedAccept = _CryptoUtils.base64StringToBytes(accept);
         if (expectedAccept.length != receivedAccept.length) {
           error("Reasponse header 'Sec-WebSocket-Accept' is the wrong length");
         }
diff --git a/sdk/lib/mdv_observe_impl/mdv_observe_impl.dart b/sdk/lib/mdv_observe_impl/mdv_observe_impl.dart
index e56554b..577f0b8 100644
--- a/sdk/lib/mdv_observe_impl/mdv_observe_impl.dart
+++ b/sdk/lib/mdv_observe_impl/mdv_observe_impl.dart
@@ -63,16 +63,15 @@
  * call [notifyPropertyChange]. See that method for an example.
  */
 abstract class ObservableMixin implements Observable {
-  StreamController<List<ChangeRecord>> _observers;
-  Stream<List<ChangeRecord>> _stream;
+  StreamController _multiplexController;
   List<ChangeRecord> _changes;
 
   Stream<List<ChangeRecord>> get changes {
-    if (_observers == null) {
-      _observers = new StreamController<List<ChangeRecord>>();
-      _stream = _observers.stream.asBroadcastStream();
+    if (_multiplexController == null) {
+      _multiplexController =
+          new StreamController<List<ChangeRecord>>.broadcast();
     }
-    return _stream;
+    return _multiplexController.stream;
   }
 
   void _deliverChanges() {
@@ -80,7 +79,7 @@
     _changes = null;
     if (hasObservers && changes != null) {
       // TODO(jmesserly): make "changes" immutable
-      _observers.add(changes);
+      _multiplexController.add(changes);
     }
   }
 
@@ -88,7 +87,8 @@
    * True if this object has any observers, and should call
    * [notifyPropertyChange] for changes.
    */
-  bool get hasObservers => _observers != null && _observers.hasListener;
+  bool get hasObservers => _multiplexController != null &&
+                           _multiplexController.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 86bbce1..1e9377e 100644
--- a/sdk/lib/mirrors/mirrors.dart
+++ b/sdk/lib/mirrors/mirrors.dart
@@ -16,7 +16,6 @@
 
 import 'dart:async';
 import 'dart:isolate';
-import 'dart:uri';
 
 /**
  * A [MirrorSystem] is the main interface used to reflect on a set of
diff --git a/sdk/lib/typed_data/dart2js/typed_data_dart2js.dart b/sdk/lib/typed_data/dart2js/typed_data_dart2js.dart
index d6e5f43..d7afeed 100644
--- a/sdk/lib/typed_data/dart2js/typed_data_dart2js.dart
+++ b/sdk/lib/typed_data/dart2js/typed_data_dart2js.dart
@@ -314,6 +314,8 @@
 
   bool get isEmpty => this.length == 0;
 
+  bool get isNotEmpty => !isEmpty;
+
   Iterable<num> take(int n) => IterableMixinWorkaround.takeList(this, n);
 
   Iterable<num> takeWhile(bool test(num value)) {
@@ -534,6 +536,8 @@
 
   bool get isEmpty => this.length == 0;
 
+  bool get isNotEmpty => !isEmpty;
+
   Iterable<num> take(int n) => IterableMixinWorkaround.takeList(this, n);
 
   Iterable<num> takeWhile(bool test(num value)) {
@@ -754,6 +758,8 @@
 
   bool get isEmpty => this.length == 0;
 
+  bool get isNotEmpty => !isEmpty;
+
   Iterable<int> take(int n) => IterableMixinWorkaround.takeList(this, n);
 
   Iterable<int> takeWhile(bool test(int value)) {
@@ -974,6 +980,8 @@
 
   bool get isEmpty => this.length == 0;
 
+  bool get isNotEmpty => !isEmpty;
+
   Iterable<int> take(int n) => IterableMixinWorkaround.takeList(this, n);
 
   Iterable<int> takeWhile(bool test(int value)) {
@@ -1194,6 +1202,8 @@
 
   bool get isEmpty => this.length == 0;
 
+  bool get isNotEmpty => !isEmpty;
+
   Iterable<int> take(int n) => IterableMixinWorkaround.takeList(this, n);
 
   Iterable<int> takeWhile(bool test(int value)) {
@@ -1414,6 +1424,8 @@
 
   bool get isEmpty => this.length == 0;
 
+  bool get isNotEmpty => !isEmpty;
+
   Iterable<int> take(int n) => IterableMixinWorkaround.takeList(this, n);
 
   Iterable<int> takeWhile(bool test(int value)) {
@@ -1634,6 +1646,8 @@
 
   bool get isEmpty => this.length == 0;
 
+  bool get isNotEmpty => !isEmpty;
+
   Iterable<int> take(int n) => IterableMixinWorkaround.takeList(this, n);
 
   Iterable<int> takeWhile(bool test(int value)) {
@@ -1853,6 +1867,8 @@
 
   bool get isEmpty => this.length == 0;
 
+  bool get isNotEmpty => !isEmpty;
+
   Iterable<int> take(int n) => IterableMixinWorkaround.takeList(this, n);
 
   Iterable<int> takeWhile(bool test(int value)) {
@@ -2073,6 +2089,8 @@
 
   bool get isEmpty => this.length == 0;
 
+  bool get isNotEmpty => !isEmpty;
+
   Iterable<int> take(int n) => IterableMixinWorkaround.takeList(this, n);
 
   Iterable<int> takeWhile(bool test(int value)) {
diff --git a/sdk/lib/uri/encode_decode.dart b/sdk/lib/uri/encode_decode.dart
deleted file mode 100644
index 6cddcc0..0000000
--- a/sdk/lib/uri/encode_decode.dart
+++ /dev/null
@@ -1,198 +0,0 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-part of dart.uri;
-
-/**
- * Javascript-like URI encode/decode functions.
- * The documentation here borrows heavily from the original Javascript
- * doumentation on MDN at:
- * https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects
- */
-
-/**
- * A JavaScript-like URI encoder. Encodes Uniform Resource Identifier [uri]
- * by replacing each instance of certain characters by one, two, three, or four
- * escape sequences representing the UTF-8 encoding of the character (will
- * only be four escape sequences for characters composed of two "surrogate"
- * characters). This assumes that [uri] is a complete URI, so does not encode
- * reserved characters that have special meaning in the URI: [:#;,/?:@&=+\$:]
- * It returns the escaped URI.
- */
-String encodeUri(String uri) {
-  // Bit vector of 128 bits where each bit indicate whether a
-  // character code on the 0-127 needs to be escaped or not.
-  const canonicalTable = const [
-                //             LSB            MSB
-                //              |              |
-      0x0000,   // 0x00 - 0x0f  0000000000000000
-      0x0000,   // 0x10 - 0x1f  0000000000000000
-                //               ! #$ &'()*+,-./
-      0xf7da,   // 0x20 - 0x2f  0101101111101111
-                //              0123456789:; = ?
-      0xafff,   // 0x30 - 0x3f  1111111111110101
-                //              @ABCDEFGHIJKLMNO
-      0xffff,   // 0x40 - 0x4f  1111111111111111
-                //              PQRSTUVWXYZ    _
-      0x87ff,   // 0x50 - 0x5f  1111111111100001
-                //               abcdefghijklmno
-      0xfffe,   // 0x60 - 0x6f  0111111111111111
-                //              pqrstuvwxyz   ~
-      0x47ff];  // 0x70 - 0x7f  1111111111100010
-  return _uriEncode(canonicalTable, uri);
-}
-
-/**
- * An implementation of JavaScript's decodeURIComponent function.
- * Decodes a Uniform Resource Identifier [uri] previously created by
- * encodeURI or by a similar routine. It replaces each escape sequence
- * in [uri] with the character that it represents. It does not decode
- * escape sequences that could not have been introduced by encodeURI.
- * It returns the unescaped URI.
- */
-String decodeUri(String uri) {
-  return _uriDecode(uri);
-}
-
-/**
- * A javaScript-like URI component encoder, this encodes a URI
- * [component] by replacing each instance of certain characters by one,
- * two, three, or four escape sequences representing the UTF-8 encoding of
- * the character (will only be four escape sequences for characters composed
- * of two "surrogate" characters).
- * To avoid unexpected requests to the server, you should call
- * encodeURIComponent on any user-entered parameters that will be passed as
- * part of a URI. For example, a user could type "Thyme &time=again" for a
- * variable comment. Not using encodeURIComponent on this variable will give
- * comment=Thyme%20&time=again. Note that the ampersand and the equal sign
- * mark a new key and value pair. So instead of having a POST comment key
- * equal to "Thyme &time=again", you have two POST keys, one equal to "Thyme "
- * and another (time) equal to again.
- * It returns the escaped string.
- */
-String encodeUriComponent(String component) {
-  // Bit vector of 128 bits where each bit indicate whether a
-  // character code on the 0-127 needs to be escaped or not.
-  const canonicalTable = const [
-                //             LSB            MSB
-                //              |              |
-      0x0000,   // 0x00 - 0x0f  0000000000000000
-      0x0000,   // 0x10 - 0x1f  0000000000000000
-                //               !     '()*  -.
-      0x6782,   // 0x20 - 0x2f  0100000111100110
-                //              0123456789
-      0x03ff,   // 0x30 - 0x3f  1111111111000000
-                //              @ABCDEFGHIJKLMNO
-      0xfffe,   // 0x40 - 0x4f  0111111111111111
-                //              PQRSTUVWXYZ    _
-      0x87ff,   // 0x50 - 0x5f  1111111111100001
-                //               abcdefghijklmno
-      0xfffe,   // 0x60 - 0x6f  0111111111111111
-                //              pqrstuvwxyz   ~
-      0x47ff];  // 0x70 - 0x7f  1111111111100010
-  return _uriEncode(canonicalTable, component);
-}
-
-/**
- * An implementation of JavaScript's decodeURIComponent function.
- * Decodes a Uniform Resource Identifier (URI) [component] previously
- * created by encodeURIComponent or by a similar routine.
- * It returns the unescaped string.
- */
-String decodeUriComponent(String encodedComponent) {
-  return _uriDecode(encodedComponent);
-}
-
-/**
- * This is the internal implementation of JavaScript's encodeURI function.
- * It encodes all characters in the string [text] except for those
- * that appear in [canonicalTable], and returns the escaped string.
- */
-String _uriEncode(List<int> canonicalTable, String text) {
-  final String hex = '0123456789ABCDEF';
-  var byteToHex = (int v) => '%${hex[v >> 4]}${hex[v & 0x0f]}';
-  StringBuffer result = new StringBuffer();
-  for (int i = 0; i < text.length; i++) {
-    int ch = text.codeUnitAt(i);
-    if (ch < 128 && ((canonicalTable[ch >> 4] & (1 << (ch & 0x0f))) != 0)) {
-      result.write(text[i]);
-    } else if (text[i] == " ") {
-      result.write("+");
-    } else {
-      if (ch >= 0xD800 && ch < 0xDC00) {
-        // Low surrogate. We expect a next char high surrogate.
-        ++i;
-        int nextCh = text.length == i ? 0 : text.codeUnitAt(i);
-        if (nextCh >= 0xDC00 && nextCh < 0xE000) {
-          // convert the pair to a U+10000 codepoint
-          ch = 0x10000 + ((ch - 0xD800) << 10) + (nextCh - 0xDC00);
-        } else {
-          throw new ArgumentError('Malformed URI');
-        }
-      }
-      for (int codepoint in codepointsToUtf8([ch])) {
-        result.write(byteToHex(codepoint));
-      }
-    }
-  }
-  return result.toString();
-}
-
-/**
- * Convert a byte (2 character hex sequence) in string [s] starting
- * at position [pos] to its ordinal value
- */
-int _hexCharPairToByte(String s, int pos) {
-  int byte = 0;
-  for (int i = 0; i < 2; i++) {
-    var charCode = s.codeUnitAt(pos + i);
-    if (0x30 <= charCode && charCode <= 0x39) {
-      byte = byte * 16 + charCode - 0x30;
-    } else {
-      // Check ranges A-F (0x41-0x46) and a-f (0x61-0x66).
-      charCode |= 0x20;
-      if (0x61 <= charCode && charCode <= 0x66) {
-        byte = byte * 16 + charCode - 0x57;
-      } else {
-        throw new ArgumentError("Invalid URL encoding");
-      }
-    }
-  }
-  return byte;
-}
-
-/**
- * A JavaScript-like decodeURI function. It unescapes the string [text] and
- * returns the unescaped string.
- */
-String _uriDecode(String text) {
-  StringBuffer result = new StringBuffer();
-  List<int> codepoints = new List<int>();
-  for (int i = 0; i < text.length;) {
-    String ch = text[i];
-    if (ch != '%') {
-      if (ch == '+') {
-        result.write(" ");
-      } else {
-        result.write(ch);
-      }
-      i++;
-    } else {
-      codepoints.clear();
-      while (ch == '%') {
-        if (++i > text.length - 2) {
-          throw new ArgumentError('Truncated URI');
-        }
-        codepoints.add(_hexCharPairToByte(text, i));
-        i += 2;
-        if (i == text.length)
-          break;
-        ch = text[i];
-      }
-      result.write(decodeUtf8(codepoints));
-    }
-  }
-  return result.toString();
-}
-
diff --git a/sdk/lib/uri/helpers.dart b/sdk/lib/uri/helpers.dart
deleted file mode 100644
index 2a16a47..0000000
--- a/sdk/lib/uri/helpers.dart
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-part of dart.uri;
-
-String merge(String base, String reference) {
-  if (base == "") return "/$reference";
-  return "${base.substring(0, base.lastIndexOf("/") + 1)}$reference";
-}
-
-String removeDotSegments(String path) {
-  List<String> output = [];
-  bool appendSlash = false;
-  for (String segment in path.split("/")) {
-    appendSlash = false;
-    if (segment == "..") {
-      if (!output.isEmpty &&
-          ((output.length != 1) || (output[0] != ""))) output.removeLast();
-      appendSlash = true;
-    } else if ("." == segment) {
-      appendSlash = true;
-    } else {
-      output.add(segment);
-    }
-  }
-  if (appendSlash) output.add("");
-  return output.join("/");
-}
diff --git a/sdk/lib/uri/uri.dart b/sdk/lib/uri/uri.dart
deleted file mode 100644
index 967e9a3..0000000
--- a/sdk/lib/uri/uri.dart
+++ /dev/null
@@ -1,280 +0,0 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library dart.uri;
-
-import 'dart:math';
-import 'dart:utf';
-
-part 'encode_decode.dart';
-part 'helpers.dart';
-
-/**
- * A parsed URI, inspired by Closure's [URI][] class. Implements [RFC-3986][].
- * The domain component can either be a hostname, a IPv4 address or an IPv6
- * address, contained in '[' and ']', following [RFC-2732][]. If the domain
- * component contains a ':', the String returned from [toString] will have
- * '[' and ']' around the domain part.
- * [URI]: http://closure-library.googlecode.com/svn/docs/class_goog_Uri.html
- * [RFC-3986]: http://tools.ietf.org/html/rfc3986#section-4.3)
- * [RFC-2732]: http://www.ietf.org/rfc/rfc2732.txt
- */
-class Uri {
-  final String scheme;
-  final String userInfo;
-  final String domain;
-  final int port;
-  final String path;
-  final String query;
-  final String fragment;
-
-  static Uri parse(String uri) => new Uri._fromMatch(_splitRe.firstMatch(uri));
-
-  Uri._fromMatch(Match m) :
-    this.fromComponents(scheme: _emptyIfNull(m[_COMPONENT_SCHEME]),
-                        userInfo: _emptyIfNull(m[_COMPONENT_USER_INFO]),
-                        domain: _eitherOf(
-                            m[_COMPONENT_DOMAIN], m[_COMPONENT_DOMAIN_IPV6]),
-                        port: _parseIntOrZero(m[_COMPONENT_PORT]),
-                        path: _emptyIfNull(m[_COMPONENT_PATH]),
-                        query: _emptyIfNull(m[_COMPONENT_QUERY_DATA]),
-                        fragment: _emptyIfNull(m[_COMPONENT_FRAGMENT]));
-
-  const Uri.fromComponents({this.scheme: "",
-                            this.userInfo: "",
-                            this.domain: "",
-                            this.port: 0,
-                            this.path: "",
-                            this.query: "",
-                            this.fragment: ""});
-
-  Uri(String uri) : this._fromMatch(_splitRe.firstMatch(uri));
-
-  static String _emptyIfNull(String val) => val != null ? val : '';
-
-  static int _parseIntOrZero(String val) {
-    if (val != null && val != '') {
-      return int.parse(val);
-    } else {
-      return 0;
-    }
-  }
-
-  static String _eitherOf(String val1, String val2) {
-    if (val1 != null) return val1;
-    if (val2 != null) return val2;
-    return '';
-  }
-
-  // NOTE: This code was ported from: closure-library/closure/goog/uri/utils.js
-  static final RegExp _splitRe = new RegExp(
-      '^'
-      '(?:'
-        '([^:/?#.]+)'                   // scheme - ignore special characters
-                                        // used by other URL parts such as :,
-                                        // ?, /, #, and .
-      ':)?'
-      '(?://'
-        '(?:([^/?#]*)@)?'               // userInfo
-        '(?:'
-          r'([\w\d\-\u0100-\uffff.%]*)'
-                                        // domain - restrict to letters,
-                                        // digits, dashes, dots, percent
-                                        // escapes, and unicode characters.
-          '|'
-          // TODO(ajohnsen): Only allow a max number of parts?
-          r'\[([A-Fa-f0-9:.]*)\])'
-                                        // IPv6 domain - restrict to hex,
-                                        // dot and colon.
-        '(?::([0-9]+))?'                // port
-      ')?'
-      r'([^?#[]+)?'                     // path
-      r'(?:\?([^#]*))?'                 // query
-      '(?:#(.*))?'                      // fragment
-      r'$');
-
-  static const _COMPONENT_SCHEME = 1;
-  static const _COMPONENT_USER_INFO = 2;
-  static const _COMPONENT_DOMAIN = 3;
-  static const _COMPONENT_DOMAIN_IPV6 = 4;
-  static const _COMPONENT_PORT = 5;
-  static const _COMPONENT_PATH = 6;
-  static const _COMPONENT_QUERY_DATA = 7;
-  static const _COMPONENT_FRAGMENT = 8;
-
-  /**
-   * Returns `true` if the URI is absolute.
-   */
-  bool get isAbsolute {
-    if ("" == scheme) return false;
-    if ("" != fragment) return false;
-    return true;
-
-    /* absolute-URI  = scheme ":" hier-part [ "?" query ]
-     * hier-part   = "//" authority path-abempty
-     *             / path-absolute
-     *             / path-rootless
-     *             / path-empty
-     *
-     * path          = path-abempty    ; begins with "/" or is empty
-     *               / path-absolute   ; begins with "/" but not "//"
-     *               / path-noscheme   ; begins with a non-colon segment
-     *               / path-rootless   ; begins with a segment
-     *               / path-empty      ; zero characters
-     *
-     * path-abempty  = *( "/" segment )
-     * path-absolute = "/" [ segment-nz *( "/" segment ) ]
-     * path-noscheme = segment-nz-nc *( "/" segment )
-     * path-rootless = segment-nz *( "/" segment )
-     * path-empty    = 0<pchar>
-     * segment       = *pchar
-     * segment-nz    = 1*pchar
-     * segment-nz-nc = 1*( unreserved / pct-encoded / sub-delims / "@" )
-     *               ; non-zero-length segment without any colon ":"
-     *
-     * pchar         = unreserved / pct-encoded / sub-delims / ":" / "@"
-     */
-  }
-
-  Uri resolve(String uri) {
-    return resolveUri(Uri.parse(uri));
-  }
-
-  Uri resolveUri(Uri reference) {
-    // From RFC 3986.
-    String targetScheme;
-    String targetUserInfo;
-    String targetDomain;
-    int targetPort;
-    String targetPath;
-    String targetQuery;
-    if (reference.scheme != "") {
-      targetScheme = reference.scheme;
-      targetUserInfo = reference.userInfo;
-      targetDomain = reference.domain;
-      targetPort = reference.port;
-      targetPath = removeDotSegments(reference.path);
-      targetQuery = reference.query;
-    } else {
-      if (reference.hasAuthority) {
-        targetUserInfo = reference.userInfo;
-        targetDomain = reference.domain;
-        targetPort = reference.port;
-        targetPath = removeDotSegments(reference.path);
-        targetQuery = reference.query;
-      } else {
-        if (reference.path == "") {
-          targetPath = this.path;
-          if (reference.query != "") {
-            targetQuery = reference.query;
-          } else {
-            targetQuery = this.query;
-          }
-        } else {
-          if (reference.path.startsWith("/")) {
-            targetPath = removeDotSegments(reference.path);
-          } else {
-            targetPath = removeDotSegments(merge(this.path, reference.path));
-          }
-          targetQuery = reference.query;
-        }
-        targetUserInfo = this.userInfo;
-        targetDomain = this.domain;
-        targetPort = this.port;
-      }
-      targetScheme = this.scheme;
-    }
-    return new Uri.fromComponents(scheme: targetScheme,
-                                  userInfo: targetUserInfo,
-                                  domain: targetDomain,
-                                  port: targetPort,
-                                  path: targetPath,
-                                  query: targetQuery,
-                                  fragment: reference.fragment);
-  }
-
-  bool get hasAuthority {
-    return (userInfo != "") || (domain != "") || (port != 0);
-  }
-
-  /**
-   * For http/https schemes returns URI's [origin][] - scheme://domain:port.
-   * For all other schemes throws ArgumentError.
-   * [origin]: http://www.w3.org/TR/2011/WD-html5-20110405/origin-0.html#origin
-   */
-  String get origin {
-    if (scheme == "") {
-      // TODO(aprelev@gmail.com): Use StateException instead
-      throw new ArgumentError("Cannot use origin without a scheme");
-    }
-    if (scheme != "http" && scheme != "https") {
-      // TODO(aprelev@gmail.com): Use StateException instead
-      throw new ArgumentError(
-        "origin is applicable to http/https schemes only. Not \'$scheme\'");
-    }
-    StringBuffer sb = new StringBuffer();
-    sb.write(scheme);
-    sb.write(":");
-    if (domain == null || domain == "") {
-      // TODO(aprelev@gmail.com): Use StateException instead
-      throw new ArgumentError("Cannot use origin without a domain");
-    }
-
-    sb.write("//");
-    sb.write(domain);
-    if (port != 0) {
-      sb.write(":");
-      sb.write(port);
-    }
-    return sb.toString();
-  }
-
-  String toString() {
-    StringBuffer sb = new StringBuffer();
-    _addIfNonEmpty(sb, scheme, scheme, ':');
-    if (hasAuthority || (scheme == "file")) {
-      sb.write("//");
-      _addIfNonEmpty(sb, userInfo, userInfo, "@");
-      sb.write(domain == null ? "null" :
-          domain.contains(':') ? '[$domain]' : domain);
-      if (port != 0) {
-        sb.write(":");
-        sb.write(port.toString());
-      }
-    }
-    sb.write(path == null ? "null" : path);
-    _addIfNonEmpty(sb, query, "?", query);
-    _addIfNonEmpty(sb, fragment, "#", fragment);
-    return sb.toString();
-  }
-
-  bool operator==(other) {
-    if (other is! Uri) return false;
-    Uri uri = other;
-    return scheme == uri.scheme &&
-        userInfo == uri.userInfo &&
-        domain == uri.domain &&
-        port == uri.port &&
-        path == uri.path &&
-        query == uri.query &&
-        fragment == uri.fragment;
-  }
-
-  int get hashCode {
-    int combine(part, current) {
-      // The sum is truncated to 30 bits to make sure it fits into a Smi.
-      return (current * 31 + part.hashCode) & 0x3FFFFFFF;
-    }
-    return combine(scheme, combine(userInfo, combine(domain, combine(port,
-        combine(path, combine(query, combine(fragment, 1)))))));
-  }
-
-  static void _addIfNonEmpty(StringBuffer sb, String test,
-                             String first, String second) {
-    if ("" != test) {
-      sb.write(first == null ? "null" : first);
-      sb.write(second == null ? "null" : second);
-    }
-  }
-}
diff --git a/sdk/lib/uri/uri_sources.gypi b/sdk/lib/uri/uri_sources.gypi
deleted file mode 100644
index 09f54fc..0000000
--- a/sdk/lib/uri/uri_sources.gypi
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
-# for details. All rights reserved. Use of this source code is governed by a
-# BSD-style license that can be found in the LICENSE file.
-
-# This file contains all sources for the dart:uri library.
-{
-  'sources': [
-    'uri.dart',
-    # The above file needs to be first as it lists the parts below.
-    'helpers.dart',
-    'encode_decode.dart',
-  ],
-}
diff --git a/sdk/lib/utf/utf_stream.dart b/sdk/lib/utf/utf_stream.dart
index 7d72118..8440313 100644
--- a/sdk/lib/utf/utf_stream.dart
+++ b/sdk/lib/utf/utf_stream.dart
@@ -4,16 +4,6 @@
 
 part of dart.utf;
 
-class _HelperStreamController<T> extends StreamController<T> {
-  final Function onPauseChanged;
-
-  _HelperStreamController(this.onPauseChanged);
-
-  void onPauseStateChange() {
-    onPauseChanged();
-  }
-}
-
 abstract class _StringDecoder
     extends StreamEventTransformer<List<int>, String> {
   List<int> _carry;
diff --git a/sdk/lib/web_audio/dartium/web_audio_dartium.dart b/sdk/lib/web_audio/dartium/web_audio_dartium.dart
index 6c60ae1..786b08d 100644
--- a/sdk/lib/web_audio/dartium/web_audio_dartium.dart
+++ b/sdk/lib/web_audio/dartium/web_audio_dartium.dart
@@ -260,6 +260,9 @@
   @DomName('AudioContext.completeEvent')
   @DocsEditable
   static const EventStreamProvider<Event> completeEvent = const EventStreamProvider<Event>('complete');
+
+  @DomName('AudioContext.AudioContext')
+  @DocsEditable
   factory AudioContext() => _create();
 
   @DocsEditable
diff --git a/tests/co19/co19-analyzer.status b/tests/co19/co19-analyzer.status
index 63668be..f037e57 100644
--- a/tests/co19/co19-analyzer.status
+++ b/tests/co19/co19-analyzer.status
@@ -68,12 +68,6 @@
 Language/11_Expressions/06_Lists_A03_t01: fail
 Language/11_Expressions/06_Lists_A06_t01: fail
 Language/11_Expressions/07_Maps_A02_t02: fail
-Language/11_Expressions/08_Throw_A06_t01: fail
-Language/11_Expressions/08_Throw_A06_t02: fail
-Language/11_Expressions/08_Throw_A06_t03: fail
-Language/11_Expressions/08_Throw_A06_t04: fail
-Language/11_Expressions/08_Throw_A06_t05: fail
-Language/11_Expressions/08_Throw_A06_t06: 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
@@ -198,6 +192,10 @@
 Language/03_Overview/1_Scoping_A02_t12: fail, OK
 Language/03_Overview/1_Scoping_A02_t16: fail, OK
 
+# co19 issue #420, 'throw' without exception; deprecated; rethrow should be used
+Language/11_Expressions/08_Throw_A05_t01: fail, OK
+Language/11_Expressions/08_Throw_A05_t02: fail, OK
+Language/11_Expressions/08_Throw_A05_t03: fail, OK
 
 
 [ $runtime == drt && $compiler == none ]
diff --git a/tests/co19/co19-dart2dart.status b/tests/co19/co19-dart2dart.status
index d9e50ce..e639cac 100644
--- a/tests/co19/co19-dart2dart.status
+++ b/tests/co19/co19-dart2dart.status
@@ -85,7 +85,6 @@
 Language/03_Overview/1_Scoping_A02_t05: Fail # Inherited from dart2js
 Language/03_Overview/1_Scoping_A02_t06: Fail # inherited from dart2js
 Language/03_Overview/1_Scoping_A02_t07: Fail # inherited from dart2js
-Language/03_Overview/1_Scoping_A02_t12: Fail # inherited from dart2js
 Language/03_Overview/2_Privacy_A01_t06: Fail # New import syntax
 Language/05_Variables/05_Variables_A01_t04: Fail # http://dartbug.com/5519
 Language/05_Variables/05_Variables_A01_t05: Fail # http://dartbug.com/5519
diff --git a/tests/co19/co19-dart2js.status b/tests/co19/co19-dart2js.status
index 4cf42f1..48de78a 100644
--- a/tests/co19/co19-dart2js.status
+++ b/tests/co19/co19-dart2js.status
@@ -165,8 +165,6 @@
 
 Language/07_Classes/6_Constructors/2_Factories_A01_t05: Fail # Partially implemented rediriecting constructors makes this fail.
 
-Language/09_Generics/09_Generics_A04_t03: Fail # dart2js does not treat 2.0 as a double; dartbug.com/1533
-
 [ $compiler == dart2js && $runtime == ie9 ]
 Language/11_Expressions/03_Numbers_A01_t06: Fail # Issue: 8920
 Language/11_Expressions/03_Numbers_A01_t09: Fail # Issue: 8920
@@ -273,9 +271,6 @@
 
 Language/14_Types/3_Type_Declarations/1_Typedef_A01_t01: Fail # http://dartbug.com/5022
 
-LibTest/core/List/operator_subscript_A03_t01: Fail # http://dartbug.com/9228
-LibTest/core/List/operator_subscripted_assignment_A03_t01: Fail # http://dartbug.com/9228
-Language/09_Generics/09_Generics_A04_t01: Fail, OK # 1.0 is an int in dart2js; dartbug.com/1533.
 
 Language/11_Expressions/14_Function_Invocation/4_Function_Expression_Invocation_A01_t02: Fail, OK # co19 issue 405
 Language/11_Expressions/15_Method_Invocation/1_Ordinary_Invocation_A05_t03: Fail, OK # co19 issue 405
@@ -611,7 +606,6 @@
 Language/07_Classes/6_Constructors/1_Generative_Constructors_A13_t01: Fail # compiler cancelled: cannot resolve type T
 
 Language/03_Overview/1_Scoping_A02_t07: Fail # duplicate definition of f(var f){f();}
-Language/03_Overview/1_Scoping_A02_t12: Fail # duplicate definition of x=42
 Language/03_Overview/2_Privacy_A01_t06: Fail # cannot resolve type _inaccessibleFuncType
 
 Language/11_Expressions/01_Constants_A12_t01: Fail # internal error: CompileTimeConstantEvaluator not implemented
diff --git a/tests/co19/co19-runtime.status b/tests/co19/co19-runtime.status
index 850976f..79111bd 100644
--- a/tests/co19/co19-runtime.status
+++ b/tests/co19/co19-runtime.status
@@ -514,10 +514,6 @@
 *: Skip
 
 
-[ $compiler == none && $arch == arm ]
-*: Skip
-
-
 [ $compiler == none && $arch == simmips ]
 *: Skip
 
diff --git a/tests/compiler/dart2js/analyze_all_test.dart b/tests/compiler/dart2js/analyze_all_test.dart
index 439019d..2a7fcc7 100644
--- a/tests/compiler/dart2js/analyze_all_test.dart
+++ b/tests/compiler/dart2js/analyze_all_test.dart
@@ -27,7 +27,7 @@
 """;
 
 main() {
-  Uri uri = new Uri('test:code');
+  Uri uri = Uri.parse('test:code');
   var compiler = compilerFor(SOURCE, uri, analyzeAll: false);
   compiler.runCompiler(uri);
   Expect.isFalse(compiler.compilationFailed);
diff --git a/tests/compiler/dart2js/analyze_api_test.dart b/tests/compiler/dart2js/analyze_api_test.dart
index 4e75440..a4cca28 100644
--- a/tests/compiler/dart2js/analyze_api_test.dart
+++ b/tests/compiler/dart2js/analyze_api_test.dart
@@ -5,15 +5,8 @@
 library analyze_api;
 
 import "package:expect/expect.dart";
-import 'dart:uri';
-import 'dart:io';
-import '../../../sdk/lib/_internal/compiler/compiler.dart' as api;
-import '../../../sdk/lib/_internal/compiler/implementation/apiimpl.dart';
-import '../../../sdk/lib/_internal/compiler/implementation/dart2jslib.dart'
-    hide Compiler;
-import '../../../sdk/lib/_internal/compiler/implementation/filenames.dart';
-import '../../../sdk/lib/_internal/compiler/implementation/source_file_provider.dart';
 import '../../../sdk/lib/_internal/libraries.dart';
+import 'analyze_helper.dart';
 
 /**
  * Map of white-listed warnings and errors.
@@ -26,7 +19,7 @@
  */
 // TODO(johnniwinther): Support canonical URIs as keys and message kinds as
 // values.
-const Map<String,List<String>> WHITE_LIST = const {
+const Map<String, List<String>> WHITE_LIST = const {
   'html_dart2js.dart':
       const ['Warning: Using "new Symbol"', // Issue 10565.
              // Issue 10688:
@@ -35,105 +28,12 @@
              "Warning: no operator [] in class Iterable"],
 };
 
-class CollectingDiagnosticHandler extends FormattingDiagnosticHandler {
-  bool hasWarnings = false;
-  bool hasErrors = false;
-
-  Map<String,Map<String,int>> whiteListMap = new Map<String,Map<String,int>>();
-
-  CollectingDiagnosticHandler(SourceFileProvider provider) : super(provider) {
-    WHITE_LIST.forEach((String file, List<String> messageParts) {
-      var useMap = new Map<String,int>();
-      for (String messagePart in messageParts) {
-        useMap[messagePart] = 0;
-      }
-      whiteListMap[file] = useMap;
-    });
-  }
-
-  bool checkWhiteListUse() {
-    bool allUsed = true;
-    for (String file in whiteListMap.keys) {
-      for (String messagePart in whiteListMap[file].keys) {
-        if (whiteListMap[file][messagePart] == 0) {
-          print("White-listing '$messagePart' is unused in '$file'. "
-                "Remove the white-listing from the WHITE_LIST map.");
-          allUsed = false;
-        }
-      }
-    }
-    return allUsed;
-  }
-
-  void reportWhiteListUse() {
-    for (String file in whiteListMap.keys) {
-      for (String messagePart in whiteListMap[file].keys) {
-        int useCount = whiteListMap[file][messagePart];
-        print("White-listed message '$messagePart' suppressed $useCount "
-              "time(s) in '$file'.");
-      }
-    }
-  }
-
-  bool checkWhiteList(Uri uri, String message) {
-    if (uri == null) {
-      return false;
-    }
-    String path = uri.path;
-    for (String file in whiteListMap.keys) {
-      if (path.endsWith(file)) {
-        for (String messagePart in whiteListMap[file].keys) {
-          if (message.contains(messagePart)) {
-            whiteListMap[file][messagePart]++;
-            return true;
-          }
-        }
-      }
-    }
-    return false;
-  }
-
-  void diagnosticHandler(Uri uri, int begin, int end, String message,
-                         api.Diagnostic kind) {
-    if (kind == api.Diagnostic.WARNING) {
-      if (checkWhiteList(uri, message)) {
-        // Suppress white listed warnings.
-        return;
-      }
-      hasWarnings = true;
-    }
-    if (kind == api.Diagnostic.ERROR) {
-      if (checkWhiteList(uri, message)) {
-        // Suppress white listed warnings.
-        return;
-      }
-      hasErrors = true;
-    }
-    super.diagnosticHandler(uri, begin, end, message, kind);
-  }
-}
-
 void main() {
-  var libraryRoot = currentDirectory.resolve('sdk/');
   var uriList = new List<Uri>();
   LIBRARIES.forEach((String name, LibraryInfo info) {
     if (info.documented) {
-      uriList.add(new Uri.fromComponents(scheme: 'dart', path: name));
+      uriList.add(new Uri(scheme: 'dart', path: name));
     }
   });
-  var provider = new SourceFileProvider();
-  var handler = new CollectingDiagnosticHandler(provider);
-  var compiler = new Compiler(
-      provider.readStringFromUri,
-      null,
-      handler.diagnosticHandler,
-      libraryRoot, libraryRoot,
-      <String>['--analyze-only', '--analyze-all',
-               '--categories=Client,Server']);
-  compiler.librariesToAnalyzeWhenRun = uriList;
-  compiler.run(null);
-  Expect.isFalse(handler.hasWarnings);
-  Expect.isFalse(handler.hasErrors);
-  Expect.isTrue(handler.checkWhiteListUse());
-  handler.reportWhiteListUse();
+  analyze(uriList, WHITE_LIST);
 }
diff --git a/tests/compiler/dart2js/analyze_dart2js_test.dart b/tests/compiler/dart2js/analyze_dart2js_test.dart
new file mode 100644
index 0000000..cb66fdf
--- /dev/null
+++ b/tests/compiler/dart2js/analyze_dart2js_test.dart
@@ -0,0 +1,29 @@
+// 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 analyze_api;
+
+import "package:expect/expect.dart";
+import '../../../sdk/lib/_internal/compiler/implementation/filenames.dart';
+import 'analyze_helper.dart';
+
+/**
+ * Map of white-listed warnings and errors.
+ *
+ * Only add a white-listing together with a bug report to dartbug.com and add
+ * the bug issue number as a comment on the white-listing.
+ *
+ * Use an identifiable suffix of the file uri as key. Use a fixed substring of
+ * the error/warning message in the list of white-listings for each file.
+ */
+// TODO(johnniwinther): Support canonical URIs as keys and message kinds as
+// values.
+const Map<String,List<String>> WHITE_LIST = const {
+};
+
+void main() {
+  var uri = currentDirectory.resolve(
+      'sdk/lib/_internal/compiler/implementation/dart2js.dart');
+  analyze([uri], WHITE_LIST);
+}
diff --git a/tests/compiler/dart2js/analyze_helper.dart b/tests/compiler/dart2js/analyze_helper.dart
new file mode 100644
index 0000000..c3e6729
--- /dev/null
+++ b/tests/compiler/dart2js/analyze_helper.dart
@@ -0,0 +1,130 @@
+// 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 analyze_helper;
+
+import "package:expect/expect.dart";
+import 'dart:io';
+import '../../../sdk/lib/_internal/compiler/compiler.dart' as api;
+import '../../../sdk/lib/_internal/compiler/implementation/apiimpl.dart';
+import '../../../sdk/lib/_internal/compiler/implementation/dart2jslib.dart'
+    hide Compiler;
+import '../../../sdk/lib/_internal/compiler/implementation/filenames.dart';
+import '../../../sdk/lib/_internal/compiler/implementation/source_file_provider.dart';
+
+/**
+ * Map of white-listed warnings and errors.
+ *
+ * Only add a white-listing together with a bug report to dartbug.com and add
+ * the bug issue number as a comment on the white-listing.
+ *
+ * Use an identifiable suffix of the file uri as key. Use a fixed substring of
+ * the error/warning message in the list of white-listings for each file.
+ */
+// TODO(johnniwinther): Support canonical URIs as keys and message kinds as
+// values.
+
+class CollectingDiagnosticHandler extends FormattingDiagnosticHandler {
+  bool hasWarnings = false;
+  bool hasErrors = false;
+
+  Map<String, Map<String, int>> whiteListMap
+      = new Map<String, Map<String, int>>();
+
+  CollectingDiagnosticHandler(Map<String, List<String>> whiteList,
+                              SourceFileProvider provider)
+      : super(provider) {
+    whiteList.forEach((String file, List<String> messageParts) {
+      var useMap = new Map<String,int>();
+      for (String messagePart in messageParts) {
+        useMap[messagePart] = 0;
+      }
+      whiteListMap[file] = useMap;
+    });
+  }
+
+  void checkResults() {
+    Expect.isFalse(hasWarnings);
+    Expect.isFalse(hasErrors);
+    Expect.isTrue(checkWhiteListUse());
+    reportWhiteListUse();
+  }
+
+  bool checkWhiteListUse() {
+    bool allUsed = true;
+    for (String file in whiteListMap.keys) {
+      for (String messagePart in whiteListMap[file].keys) {
+        if (whiteListMap[file][messagePart] == 0) {
+          print("White-listing '$messagePart' is unused in '$file'. "
+                "Remove the white-listing from the white list map.");
+          allUsed = false;
+        }
+      }
+    }
+    return allUsed;
+  }
+
+  void reportWhiteListUse() {
+    for (String file in whiteListMap.keys) {
+      for (String messagePart in whiteListMap[file].keys) {
+        int useCount = whiteListMap[file][messagePart];
+        print("White-listed message '$messagePart' suppressed $useCount "
+              "time(s) in '$file'.");
+      }
+    }
+  }
+
+  bool checkWhiteList(Uri uri, String message) {
+    if (uri == null) {
+      return false;
+    }
+    String path = uri.path;
+    for (String file in whiteListMap.keys) {
+      if (path.endsWith(file)) {
+        for (String messagePart in whiteListMap[file].keys) {
+          if (message.contains(messagePart)) {
+            whiteListMap[file][messagePart]++;
+            return true;
+          }
+        }
+      }
+    }
+    return false;
+  }
+
+  void diagnosticHandler(Uri uri, int begin, int end, String message,
+                         api.Diagnostic kind) {
+    if (kind == api.Diagnostic.WARNING) {
+      if (checkWhiteList(uri, message)) {
+        // Suppress white listed warnings.
+        return;
+      }
+      hasWarnings = true;
+    }
+    if (kind == api.Diagnostic.ERROR) {
+      if (checkWhiteList(uri, message)) {
+        // Suppress white listed warnings.
+        return;
+      }
+      hasErrors = true;
+    }
+    super.diagnosticHandler(uri, begin, end, message, kind);
+  }
+}
+
+void analyze(List<Uri> uriList, Map<String, List<String>> whiteList) {
+  var libraryRoot = currentDirectory.resolve('sdk/');
+  var provider = new SourceFileProvider();
+  var handler = new CollectingDiagnosticHandler(whiteList, provider);
+  var compiler = new Compiler(
+      provider.readStringFromUri,
+      null,
+      handler.diagnosticHandler,
+      libraryRoot, libraryRoot,
+      <String>['--analyze-only', '--analyze-all',
+               '--categories=Client,Server']);
+  compiler.librariesToAnalyzeWhenRun = uriList;
+  compiler.run(null);
+  handler.checkResults();
+}
diff --git a/tests/compiler/dart2js/analyze_only_test.dart b/tests/compiler/dart2js/analyze_only_test.dart
index c890e85..34e52c7 100644
--- a/tests/compiler/dart2js/analyze_only_test.dart
+++ b/tests/compiler/dart2js/analyze_only_test.dart
@@ -7,7 +7,6 @@
 
 import "package:expect/expect.dart";
 import 'dart:async';
-import 'dart:uri';
 
 import '../../utils/dummy_compiler_test.dart' as dummy;
 import '../../../sdk/lib/_internal/compiler/compiler.dart';
@@ -36,9 +35,9 @@
   print('main source:\n$main');
   print('options: $options\n');
   Future<String> result =
-      compile(new Uri.fromComponents(scheme: 'main'),
-              new Uri.fromComponents(scheme: 'lib', path: '/'),
-              new Uri.fromComponents(scheme: 'package', path: '/'),
+      compile(new Uri(scheme: 'main'),
+              new Uri(scheme: 'lib', path: '/'),
+              new Uri(scheme: 'package', path: '/'),
               localProvider, localHandler, options);
   result.then((String code) {
     onValue(code, errors, warnings);
diff --git a/tests/compiler/dart2js/backend_htype_list_test.dart b/tests/compiler/dart2js/backend_htype_list_test.dart
index 7b44059..67acff3 100644
--- a/tests/compiler/dart2js/backend_htype_list_test.dart
+++ b/tests/compiler/dart2js/backend_htype_list_test.dart
@@ -29,7 +29,7 @@
 FunctionSignature compileAndFindSignature(String code,
                                           String className,
                                           String memberName) {
-  Uri uri = new Uri.fromComponents(scheme: 'source');
+  Uri uri = new Uri(scheme: 'source');
   var compiler = compilerFor(code, uri);
   compiler.runCompiler(uri);
   var cls = findElement(compiler, className);
diff --git a/tests/compiler/dart2js/bad_loop_test.dart b/tests/compiler/dart2js/bad_loop_test.dart
index 5705095..dbf8795 100644
--- a/tests/compiler/dart2js/bad_loop_test.dart
+++ b/tests/compiler/dart2js/bad_loop_test.dart
@@ -37,7 +37,7 @@
                                    libraryRoot,
                                    packageRoot,
                                    ['--analyze-only']);
-  compiler.run(new Uri('memory:main.dart'));
+  compiler.run(Uri.parse('memory:main.dart'));
   Expect.isTrue(compiler.compilationFailed);
   Expect.equals(5, errorCount);
   Expect.equals(1, warningCount);
diff --git a/tests/compiler/dart2js/call_site_simple_type_inferer_test.dart b/tests/compiler/dart2js/call_site_simple_type_inferer_test.dart
index 8ff09c7..d3fd545 100644
--- a/tests/compiler/dart2js/call_site_simple_type_inferer_test.dart
+++ b/tests/compiler/dart2js/call_site_simple_type_inferer_test.dart
@@ -14,7 +14,7 @@
                     String memberName,
                     bool disableInlining,
                     check(compiler, element)) {
-  Uri uri = new Uri.fromComponents(scheme: 'source');
+  Uri uri = new Uri(scheme: 'source');
   var compiler = compilerFor(code, uri);
   compiler.disableInlining = disableInlining;
   compiler.runCompiler(uri);
diff --git a/tests/compiler/dart2js/call_site_type_inferer_static_test.dart b/tests/compiler/dart2js/call_site_type_inferer_static_test.dart
index 5a77227..e8a1f0b 100644
--- a/tests/compiler/dart2js/call_site_type_inferer_static_test.dart
+++ b/tests/compiler/dart2js/call_site_type_inferer_static_test.dart
@@ -13,7 +13,7 @@
                     String functionName,
                     bool disableInlining,
                     check(compiler, element)) {
-  Uri uri = new Uri.fromComponents(scheme: 'source');
+  Uri uri = new Uri(scheme: 'source');
   var compiler = compilerFor(code, uri);
   compiler.disableInlining = disableInlining;
   compiler.runCompiler(uri);
diff --git a/tests/compiler/dart2js/call_site_type_inferer_test.dart b/tests/compiler/dart2js/call_site_type_inferer_test.dart
index bad589f..7e75dd1 100644
--- a/tests/compiler/dart2js/call_site_type_inferer_test.dart
+++ b/tests/compiler/dart2js/call_site_type_inferer_test.dart
@@ -14,7 +14,7 @@
                     String memberName,
                     bool disableInlining,
                     check(compiler, element)) {
-  Uri uri = new Uri.fromComponents(scheme: 'source');
+  Uri uri = new Uri(scheme: 'source');
   var compiler = compilerFor(code, uri);
   compiler.disableInlining = disableInlining;
   compiler.runCompiler(uri);
diff --git a/tests/compiler/dart2js/codegen_helper.dart b/tests/compiler/dart2js/codegen_helper.dart
index f89a80b..23884da 100644
--- a/tests/compiler/dart2js/codegen_helper.dart
+++ b/tests/compiler/dart2js/codegen_helper.dart
@@ -23,7 +23,7 @@
                                    libraryRoot,
                                    packageRoot,
                                    options);
-  Uri uri = new Uri('memory:main.dart');
+  Uri uri = Uri.parse('memory:main.dart');
   Expect.isTrue(compiler.run(uri));
   Map<String, String> result = new Map<String, String>();
   for (var element in compiler.backend.generatedCode.keys) {
diff --git a/tests/compiler/dart2js/compiler_helper.dart b/tests/compiler/dart2js/compiler_helper.dart
index e602004..8c72e42 100644
--- a/tests/compiler/dart2js/compiler_helper.dart
+++ b/tests/compiler/dart2js/compiler_helper.dart
@@ -6,8 +6,6 @@
 library compiler_helper;
 
 import "package:expect/expect.dart";
-import 'dart:uri';
-export 'dart:uri' show Uri;
 
 import '../../../sdk/lib/_internal/compiler/implementation/elements/elements.dart'
        as lego;
@@ -90,7 +88,7 @@
 }
 
 String compileAll(String code, {String coreSource: DEFAULT_CORELIB}) {
-  Uri uri = new Uri.fromComponents(scheme: 'source');
+  Uri uri = new Uri(scheme: 'source');
   MockCompiler compiler = compilerFor(code, uri, coreSource: coreSource);
   compiler.runCompiler(uri);
   Expect.isFalse(compiler.compilationFailed,
@@ -101,7 +99,7 @@
 dynamic compileAndCheck(String code,
                         String name,
                         check(MockCompiler compiler, lego.Element element)) {
-  Uri uri = new Uri.fromComponents(scheme: 'source');
+  Uri uri = new Uri(scheme: 'source');
   MockCompiler compiler = compilerFor(code, uri);
   compiler.runCompiler(uri);
   lego.Element element = findElement(compiler, name);
@@ -110,7 +108,7 @@
 
 compileSources(Map<String, String> sources,
                check(MockCompiler compiler)) {
-  Uri base = new Uri.fromComponents(scheme: 'source');
+  Uri base = new Uri(scheme: 'source');
   Uri mainUri = base.resolve('main.dart');
   String mainCode = sources['main.dart'];
   Expect.isNotNull(mainCode, 'No source code found for "main.dart"');
diff --git a/tests/compiler/dart2js/concrete_type_inference_test.dart b/tests/compiler/dart2js/concrete_type_inference_test.dart
index 6a748c6..c801442 100644
--- a/tests/compiler/dart2js/concrete_type_inference_test.dart
+++ b/tests/compiler/dart2js/concrete_type_inference_test.dart
@@ -8,7 +8,7 @@
 
 void compileAndFind(String code, String name,
                     check(compiler, element)) {
-  Uri uri = new Uri.fromComponents(scheme: 'source');
+  Uri uri = new Uri(scheme: 'source');
   var compiler = compilerFor(code, uri);
   compiler.runCompiler(uri);
   var element = findElement(compiler, name);
diff --git a/tests/compiler/dart2js/cpa_inference_test.dart b/tests/compiler/dart2js/cpa_inference_test.dart
index 5a53ec9..2e69408 100644
--- a/tests/compiler/dart2js/cpa_inference_test.dart
+++ b/tests/compiler/dart2js/cpa_inference_test.dart
@@ -167,11 +167,12 @@
   class Closure {}
   class Null {}
   class Type {}
+  class StackTrace {}
   class Dynamic_ {}
   bool identical(Object a, Object b) {}''';
 
 AnalysisResult analyze(String code, {int maxConcreteTypeSize: 1000}) {
-  Uri uri = new Uri.fromComponents(scheme: 'source');
+  Uri uri = new Uri(scheme: 'source');
   MockCompiler compiler = new MockCompiler(
       coreSource: CORELIB,
       enableConcreteTypeInference: true,
diff --git a/tests/compiler/dart2js/dart_backend_test.dart b/tests/compiler/dart2js/dart_backend_test.dart
index 0b5f109..59fe13f 100644
--- a/tests/compiler/dart2js/dart_backend_test.dart
+++ b/tests/compiler/dart2js/dart_backend_test.dart
@@ -4,7 +4,6 @@
 
 import "package:expect/expect.dart";
 import 'dart:async';
-import 'dart:uri';
 import 'parser_helper.dart';
 import 'mock_compiler.dart';
 import '../../../sdk/lib/_internal/compiler/compiler.dart';
@@ -29,6 +28,7 @@
 class Null {}
 class TypeError {}
 class Type {}
+class StackTrace {}
 class LinkedHashMap {}
 class Math {
   static double parseDouble(String s) => 1.0;
@@ -87,7 +87,7 @@
     String srcMain, String srcLibrary,
     {void continuation(String s), bool minify: false,
     bool stripTypes: false}) {
-  fileUri(path) => new Uri.fromComponents(scheme: 'file', path: path);
+  fileUri(path) => new Uri(scheme: 'file', path: path);
 
   final scriptUri = fileUri('script.dart');
   final libUri = fileUri('mylib.dart');
diff --git a/tests/compiler/dart2js/dead_code_test.dart b/tests/compiler/dart2js/dead_code_test.dart
new file mode 100644
index 0000000..993d7e950
--- /dev/null
+++ b/tests/compiler/dart2js/dead_code_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 'compiler_helper.dart';
+
+String TEST = r'''
+main() {
+  foo(null);
+}
+foo(a) {
+  if (a != null) return 42;
+  return 54;
+}
+''';
+
+main() {
+  String generated = compileAll(TEST);
+  Expect.isFalse(generated.contains('return 42'), 'dead code not eliminated');
+}
diff --git a/tests/compiler/dart2js/deferred_load_graph_segmentation_test.dart b/tests/compiler/dart2js/deferred_load_graph_segmentation_test.dart
index b05ead8..eec688a 100644
--- a/tests/compiler/dart2js/deferred_load_graph_segmentation_test.dart
+++ b/tests/compiler/dart2js/deferred_load_graph_segmentation_test.dart
@@ -27,7 +27,7 @@
                                    libraryRoot,
                                    packageRoot,
                                    ['--analyze-only']);
-  compiler.run(new Uri('memory:main.dart'));
+  compiler.run(Uri.parse('memory:main.dart'));
   var main = compiler.mainApp.find(dart2js.Compiler.MAIN);
   Expect.isNotNull(main, 'Could not find "main"');
   compiler.deferredLoadTask.onResolutionComplete(main);
diff --git a/tests/compiler/dart2js/deprecated_features_test.dart b/tests/compiler/dart2js/deprecated_features_test.dart
index 3ca046e..3d0a12e 100644
--- a/tests/compiler/dart2js/deprecated_features_test.dart
+++ b/tests/compiler/dart2js/deprecated_features_test.dart
@@ -6,7 +6,6 @@
 
 import "package:expect/expect.dart";
 import 'dart:async';
-import 'dart:uri';
 
 import '../../../sdk/lib/_internal/compiler/compiler.dart';
 import '../../utils/dummy_compiler_test.dart' as dummy;
@@ -35,9 +34,9 @@
   }
 
   String code = deprecatedFutureValue(
-      compile(new Uri.fromComponents(scheme: 'main'),
-              new Uri.fromComponents(scheme: 'lib', path: '/'),
-              new Uri.fromComponents(scheme: 'package', path: '/'),
+      compile(new Uri(scheme: 'main'),
+              new Uri(scheme: 'lib', path: '/'),
+              new Uri(scheme: 'package', path: '/'),
               provider, handler));
   if (code == null) {
     throw 'Compilation failed: ${messages}';
diff --git a/tests/compiler/dart2js/field_type_inferer_test.dart b/tests/compiler/dart2js/field_type_inferer_test.dart
index 59db184..ee2b5fb 100644
--- a/tests/compiler/dart2js/field_type_inferer_test.dart
+++ b/tests/compiler/dart2js/field_type_inferer_test.dart
@@ -15,7 +15,7 @@
                     String memberName,
                     bool disableInlining,
                     check(compiler, element)) {
-  Uri uri = new Uri.fromComponents(scheme: 'source');
+  Uri uri = new Uri(scheme: 'source');
   var compiler = compilerFor(code, uri);
   compiler.runCompiler(uri);
   compiler.disableInlining = disableInlining;
diff --git a/tests/compiler/dart2js/field_type_simple_inferer_test.dart b/tests/compiler/dart2js/field_type_simple_inferer_test.dart
index 7422b80..1e25741 100644
--- a/tests/compiler/dart2js/field_type_simple_inferer_test.dart
+++ b/tests/compiler/dart2js/field_type_simple_inferer_test.dart
@@ -14,7 +14,7 @@
                     String memberName,
                     bool disableInlining,
                     check(compiler, element)) {
-  Uri uri = new Uri.fromComponents(scheme: 'source');
+  Uri uri = new Uri(scheme: 'source');
   var compiler = compilerFor(code, uri);
   compiler.runCompiler(uri);
   compiler.disableInlining = disableInlining;
@@ -334,11 +334,13 @@
 const String TEST_20 = r"""
   class A {
     var f;
-    A(x) {
-      for (var i in this) {
+    A() {
+      for (f in this) {
       }
-      f = 42;
     }
+    get iterator => this;
+    get current => 42;
+    bool moveNext() => false;
   }
   main() {
     new A();
@@ -508,7 +510,7 @@
   runTest(TEST_19, {'f1': (inferrer) => inferrer.intType,
                     'f2': (inferrer) => inferrer.stringType,
                     'f3': (inferrer) => inferrer.dynamicType});
-  runTest(TEST_20, {'f': (inferrer) => inferrer.intType});
+  runTest(TEST_20, {'f': (inferrer) => inferrer.intType.nullable()});
   runTest(TEST_21, {'f': (inferrer) => inferrer.intType.nullable()});
 
   runTest(TEST_22, {'f1': (inferrer) => inferrer.intType,
diff --git a/tests/compiler/dart2js/gvn_dynamic_field_get_test.dart b/tests/compiler/dart2js/gvn_dynamic_field_get_test.dart
index 739645b..c1a784a 100644
--- a/tests/compiler/dart2js/gvn_dynamic_field_get_test.dart
+++ b/tests/compiler/dart2js/gvn_dynamic_field_get_test.dart
@@ -22,7 +22,7 @@
 """;
 
 main() {
-  Uri uri = new Uri.fromComponents(scheme: 'source');
+  Uri uri = new Uri(scheme: 'source');
   var compiler = compilerFor(TEST, uri);
   compiler.runCompiler(uri);
   String generated = compiler.assembledCode;
diff --git a/tests/compiler/dart2js/memory_source_file_helper.dart b/tests/compiler/dart2js/memory_source_file_helper.dart
index db1c4f0..10f3102 100644
--- a/tests/compiler/dart2js/memory_source_file_helper.dart
+++ b/tests/compiler/dart2js/memory_source_file_helper.dart
@@ -5,8 +5,6 @@
 library dart2js.test.memory_source_file_helper;
 
 import 'dart:async' show Future;
-import 'dart:uri' show Uri;
-export 'dart:uri' show Uri;
 import 'dart:io';
 export 'dart:io' show Options;
 
diff --git a/tests/compiler/dart2js/metadata_test.dart b/tests/compiler/dart2js/metadata_test.dart
index c40d9a7..0e3b20b 100644
--- a/tests/compiler/dart2js/metadata_test.dart
+++ b/tests/compiler/dart2js/metadata_test.dart
@@ -143,15 +143,15 @@
   void compileAndCheckLibrary(
       String source,
       Link<MetadataAnnotation> extractMetadata(LibraryElement element)) {
-    Uri partUri = new Uri.fromComponents(scheme: 'source', path: 'part.dart');
+    Uri partUri = new Uri(scheme: 'source', path: 'part.dart');
     String partSource = '@native part of foo;';
 
-    Uri libUri = new Uri.fromComponents(scheme: 'source', path: 'lib.dart');
+    Uri libUri = new Uri(scheme: 'source', path: 'lib.dart');
     String libSource = 'library lib;';
 
-    Uri uri = new Uri.fromComponents(scheme: 'source', path: 'main.dart');
+    Uri uri = new Uri(scheme: 'source', path: 'main.dart');
 
-    Uri async = new Uri.fromComponents(scheme: 'dart', path: 'async');
+    Uri async = new Uri(scheme: 'dart', path: 'async');
 
     var compiler = compilerFor(source, uri)
         ..registerSource(partUri, partSource)
diff --git a/tests/compiler/dart2js/mirrors_metadata_test.dart b/tests/compiler/dart2js/mirrors_metadata_test.dart
index c52c744..22b0c81 100644
--- a/tests/compiler/dart2js/mirrors_metadata_test.dart
+++ b/tests/compiler/dart2js/mirrors_metadata_test.dart
@@ -5,7 +5,6 @@
 import 'package:expect/expect.dart';
 import 'dart:async';
 import 'dart:io';
-import 'dart:uri';
 import '../../../sdk/lib/_internal/compiler/implementation/filenames.dart';
 import '../../../sdk/lib/_internal/compiler/implementation/mirrors/mirrors.dart';
 import '../../../sdk/lib/_internal/compiler/implementation/mirrors/dart2js_mirror.dart';
@@ -13,7 +12,7 @@
 import 'mock_compiler.dart';
 
 const String SOURCE = 'source';
-const Uri SOURCE_URI = const Uri.fromComponents(scheme: SOURCE, path: SOURCE);
+Uri SOURCE_URI = new Uri(scheme: SOURCE, path: SOURCE);
 
 MirrorSystem createMirrorSystem(String source) {
   MockCompiler compiler = new MockCompiler(
diff --git a/tests/compiler/dart2js/mirrors_test.dart b/tests/compiler/dart2js/mirrors_test.dart
index 38ceef2..6fc2094 100644
--- a/tests/compiler/dart2js/mirrors_test.dart
+++ b/tests/compiler/dart2js/mirrors_test.dart
@@ -11,10 +11,8 @@
 import '../../../sdk/lib/_internal/compiler/implementation/source_file_provider.dart';
 
 import 'dart:io';
-import 'dart:uri';
 
-const Uri DART_MIRRORS_URI =
-  const Uri.fromComponents(scheme: 'dart', path: 'mirrors');
+final Uri DART_MIRRORS_URI = new Uri(scheme: 'dart', path: 'mirrors');
 
 int count(Iterable iterable) {
   var count = 0;
diff --git a/tests/compiler/dart2js/mock_compiler.dart b/tests/compiler/dart2js/mock_compiler.dart
index 63e8492..d0c1089 100644
--- a/tests/compiler/dart2js/mock_compiler.dart
+++ b/tests/compiler/dart2js/mock_compiler.dart
@@ -6,7 +6,6 @@
 
 import "package:expect/expect.dart";
 import 'dart:collection';
-import 'dart:uri';
 
 import '../../../sdk/lib/_internal/compiler/compiler.dart' as api;
 import '../../../sdk/lib/_internal/compiler/implementation/elements/elements.dart';
@@ -160,6 +159,7 @@
     String toString() { return null; }
     noSuchMethod(im) { throw im; }
   }
+  abstract class StackTrace {}
   class Type {}
   class Function {}
   class List<E> {}
@@ -246,7 +246,7 @@
    * is fixed to export its top-level declarations.
    */
   LibraryElement createLibrary(String name, String source) {
-    Uri uri = new Uri.fromComponents(scheme: "dart", path: name);
+    Uri uri = new Uri(scheme: "dart", path: name);
     var script = new Script(uri, new MockFile(source));
     var library = new LibraryElementX(script);
     parseScript(source, library);
@@ -401,7 +401,7 @@
 }
 
 LibraryElement mockLibrary(Compiler compiler, String source) {
-  Uri uri = new Uri.fromComponents(scheme: "source");
+  Uri uri = new Uri(scheme: "source");
   var library = new LibraryElementX(new Script(uri, new MockFile(source)));
   importLibrary(library, compiler.coreLibrary, compiler);
   return library;
diff --git a/tests/compiler/dart2js/parser_helper.dart b/tests/compiler/dart2js/parser_helper.dart
index 3ba38e9..4b4c762 100644
--- a/tests/compiler/dart2js/parser_helper.dart
+++ b/tests/compiler/dart2js/parser_helper.dart
@@ -5,7 +5,6 @@
 library parser_helper;
 
 import "package:expect/expect.dart";
-import "dart:uri";
 
 import "../../../sdk/lib/_internal/compiler/implementation/elements/elements.dart";
 import "../../../sdk/lib/_internal/compiler/implementation/tree/tree.dart";
@@ -43,7 +42,7 @@
   if (diagnosticHandler == null) diagnosticHandler = new LoggerCanceler();
   Script script =
       new Script(
-          new Uri.fromComponents(scheme: "source"),
+          new Uri(scheme: "source"),
           new MockFile(text));
   LibraryElement library = new LibraryElementX(script);
   library.canUseNative = true;
@@ -84,8 +83,7 @@
                         LibraryElement library,
                         [void registerSource(Uri uri, String source)]) {
   Token tokens = scan(text);
-  Uri uri =
-      new Uri.fromComponents(scheme: "source", path: '${++sourceCounter}');
+  Uri uri = new Uri(scheme: "source", path: '${++sourceCounter}');
   if (registerSource != null) {
     registerSource(uri, text);
   }
diff --git a/tests/compiler/dart2js/part_of_test.dart b/tests/compiler/dart2js/part_of_test.dart
index aec3c73..629c267 100644
--- a/tests/compiler/dart2js/part_of_test.dart
+++ b/tests/compiler/dart2js/part_of_test.dart
@@ -5,18 +5,17 @@
 library part_of_test;
 
 import "package:expect/expect.dart";
-import 'dart:uri';
 import 'mock_compiler.dart';
 import '../../../sdk/lib/_internal/compiler/implementation/dart2jslib.dart'
     show MessageKind;
 
-final libraryUri = new Uri('test:library.dart');
+final libraryUri = Uri.parse('test:library.dart');
 const String LIBRARY_SOURCE = '''
 library foo;
 part 'part.dart';
 ''';
 
-final partUri = new Uri('test:part.dart');
+final partUri = Uri.parse('test:part.dart');
 const String PART_SOURCE = '''
 part of bar;
 ''';
diff --git a/tests/compiler/dart2js/patch_test.dart b/tests/compiler/dart2js/patch_test.dart
index 1d33715..3cf4b46 100644
--- a/tests/compiler/dart2js/patch_test.dart
+++ b/tests/compiler/dart2js/patch_test.dart
@@ -9,12 +9,11 @@
 import "../../../sdk/lib/_internal/compiler/implementation/util/util.dart";
 import "mock_compiler.dart";
 import "parser_helper.dart";
-import "dart:uri";
 
 Compiler applyPatch(String script, String patch) {
   String core = "$DEFAULT_CORELIB\n$script";
   MockCompiler compiler = new MockCompiler(coreSource: core);
-  var uri = new Uri("core.dartp");
+  var uri = Uri.parse("core.dartp");
   compiler.sourceFiles[uri.toString()] = new MockFile(patch);
   var handler = new LibraryDependencyHandler(compiler);
   compiler.patchParser.patchLibrary(handler, uri, compiler.coreLibrary);
diff --git a/tests/compiler/dart2js/reexport_handled_test.dart b/tests/compiler/dart2js/reexport_handled_test.dart
index 8a1ca82..d309fcd 100644
--- a/tests/compiler/dart2js/reexport_handled_test.dart
+++ b/tests/compiler/dart2js/reexport_handled_test.dart
@@ -5,19 +5,18 @@
 library reexport_handled_test;
 
 import "package:expect/expect.dart";
-import 'dart:uri';
 import 'mock_compiler.dart';
 import '../../../sdk/lib/_internal/compiler/implementation/elements/elements.dart'
     show Element,
          LibraryElement;
 
-final exportingLibraryUri = new Uri('exporting.dart');
+final exportingLibraryUri = Uri.parse('exporting.dart');
 const String EXPORTING_LIBRARY_SOURCE = '''
 library exporting;
 var foo;
 ''';
 
-final reexportingLibraryUri = new Uri('reexporting.dart');
+final reexportingLibraryUri = Uri.parse('reexporting.dart');
 const String REEXPORTING_LIBRARY_SOURCE = '''
 library reexporting;
 export 'exporting.dart';
@@ -51,4 +50,4 @@
     }
   }
   return null;
-}
\ No newline at end of file
+}
diff --git a/tests/compiler/dart2js/resolution_test.dart b/tests/compiler/dart2js/resolution_test.dart
index c1a327f..32f5945 100644
--- a/tests/compiler/dart2js/resolution_test.dart
+++ b/tests/compiler/dart2js/resolution_test.dart
@@ -92,7 +92,7 @@
 """;
 
 void test(String code, void check(Compiler compiler)) {
-  Uri uri = new Uri.fromComponents(scheme: 'source');
+  Uri uri = new Uri(scheme: 'source');
   var compiler = compilerFor(code, uri);
   compiler.runCompiler(uri);
   check(compiler);
diff --git a/tests/compiler/dart2js/resolver_test.dart b/tests/compiler/dart2js/resolver_test.dart
index a1d6ad3..dcdcc07 100644
--- a/tests/compiler/dart2js/resolver_test.dart
+++ b/tests/compiler/dart2js/resolver_test.dart
@@ -759,6 +759,7 @@
          class Map {}
          class Closure {}
          class Null {}
+         class StackTrace {}
          class Dynamic_ {}
          class Type {}
          class Object { Object() : super(); }''';
@@ -783,7 +784,7 @@
 }
 
 compileScript(String source) {
-  Uri uri = new Uri.fromComponents(scheme: 'source');
+  Uri uri = new Uri(scheme: 'source');
   MockCompiler compiler = compilerFor(source, uri);
   compiler.runCompiler(uri);
   return compiler;
diff --git a/tests/compiler/dart2js/simple_inferrer_and_or_test.dart b/tests/compiler/dart2js/simple_inferrer_and_or_test.dart
index 40c01a5..eccf849 100644
--- a/tests/compiler/dart2js/simple_inferrer_and_or_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_and_or_test.dart
@@ -55,7 +55,7 @@
 
 
 void main() {
-  Uri uri = new Uri.fromComponents(scheme: 'source');
+  Uri uri = new Uri(scheme: 'source');
   var compiler = compilerFor(TEST, uri);
   compiler.runCompiler(uri);
   var typesInferrer = compiler.typesTask.typesInferrer;
diff --git a/tests/compiler/dart2js/simple_inferrer_closure_test.dart b/tests/compiler/dart2js/simple_inferrer_closure_test.dart
index f731839..23d6db0 100644
--- a/tests/compiler/dart2js/simple_inferrer_closure_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_closure_test.dart
@@ -80,7 +80,7 @@
 
 
 void main() {
-  Uri uri = new Uri.fromComponents(scheme: 'source');
+  Uri uri = new Uri(scheme: 'source');
   var compiler = compilerFor(TEST, uri);
   compiler.runCompiler(uri);
   var typesInferrer = compiler.typesTask.typesInferrer;
diff --git a/tests/compiler/dart2js/simple_inferrer_final_field2_test.dart b/tests/compiler/dart2js/simple_inferrer_final_field2_test.dart
index a374e9c..e03c4f3 100644
--- a/tests/compiler/dart2js/simple_inferrer_final_field2_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_final_field2_test.dart
@@ -24,7 +24,7 @@
 """;
 
 void main() {
-  Uri uri = new Uri.fromComponents(scheme: 'source');
+  Uri uri = new Uri(scheme: 'source');
   var compiler = compilerFor(TEST, uri);
   compiler.runCompiler(uri);
   var typesInferrer = compiler.typesTask.typesInferrer;
diff --git a/tests/compiler/dart2js/simple_inferrer_final_field3_test.dart b/tests/compiler/dart2js/simple_inferrer_final_field3_test.dart
index b43693e..058187b 100644
--- a/tests/compiler/dart2js/simple_inferrer_final_field3_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_final_field3_test.dart
@@ -23,7 +23,7 @@
 """;
 
 void main() {
-  Uri uri = new Uri.fromComponents(scheme: 'source');
+  Uri uri = new Uri(scheme: 'source');
   var compiler = compilerFor(TEST, uri);
   compiler.runCompiler(uri);
   var typesInferrer = compiler.typesTask.typesInferrer;
diff --git a/tests/compiler/dart2js/simple_inferrer_final_field_test.dart b/tests/compiler/dart2js/simple_inferrer_final_field_test.dart
index 2e3cc4c..3108608 100644
--- a/tests/compiler/dart2js/simple_inferrer_final_field_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_final_field_test.dart
@@ -26,7 +26,7 @@
 """;
 
 void main() {
-  Uri uri = new Uri.fromComponents(scheme: 'source');
+  Uri uri = new Uri(scheme: 'source');
   var compiler = compilerFor(TEST, uri);
   compiler.runCompiler(uri);
   var typesInferrer = compiler.typesTask.typesInferrer;
diff --git a/tests/compiler/dart2js/simple_inferrer_no_such_method_test.dart b/tests/compiler/dart2js/simple_inferrer_no_such_method_test.dart
index 91fb20d..400c0f8 100644
--- a/tests/compiler/dart2js/simple_inferrer_no_such_method_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_no_such_method_test.dart
@@ -93,7 +93,7 @@
 """;
 
 main() {
-  Uri uri = new Uri.fromComponents(scheme: 'source');
+  Uri uri = new Uri(scheme: 'source');
 
   var compiler = compilerFor(TEST1, uri);
   compiler.runCompiler(uri);
diff --git a/tests/compiler/dart2js/simple_inferrer_postfix_prefix_test.dart b/tests/compiler/dart2js/simple_inferrer_postfix_prefix_test.dart
index 3c9aaa1..cfae3a7 100644
--- a/tests/compiler/dart2js/simple_inferrer_postfix_prefix_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_postfix_prefix_test.dart
@@ -61,7 +61,7 @@
 """;
 
 void main() {
-  Uri uri = new Uri.fromComponents(scheme: 'source');
+  Uri uri = new Uri(scheme: 'source');
   var compiler = compilerFor(TEST, uri);
   compiler.runCompiler(uri);
   var typesInferrer = compiler.typesTask.typesInferrer;
diff --git a/tests/compiler/dart2js/simple_inferrer_test.dart b/tests/compiler/dart2js/simple_inferrer_test.dart
index 2c8f602..c9776bb 100644
--- a/tests/compiler/dart2js/simple_inferrer_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_test.dart
@@ -457,7 +457,7 @@
 """;
 
 void main() {
-  Uri uri = new Uri.fromComponents(scheme: 'source');
+  Uri uri = new Uri(scheme: 'source');
   var compiler = compilerFor(TEST, uri);
   compiler.runCompiler(uri);
   var typesInferrer = compiler.typesTask.typesInferrer;
diff --git a/tests/compiler/dart2js/simple_inferrer_try_catch_test.dart b/tests/compiler/dart2js/simple_inferrer_try_catch_test.dart
index 2b6ebef..917ffe9 100644
--- a/tests/compiler/dart2js/simple_inferrer_try_catch_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_try_catch_test.dart
@@ -154,7 +154,7 @@
 
 
 void main() {
-  Uri uri = new Uri.fromComponents(scheme: 'source');
+  Uri uri = new Uri(scheme: 'source');
   var compiler = compilerFor(TEST, uri);
   compiler.runCompiler(uri);
   var typesInferrer = compiler.typesTask.typesInferrer;
diff --git a/tests/compiler/dart2js/simple_inferrer_unregister_call_test.dart b/tests/compiler/dart2js/simple_inferrer_unregister_call_test.dart
index b277c2b..0341df4 100644
--- a/tests/compiler/dart2js/simple_inferrer_unregister_call_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_unregister_call_test.dart
@@ -30,7 +30,7 @@
 
 
 void main() {
-  Uri uri = new Uri.fromComponents(scheme: 'source');
+  Uri uri = new Uri(scheme: 'source');
   var compiler = compilerFor(TEST, uri);
   compiler.runCompiler(uri);
   var typesInferrer = compiler.typesTask.typesInferrer;
diff --git a/tests/compiler/dart2js/size_test.dart b/tests/compiler/dart2js/size_test.dart
index cfc318c..3d6fd7b 100644
--- a/tests/compiler/dart2js/size_test.dart
+++ b/tests/compiler/dart2js/size_test.dart
@@ -18,6 +18,7 @@
   class Function {}
   class Type {}
   class Map {}
+  class StackTrace {}
   identical(a, b) => true;
 ''';
 
diff --git a/tests/compiler/dart2js/source_mapping_test.dart b/tests/compiler/dart2js/source_mapping_test.dart
index 6b47737..3cccbbd 100644
--- a/tests/compiler/dart2js/source_mapping_test.dart
+++ b/tests/compiler/dart2js/source_mapping_test.dart
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import "package:expect/expect.dart";
-import 'dart:uri';
 
 import "../../../sdk/lib/_internal/compiler/implementation/dart2jslib.dart";
 import '../../../sdk/lib/_internal/compiler/implementation/source_file.dart';
@@ -12,7 +11,7 @@
 
 CodeBuffer compileAll(SourceFile sourceFile) {
   MockCompiler compiler = new MockCompiler();
-  Uri uri = new Uri.fromComponents(path: sourceFile.filename);
+  Uri uri = new Uri(path: sourceFile.filename);
   compiler.sourceFiles[uri.toString()] = sourceFile;
   compiler.runCompiler(uri);
   return compiler.backend.emitter.mainBuffer;
diff --git a/tests/compiler/dart2js/type_checker_test.dart b/tests/compiler/dart2js/type_checker_test.dart
index 6b813b0..1a6bc16 100644
--- a/tests/compiler/dart2js/type_checker_test.dart
+++ b/tests/compiler/dart2js/type_checker_test.dart
@@ -31,6 +31,7 @@
                 testReturn,
                 testFor,
                 testWhile,
+                testTry,
                 testOperators,
                 testConstructorInvocationArgumentCount,
                 testConstructorInvocationArgumentTypes,
@@ -107,6 +108,21 @@
   analyze("do { int i = 0.5; } while (null);", MessageKind.NOT_ASSIGNABLE);
 }
 
+testTry() {
+  analyze("try {} finally {}");
+  analyze("try {} catch (e) { int i = e;} finally {}");
+  analyze("try {} catch (e, s) { int i = e; StackTrace j = s; } finally {}");
+  analyze("try {} on String catch (e) {} finally {}");
+  analyze("try { int i = ''; } finally {}", MessageKind.NOT_ASSIGNABLE);
+  analyze("try {} finally { int i = ''; }", MessageKind.NOT_ASSIGNABLE);
+  analyze("try {} on String catch (e) { int i = e; } finally {}",
+      MessageKind.NOT_ASSIGNABLE);
+  analyze("try {} catch (e, s) { int i = e; int j = s; } finally {}",
+      MessageKind.NOT_ASSIGNABLE);
+  analyze("try {} on String catch (e, s) { int i = e; int j = s; } finally {}",
+      [MessageKind.NOT_ASSIGNABLE, MessageKind.NOT_ASSIGNABLE]);
+}
+
 testOperators() {
   // TODO(karlklose): add the DartC tests for operators when we can parse
   // classes with operators.
@@ -186,209 +202,224 @@
 
 void testMethodInvocationArgumentCount() {
   compiler.parseScript(CLASS_WITH_METHODS);
-  final String header = "{ ClassWithMethods c; ";
-  analyze("${header}c.untypedNoArgumentMethod(1); }",
-          MessageKind.ADDITIONAL_ARGUMENT);
-  analyze("${header}c.untypedOneArgumentMethod(); }",
-          MessageKind.MISSING_ARGUMENT);
-  analyze("${header}c.untypedOneArgumentMethod(1, 1); }",
-          MessageKind.ADDITIONAL_ARGUMENT);
-  analyze("${header}c.untypedTwoArgumentMethod(); }",
-          MessageKind.MISSING_ARGUMENT);
-  analyze("${header}c.untypedTwoArgumentMethod(1, 2, 3); }",
-          MessageKind.ADDITIONAL_ARGUMENT);
-  analyze("${header}c.intNoArgumentMethod(1); }",
-          MessageKind.ADDITIONAL_ARGUMENT);
-  analyze("${header}c.intOneArgumentMethod(); }",
-          MessageKind.MISSING_ARGUMENT);
-  analyze("${header}c.intOneArgumentMethod(1, 1); }",
-          MessageKind.ADDITIONAL_ARGUMENT);
-  analyze("${header}c.intTwoArgumentMethod(); }",
-          MessageKind.MISSING_ARGUMENT);
-  analyze("${header}c.intTwoArgumentMethod(1, 2, 3); }",
-          MessageKind.ADDITIONAL_ARGUMENT);
-  // analyze("${header}c.untypedField(); }");
 
-  analyze("${header}c.intOneArgumentOneOptionalMethod(); }",
-          [MessageKind.MISSING_ARGUMENT]);
-  analyze("${header}c.intOneArgumentOneOptionalMethod(0); }");
-  analyze("${header}c.intOneArgumentOneOptionalMethod(0, 1); }");
-  analyze("${header}c.intOneArgumentOneOptionalMethod(0, 1, 2); }",
-          [MessageKind.ADDITIONAL_ARGUMENT]);
-  analyze("${header}c.intOneArgumentOneOptionalMethod(0, 1, c: 2); }",
-          [MessageKind.NAMED_ARGUMENT_NOT_FOUND]);
-  analyze("${header}c.intOneArgumentOneOptionalMethod(0, b: 1); }",
-          [MessageKind.NAMED_ARGUMENT_NOT_FOUND]);
-  analyze("${header}c.intOneArgumentOneOptionalMethod(a: 0, b: 1); }",
-          [MessageKind.NAMED_ARGUMENT_NOT_FOUND,
-           MessageKind.NAMED_ARGUMENT_NOT_FOUND,
-           MessageKind.MISSING_ARGUMENT]);
+  check(String text, [expectedWarnings]) {
+    analyze("{ ClassWithMethods c; $text }", expectedWarnings);
+  }
 
-  analyze("${header}c.intTwoOptionalMethod(); }");
-  analyze("${header}c.intTwoOptionalMethod(0); }");
-  analyze("${header}c.intTwoOptionalMethod(0, 1); }");
-  analyze("${header}c.intTwoOptionalMethod(0, 1, 2); }",
-          [MessageKind.ADDITIONAL_ARGUMENT]);
-  analyze("${header}c.intTwoOptionalMethod(a: 0); }",
-          [MessageKind.NAMED_ARGUMENT_NOT_FOUND]);
-  analyze("${header}c.intTwoOptionalMethod(0, b: 1); }",
-          [MessageKind.NAMED_ARGUMENT_NOT_FOUND]);
+  check("c.untypedNoArgumentMethod(1);", MessageKind.ADDITIONAL_ARGUMENT);
+  check("c.untypedOneArgumentMethod();", MessageKind.MISSING_ARGUMENT);
+  check("c.untypedOneArgumentMethod(1, 1);", MessageKind.ADDITIONAL_ARGUMENT);
+  check("c.untypedTwoArgumentMethod();", MessageKind.MISSING_ARGUMENT);
+  check("c.untypedTwoArgumentMethod(1, 2, 3);",
+        MessageKind.ADDITIONAL_ARGUMENT);
+  check("c.intNoArgumentMethod(1);", MessageKind.ADDITIONAL_ARGUMENT);
+  check("c.intOneArgumentMethod();", MessageKind.MISSING_ARGUMENT);
+  check("c.intOneArgumentMethod(1, 1);", MessageKind.ADDITIONAL_ARGUMENT);
+  check("c.intTwoArgumentMethod();", MessageKind.MISSING_ARGUMENT);
+  check("c.intTwoArgumentMethod(1, 2, 3);", MessageKind.ADDITIONAL_ARGUMENT);
+  // check("c.untypedField();");
 
-  analyze("${header}c.intOneArgumentOneNamedMethod(); }",
-          [MessageKind.MISSING_ARGUMENT]);
-  analyze("${header}c.intOneArgumentOneNamedMethod(0); }");
-  analyze("${header}c.intOneArgumentOneNamedMethod(0, b: 1); }");
-  analyze("${header}c.intOneArgumentOneNamedMethod(b: 1); }",
-          [MessageKind.MISSING_ARGUMENT]);
-  analyze("${header}c.intOneArgumentOneNamedMethod(0, b: 1, c: 2); }",
-          [MessageKind.NAMED_ARGUMENT_NOT_FOUND]);
-  analyze("${header}c.intOneArgumentOneNamedMethod(0, 1); }",
-          [MessageKind.ADDITIONAL_ARGUMENT]);
-  analyze("${header}c.intOneArgumentOneNamedMethod(0, 1, c: 2); }",
-          [MessageKind.ADDITIONAL_ARGUMENT,
-           MessageKind.NAMED_ARGUMENT_NOT_FOUND]);
-  analyze("${header}c.intOneArgumentOneNamedMethod(a: 1, b: 1); }",
-          [MessageKind.NAMED_ARGUMENT_NOT_FOUND,
-           MessageKind.MISSING_ARGUMENT]);
+  check("c.intOneArgumentOneOptionalMethod();", [MessageKind.MISSING_ARGUMENT]);
+  check("c.intOneArgumentOneOptionalMethod(0);");
+  check("c.intOneArgumentOneOptionalMethod(0, 1);");
+  check("c.intOneArgumentOneOptionalMethod(0, 1, 2);",
+        [MessageKind.ADDITIONAL_ARGUMENT]);
+  check("c.intOneArgumentOneOptionalMethod(0, 1, c: 2);",
+        [MessageKind.NAMED_ARGUMENT_NOT_FOUND]);
+  check("c.intOneArgumentOneOptionalMethod(0, b: 1);",
+        [MessageKind.NAMED_ARGUMENT_NOT_FOUND]);
+  check("c.intOneArgumentOneOptionalMethod(a: 0, b: 1);",
+        [MessageKind.NAMED_ARGUMENT_NOT_FOUND,
+         MessageKind.NAMED_ARGUMENT_NOT_FOUND,
+         MessageKind.MISSING_ARGUMENT]);
 
-  analyze("${header}c.intTwoNamedMethod(); }");
-  analyze("${header}c.intTwoNamedMethod(a: 0); }");
-  analyze("${header}c.intTwoNamedMethod(b: 1); }");
-  analyze("${header}c.intTwoNamedMethod(a: 0, b: 1); }");
-  analyze("${header}c.intTwoNamedMethod(b: 1, a: 0); }");
-  analyze("${header}c.intTwoNamedMethod(0); }",
-          [MessageKind.ADDITIONAL_ARGUMENT]);
-  analyze("${header}c.intTwoNamedMethod(c: 2); }",
-          [MessageKind.NAMED_ARGUMENT_NOT_FOUND]);
-  analyze("${header}c.intTwoNamedMethod(a: 0, c: 2); }",
-          [MessageKind.NAMED_ARGUMENT_NOT_FOUND]);
-  analyze("${header}c.intTwoNamedMethod(a: 0, b: 1, c: 2); }",
-          [MessageKind.NAMED_ARGUMENT_NOT_FOUND]);
-  analyze("${header}c.intTwoNamedMethod(c: 2, b: 1, a: 0); }",
-          [MessageKind.NAMED_ARGUMENT_NOT_FOUND]);
-  analyze("${header}c.intTwoNamedMethod(0, b: 1); }",
-          [MessageKind.ADDITIONAL_ARGUMENT]);
-  analyze("${header}c.intTwoNamedMethod(0, 1); }",
-          [MessageKind.ADDITIONAL_ARGUMENT,
-           MessageKind.ADDITIONAL_ARGUMENT]);
-  analyze("${header}c.intTwoNamedMethod(0, c: 2); }",
-          [MessageKind.ADDITIONAL_ARGUMENT,
-           MessageKind.NAMED_ARGUMENT_NOT_FOUND]);
+  check("c.intTwoOptionalMethod();");
+  check("c.intTwoOptionalMethod(0);");
+  check("c.intTwoOptionalMethod(0, 1);");
+  check("c.intTwoOptionalMethod(0, 1, 2);", [MessageKind.ADDITIONAL_ARGUMENT]);
+  check("c.intTwoOptionalMethod(a: 0);",
+        [MessageKind.NAMED_ARGUMENT_NOT_FOUND]);
+  check("c.intTwoOptionalMethod(0, b: 1);",
+        [MessageKind.NAMED_ARGUMENT_NOT_FOUND]);
 
+  check("c.intOneArgumentOneNamedMethod();", [MessageKind.MISSING_ARGUMENT]);
+  check("c.intOneArgumentOneNamedMethod(0);");
+  check("c.intOneArgumentOneNamedMethod(0, b: 1);");
+  check("c.intOneArgumentOneNamedMethod(b: 1);",
+        [MessageKind.MISSING_ARGUMENT]);
+  check("c.intOneArgumentOneNamedMethod(0, b: 1, c: 2);",
+        [MessageKind.NAMED_ARGUMENT_NOT_FOUND]);
+  check("c.intOneArgumentOneNamedMethod(0, 1);",
+        [MessageKind.ADDITIONAL_ARGUMENT]);
+  check("c.intOneArgumentOneNamedMethod(0, 1, c: 2);",
+        [MessageKind.ADDITIONAL_ARGUMENT,
+         MessageKind.NAMED_ARGUMENT_NOT_FOUND]);
+  check("c.intOneArgumentOneNamedMethod(a: 1, b: 1);",
+        [MessageKind.NAMED_ARGUMENT_NOT_FOUND,
+         MessageKind.MISSING_ARGUMENT]);
+
+  check("c.intTwoNamedMethod();");
+  check("c.intTwoNamedMethod(a: 0);");
+  check("c.intTwoNamedMethod(b: 1);");
+  check("c.intTwoNamedMethod(a: 0, b: 1);");
+  check("c.intTwoNamedMethod(b: 1, a: 0);");
+  check("c.intTwoNamedMethod(0);", [MessageKind.ADDITIONAL_ARGUMENT]);
+  check("c.intTwoNamedMethod(c: 2);", [MessageKind.NAMED_ARGUMENT_NOT_FOUND]);
+  check("c.intTwoNamedMethod(a: 0, c: 2);",
+        [MessageKind.NAMED_ARGUMENT_NOT_FOUND]);
+  check("c.intTwoNamedMethod(a: 0, b: 1, c: 2);",
+        [MessageKind.NAMED_ARGUMENT_NOT_FOUND]);
+  check("c.intTwoNamedMethod(c: 2, b: 1, a: 0);",
+        [MessageKind.NAMED_ARGUMENT_NOT_FOUND]);
+  check("c.intTwoNamedMethod(0, b: 1);", [MessageKind.ADDITIONAL_ARGUMENT]);
+  check("c.intTwoNamedMethod(0, 1);",
+        [MessageKind.ADDITIONAL_ARGUMENT,
+         MessageKind.ADDITIONAL_ARGUMENT]);
+  check("c.intTwoNamedMethod(0, c: 2);",
+        [MessageKind.ADDITIONAL_ARGUMENT,
+         MessageKind.NAMED_ARGUMENT_NOT_FOUND]);
 }
 
 void testMethodInvocations() {
   compiler.parseScript(CLASS_WITH_METHODS);
-  final String header = """{
-      ClassWithMethods c;
-      SubClass d;
-      var e;
-      int i;
-      int j;
-      int localMethod(String str) { return 0; }
-      """;
 
-  analyze("${header}int k = c.untypedNoArgumentMethod(); }");
-  analyze("${header}ClassWithMethods x = c.untypedNoArgumentMethod(); }");
-  analyze("${header}ClassWithMethods x = d.untypedNoArgumentMethod(); }");
-  analyze("${header}int k = d.intMethod(); }");
-  analyze("${header}int k = c.untypedOneArgumentMethod(c); }");
-  analyze("${header}ClassWithMethods x = c.untypedOneArgumentMethod(1); }");
-  analyze("${header}int k = c.untypedOneArgumentMethod('string'); }");
-  analyze("${header}int k = c.untypedOneArgumentMethod(i); }");
-  analyze("${header}int k = d.untypedOneArgumentMethod(d); }");
-  analyze("${header}ClassWithMethods x = d.untypedOneArgumentMethod(1); }");
-  analyze("${header}int k = d.untypedOneArgumentMethod('string'); }");
-  analyze("${header}int k = d.untypedOneArgumentMethod(i); }");
+  check(String text, [expectedWarnings]){
+    analyze("""{
+               ClassWithMethods c;
+               SubClass d;
+               var e;
+               int i;
+               int j;
+               int localMethod(String str) { return 0; }
+               $text
+               }
+               """, expectedWarnings);
+  }
 
-  analyze("${header}int k = c.untypedTwoArgumentMethod(1, 'string'); }");
-  analyze("${header}int k = c.untypedTwoArgumentMethod(i, j); }");
-  analyze("${header}ClassWithMethods x = c.untypedTwoArgumentMethod(i, c); }");
-  analyze("${header}int k = d.untypedTwoArgumentMethod(1, 'string'); }");
-  analyze("${header}int k = d.untypedTwoArgumentMethod(i, j); }");
-  analyze("${header}ClassWithMethods x = d.untypedTwoArgumentMethod(i, d); }");
+  check("int k = c.untypedNoArgumentMethod();");
+  check("ClassWithMethods x = c.untypedNoArgumentMethod();");
+  check("ClassWithMethods x = d.untypedNoArgumentMethod();");
+  check("int k = d.intMethod();");
+  check("int k = c.untypedOneArgumentMethod(c);");
+  check("ClassWithMethods x = c.untypedOneArgumentMethod(1);");
+  check("int k = c.untypedOneArgumentMethod('string');");
+  check("int k = c.untypedOneArgumentMethod(i);");
+  check("int k = d.untypedOneArgumentMethod(d);");
+  check("ClassWithMethods x = d.untypedOneArgumentMethod(1);");
+  check("int k = d.untypedOneArgumentMethod('string');");
+  check("int k = d.untypedOneArgumentMethod(i);");
 
-  analyze("${header}int k = c.intNoArgumentMethod(); }");
-  analyze("${header}ClassWithMethods x = c.intNoArgumentMethod(); }",
-          MessageKind.NOT_ASSIGNABLE);
+  check("int k = c.untypedTwoArgumentMethod(1, 'string');");
+  check("int k = c.untypedTwoArgumentMethod(i, j);");
+  check("ClassWithMethods x = c.untypedTwoArgumentMethod(i, c);");
+  check("int k = d.untypedTwoArgumentMethod(1, 'string');");
+  check("int k = d.untypedTwoArgumentMethod(i, j);");
+  check("ClassWithMethods x = d.untypedTwoArgumentMethod(i, d);");
 
-  analyze("${header}int k = c.intOneArgumentMethod(c); }",
-          MessageKind.NOT_ASSIGNABLE);
-  analyze("${header}ClassWithMethods x = c.intOneArgumentMethod(1); }",
-          MessageKind.NOT_ASSIGNABLE);
-  analyze("${header}int k = c.intOneArgumentMethod('string'); }",
-          MessageKind.NOT_ASSIGNABLE);
-  analyze("${header}int k = c.intOneArgumentMethod(i); }");
+  check("int k = c.intNoArgumentMethod();");
+  check("ClassWithMethods x = c.intNoArgumentMethod();",
+        MessageKind.NOT_ASSIGNABLE);
 
-  analyze("${header}int k = c.intTwoArgumentMethod(1, 'string'); }",
-          MessageKind.NOT_ASSIGNABLE);
-  analyze("${header}int k = c.intTwoArgumentMethod(i, j); }");
-  analyze("${header}ClassWithMethods x = c.intTwoArgumentMethod(i, j); }",
-          MessageKind.NOT_ASSIGNABLE);
+  check("int k = c.intOneArgumentMethod(c);", MessageKind.NOT_ASSIGNABLE);
+  check("ClassWithMethods x = c.intOneArgumentMethod(1);",
+        MessageKind.NOT_ASSIGNABLE);
+  check("int k = c.intOneArgumentMethod('string');",
+        MessageKind.NOT_ASSIGNABLE);
+  check("int k = c.intOneArgumentMethod(i);");
 
-  analyze("${header}c.functionField(); }");
-  analyze("${header}d.functionField(); }");
-  analyze("${header}c.functionField(1); }");
-  analyze("${header}d.functionField('string'); }");
+  check("int k = c.intTwoArgumentMethod(1, 'string');",
+        MessageKind.NOT_ASSIGNABLE);
+  check("int k = c.intTwoArgumentMethod(i, j);");
+  check("ClassWithMethods x = c.intTwoArgumentMethod(i, j);",
+        MessageKind.NOT_ASSIGNABLE);
 
-  analyze("${header}c.intField(); }", MessageKind.NOT_CALLABLE);
-  analyze("${header}d.intField(); }", MessageKind.NOT_CALLABLE);
+  check("c.functionField();");
+  check("d.functionField();");
+  check("c.functionField(1);");
+  check("d.functionField('string');");
 
-  analyze("${header}c.untypedField(); }");
-  analyze("${header}d.untypedField(); }");
-  analyze("${header}c.untypedField(1); }");
-  analyze("${header}d.untypedField('string'); }");
+  check("c.intField();", MessageKind.NOT_CALLABLE);
+  check("d.intField();", MessageKind.NOT_CALLABLE);
+
+  check("c.untypedField();");
+  check("d.untypedField();");
+  check("c.untypedField(1);");
+  check("d.untypedField('string');");
+
+
+  check("c.intOneArgumentOneOptionalMethod('');",
+        MessageKind.NOT_ASSIGNABLE);
+  check("c.intOneArgumentOneOptionalMethod('', '');",
+        [MessageKind.NOT_ASSIGNABLE, MessageKind.NOT_ASSIGNABLE]);
+
+  check("c.intTwoOptionalMethod('');", MessageKind.NOT_ASSIGNABLE);
+  check("c.intTwoOptionalMethod('', '');",
+        [MessageKind.NOT_ASSIGNABLE, MessageKind.NOT_ASSIGNABLE]);
+
+  check("c.intOneArgumentOneNamedMethod('');",
+        MessageKind.NOT_ASSIGNABLE);
+  check("c.intOneArgumentOneNamedMethod('', b: '');",
+        [MessageKind.NOT_ASSIGNABLE, MessageKind.NOT_ASSIGNABLE]);
+
+  check("c.intTwoNamedMethod(a: '');", MessageKind.NOT_ASSIGNABLE);
+  check("c.intTwoNamedMethod(b: '');", MessageKind.NOT_ASSIGNABLE);
+  check("c.intTwoNamedMethod(a: '', b: '');",
+        [MessageKind.NOT_ASSIGNABLE, MessageKind.NOT_ASSIGNABLE]);
+  check("c.intTwoNamedMethod(b: '', a: '');",
+        [MessageKind.NOT_ASSIGNABLE, MessageKind.NOT_ASSIGNABLE]);
 
   // Invocation of dynamic variable.
-  analyze("${header}e(); }");
-  analyze("${header}e(1); }");
-  analyze("${header}e('string'); }");
+  check("e();");
+  check("e(1);");
+  check("e('string');");
 
   // Invocation on local method.
-  analyze("${header}localMethod(); }", MessageKind.MISSING_ARGUMENT);
-  analyze("${header}localMethod(1); }", MessageKind.NOT_ASSIGNABLE);
-  analyze("${header}localMethod('string'); }");
-  analyze("${header}int k = localMethod('string'); }");
-  analyze("${header}String k = localMethod('string'); }",
-      MessageKind.NOT_ASSIGNABLE);
+  check("localMethod();", MessageKind.MISSING_ARGUMENT);
+  check("localMethod(1);", MessageKind.NOT_ASSIGNABLE);
+  check("localMethod('string');");
+  check("int k = localMethod('string');");
+  check("String k = localMethod('string');", MessageKind.NOT_ASSIGNABLE);
 
   // Invocation on parenthesized expressions.
-  analyze("${header}(e)(); }");
-  analyze("${header}(e)(1); }");
-  analyze("${header}(e)('string'); }");
-  analyze("${header}(foo)(); }");
-  analyze("${header}(foo)(1); }");
-  analyze("${header}(foo)('string'); }");
+  check("(e)();");
+  check("(e)(1);");
+  check("(e)('string');");
+  check("(foo)();");
+  check("(foo)(1);");
+  check("(foo)('string');");
 
   // Invocations on function expressions.
-  analyze("${header}(foo){}(); }", MessageKind.MISSING_ARGUMENT);
-  analyze("${header}(foo){}(1); }");
-  analyze("${header}(foo){}('string'); }");
-  analyze("${header}(int foo){}('string'); }", MessageKind.NOT_ASSIGNABLE);
-  analyze("${header}(String foo){}('string'); }");
-  analyze("${header}int k = int bar(String foo){ return 0; }('string'); }");
-  analyze("${header}int k = String bar(String foo){ return foo; }('string'); }",
-      MessageKind.NOT_ASSIGNABLE);
+  check("(foo){}();", MessageKind.MISSING_ARGUMENT);
+  check("(foo){}(1);");
+  check("(foo){}('string');");
+  check("(int foo){}('string');", MessageKind.NOT_ASSIGNABLE);
+  check("(String foo){}('string');");
+  check("int k = int bar(String foo){ return 0; }('string');");
+  check("int k = String bar(String foo){ return foo; }('string');",
+        MessageKind.NOT_ASSIGNABLE);
 
   // Static invocations.
-  analyze("${header}ClassWithMethods.staticMethod(); }",
-      MessageKind.MISSING_ARGUMENT);
-  analyze("${header}ClassWithMethods.staticMethod(1); }",
-      MessageKind.NOT_ASSIGNABLE);
-  analyze("${header}ClassWithMethods.staticMethod('string'); }");
-  analyze("${header}int k = ClassWithMethods.staticMethod('string'); }");
-  analyze("${header}String k = ClassWithMethods.staticMethod('string'); }",
-      MessageKind.NOT_ASSIGNABLE);
+  check("ClassWithMethods.staticMethod();",
+        MessageKind.MISSING_ARGUMENT);
+  check("ClassWithMethods.staticMethod(1);",
+        MessageKind.NOT_ASSIGNABLE);
+  check("ClassWithMethods.staticMethod('string');");
+  check("int k = ClassWithMethods.staticMethod('string');");
+  check("String k = ClassWithMethods.staticMethod('string');",
+        MessageKind.NOT_ASSIGNABLE);
 
   // Invocation on dynamic variable.
-  analyze("${header}e.foo(); }");
-  analyze("${header}e.foo(1); }");
-  analyze("${header}e.foo('string'); }");
+  check("e.foo();");
+  check("e.foo(1);");
+  check("e.foo('string');");
 
   // Invocation on unresolved variable.
-  analyze("${header}foo(); }");
-  analyze("${header}foo(1); }");
-  analyze("${header}foo('string'); }");
+  check("foo();");
+  check("foo(1);");
+  check("foo('string');");
+  check("foo(a: 'string');");
+  check("foo(a: localMethod(1));", MessageKind.NOT_ASSIGNABLE);
 
   // TODO(johnniwinther): Add tests of invocations using implicit this.
 }
diff --git a/tests/compiler/dart2js/type_equals_test.dart b/tests/compiler/dart2js/type_equals_test.dart
index adf43c0..0c283db 100644
--- a/tests/compiler/dart2js/type_equals_test.dart
+++ b/tests/compiler/dart2js/type_equals_test.dart
@@ -50,7 +50,7 @@
 }
 
 void main() {
-  var uri = new Uri.fromComponents(scheme: 'source');
+  var uri = new Uri(scheme: 'source');
   var compiler = compilerFor(
       r"""
       typedef int Typedef1<X,Y>(String s1);
diff --git a/tests/compiler/dart2js/type_test_helper.dart b/tests/compiler/dart2js/type_test_helper.dart
index 7f1eaa22..db1a43f 100644
--- a/tests/compiler/dart2js/type_test_helper.dart
+++ b/tests/compiler/dart2js/type_test_helper.dart
@@ -23,7 +23,7 @@
   final MockCompiler compiler;
 
   factory TypeEnvironment(String source) {
-    var uri = new Uri.fromComponents(scheme: 'source');
+    var uri = new Uri(scheme: 'source');
     MockCompiler compiler = compilerFor('''
         main() {}
         $source''',
diff --git a/tests/compiler/dart2js/type_variable_bound_test.dart b/tests/compiler/dart2js/type_variable_bound_test.dart
index 6dd38a8..01761c4 100644
--- a/tests/compiler/dart2js/type_variable_bound_test.dart
+++ b/tests/compiler/dart2js/type_variable_bound_test.dart
@@ -6,7 +6,7 @@
 import "package:expect/expect.dart";
 
 compile(String source) {
-  Uri uri = new Uri('test:code');
+  Uri uri = Uri.parse('test:code');
   var compiler = compilerFor(source, uri);
   compiler.runCompiler(uri);
   return compiler;
diff --git a/tests/compiler/dart2js/unparser_test.dart b/tests/compiler/dart2js/unparser_test.dart
index 936b60e..d470b3f 100644
--- a/tests/compiler/dart2js/unparser_test.dart
+++ b/tests/compiler/dart2js/unparser_test.dart
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import "package:expect/expect.dart";
-import 'dart:uri';
 import 'parser_helper.dart';
 import 'mock_compiler.dart';
 import '../../../sdk/lib/_internal/compiler/implementation/tree/tree.dart';
diff --git a/tests/compiler/dart2js/uri_extras_test.dart b/tests/compiler/dart2js/uri_extras_test.dart
index 0d224bc0..7045384 100644
--- a/tests/compiler/dart2js/uri_extras_test.dart
+++ b/tests/compiler/dart2js/uri_extras_test.dart
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import "package:expect/expect.dart";
-import 'dart:uri';
 
 import '../../../sdk/lib/_internal/compiler/implementation/util/uri_extras.dart';
 
diff --git a/tests/compiler/dart2js/value_range_test.dart b/tests/compiler/dart2js/value_range_test.dart
index f623ced..474d2a1 100644
--- a/tests/compiler/dart2js/value_range_test.dart
+++ b/tests/compiler/dart2js/value_range_test.dart
@@ -219,6 +219,7 @@
   class Closure {}
   class Null {}
   class Dynamic_ {}
+  class StackTrace {}
   bool identical(Object a, Object b) {}''';
 
 const String INTERCEPTORSLIB_WITH_MEMBERS = r'''
diff --git a/tests/corelib/collection_length_test.dart b/tests/corelib/collection_length_test.dart
index 01a8061..3259ab2 100644
--- a/tests/corelib/collection_length_test.dart
+++ b/tests/corelib/collection_length_test.dart
@@ -52,12 +52,13 @@
 void testLength(var lengthable, int size) {
   print(lengthable.runtimeType);  // Show what hangs the test.
   int length = 0;
-  // If length or isEmpty is not a constant-time (or very fast) operation,
-  // this will timeout.
+  // If length, isEmpty or isNotEmpty is not a constant-time (or very fast)
+  // operation, this will timeout.
   for (int i = 0; i < 100000; i++) {
     if (!lengthable.isEmpty) length += lengthable.length;
+    if (lengthable.isNotEmpty) length += lengthable.length;
   }
-  if (length != size * 100000) throw "Bad length: $length / size: $size";
+  if (length != size * 200000) throw "Bad length: $length / size: $size";
 }
 
 
diff --git a/tests/corelib/core_runtime_types_test.dart b/tests/corelib/core_runtime_types_test.dart
index a86b800..ee91954 100644
--- a/tests/corelib/core_runtime_types_test.dart
+++ b/tests/corelib/core_runtime_types_test.dart
@@ -167,6 +167,7 @@
   static testStringMethods() {
     var s = "abcdef";
     assertEquals(s.isEmpty, false);
+    assertEquals(s.isNotEmpty, true);
     assertEquals(s.startsWith("abc"), true);
     assertEquals(s.endsWith("def"), true);
     assertEquals(s.startsWith("aa"), false);
diff --git a/tests/corelib/corelib.status b/tests/corelib/corelib.status
index 3d21fe2..7e3010d 100644
--- a/tests/corelib/corelib.status
+++ b/tests/corelib/corelib.status
@@ -97,9 +97,6 @@
 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 28629a9..395cc57 100644
--- a/tests/corelib/list_test.dart
+++ b/tests/corelib/list_test.dart
@@ -49,6 +49,7 @@
 void testLength(int length, List list) {
   Expect.equals(length, list.length);
   (length == 0 ? Expect.isTrue : Expect.isFalse)(list.isEmpty);
+  (length != 0 ? Expect.isTrue : Expect.isFalse)(list.isNotEmpty);
 }
 
 void testTypedLengthInvariantOperations(List list) {
diff --git a/tests/corelib/map_test.dart b/tests/corelib/map_test.dart
index a5bbbda7f..05afcf6 100644
--- a/tests/corelib/map_test.dart
+++ b/tests/corelib/map_test.dart
@@ -47,7 +47,7 @@
   Expect.equals(false, map.containsKey(1));
   map[1] = 1;
   map[1] = 2;
-  Expect.equals(1, map.length);
+  testLength(1, map);
 }
 
 void testMap(Map map, key1, key2, key3, key4, key5, key6, key7, key8) {
@@ -60,20 +60,20 @@
   int value7 = 70;
   int value8 = 80;
 
-  Expect.equals(0, map.length);
+  testLength(0, map);
 
   map[key1] = value1;
   Expect.equals(value1, map[key1]);
   map[key1] = value2;
   Expect.equals(false, map.containsKey(key2));
-  Expect.equals(1, map.length);
+  testLength(1, map);
 
   map[key1] = value1;
   Expect.equals(value1, map[key1]);
   // Add enough entries to make sure the table grows.
   map[key2] = value2;
   Expect.equals(value2, map[key2]);
-  Expect.equals(2, map.length);
+  testLength(2, map);
   map[key3] = value3;
   Expect.equals(value2, map[key2]);
   Expect.equals(value3, map[key3]);
@@ -98,15 +98,15 @@
   Expect.equals(value6, map[key6]);
   Expect.equals(value7, map[key7]);
   Expect.equals(value8, map[key8]);
-  Expect.equals(8, map.length);
+  testLength(8, map);
 
   map.remove(key4);
   Expect.equals(false, map.containsKey(key4));
-  Expect.equals(7, map.length);
+  testLength(7, map);
 
   // Test clearing the table.
   map.clear();
-  Expect.equals(0, map.length);
+  testLength(0, map);
   Expect.equals(false, map.containsKey(key1));
   Expect.equals(false, map.containsKey(key2));
   Expect.equals(false, map.containsKey(key3));
@@ -119,34 +119,34 @@
   // Test adding and removing again.
   map[key1] = value1;
   Expect.equals(value1, map[key1]);
-  Expect.equals(1, map.length);
+  testLength(1, map);
   map[key2] = value2;
   Expect.equals(value2, map[key2]);
-  Expect.equals(2, map.length);
+  testLength(2, map);
   map[key3] = value3;
   Expect.equals(value3, map[key3]);
   map.remove(key3);
-  Expect.equals(2, map.length);
+  testLength(2, map);
   map[key4] = value4;
   Expect.equals(value4, map[key4]);
   map.remove(key4);
-  Expect.equals(2, map.length);
+  testLength(2, map);
   map[key5] = value5;
   Expect.equals(value5, map[key5]);
   map.remove(key5);
-  Expect.equals(2, map.length);
+  testLength(2, map);
   map[key6] = value6;
   Expect.equals(value6, map[key6]);
   map.remove(key6);
-  Expect.equals(2, map.length);
+  testLength(2, map);
   map[key7] = value7;
   Expect.equals(value7, map[key7]);
   map.remove(key7);
-  Expect.equals(2, map.length);
+  testLength(2, map);
   map[key8] = value8;
   Expect.equals(value8, map[key8]);
   map.remove(key8);
-  Expect.equals(2, map.length);
+  testLength(2, map);
 
   Expect.equals(true, map.containsKey(key1));
   Expect.equals(true, map.containsValue(value1));
@@ -213,11 +213,11 @@
   map.clear();
   for (int i = 0; i < 100; i++) {
     map[1] = 2;
-    Expect.equals(1, map.length);
+    testLength(1, map);
     map.remove(1);
-    Expect.equals(0, map.length);
+    testLength(0, map);
   }
-  Expect.equals(0, map.length);
+  testLength(0, map);
 }
 
 void testMapLiteral() {
@@ -347,15 +347,15 @@
   map[nan] = 'value:0';
   Expect.isFalse(map.containsKey(nan));
   Expect.equals(null, map[nan]);
-  Expect.equals(1, map.length);
+  testLength(1, map);
 
   map[nan] = 'value:1';
   Expect.isFalse(map.containsKey(nan));
   Expect.equals(null, map[nan]);
-  Expect.equals(2, map.length);
+  testLength(2, map);
 
   Expect.equals(null, map.remove(nan));
-  Expect.equals(2, map.length);
+  testLength(2, map);
 
   var count = 0;
   map.forEach((key, value) {
@@ -366,3 +366,9 @@
   map.clear();
   Expect.isTrue(map.isEmpty);
 }
+
+void testLength(int length, Map map) {
+  Expect.equals(length, map.length);
+  (length == 0 ? Expect.isTrue : Expect.isFalse)(map.isEmpty);
+  (length != 0 ? Expect.isTrue : Expect.isFalse)(map.isNotEmpty);
+}
diff --git a/tests/corelib/queue_test.dart b/tests/corelib/queue_test.dart
index 6e5a0d77..3cf139f 100644
--- a/tests/corelib/queue_test.dart
+++ b/tests/corelib/queue_test.dart
@@ -124,7 +124,7 @@
   }
 
   void checkQueue(Queue queue, int expectedSize, int expectedSum) {
-    Expect.equals(expectedSize, queue.length);
+    testLength(expectedSize, queue);
     int sum = 0;
     void sumElements(int value) {
       sum += value;
@@ -136,6 +136,7 @@
   testLength(int length, Queue queue) {
     Expect.equals(length, queue.length);
     ((length == 0) ? Expect.isTrue : Expect.isFalse)(queue.isEmpty);
+    ((length != 0) ? Expect.isTrue : Expect.isFalse)(queue.isNotEmpty);
   }
 
   void testAddAll() {
diff --git a/tests/corelib/set_test.dart b/tests/corelib/set_test.dart
index 5acb8a5..f085835 100644
--- a/tests/corelib/set_test.dart
+++ b/tests/corelib/set_test.dart
@@ -10,29 +10,29 @@
 
 void testMain(Set create()) {
   Set set = create();
-  Expect.equals(0, set.length);
+  testLength(0, set);
   set.add(1);
-  Expect.equals(1, set.length);
+  testLength(1, set);
   Expect.isTrue(set.contains(1));
 
   set.add(1);
-  Expect.equals(1, set.length);
+  testLength(1, set);
   Expect.isTrue(set.contains(1));
 
   set.remove(1);
-  Expect.equals(0, set.length);
+  testLength(0, set);
   Expect.isFalse(set.contains(1));
 
   for (int i = 0; i < 10; i++) {
     set.add(i);
   }
 
-  Expect.equals(10, set.length);
+  testLength(10, set);
   for (int i = 0; i < 10; i++) {
     Expect.isTrue(set.contains(i));
   }
 
-  Expect.equals(10, set.length);
+  testLength(10, set);
 
   for (int i = 10; i < 20; i++) {
     Expect.isFalse(set.contains(i));
@@ -160,14 +160,14 @@
     list[i] = i + 10;
   }
   set.addAll(list);
-  Expect.equals(20, set.length);
+  testLength(20, set);
   for (int i = 0; i < 20; i++) {
     Expect.isTrue(set.contains(i));
   }
 
   // Test Set.removeAll
   set.removeAll(list);
-  Expect.equals(10, set.length);
+  testLength(10, set);
   for (int i = 0; i < 10; i++) {
     Expect.isTrue(set.contains(i));
   }
@@ -177,9 +177,15 @@
 
   // Test Set.clear.
   set.clear();
-  Expect.equals(0, set.length);
+  testLength(0, set);
   set.add(11);
-  Expect.equals(1, set.length);
+  testLength(1, set);
+}
+
+void testLength(int length, Set set) {
+  Expect.equals(length, set.length);
+  (length == 0 ? Expect.isTrue : Expect.isFalse)(set.isEmpty);
+  (length != 0 ? Expect.isTrue : Expect.isFalse)(set.isNotEmpty);
 }
 
 main() {
diff --git a/tests/corelib/string_buffer_test.dart b/tests/corelib/string_buffer_test.dart
index 093c7ad..2c556f7 100644
--- a/tests/corelib/string_buffer_test.dart
+++ b/tests/corelib/string_buffer_test.dart
@@ -8,10 +8,10 @@
 
 void testConstructor() {
   StringBuffer bf = new StringBuffer("");
-  Expect.equals(true, bf.isEmpty);
+  testBufferLength(0, bf);
 
   bf = new StringBuffer("abc");
-  Expect.equals(3, bf.length);
+  testBufferLength(3, bf);
   Expect.equals("abc", bf.toString());
 
   bf = new StringBuffer("\x00");
@@ -22,7 +22,7 @@
   Expect.equals(true, bf.isEmpty);
 
   bf.write("a");
-  Expect.equals(1, bf.length);
+  testBufferLength(1, bf);
   Expect.equals("a", bf.toString());
 
   bf = new StringBuffer("");
@@ -70,13 +70,13 @@
 
 void testLength() {
   StringBuffer bf = new StringBuffer("");
-  Expect.equals(0, bf.length);
+  testBufferLength(0, bf);
   bf.write("foo");
-  Expect.equals(3, bf.length);
+  testBufferLength(3, bf);
   bf.write("bar");
-  Expect.equals(6, bf.length);
+  testBufferLength(6, bf);
   bf.write("");
-  Expect.equals(6, bf.length);
+  testBufferLength(6, bf);
 }
 
 void testIsEmpty() {
@@ -103,14 +103,14 @@
   bf.write("foo");
   bf.clear();
   Expect.equals("", bf.toString());
-  Expect.equals(0, bf.length);
+  testBufferLength(0, bf);
 
   bf.write("bar");
   Expect.equals("bar", bf.toString());
-  Expect.equals(3, bf.length);
+  testBufferLength(3, bf);
   bf.clear();
   Expect.equals("", bf.toString());
-  Expect.equals(0, bf.length);
+  testBufferLength(0, bf);
 }
 
 void testToString() {
@@ -172,6 +172,12 @@
   Expect.throws(() { bf2.writeCharCode(0x110000); });
 }
 
+void testBufferLength(int length, StringBuffer bf) {
+  Expect.equals(length, bf.length);
+  (length == 0 ? Expect.isTrue : Expect.isFalse)(bf.isEmpty);
+  (length != 0 ? Expect.isTrue : Expect.isFalse)(bf.isNotEmpty);
+}
+
 void main() {
   testToString();
   testConstructor();
diff --git a/tests/corelib/string_test.dart b/tests/corelib/string_test.dart
index fd73fea..dbcd630 100644
--- a/tests/corelib/string_test.dart
+++ b/tests/corelib/string_test.dart
@@ -24,6 +24,14 @@
     testCharCodes();
   }
 
+  static void testLength() {
+    String str = "";
+    for (var i = 0; i < 20; i++) {
+      testStringLength(i, str);
+      str += " ";
+    }
+  }
+
   static void testOutOfRange() {
     String a = "Hello";
     bool exception_caught = false;
@@ -53,7 +61,7 @@
     String str = "string";
     for (int i = 0; i < str.length; i++) {
       Expect.equals(true, str[i] is String);
-      Expect.equals(1, str[i].length);
+      testStringLength(1, str[i]);
     }
   }
 
@@ -68,7 +76,7 @@
     var a = "One";
     var b = "Four";
     var c = a + b;
-    Expect.equals(7, c.length);
+    testStringLength(7, c);
     Expect.equals("OneFour", c);
   }
 
@@ -286,6 +294,12 @@
   }
 }
 
+void testStringLength(int length, String str) {
+  Expect.equals(length, str.length);
+  (length == 0 ? Expect.isTrue : Expect.isFalse)(str.isEmpty);
+  (length != 0 ? Expect.isTrue : Expect.isFalse)(str.isNotEmpty);
+}
+
 main() {
   StringTest.testMain();
 }
diff --git a/tests/corelib/uri_ipv6_test.dart b/tests/corelib/uri_ipv6_test.dart
new file mode 100644
index 0000000..1ec9d57
--- /dev/null
+++ b/tests/corelib/uri_ipv6_test.dart
@@ -0,0 +1,113 @@
+// 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';
+
+
+void testValidIpv6Uri() {
+  var path = 'http://[::1]:1234/path?query=5#now';
+  var uri = Uri.parse(path);
+  Expect.equals('http', uri.scheme);
+  Expect.equals('::1', uri.host);
+  Expect.equals(1234, uri.port);
+  Expect.equals('/path', uri.path);
+  Expect.equals('query=5', uri.query);
+  Expect.equals('now', uri.fragment);
+  Expect.equals(path, uri.toString());
+
+  path = 'http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:8080/index.html';
+  uri = Uri.parse(path);
+  Expect.equals('http', uri.scheme);
+  Expect.equals('FEDC:BA98:7654:3210:FEDC:BA98:7654:3210', uri.host);
+  Expect.equals(8080, uri.port);
+  Expect.equals('/index.html', uri.path);
+  Expect.equals(path, uri.toString());
+
+  path = 'http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:80/index.html';
+  uri = Uri.parse(path);
+  Expect.equals('http', uri.scheme);
+  Expect.equals('FEDC:BA98:7654:3210:FEDC:BA98:7654:3210', uri.host);
+  Expect.equals(0, uri.port);
+  Expect.equals('/index.html', uri.path);
+  Expect.equals('http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]/index.html',
+                uri.toString());
+
+  path = 'https://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:443/index.html';
+  uri = Uri.parse(path);
+  Expect.equals('https', uri.scheme);
+  Expect.equals('FEDC:BA98:7654:3210:FEDC:BA98:7654:3210', uri.host);
+  Expect.equals(0, uri.port);
+  Expect.equals('/index.html', uri.path);
+  Expect.equals('https://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]/index.html',
+                uri.toString());
+
+  path = 'http://[1080:0:0:0:8:800:200C:417A]/index.html';
+  uri = Uri.parse(path);
+  Expect.equals('http', uri.scheme);
+  Expect.equals('1080:0:0:0:8:800:200C:417A', uri.host);
+  Expect.equals(0, uri.port);
+  Expect.equals('/index.html', uri.path);
+  Expect.equals(path, uri.toString());
+
+  path = 'http://[3ffe:2a00:100:7031::1]';
+  uri = Uri.parse(path);
+  Expect.equals('http', uri.scheme);
+  Expect.equals('3ffe:2a00:100:7031::1', uri.host);
+  Expect.equals(0, uri.port);
+  Expect.equals('', uri.path);
+  Expect.equals(path, uri.toString());
+
+  path = 'http://[1080::8:800:200C:417A]/foo';
+  uri = Uri.parse(path);
+  Expect.equals('http', uri.scheme);
+  Expect.equals('1080::8:800:200C:417A', uri.host);
+  Expect.equals(0, uri.port);
+  Expect.equals('/foo', uri.path);
+  Expect.equals(path, uri.toString());
+
+  path = 'http://[::192.9.5.5]/ipng';
+  uri = Uri.parse(path);
+  Expect.equals('http', uri.scheme);
+  Expect.equals('::192.9.5.5', uri.host);
+  Expect.equals(0, uri.port);
+  Expect.equals('/ipng', uri.path);
+  Expect.equals(path, uri.toString());
+
+  path = 'http://[::FFFF:129.144.52.38]:8080/index.html';
+  uri = Uri.parse(path);
+  Expect.equals('http', uri.scheme);
+  Expect.equals('::FFFF:129.144.52.38', uri.host);
+  Expect.equals(8080, uri.port);
+  Expect.equals('/index.html', uri.path);
+  Expect.equals(path, uri.toString());
+
+  path = 'http://[::FFFF:129.144.52.38]:80/index.html';
+  uri = Uri.parse(path);
+  Expect.equals('http', uri.scheme);
+  Expect.equals('::FFFF:129.144.52.38', uri.host);
+  Expect.equals(0, uri.port);
+  Expect.equals('/index.html', uri.path);
+  Expect.equals('http://[::FFFF:129.144.52.38]/index.html', uri.toString());
+
+  path = 'https://[::FFFF:129.144.52.38]:443/index.html';
+  uri = Uri.parse(path);
+  Expect.equals('https', uri.scheme);
+  Expect.equals('::FFFF:129.144.52.38', uri.host);
+  Expect.equals(0, uri.port);
+  Expect.equals('/index.html', uri.path);
+  Expect.equals('https://[::FFFF:129.144.52.38]/index.html', uri.toString());
+
+  path = 'http://[2010:836B:4179::836B:4179]';
+  uri = Uri.parse(path);
+  Expect.equals('http', uri.scheme);
+  Expect.equals('2010:836B:4179::836B:4179', uri.host);
+  Expect.equals(0, uri.port);
+  Expect.equals('', uri.path);
+  Expect.equals(path, uri.toString());
+}
+
+void main() {
+  testValidIpv6Uri();
+}
+
diff --git a/tests/corelib/uri_normalize_test.dart b/tests/corelib/uri_normalize_test.dart
new file mode 100644
index 0000000..91bbe10
--- /dev/null
+++ b/tests/corelib/uri_normalize_test.dart
@@ -0,0 +1,42 @@
+// 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";
+
+testNormalizePath() {
+  test(String expected, String path) {
+    var uri = new Uri(path: path);
+    Expect.equals(expected, uri.path);
+    Expect.equals(expected, uri.toString());
+  }
+
+  var unreserved = "-._~0123456789"
+                   "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+                   "abcdefghijklmnopqrstuvwxyz";
+
+  test("A", "%41");
+  test("AB", "%41%42");
+  test("%40AB", "%40%41%42");
+  test("a", "%61");
+  test("ab", "%61%62");
+  test("%60ab", "%60%61%62");
+  test(unreserved, unreserved);
+
+  var x = new StringBuffer();
+  for (int i = 32; i < 128; i++) {
+    if (unreserved.indexOf(new String.fromCharCode(i)) != -1) {
+      x.writeCharCode(i);
+    } else {
+      x.write("%");
+      x.write(i.toRadixString(16));
+    }
+  }
+  print(x.toString().toUpperCase());
+  Expect.equals(x.toString().toUpperCase(),
+                new Uri(path: x.toString()).toString().toUpperCase());
+}
+
+main() {
+  testNormalizePath();
+}
diff --git a/tests/corelib/uri_path_test.dart b/tests/corelib/uri_path_test.dart
new file mode 100644
index 0000000..bc62d3e
--- /dev/null
+++ b/tests/corelib/uri_path_test.dart
@@ -0,0 +1,83 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+void testInvalidArguments() {
+}
+
+void testPath() {
+  test(s, uri) {
+    Expect.equals(s, uri.toString());
+    Expect.equals(uri, Uri.parse(s));
+  }
+
+  test("urn:", new Uri(scheme: "urn"));
+  test("urn:xxx", new Uri(scheme: "urn", path: "xxx"));
+  test("urn:xxx:yyy", new Uri(scheme: "urn", path: "xxx:yyy"));
+}
+
+void testPathSegments() {
+  test(String path, List<String> segments) {
+    void check(uri) {
+      Expect.equals(path, uri.path);
+      Expect.equals(path, uri.toString());
+      Expect.listEquals(segments, uri.pathSegments);
+    }
+
+    var uri1 = new Uri(pathSegments: segments);
+    var uri2 = new Uri(path: path);
+    var uri3 = Uri.parse(path);
+    check(uri1);
+    check(uri2);
+    check(uri3);
+    Expect.equals(uri1, uri3);
+    Expect.equals(uri2, uri3);
+  }
+
+  test("", []);
+  test("%20", [" "]);
+  test("%20/%20%20", [" ", "  "]);
+  test("A", ["A"]);
+  test("%C3%B8", ["ø"]);
+  test("%C3%B8/%C3%A5", ["ø", "å"]);
+  test("%C8%A4/%E5%B9%B3%E4%BB%AE%E5%90%8D", ["Ȥ", "平仮名"]);
+  test("A/b", ["A", "b"]);
+  test("A/%25", ["A", "%"]);
+  test("%2F/a%2Fb", ["/", "a/b"]);
+  test("name;v=1.1", ["name;v=1.1"]);
+  test("name,v=1.1", ["name,v=1.1"]);
+  test("name;v=1.1/name,v=1.1", ["name;v=1.1", "name,v=1.1"]);
+
+  var unreserved = "-._~0123456789"
+                   "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+                   "abcdefghijklmnopqrstuvwxyz";
+  var subDelimiters = r"!$&'()*+,;=";
+  var additionalPathChars = ":@";
+  var pchar = unreserved + subDelimiters + additionalPathChars;
+
+  var encoded = new StringBuffer();
+  var unencoded = new StringBuffer();
+  for (int i = 32; i < 128; i++) {
+    if (pchar.indexOf(new String.fromCharCode(i)) != -1) {
+      encoded.writeCharCode(i);
+    } else {
+      encoded.write("%");
+      encoded.write(i.toRadixString(16).toUpperCase());
+    }
+    unencoded.writeCharCode(i);
+  }
+  encoded = encoded.toString();
+  unencoded = unencoded.toString();
+  print(encoded);
+  print(unencoded);
+  test(encoded, [unencoded]);
+  test(encoded + "/" + encoded, [unencoded, unencoded]);
+}
+
+main() {
+  testInvalidArguments();
+  testPath();
+  testPathSegments();
+}
diff --git a/tests/corelib/uri_query_test.dart b/tests/corelib/uri_query_test.dart
new file mode 100644
index 0000000..acbe9d8
--- /dev/null
+++ b/tests/corelib/uri_query_test.dart
@@ -0,0 +1,121 @@
+// 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";
+
+void testInvalidArguments() {
+}
+
+void testEncodeQueryComponent() {
+  // This exact data is from posting a form in Chrome 26 with the one
+  // exception that * is encoded as %30 and ~ is not encoded as %7E.
+  Expect.equals(
+      "%21%22%23%24%25%26%27%28%29%2A%2B%2C-.%2F%"
+      "3A%3B%3C%3D%3E%3F%40%5B%5C%5D%5E_%60%7B%7C%7D~",
+      Uri.encodeQueryComponent("!\"#\$%&'()*+,-./:;<=>?@[\\]^_`{|}~"));
+  Expect.equals("+%2B+", Uri.encodeQueryComponent(" + "));
+  Expect.equals("%2B+%2B", Uri.encodeQueryComponent("+ +"));
+}
+
+void testQueryParameters() {
+  test(String query, Map<String, String> parameters) {
+    check(uri) {
+      Expect.equals(query, uri.query);
+      if (query.isEmpty) {
+        Expect.equals(query, uri.toString());
+      } else {
+        Expect.equals("?$query", uri.toString());
+      }
+      if (parameters.containsValue(null)) {
+      } else {
+        Expect.mapEquals(parameters, uri.queryParameters);
+      }
+    }
+
+    var uri1 = new Uri(queryParameters: parameters);
+    var uri2 = new Uri(query: query);
+    var uri3 = Uri.parse("?$query");
+    check(uri1);
+    check(uri2);
+    check(uri3);
+    Expect.equals(uri1, uri3);
+    Expect.equals(uri2, uri3);
+  }
+
+  test("", {});
+  test("A", {"A": null});
+  test("A", {"A": ""});
+  test("A=a", {"A": "a"});
+  test("A=+", {"A": " "});
+  test("A=%2B", {"A": "+"});
+  test("A=a&B", {"A": "a", "B": null});
+  test("A=a&B", {"A": "a", "B": ""});
+  test("A=a&B=b", {"A": "a", "B": "b"});
+
+  var unreserved = "-._~0123456789"
+                   "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+                   "abcdefghijklmnopqrstuvwxyz";
+  var encoded = new StringBuffer();
+  var unencoded = new StringBuffer();
+  for (int i = 32; i < 128; i++) {
+    if (i == 32) {
+      encoded.write("+");
+    } else if (unreserved.indexOf(new String.fromCharCode(i)) != -1) {
+      encoded.writeCharCode(i);
+    } else {
+      encoded.write("%");
+      encoded.write(i.toRadixString(16).toUpperCase());
+    }
+    unencoded.writeCharCode(i);
+  }
+  encoded = encoded.toString();
+  unencoded = unencoded.toString();
+  print(encoded);
+  print(unencoded);
+  test("a=$encoded", {"a": unencoded});
+  test("a=$encoded&b=$encoded", {"a": unencoded, "b": unencoded});
+
+  var map = new Map();
+  map[unencoded] = unencoded;
+  test("$encoded=$encoded", map);
+}
+
+testInvalidQueryParameters() {
+  test(String query, Map<String, String> parameters) {
+    check(uri) {
+      Expect.equals(query, uri.query);
+      if (query.isEmpty) {
+        Expect.equals(query, uri.toString());
+      } else {
+        Expect.equals("?$query", uri.toString());
+      }
+      if (parameters.containsValue(null)) {
+      } else {
+        Expect.mapEquals(parameters, uri.queryParameters);
+      }
+    }
+
+    var uri1 = new Uri(query: query);
+    var uri2 = Uri.parse("?$query");
+    check(uri1);
+    check(uri2);
+    Expect.equals(uri1, uri2);
+  }
+
+  test("=", {});
+  test("=xxx", {});
+  test("===", {});
+  test("=xxx=yyy=zzz", {});
+  test("=&=&=", {});
+  test("=xxx&=yyy&=zzz", {});
+  test("&=&=&", {});
+  test("&=xxx&=xxx&", {});
+}
+
+main() {
+  testInvalidArguments();
+  testEncodeQueryComponent();
+  testQueryParameters();
+  testInvalidQueryParameters();
+}
diff --git a/tests/corelib/uri_scheme_test.dart b/tests/corelib/uri_scheme_test.dart
new file mode 100644
index 0000000..2a7fd76
--- /dev/null
+++ b/tests/corelib/uri_scheme_test.dart
@@ -0,0 +1,29 @@
+// 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";
+
+void testInvalidArguments() {
+  Expect.throws(() => new Uri(scheme: "_"), (e) => e is ArgumentError);
+  Expect.throws(() => new Uri(scheme: "http_s"), (e) => e is ArgumentError);
+}
+
+void testScheme() {
+  test(String expectedScheme, String expectedUri, String scheme) {
+    var uri = new Uri(scheme: scheme);
+    Expect.equals(expectedScheme, uri.scheme);
+    Expect.equals(expectedUri, uri.toString());
+  }
+
+  test("http", "http:", "http");
+  test("http", "http:", "HTTP");
+  test("http+ssl", "http+ssl:", "HTTP+ssl");
+  test("urn", "urn:", "urn");
+  test("urn", "urn:", "UrN");
+}
+
+main() {
+  testInvalidArguments();
+  testScheme();
+}
diff --git a/tests/utils/uri_test.dart b/tests/corelib/uri_test.dart
similarity index 74%
rename from tests/utils/uri_test.dart
rename to tests/corelib/uri_test.dart
index 3653d2a..0d671b7 100644
--- a/tests/utils/uri_test.dart
+++ b/tests/corelib/uri_test.dart
@@ -6,30 +6,34 @@
 
 import "package:expect/expect.dart";
 import 'dart:utf';
-import 'dart:uri';
 
 testUri(String uri, bool isAbsolute) {
   Expect.equals(isAbsolute, Uri.parse(uri).isAbsolute);
-  Expect.equals(isAbsolute, new Uri(uri).isAbsolute);
   Expect.stringEquals(uri, Uri.parse(uri).toString());
-  Expect.stringEquals(uri, new Uri(uri).toString());
 
   // Test equals and hashCode members.
-  Expect.equals(new Uri(uri), new Uri(uri));
-  Expect.equals(new Uri(uri).hashCode, new Uri(uri).hashCode);
+  Expect.equals(Uri.parse(uri), Uri.parse(uri));
+  Expect.equals(Uri.parse(uri).hashCode, Uri.parse(uri).hashCode);
 }
 
 testEncodeDecode(String orig, String encoded) {
-  var e = encodeUri(orig);
+  var e = Uri.encodeFull(orig);
   Expect.stringEquals(encoded, e);
-  var d = decodeUri(encoded);
+  var d = Uri.decodeFull(encoded);
   Expect.stringEquals(orig, d);
 }
 
 testEncodeDecodeComponent(String orig, String encoded) {
-  var e = encodeUriComponent(orig);
+  var e = Uri.encodeComponent(orig);
   Expect.stringEquals(encoded, e);
-  var d = decodeUriComponent(encoded);
+  var d = Uri.decodeComponent(encoded);
+  Expect.stringEquals(orig, d);
+}
+
+testEncodeDecodeQueryComponent(String orig, String encoded) {
+  var e = Uri.encodeQueryComponent(orig);
+  Expect.stringEquals(encoded, e);
+  var d = Uri.decodeQueryComponent(encoded);
   Expect.stringEquals(orig, d);
 }
 
@@ -89,48 +93,56 @@
                       base.resolve("../g;p/h;s").toString());
 }
 
+void testResolvePath(String expected, String path) {
+  Expect.equals(expected, new Uri().resolveUri(new Uri(path: path)).path);
+  Expect.equals(
+      "http://localhost$expected",
+      Uri.parse("http://localhost").resolveUri(new Uri(path: path)).toString());
+}
+
 main() {
   testUri("http:", true);
   testUri("file://", true);
   testUri("file", false);
-  testUri("http://user@example.com:80/fisk?query=89&hest=silas", true);
-  testUri("http://user@example.com:80/fisk?query=89&hest=silas#fragment",
+  testUri("http://user@example.com:8080/fisk?query=89&hest=silas", true);
+  testUri("http://user@example.com:8080/fisk?query=89&hest=silas#fragment",
           false);
-  Expect.stringEquals("http://user@example.com:80/a/b/c?query#fragment",
-                      const Uri.fromComponents(
+  Expect.stringEquals("http://user@example.com/a/b/c?query#fragment",
+                      new Uri(
                           scheme: "http",
                           userInfo: "user",
-                          domain: "example.com",
+                          host: "example.com",
                           port: 80,
                           path: "/a/b/c",
                           query: "query",
                           fragment: "fragment").toString());
-  Expect.stringEquals("null://null@null/a/b/c/?null#null",
-                      const Uri.fromComponents(
+  Expect.stringEquals("//null@null/a/b/c/",
+                      new Uri(
                           scheme: null,
                           userInfo: null,
-                          domain: null,
+                          host: null,
                           port: 0,
                           path: "/a/b/c/",
                           query: null,
                           fragment: null).toString());
   Expect.stringEquals("file://", Uri.parse("file:").toString());
-  Expect.stringEquals("file://", new Uri("file:").toString());
-  Expect.stringEquals("/a/g", removeDotSegments("/a/b/c/./../../g"));
-  Expect.stringEquals("mid/6", removeDotSegments("mid/content=5/../6"));
-  Expect.stringEquals("a/b/e", removeDotSegments("a/b/c/d/../../e"));
-  Expect.stringEquals("a/b/e", removeDotSegments("../a/b/c/d/../../e"));
-  Expect.stringEquals("a/b/e", removeDotSegments("./a/b/c/d/../../e"));
-  Expect.stringEquals("a/b/e", removeDotSegments("../a/b/./c/d/../../e"));
-  Expect.stringEquals("a/b/e", removeDotSegments("./a/b/./c/d/../../e"));
-  Expect.stringEquals("a/b/e/", removeDotSegments("./a/b/./c/d/../../e/."));
-  Expect.stringEquals("a/b/e/", removeDotSegments("./a/b/./c/d/../../e/./."));
-  Expect.stringEquals("a/b/e/", removeDotSegments("./a/b/./c/d/../../e/././."));
+
+  testResolvePath("/a/g", "/a/b/c/./../../g");
+  testResolvePath("/a/g", "/a/b/c/./../../g");
+  testResolvePath("/mid/6", "mid/content=5/../6");
+  testResolvePath("/a/b/e", "a/b/c/d/../../e");
+  testResolvePath("/a/b/e", "../a/b/c/d/../../e");
+  testResolvePath("/a/b/e", "./a/b/c/d/../../e");
+  testResolvePath("/a/b/e", "../a/b/./c/d/../../e");
+  testResolvePath("/a/b/e", "./a/b/./c/d/../../e");
+  testResolvePath("/a/b/e/", "./a/b/./c/d/../../e/.");
+  testResolvePath("/a/b/e/", "./a/b/./c/d/../../e/./.");
+  testResolvePath("/a/b/e/", "./a/b/./c/d/../../e/././.");
 
   final urisSample = "http://a/b/c/d;p?q";
   Uri baseFromString = Uri.parse(urisSample);
   testUriPerRFCs(baseFromString);
-  Uri base = new Uri(urisSample);
+  Uri base = Uri.parse(urisSample);
   testUriPerRFCs(base);
 
   Expect.stringEquals(
@@ -147,48 +159,48 @@
       Uri.parse("https://example.com:1234/a/b/c").origin);
   Expect.throws(
       () => Uri.parse("http:").origin,
-      (e) { return e is ArgumentError; },
-      "origin for uri with empty domain should fail");
+      (e) { return e is StateError; },
+      "origin for uri with empty host should fail");
   Expect.throws(
-      () => const Uri.fromComponents(
+      () => new Uri(
           scheme: "http",
           userInfo: null,
-          domain: "",
+          host: "",
           port: 80,
           path: "/a/b/c",
           query: "query",
           fragment: "fragment").origin,
-      (e) { return e is ArgumentError; },
-      "origin for uri with empty domain should fail");
+      (e) { return e is StateError; },
+      "origin for uri with empty host should fail");
   Expect.throws(
-      () => const Uri.fromComponents(
+      () => new Uri(
           scheme: null,
           userInfo: null,
-          domain: "",
+          host: "",
           port: 80,
           path: "/a/b/c",
           query: "query",
           fragment: "fragment").origin,
-      (e) { return e is ArgumentError; },
+      (e) { return e is StateError; },
       "origin for uri with empty scheme should fail");
   Expect.throws(
-      () => const Uri.fromComponents(
+      () => new Uri(
           scheme: "http",
           userInfo: null,
-          domain: null,
+          host: null,
           port: 80,
           path: "/a/b/c",
           query: "query",
           fragment: "fragment").origin,
-      (e) { return e is ArgumentError; },
-      "origin for uri with empty domain should fail");
+      (e) { return e is StateError; },
+      "origin for uri with empty host should fail");
   Expect.throws(
       () => Uri.parse("http://:80").origin,
-      (e) { return e is ArgumentError; },
-      "origin for uri with empty domain should fail");
+      (e) { return e is StateError; },
+      "origin for uri with empty host should fail");
   Expect.throws(
       () => Uri.parse("file://localhost/test.txt").origin,
-      (e) { return e is ArgumentError; },
+      (e) { return e is StateError; },
       "origin for non-http/https uri should fail");
 
   // URI encode tests
@@ -197,7 +209,7 @@
 
   Expect.stringEquals("\u{10000}", s);
 
-  testEncodeDecode("A + B", "A+%2B+B");
+  testEncodeDecode("A + B", "A%20%2B%20B");
   testEncodeDecode("\uFFFE", "%EF%BF%BE");
   testEncodeDecode("\uFFFF", "%EF%BF%BF");
   testEncodeDecode("\uFFFE", "%EF%BF%BE");
@@ -207,6 +219,7 @@
   testEncodeDecode("\u0800", "%E0%A0%80");
   testEncodeDecode(":/@',;?&=+\$", ":/@',;?&=%2B\$");
   testEncodeDecode(s, "%F0%90%80%80");
+  testEncodeDecodeComponent("A + B", "A%20%2B%20B");
   testEncodeDecodeComponent("\uFFFE", "%EF%BF%BE");
   testEncodeDecodeComponent("\uFFFF", "%EF%BF%BF");
   testEncodeDecodeComponent("\uFFFE", "%EF%BF%BE");
@@ -216,4 +229,5 @@
   testEncodeDecodeComponent("\u0800", "%E0%A0%80");
   testEncodeDecodeComponent(":/@',;?&=+\$", "%3A%2F%40'%2C%3B%3F%26%3D%2B%24");
   testEncodeDecodeComponent(s, "%F0%90%80%80");
+  testEncodeDecodeQueryComponent("A + B", "A+%2B+B");
 }
diff --git a/tests/html/custom_element_bindings_test.dart b/tests/html/custom_element_bindings_test.dart
index c80c5fb..3b9d6a9 100644
--- a/tests/html/custom_element_bindings_test.dart
+++ b/tests/html/custom_element_bindings_test.dart
@@ -283,4 +283,5 @@
   Iterable<V> get values => _map.values;
   int get length => _map.length;
   bool get isEmpty => _map.isEmpty;
+  bool get isNotEmpty => _map.isNotEmpty;
 }
diff --git a/tests/html/form_data_test.dart b/tests/html/form_data_test.dart
index 75dedce..3017810 100644
--- a/tests/html/form_data_test.dart
+++ b/tests/html/form_data_test.dart
@@ -7,7 +7,6 @@
 import '../../pkg/unittest/lib/unittest.dart';
 import '../../pkg/unittest/lib/html_individual_config.dart';
 import 'dart:html';
-import 'dart:uri';
 
 void fail(message) {
   guardAsync(() {
diff --git a/tests/html/location_test.dart b/tests/html/location_test.dart
index 88e3f2d..d5c8e5e 100644
--- a/tests/html/location_test.dart
+++ b/tests/html/location_test.dart
@@ -2,7 +2,6 @@
 import '../../pkg/unittest/lib/unittest.dart';
 import '../../pkg/unittest/lib/html_config.dart';
 import 'dart:html';
-import 'dart:uri';
 
 main() {
   useHtmlConfiguration();
@@ -23,8 +22,8 @@
     var origin = window.location.origin;
 
     // We build up the origin from Uri, then make sure that it matches.
-    var uri = new Uri(window.location.href);
-    var reconstructedOrigin = '${uri.scheme}://${uri.domain}';
+    var uri = Uri.parse(window.location.href);
+    var reconstructedOrigin = '${uri.scheme}://${uri.host}';
     if (uri.port != 0) {
       reconstructedOrigin = '$reconstructedOrigin:${uri.port}';
     }
diff --git a/tests/html/rtc_test.dart b/tests/html/rtc_test.dart
index d5cf9aa..df096ab0 100644
--- a/tests/html/rtc_test.dart
+++ b/tests/html/rtc_test.dart
@@ -17,16 +17,20 @@
   });
 
   group('functionality', () {
-    // TODO(efortuna): More thorough testing of this API requires the user to
+    // More thorough testing of this API requires the user to
     // explicitly click "allow this site to access my camera and/or microphone."
     // or particularly allow that site to always have those permission on each
-    // computer the test is run. Contact WebKit and/or Chrome people to
-    // determine how they test with this issue.
+    // computer the test is run. For more through tests, see
+    // interactive_test.dart.
     if (RtcPeerConnection.supported) {
       test('peer connection', () {
         var pc = new RtcPeerConnection(
-            {'iceServers': [ {'url':'stun:foo.com:19302'}]});
+            {'iceServers': [ {'url':'stun:216.93.246.18:3478'}]});
         expect(pc is RtcPeerConnection, isTrue);
+        // TODO(efortuna): Uncomment this test when RTCPeerConnection correctly
+        // implements EventListener in Firefox (works correctly in nightly, so
+        // it's coming!).
+        //pc.onIceCandidate.listen((candidate) {});
       });
 
       test('ice candidate', () {
diff --git a/tests/html/shadow_dom_layout_test.dart b/tests/html/shadow_dom_layout_test.dart
deleted file mode 100644
index 82705bc..0000000
--- a/tests/html/shadow_dom_layout_test.dart
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library ShadowDOMTest;
-
-import 'dart:html';
-
-// Test that children of a shadow host get distributed properly to the
-// insertion points of a shadow subtree. Output should be three boxes,
-// ordered blue, red, green down the page.
-main() {
-  var div = new DivElement();
-  document.body.children.add(div);
-
-  // build some DOM elements
-  var bluebox = _colorBox('blue', 40, 20);
-  bluebox.classes.add('foo');
-  var redbox = _colorBox('red', 30, 30);
-  var greenbox = _colorBox('green', 60, 10);
-
-  // assemble DOM
-  var sRoot = div.createShadowRoot();
-  sRoot.append(new Element.html('<content select=".foo"></content>'));
-  sRoot.append(redbox);
-  sRoot.append(new Element.tag('content'));
-
-  div.append(bluebox);
-  div.append(greenbox);
-}
-
-DivElement _colorBox(String color, int width, int height) {
-  var style = ('background-color:$color; '
-      'width:${width}px; height:${height}px;');
-  return new Element.html('<div style="$style"></div>');
-}
diff --git a/tests/html/shadow_dom_layout_test.txt b/tests/html/shadow_dom_layout_test.txt
deleted file mode 100644
index 382a2f5..0000000
--- a/tests/html/shadow_dom_layout_test.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-Content-Type: text/plain
-layer at (0,0) size 800x600
-  RenderView at (0,0) size 800x600
-layer at (0,0) size 800x76
-  RenderBlock {HTML} at (0,0) size 800x76
-    RenderBody {BODY} at (8,8) size 784x60
-      RenderBlock {DIV} at (0,0) size 784x60
-        RenderBlock {DIV} at (0,0) size 40x20 [bgcolor=#0000FF]
-        RenderBlock {DIV} at (0,20) size 30x30 [bgcolor=#FF0000]
-        RenderBlock {DIV} at (0,50) size 60x10 [bgcolor=#008000]
-#EOF
diff --git a/tests/isolate/isolate.status b/tests/isolate/isolate.status
index e45b9ed..1937b48 100644
--- a/tests/isolate/isolate.status
+++ b/tests/isolate/isolate.status
@@ -11,8 +11,6 @@
 compute_this_script_browser_stream_test: Skip # browser specific test
 ports_compilation_browser_test: Skip # browser specific test
 unresolved_ports_negative_test: Skip # See Issue 6839
-global_error_handler_test: Fail, Pass # See Issue 9013.
-global_error_handler_stream_test: Fail # See Issue 9013.
 isolate_stress_test: Fail # TODO(ahe): This should be able to pass when we have wrapper-less tests.
 
 
@@ -47,6 +45,10 @@
 spawn_uri_vm_negative_test: fail
 unresolved_ports_negative_test: fail
 
+# test issue 10888
+global_error_handler_stream_test: fail, OK
+global_error_handler_test: fail, OK
+
 [ $compiler == dart2js && ($runtime == d8 || $jscl) ]
 illegal_msg_stream_test: Fail # Issue 6750
 typed_data_message_test: Fail, OK # DataView only supported in browsers.
@@ -127,9 +129,6 @@
 [ $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/field1_negative_test.dart b/tests/language/field1_negative_test.dart
index e10f754..a860b3d 100644
--- a/tests/language/field1_negative_test.dart
+++ b/tests/language/field1_negative_test.dart
@@ -4,7 +4,6 @@
 // Dart test to catch error reporting bugs in class fields declarations.
 // Should be an error because we have setter/getter functions and fields
 // in the class.
-// VMOptions=--compile_all
 
 class C {
   var a;
@@ -27,6 +26,7 @@
 
 class Field1NegativeTest {
   static testMain() {
+    var c = new C();
   }
 }
 
diff --git a/tests/language/field2_negative_test.dart b/tests/language/field2_negative_test.dart
index f37d307..26cb3c8 100644
--- a/tests/language/field2_negative_test.dart
+++ b/tests/language/field2_negative_test.dart
@@ -4,7 +4,6 @@
 // Dart test to catch error reporting bugs in class fields declarations.
 // Should be an error because we have setter/getter functions and fields
 // in the class.
-// VMOptions=--compile_all
 
 class C {
   get a {
@@ -27,6 +26,7 @@
 
 class Field2NegativeTest {
   static testMain() {
+    var c = new C();
   }
 }
 
diff --git a/tests/language/field4_negative_test.dart b/tests/language/field4_negative_test.dart
index 426fc0f..2f00c26 100644
--- a/tests/language/field4_negative_test.dart
+++ b/tests/language/field4_negative_test.dart
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 // Dart test to catch error reporting bugs in class fields declarations.
 // Should be an error because we have a field overriding a function name.
-// VMOptions=--compile_all
 
 class A {
   int a() {
@@ -14,6 +13,7 @@
 
 class Field4NegativeTest {
   static testMain() {
+    var a = new A();
   }
 }
 
diff --git a/tests/language/field5_negative_test.dart b/tests/language/field5_negative_test.dart
index 9e6da06..3ba641b 100644
--- a/tests/language/field5_negative_test.dart
+++ b/tests/language/field5_negative_test.dart
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 // Dart test to catch error reporting bugs in class fields declarations.
 // Should be an error because we have a function overriding a field name.
-// VMOptions=--compile_all
 
 class A {
   var a;
@@ -14,6 +13,7 @@
 
 class Field5NegativeTest {
   static testMain() {
+    var a = new A();
   }
 }
 
diff --git a/tests/language/field6_negative_test.dart b/tests/language/field6_negative_test.dart
index d841bbd..c9a9931 100644
--- a/tests/language/field6_negative_test.dart
+++ b/tests/language/field6_negative_test.dart
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 // Dart test to catch error reporting bugs in class fields declarations.
 // Should be an error because we have a getter overriding a function name.
-// VMOptions=--compile_all
 
 class A {
   int a() {
@@ -16,6 +15,7 @@
 
 class Field6NegativeTest {
   static testMain() {
+    var a = new A();
   }
 }
 
diff --git a/tests/language/field6a_negative_test.dart b/tests/language/field6a_negative_test.dart
index 8d8ac44..d2e540a 100644
--- a/tests/language/field6a_negative_test.dart
+++ b/tests/language/field6a_negative_test.dart
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 // Dart test to catch error reporting bugs in class fields declarations.
 // Should be an error because we have a function overriding a getter.
-// VMOptions=--compile_all
 
 class A {
   int get a {
@@ -16,6 +15,7 @@
 
 class Field6aNegativeTest {
   static testMain() {
+    var a = new A();
   }
 }
 
diff --git a/tests/language/field_inference_test.dart b/tests/language/field_inference_test.dart
new file mode 100644
index 0000000..5996610
--- /dev/null
+++ b/tests/language/field_inference_test.dart
@@ -0,0 +1,50 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Regression test for dart2js and its SsaConstructionFieldTypes
+// phase.
+
+import "package:expect/expect.dart";
+
+class A {
+  var _field;
+  final other;
+  get field => _field;
+  A(this._field) : other = null;
+  A.fromOther(this.other) {
+    _field = other.field;
+  }
+}
+
+class B {
+  var a;
+  B() {
+    try { // Defeat inlining.
+      // An inlined generative constructor call used to confuse
+      // dart2js.
+      a = new A(42);
+    } catch (e) {
+      rethrow;
+    }
+  }
+}
+
+var array = [new A(42), new B()];
+
+main() {
+  // Surround the call to [analyzeAfterB] by two [: new B() :] calls
+  // to ensure the [B] constructor will be analyzed first.
+  new B();
+  var a = analyzeAfterB();
+  new B();
+  Expect.equals(42, a._field);
+}
+
+analyzeAfterB() {
+  try { // Defeat inlining.
+    return new A.fromOther(array[0]);
+  } catch (e) {
+    rethrow;
+  }
+}
diff --git a/tests/language/for_in_side_effects_test.dart b/tests/language/for_in_side_effects_test.dart
new file mode 100644
index 0000000..385dc24
--- /dev/null
+++ b/tests/language/for_in_side_effects_test.dart
@@ -0,0 +1,29 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Regression test for dart2js that used to not see side effects of
+// iterator calls made in a "for in".
+
+import "package:expect/expect.dart";
+
+var global = 42;
+var array = [new A()];
+
+class A {
+  get iterator {
+    global = 54;
+    return this;
+  }
+  moveNext() => false;
+
+  bar(a) {
+    for (var a in this) {
+    }
+  }
+}
+
+main() {
+  array[0].bar(global);
+  Expect.equals(54, global);
+}
diff --git a/tests/language/for_inlining_test.dart b/tests/language/for_inlining_test.dart
new file mode 100644
index 0000000..6615c1e
--- /dev/null
+++ b/tests/language/for_inlining_test.dart
@@ -0,0 +1,20 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Regression test for dart2js that used to emit an invalid JS
+// variable declaration initializer in a for initializer.
+
+import "package:expect/expect.dart";
+
+var global;
+
+inlineMe() {
+  global = 42;
+  return 54;
+}
+
+main() {
+  for (var t = inlineMe(); t < 42; t++) {}
+  Expect.equals(42, global);
+}
diff --git a/tests/language/inline_in_for_initializer_and_bailout_test.dart b/tests/language/inline_in_for_initializer_and_bailout_test.dart
new file mode 100644
index 0000000..53689f5
--- /dev/null
+++ b/tests/language/inline_in_for_initializer_and_bailout_test.dart
@@ -0,0 +1,24 @@
+// 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 a = 42;
+
+inlineMe() {
+  // Add control flow to confuse the compiler.
+  if (a is int) {
+    print('a is int');
+  }
+  return a[0];
+}
+
+main() {
+  a = [42];
+  // Make [main] recursive to force a bailout version.
+  if (false) main();
+  int i = 0;
+  for (i = inlineMe(); i < 42; i++);
+  Expect.equals(42, i);
+}
diff --git a/tests/language/interface_static_method_negative_test.dart b/tests/language/interface_static_method_negative_test.dart
index ef1925e..5e8a83c 100644
--- a/tests/language/interface_static_method_negative_test.dart
+++ b/tests/language/interface_static_method_negative_test.dart
@@ -1,7 +1,6 @@
 // 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.
-// VMOptions=--compile_all
 
 abstract class A {
   static void foo();
@@ -10,6 +9,7 @@
 class InterfaceStaticMethodNegativeTest {
 
   static testMain() {
+    var a = new A();
   }
 }
 
diff --git a/tests/language/language.status b/tests/language/language.status
index b61389a..bd59fc9 100644
--- a/tests/language/language.status
+++ b/tests/language/language.status
@@ -34,7 +34,6 @@
 closure_type_variable_test: Fail # Type variable used as expression (dartbug.com/6282)
 built_in_identifier_prefix_test: Fail # http://dartbug.com/6970
 library_juxtaposition_test: Fail # Issue 6877
-gc_test: Pass, Fail # Issue 1487
 pseudo_kw_illegal_test/14: Fail  # Issue 356
 method_override2_test/00: Fail # Issue 7076.
 method_override2_test/02: Fail # Issue 7076.
@@ -87,12 +86,6 @@
 execute_finally10_test: Fail # Issue 430
 execute_finally11_test: Fail # Issue 430
 
-[ $compiler == none && ($system == macos || $system == linux) && $arch == ia32 && $checked ]
-gc_test: Skip  # Issue 1487, flaky.
-
-[ $compiler == none && $mode == debug ]
-gc_test: Skip  # Takes too long.
-
 [ $compiler == none && $unchecked ]
 
 # Only checked mode reports an error on type assignment
@@ -311,15 +304,6 @@
 final_variable_assignment_test/02: Fail
 final_variable_assignment_test/03: Fail
 final_variable_assignment_test/04: Fail
-gc_test: Skip # Issue 1487
-field5_negative_test: Fail # Issue 10839
-field4_negative_test: Fail # Issue 10839
-field6_negative_test: Fail # Issue 10839
-non_const_super_negative_test: Fail # Issue 10839
-field2_negative_test: Fail # Issue 10839
-interface_static_method_negative_test: Fail # Issue 10839
-field1_negative_test: Fail # Issue 10839
-field6a_negative_test: Fail # Issue 10839
 
 
 [ $runtime == dartium ]
@@ -344,17 +328,12 @@
 
 [ $compiler == dart2dart ]
 built_in_identifier_prefix_test: Fail # Inherited from dart2js.
-const_factory_redirection_test: Fail # http://dartbug.com/6894
-compile_time_constant_h_test: Fail
 constructor_redirect2_test/03: Fail
 constructor_initializer_test: Fail # VM issue
-factory_implementation_test/none: Fail
-factory_implementation_test/00:Fail
 factory2_test: Fail
 factory3_test: Fail
 factory5_test/none: Fail
 factory5_test/00: Fail
-factory_implementation_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
@@ -438,8 +417,6 @@
 const_var_test: Pass, Fail # Map literals take 2 type arguments.
 map_literal3_test: Fail # Map literals take 2 type arguments.
 class_cycle_negative_test: Fail, OK # Bad test: assumes eager loading.
-field1_negative_test: Fail, OK # Bad test: assumes eager loading.
-field6_negative_test: Fail, OK # Bad test: assumes eager loading.
 interface_cycle_negative_test: Fail, OK # Bad test: assumes eager loading.
 # Common problems with dart2js.  In illegal family, invalid
 # declarations are simply not parsed.  In pseudo kw dart2js
@@ -456,13 +433,7 @@
 duplicate_implements_test/02: Fail
 duplicate_implements_test/03: Fail
 duplicate_implements_test/04: Fail
-field2_negative_test: Fail
-field4_negative_test: Fail
-field5_negative_test: Fail
-field6a_negative_test: Fail
 interface_factory_constructor_negative_test: Fail
-interface_static_method_negative_test: Fail
-non_const_super_negative_test: Fail
 method_override2_test/00: Fail
 method_override2_test/02: Fail
 method_override2_test/03: Fail
@@ -485,7 +456,6 @@
 function_type_alias5_test/01: Fail
 function_type_alias5_test/02: Fail
 function_type_alias7_test/00: Fail
-implicit_scope_test: Fail
 instanceof3_test: Fail
 parameter_initializer6_negative_test: Fail # Issue 3502
 syntax_test/47: Fail
@@ -493,7 +463,6 @@
 constructor5_test: Fail
 constructor6_test: Fail
 closure_in_initializer_test: Fail
-gc_test: Pass,Fail
 super_first_constructor_test: Fail
 # VM specific tests.
 disable_privacy_test: Pass, Fail, Ok
@@ -592,23 +561,6 @@
 class_cycle_test/00: fail
 class_cycle_test/01: fail
 class_cycle_test/03: fail
-class_literal_test/02: fail
-class_literal_test/05: fail
-class_literal_test/07: fail
-class_literal_test/10: fail
-class_literal_test/11: fail
-class_literal_test/12: fail
-class_literal_test/14: fail
-class_literal_test/17: fail
-class_literal_test/18: fail
-class_literal_test/19: fail
-class_literal_test/22: fail
-class_literal_test/23: fail
-class_literal_test/24: fail
-class_literal_test/27: fail
-class_literal_test/28: fail
-class_literal_test/29: fail
-class_literal_test/none: fail
 closure_call_wrong_argument_count_negative_test: fail
 compile_time_constant10_test/none: fail
 compile_time_constant8_test: fail
@@ -620,17 +572,13 @@
 compile_time_constant_b_test: fail
 compile_time_constant_c_test/01: fail
 compile_time_constant_c_test/02: fail
-compile_time_constant_checked2_test/01: fail
 compile_time_constant_checked2_test/02: fail
 compile_time_constant_checked2_test/03: fail
 compile_time_constant_checked2_test/04: fail
-compile_time_constant_checked2_test/05: fail
 compile_time_constant_checked2_test/06: fail
-compile_time_constant_checked3_test/01: fail
 compile_time_constant_checked3_test/02: fail
 compile_time_constant_checked3_test/03: fail
 compile_time_constant_checked3_test/04: fail
-compile_time_constant_checked3_test/05: fail
 compile_time_constant_checked3_test/06: fail
 compile_time_constant_d_test: fail
 compile_time_constant_e_test: fail
@@ -778,11 +726,6 @@
 syntax_test/33: fail
 ternary_test: fail
 throw7_negative_test: fail
-try_catch_on_syntax_test/01: fail
-try_catch_on_syntax_test/07: fail
-try_catch_syntax_test/08: fail
-try_catch_syntax_test/16: fail
-try_catch_syntax_test/17: fail
 type_error_test: fail
 type_parameter_test/01: fail
 type_parameter_test/02: fail
@@ -812,14 +755,67 @@
 unresolved_top_level_var_negative_test: fail
 
 # test issue 10683, It is a compile-time error if e refers to the name v or the name v=.
-block_scope_test: fail
-lazy_static3_test: fail
+block_scope_test: fail, OK
+lazy_static3_test: fail, OK
 
 # test issue 10752, there are 'implicit' scopes for 'if', 'while' and 'do-while'
 implicit_scope_test: fail, OK
 
-[ $arch == arm ]
-*: Skip
+# test issue 10889, "throw" requires expression, "rethrow" should be used instead
+execute_finally10_test: fail, OK
+execute_finally11_test: fail, OK
+final_used_in_try_test: fail, OK
+full_stacktrace2_test: fail, OK
+stack_trace_test: fail, OK
+throw3_test: fail, OK
+try_catch3_test: fail, OK
+
+# test issue 10890; on-catch UnknownType is a static warning, not error
+try_catch_on_syntax_test/01: fail, OK
+try_catch_on_syntax_test/07: fail, OK
+try_catch_syntax_test/08: fail, OK
+
+# test issue 10899; it is static warning, not error, to call methods of class literal
+class_literal_test/02: fail, OK
+class_literal_test/05: fail, OK
+class_literal_test/07: fail, OK
+class_literal_test/10: fail, OK
+class_literal_test/11: fail, OK
+class_literal_test/12: fail, OK
+class_literal_test/14: fail, OK
+class_literal_test/17: fail, OK
+class_literal_test/18: fail, OK
+class_literal_test/19: fail, OK
+class_literal_test/22: fail, OK
+class_literal_test/23: fail, OK
+class_literal_test/24: fail, OK
+class_literal_test/27: fail, OK
+class_literal_test/28: fail, OK
+class_literal_test/29: fail, OK
+class_literal_test/none: fail, OK
+
+[ $compiler == dartanalyzer && $checked ]
+factory1_test/00: fail
+factory1_test/01: fail
+field_type_check2_test/01: fail
+factory_implementation_test/00: fail
+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
+getters_setters2_test/03: fail
+type_variable_bounds3_test/00: fail
+type_variable_bounds2_test/05: fail
+type_variable_scope_test/00: fail
+type_variable_scope_test/01: fail
+type_variable_scope_test/02: fail
+type_variable_scope_test/03: fail
+type_variable_scope_test/04: fail
+type_variable_scope_test/05: fail
+
 
 [ $arch == simarm ]
 *: Skip
diff --git a/tests/language/language_dart2js.status b/tests/language/language_dart2js.status
index 541b3c9..0b6a3c9 100644
--- a/tests/language/language_dart2js.status
+++ b/tests/language/language_dart2js.status
@@ -174,7 +174,6 @@
 get_set_syntax_test/14: Fail # Fixed by https://chromiumcodereview.appspot.com/10915111
 get_set_syntax_test/15: Fail # Fixed by https://chromiumcodereview.appspot.com/10915111
 get_set_syntax_test/16: Fail # Fixed by https://chromiumcodereview.appspot.com/10915111
-implicit_scope_test: Fail # duplicate definition of a="bar"
 method_binding_test: Fail # internal error: super property read not implemented.
 method_override_test: Fail # cannot resolve type GetKeysFunctionType
 method_override2_test/00: Fail # accepts illegal override
@@ -227,8 +226,6 @@
 
 class_cycle_negative_test: Fail, OK # Bad test: assumes eager loading.
 external_test/16: Fail, OK # Bad test: assumes eager loading.
-field1_negative_test: Fail, OK # Bad test: assumes eager loading.
-field6_negative_test: Fail, OK # Bad test: assumes eager loading.
 interface_cycle_negative_test: Fail, OK # Bad test: assumes eager loading.
 syntax_test/47: Fail, OK # Bad test: assumes eager loading.
 
@@ -253,21 +250,15 @@
 duplicate_implements_test/02: Fail # Negative language test.
 duplicate_implements_test/03: Fail # Negative language test.
 duplicate_implements_test/04: Fail # Negative language test.
-field2_negative_test: Fail # Negative language test.
 field3_negative_test: Fail # Negative language test.
-field4_negative_test: Fail # Negative language test.
-field5_negative_test: Fail # Negative language test.
-field6a_negative_test: Fail # Negative language test.
 final_for_in_variable_test/01: Fail # Negative language test
 instantiate_type_variable_negative_test: Pass  # For the wrong reason.
 interface_factory3_negative_test: Fail # Negative language test.
 interface_factory_constructor_negative_test: Fail # Negative language test.
-interface_static_method_negative_test: Fail # Negative language test.
 list_literal1_negative_test: Fail # Negative language test.
 list_literal2_negative_test: Fail # Negative language test.
 map_literal1_negative_test: Fail # Negative language test.
 map_literal2_negative_test: Fail # Negative language test.
-non_const_super_negative_test: Fail # Negative language test.
 number_identifier_negative_test: Fail # Negative language test.
 operator1_negative_test: Fail # Negative language test.
 prefix23_negative_test: Fail # Negative language test.
diff --git a/tests/language/non_const_super_negative_test.dart b/tests/language/non_const_super_negative_test.dart
index 17f3d5a..32742e2 100644
--- a/tests/language/non_const_super_negative_test.dart
+++ b/tests/language/non_const_super_negative_test.dart
@@ -2,7 +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.
 // Check fails because const class extends from non const class.
-// VMOptions=--compile_all
 
 class Base {
   Base() {}
@@ -15,6 +14,7 @@
 
 class NonConstSuperNegativeTest {
   static testMain() {
+    var a = new Sub();
   }
 }
 
diff --git a/tests/language/super_abstract_method_test.dart b/tests/language/super_abstract_method_test.dart
new file mode 100644
index 0000000..fbb3648
--- /dev/null
+++ b/tests/language/super_abstract_method_test.dart
@@ -0,0 +1,25 @@
+// 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 that a method overridden by an abstract method is called at
+// runtime.
+
+import "package:expect/expect.dart";
+
+class Base {
+  foo() => 42;
+}
+
+abstract class A extends Base {
+  foo();
+}
+
+class B extends A {
+  testSuperCall() => super.foo();
+}
+
+main() {
+  Expect.equals(42, new B().foo());
+  Expect.equals(42, new B().testSuperCall());
+}
diff --git a/tests/lib/analyzer/analyze_tests.status b/tests/lib/analyzer/analyze_tests.status
index 949fd4f..90d7b8b 100644
--- a/tests/lib/analyzer/analyze_tests.status
+++ b/tests/lib/analyzer/analyze_tests.status
@@ -21,8 +21,8 @@
 standalone/io/raw_secure_server_socket_argument_test: Fail
 
 # Test runner does not use the latest VM.
-standalone/io/test_runner_test: Fail
-standalone/io/skipping_dart2js_compilations_test: Fail
+standalone/io/test_runner_test: Skip
+standalone/io/skipping_dart2js_compilations_test: Skip
 
 # Implicit downcast.
 standalone/typed_data_view_test: Fail
diff --git a/tests/lib/async/run_async6_test.dart b/tests/lib/async/run_async6_test.dart
new file mode 100644
index 0000000..e89bc03
--- /dev/null
+++ b/tests/lib/async/run_async6_test.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library run_async_test;
+
+import 'dart:async';
+import '../../../pkg/unittest/lib/unittest.dart';
+
+bool _unhandledExceptionCallback(exception) => true;
+
+main() {
+  test('run async test', () {
+    var callback = expectAsync0(() {});
+    runAsync(() {
+      runAsync(() {
+        callback();
+      });
+      throw new Exception('exception');
+    });
+  });
+}
diff --git a/tests/lib/async/stream_controller_async_test.dart b/tests/lib/async/stream_controller_async_test.dart
index e2aab21..65e658f 100644
--- a/tests/lib/async/stream_controller_async_test.dart
+++ b/tests/lib/async/stream_controller_async_test.dart
@@ -53,28 +53,6 @@
     c.add(42);
   });
 
-  test("Single-subscription StreamController subscription changes", () {
-    StreamController c = new StreamController();
-    EventSink sink = c.sink;
-    Stream stream = c.stream;
-    int counter = 0;
-    var subscription;
-    subscription = stream.listen((data) {
-      counter += data;
-      Expect.throws(() => stream.listen(null), (e) => e is StateError);
-      subscription.cancel();
-      stream.listen((data) {
-        counter += data * 10;
-      },
-      onDone: expectAsync0(() {
-        Expect.equals(1 + 20, counter);
-      }));
-    });
-    sink.add(1);
-    sink.add(2);
-    sink.close();
-  });
-
   test("Single-subscription StreamController events are buffered when"
        " there is no subscriber",
        () {
@@ -93,33 +71,6 @@
         Expect.equals(3, counter);
       }));
   });
-
-  // Test subscription changes while firing.
-  test("Single-subscription StreamController subscription changes while firing",
-       () {
-    StreamController c = new StreamController();
-    EventSink sink = c.sink;
-    Stream stream = c.stream;
-    int counter = 0;
-    var subscription = stream.listen(null);
-    subscription.onData(expectAsync1((data) {
-      counter += data;
-      subscription.cancel();
-      stream.listen((data) {
-        counter += 10 * data;
-      },
-      onDone: expectAsync0(() {
-        Expect.equals(1 + 20 + 30 + 40 + 50, counter);
-      }));
-      Expect.throws(() => stream.listen(null), (e) => e is StateError);
-    }));
-    sink.add(1); // seen by stream 1
-    sink.add(2); // seen by stream 10 and 100
-    sink.add(3); // -"-
-    sink.add(4); // -"-
-    sink.add(5); // seen by stream 10
-    sink.close();
-  });
 }
 
 testExtraMethods() {
@@ -478,10 +429,85 @@
   testFuture("drain", (s, act) => s.drain().then(act));
 }
 
+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();
+  });
+
+  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();
+  });
+
+  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();
+  });
+
+  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();
+  });
+
+  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);
+      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.
+  });
+}
+
 main() {
   testController();
   testSingleController();
   testExtraMethods();
   testPause();
   testRethrow();
+  testBroadcastController();
 }
diff --git a/tests/lib/async/stream_periodic4_test.dart b/tests/lib/async/stream_periodic4_test.dart
index 5b6eda3..779947b 100644
--- a/tests/lib/async/stream_periodic4_test.dart
+++ b/tests/lib/async/stream_periodic4_test.dart
@@ -8,13 +8,7 @@
 import "dart:async";
 import '../../../pkg/unittest/lib/unittest.dart';
 
-int iteration = 0;
-
 void runTest(period, maxElapsed, pauseDuration) {
-  print("Iteration: $iteration");
-  var myIteration = iteration;
-  iteration++;
-
   Function done = expectAsync0(() { });
 
   Stopwatch watch = new Stopwatch()..start();
@@ -29,10 +23,8 @@
         expect(true, false);
       } else {
         subscription.cancel();
-        print("Cancelling subscription of iteration: $myIteration");
         // Call 'done' ourself, since it won't be invoked in the onDone handler.
         runTest(period * 2, maxElapsed * 2, pauseDuration * 2);
-        print("Invoking done of iteration inside listener: $myIteration");
         done();
         return;
       }
@@ -46,10 +38,7 @@
         subscription.resume();
       });
     }
-  }, onDone: () {
-    print("Invoking done of iteration: $myIteration");
-    done();
-  });
+  }, onDone: done);
 }
 
 main() {
diff --git a/tests/lib/async/stream_state_helper.dart b/tests/lib/async/stream_state_helper.dart
index dbc645a..c433e39 100644
--- a/tests/lib/async/stream_state_helper.dart
+++ b/tests/lib/async/stream_state_helper.dart
@@ -9,6 +9,7 @@
 import "dart:collection";
 
 class StreamProtocolTest {
+  bool trace = false;
   StreamController _controller;
   Stream _controllerStream;
   StreamSubscription _subscription;
@@ -20,9 +21,8 @@
     _controller = new StreamController(
           onListen: _onSubcription,
           onPause: _onPause,
-          onResume: _onPause,
-          onCancel: _onSubcription);
-    // TODO(lrn): Make it work with multiple subscribers too.
+          onResume: _onResume,
+          onCancel: _onCancel);
     if (broadcast) {
       _controllerStream = _controller.stream.asBroadcastStream();
     } else {
@@ -54,7 +54,7 @@
     _subscription.pause(resumeSignal);
   }
 
-  void resume([Future resumeSignal]) {
+  void resume() {
     if (_subscription == null) throw new StateError("Not subscribed");
     _subscription.resume();
   }
@@ -67,6 +67,7 @@
 
   // Handling of stream events.
   void _onData(var data) {
+    if (trace) print("[Data : $data]");
     _withNextExpectation((Event expect) {
       if (!expect.matchData(data)) {
         _fail("Expected: $expect\n"
@@ -76,15 +77,17 @@
   }
 
   void _onError(error) {
+    if (trace) print("[Error : $error]");
     _withNextExpectation((Event expect) {
       if (!expect.matchError(error)) {
         _fail("Expected: $expect\n"
-              "Found   : [Data: ${error}]");
+              "Found   : [Error: ${error}]");
       }
     });
   }
 
   void _onDone() {
+    if (trace) print("[Done]");
     _subscription = null;
     _withNextExpectation((Event expect) {
       if (!expect.matchDone()) {
@@ -95,20 +98,41 @@
   }
 
   void _onPause() {
+    if (trace) print("[Pause]");
     _withNextExpectation((Event expect) {
-      if (!expect.matchPauseChange(_controller)) {
+      if (!expect.matchPause()) {
         _fail("Expected: $expect\n"
-              "Found   : [Paused:${_controller.isPaused}]");
+              "Found   : [Paused]");
+      }
+    });
+  }
+
+  void _onResume() {
+    if (trace) print("[Resumed]");
+    _withNextExpectation((Event expect) {
+      if (!expect.matchResume()) {
+        _fail("Expected: $expect\n"
+              "Found   : [Resumed]");
       }
     });
   }
 
   void _onSubcription() {
+    if (trace) print("[Subscribed]");
     _withNextExpectation((Event expect) {
-      if (!expect.matchSubscriptionChange(_controller)) {
+      if (!expect.matchSubscribe()) {
         _fail("Expected: $expect\n"
-              "Found: [Has listener:${_controller.hasListener}, "
-                      "Paused:${_controller.isPaused}]");
+              "Found: [Subscribed]");
+      }
+    });
+  }
+
+  void _onCancel() {
+    if (trace) print("[Cancelled]");
+    _withNextExpectation((Event expect) {
+      if (!expect.matchCancel()) {
+        _fail("Expected: $expect\n"
+              "Found: [Cancelled]");
       }
     });
   }
@@ -117,9 +141,10 @@
     if (_nextExpectationIndex == _expectations.length) {
       action(new MismatchEvent());
     } else {
-      Event next = _expectations[_nextExpectationIndex++];
+      Event next = _expectations[_nextExpectationIndex];
       action(next);
     }
+    _nextExpectationIndex++;
     _checkDone();
   }
 
@@ -155,18 +180,31 @@
     }
     _expectations.add(new DoneEvent(action));
   }
-  void expectPause(bool isPaused, [void action()]) {
+  void expectPause([void action()]) {
     if (_onComplete == null) {
       _fail("Adding expectation after completing");
     }
-    _expectations.add(new PauseCallbackEvent(isPaused, action));
+    _expectations.add(new PauseCallbackEvent(action));
   }
-  void expectSubscription(bool hasListener, bool isPaused, [void action()]) {
+  void expectResume([void action()]) {
+    if (_onComplete == null) {
+      _fail("Adding expectation after completing");
+    }
+    _expectations.add(new ResumeCallbackEvent(action));
+  }
+  void expectSubscription([void action()]) {
     if (_onComplete == null) {
       _fail("Adding expectation after completing");
     }
     _expectations.add(
-          new SubscriptionCallbackEvent(hasListener, isPaused, action));
+          new SubscriptionCallbackEvent(action));
+  }
+  void expectCancel([void action()]) {
+    if (_onComplete == null) {
+      _fail("Adding expectation after completing");
+    }
+    _expectations.add(
+          new CancelCallbackEvent(action));
   }
 
   void _fail(String message) {
@@ -178,11 +216,6 @@
   }
 }
 
-class EventCollector {
-  final Queue<Event> events = new Queue<Event>();
-
-}
-
 class Event {
   Function _action;
   Event(void this._action());
@@ -202,13 +235,23 @@
     if (_action != null) _action();
     return true;
   }
-  bool matchPauseChange(StreamController c) {
-    if (!_testPause(c)) return false;
+  bool matchPause() {
+    if (!_testPause()) return false;
     if (_action != null) _action();
     return true;
   }
-  bool matchSubscriptionChange(StreamController c) {
-    if (!_testSubscribe(c)) return false;
+  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();
     return true;
   }
@@ -216,8 +259,10 @@
   bool _testData(_) => false;
   bool _testError(_) => false;
   bool _testDone() => false;
-  bool _testPause(_) => false;
-  bool _testSubscribe(_) => false;
+  bool _testPause() => false;
+  bool _testResume() => false;
+  bool _testSubscribe() => false;
+  bool _testCancel() => false;
 }
 
 class MismatchEvent extends Event {
@@ -246,22 +291,27 @@
 }
 
 class PauseCallbackEvent extends Event {
-  final bool isPaused;
-  PauseCallbackEvent(this.isPaused, void action())
-      : super(action);
-  bool _testPause(StreamController c) => isPaused == c.isPaused;
-  String toString() => "[Paused:$isPaused]";
+  PauseCallbackEvent(void action()) : super(action);
+  bool _testPause() => true;
+  String toString() => "[Paused]";
+}
+
+class ResumeCallbackEvent extends Event {
+  ResumeCallbackEvent(void action()) : super(action);
+  bool _testResume() => true;
+  String toString() => "[Resumed]";
 }
 
 class SubscriptionCallbackEvent extends Event {
-  final bool hasListener;
-  final bool isPaused;
-  SubscriptionCallbackEvent(this.hasListener, this.isPaused, void action())
-      : super(action);
-  bool _testSubscribe(StreamController c) {
-    return hasListener == c.hasListener && isPaused == c.isPaused;
-  }
-  String toString() => "[Has listener:$hasListener, Paused:$isPaused]";
+  SubscriptionCallbackEvent(void action()) : super(action);
+  bool _testSubscribe() => true;
+  String toString() => "[Subscribed]";
+}
+
+class CancelCallbackEvent extends Event {
+  CancelCallbackEvent(void action()) : super(action);
+  bool _testCancel() => true;
+  String toString() => "[Cancelled]";
 }
 
 
@@ -280,12 +330,20 @@
     _actual = "*[Done]";
     return true;
   }
-  bool _testPause(StreamController c) {
-    _actual = "*[Paused:${c.isPaused}]";
+  bool _testPause() {
+    _actual = "*[Paused]";
     return true;
   }
-  bool _testSubcribe(StreamController c) {
-    _actual = "*[Has listener:${c.hasListener}, Paused:${c.isPaused}]";
+  bool _testResume() {
+    _actual = "*[Resumed]";
+    return true;
+  }
+  bool _testSubcribe() {
+    _actual = "*[Subscribed]";
+    return true;
+  }
+  bool _testCancel() {
+    _actual = "*[Cancelled]";
     return true;
   }
 
diff --git a/tests/lib/async/stream_state_nonzero_timer_test.dart b/tests/lib/async/stream_state_nonzero_timer_test.dart
index 868f760..0beff6f 100644
--- a/tests/lib/async/stream_state_nonzero_timer_test.dart
+++ b/tests/lib/async/stream_state_nonzero_timer_test.dart
@@ -24,28 +24,28 @@
 
   test("$p-sub-data/pause/resume/pause/resume-done", () {
     var t = new StreamProtocolTest(broadcast);
-    t..expectSubscription(true, false)
+    t..expectSubscription()
      ..expectData(42, () {
          t.pause();
        })
-     ..expectPause(true, () { t.resume(); })
-     ..expectPause(false, () { t.pause(); })
-     ..expectPause(true, () { t.resume(); })
-     ..expectPause(false, () { t.close(); })
+     ..expectPause(() { t.resume(); })
+     ..expectResume(() { t.pause(); })
+     ..expectPause(() { t.resume(); })
+     ..expectResume(() { t.close(); })
      ..expectDone()
-     ..expectSubscription(false, false);
+     ..expectCancel();
     t..subscribe()..add(42);
   });
 
   test("$p-sub-data/pause-done", () {
     var t = new StreamProtocolTest(broadcast);
-    t..expectSubscription(true, false)
+    t..expectSubscription()
      ..expectData(42, () {
          t.pause(new Future.delayed(ms5, () => null));
        })
-     ..expectPause(true)
+     ..expectPause()
      ..expectDone()
-     ..expectSubscription(false, false);
+     ..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();
@@ -53,20 +53,20 @@
 
   test("$p-sub-data/pause-resume/done", () {
     var t = new StreamProtocolTest(broadcast);
-    t..expectSubscription(true, false)
+    t..expectSubscription()
      ..expectData(42, () {
          t.pause(new Future.delayed(ms5, () => null));
        })
-     ..expectPause(true)
-     ..expectPause(false, () { t.close(); })
+     ..expectPause()
+     ..expectResume(t.close)
      ..expectDone()
-     ..expectSubscription(false, false);
+     ..expectCancel();
     t..subscribe()..add(42);
   });
 
   test("$p-sub-data/data+pause-data-resume-done", () {
     var t = new StreamProtocolTest(broadcast);
-    t..expectSubscription(true, false)
+    t..expectSubscription()
      ..expectData(42, () {
          t.add(43);
          t.pause(new Future.delayed(ms5, () => null));
@@ -74,30 +74,30 @@
          // After that, the controller stays paused until the pending queue
          // is empty.
        })
-     ..expectPause(true)
+     ..expectPause()
      ..expectData(43)
-     ..expectPause(false, () { t.close(); })
+     ..expectResume(t.close)
      ..expectDone()
-     ..expectSubscription(false, false);
+     ..expectCancel();
     t..subscribe()..add(42);
   });
-
+return;
   test("$p-pause-during-callback", () {
     var t = new StreamProtocolTest(broadcast);
-    t..expectSubscription(true, false)
+    t..expectSubscription()
      ..expectData(42, () {
        t.pause();
      })
-     ..expectPause(true, () {
+     ..expectPause(() {
        t.resume();
      })
-     ..expectPause(false, () {
+     ..expectResume(() {
        t.pause();
        t.resume();
        t.close();
      })
      ..expectDone()
-     ..expectSubscription(false, false);
+     ..expectCancel();
     t..subscribe()
      ..add(42);
   });
diff --git a/tests/lib/async/stream_state_test.dart b/tests/lib/async/stream_state_test.dart
index d6d873f..08cb7a1 100644
--- a/tests/lib/async/stream_state_test.dart
+++ b/tests/lib/async/stream_state_test.dart
@@ -20,10 +20,10 @@
   var p = broadcast ? "BC" : "SC";
   test("$p-sub-data-done", () {
     var t = new StreamProtocolTest(broadcast);
-    t..expectSubscription(true, false)
+    t..expectSubscription()
      ..expectData(42)
      ..expectDone()
-     ..expectSubscription(false, false);
+     ..expectCancel();
     t..subscribe()..add(42)..close();
   });
 
@@ -32,33 +32,33 @@
     if (broadcast) {
       t..expectDone();
     } else {
-      t..expectSubscription(true, false)
+      t..expectSubscription()
        ..expectData(42)
        ..expectDone()
-       ..expectSubscription(false, false);
+       ..expectCancel();
     }
     t..add(42)..close()..subscribe();
   });
 
   test("$p-sub-data/pause+resume-done", () {
     var t = new StreamProtocolTest(broadcast);
-    t..expectSubscription(true, false)
+    t..expectSubscription()
      ..expectData(42, () {
          t.pause();
          t.resume();
          t.close();
        })
      ..expectDone()
-     ..expectSubscription(false, false);
+     ..expectCancel();
     t..subscribe()..add(42);
   });
 
   test("$p-sub-data-unsubonerror", () {
     var t = new StreamProtocolTest(broadcast);
-    t..expectSubscription(true, false)
+    t..expectSubscription()
      ..expectData(42)
      ..expectError("bad")
-     ..expectSubscription(false, !broadcast);
+     ..expectCancel();
     t..subscribe(cancelOnError: true)
      ..add(42)
      ..error("bad")
@@ -68,12 +68,12 @@
 
   test("$p-sub-data-no-unsubonerror", () {
     var t = new StreamProtocolTest(broadcast);
-    t..expectSubscription(true, false)
+    t..expectSubscription()
      ..expectData(42)
      ..expectError("bad")
      ..expectData(43)
      ..expectDone()
-     ..expectSubscription(false, false);
+     ..expectCancel();
     t..subscribe(cancelOnError: false)
      ..add(42)
      ..error("bad")
@@ -83,62 +83,15 @@
 
   test("$p-pause-resume-during-event", () {
     var t = new StreamProtocolTest(broadcast);
-    t..expectSubscription(true, false)
+    t..expectSubscription()
      ..expectData(42, () {
        t.pause();
        t.resume();
      })
      ..expectDone()
-     ..expectSubscription(false, false);
+     ..expectCancel();
     t..subscribe()
      ..add(42)
      ..close();
   });
-
-  test("$p-cancel-sub-during-event", () {
-    var t = new StreamProtocolTest(broadcast);
-    t..expectSubscription(true, false)
-     ..expectData(42, () {
-       t.cancel();
-       t.subscribe();
-     })
-     ..expectData(43)
-     ..expectDone()
-     ..expectSubscription(false, false);
-    t..subscribe()
-     ..add(42)
-     ..add(43)
-     ..close();
-  });
-
-  test("$p-cancel-sub-during-callback", () {
-    var t = new StreamProtocolTest(broadcast);
-    t..expectSubscription(true, false)
-     ..expectData(42, () {
-       t.pause();
-     })
-     ..expectPause(true, () {
-       t.cancel();  // Cancels pause
-       t.subscribe();
-     })
-     ..expectPause(false)
-     ..expectData(43)
-     ..expectDone()
-     ..expectSubscription(false, false);
-    t..subscribe()
-     ..add(42)
-     ..add(43)
-     ..close();
-  });
-
-  test("$p-sub-after-done-is-done", () {
-    var t = new StreamProtocolTest(broadcast);
-    t..expectSubscription(true, false)
-     ..expectDone()
-     ..expectSubscription(false, false)
-     ..expectDone();
-    t..subscribe()
-     ..close()
-     ..subscribe();  // Subscribe after done does not cause callbacks at all.
-  });
 }
diff --git a/tests/lib/crypto/base64_test.dart b/tests/lib/crypto/base64_test.dart
index 663e067..efc438e 100644
--- a/tests/lib/crypto/base64_test.dart
+++ b/tests/lib/crypto/base64_test.dart
@@ -6,7 +6,7 @@
 library base64_test;
 
 import "package:expect/expect.dart";
-import 'dart:crypto';
+import "package:crypto/crypto.dart";
 import 'dart:math';
 
 // Data from http://tools.ietf.org/html/rfc4648.
diff --git a/tests/lib/crypto/hmac_md5_test.dart b/tests/lib/crypto/hmac_md5_test.dart
index 8f9e768..2d717b9 100644
--- a/tests/lib/crypto/hmac_md5_test.dart
+++ b/tests/lib/crypto/hmac_md5_test.dart
@@ -6,7 +6,7 @@
 library hmac_md5_test;
 
 import "package:expect/expect.dart";
-import 'dart:crypto';
+import "package:crypto/crypto.dart";
 
 // Data from http://tools.ietf.org/html/rfc2202.
 var hmac_md5_inputs =
diff --git a/tests/lib/crypto/hmac_sha1_test.dart b/tests/lib/crypto/hmac_sha1_test.dart
index 12e0c00..de79470 100644
--- a/tests/lib/crypto/hmac_sha1_test.dart
+++ b/tests/lib/crypto/hmac_sha1_test.dart
@@ -6,7 +6,7 @@
 library hmac_sha1_test;
 
 import "package:expect/expect.dart";
-import 'dart:crypto';
+import "package:crypto/crypto.dart";
 
 part 'hmac_sha1_test_vectors.dart';
 
diff --git a/tests/lib/crypto/hmac_sha256_test.dart b/tests/lib/crypto/hmac_sha256_test.dart
index 1d52efd..73fa561 100644
--- a/tests/lib/crypto/hmac_sha256_test.dart
+++ b/tests/lib/crypto/hmac_sha256_test.dart
@@ -6,7 +6,7 @@
 library hmac_sha256_test;
 
 import "package:expect/expect.dart";
-import 'dart:crypto';
+import "package:crypto/crypto.dart";
 
 part 'hmac_sha256_test_vectors.dart';
 
diff --git a/tests/lib/crypto/sha1_test.dart b/tests/lib/crypto/sha1_test.dart
index 1254dc8..24a7271 100644
--- a/tests/lib/crypto/sha1_test.dart
+++ b/tests/lib/crypto/sha1_test.dart
@@ -6,7 +6,7 @@
 library sha1_test;
 
 import "package:expect/expect.dart";
-import 'dart:crypto';
+import "package:crypto/crypto.dart";
 
 part 'sha1_long_test_vectors.dart';
 part 'sha1_short_test_vectors.dart';
diff --git a/tests/lib/crypto/sha256_test.dart b/tests/lib/crypto/sha256_test.dart
index f42a3f2..528c831 100644
--- a/tests/lib/crypto/sha256_test.dart
+++ b/tests/lib/crypto/sha256_test.dart
@@ -6,7 +6,7 @@
 library sha256_test;
 
 import "package:expect/expect.dart";
-import 'dart:crypto';
+import "package:crypto/crypto.dart";
 
 part 'sha256_long_test_vectors.dart';
 part 'sha256_short_test_vectors.dart';
diff --git a/tests/lib/lib.status b/tests/lib/lib.status
index 097a374..f905060 100644
--- a/tests/lib/lib.status
+++ b/tests/lib/lib.status
@@ -2,8 +2,6 @@
 # for details. All rights reserved. Use of this source code is governed by a
 # BSD-style license that can be found in the LICENSE file.
 
-async/stream_periodic4_test: Fail, Pass # floitsch: Marking as flaky while collection debug information. http://dartbug.com/9619
-
 # The typed_data library is not supported by dart2js or dart2dart yet.
 [ $compiler == dart2js  || $compiler == dart2dart ]
 typed_data/*: Fail
@@ -18,9 +16,15 @@
 math/*: Skip
 mirrors/mirrors_test: Fail # TODO(ahe): I'm working on fixing this.
 mirrors/library_uri_io_test: Skip # Not intended for dart2js as it uses dart:io.
-mirrors/library_uri_package_test: Fail # dart:mirrors not fully implemented.
 async/run_async3_test: Fail # _enqueueImmediate runs after Timer. http://dartbug.com/9002
 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
+
+[ $compiler == dart2js && $minified ]
+mirrors/mirrors_resolve_fields_test: Fail # Issue 6490
+
+[ $csp ]
+mirrors/library_uri_package_test: Fail, Pass # Issue 6490
 
 [ $compiler == dart2js && $checked ]
 async/stream_event_transform_test: Fail # Issue 7733.
@@ -84,16 +88,13 @@
 
 [ $runtime == vm || ($compiler == none && $runtime == drt) ]
 async/run_async3_test: Fail # _enqueueImmediate runs after Timer. http://dartbug.com/9001.
-async/run_async4_test: Pass, Fail # http://dartbug.com/9013
 
 [ $compiler == none && $runtime == drt ]
 async/timer_isolate_test: Skip # See Issue 4997
 async/timer_not_available_test: Skip # only meant to test when there is no way to
                                      # implement timer (currently only in d8)
 mirrors/library_uri_io_test: Skip # Not intended for drt as it uses dart:io.
-
-[ $arch == arm ]
-*: Skip
+async/run_async6_test: Fail # Issue 10910
 
 [ $arch == simarm ]
 *: Skip
diff --git a/tests/lib/math/coin_test.dart b/tests/lib/math/coin_test.dart
index 0da9aed..1ca2261 100644
--- a/tests/lib/math/coin_test.dart
+++ b/tests/lib/math/coin_test.dart
@@ -27,4 +27,36 @@
         "Tails: $tails\n"
         "Ratio: ${heads/tails}\n");
   Expect.approxEquals(1.0, heads/tails, 0.1);
+
+  heads = 0;
+  tails = 0;
+  for (var i = 0; i < 10000; i++) {
+    rnd = new Random(i);
+    if (rnd.nextBool()) {
+      heads++;
+    } else {
+      tails++;
+    }
+  }
+  print("Heads: $heads\n"
+        "Tails: $tails\n"
+        "Ratio: ${heads/tails}\n");
+  Expect.approxEquals(1.0, heads/tails, 0.1);
+
+  // A sequence of newly allocated Random number generators should have fair
+  // initial tosses.
+  heads = 0;
+  tails = 0;
+  for (var i = 0; i < 10000; i++) {
+    rnd = new Random();
+    if (rnd.nextBool()) {
+      heads++;
+    } else {
+      tails++;
+    }
+  }
+  print("Heads: $heads\n"
+        "Tails: $tails\n"
+        "Ratio: ${heads/tails}\n");
+  Expect.approxEquals(1.0, heads/tails, 0.1);
 }
\ No newline at end of file
diff --git a/tests/lib/math/random_test.dart b/tests/lib/math/random_test.dart
index f06fa2b..d1e02bc 100644
--- a/tests/lib/math/random_test.dart
+++ b/tests/lib/math/random_test.dart
@@ -14,38 +14,38 @@
   var rnd = new Random(20130307);
   // Make sure we do not break the random number generation.
   var i = 0;
-  Expect.equals(         0, rnd.nextInt(1 << ++i));
-  Expect.equals(         2, rnd.nextInt(1 << ++i));
-  Expect.equals(         7, rnd.nextInt(1 << ++i));
-  Expect.equals(         8, rnd.nextInt(1 << ++i));
   Expect.equals(         1, rnd.nextInt(1 << ++i));
-  Expect.equals(        61, rnd.nextInt(1 << ++i));
-  Expect.equals(        31, rnd.nextInt(1 << ++i));
-  Expect.equals(       230, rnd.nextInt(1 << ++i));
-  Expect.equals(       390, rnd.nextInt(1 << ++i));
-  Expect.equals(       443, rnd.nextInt(1 << ++i));
-  Expect.equals(      1931, rnd.nextInt(1 << ++i));
-  Expect.equals(      3028, rnd.nextInt(1 << ++i));
-  Expect.equals(      5649, rnd.nextInt(1 << ++i));
-  Expect.equals(      4603, rnd.nextInt(1 << ++i));
-  Expect.equals(     27684, rnd.nextInt(1 << ++i));
-  Expect.equals(     54139, rnd.nextInt(1 << ++i));
-  Expect.equals(     83454, rnd.nextInt(1 << ++i));
-  Expect.equals(    106708, rnd.nextInt(1 << ++i));
-  Expect.equals(    112143, rnd.nextInt(1 << ++i));
-  Expect.equals(    875266, rnd.nextInt(1 << ++i));
-  Expect.equals(    971126, rnd.nextInt(1 << ++i));
-  Expect.equals(   1254573, rnd.nextInt(1 << ++i));
-  Expect.equals(   4063839, rnd.nextInt(1 << ++i));
-  Expect.equals(   7854646, rnd.nextInt(1 << ++i));
-  Expect.equals(  29593843, rnd.nextInt(1 << ++i));
-  Expect.equals(  17672573, rnd.nextInt(1 << ++i));
-  Expect.equals(  80223657, rnd.nextInt(1 << ++i));
-  Expect.equals( 142194155, rnd.nextInt(1 << ++i));
+  Expect.equals(         1, rnd.nextInt(1 << ++i));
+  Expect.equals(         7, rnd.nextInt(1 << ++i));
+  Expect.equals(         6, rnd.nextInt(1 << ++i));
+  Expect.equals(         6, rnd.nextInt(1 << ++i));
+  Expect.equals(        59, rnd.nextInt(1 << ++i));
+  Expect.equals(        11, rnd.nextInt(1 << ++i));
+  Expect.equals(       212, rnd.nextInt(1 << ++i));
+  Expect.equals(        17, rnd.nextInt(1 << ++i));
+  Expect.equals(       507, rnd.nextInt(1 << ++i));
+  Expect.equals(      1060, rnd.nextInt(1 << ++i));
+  Expect.equals(       891, rnd.nextInt(1 << ++i));
+  Expect.equals(      1534, rnd.nextInt(1 << ++i));
+  Expect.equals(      8404, rnd.nextInt(1 << ++i));
+  Expect.equals(     13839, rnd.nextInt(1 << ++i));
+  Expect.equals(     23298, rnd.nextInt(1 << ++i));
+  Expect.equals(     53622, rnd.nextInt(1 << ++i));
+  Expect.equals(    205997, rnd.nextInt(1 << ++i));
+  Expect.equals(    393823, rnd.nextInt(1 << ++i));
+  Expect.equals(    514614, rnd.nextInt(1 << ++i));
+  Expect.equals(    233715, rnd.nextInt(1 << ++i));
+  Expect.equals(    895357, rnd.nextInt(1 << ++i));
+  Expect.equals(   4726185, rnd.nextInt(1 << ++i));
+  Expect.equals(   7976427, rnd.nextInt(1 << ++i));
   Expect.equals(  31792146, rnd.nextInt(1 << ++i));
-  Expect.equals(1042196170, rnd.nextInt(1 << ++i));
-  Expect.equals(1589656273, rnd.nextInt(1 << ++i));
-  Expect.equals(1547294578, rnd.nextInt(1 << ++i));
+  Expect.equals(  35563210, rnd.nextInt(1 << ++i));
+  Expect.equals( 113261265, rnd.nextInt(1 << ++i));
+  Expect.equals( 205117298, rnd.nextInt(1 << ++i));
+  Expect.equals( 447729735, rnd.nextInt(1 << ++i));
+  Expect.equals(1072507596, rnd.nextInt(1 << ++i));
+  Expect.equals(2134030067, rnd.nextInt(1 << ++i));
+  Expect.equals(721180690, rnd.nextInt(1 << ++i));
   Expect.equals(32, i);
   // If max is too large expect an ArgumentError. 
   Expect.throws(() => rnd.nextInt((1 << i)+1), (e) => e is ArgumentError);
diff --git a/tests/lib/mirrors/library_uri_io_test.dart b/tests/lib/mirrors/library_uri_io_test.dart
index beddc40..add283d 100644
--- a/tests/lib/mirrors/library_uri_io_test.dart
+++ b/tests/lib/mirrors/library_uri_io_test.dart
@@ -8,7 +8,6 @@
 
 import 'dart:mirrors';
 import 'dart:io';
-import 'dart:uri';
 import '../../../pkg/unittest/lib/unittest.dart';
 
 class Class {
@@ -25,7 +24,7 @@
   var mirrors = currentMirrorSystem();
   test("Test current library uri", () {
     String appendSlash(String path) => path.endsWith('/') ? path : '$path/';
-    Uri cwd = new Uri.fromComponents(
+    Uri cwd = new Uri(
         scheme: 'file',
         path: appendSlash(new Path(new File('.').fullPathSync()).toString()));
     Uri uri = cwd.resolve(new Path(new Options().script).toString());
diff --git a/tests/lib/mirrors/library_uri_package_test.dart b/tests/lib/mirrors/library_uri_package_test.dart
index bcd1085..db1ceea 100644
--- a/tests/lib/mirrors/library_uri_package_test.dart
+++ b/tests/lib/mirrors/library_uri_package_test.dart
@@ -7,7 +7,6 @@
 library MirrorsTest;
 
 import 'dart:mirrors';
-import 'dart:uri';
 import 'package:args/args.dart';
 import '../../../pkg/unittest/lib/unittest.dart';
 
diff --git a/tests/lib/mirrors/mirrors_resolve_fields_test.dart b/tests/lib/mirrors/mirrors_resolve_fields_test.dart
new file mode 100644
index 0000000..f513ae2
--- /dev/null
+++ b/tests/lib/mirrors/mirrors_resolve_fields_test.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Regression test for dart2js that used to not resolve instance
+// fields when a class is only instantiated through mirrors.
+
+import "package:expect/expect.dart";
+import 'dart:mirrors';
+
+class A {
+  static const int _STATE_INITIAL = 0;
+  int _state = _STATE_INITIAL;
+  A();
+}
+
+main() {
+  var mirrors = currentMirrorSystem();  
+  var classMirror = reflectClass(A);
+  var instanceMirror = classMirror.newInstance(const Symbol(''),[]);
+  Expect.equals(A._STATE_INITIAL, instanceMirror.reflectee._state);
+}
diff --git a/tests/lib/mirrors/mirrors_test.dart b/tests/lib/mirrors/mirrors_test.dart
index 3c5164d..695ee778 100644
--- a/tests/lib/mirrors/mirrors_test.dart
+++ b/tests/lib/mirrors/mirrors_test.dart
@@ -8,7 +8,6 @@
 library MirrorsTest;
 import "dart:mirrors";
 import "../../../pkg/unittest/lib/unittest.dart";
-import 'dart:uri';
 
 var topLevelField;
 
@@ -161,7 +160,7 @@
   expect(objectMirror.reflectee.field, equals(1234));
 }
 
-testNames(mirrors) {
+testNames(mirrors, isDart2js) {
   var libMirror = mirrors.findLibrary(const Symbol("MirrorsTest")).single;
   var classMirror = libMirror.classes[const Symbol('Class')];
   var typedefMirror = libMirror.members[const Symbol('Typedef')];
@@ -174,14 +173,16 @@
   expect(classMirror.simpleName, equals(const Symbol('Class')));
   expect(classMirror.qualifiedName, equals(const Symbol('MirrorsTest.Class')));
 
-  TypeVariableMirror typeVariable = classMirror.typeVariables.values.single;
-  expect(typeVariable.simpleName, equals(const Symbol('T')));
-  expect(typeVariable.qualifiedName,
-         equals(const Symbol('MirrorsTest.Class.T')));
+  if (!isDart2js) { // TODO(ahe): Implement this in dart2js.
+    TypeVariableMirror typeVariable = classMirror.typeVariables.values.single;
+    expect(typeVariable.simpleName, equals(const Symbol('T')));
+    expect(typeVariable.qualifiedName,
+           equals(const Symbol('MirrorsTest.Class.T')));
 
-  expect(typedefMirror.simpleName, equals(const Symbol('Typedef')));
-  expect(typedefMirror.qualifiedName,
-         equals(const Symbol('MirrorsTest.Typedef')));
+    expect(typedefMirror.simpleName, equals(const Symbol('Typedef')));
+    expect(typedefMirror.qualifiedName,
+           equals(const Symbol('MirrorsTest.Typedef')));
+  }
 
   expect(methodMirror.simpleName, equals(const Symbol('testNames')));
   expect(methodMirror.qualifiedName,
@@ -207,9 +208,6 @@
   test("Test field access", () { testFieldAccess(mirrors); });
   test("Test closure mirrors", () { testClosureMirrors(mirrors); });
   test("Test invoke constructor", () { testInvokeConstructor(mirrors); });
-  if (isDart2js) return;
-  test("Test reflect type", () { testReflectClass(mirrors); });
-  test("Test simple and qualifiedName", () { testNames(mirrors); });
   test("Test current library uri", () {
     testLibraryUri(new Class(),
       (Uri uri) => uri.path.endsWith('/mirrors_test.dart'));
@@ -217,6 +215,9 @@
   test("Test dart library uri", () {
     testLibraryUri("test", (Uri uri) => uri == Uri.parse('dart:core'));
   });
+  test("Test simple and qualifiedName", () { testNames(mirrors, isDart2js); });
+  if (isDart2js) return; // TODO(ahe): Remove this line.
+  test("Test reflect type", () { testReflectClass(mirrors); });
 }
 
 main() {
diff --git a/tests/lib/uri/uri_ipv6_test.dart b/tests/lib/uri/uri_ipv6_test.dart
deleted file mode 100644
index 1b69cf9..0000000
--- a/tests/lib/uri/uri_ipv6_test.dart
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:expect/expect.dart';
-import 'dart:uri';
-
-
-void testValidIpv6Uri() {
-  var path = 'http://[::1]:1234/path?query=5#now';
-  var uri = Uri.parse(path);
-  Expect.equals('http', uri.scheme);
-  Expect.equals('::1', uri.domain);
-  Expect.equals(1234, uri.port);
-  Expect.equals('/path', uri.path);
-  Expect.equals('query=5', uri.query);
-  Expect.equals('now', uri.fragment);
-  Expect.equals(path, uri.toString());
-
-  path = 'http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:80/index.html';
-  uri = Uri.parse(path);
-  Expect.equals('http', uri.scheme);
-  Expect.equals('FEDC:BA98:7654:3210:FEDC:BA98:7654:3210', uri.domain);
-  Expect.equals(80, uri.port);
-  Expect.equals('/index.html', uri.path);
-  Expect.equals(path, uri.toString());
-
-  path = 'http://[1080:0:0:0:8:800:200C:417A]/index.html';
-  uri = Uri.parse(path);
-  Expect.equals('http', uri.scheme);
-  Expect.equals('1080:0:0:0:8:800:200C:417A', uri.domain);
-  Expect.equals(0, uri.port);
-  Expect.equals('/index.html', uri.path);
-  Expect.equals(path, uri.toString());
-
-  path = 'http://[3ffe:2a00:100:7031::1]';
-  uri = Uri.parse(path);
-  Expect.equals('http', uri.scheme);
-  Expect.equals('3ffe:2a00:100:7031::1', uri.domain);
-  Expect.equals(0, uri.port);
-  Expect.equals('', uri.path);
-  Expect.equals(path, uri.toString());
-
-  path = 'http://[1080::8:800:200C:417A]/foo';
-  uri = Uri.parse(path);
-  Expect.equals('http', uri.scheme);
-  Expect.equals('1080::8:800:200C:417A', uri.domain);
-  Expect.equals(0, uri.port);
-  Expect.equals('/foo', uri.path);
-  Expect.equals(path, uri.toString());
-
-  path = 'http://[::192.9.5.5]/ipng';
-  uri = Uri.parse(path);
-  Expect.equals('http', uri.scheme);
-  Expect.equals('::192.9.5.5', uri.domain);
-  Expect.equals(0, uri.port);
-  Expect.equals('/ipng', uri.path);
-  Expect.equals(path, uri.toString());
-
-  path = 'http://[::FFFF:129.144.52.38]:80/index.html';
-  uri = Uri.parse(path);
-  Expect.equals('http', uri.scheme);
-  Expect.equals('::FFFF:129.144.52.38', uri.domain);
-  Expect.equals(80, uri.port);
-  Expect.equals('/index.html', uri.path);
-  Expect.equals(path, uri.toString());
-
-  path = 'http://[2010:836B:4179::836B:4179]';
-  uri = Uri.parse(path);
-  Expect.equals('http', uri.scheme);
-  Expect.equals('2010:836B:4179::836B:4179', uri.domain);
-  Expect.equals(0, uri.port);
-  Expect.equals('', uri.path);
-  Expect.equals(path, uri.toString());
-}
-
-void main() {
-  testValidIpv6Uri();
-}
-
diff --git a/tests/standalone/io/http_auth_digest_test.dart b/tests/standalone/io/http_auth_digest_test.dart
index 74e9d93..2a3828d 100644
--- a/tests/standalone/io/http_auth_digest_test.dart
+++ b/tests/standalone/io/http_auth_digest_test.dart
@@ -2,12 +2,11 @@
 // 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:crypto/crypto.dart";
 import "package:expect/expect.dart";
 import 'dart:async';
-import 'dart:crypto';
 import 'dart:io';
 import 'dart:isolate';
-import 'dart:uri';
 import 'dart:utf';
 
 class Server {
diff --git a/tests/standalone/io/http_auth_test.dart b/tests/standalone/io/http_auth_test.dart
index f0a9733..9869a94 100644
--- a/tests/standalone/io/http_auth_test.dart
+++ b/tests/standalone/io/http_auth_test.dart
@@ -2,12 +2,11 @@
 // 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:crypto/crypto.dart";
 import "package:expect/expect.dart";
 import 'dart:async';
-import 'dart:crypto';
 import 'dart:io';
 import 'dart:isolate';
-import 'dart:uri';
 import 'dart:utf';
 
 class Server {
diff --git a/tests/standalone/io/http_client_exception_test.dart b/tests/standalone/io/http_client_exception_test.dart
index 0d2f1e3..9028b6d 100644
--- a/tests/standalone/io/http_client_exception_test.dart
+++ b/tests/standalone/io/http_client_exception_test.dart
@@ -6,7 +6,6 @@
 import "package:expect/expect.dart";
 import "dart:io";
 import "dart:isolate";
-import "dart:uri";
 
 void testInvalidUrl() {
   HttpClient client = new HttpClient();
diff --git a/tests/standalone/io/http_connection_close_test.dart b/tests/standalone/io/http_connection_close_test.dart
index c56ef39..70fbda0 100644
--- a/tests/standalone/io/http_connection_close_test.dart
+++ b/tests/standalone/io/http_connection_close_test.dart
@@ -6,7 +6,6 @@
 import "package:expect/expect.dart";
 import "dart:async";
 import "dart:io";
-import "dart:uri";
 
 void testHttp10Close(bool closeRequest) {
   HttpServer.bind("127.0.0.1", 0).then((server) {
diff --git a/tests/standalone/io/http_multipart_test.dart b/tests/standalone/io/http_multipart_test.dart
index d564fc9..45cdec9 100644
--- a/tests/standalone/io/http_multipart_test.dart
+++ b/tests/standalone/io/http_multipart_test.dart
@@ -116,7 +116,6 @@
                               'Content of file',
                               contentType: 'text/plain',
                               filename: 'file1.txt')]);
-
   // Similar test using Chrome posting.
   message = [
       45, 45, 45, 45, 45, 45, 87, 101, 98, 75, 105, 116, 70, 111, 114, 109, 66,
diff --git a/tests/standalone/io/http_parser_test.dart b/tests/standalone/io/http_parser_test.dart
index c0d4e1e..dbd9564 100644
--- a/tests/standalone/io/http_parser_test.dart
+++ b/tests/standalone/io/http_parser_test.dart
@@ -7,7 +7,6 @@
 import 'dart:math';
 import 'dart:typed_data';
 import 'dart:isolate';
-import 'dart:uri';
 
 part '../../../sdk/lib/io/io_sink.dart';
 part '../../../sdk/lib/io/http.dart';
@@ -74,7 +73,6 @@
               bytesReceived += data.length;
             },
             onDone: () {
-              Expect.isFalse(upgraded);
               port2.close();
               Expect.equals(expectedMethod, method);
               Expect.stringEquals(expectedUri, uri.toString());
@@ -101,7 +99,6 @@
 
         incoming.dataDone.then((_) {
           port1.close();
-          Expect.isFalse(upgraded);
         });
       });
 
@@ -204,6 +201,24 @@
       controller = new StreamController();
       var port = new ReceivePort();
       controller.stream.pipe(httpParser);
+      int doneCallCount = 0;
+      // Called when done parsing entire message and done parsing body.
+      // Only executed when both are done.
+      void whenDone() {
+        doneCallCount++;
+        if (doneCallCount < 2) return;
+        Expect.equals(expectedVersion, headers.protocolVersion);
+        Expect.equals(expectedStatusCode, statusCode);
+        Expect.equals(expectedReasonPhrase, reasonPhrase);
+        Expect.isTrue(headersCompleteCalled);
+        Expect.equals(expectedBytesReceived, bytesReceived);
+        if (!upgrade) {
+          Expect.isTrue(dataEndCalled);
+          if (close) Expect.isTrue(dataEndClose);
+          Expect.equals(dataEndClose, connectionClose);
+        }
+      };
+
       var subscription = httpParser.listen((incoming) {
         port.close();
         statusCode = incoming.statusCode;
@@ -230,21 +245,9 @@
             onDone: () {
               dataEndCalled = true;
               dataEndClose = close;
+              whenDone();
             });
-      });
-
-      subscription.onDone(() {
-        Expect.equals(expectedVersion, headers.protocolVersion);
-        Expect.equals(expectedStatusCode, statusCode);
-        Expect.equals(expectedReasonPhrase, reasonPhrase);
-        Expect.isTrue(headersCompleteCalled);
-        Expect.equals(expectedBytesReceived, bytesReceived);
-        if (!upgrade) {
-          Expect.isTrue(dataEndCalled);
-          if (close) Expect.isTrue(dataEndClose);
-          Expect.equals(dataEndClose, connectionClose);
-        }
-      });
+      }, onDone: whenDone);
 
       headersCompleteCalled = false;
       dataEndCalled = false;
diff --git a/tests/standalone/io/http_proxy_configuration_test.dart b/tests/standalone/io/http_proxy_configuration_test.dart
index 829a080..4bff020 100644
--- a/tests/standalone/io/http_proxy_configuration_test.dart
+++ b/tests/standalone/io/http_proxy_configuration_test.dart
@@ -4,7 +4,6 @@
 
 import "package:expect/expect.dart";
 import "dart:io";
-import "dart:uri";
 
 expect(expected, String uri, environment) {
   Expect.equals(expected,
diff --git a/tests/standalone/io/http_proxy_test.dart b/tests/standalone/io/http_proxy_test.dart
index abab0bb..5e7bfe1 100644
--- a/tests/standalone/io/http_proxy_test.dart
+++ b/tests/standalone/io/http_proxy_test.dart
@@ -2,11 +2,10 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import "package:crypto/crypto.dart";
 import "package:expect/expect.dart";
 import "dart:async";
-import 'dart:crypto';
 import "dart:io";
-import "dart:uri";
 import 'dart:utf';
 
 class Server {
diff --git a/tests/standalone/io/http_redirect_test.dart b/tests/standalone/io/http_redirect_test.dart
index b3caef5..f67ff751 100644
--- a/tests/standalone/io/http_redirect_test.dart
+++ b/tests/standalone/io/http_redirect_test.dart
@@ -6,7 +6,6 @@
 import "package:expect/expect.dart";
 import "dart:async";
 import "dart:io";
-import "dart:uri";
 
 Future<HttpServer> setupServer() {
   Completer completer = new Completer();
@@ -197,15 +196,11 @@
         (HttpRequest request, HttpResponse response) {
           request.listen((_) {}, onDone: () {
             Expect.equals("POST", request.method);
-            request.listen(
-                (_) {},
-                onDone: () {
-                  response.headers.set(
-                      HttpHeaders.LOCATION,
-                      "http://127.0.0.1:${server.port}/303target");
-                  response.statusCode = HttpStatus.SEE_OTHER;
-                  response.close();
-                });
+            response.headers.set(
+                HttpHeaders.LOCATION,
+                "http://127.0.0.1:${server.port}/303target");
+            response.statusCode = HttpStatus.SEE_OTHER;
+            response.close();
           });
         });
     addRequestHandler(
diff --git a/tests/standalone/io/http_request_pipeling_test.dart b/tests/standalone/io/http_request_pipeling_test.dart
index 682c592..0da43df 100644
--- a/tests/standalone/io/http_request_pipeling_test.dart
+++ b/tests/standalone/io/http_request_pipeling_test.dart
@@ -9,7 +9,6 @@
 
 import "package:expect/expect.dart";
 import "dart:io";
-import "dart:uri";
 
 void main() {
   final int REQUEST_COUNT = 100;
diff --git a/tests/standalone/io/http_server_response_test.dart b/tests/standalone/io/http_server_response_test.dart
index 0e75d34..5b0a525 100644
--- a/tests/standalone/io/http_server_response_test.dart
+++ b/tests/standalone/io/http_server_response_test.dart
@@ -243,6 +243,34 @@
 }
 
 
+void testIgnoreRequestData() {
+  HttpServer.bind("127.0.0.1", 0)
+      .then((server) {
+        server.listen((request) {
+          // Ignore request data.
+          request.response.write("all-okay");
+          request.response.close();
+        });
+
+        var client = new HttpClient();
+        client.get("127.0.0.1", server.port, "/")
+            .then((request) {
+              request.contentLength = 1024 * 1024;
+              request.add(new Uint8List(1024 * 1024));
+              return request.close();
+            })
+            .then((response) {
+              response
+                  .fold(0, (s, b) => s + b.length)
+                  .then((bytes) {
+                    Expect.equals(8, bytes);
+                    server.close();
+                  });
+            });
+      });
+}
+
+
 void main() {
   testResponseDone();
   testResponseAddStream();
@@ -250,4 +278,5 @@
   testResponseAddClosed();
   testBadResponseAdd();
   testBadResponseClose();
+  testIgnoreRequestData();
 }
diff --git a/tests/standalone/io/http_session_test.dart b/tests/standalone/io/http_session_test.dart
index 4fe3d9d..a3141c8 100644
--- a/tests/standalone/io/http_session_test.dart
+++ b/tests/standalone/io/http_session_test.dart
@@ -68,7 +68,7 @@
 void testTimeout(int sessionCount) {
   var client = new HttpClient();
   HttpServer.bind("127.0.0.1", 0).then((server) {
-    server.sessionTimeout = 0;
+    server.sessionTimeout = 1;
     var timeouts = [];
     server.listen((request) {
       var c = new Completer();
diff --git a/tests/standalone/io/http_stream_close_test.dart b/tests/standalone/io/http_stream_close_test.dart
index b47209e..f5d4aeb 100644
--- a/tests/standalone/io/http_stream_close_test.dart
+++ b/tests/standalone/io/http_stream_close_test.dart
@@ -4,7 +4,6 @@
 //
 
 import "dart:io";
-import "dart:uri";
 
 main() {
   bool serverOnClosed = false;
diff --git a/tests/standalone/io/https_client_certificate_test.dart b/tests/standalone/io/https_client_certificate_test.dart
index fea97ef..141470a 100644
--- a/tests/standalone/io/https_client_certificate_test.dart
+++ b/tests/standalone/io/https_client_certificate_test.dart
@@ -5,7 +5,6 @@
 import "package:expect/expect.dart";
 import "dart:async";
 import "dart:io";
-import "dart:uri";
 import "dart:isolate";
 
 const HOST_NAME = "localhost";
diff --git a/tests/standalone/io/https_client_exception_test.dart b/tests/standalone/io/https_client_exception_test.dart
index 8acac41..6994e05 100644
--- a/tests/standalone/io/https_client_exception_test.dart
+++ b/tests/standalone/io/https_client_exception_test.dart
@@ -5,7 +5,6 @@
 import "package:expect/expect.dart";
 import "dart:io";
 import "dart:isolate";
-import "dart:uri";
 
 void testBadHostName() {
   HttpClient client = new HttpClient();
diff --git a/tests/standalone/io/https_server_test.dart b/tests/standalone/io/https_server_test.dart
index 08fec0c..2e0b2a0 100644
--- a/tests/standalone/io/https_server_test.dart
+++ b/tests/standalone/io/https_server_test.dart
@@ -5,7 +5,6 @@
 import "package:expect/expect.dart";
 import "dart:async";
 import "dart:io";
-import "dart:uri";
 import "dart:isolate";
 
 const HOST_NAME = "localhost";
diff --git a/tests/standalone/io/pipe_server_test.dart b/tests/standalone/io/pipe_server_test.dart
index d86e5f5..90bfb5e 100644
--- a/tests/standalone/io/pipe_server_test.dart
+++ b/tests/standalone/io/pipe_server_test.dart
@@ -51,7 +51,6 @@
       String srcFileName =
           getDataFilename("tests/standalone/io/readline_test1.dat");
       Stream fileInput = new File(srcFileName).openRead();
-
       fileInput.pipe(_socket).then((_) {
         var tempDir = new Directory('').createTempSync();
         var dstFileName = tempDir.path + "/readline_test1.dat";
diff --git a/tests/standalone/io/regress_8828_test.dart b/tests/standalone/io/regress_8828_test.dart
index c33a56d..b801545 100644
--- a/tests/standalone/io/regress_8828_test.dart
+++ b/tests/standalone/io/regress_8828_test.dart
@@ -26,7 +26,7 @@
           return request.close();
         })
         .then((HttpClientResponse response) {
-            List<int> body = new List();
+          List<int> body = new List();
           response.listen(body.addAll,
                           onDone: () {
                             Expect.equals("first line\nsecond line\n",
diff --git a/tests/standalone/io/secure_builtin_roots_database_test.dart b/tests/standalone/io/secure_builtin_roots_database_test.dart
index 3966032..6b55c71 100644
--- a/tests/standalone/io/secure_builtin_roots_database_test.dart
+++ b/tests/standalone/io/secure_builtin_roots_database_test.dart
@@ -4,7 +4,6 @@
 
 import "package:expect/expect.dart";
 import "dart:io";
-import "dart:uri";
 import "dart:isolate";
 import "dart:async";
 
diff --git a/tests/standalone/io/secure_builtin_roots_test.dart b/tests/standalone/io/secure_builtin_roots_test.dart
index edfffad..32609a8 100644
--- a/tests/standalone/io/secure_builtin_roots_test.dart
+++ b/tests/standalone/io/secure_builtin_roots_test.dart
@@ -4,7 +4,6 @@
 
 import "package:expect/expect.dart";
 import "dart:io";
-import "dart:uri";
 import "dart:isolate";
 import "dart:async";
 
diff --git a/tests/standalone/io/secure_no_builtin_roots_database_test.dart b/tests/standalone/io/secure_no_builtin_roots_database_test.dart
index 8c647d0..dcdb2be 100644
--- a/tests/standalone/io/secure_no_builtin_roots_database_test.dart
+++ b/tests/standalone/io/secure_no_builtin_roots_database_test.dart
@@ -4,7 +4,6 @@
 
 import "package:expect/expect.dart";
 import "dart:io";
-import "dart:uri";
 import "dart:isolate";
 import "dart:async";
 
diff --git a/tests/standalone/io/secure_no_builtin_roots_test.dart b/tests/standalone/io/secure_no_builtin_roots_test.dart
index c411e62..a71c5fc 100644
--- a/tests/standalone/io/secure_no_builtin_roots_test.dart
+++ b/tests/standalone/io/secure_no_builtin_roots_test.dart
@@ -4,7 +4,6 @@
 
 import "package:expect/expect.dart";
 import "dart:io";
-import "dart:uri";
 import "dart:isolate";
 import "dart:async";
 
diff --git a/tests/standalone/io/skipping_dart2js_compilations_test.dart b/tests/standalone/io/skipping_dart2js_compilations_test.dart
index 2dd7bf2..d018541 100644
--- a/tests/standalone/io/skipping_dart2js_compilations_test.dart
+++ b/tests/standalone/io/skipping_dart2js_compilations_test.dart
@@ -17,7 +17,6 @@
 import 'package:expect/expect.dart';
 import 'dart:async';
 import 'dart:io';
-import 'dart:uri';
 import '../../../tools/testing/dart/test_suite.dart' as suite;
 import '../../../tools/testing/dart/test_runner.dart' as runner;
 import '../../../tools/testing/dart/test_options.dart' as options;
@@ -153,7 +152,7 @@
   var executable = new Options().executable;
   var arguments = [createFileScript, fileUtils.scriptOutputPath.toNativePath()];
   var bootstrapDeps = [
-      new Uri("file://${fileUtils.testSnapshotFilePath}")];
+      Uri.parse("file://${fileUtils.testSnapshotFilePath}")];
   var commands = [new runner.CompilationCommand(
       fileUtils.testJsFilePath.toNativePath(),
       false,
diff --git a/tests/standalone/io/web_socket_test.dart b/tests/standalone/io/web_socket_test.dart
index 4e5df10..cd72efa 100644
--- a/tests/standalone/io/web_socket_test.dart
+++ b/tests/standalone/io/web_socket_test.dart
@@ -12,7 +12,6 @@
 import "dart:io";
 import "dart:isolate";
 import "dart:typed_data";
-import "dart:uri";
 
 const String CERT_NAME = 'localhost_cert';
 const String HOST_NAME = 'localhost';
diff --git a/tests/standalone/standalone.status b/tests/standalone/standalone.status
index 10e39ba..6027974 100644
--- a/tests/standalone/standalone.status
+++ b/tests/standalone/standalone.status
@@ -4,12 +4,6 @@
 
 package/invalid_uri_test: Fail, OK # Fails intentionally
 
-[ $runtime == vm && $system == macos ]
-debugger/basic_debugger_test: Pass, Crash # Issue 10488.
-
-[ $runtime == vm && $system == windows ]
-debugger/*: Skip # Issue: 10791
-
 [ $runtime == vm ]
 # Fails because checked-in dart executable is not up to date.
 io/test_runner_test: Fail
@@ -17,6 +11,8 @@
 # Skip this because it is leaving temp directories behind when it fails.
 io/skipping_dart2js_compilations_test: Skip
 
+io/http_content_length_test: Pass, Fail # Issue 10934
+
 [ $runtime == vm && ( $system == windows ) ]
 io/raw_socket_test: Pass, Fail # Issue 8901
 
@@ -66,6 +62,8 @@
 # package test issue 7392
 package/package1_test: Fail
 package/package_test: Fail
+io/test_runner_test: Fail # Library dart:uri removed.
+io/skipping_dart2js_compilations_test: Skip # Library dart:uri removed.
 
 
 # The dart:io library is created at build time from separate files, and
@@ -110,6 +108,8 @@
 debugger/*: Skip # Do not run standalone vm debugger tests with dart2js.
 left_shift_bit_and_op_test: Skip # Integers exceed dart2js precision.
 pow_test: Skip # Precision > 53 bits.
+io/test_runner_test: Fail # Library dart:uri removed.
+io/skipping_dart2js_compilations_test: Skip # Library dart:uri removed.
 
 [ $compiler == dart2js && $jscl ]
 assert_test: Fail, OK # Assumes unspecified fields on the AssertionError.
@@ -117,7 +117,6 @@
 deoptimization_test: Fail, OK # Requires bigint.
 out_of_memory_test: Fail, OK # d8 handles much larger arrays than Dart VM.
 io/options_test: Fail, OK # Cannot pass options to d8.
-io/http_parser_test: Fail, OK # Cancelling a Timer not implemented in d8/jsshell.
 
 [ $compiler == dart2js && $runtime == none ]
 io/options_test: Fail
@@ -134,9 +133,6 @@
 # Skip until we stabilize language tests.
 *: Skip
 
-[ $arch == arm ]
-*: Skip
-
 [ $arch == simarm ]
 *: Skip
 
diff --git a/tests/utils/dummy_compiler_test.dart b/tests/utils/dummy_compiler_test.dart
index ae44c27..50ab451 100644
--- a/tests/utils/dummy_compiler_test.dart
+++ b/tests/utils/dummy_compiler_test.dart
@@ -6,7 +6,6 @@
 library dummy_compiler;
 
 import 'dart:async';
-import 'dart:uri';
 
 import '../../sdk/lib/_internal/compiler/compiler.dart';
 
@@ -32,6 +31,7 @@
                   class Closure {}
                   class Dynamic_ {}
                   class Null {}
+                  class StackTrace {}
                   class LinkedHashMap {}
                   identical(a, b) => true;
                   getRuntimeTypeInfo(o) {}
@@ -93,9 +93,9 @@
 
 main() {
   Future<String> result =
-      compile(new Uri.fromComponents(scheme: 'main'),
-              new Uri.fromComponents(scheme: 'lib', path: '/'),
-              new Uri.fromComponents(scheme: 'package', path: '/'),
+      compile(new Uri(scheme: 'main'),
+              new Uri(scheme: 'lib', path: '/'),
+              new Uri(scheme: 'package', path: '/'),
               provider, handler);
   result.then((String code) {
     if (code == null) {
diff --git a/tests/utils/recursive_import_test.dart b/tests/utils/recursive_import_test.dart
index d411707..59aade0 100644
--- a/tests/utils/recursive_import_test.dart
+++ b/tests/utils/recursive_import_test.dart
@@ -7,7 +7,6 @@
 import "package:expect/expect.dart";
 import 'dart:async';
 import '../../sdk/lib/_internal/compiler/compiler.dart';
-import 'dart:uri';
 
 const CORE_LIB = """
 library core;
@@ -26,6 +25,7 @@
 class Dynamic_ {}
 class Type {}
 class Null {}
+class StackTrace {}
 class LinkedHashMap {}
 getRuntimeTypeInfo(o) {}
 setRuntimeTypeInfo(o, i) {}
@@ -103,9 +103,9 @@
   }
 
   Future<String> result =
-      compile(new Uri.fromComponents(scheme: 'main'),
-              new Uri.fromComponents(scheme: 'lib', path: '/'),
-              new Uri.fromComponents(scheme: 'package', path: '/'),
+      compile(new Uri(scheme: 'main'),
+              new Uri(scheme: 'lib', path: '/'),
+              new Uri(scheme: 'package', path: '/'),
               provider, handler);
   result.then((String code) {
     Expect.isNull(code);
diff --git a/tests/utils/utils.status b/tests/utils/utils.status
index c1aab5a..d8a3a34 100644
--- a/tests/utils/utils.status
+++ b/tests/utils/utils.status
@@ -23,9 +23,6 @@
 # Skip until we stabilize language tests.
 *: Skip
 
-[ $arch == arm ]
-*: Skip
-
 [ $arch == simarm ]
 *: Skip
 
diff --git a/tools/VERSION b/tools/VERSION
index 2be690f..0a54219 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -1,4 +1,4 @@
 MAJOR 0
 MINOR 5
-BUILD 11
-PATCH 1
+BUILD 12
+PATCH 0
diff --git a/tools/bots/compiler.py b/tools/bots/compiler.py
index fd34ac6..38c116b 100644
--- a/tools/bots/compiler.py
+++ b/tools/bots/compiler.py
@@ -23,7 +23,7 @@
 DART2JS_BUILDER = (
     r'dart2js-(linux|mac|windows)(-(jsshell))?-(debug|release)(-(checked|host-checked))?(-(host-checked))?(-(minified))?-?(\d*)-?(\d*)')
 WEB_BUILDER = (
-    r'dart2js-(ie9|ie10|ff|safari|chrome|chromeOnAndroid|opera)-(win7|win8|mac10\.8|mac10\.7|linux)(-(all|html))?(-(csp))?(-(\d+)-(\d+))?')
+    r'dart2js-(ie9|ie10|ff|safari|chrome|chromeOnAndroid|opera|drt)-(win7|win8|mac10\.8|mac10\.7|linux)(-(all|html))?(-(csp))?(-(\d+)-(\d+))?')
 
 
 def GetBuildInfo(builder_name, is_buildbot):
@@ -80,14 +80,15 @@
   else :
     return None
 
-  if system == 'windows':
-    system = 'win7'
+  # We have both win7 and win8 bots, functionality is the same.
+  if system.startswith('win'):
+    system = 'windows'
 
   # We have both 10.8 and 10.7 bots, functionality is the same.
   if system == 'mac10.8' or system == 'mac10.7':
     system = 'mac'
 
-  if (system == 'win7' and platform.system() != 'Windows') or (
+  if (system == 'windows' and platform.system() != 'Windows') or (
       system == 'mac' and platform.system() != 'Darwin') or (
       system == 'linux' and platform.system() != 'Linux'):
     print ('Error: You cannot emulate a buildbot with a platform different '
@@ -108,6 +109,31 @@
   flags = [x for x in flags if not '=' in x]
   return ('%s tests %s' % (name, ' '.join(flags))).strip()
 
+# TODO(ricow): remove this once we have browser controller drivers for all
+# supported platforms.
+def UseBrowserController(runtime, system):
+  supported_platforms = {
+    'linux': ['ff', 'chromeOnAndroid', 'chrome'],
+    'mac': [],
+    'windows': []
+  }
+  # Platforms that we run on the fyi waterfall only.
+  fyi_supported_platforms = {
+    'linux': [],
+    'mac': ['safari'],
+    'windows': []
+  }
+
+  if (runtime in supported_platforms[system]):
+    return True
+
+  if (os.environ.get('BUILDBOT_SCHEDULER') == "fyi-main" and
+      runtime in fyi_supported_platforms[system]):
+    return True
+
+  return False
+
+
 IsFirstTestStepCall = True
 def TestStep(name, mode, system, compiler, runtime, targets, flags):
   step_name = TestStepName(name, flags)
@@ -120,10 +146,6 @@
 
     user_test = os.environ.get('USER_TEST', 'no')
 
-    # TODO(ricow): temporary hack to run on fyi with --use_browser_controller
-    if os.environ.get('BUILDBOT_SCHEDULER') == "fyi-main" and runtime == 'drt':
-      runtime = 'chrome'
-
     cmd.extend([sys.executable,
                 os.path.join(os.curdir, 'tools', 'test.py'),
                 '--step_name=' + step_name,
@@ -135,18 +157,12 @@
                 '--report',
                 '--write-debug-log'])
 
-    # TODO(ricow/kustermann): Issue 7339
-    if runtime == "safari":
-      cmd.append('--nobatch')
-
     if user_test == 'yes':
       cmd.append('--progress=color')
     else:
       cmd.extend(['--progress=buildbot', '-v'])
 
-    # TODO(ricow): temporary hack to run on fyi with --use_browser_controller
-    if (os.environ.get('BUILDBOT_SCHEDULER') == "fyi-main" and
-        runtime in ['chrome', 'ff', 'chromeOnAndroid']):
+    if UseBrowserController(runtime, system):
       cmd.append('--use_browser_controller')
 
     global IsFirstTestStepCall
@@ -168,7 +184,7 @@
    Args:
      - runtime: either 'd8', 'jsshell', or one of the browsers, see GetBuildInfo
      - mode: either 'debug' or 'release'
-     - system: either 'linux', 'mac', 'win7', or 'win8'
+     - system: either 'linux', 'mac', 'windows'
      - flags: extra flags to pass to test.dart
      - is_buildbot: true if we are running on a real buildbot instead of
        emulating one.
@@ -194,16 +210,13 @@
           'Local', 'Google', 'Chrome', 'Application', 'chrome.exe')}
     return path_dict[runtime]
 
-  if system == 'linux' and runtime == 'chrome':
-    # TODO(ngeoffray): We should install selenium on the buildbot.
-    runtime = 'drt'
-  elif (runtime == 'ff' or runtime == 'chrome') and is_buildbot:
+  if (runtime == 'ff' or runtime == 'chrome') and is_buildbot:
     # Print out browser version numbers if we're running on the buildbot (where
     # we know the paths to these browser installations).
     version_query_string = '"%s" --version' % GetPath(runtime)
-    if runtime == 'ff' and system.startswith('win'):
+    if runtime == 'ff' and system == 'windows':
       version_query_string += '| more'
-    elif runtime == 'chrome' and system.startswith('win'):
+    elif runtime == 'chrome' and system == 'windows':
       version_query_string = ('''reg query "HKCU\\Software\\Microsoft\\''' +
           '''Windows\\CurrentVersion\\Uninstall\\Google Chrome" /v Version''')
     p = subprocess.Popen(version_query_string,
@@ -226,7 +239,7 @@
     TestStep("dart2js_unit", mode, system, 'none', 'vm', ['dart2js'],
              unit_test_flags)
 
-  if system.startswith('win') and runtime.startswith('ie10'):
+  if system == 'windows' and runtime == 'ie10':
     TestStep("dart2js", mode, system, 'dart2js', runtime, ['html'], flags)
   else:
     # Run the default set of test suites.
@@ -268,10 +281,10 @@
   behavior has not been reproduced outside of the buildbots.
 
   Args:
-     - system: either 'linux', 'mac', 'win7', or 'win8'
+     - system: either 'linux', 'mac', 'windows'
      - browser: one of the browsers, see GetBuildInfo
   """
-  if system.startswith('win'):
+  if system == 'windows':
     temp_dir = 'C:\\Users\\chrome-bot\\AppData\\Local\\Temp'
     for name in os.listdir(temp_dir):
       fullname = os.path.join(temp_dir, name)
@@ -290,7 +303,7 @@
   # on the slow (all) IE windows bots. This is a hack and we should use the
   # normal sharding and checked splitting functionality when we get more
   # vms for testing this.
-  if (build_info.system == 'linux' and build_info.runtime == 'chrome'):
+  if (build_info.system == 'linux' and build_info.runtime == 'drt'):
     return True
   if build_info.runtime.startswith('ie') and build_info.test_set == 'all':
     return True
diff --git a/tools/bots/cross-vm.py b/tools/bots/cross-vm.py
index e58c6c0..54d43c1 100644
--- a/tools/bots/cross-vm.py
+++ b/tools/bots/cross-vm.py
@@ -7,7 +7,6 @@
 import re
 import shutil
 import sys
-import tempfile
 
 import bot
 
@@ -26,64 +25,134 @@
   sys.stdout.flush()
   bot.RunProcess(args)
 
-def main():
-  name, is_buildbot = bot.GetBotName()
+def tarball_name(arch, mode):
+  return 'cross_build_%s_%s.tar.bz2' % (arch, mode)
+
+def record_names(name, arch, mode):
+  return ('record_%s_%s_%s.json' % (name, arch, mode),
+          'record_output_%s_%s_%s.json' % (name, arch, mode))
+
+def cross_compiling_builder(arch, mode):
   build_py = os.path.join('tools', 'build.py')
   test_py = os.path.join('tools', 'test.py')
+  test_args = [sys.executable, test_py, '--progress=line', '--report',
+               '--time', '--compiler=none', '--runtime=vm', '--write-debug-log']
+
+  tarball = tarball_name(arch, mode)
+  (recording, recording_out) = record_names('tests', arch, mode)
+  (checked_recording, checked_recording_out) = record_names(
+      'checked_tests', arch, mode)
+
+  temporary_files = [tarball, recording, recording_out, checked_recording,
+                     checked_recording_out]
+  bot.Clobber()
+  try:
+    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(args)
+      with bot.BuildStep('Create build tarball'):
+        run(['tar', '-cjf', tarball, '--exclude=**/obj',
+             '--exclude=**/obj.host', '--exclude=**/obj.target',
+             '--exclude=**/*analyzer*', '--exclude=**/*IA32', 'out/'])
+
+      with bot.BuildStep('Upload build tarball'):
+        uri = "%s/%s" % (GCS_BUCKET, tarball)
+        run([GSUTIL, 'cp', tarball, uri])
+        run([GSUTIL, 'setacl', 'public-read', uri])
+
+      with bot.BuildStep('prepare tests'):
+        uri = "%s/%s" % (GCS_BUCKET, recording)
+        run(test_args + ['--mode=' + mode, '--arch=' + arch,
+                         '--record_to_file=' + recording])
+        run([GSUTIL, 'cp', recording, uri])
+        run([GSUTIL, 'setacl', 'public-read', uri])
+
+      with bot.BuildStep('prepare checked_tests'):
+        uri = "%s/%s" % (GCS_BUCKET, checked_recording)
+        run(test_args + ['--mode=' + mode, '--arch=' + arch, '--checked',
+                         '--record_to_file=' + checked_recording])
+        run([GSUTIL, 'cp', checked_recording, uri])
+        run([GSUTIL, 'setacl', 'public-read', uri])
+    elif num_run == 2:
+      with bot.BuildStep('tests'):
+        uri = "%s/%s" % (GCS_BUCKET, recording_out)
+        run([GSUTIL, 'cp', uri, recording_out])
+        run(test_args + ['--mode=' + mode, '--arch=' + arch,
+                         '--replay_from_file=' + recording_out])
+
+      with bot.BuildStep('checked_tests'):
+        uri = "%s/%s" % (GCS_BUCKET, checked_recording_out)
+        run([GSUTIL, 'cp', uri, checked_recording_out])
+        run(test_args + ['--mode=' + mode, '--arch=' + arch, '--checked',
+                         '--replay_from_file=' + checked_recording_out])
+    else:
+      raise Exception("Invalid annotated steps run")
+  finally:
+    for path in temporary_files:
+      if os.path.exists(path):
+        os.remove(path)
+
+def target_builder(arch, mode):
+  execute_testcases_py = os.path.join('tools', 'execute_recorded_testcases.py')
+
+  tarball = tarball_name(arch, mode)
+  (recording, recording_out) = record_names('tests', arch, mode)
+  (checked_recording, checked_recording_out) = record_names(
+      'checked_tests', arch, mode)
+
+  temporary_files = [tarball, recording, recording_out, checked_recording,
+                     checked_recording_out]
+  bot.Clobber()
+  try:
+    with bot.BuildStep('Fetch build tarball'):
+      run([GSUTIL, 'cp', "%s/%s" % (GCS_BUCKET, tarball), tarball])
+
+    with bot.BuildStep('Unpack build tarball'):
+      run(['tar', '-xjf', tarball])
+
+    with bot.BuildStep('execute tests'):
+      uri = "%s/%s" % (GCS_BUCKET, recording)
+      uri_out = "%s/%s" % (GCS_BUCKET, recording_out)
+      run([GSUTIL, 'cp', uri, recording])
+      run(['python', execute_testcases_py, recording, recording_out])
+      run([GSUTIL, 'cp', recording_out, uri_out])
+      run([GSUTIL, 'setacl', 'public-read', uri_out])
+
+    with bot.BuildStep('execute checked_tests'):
+      uri = "%s/%s" % (GCS_BUCKET, checked_recording)
+      uri_out = "%s/%s" % (GCS_BUCKET, checked_recording_out)
+      run([GSUTIL, 'cp', uri, checked_recording])
+      run(['python', execute_testcases_py, checked_recording,
+           checked_recording_out])
+      run([GSUTIL, 'cp', recording_out, uri_out])
+      run([GSUTIL, 'setacl', 'public-read', uri_out])
+  finally:
+    for path in temporary_files:
+      if os.path.exists(path):
+        os.remove(path)
+
+def main():
+  name, is_buildbot = bot.GetBotName()
 
   cross_vm_pattern_match = re.match(CROSS_VM, name)
   target_vm_pattern_match = re.match(TARGET_VM, name)
   if cross_vm_pattern_match:
     arch = cross_vm_pattern_match.group(1)
     mode = cross_vm_pattern_match.group(2)
-
-    bot.Clobber()
-    with bot.BuildStep('Build %s %s' % (arch, mode)):
-      args = [sys.executable, build_py,
-              '-m%s' % mode, '--arch=%s' % arch, 'runtime']
-      run(args)
-
-    tarball = 'cross_build_%s_%s.tar.bz2' % (arch, mode)
-    try:
-      with bot.BuildStep('Create build tarball'):
-        run(['tar', '-cjf', tarball, '--exclude=**/obj',
-             '--exclude=**/obj.host', '--exclude=**/obj.target',
-             '--exclude=**/*analyzer*', 'out/'])
-
-      with bot.BuildStep('Upload build tarball'):
-        uri = "%s/%s" % (GCS_BUCKET, tarball)
-        run([GSUTIL, 'cp', tarball, uri])
-        run([GSUTIL, 'setacl', 'public-read', uri])
-    finally:
-      if os.path.exists(tarball):
-        os.remove(tarball)
+    cross_compiling_builder(arch, mode)
   elif target_vm_pattern_match:
     arch = target_vm_pattern_match.group(1)
     mode = target_vm_pattern_match.group(2)
-
-    bot.Clobber()
-    tarball = 'cross_build_%s_%s.tar.bz2' % (arch, mode)
-    try:
-      test_args = [sys.executable, test_py, '--progress=line', '--report',
-              '--time', '--mode=' + mode, '--arch=' + arch, '--compiler=none',
-              '--runtime=vm', '--write-debug-log']
-
-      with bot.BuildStep('Fetch build tarball'):
-        run([GSUTIL, 'cp', "%s/%s" % (GCS_BUCKET, tarball), tarball])
-
-      with bot.BuildStep('Unpack build tarball'):
-        run(['tar', '-xjf', tarball])
-
-      with bot.BuildStep('tests'):
-        run(test_args)
-
-      with bot.BuildStep('checked_tests'):
-        run(test_args + ['--checked'])
-    finally:
-      if os.path.exists(tarball):
-        os.remove(tarball)
+    target_builder(arch, mode)
   else:
     raise Exception("Unknown builder name %s" % name)
 
 if __name__ == '__main__':
-  sys.exit(main())
+  try:
+    sys.exit(main())
+  except OSError as e:
+    sys.exit(e.errno)
diff --git a/tools/create_sdk.py b/tools/create_sdk.py
index c2c5cd0..d157268 100755
--- a/tools/create_sdk.py
+++ b/tools/create_sdk.py
@@ -38,7 +38,6 @@
 # ......math/
 # ......mdv_observe_impl/
 # ......mirrors/
-# ......uri/
 # ......utf/
 # ......typed_data/
 # ....packages/
@@ -205,7 +204,7 @@
   os.makedirs(LIB)
 
   #
-  # Create and populate lib/{core, crypto, isolate, json, uri, utf, ...}.
+  # Create and populate lib/{core, crypto, isolate, json, utf, ...}.
   #
 
   os.makedirs(join(LIB, 'html'))
@@ -221,7 +220,7 @@
                   join('indexed_db', 'dart2js'), join('indexed_db', 'dartium'),
                   'json', 'math', 'mdv_observe_impl', 'mirrors', 'typed_data',
                   join('svg', 'dart2js'), join('svg', 'dartium'),
-                  'uri', 'utf',
+                  'utf',
                   join('web_audio', 'dart2js'), join('web_audio', 'dartium'),
                   join('web_gl', 'dart2js'), join('web_gl', 'dartium'),
                   join('web_sql', 'dart2js'), join('web_sql', 'dartium')]:
diff --git a/tools/dom/docs/docs.json b/tools/dom/docs/docs.json
index 4a34c77..3ba329e 100644
--- a/tools/dom/docs/docs.json
+++ b/tools/dom/docs/docs.json
@@ -590,12 +590,12 @@
           "   *",
           "   *     var request = new HttpRequest();",
           "   *     request.open('GET', 'http://dartlang.org')",
-          "   *     request.on.load.add((event) => print('Request complete'));",
+          "   *     request.onLoad.add((event) => print('Request complete'));",
           "   *",
           "   * is the (more verbose) equivalent of",
           "   *",
-          "   *     var request = new HttpRequest.get('http://dartlang.org',",
-          "   *         (event) => print('Request complete'));",
+          "   *     HttpRequest.getString('http://dartlang.org').then(",
+          "   *         (result) => print('Request complete: $result'));",
           "   */"
         ]
       }
diff --git a/tools/dom/dom.json b/tools/dom/dom.json
index 4c2dc62..c01a78f 100644
--- a/tools/dom/dom.json
+++ b/tools/dom/dom.json
@@ -115,6 +115,7 @@
   "AudioContext": {
     "comment": "https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html#AudioContext-section",
     "members": {
+      "AudioContext": {},
       "activeSourceCount": {},
       "createAnalyser": {},
       "createBiquadFilter": {},
@@ -280,6 +281,7 @@
   "Blob": {
     "comment": "http://www.w3.org/TR/FileAPI/#dfn-Blob",
     "members": {
+      "Blob": {},
       "size": {},
       "slice": {},
       "type": {}
@@ -1062,6 +1064,9 @@
     "comment": "http://www.w3.org/TR/XMLHttpRequest2/#interface-formdata",
     "members": {
       "DOMFormData": {},
+      "FormData": {
+        "support_level": "untriaged"
+      },
       "append": {}
     },
     "support_level": "stable"
@@ -1151,6 +1156,9 @@
     "comment": "http://developer.apple.com/library/safari/#documentation/DataManagement/Reference/DOMWindowAdditionsReference/DOMWindowAdditions/DOMWindowAdditions.html",
     "members": {
       "DOMPoint": {},
+      "_DomPoint": {
+        "support_level": "untriaged"
+      },
       "x": {},
       "y": {}
     },
@@ -5653,6 +5661,7 @@
   "MutationObserver": {
     "comment": "http://www.w3.org/TR/domcore/#interface-mutationobserver",
     "members": {
+      "MutationObserver": {},
       "_observe": {},
       "disconnect": {},
       "observe": {},
@@ -11593,6 +11602,9 @@
     "members": {
       "DONE": {},
       "HEADERS_RECEIVED": {},
+      "HttpRequest": {
+        "support_level": "untriaged"
+      },
       "LOADING": {},
       "OPENED": {},
       "UNSENT": {},
diff --git a/tools/dom/dom.py b/tools/dom/dom.py
index 793764c..f4a5c85 100755
--- a/tools/dom/dom.py
+++ b/tools/dom/dom.py
@@ -183,7 +183,8 @@
   'test_docs': [test_docs, 'Tests docs.dart'],
   'test_chrome': [test_chrome, 'Run tests in checked mode in Chrome.\n'
       '\t\tOptionally provide name of test to run.'],
-  'test_drt': [test_drt, 'Run tests in checked mode in DumpRenderTree.\n'
+  # TODO(antonm): fix option name.
+  'test_drt': [test_drt, 'Run tests in checked mode in content shell.\n'
       '\t\tOptionally provide name of test to run.'],
   'test_ff': [test_ff, 'Run tests in checked mode in Firefox.\n'
       '\t\tOptionally provide name of test to run.'],
diff --git a/tools/dom/scripts/generator.py b/tools/dom/scripts/generator.py
index 17db760..73bf90e 100644
--- a/tools/dom/scripts/generator.py
+++ b/tools/dom/scripts/generator.py
@@ -84,6 +84,12 @@
 
     'NodeList': 'NodeList,RadioNodeList',
 
+    'RTCPeerConnection': 'RTCPeerConnection,mozRTCPeerConnection',
+
+    'RTCIceCandidate': 'RTCIceCandidate,mozRTCIceCandidate',
+
+    'RTCSessionDescription': 'RTCSessionDescription,mozRTCSessionDescription',
+
     'TransitionEvent': 'TransitionEvent,WebKitTransitionEvent',
 
     'WheelEvent': 'WheelEvent,MouseWheelEvent,MouseScrollEvent',
@@ -357,6 +363,12 @@
           right_bracket)
     return ', '.join(argtexts)
 
+  def NumberOfRequiredInDart(self):
+    """ Returns a number of required arguments in Dart declaration of
+    the operation.
+    """
+    return len(filter(lambda i: not i.is_optional, self.param_infos))
+
   def ParametersAsArgumentList(self, parameter_count=None):
     """Returns a string of the parameter names suitable for passing the
     parameters as arguments.
diff --git a/tools/dom/scripts/htmldartgenerator.py b/tools/dom/scripts/htmldartgenerator.py
index 266bc20..26aab5a 100644
--- a/tools/dom/scripts/htmldartgenerator.py
+++ b/tools/dom/scripts/htmldartgenerator.py
@@ -198,14 +198,17 @@
       self.EmitOperation(info, method_name)
 
   def _GenerateOverloadDispatcher(self,
+      info,
       signatures,
       is_void,
-      parameter_names,
       declaration,
       generate_call,
       is_optional,
       can_omit_type_check=lambda type, pos: False):
 
+    parameter_names = [p.name for p in info.param_infos]
+    number_of_required_in_dart = info.NumberOfRequiredInDart()
+
     body_emitter = self._members_emitter.Emit(
         '\n'
         '  $DECLARATION {\n'
@@ -246,13 +249,8 @@
         elif not can_omit_type_check(test_type, i):
           checks.append('(%s is %s || %s == null)' % (
               parameter_name, test_type, parameter_name))
-        else:
-          for signature in signatures:
-            if (len(signature) <= i or signature[i].id not in
-                parameter_name.split('_OR_')):
-
-              checks.append('?%s' % parameter_name)
-              break
+        elif i >= number_of_required_in_dart:
+          checks.append('?%s' % parameter_name)
 
       # There can be multiple presence checks.  We need them all since a later
       # optional argument could have been passed by name, leaving 'holes'.
@@ -307,8 +305,8 @@
       GenerateCall(0, argument_count, [])
 
   def _GenerateDispatcherBody(self,
+      info,
       operations,
-      parameter_names,
       declaration,
       generate_call,
       is_optional,
@@ -324,9 +322,9 @@
       return is_optional(operations[signature_index], argument)
 
     self._GenerateOverloadDispatcher(
+        info,
         [operation.arguments for operation in operations],
         operations[0].type.id == 'void',
-        parameter_names,
         declaration,
         GenerateCall,
         IsOptional,
@@ -437,9 +435,9 @@
       constructor_full_name = constructor_info._ConstructorFullName(
           self._DartType)
       self._GenerateOverloadDispatcher(
+          constructor_info,
           constructor_info.idl_args,
           False,
-          [info.name for info in constructor_info.param_infos],
           emitter.Format('$(METADATA)$FACTORY_KEYWORD $CTOR($PARAMS)',
             FACTORY_KEYWORD=('factory' if not custom_factory_ctr else
                 'static %s' % constructor_full_name),
diff --git a/tools/dom/scripts/systemhtml.py b/tools/dom/scripts/systemhtml.py
index ada9609..9c75488 100644
--- a/tools/dom/scripts/systemhtml.py
+++ b/tools/dom/scripts/systemhtml.py
@@ -1012,8 +1012,8 @@
         html_name,
         info.ParametersDeclaration(InputType))
     self._GenerateDispatcherBody(
+        info,
         operations,
-        parameter_names,
         declaration,
         GenerateCall,
         lambda _, argument: IsOptional(argument),
diff --git a/tools/dom/scripts/systemnative.py b/tools/dom/scripts/systemnative.py
index fb659f4..9b4b677 100644
--- a/tools/dom/scripts/systemnative.py
+++ b/tools/dom/scripts/systemnative.py
@@ -241,8 +241,12 @@
     if 'CustomConstructor' not in self._interface.ext_attrs:
         return False
 
+    annotations = self._metadata.GetFormattedMetadata(self._library_name,
+        self._interface, self._interface.id, '  ')
+
     self._members_emitter.Emit(
-        '  factory $CTOR($PARAMS) => _create($FACTORY_PARAMS);\n',
+        '\n  $(ANNOTATIONS)factory $CTOR($PARAMS) => _create($FACTORY_PARAMS);\n',
+        ANNOTATIONS=annotations,
         CTOR=constructor_info._ConstructorFullName(self._DartType),
         PARAMS=constructor_info.ParametersDeclaration(self._DartType),
         FACTORY_PARAMS= \
@@ -557,14 +561,15 @@
       if not is_custom:
         self._GenerateOperationNativeCallback(operation, operation.arguments, cpp_callback_name)
     else:
-      self._GenerateDispatcher(info.operations, dart_declaration, [info.name for info in info.param_infos])
+      self._GenerateDispatcher(info, info.operations, dart_declaration)
 
-  def _GenerateDispatcher(self, operations, dart_declaration, parameter_names):
+  def _GenerateDispatcher(self, info, operations, dart_declaration):
 
     def GenerateCall(
         stmts_emitter, call_emitter, version, operation, argument_count):
       overload_name = '_%s_%s' % (operation.id, version)
-      argument_list = ', '.join(parameter_names[:argument_count])
+      argument_list = ', '.join(
+          [p.name for p in info.param_infos[:argument_count]])
       call_emitter.Emit('$NAME($ARGS)', NAME=overload_name, ARGS=argument_list)
 
       dart_declaration = '%s%s %s(%s)' % (
@@ -577,8 +582,8 @@
       self._GenerateOperationNativeCallback(operation, operation.arguments[:argument_count], cpp_callback_name)
 
     self._GenerateDispatcherBody(
+        info,
         operations,
-        parameter_names,
         dart_declaration,
         GenerateCall,
         self._IsArgumentOptionalInWebCore)
diff --git a/tools/dom/src/AttributeMap.dart b/tools/dom/src/AttributeMap.dart
index 6c96bc9..b0cb0cc 100644
--- a/tools/dom/src/AttributeMap.dart
+++ b/tools/dom/src/AttributeMap.dart
@@ -70,6 +70,11 @@
   }
 
   /**
+   * Returns true if there is at least one {key, value} pair in the map.
+   */
+  bool get isNotEmpty => !isEmpty;
+
+  /**
    * Checks to see if the node should be included in this map.
    */
   bool _matches(Node node);
@@ -216,6 +221,8 @@
   // TODO: Use lazy iterator when it is available on Map.
   bool get isEmpty => length == 0;
 
+  bool get isNotEmpty => !isEmpty;
+
   // Helpers.
   String _attr(String key) => 'data-$key';
   bool _matches(String key) => key.startsWith('data-');
diff --git a/tools/dom/src/EventStreamProvider.dart b/tools/dom/src/EventStreamProvider.dart
index 303a4e8..d19ab14 100644
--- a/tools/dom/src/EventStreamProvider.dart
+++ b/tools/dom/src/EventStreamProvider.dart
@@ -117,6 +117,9 @@
   /**
    * Gets a [Stream] for this event type, on the specified target.
    *
+   * This will always return a broadcast stream so multiple listeners can be
+   * used simultaneously.
+   *
    * This may be used to capture DOM events:
    *
    *     Element.keyDownEvent.forTarget(element, useCapture: true).listen(...);
diff --git a/tools/dom/src/PathObserver.dart b/tools/dom/src/PathObserver.dart
index bf687cb..b0eda5f 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(onListen: _observe, onCancel: _unobserve);
+    _values = new StreamController.broadcast(onListen: _observe,
+                                             onCancel: _unobserve);
 
     if (_isValid) {
       var segments = [];
diff --git a/tools/dom/src/native_DOMImplementation.dart b/tools/dom/src/native_DOMImplementation.dart
index 9b1233b..65c918e 100644
--- a/tools/dom/src/native_DOMImplementation.dart
+++ b/tools/dom/src/native_DOMImplementation.dart
@@ -139,6 +139,7 @@
   Iterable<String> get values => Maps.getValues(this);
   int get length => Maps.length(this);
   bool get isEmpty => Maps.isEmpty(this);
+  bool get isNotEmpty => Maps.isNotEmpty(this);
 }
 
 final Future<SendPort> __HELPER_ISOLATE_PORT =
diff --git a/tools/dom/templates/html/dart2js/html_dart2js.darttemplate b/tools/dom/templates/html/dart2js/html_dart2js.darttemplate
index 2a20d31..64629ed 100644
--- a/tools/dom/templates/html/dart2js/html_dart2js.darttemplate
+++ b/tools/dom/templates/html/dart2js/html_dart2js.darttemplate
@@ -74,7 +74,7 @@
 HtmlDocument get document => JS('HtmlDocument', 'document');
 
 Element query(String selector) => document.query(selector);
-List<Element> queryAll(String selector) => document.queryAll(selector);
+ElementList queryAll(String selector) => document.queryAll(selector);
 
 // Workaround for tags like <cite> that lack their own Element subclass --
 // Dart issue 1990.
diff --git a/tools/dom/templates/html/dart2js/impl_RTCIceCandidate.darttemplate b/tools/dom/templates/html/dart2js/impl_RTCIceCandidate.darttemplate
index ce3ebd7..6090f90 100644
--- a/tools/dom/templates/html/dart2js/impl_RTCIceCandidate.darttemplate
+++ b/tools/dom/templates/html/dart2js/impl_RTCIceCandidate.darttemplate
@@ -6,7 +6,13 @@
 
 $(ANNOTATIONS)class $CLASSNAME$EXTENDS$IMPLEMENTS$NATIVESPEC {
   factory $CLASSNAME(Map dictionary) {
-    return JS('RtcIceCandidate', 'new RTCIceCandidate(#)',
+    // TODO(efortuna): Remove this check if when you can actually construct with
+    // the unprefixed RTCIceCandidate in Firefox (currently both are defined,
+    // but one can't be used as a constructor).
+    var constructorName = JS('', 'window[#]',
+        Device.isFirefox ? '${Device.propertyPrefix}RTCIceCandidate' : 
+        'RTCIceCandidate');
+    return JS('RtcIceCandidate', 'new #(#)', constructorName,
         convertDartToNative_SerializedScriptValue(dictionary));
   }
 $!MEMBERS
diff --git a/tools/dom/templates/html/dart2js/impl_RTCSessionDescription.darttemplate b/tools/dom/templates/html/dart2js/impl_RTCSessionDescription.darttemplate
index f9b879e..6dd65b4 100644
--- a/tools/dom/templates/html/dart2js/impl_RTCSessionDescription.darttemplate
+++ b/tools/dom/templates/html/dart2js/impl_RTCSessionDescription.darttemplate
@@ -6,7 +6,14 @@
 
 $(ANNOTATIONS)class $CLASSNAME$EXTENDS$IMPLEMENTS$NATIVESPEC {
   factory $CLASSNAME(Map dictionary) {
-    return JS('RtcSessionDescription', 'new RTCSessionDescription(#)',
+    // TODO(efortuna): Remove this check if when you can actually construct with
+    // the unprefixed RTCIceCandidate in Firefox (currently both are defined,
+    // but one can't be used as a constructor).
+    var constructorName = JS('', 'window[#]',
+        Device.isFirefox ? '${Device.propertyPrefix}RTCSessionDescription' : 
+       'RTCSessionDescription');
+    return JS('RtcSessionDescription', 
+        'new #(#)', constructorName,
         convertDartToNative_SerializedScriptValue(dictionary));
   }
 $!MEMBERS
diff --git a/tools/dom/templates/html/dartium/html_dartium.darttemplate b/tools/dom/templates/html/dartium/html_dartium.darttemplate
index 3e020a0..24323cb 100644
--- a/tools/dom/templates/html/dartium/html_dartium.darttemplate
+++ b/tools/dom/templates/html/dartium/html_dartium.darttemplate
@@ -80,7 +80,7 @@
 
 
 Element query(String selector) => document.query(selector);
-List<Element> queryAll(String selector) => document.queryAll(selector);
+ElementList queryAll(String selector) => document.queryAll(selector);
 
 int _getNewIsolateId() => _Utils._getNewIsolateId();
 
diff --git a/tools/dom/templates/html/impl/impl_IDBFactory.darttemplate b/tools/dom/templates/html/impl/impl_IDBFactory.darttemplate
index 842b6f4..6b2501b 100644
--- a/tools/dom/templates/html/impl/impl_IDBFactory.darttemplate
+++ b/tools/dom/templates/html/impl/impl_IDBFactory.darttemplate
@@ -56,7 +56,14 @@
       if (onBlocked != null) {
         request.onBlocked.listen(onBlocked);
       }
-      return _completeRequest(request);
+      var completer = new Completer.sync();
+      request.onSuccess.listen((e) {
+        completer.complete(this);
+      });
+      request.onError.listen((e) {
+        completer.completeError(e);
+      });
+      return completer.future;
     } catch (e, stacktrace) {
       return new Future.error(e, stacktrace);
     }
diff --git a/tools/dom/templates/html/impl/impl_RTCPeerConnection.darttemplate b/tools/dom/templates/html/impl/impl_RTCPeerConnection.darttemplate
index 46dcc37..1184bd0 100644
--- a/tools/dom/templates/html/impl/impl_RTCPeerConnection.darttemplate
+++ b/tools/dom/templates/html/impl/impl_RTCPeerConnection.darttemplate
@@ -29,11 +29,12 @@
     // Currently in Firefox some of the RTC elements are defined but throw an
     // error unless the user has specifically enabled them in their
     // about:config. So we have to construct an element to actually test if RTC
-    // is supported at at the given time.
+    // is supported at the given time. 
     try {
-      var c = new RtcPeerConnection({"iceServers": [ {"url":"stun:foo.com"}]});
-      return c is RtcPeerConnection;
-    } catch (_) {}
+      new RtcPeerConnection(
+          {"iceServers": [ {"url":"stun:localhost"}]});
+      return true;
+    } catch (_) { return false;}
     return false;
   }
 $else
@@ -56,5 +57,3 @@
   }
 $!MEMBERS
 }
-
-
diff --git a/tools/dom/templates/html/impl/impl_Storage.darttemplate b/tools/dom/templates/html/impl/impl_Storage.darttemplate
index d043abe..b454b53 100644
--- a/tools/dom/templates/html/impl/impl_Storage.darttemplate
+++ b/tools/dom/templates/html/impl/impl_Storage.darttemplate
@@ -78,5 +78,7 @@
   int get length => $dom_length;
 
   bool get isEmpty => $dom_key(0) == null;
+
+  bool get isNotEmpty => !isEmpty;
 $!MEMBERS
 }
diff --git a/tools/execute_recorded_testcases.py b/tools/execute_recorded_testcases.py
new file mode 100755
index 0000000..f307277
--- /dev/null
+++ b/tools/execute_recorded_testcases.py
@@ -0,0 +1,67 @@
+#!/usr/bin/env python
+
+import sys
+import json
+import subprocess
+import time
+import threading
+
+def run_command(name, executable, arguments, timeout_in_seconds):
+  print "Running %s: '%s'" % (name, [executable] + arguments)
+
+  # The timeout_handler will set this to True if the command times out.
+  timeout_value = {'did_timeout' : False}
+
+  start = time.time()
+
+  process = subprocess.Popen([executable] + arguments,
+                             stdout=subprocess.PIPE,
+                             stderr=subprocess.PIPE)
+  def timeout_handler():
+    timeout_value['did_timeout'] = True
+    process.kill()
+  timer = threading.Timer(timeout_in_seconds, timeout_handler)
+  timer.start()
+
+  stdout, stderr = process.communicate()
+  exit_code = process.wait()
+  timer.cancel()
+
+  end = time.time()
+
+  return (exit_code, stdout, stderr, end - start, timeout_value['did_timeout'])
+
+def main(args):
+  recording_file = args[0]
+  result_file = args[1]
+
+  with open(recording_file) as fd:
+    test_cases = json.load(fd)
+
+  for test_case in test_cases:
+    name = test_case['name']
+    command = test_case['command']
+    executable = command['executable']
+    arguments = command['arguments']
+    timeout_limit = command['timeout_limit']
+
+    exit_code, stdout, stderr, duration, did_timeout = (
+        run_command(name, executable, arguments, timeout_limit))
+
+    test_case['command_output'] = {
+      'exit_code' : exit_code,
+      'stdout' : stdout,
+      'stderr' : stderr,
+      'duration' : duration,
+      'did_timeout' : did_timeout,
+    }
+  with open(result_file, 'w') as fd:
+    json.dump(test_cases, fd)
+
+if __name__ == '__main__':
+  if len(sys.argv) != 3:
+    print >> sys.stderr, ("Usage: %s <input-file.json> <output-file.json>"
+                          % sys.argv[0])
+    sys.exit(1)
+  sys.exit(main(sys.argv[1:]))
+
diff --git a/tools/get_archive.py b/tools/get_archive.py
index e919267..e7ab03d 100755
--- a/tools/get_archive.py
+++ b/tools/get_archive.py
@@ -4,7 +4,7 @@
 # for details. All rights reserved. Use of this source code is governed by a
 # BSD-style license that can be found in the LICENSE file.
 
-# Gets or updates a DumpRenderTree (a nearly headless build of chrome). This is
+# Gets or updates a content shell (a nearly headless build of chrome). This is
 # used for running browser tests of client applications.
 
 import json
@@ -113,7 +113,7 @@
   if not HasBotoConfig():
     print >>sys.stderr, '''
 *******************************************************************************
-* WARNING: Can't download DumpRenderTree! This is required to test client apps.
+* WARNING: Can't download content shell! This is required to test client apps.
 * You need to do a one-time configuration step to access Google Storage.
 * Please run this command and follow the instructions:
 *     %s config
@@ -347,7 +347,7 @@
     GetSdkRevision('sdk', SDK_DIR, SDK_VERSION, SDK_LATEST_PATTERN,
         SDK_PERMANENT, args.revision)
   elif positional[0] == 'drt':
-    GetDartiumRevision('DumpRenderTree', DRT_DIR, DRT_VERSION,
+    GetDartiumRevision('content_shell', DRT_DIR, DRT_VERSION,
                          DRT_LATEST_PATTERN, DRT_PERMANENT_PATTERN,
                          args.revision)
     CopyDrtFont(DRT_DIR)
diff --git a/tools/test.dart b/tools/test.dart
index 089a721..781ae2c 100755
--- a/tools/test.dart
+++ b/tools/test.dart
@@ -26,11 +26,12 @@
 
 import "dart:async";
 import "dart:io";
-import "testing/dart/test_runner.dart";
-import "testing/dart/test_options.dart";
-import "testing/dart/test_suite.dart";
-import "testing/dart/test_progress.dart";
 import "testing/dart/http_server.dart";
+import "testing/dart/record_and_replay.dart";
+import "testing/dart/test_options.dart";
+import "testing/dart/test_progress.dart";
+import "testing/dart/test_runner.dart";
+import "testing/dart/test_suite.dart";
 import "testing/dart/utils.dart";
 
 import "../compiler/tests/dartc/test_config.dart";
@@ -87,6 +88,27 @@
   var printTiming = firstConf['time'];
   var listTests = firstConf['list'];
 
+  var recordingPath = firstConf['record_to_file'];
+  var recordingOutputPath = firstConf['replay_from_file'];
+
+  if (recordingPath != null && recordingOutputPath != null) {
+    print("Fatal: Can't have the '--record_to_file' and '--replay_from_file'"
+          "at the same time. Exiting ...");
+    exit(1);
+  }
+
+  var testCaseRecorder;
+  if (recordingPath != null) {
+    testCaseRecorder = new TestCaseRecorder(new Path(recordingPath));
+  }
+
+  var testCaseOutputArchive;
+  if (recordingOutputPath != null) {
+      testCaseOutputArchive = new TestCaseOutputArchive();
+      testCaseOutputArchive.loadFromPath(new Path(recordingOutputPath));
+  }
+
+
   if (!firstConf['append_logs'])  {
     var file = new File(TestUtils.flakyFileName());
     if (file.existsSync()) {
@@ -145,9 +167,16 @@
       if (key == 'co19') {
         testSuites.add(new Co19TestSuite(conf));
       } else if (conf['runtime'] == 'vm' && key == 'vm') {
-        // vm tests contain both cc tests (added here) and dart tests (added in
-        // [TEST_SUITE_DIRECTORIES]).
-        testSuites.add(new VMTestSuite(conf));
+        // 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));
+        }
       } else if (conf['analyzer']) {
         if (key == 'dartc' && conf['compiler'] == 'dartc') {
           testSuites.add(new JUnitDartcTestSuite(conf));
@@ -216,6 +245,7 @@
   }
   eventListener.add(new ExitCodeSetter());
 
+
   void startProcessQueue() {
     // Start process queue.
     new ProcessQueue(maxProcesses,
@@ -225,7 +255,9 @@
                      eventListener,
                      allTestsFinished,
                      verbose,
-                     listTests);
+                     listTests,
+                     testCaseRecorder,
+                     testCaseOutputArchive);
   }
 
   // Start all the HTTP servers required before starting the process queue.
diff --git a/tools/testing/dart/browser_controller.dart b/tools/testing/dart/browser_controller.dart
index 911d86d..9b5e966 100644
--- a/tools/testing/dart/browser_controller.dart
+++ b/tools/testing/dart/browser_controller.dart
@@ -37,6 +37,8 @@
    */
   Process process;
 
+  Function logger;
+
   /**
    * Id of the browser
    */
@@ -46,11 +48,15 @@
   Function onClose;
 
   /** Print everything (stdout, stderr, usageLog) whenever we add to it */
-  bool debugPrint = true;
+  bool debugPrint = false;
+
+  // We use this to gracefully handle double calls to close.
+  bool underTermination = false;
 
   void _logEvent(String event) {
     String toLog = "$this ($id) - ${new DateTime.now()}: $event \n";
     if (debugPrint) print("usageLog: $toLog");
+    if (logger != null) logger(toLog);
     _usageLog.write(toLog);
   }
 
@@ -119,6 +125,11 @@
   /** Close the browser */
   Future<bool> close() {
     _logEvent("Close called on browser");
+    if (underTermination) {
+      _logEvent("Browser already under termination.");
+      return new Future.immediate(true);
+    }
+    underTermination = true;
     if (process == null) {
       _logEvent("No process open, nothing to kill.");
       return new Future.immediate(true);
@@ -178,6 +189,102 @@
   Future<bool> start(String url);
 }
 
+class Safari extends Browser {
+  /**
+   * The binary used to run safari - changing this can be nececcary for
+   * testing or using non standard safari installation.
+   */
+  const String binary = "/Applications/Safari.app/Contents/MacOS/Safari";
+
+  /**
+   * We get the safari version by parsing a version file
+   */
+  const String versionFile = "/Applications/Safari.app/Contents/version.plist";
+
+
+  Future<bool> allowPopUps() {
+    var command = "defaults";
+    var args = ["write", "com.apple.safari",
+                "com.apple.Safari.ContentPageGroupIdentifier."
+                "WebKit2JavaScriptCanOpenWindowsAutomatically",
+                "1"];
+    return Process.run(command, args).then((result) {
+        if (result.exitCode != 0) {
+          _logEvent("Could not disable pop-up blocking for safari");
+          return false;
+        }
+        return true;
+    });
+  }
+
+  Future<String> getVersion() {
+    /**
+     * Example of the file:
+     * <?xml version="1.0" encoding="UTF-8"?>
+     * <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+     * <plist version="1.0">
+     * <dict>
+     *	     <key>BuildVersion</key>
+     * 	     <string>2</string>
+     * 	     <key>CFBundleShortVersionString</key>
+     * 	     <string>6.0.4</string>
+     * 	     <key>CFBundleVersion</key>
+     * 	     <string>8536.29.13</string>
+     * 	     <key>ProjectName</key>
+     * 	     <string>WebBrowser</string>
+     * 	     <key>SourceVersion</key>
+     * 	     <string>7536029013000000</string>
+     * </dict>
+     * </plist>
+     */
+    File f = new File(versionFile);
+    return f.readAsLines().then((content) {
+      bool versionOnNextLine = false;
+      for (var line in content) {
+        if (versionOnNextLine) return line;
+        if (line.contains("CFBundleShortVersionString")) {
+          versionOnNextLine = true;
+        }
+      }
+      return null;
+    });
+  }
+
+  void _createLaunchHTML(var path, var url) {
+    var file = new File("${path}/launch.html");
+    var randomFile = file.openSync(FileMode.WRITE);
+    var content = '<script language="JavaScript">location = "$url"</script>';
+    randomFile.writeStringSync(content);
+    randomFile.close();
+  }
+
+  Future<bool> start(String url) {
+    _logEvent("Starting Safari browser on: $url");
+    // Get the version and log that.
+    return allowPopUps().then((success) {
+      if (!success) {
+        return new Future.immediate(false);
+      }
+      return getVersion().then((version) {
+        _logEvent("Got version: $version");
+        var args = ["'$url'"];
+        return new Directory('').createTemp().then((userDir) {
+          _cleanup = () { userDir.delete(recursive: true); };
+          _createLaunchHTML(userDir.path, url);
+          var args = ["${userDir.path}/launch.html"];
+          return startBrowser(binary, args);
+        });
+      }).catchError((e) {
+        _logEvent("Running $binary --version failed with $e");
+        return false;
+      });
+    });
+  }
+
+  String toString() => "Safari";
+}
+
+
 class Chrome extends Browser {
   /**
    * The binary used to run chrome - changing this can be nececcary for
@@ -235,21 +342,11 @@
     var turnScreenOnIntent =
         new Intent(mainAction, turnScreenOnPackage, '.Main');
 
-    // FIXME(kustermann): Remove this hack as soon as we've got a v8 mirror in
-    // golo
     var testing_resources_dir =
         new Path('third_party/android_testing_resources');
-    var testing_resources_dir_tmp = 
-        new Path('/tmp/android_testing_resources');
     if (!new Directory.fromPath(testing_resources_dir).existsSync()) {
-      DebugLogger.warning("$testing_resources_dir doesn't exist, "
-                          "trying to use $testing_resources_dir_tmp");
-      testing_resources_dir = testing_resources_dir_tmp;
-      if (!new Directory.fromPath(testing_resources_dir).existsSync()) {
-        DebugLogger.error("$testing_resources_dir_tmp doesn't exist either. "
-                          " This is a fatal error. Exiting now.");
-        exit(1);
-      }
+      DebugLogger.error("$testing_resources_dir doesn't exist. Exiting now.");
+      exit(1);
     }
 
     var chromeAPK = testing_resources_dir.append('com.android.chrome-1.apk');
@@ -392,6 +489,8 @@
   String local_ip;
   String browserName;
   int maxNumBrowsers;
+  // Used to send back logs from the browser (start, stop etc)
+  Function logger;
 
   bool underTermination = false;
 
@@ -518,6 +617,9 @@
         print("could not kill browser $id");
         return;
       }
+      // We don't want to start a new browser if we are terminating.
+      if (underTermination) return;
+
       var browser;
       if (browserName == 'chromeOnAndroid') {
         browser = new AndroidChrome(adbDeviceMapping[id]);
@@ -607,13 +709,18 @@
   }
 
   Browser getInstance() {
+    var browser;
     if (browserName == "chrome") {
-      return new Chrome();
+      browser = new Chrome();
     } else if (browserName == "ff") {
-      return new Firefox();
+      browser = new Firefox();
+    } else if (browserName == "safari") {
+      browser = new Safari();
     } else {
       throw "Non supported browser for browser controller";
     }
+    browser.logger = logger;
+    return browser;
   }
 }
 
@@ -673,11 +780,11 @@
         request.response.write(textResponse);
         request.listen((_) {}, onDone: request.response.close);
         request.response.done.catchError((error) {
-        if (!underTermination) {
-          print("URI ${request.uri}");
-          print("Textresponse $textResponse");
-          throw("Error returning content to browser: $error");
-        }
+          if (!underTermination) {
+            print("URI ${request.uri}");
+            print("Textresponse $textResponse");
+            throw "Error returning content to browser: $error";
+          }
       });
       }
       void errorHandler(e) {
diff --git a/tools/testing/dart/drt_updater.dart b/tools/testing/dart/drt_updater.dart
index 67e1716..ea86b4a 100644
--- a/tools/testing/dart/drt_updater.dart
+++ b/tools/testing/dart/drt_updater.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+// TODO(antonm): rename to something like test_runner_updater.
+
 library drt_updater;
 
 import "dart:async";
@@ -60,18 +62,18 @@
   }
 }
 
-_DartiumUpdater _dumpRenderTreeUpdater;
+_DartiumUpdater _contentShellUpdater;
 _DartiumUpdater _dartiumUpdater;
 
 _DartiumUpdater runtimeUpdater(Map configuration) {
   String runtime = configuration['runtime'];
   if (runtime == 'drt' && configuration['drt'] == '') {
-    // Download the default DumpRenderTree from Google Storage.
-    if (_dumpRenderTreeUpdater == null) {
-      _dumpRenderTreeUpdater = new _DartiumUpdater('DumpRenderTree',
-                                                   'get_archive.py', 'drt');
+    // Download the default content shell from Google Storage.
+    if (_contentShellUpdater == null) {
+      _contentShellUpdater = new _DartiumUpdater('Content Shell',
+                                                 'get_archive.py', 'drt');
     }
-    return _dumpRenderTreeUpdater;
+    return _contentShellUpdater;
   } else if (runtime == 'dartium' && configuration['dartium'] == '') {
     // Download the default Dartium from Google Storage.
     if (_dartiumUpdater == null) {
diff --git a/tools/testing/dart/record_and_replay.dart b/tools/testing/dart/record_and_replay.dart
new file mode 100644
index 0000000..fd5df68
--- /dev/null
+++ b/tools/testing/dart/record_and_replay.dart
@@ -0,0 +1,126 @@
+// 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.
+
+library record_and_replay;
+
+import 'dart:io';
+import 'dart:json' as json;
+import 'dart:utf';
+
+import 'test_runner.dart';
+
+/*
+ * Json files look like this:
+ *
+ * [
+ *   {
+ *     'name' : '...',
+ *     'configuration' : '...',
+ *     'command' : {
+ *       'timeout_limit' : 60,
+ *       'executable' : '...',
+ *       'arguments' : ['arg1, 'arg2', '...'],
+ *     },
+ *     'command_output' : {
+ *       'exit_code' : 42,
+ *       'stdout' : '...',
+ *       'stderr' : '...',
+ *       'duration' : 1.5,
+ *       'did_timeout' : false,
+ *     },
+ *   },
+ *   ....
+ * ]
+ */
+
+
+class TestCaseRecorder {
+  Path _outputPath;
+  List<Map> _recordedCommandInvocations = [];
+  var _cwd;
+
+  TestCaseRecorder(this._outputPath) {
+    _cwd  = new Directory.current().path;
+  }
+
+  void nextTestCase(TestCase testCase) {
+    assert(testCase.commands.length == 1);
+
+    var command = testCase.commands[0];
+    assert(command.environment == null);
+
+    var arguments = [];
+    for (var rawArgument in command.arguments) {
+      if (rawArgument.startsWith(_cwd)) {
+        var relative = new Path(rawArgument).relativeTo(new Path(_cwd));
+        arguments.add(relative.toNativePath());
+      } else {
+        arguments.add(rawArgument);
+      }
+    }
+
+    var commandExecution = {
+      'name' : testCase.displayName,
+      'configuration' : testCase.configurationString,
+      'command' : {
+        'timeout_limit' : testCase.timeout,
+        'executable' : command.executable,
+        'arguments' : arguments,
+      },
+    };
+    _recordedCommandInvocations.add(commandExecution);
+  }
+
+  void finish() {
+    var file = new File.fromPath(_outputPath);
+    var jsonString = json.stringify(_recordedCommandInvocations);
+    file.writeAsStringSync(jsonString);
+    print("TestCaseRecorder: written all TestCases to ${_outputPath}");
+  }
+}
+
+class TestCaseOutputArchive {
+  Map<String, Map> _testCaseOutputRecords;
+
+  void loadFromPath(Path recordingPath) {
+    var file = new File.fromPath(recordingPath);
+    var testCases = json.parse(file.readAsStringSync());
+    _testCaseOutputRecords = {};
+    for (var testCase in testCases) {
+      var key = _indexKey(testCase['configuration'], testCase['name']);
+      _testCaseOutputRecords[key] = testCase['command_output'];
+    }
+  }
+
+  CommandOutput outputOf(TestCase testCase) {
+    var key = _indexKey(testCase.configurationString, testCase.displayName);
+    var command_output = _testCaseOutputRecords[key];
+    if (command_output == null) {
+      print("Sorry, but there is no command output for "
+            "${testCase.displayName}");
+
+      exit(42);
+    }
+
+    double seconds = command_output['duration'];
+    var duration = new Duration(seconds: seconds.round(),
+                                milliseconds: (seconds/1000).round());
+    var commandOutput = new CommandOutput.fromCase(
+        testCase,
+        testCase.commands.first,
+        command_output['exit_code'],
+        false,
+        command_output['did_timeout'],
+        encodeUtf8(command_output['stdout']),
+        encodeUtf8(command_output['stderr']),
+        duration,
+        false);
+    return commandOutput;
+  }
+
+  String _indexKey(String configuration, String name) {
+    return "${configuration}__$name";
+  }
+}
+
diff --git a/tools/testing/dart/test_options.dart b/tools/testing/dart/test_options.dart
index bda38e0..b04f731 100644
--- a/tools/testing/dart/test_options.dart
+++ b/tools/testing/dart/test_options.dart
@@ -85,6 +85,7 @@
               ['-c', '--compiler'],
               ['none', 'dart2dart', 'dart2js', 'dartc', 'dartanalyzer'],
               'none'),
+          // TODO(antonm): fix the option drt.
           new _TestOptionSpecification(
               'runtime',
               '''Where the tests should be run.
@@ -95,7 +96,7 @@
     jsshell: Run JavaScript from the command line using firefox js-shell.
 
     drt: Run Dart or JavaScript in the headless version of Chrome,
-         DumpRenderTree.
+         Content shell.
 
     dartium: Run Dart or JavaScript in Dartium.
 
@@ -113,7 +114,7 @@
               'arch',
               'The architecture to run tests for',
               ['-a', '--arch'],
-              ['all', 'ia32', 'x64', 'simarm', 'simmips'],
+              ['all', 'ia32', 'x64', 'simarm', 'simmips', 'arm'],
               'ia32'),
           new _TestOptionSpecification(
               'system',
@@ -252,8 +253,8 @@
               [],
               ''),
           new _TestOptionSpecification(
-              'drt',
-              'Path to DumpRenderTree executable',
+              'drt', // TODO(antonm): fix the option name.
+              'Path to content shell executable',
               ['--drt'],
               [],
               ''),
@@ -318,7 +319,21 @@
               'This address is also used for browsers to connect.',
               ['--local_ip'],
               [],
-              '127.0.0.1'),];
+              '127.0.0.1'),
+          new _TestOptionSpecification(
+              'record_to_file',
+              'Records all the commands that need to be executed and writes it '
+              'out to a file.',
+              ['--record_to_file'],
+              [],
+              null),
+          new _TestOptionSpecification(
+              'replay_from_file',
+              'Records all the commands that need to be executed and writes it '
+              'out to a file.',
+              ['--replay_from_file'],
+              [],
+              null),];
   }
 
 
diff --git a/tools/testing/dart/test_progress.dart b/tools/testing/dart/test_progress.dart
index 0c6b7a7..b9ce10b 100644
--- a/tools/testing/dart/test_progress.dart
+++ b/tools/testing/dart/test_progress.dart
@@ -309,6 +309,9 @@
         (FileSystemEntity fse) {
           if (fse is Directory) count++;
         },
+        onError: (error) {
+          DebugLogger.warning("Could not list temp directories, got: $error");
+        },
         onDone: () {
           if (count > MIN_NUMBER_OF_TEMP_DIRS) {
             DebugLogger.warning("There are ${count} directories "
diff --git a/tools/testing/dart/test_runner.dart b/tools/testing/dart/test_runner.dart
index 93c38e9..9169a83 100644
--- a/tools/testing/dart/test_runner.dart
+++ b/tools/testing/dart/test_runner.dart
@@ -24,6 +24,7 @@
 import "test_progress.dart";
 import "test_suite.dart";
 import "utils.dart";
+import 'record_and_replay.dart';
 
 const int NO_TIMEOUT = 0;
 const int SLOW_TIMEOUT_MULTIPLIER = 4;
@@ -180,20 +181,20 @@
   }
 }
 
-class DumpRenderTreeCommand extends Command {
+class ContentShellCommand extends Command {
   /**
-   * If [expectedOutputPath] is set, the output of DumpRenderTree is compared
+   * If [expectedOutputPath] is set, the output of content shell is compared
    * with the content of [expectedOutputPath].
    * This is used for example for pixel tests, where [expectedOutputPath] points
    * to a *png file.
    */
   io.Path expectedOutputPath;
 
-  DumpRenderTreeCommand(String executable,
-                        String htmlFile,
-                        List<String> options,
-                        List<String> dartFlags,
-                        io.Path this.expectedOutputPath)
+  ContentShellCommand(String executable,
+                      String htmlFile,
+                      List<String> options,
+                      List<String> dartFlags,
+                      io.Path this.expectedOutputPath)
       : super(executable,
               _getArguments(options, htmlFile),
               _getEnvironment(dartFlags));
@@ -392,7 +393,8 @@
   List<BrowserTestCase> observers;
 
   BrowserTestCase(displayName, commands, configuration, completedHandler,
-      expectedOutcomes, info, isNegative, [this.waitingForOtherTest = false])
+                  expectedOutcomes, info, isNegative, this._testingUrl,
+                  [this.waitingForOtherTest = false])
     : super(displayName, commands, configuration, completedHandler,
         expectedOutcomes, isNegative: isNegative, info: info) {
     numRetries = 2; // Allow two retries to compensate for flaky browser tests.
@@ -405,6 +407,8 @@
 
   List<String> get batchTestArguments => _lastArguments.sublist(1);
 
+  String _testingUrl;
+
   /** Add a test case to listen for when this current test has completed. */
   void addObserver(BrowserTestCase testCase) {
     observers.add(testCase);
@@ -419,6 +423,8 @@
       testCase.waitingForOtherTest = false;
     }
   }
+
+  String get testingUrl => _testingUrl;
 }
 
 
@@ -645,7 +651,7 @@
     }
 
     if (command.expectedOutputFile != null) {
-      // We are either doing a pixel test or a layout test with DumpRenderTree
+      // We are either doing a pixel test or a layout test with content shell
       return _failedBecauseOfUnexpectedDRTOutput;
     }
     return _browserTestFailure;
@@ -653,10 +659,10 @@
 
   bool get _failedBecauseOfMissingXDisplay {
     // Browser case:
-    // If the browser test failed, it may have been because DumpRenderTree
-    // and the virtual framebuffer X server didn't hook up, or DRT crashed with
-    // a core dump. Sometimes DRT crashes after it has set the stdout to PASS,
-    // so we have to do this check first.
+    // If the browser test failed, it may have been because content shell
+    // and the virtual framebuffer X server didn't hook up, or it crashed with
+    // a core dump. Sometimes content shell crashes after it has set the stdout
+    // to PASS, so we have to do this check first.
     var stderrLines = decodeUtf8(super.stderr).split("\n");
     for (String line in stderrLines) {
       // TODO(kustermann,ricow): Issue: 7564
@@ -677,7 +683,7 @@
 
   bool get _failedBecauseOfUnexpectedDRTOutput {
     /*
-     * The output of DumpRenderTree is different for pixel tests than for
+     * The output of content shell is different for pixel tests than for
      * layout tests.
      *
      * On a pixel test, the DRT output has the following format
@@ -1337,6 +1343,10 @@
   int _numFailedTests = 0;
   bool _allTestsWereEnqueued = false;
 
+  // Support for recording and replaying test commands.
+  TestCaseRecorder _testCaseRecorder;
+  TestCaseOutputArchive _testCaseOutputArchive;
+
   /** The number of tests we allow to actually fail before we stop retrying. */
   int _MAX_FAILED_NO_RETRY = 4;
   bool _verbose;
@@ -1380,7 +1390,9 @@
                this._eventListener,
                this._allDone,
                [bool verbose = false,
-                bool listTests = false])
+                bool listTests = false,
+                this._testCaseRecorder,
+                this._testCaseOutputArchive])
       : _verbose = verbose,
         _listTests = listTests,
         _tests = new Queue<TestCase>(),
@@ -1411,6 +1423,47 @@
   }
 
   void _runTests(List<TestSuite> testSuites) {
+    var newTest;
+    var allTestsKnown;
+
+    if (_testCaseRecorder != null) {
+      // Mode: recording.
+      newTest = _testCaseRecorder.nextTestCase;
+      allTestsKnown = () {
+        // We don't call any event*() methods, so test_progress.dart will not be
+        // notified (that's fine, since we're not running any tests).
+        _testCaseRecorder.finish();
+        _allDone();
+      };
+    } else {
+      if (_testCaseOutputArchive != null) {
+        // Mode: replaying.
+        newTest = (TestCase testCase) {
+          // We're doing this asynchronously to emulate the normal behaviour.
+          eventTestAdded(testCase);
+          Timer.run(() {
+            var output = _testCaseOutputArchive.outputOf(testCase);
+            testCase.completed();
+            eventFinishedTestCase(testCase);
+          });
+        };
+        allTestsKnown = () {
+          // If we're replaying commands, we need to call [_cleanupAndMarkDone]
+          // manually. We're putting it at the end of the event queue to make
+          // sure all the previous events were fired.
+          Timer.run(() => _cleanupAndMarkDone());
+        };
+      } else {
+        // Mode: none (we're not recording/replaying).
+        newTest = (TestCase testCase) {
+          _tests.add(testCase);
+          eventTestAdded(testCase);
+          _runTest(testCase);
+        };
+        allTestsKnown = _checkDone;
+      }
+    }
+
     // FIXME: For some reason we cannot call this method on all test suites
     // in parallel.
     // If we do, not all tests get enqueued (if --arch=all was specified,
@@ -1420,10 +1473,10 @@
     void enqueueNextSuite() {
       if (!iterator.moveNext()) {
         _allTestsWereEnqueued = true;
+        allTestsKnown();
         eventAllTestsKnown();
-        _checkDone();
       } else {
-        iterator.current.forEachTest(_runTest, _testCache, enqueueNextSuite);
+        iterator.current.forEachTest(newTest, _testCache, enqueueNextSuite);
       }
     }
     enqueueNextSuite();
@@ -1495,8 +1548,6 @@
       browserUsed = test.configuration['runtime'];
       if (_needsSelenium) _ensureSeleniumServerRunning();
     }
-    eventTestAdded(test);
-    _tests.add(test);
     _tryRunTest();
   }
 
@@ -1598,10 +1649,11 @@
   Future<BrowserTestRunner> _getBrowserTestRunner(TestCase test) {
     var local_ip = test.configuration['local_ip'];
     var runtime = test.configuration['runtime'];
-    var num_browsers = test.configuration['tasks'];
+    var num_browsers = 1;//test.configuration['tasks'];
     if (_browserTestRunners[runtime] == null) {
       var testRunner =
         new BrowserTestRunner(local_ip, runtime, num_browsers);
+      testRunner.logger = DebugLogger.info;
       _browserTestRunners[runtime] = testRunner;
       return testRunner.start().then((started) {
         if (started) {
@@ -1615,13 +1667,8 @@
   }
 
   void _startBrowserControllerTest(var test) {
-    // Get the url.
-    // TODO(ricow): This is not needed when we have eliminated selenium.
-    var nextCommandIndex = test.commandOutputs.keys.length;
-    var url = test.commands[nextCommandIndex].toString().split("--out=")[1];
-    // Remove trailing "
-    url = url.split('"')[0];
     var callback = (var output) {
+      var nextCommandIndex = test.commandOutputs.keys.length;
       new CommandOutput.fromCase(test,
                                  test.commands[nextCommandIndex],
                                  0,
@@ -1633,7 +1680,9 @@
                                  false);
       test.completedHandler(test);
     };
-    BrowserTest browserTest = new BrowserTest(url, callback, test.timeout);
+    BrowserTest browserTest = new BrowserTest(test.testingUrl,
+                                              callback,
+                                              test.timeout);
     _getBrowserTestRunner(test).then((testRunner) {
       testRunner.queueTest(browserTest);
     });
@@ -1654,7 +1703,9 @@
         print(fields.join('\t'));
         return;
       }
-      if (test.usesWebDriver && _needsSelenium && !_isSeleniumAvailable ||
+
+      if (test.usesWebDriver && _needsSelenium && !test.usesBrowserController
+          && !_isSeleniumAvailable ||
           (test is BrowserTestCase && test.waitingForOtherTest)) {
         // The test is not yet ready to run. Put the test back in
         // the queue.  Avoid spin-polling by using a timeout.
diff --git a/tools/testing/dart/test_suite.dart b/tools/testing/dart/test_suite.dart
index 38fd5ee..2a6fa18 100644
--- a/tools/testing/dart/test_suite.dart
+++ b/tools/testing/dart/test_suite.dart
@@ -517,7 +517,7 @@
   }
 
   /**
-   * If DumpRenderTree/Dartium is required, and not yet updated, waits for
+   * If Content shell/Dartium is required, and not yet updated, waits for
    * the update then completes. Otherwise completes immediately.
    */
   Future updateDartium() {
@@ -997,6 +997,7 @@
                                                  subtestNames, subtestIndex);
 
         List<String> args = <String>[];
+
         if (TestUtils.usesWebDriver(runtime)) {
           args = [
               dartDir.append('tools/testing/run_selenium.py').toNativePath(),
@@ -1018,9 +1019,10 @@
           }
 
           var dartFlags = [];
-          var dumpRenderTreeOptions = [];
+          var contentShellOptions = [];
 
-          dumpRenderTreeOptions.add('--no-timeout');
+          contentShellOptions.add('--no-timeout');
+          contentShellOptions.add('--dump-render-tree');
 
           if (compiler == 'none' || compiler == 'dart2dart') {
             dartFlags.add('--ignore-unrecognized-flags');
@@ -1034,15 +1036,15 @@
           if (expectedOutput != null) {
             if (expectedOutput.toNativePath().endsWith('.png')) {
               // pixel tests are specified by running DRT "foo.html'-p"
-              dumpRenderTreeOptions.add('--notree');
+              contentShellOptions.add('--notree');
               fullHtmlPath = "${fullHtmlPath}'-p";
             }
           }
-          commandSet.add(new DumpRenderTreeCommand(dumpRenderTreeFilename,
-                                                   fullHtmlPath,
-                                                   dumpRenderTreeOptions,
-                                                   dartFlags,
-                                                   expectedOutput));
+          commandSet.add(new ContentShellCommand(contentShellFilename,
+                                                 fullHtmlPath,
+                                                 contentShellOptions,
+                                                 dartFlags,
+                                                 expectedOutput));
         }
 
         // Create BrowserTestCase and queue it.
@@ -1053,18 +1055,20 @@
           testCase = new BrowserTestCase(testDisplayName,
               commandSet, configuration, completeHandler,
               expectations['$testName/${subtestNames[subtestIndex]}'],
-              info, info.hasCompileError || info.hasRuntimeError,
+              info, info.hasCompileError || info.hasRuntimeError, fullHtmlPath,
               subtestIndex != 0);
         } else {
           testCase = new BrowserTestCase(testDisplayName,
               commandSet, configuration, completeHandler, expectations,
-              info, info.hasCompileError || info.hasRuntimeError, false);
+              info, info.hasCompileError || info.hasRuntimeError, fullHtmlPath,
+              false);
         }
         if (subtestIndex == 0) {
           multitestParentTest = testCase;
         } else {
           multitestParentTest.addObserver(testCase);
         }
+
         doTest(testCase);
         subtestIndex++;
       } while(subtestIndex < subtestNames.length);
@@ -1172,15 +1176,15 @@
     }
   }
 
-  String get dumpRenderTreeFilename {
+  String get contentShellFilename {
     if (configuration['drt'] != '') {
       return configuration['drt'];
     }
     if (Platform.operatingSystem == 'macos') {
-      return dartDir.append('/client/tests/drt/DumpRenderTree.app/Contents/'
-                            'MacOS/DumpRenderTree').toNativePath();
+      return dartDir.append('/client/tests/drt/Content Shell.app/Contents/'
+                            'MacOS/Content Shell').toNativePath();
     }
-    return dartDir.append('client/tests/drt/DumpRenderTree').toNativePath();
+    return dartDir.append('client/tests/drt/content_shell').toNativePath();
   }
 
   String get dartiumFilename {
diff --git a/tools/testing/drt-trampoline.py b/tools/testing/drt-trampoline.py
deleted file mode 100644
index ac5b23d69..0000000
--- a/tools/testing/drt-trampoline.py
+++ /dev/null
@@ -1,147 +0,0 @@
-# Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
-# for details. All rights reserved. Use of this source code is governed by a
-# BSD-style license that can be found in the LICENSE file.
-#
-# For now we have to use this trampoline to turn --dart-flags command line
-# switch into env variable DART_FLAGS.  Eventually, DumpRenderTree should
-# support --dart-flags and this hack may go away.
-#
-# Expected invocation: python drt-trampoline.py <path to DRT> <DRT command line>
-
-import optparse
-import os
-import signal
-import subprocess
-import sys
-
-def parse_options(argv):
-  parser = optparse.OptionParser()
-  parser.add_option('--dart-flags',
-                    metavar='FLAGS',
-                    dest='dart_flags')
-  parser.add_option('--out-expectation',
-                    metavar='FILE',
-                    dest='out_expected_file')
-  parser.add_option('--package-root',
-                    metavar='DIRECTORY',
-                    dest='dart_package_root')
-  parser.add_option('--no-timeout',
-                    action='store_true')
-  return parser.parse_args(args=argv)
-
-
-def main(argv):
-  drt_path = argv[1]
-  (options, arguments) = parse_options(argv[2:])
-
-  cmd = [drt_path]
-
-  env = None
-  test_file = None
-  dart_flags = options.dart_flags
-  out_expected_file = options.out_expected_file
-  dart_package_root = options.dart_package_root
-  is_png = False
-
-  if dart_flags:
-    if not env:
-      env = dict(os.environ.items())
-    env['DART_FLAGS'] = dart_flags
-
-  if dart_package_root:
-    if not env:
-      env = dict(os.environ.items())
-    absolute_path = os.path.abspath(dart_package_root)
-    absolute_path = absolute_path.replace(os.path.sep, '/')
-    if not absolute_path.startswith('/'):
-      # Happens on Windows for C:\packages
-      absolute_path = '/%s' % absolute_path
-    env['DART_PACKAGE_ROOT'] = 'file://%s' % absolute_path
-
-  if out_expected_file:
-    if out_expected_file.endswith('.png'):
-      cmd.append('--notree')
-      is_png = True
-    elif not out_expected_file.endswith('.txt'):
-      raise Exception(
-        'Bad file expectation (%s) please specify either a .txt or a .png file'
-        % out_expected_file)
-
-  if options.no_timeout:
-    cmd.append('--no-timeout')
-
-  for arg in arguments:
-    if '.html' in arg:
-      test_file = arg
-    else:
-      cmd.append(arg)
-
-  if is_png:
-    # pixel tests are specified by running DRT "foo.html'-p"
-    cmd.append(test_file + "'-p")
-  else:
-    cmd.append(test_file)
-
-  stdout = subprocess.PIPE if out_expected_file else None
-  p = subprocess.Popen(cmd, env=env, stdout=stdout)
-
-  def signal_handler(signal, frame):
-    p.terminate()
-    sys.exit(0)
-
-  # SIGINT is Ctrl-C.
-  signal.signal(signal.SIGINT, signal_handler)
-  # SIGTERM is sent by test.dart when a process times out.
-  signal.signal(signal.SIGTERM, signal_handler)
-  output, error = p.communicate()
-  signal.signal(signal.SIGINT, signal.SIG_DFL)
-  signal.signal(signal.SIGTERM, signal.SIG_DFL)
-
-  if p.returncode != 0:
-    raise Exception('Failed to run command. return code=%s' % p.returncode)
-
-  if out_expected_file:
-    # Compare output to the given expectation file.
-    expectation = None
-    if is_png:
-      # DRT prints the image to STDOUT, but includes extra text that we trim:
-      # - several header lines until a line saying 'Content-Length:'
-      # - a '#EOF\n' at the end
-      last_header_line = output.find('Content-Length:')
-      start_pos = output.find('\n', last_header_line) + 1
-      output = output[start_pos : -len('#EOF\n')]
-    if os.path.exists(out_expected_file):
-      with open(out_expected_file, 'r') as f:
-        expectation = f.read()
-    else:
-      # Instructions on how to create the expectation will be printed below
-      # (outout != expectation)
-      print 'File %s was not found' % out_expected_file
-      expectation = None
-
-    # Report test status using the format test.dart expects to see from DRT.
-    print 'Content-Type: text/plain'
-    if expectation == output:
-      print 'PASS'
-      print 'Expectation matches'
-    else:
-      # Generate a temporary file in the same place as the .html file:
-      out_file = test_file[:test_file.rfind('.html')] + out_expected_file[-4:]
-      with open(out_file, 'w') as f:
-        f.write(output)
-      print 'FAIL'
-      print 'Expectation didn\'t match.\n'
-      if len(output) == 0:
-        print ('\033[31mERROR\033[0m: DumpRenderTree generated an empty pixel '
-            'output! This is commonly an error in executing DumpRenderTree, and'
-            ' not that expectations are out of date.\n')
-      print 'You can update expectations by running:\n'
-      print 'cp %s %s\n' % (out_file, out_expected_file)
-    print '#EOF'
-
-if __name__ == '__main__':
-  try:
-    sys.exit(main(sys.argv))
-  except StandardError as e:
-    print 'Fail: ' + str(e)
-    sys.exit(1)
diff --git a/tools/testing/legpad/example.dart b/tools/testing/legpad/example.dart
deleted file mode 100644
index 5134f16..0000000
--- a/tools/testing/legpad/example.dart
+++ /dev/null
@@ -1,6 +0,0 @@
-void main() {
-  for (int i = 0; i < 5; i++) {
-    print("i is $i");
-  }
-  print("done");
-}
\ No newline at end of file
diff --git a/tools/testing/legpad/example.sh b/tools/testing/legpad/example.sh
deleted file mode 100755
index 96cb79f..0000000
--- a/tools/testing/legpad/example.sh
+++ /dev/null
@@ -1,10 +0,0 @@
-# Sample script showing how to use legpad.
-
-# First compile "legpad.dart" to "legpad.dart.js" usung dart2js.
-set -x
-DART_DIR="../../.."
-$DART_DIR/out/Release_ia32/dart2js --out=legpad.dart.js legpad.dart
-
-# Now run legpad to generate an html page that can be used to compile
-# example.dart
-python legpad.py example.dart
diff --git a/tools/testing/legpad/legpad.dart b/tools/testing/legpad/legpad.dart
deleted file mode 100644
index b6acfe7..0000000
--- a/tools/testing/legpad/legpad.dart
+++ /dev/null
@@ -1,136 +0,0 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-#import("dart:html", prefix:"html");
-#import('../../../lib/compiler/compiler.dart', prefix: "compiler_lib");
-#import('../../../lib/uri/uri.dart', prefix:"uri_lib");
-
-/**
- * This is the entrypoint for a version of the leg compiler that
- * runs in the browser.
- *
- * Because this is running in the browser, we do not access
- * the file system.  Instead, we assume that all necessary files
- * have been placed in inert <script> elements somewhere on the html page.
- *
- * (See legpad.py for more details on how the html page is constructed.)
- */
-void main() {
-  new Legpad().run();
-}
-
-class Legpad {
-  // id of script element containing name of the main dart file
-  // to compile
-  static const String MAIN_ID = "main_id";
-
-  Legpad() : warnings = new StringBuffer();
-
-  // accumulates diagnostic messages emitted by the leg compiler
-  StringBuffer warnings;
-
-  // the generated javascript
-  String output;
-
-  String readAll(String filename) {
-    String text = getText(idOfFilename(filename));
-    print("read $filename (${text.length} bytes)");
-    return text;
-  }
-
-  void diagnosticHandler(uri_lib.Uri uri, int begin, int end,
-                                 String message, bool fatal) {
-    warnings.add(message);
-    if (uri != null) {
-      warnings.add(" ($uri: $begin, $end)");
-    }
-    if (fatal) {
-      warnings.add(" (fatal)");
-    }
-    warnings.add("\n");
-  }
-
-  Future<String> readUriFromString(uri_lib.Uri uri) {
-    Completer<String> completer = new Completer<String>();
-    completer.complete(readAll(uri.toString()));
-    return completer.future;
-  }
-
-  /**
-   * Returns the id of the <script> element that contains
-   * the contents of this file.  (Replace all slashes
-   * and dots in the file name with underscores.)
-   */
-  String idOfFilename(String filename) {
-    return filename.replaceAll("/", "_").replaceAll(".", "_");
-  }
-
-  void run() {
-    String mainFile = getText(MAIN_ID);
-    setText("input", readAll(mainFile));
-    Stopwatch stopwatch = new Stopwatch()..start();
-    runLeg();
-    int elapsedMillis = stopwatch.elapsedMilliseconds;
-    if (output == null) {
-      output = "throw 'dart2js compilation error';\n";
-    }
-
-    setText("output", output);
-    setText("warnings", warnings.toString());
-    int lineCount = lineCount(output);
-    String timing = "generated $lineCount lines "
-        "(${output.length} characters) in "
-        "${((elapsedMillis) / 1000).toStringAsPrecision(3)} seconds";
-    setText("timing", timing);
-  }
-
-  static int lineCount(String s) {
-    Iterable<Match> matches = "\n".allMatches(s);
-    int n = 0;
-    for (Match m in matches) {
-      n++;
-    }
-    return n;
-  }
-
-  void runLeg() {
-    uri_lib.Uri mainUri = new uri_lib.Uri.fromString(getText(MAIN_ID));
-    uri_lib.Uri libraryRoot = new uri_lib.Uri.fromString("dartdir/");
-    List<String> compilerArgs = [
-      "--enable_type_checks",
-      "--enable_asserts"
-    ];
-
-    // TODO(mattsh): dart2js api should be synchronous
-    Future<String> futureJavascript = compiler_lib.compile(mainUri,
-         libraryRoot, readUriFromString, diagnosticHandler, compilerArgs);
-
-    if (futureJavascript == null) {
-      return;
-    }
-    output = futureJavascript.value;
-  }
-
-  void setText(String id, String text) {
-    html.Element element = html.document.query("#$id");
-    if (element == null) {
-      throw new Exception("Can't find element $id");
-    }
-    element.innerHTML = htmlEscape(text);
-  }
-
-  String getText(String id) {
-    html.Element element = html.document.query("#$id");
-    if (element == null) {
-      throw new Exception("Can't find element $id");
-    }
-    return element.text.trim();
-  }
-
-  // TODO(mattsh): should exist in standard lib somewhere
-  static String htmlEscape(String text) {
-    return text.replaceAll('&', '&amp;').replaceAll(
-        '>', '&gt;').replaceAll('<', '&lt;');
-  }
-}
diff --git a/tools/testing/legpad/legpad.py b/tools/testing/legpad/legpad.py
deleted file mode 100644
index 1a4aa55..0000000
--- a/tools/testing/legpad/legpad.py
+++ /dev/null
@@ -1,367 +0,0 @@
-#!/usr/bin/env python
-
-# 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.
-
-"""
-Legpad is used to compile .dart files to javascript, using the dart2js compiler.
-
-This is accomplished by creating an html file (usually called
-<something>.legpad.html) that executes the dart2js compiler when the page
-is loaded by a web browser (or DumpRenderTree).
-
-The <something>.legpad.html file contains:
-
-  1. all the dart files that compose a user's dart program
-  2. all the dart files of dart:core and other standard dart libraries
-      (or any other symbol that can follow "dart:" in an import statement
-  3. legpad.dart (compiled to javascript)
-
-The contents of each dart file is placed in a separate <script> tag.
-
-When the html page is loaded by a browser, the leg compiler is invoked
-and the dart program is compiled to javascript.  The generated javascript is
-placed in a <pre> element with id "output".
-
-When the html page is passed to DumpRenderTree, the dumped output will
-have the generated javascript.
-
-See 'example.sh' for an example of how to run legpad.
-"""
-
-import logging
-import optparse
-import os.path
-import platform
-import re
-import subprocess
-import sys
-
-
-class FileNotFoundException(Exception):
-  def __init__(self, file_name):
-    self._name = file_name
-
-  def __str__(self):
-    return self._name
-
-
-class CommandFailedException(Exception):
-  def __init__(self, message):
-    self._message = message
-
-  def GetMessage(self):
-    return self._message
-
-
-# Template for the legpad.html page we're going to generate.
-HTML = """<!DOCTYPE html>
-<html>
-<head>
-  <style type="text/css">
-    textarea {
-      width: 100%;
-      height: 200px;
-    }
-    .label {
-      margin-top: 5px;
-    }
-    pre {
-      border: 2px solid black;
-    }
-  </style>
-  {{script_tags}}
-  <script type="text/javascript">
-    if (window.layoutTestController) {
-      layoutTestController.dumpAsText();
-    }
-  </script>
-</head>
-<body>
-  <h1>Legpad</h1>
-  <div class="label">Input:</div>
-  <textarea id="input"></textarea>
-  <div class="label">Compiler Messages:</div>
-  <pre id="warnings"></pre>
-  <div class="label">Timing:</div>
-  <pre id="timing"></pre>
-  <div class="label">Output:</div>
-  <pre id="output"></pre>
-  <script type="text/javascript">
-    {{LEGPAD_JS}}
-  </script>
-</body>
-</html>
-"""
-
-# This finds everything after the word "Output:" in the html page.
-# (Note, because the javascript we're fishing out spans multiple lines
-# we need to use the DOTALL switch here.)
-OUTPUT_JAVASCRIPT_REGEX = re.compile(".*\nOutput:\n(.*)\n#EOF", re.DOTALL)
-
-# If the legpad.dart encounters a compilation error, the generated
-# javascript will contains the words "dart2js compilation error".
-COMPILATION_ERROR_REGEX = re.compile(".*dart2js compilation error.*", re.DOTALL)
-
-# We use "application/inert" here to make the browser ignore the
-# these script tags.  (legpad.dart will fish out the contents as needed.)
-#
-SCRIPT_TAG = """<script type="application/inert" id="{{id}}">
-{{contents}}
-</script>
-"""
-
-# Regex that finds #import, #source and #native directives in .dart files.
-#   match.group(1) = "import", "source" or "native"
-#   match.group(2) = url of file being imported
-DIRECTIVE_RE = re.compile(r"^#(import|source|native)\([\"']([^\"']*)[\"']")
-
-# id of script tag that holds name of the top dart file to be compiled,
-# (This file name passed will be passed to the leg compiler by legpad.dart.)
-MAIN_ID = "main_id"
-
-# TODO(mattsh): read this from some config file once ahe/zundel create it
-DART_LIBRARIES = {
-    "core": "lib/compiler/implementation/lib/core.dart",
-    "_js_helper": "lib/compiler/implementation/lib/js_helper.dart",
-    "_interceptors": "lib/compiler/implementation/lib/interceptors.dart",
-    "dom": "lib/dom/frog/dom_frog.dart",
-    "html": "lib/html/frog/html_frog.dart",
-    "io": "lib/compiler/implementation/lib/io.dart",
-    "isolate": "lib/isolate/isolate_leg.dart",
-    "json": "lib/json/json.dart",
-    "uri": "lib/uri/uri.dart",
-    "utf": "lib/utf/utf.dart",
-}
-
-class Pad(object):
-  """
-  Accumulates all source files that are needed to compile a dart program,
-  and places them in <script> tags on an html page.
-  """
-
-  def __init__(self, argv):
-    parser = optparse.OptionParser(usage=
-      "%prog [options] file_to_compile.dart"
-    )
-    parser.add_option("-o", "--out",
-        help="name of javascript output file")
-    parser.add_option("-v", "--verbose", action="store_true",
-        help="more verbose logging")
-    (options, args) = parser.parse_args(argv)
-
-    log_level = logging.INFO
-    if options.verbose:
-      log_level = logging.DEBUG
-    logging.basicConfig(level=log_level)
-
-    if len(args) < 2:
-      parser.print_help()
-      sys.exit(1)
-
-    self.main_file = os.path.abspath(args[1])
-
-    # directory of this script
-    self.legpad_dir = os.path.abspath(os.path.dirname(argv[0]))
-
-    # root of dart source repo
-    self.dart_dir = os.path.dirname(os.path.dirname(os.path.dirname(
-        self.legpad_dir)))
-
-    logging.debug("dart_dir: '%s'" % self.dart_dir)
-
-    if options.out:
-      # user has specified an output file name
-      self.js_file = os.path.abspath(options.out)
-    else:
-      # User didn't specify an output file, so use the input
-      # file name as the base of the output file name.
-      self.js_file = self.main_file + ".legpad.js"
-
-    logging.debug("js_file: '%s" % self.js_file)
-
-    # this is the html file that we pass to DumpRenderTree
-    self.html_file = self.main_file + ".legpad.html"
-    logging.debug("html_file: '%s'" % self.html_file)
-
-    # map from file name to File object (contains entries for all corelib
-    # and all other dart files needed to compile main_file)
-    self.name_to_file = {}
-
-    # map from script tag id to File object
-    self.id_to_file = {}
-
-    self.load_libraries()
-    self.load_file(self.main_file)
-
-    html = self.generate_html()
-    write_file(self.html_file, html)
-
-    js = self.generate_js()
-    write_file(self.js_file, js)
-
-    line_count = len(js.splitlines())
-    logging.debug("generated '%s' (%d lines)", self.js_file, line_count)
-
-    match = COMPILATION_ERROR_REGEX.match(js)
-    if match:
-      sys.exit(1)
-
-  def generate_html(self):
-    tags = []
-    for f in self.id_to_file.values():
-      tags.append(self._create_tag(f.id, f.contents))
-    tags.append(self._create_tag(MAIN_ID, self.shorten(self.main_file)))
-    html = HTML.replace("{{script_tags}}", "".join(tags))
-
-    legpad_js = os.path.join(self.legpad_dir, "legpad.dart.js")
-    check_exists(legpad_js)
-
-    html = html.replace("{{LEGPAD_JS}}", read_file(legpad_js))
-    return html
-
-  def generate_js(self):
-    drt = os.path.join(self.dart_dir, "client/tests/drt/DumpRenderTree")
-    if platform.system() == 'Darwin':
-      drt += ".app"
-    elif platform.system() == 'Windows':
-      raise Exception("legpad does not run on Windows")
-
-    check_exists(drt)
-    args = []
-    args.append(drt)
-    args.append(self.html_file)
-
-    stdout = run_command(args)
-    match = OUTPUT_JAVASCRIPT_REGEX.match(stdout)
-    if not match:
-      raise Exception("can't find regex in DumpRenderTree output")
-    return match.group(1)
-
-  @staticmethod
-  def _create_tag(id, contents):
-    s = SCRIPT_TAG
-    s = s.replace("{{id}}", id)
-    # TODO(mattsh) - need to html escape here
-    s = s.replace("{{contents}}", contents)
-    return s
-
-  def dart_library(self, name):
-    path = DART_LIBRARIES[name]
-    if not path:
-      raise Exception("unrecognized 'dart:%s'", name)
-    return os.path.join(self.dart_dir, path)
-
-  def load_libraries(self):
-    for name in DART_LIBRARIES:
-      self.load_file(self.dart_library(name))
-
-  def load_file(self, name):
-    name = os.path.abspath(name)
-    if name in self.name_to_file:
-      return
-    f = File(self, name)
-    self.name_to_file[f.name] = f
-    if f.id in self.id_to_file:
-      raise Exception("ambiguous id '%s'" % f.id)
-    self.id_to_file[f.id] = f
-    f.directives()
-
-  def shorten(self, name):
-    """
-    Change that full path of the dart svn repo to simply "dartdir"
-    """
-    return name.replace(self.dart_dir, "dartdir")
-
-  def make_id(self, name):
-    """
-    Generates an id (based on the file name) for the <script> tag that will
-    hold the contents of this file.
-    """
-    return self.shorten(name).replace("/", "_").replace(".", "_")
-
-
-class File(object):
-  def __init__(self, pad, name):
-    self.pad = pad
-    self.name = name
-    self.id = pad.make_id(name)
-    self.contents = read_file(name)
-
-  def directives(self):
-    """Load files referenced by #source, #import and #native directives."""
-    lines = self.contents.split("\n")
-    self.line_number = 0
-    for line in lines:
-      self.line_number += 1
-      self._directive(line)
-
-  def _directive(self, line):
-    match = DIRECTIVE_RE.match(line)
-    if not match:
-      return
-    url = match.group(2)
-    if url.startswith("dart:"):
-      path = self.pad.dart_library(url[len("dart:"):])
-    else:
-      path = os.path.join(os.path.dirname(self.name), url)
-    self.pad.load_file(path)
-
-
-def read_file(file_name):
-  check_exists(file_name)
-  with open(file_name, "r") as input:
-    contents = input.read()
-  logging.debug("read_file '%s' (%d bytes)" % (file_name, len(contents)))
-  return contents
-
-
-def write_file(file_name, contents):
-  with open(file_name, "w") as output:
-    output.write(contents)
-
-  check_exists(file_name)
-  logging.debug("write_file '%s' (%d bytes)" % (file_name, len(contents)))
-
-
-def check_exists(file_name):
-  if not os.path.exists(file_name):
-    raise FileNotFoundException(file_name)
-
-
-def format_command(args):
-  return ' '.join(args)
-
-
-def run_command(args):
-  """
-  Args:
-    command: comamnd with arguments to exec
-  Returns:
-    all output that this command sent to stdout
-  """
-
-  command = format_command(args)
-  logging.info("RUNNING: '%s'" % command)
-  child = subprocess.Popen(args,
-      stdout=subprocess.PIPE,
-      stderr=subprocess.PIPE,
-      close_fds=True)
-  (stdout, stderr) = child.communicate()
-  exit_code = child.wait()
-  if exit_code:
-    for line in stderr.splitlines():
-      logging.info(line)
-    msg = "FAILURE (exit_code=%d): '%s'" % (exit_code, command)
-    logging.error(msg)
-    raise CommandFailedException(msg)
-  logging.debug("SUCCEEDED (%d bytes)" % len(stdout))
-  return stdout
-
-
-def main(argv):
-  Pad(argv)
-
-if __name__ == "__main__":
-  sys.exit(main(sys.argv))
diff --git a/utils/apidoc/apidoc.dart b/utils/apidoc/apidoc.dart
index 753f8b2..bc20887c 100644
--- a/utils/apidoc/apidoc.dart
+++ b/utils/apidoc/apidoc.dart
@@ -17,7 +17,6 @@
 import 'dart:async';
 import 'dart:io';
 import 'dart:json' as json;
-import 'dart:uri';
 
 import 'html_diff.dart';
 
diff --git a/utils/apidoc/html_diff.dart b/utils/apidoc/html_diff.dart
index fd8e0a2..1bb8069e 100644
--- a/utils/apidoc/html_diff.dart
+++ b/utils/apidoc/html_diff.dart
@@ -10,7 +10,6 @@
 
 import 'dart:async';
 import 'dart:io';
-import 'dart:uri';
 
 import 'lib/metadata.dart';
 
@@ -25,11 +24,11 @@
 // TODO(amouravski): There is currently magic that looks at dart:* libraries
 // rather than the declared library names. This changed due to recent syntax
 // changes. We should only need to look at the library 'html'.
-const List<Uri> HTML_LIBRARY_URIS = const [
-    const Uri.fromComponents(scheme: 'dart', path: 'html'),
-    const Uri.fromComponents(scheme: 'dart', path: 'indexed_db'),
-    const Uri.fromComponents(scheme: 'dart', path: 'svg'),
-    const Uri.fromComponents(scheme: 'dart', path: 'web_audio')];
+final List<Uri> HTML_LIBRARY_URIS = [
+    new Uri(scheme: 'dart', path: 'html'),
+    new Uri(scheme: 'dart', path: 'indexed_db'),
+    new Uri(scheme: 'dart', path: 'svg'),
+    new Uri(scheme: 'dart', path: 'web_audio')];
 
 /**
  * A class for computing a many-to-many mapping between the types and
diff --git a/utils/apidoc/mdn/extractRunner.js b/utils/apidoc/mdn/extractRunner.js
index 8e84d0b..6a95a2e 100644
--- a/utils/apidoc/mdn/extractRunner.js
+++ b/utils/apidoc/mdn/extractRunner.js
@@ -116,11 +116,11 @@
 
   /*
   // TODO(jacobr): Make this run on platforms other than OS X.
-  var cmd = '../../../client/tests/drt/DumpRenderTree.app/Contents/MacOS/' +
-      'DumpRenderTree ' + absoluteDumpFileName;
+  var cmd = '../../../client/tests/drt/Content Shell.app/Contents/MacOS/' +
+      Content Shell' + absoluteDumpFileName;
   */
   // TODO(eub): Make this run on platforms other than Linux.
-  var cmd = '../../../client/tests/drt/DumpRenderTree ' + absoluteDumpFileName;
+  var cmd = '../../../client/tests/drt/content_shell ' + absoluteDumpFileName;
   console.log(cmd);
   exec(cmd,
     function (error, stdout, stderr) {
diff --git a/utils/testrunner/options.dart b/utils/testrunner/options.dart
index 0e736be..3d5714f 100644
--- a/utils/testrunner/options.dart
+++ b/utils/testrunner/options.dart
@@ -16,10 +16,12 @@
       allowed: ['vm', 'drt-dart', 'drt-js'],
       allowedHelp: {
         'vm': 'Run Dart code natively on the standalone dart vm.',
+        // TODO(antonm): fix option name.
         'drt-dart': 'Run Dart code natively in the headless version of\n'
-          'Chrome, DumpRenderTree.',
+          'Chrome, Content shell.',
+        // TODO(antonm): fix option name.
         'drt-js': 'Run Dart compiled to JavaScript in the headless version\n'
-            'of Chrome, DumpRenderTree.'
+            'of Chrome, Content shell.'
       });
 
   parser.addFlag('checked', defaultsTo: false,
diff --git a/utils/testrunner/run_pipeline.dart b/utils/testrunner/run_pipeline.dart
index 5fc1446..f1de2d3 100644
--- a/utils/testrunner/run_pipeline.dart
+++ b/utils/testrunner/run_pipeline.dart
@@ -157,7 +157,6 @@
 import 'dart:async';
 import 'dart:io';
 import 'dart:math';
-import 'dart:uri';
 part '${normalizePath('${config["runnerDir"]}/layout_test_controller.dart')}';
     ''';
     extras = '''
@@ -241,7 +240,6 @@
 import 'dart:math';
 import 'dart:isolate';
 import 'dart:html';
-import 'dart:uri';
 import 'package:unittest/unittest.dart' as unittest;
 import '${normalizePath('$testFile')}' as test;
 part '${normalizePath('${config["runnerDir"]}/layout_test_runner.dart')}';
diff --git a/utils/testrunner/testrunner.dart b/utils/testrunner/testrunner.dart
index dda5e31..7ecf8ac 100755
--- a/utils/testrunner/testrunner.dart
+++ b/utils/testrunner/testrunner.dart
@@ -41,16 +41,18 @@
  * The three runtimes are:
  *
  *   vm - run native Dart in the VM; i.e. using $DARTSDK/dart-sdk/bin/dart.
- *   drt-dart - run native Dart in DumpRenderTree, the headless version of
- *       Dartium, which is located in $DARTSDK/chromium/DumpRenderTree, if
+ *   TODO(antonm): fix the option name.
+ *   drt-dart - run native Dart in content shell, the headless version of
+ *       Dartium, which is located in $DARTSDK/chromium/content_shell, if
  *       you installed the SDK that is bundled with the editor, or available
  *       from http://gsdview.appspot.com/dartium-archive/continuous/
  *       otherwise.
  *
- *   drt-js - run Dart compiled to Javascript in DumpRenderTree.
+ *   TODO(antonm): fix the option name.
+ *   drt-js - run Dart compiled to Javascript in content shell.
  *
  * testrunner supports simple DOM render tests. These can use expected values
- * for the render output from DumpRenderTree, either are textual DOM
+ * for the render output from content shell, either are textual DOM
  * descriptions (`--layout-tests`) or pixel renderings (`--pixel-tests`).
  * When running layout tests, testrunner will see if there is a file with
  * a .png or a .txt extension in a directory with the same name as the
@@ -357,19 +359,19 @@
     config['dart'] = '$dartsdk${pathSep}dart-sdk${pathSep}bin${pathSep}dart';
     config['pub'] = '$dartsdk${pathSep}dart-sdk${pathSep}bin${pathSep}pub';
     config['drt'] = 
-      '$dartsdk/chromium/DumpRenderTree.app/Contents/MacOS/DumpRenderTree';
+      '$dartsdk/chromium/Content Shell.app/Contents/MacOS/Content Shell';
   } else if (Platform.operatingSystem == 'linux') {
     config['dart2js'] =
         '$dartsdk${pathSep}dart-sdk${pathSep}bin${pathSep}dart2js';
     config['dart'] = '$dartsdk${pathSep}dart-sdk${pathSep}bin${pathSep}dart';
     config['pub'] = '$dartsdk${pathSep}dart-sdk${pathSep}bin${pathSep}pub';
-    config['drt'] = '$dartsdk${pathSep}chromium${pathSep}DumpRenderTree';
+    config['drt'] = '$dartsdk${pathSep}chromium${pathSep}content_shell';
   } else {
     config['dart2js'] =
         '$dartsdk${pathSep}dart-sdk${pathSep}bin${pathSep}dart2js.bat';
     config['dart'] = '$dartsdk${pathSep}dart-sdk${pathSep}bin${pathSep}dart.exe';
     config['pub'] = '$dartsdk${pathSep}dart-sdk${pathSep}bin${pathSep}pub.bat';
-    config['drt'] = '$dartsdk${pathSep}chromium${pathSep}DumpRenderTree.exe';
+    config['drt'] = '$dartsdk${pathSep}chromium${pathSep}content_shell.exe';
   }
 
   for (var prog in [ 'drt', 'dart', 'pub', 'dart2js' ]) {
diff --git a/utils/tests/testrunner/http_client_tests/http_client_test.dart b/utils/tests/testrunner/http_client_tests/http_client_test.dart
index b46745a..0016ce4 100644
--- a/utils/tests/testrunner/http_client_tests/http_client_test.dart
+++ b/utils/tests/testrunner/http_client_tests/http_client_test.dart
@@ -6,7 +6,6 @@
 
 import 'dart:async';
 import 'dart:io';
-import 'dart:uri';
 import 'package:unittest/unittest.dart';
 
 main() {