Version 0.6.6.0 .

svn merge -r 25013:25115 https://dart.googlecode.com/svn/branches/bleeding_edge trunk

git-svn-id: http://dart.googlecode.com/svn/trunk@25119 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/pkg/analyzer_experimental/lib/src/generated/java_io.dart b/pkg/analyzer_experimental/lib/src/generated/java_io.dart
index d186c47..41c2e24 100644
--- a/pkg/analyzer_experimental/lib/src/generated/java_io.dart
+++ b/pkg/analyzer_experimental/lib/src/generated/java_io.dart
@@ -1,6 +1,7 @@
 library java.io;
 
 import "dart:io";
+import 'package:path/path.dart' as pathos;
 
 class JavaSystemIO {
   static Map<String, String> _properties = new Map();
@@ -33,14 +34,14 @@
         String sdkPath;
         // may be "xcodebuild/ReleaseIA32/dart" with "dart-sdk" sibling
         {
-          sdkPath = new Path(exec).directoryPath.append("dart-sdk").toNativePath();
+          sdkPath = pathos.join(pathos.dirname(exec), "dart-sdk");
           if (new Directory(sdkPath).existsSync()) {
             _properties[name] = sdkPath;
             return sdkPath;
           }
         }
         // probably be "dart-sdk/bin/dart"
-        sdkPath = new Path(exec).directoryPath.directoryPath.toString();
+        sdkPath = pathos.dirname(pathos.dirname(exec));
         _properties[name] = sdkPath;
         return sdkPath;
       }
@@ -58,26 +59,27 @@
 class JavaFile {
   static final String separator = Platform.pathSeparator;
   static final int separatorChar = Platform.pathSeparator.codeUnitAt(0);
-  Path _path;
+  String _path;
   JavaFile(String path) {
-    this._path = new Path(path);
+    _path = pathos.normalize(path);
   }
   JavaFile.relative(JavaFile base, String child) {
     if (child.isEmpty) {
       this._path = base._path;
     } else {
-      this._path = base._path.join(new Path(child));
+      this._path = pathos.join(base._path, child);
     }
   }
-  JavaFile.fromUri(Uri uri) : this(uri.path);
+  JavaFile.fromUri(Uri uri) : this(pathos.fromUri(uri));
+  String toString() => _path.toString();
   int get hashCode => _path.hashCode;
   bool operator ==(other) {
-    return other is JavaFile && other._path.toNativePath() == _path.toNativePath();
+    return other is JavaFile && other._path == _path;
   }
-  String getPath() => _path.toNativePath();
-  String getName() => _path.filename;
+  String getPath() => _path;
+  String getName() => pathos.basename(_path);
   String getParent() {
-    var result = _path.directoryPath.toNativePath();
+    var result = pathos.dirname(_path);
     // "." or  "/" or  "C:\"
     if (result.length < 4) return null;
     return result;
@@ -87,8 +89,8 @@
     if (parent == null) return null;
     return new JavaFile(parent);
   }
-  String getAbsolutePath() => _path.canonicalize().toNativePath();
-  String getCanonicalPath() => _path.canonicalize().toNativePath();
+  String getAbsolutePath() => pathos.absolute(_path);
+  String getCanonicalPath() => _newFile().fullPathSync();
   JavaFile getAbsoluteFile() => new JavaFile(getAbsolutePath());
   JavaFile getCanonicalFile() => new JavaFile(getCanonicalPath());
   bool exists() {
@@ -103,7 +105,7 @@
   bool isDirectory() {
     return _newDirectory().existsSync();
   }
-  Uri toURI() => new Uri(path: _path.toString());
+  Uri toURI() => pathos.toUri(_path);
   String readAsStringSync() => _newFile().readAsStringSync();
   int lastModified() {
     if (!_newFile().existsSync()) return 0;
@@ -111,13 +113,13 @@
 
   }
   List<JavaFile> listFiles() {
-    List<JavaFile> files = [];
-    List<FileSystemEntity> entities = _newDirectory().listSync();
+    var files = <JavaFile>[];
+    var entities = _newDirectory().listSync();
     for (FileSystemEntity entity in entities) {
       files.add(new JavaFile(entity.path));
     }
     return files;
   }
-  File _newFile() => new File.fromPath(_path);
-  Directory _newDirectory() => new Directory.fromPath(_path);
+  File _newFile() => new File(_path);
+  Directory _newDirectory() => new Directory(_path);
 }
diff --git a/pkg/barback/lib/barback.dart b/pkg/barback/lib/barback.dart
index 8c3928e..eb0e1e8 100644
--- a/pkg/barback/lib/barback.dart
+++ b/pkg/barback/lib/barback.dart
@@ -6,7 +6,7 @@
 
 export 'src/asset.dart';
 export 'src/asset_id.dart';
-export 'src/asset_provider.dart';
 export 'src/errors.dart';
+export 'src/package_provider.dart';
 export 'src/transform.dart' show Transform;
 export 'src/transformer.dart';
\ No newline at end of file
diff --git a/pkg/barback/lib/src/asset_graph.dart b/pkg/barback/lib/src/asset_cascade.dart
similarity index 78%
rename from pkg/barback/lib/src/asset_graph.dart
rename to pkg/barback/lib/src/asset_cascade.dart
index 5682fb1..0e8893a 100644
--- a/pkg/barback/lib/src/asset_graph.dart
+++ b/pkg/barback/lib/src/asset_cascade.dart
@@ -2,26 +2,39 @@
 // 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 barback.asset_graph;
+library barback.asset_cascade;
 
 import 'dart:async';
 import 'dart:collection';
 
 import 'asset.dart';
 import 'asset_id.dart';
-import 'asset_provider.dart';
 import 'asset_set.dart';
 import 'errors.dart';
 import 'change_batch.dart';
+import 'package_graph.dart';
 import 'phase.dart';
 import 'transformer.dart';
+import 'utils.dart';
 
-/// The main build dependency manager.
+/// The asset cascade for an individual package.
 ///
-/// For any given input file, it can tell which output files are affected by
-/// it, and vice versa.
-class AssetGraph {
-  final AssetProvider _provider;
+/// This keeps track of which [Transformer]s are applied to which assets, and
+/// re-runs those transformers when their dependencies change. The transformed
+/// assets are accessible via [getAssetById].
+///
+/// A cascade consists of one or more [Phases], each of which has one or more
+/// [Transformer]s that run in parallel, potentially on the same inputs. The
+/// inputs of the first phase are the source assets for this cascade's package.
+/// The inputs of each successive phase are the outputs of the previous phase,
+/// as well as any assets that haven't yet been transformed.
+class AssetCascade {
+  /// The name of the package whose assets are managed.
+  final String package;
+
+  /// The [PackageGraph] that tracks all [AssetCascade]s for all dependencies of
+  /// the current app.
+  final PackageGraph _graph;
 
   final _phases = <Phase>[];
 
@@ -33,10 +46,10 @@
   Stream<BuildResult> get results => _resultsController.stream;
   final _resultsController = new StreamController<BuildResult>.broadcast();
 
-  /// A stream that emits any errors from the asset graph or the transformers.
+  /// A stream that emits any errors from the cascade or the transformers.
   ///
   /// This emits errors as they're detected. If an error occurs in one part of
-  /// the asset graph, unrelated parts will continue building.
+  /// the cascade, unrelated parts will continue building.
   ///
   /// This will not emit programming errors from barback itself. Those will be
   /// emitted through the [results] stream's error channel.
@@ -55,12 +68,12 @@
 
   ChangeBatch _sourceChanges;
 
-  /// Creates a new [AssetGraph].
+  /// Creates a new [AssetCascade].
   ///
-  /// It loads source assets using [provider] and then uses [transformerPhases]
-  /// to generate output files from them.
+  /// It loads source assets within [package] using [provider] and then uses
+  /// [transformerPhases] to generate output files from them.
   //TODO(rnystrom): Better way of specifying transformers and their ordering.
-  AssetGraph(this._provider,
+  AssetCascade(this._graph, this.package,
       Iterable<Iterable<Transformer>> transformerPhases) {
     // Flatten the phases to a list so we can traverse backwards to wire up
     // each phase to its next.
@@ -84,6 +97,8 @@
   /// it has been created and return it. If the asset cannot be found, throws
   /// [AssetNotFoundException].
   Future<Asset> getAssetById(AssetId id) {
+    assert(id.package == package);
+
     // TODO(rnystrom): Waiting for the entire build to complete is unnecessary
     // in some cases. Should optimize:
     // * [id] may be generated before the compilation is finished. We should
@@ -95,7 +110,7 @@
     // * If [id] has never been generated and all active transformers provide
     //   metadata about the file names of assets it can emit, we can prove that
     //   none of them can emit [id] and fail early.
-    return _waitForProcess().then((_) {
+    return (_processDone == null ? new Future.value() : _processDone).then((_) {
       // Each phase's inputs are the outputs of the previous phase. Find the
       // last phase that contains the asset. Since the last phase has no
       // transformers, this will find the latest output for that id.
@@ -126,6 +141,7 @@
   /// transforms that use it will be re-applied.
   void updateSources(Iterable<AssetId> sources) {
     if (_sourceChanges == null) _sourceChanges = new ChangeBatch();
+    assert(sources.every((id) => id.package == package));
     _sourceChanges.update(sources);
 
     _waitForProcess();
@@ -134,6 +150,7 @@
   /// Removes [removed] from the graph's known set of source assets.
   void removeSources(Iterable<AssetId> removed) {
     if (_sourceChanges == null) _sourceChanges = new ChangeBatch();
+    assert(removed.every((id) => id.package == package));
     _sourceChanges.remove(removed);
 
     _waitForProcess();
@@ -218,7 +235,7 @@
       var futures = [];
       for (var id in changes.updated) {
         // TODO(rnystrom): Catch all errors from provider and route to results.
-        futures.add(_provider.getAsset(id).then((asset) {
+        futures.add(_graph.provider.getAsset(id).then((asset) {
           updated.add(asset);
         }).catchError((error) {
           if (error is AssetNotFoundException) {
@@ -238,7 +255,7 @@
   }
 }
 
-/// An event indicating that the asset graph has finished building.
+/// An event indicating that the cascade has finished building all assets.
 ///
 /// A build can end either in success or failure. If there were no errors during
 /// the build, it's considered to be a success; any errors render it a failure,
@@ -252,4 +269,28 @@
 
   BuildResult(Iterable errors)
       : errors = errors.toList();
+
+  /// Creates a build result indicating a successful build.
+  ///
+  /// This equivalent to a build result with no errors.
+  BuildResult.success()
+      : this([]);
+
+  String toString() {
+    if (succeeded) return "success";
+
+    return "errors:\n" + errors.map((error) {
+      var stackTrace = getAttachedStackTrace(error);
+      if (stackTrace != null) stackTrace = new Trace.from(stackTrace);
+
+      var msg = new StringBuffer();
+      msg.write(prefixLines(error.toString()));
+      if (stackTrace != null) {
+        msg.write("\n\n");
+        msg.write("Stack trace:\n");
+        msg.write(prefixLines(stackTrace.toString()));
+      }
+      return msg.toString();
+    }).join("\n\n");
+  }
 }
diff --git a/pkg/barback/lib/src/asset_node.dart b/pkg/barback/lib/src/asset_node.dart
index 7bef7a0..ae2b70e 100644
--- a/pkg/barback/lib/src/asset_node.dart
+++ b/pkg/barback/lib/src/asset_node.dart
@@ -7,7 +7,6 @@
 import 'dart:async';
 
 import 'asset.dart';
-import 'asset_graph.dart';
 import 'asset_id.dart';
 import 'phase.dart';
 import 'transform_node.dart';
diff --git a/pkg/barback/lib/src/errors.dart b/pkg/barback/lib/src/errors.dart
index 65dcad6..9ebca8e 100644
--- a/pkg/barback/lib/src/errors.dart
+++ b/pkg/barback/lib/src/errors.dart
@@ -36,3 +36,14 @@
 
   String toString() => "Missing input $id.";
 }
+
+/// Error thrown when a transformer outputs an asset with the wrong package
+/// name.
+class InvalidOutputException implements Exception {
+  final String package;
+  final AssetId id;
+
+  InvalidOutputException(this.package, this.id);
+
+  String toString() => "Invalid output $id: must be in package $package.";
+}
diff --git a/pkg/barback/lib/src/package_graph.dart b/pkg/barback/lib/src/package_graph.dart
new file mode 100644
index 0000000..4dc2719
--- /dev/null
+++ b/pkg/barback/lib/src/package_graph.dart
@@ -0,0 +1,119 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library barback.package_graph;
+
+import 'dart:async';
+
+import 'package:stack_trace/stack_trace.dart';
+
+import 'asset.dart';
+import 'asset_cascade.dart';
+import 'asset_id.dart';
+import 'errors.dart';
+import 'package_provider.dart';
+import 'utils.dart';
+
+/// The collection of [AssetCascade]s for an entire application.
+///
+/// This tracks each package's [AssetCascade] and routes asset requests between
+/// them.
+class PackageGraph {
+  /// The provider that exposes asset and package information.
+  final PackageProvider provider;
+
+  /// The [AssetCascade] for each package.
+  final _cascades = <String, AssetCascade>{};
+
+  /// The current [BuildResult] for each package's [AssetCascade].
+  ///
+  /// The result for a given package will be `null` if that [AssetCascade] is
+  /// actively building.
+  final _cascadeResults = <String, BuildResult>{};
+
+  /// A stream that emits a [BuildResult] each time the build is completed,
+  /// whether or not it succeeded.
+  ///
+  /// This will emit a result only once every package's [AssetCascade] has
+  /// finished building.
+  ///
+  /// If an unexpected error in barback itself occurs, it will be emitted
+  /// through this stream's error channel.
+  Stream<BuildResult> get results => _resultsController.stream;
+  final _resultsController = new StreamController<BuildResult>.broadcast();
+
+  /// A stream that emits any errors from the graph or the transformers.
+  ///
+  /// This emits errors as they're detected. If an error occurs in one part of
+  /// the graph, unrelated parts will continue building.
+  ///
+  /// This will not emit programming errors from barback itself. Those will be
+  /// emitted through the [results] stream's error channel.
+  Stream get errors => _errors;
+  Stream _errors;
+
+  /// Creates a new [PackageGraph] that will transform assets in all packages
+  /// made available by [provider].
+  PackageGraph(this.provider) {
+    for (var package in provider.packages) {
+      var cascade = new AssetCascade(this, package,
+          provider.getTransformers(package));
+      // The initial result for each cascade is "success" since the cascade
+      // doesn't start building until some source in that graph is updated.
+      _cascadeResults[package] = new BuildResult.success();
+      _cascades[package] = cascade;
+
+      cascade.results.listen((result) {
+        _cascadeResults[cascade.package] = result;
+        // If any cascade hasn't yet finished, the overall build isn't finished
+        // either.
+        if (_cascadeResults.values.any((result) => result == null)) return;
+
+        // Include all build errors for all cascades. If no cascades have
+        // errors, the result will automatically be considered a success.
+        _resultsController.add(new BuildResult(flatten(
+            _cascadeResults.values.map((result) => result.errors))));
+      }, onError: _resultsController.addError);
+    }
+
+    _errors = mergeStreams(_cascades.values.map((cascade) => cascade.errors));
+  }
+
+  /// Gets the asset identified by [id].
+  ///
+  /// If [id] is for a generated or transformed asset, this will wait until
+  /// it has been created and return it. If the asset cannot be found, throws
+  /// [AssetNotFoundException].
+  Future<Asset> getAssetById(AssetId id) {
+    var cascade = _cascades[id.package];
+    if (cascade != null) return cascade.getAssetById(id);
+    return new Future.error(
+        new AssetNotFoundException(id),
+        new Trace.current().vmTrace);
+  }
+
+  /// Adds [sources] to the graph's known set of source assets.
+  ///
+  /// Begins applying any transforms that can consume any of the sources. If a
+  /// given source is already known, it is considered modified and all
+  /// transforms that use it will be re-applied.
+  void updateSources(Iterable<AssetId> sources) {
+    groupBy(sources, (id) => id.package).forEach((package, ids) {
+      var cascade = _cascades[package];
+      if (cascade == null) throw new ArgumentError("Unknown package $package.");
+      _cascadeResults[package] = null;
+      cascade.updateSources(ids);
+    });
+  }
+
+  /// Removes [removed] from the graph's known set of source assets.
+  void removeSources(Iterable<AssetId> sources) {
+    groupBy(sources, (id) => id.package).forEach((package, ids) {
+      var cascade = _cascades[package];
+      if (cascade == null) throw new ArgumentError("Unknown package $package.");
+      _cascadeResults[package] = null;
+      cascade.removeSources(ids);
+    });
+  }
+}
diff --git a/pkg/barback/lib/src/asset_provider.dart b/pkg/barback/lib/src/package_provider.dart
similarity index 72%
rename from pkg/barback/lib/src/asset_provider.dart
rename to pkg/barback/lib/src/package_provider.dart
index 565e5ac..8506d14 100644
--- a/pkg/barback/lib/src/asset_provider.dart
+++ b/pkg/barback/lib/src/package_provider.dart
@@ -2,18 +2,19 @@
 // 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 barback.asset_provider;
+library barback.package_provider;
 
 import 'dart:async';
 
 import 'asset.dart';
 import 'asset_id.dart';
+import 'transformer.dart';
 
 /// API for locating and accessing packages on disk.
 ///
 /// Implemented by pub and provided to barback so that it isn't coupled
 /// directly to pub.
-abstract class AssetProvider {
+abstract class PackageProvider {
   /// The names of all packages that can be provided by this provider.
   ///
   /// This is equal to the transitive closure of the entrypoint package
@@ -28,5 +29,11 @@
   /// within the package, to only return the files within that subdirectory.
   List<AssetId> listAssets(String package, {String within});
 
+  /// Returns the list of transformer phases that are applicable to [package].
+  ///
+  /// The phases will be run in sequence, with the outputs of one pipelined into
+  /// the next. All [Transformer]s in a single phase will be run in parallel.
+  Iterable<Iterable<Transformer>> getTransformers(String package);
+
   Future<Asset> getAsset(AssetId id);
 }
diff --git a/pkg/barback/lib/src/phase.dart b/pkg/barback/lib/src/phase.dart
index 26d64da..b4efbc7 100644
--- a/pkg/barback/lib/src/phase.dart
+++ b/pkg/barback/lib/src/phase.dart
@@ -7,7 +7,7 @@
 import 'dart:async';
 
 import 'asset.dart';
-import 'asset_graph.dart';
+import 'asset_cascade.dart';
 import 'asset_id.dart';
 import 'asset_node.dart';
 import 'asset_set.dart';
@@ -15,7 +15,7 @@
 import 'transform_node.dart';
 import 'transformer.dart';
 
-/// One phase in the ordered series of transformations in an [AssetGraph].
+/// One phase in the ordered series of transformations in an [AssetCascade].
 ///
 /// Each phase can access outputs from previous phases and can in turn pass
 /// outputs to later phases. Phases are processed strictly serially. All
@@ -28,8 +28,8 @@
 /// goes to advance to phase 3, it will see that modification and start the
 /// waterfall from the beginning again.
 class Phase {
-  /// The graph that owns this phase.
-  final AssetGraph graph;
+  /// The cascade that owns this phase.
+  final AssetCascade cascade;
 
   /// This phase's position relative to the other phases. Zero-based.
   final int _index;
@@ -64,7 +64,7 @@
   /// Outputs from this phase will be passed to it.
   final Phase _next;
 
-  Phase(this.graph, this._index, this._transformers, this._next);
+  Phase(this.cascade, this._index, this._transformers, this._next);
 
   /// Updates the phase's inputs with [updated] and removes [removed].
   ///
@@ -177,7 +177,7 @@
       collisions = collisions.toList();
       collisions.sort((a, b) => a.toString().compareTo(b.toString()));
       for (var collision in collisions) {
-        graph.reportError(new AssetCollisionException(collision));
+        cascade.reportError(new AssetCollisionException(collision));
         // TODO(rnystrom): Define what happens after a collision occurs.
       }
 
diff --git a/pkg/barback/lib/src/transform_node.dart b/pkg/barback/lib/src/transform_node.dart
index 194f073..b17c9a5 100644
--- a/pkg/barback/lib/src/transform_node.dart
+++ b/pkg/barback/lib/src/transform_node.dart
@@ -7,7 +7,6 @@
 import 'dart:async';
 
 import 'asset.dart';
-import 'asset_graph.dart';
 import 'asset_id.dart';
 import 'asset_node.dart';
 import 'asset_set.dart';
@@ -62,9 +61,9 @@
     var newOutputs = new AssetSet();
     var transform = createTransform(this, newInputs, newOutputs);
     return _transformer.apply(transform).catchError((error) {
-      // Catch all transformer errors and pipe them to the results stream.
-      // This is so a broken transformer doesn't take down the whole graph.
-      phase.graph.reportError(error);
+      // Catch all transformer errors and pipe them to the results stream. This
+      // is so a broken transformer doesn't take down the whole graph.
+      phase.cascade.reportError(error);
 
       // Don't allow partial results from a failed transform.
       newOutputs.clear();
@@ -86,6 +85,16 @@
 
       // See which outputs are missing from the last run.
       var outputIds = newOutputs.map((asset) => asset.id).toSet();
+      var invalidIds = outputIds
+          .where((id) => id.package != phase.cascade.package).toSet();
+      outputIds.removeAll(invalidIds);
+
+      for (var id in invalidIds) {
+        // TODO(nweiz): report this as a warning rather than a failing error.
+        phase.cascade.reportError(
+            new InvalidOutputException(phase.cascade.package, id));
+      }
+
       var removed = _outputs.difference(outputIds);
       _outputs = outputIds;
 
diff --git a/pkg/barback/lib/src/utils.dart b/pkg/barback/lib/src/utils.dart
index c4ab3a3..9da4b0e 100644
--- a/pkg/barback/lib/src/utils.dart
+++ b/pkg/barback/lib/src/utils.dart
@@ -4,6 +4,8 @@
 
 library barback.utils;
 
+import 'dart:async';
+
 /// Converts a number in the range [0-255] to a two digit hex string.
 ///
 /// For example, given `255`, returns `ff`.
@@ -12,4 +14,90 @@
 
   const DIGITS = "0123456789abcdef";
   return DIGITS[(byte ~/ 16) % 16] + DIGITS[byte % 16];
-}
\ No newline at end of file
+}
+
+/// Group the elements in [iter] by the value returned by [fn].
+///
+/// This returns a map whose keys are the return values of [fn] and whose values
+/// are lists of each element in [iter] for which [fn] returned that key.
+Map groupBy(Iterable iter, fn(element)) {
+  var map = {};
+  for (var element in iter) {
+    var list = map.putIfAbsent(fn(element), () => []);
+    list.add(element);
+  }
+  return map;
+}
+
+/// Flattens nested lists inside an iterable into a single list containing only
+/// non-list elements.
+List flatten(Iterable nested) {
+  var result = [];
+  helper(list) {
+    for (var element in list) {
+      if (element is List) {
+        helper(element);
+      } else {
+        result.add(element);
+      }
+    }
+  }
+  helper(nested);
+  return result;
+}
+
+/// Passes each key/value pair in [map] to [fn] and returns a new [Map] whose
+/// values are the return values of [fn].
+Map mapMapValues(Map map, fn(key, value)) =>
+  new Map.fromIterable(map.keys, value: (key) => fn(key, map[key]));
+
+/// Merges [streams] into a single stream that emits events from all sources.
+Stream mergeStreams(Iterable<Stream> streams) {
+  streams = streams.toList();
+  var doneCount = 0;
+  // Use a sync stream to preserve the synchrony behavior of the input streams.
+  // If the inputs are sync, then this will be sync as well; if the inputs are
+  // async, then the events we receive will also be async, and forwarding them
+  // sync won't change that.
+  var controller = new StreamController(sync: true);
+
+  for (var stream in streams) {
+    stream.listen((value) {
+      controller.add(value);
+    }, onError: (error) {
+      controller.addError(error);
+    }, onDone: () {
+      doneCount++;
+      if (doneCount == streams.length) controller.close();
+    });
+  }
+
+  return controller.stream;
+}
+
+/// Prepends each line in [text] with [prefix]. If [firstPrefix] is passed, the
+/// first line is prefixed with that instead.
+String prefixLines(String text, {String prefix: '| ', String firstPrefix}) {
+  var lines = text.split('\n');
+  if (firstPrefix == null) {
+    return lines.map((line) => '$prefix$line').join('\n');
+  }
+
+  var firstLine = "$firstPrefix${lines.first}";
+  lines = lines.skip(1).map((line) => '$prefix$line').toList();
+  lines.insert(0, firstLine);
+  return lines.join('\n');
+}
+
+/// Returns a [Future] that completes after pumping the event queue [times]
+/// times. By default, this should pump the event queue enough times to allow
+/// any code to run, as long as it's not waiting on some external event.
+Future pumpEventQueue([int times=20]) {
+  if (times == 0) return new Future.value();
+  // We use a delayed future to allow runAsync events to finish. The
+  // Future.value or Future() constructors use runAsync themselves and would
+  // therefore not wait for runAsync callbacks that are scheduled after invoking
+  // this method.
+  return new Future.delayed(Duration.ZERO, () => pumpEventQueue(times - 1));
+}
+
diff --git a/pkg/barback/pubspec.yaml b/pkg/barback/pubspec.yaml
index dcb2061..e0786a8 100644
--- a/pkg/barback/pubspec.yaml
+++ b/pkg/barback/pubspec.yaml
@@ -13,6 +13,7 @@
   responsiveness.
 dependencies:
   path: any
+  stack_trace: any
 dev_dependencies:
   scheduled_test: any
   unittest: any
diff --git a/pkg/barback/test/asset_graph/errors_test.dart b/pkg/barback/test/package_graph/errors_test.dart
similarity index 62%
rename from pkg/barback/test/asset_graph/errors_test.dart
rename to pkg/barback/test/package_graph/errors_test.dart
index 75e16bf..0653022 100644
--- a/pkg/barback/test/asset_graph/errors_test.dart
+++ b/pkg/barback/test/package_graph/errors_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.
 
-library barback.test.asset_graph.source_test;
+library barback.test.package_graph.source_test;
 
 import 'dart:async';
 
 import 'package:barback/barback.dart';
-import 'package:barback/src/asset_graph.dart';
 import 'package:scheduled_test/scheduled_test.dart';
 
 import '../utils.dart';
@@ -16,35 +15,43 @@
   initConfig();
 
   test("errors if two transformers output the same file", () {
-    initGraph(["app|foo.a"], [
+    initGraph(["app|foo.a"], {"app": [
       [
         new RewriteTransformer("a", "b"),
         new RewriteTransformer("a", "b")
       ]
-    ]);
+    ]});
     updateSources(["app|foo.a"]);
 
     buildShouldFail([isAssetCollisionException("app|foo.b")]);
   });
 
   test("does not report asset not found errors in results", () {
-    initGraph();
+    initGraph(["app|bar.txt"]);
+
+    // Trigger a build.
+    updateSources(["app|bar.txt"]);
 
     expectNoAsset("app|foo.txt");
     buildShouldSucceed();
   });
 
-  test("reports an error for an unprovided source", () {
+  test("reports an error for an unprovided package", () {
     initGraph();
+    expect(() => updateSources(["unknown|foo.txt"]), throwsArgumentError);
+  });
+
+  test("reports an error for an unprovided source", () {
+    initGraph(["app|known.txt"]);
     updateSources(["app|unknown.txt"]);
 
     buildShouldFail([isAssetNotFoundException("app|unknown.txt")]);
   });
 
   test("reports missing input errors in results", () {
-    initGraph({"app|a.txt": "a.inc"}, [
+    initGraph({"app|a.txt": "a.inc"}, {"app": [
       [new ManyToOneTransformer("txt")]
-    ]);
+    ]});
 
     buildShouldFail([isMissingInputException("app|a.inc")]);
 
@@ -53,15 +60,26 @@
     expectNoAsset("app|a.out");
   });
 
+  test("reports an error if a transformer emits an asset for another package",
+      () {
+    initGraph(["app|foo.txt"], {
+      "app": [[new CreateAssetTransformer("wrong|foo.txt")]]
+    });
+
+    buildShouldFail([isInvalidOutputException("app", "wrong|foo.txt")]);
+
+    updateSources(["app|foo.txt"]);
+  });
+
   test("fails if a non-primary input is removed", () {
     initGraph({
       "app|a.txt": "a.inc,b.inc,c.inc",
       "app|a.inc": "a",
       "app|b.inc": "b",
       "app|c.inc": "c"
-    }, [
+    }, {"app": [
       [new ManyToOneTransformer("txt")]
-    ]);
+    ]});
 
     updateSources(["app|a.txt", "app|a.inc", "app|b.inc", "app|c.inc"]);
     expectAsset("app|a.out", "abc");
@@ -76,9 +94,9 @@
   });
 
   test("catches transformer exceptions and reports them", () {
-    initGraph(["app|foo.txt"], [
+    initGraph(["app|foo.txt"], {"app": [
       [new BadTransformer(["app|foo.out"])]
-    ]);
+    ]});
 
     schedule(() {
       updateSources(["app|foo.txt"]);
@@ -92,9 +110,9 @@
   // TODO(rnystrom): Is this the behavior we expect? If a transformer fails
   // to transform a file, should we just skip past it to the source?
   test("yields a source if a transform fails on it", () {
-    initGraph(["app|foo.txt"], [
+    initGraph(["app|foo.txt"], {"app": [
       [new BadTransformer(["app|foo.txt"])]
-    ]);
+    ]});
 
     schedule(() {
       updateSources(["app|foo.txt"]);
@@ -104,7 +122,7 @@
   });
 
   test("catches errors even if nothing is waiting for process results", () {
-    initGraph(["app|foo.txt"], [[new BadTransformer([])]]);
+    initGraph(["app|foo.txt"], {"app": [[new BadTransformer([])]]});
 
     schedule(() {
       updateSources(["app|foo.txt"]);
@@ -116,9 +134,9 @@
   });
 
   test("discards outputs from failed transforms", () {
-    initGraph(["app|foo.txt"], [
+    initGraph(["app|foo.txt"], {"app": [
       [new BadTransformer(["a.out", "b.out"])]
-    ]);
+    ]});
 
     schedule(() {
       updateSources(["app|foo.txt"]);
@@ -126,4 +144,32 @@
 
     expectNoAsset("app|a.out");
   });
+
+  test("fails if only one package fails", () {
+    initGraph(["pkg1|foo.txt", "pkg2|foo.txt"],
+        {"pkg1": [[new BadTransformer([])]]});
+
+    schedule(() {
+      updateSources(["pkg1|foo.txt", "pkg2|foo.txt"]);
+    });
+
+    expectAsset("pkg2|foo.txt", "foo");
+    buildShouldFail([equals(BadTransformer.ERROR)]);
+  });
+
+  test("emits multiple failures if multiple packages fail", () {
+    initGraph(["pkg1|foo.txt", "pkg2|foo.txt"], {
+      "pkg1": [[new BadTransformer([])]],
+      "pkg2": [[new BadTransformer([])]]
+    });
+
+    schedule(() {
+      updateSources(["pkg1|foo.txt", "pkg2|foo.txt"]);
+    });
+
+    buildShouldFail([
+      equals(BadTransformer.ERROR),
+      equals(BadTransformer.ERROR)
+    ]);
+  });
 }
diff --git a/pkg/barback/test/asset_graph/source_test.dart b/pkg/barback/test/package_graph/source_test.dart
similarity index 92%
rename from pkg/barback/test/asset_graph/source_test.dart
rename to pkg/barback/test/package_graph/source_test.dart
index 8227edb..0367d88 100644
--- a/pkg/barback/test/asset_graph/source_test.dart
+++ b/pkg/barback/test/package_graph/source_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.
 
-library barback.test.asset_graph.source_test;
+library barback.test.package_graph.source_test;
 
 import 'dart:async';
 
 import 'package:barback/barback.dart';
-import 'package:barback/src/asset_graph.dart';
 import 'package:scheduled_test/scheduled_test.dart';
 
 import '../utils.dart';
@@ -44,9 +43,9 @@
   });
 
   test("gets a source asset if not transformed", () {
-    initGraph(["app|foo.txt"], [
+    initGraph(["app|foo.txt"], {"app": [
       [new RewriteTransformer("nottxt", "whatever")]
-    ]);
+    ]});
 
     updateSources(["app|foo.txt"]);
     expectAsset("app|foo.txt");
@@ -67,7 +66,7 @@
 
   test("collapses redundant updates", () {
     var transformer = new RewriteTransformer("blub", "blab");
-    initGraph(["app|foo.blub"], [[transformer]]);
+    initGraph(["app|foo.blub"], {"app": [[transformer]]});
 
     schedule(() {
       // Make a bunch of synchronous update calls.
@@ -108,7 +107,7 @@
 
   test("restarts a build if a source is updated while sources are loading", () {
     var transformer = new RewriteTransformer("txt", "out");
-    initGraph(["app|foo.txt", "app|other.bar"], [[transformer]]);
+    initGraph(["app|foo.txt", "app|other.bar"], {"app": [[transformer]]});
 
     // Run the whole graph so all nodes are clean.
     updateSources(["app|foo.txt", "app|other.bar"]);
diff --git a/pkg/barback/test/asset_graph/transform_test.dart b/pkg/barback/test/package_graph/transform_test.dart
similarity index 75%
rename from pkg/barback/test/asset_graph/transform_test.dart
rename to pkg/barback/test/package_graph/transform_test.dart
index 64d506f..ceabe21 100644
--- a/pkg/barback/test/asset_graph/transform_test.dart
+++ b/pkg/barback/test/package_graph/transform_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.
 
-library barback.test.asset_graph.transform_test;
+library barback.test.package_graph.transform_test;
 
 import 'dart:async';
 
 import 'package:barback/barback.dart';
-import 'package:barback/src/asset_graph.dart';
 import 'package:scheduled_test/scheduled_test.dart';
 
 import '../utils.dart';
@@ -15,57 +14,57 @@
 main() {
   initConfig();
   test("gets a transformed asset with a different path", () {
-    initGraph(["app|foo.blub"], [
+    initGraph(["app|foo.blub"], {"app": [
       [new RewriteTransformer("blub", "blab")]
-    ]);
+    ]});
     updateSources(["app|foo.blub"]);
     expectAsset("app|foo.blab", "foo.blab");
   });
 
   test("gets a transformed asset with the same path", () {
-    initGraph(["app|foo.blub"], [
+    initGraph(["app|foo.blub"], {"app": [
       [new RewriteTransformer("blub", "blub")]
-    ]);
+    ]});
     updateSources(["app|foo.blub"]);
     expectAsset("app|foo.blub", "foo.blub");
   });
 
   test("doesn't find an output from a later phase", () {
-    initGraph(["app|foo.a"], [
+    initGraph(["app|foo.a"], {"app": [
       [new RewriteTransformer("b", "c")],
       [new RewriteTransformer("a", "b")]
-    ]);
+    ]});
     updateSources(["app|foo.a"]);
     expectNoAsset("app|foo.c");
   });
 
   test("doesn't find an output from the same phase", () {
-    initGraph(["app|foo.a"], [
+    initGraph(["app|foo.a"], {"app": [
       [
         new RewriteTransformer("a", "b"),
         new RewriteTransformer("b", "c")
       ]
-    ]);
+    ]});
     updateSources(["app|foo.a"]);
     expectAsset("app|foo.b", "foo.b");
     expectNoAsset("app|foo.c");
   });
 
   test("finds the latest output before the transformer's phase", () {
-    initGraph(["app|foo.blub"], [
+    initGraph(["app|foo.blub"], {"app": [
       [new RewriteTransformer("blub", "blub")],
       [
         new RewriteTransformer("blub", "blub"),
         new RewriteTransformer("blub", "done")
       ],
       [new RewriteTransformer("blub", "blub")]
-    ]);
+    ]});
     updateSources(["app|foo.blub"]);
     expectAsset("app|foo.done", "foo.blub.done");
   });
 
   test("applies multiple transformations to an asset", () {
-    initGraph(["app|foo.a"], [
+    initGraph(["app|foo.a"], {"app": [
       [new RewriteTransformer("a", "b")],
       [new RewriteTransformer("b", "c")],
       [new RewriteTransformer("c", "d")],
@@ -76,14 +75,14 @@
       [new RewriteTransformer("h", "i")],
       [new RewriteTransformer("i", "j")],
       [new RewriteTransformer("j", "k")],
-    ]);
+    ]});
     updateSources(["app|foo.a"]);
     expectAsset("app|foo.k", "foo.b.c.d.e.f.g.h.i.j.k");
   });
 
   test("only runs a transform once for all of its outputs", () {
     var transformer = new RewriteTransformer("blub", "a b c");
-    initGraph(["app|foo.blub"], [[transformer]]);
+    initGraph(["app|foo.blub"], {"app": [[transformer]]});
     updateSources(["app|foo.blub"]);
     expectAsset("app|foo.a", "foo.a");
     expectAsset("app|foo.b", "foo.b");
@@ -96,7 +95,7 @@
   test("runs transforms in the same phase in parallel", () {
     var transformerA = new RewriteTransformer("txt", "a");
     var transformerB = new RewriteTransformer("txt", "b");
-    initGraph(["app|foo.txt"], [[transformerA, transformerB]]);
+    initGraph(["app|foo.txt"], {"app": [[transformerA, transformerB]]});
 
     transformerA.wait();
     transformerB.wait();
@@ -123,7 +122,7 @@
 
   test("does not reapply transform when inputs are not modified", () {
     var transformer = new RewriteTransformer("blub", "blab");
-    initGraph(["app|foo.blub"], [[transformer]]);
+    initGraph(["app|foo.blub"], {"app": [[transformer]]});
     updateSources(["app|foo.blub"]);
     expectAsset("app|foo.blab", "foo.blab");
     expectAsset("app|foo.blab", "foo.blab");
@@ -136,7 +135,7 @@
 
   test("reapplies a transform when its input is modified", () {
     var transformer = new RewriteTransformer("blub", "blab");
-    initGraph(["app|foo.blub"], [[transformer]]);
+    initGraph(["app|foo.blub"], {"app": [[transformer]]});
 
     schedule(() {
       updateSources(["app|foo.blub"]);
@@ -167,7 +166,7 @@
       "app|a.txt": "a.inc,b.inc",
       "app|a.inc": "a",
       "app|b.inc": "b"
-    }, [[transformer]]);
+    }, {"app": [[transformer]]});
 
     updateSources(["app|a.txt", "app|a.inc", "app|b.inc"]);
 
@@ -195,9 +194,9 @@
   });
 
   test("allows a transform to generate multiple outputs", () {
-    initGraph({"app|foo.txt": "a.out,b.out"}, [
+    initGraph({"app|foo.txt": "a.out,b.out"}, {"app": [
       [new OneToManyTransformer("txt")]
-    ]);
+    ]});
 
     updateSources(["app|foo.txt"]);
 
@@ -210,10 +209,10 @@
     var aa = new RewriteTransformer("aa", "aaa");
     var b = new RewriteTransformer("b", "bb");
     var bb = new RewriteTransformer("bb", "bbb");
-    initGraph(["app|foo.a", "app|foo.b"], [
+    initGraph(["app|foo.a", "app|foo.b"], {"app": [
       [a, b],
       [aa, bb],
-    ]);
+    ]});
 
     updateSources(["app|foo.a"]);
     updateSources(["app|foo.b"]);
@@ -236,9 +235,9 @@
 
   test("doesn't get an output from a transform whose primary input is removed",
       () {
-    initGraph(["app|foo.txt"], [
+    initGraph(["app|foo.txt"], {"app": [
       [new RewriteTransformer("txt", "out")]
-    ]);
+    ]});
 
     updateSources(["app|foo.txt"]);
     expectAsset("app|foo.out", "foo.out");
@@ -254,7 +253,7 @@
    initGraph({
       "app|a.txt": "a.inc",
       "app|a.inc": "a"
-    }, [[new ManyToOneTransformer("txt")]]);
+    }, {"app": [[new ManyToOneTransformer("txt")]]});
 
     updateSources(["app|a.txt", "app|a.inc"]);
     expectAsset("app|a.out", "a");
@@ -269,7 +268,7 @@
 
   test("restarts processing if a change occurs during processing", () {
     var transformer = new RewriteTransformer("txt", "out");
-    initGraph(["app|foo.txt"], [[transformer]]);
+    initGraph(["app|foo.txt"], {"app": [[transformer]]});
 
     transformer.wait();
 
@@ -301,9 +300,9 @@
     initGraph({
       "app|a.a": "a.out,shared.out",
       "app|b.b": "b.out"
-    }, [
+    }, {"app": [
       [new OneToManyTransformer("a"), new OneToManyTransformer("b")]
-    ]);
+    ]});
 
     updateSources(["app|a.a", "app|b.b"]);
 
@@ -327,7 +326,8 @@
   test("restarts before finishing later phases when a change occurs", () {
     var txtToInt = new RewriteTransformer("txt", "int");
     var intToOut = new RewriteTransformer("int", "out");
-    initGraph(["app|foo.txt", "app|bar.txt"], [[txtToInt], [intToOut]]);
+    initGraph(["app|foo.txt", "app|bar.txt"],
+        {"app": [[txtToInt], [intToOut]]});
 
     txtToInt.wait();
 
@@ -356,4 +356,55 @@
       expect(intToOut.numRuns, equals(2));
     });
   });
+
+  test("applies transforms to the correct packages", () {
+    var rewrite1 = new RewriteTransformer("txt", "out1");
+    var rewrite2 = new RewriteTransformer("txt", "out2");
+    initGraph([
+      "pkg1|foo.txt",
+      "pkg2|foo.txt"
+    ], {"pkg1": [[rewrite1]], "pkg2": [[rewrite2]]});
+
+    updateSources(["pkg1|foo.txt", "pkg2|foo.txt"]);
+    expectAsset("pkg1|foo.out1", "foo.out1");
+    expectAsset("pkg2|foo.out2", "foo.out2");
+    buildShouldSucceed();
+  });
+
+  test("transforms don't see generated assets in other packages", () {
+    var fooToBar = new RewriteTransformer("foo", "bar");
+    var barToBaz = new RewriteTransformer("bar", "baz");
+    initGraph(["pkg1|file.foo"], {"pkg1": [[fooToBar]], "pkg2": [[barToBaz]]});
+
+    updateSources(["pkg1|file.foo"]);
+    expectAsset("pkg1|file.bar", "file.bar");
+    expectNoAsset("pkg2|file.baz");
+    buildShouldSucceed();
+  });
+
+  test("doesn't emit a result until all builds are finished", () {
+    var rewrite = new RewriteTransformer("txt", "out");
+    initGraph([
+      "pkg1|foo.txt",
+      "pkg2|foo.txt"
+    ], {"pkg1": [[rewrite]], "pkg2": [[rewrite]]});
+
+    // First, run both packages' transformers so both packages are successful.
+    updateSources(["pkg1|foo.txt", "pkg2|foo.txt"]);
+    expectAsset("pkg1|foo.out", "foo.out");
+    expectAsset("pkg2|foo.out", "foo.out");
+    buildShouldSucceed();
+
+    // pkg1 is still successful, but pkg2 is waiting on the provider, so the
+    // overall build shouldn't finish.
+    pauseProvider();
+    schedule(() => updateSources(["pkg2|foo.txt"]));
+    expectAsset("pkg1|foo.out", "foo.out");
+    buildShouldNotBeDone();
+
+    // Now that the provider is unpaused, pkg2's transforms finish and the
+    // overall build succeeds.
+    resumeProvider();
+    buildShouldSucceed();
+  });
 }
diff --git a/pkg/barback/test/utils.dart b/pkg/barback/test/utils.dart
index 0641a57..1dda697 100644
--- a/pkg/barback/test/utils.dart
+++ b/pkg/barback/test/utils.dart
@@ -9,15 +9,18 @@
 import 'dart:io';
 
 import 'package:barback/barback.dart';
-import 'package:barback/src/asset_graph.dart';
+import 'package:barback/src/asset_cascade.dart';
+import 'package:barback/src/package_graph.dart';
+import 'package:barback/src/utils.dart';
 import 'package:path/path.dart' as pathos;
 import 'package:scheduled_test/scheduled_test.dart';
+import 'package:stack_trace/stack_trace.dart';
 import 'package:unittest/compact_vm_config.dart';
 
 var _configured = false;
 
 MockProvider _provider;
-AssetGraph _graph;
+PackageGraph _graph;
 
 /// Calls to [buildShouldSucceed] and [buildShouldFail] set expectations on
 /// successive [BuildResult]s from [_graph]. This keeps track of how many calls
@@ -30,8 +33,8 @@
   useCompactVMConfiguration();
 }
 
-/// Creates a new [AssetProvider] and [AssetGraph] with the given [assets] and
-/// [transformers].
+/// Creates a new [PackageProvider] and [PackageGraph] with the given [assets]
+/// and [transformers].
 ///
 /// This graph is used internally by most of the other functions in this
 /// library so you must call it in the test before calling any of the other
@@ -42,16 +45,20 @@
 /// one. If it's a [Map], each key should be a string that can be parsed to an
 /// [AssetId] and the value should be a string defining the contents of that
 /// asset.
-void initGraph([assets, Iterable<Iterable<Transformer>> transformers]) {
+///
+/// [transformers] is a map from package names to the transformers for each
+/// package.
+void initGraph([assets,
+    Map<String, Iterable<Iterable<Transformer>>> transformers]) {
   if (assets == null) assets = [];
-  if (transformers == null) transformers = [];
+  if (transformers == null) transformers = {};
 
-  _provider = new MockProvider(assets);
-  _graph = new AssetGraph(_provider, transformers);
+  _provider = new MockProvider(assets, transformers);
+  _graph = new PackageGraph(_provider);
   _nextBuildResult = 0;
 }
 
-/// Updates [assets] in the current [AssetProvider].
+/// Updates [assets] in the current [PackageProvider].
 ///
 /// Each item in the list may either be an [AssetId] or a string that can be
 /// parsed as one. Note that this method is not automatically scheduled.
@@ -65,7 +72,7 @@
   _graph.updateSources(assets);
 }
 
-/// Removes [assets] from the current [AssetProvider].
+/// Removes [assets] from the current [PackageProvider].
 ///
 /// Each item in the list may either be an [AssetId] or a string that can be
 /// parsed as one. Note that this method is not automatically scheduled.
@@ -89,12 +96,12 @@
   }, "modify asset $name");
 }
 
-/// Schedules a pause of the internally created [AssetProvider].
+/// Schedules a pause of the internally created [PackageProvider].
 ///
-/// All asset requests that the [AssetGraph] makes to the provider after this
+/// All asset requests that the [PackageGraph] makes to the provider after this
 /// will not complete until [resumeProvider] is called.
 void pauseProvider() {
-  schedule(() =>_provider._pause(), "pause provider");
+  schedule(() => _provider._pause(), "pause provider");
 }
 
 /// Schedules an unpause of the provider after a call to [pauseProvider] and
@@ -103,9 +110,38 @@
   schedule(() => _provider._resume(), "resume provider");
 }
 
+/// Asserts that the current build step shouldn't have finished by this point in
+/// the schedule.
+///
+/// This uses the same build counter as [buildShouldSucceed] and
+/// [buildShouldFail], so those can be used to validate build results before and
+/// after this.
+void buildShouldNotBeDone() {
+  var resultAllowed = false;
+  var trace = new Trace.current();
+  _graph.results.elementAt(_nextBuildResult).then((result) {
+    if (resultAllowed) return;
+
+    currentSchedule.signalError(
+        new Exception("Expected build not to terminate "
+            "here, but it terminated with result: $result"), trace);
+  }).catchError((error) {
+    if (resultAllowed) return;
+    currentSchedule.signalError(error);
+  });
+
+  schedule(() {
+    // Pump the event queue in case the build completes out-of-band after we get
+    // here. If it does, we want to signal an error.
+    return pumpEventQueue().then((_) {
+      resultAllowed = true;
+    });
+  }, "ensuring build doesn't terminate");
+}
+
 /// Expects that the next [BuildResult] is a build success.
 void buildShouldSucceed() {
-  expect(_graph.results.elementAt(_nextBuildResult++).then((result) {
+  expect(_getNextBuildResult().then((result) {
     expect(result.succeeded, isTrue);
   }), completes);
 }
@@ -116,7 +152,7 @@
 /// build to fail. Every matcher is expected to match an error, but the order of
 /// matchers is unimportant.
 void buildShouldFail(List matchers) {
-  expect(_graph.results.elementAt(_nextBuildResult++).then((result) {
+  expect(_getNextBuildResult().then((result) {
     expect(result.succeeded, isFalse);
     expect(result.errors.length, equals(matchers.length));
     for (var matcher in matchers) {
@@ -125,6 +161,9 @@
   }), completes);
 }
 
+Future<BuildResult> _getNextBuildResult() =>
+  _graph.results.elementAt(_nextBuildResult++);
+
 /// Pauses the schedule until the currently running build completes.
 ///
 /// Validates that the build completed successfully.
@@ -174,22 +213,6 @@
   }, "get asset $name");
 }
 
-/// Schedules an expectation that [graph] will have an error on an asset
-/// matching [name] for missing [input].
-Future expectMissingInput(AssetGraph graph, String name, String input) {
-  var missing = new AssetId.parse(input);
-
-  // Make sure the future gets the error.
-  schedule(() {
-    return graph.getAssetById(new AssetId.parse(name)).then((asset) {
-      fail("Should have thrown error but got $asset.");
-    }).catchError((error) {
-      expect(error, new isInstanceOf<MissingInputException>());
-      expect(error.id, equals(missing));
-    });
-  }, "get missing input on $name");
-}
-
 /// Returns a matcher for an [AssetNotFoundException] with the given [id].
 Matcher isAssetNotFoundException(String name) {
   var id = new AssetId.parse(name);
@@ -214,11 +237,21 @@
       predicate((error) => error.id == id, 'id is $name'));
 }
 
+/// Returns a matcher for an [InvalidOutputException] with the given id and
+/// package name.
+Matcher isInvalidOutputException(String package, String name) {
+  var id = new AssetId.parse(name);
+  return allOf(
+      new isInstanceOf<InvalidOutputException>(),
+      predicate((error) => error.package == package, 'package is $package'),
+      predicate((error) => error.id == id, 'id is $name'));
+}
+
 /// An [AssetProvider] that provides the given set of assets.
-class MockProvider implements AssetProvider {
+class MockProvider implements PackageProvider {
   Iterable<String> get packages => _packages.keys;
 
-  final _packages = new Map<String, List<MockAsset>>();
+  Map<String, _MockPackage> _packages;
 
   /// The completer that [getAsset()] is waiting on to complete when paused.
   ///
@@ -238,26 +271,38 @@
     _pauseCompleter = null;
   }
 
-  MockProvider(assets) {
+  MockProvider(assets,
+      Map<String, Iterable<Iterable<Transformer>>> transformers) {
+    var assetList;
     if (assets is Map) {
-      assets.forEach((asset, contents) {
+      assetList = assets.keys.map((asset) {
         var id = new AssetId.parse(asset);
-        var package = _packages.putIfAbsent(id.package, () => []);
-        package.add(new MockAsset(id, contents));
+        return new MockAsset(id, assets[asset]);
       });
     } else if (assets is Iterable) {
-      for (var asset in assets) {
+      assetList = assets.map((asset) {
         var id = new AssetId.parse(asset);
-        var package = _packages.putIfAbsent(id.package, () => []);
         var contents = pathos.basenameWithoutExtension(id.path);
-        package.add(new MockAsset(id, contents));
-      }
+        return new MockAsset(id, contents);
+      });
     }
+
+    _packages = mapMapValues(groupBy(assetList, (asset) => asset.id.package),
+        (package, assets) {
+      var packageTransformers = transformers[package];
+      if (packageTransformers == null) packageTransformers = [];
+      return new _MockPackage(assets, packageTransformers.toList());
+    });
+
+    // If there are no assets or transformers, add a dummy package. This better
+    // simulates the real world, where there'll always be at least the
+    // entrypoint package.
+    if (_packages.isEmpty) _packages = {"app": new _MockPackage([], [])};
   }
 
   void _modifyAsset(String name, String contents) {
     var id = new AssetId.parse(name);
-    var asset = _packages[id.package].firstWhere((a) => a.id == id);
+    var asset = _packages[id.package].assets.firstWhere((a) => a.id == id);
     asset.contents = contents;
   }
 
@@ -266,7 +311,15 @@
       throw new UnimplementedError("Doesn't handle 'within' yet.");
     }
 
-    return _packages[package].map((asset) => asset.id);
+    return _packages[package].assets.map((asset) => asset.id);
+  }
+
+  Iterable<Iterable<Transformer>> getTransformers(String package) {
+    var mockPackage = _packages[package];
+    if (mockPackage == null) {
+      throw new ArgumentError("No package named $package.");
+    }
+    return mockPackage.transformers;
   }
 
   Future<Asset> getAsset(AssetId id) {
@@ -281,12 +334,22 @@
       var package = _packages[id.package];
       if (package == null) throw new AssetNotFoundException(id);
 
-      return package.firstWhere((asset) => asset.id == id,
+      return package.assets.firstWhere((asset) => asset.id == id,
           orElse: () => throw new AssetNotFoundException(id));
     });
   }
 }
 
+/// Used by [MockProvider] to keep track of which assets and transformers exist
+/// for each package.
+class _MockPackage {
+  final List<MockAsset> assets;
+  final List<List<Transformer>> transformers;
+
+  _MockPackage(this.assets, Iterable<Iterable<Transformer>> transformers)
+      : transformers = transformers.map((phase) => phase.toList()).toList();
+}
+
 /// A [Transformer] that takes assets ending with one extension and generates
 /// assets with a given extension.
 ///
@@ -466,6 +529,21 @@
   }
 }
 
+/// A transformer that outputs an asset with the given id.
+class CreateAssetTransformer extends Transformer {
+  final String output;
+
+  CreateAssetTransformer(this.output);
+
+  Future<bool> isPrimary(Asset asset) => new Future.value(true);
+
+  Future apply(Transform transform) {
+    return new Future(() {
+      transform.addOutput(new MockAsset(new AssetId.parse(output), output));
+    });
+  }
+}
+
 /// An implementation of [Asset] that never hits the file system.
 class MockAsset implements Asset {
   final AssetId id;
diff --git a/pkg/browser/lib/interop.js b/pkg/browser/lib/interop.js
index 52cc966..40e1700 100644
--- a/pkg/browser/lib/interop.js
+++ b/pkg/browser/lib/interop.js
@@ -13,6 +13,11 @@
   ReceivePortSync.map[this.id] = this;
 }
 
+// Type for remote proxies to Dart objects with dart2js.
+function DartProxy(o) {
+  this.o = o;
+}
+
 (function() {
   // Serialize the following types as follows:
   //  - primitives / null: unchanged
@@ -215,3 +220,320 @@
     return deserialize(result);
   }
 })();
+
+(function() {
+  // Proxy support for js.dart.
+
+  var globalContext = window;
+
+  // Table for local objects and functions that are proxied.
+  function ProxiedObjectTable() {
+    // Name for debugging.
+    this.name = 'js-ref';
+
+    // Table from IDs to JS objects.
+    this.map = {};
+
+    // Generator for new IDs.
+    this._nextId = 0;
+
+    // Ports for managing communication to proxies.
+    this.port = new ReceivePortSync();
+    this.sendPort = this.port.toSendPort();
+  }
+
+  // Number of valid IDs.  This is the number of objects (global and local)
+  // kept alive by this table.
+  ProxiedObjectTable.prototype.count = function () {
+    return Object.keys(this.map).length;
+  }
+
+  // Adds an object to the table and return an ID for serialization.
+  ProxiedObjectTable.prototype.add = function (obj) {
+    for (var ref in this.map) {
+      var o = this.map[ref];
+      if (o === obj) {
+        return ref;
+      }
+    }
+    var ref = this.name + '-' + this._nextId++;
+    this.map[ref] = obj;
+    return ref;
+  }
+
+  // Gets the object or function corresponding to this ID.
+  ProxiedObjectTable.prototype.get = function (id) {
+    if (!this.map.hasOwnProperty(id)) {
+      throw 'Proxy ' + id + ' has been invalidated.'
+    }
+    return this.map[id];
+  }
+
+  ProxiedObjectTable.prototype._initialize = function () {
+    // Configure this table's port to forward methods, getters, and setters
+    // from the remote proxy to the local object.
+    var table = this;
+
+    this.port.receive(function (message) {
+      // TODO(vsm): Support a mechanism to register a handler here.
+      try {
+        var receiver = table.get(message[0]);
+        var member = message[1];
+        var kind = message[2];
+        var args = message[3].map(deserialize);
+        if (kind == 'get') {
+          // Getter.
+          var field = member;
+          if (field in receiver && args.length == 0) {
+            return [ 'return', serialize(receiver[field]) ];
+          }
+        } else if (kind == 'set') {
+          // Setter.
+          var field = member;
+          if (args.length == 1) {
+            return [ 'return', serialize(receiver[field] = args[0]) ];
+          }
+        } else if (kind == 'hasProperty') {
+          var field = member;
+          return [ 'return', field in receiver ];
+        } else if (kind == 'apply') {
+          // Direct function invocation.
+          return [ 'return',
+              serialize(receiver.apply(args[0], args.slice(1))) ];
+        } else if (member == '[]' && args.length == 1) {
+          // Index getter.
+          return [ 'return', serialize(receiver[args[0]]) ];
+        } else if (member == '[]=' && args.length == 2) {
+          // Index setter.
+          return [ 'return', serialize(receiver[args[0]] = args[1]) ];
+        } else {
+          // Member function invocation.
+          var f = receiver[member];
+          if (f) {
+            var result = f.apply(receiver, args);
+            return [ 'return', serialize(result) ];
+          }
+        }
+        return [ 'none' ];
+      } catch (e) {
+        return [ 'throws', e.toString() ];
+      }
+    });
+  }
+
+  // Singleton for local proxied objects.
+  var proxiedObjectTable = new ProxiedObjectTable();
+  proxiedObjectTable._initialize()
+
+  // Type for remote proxies to Dart objects.
+  function DartProxy(id, sendPort) {
+    this.id = id;
+    this.port = sendPort;
+  }
+
+  // Serializes JS types to SendPortSync format:
+  // - primitives -> primitives
+  // - sendport -> sendport
+  // - Function -> [ 'funcref', function-id, sendport ]
+  // - Object -> [ 'objref', object-id, sendport ]
+  function serialize(message) {
+    if (message == null) {
+      return null;  // Convert undefined to null.
+    } else if (typeof(message) == 'string' ||
+               typeof(message) == 'number' ||
+               typeof(message) == 'boolean') {
+      // Primitives are passed directly through.
+      return message;
+    } else if (message instanceof SendPortSync) {
+      // Non-proxied objects are serialized.
+      return message;
+    } else if (typeof(message) == 'function') {
+      if ('_dart_id' in message) {
+        // Remote function proxy.
+        var remoteId = message._dart_id;
+        var remoteSendPort = message._dart_port;
+        return [ 'funcref', remoteId, remoteSendPort ];
+      } else {
+        // Local function proxy.
+        return [ 'funcref',
+                 proxiedObjectTable.add(message),
+                 proxiedObjectTable.sendPort ];
+      }
+    } else if (message instanceof DartProxy) {
+      // Remote object proxy.
+      return [ 'objref', message.id, message.port ];
+    } else {
+      // Local object proxy.
+      return [ 'objref',
+               proxiedObjectTable.add(message),
+               proxiedObjectTable.sendPort ];
+    }
+  }
+
+  function deserialize(message) {
+    if (message == null) {
+      return null;  // Convert undefined to null.
+    } else if (typeof(message) == 'string' ||
+               typeof(message) == 'number' ||
+               typeof(message) == 'boolean') {
+      // Primitives are passed directly through.
+      return message;
+    } else if (message instanceof SendPortSync) {
+      // Serialized type.
+      return message;
+    }
+    var tag = message[0];
+    switch (tag) {
+      case 'funcref': return deserializeFunction(message);
+      case 'objref': return deserializeObject(message);
+    }
+    throw 'Unsupported serialized data: ' + message;
+  }
+
+  // Create a local function that forwards to the remote function.
+  function deserializeFunction(message) {
+    var id = message[1];
+    var port = message[2];
+    // TODO(vsm): Add a more robust check for a local SendPortSync.
+    if ("receivePort" in port) {
+      // Local function.
+      return proxiedObjectTable.get(id);
+    } else {
+      // Remote function.  Forward to its port.
+      var f = function () {
+        var args = Array.prototype.slice.apply(arguments);
+        args.splice(0, 0, this);
+        args = args.map(serialize);
+        var result = port.callSync([id, '#call', args]);
+        if (result[0] == 'throws') throw deserialize(result[1]);
+        return deserialize(result[1]);
+      };
+      // Cache the remote id and port.
+      f._dart_id = id;
+      f._dart_port = port;
+      return f;
+    }
+  }
+
+  // Creates a DartProxy to forwards to the remote object.
+  function deserializeObject(message) {
+    var id = message[1];
+    var port = message[2];
+    // TODO(vsm): Add a more robust check for a local SendPortSync.
+    if ("receivePort" in port) {
+      // Local object.
+      return proxiedObjectTable.get(id);
+    } else {
+      // Remote object.
+      return new DartProxy(id, port);
+    }
+  }
+
+  // Remote handler to construct a new JavaScript object given its
+  // serialized constructor and arguments.
+  function construct(args) {
+    args = args.map(deserialize);
+    var constructor = args[0];
+    args = Array.prototype.slice.call(args, 1);
+
+    // Until 10 args, the 'new' operator is used. With more arguments we use a
+    // generic way that may not work, particularly when the constructor does not
+    // have an "apply" method.
+    var ret = null;
+    if (args.length === 0) {
+      ret = new constructor();
+    } else if (args.length === 1) {
+      ret = new constructor(args[0]);
+    } else if (args.length === 2) {
+      ret = new constructor(args[0], args[1]);
+    } else if (args.length === 3) {
+      ret = new constructor(args[0], args[1], args[2]);
+    } else if (args.length === 4) {
+      ret = new constructor(args[0], args[1], args[2], args[3]);
+    } else if (args.length === 5) {
+      ret = new constructor(args[0], args[1], args[2], args[3], args[4]);
+    } else if (args.length === 6) {
+      ret = new constructor(args[0], args[1], args[2], args[3], args[4],
+                            args[5]);
+    } else if (args.length === 7) {
+      ret = new constructor(args[0], args[1], args[2], args[3], args[4],
+                            args[5], args[6]);
+    } else if (args.length === 8) {
+      ret = new constructor(args[0], args[1], args[2], args[3], args[4],
+                            args[5], args[6], args[7]);
+    } else if (args.length === 9) {
+      ret = new constructor(args[0], args[1], args[2], args[3], args[4],
+                            args[5], args[6], args[7], args[8]);
+    } else if (args.length === 10) {
+      ret = new constructor(args[0], args[1], args[2], args[3], args[4],
+                            args[5], args[6], args[7], args[8], args[9]);
+    } else {
+      // Dummy Type with correct constructor.
+      var Type = function(){};
+      Type.prototype = constructor.prototype;
+
+      // Create a new instance
+      var instance = new Type();
+
+      // Call the original constructor.
+      ret = constructor.apply(instance, args);
+      ret = Object(ret) === ret ? ret : instance;
+    }
+    return serialize(ret);
+  }
+
+  // Remote handler to return the top-level JavaScript context.
+  function context(data) {
+    return serialize(globalContext);
+  }
+
+  // Return true if a JavaScript proxy is instance of a given type (instanceof).
+  function proxyInstanceof(args) {
+    var obj = deserialize(args[0]);
+    var type = deserialize(args[1]);
+    return obj instanceof type;
+  }
+
+  // Return true if a JavaScript proxy is instance of a given type (instanceof).
+  function proxyDeleteProperty(args) {
+    var obj = deserialize(args[0]);
+    var member = deserialize(args[1]);
+    delete obj[member];
+  }
+
+  function proxyConvert(args) {
+    return serialize(deserializeDataTree(args));
+  }
+
+  function deserializeDataTree(data) {
+    var type = data[0];
+    var value = data[1];
+    if (type === 'map') {
+      var obj = {};
+      for (var i = 0; i < value.length; i++) {
+        obj[value[i][0]] = deserializeDataTree(value[i][1]);
+      }
+      return obj;
+    } else if (type === 'list') {
+      var list = [];
+      for (var i = 0; i < value.length; i++) {
+        list.push(deserializeDataTree(value[i]));
+      }
+      return list;
+    } else /* 'simple' */ {
+      return deserialize(value);
+    }
+  }
+
+  function makeGlobalPort(name, f) {
+    var port = new ReceivePortSync();
+    port.receive(f);
+    window.registerPort(name, port.toSendPort());
+  }
+
+  makeGlobalPort('dart-js-context', context);
+  makeGlobalPort('dart-js-create', construct);
+  makeGlobalPort('dart-js-instanceof', proxyInstanceof);
+  makeGlobalPort('dart-js-delete-property', proxyDeleteProperty);
+  makeGlobalPort('dart-js-convert', proxyConvert);
+})();
diff --git a/pkg/docgen/README.md b/pkg/docgen/README.md
index a26d1e9..0e3b3da 100644
--- a/pkg/docgen/README.md
+++ b/pkg/docgen/README.md
@@ -1,11 +1,65 @@
+docgen
+======
+
 A documentation generator for Dart.
+- - -
+The docgen tool takes in a file or directory as input and produces documentation
+for all `.dart` file it finds as YAML or JSON files. This outputs information 
+about all classes, variables, functions, and methods defined in the library and 
+its imported libraries.
 
-The docgen tool takes in a library as input and produces documentation
-for it as well as all libraries it imports and uses.
+### Generating Files & Uploading to Cloud Storage
 
-This outputs information about all classes, variables, functions, and
-methods defined in the library and its imported libraries.
+The viewer uses YAML files generated by the docgen package as the data 
+being displayed. These files are stored in Google Cloud Storage.
 
-## USAGE
+ - Run `python upload_docgen.py` to generate these files and upload them to 
+ Cloud Storage as a new version.
+- - -
+These tasks can be done separately if necessary:
 
-  dart docgen.dart path/to/file.dart
\ No newline at end of file
+##### 
+
+#### Generating YAML Files
+
+YAML files can be generated using the docgen package in the dart repository. 
+
+###### Usage 
+
+Run  `dart docgen.dart [OPTIONS] <path to directory or file>`
+
+###### Options available
+
+- `-h`, `--help` Prints help and usage information.
+- `-v`, `--verbose` Output more logging information.
+- `-j`, `--[no-]json` Outputs to JSON. Files are outputted to YAML by default.
+- `--include-private` Flag to include private declarations.
+- `--include-sdk` Flag to parse SDK Library files imported.
+- `--parse-sdk` Parses the SDK libraries only. (Ignores the path passed in.)
+- `--package-root` Sets the package root of the library being analyzed.
+
+###### Output Directory
+Documented libraries will be located at bin/docs in either YAML or JSON format 
+depending on options specified. There will also be a library_list.txt, 
+containing a list of all the libraries inside the docs folder. 
+
+To get more information on how to use the outputted documentation with 
+dartdoc-viewer, please take a look at the 
+[dartdoc-viewer documentation][dartdoc-viewer].
+
+[dartdoc-viewer]: https://github.com/dart-lang/dartdoc-viewer "Dartdoc-Viewer"
+
+#### Uploading to Cloud Storage
+
+To push new files to Google Cloud Storage for use by the viewer, use the 
+`gsutil` tool located at third_party/gsutil/gsutil in the Dart repository.
+
+ - Run `python gsutil -m cp -q -a public-read -r <folder> gs://dartlang-docgen`
+ to upload the specified folder to the viewer's bucket. Be sure to also upload 
+ a new VERSION file if the uploaded folder is to be used.**
+
+**Note that the bucket contains several numbered folders for each version of 
+the documentation. Run `python gsutil ls gs://dartlang-docgen` to see the file 
+layout. Follow this convention and update a new VERSION file when uploading 
+a new version of documentation. You can see the format of the VERSION file 
+by running `python gsutil cat gs://dartlang-docgen/VERSION`.
diff --git a/pkg/docgen/lib/dart2yaml.dart b/pkg/docgen/lib/dart2yaml.dart
index a481aca..cccb8eb 100644
--- a/pkg/docgen/lib/dart2yaml.dart
+++ b/pkg/docgen/lib/dart2yaml.dart
@@ -52,8 +52,11 @@
  * Returns an escaped String form of the inputted element.
  */
 String _processElement(var element) {
-  return "\"${element.toString().replaceAll('\\', '\\\\')
-    .replaceAll("\"", "\\\"")}\"\n";
+  var contents = element.toString()
+      .replaceAll('\\', r'\\')
+      .replaceAll('"', r'\"')
+      .replaceAll('\n', r'\n');
+  return '"$contents"\n';
 }
 
 /**
diff --git a/pkg/docgen/lib/docgen.dart b/pkg/docgen/lib/docgen.dart
index 357fe96..f88df54 100644
--- a/pkg/docgen/lib/docgen.dart
+++ b/pkg/docgen/lib/docgen.dart
@@ -266,9 +266,9 @@
       }
     }
   });
-  commentText = commentText == null ? '' :
-      markdown.markdownToHtml(commentText.trim(), linkResolver: linkResolver)
-      .replaceAll('\n', ' ');
+  
+  commentText = commentText == null ? '' : 
+      markdown.markdownToHtml(commentText.trim(), linkResolver: linkResolver);
   return commentText;
 }
 
@@ -300,9 +300,9 @@
   mirrorMap.forEach((String mirrorName, VariableMirror mirror) {
     if (includePrivate || !mirror.isPrivate) {
       _currentMember = mirror;
-      data[mirrorName] = new Variable(mirrorName, mirror.qualifiedName,
-          mirror.isFinal, mirror.isStatic, mirror.type.qualifiedName,
-          _getComment(mirror), _getAnnotations(mirror));
+      data[mirrorName] = new Variable(mirrorName, mirror.isFinal, 
+          mirror.isStatic, mirror.type.qualifiedName, _getComment(mirror), 
+          _getAnnotations(mirror));
     }
   });
   return data;
@@ -311,21 +311,42 @@
 /**
  * Returns a map of [Method] objects constructed from inputted mirrors.
  */
-Map<String, Method> _getMethods(Map<String, MethodMirror> mirrorMap,
-    bool includePrivate) {
-  var data = {};
+Map<String, Map<String, Method>> _getMethods
+    (Map<String, MethodMirror> mirrorMap, bool includePrivate) {
+
+  var setters = {};
+  var getters = {};
+  var constructors = {};
+  var operators = {};
+  var methods = {};
+  
   mirrorMap.forEach((String mirrorName, MethodMirror mirror) {
     if (includePrivate || !mirror.isPrivate) {
+      var method = new Method(mirrorName, mirror.isStatic, 
+          mirror.returnType.qualifiedName, _getComment(mirror), 
+          _getParameters(mirror.parameters), _getAnnotations(mirror));
       _currentMember = mirror;
-      data[mirrorName] = new Method(mirrorName, mirror.qualifiedName,
-          mirror.isSetter, mirror.isGetter, mirror.isConstructor,
-          mirror.isOperator, mirror.isStatic, mirror.returnType.qualifiedName,
-          _getComment(mirror), _getParameters(mirror.parameters),
-          _getAnnotations(mirror));
+      if (mirror.isSetter) {
+        setters[mirrorName] = method;
+      } else if (mirror.isGetter) {
+        getters[mirrorName] = method;
+      } else if (mirror.isConstructor) {
+        constructors[mirrorName] = method;
+      } else if (mirror.isOperator) {
+        operators[mirrorName] = method;
+      } else if (mirror.isRegularMethod) {
+         methods[mirrorName] = method;
+      } else {
+        throw new StateError('${mirror.qualifiedName} - no method type match');
+      }
     }
   });
-  return data;
-}
+  return {'setters' : setters,
+          'getters' : getters,
+          'constructors' : constructors,
+          'operators' : operators,
+          'methods' : methods};
+} 
 
 /**
  * Returns a map of [Class] objects constructed from inputted mirrors.
@@ -340,9 +361,8 @@
           mirror.superclass.qualifiedName : '';
       var interfaces =
           mirror.superinterfaces.map((interface) => interface.qualifiedName);
-      data[mirrorName] = new Class(mirrorName, mirror.qualifiedName,
-          superclass, mirror.isAbstract, mirror.isTypedef,
-          _getComment(mirror), interfaces.toList(),
+      data[mirrorName] = new Class(mirrorName, superclass, mirror.isAbstract, 
+          mirror.isTypedef, _getComment(mirror), interfaces.toList(),
           _getVariables(mirror.variables, includePrivate),
           _getMethods(mirror.methods, includePrivate),
           _getAnnotations(mirror));
@@ -358,10 +378,10 @@
   var data = {};
   mirrorList.forEach((ParameterMirror mirror) {
     _currentMember = mirror;
-    data[mirror.simpleName] = new Parameter(mirror.simpleName,
-        mirror.qualifiedName, mirror.isOptional, mirror.isNamed,
-        mirror.hasDefaultValue, mirror.type.qualifiedName,
-        mirror.defaultValue, _getAnnotations(mirror));
+    data[mirror.simpleName] = new Parameter(mirror.simpleName, 
+        mirror.isOptional, mirror.isNamed, mirror.hasDefaultValue, 
+        mirror.type.qualifiedName, mirror.defaultValue, 
+        _getAnnotations(mirror));
   });
   return data;
 }
@@ -388,7 +408,11 @@
 Map recurseMap(Map inputMap) {
   var outputMap = {};
   inputMap.forEach((key, value) {
-    outputMap[key] = value.toMap();
+    if (value is Map) {
+      outputMap[key] = recurseMap(value);
+    } else {
+      outputMap[key] = value.toMap();
+    }
   });
   return outputMap;
 }
@@ -405,8 +429,8 @@
   Map<String, Variable> variables;
 
   /// Top-level functions in the library.
-  Map<String, Method> functions;
-
+  Map<String, Map<String, Method>> functions;
+  
   /// Classes defined within the library
   Map<String, Class> classes;
 
@@ -443,26 +467,24 @@
   Map<String, Variable> variables;
 
   /// Methods in the class.
-  Map<String, Method> methods;
-
+  Map<String, Map<String, Method>> methods;
+  
   String name;
-  String qualifiedName;
   String superclass;
   bool isAbstract;
   bool isTypedef;
 
   /// List of the meta annotations on the class.
   List<String> annotations;
-
-  Class(this.name, this.qualifiedName, this.superclass, this.isAbstract,
-      this.isTypedef, this.comment, this.interfaces, this.variables,
-      this.methods, this.annotations);
+  
+  Class(this.name, this.superclass, this.isAbstract, this.isTypedef, 
+      this.comment, this.interfaces, this.variables, this.methods, 
+      this.annotations);
 
   /// Generates a map describing the [Class] object.
   Map toMap() {
     var classMap = {};
     classMap['name'] = name;
-    classMap['qualifiedname'] = qualifiedName;
     classMap['comment'] = comment;
     classMap['superclass'] = superclass;
     classMap['abstract'] = isAbstract.toString();
@@ -484,22 +506,20 @@
   String comment;
 
   String name;
-  String qualifiedName;
   bool isFinal;
   bool isStatic;
   String type;
 
   /// List of the meta annotations on the variable.
   List<String> annotations;
-
-  Variable(this.name, this.qualifiedName, this.isFinal, this.isStatic,
-      this.type, this.comment, this.annotations);
-
+  
+  Variable(this.name, this.isFinal, this.isStatic, this.type, this.comment, 
+      this.annotations);
+  
   /// Generates a map describing the [Variable] object.
   Map toMap() {
     var variableMap = {};
     variableMap['name'] = name;
-    variableMap['qualifiedname'] = qualifiedName;
     variableMap['comment'] = comment;
     variableMap['final'] = isFinal.toString();
     variableMap['static'] = isStatic.toString();
@@ -521,29 +541,20 @@
   Map<String, Parameter> parameters;
 
   String name;
-  String qualifiedName;
-  bool isSetter;
-  bool isGetter;
-  bool isConstructor;
-  bool isOperator;
   bool isStatic;
   String returnType;
 
   /// List of the meta annotations on the method.
   List<String> annotations;
-
-  Method(this.name, this.qualifiedName, this.isSetter, this.isGetter,
-      this.isConstructor, this.isOperator, this.isStatic, this.returnType,
-      this.comment, this.parameters, this.annotations);
-
+  
+  Method(this.name, this.isStatic, this.returnType, this.comment, 
+      this.parameters, this.annotations);
+  
   /// Generates a map describing the [Method] object.
   Map toMap() {
     var methodMap = {};
     methodMap['name'] = name;
-    methodMap['qualifiedname'] = qualifiedName;
     methodMap['comment'] = comment;
-    methodMap['type'] = isSetter ? 'setter' : isGetter ? 'getter' :
-      isOperator ? 'operator' : isConstructor ? 'constructor' : 'method';
     methodMap['static'] = isStatic.toString();
     methodMap['return'] = returnType;
     methodMap['parameters'] = recurseMap(parameters);
@@ -558,7 +569,6 @@
 class Parameter {
 
   String name;
-  String qualifiedName;
   bool isOptional;
   bool isNamed;
   bool hasDefaultValue;
@@ -567,15 +577,14 @@
 
   /// List of the meta annotations on the parameter.
   List<String> annotations;
-
-  Parameter(this.name, this.qualifiedName, this.isOptional, this.isNamed,
-      this.hasDefaultValue, this.type, this.defaultValue, this.annotations);
-
+  
+  Parameter(this.name, this.isOptional, this.isNamed, this.hasDefaultValue, 
+      this.type, this.defaultValue, this.annotations);
+  
   /// Generates a map describing the [Parameter] object.
   Map toMap() {
     var parameterMap = {};
     parameterMap['name'] = name;
-    parameterMap['qualifiedname'] = qualifiedName;
     parameterMap['optional'] = isOptional.toString();
     parameterMap['named'] = isNamed.toString();
     parameterMap['default'] = hasDefaultValue.toString();
diff --git a/pkg/docgen/test/single_library_test.dart b/pkg/docgen/test/single_library_test.dart
index e92c857..f00ddc4 100644
--- a/pkg/docgen/test/single_library_test.dart
+++ b/pkg/docgen/test/single_library_test.dart
@@ -57,8 +57,12 @@
           var classes = library.classes.values;
           expect(classes.every((e) => e is Class), isTrue);
           
+          var classMethodTypes = [];
+          classes.forEach((e) => classMethodTypes.addAll(e.methods.values));
+          expect(classMethodTypes.every((e) => e is Map), isTrue);
+
           var classMethods = [];
-          classes.forEach((e) => classMethods.addAll(e.methods.values));
+          classMethodTypes.forEach((e) => classMethods.addAll(e.values));
           expect(classMethods.every((e) => e is Method), isTrue);
           
           var methodParameters = [];
@@ -67,7 +71,11 @@
           });
           expect(methodParameters.every((e) => e is Parameter), isTrue);
           
-          var functions = library.functions.values;
+          var functionTypes = library.functions.values;
+          expect(functionTypes.every((e) => e is Map), isTrue);
+          
+          var functions = [];
+          functionTypes.forEach((e) => functions.addAll(e.values));
           expect(functions.every((e) => e is Method), isTrue);
           
           var functionParameters = [];
diff --git a/pkg/path/lib/path.dart b/pkg/path/lib/path.dart
index b425124..25ce0e6 100644
--- a/pkg/path/lib/path.dart
+++ b/pkg/path/lib/path.dart
@@ -525,7 +525,7 @@
     var needsSeparator = false;
     var isAbsoluteAndNotRootRelative = false;
 
-    for (var part in parts) {
+    for (var part in parts.where((part) => part != '')) {
       if (this.isRootRelative(part) && isAbsoluteAndNotRootRelative) {
         // If the new part is root-relative, it preserves the previous root but
         // replaces the path after it.
diff --git a/pkg/path/test/posix_test.dart b/pkg/path/test/posix_test.dart
index f3232bc..c26a5ba 100644
--- a/pkg/path/test/posix_test.dart
+++ b/pkg/path/test/posix_test.dart
@@ -153,6 +153,14 @@
       expect(builder.join('a', 'b', 'c', null, null), equals('a/b/c'));
     });
 
+    test('ignores empty strings', () {
+      expect(builder.join(''), '');
+      expect(builder.join('', ''), '');
+      expect(builder.join('', 'a'), 'a');
+      expect(builder.join('a', '', 'b', '', '', '', 'c'), 'a/b/c');
+      expect(builder.join('a', 'b', ''), 'a/b');
+    });
+
     test('disallows intermediate nulls', () {
       expect(() => builder.join('a', null, 'b'), throwsArgumentError);
       expect(() => builder.join(null, 'a'), throwsArgumentError);
diff --git a/pkg/path/test/url_test.dart b/pkg/path/test/url_test.dart
index 3e03d50..d040a59 100644
--- a/pkg/path/test/url_test.dart
+++ b/pkg/path/test/url_test.dart
@@ -223,6 +223,14 @@
       expect(builder.join('a', 'b', 'c', null, null), equals('a/b/c'));
     });
 
+    test('ignores empty strings', () {
+      expect(builder.join(''), '');
+      expect(builder.join('', ''), '');
+      expect(builder.join('', 'a'), 'a');
+      expect(builder.join('a', '', 'b', '', '', '', 'c'), 'a/b/c');
+      expect(builder.join('a', 'b', ''), 'a/b');
+    });
+
     test('disallows intermediate nulls', () {
       expect(() => builder.join('a', null, 'b'), throwsArgumentError);
       expect(() => builder.join(null, 'a'), throwsArgumentError);
diff --git a/pkg/path/test/windows_test.dart b/pkg/path/test/windows_test.dart
index 7b3cf60..7409439 100644
--- a/pkg/path/test/windows_test.dart
+++ b/pkg/path/test/windows_test.dart
@@ -172,6 +172,14 @@
       expect(builder.join('a', 'b', 'c', null, null), equals(r'a\b\c'));
     });
 
+    test('ignores empty strings', () {
+      expect(builder.join(''), '');
+      expect(builder.join('', ''), '');
+      expect(builder.join('', 'a'), 'a');
+      expect(builder.join('a', '', 'b', '', '', '', 'c'), r'a\b\c');
+      expect(builder.join('a', 'b', ''), r'a\b');
+    });
+
     test('disallows intermediate nulls', () {
       expect(() => builder.join('a', null, 'b'), throwsArgumentError);
       expect(() => builder.join(null, 'a'), throwsArgumentError);
diff --git a/pkg/pkg.status b/pkg/pkg.status
index 2b17cfc..0a89418 100644
--- a/pkg/pkg.status
+++ b/pkg/pkg.status
@@ -92,17 +92,11 @@
 serialization/test/no_library_test: Fail # Issue 6490
 
 [ $compiler == dart2js && $minified ]
-serialization/test/serialization_test: Fail # Issue 6490
-serialization/test/no_library_test: Fail # Issue 6490
-
 # The unminified unittest tests test that the real names of Dart types are
 # printed. Minified versions of these tests exist that test the behavior when
 # minified.
 unittest/test/*_unminified_test: Skip # DO NOT COPY THIS UNLESS YOU WORK ON DART2JS
 
-[ $compiler == dart2js && $unchecked && ($runtime == d8 || $runtime == chrome || $runtime == drt) ]
-crypto/test/sha1_test: Fail # V8 bug: https://code.google.com/p/v8/issues/detail?id=2692
-
 [ $compiler == dart2js && $browser ]
 path/test/dartium_test: Fail # Issue 6490
 stack_trace/test/vm_test: Fail, OK # VM-specific traces
diff --git a/pkg/source_maps/lib/span.dart b/pkg/source_maps/lib/span.dart
index 7ca0ca9..1d2152d 100644
--- a/pkg/source_maps/lib/span.dart
+++ b/pkg/source_maps/lib/span.dart
@@ -69,6 +69,8 @@
   bool operator ==(Span other) =>
     sourceUrl == other.sourceUrl && start == other.start && end == other.end;
 
+  int get hashCode => sourceUrl.hashCode + start + (31 * (end - start));
+
   String toString() => '<$runtimeType: $start $end $formatLocation $text>';
 }
 
diff --git a/runtime/bin/bin.gypi b/runtime/bin/bin.gypi
index 731342a..d33f9ac 100644
--- a/runtime/bin/bin.gypi
+++ b/runtime/bin/bin.gypi
@@ -337,7 +337,7 @@
       'type': 'none',
       'toolsets':['host'],
       'includes': [
-        'resources_sources.gypi'
+        'resources_sources.gypi',
       ],
       'actions': [
         {
@@ -381,6 +381,9 @@
         'builtin.h',
         'io_natives.h',
         'resources.h',
+        'vmservice.h',
+        'vmservice_impl.cc',
+        'vmservice_impl.h',
         '<(snapshot_cc_file)',
         '<(resources_cc_file)',
       ],
@@ -442,6 +445,9 @@
         'builtin.h',
         'io_natives.h',
         'resources.h',
+        'vmservice.h',
+        'vmservice_impl.cc',
+        'vmservice_impl.h',
         # Include generated source files.
         '<(builtin_cc_file)',
         '<(io_cc_file)',
diff --git a/runtime/bin/eventhandler.cc b/runtime/bin/eventhandler.cc
index 94f0778..3cb5456 100644
--- a/runtime/bin/eventhandler.cc
+++ b/runtime/bin/eventhandler.cc
@@ -5,6 +5,7 @@
 #include "bin/dartutils.h"
 #include "bin/eventhandler.h"
 #include "bin/socket.h"
+#include "bin/thread.h"
 
 #include "include/dart_api.h"
 
@@ -12,33 +13,61 @@
 namespace dart {
 namespace bin {
 
-static const int kNativeEventHandlerFieldIndex = 0;
 static const intptr_t kTimerId = -1;
 static const intptr_t kInvalidId = -2;
 
-/*
- * Returns the reference of the EventHandler stored in the native field.
- */
-static EventHandler* GetEventHandler(Dart_Handle handle) {
-  intptr_t value = 0;
-  Dart_Handle result = Dart_GetNativeInstanceField(
-      handle, kNativeEventHandlerFieldIndex, &value);
-  if (Dart_IsError(result)) {
-    Dart_PropagateError(result);
+static EventHandler* event_handler = NULL;
+// TODO(ajohnsen): Consider removing mutex_ if we can enforce an invariant
+//    that eventhandler is kept alive untill all isolates are closed.
+static dart::Mutex* mutex_ = new dart::Mutex();
+
+
+void TimeoutQueue::UpdateTimeout(Dart_Port port, int64_t timeout) {
+  // Find port if present.
+  Timeout* last = NULL;
+  Timeout* current = timeouts_;
+  while (current != NULL) {
+    if (current->port() == port) {
+      // Found.
+      if (timeout < 0) {
+        // Remove from list and delete existing.
+        if (last != NULL) {
+          last->set_next(current->next());
+        } else {
+          timeouts_ = current->next();
+        }
+        delete current;
+      } else {
+        // Update timeout.
+        current->set_timeout(timeout);
+      }
+      break;
+    }
+    last = current;
+    current = current->next();
   }
-  EventHandler* event_handler = reinterpret_cast<EventHandler*>(value);
-  ASSERT(event_handler != NULL);
-  return event_handler;
+  if (current == NULL && timeout >= 0) {
+    // Not found, create a new.
+    timeouts_ = new Timeout(port, timeout, timeouts_);
+  }
+  // Clear and find next timeout.
+  next_timeout_ = NULL;
+  current = timeouts_;
+  while (current != NULL) {
+    if (next_timeout_ == NULL ||
+        current->timeout() < next_timeout_->timeout()) {
+      next_timeout_ = current;
+    }
+    current = current->next();
+  }
 }
 
 
-/*
- * Sets the reference of the EventHandler in the native field.
- */
-static void SetEventHandler(Dart_Handle handle, EventHandler* event_handler) {
-  Dart_SetNativeInstanceField(handle,
-                              kNativeEventHandlerFieldIndex,
-                              reinterpret_cast<intptr_t>(event_handler));
+void EventHandler::Stop() {
+  MutexLocker locker(mutex_);
+  if (event_handler == NULL) return;
+  event_handler->Shutdown();
+  event_handler = NULL;
 }
 
 
@@ -48,11 +77,9 @@
  * object.
  */
 void FUNCTION_NAME(EventHandler_Start)(Dart_NativeArguments args) {
-  Dart_EnterScope();
-  Dart_Handle handle = Dart_GetNativeArgument(args, 0);
-  EventHandler* event_handler = EventHandler::Start();
-  SetEventHandler(handle, event_handler);
-  Dart_ExitScope();
+  MutexLocker locker(mutex_);
+  if (event_handler != NULL) return;
+  event_handler = EventHandler::Start();
 }
 
 
@@ -63,8 +90,6 @@
  */
 void FUNCTION_NAME(EventHandler_SendData)(Dart_NativeArguments args) {
   Dart_EnterScope();
-  Dart_Handle handle = Dart_GetNativeArgument(args, 0);
-  EventHandler* event_handler = GetEventHandler(handle);
   Dart_Handle sender = Dart_GetNativeArgument(args, 1);
   intptr_t id = kInvalidId;
   if (Dart_IsNull(sender)) {
@@ -72,11 +97,18 @@
   } else {
     Socket::GetSocketIdNativeField(sender, &id);
   }
-  handle = Dart_GetNativeArgument(args, 2);
+  Dart_Handle handle = Dart_GetNativeArgument(args, 2);
   Dart_Port dart_port =
       DartUtils::GetIntegerField(handle, DartUtils::kIdFieldName);
   int64_t data = DartUtils::GetIntegerValue(Dart_GetNativeArgument(args, 3));
-  event_handler->SendData(id, dart_port, data);
+  {
+    MutexLocker locker(mutex_);
+    // Only send if the event_handler is not NULL. This means that the handler
+    // shut down, and a message is send later on.
+    if (event_handler != NULL) {
+      event_handler->SendData(id, dart_port, data);
+    }
+  }
   Dart_ExitScope();
 }
 
diff --git a/runtime/bin/eventhandler.h b/runtime/bin/eventhandler.h
index 5d7832e..e75250f 100644
--- a/runtime/bin/eventhandler.h
+++ b/runtime/bin/eventhandler.h
@@ -27,6 +27,61 @@
   kPipe = 17,
 };
 
+
+class TimeoutQueue {
+ private:
+  class Timeout {
+   public:
+    Timeout(Dart_Port port, int64_t timeout, Timeout* next)
+        : port_(port), timeout_(timeout), next_(next) {}
+
+    Dart_Port port() const { return port_; }
+
+    int64_t timeout() const { return timeout_; }
+    void set_timeout(int64_t timeout) {
+      ASSERT(timeout >= 0);
+      timeout_ = timeout;
+    }
+
+    Timeout* next() const { return next_; }
+    void set_next(Timeout* next) {
+      next_ = next;
+    }
+
+   private:
+    Dart_Port port_;
+    int64_t timeout_;
+    Timeout* next_;
+  };
+
+ public:
+  TimeoutQueue() : next_timeout_(NULL), timeouts_(NULL) {}
+
+  ~TimeoutQueue() {
+    while (HasTimeout()) RemoveCurrent();
+  }
+
+  bool HasTimeout() const { return next_timeout_ != NULL; }
+
+  int64_t CurrentTimeout() const {
+    return next_timeout_->timeout();
+  }
+
+  Dart_Port CurrentPort() const {
+    return next_timeout_->port();
+  }
+
+  void RemoveCurrent() {
+    UpdateTimeout(CurrentPort(), -1);
+  }
+
+  void UpdateTimeout(Dart_Port port, int64_t timeout);
+
+ private:
+  Timeout* next_timeout_;
+  Timeout* timeouts_;
+};
+
 }  // namespace bin
 }  // namespace dart
 
@@ -59,12 +114,11 @@
   static EventHandler* Start() {
     EventHandler* handler = new EventHandler();
     handler->delegate_.Start(handler);
-    IsolateData* isolate_data =
-        reinterpret_cast<IsolateData*>(Dart_CurrentIsolateData());
-    isolate_data->event_handler = handler;
     return handler;
   }
 
+  static void Stop();
+
  private:
   friend class EventHandlerImplementation;
   EventHandlerImplementation delegate_;
diff --git a/runtime/bin/eventhandler_android.cc b/runtime/bin/eventhandler_android.cc
index 74fb5da..594a6db 100644
--- a/runtime/bin/eventhandler_android.cc
+++ b/runtime/bin/eventhandler_android.cc
@@ -104,8 +104,6 @@
   FDUtils::SetNonBlocking(interrupt_fds_[0]);
   FDUtils::SetCloseOnExec(interrupt_fds_[0]);
   FDUtils::SetCloseOnExec(interrupt_fds_[1]);
-  timeout_ = kInfinityTimeout;
-  timeout_port_ = 0;
   shutdown_ = false;
   // The initial size passed to epoll_create is ignore on newer (>=
   // 2.6.8) Linux versions
@@ -194,8 +192,7 @@
   InterruptMessage msg;
   while (GetInterruptMessage(&msg)) {
     if (msg.id == kTimerId) {
-      timeout_ = msg.data;
-      timeout_port_ = msg.dart_port;
+      timeout_queue_.UpdateTimeout(msg.dart_port, msg.data);
     } else if (msg.id == kShutdownId) {
       shutdown_ = true;
     } else {
@@ -360,21 +357,22 @@
 
 
 int64_t EventHandlerImplementation::GetTimeout() {
-  if (timeout_ == kInfinityTimeout) {
+  if (!timeout_queue_.HasTimeout()) {
     return kInfinityTimeout;
   }
-  int64_t millis = timeout_ - TimerUtils::GetCurrentTimeMilliseconds();
+  int64_t millis = timeout_queue_.CurrentTimeout() -
+      TimerUtils::GetCurrentTimeMilliseconds();
   return (millis < 0) ? 0 : millis;
 }
 
 
 void EventHandlerImplementation::HandleTimeout() {
-  if (timeout_ != kInfinityTimeout) {
-    int64_t millis = timeout_ - TimerUtils::GetCurrentTimeMilliseconds();
+  if (timeout_queue_.HasTimeout()) {
+    int64_t millis = timeout_queue_.CurrentTimeout() -
+        TimerUtils::GetCurrentTimeMilliseconds();
     if (millis <= 0) {
-      DartUtils::PostNull(timeout_port_);
-      timeout_ = kInfinityTimeout;
-      timeout_port_ = 0;
+      DartUtils::PostNull(timeout_queue_.CurrentPort());
+      timeout_queue_.RemoveCurrent();
     }
   }
 }
diff --git a/runtime/bin/eventhandler_android.h b/runtime/bin/eventhandler_android.h
index f127d6d..212193a 100644
--- a/runtime/bin/eventhandler_android.h
+++ b/runtime/bin/eventhandler_android.h
@@ -116,8 +116,7 @@
   static uint32_t GetHashmapHashFromFd(intptr_t fd);
 
   HashMap socket_map_;
-  int64_t timeout_;  // Time for next timeout.
-  Dart_Port timeout_port_;
+  TimeoutQueue timeout_queue_;
   bool shutdown_;
   int interrupt_fds_[2];
   int epoll_fd_;
diff --git a/runtime/bin/eventhandler_linux.cc b/runtime/bin/eventhandler_linux.cc
index 9ed591a..2b62391 100644
--- a/runtime/bin/eventhandler_linux.cc
+++ b/runtime/bin/eventhandler_linux.cc
@@ -111,8 +111,6 @@
   FDUtils::SetNonBlocking(interrupt_fds_[0]);
   FDUtils::SetCloseOnExec(interrupt_fds_[0]);
   FDUtils::SetCloseOnExec(interrupt_fds_[1]);
-  timeout_ = kInfinityTimeout;
-  timeout_port_ = 0;
   shutdown_ = false;
   // The initial size passed to epoll_create is ignore on newer (>=
   // 2.6.8) Linux versions
@@ -198,12 +196,12 @@
   return (total_read == kInterruptMessageSize) ? true : false;
 }
 
+
 void EventHandlerImplementation::HandleInterruptFd() {
   InterruptMessage msg;
   while (GetInterruptMessage(&msg)) {
     if (msg.id == kTimerId) {
-      timeout_ = msg.data;
-      timeout_port_ = msg.dart_port;
+      timeout_queue_.UpdateTimeout(msg.dart_port, msg.data);
     } else if (msg.id == kShutdownId) {
       shutdown_ = true;
     } else {
@@ -365,21 +363,23 @@
 
 
 int64_t EventHandlerImplementation::GetTimeout() {
-  if (timeout_ == kInfinityTimeout) {
+  if (!timeout_queue_.HasTimeout()) {
     return kInfinityTimeout;
   }
-  int64_t millis = timeout_ - TimerUtils::GetCurrentTimeMilliseconds();
+  int64_t millis = timeout_queue_.CurrentTimeout() -
+      TimerUtils::GetCurrentTimeMilliseconds();
   return (millis < 0) ? 0 : millis;
 }
 
 
 void EventHandlerImplementation::HandleTimeout() {
-  if (timeout_ != kInfinityTimeout) {
-    int64_t millis = timeout_ - TimerUtils::GetCurrentTimeMilliseconds();
+  if (timeout_queue_.HasTimeout()) {
+    int64_t millis = timeout_queue_.CurrentTimeout() -
+        TimerUtils::GetCurrentTimeMilliseconds();
     if (millis <= 0) {
-      DartUtils::PostNull(timeout_port_);
-      timeout_ = kInfinityTimeout;
-      timeout_port_ = 0;
+      DartUtils::PostNull(timeout_queue_.CurrentPort());
+      // Remove current from queue.
+      timeout_queue_.RemoveCurrent();
     }
   }
 }
diff --git a/runtime/bin/eventhandler_linux.h b/runtime/bin/eventhandler_linux.h
index d8fc509..3a2fe83 100644
--- a/runtime/bin/eventhandler_linux.h
+++ b/runtime/bin/eventhandler_linux.h
@@ -115,8 +115,7 @@
   static uint32_t GetHashmapHashFromFd(intptr_t fd);
 
   HashMap socket_map_;
-  int64_t timeout_;  // Time for next timeout.
-  Dart_Port timeout_port_;
+  TimeoutQueue timeout_queue_;
   bool shutdown_;
   int interrupt_fds_[2];
   int epoll_fd_;
diff --git a/runtime/bin/eventhandler_macos.cc b/runtime/bin/eventhandler_macos.cc
index 826e600..9a60d6f 100644
--- a/runtime/bin/eventhandler_macos.cc
+++ b/runtime/bin/eventhandler_macos.cc
@@ -130,8 +130,6 @@
   FDUtils::SetNonBlocking(interrupt_fds_[0]);
   FDUtils::SetCloseOnExec(interrupt_fds_[0]);
   FDUtils::SetCloseOnExec(interrupt_fds_[1]);
-  timeout_ = kInfinityTimeout;
-  timeout_port_ = 0;
   shutdown_ = false;
 
   kqueue_fd_ = TEMP_FAILURE_RETRY(kqueue());
@@ -215,8 +213,7 @@
   InterruptMessage msg;
   while (GetInterruptMessage(&msg)) {
     if (msg.id == kTimerId) {
-      timeout_ = msg.data;
-      timeout_port_ = msg.dart_port;
+      timeout_queue_.UpdateTimeout(msg.dart_port, msg.data);
     } else if (msg.id == kShutdownId) {
       shutdown_ = true;
     } else {
@@ -360,21 +357,22 @@
 
 
 int64_t EventHandlerImplementation::GetTimeout() {
-  if (timeout_ == kInfinityTimeout) {
+  if (!timeout_queue_.HasTimeout()) {
     return kInfinityTimeout;
   }
-  int64_t millis = timeout_ - TimerUtils::GetCurrentTimeMilliseconds();
+  int64_t millis = timeout_queue_.CurrentTimeout() -
+      TimerUtils::GetCurrentTimeMilliseconds();
   return (millis < 0) ? 0 : millis;
 }
 
 
 void EventHandlerImplementation::HandleTimeout() {
-  if (timeout_ != kInfinityTimeout) {
-    int64_t millis = timeout_ - TimerUtils::GetCurrentTimeMilliseconds();
+  if (timeout_queue_.HasTimeout()) {
+    int64_t millis = timeout_queue_.CurrentTimeout() -
+        TimerUtils::GetCurrentTimeMilliseconds();
     if (millis <= 0) {
-      DartUtils::PostNull(timeout_port_);
-      timeout_ = kInfinityTimeout;
-      timeout_port_ = 0;
+      DartUtils::PostNull(timeout_queue_.CurrentPort());
+      timeout_queue_.RemoveCurrent();
     }
   }
 }
diff --git a/runtime/bin/eventhandler_macos.h b/runtime/bin/eventhandler_macos.h
index 6bf4d61..0a17ed6 100644
--- a/runtime/bin/eventhandler_macos.h
+++ b/runtime/bin/eventhandler_macos.h
@@ -128,8 +128,7 @@
   static uint32_t GetHashmapHashFromFd(intptr_t fd);
 
   HashMap socket_map_;
-  int64_t timeout_;  // Time for next timeout.
-  Dart_Port timeout_port_;
+  TimeoutQueue timeout_queue_;
   bool shutdown_;
   int interrupt_fds_[2];
   int kqueue_fd_;
diff --git a/runtime/bin/eventhandler_patch.dart b/runtime/bin/eventhandler_patch.dart
index 1027708..46c1e3d 100644
--- a/runtime/bin/eventhandler_patch.dart
+++ b/runtime/bin/eventhandler_patch.dart
@@ -24,7 +24,7 @@
 }
 
 
-class _EventHandlerImpl extends NativeFieldWrapperClass1 {
+class _EventHandlerImpl {
   _EventHandlerImpl() { }
   void _start() native "EventHandler_Start";
   void _sendData(Object sender, ReceivePort receivePort, int data)
diff --git a/runtime/bin/eventhandler_win.cc b/runtime/bin/eventhandler_win.cc
index f1257c3..332f80f 100644
--- a/runtime/bin/eventhandler_win.cc
+++ b/runtime/bin/eventhandler_win.cc
@@ -670,8 +670,7 @@
   if (msg->id == kTimeoutId) {
     // Change of timeout request. Just set the new timeout and port as the
     // completion thread will use the new timeout value for its next wait.
-    timeout_ = msg->data;
-    timeout_port_ = msg->dart_port;
+    timeout_queue_.UpdateTimeout(msg->dart_port, msg->data);
   } else if (msg->id == kShutdownId) {
     shutdown_ = true;
   } else {
@@ -864,10 +863,9 @@
 }
 
 void EventHandlerImplementation::HandleTimeout() {
-  // TODO(sgjesse) check if there actually is a timeout.
-  DartUtils::PostNull(timeout_port_);
-  timeout_ = kInfinityTimeout;
-  timeout_port_ = 0;
+  if (!timeout_queue_.HasTimeout()) return;
+  DartUtils::PostNull(timeout_queue_.CurrentPort());
+  timeout_queue_.RemoveCurrent();
 }
 
 
@@ -909,8 +907,6 @@
   if (completion_port_ == NULL) {
     FATAL("Completion port creation failed");
   }
-  timeout_ = kInfinityTimeout;
-  timeout_port_ = 0;
   shutdown_ = false;
 }
 
@@ -921,10 +917,11 @@
 
 
 int64_t EventHandlerImplementation::GetTimeout() {
-  if (timeout_ == kInfinityTimeout) {
+  if (!timeout_queue_.HasTimeout()) {
     return kInfinityTimeout;
   }
-  int64_t millis = timeout_ - TimerUtils::GetCurrentTimeMilliseconds();
+  int64_t millis = timeout_queue_.CurrentTimeout() -
+      TimerUtils::GetCurrentTimeMilliseconds();
   return (millis < 0) ? 0 : millis;
 }
 
diff --git a/runtime/bin/eventhandler_win.h b/runtime/bin/eventhandler_win.h
index 73e8917..280175c 100644
--- a/runtime/bin/eventhandler_win.h
+++ b/runtime/bin/eventhandler_win.h
@@ -390,8 +390,7 @@
  private:
   ClientSocket* client_sockets_head_;
 
-  int64_t timeout_;  // Time for next timeout.
-  Dart_Port timeout_port_;
+  TimeoutQueue timeout_queue_;  // Time for next timeout.
   bool shutdown_;
   HANDLE completion_port_;
 };
diff --git a/runtime/bin/isolate_data.h b/runtime/bin/isolate_data.h
index 2992a08..df76864 100644
--- a/runtime/bin/isolate_data.h
+++ b/runtime/bin/isolate_data.h
@@ -21,11 +21,10 @@
 class IsolateData {
  public:
   IsolateData()
-      : event_handler(NULL), object_array_class(NULL),
+      : object_array_class(NULL),
         growable_object_array_class(NULL), immutable_array_class(NULL) {
   }
 
-  EventHandler* event_handler;
   Dart_PersistentHandle object_array_class;
   Dart_PersistentHandle growable_object_array_class;
   Dart_PersistentHandle immutable_array_class;
diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc
index af29300..c749000 100644
--- a/runtime/bin/main.cc
+++ b/runtime/bin/main.cc
@@ -20,6 +20,7 @@
 #include "bin/log.h"
 #include "bin/platform.h"
 #include "bin/process.h"
+#include "bin/vmservice_impl.h"
 #include "platform/globals.h"
 
 namespace dart {
@@ -66,6 +67,12 @@
 static bool has_print_script = false;
 
 
+// VM Service options.
+static bool start_vm_service = false;
+static int vm_service_server_port = -1;
+static const int DEFAULT_VM_SERVICE_SERVER_PORT = 8181;
+
+
 static bool IsValidFlag(const char* name,
                         const char* prefix,
                         intptr_t prefix_length) {
@@ -199,6 +206,25 @@
 }
 
 
+static bool ProcessEnableVmServiceOption(const char* port) {
+  ASSERT(port != NULL);
+  vm_service_server_port = -1;
+  if (*port == '\0') {
+    vm_service_server_port = DEFAULT_VM_SERVICE_SERVER_PORT;
+  } else {
+    if ((*port == '=') || (*port == ':')) {
+      vm_service_server_port = atoi(port + 1);
+    }
+  }
+  if (vm_service_server_port < 0) {
+    Log::PrintErr("unrecognized --enable-vm-service option syntax. "
+                    "Use --enable-vm-service[:<port number>]\n");
+    return false;
+  }
+  start_vm_service = true;
+  return true;
+}
+
 static struct {
   const char* option_name;
   bool (*process)(const char* option);
@@ -217,6 +243,7 @@
   { "--snapshot=", ProcessGenScriptSnapshotOption },
   { "--print-script", ProcessPrintScriptOption },
   { "--check-function-fingerprints", ProcessFingerprintedFunctions },
+  { "--enable-vm-service", ProcessEnableVmServiceOption },
   { NULL, NULL }
 };
 
@@ -549,6 +576,10 @@
 "--print-script\n"
 "  generates Dart source code back and prints it after parsing a Dart script\n"
 "\n"
+"--enable-vm-service[:<port number>]\n"
+"  enables the VM service and listens on specified port for connections\n"
+"  (default port number is 8181)\n"
+"\n"
 "The following options are only used for VM development and may\n"
 "be changed in any future version:\n");
     const char* print_flags = "--print_flags";
@@ -593,10 +624,14 @@
 }
 
 
-static const int kErrorExitCode = 255;  // Indicates we encountered an error.
+// Exit code indicating a compilation error.
+static const int kCompilationErrorExitCode = 254;
+
+// Exit code indicating an unhandled error that is not a compilation error.
+static const int kErrorExitCode = 255;
 
 
-static int ErrorExit(const char* format, ...) {
+static int ErrorExit(int exit_code, const char* format, ...) {
   va_list arguments;
   va_start(arguments, format);
   Log::VPrintErr(format, arguments);
@@ -606,14 +641,19 @@
   Dart_ExitScope();
   Dart_ShutdownIsolate();
 
-  return kErrorExitCode;
+  return exit_code;
+}
+
+
+static int DartErrorExit(Dart_Handle error) {
+  const int exit_code = Dart_IsCompilationError(error) ?
+      kCompilationErrorExitCode : kErrorExitCode;
+  return ErrorExit(exit_code, "%s\n", Dart_GetError(error));
 }
 
 
 static void ShutdownIsolate(void* callback_data) {
   IsolateData* isolate_data = reinterpret_cast<IsolateData*>(callback_data);
-  EventHandler* handler = isolate_data->event_handler;
-  if (handler != NULL) handler->Shutdown();
   delete isolate_data;
 }
 
@@ -720,6 +760,16 @@
     }
   }
 
+  // Start the VM service isolate, if necessary.
+  if (start_vm_service) {
+    ASSERT(vm_service_server_port >= 0);
+    bool r = VmService::Start(vm_service_server_port);
+    if (!r) {
+      Log::PrintErr("Could not start VM Service isolate %s",
+                    VmService::GetErrorMessage());
+    }
+  }
+
   // Call CreateIsolateAndSetup which creates an isolate and loads up
   // the specified application script.
   char* error = NULL;
@@ -767,14 +817,14 @@
     if (has_compile_all) {
       result = Dart_CompileAll();
       if (Dart_IsError(result)) {
-        return ErrorExit("%s\n", Dart_GetError(result));
+        return DartErrorExit(result);
       }
     }
 
     if (has_check_function_fingerprints) {
       result = Dart_CheckFunctionFingerprints();
       if (Dart_IsError(result)) {
-        return ErrorExit("%s\n", Dart_GetError(result));
+        return DartErrorExit(result);
       }
     }
 
@@ -782,19 +832,21 @@
     Dart_Handle options_result =
         SetupRuntimeOptions(&dart_options, executable_name, script_name);
     if (Dart_IsError(options_result)) {
-      return ErrorExit("%s\n", Dart_GetError(options_result));
+      return DartErrorExit(options_result);
     }
     // Lookup the library of the root script.
     Dart_Handle library = Dart_RootLibrary();
     if (Dart_IsNull(library)) {
-      return ErrorExit("Unable to find root library for '%s'\n",
+      return ErrorExit(kErrorExitCode,
+                       "Unable to find root library for '%s'\n",
                        script_name);
     }
     // Set debug breakpoint if specified on the command line.
     if (breakpoint_at != NULL) {
       result = SetBreakpoint(breakpoint_at, library);
       if (Dart_IsError(result)) {
-        return ErrorExit("Error setting breakpoint at '%s': %s\n",
+        return ErrorExit(kErrorExitCode,
+                         "Error setting breakpoint at '%s': %s\n",
                          breakpoint_at,
                          Dart_GetError(result));
       }
@@ -802,19 +854,19 @@
     if (has_print_script) {
       result = GenerateScriptSource();
       if (Dart_IsError(result)) {
-        return ErrorExit("%s\n", Dart_GetError(result));
+        return DartErrorExit(result);
       }
     } else {
       // Lookup and invoke the top level main function.
       result = Dart_Invoke(library, DartUtils::NewString("main"), 0, NULL);
       if (Dart_IsError(result)) {
-        return ErrorExit("%s\n", Dart_GetError(result));
+        return DartErrorExit(result);
       }
 
       // Keep handling messages until the last active receive port is closed.
       result = Dart_RunLoop();
       if (Dart_IsError(result)) {
-        return ErrorExit("%s\n", Dart_GetError(result));
+        return DartErrorExit(result);
       }
     }
   }
@@ -824,6 +876,8 @@
   Dart_ShutdownIsolate();
   // Terminate process exit-code handler.
   Process::TerminateExitCodeHandler();
+  EventHandler::Stop();
+
   // Free copied argument strings if converted.
   if (argv_converted) {
     for (int i = 0; i < argc; i++) free(argv[i]);
diff --git a/runtime/bin/resources.h b/runtime/bin/resources.h
index 0f3f7c3..6ee066a 100644
--- a/runtime/bin/resources.h
+++ b/runtime/bin/resources.h
@@ -30,6 +30,14 @@
     return kNoSuchInstance;
   }
 
+  static intptr_t get_resource_count() {
+    return builtin_resources_count_;
+  }
+
+  static const char* get_resource_path(intptr_t i) {
+    return get_resource(i)->path_;
+  }
+
  private:
   struct resource_map_entry {
     const char* path_;
@@ -46,9 +54,6 @@
     return &builtin_resources_[i];
   }
 
-  static intptr_t get_resource_count() {
-    return builtin_resources_count_; }
-
   DISALLOW_ALLOCATION();
   DISALLOW_IMPLICIT_CONSTRUCTORS(Resources);
 };
diff --git a/runtime/bin/resources_sources.gypi b/runtime/bin/resources_sources.gypi
index e48b460..1f9bb71 100644
--- a/runtime/bin/resources_sources.gypi
+++ b/runtime/bin/resources_sources.gypi
@@ -2,9 +2,8 @@
 # BSD-style license that can be found in the LICENSE file.
 
 # This file contains all sources for the Resources table.
-# Currently this is unused but at least one source file is needed to build.
 {
   'sources': [
-    'common_patch.dart'
+    'vmservice/vmservice.dart',
   ],
 }
diff --git a/runtime/bin/secure_socket_unsupported.cc b/runtime/bin/secure_socket_unsupported.cc
index 99e5e3b..de97dc8 100644
--- a/runtime/bin/secure_socket_unsupported.cc
+++ b/runtime/bin/secure_socket_unsupported.cc
@@ -95,6 +95,14 @@
 }
 
 
+void FUNCTION_NAME(SecureSocket_Renegotiate)(Dart_NativeArguments args) {
+  Dart_EnterScope();
+  Dart_ThrowException(DartUtils::NewDartArgumentError(
+      "Secure Sockets unsupported on this platform"));
+  Dart_ExitScope();
+}
+
+
 void FUNCTION_NAME(SecureSocket_NewServicePort)(Dart_NativeArguments args) {
   Dart_EnterScope();
   Dart_ThrowException(DartUtils::NewDartArgumentError(
diff --git a/runtime/bin/vmservice.h b/runtime/bin/vmservice.h
new file mode 100644
index 0000000..4dcf93f
--- /dev/null
+++ b/runtime/bin/vmservice.h
@@ -0,0 +1,17 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#ifndef BIN_VMSERVICE_H_
+#define BIN_VMSERVICE_H_
+
+#include "include/dart_api.h"
+
+namespace dart {
+namespace bin {
+
+
+}  // namespace bin
+}  // namespace dart
+
+#endif  // BIN_VMSERVICE_H_
diff --git a/runtime/bin/vmservice/vmservice.dart b/runtime/bin/vmservice/vmservice.dart
new file mode 100644
index 0000000..e074e9a
--- /dev/null
+++ b/runtime/bin/vmservice/vmservice.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.
+
+library vmservice;
+
+import 'dart:async';
+import 'dart:json' as JSON;
+import 'dart:io';
+import 'dart:isolate';
+import 'dart:typed_data';
+import 'dart:utf' as UTF;
+
+
+void messageHandler(message, SendPort replyTo) {
+}
+
+
+main() {
+  port.receive(messageHandler);
+}
diff --git a/runtime/bin/vmservice_impl.cc b/runtime/bin/vmservice_impl.cc
new file mode 100644
index 0000000..c31544a
--- /dev/null
+++ b/runtime/bin/vmservice_impl.cc
@@ -0,0 +1,338 @@
+// 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/vmservice_impl.h"
+
+#include "include/dart_api.h"
+
+#include "bin/builtin.h"
+#include "bin/dartutils.h"
+#include "bin/resources.h"
+#include "bin/thread.h"
+#include "bin/isolate_data.h"
+
+
+namespace dart {
+namespace bin {
+
+// snapshot_buffer points to a snapshot if we link in a snapshot otherwise
+// it is initialized to NULL.
+extern const uint8_t* snapshot_buffer;
+#define RETURN_ERROR_HANDLE(handle)                             \
+  if (Dart_IsError(handle)) {                                   \
+    return handle;                                              \
+  }
+
+#define SHUTDOWN_ON_ERROR(handle)                               \
+  if (Dart_IsError(handle)) {                                   \
+    error_msg_ = strdup(Dart_GetError(handle));                 \
+    Dart_ExitScope();                                           \
+    Dart_ShutdownIsolate();                                     \
+    return false;                                               \
+  }
+
+#define kLibraryResourceNamePrefix "/vmservice"
+static const char* kLibraryScriptResourceName =
+    kLibraryResourceNamePrefix "/vmservice.dart";
+static const char* kLibrarySourceResourceNames[] = {
+    NULL
+};
+
+#define kClientResourceNamePrefix "/client/web/out"
+
+Dart_Isolate VmService::isolate_ = NULL;
+Dart_Port VmService::port_ = ILLEGAL_PORT;
+dart::Monitor* VmService::monitor_ = NULL;
+const char* VmService::error_msg_ = NULL;
+
+// These must be kept in sync with vmservice/constants.dart
+#define VM_SERVICE_ISOLATE_STARTUP_MESSAGE_ID 1
+#define VM_SERVICE_ISOLATE_SHUTDOWN_MESSAGE_ID 2
+
+
+bool VmService::Start(intptr_t server_port) {
+  monitor_ = new dart::Monitor();
+  ASSERT(monitor_ != NULL);
+  error_msg_ = NULL;
+
+
+  {
+    // Take lock before spawning new thread.
+    MonitorLocker ml(monitor_);
+    // Spawn new thread.
+    dart::Thread::Start(ThreadMain, server_port);
+    // Wait until service is running on spawned thread.
+    ml.Wait();
+  }
+  return port_ != ILLEGAL_PORT;
+}
+
+
+bool VmService::_Start(intptr_t server_port) {
+  ASSERT(isolate_ == NULL);
+  char* error = NULL;
+  isolate_ = Dart_CreateIsolate("vmservice:", "main", snapshot_buffer,
+                                new IsolateData(),
+                                &error);
+  if (isolate_ == NULL) {
+    error_msg_ = error;
+    return false;
+  }
+
+  Dart_EnterScope();
+
+  if (snapshot_buffer != NULL) {
+    // Setup the native resolver as the snapshot does not carry it.
+    Builtin::SetNativeResolver(Builtin::kBuiltinLibrary);
+    Builtin::SetNativeResolver(Builtin::kIOLibrary);
+  }
+
+  // Set up the library tag handler for this isolate.
+  Dart_Handle result = Dart_SetLibraryTagHandler(DartUtils::LibraryTagHandler);
+  SHUTDOWN_ON_ERROR(result);
+
+  // Load the specified application script into the newly created isolate.
+
+  // 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 builtin_lib =
+      Builtin::LoadAndCheckLibrary(Builtin::kBuiltinLibrary);
+  SHUTDOWN_ON_ERROR(builtin_lib);
+
+  // Prepare for script loading by setting up the 'print' and 'timer'
+  // closures and setting up 'package root' for URI resolution.
+  result = DartUtils::PrepareForScriptLoading("", builtin_lib);
+  SHUTDOWN_ON_ERROR(result);
+
+  {
+    // Load source into service isolate.
+    Dart_Handle library = LoadScript(kLibraryScriptResourceName);
+    SHUTDOWN_ON_ERROR(library);
+    result = LoadSources(library, kLibrarySourceResourceNames);
+    SHUTDOWN_ON_ERROR(result);
+  }
+
+  // Make the isolate runnable so that it is ready to handle messages.
+  Dart_ExitScope();
+  Dart_ExitIsolate();
+
+  bool retval = Dart_IsolateMakeRunnable(isolate_);
+  if (!retval) {
+    Dart_EnterIsolate(isolate_);
+    Dart_ShutdownIsolate();
+    error_msg_ = "Invalid isolate state - Unable to make it runnable.";
+    return false;
+  }
+
+  Dart_EnterIsolate(isolate_);
+  Dart_EnterScope();
+
+  Dart_Handle library = Dart_RootLibrary();
+  result = Dart_Invoke(library, DartUtils::NewString("main"), 0, NULL);
+  SHUTDOWN_ON_ERROR(result);
+
+  result = LoadResources(library);
+  SHUTDOWN_ON_ERROR(result);
+
+  port_ = Dart_GetMainPortId();
+
+  Dart_ExitScope();
+  Dart_ExitIsolate();
+
+  return true;
+}
+
+
+void VmService::_Stop() {
+  port_ = ILLEGAL_PORT;
+}
+
+
+const char* VmService::GetErrorMessage() {
+  return error_msg_ == NULL ? "No error." : error_msg_;
+}
+
+
+Dart_Port VmService::port() {
+  return port_;
+}
+
+
+bool VmService::IsRunning() {
+  return port_ != ILLEGAL_PORT;
+}
+
+
+Dart_Handle VmService::LoadScript(const char* name) {
+  Dart_Handle url = Dart_NewStringFromCString(name);
+  const char* vmservice_source = NULL;
+  int r = Resources::ResourceLookup(name, &vmservice_source);
+  ASSERT(r != Resources::kNoSuchInstance);
+  Dart_Handle source = Dart_NewStringFromCString(vmservice_source);
+  return Dart_LoadScript(url, source, 0, 0);
+}
+
+
+Dart_Handle VmService::LoadSource(Dart_Handle library, const char* name) {
+  Dart_Handle url = Dart_NewStringFromCString(name);
+  const char* vmservice_source = NULL;
+  int r = Resources::ResourceLookup(name, &vmservice_source);
+  if (r == Resources::kNoSuchInstance) {
+    printf("Can't find %s\n", name);
+  }
+  ASSERT(r != Resources::kNoSuchInstance);
+  Dart_Handle source = Dart_NewStringFromCString(vmservice_source);
+  return Dart_LoadSource(library, url, source);
+}
+
+
+Dart_Handle VmService::LoadSources(Dart_Handle library, const char* names[]) {
+  Dart_Handle result = Dart_Null();
+  for (int i = 0; names[i] != NULL; i++) {
+    result = LoadSource(library, names[i]);
+    if (Dart_IsError(result)) {
+      break;
+    }
+  }
+  return result;
+}
+
+
+Dart_Handle VmService::LoadResource(Dart_Handle library,
+                                    const char* resource_name,
+                                    const char* prefix) {
+  intptr_t prefix_len = strlen(prefix);
+  // Prepare for invoke call.
+  Dart_Handle name = Dart_NewStringFromCString(resource_name+prefix_len);
+  RETURN_ERROR_HANDLE(name);
+  const char* data_buffer = NULL;
+  int data_buffer_length = Resources::ResourceLookup(resource_name,
+                                                     &data_buffer);
+  if (data_buffer_length == Resources::kNoSuchInstance) {
+    printf("Could not find %s %s\n", resource_name, resource_name+prefix_len);
+  }
+  ASSERT(data_buffer_length != Resources::kNoSuchInstance);
+  Dart_Handle data_list = Dart_NewTypedData(Dart_TypedData_kUint8,
+                                            data_buffer_length);
+  RETURN_ERROR_HANDLE(data_list);
+  Dart_TypedData_Type type = Dart_TypedData_kInvalid;
+  void* data_list_buffer = NULL;
+  intptr_t data_list_buffer_length = 0;
+  Dart_Handle result = Dart_TypedDataAcquireData(data_list, &type,
+                                                 &data_list_buffer,
+                                                 &data_list_buffer_length);
+  RETURN_ERROR_HANDLE(result);
+  ASSERT(data_buffer_length == data_list_buffer_length);
+  ASSERT(data_list_buffer != NULL);
+  ASSERT(type = Dart_TypedData_kUint8);
+  memmove(data_list_buffer, &data_buffer[0], data_buffer_length);
+  result = Dart_TypedDataReleaseData(data_list);
+  RETURN_ERROR_HANDLE(result);
+
+  // Make invoke call.
+  const intptr_t kNumArgs = 2;
+  Dart_Handle args[kNumArgs] = { name, data_list };
+  result = Dart_Invoke(library, Dart_NewStringFromCString("_addResource"),
+                       kNumArgs, args);
+  return result;
+}
+
+
+Dart_Handle VmService::LoadResources(Dart_Handle library) {
+  Dart_Handle result = Dart_Null();
+  intptr_t prefixLen = strlen(kClientResourceNamePrefix);
+  for (intptr_t i = 0; i < Resources::get_resource_count(); i++) {
+    const char* path = Resources::get_resource_path(i);
+    if (!strncmp(path, kClientResourceNamePrefix, prefixLen)) {
+      result = LoadResource(library, path, kClientResourceNamePrefix);
+      if (Dart_IsError(result)) {
+        break;
+      }
+    }
+  }
+  return result;
+}
+
+
+void VmService::ThreadMain(uword parameters) {
+  ASSERT(Dart_CurrentIsolate() == NULL);
+  ASSERT(isolate_ == NULL);
+
+  intptr_t server_port = static_cast<intptr_t>(parameters);
+  ASSERT(server_port >= 0);
+
+  // Lock scope.
+  {
+    MonitorLocker ml(monitor_);
+    bool r = _Start(server_port);
+    if (!r) {
+      port_ = ILLEGAL_PORT;
+      monitor_->Notify();
+      return;
+    }
+
+    Dart_EnterIsolate(isolate_);
+    Dart_EnterScope();
+
+    Dart_Handle receievePort = Dart_GetReceivePort(port_);
+    ASSERT(!Dart_IsError(receievePort));
+    monitor_->Notify();
+  }
+
+  // Keep handling messages until the last active receive port is closed.
+  Dart_Handle result = Dart_RunLoop();
+  if (Dart_IsError(result)) {
+    printf("VmService error %s\n", Dart_GetError(result));
+  }
+
+  _Stop();
+
+  Dart_ExitScope();
+  Dart_ExitIsolate();
+}
+
+
+
+
+static Dart_Handle MakeServiceControlMessage(Dart_Port port) {
+  Dart_Handle list = Dart_NewList(2);
+  ASSERT(!Dart_IsError(list));
+  Dart_Handle sendPort = Dart_NewSendPort(port);
+  ASSERT(!Dart_IsError(sendPort));
+  Dart_ListSetAt(list, 1, sendPort);
+  return list;
+}
+
+
+bool VmService::SendIsolateStartupMessage(Dart_Port port) {
+  if (!IsRunning()) {
+    return false;
+  }
+  Dart_Isolate isolate = Dart_CurrentIsolate();
+  ASSERT(isolate != NULL);
+  ASSERT(Dart_GetMainPortId() == port);
+  Dart_Handle list = MakeServiceControlMessage(port);
+  Dart_ListSetAt(list, 0,
+                 Dart_NewInteger(VM_SERVICE_ISOLATE_STARTUP_MESSAGE_ID));
+  return Dart_Post(port_, list);
+}
+
+
+bool VmService::SendIsolateShutdownMessage(Dart_Port port) {
+  if (!IsRunning()) {
+    return false;
+  }
+  Dart_Isolate isolate = Dart_CurrentIsolate();
+  ASSERT(isolate != NULL);
+  ASSERT(Dart_GetMainPortId() == port);
+  Dart_Handle list = MakeServiceControlMessage(port);
+  Dart_ListSetAt(list, 0,
+                 Dart_NewInteger(VM_SERVICE_ISOLATE_SHUTDOWN_MESSAGE_ID));
+  return Dart_Post(port_, list);
+}
+
+
+}  // namespace bin
+}  // namespace dart
diff --git a/runtime/bin/vmservice_impl.h b/runtime/bin/vmservice_impl.h
new file mode 100644
index 0000000..2807627
--- /dev/null
+++ b/runtime/bin/vmservice_impl.h
@@ -0,0 +1,54 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#ifndef BIN_VMSERVICE_IMPL_H_
+#define BIN_VMSERVICE_IMPL_H_
+
+#include "bin/vmservice.h"
+#include "platform/thread.h"
+
+
+namespace dart {
+namespace bin {
+
+class VmService {
+ public:
+  // Returns false if service could not be started.
+  static bool Start(intptr_t server_port);
+  // Error message if startup failed.
+  static const char* GetErrorMessage();
+
+  static Dart_Port port();
+
+  static bool IsRunning();
+
+  static bool SendIsolateStartupMessage(Dart_Port port);
+  static bool SendIsolateShutdownMessage(Dart_Port port);
+
+ private:
+  static bool _Start(intptr_t server_port);
+  static void _Stop();
+  static Dart_Handle LoadScript(const char* name);
+  static Dart_Handle LoadSources(Dart_Handle library, const char** names);
+  static Dart_Handle LoadSource(Dart_Handle library, const char* name);
+  static Dart_Handle LoadResources(Dart_Handle library);
+  static Dart_Handle LoadResource(Dart_Handle library, const char* name,
+                                  const char* prefix);
+
+  static void ThreadMain(uword parameters);
+
+  static Dart_Isolate isolate_;
+  static Dart_Port port_;
+  static const char* error_msg_;
+  static dart::Monitor* monitor_;
+
+  DISALLOW_ALLOCATION();
+  DISALLOW_IMPLICIT_CONSTRUCTORS(VmService);
+};
+
+
+}  // namespace bin
+}  // namespace dart
+
+#endif  // BIN_VMSERVICE_IMPL_H_
diff --git a/runtime/lib/expando_patch.dart b/runtime/lib/expando_patch.dart
index 5de84c4..07ed0b7 100644
--- a/runtime/lib/expando_patch.dart
+++ b/runtime/lib/expando_patch.dart
@@ -114,8 +114,14 @@
 
     for (var i = 0; i < old_data.length; i++) {
       var entry = old_data[i];
-      if ((entry != null) && (entry.key != null)) {
-        this[entry.key] = entry.value;
+      if (entry != null) {
+        // Ensure that the entry.key is not cleared between checking for it and
+        // inserting it into the new table.
+        var val = entry.value;
+        var key = entry.key;
+        if (key != null) {
+          this[key] = val;
+        }
       }
     }
   }
diff --git a/runtime/lib/invocation_mirror.cc b/runtime/lib/invocation_mirror.cc
index a8c70b3..913dcf4 100644
--- a/runtime/lib/invocation_mirror.cc
+++ b/runtime/lib/invocation_mirror.cc
@@ -35,8 +35,7 @@
   const Function& function = Function::Handle(
       Resolver::ResolveDynamic(receiver,
                                fun_name,
-                               args_desc.Count(),
-                               args_desc.NamedCount()));
+                               args_desc));
   Object& result = Object::Handle();
   if (function.IsNull()) {
     result = DartEntry::InvokeNoSuchMethod(receiver,
diff --git a/runtime/lib/mirrors.cc b/runtime/lib/mirrors.cc
index 3cb8690..1cb1c74 100644
--- a/runtime/lib/mirrors.cc
+++ b/runtime/lib/mirrors.cc
@@ -13,6 +13,7 @@
 #include "vm/message.h"
 #include "vm/port.h"
 #include "vm/resolver.h"
+#include "vm/symbols.h"
 
 namespace dart {
 
@@ -68,19 +69,6 @@
 }
 
 
-static Dart_Handle IsMirror(Dart_Handle object, bool* is_mirror) {
-  Dart_Handle cls_name = NewString("Mirror");
-  Dart_Handle type = Dart_GetType(MirrorLib(), cls_name, 0, NULL);
-  if (Dart_IsError(type)) {
-    return type;
-  }
-  Dart_Handle result = Dart_ObjectIsType(object, type, is_mirror);
-  if (Dart_IsError(result)) {
-    return result;
-  }
-  return Dart_True();  // Indicates success.  Result is in is_mirror.
-}
-
 static Dart_Handle IsMethodMirror(Dart_Handle object, bool* is_mirror) {
   Dart_Handle cls_name = NewString("MethodMirror");
   Dart_Handle type = Dart_GetType(MirrorLib(), cls_name, 0, NULL);
@@ -108,14 +96,6 @@
 }
 
 
-static bool IsSimpleValue(Dart_Handle object) {
-  return (Dart_IsNull(object) ||
-          Dart_IsNumber(object) ||
-          Dart_IsString(object) ||
-          Dart_IsBoolean(object));
-}
-
-
 static void FreeVMReference(Dart_WeakPersistentHandle weak_ref, void* data) {
   Dart_PersistentHandle perm_handle =
       reinterpret_cast<Dart_PersistentHandle>(data);
@@ -282,58 +262,6 @@
   // will return nonsense if mirror is not an ObjectMirror
 }
 
-static Dart_Handle UnwrapArg(Dart_Handle arg) {
-    if (Dart_IsError(arg)) {
-      return arg;
-    }
-    bool is_mirror = false;
-    Dart_Handle result = IsMirror(arg, &is_mirror);
-    if (Dart_IsError(result)) {
-      return result;
-    }
-    if (is_mirror) {
-      return UnwrapMirror(arg);
-    } else {
-      // Simple value.
-      ASSERT(IsSimpleValue(arg));
-      return arg;
-    }
-}
-
-static Dart_Handle UnwrapArgList(Dart_Handle arg_list,
-                                 GrowableArray<Dart_Handle>* arg_array) {
-  intptr_t len = 0;
-  Dart_Handle result = Dart_ListLength(arg_list, &len);
-  if (Dart_IsError(result)) {
-    return result;
-  }
-  for (intptr_t i = 0; i < len; i++) {
-    Dart_Handle arg = Dart_ListGetAt(arg_list, i);
-    Dart_Handle unwrapped_arg = UnwrapArg(arg);
-    if (Dart_IsError(unwrapped_arg)) {
-      return unwrapped_arg;
-    }
-    arg_array->Add(unwrapped_arg);
-  }
-  return Dart_True();
-}
-
-static Dart_Handle UnpackLocalArgList(Dart_Handle arg_list,
-                                      GrowableArray<Dart_Handle>* arg_array) {
-  intptr_t len = 0;
-  Dart_Handle result = Dart_ListLength(arg_list, &len);
-  if (Dart_IsError(result)) {
-    return result;
-  }
-  for (intptr_t i = 0; i < len; i++) {
-    Dart_Handle arg = Dart_ListGetAt(arg_list, i);
-    if (Dart_IsError(arg)) {
-      return arg;
-    }
-    arg_array->Add(arg);
-  }
-  return Dart_True();
-}
 
 static Dart_Handle CreateLazyMirror(Dart_Handle target);
 
@@ -631,69 +559,37 @@
 
 static Dart_Handle CreateMethodMirror(Dart_Handle func,
                                       Dart_Handle owner_mirror) {
-  ASSERT(Dart_IsFunction(func));
+  // TODO(11742): Unwrapping is needed until the whole method is converted.
+  Isolate* isolate = Isolate::Current();
+  DARTSCOPE(isolate);
+  const Function& func_obj = Api::UnwrapFunctionHandle(isolate, func);
+
   Dart_Handle mirror_cls_name = NewString("_LocalMethodMirrorImpl");
   Dart_Handle mirror_type = Dart_GetType(MirrorLib(), mirror_cls_name, 0, NULL);
   if (Dart_IsError(mirror_type)) {
     return mirror_type;
   }
 
-  bool is_static = false;
-  bool is_abstract = false;
-  bool is_getter = false;
-  bool is_setter = false;
-  bool is_constructor = false;
-
-  Dart_Handle result = Dart_FunctionIsStatic(func, &is_static);
-  if (Dart_IsError(result)) {
-    return result;
-  }
-  result = Dart_FunctionIsAbstract(func, &is_abstract);
-  if (Dart_IsError(result)) {
-    return result;
-  }
-  result = Dart_FunctionIsGetter(func, &is_getter);
-  if (Dart_IsError(result)) {
-    return result;
-  }
-  result = Dart_FunctionIsSetter(func, &is_setter);
-  if (Dart_IsError(result)) {
-    return result;
-  }
-  result = Dart_FunctionIsConstructor(func, &is_constructor);
-  if (Dart_IsError(result)) {
-    return result;
-  }
-
   Dart_Handle return_type = Dart_FunctionReturnType(func);
   if (Dart_IsError(return_type)) {
     return return_type;
   }
 
-  int64_t fixed_param_count;
-  int64_t opt_param_count;
-  result = Dart_FunctionParameterCounts(func,
-                                        &fixed_param_count,
-                                        &opt_param_count);
-  if (Dart_IsError(result)) {
-    return result;
-  }
-
   // TODO(turnidge): Implement constructor kinds (arguments 7 - 10).
   Dart_Handle args[] = {
     CreateMirrorReference(func),
     owner_mirror,
     CreateParameterMirrorList(func),
     CreateLazyMirror(return_type),
-    Dart_NewBoolean(is_static),
-    Dart_NewBoolean(is_abstract),
-    Dart_NewBoolean(is_getter),
-    Dart_NewBoolean(is_setter),
-    Dart_NewBoolean(is_constructor),
-    Dart_False(),
-    Dart_False(),
-    Dart_False(),
-    Dart_False(),
+    func_obj.is_static() ? Api::True() : Api::False(),
+    func_obj.is_abstract() ? Api::True() : Api::False(),
+    func_obj.IsGetterFunction() ? Api::True() : Api::False(),
+    func_obj.IsSetterFunction() ? Api::True() : Api::False(),
+    func_obj.IsConstructor() ? Api::True() : Api::False(),
+    Api::False(),
+    Api::False(),
+    Api::False(),
+    Api::False()
   };
   Dart_Handle mirror =
       Dart_New(mirror_type, Dart_Null(), ARRAY_SIZE(args), args);
@@ -952,6 +848,7 @@
     return member_map;
   }
   Dart_Handle args[] = {
+    CreateMirrorReference(lib),
     CreateVMReference(lib),
     Dart_LibraryName(lib),
     Dart_LibraryUrl(lib),
@@ -1121,51 +1018,6 @@
 }
 
 
-static Dart_Handle CreateMirroredError(Dart_Handle error) {
-  ASSERT(Dart_IsError(error));
-  if (Dart_IsUnhandledExceptionError(error)) {
-    Dart_Handle exc = Dart_ErrorGetException(error);
-    if (Dart_IsError(exc)) {
-      return exc;
-    }
-    Dart_Handle exc_string = Dart_ToString(exc);
-    if (Dart_IsError(exc_string)) {
-      // Only propagate fatal errors from exc.toString().  Ignore the rest.
-      if (Dart_IsFatalError(exc_string)) {
-        return exc_string;
-      }
-      exc_string = Dart_Null();
-    }
-
-    Dart_Handle stack = Dart_ErrorGetStacktrace(error);
-    if (Dart_IsError(stack)) {
-      return stack;
-    }
-    Dart_Handle cls_name = NewString("MirroredUncaughtExceptionError");
-    Dart_Handle type = Dart_GetType(MirrorLib(), cls_name, 0, NULL);
-    Dart_Handle args[] = {
-      CreateInstanceMirror(exc),
-      exc_string,
-      stack,
-    };
-    Dart_Handle mirrored_exc =
-        Dart_New(type, Dart_Null(), ARRAY_SIZE(args), args);
-    return Dart_NewUnhandledExceptionError(mirrored_exc);
-  } else if (Dart_IsApiError(error) ||
-             Dart_IsCompilationError(error)) {
-    Dart_Handle cls_name = NewString("MirroredCompilationError");
-    Dart_Handle type = Dart_GetType(MirrorLib(), cls_name, 0, NULL);
-    Dart_Handle args[] = { NewString(Dart_GetError(error)) };
-    Dart_Handle mirrored_exc =
-        Dart_New(type, Dart_Null(), ARRAY_SIZE(args), args);
-    return Dart_NewUnhandledExceptionError(mirrored_exc);
-  } else {
-    ASSERT(Dart_IsFatalError(error));
-    return error;
-  }
-}
-
-
 void NATIVE_ENTRY_FUNCTION(Mirrors_makeLocalMirrorSystem)(
     Dart_NativeArguments args) {
   Dart_EnterScope();
@@ -1242,176 +1094,6 @@
   Dart_ExitScope();
 }
 
-void NATIVE_ENTRY_FUNCTION(LocalObjectMirrorImpl_invoke)(
-    Dart_NativeArguments args) {
-  Dart_EnterScope();
-  Dart_Handle mirror = Dart_GetNativeArgument(args, 0);
-  Dart_Handle member_name = Dart_GetNativeArgument(args, 1);
-  // The arguments are either simple values or instance mirrors.
-  Dart_Handle positional_arguments = Dart_GetNativeArgument(args, 2);
-  Dart_Handle async = Dart_GetNativeArgument(args, 3);
-
-  Dart_Handle reflectee = UnwrapMirror(mirror);
-  Dart_Handle result;
-  GrowableArray<Dart_Handle> invoke_args;
-  if (Dart_IdentityEquals(async, Dart_True())) {
-    result = UnwrapArgList(positional_arguments, &invoke_args);
-  } else {
-    result = UnpackLocalArgList(positional_arguments, &invoke_args);
-  }
-  if (Dart_IsError(result)) {
-    Dart_PropagateError(result);
-  }
-  result = Dart_Invoke(reflectee,
-                       member_name,
-                       invoke_args.length(),
-                       invoke_args.data());
-  if (Dart_IsError(result)) {
-    // Instead of propagating the error from an invoke directly, we
-    // provide reflective access to the error.
-    Dart_PropagateError(CreateMirroredError(result));
-  }
-
-  Dart_Handle wrapped_result = CreateInstanceMirror(result);
-  if (Dart_IsError(wrapped_result)) {
-    Dart_PropagateError(wrapped_result);
-  }
-  Dart_SetReturnValue(args, wrapped_result);
-  Dart_ExitScope();
-}
-
-
-void NATIVE_ENTRY_FUNCTION(LocalObjectMirrorImpl_getField)(
-    Dart_NativeArguments args) {
-  Dart_EnterScope();
-  Dart_Handle mirror = Dart_GetNativeArgument(args, 0);
-  Dart_Handle fieldName = Dart_GetNativeArgument(args, 1);
-
-  Dart_Handle reflectee = UnwrapMirror(mirror);
-  Dart_Handle result = Dart_GetField(reflectee, fieldName);
-  if (Dart_IsError(result)) {
-    // Instead of propagating the error from a GetField directly, we
-    // provide reflective access to the error.
-    Dart_PropagateError(CreateMirroredError(result));
-  }
-
-  Dart_Handle wrapped_result = CreateInstanceMirror(result);
-  if (Dart_IsError(wrapped_result)) {
-    Dart_PropagateError(wrapped_result);
-  }
-  Dart_SetReturnValue(args, wrapped_result);
-  Dart_ExitScope();
-}
-
-
-void NATIVE_ENTRY_FUNCTION(LocalObjectMirrorImpl_setField)(
-    Dart_NativeArguments args) {
-  Dart_EnterScope();
-  Dart_Handle mirror = Dart_GetNativeArgument(args, 0);
-  Dart_Handle fieldName = Dart_GetNativeArgument(args, 1);
-  Dart_Handle value = Dart_GetNativeArgument(args, 2);
-  Dart_Handle async = Dart_GetNativeArgument(args, 3);
-
-  Dart_Handle reflectee = UnwrapMirror(mirror);
-  Dart_Handle set_arg;
-  if (Dart_IdentityEquals(async, Dart_True())) {
-    set_arg = UnwrapArg(value);
-  } else {
-    set_arg = value;
-  }
-  if (Dart_IsError(set_arg)) {
-    Dart_PropagateError(set_arg);
-  }
-  Dart_Handle result = Dart_SetField(reflectee, fieldName, set_arg);
-  if (Dart_IsError(result)) {
-    // Instead of propagating the error from a SetField directly, we
-    // provide reflective access to the error.
-    Dart_PropagateError(CreateMirroredError(result));
-  }
-
-  Dart_Handle wrapped_result = CreateInstanceMirror(result);
-  if (Dart_IsError(wrapped_result)) {
-    Dart_PropagateError(wrapped_result);
-  }
-  Dart_SetReturnValue(args, wrapped_result);
-  Dart_ExitScope();
-}
-
-
-void NATIVE_ENTRY_FUNCTION(LocalClosureMirrorImpl_apply)(
-    Dart_NativeArguments args) {
-  Dart_EnterScope();
-  Dart_Handle mirror = Dart_GetNativeArgument(args, 0);
-  // The arguments are either simple values or instance mirrors.
-  Dart_Handle positional_arguments = Dart_GetNativeArgument(args, 1);
-  Dart_Handle async = Dart_GetNativeArgument(args, 2);
-
-  Dart_Handle reflectee = UnwrapMirror(mirror);
-  GrowableArray<Dart_Handle> invoke_args;
-  Dart_Handle result;
-  if (Dart_IdentityEquals(async, Dart_True())) {
-    result = UnwrapArgList(positional_arguments, &invoke_args);
-  } else {
-    result = UnpackLocalArgList(positional_arguments, &invoke_args);
-  }
-  if (Dart_IsError(result)) {
-    Dart_PropagateError(result);
-  }
-  result =
-      Dart_InvokeClosure(reflectee, invoke_args.length(), invoke_args.data());
-  if (Dart_IsError(result)) {
-    // Instead of propagating the error from an apply directly, we
-    // provide reflective access to the error.
-    Dart_PropagateError(CreateMirroredError(result));
-  }
-
-  Dart_Handle wrapped_result = CreateInstanceMirror(result);
-  if (Dart_IsError(wrapped_result)) {
-    Dart_PropagateError(wrapped_result);
-  }
-  Dart_SetReturnValue(args, wrapped_result);
-  Dart_ExitScope();
-}
-
-
-void NATIVE_ENTRY_FUNCTION(LocalClassMirrorImpl_invokeConstructor)(
-    Dart_NativeArguments args) {
-  Dart_EnterScope();
-  Dart_Handle klass_mirror = Dart_GetNativeArgument(args, 0);
-  Dart_Handle constructor_name = Dart_GetNativeArgument(args, 1);
-  // The arguments are either simple values or instance mirrors.
-  Dart_Handle positional_arguments = Dart_GetNativeArgument(args, 2);
-  Dart_Handle async = Dart_GetNativeArgument(args, 3);
-
-  Dart_Handle klass = UnwrapMirror(klass_mirror);
-  GrowableArray<Dart_Handle> invoke_args;
-  Dart_Handle result;
-  if (Dart_IdentityEquals(async, Dart_True())) {
-    result = UnwrapArgList(positional_arguments, &invoke_args);
-  } else {
-    result = UnpackLocalArgList(positional_arguments, &invoke_args);
-  }
-  if (Dart_IsError(result)) {
-    Dart_PropagateError(result);
-  }
-  result = Dart_New(klass,
-                    constructor_name,
-                    invoke_args.length(),
-                    invoke_args.data());
-  if (Dart_IsError(result)) {
-    // Instead of propagating the error from an invoke directly, we
-    // provide reflective access to the error.
-    Dart_PropagateError(CreateMirroredError(result));
-  }
-
-  Dart_Handle wrapped_result = CreateInstanceMirror(result);
-  if (Dart_IsError(wrapped_result)) {
-    Dart_PropagateError(wrapped_result);
-  }
-  Dart_SetReturnValue(args, wrapped_result);
-  Dart_ExitScope();
-}
-
 
 void HandleMirrorsMessage(Isolate* isolate,
                           Dart_Port reply_port,
@@ -1420,6 +1102,130 @@
 }
 
 
+// TODO(11742): This is transitional.
+static RawInstance* Reflect(const Instance& reflectee) {
+  Isolate* isolate = Isolate::Current();
+  DARTSCOPE(isolate);
+  return Instance::RawCast(
+      Api::UnwrapHandle(
+          CreateInstanceMirror(
+              Api::NewHandle(isolate, reflectee.raw()))));
+}
+
+
+static void ThrowMirroredUnhandledError(const Error& original_error) {
+  const UnhandledException& unhandled_ex =
+      UnhandledException::Cast(original_error);
+  Instance& exc = Instance::Handle(unhandled_ex.exception());
+  Instance& stack = Instance::Handle(unhandled_ex.stacktrace());
+
+  Object& exc_string_or_error =
+      Object::Handle(DartLibraryCalls::ToString(exc));
+  String& exc_string = String::Handle();
+  // Ignore any errors that might occur in toString.
+  if (exc_string_or_error.IsString()) {
+    exc_string ^= exc_string_or_error.raw();
+  }
+
+  Instance& mirror_on_exc = Instance::Handle(Reflect(exc));
+
+  Array& args = Array::Handle(Array::New(3));
+  args.SetAt(0, mirror_on_exc);
+  args.SetAt(1, exc_string);
+  args.SetAt(2, stack);
+
+  Exceptions::ThrowByType(Exceptions::kMirroredUncaughtExceptionError, args);
+  UNREACHABLE();
+}
+
+
+static void ThrowMirroredCompilationError(const String& message) {
+  Array& args = Array::Handle(Array::New(1));
+  args.SetAt(0, message);
+
+  Exceptions::ThrowByType(Exceptions::kMirroredCompilationError, args);
+  UNREACHABLE();
+}
+
+
+static void ThrowInvokeError(const Error& error) {
+  if (error.IsUnhandledException()) {
+    // An ordinary runtime error.
+    ThrowMirroredUnhandledError(error);
+  }
+  if (error.IsLanguageError()) {
+    // A compilation error that was delayed by lazy compilation.
+    const LanguageError& compilation_error = LanguageError::Cast(error);
+    String& message = String::Handle(compilation_error.message());
+    ThrowMirroredCompilationError(message);
+  }
+  UNREACHABLE();
+}
+
+
+static RawFunction* ResolveConstructor(const char* current_func,
+                                       const Class& cls,
+                                       const String& class_name,
+                                       const String& constr_name,
+                                       int num_args) {
+  // The constructor must be present in the interface.
+  const Function& constructor =
+      Function::Handle(cls.LookupFunctionAllowPrivate(constr_name));
+  if (constructor.IsNull() ||
+      (!constructor.IsConstructor() && !constructor.IsFactory())) {
+    const String& lookup_class_name = String::Handle(cls.Name());
+    if (!class_name.Equals(lookup_class_name)) {
+      // When the class name used to build the constructor name is
+      // different than the name of the class in which we are doing
+      // the lookup, it can be confusing to the user to figure out
+      // what's going on.  Be a little more explicit for these error
+      // messages.
+      const String& message = String::Handle(
+          String::NewFormatted(
+              "%s: could not find factory '%s' in class '%s'.",
+              current_func,
+              constr_name.ToCString(),
+              lookup_class_name.ToCString()));
+      ThrowMirroredCompilationError(message);
+      UNREACHABLE();
+    } else {
+      const String& message = String::Handle(
+          String::NewFormatted("%s: could not find constructor '%s'.",
+                               current_func, constr_name.ToCString()));
+      ThrowMirroredCompilationError(message);
+      UNREACHABLE();
+    }
+  }
+  int extra_args = (constructor.IsConstructor() ? 2 : 1);
+  String& error_message = String::Handle();
+  if (!constructor.AreValidArgumentCounts(num_args + extra_args,
+                                          0,
+                                          &error_message)) {
+    const String& message = String::Handle(
+        String::NewFormatted("%s: wrong argument count for "
+                             "constructor '%s': %s.",
+                             current_func,
+                             constr_name.ToCString(),
+                             error_message.ToCString()));
+    ThrowMirroredCompilationError(message);
+    UNREACHABLE();
+  }
+  return constructor.raw();
+}
+
+
+static bool FieldIsUninitialized(const Field& field) {
+  ASSERT(!field.IsNull());
+
+  // Return getter method for uninitialized fields, rather than the
+  // field object, since the value in the field object will not be
+  // initialized until the first time the getter is invoked.
+  const Instance& value = Instance::Handle(field.value());
+  ASSERT(value.raw() != Object::transition_sentinel().raw());
+  return value.raw() == Object::sentinel().raw();
+}
+
+
 DEFINE_NATIVE_ENTRY(ClassMirror_name, 1) {
   const MirrorReference& klass_ref =
       MirrorReference::CheckedHandle(arguments->NativeArgAt(0));
@@ -1428,6 +1234,555 @@
   return klass.Name();
 }
 
+
+// Invoke the function, or noSuchMethod if it is null. Propagate any unhandled
+// exceptions. Wrap and propagate any compilation errors.
+static RawObject* ReflectivelyInvokeDynamicFunction(const Instance& receiver,
+                                                    const Function& function,
+                                                    const String& target_name,
+                                                    const Array& arguments) {
+  // Note "arguments" is already the internal arguments with the receiver as
+  // the first element.
+  Object& result = Object::Handle();
+  if (function.IsNull()) {
+    const Array& arguments_descriptor =
+        Array::Handle(ArgumentsDescriptor::New(arguments.Length()));
+    result = DartEntry::InvokeNoSuchMethod(receiver,
+                                           target_name,
+                                           arguments,
+                                           arguments_descriptor);
+  } else {
+    result = DartEntry::InvokeFunction(function, arguments);
+  }
+
+  if (result.IsError()) {
+    ThrowInvokeError(Error::Cast(result));
+    UNREACHABLE();
+  }
+  return result.raw();
+}
+
+
+DEFINE_NATIVE_ENTRY(InstanceMirror_invoke, 4) {
+  // Argument 0 is the mirror, which is unused by the native. It exists
+  // because this native is an instance method in order to be polymorphic
+  // with its cousins.
+
+  const Instance& reflectee =
+      Instance::CheckedHandle(arguments->NativeArgAt(1));
+
+  const String& function_name =
+      String::CheckedHandle(arguments->NativeArgAt(2));
+
+  const Array& positional_args =
+      Array::CheckedHandle(arguments->NativeArgAt(3));
+  intptr_t number_of_arguments = positional_args.Length();
+
+  const Array& args =
+      Array::Handle(Array::New(number_of_arguments + 1));  // Plus receiver.
+  Object& arg = Object::Handle();
+  args.SetAt(0, reflectee);
+  for (int i = 0; i < number_of_arguments; i++) {
+    arg = positional_args.At(i);
+    args.SetAt(i + 1, arg);  // Plus receiver.
+  }
+
+  ArgumentsDescriptor args_desc(
+      Array::Handle(ArgumentsDescriptor::New(args.Length())));
+  // TODO(11771): This won't find private members.
+  const Function& function = Function::Handle(
+      Resolver::ResolveDynamic(reflectee,
+                               function_name,
+                               args_desc));
+
+  return ReflectivelyInvokeDynamicFunction(reflectee,
+                                           function,
+                                           function_name,
+                                           args);
+}
+
+
+DEFINE_NATIVE_ENTRY(InstanceMirror_invokeGetter, 3) {
+  // Argument 0 is the mirror, which is unused by the native. It exists
+  // because this native is an instance method in order to be polymorphic
+  // with its cousins.
+
+  const Instance& reflectee =
+      Instance::CheckedHandle(arguments->NativeArgAt(1));
+
+  const String& getter_name =
+      String::CheckedHandle(arguments->NativeArgAt(2));
+
+  // Every instance field has a getter Function.  Try to find the
+  // getter in any superclass and use that function to access the
+  // field.
+  // NB: We do not use Resolver::ResolveDynamic because we want to find private
+  // members.
+  Class& klass = Class::Handle(reflectee.clazz());
+  String& internal_getter_name = String::Handle(Field::GetterName(getter_name));
+  Function& getter = Function::Handle();
+  while (!klass.IsNull()) {
+    getter = klass.LookupDynamicFunctionAllowPrivate(internal_getter_name);
+    if (!getter.IsNull()) {
+      break;
+    }
+    klass = klass.SuperClass();
+  }
+
+  const int kNumArgs = 1;
+  const Array& args = Array::Handle(Array::New(kNumArgs));
+  args.SetAt(0, reflectee);
+
+  return ReflectivelyInvokeDynamicFunction(reflectee,
+                                           getter,
+                                           internal_getter_name,
+                                           args);
+}
+
+
+DEFINE_NATIVE_ENTRY(InstanceMirror_invokeSetter, 4) {
+  // Argument 0 is the mirror, which is unused by the native. It exists
+  // because this native is an instance method in order to be polymorphic
+  // with its cousins.
+
+  const Instance& reflectee =
+      Instance::CheckedHandle(arguments->NativeArgAt(1));
+
+  const String& setter_name =
+      String::CheckedHandle(arguments->NativeArgAt(2));
+
+  const Instance& value = Instance::CheckedHandle(arguments->NativeArgAt(3));
+
+  String& internal_setter_name =
+      String::Handle(Field::SetterName(setter_name));
+  Function& setter = Function::Handle();
+
+  Class& klass = Class::Handle(reflectee.clazz());
+  Field& field = Field::Handle();
+
+  while (!klass.IsNull()) {
+    field = klass.LookupInstanceField(setter_name);
+    if (!field.IsNull() && field.is_final()) {
+      const String& message = String::Handle(
+          String::NewFormatted("%s: cannot set final field '%s'.",
+                               "InstanceMirror_invokeSetter",
+                               setter_name.ToCString()));
+      ThrowMirroredCompilationError(message);
+      UNREACHABLE();
+    }
+    setter = klass.LookupDynamicFunctionAllowPrivate(internal_setter_name);
+    if (!setter.IsNull()) {
+      break;
+    }
+    klass = klass.SuperClass();
+  }
+
+  // Invoke the setter and return the result.
+  const int kNumArgs = 2;
+  const Array& args = Array::Handle(Array::New(kNumArgs));
+  args.SetAt(0, reflectee);
+  args.SetAt(1, value);
+
+  return ReflectivelyInvokeDynamicFunction(reflectee,
+                                           setter,
+                                           internal_setter_name,
+                                           args);
+}
+
+
+DEFINE_NATIVE_ENTRY(ClosureMirror_apply, 2) {
+  const Instance& closure = Instance::CheckedHandle(arguments->NativeArgAt(0));
+  ASSERT(!closure.IsNull() && closure.IsCallable(NULL, NULL));
+
+  const Array& positional_args =
+      Array::CheckedHandle(arguments->NativeArgAt(1));
+  intptr_t number_of_arguments = positional_args.Length();
+
+  // Set up arguments to include the closure as the first argument.
+  const Array& args = Array::Handle(Array::New(number_of_arguments + 1));
+  Object& obj = Object::Handle();
+  args.SetAt(0, closure);
+  for (int i = 0; i < number_of_arguments; i++) {
+    obj = positional_args.At(i);
+    args.SetAt(i + 1, obj);
+  }
+
+  obj = DartEntry::InvokeClosure(args);
+  if (obj.IsError()) {
+    ThrowInvokeError(Error::Cast(obj));
+    UNREACHABLE();
+  }
+  return obj.raw();
+}
+
+
+DEFINE_NATIVE_ENTRY(ClassMirror_invoke, 4) {
+  // Argument 0 is the mirror, which is unused by the native. It exists
+  // because this native is an instance method in order to be polymorphic
+  // with its cousins.
+
+  const MirrorReference& klass_ref =
+      MirrorReference::CheckedHandle(arguments->NativeArgAt(1));
+  Class& klass = Class::Handle();
+  klass ^= klass_ref.referent();
+
+  const String& function_name =
+      String::CheckedHandle(arguments->NativeArgAt(2));
+
+  const Array& positional_args =
+      Array::CheckedHandle(arguments->NativeArgAt(3));
+  intptr_t number_of_arguments = positional_args.Length();
+
+  // TODO(11771): This won't find private members.
+  const Function& function = Function::Handle(
+        Resolver::ResolveStatic(klass,
+                                function_name,
+                                number_of_arguments,
+                                Object::empty_array(),
+                                Resolver::kIsQualified));
+  if (function.IsNull()) {
+    const String& klass_name = String::Handle(klass.Name());
+    const String& message = String::Handle(
+      String::NewFormatted("%s: did not find static method '%s.%s'.",
+                           "ClassMirror_invoke",
+                           klass_name.ToCString(),
+                           function_name.ToCString()));
+    ThrowMirroredCompilationError(message);
+    UNREACHABLE();
+  }
+  Object& result = Object::Handle(DartEntry::InvokeFunction(function,
+                                                            positional_args));
+  if (result.IsError()) {
+    ThrowInvokeError(Error::Cast(result));
+    UNREACHABLE();
+  }
+  return result.raw();
+}
+
+
+DEFINE_NATIVE_ENTRY(ClassMirror_invokeGetter, 3) {
+  // Argument 0 is the mirror, which is unused by the native. It exists
+  // because this native is an instance method in order to be polymorphic
+  // with its cousins.
+
+  const MirrorReference& klass_ref =
+      MirrorReference::CheckedHandle(arguments->NativeArgAt(1));
+  Class& klass = Class::Handle();
+  klass ^= klass_ref.referent();
+
+  const String& getter_name =
+      String::CheckedHandle(arguments->NativeArgAt(2));
+
+  // Note static fields do not have implicit getters.
+  const Field& field = Field::Handle(klass.LookupStaticField(getter_name));
+  if (field.IsNull() || FieldIsUninitialized(field)) {
+    const String& internal_getter_name = String::Handle(
+        Field::GetterName(getter_name));
+    const Function& getter = Function::Handle(
+        klass.LookupStaticFunctionAllowPrivate(internal_getter_name));
+
+    if (getter.IsNull()) {
+      const String& message = String::Handle(
+        String::NewFormatted("%s: did not find static getter '%s'.",
+                             "ClassMirror_invokeGetter",
+                             getter_name.ToCString()));
+      ThrowMirroredCompilationError(message);
+      UNREACHABLE();
+    }
+
+    // Invoke the getter and return the result.
+    Object& result = Object::Handle(
+        DartEntry::InvokeFunction(getter, Object::empty_array()));
+    if (result.IsError()) {
+      ThrowInvokeError(Error::Cast(result));
+      UNREACHABLE();
+    }
+    return result.raw();
+  }
+  return field.value();
+}
+
+
+DEFINE_NATIVE_ENTRY(ClassMirror_invokeSetter, 4) {
+  // Argument 0 is the mirror, which is unused by the native. It exists
+  // because this native is an instance method in order to be polymorphic
+  // with its cousins.
+
+  const MirrorReference& klass_ref =
+      MirrorReference::CheckedHandle(arguments->NativeArgAt(1));
+  Class& klass = Class::Handle();
+  klass ^= klass_ref.referent();
+
+  const String& setter_name =
+      String::CheckedHandle(arguments->NativeArgAt(2));
+
+  const Instance& value = Instance::CheckedHandle(arguments->NativeArgAt(3));
+
+  // Check for real fields and user-defined setters.
+  const Field& field = Field::Handle(klass.LookupStaticField(setter_name));
+  if (field.IsNull()) {
+    const String& internal_setter_name = String::Handle(
+      Field::SetterName(setter_name));
+    const Function& setter = Function::Handle(
+      klass.LookupStaticFunctionAllowPrivate(internal_setter_name));
+
+    if (setter.IsNull()) {
+      const String& message = String::Handle(
+        String::NewFormatted("%s: did not find static setter '%s'.",
+                             "ClassMirror_invokeSetter",
+                             setter_name.ToCString()));
+      ThrowMirroredCompilationError(message);
+      UNREACHABLE();
+    }
+
+    // Invoke the setter and return the result.
+    const int kNumArgs = 1;
+    const Array& args = Array::Handle(Array::New(kNumArgs));
+    args.SetAt(0, value);
+
+    Object& result = Object::Handle(
+        DartEntry::InvokeFunction(setter, args));
+    if (result.IsError()) {
+      ThrowInvokeError(Error::Cast(result));
+      UNREACHABLE();
+    }
+    return result.raw();
+  }
+
+  if (field.is_final()) {
+    const String& message = String::Handle(
+        String::NewFormatted("%s: cannot set final field '%s'.",
+                             "ClassMirror_invokeSetter",
+                             setter_name.ToCString()));
+    ThrowMirroredCompilationError(message);
+    UNREACHABLE();
+  }
+
+  field.set_value(value);
+  return value.raw();
+}
+
+
+DEFINE_NATIVE_ENTRY(ClassMirror_invokeConstructor, 3) {
+  const MirrorReference& klass_ref =
+      MirrorReference::CheckedHandle(arguments->NativeArgAt(0));
+  Class& klass = Class::Handle();
+  klass ^= klass_ref.referent();
+
+  const String& constructor_name =
+      String::CheckedHandle(arguments->NativeArgAt(1));
+
+  const Array& positional_args =
+      Array::CheckedHandle(arguments->NativeArgAt(2));
+
+  intptr_t number_of_arguments = positional_args.Length();
+
+  // By convention, the static function implementing a named constructor 'C'
+  // for class 'A' is labeled 'A.C', and the static function implementing the
+  // unnamed constructor for class 'A' is labeled 'A.'.
+  // This convention prevents users from explicitly calling constructors.
+  const String& klass_name = String::Handle(klass.Name());
+  String& internal_constructor_name =
+      String::Handle(String::Concat(klass_name, Symbols::Dot()));
+  if (!constructor_name.IsNull()) {
+    internal_constructor_name =
+        String::Concat(internal_constructor_name, constructor_name);
+  }
+
+  const Function& constructor =
+      Function::Handle(ResolveConstructor("ClassMirror_invokeConstructor",
+                                          klass,
+                                          klass_name,
+                                          internal_constructor_name,
+                                          number_of_arguments));
+
+  const Object& result =
+      Object::Handle(DartEntry::InvokeConstructor(klass,
+                                                  constructor,
+                                                  positional_args));
+  if (result.IsError()) {
+    ThrowInvokeError(Error::Cast(result));
+    UNREACHABLE();
+  }
+  // Factories may return null.
+  ASSERT(result.IsInstance() || result.IsNull());
+  return result.raw();
+}
+
+
+DEFINE_NATIVE_ENTRY(LibraryMirror_invoke, 4) {
+  // Argument 0 is the mirror, which is unused by the native. It exists
+  // because this native is an instance method in order to be polymorphic
+  // with its cousins.
+
+  const MirrorReference& library_ref =
+      MirrorReference::CheckedHandle(arguments->NativeArgAt(1));
+  Library& library = Library::Handle();
+  library ^= library_ref.referent();
+
+  const String& function_name =
+      String::CheckedHandle(arguments->NativeArgAt(2));
+
+  const Array& positional_args =
+      Array::CheckedHandle(arguments->NativeArgAt(3));
+  intptr_t number_of_arguments = positional_args.Length();
+
+
+  const Function& function = Function::Handle(
+      library.LookupFunctionAllowPrivate(function_name));
+
+  if (function.IsNull()) {
+    const String& message = String::Handle(
+      String::NewFormatted("%s: did not find top-level function '%s'.",
+                           "LibraryMirror_invoke",
+                           function_name.ToCString()));
+    ThrowMirroredCompilationError(message);
+    UNREACHABLE();
+  }
+
+  // LookupFunctionAllowPrivate does not check argument arity, so we
+  // do it here.
+  String& error_message = String::Handle();
+  if (!function.AreValidArgumentCounts(number_of_arguments,
+                                       /* num_named_args */ 0,
+                                       &error_message)) {
+    const String& message = String::Handle(
+      String::NewFormatted("%s: wrong argument count for function '%s': %s.",
+                           "LibraryMirror_invoke",
+                           function_name.ToCString(),
+                           error_message.ToCString()));
+    ThrowMirroredCompilationError(message);
+    UNREACHABLE();
+  }
+
+  const Object& result = Object::Handle(
+      DartEntry::InvokeFunction(function, positional_args));
+  if (result.IsError()) {
+    ThrowInvokeError(Error::Cast(result));
+    UNREACHABLE();
+  }
+  return result.raw();
+}
+
+
+DEFINE_NATIVE_ENTRY(LibraryMirror_invokeGetter, 3) {
+  // Argument 0 is the mirror, which is unused by the native. It exists
+  // because this native is an instance method in order to be polymorphic
+  // with its cousins.
+
+  const MirrorReference& library_ref =
+      MirrorReference::CheckedHandle(arguments->NativeArgAt(1));
+  Library& library = Library::Handle();
+  library ^= library_ref.referent();
+
+  const String& getter_name =
+      String::CheckedHandle(arguments->NativeArgAt(2));
+
+  // To access a top-level we may need to use the Field or the
+  // getter Function.  The getter function may either be in the
+  // library or in the field's owner class, depending.
+  const Field& field =
+      Field::Handle(library.LookupFieldAllowPrivate(getter_name));
+  Function& getter = Function::Handle();
+  if (field.IsNull()) {
+    // No field found.  Check for a getter in the lib.
+    const String& internal_getter_name =
+        String::Handle(Field::GetterName(getter_name));
+    getter = library.LookupFunctionAllowPrivate(internal_getter_name);
+  } else if (FieldIsUninitialized(field)) {
+    // A field was found.  Check for a getter in the field's owner classs.
+    const Class& klass = Class::Handle(field.owner());
+    const String& internal_getter_name =
+        String::Handle(Field::GetterName(getter_name));
+    getter = klass.LookupStaticFunctionAllowPrivate(internal_getter_name);
+  }
+
+  if (!getter.IsNull()) {
+    // Invoke the getter and return the result.
+    const Object& result = Object::Handle(
+        DartEntry::InvokeFunction(getter, Object::empty_array()));
+    if (result.IsError()) {
+      ThrowInvokeError(Error::Cast(result));
+      UNREACHABLE();
+    }
+    return result.raw();
+  } else if (!field.IsNull()) {
+    return field.value();
+  } else {
+    const String& message = String::Handle(
+        String::NewFormatted("%s: did not find top-level variable '%s'.",
+                             "LibraryMirror_invokeGetter",
+                             getter_name.ToCString()));
+    ThrowMirroredCompilationError(message);
+    UNREACHABLE();
+    return Instance::null();
+  }
+}
+
+
+DEFINE_NATIVE_ENTRY(LibraryMirror_invokeSetter, 4) {
+  // Argument 0 is the mirror, which is unused by the native. It exists
+  // because this native is an instance method in order to be polymorphic
+  // with its cousins.
+
+  const MirrorReference& library_ref =
+      MirrorReference::CheckedHandle(arguments->NativeArgAt(1));
+  Library& library = Library::Handle();
+  library ^= library_ref.referent();
+
+  const String& setter_name =
+      String::CheckedHandle(arguments->NativeArgAt(2));
+
+  const Instance& value = Instance::CheckedHandle(arguments->NativeArgAt(3));
+
+  // To access a top-level we may need to use the Field or the
+  // setter Function.  The setter function may either be in the
+  // library or in the field's owner class, depending.
+  const Field& field =
+      Field::Handle(library.LookupFieldAllowPrivate(setter_name));
+
+  if (field.IsNull()) {
+    const String& internal_setter_name =
+        String::Handle(Field::SetterName(setter_name));
+    const Function& setter = Function::Handle(
+        library.LookupFunctionAllowPrivate(internal_setter_name));
+
+    if (setter.IsNull()) {
+      const String& message = String::Handle(
+        String::NewFormatted("%s: did not find top-level variable '%s'.",
+                             "LibraryMirror_invokeSetter",
+                             setter_name.ToCString()));
+      ThrowMirroredCompilationError(message);
+      UNREACHABLE();
+    }
+
+    // Invoke the setter and return the result.
+    const int kNumArgs = 1;
+    const Array& args = Array::Handle(Array::New(kNumArgs));
+    args.SetAt(0, value);
+    const Object& result = Object::Handle(
+        DartEntry::InvokeFunction(setter, args));
+    if (result.IsError()) {
+      ThrowInvokeError(Error::Cast(result));
+      UNREACHABLE();
+    }
+    return result.raw();
+  }
+
+  if (field.is_final()) {
+    const String& message = String::Handle(
+      String::NewFormatted("%s: cannot set final top-level variable '%s'.",
+                           "LibraryMirror_invokeSetter",
+                           setter_name.ToCString()));
+    ThrowMirroredCompilationError(message);
+    UNREACHABLE();
+  }
+
+  field.set_value(value);
+  return value.raw();
+}
+
+
 DEFINE_NATIVE_ENTRY(MethodMirror_name, 1) {
   const MirrorReference& func_ref =
       MirrorReference::CheckedHandle(arguments->NativeArgAt(0));
diff --git a/runtime/lib/mirrors_impl.dart b/runtime/lib/mirrors_impl.dart
index 16e9286..838af66 100644
--- a/runtime/lib/mirrors_impl.dart
+++ b/runtime/lib/mirrors_impl.dart
@@ -73,6 +73,22 @@
 List<InstanceMirror> _metadata(mirror) 
   native 'Mirrors_metadata';
 
+// This will verify the argument types, unwrap them, and ensure we have a fixed
+// array.
+List _unwarpAsyncPositionals(wrappedArgs){
+  List unwrappedArgs = new List(wrappedArgs.length);
+  for(int i = 0; i < wrappedArgs.length; i++){
+    var wrappedArg = wrappedArgs[i];
+    if(_isSimpleValue(wrappedArg)) {
+      unwrappedArgs[i] = wrappedArg;
+    } else if(wrappedArg is InstanceMirror) {
+      unwrappedArgs[i] = wrappedArg._reflectee;
+    } else { 
+      throw "positional argument $i ($arg) was not a simple value or InstanceMirror";
+    }
+  }
+  return unwrappedArgs;
+}
 
 class _LocalMirrorSystemImpl extends MirrorSystem {
   // Change parameter back to "this.libraries" when native code is changed.
@@ -165,7 +181,9 @@
 
 abstract class _LocalObjectMirrorImpl extends _LocalVMObjectMirrorImpl
     implements ObjectMirror {
-  _LocalObjectMirrorImpl(ref) : super(ref) {}
+  _LocalObjectMirrorImpl(this._reflectee, ref) : super(ref) {}
+
+  final _reflectee; // May be a MirrorReference or an ordinary object.
 
   InstanceMirror invoke(Symbol memberName,
                         List positionalArguments,
@@ -174,15 +192,20 @@
       throw new UnimplementedError(
           'named argument support is not implemented');
     }
-    return _invoke(this, _n(memberName), positionalArguments, false); 
+    return reflect(this._invoke(_reflectee,
+                                _n(memberName),
+                                positionalArguments.toList(growable:false))); 
   }
 
-  InstanceMirror getField(Symbol fieldName) {
-    return _getField(this, _n(fieldName)); 
+  InstanceMirror getField(Symbol memberName) {
+    return reflect(this._invokeGetter(_reflectee,
+                                      _n(memberName))); 
   }
 
-  InstanceMirror setField(Symbol fieldName, Object arg) {
-    return _setField(this, _n(fieldName), arg, false); 
+  InstanceMirror setField(Symbol memberName, Object value) {
+    return reflect(this._invokeSetter(_reflectee,
+                                      _n(memberName),
+                                      value)); 
   }
 
   Future<InstanceMirror> invokeAsync(Symbol memberName,
@@ -192,35 +215,44 @@
       throw new UnimplementedError(
           'named argument support is not implemented');
     }
-    // Walk the arguments and make sure they are legal.
-    for (int i = 0; i < positionalArguments.length; i++) {
-      var arg = positionalArguments[i];
-      _validateArgument(i, arg);
-    }
+
     try {
-      return new Future<InstanceMirror>.value(
-          _invoke(this, _n(memberName), positionalArguments, true));
-    } catch (exception, s) {
-      return new Future<InstanceMirror>.error(exception, s);
+      var result = this._invoke(_reflectee,
+                                _n(memberName),
+                                _unwarpAsyncPositionals(positionalArguments));
+      return new Future.value(reflect(result)); 
+    } on MirroredError catch(e) {
+      return new Future.error(e);
     }
   }
 
-  Future<InstanceMirror> getFieldAsync(Symbol fieldName) {
-    try {
-      return new Future<InstanceMirror>.value(_getField(this, _n(fieldName)));
-    } catch (exception, s) {
-      return new Future<InstanceMirror>.error(exception, s);
+  Future<InstanceMirror> getFieldAsync(Symbol memberName) {
+   try {
+      var result = this._invokeGetter(_reflectee,
+                                      _n(memberName));
+      return new Future.value(reflect(result)); 
+    } on MirroredError catch(e) {
+      return new Future.error(e);
     }
   }
 
-  Future<InstanceMirror> setFieldAsync(Symbol fieldName, Object arg) {
-    _validateArgument(0, arg);
-
+  Future<InstanceMirror> setFieldAsync(Symbol memberName, Object value) {
     try {
-      return new Future<InstanceMirror>.value(
-          _setField(this, _n(fieldName), arg, true));
-    } catch (exception, s) {
-      return new Future<InstanceMirror>.error(exception, s);
+      var unwrappedValue;
+      if(_isSimpleValue(value)) {
+        unwrappedValue = value;
+      } else if(wrappedArg is InstanceMirror) {
+        unwrappedValue = value._reflectee;
+      } else { 
+        throw "setter argument ($value) must be a simple value or InstanceMirror";
+      }
+
+      var result = this._invokeSetter(_reflectee,
+                                      _n(memberName),
+                                      unwrappedValue);
+      return new Future.value(reflect(result)); 
+    } on MirroredError catch(e) {
+      return new Future.error(e);
     }
   }
 
@@ -236,15 +268,6 @@
             'positional argument $i ($arg) was not a simple value');
       }
   }
-
-  static _invoke(ref, memberName, positionalArguments, async)
-      native 'LocalObjectMirrorImpl_invoke';
-
-  static _getField(ref, fieldName) // same for sync and async versions
-      native 'LocalObjectMirrorImpl_getField';
-
-  static _setField(ref, fieldName, value, async)
-      native 'LocalObjectMirrorImpl_setField';
 }
 
 class _LocalInstanceMirrorImpl extends _LocalObjectMirrorImpl
@@ -254,7 +277,7 @@
 
   _LocalInstanceMirrorImpl(ref,
                            this._type,
-                           this._reflectee) : super(ref) {}
+                           reflectee) : super(reflectee, ref) {}
 
   var _type;
   ClassMirror get type {
@@ -267,7 +290,6 @@
   // LocalInstanceMirrors always reflect local instances
   bool hasReflectee = true;
 
-  var _reflectee;
   get reflectee => _reflectee;
 
   delegate(Invocation invocation) {
@@ -276,16 +298,25 @@
       // system to access a private field in a different library.  For
       // some reason, that works.  On the other hand, calling a
       // private method does not work.
+      
       _LocalInstanceMirrorImpl mirror =
           _Mirrors.makeLocalInstanceMirror(invocation);
       _invokeOnClosure =
-          _LocalObjectMirrorImpl._getField(mirror.type, '_invokeOnClosure')
-          .reflectee;
+          reflectClass(invocation.runtimeType).getField(const Symbol('_invokeOnClosure')).reflectee;
     }
     return _invokeOnClosure(reflectee, invocation);
   }
 
   String toString() => 'InstanceMirror on ${Error.safeToString(_reflectee)}';
+
+  _invoke(reflectee, functionName, positionalArguments)
+      native 'InstanceMirror_invoke';
+
+  _invokeGetter(reflectee, getterName)
+      native 'InstanceMirror_invokeGetter';
+
+  _invokeSetter(reflectee, setterName, value)
+      native 'InstanceMirror_invokeSetter';
 }
 
 class _LocalClosureMirrorImpl extends _LocalInstanceMirrorImpl
@@ -308,35 +339,37 @@
       throw new UnimplementedError(
           'named argument support is not implemented');
     }
-    return _apply(this, positionalArguments, false);
+    // It is tempting to implement this in terms of Function.apply, but then
+    // lazy compilation errors would be fatal.
+    return reflect(_apply(_reflectee,
+                          positionalArguments.toList(growable:false)));
   }
 
-  Future<InstanceMirror> applyAsync(List<Object> positionalArguments,
-                                    [Map<Symbol, Object> namedArguments]) {
+  Future<InstanceMirror> applyAsync(List positionalArguments,
+                                    [Map<Symbol, dynamic> namedArguments]) {
     if (namedArguments != null) {
       throw new UnimplementedError(
           'named argument support is not implemented');
     }
-    // Walk the arguments and make sure they are legal.
-    for (int i = 0; i < positionalArguments.length; i++) {
-      var arg = positionalArguments[i];
-      _LocalObjectMirrorImpl._validateArgument(i, arg);
-    }
+
     try {
-      return new Future<InstanceMirror>.value(
-          _apply(this, positionalArguments, true));
-    } catch (exception) {
-      return new Future<InstanceMirror>.error(exception);
+      var result = _apply(_reflectee,
+                          _unwarpAsyncPositionals(positionalArguments));
+      return new Future.value(reflect(result)); 
+    } on MirroredError catch(e) {
+      return new Future.error(e);
     }
   }
 
+
+
   Future<InstanceMirror> findInContext(Symbol name) {
     throw new UnimplementedError(
         'ClosureMirror.findInContext() is not implemented');
   }
 
-  static _apply(ref, positionalArguments, async)
-      native 'LocalClosureMirrorImpl_apply';
+  static _apply(reflectee, positionalArguments)
+      native 'ClosureMirror_apply';
 
   String toString() => "ClosureMirror on '${Error.safeToString(_reflectee)}'";
 }
@@ -370,7 +403,7 @@
 
 class _LocalClassMirrorImpl extends _LocalObjectMirrorImpl
     implements ClassMirror {
-  _LocalClassMirrorImpl(this._reflectee,
+  _LocalClassMirrorImpl(reflectee,
                         ref,
                         String simpleName,
                         this.isClass,
@@ -385,16 +418,14 @@
         this.members = _convertStringToSymbolMap(members),
         this.constructors = _convertStringToSymbolMap(constructors),
         this.typeVariables = _convertStringToSymbolMap(typeVariables),
-        super(ref);
-
-  final _MirrorReference _reflectee;
+        super(reflectee, ref);
 
   Symbol _simpleName;
   Symbol get simpleName {
     // dynamic, void and the function types have their names set eagerly in the
     // constructor.
     if(_simpleName == null) {
-      _simpleName = _s(_ClassMirror_name(_reflectee));
+      _simpleName = _s(_name(_reflectee));
     }
     return _simpleName;
   }
@@ -528,10 +559,9 @@
       throw new UnimplementedError(
           'named argument support is not implemented');
     }
-    return _invokeConstructor(this,
-                              _n(constructorName),
-                              positionalArguments,
-                              false);
+    return reflect(_invokeConstructor(_reflectee,
+                                      _n(constructorName),
+                                      positionalArguments.toList(growable:false)));
   }
 
   Future<InstanceMirror> newInstanceAsync(Symbol constructorName,
@@ -541,19 +571,14 @@
       throw new UnimplementedError(
           'named argument support is not implemented');
     }
-    // Walk the arguments and make sure they are legal.
-    for (int i = 0; i < positionalArguments.length; i++) {
-      var arg = positionalArguments[i];
-      _LocalObjectMirrorImpl._validateArgument(i, arg);
-    }
+
     try {
-      return new Future<InstanceMirror>.value(
-          _invokeConstructor(this,
-                             _n(constructorName),
-                             positionalArguments,
-                             true));
-    } catch (exception) {
-      return new Future<InstanceMirror>.error(exception);
+      var result = _invokeConstructor(_reflectee,
+                                      _n(constructorName),
+                                      _unwarpAsyncPositionals(positionalArguments));
+      return new Future.value(reflect(result)); 
+    } on MirroredError catch(e) {
+      return new Future.error(e);
     }
   }
 
@@ -561,11 +586,21 @@
   // reflect() and then make them into a Dart list
   List<InstanceMirror> get metadata => _metadata(this).map(reflect).toList();
 
-  static _invokeConstructor(ref, constructorName, positionalArguments, async)
-      native 'LocalClassMirrorImpl_invokeConstructor';
 
-  static String _ClassMirror_name(reflectee)
+  static _name(reflectee)
       native "ClassMirror_name";
+
+  _invoke(reflectee, memberName, positionalArguments)
+      native 'ClassMirror_invoke';
+
+  _invokeGetter(reflectee, getterName)
+      native 'ClassMirror_invokeGetter';
+
+  _invokeSetter(reflectee, setterName, value)
+      native 'ClassMirror_invokeSetter';
+
+  static _invokeConstructor(reflectee, constructorName, positionalArguments)
+      native 'ClassMirror_invokeConstructor';
 }
 
 class _LazyFunctionTypeMirror {
@@ -733,14 +768,15 @@
 
 class _LocalLibraryMirrorImpl extends _LocalObjectMirrorImpl
     implements LibraryMirror {
-  _LocalLibraryMirrorImpl(ref,
+  _LocalLibraryMirrorImpl(reflectee,
+                          ref,
                           String simpleName,
                           String url,
                           Map<String, Mirror> members)
       : this.simpleName = _s(simpleName),
         this.members = _convertStringToSymbolMap(members),
         this.uri = Uri.parse(url),
-        super(ref);
+        super(reflectee, ref);
 
   final Symbol simpleName;
 
@@ -815,6 +851,15 @@
   List<InstanceMirror> get metadata => _metadata(this).map(reflect).toList();
 
   String toString() => "LibraryMirror on '${_n(simpleName)}'";
+
+  _invoke(reflectee, memberName, positionalArguments)
+      native 'LibraryMirror_invoke';
+
+  _invokeGetter(reflectee, getterName)
+      native 'LibraryMirror_invokeGetter';
+
+  _invokeSetter(reflectee, setterName, value)
+      native 'LibraryMirror_invokeSetter';
 }
 
 class _LocalMethodMirrorImpl extends _LocalMirrorImpl
diff --git a/runtime/vm/assembler_arm.cc b/runtime/vm/assembler_arm.cc
index aa3a33d..8faef96 100644
--- a/runtime/vm/assembler_arm.cc
+++ b/runtime/vm/assembler_arm.cc
@@ -1219,8 +1219,35 @@
 }
 
 
-void Assembler::EmitSIMDqqq(int32_t opcode, int sz,
+static inline int ShiftOfOperandSize(OperandSize size) {
+  switch (size) {
+    case kByte:
+    case kUnsignedByte:
+      return 0;
+    case kHalfword:
+    case kUnsignedHalfword:
+      return 1;
+    case kWord:
+    case kUnsignedWord:
+      return 2;
+    case kWordPair:
+      return 3;
+    case kSWord:
+    case kDWord:
+      return 0;
+    default:
+      UNREACHABLE();
+      break;
+  }
+
+  UNREACHABLE();
+  return -1;
+}
+
+
+void Assembler::EmitSIMDqqq(int32_t opcode, OperandSize size,
                             QRegister qd, QRegister qn, QRegister qm) {
+  int sz = ShiftOfOperandSize(size);
   int32_t encoding =
       (static_cast<int32_t>(kSpecialCondition) << kConditionShift) |
       B25 | B6 |
@@ -1235,14 +1262,59 @@
 }
 
 
-void Assembler::vaddqi(int sz, QRegister qd, QRegister qn, QRegister qm) {
-  ASSERT((sz >= 0) && (sz <= 3));
+void Assembler::EmitSIMDddd(int32_t opcode, OperandSize size,
+                            DRegister dd, DRegister dn, DRegister dm) {
+  int sz = ShiftOfOperandSize(size);
+  int32_t encoding =
+      (static_cast<int32_t>(kSpecialCondition) << kConditionShift) |
+      B25 |
+      opcode | ((sz & 0x3) * B20) |
+      ((static_cast<int32_t>(dd) >> 4)*B22) |
+      ((static_cast<int32_t>(dn) & 0xf)*B16) |
+      ((static_cast<int32_t>(dd) & 0xf)*B12) |
+      ((static_cast<int32_t>(dn) >> 4)*B7) |
+      ((static_cast<int32_t>(dm) >> 4)*B5) |
+      (static_cast<int32_t>(dm) & 0xf);
+  Emit(encoding);
+}
+
+
+void Assembler::vaddqi(OperandSize sz,
+                       QRegister qd, QRegister qn, QRegister qm) {
   EmitSIMDqqq(B11, sz, qd, qn, qm);
 }
 
 
 void Assembler::vaddqs(QRegister qd, QRegister qn, QRegister qm) {
-  EmitSIMDqqq(B11 | B10 | B8, 0, qd, qn, qm);
+  EmitSIMDqqq(B11 | B10 | B8, kSWord, qd, qn, qm);
+}
+
+
+void Assembler::vsubqi(OperandSize sz,
+                       QRegister qd, QRegister qn, QRegister qm) {
+  EmitSIMDqqq(B24 | B11, sz, qd, qn, qm);
+}
+
+
+void Assembler::vsubqs(QRegister qd, QRegister qn, QRegister qm) {
+  EmitSIMDqqq(B21 | B11 | B10 | B8, kSWord, qd, qn, qm);
+}
+
+
+void Assembler::vmulqi(OperandSize sz,
+                       QRegister qd, QRegister qn, QRegister qm) {
+  EmitSIMDqqq(B11 | B8 | B4, sz, qd, qn, qm);
+}
+
+
+void Assembler::vmulqs(QRegister qd, QRegister qn, QRegister qm) {
+  EmitSIMDqqq(B24 | B11 | B10 | B8 | B4, kSWord, qd, qn, qm);
+}
+
+
+void Assembler::vtbl(DRegister dd, DRegister dn, int len, DRegister dm) {
+  ASSERT((len >= 1) && (len <= 4));
+  EmitSIMDddd(B24 | B23 | B11 | ((len - 1) * B8), kWordPair, dd, dn, dm);
 }
 
 
@@ -1315,7 +1387,7 @@
                                        Condition cond) {
   ASSERT(rd != PP);
   int32_t offset_mask = 0;
-  if (Address::CanHoldLoadOffset(kLoadWord, offset, &offset_mask)) {
+  if (Address::CanHoldLoadOffset(kWord, offset, &offset_mask)) {
     ldr(rd, Address(PP, offset), cond);
   } else {
     int32_t offset_hi = offset & ~offset_mask;  // signed
@@ -1341,7 +1413,7 @@
   const intptr_t object_pool_pc_dist =
      Instructions::HeaderSize() - Instructions::object_pool_offset() +
      CodeSize() + Instr::kPCReadOffset;
-  LoadFromOffset(kLoadWord, PP, PC, -object_pool_pc_dist);
+  LoadFromOffset(kWord, PP, PC, -object_pool_pc_dist);
 }
 
 
@@ -1477,7 +1549,7 @@
   ldr(result, FieldAddress(CTX, Context::isolate_offset()));
   const intptr_t table_offset_in_isolate =
       Isolate::class_table_offset() + ClassTable::table_offset();
-  LoadFromOffset(kLoadWord, result, result, table_offset_in_isolate);
+  LoadFromOffset(kWord, result, result, table_offset_in_isolate);
   ldr(result, Address(result, class_id, LSL, 2));
 }
 
@@ -1489,7 +1561,7 @@
   ldr(result, FieldAddress(CTX, Context::isolate_offset()));
   const intptr_t table_offset_in_isolate =
       Isolate::class_table_offset() + ClassTable::table_offset();
-  LoadFromOffset(kLoadWord, result, result, table_offset_in_isolate);
+  LoadFromOffset(kWord, result, result, table_offset_in_isolate);
   ldr(result, Address(result, scratch, LSL, 2));
 }
 
@@ -1516,24 +1588,24 @@
 }
 
 
-bool Address::CanHoldLoadOffset(LoadOperandType type,
+bool Address::CanHoldLoadOffset(OperandSize type,
                                 int32_t offset,
                                 int32_t* offset_mask) {
   switch (type) {
-    case kLoadSignedByte:
-    case kLoadSignedHalfword:
-    case kLoadUnsignedHalfword:
-    case kLoadWordPair: {
+    case kByte:
+    case kHalfword:
+    case kUnsignedHalfword:
+    case kWordPair: {
       *offset_mask = 0xff;
       return Utils::IsAbsoluteUint(8, offset);  // Addressing mode 3.
     }
-    case kLoadUnsignedByte:
-    case kLoadWord: {
+    case kUnsignedByte:
+    case kWord: {
       *offset_mask = 0xfff;
       return Utils::IsAbsoluteUint(12, offset);  // Addressing mode 2.
     }
-    case kLoadSWord:
-    case kLoadDWord: {
+    case kSWord:
+    case kDWord: {
       *offset_mask = 0x3fc;  // Multiple of 4.
       // VFP addressing mode.
       return (Utils::IsAbsoluteUint(10, offset) && Utils::IsAligned(offset, 4));
@@ -1546,22 +1618,22 @@
 }
 
 
-bool Address::CanHoldStoreOffset(StoreOperandType type,
+bool Address::CanHoldStoreOffset(OperandSize type,
                                  int32_t offset,
                                  int32_t* offset_mask) {
   switch (type) {
-    case kStoreHalfword:
-    case kStoreWordPair: {
+    case kHalfword:
+    case kWordPair: {
       *offset_mask = 0xff;
       return Utils::IsAbsoluteUint(8, offset);  // Addressing mode 3.
     }
-    case kStoreByte:
-    case kStoreWord: {
+    case kByte:
+    case kWord: {
       *offset_mask = 0xfff;
       return Utils::IsAbsoluteUint(12, offset);  // Addressing mode 2.
     }
-    case kStoreSWord:
-    case kStoreDWord: {
+    case kSWord:
+    case kDWord: {
       *offset_mask = 0x3fc;  // Multiple of 4.
       // VFP addressing mode.
       return (Utils::IsAbsoluteUint(10, offset) && Utils::IsAligned(offset, 4));
@@ -1702,7 +1774,7 @@
 void Assembler::BranchLinkOffset(Register base, int32_t offset) {
   ASSERT(base != PC);
   ASSERT(base != IP);
-  LoadFromOffset(kLoadWord, IP, base, offset);
+  LoadFromOffset(kWord, IP, base, offset);
   blx(IP);  // Use blx instruction so that the return branch prediction works.
 }
 
@@ -1749,7 +1821,7 @@
 }
 
 
-void Assembler::LoadFromOffset(LoadOperandType type,
+void Assembler::LoadFromOffset(OperandSize type,
                                Register reg,
                                Register base,
                                int32_t offset,
@@ -1762,22 +1834,22 @@
     offset = offset & offset_mask;
   }
   switch (type) {
-    case kLoadSignedByte:
+    case kByte:
       ldrsb(reg, Address(base, offset), cond);
       break;
-    case kLoadUnsignedByte:
+    case kUnsignedByte:
       ldrb(reg, Address(base, offset), cond);
       break;
-    case kLoadSignedHalfword:
+    case kHalfword:
       ldrsh(reg, Address(base, offset), cond);
       break;
-    case kLoadUnsignedHalfword:
+    case kUnsignedHalfword:
       ldrh(reg, Address(base, offset), cond);
       break;
-    case kLoadWord:
+    case kWord:
       ldr(reg, Address(base, offset), cond);
       break;
-    case kLoadWordPair:
+    case kWordPair:
       ldrd(reg, Address(base, offset), cond);
       break;
     default:
@@ -1786,7 +1858,7 @@
 }
 
 
-void Assembler::StoreToOffset(StoreOperandType type,
+void Assembler::StoreToOffset(OperandSize type,
                               Register reg,
                               Register base,
                               int32_t offset,
@@ -1800,16 +1872,16 @@
     offset = offset & offset_mask;
   }
   switch (type) {
-    case kStoreByte:
+    case kByte:
       strb(reg, Address(base, offset), cond);
       break;
-    case kStoreHalfword:
+    case kHalfword:
       strh(reg, Address(base, offset), cond);
       break;
-    case kStoreWord:
+    case kWord:
       str(reg, Address(base, offset), cond);
       break;
-    case kStoreWordPair:
+    case kWordPair:
       strd(reg, Address(base, offset), cond);
       break;
     default:
@@ -1823,7 +1895,7 @@
                                 int32_t offset,
                                 Condition cond) {
   int32_t offset_mask = 0;
-  if (!Address::CanHoldLoadOffset(kLoadSWord, offset, &offset_mask)) {
+  if (!Address::CanHoldLoadOffset(kSWord, offset, &offset_mask)) {
     ASSERT(base != IP);
     AddImmediate(IP, base, offset & ~offset_mask, cond);
     base = IP;
@@ -1838,7 +1910,7 @@
                                int32_t offset,
                                Condition cond) {
   int32_t offset_mask = 0;
-  if (!Address::CanHoldStoreOffset(kStoreSWord, offset, &offset_mask)) {
+  if (!Address::CanHoldStoreOffset(kSWord, offset, &offset_mask)) {
     ASSERT(base != IP);
     AddImmediate(IP, base, offset & ~offset_mask, cond);
     base = IP;
@@ -1853,7 +1925,7 @@
                                 int32_t offset,
                                 Condition cond) {
   int32_t offset_mask = 0;
-  if (!Address::CanHoldLoadOffset(kLoadDWord, offset, &offset_mask)) {
+  if (!Address::CanHoldLoadOffset(kDWord, offset, &offset_mask)) {
     ASSERT(base != IP);
     AddImmediate(IP, base, offset & ~offset_mask, cond);
     base = IP;
@@ -1868,7 +1940,7 @@
                                int32_t offset,
                                Condition cond) {
   int32_t offset_mask = 0;
-  if (!Address::CanHoldStoreOffset(kStoreDWord, offset, &offset_mask)) {
+  if (!Address::CanHoldStoreOffset(kDWord, offset, &offset_mask)) {
     ASSERT(base != IP);
     AddImmediate(IP, base, offset & ~offset_mask, cond);
     base = IP;
diff --git a/runtime/vm/assembler_arm.h b/runtime/vm/assembler_arm.h
index 55168ff..e07eab0 100644
--- a/runtime/vm/assembler_arm.h
+++ b/runtime/vm/assembler_arm.h
@@ -176,25 +176,16 @@
 };
 
 
-enum LoadOperandType {
-  kLoadSignedByte,
-  kLoadUnsignedByte,
-  kLoadSignedHalfword,
-  kLoadUnsignedHalfword,
-  kLoadWord,
-  kLoadWordPair,
-  kLoadSWord,
-  kLoadDWord
-};
-
-
-enum StoreOperandType {
-  kStoreByte,
-  kStoreHalfword,
-  kStoreWord,
-  kStoreWordPair,
-  kStoreSWord,
-  kStoreDWord
+enum OperandSize {
+  kByte,
+  kUnsignedByte,
+  kHalfword,
+  kUnsignedHalfword,
+  kWord,
+  kUnsignedWord,
+  kWordPair,
+  kSWord,
+  kDWord,
 };
 
 
@@ -268,10 +259,10 @@
     return (encoding_ == other.encoding_) && (kind_ == other.kind_);
   }
 
-  static bool CanHoldLoadOffset(LoadOperandType type,
+  static bool CanHoldLoadOffset(OperandSize type,
                                 int32_t offset,
                                 int32_t* offset_mask);
-  static bool CanHoldStoreOffset(StoreOperandType type,
+  static bool CanHoldStoreOffset(OperandSize type,
                                  int32_t offset,
                                  int32_t* offset_mask);
 
@@ -479,12 +470,16 @@
 
   void vadds(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL);
   void vaddd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL);
-  void vaddqi(int sz, QRegister qd, QRegister qn, QRegister qm);
+  void vaddqi(OperandSize sz, QRegister qd, QRegister qn, QRegister qm);
   void vaddqs(QRegister qd, QRegister qn, QRegister qm);
   void vsubs(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL);
   void vsubd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL);
+  void vsubqi(OperandSize sz, QRegister qd, QRegister qn, QRegister qm);
+  void vsubqs(QRegister qd, QRegister qn, QRegister qm);
   void vmuls(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL);
   void vmuld(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL);
+  void vmulqi(OperandSize sz, QRegister qd, QRegister qn, QRegister qm);
+  void vmulqs(QRegister qd, QRegister qn, QRegister qm);
   void vmlas(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL);
   void vmlad(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL);
   void vmlss(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL);
@@ -516,6 +511,10 @@
   void vcmpdz(DRegister dd, Condition cond = AL);
   void vmstat(Condition cond = AL);  // VMRS APSR_nzcv, FPSCR
 
+  // Each byte of dm is an index into the table of bytes formed by concatenating
+  // a list of 'length' registers starting with dn. The result is placed in dd.
+  void vtbl(DRegister dd, DRegister dn, int length, DRegister dm);
+
   // Branch instructions.
   void b(Label* label, Condition cond = AL);
   void bl(Label* label, Condition cond = AL);
@@ -595,12 +594,12 @@
   void CompareClassId(Register object, intptr_t class_id, Register scratch);
 
   void LoadWordFromPoolOffset(Register rd, int32_t offset, Condition cond = AL);
-  void LoadFromOffset(LoadOperandType type,
+  void LoadFromOffset(OperandSize type,
                       Register reg,
                       Register base,
                       int32_t offset,
                       Condition cond = AL);
-  void StoreToOffset(StoreOperandType type,
+  void StoreToOffset(OperandSize type,
                      Register reg,
                      Register base,
                      int32_t offset,
@@ -809,9 +808,12 @@
                  DRegister dd,
                  SRegister sm);
 
-  void EmitSIMDqqq(int32_t opcode, int sz,
+  void EmitSIMDqqq(int32_t opcode, OperandSize sz,
                    QRegister qd, QRegister qn, QRegister qm);
 
+  void EmitSIMDddd(int32_t opcode, OperandSize sz,
+                   DRegister dd, DRegister dn, DRegister dm);
+
   void EmitBranch(Condition cond, Label* label, bool link);
   static int32_t EncodeBranchOffset(int32_t offset, int32_t inst);
   static int DecodeBranchOffset(int32_t inst);
diff --git a/runtime/vm/assembler_arm_test.cc b/runtime/vm/assembler_arm_test.cc
index ff50865..d1d5b03 100644
--- a/runtime/vm/assembler_arm_test.cc
+++ b/runtime/vm/assembler_arm_test.cc
@@ -1600,15 +1600,22 @@
   if (CPUFeatures::neon_supported()) {
     __ mov(R0, ShifterOperand(1));
     __ vmovsr(S0, R0);
+    __ mov(R0, ShifterOperand(2));
     __ vmovsr(S1, R0);
+    __ mov(R0, ShifterOperand(3));
     __ vmovsr(S2, R0);
+    __ mov(R0, ShifterOperand(4));
     __ vmovsr(S3, R0);
+    __ mov(R0, ShifterOperand(5));
     __ vmovsr(S4, R0);
+    __ mov(R0, ShifterOperand(6));
     __ vmovsr(S5, R0);
+    __ mov(R0, ShifterOperand(7));
     __ vmovsr(S6, R0);
+    __ mov(R0, ShifterOperand(8));
     __ vmovsr(S7, R0);
 
-    __ vaddqi(0, Q2, Q0, Q1);
+    __ vaddqi(kByte, Q2, Q0, Q1);
 
     __ vmovrs(R0, S8);
     __ vmovrs(R1, S9);
@@ -1620,7 +1627,7 @@
     __ add(R0, R0, ShifterOperand(R3));
     __ bx(LR);
   } else {
-    __ LoadImmediate(R0, 8);
+    __ LoadImmediate(R0, 36);
     __ bx(LR);
   }
 }
@@ -1629,7 +1636,7 @@
 ASSEMBLER_TEST_RUN(Vaddqi8, test) {
   EXPECT(test != NULL);
   typedef int (*Tst)();
-  EXPECT_EQ(8, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  EXPECT_EQ(36, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
 }
 
 
@@ -1637,15 +1644,22 @@
   if (CPUFeatures::neon_supported()) {
     __ mov(R0, ShifterOperand(1));
     __ vmovsr(S0, R0);
+    __ mov(R0, ShifterOperand(2));
     __ vmovsr(S1, R0);
+    __ mov(R0, ShifterOperand(3));
     __ vmovsr(S2, R0);
+    __ mov(R0, ShifterOperand(4));
     __ vmovsr(S3, R0);
+    __ mov(R0, ShifterOperand(5));
     __ vmovsr(S4, R0);
+    __ mov(R0, ShifterOperand(6));
     __ vmovsr(S5, R0);
+    __ mov(R0, ShifterOperand(7));
     __ vmovsr(S6, R0);
+    __ mov(R0, ShifterOperand(8));
     __ vmovsr(S7, R0);
 
-    __ vaddqi(1, Q2, Q0, Q1);
+    __ vaddqi(kHalfword, Q2, Q0, Q1);
 
     __ vmovrs(R0, S8);
     __ vmovrs(R1, S9);
@@ -1657,7 +1671,7 @@
     __ add(R0, R0, ShifterOperand(R3));
     __ bx(LR);
   } else {
-    __ LoadImmediate(R0, 8);
+    __ LoadImmediate(R0, 36);
     __ bx(LR);
   }
 }
@@ -1666,7 +1680,7 @@
 ASSEMBLER_TEST_RUN(Vaddqi16, test) {
   EXPECT(test != NULL);
   typedef int (*Tst)();
-  EXPECT_EQ(8, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  EXPECT_EQ(36, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
 }
 
 
@@ -1674,15 +1688,22 @@
   if (CPUFeatures::neon_supported()) {
     __ mov(R0, ShifterOperand(1));
     __ vmovsr(S0, R0);
+    __ mov(R0, ShifterOperand(2));
     __ vmovsr(S1, R0);
+    __ mov(R0, ShifterOperand(3));
     __ vmovsr(S2, R0);
+    __ mov(R0, ShifterOperand(4));
     __ vmovsr(S3, R0);
+    __ mov(R0, ShifterOperand(5));
     __ vmovsr(S4, R0);
+    __ mov(R0, ShifterOperand(6));
     __ vmovsr(S5, R0);
+    __ mov(R0, ShifterOperand(7));
     __ vmovsr(S6, R0);
+    __ mov(R0, ShifterOperand(8));
     __ vmovsr(S7, R0);
 
-    __ vaddqi(2, Q2, Q0, Q1);
+    __ vaddqi(kWord, Q2, Q0, Q1);
 
     __ vmovrs(R0, S8);
     __ vmovrs(R1, S9);
@@ -1694,7 +1715,7 @@
     __ add(R0, R0, ShifterOperand(R3));
     __ bx(LR);
   } else {
-    __ LoadImmediate(R0, 8);
+    __ LoadImmediate(R0, 36);
     __ bx(LR);
   }
 }
@@ -1703,7 +1724,7 @@
 ASSEMBLER_TEST_RUN(Vaddqi32, test) {
   EXPECT(test != NULL);
   typedef int (*Tst)();
-  EXPECT_EQ(8, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  EXPECT_EQ(36, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
 }
 
 
@@ -1711,11 +1732,14 @@
   if (CPUFeatures::neon_supported()) {
     __ mov(R0, ShifterOperand(1));
     __ vmovsr(S0, R0);
+    __ mov(R0, ShifterOperand(2));
     __ vmovsr(S2, R0);
+    __ mov(R0, ShifterOperand(3));
     __ vmovsr(S4, R0);
+    __ mov(R0, ShifterOperand(4));
     __ vmovsr(S6, R0);
 
-    __ vaddqi(3, Q2, Q0, Q1);
+    __ vaddqi(kWordPair, Q2, Q0, Q1);
 
     __ vmovrs(R0, S8);
     __ vmovrs(R2, S10);
@@ -1723,7 +1747,7 @@
     __ add(R0, R0, ShifterOperand(R2));
     __ bx(LR);
   } else {
-    __ LoadImmediate(R0, 4);
+    __ LoadImmediate(R0, 10);
     __ bx(LR);
   }
 }
@@ -1732,20 +1756,316 @@
 ASSEMBLER_TEST_RUN(Vaddqi64, test) {
   EXPECT(test != NULL);
   typedef int (*Tst)();
-  EXPECT_EQ(4, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  EXPECT_EQ(10, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Vsubqi8, assembler) {
+  if (CPUFeatures::neon_supported()) {
+    __ mov(R0, ShifterOperand(1));
+    __ vmovsr(S0, R0);
+    __ mov(R0, ShifterOperand(2));
+    __ vmovsr(S1, R0);
+    __ mov(R0, ShifterOperand(3));
+    __ vmovsr(S2, R0);
+    __ mov(R0, ShifterOperand(4));
+    __ vmovsr(S3, R0);
+    __ mov(R0, ShifterOperand(2));
+    __ vmovsr(S4, R0);
+    __ mov(R0, ShifterOperand(4));
+    __ vmovsr(S5, R0);
+    __ mov(R0, ShifterOperand(6));
+    __ vmovsr(S6, R0);
+    __ mov(R0, ShifterOperand(8));
+    __ vmovsr(S7, R0);
+
+    __ vsubqi(kByte, Q2, Q1, Q0);
+
+    __ vmovrs(R0, S8);
+    __ vmovrs(R1, S9);
+    __ vmovrs(R2, S10);
+    __ vmovrs(R3, S11);
+
+    __ add(R0, R0, ShifterOperand(R1));
+    __ add(R0, R0, ShifterOperand(R2));
+    __ add(R0, R0, ShifterOperand(R3));
+    __ bx(LR);
+  } else {
+    __ LoadImmediate(R0, 10);
+    __ bx(LR);
+  }
+}
+
+
+ASSEMBLER_TEST_RUN(Vsubqi8, test) {
+  EXPECT(test != NULL);
+  typedef int (*Tst)();
+  EXPECT_EQ(10, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Vsubqi16, assembler) {
+  if (CPUFeatures::neon_supported()) {
+    __ mov(R0, ShifterOperand(1));
+    __ vmovsr(S0, R0);
+    __ mov(R0, ShifterOperand(2));
+    __ vmovsr(S1, R0);
+    __ mov(R0, ShifterOperand(3));
+    __ vmovsr(S2, R0);
+    __ mov(R0, ShifterOperand(4));
+    __ vmovsr(S3, R0);
+    __ mov(R0, ShifterOperand(2));
+    __ vmovsr(S4, R0);
+    __ mov(R0, ShifterOperand(4));
+    __ vmovsr(S5, R0);
+    __ mov(R0, ShifterOperand(6));
+    __ vmovsr(S6, R0);
+    __ mov(R0, ShifterOperand(8));
+    __ vmovsr(S7, R0);
+
+    __ vsubqi(kHalfword, Q2, Q1, Q0);
+
+    __ vmovrs(R0, S8);
+    __ vmovrs(R1, S9);
+    __ vmovrs(R2, S10);
+    __ vmovrs(R3, S11);
+
+    __ add(R0, R0, ShifterOperand(R1));
+    __ add(R0, R0, ShifterOperand(R2));
+    __ add(R0, R0, ShifterOperand(R3));
+    __ bx(LR);
+  } else {
+    __ LoadImmediate(R0, 10);
+    __ bx(LR);
+  }
+}
+
+
+ASSEMBLER_TEST_RUN(Vsubqi16, test) {
+  EXPECT(test != NULL);
+  typedef int (*Tst)();
+  EXPECT_EQ(10, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Vsubqi32, assembler) {
+  if (CPUFeatures::neon_supported()) {
+    __ mov(R0, ShifterOperand(1));
+    __ vmovsr(S0, R0);
+    __ mov(R0, ShifterOperand(2));
+    __ vmovsr(S1, R0);
+    __ mov(R0, ShifterOperand(3));
+    __ vmovsr(S2, R0);
+    __ mov(R0, ShifterOperand(4));
+    __ vmovsr(S3, R0);
+    __ mov(R0, ShifterOperand(2));
+    __ vmovsr(S4, R0);
+    __ mov(R0, ShifterOperand(4));
+    __ vmovsr(S5, R0);
+    __ mov(R0, ShifterOperand(6));
+    __ vmovsr(S6, R0);
+    __ mov(R0, ShifterOperand(8));
+    __ vmovsr(S7, R0);
+
+    __ vsubqi(kWord, Q2, Q1, Q0);
+
+    __ vmovrs(R0, S8);
+    __ vmovrs(R1, S9);
+    __ vmovrs(R2, S10);
+    __ vmovrs(R3, S11);
+
+    __ add(R0, R0, ShifterOperand(R1));
+    __ add(R0, R0, ShifterOperand(R2));
+    __ add(R0, R0, ShifterOperand(R3));
+    __ bx(LR);
+  } else {
+    __ LoadImmediate(R0, 10);
+    __ bx(LR);
+  }
+}
+
+
+ASSEMBLER_TEST_RUN(Vsubqi32, test) {
+  EXPECT(test != NULL);
+  typedef int (*Tst)();
+  EXPECT_EQ(10, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Vsubqi64, assembler) {
+  if (CPUFeatures::neon_supported()) {
+    __ mov(R0, ShifterOperand(1));
+    __ vmovsr(S0, R0);
+    __ mov(R0, ShifterOperand(2));
+    __ vmovsr(S2, R0);
+    __ mov(R0, ShifterOperand(2));
+    __ vmovsr(S4, R0);
+    __ mov(R0, ShifterOperand(4));
+    __ vmovsr(S6, R0);
+
+    __ vsubqi(kWordPair, Q2, Q1, Q0);
+
+    __ vmovrs(R0, S8);
+    __ vmovrs(R2, S10);
+
+    __ add(R0, R0, ShifterOperand(R2));
+    __ bx(LR);
+  } else {
+    __ LoadImmediate(R0, 3);
+    __ bx(LR);
+  }
+}
+
+
+ASSEMBLER_TEST_RUN(Vsubqi64, test) {
+  EXPECT(test != NULL);
+  typedef int (*Tst)();
+  EXPECT_EQ(3, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Vmulqi8, assembler) {
+  if (CPUFeatures::neon_supported()) {
+    __ mov(R0, ShifterOperand(1));
+    __ vmovsr(S0, R0);
+    __ mov(R0, ShifterOperand(2));
+    __ vmovsr(S1, R0);
+    __ mov(R0, ShifterOperand(3));
+    __ vmovsr(S2, R0);
+    __ mov(R0, ShifterOperand(4));
+    __ vmovsr(S3, R0);
+    __ mov(R0, ShifterOperand(5));
+    __ vmovsr(S4, R0);
+    __ mov(R0, ShifterOperand(6));
+    __ vmovsr(S5, R0);
+    __ mov(R0, ShifterOperand(7));
+    __ vmovsr(S6, R0);
+    __ mov(R0, ShifterOperand(8));
+    __ vmovsr(S7, R0);
+
+    __ vmulqi(kByte, Q2, Q1, Q0);
+
+    __ vmovrs(R0, S8);
+    __ vmovrs(R1, S9);
+    __ vmovrs(R2, S10);
+    __ vmovrs(R3, S11);
+
+    __ add(R0, R0, ShifterOperand(R1));
+    __ add(R0, R0, ShifterOperand(R2));
+    __ add(R0, R0, ShifterOperand(R3));
+    __ bx(LR);
+  } else {
+    __ LoadImmediate(R0, 70);
+    __ bx(LR);
+  }
+}
+
+
+ASSEMBLER_TEST_RUN(Vmulqi8, test) {
+  EXPECT(test != NULL);
+  typedef int (*Tst)();
+  EXPECT_EQ(70, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Vmulqi16, assembler) {
+  if (CPUFeatures::neon_supported()) {
+    __ mov(R0, ShifterOperand(1));
+    __ vmovsr(S0, R0);
+    __ mov(R0, ShifterOperand(2));
+    __ vmovsr(S1, R0);
+    __ mov(R0, ShifterOperand(3));
+    __ vmovsr(S2, R0);
+    __ mov(R0, ShifterOperand(4));
+    __ vmovsr(S3, R0);
+    __ mov(R0, ShifterOperand(5));
+    __ vmovsr(S4, R0);
+    __ mov(R0, ShifterOperand(6));
+    __ vmovsr(S5, R0);
+    __ mov(R0, ShifterOperand(7));
+    __ vmovsr(S6, R0);
+    __ mov(R0, ShifterOperand(8));
+    __ vmovsr(S7, R0);
+
+    __ vmulqi(kHalfword, Q2, Q1, Q0);
+
+    __ vmovrs(R0, S8);
+    __ vmovrs(R1, S9);
+    __ vmovrs(R2, S10);
+    __ vmovrs(R3, S11);
+
+    __ add(R0, R0, ShifterOperand(R1));
+    __ add(R0, R0, ShifterOperand(R2));
+    __ add(R0, R0, ShifterOperand(R3));
+    __ bx(LR);
+  } else {
+    __ LoadImmediate(R0, 70);
+    __ bx(LR);
+  }
+}
+
+
+ASSEMBLER_TEST_RUN(Vmulqi16, test) {
+  EXPECT(test != NULL);
+  typedef int (*Tst)();
+  EXPECT_EQ(70, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Vmulqi32, assembler) {
+  if (CPUFeatures::neon_supported()) {
+    __ mov(R0, ShifterOperand(1));
+    __ vmovsr(S0, R0);
+    __ mov(R0, ShifterOperand(2));
+    __ vmovsr(S1, R0);
+    __ mov(R0, ShifterOperand(3));
+    __ vmovsr(S2, R0);
+    __ mov(R0, ShifterOperand(4));
+    __ vmovsr(S3, R0);
+    __ mov(R0, ShifterOperand(5));
+    __ vmovsr(S4, R0);
+    __ mov(R0, ShifterOperand(6));
+    __ vmovsr(S5, R0);
+    __ mov(R0, ShifterOperand(7));
+    __ vmovsr(S6, R0);
+    __ mov(R0, ShifterOperand(8));
+    __ vmovsr(S7, R0);
+
+    __ vmulqi(kWord, Q2, Q1, Q0);
+
+    __ vmovrs(R0, S8);
+    __ vmovrs(R1, S9);
+    __ vmovrs(R2, S10);
+    __ vmovrs(R3, S11);
+
+    __ add(R0, R0, ShifterOperand(R1));
+    __ add(R0, R0, ShifterOperand(R2));
+    __ add(R0, R0, ShifterOperand(R3));
+    __ bx(LR);
+  } else {
+    __ LoadImmediate(R0, 70);
+    __ bx(LR);
+  }
+}
+
+
+ASSEMBLER_TEST_RUN(Vmulqi32, test) {
+  EXPECT(test != NULL);
+  typedef int (*Tst)();
+  EXPECT_EQ(70, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
 }
 
 
 ASSEMBLER_TEST_GENERATE(Vaddqs, assembler) {
   if (CPUFeatures::neon_supported()) {
     __ LoadSImmediate(S0, 1.0);
-    __ vmovs(S1, S0);
-    __ vmovs(S2, S0);
-    __ vmovs(S3, S0);
-    __ vmovs(S4, S0);
-    __ vmovs(S5, S0);
-    __ vmovs(S6, S0);
-    __ vmovs(S7, S0);
+    __ LoadSImmediate(S1, 2.0);
+    __ LoadSImmediate(S2, 3.0);
+    __ LoadSImmediate(S3, 4.0);
+    __ LoadSImmediate(S4, 5.0);
+    __ LoadSImmediate(S5, 6.0);
+    __ LoadSImmediate(S6, 7.0);
+    __ LoadSImmediate(S7, 8.0);
 
     __ vaddqs(Q2, Q0, Q1);
 
@@ -1758,7 +2078,7 @@
 
     __ bx(LR);
   } else {
-    __ LoadImmediate(R0, 8);
+    __ LoadImmediate(R0, 36);
     __ bx(LR);
   }
 }
@@ -1767,7 +2087,249 @@
 ASSEMBLER_TEST_RUN(Vaddqs, test) {
   EXPECT(test != NULL);
   typedef int (*Tst)();
-  EXPECT_EQ(8, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  EXPECT_EQ(36, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Vsubqs, assembler) {
+  if (CPUFeatures::neon_supported()) {
+    __ LoadSImmediate(S0, 1.0);
+    __ LoadSImmediate(S1, 2.0);
+    __ LoadSImmediate(S2, 3.0);
+    __ LoadSImmediate(S3, 4.0);
+    __ LoadSImmediate(S4, 2.0);
+    __ LoadSImmediate(S5, 4.0);
+    __ LoadSImmediate(S6, 6.0);
+    __ LoadSImmediate(S7, 8.0);
+
+    __ vsubqs(Q2, Q1, Q0);
+
+    __ vadds(S8, S8, S9);
+    __ vadds(S8, S8, S10);
+    __ vadds(S8, S8, S11);
+
+    __ vcvtis(S0, S8);
+    __ vmovrs(R0, S0);
+
+    __ bx(LR);
+  } else {
+    __ LoadImmediate(R0, 10);
+    __ bx(LR);
+  }
+}
+
+
+ASSEMBLER_TEST_RUN(Vsubqs, test) {
+  EXPECT(test != NULL);
+  typedef int (*Tst)();
+  EXPECT_EQ(10, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Vmulqs, assembler) {
+  if (CPUFeatures::neon_supported()) {
+    __ LoadSImmediate(S0, 1.0);
+    __ LoadSImmediate(S1, 2.0);
+    __ LoadSImmediate(S2, 3.0);
+    __ LoadSImmediate(S3, 4.0);
+    __ LoadSImmediate(S4, 5.0);
+    __ LoadSImmediate(S5, 6.0);
+    __ LoadSImmediate(S6, 7.0);
+    __ LoadSImmediate(S7, 8.0);
+
+    __ vmulqs(Q2, Q1, Q0);
+
+    __ vadds(S8, S8, S9);
+    __ vadds(S8, S8, S10);
+    __ vadds(S8, S8, S11);
+
+    __ vcvtis(S0, S8);
+    __ vmovrs(R0, S0);
+
+    __ bx(LR);
+  } else {
+    __ LoadImmediate(R0, 70);
+    __ bx(LR);
+  }
+}
+
+
+ASSEMBLER_TEST_RUN(Vmulqs, test) {
+  EXPECT(test != NULL);
+  typedef int (*Tst)();
+  EXPECT_EQ(70, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(VtblX, assembler) {
+  if (CPUFeatures::neon_supported()) {
+    // Index.
+    __ LoadImmediate(R0, 0x03020100);
+    __ vmovsr(S0, R0);
+    __ vmovsr(S1, R0);
+
+    // Table.
+    __ LoadSImmediate(S2, 1.0);
+    __ LoadSImmediate(S3, 2.0);
+    __ LoadSImmediate(S4, 3.0);
+    __ LoadSImmediate(S5, 4.0);
+
+    // Select.
+    __ vtbl(D3, D1, 2, D0);
+
+    // Check that S6, S7 are both 1.0
+    __ vcvtis(S0, S6);
+    __ vcvtis(S1, S7);
+    __ vmovrs(R2, S0);
+    __ vmovrs(R3, S1);
+
+    __ LoadImmediate(R0, 0);
+    __ CompareImmediate(R2, 1);
+    __ bx(LR, NE);
+    __ CompareImmediate(R3, 1);
+    __ bx(LR, NE);
+    __ LoadImmediate(R0, 42);
+    __ bx(LR);
+  } else {
+    __ LoadImmediate(R0, 42);
+    __ bx(LR);
+  }
+}
+
+
+ASSEMBLER_TEST_RUN(VtblX, test) {
+  EXPECT(test != NULL);
+  typedef int (*Tst)();
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(VtblY, assembler) {
+  if (CPUFeatures::neon_supported()) {
+    // Index.
+    __ LoadImmediate(R0, 0x07060504);
+    __ vmovsr(S0, R0);
+    __ vmovsr(S1, R0);
+
+    // Table.
+    __ LoadSImmediate(S2, 2.0);
+    __ LoadSImmediate(S3, 1.0);
+    __ LoadSImmediate(S4, 3.0);
+    __ LoadSImmediate(S5, 4.0);
+
+    // Select.
+    __ vtbl(D3, D1, 2, D0);
+
+    // Check that S6, S7 are both 1.0
+    __ vcvtis(S0, S6);
+    __ vcvtis(S1, S7);
+    __ vmovrs(R2, S0);
+    __ vmovrs(R3, S1);
+
+    __ LoadImmediate(R0, 0);
+    __ CompareImmediate(R2, 1);
+    __ bx(LR, NE);
+    __ CompareImmediate(R3, 1);
+    __ bx(LR, NE);
+    __ LoadImmediate(R0, 42);
+    __ bx(LR);
+  } else {
+    __ LoadImmediate(R0, 42);
+    __ bx(LR);
+  }
+}
+
+
+ASSEMBLER_TEST_RUN(VtblY, test) {
+  EXPECT(test != NULL);
+  typedef int (*Tst)();
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(VtblZ, assembler) {
+  if (CPUFeatures::neon_supported()) {
+    // Index.
+    __ LoadImmediate(R0, 0x0b0a0908);
+    __ vmovsr(S0, R0);
+    __ vmovsr(S1, R0);
+
+    // Table.
+    __ LoadSImmediate(S2, 2.0);
+    __ LoadSImmediate(S3, 3.0);
+    __ LoadSImmediate(S4, 1.0);
+    __ LoadSImmediate(S5, 4.0);
+
+    // Select.
+    __ vtbl(D3, D1, 2, D0);
+
+    // Check that S6, S7 are both 1.0
+    __ vcvtis(S0, S6);
+    __ vcvtis(S1, S7);
+    __ vmovrs(R2, S0);
+    __ vmovrs(R3, S1);
+
+    __ LoadImmediate(R0, 0);
+    __ CompareImmediate(R2, 1);
+    __ bx(LR, NE);
+    __ CompareImmediate(R3, 1);
+    __ bx(LR, NE);
+    __ LoadImmediate(R0, 42);
+    __ bx(LR);
+  } else {
+    __ LoadImmediate(R0, 42);
+    __ bx(LR);
+  }
+}
+
+
+ASSEMBLER_TEST_RUN(VtblZ, test) {
+  EXPECT(test != NULL);
+  typedef int (*Tst)();
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(VtblW, assembler) {
+  if (CPUFeatures::neon_supported()) {
+    // Index.
+    __ LoadImmediate(R0, 0x0f0e0d0c);
+    __ vmovsr(S0, R0);
+    __ vmovsr(S1, R0);
+
+    // Table.
+    __ LoadSImmediate(S2, 2.0);
+    __ LoadSImmediate(S3, 3.0);
+    __ LoadSImmediate(S4, 4.0);
+    __ LoadSImmediate(S5, 1.0);
+
+    // Select.
+    __ vtbl(D3, D1, 2, D0);
+
+    // Check that S6, S7 are both 1.0
+    __ vcvtis(S0, S6);
+    __ vcvtis(S1, S7);
+    __ vmovrs(R2, S0);
+    __ vmovrs(R3, S1);
+
+    __ LoadImmediate(R0, 0);
+    __ CompareImmediate(R2, 1);
+    __ bx(LR, NE);
+    __ CompareImmediate(R3, 1);
+    __ bx(LR, NE);
+    __ LoadImmediate(R0, 42);
+    __ bx(LR);
+  } else {
+    __ LoadImmediate(R0, 42);
+    __ bx(LR);
+  }
+}
+
+
+ASSEMBLER_TEST_RUN(VtblW, test) {
+  EXPECT(test != NULL);
+  typedef int (*Tst)();
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
 }
 
 
diff --git a/runtime/vm/ast.cc b/runtime/vm/ast.cc
index 809b4db..f935546 100644
--- a/runtime/vm/ast.cc
+++ b/runtime/vm/ast.cc
@@ -495,7 +495,7 @@
     const Function& getter =
         Function::Handle(cls().LookupStaticFunction(getter_name));
     ASSERT(!getter.IsNull() &&
-           (getter.kind() == RawFunction::kConstImplicitGetter));
+           (getter.kind() == RawFunction::kImplicitStaticFinalGetter));
 #endif
     return new StoreStaticFieldNode(token_pos(), field, rhs);
   }
diff --git a/runtime/vm/bootstrap_natives.h b/runtime/vm/bootstrap_natives.h
index df3fc8c0..99008cb 100644
--- a/runtime/vm/bootstrap_natives.h
+++ b/runtime/vm/bootstrap_natives.h
@@ -240,12 +240,18 @@
   V(Mirrors_makeLocalClassMirror, 1)                                           \
   V(Mirrors_makeLocalMirrorSystem, 0)                                          \
   V(Mirrors_metadata, 1)                                                       \
-  V(LocalObjectMirrorImpl_invoke, 4)                                           \
-  V(LocalObjectMirrorImpl_getField, 2)                                         \
-  V(LocalObjectMirrorImpl_setField, 4)                                         \
-  V(LocalClosureMirrorImpl_apply, 3)                                           \
-  V(LocalClassMirrorImpl_invokeConstructor, 4)                                 \
+  V(InstanceMirror_invoke, 4)                                                  \
+  V(InstanceMirror_invokeGetter, 3)                                            \
+  V(InstanceMirror_invokeSetter, 4)                                            \
+  V(ClosureMirror_apply, 2)                                                    \
   V(ClassMirror_name, 1)                                                       \
+  V(ClassMirror_invoke, 4)                                                     \
+  V(ClassMirror_invokeGetter, 3)                                               \
+  V(ClassMirror_invokeSetter, 4)                                               \
+  V(ClassMirror_invokeConstructor, 3)                                          \
+  V(LibraryMirror_invoke, 4)                                                   \
+  V(LibraryMirror_invokeGetter, 3)                                             \
+  V(LibraryMirror_invokeSetter, 4)                                             \
   V(MethodMirror_name, 1)                                                      \
   V(GrowableObjectArray_allocate, 2)                                           \
   V(GrowableObjectArray_getIndexed, 2)                                         \
diff --git a/runtime/vm/code_generator.cc b/runtime/vm/code_generator.cc
index afa0fcc..8efe89c 100644
--- a/runtime/vm/code_generator.cc
+++ b/runtime/vm/code_generator.cc
@@ -801,16 +801,13 @@
                                           const ICData& ic_data) {
   ArgumentsDescriptor
       arguments_descriptor(Array::Handle(ic_data.arguments_descriptor()));
-  intptr_t num_arguments = arguments_descriptor.Count();
-  int num_named_arguments = arguments_descriptor.NamedCount();
   String& function_name = String::Handle(ic_data.target_name());
   ASSERT(function_name.IsSymbol());
 
   Function& function = Function::Handle();
   function = Resolver::ResolveDynamic(receiver,
                                       function_name,
-                                      num_arguments,
-                                      num_named_arguments);
+                                      arguments_descriptor);
   if (function.IsNull()) {
     return Code::null();
   } else {
@@ -1063,15 +1060,11 @@
                  cls.ToCString(), name.ToCString());
   }
 
-  intptr_t arg_count =
-      Smi::Cast(Object::Handle(descriptor.At(0))).Value();
-  intptr_t named_arg_count =
-      arg_count - Smi::Cast(Object::Handle(descriptor.At(1))).Value();
+  ArgumentsDescriptor args_desc(descriptor);
   const Function& target = Function::Handle(
       Resolver::ResolveDynamicForReceiverClass(cls,
                                                name,
-                                               arg_count,
-                                               named_arg_count));
+                                               args_desc));
 
   Instructions& instructions = Instructions::Handle();
   if (!target.IsNull()) {
@@ -1112,12 +1105,12 @@
   args.Add(&receiver);
   args.Add(&arg1);
   const intptr_t kNumArguments = 2;
-  const intptr_t kNumNamedArguments = 0;
-  Function& target_function = Function::Handle();
-  target_function = Resolver::ResolveDynamic(receiver,
-                                             target_name,
-                                             kNumArguments,
-                                             kNumNamedArguments);
+    ArgumentsDescriptor args_desc(
+        Array::Handle(ArgumentsDescriptor::New(kNumArguments)));
+  const Function& target_function = Function::Handle(
+      Resolver::ResolveDynamic(receiver,
+                               target_name,
+                               args_desc));
   ASSERT(!target_function.IsNull());
   GrowableArray<intptr_t> class_ids(kNumArguments);
   ASSERT(ic_data.num_args_tested() == kNumArguments);
@@ -1189,12 +1182,12 @@
   // 1. Check if there is a getter with the same name.
   const String& getter_name = String::Handle(Field::GetterName(target_name));
   const int kNumArguments = 1;
-  const int kNumNamedArguments = 0;
+  ArgumentsDescriptor args_desc(
+      Array::Handle(ArgumentsDescriptor::New(kNumArguments)));
   const Function& getter = Function::Handle(
       Resolver::ResolveDynamicForReceiverClass(receiver_class,
                                                getter_name,
-                                               kNumArguments,
-                                               kNumNamedArguments));
+                                               args_desc));
   if (getter.IsNull() || getter.IsMethodExtractor()) {
     return false;
   }
diff --git a/runtime/vm/compiler.cc b/runtime/vm/compiler.cc
index ee9a5a0..a0dc2814 100644
--- a/runtime/vm/compiler.cc
+++ b/runtime/vm/compiler.cc
@@ -843,7 +843,7 @@
     const char* kEvalConst = "eval_const";
     const Function& func = Function::ZoneHandle(Function::New(
         String::Handle(Symbols::New(kEvalConst)),
-        RawFunction::kConstImplicitGetter,
+        RawFunction::kImplicitStaticFinalGetter,
         true,  // static function.
         false,  // not const function.
         false,  // not abstract
diff --git a/runtime/vm/constants_arm.h b/runtime/vm/constants_arm.h
index 7006fe7..1a65c51 100644
--- a/runtime/vm/constants_arm.h
+++ b/runtime/vm/constants_arm.h
@@ -164,10 +164,19 @@
 }
 
 
+static inline SRegister EvenSRegisterOf(DRegister d) {
+  return static_cast<SRegister>(d * 2);
+}
+
+static inline SRegister OddSRegisterOf(DRegister d) {
+  return static_cast<SRegister>((d * 2) + 1);
+}
+
+
 // Register aliases for floating point scratch registers.
 const QRegister QTMP = Q7;  // Overlaps with DTMP, STMP.
-const DRegister DTMP = D14;  // Overlaps with STMP.
-const SRegister STMP = S28;
+const DRegister DTMP = EvenDRegisterOf(QTMP);  // Overlaps with STMP.
+const SRegister STMP = EvenSRegisterOf(DTMP);
 
 // Architecture independent aliases.
 typedef QRegister FpuRegister;
diff --git a/runtime/vm/dart.cc b/runtime/vm/dart.cc
index e401374..af17f5e 100644
--- a/runtime/vm/dart.cc
+++ b/runtime/vm/dart.cc
@@ -14,6 +14,7 @@
 #include "vm/isolate.h"
 #include "vm/object.h"
 #include "vm/object_store.h"
+#include "vm/object_id_ring.h"
 #include "vm/port.h"
 #include "vm/simulator.h"
 #include "vm/snapshot.h"
@@ -159,6 +160,7 @@
   StackZone zone(isolate);
   HandleScope handle_scope(isolate);
   Heap::Init(isolate);
+  ObjectIdRing::Init(isolate);
   ObjectStore::Init(isolate);
 
   if (snapshot_buffer == NULL) {
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index ccda777..1162b05 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -1874,13 +1874,17 @@
     return Api::NewError("Object does not implement the List interface");
   }
   const String& name = String::Handle(Field::GetterName(Symbols::Length()));
+  const int kNumArgs = 1;
+  ArgumentsDescriptor args_desc(
+      Array::Handle(ArgumentsDescriptor::New(kNumArgs)));
   const Function& function =
-      Function::Handle(isolate, Resolver::ResolveDynamic(instance, name, 1, 0));
+      Function::Handle(isolate, Resolver::ResolveDynamic(instance,
+                                                         name,
+                                                         args_desc));
   if (function.IsNull()) {
     return Api::NewError("List object does not have a 'length' field.");
   }
 
-  const int kNumArgs = 1;
   const Array& args = Array::Handle(isolate, Array::New(kNumArgs));
   args.SetAt(0, instance);  // Set up the receiver as the first argument.
   const Object& retval =
@@ -1940,11 +1944,13 @@
     const Instance& instance =
         Instance::Handle(isolate, GetListInstance(isolate, obj));
     if (!instance.IsNull()) {
+      const int kNumArgs = 2;
+      ArgumentsDescriptor args_desc(
+          Array::Handle(ArgumentsDescriptor::New(kNumArgs)));
       const Function& function = Function::Handle(
           isolate,
-          Resolver::ResolveDynamic(instance, Symbols::IndexToken(), 2, 0));
+          Resolver::ResolveDynamic(instance, Symbols::IndexToken(), args_desc));
       if (!function.IsNull()) {
-        const int kNumArgs = 2;
         const Array& args = Array::Handle(isolate, Array::New(kNumArgs));
         const Integer& indexobj = Integer::Handle(isolate, Integer::New(index));
         args.SetAt(0, instance);
@@ -1992,12 +1998,14 @@
     const Instance& instance =
         Instance::Handle(isolate, GetListInstance(isolate, obj));
     if (!instance.IsNull()) {
+      const intptr_t kNumArgs = 3;
+      ArgumentsDescriptor args_desc(
+          Array::Handle(ArgumentsDescriptor::New(kNumArgs)));
       const Function& function = Function::Handle(
           isolate,
           Resolver::ResolveDynamic(instance,
                                    Symbols::AssignIndexToken(),
-                                   3,
-                                   0));
+                                   args_desc));
       if (!function.IsNull()) {
         const Integer& index_obj =
             Integer::Handle(isolate, Integer::New(index));
@@ -2006,7 +2014,6 @@
         if (!value_obj.IsNull() && !value_obj.IsInstance()) {
           RETURN_TYPE_ERROR(isolate, value, Instance);
         }
-        const intptr_t kNumArgs = 3;
         const Array& args = Array::Handle(isolate, Array::New(kNumArgs));
         args.SetAt(0, instance);
         args.SetAt(1, index_obj);
@@ -2165,13 +2172,15 @@
   const Instance& instance =
       Instance::Handle(isolate, GetListInstance(isolate, obj));
   if (!instance.IsNull()) {
+    const int kNumArgs = 2;
+    ArgumentsDescriptor args_desc(
+        Array::Handle(ArgumentsDescriptor::New(kNumArgs)));
     const Function& function = Function::Handle(
         isolate,
-        Resolver::ResolveDynamic(instance, Symbols::IndexToken(), 2, 0));
+        Resolver::ResolveDynamic(instance, Symbols::IndexToken(), args_desc));
     if (!function.IsNull()) {
       Object& result = Object::Handle(isolate);
       Integer& intobj = Integer::Handle(isolate);
-      const int kNumArgs = 2;
       const Array& args = Array::Handle(isolate, Array::New(kNumArgs));
       args.SetAt(0, instance);  // Set up the receiver as the first argument.
       for (int i = 0; i < length; i++) {
@@ -2260,16 +2269,17 @@
   const Instance& instance =
       Instance::Handle(isolate, GetListInstance(isolate, obj));
   if (!instance.IsNull()) {
+    const int kNumArgs = 3;
+    ArgumentsDescriptor args_desc(
+        Array::Handle(ArgumentsDescriptor::New(kNumArgs)));
     const Function& function = Function::Handle(
         isolate,
         Resolver::ResolveDynamic(instance,
                                  Symbols::AssignIndexToken(),
-                                 3,
-                                 0));
+                                 args_desc));
     if (!function.IsNull()) {
       Integer& indexobj = Integer::Handle(isolate);
       Integer& valueobj = Integer::Handle(isolate);
-      const int kNumArgs = 3;
       const Array& args = Array::Handle(isolate, Array::New(kNumArgs));
       args.SetAt(0, instance);  // Set up the receiver as the first argument.
       for (int i = 0; i < length; i++) {
@@ -2957,12 +2967,11 @@
   } else if (obj.IsNull() || obj.IsInstance()) {
     Instance& instance = Instance::Handle(isolate);
     instance ^= obj.raw();
+    ArgumentsDescriptor args_desc(
+        Array::Handle(ArgumentsDescriptor::New(number_of_arguments + 1)));
     const Function& function = Function::Handle(
         isolate,
-        Resolver::ResolveDynamic(instance,
-                                 function_name,
-                                 (number_of_arguments + 1),
-                                 Resolver::kIsQualified));
+        Resolver::ResolveDynamic(instance, function_name, args_desc));
     args.SetAt(0, instance);
     if (function.IsNull()) {
       const Array& args_descriptor =
diff --git a/runtime/vm/dart_entry.cc b/runtime/vm/dart_entry.cc
index 839407d..dd3f08f 100644
--- a/runtime/vm/dart_entry.cc
+++ b/runtime/vm/dart_entry.cc
@@ -138,12 +138,12 @@
 
   // Now use the invocation mirror object and invoke NoSuchMethod.
   const int kNumArguments = 2;
-  const int kNumNamedArguments = 0;
+  ArgumentsDescriptor args_desc(
+      Array::Handle(ArgumentsDescriptor::New(kNumArguments)));
   const Function& function = Function::Handle(
       Resolver::ResolveDynamic(receiver,
                                Symbols::NoSuchMethod(),
-                               kNumArguments,
-                               kNumNamedArguments));
+                               args_desc));
   ASSERT(!function.IsNull());
   const Array& args = Array::Handle(Array::New(kNumArguments));
   args.SetAt(0, receiver);
@@ -152,6 +152,59 @@
 }
 
 
+RawObject* DartEntry::InvokeConstructor(const Class& klass,
+                                        const Function& constructor,
+                                        const Array& arguments) {
+  Class& ultimate_klass = Class::Handle(klass.raw());
+  Function& ultimate_constructor = Function::Handle(constructor.raw());
+
+  Instance& new_object = Instance::Handle();
+  if (ultimate_constructor.IsRedirectingFactory()) {
+    Type& type = Type::Handle(ultimate_constructor.RedirectionType());
+    ultimate_klass = type.type_class();
+    ultimate_constructor = ultimate_constructor.RedirectionTarget();
+  }
+  if (ultimate_constructor.IsConstructor()) {
+    // "Constructors" are really instance initializers. They are passed a newly
+    // allocated object as an extra argument.
+    new_object = Instance::New(ultimate_klass);
+  }
+
+  // Create the argument list.
+  intptr_t number_of_arguments = arguments.Length();
+  intptr_t arg_index = 0;
+  int extra_args = (ultimate_constructor.IsConstructor() ? 2 : 1);
+  const Array& args =
+      Array::Handle(Array::New(number_of_arguments + extra_args));
+  if (ultimate_constructor.IsConstructor()) {
+    // Constructors get the uninitialized object and a constructor phase.
+    args.SetAt(arg_index++, new_object);
+    args.SetAt(arg_index++,
+               Smi::Handle(Smi::New(Function::kCtorPhaseAll)));
+  } else {
+    // Factories get type arguments.
+    args.SetAt(arg_index++, TypeArguments::Handle());
+  }
+  Object& argument = Object::Handle();
+  for (int i = 0; i < number_of_arguments; i++) {
+    argument = (arguments.At(i));
+    args.SetAt(arg_index++, argument);
+  }
+
+  // Invoke the constructor and return the new object.
+  const Object& result =
+      Object::Handle(DartEntry::InvokeFunction(ultimate_constructor, args));
+  if (result.IsError()) {
+    return result.raw();
+  }
+  if (ultimate_constructor.IsConstructor()) {
+    return new_object.raw();
+  } else {
+    return result.raw();
+  }
+}
+
+
 ArgumentsDescriptor::ArgumentsDescriptor(const Array& array)
     : array_(array) {
 }
@@ -336,12 +389,12 @@
 
 RawObject* DartLibraryCalls::ToString(const Instance& receiver) {
   const int kNumArguments = 1;  // Receiver.
-  const int kNumNamedArguments = 0;  // None.
+  ArgumentsDescriptor args_desc(
+      Array::Handle(ArgumentsDescriptor::New(kNumArguments)));
   const Function& function = Function::Handle(
       Resolver::ResolveDynamic(receiver,
                                Symbols::toString(),
-                               kNumArguments,
-                               kNumNamedArguments));
+                               args_desc));
   ASSERT(!function.IsNull());
   const Array& args = Array::Handle(Array::New(kNumArguments));
   args.SetAt(0, receiver);
@@ -355,12 +408,12 @@
 RawObject* DartLibraryCalls::Equals(const Instance& left,
                                     const Instance& right) {
   const int kNumArguments = 2;
-  const int kNumNamedArguments = 0;
+  ArgumentsDescriptor args_desc(
+      Array::Handle(ArgumentsDescriptor::New(kNumArguments)));
   const Function& function = Function::Handle(
       Resolver::ResolveDynamic(left,
                                Symbols::EqualOperator(),
-                               kNumArguments,
-                               kNumNamedArguments));
+                               args_desc));
   ASSERT(!function.IsNull());
 
   const Array& args = Array::Handle(Array::New(kNumArguments));
@@ -467,11 +520,12 @@
                                       const Instance& key,
                                       const Instance& value) {
   const int kNumArguments = 3;
+  ArgumentsDescriptor args_desc(
+      Array::Handle(ArgumentsDescriptor::New(kNumArguments)));
   const Function& function = Function::Handle(
       Resolver::ResolveDynamic(map,
                                Symbols::AssignIndexToken(),
-                               kNumArguments,
-                               0));
+                               args_desc));
   ASSERT(!function.IsNull());
   const Array& args = Array::Handle(Array::New(kNumArguments));
   args.SetAt(0, map);
diff --git a/runtime/vm/dart_entry.h b/runtime/vm/dart_entry.h
index 92d05af..63ed513 100644
--- a/runtime/vm/dart_entry.h
+++ b/runtime/vm/dart_entry.h
@@ -142,6 +142,13 @@
                                        const String& target_name,
                                        const Array& arguments,
                                        const Array& arguments_descriptor);
+
+  // Invokes a generative constructor, redirecting constructor, factory or
+  // redirecting factory. On success, returns a RawInstance. On failure,
+  // a RawError.
+  static RawObject* InvokeConstructor(const Class& klass,
+                                      const Function &constructor,
+                                      const Array& arguments);
 };
 
 
diff --git a/runtime/vm/debugger.cc b/runtime/vm/debugger.cc
index d26ae75..f479a4e 100644
--- a/runtime/vm/debugger.cc
+++ b/runtime/vm/debugger.cc
@@ -1536,7 +1536,7 @@
   RawFunction::Kind fkind = func.kind();
   if ((fkind == RawFunction::kImplicitGetter) ||
       (fkind == RawFunction::kImplicitSetter) ||
-      (fkind == RawFunction::kConstImplicitGetter) ||
+      (fkind == RawFunction::kImplicitStaticFinalGetter) ||
       (fkind == RawFunction::kMethodExtractor) ||
       (fkind == RawFunction::kNoSuchMethodDispatcher) ||
       (fkind == RawFunction::kInvokeFieldDispatcher)) {
diff --git a/runtime/vm/disassembler_arm.cc b/runtime/vm/disassembler_arm.cc
index 52e3a52..d3dd288 100644
--- a/runtime/vm/disassembler_arm.cc
+++ b/runtime/vm/disassembler_arm.cc
@@ -33,6 +33,7 @@
   void PrintRegister(int reg);
   void PrintSRegister(int reg);
   void PrintDRegister(int reg);
+  void PrintDRegisterList(int start, int reg_count);
   void PrintQRegister(int reg);
   void PrintCondition(Instr* instr);
   void PrintShiftRm(Instr* instr);
@@ -330,6 +331,18 @@
 }
 
 
+void ARMDecoder::PrintDRegisterList(int start, int reg_count) {
+  Print("{");
+  for (int i = start; i < start + reg_count; i++) {
+    PrintDRegister(i);
+    if (i != start + reg_count - 1) {
+      Print(", ");
+    }
+  }
+  Print("}");
+}
+
+
 int ARMDecoder::FormatDRegister(Instr* instr, const char* format) {
   ASSERT(format[0] == 'd');
   if (format[1] == 'n') {  // 'dn: Dn register
@@ -348,15 +361,14 @@
     ASSERT(STRING_STARTS_WITH(format, "dlist"));
     int reg_count = instr->Bits(0, 8) >> 1;
     int start = (instr->Bit(22) << 4) | instr->Bits(12, 4);
-    Print("{");
-    for (int i = start; i < start + reg_count; i++) {
-      PrintDRegister(i);
-      if (i != start + reg_count - 1) {
-        Print(", ");
-      }
-    }
-    Print("}");
+    PrintDRegisterList(start, reg_count);
     return 5;
+  } else if (format[1] == 't') {
+    ASSERT(STRING_STARTS_WITH(format, "dtbllist"));
+    int reg_count = instr->Bits(8, 2) + 1;
+    int start = (instr->Bit(7) << 4) | instr->Bits(16, 4);
+    PrintDRegisterList(start, reg_count);
+    return 8;
   }
   UNREACHABLE();
   return -1;
@@ -531,12 +543,20 @@
                                    instr->SvcField());
         return 3;
       } else if (format[1] == 'z') {
-        // 'sz: Size field of SIMD instruction.
-        int sz = 8 << (instr->Bits(20, 2));
+        // 'sz: Size field of SIMD instructions.
+        int sz = instr->Bits(20, 2);
+        char const* sz_str;
+        switch (sz) {
+          case 0: sz_str = "b"; break;
+          case 1: sz_str = "h"; break;
+          case 2: sz_str = "w"; break;
+          case 3: sz_str = "l"; break;
+          default: sz_str = "?"; break;
+        }
         buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
                                    remaining_size_in_buffer(),
-                                   "I%d",
-                                   sz);
+                                   "%s",
+                                   sz_str);
         return 2;
       } else if (format[1] == ' ') {
         // 's: S field of data processing instructions.
@@ -1270,16 +1290,33 @@
   ASSERT(instr->ConditionField() == kSpecialCondition);
   if (instr->Bit(6) == 1) {
     if ((instr->Bits(8, 4) == 8) && (instr->Bit(4) == 0) &&
-        (instr->Bit(24) == 0)) {
-      Format(instr, "vadd.'sz 'qd, 'qn, 'qm");
+        (instr->Bits(23, 2) == 0)) {
+      Format(instr, "vaddq'sz 'qd, 'qn, 'qm");
     } else if ((instr->Bits(8, 4) == 13) && (instr->Bit(4) == 0) &&
-        (instr->Bit(24) == 0)) {
-      Format(instr, "vadd.F32 'qd, 'qn, 'qm");
+               (instr->Bits(23, 2) == 0) && (instr->Bit(21) == 0)) {
+      Format(instr, "vaddqs 'qd, 'qn, 'qm");
+    } else if ((instr->Bits(8, 4) == 8) && (instr->Bit(4) == 0) &&
+               (instr->Bits(23, 2) == 2)) {
+      Format(instr, "vsubq'sz 'qd, 'qn, 'qm");
+    } else if ((instr->Bits(8, 4) == 13) && (instr->Bit(4) == 0) &&
+               (instr->Bits(23, 2) == 0) && (instr->Bit(21) == 1)) {
+      Format(instr, "vsubqs 'qd, 'qn, 'qm");
+    } else if ((instr->Bits(8, 4) == 9) && (instr->Bit(4) == 1) &&
+               (instr->Bits(23, 2) == 0)) {
+      Format(instr, "vmulq'sz 'qd, 'qn, 'qm");
+    } else if ((instr->Bits(8, 4) == 13) && (instr->Bit(4) == 1) &&
+               (instr->Bits(23, 2) == 2) && (instr->Bit(21) == 0)) {
+      Format(instr, "vmulqs 'qd, 'qn, 'qm");
     } else {
       Unknown(instr);
     }
   } else {
-    Unknown(instr);
+    if ((instr->Bits(23, 2) == 3) && (instr->Bits(20, 2) == 3) &&
+        (instr->Bits(10, 2) == 2) && (instr->Bit(4) == 0)) {
+      Format(instr, "vtbl 'dd, 'dtbllist, 'dm");
+    } else {
+      Unknown(instr);
+    }
   }
 }
 
diff --git a/runtime/vm/exceptions.cc b/runtime/vm/exceptions.cc
index f994178..35c9582 100644
--- a/runtime/vm/exceptions.cc
+++ b/runtime/vm/exceptions.cc
@@ -618,6 +618,14 @@
       library = Library::CoreLibrary();
       class_name = &Symbols::AbstractClassInstantiationError();
       break;
+    case kMirroredUncaughtExceptionError:
+      library = Library::MirrorsLibrary();
+      class_name = &Symbols::MirroredUncaughtExceptionError();
+      break;
+    case kMirroredCompilationError:
+      library = Library::MirrorsLibrary();
+      class_name = &Symbols::MirroredCompilationError();
+      break;
   }
 
   return DartLibraryCalls::ExceptionCreate(library,
diff --git a/runtime/vm/exceptions.h b/runtime/vm/exceptions.h
index 9d4a18e..e3b3c12 100644
--- a/runtime/vm/exceptions.h
+++ b/runtime/vm/exceptions.h
@@ -62,6 +62,8 @@
     kType,
     kFallThrough,
     kAbstractClassInstantiation,
+    kMirroredUncaughtExceptionError,
+    kMirroredCompilationError,
   };
 
   static void ThrowByType(ExceptionType type, const Array& arguments);
diff --git a/runtime/vm/flow_graph_builder.cc b/runtime/vm/flow_graph_builder.cc
index e0d2fff..6665626 100644
--- a/runtime/vm/flow_graph_builder.cc
+++ b/runtime/vm/flow_graph_builder.cc
@@ -802,7 +802,7 @@
     const bool is_implicit_dynamic_getter =
         (!function.is_static() &&
         ((function.kind() == RawFunction::kImplicitGetter) ||
-         (function.kind() == RawFunction::kConstImplicitGetter)));
+         (function.kind() == RawFunction::kImplicitStaticFinalGetter)));
     // Implicit getters do not need a type check at return, unless they compute
     // the initial value of a static field.
     // The body of a constructor cannot modify the type of the
diff --git a/runtime/vm/flow_graph_compiler_arm.cc b/runtime/vm/flow_graph_compiler_arm.cc
index 31acb69..82deb39 100644
--- a/runtime/vm/flow_graph_compiler_arm.cc
+++ b/runtime/vm/flow_graph_compiler_arm.cc
@@ -879,6 +879,11 @@
 
   // Copy or initialize optional named arguments.
   Label all_arguments_processed;
+#ifdef DEBUG
+    const bool check_correct_named_args = true;
+#else
+    const bool check_correct_named_args = function.IsClosureFunction();
+#endif
   if (num_opt_named_params > 0) {
     // Start by alphabetically sorting the names of the optional parameters.
     LocalVariable** opt_param = new LocalVariable*[num_opt_named_params];
@@ -946,10 +951,13 @@
     }
     delete[] opt_param;
     delete[] opt_param_position;
-    // Check that R6 now points to the null terminator in the array descriptor.
-    __ ldr(R5, Address(R6, 0));
-    __ CompareImmediate(R5, reinterpret_cast<int32_t>(Object::null()));
-    __ b(&all_arguments_processed, EQ);
+    if (check_correct_named_args) {
+      // Check that R6 now points to the null terminator in the arguments
+      // descriptor.
+      __ ldr(R5, Address(R6, 0));
+      __ CompareImmediate(R5, reinterpret_cast<int32_t>(Object::null()));
+      __ b(&all_arguments_processed, EQ);
+    }
   } else {
     ASSERT(num_opt_pos_params > 0);
     __ ldr(R8,
@@ -976,27 +984,30 @@
       __ str(R5, param_addr);
       __ Bind(&next_parameter);
     }
-    __ ldr(R7, FieldAddress(R4, ArgumentsDescriptor::count_offset()));
-    __ SmiUntag(R7);
-    // Check that R8 equals R7, i.e. no named arguments passed.
-    __ cmp(R8, ShifterOperand(R7));
-    __ b(&all_arguments_processed, EQ);
+    if (check_correct_named_args) {
+      __ ldr(R7, FieldAddress(R4, ArgumentsDescriptor::count_offset()));
+      __ SmiUntag(R7);
+      // Check that R8 equals R7, i.e. no named arguments passed.
+      __ cmp(R8, ShifterOperand(R7));
+      __ b(&all_arguments_processed, EQ);
+    }
   }
 
   __ Bind(&wrong_num_arguments);
-  // Invoke noSuchMethod function passing the original name of the function.
-  // If the function is a closure function, use "call" as the original name.
-  const String& name = String::Handle(
-      function.IsClosureFunction() ? Symbols::Call().raw() : function.name());
-  const int kNumArgsChecked = 1;
-  const ICData& ic_data = ICData::ZoneHandle(
-      ICData::New(function, name, Object::null_array(),
-                  Isolate::kNoDeoptId, kNumArgsChecked));
-  __ LoadObject(R5, ic_data);
-  __ LeaveDartFrame();  // The arguments are still on the stack.
-  __ Branch(&StubCode::CallNoSuchMethodFunctionLabel());
-  // The noSuchMethod call may return to the caller, but not here.
-  __ bkpt(0);
+  if (function.IsClosureFunction()) {
+    // Invoke noSuchMethod function passing "call" as the original name.
+    const int kNumArgsChecked = 1;
+    const ICData& ic_data = ICData::ZoneHandle(
+        ICData::New(function, Symbols::Call(), Object::null_array(),
+                    Isolate::kNoDeoptId, kNumArgsChecked));
+    __ LoadObject(R5, ic_data);
+    __ LeaveDartFrame();  // The arguments are still on the stack.
+    __ Branch(&StubCode::CallNoSuchMethodFunctionLabel());
+    // The noSuchMethod call may return to the caller, but not here.
+    __ bkpt(0);
+  } else if (check_correct_named_args) {
+    __ Stop("Wrong arguments");
+  }
 
   __ Bind(&all_arguments_processed);
   // Nullify originally passed arguments only after they have been copied and
@@ -1026,7 +1037,7 @@
   // SP: receiver.
   // Sequence node has one return node, its input is load field node.
   __ ldr(R0, Address(SP, 0 * kWordSize));
-  __ LoadFromOffset(kLoadWord, R0, R0, offset - kHeapObjectTag);
+  __ LoadFromOffset(kWord, R0, R0, offset - kHeapObjectTag);
   __ Ret();
 }
 
@@ -1323,7 +1334,7 @@
   const MegamorphicCache& cache =
       MegamorphicCache::ZoneHandle(table->Lookup(name, arguments_descriptor));
   Label not_smi, load_cache;
-  __ LoadFromOffset(kLoadWord, R0, SP, (argument_count - 1) * kWordSize);
+  __ LoadFromOffset(kWord, R0, SP, (argument_count - 1) * kWordSize);
   __ tst(R0, ShifterOperand(kSmiTagMask));
   __ b(&not_smi, NE);
   __ mov(R0, ShifterOperand(Smi::RawValue(kSmiCid)));
@@ -1511,6 +1522,7 @@
       if (locs->live_registers()->ContainsFpuRegister(fpu_reg)) {
         DRegister d1 = EvenDRegisterOf(fpu_reg);
         DRegister d2 = OddDRegisterOf(fpu_reg);
+        // TOOD(regis): merge stores using vstmd instruction.
         __ vstrd(d1, Address(SP, offset));
         __ vstrd(d2, Address(SP, offset + 2 * kWordSize));
         offset += kFpuRegisterSize;
@@ -1547,6 +1559,7 @@
       if (locs->live_registers()->ContainsFpuRegister(fpu_reg)) {
         DRegister d1 = EvenDRegisterOf(fpu_reg);
         DRegister d2 = OddDRegisterOf(fpu_reg);
+        // TOOD(regis): merge loads using vldmd instruction.
         __ vldrd(d1, Address(SP, offset));
         __ vldrd(d2, Address(SP, offset + 2 * kWordSize));
         offset += kFpuRegisterSize;
diff --git a/runtime/vm/flow_graph_compiler_ia32.cc b/runtime/vm/flow_graph_compiler_ia32.cc
index 3ecdfc3..eab9bcf 100644
--- a/runtime/vm/flow_graph_compiler_ia32.cc
+++ b/runtime/vm/flow_graph_compiler_ia32.cc
@@ -899,6 +899,11 @@
   const Immediate& raw_null =
       Immediate(reinterpret_cast<intptr_t>(Object::null()));
   Label all_arguments_processed;
+#ifdef DEBUG
+    const bool check_correct_named_args = true;
+#else
+    const bool check_correct_named_args = function.IsClosureFunction();
+#endif
   if (num_opt_named_params > 0) {
     // Start by alphabetically sorting the names of the optional parameters.
     LocalVariable** opt_param = new LocalVariable*[num_opt_named_params];
@@ -966,9 +971,12 @@
     }
     delete[] opt_param;
     delete[] opt_param_position;
-    // Check that EDI now points to the null terminator in the array descriptor.
-    __ cmpl(Address(EDI, 0), raw_null);
-    __ j(EQUAL, &all_arguments_processed, Assembler::kNearJump);
+    if (check_correct_named_args) {
+      // Check that EDI now points to the null terminator in the arguments
+      // descriptor.
+      __ cmpl(Address(EDI, 0), raw_null);
+      __ j(EQUAL, &all_arguments_processed, Assembler::kNearJump);
+    }
   } else {
     ASSERT(num_opt_pos_params > 0);
     __ movl(ECX,
@@ -995,27 +1003,30 @@
       __ movl(param_addr, EAX);
       __ Bind(&next_parameter);
     }
-    __ movl(EBX, FieldAddress(EDX, ArgumentsDescriptor::count_offset()));
-    __ SmiUntag(EBX);
-    // Check that ECX equals EBX, i.e. no named arguments passed.
-    __ cmpl(ECX, EBX);
-    __ j(EQUAL, &all_arguments_processed, Assembler::kNearJump);
+    if (check_correct_named_args) {
+      __ movl(EBX, FieldAddress(EDX, ArgumentsDescriptor::count_offset()));
+      __ SmiUntag(EBX);
+      // Check that ECX equals EBX, i.e. no named arguments passed.
+      __ cmpl(ECX, EBX);
+      __ j(EQUAL, &all_arguments_processed, Assembler::kNearJump);
+    }
   }
 
   __ Bind(&wrong_num_arguments);
-  // Invoke noSuchMethod function passing the original name of the function.
-  // If the function is a closure function, use "call" as the original name.
-  const String& name = String::Handle(
-      function.IsClosureFunction() ? Symbols::Call().raw() : function.name());
-  const int kNumArgsChecked = 1;
-  const ICData& ic_data = ICData::ZoneHandle(
-      ICData::New(function, name, Object::null_array(),
-                  Isolate::kNoDeoptId, kNumArgsChecked));
-  __ LoadObject(ECX, ic_data);
-  __ LeaveFrame();  // The arguments are still on the stack.
-  __ jmp(&StubCode::CallNoSuchMethodFunctionLabel());
-  // The noSuchMethod call may return to the caller, but not here.
-  __ int3();
+  if (function.IsClosureFunction()) {
+    // Invoke noSuchMethod function passing "call" as the original name.
+    const int kNumArgsChecked = 1;
+    const ICData& ic_data = ICData::ZoneHandle(
+        ICData::New(function, Symbols::Call(), Object::null_array(),
+                    Isolate::kNoDeoptId, kNumArgsChecked));
+    __ LoadObject(ECX, ic_data);
+    __ LeaveFrame();  // The arguments are still on the stack.
+    __ jmp(&StubCode::CallNoSuchMethodFunctionLabel());
+    // The noSuchMethod call may return to the caller, but not here.
+    __ int3();
+  } else if (check_correct_named_args) {
+    __ Stop("Wrong arguments");
+  }
 
   __ Bind(&all_arguments_processed);
   // Nullify originally passed arguments only after they have been copied and
diff --git a/runtime/vm/flow_graph_compiler_mips.cc b/runtime/vm/flow_graph_compiler_mips.cc
index a98f0a5..114c060 100644
--- a/runtime/vm/flow_graph_compiler_mips.cc
+++ b/runtime/vm/flow_graph_compiler_mips.cc
@@ -905,6 +905,11 @@
 
   // Copy or initialize optional named arguments.
   Label all_arguments_processed;
+#ifdef DEBUG
+    const bool check_correct_named_args = true;
+#else
+    const bool check_correct_named_args = function.IsClosureFunction();
+#endif
   if (num_opt_named_params > 0) {
     __ Comment("There are named parameters");
     // Start by alphabetically sorting the names of the optional parameters.
@@ -974,10 +979,13 @@
     }
     delete[] opt_param;
     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);
+    if (check_correct_named_args) {
+      // Check that T0 now points to the null terminator in the arguments
+      // descriptor.
+      __ lw(T3, Address(T0));
+      __ BranchEqual(T3, reinterpret_cast<int32_t>(Object::null()),
+                     &all_arguments_processed);
+    }
   } else {
     ASSERT(num_opt_pos_params > 0);
     __ Comment("There are optional positional parameters");
@@ -1003,26 +1011,29 @@
       __ sw(T3, Address(FP, computed_param_pos * kWordSize));
       __ Bind(&next_parameter);
     }
-    __ lw(T1, FieldAddress(S4, ArgumentsDescriptor::count_offset()));
-    __ SmiUntag(T1);
-    // Check that T2 equals T1, i.e. no named arguments passed.
-    __ beq(T2, T1, &all_arguments_processed);
+    if (check_correct_named_args) {
+      __ lw(T1, FieldAddress(S4, ArgumentsDescriptor::count_offset()));
+      __ SmiUntag(T1);
+      // Check that T2 equals T1, i.e. no named arguments passed.
+      __ beq(T2, T1, &all_arguments_processed);
+    }
   }
 
   __ Bind(&wrong_num_arguments);
-  // Invoke noSuchMethod function passing the original name of the function.
-  // If the function is a closure function, use "call" as the original name.
-  const String& name = String::Handle(
-      function.IsClosureFunction() ? Symbols::Call().raw() : function.name());
-  const int kNumArgsChecked = 1;
-  const ICData& ic_data = ICData::ZoneHandle(
-      ICData::New(function, name, Object::null_array(),
-                  Isolate::kNoDeoptId, kNumArgsChecked));
-  __ LoadObject(S5, ic_data);
-  __ LeaveDartFrame();  // The arguments are still on the stack.
-  __ Branch(&StubCode::CallNoSuchMethodFunctionLabel());
-  // The noSuchMethod call may return to the caller, but not here.
-  __ break_(0);
+  if (function.IsClosureFunction()) {
+    // Invoke noSuchMethod function passing "call" as the original name.
+    const int kNumArgsChecked = 1;
+    const ICData& ic_data = ICData::ZoneHandle(
+        ICData::New(function, Symbols::Call(), Object::null_array(),
+                    Isolate::kNoDeoptId, kNumArgsChecked));
+    __ LoadObject(S5, ic_data);
+    __ LeaveDartFrame();  // The arguments are still on the stack.
+    __ Branch(&StubCode::CallNoSuchMethodFunctionLabel());
+    // The noSuchMethod call may return to the caller, but not here.
+    __ break_(0);
+  } else if (check_correct_named_args) {
+    __ Stop("Wrong arguments");
+  }
 
   __ Bind(&all_arguments_processed);
   // Nullify originally passed arguments only after they have been copied and
diff --git a/runtime/vm/flow_graph_compiler_x64.cc b/runtime/vm/flow_graph_compiler_x64.cc
index 4375d7f..b2f730c 100644
--- a/runtime/vm/flow_graph_compiler_x64.cc
+++ b/runtime/vm/flow_graph_compiler_x64.cc
@@ -893,6 +893,11 @@
   const Immediate& raw_null =
       Immediate(reinterpret_cast<intptr_t>(Object::null()));
   Label all_arguments_processed;
+#ifdef DEBUG
+    const bool check_correct_named_args = true;
+#else
+    const bool check_correct_named_args = function.IsClosureFunction();
+#endif
   if (num_opt_named_params > 0) {
     // Start by alphabetically sorting the names of the optional parameters.
     LocalVariable** opt_param = new LocalVariable*[num_opt_named_params];
@@ -960,9 +965,12 @@
     }
     delete[] opt_param;
     delete[] opt_param_position;
-    // Check that RDI now points to the null terminator in the array descriptor.
-    __ cmpq(Address(RDI, 0), raw_null);
-    __ j(EQUAL, &all_arguments_processed, Assembler::kNearJump);
+    if (check_correct_named_args) {
+      // Check that RDI now points to the null terminator in the arguments
+      // descriptor.
+      __ cmpq(Address(RDI, 0), raw_null);
+      __ j(EQUAL, &all_arguments_processed, Assembler::kNearJump);
+    }
   } else {
     ASSERT(num_opt_pos_params > 0);
     __ movq(RCX,
@@ -989,27 +997,30 @@
       __ movq(param_addr, RAX);
       __ Bind(&next_parameter);
     }
-    __ movq(RBX, FieldAddress(R10, ArgumentsDescriptor::count_offset()));
-    __ SmiUntag(RBX);
-    // Check that RCX equals RBX, i.e. no named arguments passed.
-    __ cmpq(RCX, RBX);
-    __ j(EQUAL, &all_arguments_processed, Assembler::kNearJump);
+    if (check_correct_named_args) {
+      __ movq(RBX, FieldAddress(R10, ArgumentsDescriptor::count_offset()));
+      __ SmiUntag(RBX);
+      // Check that RCX equals RBX, i.e. no named arguments passed.
+      __ cmpq(RCX, RBX);
+      __ j(EQUAL, &all_arguments_processed, Assembler::kNearJump);
+    }
   }
 
   __ Bind(&wrong_num_arguments);
-  // Invoke noSuchMethod function passing the original name of the function.
-  // If the function is a closure function, use "call" as the original name.
-  const String& name = String::Handle(
-      function.IsClosureFunction() ? Symbols::Call().raw() : function.name());
-  const int kNumArgsChecked = 1;
-  const ICData& ic_data = ICData::ZoneHandle(
-      ICData::New(function, name, Object::null_array(),
-                  Isolate::kNoDeoptId, kNumArgsChecked));
-  __ LoadObject(RBX, ic_data);
-  __ LeaveFrame();  // The arguments are still on the stack.
-  __ jmp(&StubCode::CallNoSuchMethodFunctionLabel());
-  // The noSuchMethod call may return to the caller, but not here.
-  __ int3();
+  if (function.IsClosureFunction()) {
+    // Invoke noSuchMethod function passing "call" as the original name.
+    const int kNumArgsChecked = 1;
+    const ICData& ic_data = ICData::ZoneHandle(
+        ICData::New(function, Symbols::Call(), Object::null_array(),
+                    Isolate::kNoDeoptId, kNumArgsChecked));
+    __ LoadObject(RBX, ic_data);
+    __ LeaveFrame();  // The arguments are still on the stack.
+    __ jmp(&StubCode::CallNoSuchMethodFunctionLabel());
+    // The noSuchMethod call may return to the caller, but not here.
+    __ int3();
+  } else if (check_correct_named_args) {
+    __ Stop("Wrong arguments");
+  }
 
   __ Bind(&all_arguments_processed);
   // Nullify originally passed arguments only after they have been copied and
diff --git a/runtime/vm/flow_graph_inliner.cc b/runtime/vm/flow_graph_inliner.cc
index 4c51acf..b22eda0 100644
--- a/runtime/vm/flow_graph_inliner.cc
+++ b/runtime/vm/flow_graph_inliner.cc
@@ -370,7 +370,8 @@
   FlowGraph* caller_graph() const { return caller_graph_; }
 
   // Inlining heuristics based on Cooper et al. 2008.
-  bool ShouldWeInline(intptr_t instr_count,
+  bool ShouldWeInline(const Function& callee,
+                      intptr_t instr_count,
                       intptr_t call_site_count,
                       intptr_t const_arg_count) {
     if (inlined_size_ > FLAG_inlining_caller_size_threshold) {
@@ -387,6 +388,9 @@
         (instr_count <= FLAG_inlining_constant_arguments_size_threshold)) {
       return true;
     }
+    if (MethodRecognizer::AlwaysInline(callee)) {
+      return true;
+    }
     return false;
   }
 
@@ -462,7 +466,8 @@
 
     GrowableArray<Value*>* arguments = call_data->arguments;
     const intptr_t constant_arguments = CountConstants(*arguments);
-    if (!ShouldWeInline(function.optimized_instruction_count(),
+    if (!ShouldWeInline(function,
+                        function.optimized_instruction_count(),
                         function.optimized_call_site_count(),
                         constant_arguments)) {
       TRACE_INLINING(OS::Print("     Bailout: early heuristics with "
@@ -608,7 +613,7 @@
       function.set_optimized_call_site_count(call_site_count);
 
       // Use heuristics do decide if this call should be inlined.
-      if (!ShouldWeInline(size, call_site_count, constants_count)) {
+      if (!ShouldWeInline(function, size, call_site_count, constants_count)) {
         // If size is larger than all thresholds, don't consider it again.
         if ((size > FLAG_inlining_size_threshold) &&
             (call_site_count > FLAG_inlining_callee_call_sites_threshold) &&
@@ -750,8 +755,9 @@
           continue;
         }
       }
-      if ((call_info[call_idx].ratio * 100) < FLAG_inlining_hotness) {
-        const Function& target = call->function();
+      const Function& target = call->function();
+      if (!MethodRecognizer::AlwaysInline(target) &&
+          (call_info[call_idx].ratio * 100) < FLAG_inlining_hotness) {
         TRACE_INLINING(OS::Print(
             "  => %s (deopt count %d)\n     Bailout: cold %f\n",
             target.ToCString(),
@@ -812,7 +818,8 @@
 
       const ICData& ic_data = call->ic_data();
       const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(0));
-      if ((call_info[call_idx].ratio * 100) < FLAG_inlining_hotness) {
+      if (!MethodRecognizer::AlwaysInline(target) &&
+          (call_info[call_idx].ratio * 100) < FLAG_inlining_hotness) {
         TRACE_INLINING(OS::Print(
             "  => %s (deopt count %d)\n     Bailout: cold %f\n",
             target.ToCString(),
diff --git a/runtime/vm/flow_graph_optimizer.cc b/runtime/vm/flow_graph_optimizer.cc
index 1665cb9..a350e07 100644
--- a/runtime/vm/flow_graph_optimizer.cc
+++ b/runtime/vm/flow_graph_optimizer.cc
@@ -6,6 +6,7 @@
 
 #include "vm/bit_vector.h"
 #include "vm/cha.h"
+#include "vm/dart_entry.h"
 #include "vm/flow_graph_builder.h"
 #include "vm/flow_graph_compiler.h"
 #include "vm/hash_map.h"
@@ -102,16 +103,16 @@
     return false;
   }
   if (class_ids[0] != kDynamicCid) {
-    const intptr_t num_named_arguments = call->argument_names().IsNull() ?
-        0 : call->argument_names().Length();
+    ArgumentsDescriptor args_desc(
+        Array::Handle(ArgumentsDescriptor::New(call->ArgumentCount(),
+                                               call->argument_names())));
     const Class& receiver_class = Class::Handle(
         Isolate::Current()->class_table()->At(class_ids[0]));
-    Function& function = Function::Handle();
-    function = Resolver::ResolveDynamicForReceiverClass(
-        receiver_class,
-        call->function_name(),
-        call->ArgumentCount(),
-        num_named_arguments);
+    const Function& function = Function::Handle(
+        Resolver::ResolveDynamicForReceiverClass(
+            receiver_class,
+            call->function_name(),
+            args_desc));
     if (function.IsNull()) {
       return false;
     }
@@ -229,9 +230,9 @@
     // Replace Mint op with Smi op.
     BinarySmiOpInstr* smi_op = new BinarySmiOpInstr(
         Token::kBIT_AND,
-        bit_and_instr->AsBinaryMintOp()->instance_call(),
         new Value(left_instr),
-        new Value(right_instr));
+        new Value(right_instr),
+        bit_and_instr->deopt_id());
     bit_and_instr->ReplaceWith(smi_op, current_iterator());
   }
 }
@@ -733,7 +734,7 @@
   InsertBefore(call,
                new CheckArrayBoundInstr(new Value(length),
                                         new Value(*index),
-                                        call),
+                                        call->deopt_id()),
                call->env(),
                Definition::kEffect);
 
@@ -1105,25 +1106,25 @@
     InsertBefore(call,
                  new CheckEitherNonSmiInstr(new Value(left),
                                             new Value(right),
-                                            call),
+                                            call->deopt_id()),
                  call->env(),
                  Definition::kEffect);
 
     BinaryDoubleOpInstr* double_bin_op =
         new BinaryDoubleOpInstr(op_kind, new Value(left), new Value(right),
-                                call);
+                                call->deopt_id());
     ReplaceCall(call, double_bin_op);
   } else if (operands_type == kMintCid) {
     if (!FlowGraphCompiler::SupportsUnboxedMints()) return false;
     if ((op_kind == Token::kSHR) || (op_kind == Token::kSHL)) {
       ShiftMintOpInstr* shift_op =
           new ShiftMintOpInstr(op_kind, new Value(left), new Value(right),
-                               call);
+                               call->deopt_id());
       ReplaceCall(call, shift_op);
     } else {
       BinaryMintOpInstr* bin_op =
           new BinaryMintOpInstr(op_kind, new Value(left), new Value(right),
-                                call);
+                                call->deopt_id());
       ReplaceCall(call, bin_op);
     }
   } else if (operands_type == kFloat32x4Cid) {
@@ -1184,9 +1185,10 @@
     ConstantInstr* constant =
         flow_graph()->GetConstant(Smi::Handle(Smi::New(value - 1)));
     BinarySmiOpInstr* bin_op =
-        new BinarySmiOpInstr(Token::kBIT_AND, call,
+        new BinarySmiOpInstr(Token::kBIT_AND,
                              new Value(left),
-                             new Value(constant));
+                             new Value(constant),
+                             call->deopt_id());
     ReplaceCall(call, bin_op);
   } else {
     ASSERT(operands_type == kSmiCid);
@@ -1202,7 +1204,8 @@
       right = temp;
     }
     BinarySmiOpInstr* bin_op =
-        new BinarySmiOpInstr(op_kind, call, new Value(left), new Value(right));
+        new BinarySmiOpInstr(op_kind, new Value(left), new Value(right),
+                             call->deopt_id());
     ReplaceCall(call, bin_op);
   }
   return true;
@@ -1219,11 +1222,12 @@
                  new CheckSmiInstr(new Value(input), call->deopt_id()),
                  call->env(),
                  Definition::kEffect);
-    unary_op = new UnarySmiOpInstr(op_kind, call, new Value(input));
+    unary_op = new UnarySmiOpInstr(op_kind, new Value(input), call->deopt_id());
   } else if ((op_kind == Token::kBIT_NOT) &&
              HasOnlySmiOrMint(*call->ic_data()) &&
              FlowGraphCompiler::SupportsUnboxedMints()) {
-    unary_op = new UnaryMintOpInstr(op_kind, new Value(input), call);
+    unary_op = new UnaryMintOpInstr(
+        op_kind, new Value(input), call->deopt_id());
   } else if (HasOnlyOneDouble(*call->ic_data()) &&
              (op_kind == Token::kNEGATE)) {
     AddReceiverCheck(call);
@@ -1232,7 +1236,7 @@
     unary_op = new BinaryDoubleOpInstr(Token::kMUL,
                                        new Value(input),
                                        new Value(minus_one),
-                                       call);
+                                       call->deopt_id());
   }
   if (unary_op == NULL) return false;
 
@@ -1614,7 +1618,7 @@
     InsertBefore(call,
                  new CheckArrayBoundInstr(new Value(length),
                                           new Value(index),
-                                          call),
+                                          call->deopt_id()),
                  call->env(),
                  Definition::kEffect);
   }
@@ -1769,7 +1773,7 @@
           d2i_instr = new DoubleToIntegerInstr(new Value(input), call);
         } else {
           // Optimistically assume result fits into Smi.
-          d2i_instr = new DoubleToSmiInstr(new Value(input), call);
+          d2i_instr = new DoubleToSmiInstr(new Value(input), call->deopt_id());
         }
         ReplaceCall(call, d2i_instr);
         return true;
@@ -1788,8 +1792,7 @@
           AddReceiverCheck(call);
           DoubleToDoubleInstr* d2d_instr =
               new DoubleToDoubleInstr(new Value(call->ArgumentAt(0)),
-                                      call,
-                                      recognized_kind);
+                                      recognized_kind, call->deopt_id());
           ReplaceCall(call, d2d_instr);
         }
         return true;
@@ -2238,16 +2241,16 @@
       flow_graph()->GetConstant(Smi::Handle(Smi::New(element_size)));
   BinarySmiOpInstr* len_in_bytes =
       new BinarySmiOpInstr(Token::kMUL,
-                           call,
                            new Value(length),
-                           new Value(bytes_per_element));
+                           new Value(bytes_per_element),
+                           call->deopt_id());
   InsertBefore(call, len_in_bytes, call->env(), Definition::kValue);
 
     // Check byte_index < len_in_bytes.
   InsertBefore(call,
                new CheckArrayBoundInstr(new Value(len_in_bytes),
                                         new Value(byte_index),
-                                        call),
+                                        call->deopt_id()),
                call->env(),
                Definition::kEffect);
 
@@ -2656,12 +2659,14 @@
       Isolate::Current()->class_table()->At(receiver_cid));
 
   // Resolve equality operator.
+  const intptr_t kNumArgs = 2;
+  ArgumentsDescriptor args_desc(
+      Array::Handle(ArgumentsDescriptor::New(kNumArgs)));
   const Function& function = Function::Handle(
       Resolver::ResolveDynamicForReceiverClass(
           receiver_class,
           Symbols::EqualOperator(),
-          2,
-          0));
+          args_desc));
 
   if (function.IsNull()) {
     return false;
diff --git a/runtime/vm/flow_graph_type_propagator.cc b/runtime/vm/flow_graph_type_propagator.cc
index 3006a6a..53bfab2 100644
--- a/runtime/vm/flow_graph_type_propagator.cc
+++ b/runtime/vm/flow_graph_type_propagator.cc
@@ -412,8 +412,8 @@
   if (ToAbstractType()->IsMoreSpecificThan(*other->ToAbstractType(),
                                            &malformed_error)) {
     type_ = other->ToAbstractType();
-  } else if (ToAbstractType()->IsMoreSpecificThan(*ToAbstractType(),
-                                                  &malformed_error)) {
+  } else if (other->ToAbstractType()->IsMoreSpecificThan(*ToAbstractType(),
+                                                         &malformed_error)) {
     // Nothing to do.
   } else {
     // Can't unify.
diff --git a/runtime/vm/gc_marker.cc b/runtime/vm/gc_marker.cc
index b7ae253..c5b5dc8 100644
--- a/runtime/vm/gc_marker.cc
+++ b/runtime/vm/gc_marker.cc
@@ -14,6 +14,7 @@
 #include "vm/raw_object.h"
 #include "vm/stack_frame.h"
 #include "vm/visitor.h"
+#include "vm/object_id_ring.h"
 
 namespace dart {
 
@@ -399,6 +400,33 @@
 }
 
 
+class ObjectIdRingClearPointerVisitor : public ObjectPointerVisitor {
+ public:
+  explicit ObjectIdRingClearPointerVisitor(Isolate* isolate) :
+      ObjectPointerVisitor(isolate) {}
+
+
+  void VisitPointers(RawObject** first, RawObject** last) {
+    for (RawObject** current = first; current <= last; current++) {
+      RawObject* raw_obj = *current;
+      ASSERT(raw_obj->IsHeapObject());
+      if (raw_obj->IsOldObject() && !raw_obj->IsMarked()) {
+        // Object has become garbage. Replace it will null.
+        *current = Object::null();
+      }
+    }
+  }
+};
+
+
+void GCMarker::ProcessObjectIdTable(Isolate* isolate) {
+  ObjectIdRingClearPointerVisitor visitor(isolate);
+  ObjectIdRing* ring = isolate->object_id_ring();
+  ASSERT(ring != NULL);
+  ring->VisitPointers(&visitor);
+}
+
+
 void GCMarker::MarkObjects(Isolate* isolate,
                            PageSpace* page_space,
                            bool invoke_api_callbacks) {
@@ -412,6 +440,9 @@
   IterateWeakRoots(isolate, &mark_weak, invoke_api_callbacks);
   mark.Finalize();
   ProcessWeakTables(page_space);
+  ProcessObjectIdTable(isolate);
+
+
   Epilogue(isolate, invoke_api_callbacks);
 }
 
diff --git a/runtime/vm/gc_marker.h b/runtime/vm/gc_marker.h
index 36c899c..422d062 100644
--- a/runtime/vm/gc_marker.h
+++ b/runtime/vm/gc_marker.h
@@ -42,6 +42,8 @@
   void DrainMarkingStack(Isolate* isolate, MarkingVisitor* visitor);
   void ProcessWeakProperty(RawWeakProperty* raw_weak, MarkingVisitor* visitor);
   void ProcessWeakTables(PageSpace* page_space);
+  void ProcessObjectIdTable(Isolate* isolate);
+
 
   Heap* heap_;
 
diff --git a/runtime/vm/heap.cc b/runtime/vm/heap.cc
index 59691e8..851f6a6 100644
--- a/runtime/vm/heap.cc
+++ b/runtime/vm/heap.cc
@@ -36,7 +36,7 @@
             "old gen heap size in MB,"
             "e.g: --old_gen_heap_size=1024 allocates a 1024MB old gen heap");
 
-  Heap::Heap() : read_only_(false), gc_in_progress_(false) {
+Heap::Heap() : read_only_(false), gc_in_progress_(false) {
   for (int sel = 0;
        sel < kNumWeakSelectors;
        sel++) {
diff --git a/runtime/vm/intermediate_language.cc b/runtime/vm/intermediate_language.cc
index b04cc21..84e3fdc 100644
--- a/runtime/vm/intermediate_language.cc
+++ b/runtime/vm/intermediate_language.cc
@@ -336,7 +336,8 @@
   // List of libraries where methods can be recognized.
   return (library.raw() == Library::CoreLibrary())
       || (library.raw() == Library::MathLibrary())
-      || (library.raw() == Library::TypedDataLibrary());
+      || (library.raw() == Library::TypedDataLibrary())
+      || (library.raw() == Library::CollectionDevLibrary());
 }
 
 
@@ -363,6 +364,28 @@
 }
 
 
+bool MethodRecognizer::AlwaysInline(const Function& function) {
+  const Class& function_class = Class::Handle(function.Owner());
+  const Library& lib = Library::Handle(function_class.library());
+  if (!IsRecognizedLibrary(lib)) {
+    return false;
+  }
+
+  const String& function_name = String::Handle(function.name());
+  const String& class_name = String::Handle(function_class.Name());
+
+#define RECOGNIZE_FUNCTION(test_class_name, test_function_name, enum_name, fp) \
+  if (CompareNames(lib, #test_function_name, function_name) &&                 \
+      CompareNames(lib, #test_class_name, class_name)) {                       \
+    ASSERT(function.CheckSourceFingerprint(fp));                               \
+    return true;                                                               \
+  }
+INLINE_WHITE_LIST(RECOGNIZE_FUNCTION)
+#undef RECOGNIZE_FUNCTION
+  return false;
+}
+
+
 const char* MethodRecognizer::KindToCString(Kind kind) {
 #define KIND_TO_STRING(class_name, function_name, enum_name, fp)               \
   if (kind == k##enum_name) return #enum_name;
diff --git a/runtime/vm/intermediate_language.h b/runtime/vm/intermediate_language.h
index df01ffb..49d2a54 100644
--- a/runtime/vm/intermediate_language.h
+++ b/runtime/vm/intermediate_language.h
@@ -121,6 +121,11 @@
   V(_Uint32x4, _toFloat32x4, Uint32x4ToUint32x4, 912844231)                    \
 
 
+// A list of core function that should always be inlined.
+#define INLINE_WHITE_LIST(V)                                                   \
+  V(ListIterator, moveNext, ListIteratorMoveNext, 203118278)                   \
+  V(_GrowableObjectArray, get:iterator, GrowableArrayIterator, 810824939)
+
 // Class that recognizes the name and owner of a function and returns the
 // corresponding enum. See RECOGNIZED_LIST above for list of recognizable
 // functions.
@@ -134,6 +139,7 @@
   };
 
   static Kind RecognizeKind(const Function& function);
+  static bool AlwaysInline(const Function& function);
   static const char* KindToCString(Kind kind);
 };
 
@@ -4324,10 +4330,11 @@
  public:
   CheckEitherNonSmiInstr(Value* left,
                          Value* right,
-                         InstanceCallInstr* instance_call) {
+                         intptr_t deopt_id) {
     SetInputAt(0, left);
     SetInputAt(1, right);
-    deopt_id_ = instance_call->deopt_id();
+    // Override generated deopt-id.
+    deopt_id_ = deopt_id;
   }
 
   Value* left() const { return inputs_[0]; }
@@ -4654,11 +4661,12 @@
   BinaryDoubleOpInstr(Token::Kind op_kind,
                       Value* left,
                       Value* right,
-                      InstanceCallInstr* instance_call)
+                      intptr_t deopt_id)
       : op_kind_(op_kind) {
     SetInputAt(0, left);
     SetInputAt(1, right);
-    deopt_id_ = instance_call->deopt_id();
+    // Overrided generated deopt_id.
+    deopt_id_ = deopt_id;
   }
 
   Value* left() const { return inputs_[0]; }
@@ -5672,12 +5680,12 @@
   BinaryMintOpInstr(Token::Kind op_kind,
                            Value* left,
                            Value* right,
-                           InstanceCallInstr* instance_call)
-      : op_kind_(op_kind),
-        instance_call_(instance_call) {
+                           intptr_t deopt_id)
+      : op_kind_(op_kind) {
     SetInputAt(0, left);
     SetInputAt(1, right);
-    deopt_id_ = instance_call->deopt_id();
+    // Override generated deopt-id.
+    deopt_id_ = deopt_id;
   }
 
   Value* left() const { return inputs_[0]; }
@@ -5685,8 +5693,6 @@
 
   Token::Kind op_kind() const { return op_kind_; }
 
-  InstanceCallInstr* instance_call() const { return instance_call_; }
-
   virtual void PrintOperandsTo(BufferFormatter* f) const;
 
   virtual bool CanDeoptimize() const {
@@ -5725,7 +5731,6 @@
 
  private:
   const Token::Kind op_kind_;
-  InstanceCallInstr* instance_call_;
 
   DISALLOW_COPY_AND_ASSIGN(BinaryMintOpInstr);
 };
@@ -5736,12 +5741,13 @@
   ShiftMintOpInstr(Token::Kind op_kind,
                    Value* left,
                    Value* right,
-                   InstanceCallInstr* instance_call)
+                   intptr_t deopt_id)
       : op_kind_(op_kind) {
     ASSERT(op_kind == Token::kSHR || op_kind == Token::kSHL);
     SetInputAt(0, left);
     SetInputAt(1, right);
-    deopt_id_ = instance_call->deopt_id();
+    // Override generated deopt-id.
+    deopt_id_ = deopt_id;
   }
 
   Value* left() const { return inputs_[0]; }
@@ -5790,13 +5796,12 @@
 
 class UnaryMintOpInstr : public TemplateDefinition<1> {
  public:
-  UnaryMintOpInstr(Token::Kind op_kind,
-                          Value* value,
-                          InstanceCallInstr* instance_call)
+  UnaryMintOpInstr(Token::Kind op_kind, Value* value, intptr_t deopt_id)
       : op_kind_(op_kind) {
     ASSERT(op_kind == Token::kBIT_NOT);
     SetInputAt(0, value);
-    deopt_id_ = instance_call->deopt_id();
+    // Override generated deopt-id.
+    deopt_id_ = deopt_id;
   }
 
   Value* value() const { return inputs_[0]; }
@@ -5844,16 +5849,16 @@
 class BinarySmiOpInstr : public TemplateDefinition<2> {
  public:
   BinarySmiOpInstr(Token::Kind op_kind,
-                   InstanceCallInstr* instance_call,
                    Value* left,
-                   Value* right)
+                   Value* right,
+                   intptr_t deopt_id)
       : op_kind_(op_kind),
-        instance_call_(instance_call),
         overflow_(true),
         is_truncating_(false) {
     SetInputAt(0, left);
     SetInputAt(1, right);
-    deopt_id_ = instance_call->deopt_id();
+    // Override generated deopt-id.
+    deopt_id_ = deopt_id;
   }
 
   Value* left() const { return inputs_[0]; }
@@ -5861,10 +5866,6 @@
 
   Token::Kind op_kind() const { return op_kind_; }
 
-  InstanceCallInstr* instance_call() const { return instance_call_; }
-
-  const ICData* ic_data() const { return instance_call()->ic_data(); }
-
   void set_overflow(bool overflow) { overflow_ = overflow; }
 
   void set_is_truncating(bool value) { is_truncating_ = value; }
@@ -5896,7 +5897,6 @@
 
  private:
   const Token::Kind op_kind_;
-  InstanceCallInstr* instance_call_;
   bool overflow_;
   bool is_truncating_;
 
@@ -5908,12 +5908,13 @@
 class UnarySmiOpInstr : public TemplateDefinition<1> {
  public:
   UnarySmiOpInstr(Token::Kind op_kind,
-                  InstanceCallInstr* instance_call,
-                  Value* value)
+                  Value* value,
+                  intptr_t deopt_id)
       : op_kind_(op_kind) {
     ASSERT((op_kind == Token::kNEGATE) || (op_kind == Token::kBIT_NOT));
     SetInputAt(0, value);
-    deopt_id_ = instance_call->deopt_id();
+    // Override generated deopt-id.
+    deopt_id_ = deopt_id;
   }
 
   Value* value() const { return inputs_[0]; }
@@ -6035,9 +6036,10 @@
 // and creates a Smi.
 class DoubleToSmiInstr : public TemplateDefinition<1> {
  public:
-  DoubleToSmiInstr(Value* value, InstanceCallInstr* instance_call) {
+  DoubleToSmiInstr(Value* value, intptr_t deopt_id) {
     SetInputAt(0, value);
-    deopt_id_ = instance_call->deopt_id();
+    // Override generated deopt-id.
+    deopt_id_ = deopt_id;
   }
 
   Value* value() const { return inputs_[0]; }
@@ -6066,11 +6068,12 @@
 class DoubleToDoubleInstr : public TemplateDefinition<1> {
  public:
   DoubleToDoubleInstr(Value* value,
-                      InstanceCallInstr* instance_call,
-                      MethodRecognizer::Kind recognized_kind)
+                      MethodRecognizer::Kind recognized_kind,
+                      intptr_t deopt_id)
     : recognized_kind_(recognized_kind) {
     SetInputAt(0, value);
-    deopt_id_ = instance_call->deopt_id();
+    // Override generated deopt-id.
+    deopt_id_ = deopt_id;
   }
 
   Value* value() const { return inputs_[0]; }
@@ -6252,12 +6255,11 @@
 
 class CheckArrayBoundInstr : public TemplateInstruction<2> {
  public:
-  CheckArrayBoundInstr(Value* length,
-                       Value* index,
-                       InstanceCallInstr* instance_call) {
+  CheckArrayBoundInstr(Value* length, Value* index, intptr_t deopt_id) {
     SetInputAt(kLengthPos, length);
     SetInputAt(kIndexPos, index);
-    deopt_id_ = instance_call->deopt_id();
+    // Override generated deopt-id.
+    deopt_id_ = deopt_id;
   }
 
   Value* length() const { return inputs_[kLengthPos]; }
diff --git a/runtime/vm/intermediate_language_arm.cc b/runtime/vm/intermediate_language_arm.cc
index d6f1736..ae18cca 100644
--- a/runtime/vm/intermediate_language_arm.cc
+++ b/runtime/vm/intermediate_language_arm.cc
@@ -172,7 +172,7 @@
 
 void LoadLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   Register result = locs()->out().reg();
-  __ LoadFromOffset(kLoadWord, result, FP, local().index() * kWordSize);
+  __ LoadFromOffset(kWord, result, FP, local().index() * kWordSize);
 }
 
 
@@ -1044,7 +1044,7 @@
 void LoadUntaggedInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   Register object = locs()->in(0).reg();
   Register result = locs()->out().reg();
-  __ LoadFromOffset(kLoadWord, result, object, offset() - kHeapObjectTag);
+  __ LoadFromOffset(kWord, result, object, offset() - kHeapObjectTag);
 }
 
 
@@ -1701,7 +1701,7 @@
 void LoadStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   Register field = locs()->in(0).reg();
   Register result = locs()->out().reg();
-  __ LoadFromOffset(kLoadWord, result,
+  __ LoadFromOffset(kWord, result,
                     field, Field::value_offset() - kHeapObjectTag);
 }
 
@@ -1809,7 +1809,7 @@
   Register instance_reg = locs()->in(0).reg();
   Register result_reg = locs()->out().reg();
 
-  __ LoadFromOffset(kLoadWord, result_reg,
+  __ LoadFromOffset(kWord, result_reg,
                     instance_reg, offset_in_bytes() - kHeapObjectTag);
 }
 
@@ -2044,9 +2044,9 @@
 
   ASSERT(!exception_var().is_captured());
   ASSERT(!stacktrace_var().is_captured());
-  __ StoreToOffset(kStoreWord, kExceptionObjectReg,
+  __ StoreToOffset(kWord, kExceptionObjectReg,
                    FP, exception_var().index() * kWordSize);
-  __ StoreToOffset(kStoreWord, kStackTraceObjectReg,
+  __ StoreToOffset(kWord, kStackTraceObjectReg,
                    FP, stacktrace_var().index() * kWordSize);
 
   // Restore the pool pointer.
@@ -3200,7 +3200,7 @@
   }
 
   // Load receiver into R0.
-  __ LoadFromOffset(kLoadWord, R0, SP,
+  __ LoadFromOffset(kWord, R0, SP,
                     (instance_call()->ArgumentCount() - 1) * kWordSize);
 
   LoadValueCid(compiler, R2, R0,
diff --git a/runtime/vm/intrinsifier_arm.cc b/runtime/vm/intrinsifier_arm.cc
index 1da04b9..4faae9f 100644
--- a/runtime/vm/intrinsifier_arm.cc
+++ b/runtime/vm/intrinsifier_arm.cc
@@ -1396,13 +1396,13 @@
       FlowGraphCompiler::DataOffsetFor(kTypedDataUint32ArrayCid);
 
   __ LoadImmediate(R0, a_int32_value);
-  __ LoadFromOffset(kLoadWord, R2, R1, disp_0 - kHeapObjectTag);
-  __ LoadFromOffset(kLoadWord, R3, R1, disp_1 - kHeapObjectTag);
+  __ LoadFromOffset(kWord, R2, R1, disp_0 - kHeapObjectTag);
+  __ LoadFromOffset(kWord, R3, R1, disp_1 - kHeapObjectTag);
   __ mov(R6, ShifterOperand(0));  // Zero extend unsigned _state[kSTATE_HI].
   // Unsigned 32-bit multiply and 64-bit accumulate into R6:R3.
   __ umlal(R3, R6, R0, R2);  // R6:R3 <- R6:R3 + R0 * R2.
-  __ StoreToOffset(kStoreWord, R3, R1, disp_0 - kHeapObjectTag);
-  __ StoreToOffset(kStoreWord, R6, R1, disp_1 - kHeapObjectTag);
+  __ StoreToOffset(kWord, R3, R1, disp_0 - kHeapObjectTag);
+  __ StoreToOffset(kWord, R6, R1, disp_1 - kHeapObjectTag);
   __ Ret();
   return true;
 }
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index 76e6235..5c5f977 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -26,6 +26,7 @@
 #include "vm/thread.h"
 #include "vm/timer.h"
 #include "vm/visitor.h"
+#include "vm/object_id_ring.h"
 
 namespace dart {
 
@@ -415,6 +416,7 @@
       stacktrace_(NULL),
       stack_frame_index_(-1),
       object_histogram_(NULL),
+      object_id_ring_(NULL),
       REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_INITIALIZERS)
       reusable_handles_() {
   if (FLAG_print_object_histogram && (Dart::vm_isolate() != NULL)) {
diff --git a/runtime/vm/isolate.h b/runtime/vm/isolate.h
index 27ad1ea..b8eb6c2 100644
--- a/runtime/vm/isolate.h
+++ b/runtime/vm/isolate.h
@@ -55,6 +55,7 @@
 class TypeArguments;
 class TypeParameter;
 class ObjectHistogram;
+class ObjectIdRing;
 
 
 // Used by the deoptimization infrastructure to defer allocation of unboxed
@@ -533,6 +534,13 @@
   }
   intptr_t deopt_frame_copy_size() const { return deopt_frame_copy_size_; }
 
+  void set_object_id_ring(ObjectIdRing* ring) {
+    object_id_ring_ = ring;
+  }
+  ObjectIdRing* object_id_ring() {
+    return object_id_ring_;
+  }
+
   void PrepareForDeferredMaterialization(intptr_t count) {
     if (count > 0) {
       deferred_objects_ = new DeferredObject*[count];
@@ -686,6 +694,9 @@
   intptr_t stack_frame_index_;
   ObjectHistogram* object_histogram_;
 
+  // Ring buffer of objects assigned an id.
+  ObjectIdRing* object_id_ring_;
+
   // Reusable handles support.
 #define REUSABLE_HANDLE_FIELDS(object)                                         \
   object* object##_handle_;                                                    \
diff --git a/runtime/vm/mirrors_api_impl.cc b/runtime/vm/mirrors_api_impl.cc
index 917d54d..dcc9495 100644
--- a/runtime/vm/mirrors_api_impl.cc
+++ b/runtime/vm/mirrors_api_impl.cc
@@ -261,7 +261,7 @@
         // Skip implicit getters and setters.
         if (func.kind() == RawFunction::kImplicitGetter ||
             func.kind() == RawFunction::kImplicitSetter ||
-            func.kind() == RawFunction::kConstImplicitGetter ||
+            func.kind() == RawFunction::kImplicitStaticFinalGetter ||
             func.kind() == RawFunction::kMethodExtractor ||
             func.kind() == RawFunction::kNoSuchMethodDispatcher) {
           continue;
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 6e89a43..a16190e 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -1444,15 +1444,14 @@
     const Class& canonical_class = Class::Handle(function.signature_class());
     return canonical_class.SignatureType();
   }
-  // Return the first canonical signature type if already computed.
+  // Return the first canonical signature type if already computed at class
+  // finalization time. The optimizer may canonicalize instantiated function
+  // types of the same signature class, but these will be added after the
+  // uninstantiated signature class at index 0.
   const Array& signature_types = Array::Handle(canonical_types());
   // The canonical_types array is initialized to the empty array.
   ASSERT(!signature_types.IsNull());
   if (signature_types.Length() > 0) {
-    // At most one signature type per signature class.
-    ASSERT((signature_types.Length() == 1) ||
-           ((signature_types.Length() == 2) &&
-            (signature_types.At(1) == Type::null())));
     Type& signature_type = Type::Handle();
     signature_type ^= signature_types.At(0);
     ASSERT(!signature_type.IsNull());
@@ -2738,6 +2737,10 @@
   ReusableHandleScope reused_handles(isolate);
   Array& flds = reused_handles.ArrayHandle();
   flds ^= fields();
+  if (flds.IsNull()) {
+    // This can occur, e.g., for Null classes.
+    return Field::null();
+  }
   Field& field = reused_handles.FieldHandle();
   String& field_name = reused_handles.StringHandle();
   intptr_t len = flds.Length();
@@ -4093,8 +4096,8 @@
 }
 
 
-bool Function::AreValidArgumentCounts(int num_arguments,
-                                      int num_named_arguments,
+bool Function::AreValidArgumentCounts(intptr_t num_arguments,
+                                      intptr_t num_named_arguments,
                                       String* error_message) const {
   if (num_named_arguments > NumOptionalNamedParameters()) {
     if (error_message != NULL) {
@@ -4102,7 +4105,7 @@
       char message_buffer[kMessageBufferSize];
       OS::SNPrint(message_buffer,
                   kMessageBufferSize,
-                  "%d named passed, at most %"Pd" expected",
+                  "%"Pd" named passed, at most %"Pd" expected",
                   num_named_arguments,
                   NumOptionalNamedParameters());
       *error_message = String::New(message_buffer);
@@ -4150,10 +4153,10 @@
 }
 
 
-bool Function::AreValidArguments(int num_arguments,
+bool Function::AreValidArguments(intptr_t num_arguments,
                                  const Array& argument_names,
                                  String* error_message) const {
-  const int num_named_arguments =
+  const intptr_t num_named_arguments =
       argument_names.IsNull() ? 0 : argument_names.Length();
   if (!AreValidArgumentCounts(num_arguments,
                               num_named_arguments,
@@ -4164,13 +4167,61 @@
   Isolate* isolate = Isolate::Current();
   String& argument_name = String::Handle(isolate);
   String& parameter_name = String::Handle(isolate);
-  for (int i = 0; i < num_named_arguments; i++) {
+  for (intptr_t i = 0; i < num_named_arguments; i++) {
     argument_name ^= argument_names.At(i);
     ASSERT(argument_name.IsSymbol());
     bool found = false;
-    const int num_positional_args = num_arguments - num_named_arguments;
+    const intptr_t num_positional_args = num_arguments - num_named_arguments;
+    const intptr_t num_parameters = NumParameters();
+    for (intptr_t j = num_positional_args;
+         !found && (j < num_parameters);
+         j++) {
+      parameter_name = ParameterNameAt(j);
+      ASSERT(argument_name.IsSymbol());
+      if (argument_name.Equals(parameter_name)) {
+        found = true;
+      }
+    }
+    if (!found) {
+      if (error_message != NULL) {
+        const intptr_t kMessageBufferSize = 64;
+        char message_buffer[kMessageBufferSize];
+        OS::SNPrint(message_buffer,
+                    kMessageBufferSize,
+                    "no optional formal parameter named '%s'",
+                    argument_name.ToCString());
+        *error_message = String::New(message_buffer);
+      }
+      return false;
+    }
+  }
+  return true;
+}
+
+
+bool Function::AreValidArguments(const ArgumentsDescriptor& args_desc,
+                                 String* error_message) const {
+  const intptr_t num_arguments = args_desc.Count();
+  const intptr_t num_named_arguments = args_desc.NamedCount();
+
+  if (!AreValidArgumentCounts(num_arguments,
+                              num_named_arguments,
+                              error_message)) {
+    return false;
+  }
+  // Verify that all argument names are valid parameter names.
+  Isolate* isolate = Isolate::Current();
+  String& argument_name = String::Handle(isolate);
+  String& parameter_name = String::Handle(isolate);
+  for (intptr_t i = 0; i < num_named_arguments; i++) {
+    argument_name ^= args_desc.NameAt(i);
+    ASSERT(argument_name.IsSymbol());
+    bool found = false;
+    const intptr_t num_positional_args = num_arguments - num_named_arguments;
     const int num_parameters = NumParameters();
-    for (int j = num_positional_args; !found && (j < num_parameters); j++) {
+    for (intptr_t j = num_positional_args;
+         !found && (j < num_parameters);
+         j++) {
       parameter_name = ParameterNameAt(j);
       ASSERT(argument_name.IsSymbol());
       if (argument_name.Equals(parameter_name)) {
@@ -4873,8 +4924,8 @@
     case RawFunction::kImplicitSetter:
       kind_str = " setter";
       break;
-    case RawFunction::kConstImplicitGetter:
-      kind_str = " const-getter";
+    case RawFunction::kImplicitStaticFinalGetter:
+      kind_str = " static-final-getter";
       break;
     case RawFunction::kMethodExtractor:
       kind_str = " method-extractor";
@@ -10504,11 +10555,7 @@
     if (type.IsNull()) {
       break;
     }
-    if (!type.IsFinalized()) {
-      ASSERT((index == 0) && cls.IsSignatureClass());
-      index++;
-      continue;
-    }
+    ASSERT(type.IsFinalized());
     if (this->Equals(type)) {
       return type.raw();
     }
@@ -10529,6 +10576,30 @@
   } else {
     canonical_types.SetAt(index, *this);
   }
+#ifdef DEBUG
+  if ((index == 0) && cls.IsCanonicalSignatureClass()) {
+    // Verify that the first canonical type is the signature type by checking
+    // that the type argument vector of the canonical type ends with the
+    // uninstantiated type parameters of the signature class.
+    // The signature type is finalized during class finalization, before the
+    // optimizer may canonicalize instantiated function types of the same
+    // signature class.
+    // Although the signature class extends class Instance, the type arguments
+    // of the super class of the owner class of its signature function will be
+    // prepended to the type argument vector during class finalization.
+    const TypeArguments& type_params =
+      TypeArguments::Handle(cls.type_parameters());
+    const intptr_t num_type_params = cls.NumTypeParameters();
+    const intptr_t num_type_args = cls.NumTypeArguments();
+    TypeParameter& type_arg = TypeParameter::Handle();
+    TypeParameter& type_param = TypeParameter::Handle();
+    for (intptr_t i = 0; i < num_type_params; i++) {
+      type_arg ^= type_args.TypeAt(num_type_args - num_type_params + i);
+      type_param ^= type_params.TypeAt(i);
+      ASSERT(type_arg.Equals(type_param));
+    }
+  }
+#endif
   ASSERT(IsOld());
   SetCanonical();
   return this->raw();
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index e298739..fb7f36b 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -27,6 +27,7 @@
 CLASS_LIST(DEFINE_FORWARD_DECLARATION)
 #undef DEFINE_FORWARD_DECLARATION
 class Api;
+class ArgumentsDescriptor;
 class Assembler;
 class Closure;
 class Code;
@@ -688,6 +689,8 @@
   // 'F<T, R>(T, [b: B, c: C]) => R', then its signature type is a parameterized
   // type with this class as the type class and type parameters 'T' and 'R'
   // as its type argument vector.
+  // SignatureType is used as the type of formal parameters representing a
+  // function.
   RawType* SignatureType() const;
 
   RawLibrary* library() const { return raw_ptr()->library_; }
@@ -1494,7 +1497,7 @@
         return true;
       case RawFunction::kClosureFunction:
       case RawFunction::kConstructor:
-      case RawFunction::kConstImplicitGetter:
+      case RawFunction::kImplicitStaticFinalGetter:
         return false;
       default:
         UNREACHABLE();
@@ -1511,7 +1514,7 @@
       case RawFunction::kSetterFunction:
       case RawFunction::kImplicitGetter:
       case RawFunction::kImplicitSetter:
-      case RawFunction::kConstImplicitGetter:
+      case RawFunction::kImplicitStaticFinalGetter:
         return true;
       case RawFunction::kClosureFunction:
       case RawFunction::kConstructor:
@@ -1636,16 +1639,18 @@
 
   // Returns true if the argument counts are valid for calling this function.
   // Otherwise, it returns false and the reason (if error_message is not NULL).
-  bool AreValidArgumentCounts(int num_arguments,
-                              int num_named_arguments,
+  bool AreValidArgumentCounts(intptr_t num_arguments,
+                              intptr_t num_named_arguments,
                               String* error_message) const;
 
   // Returns true if the total argument count and the names of optional
   // arguments are valid for calling this function.
   // Otherwise, it returns false and the reason (if error_message is not NULL).
-  bool AreValidArguments(int num_arguments,
+  bool AreValidArguments(intptr_t num_arguments,
                          const Array& argument_names,
                          String* error_message) const;
+  bool AreValidArguments(const ArgumentsDescriptor& args_desc,
+                         String* error_message) const;
 
   // Fully qualified name uniquely identifying the function under gdb and during
   // ast printing. The special ':' character, if present, is replaced by '_'.
diff --git a/runtime/vm/object_id_ring.cc b/runtime/vm/object_id_ring.cc
new file mode 100644
index 0000000..f7199bd
--- /dev/null
+++ b/runtime/vm/object_id_ring.cc
@@ -0,0 +1,164 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#include "platform/assert.h"
+#include "vm/dart_api_state.h"
+#include "vm/object_id_ring.h"
+
+namespace dart {
+
+void ObjectIdRing::Init(Isolate* isolate, int32_t capacity) {
+  ObjectIdRing* ring = new ObjectIdRing(isolate, capacity);
+  isolate->set_object_id_ring(ring);
+}
+
+
+ObjectIdRing::~ObjectIdRing() {
+  ASSERT(table_ != NULL);
+  free(table_);
+  table_ = NULL;
+  if (isolate_ != NULL) {
+    isolate_->set_object_id_ring(NULL);
+    isolate_ = NULL;
+  }
+}
+
+
+int32_t ObjectIdRing::GetIdForObject(RawObject* object) {
+  return AllocateNewId(object);
+}
+
+
+RawObject* ObjectIdRing::GetObjectForId(int32_t id) {
+  int32_t index = IndexOfId(id);
+  if (index == kInvalidId) {
+    return Object::null();
+  }
+  ASSERT(index >= 0);
+  ASSERT(index < capacity_);
+  return table_[index];
+}
+
+
+void ObjectIdRing::VisitPointers(ObjectPointerVisitor* visitor) {
+  ASSERT(table_ != NULL);
+  visitor->VisitPointers(table_, capacity_);
+}
+
+
+ObjectIdRing::ObjectIdRing(Isolate* isolate, int32_t capacity) {
+  ASSERT(capacity > 0);
+  isolate_ = isolate;
+  serial_num_ = 0;
+  wrapped_ = false;
+  table_ = NULL;
+  SetCapacityAndMaxSerial(capacity, kMaxId);
+}
+
+
+void ObjectIdRing::SetCapacityAndMaxSerial(int32_t capacity,
+                                           int32_t max_serial) {
+  ASSERT(max_serial <= kMaxId);
+  capacity_ = capacity;
+  if (table_ != NULL) {
+    free(table_);
+  }
+  table_ = reinterpret_cast<RawObject**>(calloc(capacity_, kWordSize));
+  for (int i = 0; i < capacity_; i++) {
+    table_[i] = Object::null();
+  }
+  // The maximum serial number is a multiple of the capacity, so that when
+  // the serial number wraps, the index into table_ wraps with it.
+  max_serial_ = max_serial - (max_serial % capacity_);
+}
+
+
+int32_t ObjectIdRing::NextSerial() {
+  int32_t r = serial_num_;
+  serial_num_++;
+  if (serial_num_ >= max_serial_) {
+    serial_num_ = 0;
+    wrapped_ = true;
+  }
+  return r;
+}
+
+
+int32_t ObjectIdRing::AllocateNewId(RawObject* raw_obj) {
+  ASSERT(raw_obj->IsHeapObject());
+  int32_t id = NextSerial();
+  ASSERT(id != kInvalidId);
+  int32_t cursor = IndexOfId(id);
+  ASSERT(cursor != kInvalidId);
+  if (table_[cursor] != Object::null()) {
+    // Free old handle.
+    table_[cursor] = Object::null();
+  }
+  ASSERT(table_[cursor] == Object::null());
+  table_[cursor] = raw_obj;
+  return id;
+}
+
+
+int32_t ObjectIdRing::IndexOfId(int32_t id) {
+  if (!IsValidId(id)) {
+    return kInvalidId;
+  }
+  ASSERT((id >= 0) && (id < max_serial_));
+  return id % capacity_;
+}
+
+
+bool ObjectIdRing::IsValidContiguous(int32_t id) {
+  ASSERT(id != kInvalidId);
+  ASSERT((id >= 0) && (id < max_serial_));
+  if (id >= serial_num_) {
+    // Too large.
+    return false;
+  }
+  int32_t bottom = 0;
+  if (serial_num_ >= capacity_) {
+    bottom = serial_num_ - capacity_;
+  }
+  return id >= bottom;
+}
+
+
+bool ObjectIdRing::IsValidId(int32_t id) {
+  if (id == kInvalidId) {
+    return false;
+  }
+  if (id >= max_serial_) {
+    return false;
+  }
+  ASSERT((id >= 0) && (id < max_serial_));
+  if (wrapped_) {
+    // Serial number has wrapped around to 0.
+    if (serial_num_ >= capacity_) {
+      // Serial number is larger than capacity, the serial
+      // numbers are contiguous again.
+      wrapped_ = false;
+      return IsValidContiguous(id);
+    } else {
+      // When the serial number first wraps, the valid serial number range
+      // spans two intervals:
+      // #1 [0, serial_num_)
+      // #2 [max_serial_ - (capacity_ - serial_num), max_serial_)
+      //
+      // Check for both.
+      if (id < serial_num_) {
+        // Interval #1
+        return true;
+      }
+      // Interval #2
+      const int32_t max_serial_num = max_serial_;
+      const int32_t bottom = max_serial_num - (capacity_ - serial_num_);
+      return id >= bottom && bottom < max_serial_num;
+    }
+  }
+  ASSERT(wrapped_ == false);
+  return IsValidContiguous(id);
+}
+
+}  // namespace dart
diff --git a/runtime/vm/object_id_ring.h b/runtime/vm/object_id_ring.h
new file mode 100644
index 0000000..b0dfee7
--- /dev/null
+++ b/runtime/vm/object_id_ring.h
@@ -0,0 +1,66 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#ifndef VM_OBJECT_ID_RING_H_
+#define VM_OBJECT_ID_RING_H_
+
+namespace dart {
+
+// Forward declarations.
+class RawObject;
+class Isolate;
+class ObjectPointerVisitor;
+
+// A ring buffer of object pointers that have been given an id. An object
+// may be pointed to by multiple ids. Objects contained in the ring will
+// be preserved across scavenges but not old space collections.
+// When the ring buffer wraps around older objects will be replaced and their
+// ids will be invalidated.
+class ObjectIdRing {
+ public:
+  static const int32_t kMaxId = 0x3FFFFFFF;
+  static const int32_t kInvalidId = -1;
+  static const int32_t kDefaultCapacity = 1024;
+
+  static void Init(Isolate* isolate, int32_t capacity = kDefaultCapacity);
+
+  ~ObjectIdRing();
+
+  int32_t GetIdForObject(RawObject* raw_obj);
+  RawObject* GetObjectForId(int32_t id);
+
+  void VisitPointers(ObjectPointerVisitor* visitor);
+
+ private:
+  friend class ObjectIdRingTestHelper;
+
+  void SetCapacityAndMaxSerial(int32_t capacity, int32_t max_serial);
+
+  ObjectIdRing(Isolate* isolate, int32_t capacity);
+  Isolate* isolate_;
+  RawObject** table_;
+  int32_t max_serial_;
+  int32_t capacity_;
+  int32_t serial_num_;
+  bool wrapped_;
+
+  RawObject** table() {
+    return table_;
+  }
+  int32_t table_size() {
+    return capacity_;
+  }
+
+  int32_t NextSerial();
+  int32_t AllocateNewId(RawObject* object);
+  int32_t IndexOfId(int32_t id);
+  bool IsValidContiguous(int32_t id);
+  bool IsValidId(int32_t id);
+
+  DISALLOW_COPY_AND_ASSIGN(ObjectIdRing);
+};
+
+}  // namespace dart
+
+#endif  // VM_OBJECT_ID_RING_H_
diff --git a/runtime/vm/object_id_ring_test.cc b/runtime/vm/object_id_ring_test.cc
new file mode 100644
index 0000000..aeae8e2
--- /dev/null
+++ b/runtime/vm/object_id_ring_test.cc
@@ -0,0 +1,192 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#include "platform/assert.h"
+#include "vm/globals.h"
+#include "vm/object_id_ring.h"
+#include "vm/unit_test.h"
+#include "vm/dart_api_impl.h"
+#include "vm/dart_api_state.h"
+
+namespace dart {
+
+
+class ObjectIdRingTestHelper {
+ public:
+  static void SetCapacityAndMaxSerial(ObjectIdRing* ring, int32_t capacity,
+                                      int32_t max_serial) {
+    ring->SetCapacityAndMaxSerial(capacity, max_serial);
+  }
+
+  static void ExpectIdIsValid(ObjectIdRing* ring, intptr_t id) {
+    EXPECT(ring->IsValidId(id));
+  }
+
+  static void ExpectIdIsInvalid(ObjectIdRing* ring, intptr_t id) {
+    EXPECT(!ring->IsValidId(id));
+  }
+
+  static RawObject* MakeString(const char* s) {
+    return String::New(s);
+  }
+
+  static void ExpectString(RawObject* obj, const char* s) {
+    String& str = String::Handle();
+    str ^= obj;
+    EXPECT(str.Equals(s));
+  }
+};
+
+
+// Test that serial number wrapping works.
+TEST_CASE(ObjectIdRingSerialWrapTest) {
+  Isolate* isolate = Isolate::Current();
+  ObjectIdRing* ring = isolate->object_id_ring();
+  ObjectIdRingTestHelper::SetCapacityAndMaxSerial(ring, 2, 4);
+  intptr_t id;
+  id = ring->GetIdForObject(ObjectIdRingTestHelper::MakeString("0"));
+  EXPECT_EQ(0, id);
+  id = ring->GetIdForObject(ObjectIdRingTestHelper::MakeString("1"));
+  EXPECT_EQ(1, id);
+  // Test that id 1 gives us the "1" string.
+  ObjectIdRingTestHelper::ExpectString(ring->GetObjectForId(id), "1");
+  ObjectIdRingTestHelper::ExpectIdIsValid(ring, 0);
+  ObjectIdRingTestHelper::ExpectIdIsValid(ring, 1);
+  ObjectIdRingTestHelper::ExpectIdIsInvalid(ring, 2);
+  ObjectIdRingTestHelper::ExpectIdIsInvalid(ring, 3);
+  id = ring->GetIdForObject(ObjectIdRingTestHelper::MakeString("2"));
+  EXPECT_EQ(2, id);
+  ObjectIdRingTestHelper::ExpectIdIsInvalid(ring, 0);
+  ObjectIdRingTestHelper::ExpectIdIsValid(ring, 1);
+  ObjectIdRingTestHelper::ExpectIdIsValid(ring, 2);
+  ObjectIdRingTestHelper::ExpectIdIsInvalid(ring, 3);
+  id = ring->GetIdForObject(ObjectIdRingTestHelper::MakeString("3"));
+  EXPECT_EQ(3, id);
+  ObjectIdRingTestHelper::ExpectIdIsInvalid(ring, 0);
+  ObjectIdRingTestHelper::ExpectIdIsInvalid(ring, 1);
+  ObjectIdRingTestHelper::ExpectIdIsValid(ring, 2);
+  ObjectIdRingTestHelper::ExpectIdIsValid(ring, 3);
+  id = ring->GetIdForObject(ObjectIdRingTestHelper::MakeString("4"));
+  EXPECT_EQ(0, id);
+  ObjectIdRingTestHelper::ExpectString(ring->GetObjectForId(id), "4");
+  ObjectIdRingTestHelper::ExpectIdIsValid(ring, 0);
+  ObjectIdRingTestHelper::ExpectIdIsInvalid(ring, 1);
+  ObjectIdRingTestHelper::ExpectIdIsInvalid(ring, 2);
+  ObjectIdRingTestHelper::ExpectIdIsValid(ring, 3);
+  id = ring->GetIdForObject(ObjectIdRingTestHelper::MakeString("5"));
+  EXPECT_EQ(1, id);
+  ObjectIdRingTestHelper::ExpectString(ring->GetObjectForId(id), "5");
+  ObjectIdRingTestHelper::ExpectIdIsValid(ring, 0);
+  ObjectIdRingTestHelper::ExpectIdIsValid(ring, 1);
+  ObjectIdRingTestHelper::ExpectIdIsInvalid(ring, 2);
+  ObjectIdRingTestHelper::ExpectIdIsInvalid(ring, 3);
+}
+
+
+// Test that the ring table is updated when the scavenger moves an object.
+TEST_CASE(ObjectIdRingScavengeMoveTest) {
+  const char* kScriptChars =
+  "main() {\n"
+  "  return [1, 2, 3];\n"
+  "}\n";
+  Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
+  Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL);
+  intptr_t list_length = 0;
+  EXPECT_VALID(result);
+  EXPECT(!Dart_IsNull(result));
+  EXPECT(Dart_IsList(result));
+  EXPECT_VALID(Dart_ListLength(result, &list_length));
+  EXPECT_EQ(3, list_length);
+  Isolate* isolate = Isolate::Current();
+  Heap* heap = isolate->heap();
+  ObjectIdRing* ring = isolate->object_id_ring();
+  RawObject* raw_obj = Api::UnwrapHandle(result);
+  // Located in new heap.
+  EXPECT(raw_obj->IsNewObject());
+  EXPECT_NE(Object::null(), raw_obj);
+  intptr_t raw_obj_id1 = ring->GetIdForObject(raw_obj);
+  EXPECT_EQ(0, raw_obj_id1);
+  intptr_t raw_obj_id2 = ring->GetIdForObject(raw_obj);
+  EXPECT_EQ(1, raw_obj_id2);
+  intptr_t raw_obj_id3 = ring->GetIdForObject(Object::null());
+  RawObject* raw_obj1 = ring->GetObjectForId(raw_obj_id1);
+  RawObject* raw_obj2 = ring->GetObjectForId(raw_obj_id2);
+  RawObject* raw_obj3 = ring->GetObjectForId(raw_obj_id3);
+  EXPECT_NE(Object::null(), raw_obj1);
+  EXPECT_NE(Object::null(), raw_obj2);
+  EXPECT_EQ(Object::null(), raw_obj3);
+  EXPECT_EQ(RawObject::ToAddr(raw_obj), RawObject::ToAddr(raw_obj1));
+  EXPECT_EQ(RawObject::ToAddr(raw_obj), RawObject::ToAddr(raw_obj2));
+  // Force a scavenge.
+  heap->CollectGarbage(Heap::kNew);
+  RawObject* raw_object_moved1 = ring->GetObjectForId(raw_obj_id1);
+  RawObject* raw_object_moved2 = ring->GetObjectForId(raw_obj_id2);
+  RawObject* raw_object_moved3 = ring->GetObjectForId(raw_obj_id3);
+  EXPECT_NE(Object::null(), raw_object_moved1);
+  EXPECT_NE(Object::null(), raw_object_moved2);
+  EXPECT_EQ(Object::null(), raw_object_moved3);
+  EXPECT_EQ(RawObject::ToAddr(raw_object_moved1),
+            RawObject::ToAddr(raw_object_moved2));
+  // Test that objects have moved.
+  EXPECT_NE(RawObject::ToAddr(raw_obj1), RawObject::ToAddr(raw_object_moved1));
+  EXPECT_NE(RawObject::ToAddr(raw_obj2), RawObject::ToAddr(raw_object_moved2));
+  // Test that we still point at the same list.
+  Dart_Handle moved_handle = Api::NewHandle(isolate, raw_object_moved1);
+  EXPECT_VALID(moved_handle);
+  EXPECT(!Dart_IsNull(moved_handle));
+  EXPECT(Dart_IsList(moved_handle));
+  EXPECT_VALID(Dart_ListLength(moved_handle, &list_length));
+  EXPECT_EQ(3, list_length);
+}
+
+
+// Test that the ring table is updated with nulls when the old GC collects.
+TEST_CASE(ObjectIdRingOldGCTest) {
+  Isolate* isolate = Isolate::Current();
+  Heap* heap = isolate->heap();
+  ObjectIdRing* ring = isolate->object_id_ring();
+
+  intptr_t raw_obj_id1 = -1;
+  intptr_t raw_obj_id2 = -1;
+  {
+    Dart_EnterScope();
+    Dart_Handle result;
+    // Create a string in the old heap.
+    result = Api::NewHandle(isolate, String::New("old", Heap::kOld));
+    EXPECT_VALID(result);
+    intptr_t string_length = 0;
+    // Inspect string.
+    EXPECT(!Dart_IsNull(result));
+    EXPECT(Dart_IsString(result));
+    EXPECT_VALID(Dart_StringLength(result, &string_length));
+    EXPECT_EQ(3, string_length);
+    RawObject* raw_obj = Api::UnwrapHandle(result);
+    // Verify that it is located in old heap.
+    EXPECT(raw_obj->IsOldObject());
+    EXPECT_NE(Object::null(), raw_obj);
+    raw_obj_id1 = ring->GetIdForObject(raw_obj);
+    EXPECT_EQ(0, raw_obj_id1);
+    raw_obj_id2 = ring->GetIdForObject(raw_obj);
+    EXPECT_EQ(1, raw_obj_id2);
+    RawObject* raw_obj1 = ring->GetObjectForId(raw_obj_id1);
+    RawObject* raw_obj2 = ring->GetObjectForId(raw_obj_id2);
+    EXPECT_NE(Object::null(), raw_obj1);
+    EXPECT_NE(Object::null(), raw_obj2);
+    EXPECT_EQ(RawObject::ToAddr(raw_obj), RawObject::ToAddr(raw_obj1));
+    EXPECT_EQ(RawObject::ToAddr(raw_obj), RawObject::ToAddr(raw_obj2));
+    // Exit scope. Freeing result handle.
+    Dart_ExitScope();
+  }
+  // Force a GC. No reference exist to the old string anymore. It should be
+  // collected and the object id ring will now return the null object for
+  // those ids.
+  heap->CollectGarbage(Heap::kOld);
+  RawObject* raw_object_moved1 = ring->GetObjectForId(raw_obj_id1);
+  RawObject* raw_object_moved2 = ring->GetObjectForId(raw_obj_id2);
+  // Objects should now be null.
+  EXPECT_EQ(Object::null(), raw_object_moved1);
+  EXPECT_EQ(Object::null(), raw_object_moved2);
+}
+
+}  // namespace dart
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
index fb1bed9..60c57bc 100644
--- a/runtime/vm/parser.cc
+++ b/runtime/vm/parser.cc
@@ -766,8 +766,8 @@
       ASSERT(!func.is_static());
       node_sequence = parser.ParseInstanceSetter(func);
       break;
-    case RawFunction::kConstImplicitGetter:
-      node_sequence = parser.ParseStaticConstGetter(func);
+    case RawFunction::kImplicitStaticFinalGetter:
+      node_sequence = parser.ParseStaticFinalGetter(func);
       break;
     case RawFunction::kMethodExtractor:
       node_sequence = parser.ParseMethodExtractor(func);
@@ -878,11 +878,8 @@
 }
 
 
-// TODO(regis): Since a const variable is implicitly final,
-// rename ParseStaticConstGetter to ParseStaticFinalGetter and
-// rename kConstImplicitGetter to kImplicitFinalGetter.
-SequenceNode* Parser::ParseStaticConstGetter(const Function& func) {
-  TRACE_PARSER("ParseStaticConstGetter");
+SequenceNode* Parser::ParseStaticFinalGetter(const Function& func) {
+  TRACE_PARSER("ParseStaticFinalGetter");
   ParamList params;
   ASSERT(func.num_fixed_parameters() == 0);  // static.
   ASSERT(!func.HasOptionalParameters());
@@ -1582,7 +1579,7 @@
     const String& getter_name = String::ZoneHandle(Field::GetterName(name));
     super_func = Resolver::ResolveDynamicAnyArgs(super_class, getter_name);
     ASSERT(super_func.IsNull() ||
-           (super_func.kind() != RawFunction::kConstImplicitGetter));
+           (super_func.kind() != RawFunction::kImplicitStaticFinalGetter));
   }
   if (super_func.IsNull()) {
     super_func =
@@ -3139,13 +3136,13 @@
       ConsumeToken();
       init_value = Object::sentinel().raw();
       // For static const fields, the initialization expression
-      // will be parsed through the kConstImplicitGetter method
+      // will be parsed through the kImplicitStaticFinalGetter method
       // invocation/compilation.
       // For instance fields, the expression is parsed when a constructor
       // is compiled.
       // For static const fields with very simple initializer expressions
       // (e.g. a literal number or string) we optimize away the
-      // kConstImplicitGetter and initialize the field here.
+      // kImplicitStaticFinalGetter and initialize the field here.
       // We also do it for static final non-const fields, but only in production
       // mode.
 
@@ -3180,14 +3177,14 @@
       library_.AddFieldMetadata(class_field, field->metadata_pos);
     }
 
-    // For static const fields, set value to "uninitialized" and
-    // create a kConstImplicitGetter getter method.
+    // For static final fields (this includes static const fields), set value to
+    // "uninitialized" and create a kFinalImplicitGetter getter method.
     if (field->has_static && has_initializer) {
       class_field.set_value(init_value);
       if (!has_simple_literal) {
         String& getter_name = String::Handle(Field::GetterSymbol(*field->name));
         getter = Function::New(getter_name,
-                               RawFunction::kConstImplicitGetter,
+                               RawFunction::kImplicitStaticFinalGetter,
                                field->has_static,
                                field->has_const,
                                /* is_abstract = */ false,
@@ -4305,7 +4302,7 @@
         // Create a static const getter.
         String& getter_name = String::ZoneHandle(Field::GetterSymbol(var_name));
         getter = Function::New(getter_name,
-                               RawFunction::kConstImplicitGetter,
+                               RawFunction::kImplicitStaticFinalGetter,
                                is_static,
                                is_const,
                                /* is_abstract = */ false,
@@ -7641,7 +7638,7 @@
                                      Object::empty_array(),
                                      Resolver::kIsQualified);
       if (!func.IsNull()) {
-        ASSERT(func.kind() != RawFunction::kConstImplicitGetter);
+        ASSERT(func.kind() != RawFunction::kImplicitStaticFinalGetter);
         EnsureSavedCurrentContext();
         closure = new StaticGetterNode(call_pos,
                                        NULL,
@@ -7723,7 +7720,7 @@
   if (getter.IsNull()) {
     return new LoadStaticFieldNode(ident_pos, Field::ZoneHandle(field.raw()));
   } else {
-    ASSERT(getter.kind() == RawFunction::kConstImplicitGetter);
+    ASSERT(getter.kind() == RawFunction::kImplicitStaticFinalGetter);
     return new StaticGetterNode(ident_pos,
                                 NULL,  // Receiver.
                                 false,  // is_super_getter.
@@ -7808,7 +7805,7 @@
         }
         access = CreateImplicitClosureNode(func, call_pos, NULL);
       } else {
-        ASSERT(func.kind() != RawFunction::kConstImplicitGetter);
+        ASSERT(func.kind() != RawFunction::kImplicitStaticFinalGetter);
         access = new StaticGetterNode(call_pos,
                                       NULL,
                                       false,
@@ -8371,7 +8368,7 @@
                                                    Object::empty_array(),
                                                    Resolver::kIsQualified));
       ASSERT(!func.IsNull());
-      ASSERT(func.kind() == RawFunction::kConstImplicitGetter);
+      ASSERT(func.kind() == RawFunction::kImplicitStaticFinalGetter);
       Object& const_value = Object::Handle(
           DartEntry::InvokeFunction(func, Object::empty_array()));
       if (const_value.IsError()) {
@@ -8405,7 +8402,8 @@
                                   field_name);
     }
   }
-  if (getter.IsNull() || (getter.kind() == RawFunction::kConstImplicitGetter)) {
+  if (getter.IsNull() ||
+      (getter.kind() == RawFunction::kImplicitStaticFinalGetter)) {
     return NULL;
   }
   ASSERT(getter.kind() == RawFunction::kImplicitGetter);
diff --git a/runtime/vm/parser.h b/runtime/vm/parser.h
index baac074..cca62c0 100644
--- a/runtime/vm/parser.h
+++ b/runtime/vm/parser.h
@@ -435,7 +435,7 @@
 
   SequenceNode* ParseInstanceGetter(const Function& func);
   SequenceNode* ParseInstanceSetter(const Function& func);
-  SequenceNode* ParseStaticConstGetter(const Function& func);
+  SequenceNode* ParseStaticFinalGetter(const Function& func);
   SequenceNode* ParseMethodExtractor(const Function& func);
   SequenceNode* ParseNoSuchMethodDispatcher(const Function& func,
                                             Array& default_values);
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index 2c8c137..6ec46b3 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -597,7 +597,8 @@
     kConstructor,
     kImplicitGetter,     // represents an implicit getter for fields.
     kImplicitSetter,     // represents an implicit setter for fields.
-    kConstImplicitGetter,  // represents an implicit const getter for fields.
+    kImplicitStaticFinalGetter,  // represents an implicit getter for static
+                                 // final fields (incl. static const fields).
     kMethodExtractor,  // converts method into implicit closure on the receiver.
     kNoSuchMethodDispatcher,  // invokes noSuchMethod.
     kInvokeFieldDispatcher,  // invokes a field as a closure.
diff --git a/runtime/vm/resolver.cc b/runtime/vm/resolver.cc
index 9833fe7..dffbd73 100644
--- a/runtime/vm/resolver.cc
+++ b/runtime/vm/resolver.cc
@@ -4,6 +4,7 @@
 
 #include "vm/resolver.h"
 
+#include "vm/dart_entry.h"
 #include "vm/flags.h"
 #include "vm/isolate.h"
 #include "vm/object.h"
@@ -23,8 +24,7 @@
 // arguments is passed in.
 RawFunction* Resolver::ResolveDynamic(const Instance& receiver,
                                       const String& function_name,
-                                      int num_arguments,
-                                      int num_named_arguments) {
+                                      const ArgumentsDescriptor& args_desc) {
   // Figure out type of receiver first.
   Class& cls = Class::Handle();
   cls = receiver.clazz();
@@ -34,33 +34,27 @@
   }
   ASSERT(!cls.IsNull());
 
-  return ResolveDynamicForReceiverClass(
-      cls, function_name, num_arguments, num_named_arguments);
+  return ResolveDynamicForReceiverClass(cls, function_name, args_desc);
 }
 
 
 RawFunction* Resolver::ResolveDynamicForReceiverClass(
     const Class& receiver_class,
     const String& function_name,
-    int num_arguments,
-    int num_named_arguments) {
+    const ArgumentsDescriptor& args_desc) {
 
   Function& function =
       Function::Handle(ResolveDynamicAnyArgs(receiver_class, function_name));
 
   if (function.IsNull() ||
-      !function.AreValidArgumentCounts(num_arguments,
-                                       num_named_arguments,
-                                       NULL)) {
+      !function.AreValidArguments(args_desc, NULL)) {
     // Return a null function to signal to the upper levels to dispatch to
     // "noSuchMethod" function.
     if (FLAG_trace_resolving) {
       String& error_message = String::Handle(String::New("function not found"));
       if (!function.IsNull()) {
         // Obtain more detailed error message.
-        function.AreValidArgumentCounts(num_arguments,
-                                        num_named_arguments,
-                                        &error_message);
+        function.AreValidArguments(args_desc, &error_message);
       }
       OS::Print("ResolveDynamic error '%s': %s.\n",
                 function_name.ToCString(),
@@ -154,7 +148,7 @@
 RawFunction* Resolver::ResolveStatic(const Library& library,
                                      const String& class_name,
                                      const String& function_name,
-                                     int num_arguments,
+                                     intptr_t num_arguments,
                                      const Array& argument_names,
                                      StaticResolveType resolve_type) {
   ASSERT(!library.IsNull());
@@ -230,7 +224,7 @@
 
 RawFunction* Resolver::ResolveStatic(const Class&  cls,
                                      const String& function_name,
-                                     int num_arguments,
+                                     intptr_t num_arguments,
                                      const Array& argument_names,
                                      StaticResolveType resolve_type) {
   const Function& function = Function::Handle(
diff --git a/runtime/vm/resolver.h b/runtime/vm/resolver.h
index 942ea56..a0f2b33 100644
--- a/runtime/vm/resolver.h
+++ b/runtime/vm/resolver.h
@@ -16,6 +16,7 @@
 class Library;
 class RawFunction;
 class String;
+class ArgumentsDescriptor;
 
 
 // Resolver abstracts functionality needed to resolve dart functions at
@@ -25,14 +26,12 @@
   // Resolve specified dart instance function.
   static RawFunction* ResolveDynamic(const Instance& receiver,
                                      const String& function_name,
-                                     int num_arguments,
-                                     int num_named_arguments);
+                                     const ArgumentsDescriptor& args_desc);
 
   static RawFunction* ResolveDynamicForReceiverClass(
       const Class& receiver_class,
       const String& function_name,
-      int num_arguments,
-      int num_named_arguments);
+      const ArgumentsDescriptor& args_desc);
 
   static RawFunction* ResolveDynamicAnyArgs(
       const Class& receiver_class,
@@ -52,7 +51,7 @@
   static RawFunction* ResolveStatic(const Library& library,
                                     const String& cls_name,
                                     const String& function_name,
-                                    int num_arguments,
+                                    intptr_t num_arguments,
                                     const Array& argument_names,
                                     StaticResolveType resolve_type);
 
@@ -64,7 +63,7 @@
   // Resolve specified dart static function with specified arity.
   static RawFunction* ResolveStatic(const Class&  cls,
                                     const String& function_name,
-                                    int num_arguments,
+                                    intptr_t num_arguments,
                                     const Array& argument_names,
                                     StaticResolveType resolve_type);
 };
diff --git a/runtime/vm/resolver_test.cc b/runtime/vm/resolver_test.cc
index 2f253ba..d64b6d3 100644
--- a/runtime/vm/resolver_test.cc
+++ b/runtime/vm/resolver_test.cc
@@ -170,15 +170,15 @@
 
   // Now try to resolve and invoke the instance function in this class.
   {
-    const int kNumPositionalArguments = 3;
-    const int kNumNamedArguments = 0;
+    const int kNumArguments = 3;
+    ArgumentsDescriptor args_desc(
+        Array::Handle(ArgumentsDescriptor::New(kNumArguments)));
     const Function& function = Function::Handle(
         Resolver::ResolveDynamic(receiver,
                                  function_name,
-                                 kNumPositionalArguments,
-                                 kNumNamedArguments));
+                                 args_desc));
     EXPECT(!function.IsNull());
-    const Array& args = Array::Handle(Array::New(kNumPositionalArguments));
+    const Array& args = Array::Handle(Array::New(kNumArguments));
     args.SetAt(0, receiver);
     const String& arg0 = String::Handle(String::New("junk"));
     args.SetAt(1, arg0);
@@ -191,27 +191,27 @@
 
   // Now try to resolve an instance function with invalid argument count.
   {
-    const int kNumPositionalArguments = 1;
-    const int kNumNamedArguments = 0;
+    const int kNumArguments = 1;
+    ArgumentsDescriptor args_desc(
+        Array::Handle(ArgumentsDescriptor::New(kNumArguments)));
     const Function& bad_function = Function::Handle(
         Resolver::ResolveDynamic(receiver,
                                  function_name,
-                                 kNumPositionalArguments,
-                                 kNumNamedArguments));
+                                 args_desc));
     EXPECT(bad_function.IsNull());
   }
 
   // Hierarchy walking.
   {
-    const int kNumPositionalArguments = 1;
-    const int kNumNamedArguments = 0;
+    const int kNumArguments = 1;
+    ArgumentsDescriptor args_desc(
+        Array::Handle(ArgumentsDescriptor::New(kNumArguments)));
     const String& super_function_name =
         String::Handle(String::New("dynCall"));
     const Function& super_function = Function::Handle(
         Resolver::ResolveDynamic(receiver,
                                  super_function_name,
-                                 kNumPositionalArguments,
-                                 kNumNamedArguments));
+                                 args_desc));
     EXPECT(!super_function.IsNull());
   }
 }
diff --git a/runtime/vm/scavenger.cc b/runtime/vm/scavenger.cc
index 8d6e4bf..17b95f2 100644
--- a/runtime/vm/scavenger.cc
+++ b/runtime/vm/scavenger.cc
@@ -17,6 +17,7 @@
 #include "vm/verifier.h"
 #include "vm/visitor.h"
 #include "vm/weak_table.h"
+#include "vm/object_id_ring.h"
 
 namespace dart {
 
@@ -404,6 +405,14 @@
 }
 
 
+void Scavenger::IterateObjectIdTable(Isolate* isolate,
+                                     ScavengerVisitor* visitor) {
+  ObjectIdRing* ring = isolate->object_id_ring();
+  ASSERT(ring != NULL);
+  ring->VisitPointers(visitor);
+}
+
+
 void Scavenger::IterateRoots(Isolate* isolate,
                              ScavengerVisitor* visitor,
                              bool visit_prologue_weak_persistent_handles) {
@@ -413,6 +422,7 @@
                                StackFrameIterator::kDontValidateFrames);
   int64_t middle = OS::GetCurrentTimeMicros();
   IterateStoreBuffers(isolate, visitor);
+  IterateObjectIdTable(isolate, visitor);
   int64_t end = OS::GetCurrentTimeMicros();
   heap_->RecordTime(kVisitIsolateRoots, middle - start);
   heap_->RecordTime(kIterateStoreBuffers, end - middle);
diff --git a/runtime/vm/scavenger.h b/runtime/vm/scavenger.h
index 2ff0033..8dd60ab 100644
--- a/runtime/vm/scavenger.h
+++ b/runtime/vm/scavenger.h
@@ -103,6 +103,7 @@
   uword FirstObjectStart() const { return to_->start() | object_alignment_; }
   void Prologue(Isolate* isolate, bool invoke_api_callbacks);
   void IterateStoreBuffers(Isolate* isolate, ScavengerVisitor* visitor);
+  void IterateObjectIdTable(Isolate* isolate, ScavengerVisitor* visitor);
   void IterateRoots(Isolate* isolate,
                     ScavengerVisitor* visitor,
                     bool visit_prologue_weak_persistent_handles);
diff --git a/runtime/vm/simulator_arm.cc b/runtime/vm/simulator_arm.cc
index 726a25c2..9fdb01e 100644
--- a/runtime/vm/simulator_arm.cc
+++ b/runtime/vm/simulator_arm.cc
@@ -447,7 +447,7 @@
                   "h/help -- print this help string\n"
                   "break <address> -- set break point at specified address\n"
                   "p/print <reg or value or *addr> -- print integer value\n"
-                  "pf/printfloat <sreg or *addr> -- print float value\n"
+                  "ps/printsingle <sreg or *addr> -- print float value\n"
                   "pd/printdouble <dreg or *addr> -- print double value\n"
                   "po/printobject <*reg or *addr> -- print object\n"
                   "si/stepi -- single step an instruction\n"
@@ -476,7 +476,8 @@
         } else {
           OS::Print("print <reg or value or *addr>\n");
         }
-      } else if ((strcmp(cmd, "pf") == 0) || (strcmp(cmd, "printfloat") == 0)) {
+      } else if ((strcmp(cmd, "ps") == 0) ||
+                 (strcmp(cmd, "printsingle") == 0)) {
         if (args == 2) {
           float fvalue;
           if (GetFValue(arg1, &fvalue)) {
@@ -2921,7 +2922,7 @@
     int64_t* s8m_64 = reinterpret_cast<int64_t*>(&s8m);
 
     if ((instr->Bits(8, 4) == 8) && (instr->Bit(4) == 0) &&
-        (instr->Bit(24) == 0)) {
+        (instr->Bits(23, 2) == 0)) {
       // Uses q registers.
       // Format(instr, "vadd.'sz 'qd, 'qn, 'qm");
       const int size = instr->Bits(20, 2);
@@ -2945,11 +2946,67 @@
         UNREACHABLE();
       }
     } else if ((instr->Bits(8, 4) == 13) && (instr->Bit(4) == 0) &&
-               (instr->Bit(24) == 0)) {
+               (instr->Bits(23, 2) == 0) && (instr->Bit(21) == 0)) {
       // Format(instr, "vadd.F32 'qd, 'qn, 'qm");
       for (int i = 0; i < 4; i++) {
         s8d.data_[i].f = s8n.data_[i].f + s8m.data_[i].f;
       }
+    } else if ((instr->Bits(8, 4) == 8) && (instr->Bit(4) == 0) &&
+               (instr->Bits(23, 2) == 2)) {
+      // Format(instr, "vsub.'sz 'qd, 'qn, 'qm");
+      const int size = instr->Bits(20, 2);
+      if (size == 0) {
+        for (int i = 0; i < 16; i++) {
+          s8d_8[i] = s8n_8[i] - s8m_8[i];
+        }
+      } else if (size == 1) {
+        for (int i = 0; i < 8; i++) {
+          s8d_16[i] = s8n_16[i] - s8m_16[i];
+        }
+      } else if (size == 2) {
+        for (int i = 0; i < 4; i++) {
+          s8d.data_[i].u = s8n.data_[i].u - s8m.data_[i].u;
+        }
+      } else if (size == 3) {
+        for (int i = 0; i < 2; i++) {
+          s8d_64[i] = s8n_64[i] - s8m_64[i];
+        }
+      } else {
+        UNREACHABLE();
+      }
+    } else if ((instr->Bits(8, 4) == 13) && (instr->Bit(4) == 0) &&
+               (instr->Bits(23, 2) == 0) && (instr->Bit(21) == 1)) {
+      // Format(instr, "vsub.F32 'qd, 'qn, 'qm");
+      for (int i = 0; i < 4; i++) {
+        s8d.data_[i].f = s8n.data_[i].f - s8m.data_[i].f;
+      }
+    } else if ((instr->Bits(8, 4) == 9) && (instr->Bit(4) == 1) &&
+               (instr->Bits(23, 2) == 0)) {
+      // Format(instr, "vmul.'sz 'qd, 'qn, 'qm");
+      const int size = instr->Bits(20, 2);
+      if (size == 0) {
+        for (int i = 0; i < 16; i++) {
+          s8d_8[i] = s8n_8[i] * s8m_8[i];
+        }
+      } else if (size == 1) {
+        for (int i = 0; i < 8; i++) {
+          s8d_16[i] = s8n_16[i] * s8m_16[i];
+        }
+      } else if (size == 2) {
+        for (int i = 0; i < 4; i++) {
+          s8d.data_[i].u = s8n.data_[i].u * s8m.data_[i].u;
+        }
+      } else if (size == 3) {
+        UnimplementedInstruction(instr);
+      } else {
+        UNREACHABLE();
+      }
+    } else if ((instr->Bits(8, 4) == 13) && (instr->Bit(4) == 1) &&
+               (instr->Bits(23, 2) == 2) && (instr->Bit(21) == 0)) {
+      // Format(instr, "vmul.F32 'qd, 'qn, 'qm");
+      for (int i = 0; i < 4; i++) {
+        s8d.data_[i].f = s8n.data_[i].f * s8m.data_[i].f;
+      }
     } else {
       UnimplementedInstruction(instr);
     }
@@ -2957,7 +3014,42 @@
     set_qregister(qd, s8d);
   } else {
     // Q == 0, Uses 64-bit D registers.
-    UnimplementedInstruction(instr);
+    if ((instr->Bits(23, 2) == 3) && (instr->Bits(20, 2) == 3) &&
+        (instr->Bits(10, 2) == 2) && (instr->Bit(4) == 0)) {
+      // Format(instr, "vtbl 'dd, 'dtbllist, 'dm");
+      DRegister dd = instr->DdField();
+      DRegister dm = instr->DmField();
+      int reg_count = instr->Bits(8, 2) + 1;
+      int start = (instr->Bit(7) << 4) | instr->Bits(16, 4);
+      int64_t table[4];
+
+      for (int i = 0; i < reg_count; i++) {
+        DRegister d = static_cast<DRegister>(start + i);
+        table[i] = get_dregister_bits(d);
+      }
+      for (int i = reg_count; i < 4; i++) {
+        table[i] = 0;
+      }
+
+
+      int64_t dm_value = get_dregister_bits(dm);
+      int64_t result;
+      int8_t* dm_bytes = reinterpret_cast<int8_t*>(&dm_value);
+      int8_t* result_bytes = reinterpret_cast<int8_t*>(&result);
+      int8_t* table_bytes = reinterpret_cast<int8_t*>(&table[0]);
+      for (int i = 0; i < 8; i++) {
+        int idx = dm_bytes[i];
+        if ((idx >= 0) && (idx < 256)) {
+          result_bytes[i] = table_bytes[idx];
+        } else {
+          result_bytes[i] = 0;
+        }
+      }
+
+      set_dregister_bits(dd, result);
+    } else {
+      UnimplementedInstruction(instr);
+    }
   }
 }
 
diff --git a/runtime/vm/stub_code_arm.cc b/runtime/vm/stub_code_arm.cc
index 040655e..ec602d6 100644
--- a/runtime/vm/stub_code_arm.cc
+++ b/runtime/vm/stub_code_arm.cc
@@ -47,10 +47,10 @@
 
   // Save exit frame information to enable stack walking as we are about
   // to transition to Dart VM C++ code.
-  __ StoreToOffset(kStoreWord, SP, R0, Isolate::top_exit_frame_info_offset());
+  __ StoreToOffset(kWord, SP, R0, Isolate::top_exit_frame_info_offset());
 
   // Save current Context pointer into Isolate structure.
-  __ StoreToOffset(kStoreWord, CTX, R0, Isolate::top_context_offset());
+  __ StoreToOffset(kWord, CTX, R0, Isolate::top_context_offset());
 
   // Cache Isolate pointer into CTX while executing runtime code.
   __ mov(CTX, ShifterOperand(R0));
@@ -83,14 +83,14 @@
 
   // Reset exit frame information in Isolate structure.
   __ LoadImmediate(R2, 0);
-  __ StoreToOffset(kStoreWord, R2, CTX, Isolate::top_exit_frame_info_offset());
+  __ StoreToOffset(kWord, R2, CTX, Isolate::top_exit_frame_info_offset());
 
   // Load Context pointer from Isolate structure into R2.
-  __ LoadFromOffset(kLoadWord, R2, CTX, Isolate::top_context_offset());
+  __ LoadFromOffset(kWord, R2, CTX, Isolate::top_context_offset());
 
   // Reset Context pointer in Isolate structure.
   __ LoadImmediate(R3, reinterpret_cast<intptr_t>(Object::null()));
-  __ StoreToOffset(kStoreWord, R3, CTX, Isolate::top_context_offset());
+  __ StoreToOffset(kWord, R3, CTX, Isolate::top_context_offset());
 
   // Cache Context pointer into CTX while executing Dart code.
   __ mov(CTX, ShifterOperand(R2));
@@ -138,10 +138,10 @@
 
   // Save exit frame information to enable stack walking as we are about
   // to transition to native code.
-  __ StoreToOffset(kStoreWord, SP, R0, Isolate::top_exit_frame_info_offset());
+  __ StoreToOffset(kWord, SP, R0, Isolate::top_exit_frame_info_offset());
 
   // Save current Context pointer into Isolate structure.
-  __ StoreToOffset(kStoreWord, CTX, R0, Isolate::top_context_offset());
+  __ StoreToOffset(kWord, CTX, R0, Isolate::top_context_offset());
 
   // Cache Isolate pointer into CTX while executing native code.
   __ mov(CTX, ShifterOperand(R0));
@@ -179,14 +179,14 @@
 
   // Reset exit frame information in Isolate structure.
   __ LoadImmediate(R2, 0);
-  __ StoreToOffset(kStoreWord, R2, CTX, Isolate::top_exit_frame_info_offset());
+  __ StoreToOffset(kWord, R2, CTX, Isolate::top_exit_frame_info_offset());
 
   // Load Context pointer from Isolate structure into R2.
-  __ LoadFromOffset(kLoadWord, R2, CTX, Isolate::top_context_offset());
+  __ LoadFromOffset(kWord, R2, CTX, Isolate::top_context_offset());
 
   // Reset Context pointer in Isolate structure.
   __ LoadImmediate(R3, reinterpret_cast<intptr_t>(Object::null()));
-  __ StoreToOffset(kStoreWord, R3, CTX, Isolate::top_context_offset());
+  __ StoreToOffset(kWord, R3, CTX, Isolate::top_context_offset());
 
   // Cache Context pointer into CTX while executing Dart code.
   __ mov(CTX, ShifterOperand(R2));
@@ -475,15 +475,15 @@
       __ b(&slow_case, NE);
     }
     __ ldr(R8, FieldAddress(CTX, Context::isolate_offset()));
-    __ LoadFromOffset(kLoadWord, R8, R8, Isolate::heap_offset());
-    __ LoadFromOffset(kLoadWord, R8, R8, Heap::new_space_offset());
+    __ LoadFromOffset(kWord, R8, R8, Isolate::heap_offset());
+    __ LoadFromOffset(kWord, R8, R8, Heap::new_space_offset());
 
     // Calculate and align allocation size.
     // Load new object start and calculate next object start.
     // R1: array element type.
     // R2: array length as Smi.
     // R8: points to new space object.
-    __ LoadFromOffset(kLoadWord, R0, R8, Scavenger::top_offset());
+    __ LoadFromOffset(kWord, R0, R8, Scavenger::top_offset());
     intptr_t fixed_size = sizeof(RawArray) + kObjectAlignment - 1;
     __ LoadImmediate(R3, fixed_size);
     __ add(R3, R3, ShifterOperand(R2, LSL, 1));  // R2 is Smi.
@@ -498,7 +498,7 @@
     // R3: array size.
     // R7: potential next object start.
     // R8: points to new space object.
-    __ LoadFromOffset(kLoadWord, IP, R8, Scavenger::end_offset());
+    __ LoadFromOffset(kWord, IP, R8, Scavenger::end_offset());
     __ cmp(R7, ShifterOperand(IP));
     __ b(&slow_case, CS);  // Branch if unsigned higher or equal.
 
@@ -507,7 +507,7 @@
     // R0: potential new object start.
     // R7: potential next object start.
     // R8: Points to new space object.
-    __ StoreToOffset(kStoreWord, R7, R8, Scavenger::top_offset());
+    __ StoreToOffset(kWord, R7, R8, Scavenger::top_offset());
     __ add(R0, R0, ShifterOperand(kHeapObjectTag));
 
     // R0: new object start as a tagged pointer.
@@ -709,16 +709,16 @@
 
   // Save the top exit frame info. Use R5 as a temporary register.
   // StackFrameIterator reads the top exit frame info saved in this frame.
-  __ LoadFromOffset(kLoadWord, R5, R8, Isolate::top_exit_frame_info_offset());
+  __ LoadFromOffset(kWord, R5, R8, Isolate::top_exit_frame_info_offset());
   __ LoadImmediate(R6, 0);
-  __ StoreToOffset(kStoreWord, R6, R8, Isolate::top_exit_frame_info_offset());
+  __ StoreToOffset(kWord, R6, R8, Isolate::top_exit_frame_info_offset());
 
   // Save the old Context pointer. Use R4 as a temporary register.
   // Note that VisitObjectPointers will find this saved Context pointer during
   // GC marking, since it traverses any information between SP and
   // FP - kExitLinkSlotFromEntryFp.
   // EntryFrame::SavedContext reads the context saved in this frame.
-  __ LoadFromOffset(kLoadWord, R4, R8, Isolate::top_context_offset());
+  __ LoadFromOffset(kWord, R4, R8, Isolate::top_context_offset());
 
   // The constants kSavedContextSlotFromEntryFp and
   // kExitLinkSlotFromEntryFp must be kept in sync with the code below.
@@ -773,8 +773,8 @@
   // Restore the saved top exit frame info back into the Isolate structure.
   // Uses R5 as a temporary register for this.
   __ PopList((1 << R4) | (1 << R5));
-  __ StoreToOffset(kStoreWord, R4, CTX, Isolate::top_context_offset());
-  __ StoreToOffset(kStoreWord, R5, CTX, Isolate::top_exit_frame_info_offset());
+  __ StoreToOffset(kWord, R4, CTX, Isolate::top_context_offset());
+  __ StoreToOffset(kWord, R5, CTX, Isolate::top_exit_frame_info_offset());
 
   // Restore C++ ABI callee-saved registers.
   __ PopList((1 << R3) | kAbiPreservedCpuRegs);  // Ignore restored R3.
@@ -1070,7 +1070,7 @@
       for (intptr_t current_offset = sizeof(RawObject);
            current_offset < instance_size;
            current_offset += kWordSize) {
-        __ StoreToOffset(kStoreWord, R0, R2, current_offset);
+        __ StoreToOffset(kWord, R0, R2, current_offset);
       }
     } else {
       __ add(R4, R2, ShifterOperand(sizeof(RawObject)));
@@ -1093,7 +1093,7 @@
     if (is_cls_parameterized) {
       // R1: new object type arguments.
       // Set the type arguments in the new object.
-      __ StoreToOffset(kStoreWord, R1, R2, cls.type_arguments_field_offset());
+      __ StoreToOffset(kWord, R1, R2, cls.type_arguments_field_offset());
     }
     // Done allocating and initializing the instance.
     // R2: new object still missing its heap tag.
@@ -1421,7 +1421,7 @@
       __ ldr(R0, Address(SP, R0, LSL, 1));
       __ bl(&get_class_id_as_smi);
       // R0: next argument class ID (smi).
-      __ LoadFromOffset(kLoadWord, R1, R6, i * kWordSize);
+      __ LoadFromOffset(kWord, R1, R6, i * kWordSize);
       // R1: next class ID to check (smi).
     }
     __ cmp(R0, ShifterOperand(R1));  // Class id match?
@@ -1465,7 +1465,7 @@
   __ PushList((1 << R0) | (1 << R4) | (1 << R5));
   // Push call arguments.
   for (intptr_t i = 0; i < num_args; i++) {
-    __ LoadFromOffset(kLoadWord, IP, R7, -i * kWordSize);
+    __ LoadFromOffset(kWord, IP, R7, -i * kWordSize);
     __ Push(IP);
   }
   // Pass IC data object and arguments descriptor array.
@@ -1501,13 +1501,13 @@
   // R6: pointer to an IC data check group.
   const intptr_t target_offset = ICData::TargetIndexFor(num_args) * kWordSize;
   const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize;
-  __ LoadFromOffset(kLoadWord, R0, R6, target_offset);
-  __ LoadFromOffset(kLoadWord, R1, R6, count_offset);
+  __ LoadFromOffset(kWord, R0, R6, target_offset);
+  __ LoadFromOffset(kWord, R1, R6, count_offset);
   __ adds(R1, R1, ShifterOperand(Smi::RawValue(1)));
-  __ StoreToOffset(kStoreWord, R1, R6, count_offset);
+  __ StoreToOffset(kWord, R1, R6, count_offset);
   __ b(&call_target_function, VC);  // No overflow.
   __ LoadImmediate(R1, Smi::RawValue(Smi::kMaxValue));
-  __ StoreToOffset(kStoreWord, R1, R6, count_offset);
+  __ StoreToOffset(kWord, R1, R6, count_offset);
 
   __ Bind(&call_target_function);
   // R0: target function.
@@ -1628,17 +1628,17 @@
 
   // Increment count for this call.
   Label increment_done;
-  __ LoadFromOffset(kLoadWord, R1, R6, count_offset);
+  __ LoadFromOffset(kWord, R1, R6, count_offset);
   __ adds(R1, R1, ShifterOperand(Smi::RawValue(1)));
-  __ StoreToOffset(kStoreWord, R1, R6, count_offset);
+  __ StoreToOffset(kWord, R1, R6, count_offset);
   __ b(&increment_done, VC);  // No overflow.
   __ LoadImmediate(R1, Smi::RawValue(Smi::kMaxValue));
-  __ StoreToOffset(kStoreWord, R1, R6, count_offset);
+  __ StoreToOffset(kWord, R1, R6, count_offset);
   __ Bind(&increment_done);
 
   Label target_is_compiled;
   // Get function and call it, if possible.
-  __ LoadFromOffset(kLoadWord, R1, R6, target_offset);
+  __ LoadFromOffset(kWord, R1, R6, target_offset);
   __ ldr(R0, FieldAddress(R1, Function::code_offset()));
   __ CompareImmediate(R0, reinterpret_cast<intptr_t>(Object::null()));
   __ b(&target_is_compiled, NE);
diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h
index 6ac9824..8b0b2f0 100644
--- a/runtime/vm/symbols.h
+++ b/runtime/vm/symbols.h
@@ -228,6 +228,8 @@
   V(IsolateSpawnException, "IsolateSpawnException")                            \
   V(IsolateUnhandledException, "IsolateUnhandledException")                    \
   V(FiftyThreeBitOverflowError, "_FiftyThreeBitOverflowError")                 \
+  V(MirroredCompilationError, "MirroredCompilationError")                      \
+  V(MirroredUncaughtExceptionError, "MirroredUncaughtExceptionError")          \
   V(_setupFullStackTrace, "_setupFullStackTrace")                              \
   V(BooleanExpression, "boolean expression")                                   \
   V(Malformed, "malformed")                                                    \
diff --git a/runtime/vm/vm_sources.gypi b/runtime/vm/vm_sources.gypi
index 422b80b..46868ff 100644
--- a/runtime/vm/vm_sources.gypi
+++ b/runtime/vm/vm_sources.gypi
@@ -238,6 +238,9 @@
     'object.h',
     'object_arm_test.cc',
     'object_ia32_test.cc',
+    'object_id_ring.cc',
+    'object_id_ring.h',
+    'object_id_ring_test.cc',
     'object_mips_test.cc',
     'object_store.cc',
     'object_store.h',
diff --git a/sdk/lib/_internal/compiler/implementation/deferred_load.dart b/sdk/lib/_internal/compiler/implementation/deferred_load.dart
index 38a6245..b39e475 100644
--- a/sdk/lib/_internal/compiler/implementation/deferred_load.dart
+++ b/sdk/lib/_internal/compiler/implementation/deferred_load.dart
@@ -56,6 +56,8 @@
   /// DeferredLibrary from dart:async
   ClassElement get deferredLibraryClass => compiler.deferredLibraryClass;
 
+  bool get areAnyElementsDeferred => !allDeferredElements.isEmpty;
+
   bool isDeferred(Element element) {
     element = element.implementation;
     return allDeferredElements.contains(element);
diff --git a/sdk/lib/_internal/compiler/implementation/elements/elements.dart b/sdk/lib/_internal/compiler/implementation/elements/elements.dart
index 7411bc9..f367345 100644
--- a/sdk/lib/_internal/compiler/implementation/elements/elements.dart
+++ b/sdk/lib/_internal/compiler/implementation/elements/elements.dart
@@ -497,7 +497,9 @@
     if (r != 0) return r;
     Token positionA = a.position();
     Token positionB = b.position();
-    r = positionA.charOffset.compareTo(positionB.charOffset);
+    int offsetA = positionA == null ? -1 : positionA.charOffset;
+    int offsetB = positionB == null ? -1 : positionB.charOffset;
+    r = offsetA.compareTo(offsetB);
     if (r != 0) return r;
     r = a.name.slowToString().compareTo(b.name.slowToString());
     if (r != 0) return r;
@@ -881,6 +883,9 @@
   void forEachInstanceField(void f(ClassElement enclosingClass, Element field),
                             {includeSuperAndInjectedMembers: false});
 
+  /// Similar to [forEachInstanceField] but visits static fields.
+  void forEachStaticField(void f(ClassElement enclosingClass, Element field));
+
   void forEachBackendMember(void f(Element member));
 }
 
diff --git a/sdk/lib/_internal/compiler/implementation/elements/modelx.dart b/sdk/lib/_internal/compiler/implementation/elements/modelx.dart
index 58c2344..76b16e4 100644
--- a/sdk/lib/_internal/compiler/implementation/elements/modelx.dart
+++ b/sdk/lib/_internal/compiler/implementation/elements/modelx.dart
@@ -1892,6 +1892,18 @@
         includeSuperAndInjectedMembers: includeSuperAndInjectedMembers);
   }
 
+  /// Similar to [forEachInstanceField] but visits static fields.
+  void forEachStaticField(void f(ClassElement enclosingClass, Element field)) {
+    // Filters so that [f] is only invoked with static fields.
+    void fieldFilter(ClassElement enclosingClass, Element member) {
+      if (!member.isInstanceMember() && member.kind == ElementKind.FIELD) {
+        f(enclosingClass, member);
+      }
+    }
+
+    forEachMember(fieldFilter);
+  }
+
   void forEachBackendMember(void f(Element member)) {
     backendMembers.forEach(f);
   }
diff --git a/sdk/lib/_internal/compiler/implementation/enqueue.dart b/sdk/lib/_internal/compiler/implementation/enqueue.dart
index ac465fc..77a146a 100644
--- a/sdk/lib/_internal/compiler/implementation/enqueue.dart
+++ b/sdk/lib/_internal/compiler/implementation/enqueue.dart
@@ -326,31 +326,24 @@
       ClassElement cls = element.declaration.getEnclosingClass();
       registerInstantiatedType(cls.rawType, elements);
       registerStaticUse(element.declaration);
+    } else if (element.isMixinApplication) {
+      // Don't enqueue mixin applications.
+    } else if (element.isClass()) {
+      ClassElement cls = element.declaration;
+      registerInstantiatedType(cls.rawType, elements);
+      // Make sure that even abstract classes are considered instantiated.
+      universe.instantiatedClasses.add(cls);
     } else if (element.impliesType()) {
-      // Don't enqueue classes, typedefs, and type variables.
+      // Don't enqueue typedefs, and type variables.
     } else if (Elements.isStaticOrTopLevel(element)) {
       registerStaticUse(element.declaration);
     } else if (element.isInstanceMember()) {
-      if (element.isFunction()) {
-        int arity =
-            element.asFunctionElement().requiredParameterCount(compiler);
-        Selector selector =
-            new Selector.call(element.name, element.getLibrary(), arity);
-        registerInvocation(selector);
-      } else if (element.isSetter()) {
+      Selector selector = new Selector.fromElement(element, compiler);
+      registerSelectorUse(selector);
+      if (element.isField()) {
         Selector selector =
             new Selector.setter(element.name, element.getLibrary());
         registerInvokedSetter(selector);
-      } else if (element.isGetter()) {
-        Selector selector =
-            new Selector.getter(element.name, element.getLibrary());
-        registerInvokedGetter(selector);
-      } else if (element.isField()) {
-        Selector selector =
-            new Selector.setter(element.name, element.getLibrary());
-        registerInvokedSetter(selector);
-        selector = new Selector.getter(element.name, element.getLibrary());
-        registerInvokedGetter(selector);
       }
     }
   }
diff --git a/sdk/lib/_internal/compiler/implementation/js/nodes.dart b/sdk/lib/_internal/compiler/implementation/js/nodes.dart
index 1f1134c..04eafb9 100644
--- a/sdk/lib/_internal/compiler/implementation/js/nodes.dart
+++ b/sdk/lib/_internal/compiler/implementation/js/nodes.dart
@@ -28,6 +28,7 @@
   T visitLabeledStatement(LabeledStatement node);
   T visitLiteralStatement(LiteralStatement node);
 
+  T visitBlob(Blob node);
   T visitLiteralExpression(LiteralExpression node);
   T visitVariableDeclarationList(VariableDeclarationList node);
   T visitSequence(Sequence node);
@@ -103,6 +104,7 @@
   T visitDefault(Default node) => visitNode(node);
 
   T visitExpression(Expression node) => visitNode(node);
+  T visitBlob(Blob node) => visitExpression(node);
   T visitVariableReference(VariableReference node) => visitExpression(node);
 
   T visitLiteralExpression(LiteralExpression node) => visitExpression(node);
@@ -516,6 +518,22 @@
   Prefix get not => new Prefix('!', this);
 }
 
+/// Wrap a CodeBuffer as an expression.
+class Blob extends Expression {
+  // TODO(ahe): This class is an aid to convert everything to ASTs, remove when
+  // not needed anymore.
+
+  final leg.CodeBuffer buffer;
+
+  Blob(this.buffer);
+
+  accept(NodeVisitor visitor) => visitor.visitBlob(this);
+
+  void visitChildren(NodeVisitor visitor) {}
+
+  int get precedenceLevel => PRIMARY;
+}
+
 class LiteralExpression extends Expression {
   final String template;
   final List<Expression> inputs;
diff --git a/sdk/lib/_internal/compiler/implementation/js/printer.dart b/sdk/lib/_internal/compiler/implementation/js/printer.dart
index f7d65c1..a5870d8 100644
--- a/sdk/lib/_internal/compiler/implementation/js/printer.dart
+++ b/sdk/lib/_internal/compiler/implementation/js/printer.dart
@@ -140,6 +140,10 @@
     visitAll(program.body);
   }
 
+  visitBlob(Blob node) {
+    outBuffer.addBuffer(node.buffer);
+  }
+
   bool blockBody(Node body, {bool needsSeparation, bool needsNewline}) {
     if (body is Block) {
       spaceOut();
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart b/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart
index 2f90272..f7c5b46 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart
@@ -122,6 +122,47 @@
   }
 }
 
+/*
+ * Invariants:
+ *   canInline(function) implies canInline(function, insideLoop:true)
+ *   !canInline(function, insideLoop: true) implies !canInline(function)
+ */
+class FunctionInlineCache {
+  final Map<FunctionElement, bool> canBeInlined =
+      new Map<FunctionElement, bool>();
+
+  final Map<FunctionElement, bool> canBeInlinedInsideLoop =
+      new Map<FunctionElement, bool>();
+
+  // Returns [:true:]/[:false:] if we have a cached decision.
+  // Returns [:null:] otherwise.
+  bool canInline(FunctionElement element, {bool insideLoop}) {
+    return insideLoop ? canBeInlinedInsideLoop[element] : canBeInlined[element];
+  }
+
+  void markAsInlinable(FunctionElement element, {bool insideLoop}) {
+    if (insideLoop) {
+      canBeInlinedInsideLoop[element] = true;
+    } else {
+      // If we can inline a function outside a loop then we should do it inside
+      // a loop as well.
+      canBeInlined[element] = true;
+      canBeInlinedInsideLoop[element] = true;
+    }
+  }
+
+  void markAsNonInlinable(FunctionElement element, {bool insideLoop}) {
+    if (insideLoop) {
+      // If we can't inline a function inside a loop, then we should not inline
+      // it outside a loop either.
+      canBeInlined[element] = false;
+      canBeInlinedInsideLoop[element] = false;
+    } else {
+      canBeInlined[element] = false;
+    }
+  }
+}
+
 
 class JavaScriptBackend extends Backend {
   SsaBuilderTask builder;
@@ -142,12 +183,7 @@
   final Map<Element, jsAst.Expression> generatedBailoutCode =
       new Map<Element, jsAst.Expression>();
 
-  /**
-   * Keep track of which function elements are simple enough to be
-   * inlined in callers.
-   */
-  final Map<FunctionElement, bool> canBeInlined =
-      new Map<FunctionElement, bool>();
+  FunctionInlineCache inlineCache = new FunctionInlineCache();
 
   ClassElement jsInterceptorClass;
   ClassElement jsStringClass;
@@ -436,9 +472,9 @@
         compiler.findHelper(const SourceString('defineNativeMethodsFinish'));
 
     // These methods are overwritten with generated versions.
-    canBeInlined[getInterceptorMethod] = false;
-    canBeInlined[getDispatchPropertyMethod] = false;
-    canBeInlined[setDispatchPropertyMethod] = false;
+    inlineCache.markAsNonInlinable(getInterceptorMethod, insideLoop: true);
+    inlineCache.markAsNonInlinable(getDispatchPropertyMethod, insideLoop: true);
+    inlineCache.markAsNonInlinable(setDispatchPropertyMethod, insideLoop: true);
 
     List<ClassElement> classes = [
       jsInterceptorClass =
@@ -672,7 +708,7 @@
 
   void registerUseInterceptor(Enqueuer enqueuer) {
     assert(!enqueuer.isResolutionQueue);
-    if (!enqueuer.nativeEnqueuer.hasNativeClasses()) return;
+    if (!enqueuer.nativeEnqueuer.hasInstantiatedNativeClasses()) return;
     enqueuer.registerStaticUse(getNativeInterceptorMethod);
     enqueuer.registerStaticUse(defineNativeMethodsFinishMethod);
     enqueuer.registerStaticUse(initializeDispatchPropertyMethod);
@@ -1393,6 +1429,8 @@
 
   bool retainName(SourceString name) => mustPreserveNames;
 
+  bool get rememberLazies => isTreeShakingDisabled;
+
   bool retainMetadataOf(Element element) {
     if (mustRetainMetadata) {
       // TODO(ahe): This is a little hacky, but I'll have to rewrite this when
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart b/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart
index 7b04eb2..281a07a 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart
@@ -82,6 +82,7 @@
   final List<ClassElement> nativeClasses = <ClassElement>[];
   final List<Selector> trivialNsmHandlers = <Selector>[];
   final Map<String, String> mangledFieldNames = <String, String>{};
+  final Map<String, String> mangledGlobalFieldNames = <String, String>{};
   final Set<String> recordedMangledNames = new Set<String>();
   final Set<String> interceptorInvocationNames = new Set<String>();
 
@@ -137,6 +138,16 @@
   Set<FunctionType> checkedNonGenericFunctionTypes =
       new Set<FunctionType>();
 
+  /**
+   * For classes and libraries, record code for static/top-level members.
+   * Later, this code is emitted when the class or library is emitted.
+   * See [bufferForElement].
+   */
+  // TODO(ahe): Generate statics with their class, and store only libraries in
+  // this map.
+  final Map<Element, List<CodeBuffer>> elementBuffers =
+      new Map<Element, List<CodeBuffer>>();
+
   void registerDynamicFunctionTypeCheck(FunctionType functionType) {
     ClassElement classElement = Types.getClassContext(functionType);
     if (classElement != null) {
@@ -586,30 +597,39 @@
            '    $longNamesConstant'));
     }
 
-    String sliceOffset = '," + (j < $firstNormalSelector ? 1 : 0)';
-    if (firstNormalSelector == 0) sliceOffset = '"';
-    if (firstNormalSelector == shorts.length) sliceOffset = ', 1"';
+    String sliceOffset = ', (j < $firstNormalSelector) ? 1 : 0';
+    if (firstNormalSelector == 0) sliceOffset = '';
+    if (firstNormalSelector == shorts.length) sliceOffset = ', 1';
 
     String whatToPatch = nativeEmitter.handleNoSuchMethod ?
                          "Object.prototype" :
                          "objectClassObject";
 
+    var params = ['name', 'short', 'type'];
+    var sliceOffsetParam = '';
+    var slice = 'Array.prototype.slice.call';
+    if (!sliceOffset.isEmpty) {
+      sliceOffsetParam = ', sliceOffset';
+      params.add('sliceOffset');
+    }
     statements.addAll([
       js.for_('var j = 0', 'j < shortNames.length', 'j++', [
         js('var type = 0'),
         js('var short = shortNames[j]'),
         js.if_('short[0] == "${namer.getterPrefix[0]}"', js('type = 1')),
         js.if_('short[0] == "${namer.setterPrefix[0]}"', js('type = 2')),
-        js('$whatToPatch[short] = Function("'
-               'return this.$noSuchMethodName('
-                   'this,'
-                   '${namer.CURRENT_ISOLATE}.$createInvocationMirror(\'"'
-                       ' + ${minify ? "shortNames" : "longNames"}[j]'
-                       ' + "\',\'" + short + "\',"'
-                       ' + type'
-                       ' + ",Array.prototype.slice.call(arguments'
-                       '$sliceOffset'
-                       ' + "),[]))")')
+        // Generate call to:
+        // createInvocationMirror(String name, internalName, type, arguments,
+        //                        argumentNames)
+        js('$whatToPatch[short] = #(${minify ? "shortNames" : "longNames"}[j], '
+                                    'short, type$sliceOffset)',
+           js.fun(params, [js.return_(js.fun([],
+               [js.return_(js(
+                   'this.$noSuchMethodName('
+                       'this, '
+                       '${namer.CURRENT_ISOLATE}.$createInvocationMirror('
+                           'name, short, type, '
+                           '$slice(arguments$sliceOffsetParam), []))'))]))]))
       ])
     ]);
   }
@@ -821,8 +841,8 @@
 
       js('var isolatePrototype = oldIsolate.prototype'),
       js('var str = "{\\n"'),
-      js('str += '
-             '"var properties = $isolate.${namer.isolatePropertiesName};\\n"'),
+      js('str += "var properties = '
+                     'arguments.callee.${namer.isolatePropertiesName};\\n"'),
       js('var hasOwnProperty = Object.prototype.hasOwnProperty'),
 
       // for (var staticName in isolateProperties) {
@@ -856,7 +876,7 @@
     var parameters = <String>['prototype', 'staticName', 'fieldName',
                               'getterName', 'lazyValue'];
     return js.fun(parameters, [
-      js('var getter = new Function("{ return $isolate." + fieldName + ";}")'),
+      js('var getter = new Function("{ return this." + fieldName + ";}")'),
     ]..addAll(addLazyInitializerLogic())
     );
   }
@@ -864,8 +884,14 @@
   List addLazyInitializerLogic() {
     String isolate = namer.CURRENT_ISOLATE;
     String cyclicThrow = namer.isolateAccess(backend.getCyclicThrowHelper());
+    var lazies = [];
+    if (backend.rememberLazies) {
+      lazies = [
+          js.if_('!init.lazies', js('init.lazies = {}')),
+          js('init.lazies[fieldName] = getterName')];
+    }
 
-    return [
+    return lazies..addAll([
       js('var sentinelUndefined = {}'),
       js('var sentinelInProgress = {}'),
       js('prototype[fieldName] = sentinelUndefined'),
@@ -908,7 +934,7 @@
           js('$isolate[getterName] = getter')
         ])
       ]))
-    ];
+    ]);
   }
 
   List buildDefineClassAndFinishClassFunctionsIfNecessary() {
@@ -1410,6 +1436,8 @@
 
     // Add checks to the constructors of instantiated classes.
     for (ClassElement cls in typeChecks) {
+      // TODO(9556).  The properties added to 'holder' should be generated
+      // directly as properties of the class object, not added later.
       String holder = namer.isolateAccess(backend.getImplementationClass(cls));
       for (TypeCheck check in typeChecks[cls]) {
         ClassElement cls = check.cls;
@@ -1435,11 +1463,31 @@
   }
 
   /**
+   * Returns the classes with constructors used as a 'holder' in
+   * [emitRuntimeTypeSupport].
+   * TODO(9556): Some cases will go away when the class objects are created as
+   * complete.  Not all classes will go away while constructors are referenced
+   * from type substitutions.
+   */
+  Set<ClassElement> classesModifiedByEmitRuntimeTypeSupport() {
+    TypeChecks typeChecks = backend.rti.requiredChecks;
+    Set<ClassElement> result = new Set<ClassElement>();
+    for (ClassElement cls in typeChecks) {
+      for (TypeCheck check in typeChecks[cls]) {
+        result.add(backend.getImplementationClass(cls));
+        break;
+      }
+    }
+    return result;
+  }
+
+  /**
    * Documentation wanted -- johnniwinther
    *
    * Invariant: [classElement] must be a declaration element.
    */
   void visitClassFields(ClassElement classElement,
+                        bool visitStatics,
                         void addField(Element member,
                                       String name,
                                       String accessorName,
@@ -1506,18 +1554,22 @@
       }
     }
 
-    // TODO(kasperl): We should make sure to only emit one version of
-    // overridden fields. Right now, we rely on the ordering so the
-    // fields pulled in from mixins are replaced with the fields from
-    // the class definition.
+    if (visitStatics) {
+      classElement.implementation.forEachStaticField(visitField);
+    } else {
+      // TODO(kasperl): We should make sure to only emit one version of
+      // overridden fields. Right now, we rely on the ordering so the
+      // fields pulled in from mixins are replaced with the fields from
+      // the class definition.
 
-    // If a class is not instantiated then we add the field just so we can
-    // generate the field getter/setter dynamically. Since this is only
-    // allowed on fields that are in [classElement] we don't need to visit
-    // superclasses for non-instantiated classes.
-    classElement.implementation.forEachInstanceField(
-        visitField,
-        includeSuperAndInjectedMembers: isInstantiated);
+      // If a class is not instantiated then we add the field just so we can
+      // generate the field getter/setter dynamically. Since this is only
+      // allowed on fields that are in [classElement] we don't need to visit
+      // superclasses for non-instantiated classes.
+      classElement.implementation.forEachInstanceField(
+          visitField,
+          includeSuperAndInjectedMembers: isInstantiated);
+    }
   }
 
   void generateGetter(Element member, String fieldName, String accessorName,
@@ -1545,6 +1597,8 @@
   }
 
   bool canGenerateCheckedSetter(Element member) {
+    // We never generate accessors for top-level/static fields.
+    if (!member.isInstanceMember()) return false;
     DartType type = member.computeType(compiler).unalias(compiler);
     if (type.element.isTypeVariable() ||
         (type is FunctionType && type.containsTypeVariables) || 
@@ -1603,9 +1657,16 @@
                           String accessorName,
                           String memberName) {
     if (!backend.retainGetter(member)) return;
-    String previousName = mangledFieldNames.putIfAbsent(
-        '${namer.getterPrefix}$accessorName',
-        () => memberName);
+    String previousName;
+    if (member.isInstanceMember()) {
+      previousName = mangledFieldNames.putIfAbsent(
+          '${namer.getterPrefix}$accessorName',
+          () => memberName);
+    } else {
+      previousName = mangledGlobalFieldNames.putIfAbsent(
+          accessorName,
+          () => memberName);
+    }
     assert(invariant(member, previousName == memberName,
                      message: '$previousName != ${memberName}'));
   }
@@ -1614,26 +1675,30 @@
   bool emitClassFields(ClassElement classElement,
                        ClassBuilder builder,
                        String superName,
-                       { bool classIsNative: false }) {
+                       { bool classIsNative: false,
+                         bool emitStatics: false }) {
     assert(superName != null);
     String separator = '';
     String nativeName = namer.getPrimitiveInterceptorRuntimeName(classElement);
     StringBuffer buffer = new StringBuffer();
-    if (nativeName != null) {
-      buffer.write('$nativeName/');
+    if (!emitStatics) {
+      if (nativeName != null) {
+        buffer.write('$nativeName/');
+      }
+      buffer.write('$superName;');
     }
-    buffer.write('$superName;');
     int bufferClassLength = buffer.length;
 
     var fieldMetadata = [];
     bool hasMetadata = false;
 
-    visitClassFields(classElement, (Element member,
-                                    String name,
-                                    String accessorName,
-                                    bool needsGetter,
-                                    bool needsSetter,
-                                    bool needsCheckedSetter) {
+    visitClassFields(classElement, emitStatics,
+                     (Element member,
+                      String name,
+                      String accessorName,
+                      bool needsGetter,
+                      bool needsSetter,
+                      bool needsCheckedSetter) {
       // Ignore needsCheckedSetter - that is handled below.
       bool needsAccessor = (needsGetter || needsSetter);
       // We need to output the fields for non-native classes so we can auto-
@@ -1675,7 +1740,7 @@
             // TODO(sra): 'isInterceptorClass' might not be the correct test for
             // methods forced to use the interceptor convention because the
             // method's class was elsewhere mixed-in to an interceptor.
-            assert(getterCode != 0);
+            assert(!member.isInstanceMember() || getterCode != 0);
           }
           int setterCode = 0;
           if (needsSetter) {
@@ -1684,7 +1749,7 @@
             // 11:  function(receiver, value) { this.field = value; }
             setterCode += backend.fieldHasInterceptedSetter(member) ? 2 : 0;
             setterCode += backend.isInterceptorClass(classElement) ? 0 : 1;
-            assert(setterCode != 0);
+            assert(!member.isInstanceMember() || setterCode != 0);
           }
           int code = getterCode + (setterCode << 2);
           if (code == 0) {
@@ -1711,12 +1776,13 @@
   void emitClassGettersSetters(ClassElement classElement,
                                ClassBuilder builder) {
 
-    visitClassFields(classElement, (Element member,
-                                    String name,
-                                    String accessorName,
-                                    bool needsGetter,
-                                    bool needsSetter,
-                                    bool needsCheckedSetter) {
+    visitClassFields(classElement, false,
+                     (Element member,
+                      String name,
+                      String accessorName,
+                      bool needsGetter,
+                      bool needsSetter,
+                      bool needsCheckedSetter) {
       compiler.withCurrentElement(member, () {
         if (needsCheckedSetter) {
           assert(!needsSetter);
@@ -1775,6 +1841,36 @@
     }
     emitIsTests(classElement, builder);
 
+    List<CodeBuffer> classBuffers = elementBuffers[classElement];
+    if (classBuffers == null) {
+      classBuffers = [];
+    } else {
+      elementBuffers.remove(classElement);
+    }
+    CodeBuffer statics = new CodeBuffer();
+    statics.write('{$n');
+    bool hasStatics = false;
+    ClassBuilder staticsBuilder = new ClassBuilder();
+    if (emitClassFields(
+            classElement, staticsBuilder, superName, emitStatics: true)) {
+      hasStatics = true;
+      statics.write('"":$_');
+      statics.write(
+          jsAst.prettyPrint(staticsBuilder.properties.single.value, compiler));
+      statics.write(',$n');
+    }
+    for (CodeBuffer classBuffer in classBuffers) {
+      // TODO(ahe): What about deferred?
+      if (classBuffer != null) {
+        hasStatics = true;
+        statics.addBuffer(classBuffer);
+      }
+    }
+    statics.write('}$n');
+    if (hasStatics) {
+      builder.addProperty('static', new jsAst.Blob(statics));
+    }
+
     // TODO(ahe): This method (generateClass) should return a jsAst.Expression.
     if (!buffer.isEmpty) {
       buffer.write(',$n$n');
@@ -1993,6 +2089,8 @@
    * that needs to be emitted.
    */
   Function computeClassFilter() {
+    if (backend.isTreeShakingDisabled) return (ClassElement cls) => true;
+
     Set<ClassElement> unneededClasses = new Set<ClassElement>();
     // The [Bool] class is not marked as abstract, but has a factory
     // constructor that always throws. We never need to emit it.
@@ -2008,14 +2106,7 @@
     );
 
     // Add interceptors referenced by constants.
-    ConstantHandler handler = compiler.constantHandler;
-    List<Constant> constants = handler.getConstantsForEmission();
-    for (Constant constant in constants) {
-      if (constant is InterceptorConstant) {
-        InterceptorConstant inceptorConstant = constant;
-        needed.add(inceptorConstant.dispatchedType.element);
-      }
-    }
+    needed.addAll(interceptorsReferencedFromConstants());
 
     // Add unneeded interceptors to the [unneededClasses] set.
     for (ClassElement interceptor in backend.interceptedClasses) {
@@ -2028,6 +2119,19 @@
     return (ClassElement cls) => !unneededClasses.contains(cls);
   }
 
+  Set<ClassElement> interceptorsReferencedFromConstants() {
+    Set<ClassElement> classes = new Set<ClassElement>();
+    ConstantHandler handler = compiler.constantHandler;
+    List<Constant> constants = handler.getConstantsForEmission();
+    for (Constant constant in constants) {
+      if (constant is InterceptorConstant) {
+        InterceptorConstant interceptorConstant = constant;
+        classes.add(interceptorConstant.dispatchedType.element);
+      }
+    }
+    return classes;
+  }
+
   void emitFinishClassesInvocationIfNecessary(CodeBuffer buffer) {
     if (needsDefineClass) {
       buffer.write('$finishClassesName($classesCollector,'
@@ -2846,7 +2950,8 @@
 
     if (classes == backend.interceptedClasses) {
       // I.e. this is the general interceptor.
-      hasNative = compiler.enqueuer.codegen.nativeEnqueuer.hasNativeClasses();
+      hasNative = compiler.enqueuer.codegen.nativeEnqueuer
+          .hasInstantiatedNativeClasses();
     }
 
     jsAst.Block block = new jsAst.Block.empty();
@@ -3366,12 +3471,19 @@
 
       mainBuffer.add(buildGeneratedBy());
       addComment(HOOKS_API_USAGE, mainBuffer);
+
+      if (!areAnyElementsDeferred) {
+        mainBuffer.add('(function(${namer.CURRENT_ISOLATE})$_{$n');
+      }
+
       mainBuffer.add('function ${namer.isolateName}()$_{}\n');
       mainBuffer.add('init()$N$n');
       // Shorten the code by using [namer.CURRENT_ISOLATE] as temporary.
       isolateProperties = namer.CURRENT_ISOLATE;
       mainBuffer.add(
-          'var $isolateProperties$_=$_$isolatePropertiesName$N');
+          '$isolateProperties$_=$_$isolatePropertiesName$N');
+
+      emitStaticFunctions(mainBuffer);
 
       if (!regularClasses.isEmpty ||
           !deferredClasses.isEmpty ||
@@ -3427,9 +3539,7 @@
       // the classesCollector variable.
       classesCollector = 'classesCollector should not be used from now on';
 
-      emitStaticFunctions(mainBuffer);
-
-      if (!libraryBuffers.isEmpty) {
+      if (!elementBuffers.isEmpty) {
         var oldClassesCollector = classesCollector;
         classesCollector = r"$$";
         if (compiler.enableMinification) {
@@ -3451,13 +3561,44 @@
             mainBuffer.write(';');
           }
         }
+        if (!mangledGlobalFieldNames.isEmpty) {
+          var keys = mangledGlobalFieldNames.keys.toList();
+          keys.sort();
+          var properties = [];
+          for (String key in keys) {
+            var value = js.string('${mangledGlobalFieldNames[key]}');
+            properties.add(new jsAst.Property(js.string(key), value));
+          }
+          var map = new jsAst.ObjectInitializer(properties);
+          mainBuffer.write(
+              jsAst.prettyPrint(
+                  js('init.mangledGlobalNames = #', map).toStatement(),
+                  compiler));
+          if (compiler.enableMinification) {
+            mainBuffer.write(';');
+          }
+        }
         mainBuffer
             ..write(getReflectionDataParser())
             ..write('([$n');
 
-        var sortedLibraries = Elements.sortedByPosition(libraryBuffers.keys);
-        for (LibraryElement library in sortedLibraries) {
-          List<CodeBuffer> buffers = libraryBuffers[library];
+        List<Element> sortedElements =
+            Elements.sortedByPosition(elementBuffers.keys);
+        bool hasPendingStatics = false;
+        for (Element element in sortedElements) {
+          if (!element.isLibrary()) {
+            for (CodeBuffer b in elementBuffers[element]) {
+              if (b != null) {
+                hasPendingStatics = true;
+                compiler.reportInfo(
+                    element, MessageKind.GENERIC, {'text': 'Pending statics.'});
+                print(b.getText());
+              }
+            }
+            continue;
+          }
+          LibraryElement library = element;
+          List<CodeBuffer> buffers = elementBuffers[library];
           var buffer = buffers[0];
           var uri = library.canonicalUri;
           if (uri.scheme == 'file' && compiler.sourceMapUri != null) {
@@ -3489,7 +3630,10 @@
                 ..addBuffer(buffer)
                 ..write('}],$n');
           }
-          libraryBuffers[library] = const [];
+          elementBuffers[library] = const [];
+        }
+        if (hasPendingStatics) {
+          compiler.internalError('Pending statics (see above).');
         }
         mainBuffer.write('])$N');
 
@@ -3519,14 +3663,17 @@
       isolateProperties = isolatePropertiesName;
       // The following code should not use the short-hand for the
       // initialStatics.
-      mainBuffer.add('var ${namer.CURRENT_ISOLATE}$_=${_}null$N');
+      mainBuffer.add('${namer.CURRENT_ISOLATE}$_=${_}null$N');
 
       emitFinishIsolateConstructorInvocation(mainBuffer);
-      mainBuffer.add('var ${namer.CURRENT_ISOLATE}$_='
-                     '${_}new ${namer.isolateName}()$N');
+      mainBuffer.add(
+          '${namer.CURRENT_ISOLATE}$_=${_}new ${namer.isolateName}()$N');
 
       emitMain(mainBuffer);
       emitInitFunction(mainBuffer);
+      if (!areAnyElementsDeferred) {
+        mainBuffer.add('})()$n');
+      }
       compiler.assembledCode = mainBuffer.getText();
       outputSourceMap(mainBuffer, compiler.assembledCode, '');
 
@@ -3536,13 +3683,24 @@
     return compiler.assembledCode;
   }
 
-  final Map<LibraryElement, List<CodeBuffer>> libraryBuffers =
-      new Map<LibraryElement, List<CodeBuffer>>();
-
   CodeBuffer bufferForElement(Element element, CodeBuffer eagerBuffer) {
-    LibraryElement library = element.getLibrary();
-    List<CodeBuffer> buffers = libraryBuffers.putIfAbsent(
-        library, () => <CodeBuffer>[null, null]);
+    Element owner = element.getLibrary();
+    if (!element.isTopLevel() && !element.isNative()) {
+      // For static (not top level) elements, record their code in a buffer
+      // specific to the class. For now, not supported for native classes and
+      // native elements.
+      ClassElement cls =
+          element.getEnclosingClassOrCompilationUnit().declaration;
+      if (compiler.codegenWorld.instantiatedClasses.contains(cls)
+          && !cls.isNative()) {
+        owner = cls;
+      }
+    }
+    if (owner == null) {
+      compiler.internalErrorOnElement(element, 'Owner is null');
+    }
+    List<CodeBuffer> buffers = elementBuffers.putIfAbsent(
+        owner, () => <CodeBuffer>[null, null]);
     bool deferred = isDeferred(element);
     int index = deferred ? 1 : 0;
     CodeBuffer buffer = buffers[index];
@@ -3650,6 +3808,10 @@
     return compiler.deferredLoadTask.isDeferred(element);
   }
 
+  bool get areAnyElementsDeferred {
+    return compiler.deferredLoadTask.areAnyElementsDeferred;
+  }
+
   // TODO(ahe): Remove this when deferred loading is fully implemented.
   void warnNotImplemented(Element element, String message) {
     compiler.reportMessage(compiler.spanFromSpannable(element),
@@ -3659,11 +3821,13 @@
 
   // TODO(ahe): This code should be integrated in finishClasses.
   String getReflectionDataParser() {
+    String metadataField = '"${namer.metadataField}"';
     return '''
 (function (reflectionData) {
   if (!init.libraries) init.libraries = [];
   if (!init.mangledNames) init.mangledNames = {};
   if (!init.mangledGlobalNames) init.mangledGlobalNames = {};
+  if (!init.statics) init.statics = {};
   init.getterPrefix = "${namer.getterPrefix}";
   init.setterPrefix = "${namer.setterPrefix}";
   var libraries = init.libraries;
@@ -3679,39 +3843,44 @@
     var descriptor = data[3];
     var classes = [];
     var functions = [];
-    for (var property in descriptor) {
-      if (!hasOwnProperty.call(descriptor, property)) continue;
-      var element = descriptor[property];
-      var firstChar = property.substring(0, 1);
-      var previousProperty;
-      if (firstChar == "+") {
-        mangledGlobalNames[previousProperty] = property.substring(1);
-      } else if (firstChar == "@") {
-        property = property.substring(1);
-        ${namer.CURRENT_ISOLATE}[property]["${namer.metadataField}"] = element;
-      } else if (typeof element === "function") {
-        ${namer.CURRENT_ISOLATE}[previousProperty = property] = element;
-        functions.push(property);
-      } else {
-        previousProperty = property;
-        var newDesc = {};
-        var previousProp;
-        for (var prop in element) {
-          if (!hasOwnProperty.call(element, prop)) continue;
-          firstChar = prop.substring(0, 1);
-          if (firstChar == "+") {
-            mangledNames[previousProp] = prop.substring(1);
-          } else if (firstChar == "@" && prop != "@") {
-            newDesc[prop.substring(1)]["${namer.metadataField}"] ='''
-'''element[prop];
-          } else {
-            newDesc[previousProp = prop] = element[prop];
+    function processStatics(descriptor) {
+      for (var property in descriptor) {
+        if (!hasOwnProperty.call(descriptor, property)) continue;
+        if (property === "") continue;
+        var element = descriptor[property];
+        var firstChar = property.substring(0, 1);
+        var previousProperty;
+        if (firstChar === "+") {
+          mangledGlobalNames[previousProperty] = property.substring(1);
+        } else if (firstChar === "@") {
+          property = property.substring(1);
+          ${namer.CURRENT_ISOLATE}[property][$metadataField] = element;
+        } else if (typeof element === "function") {
+          ${namer.CURRENT_ISOLATE}[previousProperty = property] = element;
+          functions.push(property);
+        } else {
+          previousProperty = property;
+          var newDesc = {};
+          var previousProp;
+          for (var prop in element) {
+            if (!hasOwnProperty.call(element, prop)) continue;
+            firstChar = prop.substring(0, 1);
+            if (prop === "static") {
+              processStatics(init.statics[property] = element[prop]);
+            } else if (firstChar === "+") {
+              mangledNames[previousProp] = prop.substring(1);
+            } else if (firstChar === "@" && prop !== "@") {
+              newDesc[prop.substring(1)][$metadataField] = element[prop];
+            } else {
+              newDesc[previousProp = prop] = element[prop];
+            }
           }
+          $classesCollector[property] = newDesc;
+          classes.push(property);
         }
-        $classesCollector[property] = newDesc;
-        classes.push(property);
       }
     }
+    processStatics(descriptor);
     libraries.push([name, uri, classes, functions, metadata]);
   }
 })''';
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/emitter_no_eval.dart b/sdk/lib/_internal/compiler/implementation/js_backend/emitter_no_eval.dart
index ebdb9fd..a0f3d01 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/emitter_no_eval.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/emitter_no_eval.dart
@@ -37,7 +37,8 @@
   bool emitClassFields(ClassElement classElement,
                        ClassBuilder builder,
                        String superName,
-                       { bool classIsNative: false }) {
+                       { bool classIsNative: false,
+                         bool emitStatics: false }) {
     // Class fields are dynamically generated so they have to be
     // emitted using getters and setters instead.
     return false;
@@ -53,12 +54,13 @@
     //   get$d : function() { return this.d; }
     //   set$d : function(x) { this.d = x; }
     List<String> fields = <String>[];
-    visitClassFields(classElement, (Element member,
-                                    String name,
-                                    String accessorName,
-                                    bool needsGetter,
-                                    bool needsSetter,
-                                    bool needsCheckedSetter) {
+    visitClassFields(classElement, false,
+                     (Element member,
+                      String name,
+                      String accessorName,
+                      bool needsGetter,
+                      bool needsSetter,
+                      bool needsCheckedSetter) {
       fields.add(name);
     });
     String constructorName = namer.safeName(classElement.name.slowToString());
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/native_emitter.dart b/sdk/lib/_internal/compiler/implementation/js_backend/native_emitter.dart
index 3f29f71..6538cf2 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/native_emitter.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/native_emitter.dart
@@ -152,6 +152,11 @@
     Set<ClassElement> nonleafClasses = new Set<ClassElement>();
     neededClasses.add(compiler.objectClass);
 
+    Set<ClassElement> neededByConstant =
+        emitter.interceptorsReferencedFromConstants();
+    Set<ClassElement> modifiedClasses =
+        emitter.classesModifiedByEmitRuntimeTypeSupport();
+
     for (ClassElement classElement in preOrder.reversed) {
       // Post-order traversal ensures we visit the subclasses before their
       // superclass.  This makes it easy to tell if a class is needed because a
@@ -165,10 +170,11 @@
         needed = true;
       } else if (!builder.isTrivial) {
         needed = true;
-      } else {
-        // TODO(9556): We can't remove any unneeded classes until the class
-        // builders contain all the information.  [emitRuntimeTypeSupport] must
-        // no longer add information to a class definition.
+      } else if (neededByConstant.contains(classElement)) {
+        needed = true;
+      } else if (modifiedClasses.contains(classElement)) {
+        // TODO(9556): Remove this test when [emitRuntimeTypeSupport] no longer
+        // adds information to a class prototype or constructor.
         needed = true;
       }
 
@@ -207,21 +213,23 @@
       }
     }
 
-    // Emit code to set up dispatch data that maps tags to the interceptors.
-
-    void generateDefines(ClassElement classElement) {
-      generateDefineNativeMethods(leafTags[classElement], classElement,
-          defineNativeMethodsName);
-      generateDefineNativeMethods(nonleafTags[classElement], classElement,
-          defineNativeMethodsNonleafName);
-    }
-    generateDefines(backend.jsInterceptorClass);
-    for (ClassElement classElement in classes) {
-      generateDefines(classElement);
+    // Emit code to set up dispatch data that maps tags to the interceptors, but
+    // only if native classes are actually instantiated.
+    if (compiler.enqueuer.codegen.nativeEnqueuer
+        .hasInstantiatedNativeClasses()) {
+      void generateDefines(ClassElement classElement) {
+        generateDefineNativeMethods(leafTags[classElement], classElement,
+            defineNativeMethodsName);
+        generateDefineNativeMethods(nonleafTags[classElement], classElement,
+            defineNativeMethodsNonleafName);
+      }
+      generateDefines(backend.jsInterceptorClass);
+      for (ClassElement classElement in classes) {
+        generateDefines(classElement);
+      }
     }
 
     // Emit the native class interceptors that were actually used.
-
     for (ClassElement classElement in classes) {
       if (neededClasses.contains(classElement)) {
         ClassBuilder builder = builders[classElement];
@@ -260,7 +268,9 @@
     emitter.emitInstanceMembers(classElement, builder);
     emitter.emitIsTests(classElement, builder);
 
-    if (!hasFields && builder.properties.length == propertyCount) {
+    if (!hasFields &&
+        builder.properties.length == propertyCount &&
+        superclass is! MixinApplicationElement) {
       builder.isTrivial = true;
     }
 
diff --git a/sdk/lib/_internal/compiler/implementation/native_handler.dart b/sdk/lib/_internal/compiler/implementation/native_handler.dart
index 687003a..49975b8 100644
--- a/sdk/lib/_internal/compiler/implementation/native_handler.dart
+++ b/sdk/lib/_internal/compiler/implementation/native_handler.dart
@@ -53,7 +53,7 @@
   NativeBehavior getNativeBehaviorOf(Send node) => NativeBehavior.NONE;
 
   /// Returns whether native classes are being used.
-  bool hasNativeClasses() => false;
+  bool hasInstantiatedNativeClasses() => false;
 
   /**
    * Handles JS-calls, which can be an instantiation point for types.
@@ -84,7 +84,7 @@
   final Set<ClassElement> pendingClasses = new Set<ClassElement>();
   final Set<ClassElement> unusedClasses = new Set<ClassElement>();
 
-  bool hasNativeClasses() => !registeredClasses.isEmpty;
+  bool hasInstantiatedNativeClasses() => !registeredClasses.isEmpty;
 
   /**
    * Records matched constraints ([SpecialType] or [DartType]).  Once a type
@@ -494,6 +494,7 @@
       || libraryName == 'dart:html'
       || libraryName == 'dart:html_common'
       || libraryName == 'dart:indexed_db'
+      || libraryName == 'dart:js'
       || libraryName == 'dart:svg'
       || libraryName == 'dart:typed_data'
       || libraryName == 'dart:web_audio'
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/builder.dart b/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
index 6ba92ac..b46ef2b 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
@@ -929,9 +929,6 @@
     localsHandler = new LocalsHandler(this);
   }
 
-  static const MAX_INLINING_DEPTH = 3;
-  static const MAX_INLINING_NODES = 46;
-
   List<InliningState> inliningStack;
 
   Element returnElement;
@@ -1225,7 +1222,12 @@
     element = element.implementation;
     FunctionElement function = element;
 
-    bool cachedCanBeInlined = backend.canBeInlined[function];
+    bool insideLoop = loopNesting > 0 || graph.calledInLoop;
+
+    // Bail out early if the inlining decision is in the cache and we can't
+    // inline (no need to check the hard constraints).
+    bool cachedCanBeInlined =
+        backend.inlineCache.canInline(function, insideLoop: insideLoop);
     if (cachedCanBeInlined == false) return false;
 
     bool meetsHardConstraints() {
@@ -1239,8 +1241,9 @@
       assert(selector != null
              || Elements.isStaticOrTopLevel(element)
              || element.isGenerativeConstructorBody());
-      if (selector != null && !selector.applies(function, compiler))
+      if (selector != null && !selector.applies(function, compiler)) {
         return false;
+      }
 
       // Don't inline operator== methods if the parameter can be null.
       if (element.name == const SourceString('==')) {
@@ -1262,20 +1265,31 @@
       return true;
     }
 
-    bool heuristicsSayGoodToGo(FunctionExpression functionExpression,
-                                TreeElements newElements) {
-      if (loopNesting == 0 && !graph.calledInLoop) return false;
-
-      int maxDepth = (loopNesting > 0) ? MAX_INLINING_DEPTH : 1;
-      if (inliningStack.length >= maxDepth) return false;
-
-      if (cachedCanBeInlined == null) {
-        var canBeInlined =
-            InlineWeeder.canBeInlined(functionExpression, newElements);
-        backend.canBeInlined[function] = canBeInlined;
-        return canBeInlined;
+    bool heuristicSayGoodToGo(FunctionExpression functionExpression) {
+      // Don't inline recursivly
+      if (inliningStack.any((entry) => entry.function == function)) {
+        return false;
       }
-      return cachedCanBeInlined;
+
+      if (cachedCanBeInlined == true) return cachedCanBeInlined;
+
+      int numParameters = function.functionSignature.parameterCount;
+      int maxInliningNodes;
+      if (insideLoop) {
+        maxInliningNodes = InlineWeeder.INLINING_NODES_INSIDE_LOOP +
+            InlineWeeder.INLINING_NODES_INSIDE_LOOP_ARG_FACTOR * numParameters;
+      } else {
+        maxInliningNodes = InlineWeeder.INLINING_NODES_OUTSIDE_LOOP +
+            InlineWeeder.INLINING_NODES_OUTSIDE_LOOP_ARG_FACTOR * numParameters;
+      }
+      bool canBeInlined = InlineWeeder.canBeInlined(
+          functionExpression, maxInliningNodes);
+      if (canBeInlined) {
+        backend.inlineCache.markAsInlinable(element, insideLoop: insideLoop);
+      } else {
+        backend.inlineCache.markAsNonInlinable(element, insideLoop: insideLoop);
+      }
+      return canBeInlined;
     }
 
     void doInlining(FunctionExpression functionExpression) {
@@ -1307,13 +1321,8 @@
 
     if (meetsHardConstraints()) {
       FunctionExpression functionExpression = function.parseNode(compiler);
-      TreeElements newElements =
-          compiler.enqueuer.resolution.getCachedElements(function);
-      if (newElements == null) {
-        compiler.internalError("Element not resolved: $function");
-      }
 
-      if (heuristicsSayGoodToGo(functionExpression, newElements)) {
+      if (heuristicSayGoodToGo(functionExpression)) {
         doInlining(functionExpression);
         return true;
       }
@@ -5125,25 +5134,29 @@
  * finds whether it is too difficult to inline.
  */
 class InlineWeeder extends Visitor {
-  final TreeElements elements;
+  // Invariant: *INSIDE_LOOP* > *OUTSIDE_LOOP*
+  static const INLINING_NODES_OUTSIDE_LOOP = 18;
+  static const INLINING_NODES_OUTSIDE_LOOP_ARG_FACTOR = 3;
+  static const INLINING_NODES_INSIDE_LOOP = 42;
+  static const INLINING_NODES_INSIDE_LOOP_ARG_FACTOR = 4;
 
   bool seenReturn = false;
   bool tooDifficult = false;
   int nodeCount = 0;
+  final int maxInliningNodes;
 
-  InlineWeeder(this.elements);
+  InlineWeeder(this.maxInliningNodes);
 
   static bool canBeInlined(FunctionExpression functionExpression,
-                           TreeElements elements) {
-    InlineWeeder weeder = new InlineWeeder(elements);
+                           int maxInliningNodes) {
+    InlineWeeder weeder = new InlineWeeder(maxInliningNodes);
     weeder.visit(functionExpression.initializers);
     weeder.visit(functionExpression.body);
-    if (weeder.tooDifficult) return false;
-    return true;
+    return !weeder.tooDifficult;
   }
 
   bool registerNode() {
-    if (nodeCount++ > SsaBuilder.MAX_INLINING_NODES) {
+    if (nodeCount++ > maxInliningNodes) {
       tooDifficult = true;
       return false;
     } else {
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart b/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart
index 23e9d32..be46135 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart
@@ -620,6 +620,7 @@
    * information on [to], and that dominates the user.
    */
   void rewriteWithBetterUser(HInstruction from, HInstruction to) {
+    // BUG(11841): Turn this method into a phase to be run after GVN phases.
     Link<HCheck> better = const Link<HCheck>();
     for (HInstruction user in to.usedBy) {
       if (user == from || user is! HCheck) continue;
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/value_range_analyzer.dart b/sdk/lib/_internal/compiler/implementation/ssa/value_range_analyzer.dart
index 42560e0..7cddf8f 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/value_range_analyzer.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/value_range_analyzer.dart
@@ -615,6 +615,11 @@
 
   Range visitPhi(HPhi phi) {
     if (!phi.isInteger()) return info.newUnboundRange();
+    // Some phases may replace instructions that change the inputs of
+    // this phi. Only the [SsaTypesPropagation] phase will update the
+    // phi type. Play it safe by assuming the [SsaTypesPropagation]
+    // phase is not necessarily run before the [ValueRangeAnalyzer].
+    if (phi.inputs.any((i) => !i.isInteger())) return info.newUnboundRange();
     if (phi.block.isLoopHeader()) {
       Range range = tryInferLoopPhiRange(phi);
       if (range == null) return info.newUnboundRange();
diff --git a/sdk/lib/_internal/compiler/implementation/types/container_tracer.dart b/sdk/lib/_internal/compiler/implementation/types/container_tracer.dart
index 4913c8b..92f69e7 100644
--- a/sdk/lib/_internal/compiler/implementation/types/container_tracer.dart
+++ b/sdk/lib/_internal/compiler/implementation/types/container_tracer.dart
@@ -161,7 +161,7 @@
       analysisCount++;
     }
 
-    if (!continueAnalyzing) return inferrer.dynamicType;
+    if (!continueAnalyzing) return compiler.typesTask.dynamicType;
 
     // [potentialType] can be null if we did not find any instruction
     // that adds elements to the list.
@@ -187,7 +187,7 @@
     potentialType = potentialType == null
         ? newType
         : newType.union(potentialType, compiler);
-    if (potentialType == inferrer.dynamicType) {
+    if (potentialType == compiler.typesTask.dynamicType) {
       bailout('Moved to dynamic');
     }
   }
@@ -233,7 +233,7 @@
       print('Bailout on $analyzedNode $startElement because of $reason');
     }
     continueAnalyzing = false;
-    return inferrer.dynamicType;
+    return compiler.typesTask.dynamicType;
   }
 
   bool couldBeTheList(resolved) {
@@ -306,6 +306,8 @@
     if (!indices.isEmpty) {
       Iterable<Element> callees;
       if (callee is Element) {
+        // No need to go further, we know the call will throw.
+        if (callee.isErroneous()) return false;
         callees = [callee];
       } else {
         assert(callee is Selector);
@@ -354,11 +356,11 @@
       visitingInitializers = false;
       visit(node.body);
     }
-    return inferrer.functionType;
+    return compiler.typesTask.functionType;
   }
 
   TypeMask visitLiteralList(LiteralList node) {
-    if (node.isConst()) return inferrer.constListType;
+    if (node.isConst()) return compiler.typesTask.constListType;
     if (tracer.couldBeTheList(node)) {
       escaping = true;
       for (Node element in node.elements.nodes) {
@@ -367,7 +369,7 @@
     } else {
       node.visitChildren(this);
     }
-    return inferrer.growableListType;
+    return compiler.typesTask.growableListType;
   }
 
   // TODO(ngeoffray): Try to move the following two methods in
@@ -415,7 +417,7 @@
     bool isIndexEscaping = false;
     bool isValueEscaping = false;
     if (isIncrementOrDecrement) {
-      rhsType = inferrer.intType;
+      rhsType = compiler.typesTask.intType;
       if (node.isIndex) {
         isIndexEscaping = visitAndCatchEscaping(() {
           indexType = visit(node.arguments.head);
@@ -464,7 +466,7 @@
     } else if (isReceiver) {
       if (setterSelector.name == const SourceString('length')) {
         // Changing the length.
-        tracer.unionPotentialTypeWith(inferrer.nullType);
+        tracer.unionPotentialTypeWith(compiler.typesTask.nullType);
       }
     } else if (isValueEscaping) {
       if (element != null
@@ -518,7 +520,7 @@
     } else if (element.isFunction()) {
       return inferrer.getReturnTypeOfElement(element);
     } else {
-      return inferrer.dynamicType;
+      return compiler.typesTask.dynamicType;
     }
   }
 
@@ -530,14 +532,14 @@
       if (tracer.couldBeTheList(node)) {
         escaping = true;
       }
-      return inferrer.growableListType;
+      return compiler.typesTask.growableListType;
     } else if (Elements.isFixedListConstructorCall(element, node, compiler)) {
-      tracer.unionPotentialTypeWith(inferrer.nullType);
+      tracer.unionPotentialTypeWith(compiler.typesTask.nullType);
       visitArguments(node.arguments, element);
       if (tracer.couldBeTheList(node)) {
         escaping = true;
       }
-      return inferrer.fixedListType;
+      return compiler.typesTask.fixedListType;
     } else if (Elements.isFilledListConstructorCall(element, node, compiler)) {
       if (tracer.couldBeTheList(node)) {
         escaping = true;
@@ -547,7 +549,7 @@
       } else {
         visitArguments(node.arguments, element);
       }
-      return inferrer.fixedListType;
+      return compiler.typesTask.fixedListType;
     }
 
     bool isEscaping = visitArguments(node.arguments, element);
@@ -564,7 +566,7 @@
       return inferrer.getReturnTypeOfElement(element);
     } else {
       // Closure call or unresolved.
-      return inferrer.dynamicType;
+      return compiler.typesTask.dynamicType;
     }
   }
 
@@ -579,9 +581,9 @@
     } else if (Elements.isInstanceSend(node, elements)) {
       return visitDynamicSend(node);
     } else if (Elements.isStaticOrTopLevelFunction(element)) {
-      return inferrer.functionType;
+      return compiler.typesTask.functionType;
     } else if (Elements.isErroneousElement(element)) {
-      return inferrer.dynamicType;
+      return compiler.typesTask.dynamicType;
     } else if (Elements.isLocal(element)) {
       if (tracer.couldBeTheList(element)) {
         escaping = true;
@@ -589,7 +591,7 @@
       return locals.use(element);
     } else {
       node.visitChildren(this);
-      return inferrer.dynamicType;
+      return compiler.typesTask.dynamicType;
     }
   }
 
@@ -600,7 +602,7 @@
         visitArguments(node.arguments, elements.getSelector(node));
 
     if (isEscaping) return tracer.bailout('Passed to a closure');
-    return inferrer.dynamicType;
+    return compiler.typesTask.dynamicType;
   }
 
   TypeMask visitDynamicSend(Send node) {
@@ -645,7 +647,7 @@
 
   TypeMask visitReturn(Return node) {
     if (node.expression == null) {
-      return inferrer.nullType;
+      return compiler.typesTask.nullType;
     }
     
     TypeMask type;
diff --git a/sdk/lib/_internal/compiler/implementation/types/inferrer_visitor.dart b/sdk/lib/_internal/compiler/implementation/types/inferrer_visitor.dart
index 9878bf2..eb82a47 100644
--- a/sdk/lib/_internal/compiler/implementation/types/inferrer_visitor.dart
+++ b/sdk/lib/_internal/compiler/implementation/types/inferrer_visitor.dart
@@ -15,7 +15,7 @@
   TypeMask otherType;
   if (annotation.kind == TypeKind.TYPEDEF
       || annotation.kind == TypeKind.FUNCTION) {
-    otherType = compiler.typesTask.typesInferrer.functionType;
+    otherType = compiler.typesTask.functionType;
   } else if (annotation.kind == TypeKind.TYPE_VARIABLE) {
     return type;
   } else {
@@ -248,7 +248,7 @@
 
   TypeMask visitNode(Node node) {
     node.visitChildren(this);
-    return inferrer.dynamicType;
+    return compiler.typesTask.dynamicType;
   }
 
   TypeMask visitNewExpression(NewExpression node) {
@@ -256,39 +256,39 @@
   }
 
   TypeMask visit(Node node) {
-    return node == null ? inferrer.dynamicType : node.accept(this);
+    return node == null ? compiler.typesTask.dynamicType : node.accept(this);
   }
 
   TypeMask visitFunctionExpression(FunctionExpression node) {
     node.visitChildren(this);
-    return inferrer.functionType;
+    return compiler.typesTask.functionType;
   }
 
   TypeMask visitFunctionDeclaration(FunctionDeclaration node) {
-    locals.update(elements[node], inferrer.functionType);
+    locals.update(elements[node], compiler.typesTask.functionType);
     return visit(node.function);
   }
 
   TypeMask visitLiteralString(LiteralString node) {
-    return inferrer.stringType;
+    return compiler.typesTask.stringType;
   }
 
   TypeMask visitStringInterpolation(StringInterpolation node) {
     node.visitChildren(this);
-    return inferrer.stringType;
+    return compiler.typesTask.stringType;
   }
 
   TypeMask visitStringJuxtaposition(StringJuxtaposition node) {
     node.visitChildren(this);
-    return inferrer.stringType;
+    return compiler.typesTask.stringType;
   }
 
   TypeMask visitLiteralBool(LiteralBool node) {
-    return inferrer.boolType;
+    return compiler.typesTask.boolType;
   }
 
   TypeMask visitLiteralDouble(LiteralDouble node) {
-    return inferrer.doubleType;
+    return compiler.typesTask.doubleType;
   }
 
   TypeMask visitLiteralInt(LiteralInt node) {
@@ -297,30 +297,30 @@
     // The JavaScript backend may turn this literal into a double at
     // runtime.
     return constantSystem.isDouble(constant)
-        ? inferrer.doubleType
-        : inferrer.intType;
+        ? compiler.typesTask.doubleType
+        : compiler.typesTask.intType;
   }
 
   TypeMask visitLiteralList(LiteralList node) {
     node.visitChildren(this);
     return node.isConst()
-        ? inferrer.constListType
-        : inferrer.growableListType;
+        ? compiler.typesTask.constListType
+        : compiler.typesTask.growableListType;
   }
 
   TypeMask visitLiteralMap(LiteralMap node) {
     node.visitChildren(this);
     return node.isConst()
-        ? inferrer.constMapType
-        : inferrer.mapType;
+        ? compiler.typesTask.constMapType
+        : compiler.typesTask.mapType;
   }
 
   TypeMask visitLiteralNull(LiteralNull node) {
-    return inferrer.nullType;
+    return compiler.typesTask.nullType;
   }
 
   TypeMask visitTypeReferenceSend(Send node) {
-    return inferrer.typeType;
+    return compiler.typesTask.typeType;
   }
 
   bool isThisOrSuper(Node node) => node.isThis() || node.isSuper();
@@ -356,7 +356,7 @@
     } else if (node.isSuper()) {
       return superType;
     }
-    return inferrer.dynamicType;
+    return compiler.typesTask.dynamicType;
   }
 
   void potentiallyAddIsCheck(Send node) {
@@ -398,7 +398,7 @@
       updateIsChecks(isChecks, usePositive: true);
       visit(node.arguments.head);
       locals.merge(saved);
-      return inferrer.boolType;
+      return compiler.typesTask.boolType;
     } else if (const SourceString("||") == op.source) {
       conditionIsSimple = false;
       visit(node.receiver);
@@ -409,17 +409,17 @@
       visit(node.arguments.head);
       accumulateIsChecks = oldAccumulateIsChecks;
       locals.merge(saved);
-      return inferrer.boolType;
+      return compiler.typesTask.boolType;
     } else if (const SourceString("!") == op.source) {
       bool oldAccumulateIsChecks = accumulateIsChecks;
       accumulateIsChecks = false;
       node.visitChildren(this);
       accumulateIsChecks = oldAccumulateIsChecks;
-      return inferrer.boolType;
+      return compiler.typesTask.boolType;
     } else if (const SourceString("is") == op.source) {
       potentiallyAddIsCheck(node);
       node.visitChildren(this);
-      return inferrer.boolType;
+      return compiler.typesTask.boolType;
     } else if (const SourceString("as") == op.source) {
       TypeMask receiverType = visit(node.receiver);
       DartType type = elements.getType(node.arguments.head);
@@ -430,7 +430,7 @@
     } else if (const SourceString('===') == op.source
                || const SourceString('!==') == op.source) {
       node.visitChildren(this);
-      return inferrer.boolType;
+      return compiler.typesTask.boolType;
     } else {
       // Binary operator.
       return visitDynamicSend(node);
@@ -464,13 +464,13 @@
          link = link.tail) {
       Node definition = link.head;
       if (definition is Identifier) {
-        locals.update(elements[definition], inferrer.nullType);
+        locals.update(elements[definition], compiler.typesTask.nullType);
       } else {
         assert(definition.asSendSet() != null);
         visit(definition);
       }
     }
-    return inferrer.dynamicType;
+    return compiler.typesTask.dynamicType;
   }
 
   bool handleCondition(Node node, List<Send> tests) {
@@ -499,7 +499,7 @@
     if (simpleCondition) updateIsChecks(tests, usePositive: false);
     visit(node.elsePart);
     locals.merge(thenLocals);
-    return inferrer.dynamicType;
+    return compiler.typesTask.dynamicType;
   }
 
   void setupBreaksAndContinues(TargetElement element) {
@@ -546,7 +546,7 @@
     loopLevel--;
     mergeBreaks(target);
     clearBreaksAndContinues(target);
-    return inferrer.dynamicType;
+    return compiler.typesTask.dynamicType;
   }
 
   TypeMask visitWhile(While node) {
@@ -591,13 +591,13 @@
       locals = saved;
     }
     visit(node.finallyBlock);
-    return inferrer.dynamicType;
+    return compiler.typesTask.dynamicType;
   }
 
   TypeMask visitThrow(Throw node) {
     node.visitChildren(this);
     locals.seenReturnOrThrow = true;
-    return inferrer.dynamicType;
+    return compiler.typesTask.dynamicType;
   }
 
   TypeMask visitCatchBlock(CatchBlock node) {
@@ -605,16 +605,16 @@
     if (exception != null) {
       DartType type = elements.getType(node.type);
       TypeMask mask = type == null
-          ? inferrer.dynamicType
+          ? compiler.typesTask.dynamicType
           : new TypeMask.nonNullSubtype(type.asRaw());
       locals.update(elements[exception], mask);
     }
     Node trace = node.trace;
     if (trace != null) {
-      locals.update(elements[trace], inferrer.dynamicType);
+      locals.update(elements[trace], compiler.typesTask.dynamicType);
     }
     visit(node.block);
-    return inferrer.dynamicType;
+    return compiler.typesTask.dynamicType;
   }
 
   TypeMask visitParenthesizedExpression(ParenthesizedExpression node) {
@@ -628,7 +628,7 @@
         if (locals.aborts) break;
       }
     }
-    return inferrer.dynamicType;
+    return compiler.typesTask.dynamicType;
   }
 
   TypeMask visitLabeledStatement(LabeledStatement node) {
@@ -638,7 +638,7 @@
         || Elements.isUnusedLabel(node, elements)) {
       // Loops and switches handle their own labels.
       visit(body);
-      return inferrer.dynamicType;
+      return compiler.typesTask.dynamicType;
     }
 
     TargetElement targetElement = elements[body];
@@ -646,21 +646,21 @@
     visit(body);
     mergeBreaks(targetElement);
     clearBreaksAndContinues(targetElement);
-    return inferrer.dynamicType;
+    return compiler.typesTask.dynamicType;
   }
 
   TypeMask visitBreakStatement(BreakStatement node) {
     TargetElement target = elements[node];
     breaksFor[target].add(locals);
     locals.seenBreakOrContinue = true;
-    return inferrer.dynamicType;
+    return compiler.typesTask.dynamicType;
   }
 
   TypeMask visitContinueStatement(ContinueStatement node) {
     TargetElement target = elements[node];
     continuesFor[target].add(locals);
     locals.seenBreakOrContinue = true;
-    return inferrer.dynamicType;
+    return compiler.typesTask.dynamicType;
   }
 
   void internalError(String reason, {Node node}) {
@@ -735,6 +735,6 @@
     // that the [visitBlock] method does not assume the code after the
     // switch is dead code.
     locals.seenBreakOrContinue = false;
-    return inferrer.dynamicType;
+    return compiler.typesTask.dynamicType;
   }
 }
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 5f25672..6b49b54 100644
--- a/sdk/lib/_internal/compiler/implementation/types/simple_types_inferrer.dart
+++ b/sdk/lib/_internal/compiler/implementation/types/simple_types_inferrer.dart
@@ -178,36 +178,20 @@
       compiler = compiler,
       internal = new InternalSimpleTypesInferrer(compiler, OPTIMISTIC);
 
-  TypeMask get dynamicType => compiler.typesTask.dynamicType;
-  TypeMask get nullType => compiler.typesTask.nullType;
-  TypeMask get intType => compiler.typesTask.intType;
-  TypeMask get doubleType => compiler.typesTask.doubleType;
-  TypeMask get numType => compiler.typesTask.numType;
-  TypeMask get boolType => compiler.typesTask.boolType;
-  TypeMask get functionType => compiler.typesTask.functionType;
-  TypeMask get listType => compiler.typesTask.listType;
-  TypeMask get constListType => compiler.typesTask.constListType;
-  TypeMask get fixedListType => compiler.typesTask.fixedListType;
-  TypeMask get growableListType => compiler.typesTask.growableListType;
-  TypeMask get mapType => compiler.typesTask.mapType;
-  TypeMask get constMapType => compiler.typesTask.constMapType;
-  TypeMask get stringType => compiler.typesTask.stringType;
-  TypeMask get typeType => compiler.typesTask.typeType;
-
   TypeMask getReturnTypeOfElement(Element element) {
-    if (compiler.disableTypeInference) return dynamicType;
+    if (compiler.disableTypeInference) return compiler.typesTask.dynamicType;
     return internal.getReturnTypeOfElement(element.implementation);
   }
   TypeMask getTypeOfElement(Element element) {
-    if (compiler.disableTypeInference) return dynamicType;
+    if (compiler.disableTypeInference) return compiler.typesTask.dynamicType;
     return internal.getTypeOfElement(element.implementation);
   }
   TypeMask getTypeOfNode(Element owner, Node node) {
-    if (compiler.disableTypeInference) return dynamicType;
+    if (compiler.disableTypeInference) return compiler.typesTask.dynamicType;
     return internal.getTypeOfNode(owner, node);
   }
   TypeMask getTypeOfSelector(Selector selector) {
-    if (compiler.disableTypeInference) return dynamicType;
+    if (compiler.disableTypeInference) return compiler.typesTask.dynamicType;
     return internal.getTypeOfSelector(selector);
   }
   Iterable<Element> getCallersOf(Element element) {
diff --git a/sdk/lib/_internal/compiler/implementation/universe/universe.dart b/sdk/lib/_internal/compiler/implementation/universe/universe.dart
index c366000..db18031 100644
--- a/sdk/lib/_internal/compiler/implementation/universe/universe.dart
+++ b/sdk/lib/_internal/compiler/implementation/universe/universe.dart
@@ -154,6 +154,15 @@
                     this.namedArguments,
                     this.orderedNamedArguments,
                     this.hashCode) {
+    assert(kind == SelectorKind.INDEX
+           || (name != INDEX_NAME && name != INDEX_SET_NAME));
+    assert(kind == SelectorKind.OPERATOR
+           || kind == SelectorKind.INDEX
+           || Elements.operatorNameToIdentifier(name) == name);
+    assert(kind == SelectorKind.CALL
+           || kind == SelectorKind.GETTER
+           || kind == SelectorKind.SETTER
+           || Elements.operatorNameToIdentifier(name) != name);
     assert(!name.isPrivate() || library != null);
   }
 
@@ -177,6 +186,28 @@
         hashCode);
   }
 
+  factory Selector.fromElement(Element element, Compiler compiler) {
+    SourceString name = element.name;
+    if (element.isFunction()) {
+      int arity = element.asFunctionElement().requiredParameterCount(compiler);
+      if (name == const SourceString('[]')) {
+        return new Selector.index();
+      } else if (name == const SourceString('[]=')) {
+        return new Selector.indexSet();
+      } else if (Elements.operatorNameToIdentifier(name) != name) {
+        return new Selector(SelectorKind.OPERATOR, name, null, arity);
+      } else {
+        return new Selector.call(name, element.getLibrary(), arity);
+      }
+    } else if (element.isSetter()) {
+      return new Selector.setter(name, element.getLibrary());
+    } else if (element.isGetter()) {
+      return new Selector.getter(name, element.getLibrary());
+    } else if (element.isField()) {
+      return new Selector.getter(name, element.getLibrary());
+    }
+  }
+
   factory Selector.getter(SourceString name, LibraryElement library)
       => new Selector(SelectorKind.GETTER, name, library, 0);
 
diff --git a/sdk/lib/_internal/lib/js_mirrors.dart b/sdk/lib/_internal/lib/js_mirrors.dart
index 1d1c825..802ec36 100644
--- a/sdk/lib/_internal/lib/js_mirrors.dart
+++ b/sdk/lib/_internal/lib/js_mirrors.dart
@@ -307,7 +307,7 @@
   var mirror = classMirrors[constructorOrInterceptor];
   if (mirror == null) {
     mirror = new JsClassMirror(
-        symbol, constructorOrInterceptor, fields, fieldsMetadata);
+        symbol, mangledName, constructorOrInterceptor, fields, fieldsMetadata);
     classMirrors[constructorOrInterceptor] = mirror;
   }
   return mirror;
@@ -343,7 +343,7 @@
                                      List<Object> positionalArguments,
                                      [Map<Symbol, dynamic> namedArguments]) {
     if (namedArguments != null && !namedArguments.isEmpty) {
-      throw new UnsupportedError('Named arguments are not implemented');
+      throw new UnsupportedError('Named arguments are not implemented.');
     }
     return
         new Future<InstanceMirror>(
@@ -354,7 +354,7 @@
                         List positionalArguments,
                         [Map<Symbol,dynamic> namedArguments]) {
     if (namedArguments != null && !namedArguments.isEmpty) {
-      throw new UnsupportedError('Named arguments are not implemented');
+      throw new UnsupportedError('Named arguments are not implemented.');
     }
     // Copy the list to ensure that it can safely be passed to
     // JavaScript.
@@ -402,19 +402,22 @@
 
 class JsClassMirror extends JsTypeMirror with JsObjectMirror
     implements ClassMirror {
+  final String _mangledName;
   final _jsConstructorOrInterceptor;
-  final String _fields;
+  final String _fieldsDescriptor;
   final List _fieldsMetadata;
   List _metadata;
   JsClassMirror _superclass;
   List<JsMethodMirror> _cachedMethods;
+  List<JsVariableMirror> _cachedFields;
 
   // Set as side-effect of accessing JsLibraryMirror.classes.
   JsLibraryMirror _owner;
 
   JsClassMirror(Symbol simpleName,
+                this._mangledName,
                 this._jsConstructorOrInterceptor,
-                this._fields,
+                this._fieldsDescriptor,
                 this._fieldsMetadata)
       : super(simpleName);
 
@@ -429,15 +432,10 @@
   }
 
   Map<Symbol, MethodMirror> get constructors {
-    Map<Symbol, MethodMirror> result = new Map<Symbol, MethodMirror>();
-    JsLibraryMirror library = owner;
-    String unmangledName = n(simpleName);
-    for (JsMethodMirror mirror in library._functionMirrors) {
-      Symbol name = mirror.simpleName;
-      if (mirror.isConstructor
-          && (name == simpleName || n(name).startsWith('$unmangledName.'))) {
-        result[name] = mirror;
-        mirror._owner = this;
+    var result = new Map<Symbol, MethodMirror>();
+    for (JsMethodMirror method in _methods) {
+      if (method.isConstructor) {
+        result[method.simpleName] = method;
       }
     }
     return result;
@@ -448,7 +446,6 @@
     var prototype = JS('', '#.prototype', _jsConstructor);
     List<String> keys = extractKeys(prototype);
     var result = <JsMethodMirror>[];
-    int i = 0;
     for (String key in keys) {
       if (key == '') continue;
       String simpleName = mangledNames[key];
@@ -464,13 +461,92 @@
       result.add(mirror);
       mirror._owner = this;
     }
+
+    keys = extractKeys(JS('', 'init.statics[#]', _mangledName));
+    int length = keys.length;
+    for (int i = 0; i < length; i++) {
+      String mangledName = keys[i];
+      String unmangledName = mangledName;
+      // TODO(ahe): Create accessor for accessing $.  It is also
+      // used in js_helper.
+      var jsFunction = JS('', '#[#]', JS_CURRENT_ISOLATE(), mangledName);
+
+      bool isConstructor = false;
+      if (i + 1 < length) {
+        String reflectionName = keys[i + 1];
+        if (reflectionName.startsWith('+')) {
+          i++;
+          reflectionName = reflectionName.substring(1);
+          isConstructor = reflectionName.startsWith('new ');
+          if (isConstructor) {
+            reflectionName = reflectionName.substring(4).replaceAll(r'$', '.');
+          }
+        }
+        unmangledName = reflectionName;
+      }
+      bool isStatic = !isConstructor; // Constructors are not static.
+      JsMethodMirror mirror =
+          new JsMethodMirror.fromUnmangledName(
+              unmangledName, jsFunction, isStatic, isConstructor);
+      result.add(mirror);
+      mirror._owner = this;
+    }
+
     return _cachedMethods = result;
   }
 
+  List<VariableMirror> get _fields {
+    if (_cachedFields != null) return _cachedFields;
+    var result = <VariableMirror>[];
+    var s = _fieldsDescriptor.split(';');
+    var fields = s[1] == '' ? [] : s[1].split(',');
+    int fieldNumber = 0;
+    for (String field in fields) {
+      var metadata;
+      if (_fieldsMetadata != null) {
+        metadata = _fieldsMetadata[fieldNumber++];
+      }
+      JsVariableMirror mirror =
+          new JsVariableMirror.from(field, metadata, this, false);
+      if (mirror != null) {
+        result.add(mirror);
+      }
+    }
+
+    var staticDescriptor = JS('', 'init.statics[#]', _mangledName);
+    if (staticDescriptor != null) {
+      var staticFieldsDescriptor = JS('', '#[""]', staticDescriptor);
+      var staticFieldsMetadata = null;
+      var staticFields;
+      if (staticFieldsDescriptor is List) {
+        staticFields = staticFieldsDescriptor[0].split(',');
+        staticFieldsMetadata = staticFieldsDescriptor.sublist(1);
+      } else if (staticFieldsDescriptor is String) {
+        staticFields = staticFieldsDescriptor.split(',');
+      } else {
+        staticFields = [];
+      }
+      fieldNumber = 0;
+      for (String staticField in staticFields) {
+        var metadata;
+        if (staticFieldsMetadata != null) {
+          metadata = staticFieldsMetadata[fieldNumber++];
+        }
+        JsVariableMirror mirror =
+            new JsVariableMirror.from(staticField, metadata, this, true);
+        if (mirror != null) {
+          result.add(mirror);
+        }
+      }
+    }
+    _cachedFields = result;
+    return _cachedFields;
+  }
+
   Map<Symbol, MethodMirror> get methods {
     var result = new Map<Symbol, MethodMirror>();
     for (JsMethodMirror method in _methods) {
-      if (!method.isGetter && !method.isSetter) {
+      if (!method.isConstructor && !method.isGetter && !method.isSetter) {
         result[method.simpleName] = method;
       }
     }
@@ -478,10 +554,16 @@
   }
 
   Map<Symbol, MethodMirror> get getters {
-    // TODO(ahe): Should this include getters for fields?
+    // TODO(ahe): This is a hack to remove getters corresponding to a field.
+    var fields = variables;
+
     var result = new Map<Symbol, MethodMirror>();
     for (JsMethodMirror method in _methods) {
       if (method.isGetter) {
+
+        // TODO(ahe): This is a hack to remove getters corresponding to a field.
+        if (fields[method.simpleName] != null) continue;
+
         result[method.simpleName] = method;
       }
     }
@@ -489,10 +571,18 @@
   }
 
   Map<Symbol, MethodMirror> get setters {
-    // TODO(ahe): Should this include setters for fields?
+    // TODO(ahe): This is a hack to remove setters corresponding to a field.
+    var fields = variables;
+
     var result = new Map<Symbol, MethodMirror>();
     for (JsMethodMirror method in _methods) {
       if (method.isSetter) {
+
+        // TODO(ahe): This is a hack to remove setters corresponding to a field.
+        String name = n(method.simpleName);
+        name = name.substring(0, name.length - 1); // Remove '='.
+        if (fields[s(name)] != null) continue;
+
         result[method.simpleName] = method;
       }
     }
@@ -501,19 +591,8 @@
 
   Map<Symbol, VariableMirror> get variables {
     var result = new Map<Symbol, VariableMirror>();
-    var s = _fields.split(';');
-    var fields = s[1] == '' ? [] : s[1].split(',');
-    int fieldNumber = 0;
-    for (String field in fields) {
-      var metadata;
-      if (_fieldsMetadata != null) {
-        metadata = _fieldsMetadata[fieldNumber++];
-      }
-      JsVariableMirror mirror = new JsVariableMirror.from(field, metadata);
-      if (mirror != null) {
-        result[mirror.simpleName] = mirror;
-        mirror._owner = this;
-      }
+    for (JsVariableMirror mirror in _fields) {
+      result[mirror.simpleName] = mirror;
     }
     return result;
   }
@@ -534,44 +613,53 @@
   }
 
   InstanceMirror setField(Symbol fieldName, Object arg) {
-    // TODO(ahe): This is extremely dangerous!!!
-    JS('void', '#[#] = #', JS_CURRENT_ISOLATE(),
-       '${n(simpleName)}_${n(fieldName)}', arg);
-    return reflect(arg);
+    JsVariableMirror mirror = variables[fieldName];
+    if (mirror != null && mirror.isStatic && !mirror.isFinal) {
+      String jsName = mirror._jsName;
+      if (!JS('bool', '# in #', jsName, JS_CURRENT_ISOLATE())) {
+        throw new RuntimeError('Cannot find "$jsName" in current isolate.');
+      }
+      JS('void', '#[#] = #', JS_CURRENT_ISOLATE(), jsName, arg);
+      return reflect(arg);
+    }
+    // TODO(ahe): What receiver to use?
+    throw new NoSuchMethodError(this, '${n(fieldName)}=', [arg], null);
   }
 
   InstanceMirror getField(Symbol fieldName) {
-    // TODO(ahe): This is extremely dangerous!!!
-    return reflect(
-        JS('', '#[#]', JS_CURRENT_ISOLATE(),
-           '${n(simpleName)}_${n(fieldName)}'));
+    JsVariableMirror mirror = variables[fieldName];
+    if (mirror != null && mirror.isStatic) {
+      String jsName = mirror._jsName;
+      if (!JS('bool', '# in #', jsName, JS_CURRENT_ISOLATE())) {
+        throw new RuntimeError('Cannot find "$jsName" in current isolate.');
+      }
+      if (JS('bool', '# in init.lazies', jsName)) {
+        String getterName = JS('String', 'init.lazies[#]', jsName);
+        return reflect(JS('', '#[#]()', JS_CURRENT_ISOLATE(), getterName));
+      } else {
+        return reflect(JS('', '#[#]', JS_CURRENT_ISOLATE(), jsName));
+      }
+    }
+    // TODO(ahe): What receiver to use?
+    throw new NoSuchMethodError(this, n(fieldName), null, null);
   }
 
   InstanceMirror newInstance(Symbol constructorName,
                              List positionalArguments,
                              [Map<Symbol, dynamic> namedArguments]) {
     if (namedArguments != null && !namedArguments.isEmpty) {
-      throw new UnsupportedError('Named arguments are not implemented');
+      throw new UnsupportedError('Named arguments are not implemented.');
     }
-    String reflectiveName = 'new ${n(simpleName)}';
-    String name = n(constructorName);
-    if (!name.isEmpty) {
-      reflectiveName = '$reflectiveName\$$name';
-    }
-    reflectiveName = '$reflectiveName:${positionalArguments.length}:0';
-    String mangledName = reflectiveGlobalNames[reflectiveName];
-    var factory = JS('', '#[#]', JS_CURRENT_ISOLATE(), mangledName);
-    if (factory == null) {
-      // TODO(ahe): Pass namedArguments when NoSuchMethodError has
-      // been fixed to use Symbol.
-      // TODO(ahe): What receiver to use?
-      throw new NoSuchMethodError(
-          this, reflectiveName, positionalArguments, null);
-    }
-    return reflect(JS('', r'#.apply(#, #)',
-                      factory,
-                      JS_CURRENT_ISOLATE(),
-                      new List.from(positionalArguments)));
+    JsMethodMirror mirror = constructors.values.firstWhere(
+        (m) => m.constructorName == constructorName,
+        orElse: () {
+          // TODO(ahe): Pass namedArguments when NoSuchMethodError has been
+          // fixed to use Symbol.
+          // TODO(ahe): What receiver to use?
+          throw new NoSuchMethodError(
+              owner, n(constructorName), positionalArguments, null);
+        });
+    return reflect(mirror._invoke(positionalArguments, namedArguments));
   }
 
   Future<InstanceMirror> newInstanceAsync(
@@ -579,7 +667,7 @@
       List positionalArguments,
       [Map<Symbol, dynamic> namedArguments]) {
     if (namedArguments != null && !namedArguments.isEmpty) {
-      throw new UnsupportedError('Named arguments are not implemented');
+      throw new UnsupportedError('Named arguments are not implemented.');
     }
     return new Future<InstanceMirror>(
         () => newInstance(
@@ -616,7 +704,7 @@
 
   ClassMirror get superclass {
     if (_superclass == null) {
-      var superclassName = _fields.split(';')[0];
+      var superclassName = _fieldsDescriptor.split(';')[0];
       // Use _superclass == this to represent class with no superclass (Object).
       _superclass = (superclassName == '')
           ? this : reflectClassByMangledName(superclassName);
@@ -624,12 +712,27 @@
     return _superclass == this ? null : _superclass;
   }
 
-  // TODO(ahe): Implement these;
   InstanceMirror invoke(Symbol memberName,
                         List positionalArguments,
                         [Map<Symbol,dynamic> namedArguments]) {
-    throw new UnimplementedError();
+    // Mirror API gotcha: Calling [invoke] on a ClassMirror means invoke a
+    // static method.
+
+    if (namedArguments != null && !namedArguments.isEmpty) {
+      throw new UnsupportedError('Named arguments are not implemented.');
+    }
+    JsMethodMirror mirror = methods[memberName];
+    if (mirror == null || !mirror.isStatic) {
+      // TODO(ahe): Pass namedArguments when NoSuchMethodError has
+      // been fixed to use Symbol.
+      // TODO(ahe): What receiver to use?
+      throw new NoSuchMethodError(
+          this, n(memberName), positionalArguments, null);
+    }
+    return reflect(mirror._invoke(positionalArguments, namedArguments));
   }
+
+  // TODO(ahe): Implement these.
   List<ClassMirror> get superinterfaces => throw new UnimplementedError();
   Map<Symbol, TypeVariableMirror> get typeVariables
       => throw new UnimplementedError();
@@ -646,17 +749,21 @@
   final bool isFinal;
   final bool isStatic;
   final _metadataFunction;
-  DeclarationMirror _owner;
+  final DeclarationMirror _owner;
   List _metadata;
 
   JsVariableMirror(Symbol simpleName,
                    this._jsName,
                    this.isFinal,
                    this.isStatic,
-                   this._metadataFunction)
+                   this._metadataFunction,
+                   this._owner)
       : super(simpleName);
 
-  factory JsVariableMirror.from(String descriptor, metadataFunction) {
+  factory JsVariableMirror.from(String descriptor,
+                                metadataFunction,
+                                JsClassMirror owner,
+                                bool isStatic) {
     int length = descriptor.length;
     var code = fieldCode(descriptor.codeUnitAt(length - 1));
     bool isFinal = false;
@@ -672,8 +779,26 @@
       accessorName = accessorName.substring(0, divider);
       jsName = accessorName.substring(divider + 1);
     }
+    var unmangledName;
+    if (isStatic) {
+      unmangledName = mangledGlobalNames[accessorName];
+    } else {
+      String getterPrefix = JS('String', 'init.getterPrefix');
+      unmangledName = mangledNames['$getterPrefix$accessorName'];
+    }
+    if (unmangledName == null) unmangledName = accessorName;
+    if (!hasSetter) {
+      // TODO(ahe): This is a hack to handle checked setters in checked mode.
+      var setterName = s('$unmangledName=');
+      for (JsMethodMirror method in owner._methods) {
+        if (method.simpleName == setterName) {
+          isFinal = false;
+          break;
+        }
+      }
+    }
     return new JsVariableMirror(
-        s(accessorName), jsName, isFinal, false, metadataFunction);
+        s(unmangledName), jsName, isFinal, isStatic, metadataFunction, owner);
   }
 
   String get _prettyName => 'VariableMirror';
@@ -844,6 +969,24 @@
     return s(name.substring(index + 1));
   }
 
+  _invoke(List positionalArguments, [Map<Symbol, dynamic> namedArguments]) {
+    if (namedArguments != null && !namedArguments.isEmpty) {
+      throw new UnsupportedError('Named arguments are not implemented.');
+    }
+    if (!isStatic && !isConstructor) {
+      throw new RuntimeError('Cannot invoke instance method without receiver.');
+    }
+    if (_parameterCount != positionalArguments.length || _jsFunction == null) {
+      // TODO(ahe): Pass namedArguments when NoSuchMethodError has
+      // been fixed to use Symbol.
+      // TODO(ahe): What receiver to use?
+      throw new NoSuchMethodError(
+          owner, n(simpleName), positionalArguments, null);
+    }
+    return JS('', r'#.apply(#, #)', _jsFunction, JS_CURRENT_ISOLATE(),
+              new List.from(positionalArguments));
+  }
+
   // TODO(ahe): Implement these.
   bool get isAbstract => throw new UnimplementedError();
   bool get isRegularMethod => throw new UnimplementedError();
diff --git a/sdk/lib/_internal/libraries.dart b/sdk/lib/_internal/libraries.dart
index 044fbf2..e2af8d5 100644
--- a/sdk/lib/_internal/libraries.dart
+++ b/sdk/lib/_internal/libraries.dart
@@ -70,6 +70,11 @@
       "isolate/isolate.dart",
       dart2jsPatchPath: "_internal/lib/isolate_patch.dart"),
 
+  "js": const LibraryInfo(
+      "js/dartium/js_dartium.dart",
+      category: "Client",
+      dart2jsPath: "js/dart2js/js_dart2js.dart"),
+
   "json": const LibraryInfo(
       "json/json.dart",
       dart2jsPatchPath: "_internal/lib/json_patch.dart"),
diff --git a/sdk/lib/_internal/pub/lib/src/command/lish.dart b/sdk/lib/_internal/pub/lib/src/command/lish.dart
index c44eeeb..23f4c97 100644
--- a/sdk/lib/_internal/pub/lib/src/command/lish.dart
+++ b/sdk/lib/_internal/pub/lib/src/command/lish.dart
@@ -44,7 +44,7 @@
         help: 'Validate but do not publish the package.');
     commandParser.addFlag('force', abbr: 'f', negatable: false,
         help: 'Publish without confirmation if there are no errors.');
-    commandParser.addOption('server', defaultsTo: HostedSource.DEFAULT_URL,
+    commandParser.addOption('server', defaultsTo: HostedSource.defaultUrl,
         help: 'The package server to which to upload this package.');
   }
 
diff --git a/sdk/lib/_internal/pub/lib/src/command/uploader.dart b/sdk/lib/_internal/pub/lib/src/command/uploader.dart
index 8ecdd38..86daaa1 100644
--- a/sdk/lib/_internal/pub/lib/src/command/uploader.dart
+++ b/sdk/lib/_internal/pub/lib/src/command/uploader.dart
@@ -30,7 +30,7 @@
   Uri get server => Uri.parse(commandOptions['server']);
 
   UploaderCommand() {
-    commandParser.addOption('server', defaultsTo: HostedSource.DEFAULT_URL,
+    commandParser.addOption('server', defaultsTo: HostedSource.defaultUrl,
         help: 'The package server on which the package is hosted.');
     commandParser.addOption('package',
         help: 'The package whose uploaders will be modified.\n'
diff --git a/sdk/lib/_internal/pub/lib/src/source/hosted.dart b/sdk/lib/_internal/pub/lib/src/source/hosted.dart
index 097ec68..f65a56a 100644
--- a/sdk/lib/_internal/pub/lib/src/source/hosted.dart
+++ b/sdk/lib/_internal/pub/lib/src/source/hosted.dart
@@ -24,12 +24,17 @@
 /// A package source that installs packages from a package hosting site that
 /// uses the same API as pub.dartlang.org.
 class HostedSource extends Source {
-  /// The URL of the default package repository.
-  static const DEFAULT_URL = "https://pub.dartlang.org";
 
   final name = "hosted";
   final shouldCache = true;
 
+  /// Gets the default URL for the package server for hosted dependencies.
+  static String get defaultUrl {
+    var url = io.Platform.environment["PUB_HOSTED_URL"];
+    if (url != null) return url;
+    return "https://pub.dartlang.org";
+  }
+
   /// Downloads a list of all versions of a package that are available from the
   /// site.
   Future<List<Version>> getVersions(String name, description) {
@@ -125,7 +130,7 @@
   }
 
   List<Package> getCachedPackages([String url]) {
-    if (url == null) url = DEFAULT_URL;
+    if (url == null) url = defaultUrl;
 
     var cacheDir = path.join(systemCacheRoot,
                              _getSourceDirectory(url));
@@ -237,7 +242,7 @@
 /// this throws a descriptive FormatException.
 Pair<String, String> _parseDescription(description) {
   if (description is String) {
-    return new Pair<String, String>(description, HostedSource.DEFAULT_URL);
+    return new Pair<String, String>(description, HostedSource.defaultUrl);
   }
 
   if (description is! Map) {
@@ -256,7 +261,7 @@
   }
 
   var url = description["url"];
-  if (url == null) url = HostedSource.DEFAULT_URL;
+  if (url == null) url = HostedSource.defaultUrl;
 
   return new Pair<String, String>(name, url);
 }
diff --git a/sdk/lib/codec/encoding.dart b/sdk/lib/codec/encoding.dart
index 50b724b..40e0f2b 100644
--- a/sdk/lib/codec/encoding.dart
+++ b/sdk/lib/codec/encoding.dart
@@ -20,11 +20,41 @@
  * A [Utf8Codec] encodes strings to utf-8 code units (bytes) and decodes
  * UTF-8 code units to strings.
  */
-// TODO(floitsch): Needs a way to specify if decoding should throw or use
-// the replacement character.
 class Utf8Codec extends Encoding {
-  const Utf8Codec();
+  final bool _allowMalformed;
+
+  /**
+   * Instantiates a new [Utf8Codec].
+   *
+   * The optional [allowMalformed] argument defines how [decoder] (and [decode])
+   * deal with invalid or unterminated character sequences.
+   *
+   * If it is `true` (and not overriden at the method invocation) [decode] and
+   * the [decoder] replace invalid (or unterminated) octet
+   * sequences with the Unicode Replacement character `U+FFFD` (�). Otherwise
+   * they throw a [FormatException].
+   */
+  const Utf8Codec({ bool allowMalformed: false })
+      : _allowMalformed = allowMalformed;
+
+  /**
+   * Decodes the UTF-8 [codeUnits] (a list of unsigned 8-bit integers) to the
+   * corresponding string.
+   *
+   * If [allowMalformed] is `true` the decoder replaces invalid (or
+   * unterminated) character sequences with the Unicode Replacement character
+   * `U+FFFD` (�). Otherwise it throws a [FormatException].
+   *
+   * If [allowMalformed] is not given, it defaults to the `allowMalformed` that
+   * was used to instantiate `this`.
+   */
+  String decode(List<int> codeUnits, { bool allowMalformed }) {
+    if (allowMalformed == null) allowMalformed = _allowMalformed;
+    return new Utf8Decoder(allowMalformed: allowMalformed).convert(codeUnits);
+  }
 
   Converter<String, List<int>> get encoder => new Utf8Encoder();
-  Converter<List<int>, String> get decoder => new Utf8Decoder();
+  Converter<List<int>, String> get decoder {
+    return new Utf8Decoder(allowMalformed: _allowMalformed);
+  }
 }
diff --git a/sdk/lib/convert/utf.dart b/sdk/lib/convert/utf.dart
index 09692f0..b7fc365 100644
--- a/sdk/lib/convert/utf.dart
+++ b/sdk/lib/convert/utf.dart
@@ -21,11 +21,187 @@
  * to a string.
  */
 class Utf8Decoder extends Converter<List<int>, String> {
+  final bool _allowMalformed;
+
+  /**
+   * Instantiates a new [Utf8Decoder].
+   *
+   * The optional [allowMalformed] argument defines how [convert] deals
+   * with invalid or unterminated character sequences.
+   *
+   * If it is `true` [convert] replaces invalid (or unterminated) character
+   * sequences with the Unicode Replacement character `U+FFFD` (�). Otherwise
+   * it throws a [FormatException].
+   */
+  Utf8Decoder({ bool allowMalformed: false })
+      : this._allowMalformed = allowMalformed;
+
   /**
    * Converts the UTF-8 [codeUnits] (a list of unsigned 8-bit integers) to the
    * corresponding string.
    */
-  // TODO(floitsch): allow to configure the decoder (for example the replacement
-  // character).
-  String convert(List<int> codeUnits) => OLD_UTF_LIB.decodeUtf8(codeUnits);
+  String convert(List<int> codeUnits) {
+    StringBuffer buffer = new StringBuffer();
+    _Utf8Decoder decoder = new _Utf8Decoder(_allowMalformed);
+    decoder.convert(codeUnits, 0, codeUnits.length, buffer);
+    decoder.close(buffer);
+    return buffer.toString();
+  }
+}
+
+// UTF-8 constants.
+const int _ONE_BYTE_LIMIT = 0x7f;   // 7 bytes
+const int _TWO_BYTE_LIMIT = 0x7ff;  // 11 bytes
+const int _THREE_BYTE_LIMIT = 0xffff;  // 16 bytes
+const int _FOUR_BYTE_LIMIT = 0x10ffff;  // 21 bytes, truncated to Unicode max.
+
+// UTF-16 constants.
+const int _SURROGATE_MASK = 0xF800;
+const int _SURROGATE_TAG_MASK = 0xFC00;
+const int _SURROGATE_VALUE_MASK = 0x3FF;
+const int _LEAD_SURROGATE_MIN = 0xD800;
+const int _TAIL_SURROGATE_MIN = 0xDC00;
+
+const int _REPLACEMENT_CHARACTER = 0xFFFD;
+const int _BOM_CHARACTER = 0xFEFF;
+
+bool _isSurrogate(int codeUnit) =>
+    (codeUnit & _SURROGATE_MASK) == _LEAD_SURROGATE_MIN;
+bool _isLeadSurrogate(int codeUnit) =>
+    (codeUnit & _SURROGATE_TAG_MASK) == _LEAD_SURROGATE_MIN;
+bool _isTailSurrogate(int codeUnit) =>
+    (codeUnit & _SURROGATE_TAG_MASK) == _TAIL_SURROGATE_MIN;
+int _combineSurrogatePair(int lead, int tail) =>
+    0x10000 | ((lead & _SURROGATE_VALUE_MASK) << 10)
+            | (tail & _SURROGATE_VALUE_MASK);
+
+
+/**
+ * Decodes UTF-8.
+ *
+ * The decoder handles chunked input.
+ */
+// TODO(floitsch): make this class public.
+class _Utf8Decoder {
+  final bool _allowMalformed;
+  bool _isFirstCharacter = true;
+  int _value = 0;
+  int _expectedUnits = 0;
+  int _extraUnits = 0;
+
+  _Utf8Decoder(this._allowMalformed);
+
+  bool get hasPartialInput => _expectedUnits > 0;
+
+  // Limits of one through four byte encodings.
+  static const List<int> _LIMITS = const <int>[
+      _ONE_BYTE_LIMIT,
+      _TWO_BYTE_LIMIT,
+      _THREE_BYTE_LIMIT,
+      _FOUR_BYTE_LIMIT ];
+
+  void close(StringSink sink) {
+    if (hasPartialInput) {
+      if (!_allowMalformed) {
+        throw new FormatException("Unfinished UTF-8 octet sequence");
+      }
+      sink.writeCharCode(_REPLACEMENT_CHARACTER);
+    }
+  }
+
+  void convert(List<int> codeUnits, int startIndex, int endIndex,
+               StringSink sink) {
+    int value = _value;
+    int expectedUnits = _expectedUnits;
+    int extraUnits = _extraUnits;
+    _value = 0;
+    _expectedUnits = 0;
+    _extraUnits = 0;
+
+    int i = startIndex;
+    loop: while (true) {
+      multibyte: if (expectedUnits > 0) {
+        do {
+          if (i == endIndex) {
+            break loop;
+          }
+          int unit = codeUnits[i];
+          if ((unit & 0xC0) != 0x80) {
+            expectedUnits = 0;
+            if (!_allowMalformed) {
+              throw new FormatException(
+                  "Bad UTF-8 encoding 0x${unit.toRadixString(16)}");
+            }
+            _isFirstCharacter = false;
+            sink.writeCharCode(_REPLACEMENT_CHARACTER);
+            break multibyte;
+          } else {
+            value = (value << 6) | (unit & 0x3f);
+            expectedUnits--;
+            i++;
+          }
+        } while (expectedUnits > 0);
+        if (value <= _LIMITS[extraUnits - 1]) {
+          // Overly long encoding. The value could be encoded with a shorter
+          // encoding.
+          if (!_allowMalformed) {
+            throw new FormatException(
+                "Overlong encoding of 0x${value.toRadixString(16)}");
+          }
+          expectedUnits = extraUnits = 0;
+          value = _REPLACEMENT_CHARACTER;
+        }
+        if (value > _FOUR_BYTE_LIMIT) {
+          if (!_allowMalformed) {
+            throw new FormatException("Character outside valid Unicode range: "
+                                      "0x${value.toRadixString(16)}");
+          }
+          value = _REPLACEMENT_CHARACTER;
+        }
+        if (!_isFirstCharacter || value != _BOM_CHARACTER) {
+          sink.writeCharCode(value);
+        }
+        _isFirstCharacter = false;
+      }
+
+      while (i < endIndex) {
+        int unit = codeUnits[i++];
+        if (unit <= _ONE_BYTE_LIMIT) {
+          _isFirstCharacter = false;
+          sink.writeCharCode(unit);
+        } else {
+          if ((unit & 0xE0) == 0xC0) {
+            value = unit & 0x1F;
+            expectedUnits = extraUnits = 1;
+            continue loop;
+          }
+          if ((unit & 0xF0) == 0xE0) {
+            value = unit & 0x0F;
+            expectedUnits = extraUnits = 2;
+            continue loop;
+          }
+          // 0xF5, 0xF6 ... 0xFF never appear in valid UTF-8 sequences.
+          if ((unit & 0xF8) == 0xF0 && unit < 0xF5) {
+            value = unit & 0x07;
+            expectedUnits = extraUnits = 3;
+            continue loop;
+          }
+          if (!_allowMalformed) {
+            throw new FormatException(
+                "Bad UTF-8 encoding 0x${unit.toRadixString(16)}");
+          }
+          value = _REPLACEMENT_CHARACTER;
+          expectedUnits = extraUnits = 0;
+          _isFirstCharacter = false;
+          sink.writeCharCode(value);
+        }
+      }
+      break loop;
+    }
+    if (expectedUnits > 0) {
+      _value = value;
+      _expectedUnits = expectedUnits;
+      _extraUnits = extraUnits;
+    }
+  }
 }
diff --git a/sdk/lib/html/dart2js/html_dart2js.dart b/sdk/lib/html/dart2js/html_dart2js.dart
index 47f469b..1733d9e 100644
--- a/sdk/lib/html/dart2js/html_dart2js.dart
+++ b/sdk/lib/html/dart2js/html_dart2js.dart
@@ -8983,10 +8983,9 @@
   @DocsEditable()
   final HtmlCollection $dom_children;
 
-  @JSName('className')
   @DomName('Element.className')
   @DocsEditable()
-  String $dom_className;
+  String className;
 
   @DomName('Element.clientHeight')
   @DocsEditable()
@@ -16916,6 +16915,10 @@
   @DocsEditable()
   final Node nextNode;
 
+  @DomName('Node.nodeName')
+  @DocsEditable()
+  final String nodeName;
+
   @DomName('Node.nodeType')
   @DocsEditable()
   final int nodeType;
@@ -26638,7 +26641,7 @@
   void writeClasses(Set<String> s) {
     var classes = new List.from(s).join(' ');
     for (Element e in _elementIterable) {
-      e.$dom_className = classes;
+      e.className = classes;
     }
   }
 
@@ -26683,7 +26686,7 @@
 
   Set<String> readClasses() {
     var s = new LinkedHashSet<String>();
-    var classname = _element.$dom_className;
+    var classname = _element.className;
 
     for (String name in classname.split(' ')) {
       String trimmed = name.trim();
@@ -26696,7 +26699,7 @@
 
   void writeClasses(Set<String> s) {
     List list = new List.from(s);
-    _element.$dom_className = s.join(' ');
+    _element.className = s.join(' ');
   }
 }
 // Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
diff --git a/sdk/lib/html/dartium/html_dartium.dart b/sdk/lib/html/dartium/html_dartium.dart
index d308ceb..4a510d0 100644
--- a/sdk/lib/html/dartium/html_dartium.dart
+++ b/sdk/lib/html/dartium/html_dartium.dart
@@ -9268,11 +9268,11 @@
 
   @DomName('Element.className')
   @DocsEditable()
-  String get $dom_className native "Element_className_Getter";
+  String get className native "Element_className_Getter";
 
   @DomName('Element.className')
   @DocsEditable()
-  void set $dom_className(String value) native "Element_className_Setter";
+  void set className(String value) native "Element_className_Setter";
 
   @DomName('Element.clientHeight')
   @DocsEditable()
@@ -17887,6 +17887,10 @@
   @DocsEditable()
   Node get nextNode native "Node_nextSibling_Getter";
 
+  @DomName('Node.nodeName')
+  @DocsEditable()
+  String get nodeName native "Node_nodeName_Getter";
+
   @DomName('Node.nodeType')
   @DocsEditable()
   int get nodeType native "Node_nodeType_Getter";
@@ -28248,7 +28252,7 @@
   void writeClasses(Set<String> s) {
     var classes = new List.from(s).join(' ');
     for (Element e in _elementIterable) {
-      e.$dom_className = classes;
+      e.className = classes;
     }
   }
 
@@ -28293,7 +28297,7 @@
 
   Set<String> readClasses() {
     var s = new LinkedHashSet<String>();
-    var classname = _element.$dom_className;
+    var classname = _element.className;
 
     for (String name in classname.split(' ')) {
       String trimmed = name.trim();
@@ -28306,7 +28310,7 @@
 
   void writeClasses(Set<String> s) {
     List list = new List.from(s);
-    _element.$dom_className = s.join(' ');
+    _element.className = s.join(' ');
   }
 }
 // Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
@@ -30965,6 +30969,127 @@
   static void spawnDomFunction(Function f, int replyTo) native "Utils_spawnDomFunction";
   static void spawnDomUri(String uri, int replyTo) native "Utils_spawnDomUri";
   static int _getNewIsolateId() native "Utils_getNewIsolateId";
+
+  // The following methods were added for debugger integration to make working
+  // with the Dart C mirrors API simpler.
+  // TODO(jacobr): consider moving them to a separate library.
+  // If Dart supported dynamic code injection, we would only inject this code
+  // when the debugger is invoked.
+
+  /**
+   * Strips the private secret prefix from member names of the form
+   * someName@hash.
+   */
+  static String stripMemberName(String name) {
+    int endIndex = name.indexOf('@');
+    return endIndex > 0 ? name.substring(0, endIndex) : name;
+  }
+
+  /**
+   * Takes a list containing variable names and corresponding values and
+   * returns a map from normalized names to values. Variable names are assumed
+   * to have list offsets 2*n values at offset 2*n+1. This method is required
+   * because Dart_GetLocalVariables returns a list instead of an object that
+   * can be queried to lookup names and values.
+   */
+  static Map<String, dynamic> createLocalVariablesMap(List localVariables) {
+    var map = {};
+    for (int i = 0; i < localVariables.length; i+=2) {
+      map[stripMemberName(localVariables[i])] = localVariables[i+1];
+    }
+    return map;
+  }
+
+  /**
+   * Convenience helper to get the keys of a [Map] as a [List].
+   */
+  static List getMapKeyList(Map map) => map.keys.toList();
+
+ /**
+   * Returns the keys of an arbitrary Dart Map encoded as unique Strings.
+   * Keys that are strings are left unchanged except that the prefix ":" is
+   * added to disambiguate keys from other Dart members.
+   * Keys that are not strings have # followed by the index of the key in the map
+   * prepended to disambuguate. This scheme is simplistic but easy to encode and
+   * decode. The use case for this method is displaying all map keys in a human
+   * readable way in debugging tools.
+   */ 
+  static List<String> getEncodedMapKeyList(dynamic obj) {
+    if (obj is! Map) return null;
+    
+    var ret = new List<String>();
+    int i = 0;
+    return obj.keys.map((key) {
+      var encodedKey;
+      if (key is String) {
+        encodedKey = ':$key';
+      } else {
+        // If the key isn't a string, return a guaranteed unique for this map
+        // string representation of the key that is still somewhat human
+        // readable.
+        encodedKey = '#${i}:$key';
+      }
+      i++;
+      return encodedKey;
+    }).toList(growable: false);
+  }
+
+  static final RegExp _NON_STRING_KEY_REGEXP = new RegExp("^#(\\d+):(.+)\$");
+
+  static _decodeKey(Map map, String key) {
+    // The key is a regular old String.
+    if (key.startsWith(':')) return key.substring(1);
+
+    var match = _NON_STRING_KEY_REGEXP.firstMatch(key);
+    if (match != null) {
+      int index = int.parse(match.group(1));
+      var iter = map.keys.skip(index);
+      if (iter.isNotEmpty) {
+        var ret = iter.first;
+        // Validate that the toString representation of the key matches what we
+        // expect. FIXME: throw an error if it does not.
+        assert(match.group(2) == '$ret');
+        return ret;
+      }
+    }
+    return null;
+  }
+
+  /**
+   * Converts keys encoded with [getEncodedMapKeyList] to their actual keys.
+   */
+  static lookupValueForEncodedMapKey(Map obj, String key) => obj[_decodeKey(obj, key)];
+
+  /**
+   * Builds a constructor name with the form expected by the C Dart mirrors API.
+   */
+  static String buildConstructorName(String className, String constructorName) => '$className.$constructorName';
+
+  /**
+   * Strips the class name from an expression of the form "className.someName".
+   */
+  static String stripClassName(String str, String className) {
+    if (str.length > className.length + 1 &&
+        str.startsWith(className) && str[className.length] == '.') {
+      return str.substring(className.length + 1);
+    } else {
+      return str;
+    }
+  }
+
+  /**
+   * Removes the trailing dot from an expression ending in a dot.
+   * This method is used as Library prefixes include a trailing dot when using
+   * the C Dart debugger API.
+   */
+  static String stripTrailingDot(String str) =>
+    (str != null && str[str.length - 1] == '.') ? str.substring(0, str.length - 1) : str;
+
+  static String addTrailingDot(String str) => '${str}.';
+
+  // TODO(jacobr): we need a failsafe way to determine that a Node is really a
+  // DOM node rather than just a class that extends Node.
+  static bool isNode(obj) => obj is Node;
 }
 
 class _NPObject extends NativeFieldWrapperClass1 {
diff --git a/sdk/lib/js/dart2js/js_dart2js.dart b/sdk/lib/js/dart2js/js_dart2js.dart
new file mode 100644
index 0000000..7f806b7
--- /dev/null
+++ b/sdk/lib/js/dart2js/js_dart2js.dart
@@ -0,0 +1,201 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library dart.js;
+
+import 'dart:_foreign_helper' show JS;
+import 'dart:_js_helper' show convertDartClosureToJS;
+
+JsObject get context {
+  return new JsObject._fromJs(JS('=Object', 'window'));
+}
+
+JsObject jsify(dynamic data) => data == null ? null : new JsObject._json(data);
+
+class Callback implements Serializable<JsFunction> {
+  final Function _f; // here to allow capture in closure
+  final bool _withThis; // here to allow capture in closure
+  dynamic _jsFunction;
+
+  Callback._(this._f, this._withThis) {
+    _jsFunction = JS('=Object', r'''
+(function(){
+  var f = #;
+  return function(){
+    return f(this, Array.prototype.slice.apply(arguments));
+  };
+}).apply(this)''', convertDartClosureToJS(_call, 2));
+  }
+
+  factory Callback(Function f) => new Callback._(f, false);
+  factory Callback.withThis(Function f) => new Callback._(f, true);
+
+  _call(thisArg, List args) {
+    final arguments = new List.from(args);
+    if (_withThis) arguments.insert(0, thisArg);
+    final dartArgs = arguments.map(_convertToDart).toList();
+    return _convertToJS(Function.apply(_f, dartArgs));
+  }
+
+  JsFunction toJs() => new JsFunction._fromJs(_jsFunction);
+}
+
+class JsObject implements Serializable<JsObject> {
+  final dynamic _jsObject;
+
+  JsObject._fromJs(this._jsObject);
+
+  // TODO(vsm): Type constructor as Serializable<JsFunction> when
+  // dartbug.com/11854 is fixed.
+  factory JsObject(var constructor, [List arguments]) {
+    final constr = _convertToJS(constructor);
+    if (arguments == null) {
+      return new JsObject._fromJs(JS('=Object', 'new #()', constr));
+    }
+    final args = arguments.map(_convertToJS).toList();
+    switch (args.length) {
+      case 0:
+        return new JsObject._fromJs(JS('=Object', 'new #()', constr));
+      case 1:
+        return new JsObject._fromJs(JS('=Object', 'new #(#)', constr, args[0]));
+      case 2:
+        return new JsObject._fromJs(JS('=Object', 'new #(#,#)', constr, args[0],
+            args[1]));
+      case 3:
+        return new JsObject._fromJs(JS('=Object', 'new #(#,#,#)', constr,
+            args[0], args[1], args[2]));
+      case 4:
+        return new JsObject._fromJs(JS('=Object', 'new #(#,#,#,#)', constr,
+            args[0], args[1], args[2], args[3]));
+      case 5:
+        return new JsObject._fromJs(JS('=Object', 'new #(#,#,#,#,#)', constr,
+            args[0], args[1], args[2], args[3], args[4]));
+      case 6:
+        return new JsObject._fromJs(JS('=Object', 'new #(#,#,#,#,#,#)', constr,
+            args[0], args[1], args[2], args[3], args[4], args[5]));
+      case 7:
+        return new JsObject._fromJs(JS('=Object', 'new #(#,#,#,#,#,#,#)',
+            constr, args[0], args[1], args[2], args[3], args[4], args[5],
+            args[6]));
+      case 8:
+        return new JsObject._fromJs(JS('=Object', 'new #(#,#,#,#,#,#,#,#)',
+            constr, args[0], args[1], args[2], args[3], args[4], args[5],
+            args[6], args[7]));
+      case 9:
+        return new JsObject._fromJs(JS('=Object', 'new #(#,#,#,#,#,#,#,#,#)',
+            constr, args[0], args[1], args[2], args[3], args[4], args[5],
+            args[6], args[7], args[8]));
+      case 10:
+        return new JsObject._fromJs(JS('=Object', 'new #(#,#,#,#,#,#,#,#,#,#)',
+            constr, args[0], args[1], args[2], args[3], args[4], args[5],
+            args[6], args[7], args[8], args[9]));
+    }
+    return new JsObject._fromJs(JS('=Object', r'''(function(){
+var Type = function(){};
+Type.prototype = #.prototype;
+var instance = new Type();
+ret = #.apply(instance, #);
+ret = Object(ret) === ret ? ret : instance;
+return ret;
+})()''', constr, constr, args));
+  }
+
+  factory JsObject._json(data) => new JsObject._fromJs(_convertDataTree(data));
+
+  static _convertDataTree(data) {
+    if (data is Map) {
+      final convertedData = JS('=Object', '{}');
+      for (var key in data.keys) {
+        JS('=Object', '#[#]=#', convertedData, key,
+            _convertDataTree(data[key]));
+      }
+      return convertedData;
+    } else if (data is Iterable) {
+      return data.map(_convertDataTree).toList();
+    } else {
+      return _convertToJS(data);
+    }
+  }
+
+  JsObject toJs() => this;
+
+  operator[](key) =>
+      _convertToDart(JS('=Object', '#[#]', _convertToJS(this), key));
+  operator[]=(key, value) => JS('void', '#[#]=#', _convertToJS(this), key,
+      _convertToJS(value));
+
+  int get hashCode => 0;
+
+  operator==(other) => other is JsObject &&
+      JS('bool', '# === #', _convertToJS(this), _convertToJS(other));
+
+  bool hasProperty(String property) => JS('bool', '# in #', property,
+      _convertToJS(this));
+
+  void deleteProperty(String name) {
+    JS('void', 'delete #[#]', _convertToJS(this), name);
+  }
+
+  // TODO(vsm): Type type as Serializable<JsFunction> when
+  // dartbug.com/11854 is fixed.
+  bool instanceof(var type) =>
+      JS('bool', '# instanceof #', _convertToJS(this), _convertToJS(type));
+
+  String toString() {
+    try {
+      return JS('String', '#.toString()', _convertToJS(this));
+    } catch(e) {
+      return super.toString();
+    }
+  }
+
+  callMethod(String name, [List args]) =>
+      _convertToDart(JS('=Object', '#[#].apply(#, #)', _convertToJS(this), name,
+          _convertToJS(this),
+          args == null ? null : args.map(_convertToJS).toList()));
+}
+
+class JsFunction extends JsObject implements Serializable<JsFunction> {
+  JsFunction._fromJs(jsObject) : super._fromJs(jsObject);
+  apply(thisArg, [List args]) =>
+      _convertToDart(JS('=Object', '#.apply(#, #)', _convertToJS(this),
+          _convertToJS(thisArg),
+          args == null ? null : args.map(_convertToJS).toList()));
+}
+
+abstract class Serializable<T> {
+  T toJs();
+}
+
+dynamic _convertToJS(dynamic o) {
+  if (o == null) {
+    return null;
+  } else if (o is String || o is num || o is bool) {
+    return o;
+  } else if (o is JsObject) {
+    return o._jsObject;
+  } else if (o is Serializable) {
+    return _convertToJS(o.toJs());
+  } else if (o is Function) {
+    return _convertToJS(new Callback(o));
+  } else {
+    return JS('=Object', 'new DartProxy(#)', o);
+  }
+}
+
+dynamic _convertToDart(dynamic o) {
+  if (JS('bool', '# == null', o)) {
+    return null;
+  } else if (JS('bool', 'typeof # == "string" || # instanceof String', o, o) ||
+      JS('bool', 'typeof # == "number" || # instanceof Number', o, o) ||
+      JS('bool', 'typeof # == "boolean" || # instanceof Boolean', o, o)) {
+    return o;
+  } else if (JS('bool', '# instanceof Function', o)) {
+    return new JsFunction._fromJs(JS('=Object', '#', o));
+  } else if (JS('bool', '# instanceof DartProxy', o)) {
+    return JS('var', '#.o', o);
+  } else {
+    return new JsObject._fromJs(JS('=Object', '#', o));
+  }
+}
\ No newline at end of file
diff --git a/sdk/lib/js/dartium/js_dartium.dart b/sdk/lib/js/dartium/js_dartium.dart
new file mode 100644
index 0000000..393320f
--- /dev/null
+++ b/sdk/lib/js/dartium/js_dartium.dart
@@ -0,0 +1,371 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/**
+ * The js.dart library provides simple JavaScript invocation from Dart that
+ * works on both Dartium and on other modern browsers via Dart2JS.
+ *
+ * It provides a model based on scoped [JsObject] objects.  Proxies give Dart
+ * code access to JavaScript objects, fields, and functions as well as the
+ * ability to pass Dart objects and functions to JavaScript functions.  Scopes
+ * enable developers to use proxies without memory leaks - a common challenge
+ * with cross-runtime interoperation.
+ *
+ * The top-level [context] getter provides a [JsObject] to the global JavaScript
+ * context for the page your Dart code is running on.  In the following example:
+ *
+ *     import 'dart:js';
+ *
+ *     void main() {
+ *       context.callMethod('alert', ['Hello from Dart via JavaScript']);
+ *     }
+ *
+ * context['alert'] creates a proxy to the top-level alert function in
+ * JavaScript.  It is invoked from Dart as a regular function that forwards to
+ * the underlying JavaScript one.  By default, proxies are released when
+ * the currently executing event completes, e.g., when main is completes
+ * in this example.
+ *
+ * The library also enables JavaScript proxies to Dart objects and functions.
+ * For example, the following Dart code:
+ *
+ *     context['dartCallback'] = new Callback.once((x) => print(x*2));
+ *
+ * defines a top-level JavaScript function 'dartCallback' that is a proxy to
+ * the corresponding Dart function.  The [Callback.once] constructor allows the
+ * proxy to the Dart function to be retained across multiple events;
+ * instead it is released after the first invocation.  (This is a common
+ * pattern for asychronous callbacks.)
+ *
+ * Note, parameters and return values are intuitively passed by value for
+ * primitives and by reference for non-primitives.  In the latter case, the
+ * references are automatically wrapped and unwrapped as proxies by the library.
+ *
+ * This library also allows construction of JavaScripts objects given a
+ * [JsObject] to a corresponding JavaScript constructor.  For example, if the
+ * following JavaScript is loaded on the page:
+ *
+ *     function Foo(x) {
+ *       this.x = x;
+ *     }
+ *
+ *     Foo.prototype.add = function(other) {
+ *       return new Foo(this.x + other.x);
+ *     }
+ *
+ * then, the following Dart:
+ *
+ *     var foo = new JsObject(context['Foo'], [42]);
+ *     var foo2 = foo.callMethod('add', [foo]);
+ *     print(foo2['x']);
+ *
+ * will construct a JavaScript Foo object with the parameter 42, invoke its
+ * add method, and return a [JsObject] to a new Foo object whose x field is 84.
+ */
+
+library dart.js;
+
+import 'dart:html';
+import 'dart:isolate';
+
+// Global ports to manage communication from Dart to JS.
+SendPortSync _jsPortSync = window.lookupPort('dart-js-context');
+SendPortSync _jsPortCreate = window.lookupPort('dart-js-create');
+SendPortSync _jsPortInstanceof = window.lookupPort('dart-js-instanceof');
+SendPortSync _jsPortDeleteProperty = window.lookupPort('dart-js-delete-property');
+SendPortSync _jsPortConvert = window.lookupPort('dart-js-convert');
+
+/**
+ * Returns a proxy to the global JavaScript context for this page.
+ */
+JsObject get context => _deserialize(_jsPortSync.callSync([]));
+
+/**
+ * Converts a json-like [data] to a JavaScript map or array and return a
+ * [JsObject] to it.
+ */
+JsObject jsify(dynamic data) => data == null ? null : new JsObject._json(data);
+
+/**
+ * Converts a local Dart function to a callback that can be passed to
+ * JavaScript.
+ */
+class Callback implements Serializable<JsFunction> {
+  JsFunction _f;
+
+  Callback._(Function f, bool withThis) {
+    final id = _proxiedObjectTable.add((List args) {
+      final arguments = new List.from(args);
+      if (!withThis) arguments.removeAt(0);
+      return Function.apply(f, arguments);
+    });
+    _f = new JsFunction._internal(_proxiedObjectTable.sendPort, id);
+  }
+
+  factory Callback(Function f) => new Callback._(f, false);
+  factory Callback.withThis(Function f) => new Callback._(f, true);
+
+  JsFunction toJs() => _f;
+}
+
+/**
+ * Proxies to JavaScript objects.
+ */
+class JsObject implements Serializable<JsObject> {
+  final SendPortSync _port;
+  final String _id;
+
+  /**
+   * Constructs a [JsObject] to a new JavaScript object by invoking a (proxy to
+   * a) JavaScript [constructor].  The [arguments] list should contain either
+   * primitive values, DOM elements, or Proxies.
+   */
+  factory JsObject(Serializable<JsFunction> constructor, [List arguments]) {
+    final params = [constructor];
+    if (arguments != null) params.addAll(arguments);
+    final serialized = params.map(_serialize).toList();
+    final result = _jsPortCreate.callSync(serialized);
+    return _deserialize(result);
+  }
+
+  /**
+   * Constructs a [JsObject] to a new JavaScript map or list created defined via
+   * Dart map or list.
+   */
+  factory JsObject._json(data) => _convert(data);
+
+  static _convert(data) =>
+      _deserialize(_jsPortConvert.callSync(_serializeDataTree(data)));
+
+  static _serializeDataTree(data) {
+    if (data is Map) {
+      final entries = new List();
+      for (var key in data.keys) {
+        entries.add([key, _serializeDataTree(data[key])]);
+      }
+      return ['map', entries];
+    } else if (data is Iterable) {
+      return ['list', data.map(_serializeDataTree).toList()];
+    } else {
+      return ['simple', _serialize(data)];
+    }
+  }
+
+  JsObject._internal(this._port, this._id);
+
+  JsObject toJs() => this;
+
+  // Resolve whether this is needed.
+  operator[](arg) => _forward(this, '[]', 'method', [ arg ]);
+
+  // Resolve whether this is needed.
+  operator[]=(key, value) => _forward(this, '[]=', 'method', [ key, value ]);
+
+  int get hashCode => _id.hashCode;
+
+  // Test if this is equivalent to another Proxy.  This essentially
+  // maps to JavaScript's === operator.
+  operator==(other) => other is JsObject && this._id == other._id;
+
+  /**
+   * Check if this [JsObject] has a [name] property.
+   */
+  bool hasProperty(String name) => _forward(this, name, 'hasProperty', []);
+
+  /**
+   * Delete the [name] property.
+   */
+  void deleteProperty(String name) {
+    _jsPortDeleteProperty.callSync([this, name].map(_serialize).toList());
+  }
+
+  /**
+   * Check if this [JsObject] is instance of [type].
+   */
+  bool instanceof(Serializable<JsFunction> type) =>
+      _jsPortInstanceof.callSync([this, type].map(_serialize).toList());
+
+  String toString() {
+    try {
+      return _forward(this, 'toString', 'method', []);
+    } catch(e) {
+      return super.toString();
+    }
+  }
+
+  callMethod(String name, [List args]) {
+    return _forward(this, name, 'method', args != null ? args : []);
+  }
+
+  // Forward member accesses to the backing JavaScript object.
+  static _forward(JsObject receiver, String member, String kind, List args) {
+    var result = receiver._port.callSync([receiver._id, member, kind,
+                                          args.map(_serialize).toList()]);
+    switch (result[0]) {
+      case 'return': return _deserialize(result[1]);
+      case 'throws': throw _deserialize(result[1]);
+      case 'none': throw new NoSuchMethodError(receiver, member, args, {});
+      default: throw 'Invalid return value';
+    }
+  }
+}
+
+/// A [JsObject] subtype to JavaScript functions.
+class JsFunction extends JsObject implements Serializable<JsFunction> {
+  JsFunction._internal(SendPortSync port, String id)
+      : super._internal(port, id);
+
+  apply(thisArg, [List args]) {
+    return JsObject._forward(this, '', 'apply',
+        [thisArg]..addAll(args == null ? [] : args));
+  }
+}
+
+/// Marker class used to indicate it is serializable to js. If a class is a
+/// [Serializable] the "toJs" method will be called and the result will be used
+/// as value.
+abstract class Serializable<T> {
+  T toJs();
+}
+
+// A table to managed local Dart objects that are proxied in JavaScript.
+class _ProxiedObjectTable {
+  // Debugging name.
+  final String _name;
+
+  // Generator for unique IDs.
+  int _nextId;
+
+  // Table of IDs to Dart objects.
+  final Map<String, Object> _registry;
+
+  // Port to handle and forward requests to the underlying Dart objects.
+  // A remote proxy is uniquely identified by an ID and SendPortSync.
+  final ReceivePortSync _port;
+
+  _ProxiedObjectTable() :
+      _name = 'dart-ref',
+      _nextId = 0,
+      _registry = {},
+      _port = new ReceivePortSync() {
+    _port.receive((msg) {
+      try {
+        final receiver = _registry[msg[0]];
+        final method = msg[1];
+        final args = msg[2].map(_deserialize).toList();
+        if (method == '#call') {
+          final func = receiver as Function;
+          var result = _serialize(func(args));
+          return ['return', result];
+        } else {
+          // TODO(vsm): Support a mechanism to register a handler here.
+          throw 'Invocation unsupported on non-function Dart proxies';
+        }
+      } catch (e) {
+        // TODO(vsm): callSync should just handle exceptions itself.
+        return ['throws', '$e'];
+      }
+    });
+  }
+
+  // Adds a new object to the table and return a new ID for it.
+  String add(x) {
+    // TODO(vsm): Cache x and reuse id.
+    final id = '$_name-${_nextId++}';
+    _registry[id] = x;
+    return id;
+  }
+
+  // Gets an object by ID.
+  Object get(String id) {
+    return _registry[id];
+  }
+
+  // Gets the current number of objects kept alive by this table.
+  get count => _registry.length;
+
+  // Gets a send port for this table.
+  get sendPort => _port.toSendPort();
+}
+
+// The singleton to manage proxied Dart objects.
+_ProxiedObjectTable _proxiedObjectTable = new _ProxiedObjectTable();
+
+/// End of proxy implementation.
+
+// Dart serialization support.
+
+_serialize(var message) {
+  if (message == null) {
+    return null;  // Convert undefined to null.
+  } else if (message is String ||
+             message is num ||
+             message is bool) {
+    // Primitives are passed directly through.
+    return message;
+  } else if (message is SendPortSync) {
+    // Non-proxied objects are serialized.
+    return message;
+  } else if (message is JsFunction) {
+    // Remote function proxy.
+    return [ 'funcref', message._id, message._port ];
+  } else if (message is JsObject) {
+    // Remote object proxy.
+    return [ 'objref', message._id, message._port ];
+  } else if (message is Serializable) {
+    // use of result of toJs()
+    return _serialize(message.toJs());
+  } else if (message is Function) {
+    return _serialize(new Callback(message));
+  } else {
+    // Local object proxy.
+    return [ 'objref',
+             _proxiedObjectTable.add(message),
+             _proxiedObjectTable.sendPort ];
+  }
+}
+
+_deserialize(var message) {
+  deserializeFunction(message) {
+    var id = message[1];
+    var port = message[2];
+    if (port == _proxiedObjectTable.sendPort) {
+      // Local function.
+      return _proxiedObjectTable.get(id);
+    } else {
+      // Remote function.  Forward to its port.
+      return new JsFunction._internal(port, id);
+    }
+  }
+
+  deserializeObject(message) {
+    var id = message[1];
+    var port = message[2];
+    if (port == _proxiedObjectTable.sendPort) {
+      // Local object.
+      return _proxiedObjectTable.get(id);
+    } else {
+      // Remote object.
+      return new JsObject._internal(port, id);
+    }
+  }
+
+  if (message == null) {
+    return null;  // Convert undefined to null.
+  } else if (message is String ||
+             message is num ||
+             message is bool) {
+    // Primitives are passed directly through.
+    return message;
+  } else if (message is SendPortSync) {
+    // Serialized type.
+    return message;
+  }
+  var tag = message[0];
+  switch (tag) {
+    case 'funcref': return deserializeFunction(message);
+    case 'objref': return deserializeObject(message);
+  }
+  throw 'Unsupported serialized data: $message';
+}
diff --git a/sdk/lib/math/math.dart b/sdk/lib/math/math.dart
index b6ac482..6cea069 100644
--- a/sdk/lib/math/math.dart
+++ b/sdk/lib/math/math.dart
@@ -58,32 +58,24 @@
   * is returned.
   */
 num min(num a, num b) {
-  if (a is num) {
-    // TODO(floitsch): merge this if into the previous one, once dart2js
-    // correctly propagates types for logical ands.
-    if (b is num) {
-      if (a > b) return b;
-      if (a < b) return a;
-      if (b is double) {
-        // Special case for NaN and -0.0. If one argument is NaN return NaN.
-        // [min] must also distinguish between -0.0 and 0.0.
-        if (a is double) {
-          if (a == 0.0) {
-            // a is either 0.0 or -0.0. b is either 0.0, -0.0 or NaN.
-            // The following returns -0.0 if either a or b is -0.0, and it
-            // returns NaN if b is NaN.
-            return (a + b) * a * b;
-          }
-        }
-        // Check for NaN and b == -0.0.
-        if (a == 0 && b.isNegative || b.isNaN) return b;
-        return a;
+  if (a > b) return b;
+  if (a < b) return a;
+  if (b is double) {
+    // Special case for NaN and -0.0. If one argument is NaN return NaN.
+    // [min] must also distinguish between -0.0 and 0.0.
+    if (a is double) {
+      if (a == 0.0) {
+        // a is either 0.0 or -0.0. b is either 0.0, -0.0 or NaN.
+        // The following returns -0.0 if either a or b is -0.0, and it
+        // returns NaN if b is NaN.
+        return (a + b) * a * b;
       }
-      return a;
     }
-    throw new ArgumentError(b);
+    // Check for NaN and b == -0.0.
+    if (a == 0 && b.isNegative || b.isNaN) return b;
+    return a;
   }
-  throw new ArgumentError(a);
+  return a;
 }
 
 /**
@@ -95,34 +87,26 @@
   * then it is unspecified which of the two arguments is returned.
   */
 num max(num a, num b) {
-  if (a is num) {
-    // TODO(floitsch): merge this if into the previous one, once dart2js
-    // correctly propagates types for logical ands.
-    if (b is num) {
-      if (a > b) return a;
-      if (a < b) return b;
-      if (b is double) {
-        // Special case for NaN and -0.0. If one argument is NaN return NaN.
-        // [max] must also distinguish between -0.0 and 0.0.
-        if (a is double) {
-          if (a == 0.0) {
-            // a is either 0.0 or -0.0. b is either 0.0, -0.0, or NaN.
-            // The following returns 0.0 if either a or b is 0.0, and it
-            // returns NaN if b is NaN.
-            return a + b;
-          }
-        }
-        // Check for NaN.
-        if (b.isNaN) return b;
-        return a;
+  if (a > b) return a;
+  if (a < b) return b;
+  if (b is double) {
+    // Special case for NaN and -0.0. If one argument is NaN return NaN.
+    // [max] must also distinguish between -0.0 and 0.0.
+    if (a is double) {
+      if (a == 0.0) {
+        // a is either 0.0 or -0.0. b is either 0.0, -0.0, or NaN.
+        // The following returns 0.0 if either a or b is 0.0, and it
+        // returns NaN if b is NaN.
+        return a + b;
       }
-      // max(-0.0, 0) must return 0.
-      if (b == 0 && a.isNegative) return b;
-      return a;
     }
-    throw new ArgumentError(b);
+    // Check for NaN.
+    if (b.isNaN) return b;
+    return a;
   }
-  throw new ArgumentError(a);
+  // max(-0.0, 0) must return 0.
+  if (b == 0 && a.isNegative) return b;
+  return a;
 }
 
 /**
diff --git a/tests/co19/co19-analyzer.status b/tests/co19/co19-analyzer.status
index 906a6f5..2820b5f 100644
--- a/tests/co19/co19-analyzer.status
+++ b/tests/co19/co19-analyzer.status
@@ -20,7 +20,14 @@
 # analyzer problem: forward reference of typedef with type parameters
 Language/13_Libraries_and_Scripts/3_Parts_A02_t03: skip
 
+# not clear: typedef int func2(int);
+Language/14_Types/6_Type_dynamic_A04_t01: fail
 
+# TBF: _f is private, so does not collide
+Language/07_Classes/1_Instance_Methods_A05_t08: fail
+
+# TBF: return without value is not a warning
+Language/12_Statements/11_Return_A07_t01: fail
 
 
 # co19 issue #380, Strings class has been removed
@@ -219,6 +226,208 @@
 # co19 issue #464, not initialized final instance variable is warning, not error
 Language/07_Classes/6_Constructors/1_Generative_Constructors_A09_t01: fail
 
+# co19 issue #442, undefined name "Expect"
+Language/07_Classes/6_Constructors/1_Generative_Constructors_A17_t04: fail, OK
+Language/07_Classes/6_Constructors/2_Factories_A06_t03: fail, OK
+Language/09_Generics/09_Generics_A05_t02: fail, OK
+Language/09_Generics/09_Generics_A05_t01: fail, OK
+Language/11_Expressions/04_Booleans/1_Boolean_Conversion_A01_t01: fail, OK
+Language/11_Expressions/04_Booleans/1_Boolean_Conversion_A02_t01: fail, OK
+Language/11_Expressions/06_Lists_A09_t01: fail, OK
+Language/11_Expressions/14_Function_Invocation/2_Binding_Actuals_to_Formals_A02_t01: fail, OK
+Language/11_Expressions/14_Function_Invocation/2_Binding_Actuals_to_Formals_A03_t01: fail, OK
+Language/11_Expressions/18_Assignment_A02_t01: fail, OK
+Language/11_Expressions/18_Assignment_A04_t06: fail, OK
+Language/11_Expressions/18_Assignment_A06_t01: fail, OK
+Language/11_Expressions/19_Conditional_A02_t03: fail, OK
+Language/11_Expressions/19_Conditional_A02_t04: fail, OK
+Language/11_Expressions/19_Conditional_A04_t03: fail, OK
+Language/11_Expressions/27_Unary_Expressions_A02_t03: fail, OK
+Language/12_Statements/03_Variable_Declaration_A01_t01: fail, OK
+Language/12_Statements/03_Variable_Declaration_A01_t02: fail, OK
+Language/12_Statements/05_If_A02_t01: fail, OK
+Language/12_Statements/05_If_A02_t02: fail, OK
+Language/12_Statements/10_Try_A01_t01: fail, OK
+Language/12_Statements/11_Return_A03_t02: fail, OK
+Language/12_Statements/11_Return_A04_t01: fail, OK
+Language/12_Statements/15_Assert_A03_t03: fail, OK
+Language/12_Statements/15_Assert_A03_t09: fail, OK
+Language/12_Statements/15_Assert_A03_t08: fail, OK
+Language/12_Statements/15_Assert_A04_t02: fail, OK
+Language/14_Types/2_Dynamic_Type_System_A01_t01: fail, OK
+Language/14_Types/4_Interface_Types_A08_t03: fail, OK
+Language/14_Types/7_Type_Void_A04_t02: fail, OK
+Language/15_Reference/1_Lexical_Rules/2_Comments_A04_t03: fail, OK
+LibTest/core/AssertionError/toString_A01_t01: fail, OK
+LibTest/core/Date/add_A01_t01: fail, OK
+LibTest/core/Date/add_A03_t01: fail, OK
+LibTest/core/Date/add_A02_t01: fail, OK
+LibTest/core/Date/add_A05_t01: fail, OK
+LibTest/core/Date/compareTo_A01_t01: fail, OK
+LibTest/core/Date/compareTo_A02_t01: fail, OK
+LibTest/core/Date/compareTo_A03_t01: fail, OK
+LibTest/core/Date/compareTo_A01_t02: fail, OK
+LibTest/core/Date/Date.fromMillisecondsSinceEpoch_A01_t01: fail, OK
+LibTest/core/Date/Date.fromMillisecondsSinceEpoch_A01_t02: fail, OK
+LibTest/core/Date/Date.fromMillisecondsSinceEpoch_A02_t01: fail, OK
+LibTest/core/Date/Date.fromString_A01_t01: fail, OK
+LibTest/core/Date/Date.fromString_A01_t02: fail, OK
+LibTest/core/Date/Date.fromString_A02_t01: fail, OK
+LibTest/core/Date/Date.fromString_A03_t01: fail, OK
+LibTest/core/Date/Date.now_A01_t01: fail, OK
+LibTest/core/Date/Date.now_A01_t02: fail, OK
+LibTest/core/Date/Date.now_A01_t03: fail, OK
+LibTest/core/Date/Date.utc_A01_t01: fail, OK
+LibTest/core/Date/Date_A01_t01: fail, OK
+LibTest/core/Date/Date_A01_t03: fail, OK
+LibTest/core/Date/Date_A01_t02: fail, OK
+LibTest/core/Date/Date_A01_t04: fail, OK
+LibTest/core/Date/day_A01_t01: fail, OK
+LibTest/core/Date/difference_A01_t01: fail, OK
+LibTest/core/Date/difference_A01_t02: fail, OK
+LibTest/core/Date/difference_A02_t01: fail, OK
+LibTest/core/Date/hour_A01_t01: fail, OK
+LibTest/core/Date/isUtc_A01_t01: fail, OK
+LibTest/core/Date/millisecond_A01_t01: fail, OK
+LibTest/core/Date/millisecondsSinceEpoch_A01_t01: fail, OK
+LibTest/core/Date/minute_A01_t01: fail, OK
+LibTest/core/Date/month_A01_t01: fail, OK
+LibTest/core/Date/operator_equality_A01_t01: fail, OK
+LibTest/core/Date/operator_GE_A01_t01: fail, OK
+LibTest/core/Date/operator_GT_A01_t01: fail, OK
+LibTest/core/Date/operator_LE_A01_t01: fail, OK
+LibTest/core/Date/operator_LT_A01_t01: fail, OK
+LibTest/core/Date/second_A01_t01: fail, OK
+LibTest/core/Date/subtract_A01_t01: fail, OK
+LibTest/core/Date/subtract_A03_t01: fail, OK
+LibTest/core/Date/subtract_A02_t01: fail, OK
+LibTest/core/Date/subtract_A05_t01: fail, OK
+LibTest/core/Date/timeZoneName_A01_t01: fail, OK
+LibTest/core/Date/timeZoneOffset_A01_t01: fail, OK
+LibTest/core/Date/toLocal_A01_t01: fail, OK
+LibTest/core/Date/toString_A01_t01: fail, OK
+LibTest/core/Date/toString_A02_t01: fail, OK
+LibTest/core/Date/toUtc_A01_t01: fail, OK
+LibTest/core/Date/year_A01_t01: fail, OK
+LibTest/core/Date/weekday_A01_t01: fail, OK
+LibTest/core/List/getRange_A06_t01: fail, OK
+LibTest/core/List/indexOf_A06_t01: fail, OK
+LibTest/core/List/operator_subscript_A03_t01: fail, OK
+LibTest/core/List/operator_subscripted_assignment_A03_t01: fail, OK
+LibTest/core/Map/putIfAbsent_A01_t04: fail, OK
+LibTest/core/Strings/concatAll_A04_t01: fail, OK
+LibTest/core/Strings/join_A04_t01: fail, OK
+
+# co19 issue #443, Undefined class 'InvocationMirror'
+Language/11_Expressions/14_Function_Invocation/4_Function_Expression_Invocation_A01_t02: fail, OK
+Language/11_Expressions/15_Method_Invocation/1_Ordinary_Invocation_A05_t02: fail, OK
+Language/11_Expressions/15_Method_Invocation/1_Ordinary_Invocation_A05_t03: fail, OK
+Language/11_Expressions/15_Method_Invocation/1_Ordinary_Invocation_A05_t06: fail, OK
+Language/11_Expressions/17_Getter_Invocation_A02_t01: fail, OK
+Language/11_Expressions/17_Getter_Invocation_A02_t02: fail, OK
+
+# co19 issue #444, AsyncError has been removed
+LibTest/async/Completer/complete_A02_t02: fail, OK
+LibTest/async/Completer/completeError_A01_t01: fail, OK
+LibTest/async/Completer/completeError_A03_t02: fail, OK
+LibTest/async/Future/catchError_A01_t01: fail, OK
+LibTest/async/Future/catchError_A01_t02: fail, OK
+LibTest/async/Future/catchError_A02_t01: fail, OK
+LibTest/async/Future/catchError_A03_t01: fail, OK
+LibTest/async/Future/catchError_A03_t02: fail, OK
+LibTest/async/Future/catchError_A03_t03: fail, OK
+LibTest/async/Future/forEach_A03_t01: fail, OK
+LibTest/async/Future/Future.delayed_A02_t01: fail, OK
+LibTest/async/Future/then_A02_t01: fail, OK
+LibTest/async/Future/then_A02_t02: fail, OK
+LibTest/async/Future/then_A03_t01: fail, OK
+LibTest/async/Future/then_A04_t01: fail, OK
+LibTest/async/Future/whenComplete_A03_t01: fail, OK
+LibTest/async/Future/whenComplete_A04_t02: fail, OK
+
+# co19 issue #445, Future.immediate was repalce with Future.value
+LibTest/async/Future/asStream_A01_t01: fail, OK
+LibTest/async/Future/asStream_A01_t02: fail, OK
+LibTest/async/Future/asStream_A02_t01: fail, OK
+LibTest/async/Future/Future.immediate_A01_t01: fail, OK
+LibTest/async/Future/Future.immediateError_A01_t01: fail, OK
+LibTest/async/Future/then_A01_t03: fail, OK
+
+# co19 issue #446, Date was replaced with DateTime
+Language/14_Types/6_Type_dynamic_A03_t01: fail, OK
+
+# co19 issue 447, In Future delayed int replaced with Duration
+LibTest/async/Future/asStream_A01_t02: fail, OK
+LibTest/async/Future/asStream_A02_t01: fail, OK
+LibTest/async/Future/forEach_A01_t01: fail, OK
+LibTest/async/Future/forEach_A02_t01: fail, OK
+LibTest/async/Future/then_A01_t03: fail, OK
+LibTest/async/Future/wait_A01_t01: fail, OK
+LibTest/async/Future/wait_A01_t04: fail, OK
+LibTest/async/Future/wait_A01_t05: fail, OK
+LibTest/async/Future/wait_A01_t06: fail, OK
+LibTest/async/Future/whenComplete_A01_t01: fail, OK
+LibTest/async/Future/whenComplete_A02_t01: fail, OK
+LibTest/async/Future/whenComplete_A04_t01: fail, OK
+
+# co19 issue #448, Collection was removed
+LibTest/collection/Queue/Queue.from_A01_t01: fail, OK
+LibTest/collection/Queue/Queue.from_A01_t02: fail, OK
+LibTest/core/List/List.from_A01_t01: fail, OK
+LibTest/core/Match/pattern_A01_t01: fail, OK
+LibTest/core/Match/str_A01_t01: fail, OK
+LibTest/core/RegExp/allMatches_A01_t01: fail, OK
+LibTest/core/Set/intersection_A01_t02: fail, OK
+
+# co19 issue #449, Strings was removed
+LibTest/core/Strings/concatAll_A01_t01: fail, OK
+LibTest/core/Strings/concatAll_A02_t01: fail, OK
+LibTest/core/Strings/concatAll_A03_t01: fail, OK
+LibTest/core/Strings/join_A01_t01: fail, OK
+LibTest/core/Strings/join_A02_t01: fail, OK
+LibTest/core/Strings/join_A03_t01: fail, OK
+
+# co19 issue #450, The class 'List' does not have a constructor 'fixedLength'
+LibTest/core/List/add_A02_t01: fail, OK
+LibTest/core/List/addAll_A02_t01: fail, OK
+LibTest/core/List/clear_A02_t01: fail, OK
+LibTest/core/List/length_A04_t01: fail, OK
+LibTest/core/List/removeLast_A02_t01: fail, OK
+LibTest/core/List/removeRange_A02_t01: fail, OK
+
+# co19 issue 451, Set.intersection() requires Set argument
+LibTest/core/Set/intersection_A01_t01: fail, OK
+LibTest/core/Set/intersection_A01_t03: fail, OK
+LibTest/core/Set/intersection_A03_t01: fail, OK
+
+# co19 issue 452, more method in Iterable
+LibTest/core/Set/Set.from_A01_t02: fail, OK
+
+# co19 issue #453, abstract member in concrete class
+Language/07_Classes/07_Classes_A07_t10: fail, OK
+
+# co19 issue #454, should be static warning
+Language/11_Expressions/11_Instance_Creation/1_New_A01_t04: fail, OK
+
+# co19 issue #455, undeclared identifier is static warning
+Language/11_Expressions/14_Function_Invocation/3_Unqualified_Invocation_A01_t10: fail, OK
+Language/12_Statements/04_Local_Function_Declaration_A02_t02: fail, OK
+Language/13_Libraries_and_Scripts/1_Imports_A02_t12: fail, OK
+Language/13_Libraries_and_Scripts/1_Imports_A02_t14: fail, OK
+Language/13_Libraries_and_Scripts/1_Imports_A02_t15: fail, OK
+
+# co19 issue #456
+Language/11_Expressions/15_Method_Invocation/3_Static_Invocation_A03_t04: fail, OK
+Language/11_Expressions/15_Method_Invocation/3_Static_Invocation_A03_t05: fail, OK
+Language/11_Expressions/15_Method_Invocation/3_Static_Invocation_A04_t08: fail, OK
+
+# co19 issue 457, malformed type is static warning
+Language/11_Expressions/31_Type_Test_A05_t01: fail, OK
+Language/11_Expressions/31_Type_Test_A05_t02: fail, OK
+Language/11_Expressions/31_Type_Test_A05_t03: fail, OK
+Language/11_Expressions/32_Type_Cast_A04_t01: fail, OK
+Language/11_Expressions/32_Type_Cast_A04_t02: fail, OK
+
 # co19 issue #465, any use of a malbounded type gives rise to a static warning.
 Language/11_Expressions/11_Instance_Creation/1_New_A05_t01: fail, OK
 Language/11_Expressions/11_Instance_Creation/1_New_A05_t02: fail, OK
@@ -226,4 +435,3 @@
 Language/11_Expressions/11_Instance_Creation_A03_t01: fail, OK
 Language/11_Expressions/11_Instance_Creation_A04_t01: fail, OK
 Language/11_Expressions/11_Instance_Creation_A04_t02: fail, OK
-
diff --git a/tests/co19/co19-analyzer2.status b/tests/co19/co19-analyzer2.status
index 71b2817..81a6b85 100644
--- a/tests/co19/co19-analyzer2.status
+++ b/tests/co19/co19-analyzer2.status
@@ -20,7 +20,14 @@
 # analyzer problem: forward reference of typedef with type parameters
 Language/13_Libraries_and_Scripts/3_Parts_A02_t03: skip
 
+# not clear: typedef int func2(int);
+Language/14_Types/6_Type_dynamic_A04_t01: fail
 
+# TBF: _f is private, so does not collide
+Language/07_Classes/1_Instance_Methods_A05_t08: fail
+
+# TBF: return without value is not a warning
+Language/12_Statements/11_Return_A07_t01: fail
 
 
 # co19 issue #380, Strings class has been removed
@@ -219,6 +226,208 @@
 # co19 issue #464, not initialized final instance variable is warning, not error
 Language/07_Classes/6_Constructors/1_Generative_Constructors_A09_t01: fail
 
+# co19 issue #442, undefined name "Expect"
+Language/07_Classes/6_Constructors/1_Generative_Constructors_A17_t04: fail, OK
+Language/07_Classes/6_Constructors/2_Factories_A06_t03: fail, OK
+Language/09_Generics/09_Generics_A05_t02: fail, OK
+Language/09_Generics/09_Generics_A05_t01: fail, OK
+Language/11_Expressions/04_Booleans/1_Boolean_Conversion_A01_t01: fail, OK
+Language/11_Expressions/04_Booleans/1_Boolean_Conversion_A02_t01: fail, OK
+Language/11_Expressions/06_Lists_A09_t01: fail, OK
+Language/11_Expressions/14_Function_Invocation/2_Binding_Actuals_to_Formals_A02_t01: fail, OK
+Language/11_Expressions/14_Function_Invocation/2_Binding_Actuals_to_Formals_A03_t01: fail, OK
+Language/11_Expressions/18_Assignment_A02_t01: fail, OK
+Language/11_Expressions/18_Assignment_A04_t06: fail, OK
+Language/11_Expressions/18_Assignment_A06_t01: fail, OK
+Language/11_Expressions/19_Conditional_A02_t03: fail, OK
+Language/11_Expressions/19_Conditional_A02_t04: fail, OK
+Language/11_Expressions/19_Conditional_A04_t03: fail, OK
+Language/11_Expressions/27_Unary_Expressions_A02_t03: fail, OK
+Language/12_Statements/03_Variable_Declaration_A01_t01: fail, OK
+Language/12_Statements/03_Variable_Declaration_A01_t02: fail, OK
+Language/12_Statements/05_If_A02_t01: fail, OK
+Language/12_Statements/05_If_A02_t02: fail, OK
+Language/12_Statements/10_Try_A01_t01: fail, OK
+Language/12_Statements/11_Return_A03_t02: fail, OK
+Language/12_Statements/11_Return_A04_t01: fail, OK
+Language/12_Statements/15_Assert_A03_t03: fail, OK
+Language/12_Statements/15_Assert_A03_t09: fail, OK
+Language/12_Statements/15_Assert_A03_t08: fail, OK
+Language/12_Statements/15_Assert_A04_t02: fail, OK
+Language/14_Types/2_Dynamic_Type_System_A01_t01: fail, OK
+Language/14_Types/4_Interface_Types_A08_t03: fail, OK
+Language/14_Types/7_Type_Void_A04_t02: fail, OK
+Language/15_Reference/1_Lexical_Rules/2_Comments_A04_t03: fail, OK
+LibTest/core/AssertionError/toString_A01_t01: fail, OK
+LibTest/core/Date/add_A01_t01: fail, OK
+LibTest/core/Date/add_A03_t01: fail, OK
+LibTest/core/Date/add_A02_t01: fail, OK
+LibTest/core/Date/add_A05_t01: fail, OK
+LibTest/core/Date/compareTo_A01_t01: fail, OK
+LibTest/core/Date/compareTo_A02_t01: fail, OK
+LibTest/core/Date/compareTo_A03_t01: fail, OK
+LibTest/core/Date/compareTo_A01_t02: fail, OK
+LibTest/core/Date/Date.fromMillisecondsSinceEpoch_A01_t01: fail, OK
+LibTest/core/Date/Date.fromMillisecondsSinceEpoch_A01_t02: fail, OK
+LibTest/core/Date/Date.fromMillisecondsSinceEpoch_A02_t01: fail, OK
+LibTest/core/Date/Date.fromString_A01_t01: fail, OK
+LibTest/core/Date/Date.fromString_A01_t02: fail, OK
+LibTest/core/Date/Date.fromString_A02_t01: fail, OK
+LibTest/core/Date/Date.fromString_A03_t01: fail, OK
+LibTest/core/Date/Date.now_A01_t01: fail, OK
+LibTest/core/Date/Date.now_A01_t02: fail, OK
+LibTest/core/Date/Date.now_A01_t03: fail, OK
+LibTest/core/Date/Date.utc_A01_t01: fail, OK
+LibTest/core/Date/Date_A01_t01: fail, OK
+LibTest/core/Date/Date_A01_t03: fail, OK
+LibTest/core/Date/Date_A01_t02: fail, OK
+LibTest/core/Date/Date_A01_t04: fail, OK
+LibTest/core/Date/day_A01_t01: fail, OK
+LibTest/core/Date/difference_A01_t01: fail, OK
+LibTest/core/Date/difference_A01_t02: fail, OK
+LibTest/core/Date/difference_A02_t01: fail, OK
+LibTest/core/Date/hour_A01_t01: fail, OK
+LibTest/core/Date/isUtc_A01_t01: fail, OK
+LibTest/core/Date/millisecond_A01_t01: fail, OK
+LibTest/core/Date/millisecondsSinceEpoch_A01_t01: fail, OK
+LibTest/core/Date/minute_A01_t01: fail, OK
+LibTest/core/Date/month_A01_t01: fail, OK
+LibTest/core/Date/operator_equality_A01_t01: fail, OK
+LibTest/core/Date/operator_GE_A01_t01: fail, OK
+LibTest/core/Date/operator_GT_A01_t01: fail, OK
+LibTest/core/Date/operator_LE_A01_t01: fail, OK
+LibTest/core/Date/operator_LT_A01_t01: fail, OK
+LibTest/core/Date/second_A01_t01: fail, OK
+LibTest/core/Date/subtract_A01_t01: fail, OK
+LibTest/core/Date/subtract_A03_t01: fail, OK
+LibTest/core/Date/subtract_A02_t01: fail, OK
+LibTest/core/Date/subtract_A05_t01: fail, OK
+LibTest/core/Date/timeZoneName_A01_t01: fail, OK
+LibTest/core/Date/timeZoneOffset_A01_t01: fail, OK
+LibTest/core/Date/toLocal_A01_t01: fail, OK
+LibTest/core/Date/toString_A01_t01: fail, OK
+LibTest/core/Date/toString_A02_t01: fail, OK
+LibTest/core/Date/toUtc_A01_t01: fail, OK
+LibTest/core/Date/year_A01_t01: fail, OK
+LibTest/core/Date/weekday_A01_t01: fail, OK
+LibTest/core/List/getRange_A06_t01: fail, OK
+LibTest/core/List/indexOf_A06_t01: fail, OK
+LibTest/core/List/operator_subscript_A03_t01: fail, OK
+LibTest/core/List/operator_subscripted_assignment_A03_t01: fail, OK
+LibTest/core/Map/putIfAbsent_A01_t04: fail, OK
+LibTest/core/Strings/concatAll_A04_t01: fail, OK
+LibTest/core/Strings/join_A04_t01: fail, OK
+
+# co19 issue #443, Undefined class 'InvocationMirror'
+Language/11_Expressions/14_Function_Invocation/4_Function_Expression_Invocation_A01_t02: fail, OK
+Language/11_Expressions/15_Method_Invocation/1_Ordinary_Invocation_A05_t02: fail, OK
+Language/11_Expressions/15_Method_Invocation/1_Ordinary_Invocation_A05_t03: fail, OK
+Language/11_Expressions/15_Method_Invocation/1_Ordinary_Invocation_A05_t06: fail, OK
+Language/11_Expressions/17_Getter_Invocation_A02_t01: fail, OK
+Language/11_Expressions/17_Getter_Invocation_A02_t02: fail, OK
+
+# co19 issue #444, AsyncError has been removed
+LibTest/async/Completer/complete_A02_t02: fail, OK
+LibTest/async/Completer/completeError_A01_t01: fail, OK
+LibTest/async/Completer/completeError_A03_t02: fail, OK
+LibTest/async/Future/catchError_A01_t01: fail, OK
+LibTest/async/Future/catchError_A01_t02: fail, OK
+LibTest/async/Future/catchError_A02_t01: fail, OK
+LibTest/async/Future/catchError_A03_t01: fail, OK
+LibTest/async/Future/catchError_A03_t02: fail, OK
+LibTest/async/Future/catchError_A03_t03: fail, OK
+LibTest/async/Future/forEach_A03_t01: fail, OK
+LibTest/async/Future/Future.delayed_A02_t01: fail, OK
+LibTest/async/Future/then_A02_t01: fail, OK
+LibTest/async/Future/then_A02_t02: fail, OK
+LibTest/async/Future/then_A03_t01: fail, OK
+LibTest/async/Future/then_A04_t01: fail, OK
+LibTest/async/Future/whenComplete_A03_t01: fail, OK
+LibTest/async/Future/whenComplete_A04_t02: fail, OK
+
+# co19 issue #445, Future.immediate was repalce with Future.value
+LibTest/async/Future/asStream_A01_t01: fail, OK
+LibTest/async/Future/asStream_A01_t02: fail, OK
+LibTest/async/Future/asStream_A02_t01: fail, OK
+LibTest/async/Future/Future.immediate_A01_t01: fail, OK
+LibTest/async/Future/Future.immediateError_A01_t01: fail, OK
+LibTest/async/Future/then_A01_t03: fail, OK
+
+# co19 issue #446, Date was replaced with DateTime
+Language/14_Types/6_Type_dynamic_A03_t01: fail, OK
+
+# co19 issue 447, In Future delayed int replaced with Duration
+LibTest/async/Future/asStream_A01_t02: fail, OK
+LibTest/async/Future/asStream_A02_t01: fail, OK
+LibTest/async/Future/forEach_A01_t01: fail, OK
+LibTest/async/Future/forEach_A02_t01: fail, OK
+LibTest/async/Future/then_A01_t03: fail, OK
+LibTest/async/Future/wait_A01_t01: fail, OK
+LibTest/async/Future/wait_A01_t04: fail, OK
+LibTest/async/Future/wait_A01_t05: fail, OK
+LibTest/async/Future/wait_A01_t06: fail, OK
+LibTest/async/Future/whenComplete_A01_t01: fail, OK
+LibTest/async/Future/whenComplete_A02_t01: fail, OK
+LibTest/async/Future/whenComplete_A04_t01: fail, OK
+
+# co19 issue #448, Collection was removed
+LibTest/collection/Queue/Queue.from_A01_t01: fail, OK
+LibTest/collection/Queue/Queue.from_A01_t02: fail, OK
+LibTest/core/List/List.from_A01_t01: fail, OK
+LibTest/core/Match/pattern_A01_t01: fail, OK
+LibTest/core/Match/str_A01_t01: fail, OK
+LibTest/core/RegExp/allMatches_A01_t01: fail, OK
+LibTest/core/Set/intersection_A01_t02: fail, OK
+
+# co19 issue #449, Strings was removed
+LibTest/core/Strings/concatAll_A01_t01: fail, OK
+LibTest/core/Strings/concatAll_A02_t01: fail, OK
+LibTest/core/Strings/concatAll_A03_t01: fail, OK
+LibTest/core/Strings/join_A01_t01: fail, OK
+LibTest/core/Strings/join_A02_t01: fail, OK
+LibTest/core/Strings/join_A03_t01: fail, OK
+
+# co19 issue #450, The class 'List' does not have a constructor 'fixedLength'
+LibTest/core/List/add_A02_t01: fail, OK
+LibTest/core/List/addAll_A02_t01: fail, OK
+LibTest/core/List/clear_A02_t01: fail, OK
+LibTest/core/List/length_A04_t01: fail, OK
+LibTest/core/List/removeLast_A02_t01: fail, OK
+LibTest/core/List/removeRange_A02_t01: fail, OK
+
+# co19 issue 451, Set.intersection() requires Set argument
+LibTest/core/Set/intersection_A01_t01: fail, OK
+LibTest/core/Set/intersection_A01_t03: fail, OK
+LibTest/core/Set/intersection_A03_t01: fail, OK
+
+# co19 issue 452, more method in Iterable
+LibTest/core/Set/Set.from_A01_t02: fail, OK
+
+# co19 issue #453, abstract member in concrete class
+Language/07_Classes/07_Classes_A07_t10: fail, OK
+
+# co19 issue #454, should be static warning
+Language/11_Expressions/11_Instance_Creation/1_New_A01_t04: fail, OK
+
+# co19 issue #455, undeclared identifier is static warning
+Language/11_Expressions/14_Function_Invocation/3_Unqualified_Invocation_A01_t10: fail, OK
+Language/12_Statements/04_Local_Function_Declaration_A02_t02: fail, OK
+Language/13_Libraries_and_Scripts/1_Imports_A02_t12: fail, OK
+Language/13_Libraries_and_Scripts/1_Imports_A02_t14: fail, OK
+Language/13_Libraries_and_Scripts/1_Imports_A02_t15: fail, OK
+
+# co19 issue #456
+Language/11_Expressions/15_Method_Invocation/3_Static_Invocation_A03_t04: fail, OK
+Language/11_Expressions/15_Method_Invocation/3_Static_Invocation_A03_t05: fail, OK
+Language/11_Expressions/15_Method_Invocation/3_Static_Invocation_A04_t08: fail, OK
+
+# co19 issue 457, malformed type is static warning
+Language/11_Expressions/31_Type_Test_A05_t01: fail, OK
+Language/11_Expressions/31_Type_Test_A05_t02: fail, OK
+Language/11_Expressions/31_Type_Test_A05_t03: fail, OK
+Language/11_Expressions/32_Type_Cast_A04_t01: fail, OK
+Language/11_Expressions/32_Type_Cast_A04_t02: fail, OK
+
 # co19 issue #465, any use of a malbounded type gives rise to a static warning.
 Language/11_Expressions/11_Instance_Creation/1_New_A05_t01: fail, OK
 Language/11_Expressions/11_Instance_Creation/1_New_A05_t02: fail, OK
@@ -226,4 +435,3 @@
 Language/11_Expressions/11_Instance_Creation_A03_t01: fail, OK
 Language/11_Expressions/11_Instance_Creation_A04_t01: fail, OK
 Language/11_Expressions/11_Instance_Creation_A04_t02: fail, OK
-
diff --git a/tests/co19/co19-dart2dart.status b/tests/co19/co19-dart2dart.status
index 5692eb8..16e1222 100644
--- a/tests/co19/co19-dart2dart.status
+++ b/tests/co19/co19-dart2dart.status
@@ -4,6 +4,9 @@
 
 [ $compiler == dart2dart ]
 
+LibTest/math/max_A01_t03: Fail # co19 issue 467
+LibTest/math/min_A01_t03: Fail # co19 issue 467
+
 # The following tests fail because they contain number literals with a + prefix (co19 issue 428)
 LibTest/core/double/floor_A01_t05: Fail # issue 428
 LibTest/core/double/ceil_A01_t05: Fail # issue 428
diff --git a/tests/co19/co19-dart2js.status b/tests/co19/co19-dart2js.status
index dd3854d..33ec9d5 100644
--- a/tests/co19/co19-dart2js.status
+++ b/tests/co19/co19-dart2js.status
@@ -12,6 +12,9 @@
 # Crashes first, please. Then untriaged bugs. There is a section below
 # for co19 bugs.
 [ $compiler == dart2js ]
+LibTest/math/max_A01_t03: Fail # co19 issue 467
+LibTest/math/min_A01_t03: Fail # co19 issue 467
+
 Language/03_Overview/1_Scoping_A02_t05: Fail # TODO(ahe): Please triage this failure.
 Language/03_Overview/1_Scoping_A02_t06: Fail # TODO(ahe): Please triage this failure.
 Language/05_Variables/05_Variables_A05_t04: Fail # TODO(ahe): Please triage this failure.
@@ -72,6 +75,7 @@
 Language/12_Statements/04_Local_Function_Declaration_A02_t02: Fail # TODO(ahe): Please triage this failure.
 Language/12_Statements/09_Switch_A02_t02: Fail # TODO(ahe): Please triage this failure.
 Language/12_Statements/09_Switch_A06_t02: Fail # co19 issue 413
+Language/12_Statements/10_Try_A06_t01: Fail # Issue 11850: dart2js inlining results in stack traces not as accurate
 Language/12_Statements/10_Try_A07_t03: Fail # TODO(ahe): Please triage this failure.
 Language/12_Statements/11_Return_A05_t01: Fail # TODO(ahe): Please triage this failure.
 Language/12_Statements/11_Return_A05_t02: Fail # TODO(ahe): Please triage this failure.
@@ -132,6 +136,7 @@
 LibTest/math/pow_A01_t01: Fail # TODO(ahe): Please triage this failure.
 LibTest/math/pow_A11_t01: Fail # TODO(ahe): Please triage this failure.
 LibTest/math/pow_A13_t01: Fail # TODO(ahe): Please triage this failure.
+LibTest/core/List/sort_A01_t04: Pass, Slow # http://dartbug.com/11846
 
 
 [ $compiler == dart2js && $runtime == jsshell ]
diff --git a/tests/co19/co19-runtime.status b/tests/co19/co19-runtime.status
index 75e703b..13f3b11 100644
--- a/tests/co19/co19-runtime.status
+++ b/tests/co19/co19-runtime.status
@@ -9,6 +9,9 @@
 Language/11_Expressions/33_Argument_Definition_Test_A03_t01: Fail, OK # co19 issue 436
 Language/11_Expressions/33_Argument_Definition_Test_A03_t02: Fail, OK # co19 issue 436
 
+LibTest/math/max_A01_t03: Fail # co19 issue 467
+LibTest/math/min_A01_t03: Fail # co19 issue 467
+
 [ $runtime == vm && $system == windows ]
 LibTest/core/Stopwatch/elapsed_A01_t01: Pass, Fail # Issue 11382.
 
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 fa543ff..9c7e0cd 100644
--- a/tests/compiler/dart2js/call_site_simple_type_inferer_test.dart
+++ b/tests/compiler/dart2js/call_site_simple_type_inferer_test.dart
@@ -20,7 +20,7 @@
   compiler.runCompiler(uri);
   var cls = findElement(compiler, className);
   var member = cls.lookupLocalMember(buildSourceString(memberName));
-  return check(compiler.typesTask.typesInferrer, member);
+  return check(compiler, member);
 }
 
 const String TEST_1 = r"""
@@ -216,13 +216,14 @@
     'A',
     'x',
     enableInlining,
-    (inferrer, element) {
-      var expectedTypes = f(inferrer);
-      var signature = element.computeSignature(inferrer.compiler);
+    (compiler, element) {
+      var expectedTypes = f(compiler);
+      var signature = element.computeSignature(compiler);
       int index = 0;
+      var inferrer = compiler.typesTask.typesInferrer;
       signature.forEachParameter((Element element) {
         Expect.equals(expectedTypes[index++],
-            inferrer.getTypeOfElement(element).simplify(inferrer.compiler));
+            inferrer.getTypeOfElement(element).simplify(compiler));
       });
       Expect.equals(index, expectedTypes.length);
   });
@@ -233,47 +234,52 @@
   doTest(test, true, f);
 }
 
-subclassOfInterceptor(inferrer) {
-  return findTypeMask(inferrer.compiler, 'Interceptor', 'nonNullSubclass');
+subclassOfInterceptor(compiler) {
+  return findTypeMask(compiler, 'Interceptor', 'nonNullSubclass');
 }
 
 void test() {
-  runTest(TEST_1, (inferrer) => [inferrer.stringType]);
-  runTest(TEST_2, (inferrer) => [inferrer.intType]);
-  runTest(TEST_3, (inferrer) => [inferrer.numType]);
-  runTest(TEST_4, (inferrer) => [inferrer.numType]);
-  runTest(TEST_5, (inferrer) => [inferrer.numType]);
-  runTest(TEST_6, (inferrer) => [inferrer.numType]);
-  runTest(TEST_7a, (inferrer) => [subclassOfInterceptor(inferrer)]);
-  runTest(TEST_7b, (inferrer) => [inferrer.dynamicType.nonNullable()]);
+  runTest(TEST_1, (compiler) => [compiler.typesTask.stringType]);
+  runTest(TEST_2, (compiler) => [compiler.typesTask.intType]);
+  runTest(TEST_3, (compiler) => [compiler.typesTask.numType]);
+  runTest(TEST_4, (compiler) => [compiler.typesTask.numType]);
+  runTest(TEST_5, (compiler) => [compiler.typesTask.numType]);
+  runTest(TEST_6, (compiler) => [compiler.typesTask.numType]);
+  runTest(TEST_7a, (compiler) => [subclassOfInterceptor(compiler)]);
+  runTest(TEST_7b,
+      (compiler) => [compiler.typesTask.dynamicType.nonNullable()]);
 
-  runTest(TEST_8, (inferrer) => [inferrer.intType,
-                                 subclassOfInterceptor(inferrer),
-                                 inferrer.dynamicType.nonNullable()]);
-  runTest(TEST_9, (inferrer) => [inferrer.intType, inferrer.intType]);
-  // runTest(TEST_10, (inferrer) => [subclassOfInterceptor(inferrer),
-  //                                 subclassOfInterceptor(inferrer)]);
-  runTest(TEST_11, (inferrer) => [subclassOfInterceptor(inferrer),
-                                  subclassOfInterceptor(inferrer)]);
+  runTest(TEST_8, (compiler) => [compiler.typesTask.intType,
+                                 subclassOfInterceptor(compiler),
+                                 compiler.typesTask.dynamicType.nonNullable()]);
+  runTest(TEST_9, (compiler) => [compiler.typesTask.intType,
+                                 compiler.typesTask.intType]);
+  runTest(TEST_10, (compiler) => [subclassOfInterceptor(compiler),
+                                  subclassOfInterceptor(compiler)]);
+  runTest(TEST_11, (compiler) => [subclassOfInterceptor(compiler),
+                                  subclassOfInterceptor(compiler)]);
 
-  runTest(TEST_12, (inferrer) => [inferrer.stringType, inferrer.intType]);
+  runTest(TEST_12, (compiler) => [compiler.typesTask.stringType,
+                                  compiler.typesTask.intType]);
 
-  runTest(TEST_13, (inferrer) => [inferrer.numType]);
+  runTest(TEST_13, (compiler) => [compiler.typesTask.numType]);
 
-  runTest(TEST_14, (inferrer) => [inferrer.intType, inferrer.stringType]);
+  runTest(TEST_14, (compiler) => [compiler.typesTask.intType,
+                                  compiler.typesTask.stringType]);
 
-  runTest(TEST_15, (inferrer) => [inferrer.stringType, inferrer.boolType]);
+  runTest(TEST_15, (compiler) => [compiler.typesTask.stringType,
+                                  compiler.typesTask.boolType]);
 
-  runTest(TEST_16, (inferrer) => [inferrer.intType,
-                                  inferrer.intType,
-                                  inferrer.stringType]);
+  runTest(TEST_16, (compiler) => [compiler.typesTask.intType,
+                                  compiler.typesTask.intType,
+                                  compiler.typesTask.stringType]);
 
-  runTest(TEST_17, (inferrer) => [inferrer.intType,
-                                  inferrer.boolType,
-                                  inferrer.doubleType]);
+  runTest(TEST_17, (compiler) => [compiler.typesTask.intType,
+                                  compiler.typesTask.boolType,
+                                  compiler.typesTask.doubleType]);
 
-  runTest(TEST_18, (inferrer) => [subclassOfInterceptor(inferrer),
-                                  subclassOfInterceptor(inferrer)]);
+  runTest(TEST_18, (compiler) => [subclassOfInterceptor(compiler),
+                                  subclassOfInterceptor(compiler)]);
 }
 
 void main() {
diff --git a/tests/compiler/dart2js/class_codegen_test.dart b/tests/compiler/dart2js/class_codegen_test.dart
index 24d8c63..b4e72c1 100644
--- a/tests/compiler/dart2js/class_codegen_test.dart
+++ b/tests/compiler/dart2js/class_codegen_test.dart
@@ -81,7 +81,7 @@
 
 fieldTest() {
   String generated = compileAll(TEST_FOUR);
-  Expect.isTrue(generated.contains(r"""B: {"": "A;y,z,x"}"""));
+  Expect.isTrue(generated.contains(r"""B: {"": "A;y,z,x", static:"""));
 }
 
 constructor1() {
diff --git a/tests/compiler/dart2js/concrete_type_inference_test.dart b/tests/compiler/dart2js/concrete_type_inference_test.dart
index 71d8488..fe95c49 100644
--- a/tests/compiler/dart2js/concrete_type_inference_test.dart
+++ b/tests/compiler/dart2js/concrete_type_inference_test.dart
@@ -34,7 +34,8 @@
           printElement.computeSignature(compiler).requiredParameters.head;
         var type = compiler.typesTask.getGuaranteedTypeOfElement(parameter);
         var inferrer = compiler.typesTask.typesInferrer;
-        Expect.identical(inferrer.dynamicType, type.simplify(compiler));
+        Expect.identical(compiler.typesTask.dynamicType,
+                         type.simplify(compiler));
       });
 
   compileAndFind(
@@ -51,28 +52,28 @@
 void testBasicTypes() {
   checkPrintType('true', (compiler, type) {
     var inferrer = compiler.typesTask.typesInferrer;
-    Expect.identical(inferrer.boolType, type);
+    Expect.identical(compiler.typesTask.boolType, type);
   });
   checkPrintType('1.0', (compiler, type) {
     var inferrer = compiler.typesTask.typesInferrer;
-    Expect.identical(inferrer.doubleType, type);
+    Expect.identical(compiler.typesTask.doubleType, type);
   });
   checkPrintType('1', (compiler, type) {
     var inferrer = compiler.typesTask.typesInferrer;
-    Expect.identical(inferrer.intType, type);
+    Expect.identical(compiler.typesTask.intType, type);
   });
   checkPrintType('[]', (compiler, type) {
     var inferrer = compiler.typesTask.typesInferrer;
     if (type.isForwarding) type = type.forwardTo;
-    Expect.identical(inferrer.growableListType, type);
+    Expect.identical(compiler.typesTask.growableListType, type);
   });
   checkPrintType('null', (compiler, type) {
     var inferrer = compiler.typesTask.typesInferrer;
-    Expect.identical(inferrer.nullType, type);
+    Expect.identical(compiler.typesTask.nullType, type);
   });
   checkPrintType('"foo"', (compiler, type) {
     var inferrer = compiler.typesTask.typesInferrer;
-    Expect.identical(inferrer.stringType, type);
+    Expect.identical(compiler.typesTask.stringType, type);
   });
 }
 
@@ -90,13 +91,13 @@
         var typesTask = compiler.typesTask;
         var inferrer = typesTask.typesInferrer;
         Expect.identical(
-            inferrer.intType,
+            typesTask.intType,
             typesTask.getGuaranteedTypeOfElement(firstParameter));
         Expect.identical(
-            inferrer.nullType,
+            typesTask.nullType,
             typesTask.getGuaranteedTypeOfElement(secondParameter));
         Expect.identical(
-            inferrer.nullType,
+            typesTask.nullType,
             typesTask.getGuaranteedTypeOfElement(thirdParameter));
       });
 }
diff --git a/tests/compiler/dart2js/cpa_inference_test.dart b/tests/compiler/dart2js/cpa_inference_test.dart
index 8e81e93..1171906 100644
--- a/tests/compiler/dart2js/cpa_inference_test.dart
+++ b/tests/compiler/dart2js/cpa_inference_test.dart
@@ -1108,36 +1108,6 @@
   result.checkNodeHasType('x', []);
 }
 
-// Assuming the mock compiler's interceptor library faithfully reflects the
-// real interceptor library, this test boils down to checking that
-// JSExtendableArray and JSFixedArray don't override JSArray's square bracket
-// operators.
-testListHierarchy() {
-  final String source1 = r"""
-    import 'dart:interceptors';
-
-    main() {
-      var l = new JSExtendableArray();
-      l[0] = 'foo';
-      var x = l[0];
-      x;
-    }""";
-  AnalysisResult result1 = analyze(source1);
-  result1.checkNodeHasType('x', [result1.string]);
-
-  final String source2 = r"""
-    import 'dart:interceptors';
-
-    main() {
-      var l = new JSFixedArray();
-      l[0] = 'foo';
-      var x = l[0];
-      x;
-    }""";
-  AnalysisResult result2 = analyze(source1);
-  result2.checkNodeHasType('x', [result2.string]);
-}
-
 testSendWithWrongArity() {
   final String source = r"""
     f(x) { }
@@ -1596,7 +1566,6 @@
   testLists();
   testListWithCapacity();
   testEmptyList();
-  testListHierarchy();
   testJsCall();
   testJsCallAugmentsSeenClasses();
   testIsCheck();
diff --git a/tests/compiler/dart2js/field_type_simple_inferer_test.dart b/tests/compiler/dart2js/field_type_simple_inferer_test.dart
index db2d968..9f43fd5 100644
--- a/tests/compiler/dart2js/field_type_simple_inferer_test.dart
+++ b/tests/compiler/dart2js/field_type_simple_inferer_test.dart
@@ -20,7 +20,7 @@
   compiler.disableInlining = disableInlining;
   var cls = findElement(compiler, className);
   var member = cls.lookupMember(buildSourceString(memberName));
-  return check(compiler.typesTask.typesInferrer, member);
+  return check(compiler, member);
 }
 
 const String TEST_1 = r"""
@@ -450,8 +450,9 @@
       'A',
       name,
       disableInlining,
-      (inferrer, field) {
-        TypeMask type = f(inferrer);
+      (compiler, field) {
+        TypeMask type = f(compiler);
+        var inferrer = compiler.typesTask.typesInferrer;
         TypeMask inferredType =
             inferrer.getTypeOfElement(field).simplify(inferrer.compiler);
         Expect.equals(type, inferredType, name);
@@ -465,17 +466,16 @@
 }
 
 void test() {
-  subclassOfInterceptor(inferrer) =>
-      findTypeMask(inferrer.compiler, 'Interceptor', 'nonNullSubclass');
-  dynamicType(inferrer) => inferrer.dynamicType;
+  subclassOfInterceptor(compiler) =>
+      findTypeMask(compiler, 'Interceptor', 'nonNullSubclass');
 
-  runTest(TEST_1, {'f': (inferrer) => inferrer.nullType});
-  runTest(TEST_2, {'f1': (inferrer) => inferrer.nullType,
-                   'f2': (inferrer) => inferrer.intType});
-  runTest(TEST_3, {'f1': (inferrer) => inferrer.intType,
-                   'f2': (inferrer) => inferrer.intType.nullable()});
+  runTest(TEST_1, {'f': (compiler) => compiler.typesTask.nullType});
+  runTest(TEST_2, {'f1': (compiler) => compiler.typesTask.nullType,
+                   'f2': (compiler) => compiler.typesTask.intType});
+  runTest(TEST_3, {'f1': (compiler) => compiler.typesTask.intType,
+                   'f2': (compiler) => compiler.typesTask.intType.nullable()});
   runTest(TEST_4, {'f1': subclassOfInterceptor,
-                   'f2': (inferrer) => inferrer.stringType.nullable()});
+                   'f2': (compiler) => compiler.typesTask.stringType.nullable()});
 
   // TODO(ngeoffray): We should try to infer that the initialization
   // code at the declaration site of the fields does not matter.
@@ -486,50 +486,50 @@
   runTest(TEST_7, {'f1': subclassOfInterceptor,
                    'f2': subclassOfInterceptor});
 
-  runTest(TEST_8, {'f': (inferrer) => inferrer.stringType.nullable()});
-  runTest(TEST_9, {'f': (inferrer) => inferrer.stringType.nullable()});
-  runTest(TEST_10, {'f': (inferrer) => inferrer.intType});
-  runTest(TEST_11, {'fs': (inferrer) => inferrer.intType});
+  runTest(TEST_8, {'f': (compiler) => compiler.typesTask.stringType.nullable()});
+  runTest(TEST_9, {'f': (compiler) => compiler.typesTask.stringType.nullable()});
+  runTest(TEST_10, {'f': (compiler) => compiler.typesTask.intType});
+  runTest(TEST_11, {'fs': (compiler) => compiler.typesTask.intType});
 
   // TODO(ngeoffray): We should try to infer that the initialization
   // code at the declaration site of the fields does not matter.
   runTest(TEST_12, {'fs': subclassOfInterceptor});
 
-  runTest(TEST_13, {'fs': (inferrer) => inferrer.intType});
-  runTest(TEST_14, {'f': (inferrer) => inferrer.intType});
-  runTest(TEST_15, {'f': (inferrer) {
+  runTest(TEST_13, {'fs': (compiler) => compiler.typesTask.intType});
+  runTest(TEST_14, {'f': (compiler) => compiler.typesTask.intType});
+  runTest(TEST_15, {'f': (compiler) {
                             ClassElement cls =
-                                inferrer.compiler.backend.jsIndexableClass;
+                                compiler.typesTask.compiler.backend.jsIndexableClass;
                             return new TypeMask.nonNullSubtype(cls.rawType);
                          }});
   runTest(TEST_16, {'f': subclassOfInterceptor});
-  runTest(TEST_17, {'f': (inferrer) => inferrer.intType.nullable()});
-  runTest(TEST_18, {'f1': (inferrer) => inferrer.intType,
-                    'f2': (inferrer) => inferrer.stringType,
-                    'f3': (inferrer) => inferrer.dynamicType});
-  runTest(TEST_19, {'f1': (inferrer) => inferrer.intType,
-                    'f2': (inferrer) => inferrer.stringType,
-                    'f3': (inferrer) => inferrer.dynamicType});
-  runTest(TEST_20, {'f': (inferrer) => inferrer.intType.nullable()});
-  runTest(TEST_21, {'f': (inferrer) => inferrer.intType.nullable()});
+  runTest(TEST_17, {'f': (compiler) => compiler.typesTask.intType.nullable()});
+  runTest(TEST_18, {'f1': (compiler) => compiler.typesTask.intType,
+                    'f2': (compiler) => compiler.typesTask.stringType,
+                    'f3': (compiler) => compiler.typesTask.dynamicType});
+  runTest(TEST_19, {'f1': (compiler) => compiler.typesTask.intType,
+                    'f2': (compiler) => compiler.typesTask.stringType,
+                    'f3': (compiler) => compiler.typesTask.dynamicType});
+  runTest(TEST_20, {'f': (compiler) => compiler.typesTask.intType.nullable()});
+  runTest(TEST_21, {'f': (compiler) => compiler.typesTask.intType.nullable()});
 
-  runTest(TEST_22, {'f1': (inferrer) => inferrer.intType,
-                    'f2': (inferrer) => inferrer.intType,
-                    'f3': (inferrer) => inferrer.stringType.nullable()});
+  runTest(TEST_22, {'f1': (compiler) => compiler.typesTask.intType,
+                    'f2': (compiler) => compiler.typesTask.intType,
+                    'f3': (compiler) => compiler.typesTask.stringType.nullable()});
 
-  runTest(TEST_23, {'f1': (inferrer) => inferrer.intType.nullable(),
-                    'f2': (inferrer) => inferrer.intType.nullable(),
-                    'f3': (inferrer) => inferrer.intType.nullable(),
-                    'f4': (inferrer) => inferrer.intType.nullable()});
+  runTest(TEST_23, {'f1': (compiler) => compiler.typesTask.intType.nullable(),
+                    'f2': (compiler) => compiler.typesTask.intType.nullable(),
+                    'f3': (compiler) => compiler.typesTask.intType.nullable(),
+                    'f4': (compiler) => compiler.typesTask.intType.nullable()});
 
-  runTest(TEST_24, {'f1': (inferrer) => inferrer.intType,
-                    'f2': (inferrer) => inferrer.intType,
-                    'f3': (inferrer) => inferrer.intType,
-                    'f4': (inferrer) => inferrer.intType,
-                    'f5': (inferrer) => inferrer.numType.nullable(),
-                    'f6': (inferrer) => inferrer.stringType.nullable()});
+  runTest(TEST_24, {'f1': (compiler) => compiler.typesTask.intType,
+                    'f2': (compiler) => compiler.typesTask.intType,
+                    'f3': (compiler) => compiler.typesTask.intType,
+                    'f4': (compiler) => compiler.typesTask.intType,
+                    'f5': (compiler) => compiler.typesTask.numType.nullable(),
+                    'f6': (compiler) => compiler.typesTask.stringType.nullable()});
 
-  runTest(TEST_25, {'f1': (inferrer) => inferrer.intType });
+  runTest(TEST_25, {'f1': (compiler) => compiler.typesTask.intType });
 }
 
 void main() {
diff --git a/tests/compiler/dart2js/list_tracer_test.dart b/tests/compiler/dart2js/list_tracer_test.dart
index d782239..691c95b 100644
--- a/tests/compiler/dart2js/list_tracer_test.dart
+++ b/tests/compiler/dart2js/list_tracer_test.dart
@@ -190,7 +190,8 @@
   Uri uri = new Uri(scheme: 'source');
   var compiler = compilerFor(generateTest(allocation), uri);
   compiler.runCompiler(uri);
-  var typesInferrer = compiler.typesTask.typesInferrer;
+  var typesTask = compiler.typesTask;
+  var typesInferrer = typesTask.typesInferrer;
 
   checkType(String name, type) {
     var element = findElement(compiler, name);
@@ -199,29 +200,29 @@
     Expect.equals(type, mask.elementType.simplify(compiler), name);
   }
 
-  checkType('listInField', typesInferrer.numType);
-  checkType('listPassedToMethod', typesInferrer.numType);
-  checkType('listReturnedFromMethod', typesInferrer.numType);
-  checkType('listUsedWithCascade', typesInferrer.numType);
-  checkType('listUsedInClosure', typesInferrer.numType);
-  checkType('listPassedToSelector', typesInferrer.numType);
-  checkType('listReturnedFromSelector', typesInferrer.numType);
-  checkType('listUsedWithAddAndInsert', typesInferrer.numType);
-  checkType('listUsedWithConstraint', typesInferrer.numType);
-  checkType('listEscapingFromSetter', typesInferrer.numType);
-  checkType('listUsedInLocal', typesInferrer.numType);
-  checkType('listEscapingInSetterValue', typesInferrer.numType);
-  checkType('listEscapingInIndex', typesInferrer.numType);
-  checkType('listEscapingInIndexSet', typesInferrer.intType);
-  checkType('listEscapingTwiceInIndexSet', typesInferrer.numType);
-  checkType('listSetInNonFinalField', typesInferrer.numType);
-  checkType('listWithChangedLength', typesInferrer.intType.nullable());
+  checkType('listInField', typesTask.numType);
+  checkType('listPassedToMethod', typesTask.numType);
+  checkType('listReturnedFromMethod', typesTask.numType);
+  checkType('listUsedWithCascade', typesTask.numType);
+  checkType('listUsedInClosure', typesTask.numType);
+  checkType('listPassedToSelector', typesTask.numType);
+  checkType('listReturnedFromSelector', typesTask.numType);
+  checkType('listUsedWithAddAndInsert', typesTask.numType);
+  checkType('listUsedWithConstraint', typesTask.numType);
+  checkType('listEscapingFromSetter', typesTask.numType);
+  checkType('listUsedInLocal', typesTask.numType);
+  checkType('listEscapingInSetterValue', typesTask.numType);
+  checkType('listEscapingInIndex', typesTask.numType);
+  checkType('listEscapingInIndexSet', typesTask.intType);
+  checkType('listEscapingTwiceInIndexSet', typesTask.numType);
+  checkType('listSetInNonFinalField', typesTask.numType);
+  checkType('listWithChangedLength', typesTask.intType.nullable());
 
-  checkType('listPassedToClosure', typesInferrer.dynamicType);
-  checkType('listReturnedFromClosure', typesInferrer.dynamicType);
-  checkType('listUsedWithNonOkSelector', typesInferrer.dynamicType);
-  checkType('listPassedAsOptionalParameter', typesInferrer.dynamicType);
-  checkType('listPassedAsNamedParameter', typesInferrer.dynamicType);
+  checkType('listPassedToClosure', typesTask.dynamicType);
+  checkType('listReturnedFromClosure', typesTask.dynamicType);
+  checkType('listUsedWithNonOkSelector', typesTask.dynamicType);
+  checkType('listPassedAsOptionalParameter', typesTask.dynamicType);
+  checkType('listPassedAsNamedParameter', typesTask.dynamicType);
 
   if (!allocation.contains('filled')) {
     checkType('listUnset', new TypeMask.nonNullEmpty());
diff --git a/tests/compiler/dart2js/no_constructor_body_test.dart b/tests/compiler/dart2js/no_constructor_body_test.dart
index 666afeb..0a11b01 100644
--- a/tests/compiler/dart2js/no_constructor_body_test.dart
+++ b/tests/compiler/dart2js/no_constructor_body_test.dart
@@ -19,5 +19,5 @@
 main() {
   String generated = compileAll(TEST);
   Expect.isTrue(
-      generated.contains('A: {"": "Object;"}'));
+      generated.contains('A: {"": "Object;", static:'));
 }
diff --git a/tests/compiler/dart2js/simple_inferrer_and_or_test.dart b/tests/compiler/dart2js/simple_inferrer_and_or_test.dart
index 267f5fe..22ec51a 100644
--- a/tests/compiler/dart2js/simple_inferrer_and_or_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_and_or_test.dart
@@ -72,7 +72,7 @@
   checkReturn('returnDyn1', subclassOfInterceptor);
   checkReturn('returnDyn2', subclassOfInterceptor);
   checkReturn('returnDyn3', subclassOfInterceptor);
-  checkReturn('returnDyn4', typesInferrer.dynamicType.nonNullable());
-  checkReturn('returnDyn5', typesInferrer.dynamicType.nonNullable());
-  checkReturn('returnDyn6', typesInferrer.dynamicType.nonNullable());
+  checkReturn('returnDyn4', compiler.typesTask.dynamicType.nonNullable());
+  checkReturn('returnDyn5', compiler.typesTask.dynamicType.nonNullable());
+  checkReturn('returnDyn6', compiler.typesTask.dynamicType.nonNullable());
 }
diff --git a/tests/compiler/dart2js/simple_inferrer_closure_test.dart b/tests/compiler/dart2js/simple_inferrer_closure_test.dart
index 0f10a24..822fee3 100644
--- a/tests/compiler/dart2js/simple_inferrer_closure_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_closure_test.dart
@@ -90,15 +90,15 @@
     Expect.equals(type, typesInferrer.getReturnTypeOfElement(element));
   }
 
-  checkReturn('returnInt1', typesInferrer.intType);
+  checkReturn('returnInt1', compiler.typesTask.intType);
   // TODO(ngeoffray): We don't use types of mutated captured
   // variables anymore, because they could lead to optimistic results
   // needing to be re-analyzed.
-  checkReturn('returnInt2', typesInferrer.dynamicType);
-  checkReturn('returnInt3', typesInferrer.intType);
-  checkReturn('returnInt4', typesInferrer.intType);
+  checkReturn('returnInt2', compiler.typesTask.dynamicType);
+  checkReturn('returnInt3', compiler.typesTask.intType);
+  checkReturn('returnInt4', compiler.typesTask.intType);
 
-  checkReturn('returnDyn1', typesInferrer.dynamicType);
-  checkReturn('returnDyn2', typesInferrer.dynamicType);
-  checkReturn('returnDyn3', typesInferrer.dynamicType);
+  checkReturn('returnDyn1', compiler.typesTask.dynamicType);
+  checkReturn('returnDyn2', compiler.typesTask.dynamicType);
+  checkReturn('returnDyn3', compiler.typesTask.dynamicType);
 }
diff --git a/tests/compiler/dart2js/simple_inferrer_final_field2_test.dart b/tests/compiler/dart2js/simple_inferrer_final_field2_test.dart
index 5904dee..75bf803 100644
--- a/tests/compiler/dart2js/simple_inferrer_final_field2_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_final_field2_test.dart
@@ -35,6 +35,6 @@
     Expect.equals(type, typesInferrer.getTypeOfElement(element));
   }
 
-  checkFieldTypeInClass('A', 'intField', typesInferrer.intType);
-  checkFieldTypeInClass('A', 'stringField', typesInferrer.stringType);
+  checkFieldTypeInClass('A', 'intField', compiler.typesTask.intType);
+  checkFieldTypeInClass('A', 'stringField', compiler.typesTask.stringType);
 }
diff --git a/tests/compiler/dart2js/simple_inferrer_final_field_test.dart b/tests/compiler/dart2js/simple_inferrer_final_field_test.dart
index 8cea159..f4d5d04 100644
--- a/tests/compiler/dart2js/simple_inferrer_final_field_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_final_field_test.dart
@@ -38,10 +38,10 @@
         typesInferrer.getTypeOfElement(element).simplify(compiler));
   }
 
-  checkFieldTypeInClass('A', 'intField', typesInferrer.intType);
+  checkFieldTypeInClass('A', 'intField', compiler.typesTask.intType);
   checkFieldTypeInClass('A', 'giveUpField1',
       findTypeMask(compiler, 'Interceptor', 'nonNullSubclass'));
   checkFieldTypeInClass('A', 'giveUpField2',
-      typesInferrer.dynamicType.nonNullable());
-  checkFieldTypeInClass('A', 'fieldParameter', typesInferrer.intType);
+      compiler.typesTask.dynamicType.nonNullable());
+  checkFieldTypeInClass('A', 'fieldParameter', compiler.typesTask.intType);
 }
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 f4589cd..45669dd 100644
--- a/tests/compiler/dart2js/simple_inferrer_no_such_method_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_no_such_method_test.dart
@@ -107,27 +107,27 @@
         name);
   }
 
-  checkReturn('test1', typesInferrer.intType);
-  checkReturn('test2', typesInferrer.dynamicType.nonNullable());
-  checkReturn('test3', typesInferrer.intType);
-  checkReturn('test4', typesInferrer.mapType);
-  checkReturn('test5', typesInferrer.dynamicType.nonNullable());
-  checkReturn('test6', typesInferrer.dynamicType.nonNullable());
+  checkReturn('test1', compiler.typesTask.intType);
+  checkReturn('test2', compiler.typesTask.dynamicType.nonNullable());
+  checkReturn('test3', compiler.typesTask.intType);
+  checkReturn('test4', compiler.typesTask.mapType);
+  checkReturn('test5', compiler.typesTask.dynamicType.nonNullable());
+  checkReturn('test6', compiler.typesTask.dynamicType.nonNullable());
 
   compiler = compilerFor(TEST2, uri);
   compiler.runCompiler(uri);
   typesInferrer = compiler.typesTask.typesInferrer;
 
-  checkReturn('test1', typesInferrer.dynamicType.nonNullable());
-  checkReturn('test2', typesInferrer.mapType);
-  checkReturn('test3', typesInferrer.mapType);
-  checkReturn('test4', typesInferrer.mapType);
-  checkReturn('test5', typesInferrer.mapType);
+  checkReturn('test1', compiler.typesTask.dynamicType.nonNullable());
+  checkReturn('test2', compiler.typesTask.mapType);
+  checkReturn('test3', compiler.typesTask.mapType);
+  checkReturn('test4', compiler.typesTask.mapType);
+  checkReturn('test5', compiler.typesTask.mapType);
 
-  checkReturn('test6', typesInferrer.numType);
-  checkReturn('test7', typesInferrer.intType);
-  checkReturn('test8', typesInferrer.intType);
-  checkReturn('test9', typesInferrer.intType);
-  checkReturn('test10', typesInferrer.numType);
-  checkReturn('test11', typesInferrer.doubleType);
+  checkReturn('test6', compiler.typesTask.numType);
+  checkReturn('test7', compiler.typesTask.intType);
+  checkReturn('test8', compiler.typesTask.intType);
+  checkReturn('test9', compiler.typesTask.intType);
+  checkReturn('test10', compiler.typesTask.numType);
+  checkReturn('test11', compiler.typesTask.doubleType);
 }
diff --git a/tests/compiler/dart2js/simple_inferrer_postfix_prefix_test.dart b/tests/compiler/dart2js/simple_inferrer_postfix_prefix_test.dart
index c5fbce1..e346b11 100644
--- a/tests/compiler/dart2js/simple_inferrer_postfix_prefix_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_postfix_prefix_test.dart
@@ -64,7 +64,8 @@
   Uri uri = new Uri(scheme: 'source');
   var compiler = compilerFor(TEST, uri);
   compiler.runCompiler(uri);
-  var typesInferrer = compiler.typesTask.typesInferrer;
+  var typesTask = compiler.typesTask;
+  var typesInferrer = typesTask.typesInferrer;
 
   checkReturnInClass(String className, String methodName, type) {
     var cls = findElement(compiler, className);
@@ -76,20 +77,20 @@
   var subclassOfInterceptor =
       findTypeMask(compiler, 'Interceptor', 'nonNullSubclass');
 
-  checkReturnInClass('A', 'returnNum1', typesInferrer.numType);
-  checkReturnInClass('A', 'returnNum2', typesInferrer.numType);
-  checkReturnInClass('A', 'returnNum3', typesInferrer.numType);
-  checkReturnInClass('A', 'returnNum4', typesInferrer.numType);
-  checkReturnInClass('A', 'returnNum5', typesInferrer.numType);
-  checkReturnInClass('A', 'returnNum6', typesInferrer.numType);
+  checkReturnInClass('A', 'returnNum1', typesTask.numType);
+  checkReturnInClass('A', 'returnNum2', typesTask.numType);
+  checkReturnInClass('A', 'returnNum3', typesTask.numType);
+  checkReturnInClass('A', 'returnNum4', typesTask.numType);
+  checkReturnInClass('A', 'returnNum5', typesTask.numType);
+  checkReturnInClass('A', 'returnNum6', typesTask.numType);
   checkReturnInClass('A', 'returnDynamic1', subclassOfInterceptor);
   checkReturnInClass('A', 'returnDynamic2', subclassOfInterceptor);
-  checkReturnInClass('A', 'returnDynamic3', typesInferrer.dynamicType);
+  checkReturnInClass('A', 'returnDynamic3', typesTask.dynamicType);
 
-  checkReturnInClass('B', 'returnString1', typesInferrer.stringType);
-  checkReturnInClass('B', 'returnString2', typesInferrer.stringType);
-  checkReturnInClass('B', 'returnDynamic1', typesInferrer.dynamicType);
-  checkReturnInClass('B', 'returnDynamic2', typesInferrer.dynamicType);
-  checkReturnInClass('B', 'returnDynamic3', typesInferrer.dynamicType);
-  checkReturnInClass('B', 'returnDynamic4', typesInferrer.dynamicType);
+  checkReturnInClass('B', 'returnString1', typesTask.stringType);
+  checkReturnInClass('B', 'returnString2', typesTask.stringType);
+  checkReturnInClass('B', 'returnDynamic1', typesTask.dynamicType);
+  checkReturnInClass('B', 'returnDynamic2', typesTask.dynamicType);
+  checkReturnInClass('B', 'returnDynamic3', typesTask.dynamicType);
+  checkReturnInClass('B', 'returnDynamic4', typesTask.dynamicType);
 }
diff --git a/tests/compiler/dart2js/simple_inferrer_test.dart b/tests/compiler/dart2js/simple_inferrer_test.dart
index 186504d..fc6fe0a 100644
--- a/tests/compiler/dart2js/simple_inferrer_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_test.dart
@@ -485,7 +485,8 @@
   Uri uri = new Uri(scheme: 'source');
   var compiler = compilerFor(TEST, uri);
   compiler.runCompiler(uri);
-  var typesInferrer = compiler.typesTask.typesInferrer;
+  var typesTask = compiler.typesTask;
+  var typesInferrer = typesTask.typesInferrer;
 
   checkReturn(String name, type) {
     var element = findElement(compiler, name);
@@ -497,63 +498,63 @@
   var interceptorType =
       findTypeMask(compiler, 'Interceptor', 'nonNullSubclass');
 
-  checkReturn('returnNum1', typesInferrer.numType);
-  checkReturn('returnNum2', typesInferrer.numType);
-  checkReturn('returnInt1', typesInferrer.intType);
-  checkReturn('returnInt2', typesInferrer.intType);
-  checkReturn('returnDouble', typesInferrer.doubleType);
+  checkReturn('returnNum1', typesTask.numType);
+  checkReturn('returnNum2', typesTask.numType);
+  checkReturn('returnInt1', typesTask.intType);
+  checkReturn('returnInt2', typesTask.intType);
+  checkReturn('returnDouble', typesTask.doubleType);
   checkReturn('returnGiveUp', interceptorType);
-  checkReturn('returnInt5', typesInferrer.intType);
-  checkReturn('returnInt6', typesInferrer.intType);
-  checkReturn('returnIntOrNull', typesInferrer.intType.nullable());
-  checkReturn('returnInt3', typesInferrer.intType);
-  checkReturn('returnDynamic', typesInferrer.dynamicType);
-  checkReturn('returnInt4', typesInferrer.intType);
-  checkReturn('returnInt7', typesInferrer.intType);
-  checkReturn('returnInt8', typesInferrer.intType);
-  checkReturn('returnDynamic1', typesInferrer.dynamicType);
-  checkReturn('returnDynamic2', typesInferrer.dynamicType);
+  checkReturn('returnInt5', typesTask.intType);
+  checkReturn('returnInt6', typesTask.intType);
+  checkReturn('returnIntOrNull', typesTask.intType.nullable());
+  checkReturn('returnInt3', typesTask.intType);
+  checkReturn('returnDynamic', typesTask.dynamicType);
+  checkReturn('returnInt4', typesTask.intType);
+  checkReturn('returnInt7', typesTask.intType);
+  checkReturn('returnInt8', typesTask.intType);
+  checkReturn('returnDynamic1', typesTask.dynamicType);
+  checkReturn('returnDynamic2', typesTask.dynamicType);
   TypeMask intType = new TypeMask.nonNullSubtype(compiler.intClass.rawType);
   checkReturn('testIsCheck1', intType);
   checkReturn('testIsCheck2', intType);
   checkReturn('testIsCheck3', intType.nullable());
   checkReturn('testIsCheck4', intType);
   checkReturn('testIsCheck5', intType);
-  checkReturn('testIsCheck6', typesInferrer.dynamicType);
+  checkReturn('testIsCheck6', typesTask.dynamicType);
   checkReturn('testIsCheck7', intType);
-  checkReturn('testIsCheck8', typesInferrer.dynamicType);
+  checkReturn('testIsCheck8', typesTask.dynamicType);
   checkReturn('testIsCheck9', intType);
-  checkReturn('testIsCheck10', typesInferrer.dynamicType);
+  checkReturn('testIsCheck10', typesTask.dynamicType);
   checkReturn('testIsCheck11', intType);
-  checkReturn('testIsCheck12', typesInferrer.dynamicType);
+  checkReturn('testIsCheck12', typesTask.dynamicType);
   checkReturn('testIsCheck13', intType);
-  checkReturn('testIsCheck14', typesInferrer.dynamicType);
+  checkReturn('testIsCheck14', typesTask.dynamicType);
   checkReturn('testIsCheck15', intType);
-  checkReturn('testIsCheck16', typesInferrer.dynamicType);
+  checkReturn('testIsCheck16', typesTask.dynamicType);
   checkReturn('testIsCheck17', intType);
-  checkReturn('testIsCheck18', typesInferrer.dynamicType);
-  checkReturn('testIsCheck19', typesInferrer.dynamicType);
-  checkReturn('testIsCheck20', typesInferrer.dynamicType.nonNullable());
+  checkReturn('testIsCheck18', typesTask.dynamicType);
+  checkReturn('testIsCheck19', typesTask.dynamicType);
+  checkReturn('testIsCheck20', typesTask.dynamicType.nonNullable());
   checkReturn('returnAsString',
       new TypeMask.subtype(compiler.stringClass.computeType(compiler)));
-  checkReturn('returnIntAsNum', typesInferrer.intType);
-  checkReturn('returnAsTypedef', typesInferrer.functionType.nullable());
-  checkReturn('returnTopLevelGetter', typesInferrer.intType);
-  checkReturn('testDeadCode', typesInferrer.intType);
-  checkReturn('testLabeledIf', typesInferrer.intType.nullable());
-  checkReturn('testSwitch1', typesInferrer.intType
-      .union(typesInferrer.doubleType, compiler).nullable().simplify(compiler));
-  checkReturn('testSwitch2', typesInferrer.intType);
+  checkReturn('returnIntAsNum', typesTask.intType);
+  checkReturn('returnAsTypedef', typesTask.functionType.nullable());
+  checkReturn('returnTopLevelGetter', typesTask.intType);
+  checkReturn('testDeadCode', typesTask.intType);
+  checkReturn('testLabeledIf', typesTask.intType.nullable());
+  checkReturn('testSwitch1', typesTask.intType
+      .union(typesTask.doubleType, compiler).nullable().simplify(compiler));
+  checkReturn('testSwitch2', typesTask.intType);
   checkReturn('testSwitch3', interceptorType.nullable());
-  checkReturn('testSwitch4', typesInferrer.intType);
+  checkReturn('testSwitch4', typesTask.intType);
   checkReturn('testContinue1', interceptorType.nullable());
   checkReturn('testBreak1', interceptorType.nullable());
   checkReturn('testContinue2', interceptorType.nullable());
-  checkReturn('testBreak2', typesInferrer.intType.nullable());
-  checkReturn('testReturnElementOfConstList1', typesInferrer.intType);
-  checkReturn('testReturnElementOfConstList2', typesInferrer.intType);
-  checkReturn('testReturnItselfOrInt', typesInferrer.intType);
-  checkReturn('testReturnInvokeDynamicGetter', typesInferrer.dynamicType);
+  checkReturn('testBreak2', typesTask.intType.nullable());
+  checkReturn('testReturnElementOfConstList1', typesTask.intType);
+  checkReturn('testReturnElementOfConstList2', typesTask.intType);
+  checkReturn('testReturnItselfOrInt', typesTask.intType);
+  checkReturn('testReturnInvokeDynamicGetter', typesTask.dynamicType);
 
   checkReturnInClass(String className, String methodName, type) {
     var cls = findElement(compiler, className);
@@ -562,23 +563,23 @@
         typesInferrer.getReturnTypeOfElement(element).simplify(compiler));
   }
 
-  checkReturnInClass('A', 'returnInt1', typesInferrer.intType);
-  checkReturnInClass('A', 'returnInt2', typesInferrer.intType);
-  checkReturnInClass('A', 'returnInt3', typesInferrer.intType);
-  checkReturnInClass('A', 'returnInt4', typesInferrer.intType);
-  checkReturnInClass('A', 'returnInt5', typesInferrer.intType);
-  checkReturnInClass('A', 'returnInt6', typesInferrer.intType);
+  checkReturnInClass('A', 'returnInt1', typesTask.intType);
+  checkReturnInClass('A', 'returnInt2', typesTask.intType);
+  checkReturnInClass('A', 'returnInt3', typesTask.intType);
+  checkReturnInClass('A', 'returnInt4', typesTask.intType);
+  checkReturnInClass('A', 'returnInt5', typesTask.intType);
+  checkReturnInClass('A', 'returnInt6', typesTask.intType);
   checkReturnInClass('A', '==', interceptorType);
 
-  checkReturnInClass('B', 'returnInt1', typesInferrer.intType);
-  checkReturnInClass('B', 'returnInt2', typesInferrer.intType);
-  checkReturnInClass('B', 'returnInt3', typesInferrer.intType);
-  checkReturnInClass('B', 'returnInt4', typesInferrer.intType);
-  checkReturnInClass('B', 'returnInt5', typesInferrer.intType);
-  checkReturnInClass('B', 'returnInt6', typesInferrer.intType);
-  checkReturnInClass('B', 'returnInt7', typesInferrer.intType);
-  checkReturnInClass('B', 'returnInt8', typesInferrer.intType);
-  checkReturnInClass('B', 'returnInt9', typesInferrer.intType);
+  checkReturnInClass('B', 'returnInt1', typesTask.intType);
+  checkReturnInClass('B', 'returnInt2', typesTask.intType);
+  checkReturnInClass('B', 'returnInt3', typesTask.intType);
+  checkReturnInClass('B', 'returnInt4', typesTask.intType);
+  checkReturnInClass('B', 'returnInt5', typesTask.intType);
+  checkReturnInClass('B', 'returnInt6', typesTask.intType);
+  checkReturnInClass('B', 'returnInt7', typesTask.intType);
+  checkReturnInClass('B', 'returnInt8', typesTask.intType);
+  checkReturnInClass('B', 'returnInt9', typesTask.intType);
 
   checkFactoryConstructor(String className, String factoryName) {
     var cls = findElement(compiler, className);
diff --git a/tests/compiler/dart2js/simple_inferrer_try_catch_test.dart b/tests/compiler/dart2js/simple_inferrer_try_catch_test.dart
index 18eddc7..f4ecaef 100644
--- a/tests/compiler/dart2js/simple_inferrer_try_catch_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_try_catch_test.dart
@@ -157,7 +157,8 @@
   Uri uri = new Uri(scheme: 'source');
   var compiler = compilerFor(TEST, uri);
   compiler.runCompiler(uri);
-  var typesInferrer = compiler.typesTask.typesInferrer;
+  var typesTask = compiler.typesTask;
+  var typesInferrer = typesTask.typesInferrer;
 
   checkReturn(String name, type) {
     var element = findElement(compiler, name);
@@ -165,11 +166,11 @@
         typesInferrer.getReturnTypeOfElement(element).simplify(compiler));
   }
 
-  checkReturn('returnInt1', typesInferrer.intType);
-  checkReturn('returnInt2', typesInferrer.intType);
-  checkReturn('returnInt3', typesInferrer.intType);
-  checkReturn('returnInt4', typesInferrer.intType);
-  checkReturn('returnInt5', typesInferrer.intType);
+  checkReturn('returnInt1', typesTask.intType);
+  checkReturn('returnInt2', typesTask.intType);
+  checkReturn('returnInt3', typesTask.intType);
+  checkReturn('returnInt4', typesTask.intType);
+  checkReturn('returnInt5', typesTask.intType);
   checkReturn('returnInt6',
       new TypeMask.nonNullSubtype(compiler.intClass.rawType));
 
@@ -181,5 +182,5 @@
   checkReturn('returnDyn3', subclassOfInterceptor);
   checkReturn('returnDyn4', subclassOfInterceptor);
   checkReturn('returnDyn5', subclassOfInterceptor);
-  checkReturn('returnDyn6', typesInferrer.dynamicType);
+  checkReturn('returnDyn6', typesTask.dynamicType);
 }
diff --git a/tests/compiler/dart2js/simple_inferrer_unregister_call_test.dart b/tests/compiler/dart2js/simple_inferrer_unregister_call_test.dart
index 020f4c6..81bbe0f 100644
--- a/tests/compiler/dart2js/simple_inferrer_unregister_call_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_unregister_call_test.dart
@@ -41,5 +41,5 @@
     Expect.equals(type, typesInferrer.getReturnTypeOfElement(element));
   }
 
-  checkReturnInClass('A', '+', typesInferrer.intType);
+  checkReturnInClass('A', '+', compiler.typesTask.intType);
 }
diff --git a/tests/compiler/dart2js_extra/minified_mirrors_test.dart b/tests/compiler/dart2js_extra/minified_mirrors_test.dart
index 71533b4..e79b743 100644
--- a/tests/compiler/dart2js_extra/minified_mirrors_test.dart
+++ b/tests/compiler/dart2js_extra/minified_mirrors_test.dart
@@ -5,8 +5,10 @@
 // This test should be removed when dart2js can pass all mirror tests.
 // TODO(ahe): Remove this test.
 
-import '../../lib/mirrors/mirrors_test.dart';
+import '../../lib/mirrors/mirrors_test.dart' as test;
 
 main() {
-  mainWithArgument(isDart2js: true, isMinified: true);
+  test.isDart2js = true;
+  test.isMinified = true;
+  test.main();
 }
diff --git a/tests/compiler/dart2js_extra/mirrors_test.dart b/tests/compiler/dart2js_extra/mirrors_test.dart
index d9df6c5..cc56f5e 100644
--- a/tests/compiler/dart2js_extra/mirrors_test.dart
+++ b/tests/compiler/dart2js_extra/mirrors_test.dart
@@ -5,8 +5,10 @@
 // This test should be removed when dart2js can pass all mirror tests.
 // TODO(ahe): Remove this test.
 
-import '../../lib/mirrors/mirrors_test.dart';
+
+import '../../lib/mirrors/mirrors_test.dart' as test;
 
 main() {
-  mainWithArgument(isDart2js: true);
+  test.isDart2js = true;
+  test.main();
 }
diff --git a/tests/compiler/dart2js_foreign/dart2js_foreign.status b/tests/compiler/dart2js_foreign/dart2js_foreign.status
index d5919cc..953a89f 100644
--- a/tests/compiler/dart2js_foreign/dart2js_foreign.status
+++ b/tests/compiler/dart2js_foreign/dart2js_foreign.status
@@ -58,8 +58,6 @@
 native_checked_fields_test: Fail # TODO(ahe): Convert to metadata syntax.
 native_class_inheritance4_test: Fail # TODO(ahe): Convert to metadata syntax.
 native_class_with_dart_methods_test: Fail # TODO(ahe): Convert to metadata syntax.
-native_missing_method1_test: Fail # TODO(ahe): Convert to metadata syntax.
-native_missing_method2_test: Fail # TODO(ahe): Convert to metadata syntax.
 native_to_string_test: Fail # TODO(ahe): Convert to metadata syntax.
 
 [ $compiler == dartc || $browser ]
diff --git a/tests/compiler/dart2js_native/uninstantiated_type_parameter_test.dart b/tests/compiler/dart2js_native/uninstantiated_type_parameter_test.dart
new file mode 100644
index 0000000..61f3b604
--- /dev/null
+++ b/tests/compiler/dart2js_native/uninstantiated_type_parameter_test.dart
@@ -0,0 +1,24 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+// Test for uninstantiated native classes as type parameters.
+
+class UA {
+}
+
+class UB native "B" {
+}
+
+class C<T> {
+}
+
+main() {
+  var a = new C<UA>();
+  var b = new C<UB>();
+
+  Expect.isTrue(a is! C<int>);
+  Expect.isTrue(a is! C<C>);
+}
diff --git a/tests/corelib/corelib.status b/tests/corelib/corelib.status
index fe615af..d71a582 100644
--- a/tests/corelib/corelib.status
+++ b/tests/corelib/corelib.status
@@ -118,6 +118,7 @@
 
 [ $arch == simmips && $checked ]
 hash_map2_test: Pass, Crash # Too far PC relative branch (?)
+list_test: Pass, Crash # Invalid relative branch offset. Issue 11851.
 collection_length_test: Pass, Timeout
 
 [ $arch == simmips && $mode == debug ]
diff --git a/tests/html/html.status b/tests/html/html.status
index 71d10c1..5a76fb9 100644
--- a/tests/html/html.status
+++ b/tests/html/html.status
@@ -28,6 +28,7 @@
 indexeddb_3_test: Pass, Timeout, Slow # Issue: http://dartbug.com/9437
 indexeddb_4_test: Pass, Timeout, Slow # Issue: http://dartbug.com/9437
 async_test: Pass, Fail # timers test fails on ie10.
+js_test: Fail # http://dartbug.com/11855
 
 [ $compiler == dart2js && ( $runtime == ie9 || $runtime == ie10 ) ]
 worker_api_test: Fail # IE does not support URL.createObjectURL in web workers.
@@ -44,6 +45,9 @@
 *layout_test: Skip
 
 [ $runtime == chrome ]
+canvasrenderingcontext2d_test/drawImage_video_element: Pass,Fail # Issue 11836
+canvasrenderingcontext2d_test/drawImage_video_element_dataUrl: Pass,Fail # Issue 11836
+
 touchevent_test/supported: Fail
 
 [ $runtime == chrome || $runtime == chromeOnAndroid || $runtime == drt || $runtime == safari ]
@@ -365,10 +369,12 @@
 isolates_test: Skip   # Timeout because leg does not support web workers.
 
 [ $compiler == dart2js && $csp && ($runtime == drt || $runtime == safari || $runtime == ff || $runtime == chrome || $runtime == chromeOnAndroid) ]
+# Note: these tests are all injecting scripts by design.  This is not allowed under CSP.
 event_customevent_test: Fail       # Test cannot run under CSP restrictions.
 js_interop_1_test: Skip            # Test cannot run under CSP restrictions (times out).
 js_interop_2_test: Fail, OK        # Test cannot run under CSP restrictions.
 js_interop_3_test: Skip            # Test cannot run under CSP restrictions (times out).
+js_test: Skip                      # Test cannot run under CSP restrictions (times out).
 postmessage_structured_test: Skip  # Test cannot run under CSP restrictions (times out).
 safe_dom_test: Skip                # Test cannot run under CSP restrictions (times out).
 shadow_dom_layout_test: Fail, OK   # Test cannot run under CSP restrictions.
diff --git a/tests/html/js_test.dart b/tests/html/js_test.dart
new file mode 100644
index 0000000..ff6753d
--- /dev/null
+++ b/tests/html/js_test.dart
@@ -0,0 +1,469 @@
+// 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 jsTest;
+
+import 'dart:async';
+import 'dart:html';
+import 'dart:js';
+
+import '../../pkg/unittest/lib/unittest.dart';
+import '../../pkg/unittest/lib/html_config.dart';
+
+_injectJs() {
+  final script = new ScriptElement();
+  script.type = 'text/javascript';
+  script.innerHtml = r"""
+var x = 42;
+
+var _x = 123;
+
+var myArray = ["value1"];
+
+var foreignDoc = (function(){
+  var doc = document.implementation.createDocument("", "root", null);
+  var element = doc.createElement('element');
+  element.setAttribute('id', 'abc');
+  doc.documentElement.appendChild(element);
+  return doc;
+})();
+
+function razzle() {
+  return x;
+}
+
+function getTypeOf(o) {
+  return typeof(o);
+}
+
+function varArgs() {
+  var args = arguments;
+  var sum = 0;
+  for (var i = 0; i < args.length; ++i) {
+    sum += args[i];
+  }
+  return sum;
+}
+
+function Foo(a) {
+  this.a = a;
+}
+
+Foo.b = 38;
+
+Foo.prototype.bar = function() {
+  return this.a;
+}
+Foo.prototype.toString = function() {
+  return "I'm a Foo a=" + this.a;
+}
+
+var container = new Object();
+container.Foo = Foo;
+
+function isArray(a) {
+  return a instanceof Array;
+}
+
+function checkMap(m, key, value) {
+  if (m.hasOwnProperty(key))
+    return m[key] == value;
+  else
+    return false;
+}
+
+function invokeCallback() {
+  return callback();
+}
+
+function invokeCallbackWith11params() {
+  return callbackWith11params(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11);
+}
+
+function returnElement(element) {
+  return element;
+}
+
+function getElementAttribute(element, attr) {
+  return element.getAttribute(attr);
+}
+
+function addClassAttributes(list) {
+  var result = "";
+  for (var i=0; i < list.length; i++) {
+    result += list[i].getAttribute("class");
+  }
+  return result;
+}
+
+function getNewDivElement() {
+  return document.createElement("div");
+}
+
+function testJsMap(callback) {
+  var result = callback();
+  return result['value'];
+}
+
+function Bar() {
+  return "ret_value";
+}
+Bar.foo = "property_value";
+
+function Baz(p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11) {
+  this.f1 = p1;
+  this.f2 = p2;
+  this.f3 = p3;
+  this.f4 = p4;
+  this.f5 = p5;
+  this.f6 = p6;
+  this.f7 = p7;
+  this.f8 = p8;
+  this.f9 = p9;
+  this.f10 = p10;
+  this.f11 = p11;
+}
+""";
+  document.body.append(script);
+}
+
+class Foo implements Serializable<JsObject> {
+  final JsObject _proxy;
+
+  Foo(num a) : this._proxy = new JsObject(context['Foo'], [a]);
+
+  JsObject toJs() => _proxy;
+
+  num get a => _proxy['a'];
+  num bar() => _proxy.callMethod('bar');
+}
+
+class Color implements Serializable<String> {
+  static final RED = new Color._("red");
+  static final BLUE = new Color._("blue");
+  String _value;
+  Color._(this._value);
+  String toJs() => this._value;
+}
+
+main() {
+  _injectJs();
+  useHtmlConfiguration();
+
+  test('read global field', () {
+    expect(context['x'], equals(42));
+    expect(context['y'], isNull);
+  });
+
+  test('read global field with underscore', () {
+    expect(context['_x'], equals(123));
+    expect(context['y'], isNull);
+  });
+
+  test('hashCode and operator==(other)', () {
+    final o1 = context['Object'];
+    final o2 = context['Object'];
+    expect(o1 == o2, isTrue);
+    expect(o1.hashCode == o2.hashCode, isTrue);
+    final d = context['document'];
+    expect(o1 == d, isFalse);
+  });
+
+  test('js instantiation : new Foo()', () {
+    final Foo2 = context['container']['Foo'];
+    final foo = new JsObject(Foo2, [42]);
+    expect(foo['a'], 42);
+    expect(Foo2['b'], 38);
+  });
+
+  test('js instantiation : new Array()', () {
+    final a = new JsObject(context['Array']);
+    expect(a, isNotNull);
+    expect(a['length'], equals(0));
+
+    a.callMethod('push', ["value 1"]);
+    expect(a['length'], equals(1));
+    expect(a[0], equals("value 1"));
+
+    a.callMethod('pop');
+    expect(a['length'], equals(0));
+  });
+
+  test('js instantiation : new Date()', () {
+    final a = new JsObject(context['Date']);
+    expect(a.callMethod('getTime'), isNotNull);
+  });
+
+  test('js instantiation : new Date(12345678)', () {
+    final a = new JsObject(context['Date'], [12345678]);
+    expect(a.callMethod('getTime'), equals(12345678));
+  });
+
+  test('js instantiation : new Date("December 17, 1995 03:24:00 GMT")',
+      () {
+    final a = new JsObject(context['Date'],
+                           ["December 17, 1995 03:24:00 GMT"]);
+    expect(a.callMethod('getTime'), equals(819170640000));
+  });
+
+  test('js instantiation : new Date(1995,11,17)', () {
+    // Note: JS Date counts months from 0 while Dart counts from 1.
+    final a = new JsObject(context['Date'], [1995, 11, 17]);
+    final b = new DateTime(1995, 12, 17);
+    expect(a.callMethod('getTime'), equals(b.millisecondsSinceEpoch));
+  });
+
+  test('js instantiation : new Date(1995,11,17,3,24,0)', () {
+    // Note: JS Date counts months from 0 while Dart counts from 1.
+    final a = new JsObject(context['Date'],
+                                       [1995, 11, 17, 3, 24, 0]);
+    final b = new DateTime(1995, 12, 17, 3, 24, 0);
+    expect(a.callMethod('getTime'), equals(b.millisecondsSinceEpoch));
+  });
+
+  test('js instantiation : new Object()', () {
+    final a = new JsObject(context['Object']);
+    expect(a, isNotNull);
+
+    a['attr'] = "value";
+    expect(a['attr'], equals("value"));
+  });
+
+  test(r'js instantiation : new RegExp("^\w+$")', () {
+    final a = new JsObject(context['RegExp'], [r'^\w+$']);
+    expect(a, isNotNull);
+    expect(a.callMethod('test', ['true']), isTrue);
+    expect(a.callMethod('test', [' false']), isFalse);
+  });
+
+  test('js instantiation via map notation : new Array()', () {
+    final a = new JsObject(context['Array']);
+    expect(a, isNotNull);
+    expect(a['length'], equals(0));
+
+    a['push'].apply(a, ["value 1"]);
+    expect(a['length'], equals(1));
+    expect(a[0], equals("value 1"));
+
+    a['pop'].apply(a);
+    expect(a['length'], equals(0));
+  });
+
+  test('js instantiation via map notation : new Date()', () {
+    final a = new JsObject(context['Date']);
+    expect(a['getTime'].apply(a), isNotNull);
+  });
+
+  test('js instantiation : typed array', () {
+    if (Platform.supportsTypedData) {
+      final codeUnits = "test".codeUnits;
+      final buf = new JsObject(context['ArrayBuffer'], [codeUnits.length]);
+      final bufView = new JsObject(context['Uint8Array'], [buf]);
+      for (var i = 0; i < codeUnits.length; i++) {
+        bufView[i] = codeUnits[i];
+      }
+    }
+  });
+
+  test('js instantiation : >10 parameters', () {
+    final o = new JsObject(context['Baz'], [1,2,3,4,5,6,7,8,9,10,11]);
+    for (var i = 1; i <= 11; i++) {
+      o["f$i"] = i;
+    }
+  });
+
+  test('write global field', () {
+    context['y'] = 42;
+    expect(context['y'], equals(42));
+  });
+
+  test('get JS JsFunction', () {
+    var razzle = context['razzle'];
+    expect(razzle.apply(context), equals(42));
+  });
+
+  test('call JS function', () {
+    expect(context.callMethod('razzle'), equals(42));
+    expect(() => context.callMethod('dazzle'), throwsA(isNoSuchMethodError));
+  });
+
+  test('call JS function via map notation', () {
+    expect(context['razzle'].apply(context), equals(42));
+    expect(() => context['dazzle'].apply(context),
+        throwsA(isNoSuchMethodError));
+  });
+
+  test('call JS function with varargs', () {
+    expect(context.callMethod('varArgs', [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]),
+      equals(55));
+  });
+
+  test('allocate JS object', () {
+    var foo = new JsObject(context['Foo'], [42]);
+    expect(foo['a'], equals(42));
+    expect(foo.callMethod('bar'), equals(42));
+    expect(() => foo.callMethod('baz'), throwsA(isNoSuchMethodError));
+  });
+
+  test('call toString()', () {
+    var foo = new JsObject(context['Foo'], [42]);
+    expect(foo.toString(), equals("I'm a Foo a=42"));
+    var container = context['container'];
+    expect(container.toString(), equals("[object Object]"));
+  });
+
+  test('allocate simple JS array', () {
+    final list = [1, 2, 3, 4, 5, 6, 7, 8];
+    var array = jsify(list);
+    expect(context.callMethod('isArray', [array]), isTrue);
+    expect(array['length'], equals(list.length));
+    for (var i = 0; i < list.length ; i++) {
+      expect(array[i], equals(list[i]));
+    }
+  });
+
+  test('allocate JS array with iterable', () {
+    final set = new Set.from([1, 2, 3, 4, 5, 6, 7, 8]);
+    var array = jsify(set);
+    expect(context.callMethod('isArray', [array]), isTrue);
+    expect(array['length'], equals(set.length));
+    for (var i = 0; i < array['length'] ; i++) {
+      expect(set.contains(array[i]), isTrue);
+    }
+  });
+
+  test('allocate simple JS map', () {
+    var map = {'a': 1, 'b': 2, 'c': 3};
+    var jsMap = jsify(map);
+    expect(!context.callMethod('isArray', [jsMap]), isTrue);
+    for (final key in map.keys) {
+      expect(context.callMethod('checkMap', [jsMap, key, map[key]]), isTrue);
+    }
+  });
+
+  test('allocate complex JS object', () {
+    final object =
+      {
+        'a': [1, [2, 3]],
+        'b': {
+          'c': 3,
+          'd': new JsObject(context['Foo'], [42])
+        },
+        'e': null
+      };
+    var jsObject = jsify(object);
+    expect(jsObject['a'][0], equals(object['a'][0]));
+    expect(jsObject['a'][1][0], equals(object['a'][1][0]));
+    expect(jsObject['a'][1][1], equals(object['a'][1][1]));
+    expect(jsObject['b']['c'], equals(object['b']['c']));
+    expect(jsObject['b']['d'], equals(object['b']['d']));
+    expect(jsObject['b']['d'].callMethod('bar'), equals(42));
+    expect(jsObject['e'], isNull);
+  });
+
+  test('invoke Dart callback from JS', () {
+    expect(() => context.callMethod('invokeCallback'), throws);
+
+    context['callback'] = new Callback(() => 42);
+    expect(context.callMethod('invokeCallback'), equals(42));
+
+    context.deleteProperty('callback');
+    expect(() => context.callMethod('invokeCallback'), throws);
+
+    context['callback'] = () => 42;
+    expect(context.callMethod('invokeCallback'), equals(42));
+
+    context.deleteProperty('callback');
+  });
+
+  test('callback as parameter', () {
+    expect(context.callMethod('getTypeOf', [context['razzle']]),
+        equals("function"));
+  });
+
+  test('invoke Dart callback from JS with this', () {
+    final constructor = new Callback.withThis(($this, arg1) {
+      $this['a'] = 42;
+      $this['b'] = jsify(["a", arg1]);
+    });
+    var o = new JsObject(constructor, ["b"]);
+    expect(o['a'], equals(42));
+    expect(o['b'][0], equals("a"));
+    expect(o['b'][1], equals("b"));
+  });
+
+  test('invoke Dart callback from JS with 11 parameters', () {
+    context['callbackWith11params'] = new Callback((p1, p2, p3, p4, p5, p6, p7,
+        p8, p9, p10, p11) => '$p1$p2$p3$p4$p5$p6$p7$p8$p9$p10$p11');
+    expect(context.callMethod('invokeCallbackWith11params'),
+        equals('1234567891011'));
+  });
+
+  test('return a JS proxy to JavaScript', () {
+    var result = context.callMethod('testJsMap', [() => jsify({'value': 42})]);
+    expect(result, 42);
+  });
+
+  test('test proxy equality', () {
+    var foo1 = new JsObject(context['Foo'], [1]);
+    var foo2 = new JsObject(context['Foo'], [2]);
+    context['foo'] = foo1;
+    context['foo'] = foo2;
+    expect(foo1, isNot(equals(context['foo'])));
+    expect(foo2, equals(context['foo']));
+  });
+
+  test('test instanceof', () {
+    var foo = new JsObject(context['Foo'], [1]);
+    expect(foo.instanceof(context['Foo']), isTrue);
+    expect(foo.instanceof(context['Object']), isTrue);
+    expect(foo.instanceof(context['String']), isFalse);
+  });
+
+  test('test deleteProperty', () {
+    var object = jsify({});
+    object['a'] = 1;
+    expect(context['Object'].callMethod('keys', [object])['length'], 1);
+    expect(context['Object'].callMethod('keys', [object])[0], "a");
+    object.deleteProperty("a");
+    expect(context['Object'].callMethod('keys', [object])['length'], 0);
+  });
+
+  test('test hasProperty', () {
+    var object = jsify({});
+    object['a'] = 1;
+    expect(object.hasProperty('a'), isTrue);
+    expect(object.hasProperty('b'), isFalse);
+  });
+
+  test('test index get and set', () {
+    final myArray = context['myArray'];
+    expect(myArray['length'], equals(1));
+    expect(myArray[0], equals("value1"));
+    myArray[0] = "value2";
+    expect(myArray['length'], equals(1));
+    expect(myArray[0], equals("value2"));
+
+    final foo = new JsObject(context['Foo'], [1]);
+    foo["getAge"] = () => 10;
+    expect(foo.callMethod('getAge'), equals(10));
+  });
+
+  test('access a property of a function', () {
+    expect(context.callMethod('Bar'), "ret_value");
+    expect(context['Bar']['foo'], "property_value");
+  });
+
+  test('retrieve same dart Object', () {
+    final date = new DateTime.now();
+    context['dartDate'] = date;
+    expect(context['dartDate'], equals(date));
+  });
+
+  test('usage of Serializable', () {
+    final red = Color.RED;
+    context['color'] = red;
+    expect(context['color'], equals(red._value));
+  });
+}
diff --git a/tests/html/xhr_test.dart b/tests/html/xhr_test.dart
index 8ddae00..7c2f863 100644
--- a/tests/html/xhr_test.dart
+++ b/tests/html/xhr_test.dart
@@ -18,7 +18,11 @@
 
 main() {
   useHtmlIndividualConfiguration();
-  var url = "/root_dart/tests/html/xhr_cross_origin_data.txt";
+  // Cache blocker is a workaround for:
+  // https://code.google.com/p/dart/issues/detail?id=11834
+  var cacheBlocker = new DateTime.now().millisecondsSinceEpoch;
+  var url = '/root_dart/tests/html/xhr_cross_origin_data.txt?'
+      'cacheBlock=$cacheBlocker';
 
   void validate200Response(xhr) {
     expect(xhr.status, equals(200));
diff --git a/tests/language/issue11724_test.dart b/tests/language/issue11724_test.dart
new file mode 100644
index 0000000..146a6fe
--- /dev/null
+++ b/tests/language/issue11724_test.dart
@@ -0,0 +1,9 @@
+// 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 main() {
+  Expect.throws(() => method(<int>[]), (e) => e is NoSuchMethodError);
+}
diff --git a/tests/language/issue11793_test.dart b/tests/language/issue11793_test.dart
new file mode 100644
index 0000000..0cd00b4
--- /dev/null
+++ b/tests/language/issue11793_test.dart
@@ -0,0 +1,47 @@
+// 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, whose value range analysis phase
+// assumed loop phis that were integer necessarily had integer inputs.
+
+var array = const [0, 0.5];
+var globalB = array[0];
+var otherArray = [5];
+
+main() {
+  var b = globalB;
+  var a = b + 1;
+  if (otherArray[0] == 0) {
+    // Use a non-existing selector to prevent adding a bailout check.
+    a.noSuch();
+    a = otherArray[0];
+  }
+
+  // Use [a] to make sure it does not become dead code.
+  var f = array[a];
+
+  // Add an integer check on [b].
+  var d = array[b];
+
+  // This instruction will be GVN to the same value as [a].
+  // By being GVN'ed, [e] will have its type changed from integer
+  // to number: because of the int type check on [b], we know
+  // [: b + 1 :] returns an integer.
+  // However we update this instruction with the previous [: b + 1 :]
+  // that did not have that information and therefore only knows that
+  // the instruction returns a number.
+  var e = b + 1;
+
+  // Introduce a loop phi that has [e] as header input, and [e++] as
+  // update input. By having [e] as input, dart2js will compute an
+  // integer type for the phi. However, after GVN, [e] becomes a
+  // number.
+
+  while (otherArray[0] == 0) {
+    // Use [e] as an index for an array so that the value range
+    // analysis tries to compute a range for [e].
+    otherArray[e] = d + f;
+    e++;
+  }
+}
diff --git a/tests/language/language.status b/tests/language/language.status
index 1f8c433..0c2d5300 100644
--- a/tests/language/language.status
+++ b/tests/language/language.status
@@ -16,11 +16,13 @@
 # 3) Update the language/src directory with the updated test.
 
 [ $compiler == dart2dart ]
+mixin_type_parameters_simple_test: Fail, Crash # issue 11803
 mixin_super_constructor_named_test: Fail
 mixin_super_constructor_positionals_test: Fail
 const_constructor_super_test/01: fail
 
 [ $compiler == none ]
+mixin_type_parameters_simple_test: Fail, Crash # issue 11803
 mixin_super_constructor_named_test: Fail
 mixin_super_constructor_positionals_test: Fail
 built_in_identifier_prefix_test: Fail # http://dartbug.com/6970
diff --git a/tests/language/language_analyzer.status b/tests/language/language_analyzer.status
index bf69624..acbbb4c 100644
--- a/tests/language/language_analyzer.status
+++ b/tests/language/language_analyzer.status
@@ -4,56 +4,37 @@
 
 [ $compiler == dartanalyzer ]
 #argument_definition_test/01: fail  # issue 11565 (passing for the wrong reason)
-abstract_factory_constructor_test/00: fail
-assign_instance_method_negative_test: fail
-assign_static_type_test/06: fail
-bad_named_parameters2_test: fail
-bad_named_parameters_test: fail
-bad_override_test/01: fail
-bad_override_test/02: fail
-black_listed_test/11: fail
-built_in_identifier_prefix_test: fail
-call_constructor_on_unresolvable_class_test/01: fail
-call_constructor_on_unresolvable_class_test/02: fail
-call_constructor_on_unresolvable_class_test/03: fail
-call_constructor_on_unresolvable_class_test/07: fail
-call_nonexistent_static_test/04: fail
-call_nonexistent_static_test/06: fail
-call_nonexistent_static_test/07: fail
-call_nonexistent_static_test/09: fail
-call_nonexistent_static_test/10: fail
+
+# test issue 11581, it is not warning to call dynamic
 call_through_getter_test: fail
-cast_test/04: fail
-cast_test/05: fail
-closure_call_wrong_argument_count_negative_test: fail
-const_constructor_super_test/01: fail
+
+# test issue 11582, non-final field with 'const' constructor
 compile_time_constant10_test/none: fail
+
+# test issue 11583, int is valid key for constant map literal
 compile_time_constant_c_test/01: fail
-compile_time_constant_checked2_test/03: fail
-compile_time_constant_checked2_test/04: fail
-compile_time_constant_checked3_test/03: fail
-compile_time_constant_checked3_test/04: fail
-compile_time_constant_e_test: fail
-constructor2_negative_test: fail
-constructor3_negative_test: fail
-constructor_call_wrong_argument_count_negative_test: fail
-constructor_initializer_test: fail # uses argument definition test
-constructor_negative_test: fail
-cyclic_type_variable_test/01: fail
-cyclic_type_variable_test/02: fail
-cyclic_type_variable_test/03: fail
-cyclic_type_variable_test/04: fail
-default_factory2_test/01: fail
-default_implementation2_test: fail
-dynamic_field_test: fail
+
+# test issue 11589, export D from 2 export directives
 export_cyclic_test: fail
-f_bounded_quantification_test/01: fail
-f_bounded_quantification_test/02: fail
-factory2_test: fail
-factory5_test/00: fail
-factory_implementation_test/none: fail
+
+# test issue 11580, Function is not a malformed type
+black_listed_test/11: fail
+
+# test issue 11584, positional arguments cannot be used for named parameters
+compile_time_constant_e_test: fail
+
+# test issue 11585, static warning, not negative test
+constructor3_negative_test: fail # issue 11585
+constructor_call_wrong_argument_count_negative_test: fail
+instance_call_wrong_argument_count_negative_test: fail
+
+# test issue 11586, Class(args) is compile-time warning, not error
+constructor_negative_test: fail
+
+# test issue 11590, runtime only negative test
 field_method4_negative_test: fail
-field_override_test/01: fail
+
+# test issue 11591, assigning to the final variable is warning, not error
 final_for_in_variable_test/01: fail
 final_param_negative_test: fail
 final_var_negative_test: fail
@@ -61,38 +42,82 @@
 final_variable_assignment_test/02: fail
 final_variable_assignment_test/03: fail
 final_variable_assignment_test/04: fail
-first_class_types_constants_test: fail
-getter_no_setter2_test/00: fail
-getter_no_setter2_test/03: fail
-getter_no_setter_test/00: fail
 getter_no_setter_test/01: fail
-getters_setters2_test/01: fail
-getters_setters_type_test/01: fail
-implicit_this_test/01: fail
-implicit_this_test/04: fail
+
+# test issue 11592, Function type alias (typedef) is not a constant
+first_class_types_constants_test: fail
+
+# test issue 11594, Reference to a not resolve identifier is static warning
 import_combinators_negative_test: fail
-instance_call_wrong_argument_count_negative_test: fail
-instantiate_type_variable_negative_test: fail
 interface_static_non_final_fields_negative_test: fail
-interface_test/00: fail
+
+# test issue 11595, It is static warning to create instance (new) of the malformed type
+instantiate_type_variable_negative_test: fail
+
+# test issue 11596. e is Unknown is not a compile time error
 is_not_class2_negative_test: fail
+
+# test issue 11597, It is a compile-time error if part has no "part of" directive
 library_juxtaposition_test: fail
-map_literal3_test: fail
-mixin_illegal_constructor_test/13: fail
-mixin_illegal_constructor_test/14: fail
-mixin_illegal_constructor_test/15: fail
-mixin_illegal_constructor_test/16: fail
-mixin_illegal_syntax_test/13: fail
+
+# test issue 11598, 	Any use of a malbounded type gives rise to a static warning
 mixin_type_parameters_errors_test/01: fail
 mixin_type_parameters_errors_test/02: fail
-mixin_type_parameters_errors_test/04: fail
 mixin_type_parameters_errors_test/05: fail
-named_parameters2_test: fail
+
+
+
+
+# TBF: a.imethod = () { return 1; };
+assign_instance_method_negative_test: fail
+
+# TBF: m([int p = 'String'])
+assign_static_type_test/06: fail
+
+# TBD: using built-in identifers
+built_in_identifier_prefix_test: fail
+
+# TBF: (o as C) is not rolled back
+cast_test/04: fail
+cast_test/05: fail
+
+# TBF: It is a compile-time error if the superclass of a class C appears in the implements clause of C.
+closure_call_wrong_argument_count_negative_test: fail
+const_constructor_super_test/01: fail
+compile_time_constant10_test/none: fail
+compile_time_constant_c_test/01: fail
+
+# Runtime negative test. No static errors or warnings.
+closure_call_wrong_argument_count_negative_test: skip
+
+# TBF: m([int p = 'String']) and call 'const' instance creation
+compile_time_constant_checked2_test/03: fail
+compile_time_constant_checked3_test/03: fail
+
+# TBF: not initialized final instance variable
+constructor2_negative_test: fail
+constructor3_negative_test: fail
+constructor_call_wrong_argument_count_negative_test: fail
+constructor_initializer_test: fail # uses argument definition test
+constructor_negative_test: fail
+
+# TBF: It is a static type warning if a type parameter is a supertype of its upper bound.
+cyclic_type_variable_test/01: fail
+cyclic_type_variable_test/02: fail
+cyclic_type_variable_test/03: fail
+cyclic_type_variable_test/04: fail
+
+# TBF: It is a static type warning if any of the type arguments to k' are not subtypes of the bounds of the corresponding formal type parameters of type.
+default_factory2_test/01: fail
+
+# TBF: It is a static warning if the function type of k' is not a subtype of the type of k.
+default_implementation2_test: fail
+
+# TBD: F-bounded quantification
+f_bounded_quantification_test/01: fail
+f_bounded_quantification_test/02: fail
+
 named_parameters_aggregated_test/03: fail
-named_parameters_aggregated_test/05: fail
-new_expression_type_args_test/00: fail
-new_expression_type_args_test/01: fail
-new_expression_type_args_test/02: fail
 no_such_method_negative_test: fail
 non_const_super_negative_test: fail
 number_identifier_negative_test: fail
@@ -103,8 +128,6 @@
 prefix11_negative_test: fail
 prefix12_negative_test: fail
 prefix1_negative_test: fail
-prefix22_test: fail
-prefix23_test: fail
 prefix2_negative_test: fail
 prefix4_negative_test: fail
 prefix5_negative_test: fail
@@ -116,14 +139,8 @@
 private_member3_negative_test: fail
 pseudo_kw_illegal_test/14: fail
 pseudo_kw_test: fail
-redirecting_factory_infinite_steps_test/01: fail
 scope_negative_test: fail
-setter3_test/01: fail
-setter3_test/02: fail
 static_call_wrong_argument_count_negative_test: fail
-static_field3_test/01: fail
-static_field3_test/02: fail
-static_field3_test/04: fail
 static_field_test/01: fail
 static_field_test/02: fail
 static_field_test/03: fail
@@ -137,21 +154,13 @@
 syntax_test/33: fail
 throw7_negative_test: fail
 type_error_test: fail
-type_parameter_test/01: fail
-type_parameter_test/02: fail
-type_parameter_test/03: fail
-type_parameter_test/04: fail
-type_parameter_test/05: fail
-type_parameter_test/06: fail
+type_parameter_test/none: fail
 type_variable_bounds2_test/00: fail
 type_variable_bounds2_test/01: fail
 type_variable_bounds2_test/02: fail
 type_variable_bounds2_test/03: fail
 type_variable_bounds2_test/04: fail
 type_variable_bounds2_test/06: fail
-type_variable_bounds_test/00: fail
-type_variable_bounds_test/03: fail
-type_variable_bounds_test/04: fail
 type_variable_static_context_negative_test: fail
 unresolved_in_factory_negative_test: fail
 unresolved_top_level_method_negative_test: fail
@@ -223,6 +232,7 @@
 # Test issue 11564, named parameter starts with '_'
 named_parameters_with_object_property_names_test: fail
 
+# TBF
 method_override2_test/00: fail # issue 11497
 method_override2_test/01: fail # issue 11497
 method_override2_test/02: fail # issue 11497
@@ -236,10 +246,33 @@
 
 # testing framework problem: we do report warning, framework does not understand it
 # may be https://codereview.chromium.org/18174010/ will fix this
-mixin_type_parameters_errors_test/03: fail
 type_variable_bounds_test/08: fail
 wrong_number_type_arguments_test/01: fail
 
+# test issue 11575, classes with abstrac members are not marked as abstract
+abstract_factory_constructor_test/none: fail
+abstract_syntax_test/none: fail
+get_set_syntax_test/none: fail
+implicit_this_test/none: fail
+interface_test/none: fail
+syntax_test/none: fail
+
+# test issue 11576
+bad_constructor_test/none: fail
+
+# test issue 11577, has return type for []=
+cascade_test/none: fail
+
+# test issue 11578, redirecting factory with not subtype
+factory5_test/none: fail
+factory_redirection_test/none: fail
+type_variable_bounds_test/none: fail
+type_variable_scope_test/none: fail
+factory_implementation_test/none: fail
+
+# test issue 11579, assignment, no setter
+getter_no_setter_test/none: fail
+
 [ $compiler == dartanalyzer && $checked ]
 factory1_test/00: fail
 factory1_test/01: fail
diff --git a/tests/language/language_analyzer2.status b/tests/language/language_analyzer2.status
index a5cfdc9..096888f 100644
--- a/tests/language/language_analyzer2.status
+++ b/tests/language/language_analyzer2.status
@@ -4,56 +4,37 @@
 
 [ $compiler == dart2analyzer ]
 #argument_definition_test/01: fail  # issue 11565 (passing for the wrong reason)
-abstract_factory_constructor_test/00: fail
-assign_instance_method_negative_test: fail
-assign_static_type_test/06: fail
-bad_named_parameters2_test: fail
-bad_named_parameters_test: fail
-bad_override_test/01: fail
-bad_override_test/02: fail
-black_listed_test/11: fail
-built_in_identifier_prefix_test: fail
-call_constructor_on_unresolvable_class_test/01: fail
-call_constructor_on_unresolvable_class_test/02: fail
-call_constructor_on_unresolvable_class_test/03: fail
-call_constructor_on_unresolvable_class_test/07: fail
-call_nonexistent_static_test/04: fail
-call_nonexistent_static_test/06: fail
-call_nonexistent_static_test/07: fail
-call_nonexistent_static_test/09: fail
-call_nonexistent_static_test/10: fail
+
+# test issue 11581, it is not warning to call dynamic
 call_through_getter_test: fail
-cast_test/04: fail
-cast_test/05: fail
-closure_call_wrong_argument_count_negative_test: fail
-const_constructor_super_test/01: fail
+
+# test issue 11582, non-final field with 'const' constructor
 compile_time_constant10_test/none: fail
+
+# test issue 11583, int is valid key for constant map literal
 compile_time_constant_c_test/01: fail
-compile_time_constant_checked2_test/03: fail
-compile_time_constant_checked2_test/04: fail
-compile_time_constant_checked3_test/03: fail
-compile_time_constant_checked3_test/04: fail
-compile_time_constant_e_test: fail
-constructor2_negative_test: fail
-constructor3_negative_test: fail
-constructor_call_wrong_argument_count_negative_test: fail
-constructor_initializer_test: fail # uses argument definition test
-constructor_negative_test: fail
-cyclic_type_variable_test/01: fail
-cyclic_type_variable_test/02: fail
-cyclic_type_variable_test/03: fail
-cyclic_type_variable_test/04: fail
-default_factory2_test/01: fail
-default_implementation2_test: fail
-dynamic_field_test: fail
+
+# test issue 11589, export D from 2 export directives
 export_cyclic_test: fail
-f_bounded_quantification_test/01: fail
-f_bounded_quantification_test/02: fail
-factory2_test: fail
-factory5_test/00: fail
-factory_implementation_test/none: fail
+
+# test issue 11580, Function is not a malformed type
+black_listed_test/11: fail
+
+# test issue 11584, positional arguments cannot be used for named parameters
+compile_time_constant_e_test: fail
+
+# test issue 11585, static warning, not negative test
+constructor3_negative_test: fail # issue 11585
+constructor_call_wrong_argument_count_negative_test: fail
+instance_call_wrong_argument_count_negative_test: fail
+
+# test issue 11586, Class(args) is compile-time warning, not error
+constructor_negative_test: fail
+
+# test issue 11590, runtime only negative test
 field_method4_negative_test: fail
-field_override_test/01: fail
+
+# test issue 11591, assigning to the final variable is warning, not error
 final_for_in_variable_test/01: fail
 final_param_negative_test: fail
 final_var_negative_test: fail
@@ -61,38 +42,82 @@
 final_variable_assignment_test/02: fail
 final_variable_assignment_test/03: fail
 final_variable_assignment_test/04: fail
-first_class_types_constants_test: fail
-getter_no_setter2_test/00: fail
-getter_no_setter2_test/03: fail
-getter_no_setter_test/00: fail
 getter_no_setter_test/01: fail
-getters_setters2_test/01: fail
-getters_setters_type_test/01: fail
-implicit_this_test/01: fail
-implicit_this_test/04: fail
+
+# test issue 11592, Function type alias (typedef) is not a constant
+first_class_types_constants_test: fail
+
+# test issue 11594, Reference to a not resolve identifier is static warning
 import_combinators_negative_test: fail
-instance_call_wrong_argument_count_negative_test: fail
-instantiate_type_variable_negative_test: fail
 interface_static_non_final_fields_negative_test: fail
-interface_test/00: fail
+
+# test issue 11595, It is static warning to create instance (new) of the malformed type
+instantiate_type_variable_negative_test: fail
+
+# test issue 11596. e is Unknown is not a compile time error
 is_not_class2_negative_test: fail
+
+# test issue 11597, It is a compile-time error if part has no "part of" directive
 library_juxtaposition_test: fail
-map_literal3_test: fail
-mixin_illegal_constructor_test/13: fail
-mixin_illegal_constructor_test/14: fail
-mixin_illegal_constructor_test/15: fail
-mixin_illegal_constructor_test/16: fail
-mixin_illegal_syntax_test/13: fail
+
+# test issue 11598, 	Any use of a malbounded type gives rise to a static warning
 mixin_type_parameters_errors_test/01: fail
 mixin_type_parameters_errors_test/02: fail
-mixin_type_parameters_errors_test/04: fail
 mixin_type_parameters_errors_test/05: fail
-named_parameters2_test: fail
+
+
+
+
+# TBF: a.imethod = () { return 1; };
+assign_instance_method_negative_test: fail
+
+# TBF: m([int p = 'String'])
+assign_static_type_test/06: fail
+
+# TBD: using built-in identifers
+built_in_identifier_prefix_test: fail
+
+# TBF: (o as C) is not rolled back
+cast_test/04: fail
+cast_test/05: fail
+
+# TBF: It is a compile-time error if the superclass of a class C appears in the implements clause of C.
+closure_call_wrong_argument_count_negative_test: fail
+const_constructor_super_test/01: fail
+compile_time_constant10_test/none: fail
+compile_time_constant_c_test/01: fail
+
+# Runtime negative test. No static errors or warnings.
+closure_call_wrong_argument_count_negative_test: skip
+
+# TBF: m([int p = 'String']) and call 'const' instance creation
+compile_time_constant_checked2_test/03: fail
+compile_time_constant_checked3_test/03: fail
+
+# TBF: not initialized final instance variable
+constructor2_negative_test: fail
+constructor3_negative_test: fail
+constructor_call_wrong_argument_count_negative_test: fail
+constructor_initializer_test: fail # uses argument definition test
+constructor_negative_test: fail
+
+# TBF: It is a static type warning if a type parameter is a supertype of its upper bound.
+cyclic_type_variable_test/01: fail
+cyclic_type_variable_test/02: fail
+cyclic_type_variable_test/03: fail
+cyclic_type_variable_test/04: fail
+
+# TBF: It is a static type warning if any of the type arguments to k' are not subtypes of the bounds of the corresponding formal type parameters of type.
+default_factory2_test/01: fail
+
+# TBF: It is a static warning if the function type of k' is not a subtype of the type of k.
+default_implementation2_test: fail
+
+# TBD: F-bounded quantification
+f_bounded_quantification_test/01: fail
+f_bounded_quantification_test/02: fail
+
 named_parameters_aggregated_test/03: fail
-named_parameters_aggregated_test/05: fail
-new_expression_type_args_test/00: fail
-new_expression_type_args_test/01: fail
-new_expression_type_args_test/02: fail
 no_such_method_negative_test: fail
 non_const_super_negative_test: fail
 number_identifier_negative_test: fail
@@ -103,8 +128,6 @@
 prefix11_negative_test: fail
 prefix12_negative_test: fail
 prefix1_negative_test: fail
-prefix22_test: fail
-prefix23_test: fail
 prefix2_negative_test: fail
 prefix4_negative_test: fail
 prefix5_negative_test: fail
@@ -116,14 +139,8 @@
 private_member3_negative_test: fail
 pseudo_kw_illegal_test/14: fail
 pseudo_kw_test: fail
-redirecting_factory_infinite_steps_test/01: fail
 scope_negative_test: fail
-setter3_test/01: fail
-setter3_test/02: fail
 static_call_wrong_argument_count_negative_test: fail
-static_field3_test/01: fail
-static_field3_test/02: fail
-static_field3_test/04: fail
 static_field_test/01: fail
 static_field_test/02: fail
 static_field_test/03: fail
@@ -137,19 +154,13 @@
 syntax_test/33: fail
 throw7_negative_test: fail
 type_error_test: fail
-type_parameter_test/01: fail
-type_parameter_test/02: fail
-type_parameter_test/03: fail
-type_parameter_test/04: fail
+type_parameter_test/none: fail
 type_variable_bounds2_test/00: fail
 type_variable_bounds2_test/01: fail
 type_variable_bounds2_test/02: fail
 type_variable_bounds2_test/03: fail
 type_variable_bounds2_test/04: fail
 type_variable_bounds2_test/06: fail
-type_variable_bounds_test/00: fail
-type_variable_bounds_test/03: fail
-type_variable_bounds_test/04: fail
 type_variable_static_context_negative_test: fail
 unresolved_in_factory_negative_test: fail
 unresolved_top_level_method_negative_test: fail
@@ -221,6 +232,7 @@
 # Test issue 11564, named parameter starts with '_'
 named_parameters_with_object_property_names_test: fail
 
+# TBF
 method_override2_test/00: fail # issue 11497
 method_override2_test/01: fail # issue 11497
 method_override2_test/02: fail # issue 11497
@@ -234,10 +246,33 @@
 
 # testing framework problem: we do report warning, framework does not understand it
 # may be https://codereview.chromium.org/18174010/ will fix this
-mixin_type_parameters_errors_test/03: fail
 type_variable_bounds_test/08: fail
 wrong_number_type_arguments_test/01: fail
 
+# test issue 11575, classes with abstrac members are not marked as abstract
+abstract_factory_constructor_test/none: fail
+abstract_syntax_test/none: fail
+get_set_syntax_test/none: fail
+implicit_this_test/none: fail
+interface_test/none: fail
+syntax_test/none: fail
+
+# test issue 11576
+bad_constructor_test/none: fail
+
+# test issue 11577, has return type for []=
+cascade_test/none: fail
+
+# test issue 11578, redirecting factory with not subtype
+factory5_test/none: fail
+factory_redirection_test/none: fail
+type_variable_bounds_test/none: fail
+type_variable_scope_test/none: fail
+factory_implementation_test/none: fail
+
+# test issue 11579, assignment, no setter
+getter_no_setter_test/none: fail
+
 [ $compiler == dart2analyzer && $checked ]
 factory1_test/00: fail
 factory1_test/01: fail
diff --git a/tests/language/language_dart2js.status b/tests/language/language_dart2js.status
index d4d1733..26d084f 100644
--- a/tests/language/language_dart2js.status
+++ b/tests/language/language_dart2js.status
@@ -152,7 +152,7 @@
 get_set_syntax_test/16: Fail # Fixed by https://chromiumcodereview.appspot.com/10915111
 method_binding_test: Fail # internal error: super property read not implemented.
 method_override_test: Fail # cannot resolve type GetKeysFunctionType
-method_override5_test: Fail # Issue 11496
+method_override5_test: Pass, Fail # Issue 11496 (passes if it's inlined)
 abstract_getter_test/01: Fail # instantiation of abstract class
 abstract_factory_constructor_test/01: Fail # instantiation of abstract class
 parameter_initializer6_negative_test: Fail # Issue 3502
@@ -289,7 +289,7 @@
 expect_test: Fail
 stack_overflow_test: Fail
 stack_overflow_stacktrace_test: Fail
-inlined_throw_test: Fail # BUG(11480): Triage.
+licm2_test: Timeout # Issue: 11848
 
 
 [ $compiler == dart2js && $runtime == safari ]
diff --git a/tests/language/mixin_type_parameters_simple_test.dart b/tests/language/mixin_type_parameters_simple_test.dart
new file mode 100644
index 0000000..0df7996
--- /dev/null
+++ b/tests/language/mixin_type_parameters_simple_test.dart
@@ -0,0 +1,26 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+class S {}
+
+class M1<X> {
+  m1() => X;
+}
+
+class M2<Y> {
+  m2() => Y;
+}
+
+class A<T> extends S with M1<T> , M2<T> { }
+
+main() {
+  var a = new A<int>();
+  Expect.equals("int", a.m1().toString());
+  Expect.equals("int", a.m2().toString());
+  a = new A<String>();
+  Expect.equals("String", a.m1().toString());
+  Expect.equals("String", a.m2().toString());
+}
diff --git a/tests/language/recursive_calls_test.dart b/tests/language/recursive_calls_test.dart
new file mode 100644
index 0000000..9a44ea6
--- /dev/null
+++ b/tests/language/recursive_calls_test.dart
@@ -0,0 +1,13 @@
+// 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";
+
+int bar(x) => foo(x+1);
+int foo(x) => x > 9 ? x : bar(x);
+
+main() {
+  Expect.equals(foo(int.parse("1")), 10);
+}
+
diff --git a/tests/lib/analyzer/analyze_library.status b/tests/lib/analyzer/analyze_library.status
index 7298d80..227e5c6 100644
--- a/tests/lib/analyzer/analyze_library.status
+++ b/tests/lib/analyzer/analyze_library.status
@@ -2,3 +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.
 
+[ $compiler == dart2analyzer ]
+lib/async/async: fail
+lib/core/core: fail
+lib/typed_data/typed_data: fail
+lib/io/io: fail
diff --git a/tests/lib/analyzer/analyze_tests.status b/tests/lib/analyzer/analyze_tests.status
index 28e1660..6348c8b 100644
--- a/tests/lib/analyzer/analyze_tests.status
+++ b/tests/lib/analyzer/analyze_tests.status
@@ -3,10 +3,58 @@
 # BSD-style license that can be found in the LICENSE file.
 
 [ $compiler == dartanalyzer ]
-standalone/io/process_exit_negative_test: fail
 53bit_overflow_literal_test/01: fail, ok
 
+# https://code.google.com/p/dart/issues/detail?id=11665
+standalone/assert_test: fail
+standalone/io/directory_invalid_arguments_test: fail
+standalone/io/file_constructor_test: fail
+standalone/io/file_fuzz_test: fail
+standalone/io/http_cookie_date_test: fail
+standalone/io/http_headers_test: fail
+standalone/io/http_parser_test: fail
+standalone/io/process_invalid_arguments_test: fail
+standalone/io/raw_secure_server_socket_argument_test: fail
+standalone/io/secure_socket_argument_test: fail
+standalone/io/stdout_bad_argument_test: fail
+standalone/io/skipping_dart2js_compilations_test: fail
+standalone/io/url_encoding_test: fail
+standalone/io/web_socket_protocol_processor_test: fail
+standalone/io/test_runner_test: fail
+standalone/package/invalid_uri_test: fail
+standalone/package/package1_test: fail
+standalone/package/package_test: fail
+standalone/typed_data_view_test: fail
+standalone/typed_data_test: fail
+
+# pkg issue https://code.google.com/p/dart/issues/detail?id=11856
+standalone/io/secure_socket_renegotiate_test: fail
+
 
 [ $compiler == dart2analyzer ]
-standalone/io/process_exit_negative_test: fail
 53bit_overflow_literal_test/01: fail, ok
+
+# https://code.google.com/p/dart/issues/detail?id=11665
+standalone/assert_test: fail
+standalone/io/directory_invalid_arguments_test: fail
+standalone/io/file_constructor_test: fail
+standalone/io/file_fuzz_test: fail
+standalone/io/http_cookie_date_test: fail
+standalone/io/http_headers_test: fail
+standalone/io/http_parser_test: fail
+standalone/io/process_invalid_arguments_test: fail
+standalone/io/raw_secure_server_socket_argument_test: fail
+standalone/io/secure_socket_argument_test: fail
+standalone/io/stdout_bad_argument_test: fail
+standalone/io/skipping_dart2js_compilations_test: fail
+standalone/io/url_encoding_test: fail
+standalone/io/web_socket_protocol_processor_test: fail
+standalone/io/test_runner_test: fail
+standalone/package/invalid_uri_test: fail
+standalone/package/package1_test: fail
+standalone/package/package_test: fail
+standalone/typed_data_view_test: fail
+standalone/typed_data_test: fail
+
+# pkg issue https://code.google.com/p/dart/issues/detail?id=11856
+standalone/io/secure_socket_renegotiate_test: fail
diff --git a/tests/lib/convert/utf82_test.dart b/tests/lib/convert/utf82_test.dart
new file mode 100644
index 0000000..f972803
--- /dev/null
+++ b/tests/lib/convert/utf82_test.dart
@@ -0,0 +1,135 @@
+// 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 utf8_test;
+import "package:expect/expect.dart";
+import 'dart:convert';
+import 'dart:codec';
+
+String decode(List<int> bytes) => new Utf8Decoder().convert(bytes);
+String decodeAllowMalformed(List<int> bytes) {
+  return new Utf8Decoder(allowMalformed: true).convert(bytes);
+}
+
+String decode2(List<int> bytes) => UTF8.decode(bytes);
+String decodeAllowMalformed2(List<int> bytes) {
+  return UTF8.decode(bytes, allowMalformed: true);
+}
+
+String decode3(List<int> bytes) => new Utf8Codec().decode(bytes);
+String decodeAllowMalformed3(List<int> bytes) {
+  return new Utf8Codec(allowMalformed: true).decode(bytes);
+}
+
+String decode4(List<int> bytes) => new Utf8Codec().decoder.convert(bytes);
+String decodeAllowMalformed4(List<int> bytes) {
+  return new Utf8Codec(allowMalformed: true).decoder.convert(bytes);
+}
+
+final TESTS = [
+  // Unfinished UTF-8 sequences.
+  [ 0xc3 ],
+  [ 0xE2, 0x82 ],
+  [ 0xF0, 0xA4, 0xAD ],
+  // Overlong encoding of euro-sign.
+  [ 0xF0, 0x82, 0x82, 0xAC ],
+  // Other overlong/unfinished sequences.
+  [ 0xC0 ],
+  [ 0xC1 ],
+  [ 0xF5 ],
+  [ 0xF6 ],
+  [ 0xF7 ],
+  [ 0xF8 ],
+  [ 0xF9 ],
+  [ 0xFA ],
+  [ 0xFB ],
+  [ 0xFC ],
+  [ 0xFD ],
+  [ 0xFE ],
+  [ 0xFF ],
+  [ 0xC0, 0x80 ],
+  [ 0xC1, 0x80 ],
+  // Outside valid range.
+  [ 0xF4, 0xBF, 0xBF, 0xBF ]];
+
+final TESTS2 = [
+  // Test that 0xC0|1, 0x80 does not eat the next character.
+  [[ 0xC0, 0x80, 0x61 ], "Xa" ],
+  [[ 0xC1, 0x80, 0x61 ], "Xa" ],
+  // 0xF5 .. 0xFF never appear in valid UTF-8 sequences.
+  [[ 0xF5, 0x80 ], "XX" ],
+  [[ 0xF6, 0x80 ], "XX" ],
+  [[ 0xF7, 0x80 ], "XX" ],
+  [[ 0xF8, 0x80 ], "XX" ],
+  [[ 0xF9, 0x80 ], "XX" ],
+  [[ 0xFA, 0x80 ], "XX" ],
+  [[ 0xFB, 0x80 ], "XX" ],
+  [[ 0xFC, 0x80 ], "XX" ],
+  [[ 0xFD, 0x80 ], "XX" ],
+  [[ 0xFE, 0x80 ], "XX" ],
+  [[ 0xFF, 0x80 ], "XX" ],
+  [[ 0xF5, 0x80, 0x61 ], "XXa" ],
+  [[ 0xF6, 0x80, 0x61 ], "XXa" ],
+  [[ 0xF7, 0x80, 0x61 ], "XXa" ],
+  [[ 0xF8, 0x80, 0x61 ], "XXa" ],
+  [[ 0xF9, 0x80, 0x61 ], "XXa" ],
+  [[ 0xFA, 0x80, 0x61 ], "XXa" ],
+  [[ 0xFB, 0x80, 0x61 ], "XXa" ],
+  [[ 0xFC, 0x80, 0x61 ], "XXa" ],
+  [[ 0xFD, 0x80, 0x61 ], "XXa" ],
+  [[ 0xFE, 0x80, 0x61 ], "XXa" ],
+  [[ 0xFF, 0x80, 0x61 ], "XXa" ],
+  // Characters outside the valid range.
+  [[ 0xF5, 0x80, 0x80, 0x61 ], "XXXa" ],
+  [[ 0xF6, 0x80, 0x80, 0x61 ], "XXXa" ],
+  [[ 0xF7, 0x80, 0x80, 0x61 ], "XXXa" ],
+  [[ 0xF8, 0x80, 0x80, 0x61 ], "XXXa" ],
+  [[ 0xF9, 0x80, 0x80, 0x61 ], "XXXa" ],
+  [[ 0xFA, 0x80, 0x80, 0x61 ], "XXXa" ],
+  [[ 0xFB, 0x80, 0x80, 0x61 ], "XXXa" ],
+  [[ 0xFC, 0x80, 0x80, 0x61 ], "XXXa" ],
+  [[ 0xFD, 0x80, 0x80, 0x61 ], "XXXa" ],
+  [[ 0xFE, 0x80, 0x80, 0x61 ], "XXXa" ],
+  [[ 0xFF, 0x80, 0x80, 0x61 ], "XXXa" ]];
+
+main() {
+  var allTests = TESTS.expand((test) {
+    // Pairs of test and expected string output when malformed strings are
+    // allowed. Replacement character: U+FFFD
+    return [[ test, "\u{FFFD}" ],
+            [ new List.from([0x61])..addAll(test), "a\u{FFFD}" ],
+            [ new List.from([0x61])..addAll(test)..add(0x61), "a\u{FFFD}a" ],
+            [ new List.from(test)..add(0x61), "\u{FFFD}a" ],
+            [ new List.from(test)..addAll(test), "\u{FFFD}\u{FFFD}" ],
+            [ new List.from(test)..add(0x61)..addAll(test),
+              "\u{FFFD}a\u{FFFD}" ],
+            [ new List.from([0xc3, 0xa5])..addAll(test), "å\u{FFFD}" ],
+            [ new List.from([0xc3, 0xa5])..addAll(test)..addAll([0xc3, 0xa5]),
+              "å\u{FFFD}å" ],
+            [ new List.from(test)..addAll([0xc3, 0xa5]), "\u{FFFD}å" ],
+            [ new List.from(test)..addAll([0xc3, 0xa5])..addAll(test),
+              "\u{FFFD}å\u{FFFD}" ]];
+  });
+
+  var allTests2 = TESTS2.map((test) {
+    // Pairs of test and expected string output when malformed strings are
+    // allowed. Replacement character: U+FFFD
+    String expected = test[1].replaceAll("X", "\u{FFFD}");
+    return [test[0], expected];
+  });
+
+  for (var test in []..addAll(allTests)..addAll(allTests2)) {
+    List<int> bytes = test[0];
+    Expect.throws(() => decode(bytes), (e) => e is FormatException);
+    Expect.throws(() => decode2(bytes), (e) => e is FormatException);
+    Expect.throws(() => decode3(bytes), (e) => e is FormatException);
+    Expect.throws(() => decode4(bytes), (e) => e is FormatException);
+
+    String expected = test[1];
+    Expect.equals(expected, decodeAllowMalformed(bytes));
+    Expect.equals(expected, decodeAllowMalformed2(bytes));
+    Expect.equals(expected, decodeAllowMalformed3(bytes));
+    Expect.equals(expected, decodeAllowMalformed4(bytes));
+  }
+}
diff --git a/tests/lib/convert/utf83_test.dart b/tests/lib/convert/utf83_test.dart
new file mode 100644
index 0000000..3e155dd
--- /dev/null
+++ b/tests/lib/convert/utf83_test.dart
@@ -0,0 +1,46 @@
+// 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 utf8_test;
+import "package:expect/expect.dart";
+import 'dart:codec';
+import 'dart:convert';
+
+main() {
+  // Test that UTF8-decoder removes leading BOM.
+  Expect.equals("a", UTF8.decode([0xEF, 0xBB, 0xBF, 0x61]));
+  Expect.equals("a", UTF8.decoder.convert([0xEF, 0xBB, 0xBF, 0x61]));
+  Expect.equals("a", new Utf8Decoder().convert([0xEF, 0xBB, 0xBF, 0x61]));
+  Expect.equals("a",
+                UTF8.decode([0xEF, 0xBB, 0xBF, 0x61], allowMalformed: true));
+  Expect.equals("a", new Utf8Codec(allowMalformed: true)
+                         .decode([0xEF, 0xBB, 0xBF, 0x61]));
+  Expect.equals("a", new Utf8Codec(allowMalformed: true)
+                         .decoder.convert([0xEF, 0xBB, 0xBF, 0x61]));
+  Expect.equals("a", new Utf8Decoder(allowMalformed: true)
+                         .convert([0xEF, 0xBB, 0xBF, 0x61]));
+  Expect.equals("", UTF8.decode([0xEF, 0xBB, 0xBF]));
+  Expect.equals("", UTF8.decoder.convert([0xEF, 0xBB, 0xBF]));
+  Expect.equals("", new Utf8Decoder().convert([0xEF, 0xBB, 0xBF]));
+  Expect.equals("",
+                UTF8.decode([0xEF, 0xBB, 0xBF], allowMalformed: true));
+  Expect.equals("", new Utf8Codec(allowMalformed: true)
+                         .decode([0xEF, 0xBB, 0xBF]));
+  Expect.equals("", new Utf8Codec(allowMalformed: true)
+                         .decoder.convert([0xEF, 0xBB, 0xBF]));
+  Expect.equals("", new Utf8Decoder(allowMalformed: true)
+                         .convert([0xEF, 0xBB, 0xBF]));
+  Expect.equals("a\u{FEFF}", UTF8.decode([0x61, 0xEF, 0xBB, 0xBF]));
+  Expect.equals("a\u{FEFF}", UTF8.decoder.convert([0x61, 0xEF, 0xBB, 0xBF]));
+  Expect.equals("a\u{FEFF}",
+                new Utf8Decoder().convert([0x61, 0xEF, 0xBB, 0xBF]));
+  Expect.equals("a\u{FEFF}",
+                UTF8.decode([0x61, 0xEF, 0xBB, 0xBF], allowMalformed: true));
+  Expect.equals("a\u{FEFF}", new Utf8Codec(allowMalformed: true)
+                         .decode([0x61, 0xEF, 0xBB, 0xBF]));
+  Expect.equals("a\u{FEFF}", new Utf8Codec(allowMalformed: true)
+                         .decoder.convert([0x61, 0xEF, 0xBB, 0xBF]));
+  Expect.equals("a\u{FEFF}", new Utf8Decoder(allowMalformed: true)
+                         .convert([0x61, 0xEF, 0xBB, 0xBF]));
+}
diff --git a/tests/lib/convert/utf8_test.dart b/tests/lib/convert/utf8_test.dart
new file mode 100644
index 0000000..4fa0297
--- /dev/null
+++ b/tests/lib/convert/utf8_test.dart
@@ -0,0 +1,47 @@
+// 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 utf8_test;
+import "package:expect/expect.dart";
+import 'dart:convert';
+
+String decode(List<int> bytes) => new Utf8Decoder().convert(bytes);
+
+main() {
+  // Google favorite: "Îñţérñåţîöñåļîžåţîờñ".
+  String string = decode([0xc3, 0x8e, 0xc3, 0xb1, 0xc5, 0xa3, 0xc3, 0xa9, 0x72,
+                          0xc3, 0xb1, 0xc3, 0xa5, 0xc5, 0xa3, 0xc3, 0xae, 0xc3,
+                          0xb6, 0xc3, 0xb1, 0xc3, 0xa5, 0xc4, 0xbc, 0xc3, 0xae,
+                          0xc5, 0xbe, 0xc3, 0xa5, 0xc5, 0xa3, 0xc3, 0xae, 0xe1,
+                          0xbb, 0x9d, 0xc3, 0xb1]);
+  Expect.stringEquals("Îñţérñåţîöñåļîžåţîờñ", string);
+
+  // Blueberry porridge in Danish: "blåbærgrød".
+  string = decode([0x62, 0x6c, 0xc3, 0xa5, 0x62, 0xc3, 0xa6, 0x72, 0x67, 0x72,
+                   0xc3, 0xb8, 0x64]);
+  Expect.stringEquals("blåbærgrød", string);
+
+  // "சிவா அணாமாைல", that is "Siva Annamalai" in Tamil.
+  string = decode([0xe0, 0xae, 0x9a, 0xe0, 0xae, 0xbf, 0xe0, 0xae, 0xb5, 0xe0,
+                   0xae, 0xbe, 0x20, 0xe0, 0xae, 0x85, 0xe0, 0xae, 0xa3, 0xe0,
+                   0xae, 0xbe, 0xe0, 0xae, 0xae, 0xe0, 0xae, 0xbe, 0xe0, 0xaf,
+                   0x88, 0xe0, 0xae, 0xb2]);
+  Expect.stringEquals("சிவா அணாமாைல", string);
+
+  // "िसवा अणामालै", that is "Siva Annamalai" in Devanagari.
+  string = decode([0xe0, 0xa4, 0xbf, 0xe0, 0xa4, 0xb8, 0xe0, 0xa4, 0xb5, 0xe0,
+                   0xa4, 0xbe, 0x20, 0xe0, 0xa4, 0x85, 0xe0, 0xa4, 0xa3, 0xe0,
+                   0xa4, 0xbe, 0xe0, 0xa4, 0xae, 0xe0, 0xa4, 0xbe, 0xe0, 0xa4,
+                   0xb2, 0xe0, 0xa5, 0x88]);
+  Expect.stringEquals("िसवा अणामालै", string);
+
+  // DESERET CAPITAL LETTER BEE, unicode 0x10412(0xD801+0xDC12)
+  // UTF-8: F0 90 90 92
+  string = decode([0xf0, 0x90, 0x90, 0x92]);
+  Expect.equals(string.length, 2);
+  Expect.equals("𐐒".length, 2);
+  Expect.stringEquals("𐐒", string);
+
+  // TODO(ahe): Add tests of bad input.
+}
diff --git a/tests/lib/lib.status b/tests/lib/lib.status
index 11cee52..b443409 100644
--- a/tests/lib/lib.status
+++ b/tests/lib/lib.status
@@ -4,7 +4,8 @@
 
 [ $compiler == dart2js ]
 math/*: Skip
-mirrors/method_mirror_test: Fail # Issue 6335
+mirrors/method_mirror_name_test: Fail # Issue 6335
+mirrors/method_mirror_properties_test: Fail # Issue 11861
 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.
 async/run_async3_test: Fail # _enqueueImmediate runs after Timer. http://dartbug.com/9002
@@ -20,19 +21,8 @@
 [ $compiler == dart2js && ($runtime == d8 || $runtime == ie9) ]
 typed_data/byte_data_test: Fail, OK # d8/ie9 doesn't support DataView
 
-[ $compiler == dart2js && $minified ]
-mirrors/reflect_model_test: Fail # Issue 6490
-mirrors/to_string_test: Fail # Issue 6490
-
 [ $csp ]
-mirrors/intercepted_class_test: Fail # Issue 6490
-mirrors/intercepted_object_test: Fail # Issue 6490
-mirrors/metadata_test: Fail # Issue 6490
-mirrors/reflect_model_test: Fail # Issue 6490
-mirrors/reflect_runtime_type_test: Fail # Issue 6490
-mirrors/reflect_uninstantiated_class_test: Fail # Issue 6490
-mirrors/superclass_test: Fail # Issue 6490
-mirrors/to_string_test: Fail # Issue 6490
+mirrors/*: Skip # Issue 6490
 
 [ $compiler == dart2js && $jscl ]
 async/future_test: Fail # Timer interface not supported; dartbug.com/7728.
diff --git a/tests/lib/mirrors/abstract_test.dart b/tests/lib/mirrors/abstract_test.dart
new file mode 100644
index 0000000..3992363
--- /dev/null
+++ b/tests/lib/mirrors/abstract_test.dart
@@ -0,0 +1,19 @@
+// 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 abstract classes are retained.
+
+library test.abstract_test;
+
+import 'dart:mirrors';
+
+import 'stringify.dart';
+
+abstract class Foo {
+}
+
+void main() {
+  expect('Class(s(Foo) in s(test.abstract_test), top-level)',
+         reflectClass(Foo));
+}
diff --git a/tests/lib/mirrors/inherit_field_test.dart b/tests/lib/mirrors/inherit_field_test.dart
new file mode 100644
index 0000000..d61e3bb
--- /dev/null
+++ b/tests/lib/mirrors/inherit_field_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 inherited fields.
+
+library test.inherit_field_test;
+
+import 'dart:mirrors';
+
+import 'stringify.dart';
+
+class Foo {
+  var field;
+}
+
+class Bar extends Foo {
+}
+
+void main() {
+  expect('Variable(s(field) in s(Foo))',
+         reflectClass(Foo).members[new Symbol('field')]);
+  expect('<null>',
+         reflectClass(Bar).members[new Symbol('field')]);
+}
diff --git a/tests/lib/mirrors/lazy_static_test.dart b/tests/lib/mirrors/lazy_static_test.dart
new file mode 100644
index 0000000..d82316b
--- /dev/null
+++ b/tests/lib/mirrors/lazy_static_test.dart
@@ -0,0 +1,33 @@
+// 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 static members.
+
+import 'dart:mirrors';
+
+import 'package:expect/expect.dart';
+
+import 'stringify.dart';
+
+class Foo {
+  static var hello = {
+    'a': 'b',
+    'c': 'd',
+  };
+}
+
+void main() {
+  expect('Variable(s(hello) in s(Foo), static)',
+         reflectClass(Foo).members[new Symbol('hello')]);
+  var reflectee = reflectClass(Foo).getField(new Symbol('hello')).reflectee;
+  Expect.stringEquals('a, c', reflectee.keys.join(', '));
+  // Call the lazy getter twice as different things probably happen in the
+  // underlying implementation.
+  reflectee = reflectClass(Foo).getField(new Symbol('hello')).reflectee;
+  Expect.stringEquals('a, c', reflectee.keys.join(', '));
+  var value = 'fisk';
+  Foo.hello = value;
+  reflectee = reflectClass(Foo).getField(new Symbol('hello')).reflectee;
+  Expect.identical(value, reflectee);
+}
diff --git a/tests/lib/mirrors/method_mirror_name_test.dart b/tests/lib/mirrors/method_mirror_name_test.dart
new file mode 100644
index 0000000..a921d33
--- /dev/null
+++ b/tests/lib/mirrors/method_mirror_name_test.dart
@@ -0,0 +1,17 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "dart:mirrors";
+
+import "package:expect/expect.dart";
+import "stringify.dart";
+
+doNothing42() {}
+
+main() {
+  // Regression test for http://www.dartbug.com/6335
+  var closureMirror = reflect(doNothing42);
+  Expect.equals(stringifySymbol(closureMirror.function.simpleName),
+                "s(doNothing42)");
+}
diff --git a/tests/lib/mirrors/method_mirror_properties_test.dart b/tests/lib/mirrors/method_mirror_properties_test.dart
new file mode 100644
index 0000000..c29c6f8
--- /dev/null
+++ b/tests/lib/mirrors/method_mirror_properties_test.dart
@@ -0,0 +1,78 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "dart:mirrors";
+
+import "package:expect/expect.dart";
+
+doNothing42() {}
+
+int _x = 5;
+int get topGetter => _x;
+void set topSetter(x) { _x = x; }
+
+class AbstractC {
+
+  AbstractC();
+
+  void bar();
+  get priv;
+  set priv(value);
+}
+
+class C extends AbstractC {
+
+  static foo() {}
+
+  C();
+  C.other();
+  C.other2() : this.other();
+
+  var _priv;
+  get priv => _priv;
+  set priv(value) => _priv = value;
+}
+
+checkKinds(method, kinds) {
+  Expect.equals(method.isStatic, kinds[0]);
+  Expect.equals(method.isAbstract, kinds[1]);
+  Expect.equals(method.isGetter, kinds[2]);
+  Expect.equals(method.isSetter, kinds[3]);
+  Expect.equals(method.isConstructor, kinds[4]);
+}
+
+main() {
+  // Top level functions should be static.
+  var closureMirror = reflect(doNothing42);
+  checkKinds(closureMirror.function,
+      [true, false, false, false, false]);
+  var libraryMirror = reflectClass(C).owner;
+  checkKinds(libraryMirror.getters[const Symbol("topGetter")],
+      [true, false, true, false, false]);
+  checkKinds(libraryMirror.setters[const Symbol("topSetter=")],
+      [true, false, false, true, false]);
+  var classMirror;
+  classMirror = reflectClass(C);
+  checkKinds(classMirror.members[const Symbol("foo")],
+      [true, false, false, false, false]);
+  checkKinds(classMirror.members[const Symbol("priv")],
+      [false, false, true, false, false]);
+  checkKinds(classMirror.members[const Symbol("priv=")],
+      [false, false, false, true, false]);
+  checkKinds(classMirror.constructors[const Symbol("C")],
+      [false, false, false, false, true]);
+  checkKinds(classMirror.constructors[const Symbol("C.other")],
+      [false, false, false, false, true]);
+  checkKinds(classMirror.constructors[const Symbol("C.other2")],
+      [false, false, false, false, true]);
+  classMirror = reflectClass(AbstractC);
+  checkKinds(classMirror.constructors[const Symbol("AbstractC")],
+      [false, false, false, false, true]);
+  checkKinds(classMirror.members[const Symbol("bar")],
+      [false, true, false, false, false]);
+  checkKinds(classMirror.members[const Symbol("priv")],
+      [false, true, true, false, false]);
+  checkKinds(classMirror.members[const Symbol("priv=")],
+      [false, true, false, true, false]);
+}
diff --git a/tests/lib/mirrors/method_mirror_test.dart b/tests/lib/mirrors/method_mirror_test.dart
deleted file mode 100644
index 16851c9..0000000
--- a/tests/lib/mirrors/method_mirror_test.dart
+++ /dev/null
@@ -1,21 +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.
-
-import "dart:mirrors";
-
-import "../../../pkg/unittest/lib/unittest.dart";
-
-String _symbolToString(Symbol sym) {
-  return MirrorSystem.getName(sym);
-}
-
-doNothing42() {}
-
-main() {
-  // Regression test for http://www.dartbug.com/6335
-  test("NamedMethodName", () {
-    var closureMirror = reflect(doNothing42);
-    expect(_symbolToString(closureMirror.function.simpleName), "doNothing42");
-  });
-}
diff --git a/tests/lib/mirrors/mirrors_test.dart b/tests/lib/mirrors/mirrors_test.dart
index 13f8587..1b9a999 100644
--- a/tests/lib/mirrors/mirrors_test.dart
+++ b/tests/lib/mirrors/mirrors_test.dart
@@ -2,21 +2,34 @@
 // 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(rmacnak): Move the existing mirror tests here (a place for
-// cross-implementation tests).
-
 library MirrorsTest;
 import "dart:mirrors";
 import "../../../pkg/unittest/lib/unittest.dart";
 
+bool isDart2js = false; // TODO(ahe): Remove this field.
+bool isMinified = false; // TODO(ahe): Remove this field.
+
 var topLevelField;
+u(a, b, c) => {"a": a, "b": b, "c": c};
+_v(a, b) => a + b;
 
 class Class<T> {
   Class() { this.field = "default value"; }
   Class.withInitialValue(this.field);
   var field;
-  static var staticField;
+
+  Class.generative(this.field);
+  Class.redirecting(y) : this.generative(y*2);
+  factory Class.faktory(y) => new Class.withInitialValue(y*3);
+  factory Class.redirectingFactory(y) = Class.faktory;
+
   m(a, b, c) => {"a": a, "b": b, "c": c};
+  _n(a, b) => a + b;
+  noSuchMethod(invocation) => "DNU";
+
+  static var staticField;
+  static s(a, b, c) => {"a": a, "b": b, "c": c};
+  static _t(a, b) => a + b;
 }
 
 typedef Typedef();
@@ -27,6 +40,37 @@
 
   expect(instMirror.invoke(const Symbol("m"),['A', 'B', instance]).reflectee,
          equals({"a": 'A', "b":'B', "c": instance}));
+  expect(instMirror.invoke(const Symbol("notDefined"), []).reflectee,
+         equals("DNU"));
+  expect(instMirror.invoke(const Symbol("m"), []).reflectee,
+         equals("DNU"));  // Wrong arity.
+  // TODO(rmacnak): Implement access to private members. 
+  // expect(instMirror.invoke(const Symbol("_n"), [3, 4]).reflectee,
+  //        equals(7));
+
+  var classMirror = instMirror.type;
+  expect(classMirror.invoke(const Symbol("s"),['A', 'B', instance]).reflectee,
+         equals({"a": 'A', "b":'B', "c": instance}));
+  expect(() => classMirror.invoke(const Symbol("notDefined"), []).reflectee,
+         throws);
+  expect(() => classMirror.invoke(const Symbol("s"), []).reflectee,
+         throws);  // Wrong arity.
+  // TODO(rmacnak): Implement access to private members.
+  // expect(classMirror.invoke(const Symbol("_t"), [3, 4]).reflectee,
+  //        equals(7));
+
+  if (isDart2js) return;
+
+  var libMirror = classMirror.owner;
+  expect(libMirror.invoke(const Symbol("u"),['A', 'B', instance]).reflectee,
+         equals({"a": 'A', "b":'B', "c": instance}));
+  expect(() => libMirror.invoke(const Symbol("notDefined"), []).reflectee,
+         throws);
+  expect(() => libMirror.invoke(const Symbol("u"), []).reflectee,
+         throws);  // Wrong arity.
+  // NB: This works on the VM but fails at compile-time on dart2js.
+  // expect(libMirror.invoke(const Symbol("_v"), [3, 4]).reflectee,
+  //        equals(7));
 }
 
 testInstanceFieldAccess(mirrors) {
@@ -72,21 +116,24 @@
   var classMirror = libMirror.classes[const Symbol("Class")];
   var instMirror = reflect(instance);
   var fieldMirror = classMirror.members[const Symbol('field')];
+  var future;
 
   expect(fieldMirror is VariableMirror, isTrue);
   expect(fieldMirror.type, equals(mirrors.dynamicType));
 
-  libMirror.setField(const Symbol('topLevelField'), [91]);
-  expect(libMirror.getField(const Symbol('topLevelField')).reflectee,
-         equals([91]));
-  expect(topLevelField, equals([91]));
+  if (!isMinified) {
+    libMirror.setField(const Symbol('topLevelField'), [91]);
+    expect(libMirror.getField(const Symbol('topLevelField')).reflectee,
+           equals([91]));
+    expect(topLevelField, equals([91]));
 
-  libMirror.setFieldAsync(const Symbol('topLevelField'), 42);
-  var future = libMirror.getFieldAsync(const Symbol('topLevelField'));
-  future.then(expectAsync1((resultMirror) {
-    expect(resultMirror.reflectee, equals(42));
-    expect(topLevelField, equals(42));
-  }));
+    libMirror.setFieldAsync(const Symbol('topLevelField'), 42);
+    future = libMirror.getFieldAsync(const Symbol('topLevelField'));
+    future.then(expectAsync1((resultMirror) {
+      expect(resultMirror.reflectee, equals(42));
+      expect(topLevelField, equals(42));
+    }));
+  }
 
   classMirror.setFieldAsync(const Symbol('staticField'), 43);
   future = classMirror.getFieldAsync(const Symbol('staticField'));
@@ -134,6 +181,30 @@
   expect(instanceMirror.reflectee is Class, equals(true));
   expect(instanceMirror.reflectee.field, equals(45));
 
+
+  instanceMirror = classMirror.newInstance(const Symbol('generative'),
+                                           [7]);
+  expect(instanceMirror.reflectee is Class, equals(true));
+  expect(instanceMirror.reflectee.field, equals(7));
+
+  instanceMirror = classMirror.newInstance(const Symbol('redirecting'),
+                                           [8]);
+  expect(instanceMirror.reflectee is Class, equals(true));
+  expect(instanceMirror.reflectee.field, equals(16));
+
+  instanceMirror = classMirror.newInstance(const Symbol('faktory'),
+                                           [9]);
+  expect(instanceMirror.reflectee is Class, equals(true));
+  expect(instanceMirror.reflectee.field, equals(27));
+
+  instanceMirror = classMirror.newInstance(const Symbol('redirectingFactory'),
+                                           [10]);
+  if (!isDart2js) {
+    expect(instanceMirror.reflectee is Class, equals(true));
+    expect(instanceMirror.reflectee.field, equals(30));
+  }
+
+
   var future = classMirror.newInstanceAsync(const Symbol(''), []);
   future.then(expectAsync1((resultMirror) {
     var instance = resultMirror.reflectee;
@@ -155,12 +226,13 @@
   var symbolClassMirror = reflectClass(Symbol);
   var symbolMirror = symbolClassMirror.newInstance(const Symbol(''),
                                                    ['withInitialValue']);
+  if (isDart2js) return;
   var objectMirror = classMirror.newInstance(symbolMirror.reflectee,[1234]);
   expect(objectMirror.reflectee is Class, equals(true));
   expect(objectMirror.reflectee.field, equals(1234));
 }
 
-testNames(mirrors, isDart2js) {
+testNames(mirrors) {
   var libMirror = mirrors.findLibrary(const Symbol("MirrorsTest")).single;
   var classMirror = libMirror.classes[const Symbol('Class')];
   var typedefMirror = libMirror.members[const Symbol('Typedef')];
@@ -200,12 +272,11 @@
   expect(check(valueLibrary.uri), isTrue);
 }
 
-mainWithArgument({bool isDart2js: false, bool isMinified: false}) {
+main() {
   var mirrors = currentMirrorSystem();
   test("Test reflective method invocation", () { testInvoke(mirrors); });
   test("Test instance field access", () { testInstanceFieldAccess(mirrors); });
   test('Test intercepted objects', () { testIntercepted(mirrors); });
-  if (!isMinified) // TODO(ahe): Remove this line.
   test("Test field access", () { testFieldAccess(mirrors); });
   test("Test closure mirrors", () { testClosureMirrors(mirrors); });
   test("Test invoke constructor", () { testInvokeConstructor(mirrors); });
@@ -216,12 +287,6 @@
   test("Test dart library uri", () {
     testLibraryUri("test", (Uri uri) => uri == Uri.parse('dart:core'));
   });
-  if (!isMinified) // TODO(ahe): Remove this line.
-  test("Test simple and qualifiedName", () { testNames(mirrors, isDart2js); });
-  if (isDart2js) return; // TODO(ahe): Remove this line.
+  test("Test simple and qualifiedName", () { testNames(mirrors); });
   test("Test reflect type", () { testReflectClass(mirrors); });
 }
-
-main() {
-  mainWithArgument();
-}
diff --git a/tests/lib/mirrors/parameter_test.dart b/tests/lib/mirrors/parameter_test.dart
index 3f97939..aa5cdee 100644
--- a/tests/lib/mirrors/parameter_test.dart
+++ b/tests/lib/mirrors/parameter_test.dart
@@ -27,23 +27,23 @@
   var unnamedConstructor = constructors[new Symbol('B')];
 
   expect('[]', unnamedConstructor.parameters);
-  expect('Type(s(B) in s(test.parameter_test), top-level)',
+  expect('Class(s(B) in s(test.parameter_test), top-level)',
          unnamedConstructor.returnType);
 
   var fooConstructor = constructors[new Symbol('B.foo')];
   expect('[Parameter(s(x) in s(B.foo),'
-         ' type = Type(s(int) in s(dart.core), top-level))]',
+         ' type = Class(s(int) in s(dart.core), top-level))]',
          fooConstructor.parameters);
-  expect('Type(s(B) in s(test.parameter_test), top-level)',
+  expect('Class(s(B) in s(test.parameter_test), top-level)',
          fooConstructor.returnType);
 
   var barConstructor = constructors[new Symbol('B.bar')];
   expect('[Parameter(s(z) in s(B.bar),'
-         ' type = Type(s(int) in s(dart.core), top-level)), '
+         ' type = Class(s(int) in s(dart.core), top-level)), '
          'Parameter(s(x) in s(B.bar),'
          ' type = Type(s(dynamic), top-level))]',
          barConstructor.parameters);
-  expect('Type(s(B) in s(test.parameter_test), top-level)',
+  expect('Class(s(B) in s(test.parameter_test), top-level)',
          barConstructor.returnType);
 
   print(constructors);
diff --git a/tests/lib/mirrors/reflect_model_test.dart b/tests/lib/mirrors/reflect_model_test.dart
index e5eabdf..69239e1 100644
--- a/tests/lib/mirrors/reflect_model_test.dart
+++ b/tests/lib/mirrors/reflect_model_test.dart
@@ -47,8 +47,6 @@
   Expect.equals(89, fieldC);
 
   expect('{accessor: Method(s(accessor) in s(A), getter)'
-         // TODO(ahe): Include instance field getters?
-         ', field: Method(s(field) in s(A), getter)'
          '}',
          aClass.getters);
   expect('{accessor: Method(s(accessor) in s(B), getter)'
@@ -58,8 +56,6 @@
          cClass.getters);
 
   expect('{accessor=: Method(s(accessor=) in s(A), setter)'
-         // TODO(ahe): Include instance field setters?
-         ', field=: Method(s(field=) in s(A), setter)'
          '}',
          aClass.setters);
   expect('{accessor=: Method(s(accessor=) in s(B), setter)}',
diff --git a/tests/lib/mirrors/return_type_test.dart b/tests/lib/mirrors/return_type_test.dart
index db4ad76..ebc208a 100644
--- a/tests/lib/mirrors/return_type_test.dart
+++ b/tests/lib/mirrors/return_type_test.dart
@@ -34,9 +34,9 @@
   var i = methods[const Symbol('i')];
 
   expect('Type(s(dynamic), top-level)', f.returnType);
-  expect('Type(s(int) in s(dart.core), top-level)', g.returnType);
-  expect('Type(s(List) in s(dart.core), top-level)', h.returnType);
-  expect('Type(s(B) in s(test.return_type_test), top-level)', i.returnType);
+  expect('Class(s(int) in s(dart.core), top-level)', g.returnType);
+  expect('Class(s(List) in s(dart.core), top-level)', h.returnType);
+  expect('Class(s(B) in s(test.return_type_test), top-level)', i.returnType);
 
   print(methods);
 }
diff --git a/tests/lib/mirrors/static_test.dart b/tests/lib/mirrors/static_test.dart
new file mode 100644
index 0000000..b238e24
--- /dev/null
+++ b/tests/lib/mirrors/static_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.
+
+// Test static members.
+
+import 'dart:mirrors';
+
+import 'stringify.dart';
+
+class Foo {
+  static String bar = '...';
+  String aux = '';
+  static foo() {}
+  baz() {}
+}
+
+void main() {
+  expect('Variable(s(aux) in s(Foo))',
+         reflectClass(Foo).members[new Symbol('aux')]);
+  expect('Method(s(baz) in s(Foo))',
+         reflectClass(Foo).members[new Symbol('baz')]);
+  expect('<null>',
+         reflectClass(Foo).setters[new Symbol('aux=')]);
+  expect('Method(s(foo) in s(Foo), static)',
+         reflectClass(Foo).members[new Symbol('foo')]);
+  expect('Variable(s(bar) in s(Foo), static)',
+         reflectClass(Foo).members[new Symbol('bar')]);
+}
diff --git a/tests/lib/mirrors/stringify.dart b/tests/lib/mirrors/stringify.dart
index e8c31a8..0e3b2c0 100644
--- a/tests/lib/mirrors/stringify.dart
+++ b/tests/lib/mirrors/stringify.dart
@@ -70,7 +70,7 @@
     buffer.write(', value = ${stringify(parameter.defaultValue)}');
   }
   // TODO(ahe): Move to writeVariableOn.
-  buffer.write(', type = ${stringifyType(parameter.type)}');
+  buffer.write(', type = ${stringify(parameter.type)}');
   return 'Parameter($buffer)';
 }
 
@@ -80,6 +80,12 @@
   return 'Type($buffer)';
 }
 
+stringifyClass(ClassMirror cls) {
+  var buffer = new StringBuffer();
+  writeDeclarationOn(cls, buffer);
+  return 'Class($buffer)';
+}
+
 stringifyMethod(MethodMirror method) {
   var buffer = new StringBuffer();
   writeDeclarationOn(method, buffer);
@@ -97,6 +103,7 @@
   if (value is VariableMirror) return stringifyVariable(value);
   if (value is MethodMirror) return stringifyMethod(value);
   if (value is Symbol) return stringifySymbol(value);
+  if (value is ClassMirror) return stringifyClass(value);
   if (value is TypeMirror) return stringifyType(value);
   if (value == null) return '<null>';
   throw 'Unexpected value: $value';
diff --git a/tests/standalone/io/skipping_dart2js_compilations_test.dart b/tests/standalone/io/skipping_dart2js_compilations_test.dart
index dfb71a5..98e65f1 100644
--- a/tests/standalone/io/skipping_dart2js_compilations_test.dart
+++ b/tests/standalone/io/skipping_dart2js_compilations_test.dart
@@ -154,6 +154,7 @@
   var bootstrapDeps = [
       Uri.parse("file://${fileUtils.testSnapshotFilePath}")];
   var commands = [new runner.CompilationCommand(
+      'dart2js',
       fileUtils.testJsFilePath.toNativePath(),
       false,
       bootstrapDeps,
diff --git a/tests/standalone/io/test_runner_test.dart b/tests/standalone/io/test_runner_test.dart
index 79a8522..d07558a 100644
--- a/tests/standalone/io/test_runner_test.dart
+++ b/tests/standalone/io/test_runner_test.dart
@@ -71,13 +71,15 @@
   }
 
   TestCase _makeNormalTestCase(name, expectations) {
-    var command = new Command(Platform.executable,
+    var command = new Command('custom',
+                              Platform.executable,
                               [Platform.script, name]);
     return _makeTestCase(name, DEFAULT_TIMEOUT, command, expectations);
   }
 
   _makeCrashTestCase(name, expectations) {
-    var crashCommand = new Command(getProcessTestFileName(),
+    var crashCommand = new Command('custom_crash',
+                                   getProcessTestFileName(),
                                    ["0", "0", "1", "1"]);
     // The crash test sometimes times out. Run it with a large timeout
     // to help diagnose the delay.
diff --git a/tools/VERSION b/tools/VERSION
index 54ef79b..9d22974 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -1,4 +1,4 @@
 MAJOR 0
 MINOR 6
-BUILD 5
+BUILD 6
 PATCH 0
diff --git a/tools/bots/editor.py b/tools/bots/editor.py
index f9db5ef..ffe7311 100755
--- a/tools/bots/editor.py
+++ b/tools/bots/editor.py
@@ -5,9 +5,7 @@
 
 import os
 import re
-import shutil
 import sys
-import tempfile
 
 import bot
 
@@ -20,14 +18,6 @@
 GCS_DARTIUM_BUCKET = "gs://dartium-archive/continuous"
 GCS_EDITOR_BUCKET = "gs://continuous-editor-archive"
 
-class TempDir(object):
-  def __enter__(self):
-    self._temp_dir = tempfile.mkdtemp('eclipse-workspace')
-    return self._temp_dir
-
-  def __exit__(self, *_):
-    shutil.rmtree(self._temp_dir, ignore_errors = True)
-
 def GetBuildDirectory(mode, arch):
   configuration_dir = mode + arch.upper()
   build_directory_dict = {
@@ -96,7 +86,7 @@
   mac_build_dmg_py = os.path.join('tools', 'mac_build_editor_dmg.sh')
   editor_dir = GetEditorDirectory('Release', arch)
   dart_sdk = GetDartSdkDirectory('Release', arch)
-  with TempDir() as temp_dir:
+  with utils.TempDir('eclipse') as temp_dir:
     # Get dartium
     dartium_directory = DownloadDartium(temp_dir, 'dartium-mac.zip')
     dartium_bundle_dir = os.path.join(dartium_directory,
@@ -135,9 +125,8 @@
   for arch in test_architectures:
     editor_executable = GetEditorExecutable('Release', arch)
     with bot.BuildStep('Test Editor %s' % arch):
-      with TempDir() as temp_dir:
-        args = [editor_executable, '-noSplash', '--test', '--auto-exit',
-                '-data', temp_dir]
+      with utils.TempDir('eclipse') as temp_dir:
+        args = [editor_executable, '--test', '--auto-exit', '-data', temp_dir]
         RunProcess(args)
 
   # TODO: Permissions need to be clarified
diff --git a/tools/create_sdk.py b/tools/create_sdk.py
index 6791159..89b6aca 100755
--- a/tools/create_sdk.py
+++ b/tools/create_sdk.py
@@ -36,6 +36,7 @@
 # ......html/
 # ......io/
 # ......isolate/
+# ......js/
 # ......json/
 # ......math/
 # ......mirrors/
@@ -203,7 +204,7 @@
                   join('html', 'dart2js'), join('html', 'dartium'),
                   join('html', 'html_common'),
                   join('indexed_db', 'dart2js'), join('indexed_db', 'dartium'),
-                  'json', 'math', 'mirrors', 'typed_data',
+                  'js', 'json', 'math', 'mirrors', 'typed_data',
                   join('svg', 'dart2js'), join('svg', 'dartium'),
                   'utf',
                   join('web_audio', 'dart2js'), join('web_audio', 'dartium'),
diff --git a/tools/dom/scripts/htmlrenamer.py b/tools/dom/scripts/htmlrenamer.py
index aff410d..339ba08 100644
--- a/tools/dom/scripts/htmlrenamer.py
+++ b/tools/dom/scripts/htmlrenamer.py
@@ -195,7 +195,6 @@
   'DocumentFragment.querySelectorAll',
   'Element.childElementCount',
   'Element.children',
-  'Element.className',
   'Element.firstElementChild',
   'Element.getAttribute',
   'Element.getAttributeNS',
@@ -680,7 +679,6 @@
     'Node.get:DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC',
     'Node.get:DOCUMENT_POSITION_PRECEDING',
     'Node.get:baseURI',
-    'Node.get:nodeName',
     'Node.get:prefix',
     'Node.hasAttributes',
     'Node.isDefaultNamespace',
diff --git a/tools/dom/src/CssClassSet.dart b/tools/dom/src/CssClassSet.dart
index 5355446..58c1d6a 100644
--- a/tools/dom/src/CssClassSet.dart
+++ b/tools/dom/src/CssClassSet.dart
@@ -98,7 +98,7 @@
   void writeClasses(Set<String> s) {
     var classes = new List.from(s).join(' ');
     for (Element e in _elementIterable) {
-      e.$dom_className = classes;
+      e.className = classes;
     }
   }
 
@@ -143,7 +143,7 @@
 
   Set<String> readClasses() {
     var s = new LinkedHashSet<String>();
-    var classname = _element.$dom_className;
+    var classname = _element.className;
 
     for (String name in classname.split(' ')) {
       String trimmed = name.trim();
@@ -156,6 +156,6 @@
 
   void writeClasses(Set<String> s) {
     List list = new List.from(s);
-    _element.$dom_className = s.join(' ');
+    _element.className = s.join(' ');
   }
 }
diff --git a/tools/dom/src/native_DOMImplementation.dart b/tools/dom/src/native_DOMImplementation.dart
index 61740d3..1616d41 100644
--- a/tools/dom/src/native_DOMImplementation.dart
+++ b/tools/dom/src/native_DOMImplementation.dart
@@ -71,6 +71,127 @@
   static void spawnDomFunction(Function f, int replyTo) native "Utils_spawnDomFunction";
   static void spawnDomUri(String uri, int replyTo) native "Utils_spawnDomUri";
   static int _getNewIsolateId() native "Utils_getNewIsolateId";
+
+  // The following methods were added for debugger integration to make working
+  // with the Dart C mirrors API simpler.
+  // TODO(jacobr): consider moving them to a separate library.
+  // If Dart supported dynamic code injection, we would only inject this code
+  // when the debugger is invoked.
+
+  /**
+   * Strips the private secret prefix from member names of the form
+   * someName@hash.
+   */
+  static String stripMemberName(String name) {
+    int endIndex = name.indexOf('@');
+    return endIndex > 0 ? name.substring(0, endIndex) : name;
+  }
+
+  /**
+   * Takes a list containing variable names and corresponding values and
+   * returns a map from normalized names to values. Variable names are assumed
+   * to have list offsets 2*n values at offset 2*n+1. This method is required
+   * because Dart_GetLocalVariables returns a list instead of an object that
+   * can be queried to lookup names and values.
+   */
+  static Map<String, dynamic> createLocalVariablesMap(List localVariables) {
+    var map = {};
+    for (int i = 0; i < localVariables.length; i+=2) {
+      map[stripMemberName(localVariables[i])] = localVariables[i+1];
+    }
+    return map;
+  }
+
+  /**
+   * Convenience helper to get the keys of a [Map] as a [List].
+   */
+  static List getMapKeyList(Map map) => map.keys.toList();
+
+ /**
+   * Returns the keys of an arbitrary Dart Map encoded as unique Strings.
+   * Keys that are strings are left unchanged except that the prefix ":" is
+   * added to disambiguate keys from other Dart members.
+   * Keys that are not strings have # followed by the index of the key in the map
+   * prepended to disambuguate. This scheme is simplistic but easy to encode and
+   * decode. The use case for this method is displaying all map keys in a human
+   * readable way in debugging tools.
+   */ 
+  static List<String> getEncodedMapKeyList(dynamic obj) {
+    if (obj is! Map) return null;
+    
+    var ret = new List<String>();
+    int i = 0;
+    return obj.keys.map((key) {
+      var encodedKey;
+      if (key is String) {
+        encodedKey = ':$key';
+      } else {
+        // If the key isn't a string, return a guaranteed unique for this map
+        // string representation of the key that is still somewhat human
+        // readable.
+        encodedKey = '#${i}:$key';
+      }
+      i++;
+      return encodedKey;
+    }).toList(growable: false);
+  }
+
+  static final RegExp _NON_STRING_KEY_REGEXP = new RegExp("^#(\\d+):(.+)\$");
+
+  static _decodeKey(Map map, String key) {
+    // The key is a regular old String.
+    if (key.startsWith(':')) return key.substring(1);
+
+    var match = _NON_STRING_KEY_REGEXP.firstMatch(key);
+    if (match != null) {
+      int index = int.parse(match.group(1));
+      var iter = map.keys.skip(index);
+      if (iter.isNotEmpty) {
+        var ret = iter.first;
+        // Validate that the toString representation of the key matches what we
+        // expect. FIXME: throw an error if it does not.
+        assert(match.group(2) == '$ret');
+        return ret;
+      }
+    }
+    return null;
+  }
+
+  /**
+   * Converts keys encoded with [getEncodedMapKeyList] to their actual keys.
+   */
+  static lookupValueForEncodedMapKey(Map obj, String key) => obj[_decodeKey(obj, key)];
+
+  /**
+   * Builds a constructor name with the form expected by the C Dart mirrors API.
+   */
+  static String buildConstructorName(String className, String constructorName) => '$className.$constructorName';
+
+  /**
+   * Strips the class name from an expression of the form "className.someName".
+   */
+  static String stripClassName(String str, String className) {
+    if (str.length > className.length + 1 &&
+        str.startsWith(className) && str[className.length] == '.') {
+      return str.substring(className.length + 1);
+    } else {
+      return str;
+    }
+  }
+
+  /**
+   * Removes the trailing dot from an expression ending in a dot.
+   * This method is used as Library prefixes include a trailing dot when using
+   * the C Dart debugger API.
+   */
+  static String stripTrailingDot(String str) =>
+    (str != null && str[str.length - 1] == '.') ? str.substring(0, str.length - 1) : str;
+
+  static String addTrailingDot(String str) => '${str}.';
+
+  // TODO(jacobr): we need a failsafe way to determine that a Node is really a
+  // DOM node rather than just a class that extends Node.
+  static bool isNode(obj) => obj is Node;
 }
 
 class _NPObject extends NativeFieldWrapperClass1 {
diff --git a/tools/testing/dart/test_progress.dart b/tools/testing/dart/test_progress.dart
index b288db5..20da10f 100644
--- a/tools/testing/dart/test_progress.dart
+++ b/tools/testing/dart/test_progress.dart
@@ -94,7 +94,7 @@
     var command = test.commands[i];
     var commandOutput = test.commandOutputs[command];
     if (commandOutput != null) {
-      output.add("CommandOutput[$i]:");
+      output.add("CommandOutput[${command.displayName}]:");
       if (!commandOutput.diagnostics.isEmpty) {
         String prefix = 'diagnostics:';
         for (var s in commandOutput.diagnostics) {
@@ -203,29 +203,31 @@
 }
 
 class TimingPrinter extends EventListener {
-  List<TestCase> _tests = <TestCase>[];
+  List<CommandOutput> _commandOutputs = <CommandOutput>[];
   DateTime _startTime;
 
   TimingPrinter(this._startTime);
 
   void done(TestCase testCase) {
-    _tests.add(testCase);
+    for (var commandOutput in testCase.commandOutputs.values) {
+      _commandOutputs.add(commandOutput);
+    }
   }
 
   void allDone() {
-    // TODO: We should take all the commands into account
     Duration d = (new DateTime.now()).difference(_startTime);
     print('\n--- Total time: ${_timeString(d)} ---');
-    _tests.sort((a, b) {
-      Duration aDuration = a.lastCommandOutput.time;
-      Duration bDuration = b.lastCommandOutput.time;
-      return bDuration.inMilliseconds - aDuration.inMilliseconds;
+    _commandOutputs.sort((a, b) {
+      return b.time.inMilliseconds - a.time.inMilliseconds;
     });
-    for (int i = 0; i < 20 && i < _tests.length; i++) {
-      var name = _tests[i].displayName;
-      var duration = _tests[i].lastCommandOutput.time;
-      var configuration = _tests[i].configurationString;
-      print('${duration} - $configuration $name');
+    for (int i = 0; i < 20 && i < _commandOutputs.length; i++) {
+      var commandOutput = _commandOutputs[i];
+      var command = commandOutput.command;
+      var testCase = commandOutput.testCase;
+      var duration = commandOutput.time;
+      var configuration = testCase.configurationString;
+      print('${commandOutput.time} - $configuration'
+            ' - ${testCase.displayName} (${command.displayName})');
     }
   }
 }
diff --git a/tools/testing/dart/test_runner.dart b/tools/testing/dart/test_runner.dart
index 991f8de..e4a51d9 100644
--- a/tools/testing/dart/test_runner.dart
+++ b/tools/testing/dart/test_runner.dart
@@ -107,7 +107,11 @@
   /** The actual command line that will be executed. */
   String commandLine;
 
-  Command(this.executable, this.arguments, [this.environment = null]) {
+  /** A descriptive name for this command. */
+  String displayName;
+
+  Command(this.displayName, this.executable,
+          this.arguments, [this.environment = null]) {
     if (io.Platform.operatingSystem == 'windows') {
       // Windows can't handle the first command if it is a .bat file or the like
       // with the slashes going the other direction.
@@ -132,12 +136,13 @@
   bool _neverSkipCompilation;
   List<Uri> _bootstrapDependencies;
 
-  CompilationCommand(this._outputFile,
+  CompilationCommand(String displayName,
+                     this._outputFile,
                      this._neverSkipCompilation,
                      this._bootstrapDependencies,
                      String executable,
                      List<String> arguments)
-      : super(executable, arguments);
+      : super(displayName, executable, arguments);
 
   Future<bool> get outputIsUpToDate {
     if (_neverSkipCompilation) return new Future.value(false);
@@ -195,7 +200,8 @@
                       List<String> options,
                       List<String> dartFlags,
                       io.Path this.expectedOutputPath)
-      : super(executable,
+      : super("content_shell",
+              executable,
               _getArguments(options, htmlFile),
               _getEnvironment(dartFlags));
 
@@ -457,6 +463,8 @@
 
   Command get command;
 
+  TestCase testCase;
+
   bool get incomplete;
 
   String get result;
@@ -621,7 +629,6 @@
     }
     return testCase.isNegative ? !didFail : didFail;
   }
-
 }
 
 class BrowserCommandOutputImpl extends CommandOutputImpl {
@@ -848,11 +855,7 @@
       if (fields[ERROR_LEVEL] == 'ERROR') {
         errors.add(fields[FORMATTED_ERROR]);
       } else if (fields[ERROR_LEVEL] == 'WARNING') {
-        // We only care about testing Static type warnings
-        // ignore all others
-        if (fields[ERROR_TYPE] == 'STATIC_TYPE' || fields[ERROR_TYPE] == 'STATIC_TYPE_WARNING') {
-          staticWarnings.add(fields[FORMATTED_ERROR]);
-        }
+        staticWarnings.add(fields[FORMATTED_ERROR]);
       }
       // OK to Skip error output that doesn't match the machine format
     }
@@ -919,9 +922,9 @@
       return true;
     }
 
-    if (isStaticClean && staticWarnings.length > 0) {
+    if (isStaticClean && (errors.isNotEmpty || staticWarnings.isNotEmpty)) {
       diagnostics.add(
-          "@static-clean annotation found but analyzer returned warnings.");
+          "@static-clean annotation found but analyzer returned problems.");
       return true;
     }
 
diff --git a/tools/testing/dart/test_suite.dart b/tools/testing/dart/test_suite.dart
index 6abfa34..6796368 100644
--- a/tools/testing/dart/test_suite.dart
+++ b/tools/testing/dart/test_suite.dart
@@ -360,11 +360,12 @@
       var args = TestUtils.standardOptions(configuration);
       args.add(testName);
 
-      doTest(new TestCase(constructedName,
-                          [new Command(targetRunnerPath, args)],
-                          configuration,
-                          completeHandler,
-                          expectations));
+      doTest(
+          new TestCase(constructedName,
+                       [new Command('run_vm_unittest', targetRunnerPath, args)],
+                       configuration,
+                       completeHandler,
+                       expectations));
     }
   }
 
@@ -746,14 +747,16 @@
   }
 
   List<Command> makeCommands(TestInformation info, var vmOptions, var args) {
-    switch (configuration['compiler']) {
+    var compiler = configuration['compiler'];
+    switch (compiler) {
     case 'dart2js':
       args = new List.from(args);
       String tempDir = createOutputDirectory(info.filePath, '');
       args.add('--out=$tempDir/out.js');
 
        List<Command> commands =
-           <Command>[new CompilationCommand("$tempDir/out.js",
+           <Command>[new CompilationCommand(compiler,
+                                            "$tempDir/out.js",
                                             !useSdk,
                                             dart2JsBootstrapDependencies,
                                             compilerPath,
@@ -762,9 +765,10 @@
         // Do not attempt to run the compiled result. A compilation
         // error should be reported by the compilation command.
       } else if (configuration['runtime'] == 'd8') {
-        commands.add(new Command(d8FileName, ['$tempDir/out.js']));
+        commands.add(new Command("d8", d8FileName, ['$tempDir/out.js']));
       } else if (configuration['runtime'] == 'jsshell') {
-        commands.add(new Command(jsShellFileName, ['$tempDir/out.js']));
+        commands.add(
+            new Command("jsshell", jsShellFileName, ['$tempDir/out.js']));
       }
       return commands;
 
@@ -775,7 +779,8 @@
       args.add('--out=$tempDir/out.dart');
 
       List<Command> commands =
-          <Command>[new CompilationCommand("$tempDir/out.dart",
+          <Command>[new CompilationCommand(compiler,
+                                           "$tempDir/out.dart",
                                            !useSdk,
                                            dart2JsBootstrapDependencies,
                                            compilerPath,
@@ -788,7 +793,7 @@
         var vmArguments = new List.from(vmOptions);
         vmArguments.addAll([
             '--ignore-unrecognized-flags', '$tempDir/out.dart']);
-        commands.add(new Command(vmFileName, vmArguments));
+        commands.add(new Command("vm", vmFileName, vmArguments));
       } else {
         throw 'Unsupported runtime ${configuration["runtime"]} for dart2dart';
       }
@@ -798,9 +803,12 @@
     case 'dartc':
     case 'dartanalyzer':
     case 'dart2analyzer':
+      var displayName = (configuration['compiler'] == 'none'
+          ? 'vm' : configuration['compiler']);
       var arguments = new List.from(vmOptions);
       arguments.addAll(args);
-      return <Command>[new Command(dartShellFileName, arguments)];
+      return <Command>[
+          new Command(displayName, dartShellFileName, arguments)];
 
     default:
       throw 'Unknown compiler ${configuration["compiler"]}';
@@ -1024,7 +1032,8 @@
           args = ['tools/testing/dart/launch_browser.dart',
                   runtime,
                   fullHtmlPath];
-          commandSet.add(new Command(TestUtils.dartTestExecutable.toString(),
+          commandSet.add(new Command(runtime,
+                                     TestUtils.dartTestExecutable.toString(),
                                      args));
         } else if (TestUtils.usesWebDriver(runtime)) {
           args = [
@@ -1039,7 +1048,7 @@
           if (subtestIndex != 0) {
             args.add('--force-refresh');
           }
-          commandSet.add(new Command('python', args));
+          commandSet.add(new Command(runtime, 'python', args));
         } else {
           if (runtime != "drt") {
             print("Unknown runtime $runtime");
@@ -1106,36 +1115,27 @@
   /** Helper to create a compilation command for a single input file. */
   Command _compileCommand(String inputFile, String outputFile,
       String compiler, String dir, vmOptions, optionsFromFile) {
+    assert (['dart2js', 'dart2dart'].contains(compiler));
     String executable = compilerPath;
     List<String> args = TestUtils.standardOptions(configuration);
-    switch (compiler) {
-      case 'dart2js':
-      case 'dart2dart':
-        String packageRoot =
-          packageRootArgument(optionsFromFile['packageRoot']);
-        if (packageRoot != null) {
-          args.add(packageRoot);
-        }
-        args.add('--out=$outputFile');
-        args.add(inputFile);
-        break;
-      default:
-        print('unimplemented compiler $compiler');
-        exit(1);
+    String packageRoot =
+      packageRootArgument(optionsFromFile['packageRoot']);
+    if (packageRoot != null) {
+      args.add(packageRoot);
     }
+    args.add('--out=$outputFile');
+    args.add(inputFile);
     if (executable.endsWith('.dart')) {
       // Run the compiler script via the Dart VM.
       args.insert(0, executable);
       executable = dartShellFileName;
     }
-    if (['dart2js', 'dart2dart'].contains(configuration['compiler'])) {
-      return new CompilationCommand(outputFile,
-                                   !useSdk,
-                                   dart2JsBootstrapDependencies,
-                                   compilerPath,
-                                   args);
-    }
-    return new Command(executable, args);
+    return new CompilationCommand(compiler,
+                                  outputFile,
+                                  !useSdk,
+                                  dart2JsBootstrapDependencies,
+                                  compilerPath,
+                                  args);
   }
 
   /**
@@ -1518,7 +1518,7 @@
       "packageRoot": null,
       "hasCompileError": hasCompileError,
       "hasRuntimeError": hasRuntimeError,
-      "isStaticClean" : !hasStaticWarning,
+      "isStaticClean" : !hasCompileError && !hasStaticWarning,
       "otherScripts": <String>[],
       "isMultitest": isMultitest,
       "isMultiHtmlTest": false,
@@ -1668,7 +1668,7 @@
     });
     updatedConfiguration['timeout'] *= 3;
     doTest(new TestCase(suiteName,
-                        [new Command('java', args)],
+                        [new Command('junit_test', 'java', args)],
                         updatedConfiguration,
                         completeHandler,
                         new Set<String>.from([PASS])));
diff --git a/tools/utils.py b/tools/utils.py
index 8346d09..0abb0ed 100644
--- a/tools/utils.py
+++ b/tools/utils.py
@@ -9,8 +9,10 @@
 import os
 import platform
 import re
+import shutil
 import subprocess
 import sys
+import tempfile
 
 
 # Try to guess the host operating system.
@@ -406,6 +408,18 @@
   dart_binary_prefix = os.path.join(tools_dir, '..', 'sdk' , 'bin')
   return os.path.join(dart_binary_prefix, 'dart')
 
+class TempDir(object):
+  def __init__(self, prefix=''):
+    self._temp_dir = None
+    self._prefix = prefix
+
+  def __enter__(self):
+    self._temp_dir = tempfile.mkdtemp(self._prefix)
+    return self._temp_dir
+
+  def __exit__(self, *_):
+    shutil.rmtree(self._temp_dir, ignore_errors=True)
+
 
 if __name__ == "__main__":
   import sys