Version 1.9.0-dev.6.0

svn merge -r 43175:43494 https://dart.googlecode.com/svn/branches/bleeding_edge trunk

git-svn-id: http://dart.googlecode.com/svn/trunk@43495 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/docs/language/dartLangSpec.tex b/docs/language/dartLangSpec.tex
index 08f6aa5..eddcbb8 100644
--- a/docs/language/dartLangSpec.tex
+++ b/docs/language/dartLangSpec.tex
@@ -593,7 +593,8 @@
 
 One could allow modifiers for factories. A factory for \code{Future} could be modified by \ASYNC{}, a factory for \code{Stream} could be modified by \ASYNC* and a factory for \code{Iterable} could be modified by \SYNC*. No other scenario makes sense because the object returned by the factory would be of the wrong type. This situation is very unusual so it is not worth making an exception to the general rule for constructors in order to allow it.
 }
-
+\LMHash{}
+It is a static warning if the declared return type of a function marked \ASYNC{} may not be assigned to \code{Future}. It is a static warning if the declared return type of a function marked \SYNC* may not be assigned to \code{Iterable}. It is a static warning if the declared return type of  a function marked \ASYNC* may not be assigned to \code{Stream}.  
 
 \subsection{Function Declarations}
 \LMLabel{functionDeclarations}
@@ -3505,11 +3506,40 @@
 }
 
 \LMHash{}
-If $f$ is marked \SYNC* (\ref{functions}), then a fresh instance $i$ implementing the built-in class \code{Iterable} is associated with the invocation and immediately returned. When iteration over the iterable is started, by getting an iterator $j$ from the iterable and calling \code{moveNext()} on it, execution of the body of $f$ will begin. When $f$ terminates, $j$ is positioned after its last element, so that its current value is \NULL{} and the current call to \code{moveNext()} on $j$ returns false, as will all further calls.
+If $f$ is marked \SYNC* (\ref{functions}), then a fresh instance $i$ implementing the built-in class \code{Iterable} is associated with the invocation and immediately returned.  
 
-% Can we get more than one iterator from this Iterable? I'd say yes. And if so, do they restart the computation or do they iterate over previously computed results. My guess is the latter.
-% I also assume we extend the IterableBase implementation; otherwise one can pre-compute
-% it all
+
+\commentary{
+A Dart implementation will need to provide a specific implementation of \code{Iterable} that will be returned by \SYNC* methods. A typical strategy would be to produce an instance of a subclass of class \code{IterableBase} defined in \code{dart:core}. The only method that needs to be added by the Dart implementation in that case is \code{iterator}.  
+}
+
+\LMHash{}
+The iterable implementation must comply with the contract of \code{Iterable} and should not take any steps identified as exceptionally efficient in that contract.
+
+\commentary {
+The contract explicitly mentions a number of situations where certain iterables could be more efficient than normal. For example, by precomputing their length. Normal iterables must iterate over their elements to determine their length. This is certainly true in the case of a synchronous generator, where each element is computed by a function. It would not be acceptable to pre-compute the results of the generator and cache them, for example.
+}
+
+\LMHash{}
+When iteration over the iterable is started, by getting an iterator $j$ from the iterable and calling \code{moveNext()} on it, execution of the body of $f$ will begin. When $f$ terminates, $j$ is positioned after its last element, so that its current value is \NULL{} and the current call to \code{moveNext()} on $j$ returns false, as will all further calls.
+
+Each iterator starts a separate computation. If the \SYNC* function is impure, the sequence of values yielded by each iterator may differ. 
+
+\commentary{
+One can derive more than one iterator from a given iterable.   Note that operations on the iterable itself can create distinct iterators. An example would be \code{length}.  It is conceivable that different iterators might yield sequences of different length. The same care needs to be taken when writing \SYNC* functions as when
+writing an \code{Iterator} class. In particular, it should handle multiple
+simultaneous iterators gracefully. If the iterator depends on external state
+that might change, it should check that the state is still valid after every
+yield (and maybe throw a \code{ConcurrentModificationError} if it isn't).
+}
+
+\LMHash{}
+Each iterator runs with its own shallow copies of all local variables; in particular, each iterator has the same initial arguments, even if their bindings are modified by the function. 
+\commentary{
+Two executions of an iterator interact only via state outside the function.
+}
+% The alternative would be to cache the results of an iterator in the iterable, and check the cache at each \YIELD{}.  This would have strange issues as well. The yielded value might differ from the expression in the yield. And it is a potential memory leak as the cache is kept alive by any iterator.
+
 
 \LMHash{}
 If $f$ is synchronous and is not a generator (\ref{functions}) then execution of the body of $f$ begins immediately.  When $f$ terminates the current return value is returned to the caller.
@@ -5941,7 +5971,7 @@
 It is a compile-time error if a yield-each statement appears in a function that is not a generator function.
 
 \LMHash{}
-Let $T$ be the static type of $e$ and let $f$ be the immediately enclosing function.  It is a static type warning if $T$ may not be assigned to the declared return type of $f$. 
+Let $T$ be the static type of $e$ and let $f$ be the immediately enclosing function.  It is a static type warning if $T$ may not be assigned to the declared return type of $f$.  If $f$ is synchronous it is a static  type warning if $T$ may not be assigned to \code{Iterable}.  If $f$ is asynchronous it is a static  type warning if $T$ may not be assigned to \code{Stream}. 
 
 
 \subsection{ Assert}
diff --git a/out2.dart b/out2.dart
deleted file mode 100644
index 37b7d33..0000000
--- a/out2.dart
+++ /dev/null
@@ -1,7 +0,0 @@
-const MANGLED_GLOBAL_NAMES = 'mangledGlobalNames';
-main() {
-  var v0 = 1;
-  while (true) {
-    print(v0);
-  }
-}
diff --git a/pkg/analysis_server/doc/api.html b/pkg/analysis_server/doc/api.html
index 69af5fb..82af650 100644
--- a/pkg/analysis_server/doc/api.html
+++ b/pkg/analysis_server/doc/api.html
@@ -43,12 +43,13 @@
 </style></head>
   <body>
     <h1>Analysis Server API Specification</h1>
-    <h1 style="color:#999999">WORKING DRAFT - Version 0.3</h1>
+    <h1 style="color:#999999">Version 1.0.0</h1>
     <p>
-      This document contains a specification of the API provided by
-      the analysis server. The API in this document is currently under
-      development and should be expected to change. In some cases
-      those changes will be substantial.
+      This document contains a specification of the API provided by the
+      analysis server.  The API in this document is currently under
+      development.  Changes to the API will be accompanied by an update to the
+      protocol version number according to the principles of semantic
+      versioning <a href="http://semver.org/">http://semver.org/</a>.
     </p>
     <h2>Overview</h2>
     <p>
@@ -475,20 +476,28 @@
   "error": <span style="color:#999999">optional</span> <a href="#type_RequestError">RequestError</a>
   "result": {
     "<b>libraries</b>": List&lt;<a href="#type_FilePath">FilePath</a>&gt;
+    "<b>packageMap</b>": Map&lt;String, Map&lt;String, List&lt;<a href="#type_FilePath">FilePath</a>&gt;&gt;&gt;
   }
 }</pre></div>
-            <p>
-              Return a list of all of the libraries referenced by any files in
-              existing analysis roots.
-            </p>
-            
+        <p>
+          Return library dependency information for use in client-side indexing
+          and package URI resolution.
+        </p>
+        
       <h4>Returns</h4><dl><dt class="field"><b><i>libraries ( List&lt;<a href="#type_FilePath">FilePath</a>&gt; )</i></b></dt><dd>
-                    
-                    <p>
-                      A list of the paths of library elements referenced by
-                      files in existing analysis roots.
-                    </p>
-                </dd></dl></dd><dt class="request">analysis.getNavigation</dt><dd><div class="box"><pre>request: {
+            
+              <p>
+                A list of the paths of library elements referenced by
+                files in existing analysis roots.
+              </p>
+            </dd><dt class="field"><b><i>packageMap ( Map&lt;String, Map&lt;String, List&lt;<a href="#type_FilePath">FilePath</a>&gt;&gt;&gt; )</i></b></dt><dd>
+              
+              <p>
+                A mapping from context source roots to package maps which map
+                package names to source directories for use in client-side
+                package URI resolution.
+              </p>
+            </dd></dl></dd><dt class="request">analysis.getNavigation</dt><dd><div class="box"><pre>request: {
   "id": String
   "method": "analysis.getNavigation"
   "params": {
@@ -586,10 +595,13 @@
   "error": <span style="color:#999999">optional</span> <a href="#type_RequestError">RequestError</a>
 }</pre></div>
         <p>
-          Sets the root paths used to determine which files to
-          analyze. The set of files to be analyzed are all of the
-          files in one of the root paths that are not also in one of
-          the excluded paths.
+          Sets the root paths used to determine which files to analyze. The set
+          of files to be analyzed are all of the files in one of the root paths
+          that are not either explicitly or implicitly excluded. A file is
+          explicitly excluded if it is in one of the excluded paths. A file is
+          implicitly excluded if it is in a subdirectory of one of the root
+          paths where the name of the subdirectory starts with a period (that
+          is, a hidden directory).
         </p>
         <p>
           Note that this request determines the set of requested
@@ -1508,12 +1520,16 @@
           </dd><dt class="field"><b><i>selectionOffset ( int )</i></b></dt><dd>
             
             <p>
-              The offset of the current selection in the file.
+              The offset of the current selection in the file. In case
+              preserving, selection information is not required, 0 can be
+              specified for both selection offset and length.
             </p>
           </dd><dt class="field"><b><i>selectionLength ( int )</i></b></dt><dd>
             
             <p>
-              The length of the current selection in the file.
+              The length of the current selection in the file. In case
+              preserving, selection information is not required, 0 can be
+              specified for both selection offset and length.
             </p>
           </dd></dl><h4>Returns</h4><dl><dt class="field"><b><i>edits ( List&lt;<a href="#type_SourceEdit">SourceEdit</a>&gt; )</i></b></dt><dd>
             
@@ -1686,6 +1702,11 @@
         <p>
           Get the changes required to perform a refactoring.
         </p>
+        <p>
+          If another refactoring request is received during the processing
+          of this one, an error of type <tt>REFACTORING_REQUEST_CANCELLED</tt>
+          will be generated.
+        </p>
         
         
       <h4>Parameters</h4><dl><dt class="field"><b><i>kind ( <a href="#type_RefactoringKind">RefactoringKind</a> )</i></b></dt><dd>
@@ -1906,6 +1927,24 @@
         <p>
           Exactly one of the file and uri fields must be provided.
         </p>
+        <p>
+          If the file field is provided and the value is not the path of a file
+          (either the file does not exist or the path references something other
+          than a file), then an error of type <tt>MAP_URI_INVALID_FILE</tt> will
+          be generated.
+        </p>
+        <p>
+          If the uri field is provided and the value is not a valid URI or if
+          the URI references something that is not a file (either a file that
+          does not exist or something other than a file), then an error of type
+          <tt>MAP_URI_INVALID_URI</tt> will be generated.
+        </p>
+        <p>
+          If the contextRoot used to create the execution context is not a file
+          (either the file does not exist or the path references something other
+          than a file), then an error of type <tt>INVALID_EXECUTION_CONTEXT</tt>
+          will be generated.
+        </p>
         
         
       <h4>Parameters</h4><dl><dt class="field"><b><i>id ( <a href="#type_ExecutionContextId">ExecutionContextId</a> )</i></b></dt><dd>
@@ -3055,6 +3094,12 @@
             <p>
               A malformed request was received.
             </p>
+          </dd><dt class="value">REFACTORING_REQUEST_CANCELLED</dt><dd>
+            
+            <p>
+              Another refactoring request was received during processing of
+              this one.
+            </p>
           </dd><dt class="value">SERVER_ALREADY_STARTED</dt><dd>
             
             <p>
diff --git a/pkg/analysis_server/lib/src/analysis_server.dart b/pkg/analysis_server/lib/src/analysis_server.dart
index 43db47b..34531c6 100644
--- a/pkg/analysis_server/lib/src/analysis_server.dart
+++ b/pkg/analysis_server/lib/src/analysis_server.dart
@@ -6,6 +6,7 @@
 
 import 'dart:async';
 import 'dart:collection';
+import 'dart:math' show max;
 
 import 'package:analysis_server/src/analysis_logger.dart';
 import 'package:analysis_server/src/channel/channel.dart';
@@ -66,7 +67,7 @@
    * The version of the analysis server. The value should be replaced
    * automatically during the build.
    */
-  static final String VERSION = '0.0.1';
+  static final String VERSION = '1.0.0';
 
   /**
    * The number of milliseconds to perform operations before inserting
@@ -167,6 +168,24 @@
       new HashMap<AnalysisContext, Completer<AnalysisDoneReason>>();
 
   /**
+   * Performance information before initial analysis is complete.
+   */
+  ServerPerformance performanceDuringStartup = new ServerPerformance();
+
+  /**
+   * Performance information after initial analysis is complete
+   * or `null` if the initial analysis is not yet complete
+   */
+  ServerPerformance performanceAfterStartup;
+
+  /**
+   * The class into which performance information is currently being recorded.
+   * During startup, this will be the same as [performanceDuringStartup]
+   * and after startup is complete, this switches to [performanceAfterStartup].
+   */
+  ServerPerformance _performance;
+
+  /**
    * The option possibly set from the server initialization which disables error notifications.
    */
   bool _noErrorNotification;
@@ -225,6 +244,7 @@
       PackageMapProvider packageMapProvider, this.index,
       AnalysisServerOptions analysisServerOptions, this.defaultSdk,
       this.instrumentationService, {this.rethrowExceptions: true}) {
+    _performance = performanceDuringStartup;
     searchEngine = createSearchEngine(index);
     operationQueue = new ServerOperationQueue();
     contextDirectoryManager =
@@ -241,6 +261,12 @@
     _onPriorityChangeController =
         new StreamController<PriorityChangeEvent>.broadcast();
     running = true;
+    onAnalysisStarted.first.then((_) {
+      onAnalysisComplete.then((_) {
+        performanceAfterStartup = new ServerPerformance();
+        _performance = performanceAfterStartup;
+      });
+    });
     Notification notification = new ServerConnectedParams().toNotification();
     channel.sendNotification(notification);
     channel.listen(handleRequest, onDone: done, onError: error);
@@ -319,8 +345,11 @@
   }
 
   /**
-   * Return the [AnalysisContext] that is used to analyze the given [path].
-   * Return `null` if there is no such context.
+   * Return the preferred [AnalysisContext] for analyzing the given [path].
+   * This will be the context that explicitly contains the path, if any such
+   * context exists, otherwise it will be the first analysis context that
+   * implicitly analyzes it.  Return `null` if no context is analyzing the
+   * path.
    */
   AnalysisContext getAnalysisContext(String path) {
     // try to find a containing context
@@ -334,8 +363,8 @@
   }
 
   /**
-   * Return the [AnalysisContext] that is used to analyze the given [source].
-   * Return `null` if there is no such context.
+   * Return any [AnalysisContext] that is analyzing the given [source], either
+   * explicitly or implicitly.  Return `null` if there is no such context.
    */
   AnalysisContext getAnalysisContextForSource(Source source) {
     for (AnalysisContext context in folderMap.values) {
@@ -526,6 +555,7 @@
    * Handle a [request] that was read from the communication channel.
    */
   void handleRequest(Request request) {
+    _performance.logRequest(request);
     runZoned(() {
       int count = handlers.length;
       for (int i = 0; i < count; i++) {
@@ -833,20 +863,26 @@
    * Set the priority files to the given [files].
    */
   void setPriorityFiles(String requestId, List<String> files) {
+    // Note: when a file is a priority file, that information needs to be
+    // propagated to all contexts that analyze the file, so that all contexts
+    // will be able to do incremental resolution of the file.  See
+    // dartbug.com/22209.
     Map<AnalysisContext, List<Source>> sourceMap =
         new HashMap<AnalysisContext, List<Source>>();
     List<String> unanalyzed = new List<String>();
     files.forEach((file) {
-      AnalysisContext analysisContext = getAnalysisContext(file);
-      if (analysisContext == null) {
-        unanalyzed.add(file);
-      } else {
-        List<Source> sourceList = sourceMap[analysisContext];
-        if (sourceList == null) {
-          sourceList = <Source>[];
-          sourceMap[analysisContext] = sourceList;
+      AnalysisContext preferredContext = getAnalysisContext(file);
+      Source source = getSource(file);
+      bool contextFound = false;
+      for (AnalysisContext context in folderMap.values) {
+        if (context == preferredContext ||
+            context.getKindOf(source) != SourceKind.UNKNOWN) {
+          sourceMap.putIfAbsent(context, () => <Source>[]).add(source);
+          contextFound = true;
         }
-        sourceList.add(getSource(file));
+      }
+      if (!contextFound) {
+        unanalyzed.add(file);
       }
     });
     if (unanalyzed.isNotEmpty) {
@@ -861,6 +897,9 @@
         sourceList = Source.EMPTY_ARRAY;
       }
       context.analysisPriorityOrder = sourceList;
+      // Schedule the context for analysis so that it has the opportunity to
+      // cache the AST's for the priority sources as soon as possible.
+      schedulePerformAnalysisOperation(context);
     });
     operationQueue.reschedule();
     Source firstSource = files.length > 0 ? getSource(files[0]) : null;
@@ -1134,8 +1173,61 @@
   SourceFactory _createSourceFactory(UriResolver packageUriResolver) {
     List<UriResolver> resolvers = <UriResolver>[
         new DartUriResolver(analysisServer.defaultSdk),
-        new ResourceUriResolver(resourceProvider),
-        packageUriResolver];
+        new ResourceUriResolver(resourceProvider)];
+    if (packageUriResolver != null) {
+      resolvers.add(packageUriResolver);
+    }
     return new SourceFactory(resolvers);
   }
 }
+
+
+/**
+ * A class used by [AnalysisServer] to record performance information
+ * such as request latency.
+ */
+class ServerPerformance {
+
+  /**
+   * The creation time and the time when performance information
+   * started to be recorded here.
+   */
+  int startTime = new DateTime.now().millisecondsSinceEpoch;
+
+  /**
+   * The number of requests.
+   */
+  int requestCount = 0;
+
+  /**
+   * The total latency (milliseconds) for all recorded requests.
+   */
+  int requestLatency = 0;
+
+  /**
+   * The maximum latency (milliseconds) for all recorded requests.
+   */
+  int maxLatency = 0;
+
+  /**
+   * The number of requests with latency > 150 milliseconds.
+   */
+  int slowRequestCount = 0;
+
+  /**
+   * Log performation information about the given request.
+   */
+  void logRequest(Request request) {
+    ++requestCount;
+    if (request.clientRequestTime != null) {
+      int latency =
+          new DateTime.now().millisecondsSinceEpoch -
+          request.clientRequestTime;
+      requestLatency += latency;
+      maxLatency = max(maxLatency, latency);
+      if (latency > 150) {
+        ++slowRequestCount;
+      }
+    }
+  }
+}
diff --git a/pkg/analysis_server/lib/src/computer/computer_navigation.dart b/pkg/analysis_server/lib/src/computer/computer_navigation.dart
index ab0d854..c3081ba 100644
--- a/pkg/analysis_server/lib/src/computer/computer_navigation.dart
+++ b/pkg/analysis_server/lib/src/computer/computer_navigation.dart
@@ -33,6 +33,16 @@
     _unit.accept(new _DartUnitNavigationComputerVisitor(this));
   }
 
+  int _addFile(String file) {
+    int index = fileMap[file];
+    if (index == null) {
+      index = files.length;
+      files.add(file);
+      fileMap[file] = index;
+    }
+    return index;
+  }
+
   void _addRegion(int offset, int length, Element element) {
     if (element is FieldFormalParameterElement) {
       element = (element as FieldFormalParameterElement).field;
@@ -48,28 +58,6 @@
         new protocol.NavigationRegion(offset, length, <int>[targetIndex]));
   }
 
-  int _addTarget(Element element) {
-    int index = targetMap[element];
-    if (index == null) {
-      index = targets.length;
-      protocol.NavigationTarget target =
-          protocol.newNavigationTarget_fromElement(element, _addFile);
-      targets.add(target);
-      targetMap[element] = index;
-    }
-    return index;
-  }
-
-  int _addFile(String file) {
-    int index = fileMap[file];
-    if (index == null) {
-      index = files.length;
-      files.add(file);
-      fileMap[file] = index;
-    }
-    return index;
-  }
-
   void _addRegion_nodeStart_nodeEnd(AstNode a, AstNode b, Element element) {
     int offset = a.offset;
     int length = b.end - offset;
@@ -93,6 +81,18 @@
     int length = token.length;
     _addRegion(offset, length, element);
   }
+
+  int _addTarget(Element element) {
+    int index = targetMap[element];
+    if (index == null) {
+      index = targets.length;
+      protocol.NavigationTarget target =
+          protocol.newNavigationTarget_fromElement(element, _addFile);
+      targets.add(target);
+      targetMap[element] = index;
+    }
+    return index;
+  }
 }
 
 
@@ -245,6 +245,23 @@
     computer._addRegionForNode(node, element);
   }
 
+  @override
+  visitSuperConstructorInvocation(SuperConstructorInvocation node) {
+    Element element = node.staticElement;
+    if (element != null && element.isSynthetic) {
+      element = element.enclosingElement;
+    }
+    // add region
+    SimpleIdentifier name = node.constructorName;
+    if (name != null) {
+      computer._addRegion_nodeStart_nodeEnd(node, name, element);
+    } else {
+      computer._addRegionForToken(node.keyword, element);
+    }
+    // process arguments
+    _safelyVisit(node.argumentList);
+  }
+
   void _safelyVisit(AstNode node) {
     if (node != null) {
       node.accept(this);
diff --git a/pkg/analysis_server/lib/src/context_manager.dart b/pkg/analysis_server/lib/src/context_manager.dart
index 38c3c2d..fc42e65 100644
--- a/pkg/analysis_server/lib/src/context_manager.dart
+++ b/pkg/analysis_server/lib/src/context_manager.dart
@@ -283,7 +283,7 @@
    * Resursively adds all Dart and HTML files to the [changeSet].
    */
   void _addSourceFiles(ChangeSet changeSet, Folder folder, _ContextInfo info) {
-    if (info.excludesResource(folder)) {
+    if (info.excludesResource(folder) || folder.shortName.startsWith('.')) {
       return;
     }
     List<Resource> children = folder.getChildren();
@@ -311,26 +311,28 @@
 
   /**
    * Compute the appropriate package URI resolver for [folder], and store
-   * dependency information in [info].
+   * dependency information in [info]. Return `null` if no package map can
+   * be computed.
    */
   UriResolver _computePackageUriResolver(Folder folder, _ContextInfo info) {
-    UriResolver packageUriResolver;
     if (info.packageRoot != null) {
       info.packageMapDependencies = new Set<String>();
-      packageUriResolver =
-          new PackageUriResolver([new JavaFile(info.packageRoot)]);
+      return new PackageUriResolver([new JavaFile(info.packageRoot)]);
     } else {
       beginComputePackageMap();
       PackageMapInfo packageMapInfo =
           _packageMapProvider.computePackageMap(folder);
       endComputePackageMap();
       info.packageMapDependencies = packageMapInfo.dependencies;
-      packageUriResolver =
-          new PackageMapUriResolver(resourceProvider, packageMapInfo.packageMap);
+      if (packageMapInfo.packageMap == null) {
+        return null;
+      }
+      return new PackageMapUriResolver(
+          resourceProvider,
+          packageMapInfo.packageMap);
       // TODO(paulberry): if any of the dependencies is outside of [folder],
       // we'll need to watch their parent folders as well.
     }
-    return packageUriResolver;
   }
 
   /**
@@ -660,7 +662,7 @@
   }
 
   /**
-   * Returns `true` if [resource] is excldued, as it is in one of the children.
+   * Returns `true` if [resource] is excluded, as it is in one of the children.
    */
   bool excludesResource(Resource resource) {
     return excludes(resource.path);
diff --git a/pkg/analysis_server/lib/src/domain_analysis.dart b/pkg/analysis_server/lib/src/domain_analysis.dart
index 100276f..01d1855 100644
--- a/pkg/analysis_server/lib/src/domain_analysis.dart
+++ b/pkg/analysis_server/lib/src/domain_analysis.dart
@@ -90,10 +90,18 @@
 
   /// Implement the `analysis.getLibraryDependencies` request.
   Response getLibraryDependencies(Request request) {
-    Set<String> libraries = new LibraryDependencyCollector(
-        server.getAnalysisContexts()).collectLibraryDependencies();
-    return new AnalysisGetLibraryDependenciesResult(
-        libraries.toList(growable: false)).toResponse(request.id);
+    server.onAnalysisComplete.then((_) {
+      LibraryDependencyCollector collector =
+          new LibraryDependencyCollector(server.getAnalysisContexts());
+      Set<String> libraries = collector.collectLibraryDependencies();
+      Map<String, Map<String, List<String>>> packageMap =
+          collector.calculatePackageMap(server.folderMap);
+      server.sendResponse(new AnalysisGetLibraryDependenciesResult(
+          libraries.toList(growable: false),
+          packageMap).toResponse(request.id));
+    });
+    // delay response
+    return Response.DELAYED_RESPONSE;
   }
 
   @override
diff --git a/pkg/analysis_server/lib/src/domain_completion.dart b/pkg/analysis_server/lib/src/domain_completion.dart
index e6a57b4..2c5f528 100644
--- a/pkg/analysis_server/lib/src/domain_completion.dart
+++ b/pkg/analysis_server/lib/src/domain_completion.dart
@@ -63,7 +63,7 @@
   /**
    * Performance for the last priority change event.
    */
-  CompletionPerformance priorityChangedPerformance;
+  CompletionPerformance computeCachePerformance;
 
   /**
    * Initialize a new request handler for the given [server].
@@ -136,23 +136,23 @@
    */
   void priorityChanged(PriorityChangeEvent event) {
     Source source = event.firstSource;
-    priorityChangedPerformance = new CompletionPerformance();
-    priorityChangedPerformance.source = source;
-    if (source != null) {
-      AnalysisContext context = server.getAnalysisContextForSource(source);
-      if (context != null) {
-        String computeTag = 'computeCache';
-        priorityChangedPerformance.logStartTime(computeTag);
-        CompletionManager manager = completionManagerFor(context, source);
-        manager.computeCache().then((bool success) {
-          priorityChangedPerformance.logElapseTime(computeTag);
-          priorityChangedPerformance.complete(
-              'priorityChanged caching: $success');
-        });
-        return;
-      }
+    CompletionPerformance performance = new CompletionPerformance();
+    computeCachePerformance = performance;
+    if (source == null) {
+      performance.complete('priorityChanged caching: no source');
+      return;
     }
-    priorityChangedPerformance.complete();
+    performance.source = source;
+    AnalysisContext context = server.getAnalysisContextForSource(source);
+    if (context != null) {
+      String computeTag = 'computeCache';
+      performance.logStartTime(computeTag);
+      CompletionManager manager = completionManagerFor(context, source);
+      manager.computeCache().then((bool success) {
+        performance.logElapseTime(computeTag);
+        performance.complete('priorityChanged caching: $success');
+      });
+    }
   }
 
   /**
@@ -204,10 +204,6 @@
   void recordRequest(CompletionPerformance performance, AnalysisContext context,
       Source source, int offset) {
     performance.source = source;
-    if (priorityChangedPerformance != null &&
-        priorityChangedPerformance.source != source) {
-      priorityChangedPerformance = null;
-    }
     if (performanceListMaxLength == 0 || context == null || source == null) {
       return;
     }
diff --git a/pkg/analysis_server/lib/src/edit/edit_domain.dart b/pkg/analysis_server/lib/src/edit/edit_domain.dart
index c611d3f..3061df4 100644
--- a/pkg/analysis_server/lib/src/edit/edit_domain.dart
+++ b/pkg/analysis_server/lib/src/edit/edit_domain.dart
@@ -53,7 +53,7 @@
    */
   EditDomainHandler(this.server) {
     searchEngine = server.searchEngine;
-    refactoringManager = new _RefactoringManager(server, searchEngine);
+    _newRefactoringManager();
   }
 
   Response format(Request request) {
@@ -73,14 +73,24 @@
     } catch (e) {
       return new Response.formatInvalidFile(request);
     }
+
     String unformattedSource = contents.data;
 
+    int start = params.selectionOffset;
+    int length = params.selectionLength;
+
+    // No need to preserve 0,0 selection
+    if (start == 0 && length == 0) {
+      start = null;
+      length = null;
+    }
+
     SourceCode code = new SourceCode(
         unformattedSource,
         uri: null,
         isCompilationUnit: true,
-        selectionStart: params.selectionOffset,
-        selectionLength: params.selectionLength);
+        selectionStart: start,
+        selectionLength: length);
     DartFormatter formatter = new DartFormatter();
     SourceCode formattedResult = formatter.formatSource(code);
     String formattedSource = formattedResult.text;
@@ -192,8 +202,7 @@
       } else if (requestName == EDIT_GET_FIXES) {
         return getFixes(request);
       } else if (requestName == EDIT_GET_REFACTORING) {
-        refactoringManager.getRefactoring(request);
-        return Response.DELAYED_RESPONSE;
+        return _getRefactoring(request);
       } else if (requestName == EDIT_SORT_MEMBERS) {
         return sortMembers(request);
       }
@@ -239,6 +248,22 @@
     SourceFileEdit fileEdit = new SourceFileEdit(file, fileStamp, edits: edits);
     return new EditSortMembersResult(fileEdit).toResponse(request.id);
   }
+
+  Response _getRefactoring(Request request) {
+    if (refactoringManager.hasPendingRequest) {
+      refactoringManager.cancel();
+      _newRefactoringManager();
+    }
+    refactoringManager.getRefactoring(request);
+    return Response.DELAYED_RESPONSE;
+  }
+
+  /**
+   * Initializes [refactoringManager] with a new instance.
+   */
+  void _newRefactoringManager() {
+    refactoringManager = new _RefactoringManager(server, searchEngine);
+  }
 }
 
 
@@ -259,6 +284,7 @@
 
   final AnalysisServer server;
   final SearchEngine searchEngine;
+  StreamSubscription onAnalysisStartedSubscription;
 
   RefactoringKind kind;
   String file;
@@ -270,14 +296,19 @@
   RefactoringStatus optionsStatus;
   RefactoringStatus finalStatus;
 
-  String requestId;
+  Request request;
   EditGetRefactoringResult result;
 
   _RefactoringManager(this.server, this.searchEngine) {
-    server.onAnalysisStarted.listen(_reset);
+    onAnalysisStartedSubscription = server.onAnalysisStarted.listen(_reset);
     _reset();
   }
 
+  /**
+   * Returns `true` if a response for the current request has not yet been sent.
+   */
+  bool get hasPendingRequest => request != null;
+
   bool get _hasFatalError {
     return initStatus.hasFatalError ||
         optionsStatus.hasFatalError ||
@@ -295,36 +326,49 @@
         refactoring is RenameRefactoring;
   }
 
-  void getRefactoring(Request request) {
+  /**
+   * Cancels processing of the current request and cleans up.
+   */
+  void cancel() {
+    onAnalysisStartedSubscription.cancel();
+    server.sendResponse(new Response.refactoringRequestCancelled(request));
+    request = null;
+  }
+
+  void getRefactoring(Request _request) {
     // prepare for processing the request
-    requestId = request.id;
+    request = _request;
     result = new EditGetRefactoringResult(
         EMPTY_PROBLEM_LIST,
         EMPTY_PROBLEM_LIST,
         EMPTY_PROBLEM_LIST);
     // process the request
-    var params = new EditGetRefactoringParams.fromRequest(request);
+    var params = new EditGetRefactoringParams.fromRequest(_request);
     runZoned(() async {
       await _init(params.kind, params.file, params.offset, params.length);
       if (initStatus.hasFatalError) {
         feedback = null;
-        return _sendResultResponse();
+        _sendResultResponse();
+        return;
       }
       // set options
       if (_requiresOptions) {
         if (params.options == null) {
           optionsStatus = new RefactoringStatus();
-          return _sendResultResponse();
+          _sendResultResponse();
+          return;
         }
         optionsStatus = _setOptions(params);
         if (_hasFatalError) {
-          return _sendResultResponse();
+          _sendResultResponse();
+          return;
         }
       }
       // done if just validation
       if (params.validateOnly) {
         finalStatus = new RefactoringStatus();
-        return _sendResultResponse();
+        _sendResultResponse();
+        return;
       }
       // simulate an exception
       if (test_simulateRefactoringException_final) {
@@ -333,7 +377,8 @@
       // validation and create change
       finalStatus = await refactoring.checkFinalConditions();
       if (_hasFatalError) {
-        return _sendResultResponse();
+        _sendResultResponse();
+        return;
       }
       // simulate an exception
       if (test_simulateRefactoringException_change) {
@@ -346,7 +391,7 @@
     }, onError: (exception, stackTrace) {
       server.instrumentationService.logException(exception, stackTrace);
       server.sendResponse(
-          new Response.serverError(request, exception, stackTrace));
+          new Response.serverError(_request, exception, stackTrace));
       _reset();
     });
   }
@@ -355,7 +400,7 @@
    * Initializes this context to perform a refactoring with the specified
    * parameters. The existing [Refactoring] is reused or created as needed.
    */
-  _init(RefactoringKind kind, String file,
+  Future _init(RefactoringKind kind, String file,
       int offset, int length) async {
     await server.onAnalysisComplete;
     // check if we can continue with the existing Refactoring instance
@@ -518,15 +563,20 @@
   }
 
   void _sendResultResponse() {
+    // ignore if was cancelled
+    if (request == null) {
+      return;
+    }
+    // set feedback
     result.feedback = feedback;
     // set problems
     result.initialProblems = initStatus.problems;
     result.optionsProblems = optionsStatus.problems;
     result.finalProblems = finalStatus.problems;
     // send the response
-    server.sendResponse(result.toResponse(requestId));
+    server.sendResponse(result.toResponse(request.id));
     // done with this request
-    requestId = null;
+    request = null;
     result = null;
   }
 
diff --git a/pkg/analysis_server/lib/src/generated_protocol.dart b/pkg/analysis_server/lib/src/generated_protocol.dart
index dec7e5e..a7b579f 100644
--- a/pkg/analysis_server/lib/src/generated_protocol.dart
+++ b/pkg/analysis_server/lib/src/generated_protocol.dart
@@ -735,6 +735,7 @@
  *
  * {
  *   "libraries": List<FilePath>
+ *   "packageMap": Map<String, Map<String, List<FilePath>>>
  * }
  */
 class AnalysisGetLibraryDependenciesResult implements HasToJson {
@@ -744,7 +745,13 @@
    */
   List<String> libraries;
 
-  AnalysisGetLibraryDependenciesResult(this.libraries);
+  /**
+   * A mapping from context source roots to package maps which map package
+   * names to source directories for use in client-side package URI resolution.
+   */
+  Map<String, Map<String, List<String>>> packageMap;
+
+  AnalysisGetLibraryDependenciesResult(this.libraries, this.packageMap);
 
   factory AnalysisGetLibraryDependenciesResult.fromJson(JsonDecoder jsonDecoder, String jsonPath, Object json) {
     if (json == null) {
@@ -757,7 +764,13 @@
       } else {
         throw jsonDecoder.missingKey(jsonPath, "libraries");
       }
-      return new AnalysisGetLibraryDependenciesResult(libraries);
+      Map<String, Map<String, List<String>>> packageMap;
+      if (json.containsKey("packageMap")) {
+        packageMap = jsonDecoder._decodeMap(jsonPath + ".packageMap", json["packageMap"], valueDecoder: (String jsonPath, Object json) => jsonDecoder._decodeMap(jsonPath, json, valueDecoder: (String jsonPath, Object json) => jsonDecoder._decodeList(jsonPath, json, jsonDecoder._decodeString)));
+      } else {
+        throw jsonDecoder.missingKey(jsonPath, "packageMap");
+      }
+      return new AnalysisGetLibraryDependenciesResult(libraries, packageMap);
     } else {
       throw jsonDecoder.mismatch(jsonPath, "analysis.getLibraryDependencies result");
     }
@@ -771,6 +784,7 @@
   Map<String, dynamic> toJson() {
     Map<String, dynamic> result = {};
     result["libraries"] = libraries;
+    result["packageMap"] = packageMap;
     return result;
   }
 
@@ -784,7 +798,8 @@
   @override
   bool operator==(other) {
     if (other is AnalysisGetLibraryDependenciesResult) {
-      return _listEqual(libraries, other.libraries, (String a, String b) => a == b);
+      return _listEqual(libraries, other.libraries, (String a, String b) => a == b) &&
+          _mapEqual(packageMap, other.packageMap, (Map<String, List<String>> a, Map<String, List<String>> b) => _mapEqual(a, b, (List<String> a, List<String> b) => _listEqual(a, b, (String a, String b) => a == b)));
     }
     return false;
   }
@@ -793,6 +808,7 @@
   int get hashCode {
     int hash = 0;
     hash = _JenkinsSmiHash.combine(hash, libraries.hashCode);
+    hash = _JenkinsSmiHash.combine(hash, packageMap.hashCode);
     return _JenkinsSmiHash.finish(hash);
   }
 }
@@ -3467,12 +3483,16 @@
   String file;
 
   /**
-   * The offset of the current selection in the file.
+   * The offset of the current selection in the file. In case preserving,
+   * selection information is not required, 0 can be specified for both
+   * selection offset and length.
    */
   int selectionOffset;
 
   /**
-   * The length of the current selection in the file.
+   * The length of the current selection in the file. In case preserving,
+   * selection information is not required, 0 can be specified for both
+   * selection offset and length.
    */
   int selectionLength;
 
@@ -9191,6 +9211,7 @@
  *   INVALID_OVERLAY_CHANGE
  *   INVALID_PARAMETER
  *   INVALID_REQUEST
+ *   REFACTORING_REQUEST_CANCELLED
  *   SERVER_ALREADY_STARTED
  *   SERVER_ERROR
  *   SORT_MEMBERS_INVALID_FILE
@@ -9238,6 +9259,11 @@
   static const INVALID_REQUEST = const RequestErrorCode._("INVALID_REQUEST");
 
   /**
+   * Another refactoring request was received during processing of this one.
+   */
+  static const REFACTORING_REQUEST_CANCELLED = const RequestErrorCode._("REFACTORING_REQUEST_CANCELLED");
+
+  /**
    * The analysis server has already been started (and hence won't accept new
    * connections).
    *
@@ -9292,7 +9318,7 @@
   /**
    * A list containing all of the enum values that are defined.
    */
-  static const List<RequestErrorCode> VALUES = const <RequestErrorCode>[CONTENT_MODIFIED, FORMAT_INVALID_FILE, GET_ERRORS_INVALID_FILE, INVALID_OVERLAY_CHANGE, INVALID_PARAMETER, INVALID_REQUEST, SERVER_ALREADY_STARTED, SERVER_ERROR, SORT_MEMBERS_INVALID_FILE, SORT_MEMBERS_PARSE_ERRORS, UNANALYZED_PRIORITY_FILES, UNKNOWN_REQUEST, UNSUPPORTED_FEATURE];
+  static const List<RequestErrorCode> VALUES = const <RequestErrorCode>[CONTENT_MODIFIED, FORMAT_INVALID_FILE, GET_ERRORS_INVALID_FILE, INVALID_OVERLAY_CHANGE, INVALID_PARAMETER, INVALID_REQUEST, REFACTORING_REQUEST_CANCELLED, SERVER_ALREADY_STARTED, SERVER_ERROR, SORT_MEMBERS_INVALID_FILE, SORT_MEMBERS_PARSE_ERRORS, UNANALYZED_PRIORITY_FILES, UNKNOWN_REQUEST, UNSUPPORTED_FEATURE];
 
   final String name;
 
@@ -9312,6 +9338,8 @@
         return INVALID_PARAMETER;
       case "INVALID_REQUEST":
         return INVALID_REQUEST;
+      case "REFACTORING_REQUEST_CANCELLED":
+        return REFACTORING_REQUEST_CANCELLED;
       case "SERVER_ALREADY_STARTED":
         return SERVER_ALREADY_STARTED;
       case "SERVER_ERROR":
diff --git a/pkg/analysis_server/lib/src/get_handler.dart b/pkg/analysis_server/lib/src/get_handler.dart
index 0aabb73..2e2cb3e 100644
--- a/pkg/analysis_server/lib/src/get_handler.dart
+++ b/pkg/analysis_server/lib/src/get_handler.dart
@@ -4,6 +4,7 @@
 
 library analysis_server.src.get_handler;
 
+import 'dart:async';
 import 'dart:collection';
 import 'dart:convert';
 import 'dart:io';
@@ -16,6 +17,9 @@
 import 'package:analysis_server/src/operation/operation_analysis.dart';
 import 'package:analysis_server/src/operation/operation_queue.dart';
 import 'package:analysis_server/src/protocol.dart' hide Element;
+import 'package:analysis_server/src/services/index/index.dart';
+import 'package:analysis_server/src/services/index/local_index.dart';
+import 'package:analysis_server/src/services/index/store/split_store.dart';
 import 'package:analysis_server/src/socket_server.dart';
 import 'package:analysis_server/src/status/ast_writer.dart';
 import 'package:analysis_server/src/status/element_writer.dart';
@@ -77,6 +81,11 @@
   static const String ELEMENT_PATH = '/element';
 
   /**
+   * The path used to request information about elements with the given name.
+   */
+  static const String INDEX_ELEMENT_BY_NAME = '/index/element-by-name';
+
+  /**
    * The path used to request an overlay contents.
    */
   static const String OVERLAY_PATH = '/overlay';
@@ -87,6 +96,11 @@
   static const String OVERLAYS_PATH = '/overlays';
 
   /**
+   * The path used to request overall performance information.
+   */
+  static const String PERFORMANCE_PATH = '/performance';
+
+  /**
    * Query parameter used to represent the cache state to search for, when
    * accessing [CACHE_STATE_PATH].
    */
@@ -110,6 +124,12 @@
   static const String ID_PARAM = 'id';
 
   /**
+   * Query parameter used to represent the name of elements to search for, when
+   * accessing [INDEX_ELEMENT_BY_NAME].
+   */
+  static const String INDEX_ELEMENT_NAME = 'name';
+
+  /**
    * Query parameter used to represent the source to search for, when accessing
    * [CACHE_ENTRY_PATH].
    */
@@ -172,10 +192,14 @@
       _returnContextInfo(request);
     } else if (path == ELEMENT_PATH) {
       _returnElement(request);
+    } else if (path == INDEX_ELEMENT_BY_NAME) {
+      _returnIndexElementByName(request);
     } else if (path == OVERLAY_PATH) {
       _returnOverlayContents(request);
     } else if (path == OVERLAYS_PATH) {
       _returnOverlaysInfo(request);
+    } else if (path == PERFORMANCE_PATH) {
+      _returnPerformance(request);
     } else {
       _returnUnknownRequest(request);
     }
@@ -282,7 +306,14 @@
           buffer.write('<p>null</p>');
           return;
         }
-        ast.accept(new AstWriter(buffer));
+        AstWriter writer = new AstWriter(buffer);
+        ast.accept(writer);
+        if (writer.exceptions.isNotEmpty) {
+          buffer.write('<h3>Exceptions while creating page</h3>');
+          for (CaughtException exception in writer.exceptions) {
+            _writeException(buffer, exception);
+          }
+        }
       });
     });
   }
@@ -315,7 +346,8 @@
 
     List<Folder> allContexts = <Folder>[];
     Map<Folder, SourceEntry> entryMap = new HashMap<Folder, SourceEntry>();
-    analysisServer.folderMap.forEach((Folder folder, AnalysisContextImpl context) {
+    analysisServer.folderMap.forEach(
+        (Folder folder, AnalysisContextImpl context) {
       Source source = context.sourceFactory.forUri(sourceUri);
       if (source != null) {
         SourceEntry entry = context.getReadableSourceEntryOrNull(source);
@@ -325,7 +357,9 @@
         }
       }
     });
-    allContexts.sort((Folder firstFolder, Folder secondFolder) => firstFolder.path.compareTo(secondFolder.path));
+    allContexts.sort(
+        (Folder firstFolder, Folder secondFolder) =>
+            firstFolder.path.compareTo(secondFolder.path));
     AnalysisContextImpl context = analysisServer.folderMap[folder];
 
     _writeResponse(request, (StringBuffer buffer) {
@@ -342,7 +376,8 @@
           } else {
             buffer.write('<br>');
           }
-          AnalysisContextImpl analyzingContext = analysisServer.folderMap[folder];
+          AnalysisContextImpl analyzingContext =
+              analysisServer.folderMap[folder];
           if (analyzingContext == context) {
             buffer.write(folder.path);
           } else {
@@ -483,7 +518,11 @@
     String value = request.requestedUri.queryParameters['index'];
     int index = value != null ? int.parse(value, onError: (_) => 0) : 0;
     _writeResponse(request, (StringBuffer buffer) {
-      _writePage(buffer, 'Analysis Server - Completion Stats', [], (StringBuffer buffer) {
+      _writePage(
+          buffer,
+          'Analysis Server - Completion Stats',
+          [],
+          (StringBuffer buffer) {
         _writeCompletionPerformanceDetail(buffer, index);
         _writeCompletionPerformanceList(buffer);
       });
@@ -680,6 +719,55 @@
     });
   }
 
+  /**
+   * Return a response containing information about elements with the given
+   * name.
+   */
+  Future _returnIndexElementByName(HttpRequest request) async {
+    AnalysisServer analysisServer = _server.analysisServer;
+    if (analysisServer == null) {
+      return _returnFailure(request, 'Analysis server not running');
+    }
+    Index index = analysisServer.index;
+    String name = request.uri.queryParameters[INDEX_ELEMENT_NAME];
+    if (name == null) {
+      return _returnFailure(
+          request,
+          'Query parameter $INDEX_ELEMENT_NAME required');
+    }
+    if (index is LocalIndex) {
+      Map<List<String>, List<InspectLocation>> relations =
+          await index.findElementsByName(name);
+      _writeResponse(request, (StringBuffer buffer) {
+        _writePage(
+            buffer,
+            'Analysis Server - Index Elements',
+            ['Name: $name'],
+            (StringBuffer buffer) {
+          buffer.write('<table border="1">');
+          _writeRow(
+              buffer,
+              ['Element', 'Relationship', 'Location'],
+              header: true);
+          relations.forEach(
+              (List<String> elementPath, List<InspectLocation> relations) {
+            String elementLocation = elementPath.join(' ');
+            relations.forEach((InspectLocation location) {
+              var relString = location.relationship.identifier;
+              var locString =
+                  '${location.path} offset=${location.offset} '
+                      'length=${location.length} flags=${location.flags}';
+              _writeRow(buffer, [elementLocation, relString, locString]);
+            });
+          });
+          buffer.write('</table>');
+        });
+      });
+    } else {
+      return _returnFailure(request, 'LocalIndex expected, but $index found.');
+    }
+  }
+
   void _returnOverlayContents(HttpRequest request) {
     String idString = request.requestedUri.queryParameters[ID_PARAM];
     if (idString == null) {
@@ -738,6 +826,91 @@
   }
 
   /**
+   * Return a response displaying overall performance information.
+   */
+  void _returnPerformance(HttpRequest request) {
+    AnalysisServer analysisServer = _server.analysisServer;
+    if (analysisServer == null) {
+      return _returnFailure(request, 'Analysis server is not running');
+    }
+    _writeResponse(request, (StringBuffer buffer) {
+      _writePage(
+          buffer,
+          'Analysis Server - Performance',
+          [],
+          (StringBuffer buffer) {
+        buffer.write('<h3>Communication Performance</h3>');
+        _writeTwoColumns(buffer, (StringBuffer buffer) {
+          ServerPerformance perf = analysisServer.performanceDuringStartup;
+          int requestCount = perf.requestCount;
+          num averageLatency =
+              requestCount > 0 ? (perf.requestLatency / requestCount).round() : 0;
+          int maximumLatency = perf.maxLatency;
+          num slowRequestPercent =
+              requestCount > 0 ? (perf.slowRequestCount * 100 / requestCount).round() : 0;
+          buffer.write('<h4>Startup</h4>');
+          buffer.write('<table>');
+          _writeRow(
+              buffer,
+              [requestCount, 'requests'],
+              classes: ["right", null]);
+          _writeRow(
+              buffer,
+              [averageLatency, 'ms average latency'],
+              classes: ["right", null]);
+          _writeRow(
+              buffer,
+              [maximumLatency, 'ms maximum latency'],
+              classes: ["right", null]);
+          _writeRow(
+              buffer,
+              [slowRequestPercent, '% > 150 ms latency'],
+              classes: ["right", null]);
+          if (analysisServer.performanceAfterStartup != null) {
+            int startupTime =
+                analysisServer.performanceAfterStartup.startTime -
+                perf.startTime;
+            _writeRow(
+                buffer,
+                [startupTime, 'ms for initial analysis to complete']);
+          }
+          buffer.write('</table>');
+        }, (StringBuffer buffer) {
+          ServerPerformance perf = analysisServer.performanceAfterStartup;
+          if (perf == null) {
+            return;
+          }
+          int requestCount = perf.requestCount;
+          num averageLatency =
+              requestCount > 0 ? (perf.requestLatency * 10 / requestCount).round() / 10 : 0;
+          int maximumLatency = perf.maxLatency;
+          num slowRequestPercent =
+              requestCount > 0 ? (perf.slowRequestCount * 100 / requestCount).round() : 0;
+          buffer.write('<h4>Current</h4>');
+          buffer.write('<table>');
+          _writeRow(
+              buffer,
+              [requestCount, 'requests'],
+              classes: ["right", null]);
+          _writeRow(
+              buffer,
+              [averageLatency, 'ms average latency'],
+              classes: ["right", null]);
+          _writeRow(
+              buffer,
+              [maximumLatency, 'ms maximum latency'],
+              classes: ["right", null]);
+          _writeRow(
+              buffer,
+              [slowRequestPercent, '% > 150 ms latency'],
+              classes: ["right", null]);
+          buffer.write('</table>');
+        });
+      });
+    });
+  }
+
+  /**
    * Return a response indicating the status of the analysis server.
    */
   void _returnServerStatus(HttpRequest request) {
@@ -758,23 +931,20 @@
    * server.
    */
   void _returnUnknownRequest(HttpRequest request) {
-    HttpResponse response = request.response;
-    response.statusCode = HttpStatus.NOT_FOUND;
-    response.headers.contentType = _htmlContent;
-    response.write('<html>');
-    response.write('<head>');
-    response.write('<title>Dart Analysis Server - Page Not Found</title>');
-    response.write('</head>');
-    response.write('<body>');
-    response.write('<h1>Page Not Found</h1>');
-    response.write('<p>Try one of these links instead:</p>');
-    response.write('<ul>');
-    response.write('<li><a href="$STATUS_PATH">Server Status</a></li>');
-    response.write('<li><a href="$COMPLETION_PATH">Completion Stats</a></li>');
-    response.write('<ul>');
-    response.write('</body>');
-    response.write('</html>');
-    response.close();
+    _writeResponse(request, (StringBuffer buffer) {
+      _writePage(buffer, 'Analysis Server', [], (StringBuffer buffer) {
+        buffer.write('<h3>Pages</h3>');
+        buffer.write('<p>');
+        buffer.write(_makeLink(COMPLETION_PATH, {}, 'Completion data'));
+        buffer.write('</p>');
+        buffer.write('<p>');
+        buffer.write(_makeLink(PERFORMANCE_PATH, {}, 'Performance'));
+        buffer.write('</p>');
+        buffer.write('<p>');
+        buffer.write(_makeLink(STATUS_PATH, {}, 'Server status'));
+        buffer.write('</p>');
+      });
+    });
   }
 
   /**
@@ -886,28 +1056,24 @@
       buffer.write('<p>No completions yet</p>');
       return;
     }
-    buffer.write(
-        '<h3>Completion Performance Detail - ${performance.startTimeAndMs}</h3>');
+    buffer.write('<h3>Completion Performance Detail</h3>');
+    buffer.write('<p>${performance.startTimeAndMs} for ${performance.source}');
     buffer.write('<table>');
     _writeRow(buffer, ['Elapsed', '', 'Operation'], header: true);
     performance.operations.forEach((OperationPerformance op) {
       String elapsed = op.elapsed != null ? op.elapsed.toString() : '???';
       _writeRow(buffer, [elapsed, '&nbsp;&nbsp;', op.name]);
     });
-    if (handler.priorityChangedPerformance == null) {
-      buffer.write('<p>No priorityChanged caching</p>');
-    } else {
-      int len = handler.priorityChangedPerformance.operations.length;
-      if (len > 0) {
-        var op = handler.priorityChangedPerformance.operations[len - 1];
-        if (op != null) {
-          _writeRow(buffer, ['&nbsp;', '&nbsp;', '&nbsp;']);
-          String elapsed = op.elapsed != null ? op.elapsed.toString() : '???';
-          _writeRow(buffer, [elapsed, '&nbsp;&nbsp;', op.name]);
-        }
-      }
-    }
     buffer.write('</table>');
+    buffer.write('<p><b>Compute Cache Performance</b>: ');
+    if (handler.computeCachePerformance == null) {
+      buffer.write('none');
+    } else {
+      int elapsed = handler.computeCachePerformance.elapsedInMilliseconds;
+      Source source = handler.computeCachePerformance.source;
+      buffer.write(' $elapsed ms for $source');
+    }
+    buffer.write('</p>');
   }
 
   /**
@@ -916,7 +1082,7 @@
    */
   void _writeCompletionPerformanceList(StringBuffer buffer) {
     CompletionDomainHandler handler = _completionDomainHandler;
-    buffer.write('<h3>Completion Performance</h3>');
+    buffer.write('<h3>Completion Performance List</h3>');
     if (handler == null) {
       return;
     }
@@ -957,7 +1123,7 @@
               HTML_ESCAPE.convert(performance.snippet)]);
       ++index;
     }
-    ;
+
     buffer.write('</table>');
     buffer.write('''
       <p><strong>First (ms)</strong> - the number of milliseconds
@@ -1194,8 +1360,8 @@
    * one cell for each of the [columns], and will be a header row if [header] is
    * `true`.
    */
-  void _writeRow(StringBuffer buffer, List<Object> columns, {bool header:
-      false, List<String> classes}) {
+  void _writeRow(StringBuffer buffer, List<Object> columns, {bool header: false,
+      List<String> classes}) {
     buffer.write('<tr>');
     int count = columns.length;
     int maxClassIndex = classes == null ? 0 : classes.length - 1;
@@ -1248,6 +1414,12 @@
       buffer.write('Version: ');
       buffer.write(AnalysisServer.VERSION);
       buffer.write('</p>');
+
+      buffer.write('<p><b>Performance Data</b></p>');
+      buffer.write('<p>');
+      buffer.write(
+          _makeLink(PERFORMANCE_PATH, {}, 'Communication performance'));
+      buffer.write('</p>');
     }, (StringBuffer buffer) {
       _writeSubscriptionList(buffer, ServerService.VALUES, services);
     });
diff --git a/pkg/analysis_server/lib/src/operation/operation_analysis.dart b/pkg/analysis_server/lib/src/operation/operation_analysis.dart
index 8ea73ae..07a4fdc 100644
--- a/pkg/analysis_server/lib/src/operation/operation_analysis.dart
+++ b/pkg/analysis_server/lib/src/operation/operation_analysis.dart
@@ -173,6 +173,16 @@
       ChangeNotice notice = notices[i];
       Source source = notice.source;
       String file = source.fullName;
+      // Only send notifications if the current context is the preferred
+      // context for the file.  This avoids redundant notification messages
+      // being sent to the client (see dartbug.com/22210).
+      // TODO(paulberry): note that there is a small risk that this will cause
+      // notifications to be lost if the preferred context for a file changes
+      // while analysis is in progress (e.g. because the client sent an
+      // analysis.setAnalysisRoots message).
+      if (server.getAnalysisContext(file) != context) {
+        continue;
+      }
       // Dart
       CompilationUnit parsedDartUnit = notice.parsedDartUnit;
       CompilationUnit resolvedDartUnit = notice.resolvedDartUnit;
diff --git a/pkg/analysis_server/lib/src/protocol.dart b/pkg/analysis_server/lib/src/protocol.dart
index 1161df1..dfa810cd 100644
--- a/pkg/analysis_server/lib/src/protocol.dart
+++ b/pkg/analysis_server/lib/src/protocol.dart
@@ -810,6 +810,17 @@
 
   /**
    * Initialize a newly created instance to represent the
+   * REFACTORING_REQUEST_CANCELLED error condition.
+   */
+  Response.refactoringRequestCancelled(Request request)
+      : this(
+          request.id,
+          error: new RequestError(
+              RequestErrorCode.REFACTORING_REQUEST_CANCELLED,
+              'The `edit.getRefactoring` request was cancelled.'));
+
+  /**
+   * Initialize a newly created instance to represent the
    * SORT_MEMBERS_PARSE_ERRORS error condition.
    */
   Response.sortMembersParseErrors(Request request, int numErrors)
diff --git a/pkg/analysis_server/lib/src/search/search_domain.dart b/pkg/analysis_server/lib/src/search/search_domain.dart
index c0f8fe0..01fd53e 100644
--- a/pkg/analysis_server/lib/src/search/search_domain.dart
+++ b/pkg/analysis_server/lib/src/search/search_domain.dart
@@ -4,6 +4,8 @@
 
 library search.domain;
 
+import 'dart:async';
+
 import 'package:analysis_server/src/analysis_server.dart';
 import 'package:analysis_server/src/constants.dart';
 import 'package:analysis_server/src/protocol_server.dart' as protocol;
@@ -39,9 +41,10 @@
     searchEngine = server.searchEngine;
   }
 
-  protocol.Response findElementReferences(protocol.Request request) {
+  Future findElementReferences(protocol.Request request) async {
     var params =
         new protocol.SearchFindElementReferencesParams.fromRequest(request);
+    await server.onAnalysisComplete;
     // prepare elements
     List<Element> elements =
         server.getElementsAtOffset(params.file, params.offset);
@@ -59,15 +62,14 @@
     }).where((Element element) {
       return element != null;
     }).toList();
-    // schedule search
+    // search
     String searchId = (_nextSearchId++).toString();
-    elements.forEach((Element element) {
+    elements.forEach((Element element) async {
       var computer = new ElementReferencesComputer(searchEngine);
-      var future = computer.compute(element, params.includePotential);
-      future.then((List<protocol.SearchResult> results) {
-        bool isLast = identical(element, elements.last);
-        _sendSearchNotification(searchId, isLast, results);
-      });
+      List<protocol.SearchResult> results =
+          await computer.compute(element, params.includePotential);
+      bool isLast = identical(element, elements.last);
+      _sendSearchNotification(searchId, isLast, results);
     });
     // respond
     var result = new protocol.SearchFindElementReferencesResult();
@@ -75,82 +77,76 @@
       result.id = searchId;
       result.element = protocol.newElement_fromEngine(elements[0]);
     }
-    return result.toResponse(request.id);
+    _sendSearchResult(request, result);
   }
 
-  protocol.Response findMemberDeclarations(protocol.Request request) {
+  Future findMemberDeclarations(protocol.Request request) async {
     var params =
         new protocol.SearchFindMemberDeclarationsParams.fromRequest(request);
-    // schedule search
-    String searchId = (_nextSearchId++).toString();
-    {
-      var matchesFuture = searchEngine.searchMemberDeclarations(params.name);
-      matchesFuture.then((List<SearchMatch> matches) {
-        _sendSearchNotification(searchId, true, matches.map(toResult));
-      });
-    }
+    await server.onAnalysisComplete;
     // respond
-    return new protocol.SearchFindMemberDeclarationsResult(
-        searchId).toResponse(request.id);
+    String searchId = (_nextSearchId++).toString();
+    _sendSearchResult(
+        request,
+        new protocol.SearchFindMemberDeclarationsResult(searchId));
+    // search
+    List<SearchMatch> matches =
+        await searchEngine.searchMemberDeclarations(params.name);
+    _sendSearchNotification(searchId, true, matches.map(toResult));
   }
 
-  protocol.Response findMemberReferences(protocol.Request request) {
+  Future findMemberReferences(protocol.Request request) async {
     var params =
         new protocol.SearchFindMemberReferencesParams.fromRequest(request);
-    // schedule search
-    String searchId = (_nextSearchId++).toString();
-    {
-      var matchesFuture = searchEngine.searchMemberReferences(params.name);
-      matchesFuture.then((List<SearchMatch> matches) {
-        _sendSearchNotification(searchId, true, matches.map(toResult));
-      });
-    }
+    await server.onAnalysisComplete;
     // respond
-    return new protocol.SearchFindMemberReferencesResult(
-        searchId).toResponse(request.id);
+    String searchId = (_nextSearchId++).toString();
+    _sendSearchResult(
+        request,
+        new protocol.SearchFindMemberReferencesResult(searchId));
+    // search
+    List<SearchMatch> matches =
+        await searchEngine.searchMemberReferences(params.name);
+    _sendSearchNotification(searchId, true, matches.map(toResult));
   }
 
-  protocol.Response findTopLevelDeclarations(protocol.Request request) {
+  Future findTopLevelDeclarations(protocol.Request request) async {
     var params =
         new protocol.SearchFindTopLevelDeclarationsParams.fromRequest(request);
-    // schedule search
-    String searchId = (_nextSearchId++).toString();
-    {
-      var matchesFuture =
-          searchEngine.searchTopLevelDeclarations(params.pattern);
-      matchesFuture.then((List<SearchMatch> matches) {
-        _sendSearchNotification(searchId, true, matches.map(toResult));
-      });
-    }
+    await server.onAnalysisComplete;
     // respond
-    return new protocol.SearchFindTopLevelDeclarationsResult(
-        searchId).toResponse(request.id);
+    String searchId = (_nextSearchId++).toString();
+    _sendSearchResult(
+        request,
+        new protocol.SearchFindTopLevelDeclarationsResult(searchId));
+    // search
+    List<SearchMatch> matches =
+        await searchEngine.searchTopLevelDeclarations(params.pattern);
+    _sendSearchNotification(searchId, true, matches.map(toResult));
   }
 
   /**
    * Implement the `search.getTypeHierarchy` request.
    */
-  protocol.Response getTypeHierarchy(protocol.Request request) {
+  Future getTypeHierarchy(protocol.Request request) async {
     var params = new protocol.SearchGetTypeHierarchyParams.fromRequest(request);
-    // prepare parameters
-    // prepare Element
+    await server.onAnalysisComplete;
+    // prepare element
     List<Element> elements =
         server.getElementsAtOffset(params.file, params.offset);
     if (elements.isEmpty) {
       protocol.Response response =
           new protocol.SearchGetTypeHierarchyResult().toResponse(request.id);
-      return response;
+      server.sendResponse(response);
+      return;
     }
     Element element = elements.first;
     // prepare type hierarchy
     TypeHierarchyComputer computer = new TypeHierarchyComputer(searchEngine);
-    computer.compute(element).then((List<protocol.TypeHierarchyItem> items) {
-      protocol.Response response = new protocol.SearchGetTypeHierarchyResult(
-          hierarchyItems: items).toResponse(request.id);
-      server.sendResponse(response);
-    });
-    // delay response
-    return protocol.Response.DELAYED_RESPONSE;
+    List<protocol.TypeHierarchyItem> items = await computer.compute(element);
+    protocol.Response response = new protocol.SearchGetTypeHierarchyResult(
+        hierarchyItems: items).toResponse(request.id);
+    server.sendResponse(response);
   }
 
   @override
@@ -158,15 +154,20 @@
     try {
       String requestName = request.method;
       if (requestName == SEARCH_FIND_ELEMENT_REFERENCES) {
-        return findElementReferences(request);
+        findElementReferences(request);
+        return protocol.Response.DELAYED_RESPONSE;
       } else if (requestName == SEARCH_FIND_MEMBER_DECLARATIONS) {
-        return findMemberDeclarations(request);
+        findMemberDeclarations(request);
+        return protocol.Response.DELAYED_RESPONSE;
       } else if (requestName == SEARCH_FIND_MEMBER_REFERENCES) {
-        return findMemberReferences(request);
+        findMemberReferences(request);
+        return protocol.Response.DELAYED_RESPONSE;
       } else if (requestName == SEARCH_FIND_TOP_LEVEL_DECLARATIONS) {
-        return findTopLevelDeclarations(request);
+        findTopLevelDeclarations(request);
+        return protocol.Response.DELAYED_RESPONSE;
       } else if (requestName == SEARCH_GET_TYPE_HIERARCHY) {
-        return getTypeHierarchy(request);
+        getTypeHierarchy(request);
+        return protocol.Response.DELAYED_RESPONSE;
       }
     } on protocol.RequestFailure catch (exception) {
       return exception.response;
@@ -183,6 +184,14 @@
             isLast).toNotification());
   }
 
+  /**
+   * Send a search response with the given [result] to the given [request].
+   */
+  void _sendSearchResult(protocol.Request request, result) {
+    protocol.Response response = result.toResponse(request.id);
+    server.sendResponse(response);
+  }
+
   static protocol.SearchResult toResult(SearchMatch match) {
     return protocol.newSearchResult_fromMatch(match);
   }
diff --git a/pkg/analysis_server/lib/src/server/driver.dart b/pkg/analysis_server/lib/src/server/driver.dart
index 898aa4f..f161c54 100644
--- a/pkg/analysis_server/lib/src/server/driver.dart
+++ b/pkg/analysis_server/lib/src/server/driver.dart
@@ -111,7 +111,7 @@
    * The name of the option used to specify if [print] should print to the
    * console instead of being intercepted.
    */
-  static const String INTERNAL_DELAY_FREQUENCY = 'internal-delay-freqency';
+  static const String INTERNAL_DELAY_FREQUENCY = 'internal-delay-frequency';
 
   /**
    * The name of the option used to specify the port to which the server will
diff --git a/pkg/analysis_server/lib/src/services/completion/dart_completion_manager.dart b/pkg/analysis_server/lib/src/services/completion/dart_completion_manager.dart
index 65e3a46..44eacd6 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart_completion_manager.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart_completion_manager.dart
@@ -21,6 +21,7 @@
 import 'package:analyzer/src/generated/ast.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/generated/scanner.dart';
 
 // TODO (danrubel) these are temporary constants as we transition completion
 // relevance from CompletionRelevance.LOW/DEFAULT/HIGH to int.
@@ -61,15 +62,18 @@
   List<DartCompletionComputer> computers;
 
   DartCompletionManager(AnalysisContext context, this.searchEngine,
-      Source source, this.cache)
-      : super(context, source),
-        computers = [
+      Source source, this.cache, [this.computers])
+      : super(context, source) {
+    if (computers == null) {
+      computers = [
           new KeywordComputer(),
           new LocalComputer(),
           new ArgListComputer(),
           new CombinatorComputer(),
           new ImportedComputer(),
           new InvocationComputer()];
+    }
+  }
 
   /**
    * Create a new initialized Dart source completion manager
@@ -104,8 +108,19 @@
       CompilationUnit unit = context.parseCompilationUnit(source);
       request.unit = unit;
       request.node = new NodeLocator.con1(request.offset).searchWithin(unit);
-      request.node.accept(new _ReplacementOffsetBuilder(request));
       request.target = new CompletionTarget.forOffset(unit, request.offset);
+
+      request.replacementOffset = request.offset;
+      request.replacementLength = 0;
+      var entity = request.target.entity;
+      Token token = entity is AstNode ? entity.beginToken : entity;
+      if (token != null &&
+          token.offset <= request.offset &&
+          (token.type == TokenType.KEYWORD || token.type == TokenType.IDENTIFIER)) {
+        request.replacementOffset = token.offset;
+        request.replacementLength = token.length;
+      }
+
       List<DartCompletionComputer> todo = new List.from(computers);
       todo.removeWhere((DartCompletionComputer c) {
         return request.performance.logElapseTime(
@@ -122,11 +137,12 @@
   /**
    * If there is remaining work to be done, then wait for the unit to be
    * resolved and request that each remaining computer finish their work.
+   * Return a [Future] that completes when the last notification has been sent.
    */
-  void computeFull(DartCompletionRequest request,
+  Future computeFull(DartCompletionRequest request,
       List<DartCompletionComputer> todo) {
     request.performance.logStartTime('waitForAnalysis');
-    waitForAnalysis().then((CompilationUnit unit) {
+    return waitForAnalysis().then((CompilationUnit unit) {
       if (controller.isClosed) {
         return;
       }
@@ -181,7 +197,7 @@
    * Send the current list of suggestions to the client.
    */
   void sendResults(DartCompletionRequest request, bool last) {
-    if (controller.isClosed) {
+    if (controller == null || controller.isClosed) {
       return;
     }
     controller.add(
@@ -315,21 +331,3 @@
     return _optype;
   }
 }
-
-/**
- * Visitor used to determine the replacement offset and length
- * based upon the cursor location.
- */
-class _ReplacementOffsetBuilder extends SimpleAstVisitor {
-  final DartCompletionRequest request;
-
-  _ReplacementOffsetBuilder(this.request) {
-    request.replacementOffset = request.offset;
-    request.replacementLength = 0;
-  }
-
-  visitSimpleIdentifier(SimpleIdentifier node) {
-    request.replacementOffset = node.offset;
-    request.replacementLength = node.length;
-  }
-}
diff --git a/pkg/analysis_server/lib/src/services/completion/keyword_computer.dart b/pkg/analysis_server/lib/src/services/completion/keyword_computer.dart
index 0d85a50..a222062 100644
--- a/pkg/analysis_server/lib/src/services/completion/keyword_computer.dart
+++ b/pkg/analysis_server/lib/src/services/completion/keyword_computer.dart
@@ -35,39 +35,44 @@
 class _KeywordVisitor extends GeneralizingAstVisitor {
   final DartCompletionRequest request;
 
+  /**
+   * The identifier visited or `null` if not visited.
+   */
+  SimpleIdentifier identifier;
+
   _KeywordVisitor(this.request);
 
   @override
   visitBlock(Block node) {
-    if (_isOffsetAfterNode(node)) {
-      node.parent.accept(this);
-    } else {
-      _addSuggestions(
-          [
-              Keyword.ASSERT,
-              Keyword.CASE,
-              Keyword.CONTINUE,
-              Keyword.DO,
-              Keyword.FACTORY,
-              Keyword.FINAL,
-              Keyword.FOR,
-              Keyword.IF,
-              Keyword.NEW,
-              Keyword.RETHROW,
-              Keyword.RETURN,
-              Keyword.SUPER,
-              Keyword.SWITCH,
-              Keyword.THIS,
-              Keyword.THROW,
-              Keyword.TRY,
-              Keyword.VAR,
-              Keyword.VOID,
-              Keyword.WHILE]);
-    }
+    _addSuggestions(
+        [
+            Keyword.ASSERT,
+            Keyword.CASE,
+            Keyword.CONTINUE,
+            Keyword.DO,
+            Keyword.FACTORY,
+            Keyword.FINAL,
+            Keyword.FOR,
+            Keyword.IF,
+            Keyword.NEW,
+            Keyword.RETHROW,
+            Keyword.RETURN,
+            Keyword.SUPER,
+            Keyword.SWITCH,
+            Keyword.THIS,
+            Keyword.THROW,
+            Keyword.TRY,
+            Keyword.VAR,
+            Keyword.VOID,
+            Keyword.WHILE]);
   }
 
   @override
   visitClassDeclaration(ClassDeclaration node) {
+    // Don't suggest class name
+    if (node.name == identifier) {
+      return;
+    }
     // Inside the class declaration { }
     if (request.offset > node.leftBracket.offset) {
       _addSuggestions(
@@ -84,16 +89,7 @@
               Keyword.VOID]);
       return;
     }
-    // Very simplistic suggestion because analyzer will warn if
-    // the extends / with / implements keywords are out of order
-    if (node.extendsClause == null) {
-      _addSuggestion(Keyword.EXTENDS, COMPLETION_RELEVANCE_HIGH);
-    } else if (node.withClause == null) {
-      _addSuggestion(Keyword.WITH, COMPLETION_RELEVANCE_HIGH);
-    }
-    if (node.implementsClause == null) {
-      _addSuggestion(Keyword.IMPLEMENTS, COMPLETION_RELEVANCE_HIGH);
-    }
+    _addClassDeclarationKeywords(node);
   }
 
   @override
@@ -154,19 +150,55 @@
   }
 
   visitSimpleIdentifier(SimpleIdentifier node) {
-    AstNode parent = node.getAncestor((n) => n is TopLevelVariableDeclaration);
-    if (parent is TopLevelVariableDeclaration) {
-      if (parent.variables != null &&
-          parent.variables.type != null &&
-          parent.variables.type.name == node) {
-        AstNode unit = node.getAncestor((n) => n is CompilationUnit);
-        if (unit is CompilationUnit) {
-          visitCompilationUnit(unit);
+    identifier = node;
+    node.parent.accept(this);
+  }
+
+  void visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
+    if (identifier != null && node.beginToken == identifier.beginToken) {
+      AstNode unit = node.parent;
+      if (unit is CompilationUnit) {
+        CompilationUnitMember previous;
+        for (CompilationUnitMember member in unit.declarations) {
+          if (member == node && previous is ClassDeclaration) {
+            if (previous.endToken.isSynthetic) {
+              // Partial keywords (simple identifirs) that are part of a
+              // class declaration can be parsed
+              // as a TypeName in a TopLevelVariableDeclaration
+              _addClassDeclarationKeywords(previous);
+              return;
+            }
+          }
+          previous = member;
         }
+        // Partial keywords (simple identifiers) can be parsed
+        // as a TypeName in a TopLevelVariableDeclaration
+        unit.accept(this);
       }
     }
   }
 
+  void visitTypeName(TypeName node) {
+    node.parent.accept(this);
+  }
+
+  void visitVariableDeclarationList(VariableDeclarationList node) {
+    node.parent.accept(this);
+  }
+
+  void _addClassDeclarationKeywords(ClassDeclaration node) {
+    // Very simplistic suggestion because analyzer will warn if
+    // the extends / with / implements keywords are out of order
+    if (node.extendsClause == null) {
+      _addSuggestion(Keyword.EXTENDS, COMPLETION_RELEVANCE_HIGH);
+    } else if (node.withClause == null) {
+      _addSuggestion(Keyword.WITH, COMPLETION_RELEVANCE_HIGH);
+    }
+    if (node.implementsClause == null) {
+      _addSuggestion(Keyword.IMPLEMENTS, COMPLETION_RELEVANCE_HIGH);
+    }
+  }
+
   void _addSuggestion(Keyword keyword, [int relevance =
       COMPLETION_RELEVANCE_DEFAULT]) {
     String completion = keyword.syntax;
diff --git a/pkg/analysis_server/lib/src/services/dependencies/library_dependencies.dart b/pkg/analysis_server/lib/src/services/dependencies/library_dependencies.dart
index 95299b1..a482435 100644
--- a/pkg/analysis_server/lib/src/services/dependencies/library_dependencies.dart
+++ b/pkg/analysis_server/lib/src/services/dependencies/library_dependencies.dart
@@ -4,9 +4,11 @@
 
 library services.dependencies.library;
 
+import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/src/generated/element.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/generated/source_io.dart';
 
 class LibraryDependencyCollector {
 
@@ -17,6 +19,24 @@
 
   LibraryDependencyCollector(this._contexts);
 
+  Map<String, Map<String, List<String>>> calculatePackageMap(Map<Folder,
+      AnalysisContext> folderMap) {
+
+    Map<AnalysisContext, Folder> contextMap = _reverse(folderMap);
+    Map<String, Map<String, List<String>>> result =
+        new Map<String, Map<String, List<String>>>();
+    for (AnalysisContext context in _contexts) {
+      Map<String, List<Folder>> packageMap = context.sourceFactory.packageMap;
+      if (packageMap != null) {
+        Map<String, List<String>> map = new Map<String, List<String>>();
+        packageMap.forEach((String name, List<Folder> folders) => map[name] =
+            new List.from(folders.map((Folder f) => f.path)));
+        result[contextMap[context].path] = map;
+      }
+    }
+    return result;
+  }
+
   Set<String> collectLibraryDependencies() {
     _contexts.forEach(
         (AnalysisContext context) =>
@@ -25,6 +45,13 @@
     return _dependencies;
   }
 
+  Map<AnalysisContext, Folder> _reverse(Map<Folder, AnalysisContext> map) {
+    Map<AnalysisContext, Folder> reverseMap =
+        new Map<AnalysisContext, Folder>();
+    map.forEach((Folder f, AnalysisContext c) => reverseMap[c] = f);
+    return reverseMap;
+  }
+
   void _addDependencies(LibraryElement libraryElement) {
     if (libraryElement == null) {
       return;
diff --git a/pkg/analysis_server/lib/src/services/index/local_index.dart b/pkg/analysis_server/lib/src/services/index/local_index.dart
index c95a0be..68a5032 100644
--- a/pkg/analysis_server/lib/src/services/index/local_index.dart
+++ b/pkg/analysis_server/lib/src/services/index/local_index.dart
@@ -36,6 +36,14 @@
   }
 
   /**
+   * Returns all relations with [Element]s with the given [name].
+   */
+  Future<Map<List<String>, List<InspectLocation>>>
+      findElementsByName(String name) {
+    return _store.inspect_getElementRelations(name);
+  }
+
+  /**
    * Returns a `Future<List<Location>>` that completes with the list of
    * [Location]s of the given [relationship] with the given [element].
    *
diff --git a/pkg/analysis_server/lib/src/services/index/store/codec.dart b/pkg/analysis_server/lib/src/services/index/store/codec.dart
index 1625edd..8f6a2ed 100644
--- a/pkg/analysis_server/lib/src/services/index/store/codec.dart
+++ b/pkg/analysis_server/lib/src/services/index/store/codec.dart
@@ -145,6 +145,34 @@
     return index;
   }
 
+  /**
+   * Returns a list with the location components of the element with the
+   * given encoded ID.
+   */
+  List<String> inspect_decodePath(int id) {
+    List<int> path = _indexToPath[id];
+    return _getLocationComponents(path);
+  }
+
+  /**
+   * Returns a map of element IDs to their locations for elements with
+   * the [requiredName].
+   */
+  Map<int, List<String>> inspect_getElements(String requiredName) {
+    Map<int, List<String>> result = <int, List<String>>{};
+    for (int i = 0; i < _indexToPath.length; i++) {
+      List<int> path = _indexToPath[i];
+      int nameIndex = path[path.length - 1];
+      if (nameIndex >= 0) {
+        String name = _stringCodec.decode(nameIndex);
+        if (name == requiredName) {
+          result[i] = path.map(_stringCodec.decode).toList();
+        }
+      }
+    }
+    return result;
+  }
+
   int _encodePath(List<int> path) {
     int index = _pathToIndex[path];
     if (index == null) {
diff --git a/pkg/analysis_server/lib/src/services/index/store/split_store.dart b/pkg/analysis_server/lib/src/services/index/store/split_store.dart
index d16d29a..fc1ca31 100644
--- a/pkg/analysis_server/lib/src/services/index/store/split_store.dart
+++ b/pkg/analysis_server/lib/src/services/index/store/split_store.dart
@@ -34,6 +34,11 @@
   void delete(String name);
 
   /**
+   * Returns names of all known nodes.
+   */
+  List<String> inspect_getAllNodeNames();
+
+  /**
    * Read the entire file contents as a list of bytes.
    */
   Future<List<int>> read(String name);
@@ -89,6 +94,13 @@
     });
   }
 
+  /**
+   * Returns names of all known nodes.
+   */
+  List<String> inspect_getAllNodeNames() {
+    return _fileManager.inspect_getAllNodeNames();
+  }
+
   @override
   IndexNode newNode(AnalysisContext context) =>
       new IndexNode(context, elementCodec, _relationshipCodec);
@@ -280,6 +292,32 @@
   }
 
   /**
+   * Returns [InspectLocation]s for the element with the given ID.
+   */
+  List<InspectLocation> inspect_getRelations(String name, int elementId) {
+    List<InspectLocation> result = <InspectLocation>[];
+    _relations.forEach((RelationKeyData key, locations) {
+      if (key.elementId == elementId) {
+        for (LocationData location in locations) {
+          Relationship relationship =
+              _relationshipCodec.decode(key.relationshipId);
+          List<String> path =
+              _elementCodec.inspect_decodePath(location.elementId);
+          result.add(
+              new InspectLocation(
+                  name,
+                  relationship,
+                  path,
+                  location.offset,
+                  location.length,
+                  location.flags));
+        }
+      }
+    });
+    return result;
+  }
+
+  /**
    * Records that the given [element] and [location] have the given [relationship].
    *
    * [element] - the [Element] that is related to the location.
@@ -305,6 +343,19 @@
 }
 
 
+class InspectLocation {
+  final String nodeName;
+  final Relationship relationship;
+  final List<String> path;
+  final int offset;
+  final int length;
+  final int flags;
+
+  InspectLocation(this.nodeName, this.relationship, this.path, this.offset,
+      this.length, this.flags);
+}
+
+
 /**
  * A container with information about a [Location].
  */
@@ -681,6 +732,45 @@
     });
   }
 
+  /**
+   * Returns all relations with [Element]s with the given [name].
+   */
+  Future<Map<List<String>, List<InspectLocation>>>
+      inspect_getElementRelations(String name) {
+    Map<List<String>, List<InspectLocation>> result = <List<String>,
+        List<InspectLocation>>{};
+    // prepare elements
+    Map<int, List<String>> elementMap = _elementCodec.inspect_getElements(name);
+    // prepare relations with each element
+    List<Future> futures = <Future>[];
+    if (_nodeManager is FileNodeManager) {
+      List<String> nodeNames =
+          (_nodeManager as FileNodeManager).inspect_getAllNodeNames();
+      nodeNames.forEach((nodeName) {
+        Future<IndexNode> nodeFuture = _nodeManager.getNode(nodeName);
+        Future relationsFuture = nodeFuture.then((node) {
+          if (node != null) {
+            elementMap.forEach((int elementId, List<String> elementPath) {
+              List<InspectLocation> relations =
+                  node.inspect_getRelations(nodeName, elementId);
+              List<InspectLocation> resultLocations = result[elementPath];
+              if (resultLocations == null) {
+                resultLocations = <InspectLocation>[];
+                result[elementPath] = resultLocations;
+              }
+              resultLocations.addAll(relations);
+            });
+          }
+        });
+        futures.add(relationsFuture);
+      });
+    }
+    // wait for all nodex
+    return Future.wait(futures).then((_) {
+      return result;
+    });
+  }
+
   @override
   void recordRelationship(Element element, Relationship relationship,
       Location location) {
diff --git a/pkg/analysis_server/lib/src/services/index/store/temporary_folder_file_manager.dart b/pkg/analysis_server/lib/src/services/index/store/temporary_folder_file_manager.dart
index ddf915e..653be9e 100644
--- a/pkg/analysis_server/lib/src/services/index/store/temporary_folder_file_manager.dart
+++ b/pkg/analysis_server/lib/src/services/index/store/temporary_folder_file_manager.dart
@@ -53,6 +53,18 @@
   }
 
   @override
+  List<String> inspect_getAllNodeNames() {
+    List<String> names = <String>[];
+    List<FileSystemEntity> filePathList = _directory.listSync();
+    for (FileSystemEntity file in filePathList) {
+      String filePath = file.path;
+      String name = pathos.basename(filePath);
+      names.add(name);
+    }
+    return names;
+  }
+
+  @override
   Future<List<int>> read(String name) {
     if (_directory == null) {
       return new Future.value(null);
diff --git a/pkg/analysis_server/lib/src/services/refactoring/convert_method_to_getter.dart b/pkg/analysis_server/lib/src/services/refactoring/convert_method_to_getter.dart
index 6b63f76..55cc6a7 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/convert_method_to_getter.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/convert_method_to_getter.dart
@@ -132,7 +132,7 @@
         if (invocation != null) {
           SourceRange range = rangeEndEnd(refRange, invocation);
           SourceEdit edit = newSourceEdit_range(range, '');
-          doSourceChange_addElementEdit(change, element, edit);
+          doSourceChange_addElementEdit(change, refElement, edit);
         }
       }
     });
diff --git a/pkg/analysis_server/lib/src/status/ast_writer.dart b/pkg/analysis_server/lib/src/status/ast_writer.dart
index a5dd302..97e9fa4 100644
--- a/pkg/analysis_server/lib/src/status/ast_writer.dart
+++ b/pkg/analysis_server/lib/src/status/ast_writer.dart
@@ -7,6 +7,7 @@
 import 'dart:convert';
 
 import 'package:analyzer/src/generated/ast.dart';
+import 'package:analyzer/src/generated/java_engine.dart';
 
 /**
  * A visitor that will produce an HTML representation of an AST structure.
@@ -23,6 +24,12 @@
   int indentLevel = 0;
 
   /**
+   * A list containing the exceptions that were caught while attempting to write
+   * out an AST structure.
+   */
+  List<CaughtException> exceptions = <CaughtException>[];
+
+  /**
    * Initialize a newly created element writer to write the HTML representation
    * of visited nodes on the given [buffer].
    */
@@ -174,9 +181,21 @@
    */
   void _writeProperty(String name, Object value) {
     if (value != null) {
+      String valueString = null;
+      try {
+        valueString = value.toString();
+      } catch (exception, stackTrace) {
+        exceptions.add(new CaughtException(exception, stackTrace));
+      }
       _indent(2);
       buffer.write('$name = ');
-      buffer.write(HTML_ESCAPE.convert(value.toString()));
+      if (valueString == null) {
+        buffer.write('<span style="color: #FF0000">');
+        buffer.write(HTML_ESCAPE.convert(value.runtimeType.toString()));
+        buffer.write('</span>');
+      } else {
+        buffer.write(HTML_ESCAPE.convert(valueString));
+      }
       buffer.write('<br>');
     }
   }
diff --git a/pkg/analysis_server/pubspec.yaml b/pkg/analysis_server/pubspec.yaml
index a4ede1e..3af3854 100644
--- a/pkg/analysis_server/pubspec.yaml
+++ b/pkg/analysis_server/pubspec.yaml
@@ -6,7 +6,7 @@
 environment:
   sdk: '>=1.0.0 <2.0.0'
 dependencies:
-  analyzer: 0.23.0-dev.13
+  analyzer: 0.23.0
   args: '>=0.12.1 <0.13.0'
   logging: any
   path: any
diff --git a/pkg/analysis_server/test/analysis/notification_navigation_test.dart b/pkg/analysis_server/test/analysis/notification_navigation_test.dart
index 0e810d1..b04ff9c 100644
--- a/pkg/analysis_server/test/analysis/notification_navigation_test.dart
+++ b/pkg/analysis_server/test/analysis/notification_navigation_test.dart
@@ -581,6 +581,45 @@
     });
   }
 
+  test_superConstructorInvocation() {
+    addTestFile('''
+class A {
+  A() {}
+  A.named() {}
+}
+class B extends A {
+  B() : super();
+  B.named() : super.named();
+}
+''');
+    return prepareNavigation().then((_) {
+      {
+        assertHasRegionString('super');
+        assertHasTarget('A() {}', 0);
+      }
+      {
+        assertHasRegionString('super.named');
+        assertHasTarget('named() {}');
+      }
+    });
+  }
+
+  test_superConstructorInvocation_synthetic() {
+    addTestFile('''
+class A {
+}
+class B extends A {
+  B() : super();
+}
+''');
+    return prepareNavigation().then((_) {
+      {
+        assertHasRegionString('super');
+        assertHasTarget('A {');
+      }
+    });
+  }
+
   test_targetElement() {
     addTestFile('''
 class AAA {}
diff --git a/pkg/analysis_server/test/analysis_abstract.dart b/pkg/analysis_server/test/analysis_abstract.dart
index b167e77..c42b3b2 100644
--- a/pkg/analysis_server/test/analysis_abstract.dart
+++ b/pkg/analysis_server/test/analysis_abstract.dart
@@ -7,6 +7,7 @@
 import 'dart:async';
 
 import 'package:analysis_server/src/analysis_server.dart';
+import 'package:analysis_server/src/constants.dart';
 import 'package:analysis_server/src/domain_analysis.dart';
 import 'package:analysis_server/src/protocol.dart';
 import 'package:analysis_server/src/services/index/index.dart';
@@ -34,7 +35,6 @@
 }
 
 
-
 /**
  * An abstract base for all 'analysis' domain tests.
  */
@@ -45,19 +45,16 @@
   AnalysisServer server;
   RequestHandler handler;
 
-  Map<AnalysisService, List<String>> analysisSubscriptions = {};
+  final List<ServerErrorParams> serverErrors = <ServerErrorParams>[];
+  final Map<AnalysisService, List<String>> analysisSubscriptions = {};
 
   String projectPath = '/project';
   String testFolder = '/project/bin/';
   String testFile = '/project/bin/test.dart';
   String testCode;
 
-//  Map<String, List<AnalysisError>> filesErrors = {};
-//  Map<String, List<Map<String, Object>>> filesHighlights = {};
-//  Map<String, List<Map<String, Object>>> filesNavigation = {};
-
-
   AbstractAnalysisTest();
+
   void addAnalysisSubscription(AnalysisService service, String file) {
     // add file to subscription
     var files = analysisSubscriptions[service];
@@ -145,95 +142,13 @@
     return testFile;
   }
 
-//  /**
-//   * Returns [AnalysisError]s recorded for the given [file].
-//   * May be empty, but not `null`.
-//   */
-//  List<AnalysisError> getErrors(String file) {
-//    List<AnalysisError> errors = filesErrors[file];
-//    if (errors != null) {
-//      return errors;
-//    }
-//    return <AnalysisError>[];
-//  }
-//
-//  /**
-//   * Returns highlights recorded for the given [file].
-//   * May be empty, but not `null`.
-//   */
-//  List<Map<String, Object>> getHighlights(String file) {
-//    List<Map<String, Object>> highlights = filesHighlights[file];
-//    if (highlights != null) {
-//      return highlights;
-//    }
-//    return [];
-//  }
-//
-//  /**
-//   * Returns navigation regions recorded for the given [file].
-//   * May be empty, but not `null`.
-//   */
-//  List<Map<String, Object>> getNavigation(String file) {
-//    List<Map<String, Object>> navigation = filesNavigation[file];
-//    if (navigation != null) {
-//      return navigation;
-//    }
-//    return [];
-//  }
-//
-//  /**
-//   * Returns [AnalysisError]s recorded for the [testFile].
-//   * May be empty, but not `null`.
-//   */
-//  List<AnalysisError> getTestErrors() {
-//    return getErrors(testFile);
-//  }
-//
-//  /**
-//   * Returns highlights recorded for the given [testFile].
-//   * May be empty, but not `null`.
-//   */
-//  List<Map<String, Object>> getTestHighlights() {
-//    return getHighlights(testFile);
-//  }
-//
-//  /**
-//   * Returns navigation information recorded for the given [testFile].
-//   * May be empty, but not `null`.
-//   */
-//  List<Map<String, Object>> getTestNavigation() {
-//    return getNavigation(testFile);
-//  }
-
   void processNotification(Notification notification) {
-//    if (notification.event == NOTIFICATION_ERRORS) {
-//      String file = notification.getParameter(FILE);
-//      List<Map<String, Object>> errorMaps = notification.getParameter(ERRORS);
-//      filesErrors[file] = errorMaps.map(jsonToAnalysisError).toList();
-//    }
-//    if (notification.event == NOTIFICATION_HIGHLIGHTS) {
-//      String file = notification.getParameter(FILE);
-//      filesHighlights[file] = notification.getParameter(REGIONS);
-//    }
-//    if (notification.event == NOTIFICATION_NAVIGATION) {
-//      String file = notification.getParameter(FILE);
-//      filesNavigation[file] = notification.getParameter(REGIONS);
-//    }
+    if (notification.event == SERVER_ERROR) {
+      var params = new ServerErrorParams.fromNotification(notification);
+      serverErrors.add(params);
+    }
   }
 
-//  /**
-//   * Creates a project with a single Dart file `/project/bin/test.dart` with
-//   * the given [code].
-//   */
-//  void createSingleFileProject(code) {
-//    this.testCode = _getCodeString(code);
-//    resourceProvider.newFolder('/project');
-//    resourceProvider.newFile(testFile, testCode);
-//    Request request = new AnalysisSetAnalysisRootsParams(['/project'],
-//        []).toRequest('0');
-//    handleSuccessfulRequest(request);
-//  }
-
   void setUp() {
     serverChannel = new MockServerChannel();
     resourceProvider = new MemoryResourceProvider();
@@ -263,4 +178,12 @@
   Future waitForTasksFinished() {
     return server.onAnalysisComplete;
   }
+
+  /**
+   * Completes with a successful [Response] for the given [request].
+   * Otherwise fails.
+   */
+  Future<Response> waitResponse(Request request) async {
+    return serverChannel.sendRequest(request);
+  }
 }
diff --git a/pkg/analysis_server/test/analysis_server_test.dart b/pkg/analysis_server/test/analysis_server_test.dart
index 528324a..90ab3ca 100644
--- a/pkg/analysis_server/test/analysis_server_test.dart
+++ b/pkg/analysis_server/test/analysis_server_test.dart
@@ -225,6 +225,54 @@
     });
   }
 
+  /**
+   * Test that having multiple analysis contexts analyze the same file doesn't
+   * cause that file to receive duplicate notifications when it's modified.
+   */
+  Future test_no_duplicate_notifications() async {
+    // Subscribe to STATUS so we'll know when analysis is done.
+    server.serverServices = [ServerService.STATUS].toSet();
+    resourceProvider.newFolder('/foo');
+    resourceProvider.newFolder('/bar');
+    resourceProvider.newFile('/foo/foo.dart', 'import "../bar/bar.dart";');
+    File bar = resourceProvider.newFile('/bar/bar.dart', 'library bar;');
+    server.setAnalysisRoots('0', ['/foo', '/bar'], [], {});
+    Map<AnalysisService, Set<String>> subscriptions = <AnalysisService,
+        Set<String>>{};
+    for (AnalysisService service in AnalysisService.VALUES) {
+      subscriptions[service] = <String>[bar.path].toSet();
+    }
+    server.setAnalysisSubscriptions(subscriptions);
+    await pumpEventQueue(100);
+    expect(server.statusAnalyzing, isFalse);
+    channel.notificationsReceived.clear();
+    server.updateContent('0', {
+      bar.path: new AddContentOverlay('library bar; void f() {}')
+    });
+    await pumpEventQueue(100);
+    expect(server.statusAnalyzing, isFalse);
+    expect(channel.notificationsReceived, isNotEmpty);
+    Set<String> notificationTypesReceived = new Set<String>();
+    for (Notification notification in channel.notificationsReceived) {
+      String notificationType = notification.event;
+      switch (notificationType) {
+        case 'server.status':
+        case 'analysis.errors':
+          // It's normal for these notifications to be sent multiple times.
+          break;
+        case 'analysis.outline':
+          // It's normal for this notification to be sent twice.
+          // TODO(paulberry): why?
+          break;
+        default:
+          if (!notificationTypesReceived.add(notificationType)) {
+            fail('Notification type $notificationType received more than once');
+          }
+          break;
+      }
+    }
+  }
+
   Future test_prioritySourcesChangedEvent() {
     resourceProvider.newFolder('/foo');
 
diff --git a/pkg/analysis_server/test/completion_test.dart b/pkg/analysis_server/test/completion_test.dart
index 464765b..a7d7f56 100644
--- a/pkg/analysis_server/test/completion_test.dart
+++ b/pkg/analysis_server/test/completion_test.dart
@@ -129,8 +129,7 @@
 
     buildTests('testCommentSnippets020', '''
 classMap{}class tst {var newt;void newf(){}test() {var newz;new!1/**/;}}''',
-        <String>["1+newt", "1+newf", "1+newz", "1-Map"],
-        failingTests: '1');
+        <String>["1+newt", "1+newf", "1+newz", "1-Map"]);
 
     buildTests('testCommentSnippets021', '''
 class Map{}class tst {var newt;void newf(){}test() {var newz;new !1/**/;}}''',
diff --git a/pkg/analysis_server/test/context_manager_test.dart b/pkg/analysis_server/test/context_manager_test.dart
index 80cf74d..6cde096 100644
--- a/pkg/analysis_server/test/context_manager_test.dart
+++ b/pkg/analysis_server/test/context_manager_test.dart
@@ -193,7 +193,7 @@
       subProjectA: {
         'foo': [resourceProvider.newFolder('/package/foo')]
       },
-      subProjectA: {
+      subProjectB: {
         'bar': [resourceProvider.newFolder('/package/bar')]
       },
     };
@@ -205,7 +205,7 @@
     manager.assertContextFiles(subProjectA, [subProjectA_file]);
     manager.assertContextFiles(subProjectB, [subProjectB_file]);
     // verify package maps
-    _checkPackageMap(root, equals(packageMapProvider.packageMaps[root]));
+    _checkPackageMap(root, isNull);
     _checkPackageMap(
         subProjectA,
         equals(packageMapProvider.packageMaps[subProjectA]));
@@ -756,9 +756,9 @@
    */
   void _checkPackageMap(String path, expectation) {
     UriResolver resolver = manager.currentContextPackageUriResolvers[path];
-    expect(resolver, new isInstanceOf<PackageMapUriResolver>());
-    PackageMapUriResolver packageMapUriResolver = resolver;
-    expect(packageMapUriResolver.packageMap, expectation);
+    Map<String, List<Folder>> packageMap =
+        resolver is PackageMapUriResolver ? resolver.packageMap : null;
+    expect(packageMap, expectation);
   }
 
   /**
diff --git a/pkg/analysis_server/test/domain_server_test.dart b/pkg/analysis_server/test/domain_server_test.dart
index 19d3b66..9bf0f76 100644
--- a/pkg/analysis_server/test/domain_server_test.dart
+++ b/pkg/analysis_server/test/domain_server_test.dart
@@ -40,7 +40,7 @@
       expect(response.toJson(), equals({
         Response.ID: '0',
         Response.RESULT: {
-          VERSION: '0.0.1'
+          VERSION: '1.0.0'
         }
       }));
     });
diff --git a/pkg/analysis_server/test/edit/refactoring_test.dart b/pkg/analysis_server/test/edit/refactoring_test.dart
index 1de0f55..51e1a4e 100644
--- a/pkg/analysis_server/test/edit/refactoring_test.dart
+++ b/pkg/analysis_server/test/edit/refactoring_test.dart
@@ -13,6 +13,7 @@
 import 'package:unittest/unittest.dart' hide ERROR;
 
 import '../analysis_abstract.dart';
+import '../mocks.dart';
 import '../reflective_tests.dart';
 
 
@@ -1029,7 +1030,7 @@
 @reflectiveTest
 class RenameTest extends _AbstractGetRefactoring_Test {
   Future<Response> sendRenameRequest(String search, String newName,
-      [bool validateOnly = false]) {
+      {String id: '0', bool validateOnly: false}) {
     RenameOptions options = newName != null ? new RenameOptions(newName) : null;
     Request request = new EditGetRefactoringParams(
         RefactoringKind.RENAME,
@@ -1037,10 +1038,29 @@
         findOffset(search),
         0,
         validateOnly,
-        options: options).toRequest('0');
+        options: options).toRequest(id);
     return serverChannel.sendRequest(request);
   }
 
+  test_cancelPendingRequest() async {
+    addTestFile('''
+main() {
+  int test = 0;
+  print(test);
+}
+''');
+    // send the "1" request, but don't wait for it
+    Future<Response> futureA = sendRenameRequest('test =', 'nameA', id: '1');
+    // send the "2" request and wait for it
+    Response responseB = await sendRenameRequest('test =', 'nameB', id: '2');
+    // wait for the (delayed) "1" response
+    Response responseA = await futureA;
+    // "1" was cancelled
+    // "2" is successful
+    expect(responseA, isResponseFailure('1', RequestErrorCode.REFACTORING_REQUEST_CANCELLED));
+    expect(responseB, isResponseSuccess('2'));
+  }
+
   test_class() {
     addTestFile('''
 class Test {
@@ -1094,7 +1114,7 @@
 }
 ''');
     return getRefactoringResult(() {
-      return sendRenameRequest('Test {}', 'NewName', true);
+      return sendRenameRequest('Test {}', 'NewName', validateOnly: true);
     }).then((result) {
       RenameFeedback feedback = result.feedback;
       assertResultProblemsOK(result);
@@ -1523,7 +1543,7 @@
 }
 ''');
     return getRefactoringResult(() {
-      return sendRenameRequest('test = 0', 'newName', false);
+      return sendRenameRequest('test = 0', 'newName');
     }).then((result) {
       List<RefactoringProblem> problems = result.finalProblems;
       expect(problems, hasLength(1));
@@ -1542,7 +1562,7 @@
 ''');
     // send the first request
     return getRefactoringResult(() {
-      return sendRenameRequest('initialName =', 'newName', true);
+      return sendRenameRequest('initialName =', 'newName', validateOnly: true);
     }).then((result) {
       RenameFeedback feedback = result.feedback;
       expect(feedback.oldName, 'initialName');
@@ -1556,7 +1576,7 @@
       // send the second request, with the same kind, file and offset
       return waitForTasksFinished().then((_) {
         return getRefactoringResult(() {
-          return sendRenameRequest('otherName =', 'newName', true);
+          return sendRenameRequest('otherName =', 'newName', validateOnly: true);
         }).then((result) {
           RenameFeedback feedback = result.feedback;
           // the refactoring was reset, so we don't get a stale result
diff --git a/pkg/analysis_server/test/integration/integration_test_methods.dart b/pkg/analysis_server/test/integration/integration_test_methods.dart
index 2158ed6..4850c83 100644
--- a/pkg/analysis_server/test/integration/integration_test_methods.dart
+++ b/pkg/analysis_server/test/integration/integration_test_methods.dart
@@ -231,8 +231,8 @@
   }
 
   /**
-   * Return a list of all of the libraries referenced by any files in existing
-   * analysis roots.
+   * Return library dependency information for use in client-side indexing and
+   * package URI resolution.
    *
    * Returns
    *
@@ -240,6 +240,12 @@
    *
    *   A list of the paths of library elements referenced by files in existing
    *   analysis roots.
+   *
+   * packageMap ( Map<String, Map<String, List<FilePath>>> )
+   *
+   *   A mapping from context source roots to package maps which map package
+   *   names to source directories for use in client-side package URI
+   *   resolution.
    */
   Future<AnalysisGetLibraryDependenciesResult> sendAnalysisGetLibraryDependencies() {
     return server.send("analysis.getLibraryDependencies", null)
@@ -324,7 +330,11 @@
   /**
    * Sets the root paths used to determine which files to analyze. The set of
    * files to be analyzed are all of the files in one of the root paths that
-   * are not also in one of the excluded paths.
+   * are not either explicitly or implicitly excluded. A file is explicitly
+   * excluded if it is in one of the excluded paths. A file is implicitly
+   * excluded if it is in a subdirectory of one of the root paths where the
+   * name of the subdirectory starts with a period (that is, a hidden
+   * directory).
    *
    * Note that this request determines the set of requested analysis roots. The
    * actual set of analysis roots at any given time is the intersection of this
@@ -1052,11 +1062,15 @@
    *
    * selectionOffset ( int )
    *
-   *   The offset of the current selection in the file.
+   *   The offset of the current selection in the file. In case preserving,
+   *   selection information is not required, 0 can be specified for both
+   *   selection offset and length.
    *
    * selectionLength ( int )
    *
-   *   The length of the current selection in the file.
+   *   The length of the current selection in the file. In case preserving,
+   *   selection information is not required, 0 can be specified for both
+   *   selection offset and length.
    *
    * Returns
    *
@@ -1182,6 +1196,9 @@
   /**
    * Get the changes required to perform a refactoring.
    *
+   * If another refactoring request is received during the processing of this
+   * one, an error of type REFACTORING_REQUEST_CANCELLED will be generated.
+   *
    * Parameters
    *
    * kind ( RefactoringKind )
@@ -1351,6 +1368,21 @@
    *
    * Exactly one of the file and uri fields must be provided.
    *
+   * If the file field is provided and the value is not the path of a file
+   * (either the file does not exist or the path references something other
+   * than a file), then an error of type MAP_URI_INVALID_FILE will be
+   * generated.
+   *
+   * If the uri field is provided and the value is not a valid URI or if the
+   * URI references something that is not a file (either a file that does not
+   * exist or something other than a file), then an error of type
+   * MAP_URI_INVALID_URI will be generated.
+   *
+   * If the contextRoot used to create the execution context is not a file
+   * (either the file does not exist or the path references something other
+   * than a file), then an error of type INVALID_EXECUTION_CONTEXT will be
+   * generated.
+   *
    * Parameters
    *
    * id ( ExecutionContextId )
diff --git a/pkg/analysis_server/test/integration/protocol_matchers.dart b/pkg/analysis_server/test/integration/protocol_matchers.dart
index d426e9c..3605eee 100644
--- a/pkg/analysis_server/test/integration/protocol_matchers.dart
+++ b/pkg/analysis_server/test/integration/protocol_matchers.dart
@@ -155,11 +155,13 @@
  *
  * {
  *   "libraries": List<FilePath>
+ *   "packageMap": Map<String, Map<String, List<FilePath>>>
  * }
  */
 final Matcher isAnalysisGetLibraryDependenciesResult = new LazyMatcher(() => new MatchesJsonObject(
   "analysis.getLibraryDependencies result", {
-    "libraries": isListOf(isFilePath)
+    "libraries": isListOf(isFilePath),
+    "packageMap": isMapOf(isString, isMapOf(isString, isListOf(isFilePath)))
   }));
 
 /**
@@ -1800,6 +1802,7 @@
  *   INVALID_OVERLAY_CHANGE
  *   INVALID_PARAMETER
  *   INVALID_REQUEST
+ *   REFACTORING_REQUEST_CANCELLED
  *   SERVER_ALREADY_STARTED
  *   SERVER_ERROR
  *   SORT_MEMBERS_INVALID_FILE
@@ -1816,6 +1819,7 @@
   "INVALID_OVERLAY_CHANGE",
   "INVALID_PARAMETER",
   "INVALID_REQUEST",
+  "REFACTORING_REQUEST_CANCELLED",
   "SERVER_ALREADY_STARTED",
   "SERVER_ERROR",
   "SORT_MEMBERS_INVALID_FILE",
diff --git a/pkg/analysis_server/test/mocks.dart b/pkg/analysis_server/test/mocks.dart
index c017c63..9475cbb 100644
--- a/pkg/analysis_server/test/mocks.dart
+++ b/pkg/analysis_server/test/mocks.dart
@@ -283,9 +283,6 @@
     return responseController.stream.firstWhere((response) {
       return response.id == id;
     });
-//    return responseController.stream.firstWhere((response) {
-//      return response.id == id;
-//    });
   }
 }
 
diff --git a/pkg/analysis_server/test/search/abstract_search_domain.dart b/pkg/analysis_server/test/search/abstract_search_domain.dart
index 655ea34..11a84aa 100644
--- a/pkg/analysis_server/test/search/abstract_search_domain.dart
+++ b/pkg/analysis_server/test/search/abstract_search_domain.dart
@@ -17,8 +17,8 @@
 
 
 class AbstractSearchDomainTest extends AbstractAnalysisTest {
+  final Map<String, _ResultSet> resultSets = {};
   String searchId;
-  bool searchDone = false;
   List<SearchResult> results = <SearchResult>[];
   SearchResult result;
 
@@ -75,24 +75,39 @@
   void processNotification(Notification notification) {
     if (notification.event == SEARCH_RESULTS) {
       var params = new SearchResultsParams.fromNotification(notification);
-      if (params.id == searchId) {
-        results.addAll(params.results);
-        searchDone = params.isLast;
+      String id = params.id;
+      _ResultSet resultSet = resultSets[id];
+      if (resultSet == null) {
+        resultSet = new _ResultSet(id);
+        resultSets[id] = resultSet;
       }
+      resultSet.results.addAll(params.results);
+      resultSet.done = params.isLast;
     }
   }
 
   @override
   void setUp() {
     super.setUp();
+    server.handlers = [new SearchDomainHandler(server),];
     createProject();
-    handler = new SearchDomainHandler(server);
   }
 
   Future waitForSearchResults() {
-    if (searchDone) {
+    _ResultSet resultSet = resultSets[searchId];
+    if (resultSet != null && resultSet.done) {
+      results = resultSet.results;
       return new Future.value();
     }
     return new Future.delayed(Duration.ZERO, waitForSearchResults);
   }
 }
+
+
+class _ResultSet {
+  final String id;
+  final List<SearchResult> results = <SearchResult>[];
+  bool done = false;
+
+  _ResultSet(this.id);
+}
diff --git a/pkg/analysis_server/test/search/element_references_test.dart b/pkg/analysis_server/test/search/element_references_test.dart
index 8081178..a2b0a5c 100644
--- a/pkg/analysis_server/test/search/element_references_test.dart
+++ b/pkg/analysis_server/test/search/element_references_test.dart
@@ -28,28 +28,25 @@
     expect(result.isPotential, isPotential);
   }
 
-  Future findElementReferences(String search, bool includePotential) {
+  Future findElementReferences(String search, bool includePotential) async {
     int offset = findOffset(search);
-    return waitForTasksFinished().then((_) {
-      Request request = new SearchFindElementReferencesParams(
-          testFile,
-          offset,
-          includePotential).toRequest('0');
-      Response response = handleSuccessfulRequest(request);
-      var result = new SearchFindElementReferencesResult.fromResponse(response);
-      searchId = result.id;
-      searchElement = result.element;
-      results.clear();
-      searchDone = false;
-      if (searchId == null) {
-        return null;
-      } else {
-        return waitForSearchResults();
-      }
-    });
+    await waitForTasksFinished();
+    Request request = new SearchFindElementReferencesParams(
+        testFile,
+        offset,
+        includePotential).toRequest('0');
+    Response response = await waitResponse(request);
+    var result = new SearchFindElementReferencesResult.fromResponse(response);
+    searchId = result.id;
+    searchElement = result.element;
+    if (searchId == null) {
+      return null;
+    } else {
+      return waitForSearchResults();
+    }
   }
 
-  test_constructor_named() {
+  test_constructor_named() async {
     addTestFile('''
 class A {
   A.named(p);
@@ -59,14 +56,13 @@
   new A.named(2);
 }
 ''');
-    return findElementReferences('named(p)', false).then((_) {
-      expect(searchElement.kind, ElementKind.CONSTRUCTOR);
-      assertHasResult(SearchResultKind.REFERENCE, '.named(1)', 6);
-      assertHasResult(SearchResultKind.REFERENCE, '.named(2)', 6);
-    });
+    await findElementReferences('named(p)', false);
+    expect(searchElement.kind, ElementKind.CONSTRUCTOR);
+    assertHasResult(SearchResultKind.REFERENCE, '.named(1)', 6);
+    assertHasResult(SearchResultKind.REFERENCE, '.named(2)', 6);
   }
 
-  test_constructor_named_potential() {
+  test_constructor_named_potential() async {
     // Constructors in other classes shouldn't be considered potential matches,
     // nor should unresolved method calls, since constructor call sites are
     // statically bound to their targets).
@@ -83,15 +79,14 @@
   x.named(3);
 }
 ''');
-    return findElementReferences('named(p); // A', true).then((_) {
-      expect(searchElement.kind, ElementKind.CONSTRUCTOR);
-      assertHasResult(SearchResultKind.DECLARATION, '.named(p)', 6);
-      assertHasResult(SearchResultKind.REFERENCE, '.named(1)', 6);
-      expect(results, hasLength(2));
-    });
+    await findElementReferences('named(p); // A', true);
+    expect(searchElement.kind, ElementKind.CONSTRUCTOR);
+    assertHasResult(SearchResultKind.DECLARATION, '.named(p)', 6);
+    assertHasResult(SearchResultKind.REFERENCE, '.named(1)', 6);
+    expect(results, hasLength(2));
   }
 
-  test_constructor_unnamed() {
+  test_constructor_unnamed() async {
     addTestFile('''
 class A {
   A(p);
@@ -101,14 +96,13 @@
   new A(2);
 }
 ''');
-    return findElementReferences('A(p)', false).then((_) {
-      expect(searchElement.kind, ElementKind.CONSTRUCTOR);
-      assertHasResult(SearchResultKind.REFERENCE, '(1)', 0);
-      assertHasResult(SearchResultKind.REFERENCE, '(2)', 0);
-    });
+    await findElementReferences('A(p)', false);
+    expect(searchElement.kind, ElementKind.CONSTRUCTOR);
+    assertHasResult(SearchResultKind.REFERENCE, '(1)', 0);
+    assertHasResult(SearchResultKind.REFERENCE, '(2)', 0);
   }
 
-  test_constructor_unnamed_potential() {
+  test_constructor_unnamed_potential() async {
     // Constructors in other classes shouldn't be considered potential matches,
     // even if they are also unnamed (since constructor call sites are
     // statically bound to their targets).
@@ -130,15 +124,14 @@
   new B(2);
 }
 ''');
-    return findElementReferences('A(p)', true).then((_) {
-      expect(searchElement.kind, ElementKind.CONSTRUCTOR);
-      assertHasResult(SearchResultKind.DECLARATION, '(p); // A', 0);
-      assertHasResult(SearchResultKind.REFERENCE, '(1)', 0);
-      expect(results, hasLength(2));
-    });
+    await findElementReferences('A(p)', true);
+    expect(searchElement.kind, ElementKind.CONSTRUCTOR);
+    assertHasResult(SearchResultKind.DECLARATION, '(p); // A', 0);
+    assertHasResult(SearchResultKind.REFERENCE, '(1)', 0);
+    expect(results, hasLength(2));
   }
 
-  test_field_explicit() {
+  test_field_explicit() async {
     addTestFile('''
 class A {
   var fff; // declaration
@@ -157,25 +150,24 @@
   a.fff(); // in main()
 }
 ''');
-    return findElementReferences('fff; // declaration', false).then((_) {
-      expect(searchElement.kind, ElementKind.FIELD);
-      expect(results, hasLength(10));
-      assertHasResult(SearchResultKind.DECLARATION, 'fff; // declaration');
-      assertHasResult(SearchResultKind.REFERENCE, 'fff); // in constructor');
-      // m()
-      assertHasResult(SearchResultKind.WRITE, 'fff = 2;');
-      assertHasResult(SearchResultKind.WRITE, 'fff += 3;');
-      assertHasResult(SearchResultKind.READ, 'fff); // in m()');
-      assertHasResult(SearchResultKind.INVOCATION, 'fff(); // in m()');
-      // main()
-      assertHasResult(SearchResultKind.WRITE, 'fff = 20;');
-      assertHasResult(SearchResultKind.WRITE, 'fff += 30;');
-      assertHasResult(SearchResultKind.READ, 'fff); // in main()');
-      assertHasResult(SearchResultKind.INVOCATION, 'fff(); // in main()');
-    });
+    await findElementReferences('fff; // declaration', false);
+    expect(searchElement.kind, ElementKind.FIELD);
+    expect(results, hasLength(10));
+    assertHasResult(SearchResultKind.DECLARATION, 'fff; // declaration');
+    assertHasResult(SearchResultKind.REFERENCE, 'fff); // in constructor');
+    // m()
+    assertHasResult(SearchResultKind.WRITE, 'fff = 2;');
+    assertHasResult(SearchResultKind.WRITE, 'fff += 3;');
+    assertHasResult(SearchResultKind.READ, 'fff); // in m()');
+    assertHasResult(SearchResultKind.INVOCATION, 'fff(); // in m()');
+    // main()
+    assertHasResult(SearchResultKind.WRITE, 'fff = 20;');
+    assertHasResult(SearchResultKind.WRITE, 'fff += 30;');
+    assertHasResult(SearchResultKind.READ, 'fff); // in main()');
+    assertHasResult(SearchResultKind.INVOCATION, 'fff(); // in main()');
   }
 
-  test_field_implicit() {
+  test_field_implicit() async {
     addTestFile('''
 class A {
   var  get fff => null;
@@ -190,24 +182,26 @@
   a.fff = 10;
 }
 ''');
-    return findElementReferences('fff =>', false).then((_) {
+    {
+      await findElementReferences('fff =>', false);
       expect(searchElement.kind, ElementKind.FIELD);
       expect(results, hasLength(4));
       assertHasResult(SearchResultKind.READ, 'fff); // in m()');
       assertHasResult(SearchResultKind.WRITE, 'fff = 1;');
       assertHasResult(SearchResultKind.READ, 'fff); // in main()');
       assertHasResult(SearchResultKind.WRITE, 'fff = 10;');
-      return findElementReferences('fff(x) {}', false);
-    }).then((_) {
+    }
+    {
+      await findElementReferences('fff(x) {}', false);
       expect(results, hasLength(4));
       assertHasResult(SearchResultKind.READ, 'fff); // in m()');
       assertHasResult(SearchResultKind.WRITE, 'fff = 1;');
       assertHasResult(SearchResultKind.READ, 'fff); // in main()');
       assertHasResult(SearchResultKind.WRITE, 'fff = 10;');
-    });
+    }
   }
 
-  test_field_inFormalParameter() {
+  test_field_inFormalParameter() async {
     addTestFile('''
 class A {
   var fff; // declaration
@@ -218,17 +212,16 @@
   }
 }
 ''');
-    return findElementReferences('fff); // in constructor', false).then((_) {
-      expect(searchElement.kind, ElementKind.FIELD);
-      expect(results, hasLength(4));
-      assertHasResult(SearchResultKind.DECLARATION, 'fff; // declaration');
-      assertHasResult(SearchResultKind.REFERENCE, 'fff); // in constructor');
-      assertHasResult(SearchResultKind.WRITE, 'fff = 2;');
-      assertHasResult(SearchResultKind.READ, 'fff); // in m()');
-    });
+    await findElementReferences('fff); // in constructor', false);
+    expect(searchElement.kind, ElementKind.FIELD);
+    expect(results, hasLength(4));
+    assertHasResult(SearchResultKind.DECLARATION, 'fff; // declaration');
+    assertHasResult(SearchResultKind.REFERENCE, 'fff); // in constructor');
+    assertHasResult(SearchResultKind.WRITE, 'fff = 2;');
+    assertHasResult(SearchResultKind.READ, 'fff); // in m()');
   }
 
-  test_function() {
+  test_function() async {
     addTestFile('''
 fff(p) {}
 main() {
@@ -236,15 +229,14 @@
   print(fff);
 }
 ''');
-    return findElementReferences('fff(p) {}', false).then((_) {
-      expect(searchElement.kind, ElementKind.FUNCTION);
-      expect(results, hasLength(2));
-      assertHasResult(SearchResultKind.INVOCATION, 'fff(1)');
-      assertHasResult(SearchResultKind.REFERENCE, 'fff);');
-    });
+    await findElementReferences('fff(p) {}', false);
+    expect(searchElement.kind, ElementKind.FUNCTION);
+    expect(results, hasLength(2));
+    assertHasResult(SearchResultKind.INVOCATION, 'fff(1)');
+    assertHasResult(SearchResultKind.REFERENCE, 'fff);');
   }
 
-  test_hierarchy_field_explicit() {
+  test_hierarchy_field_explicit() async {
     addTestFile('''
   class A {
     int fff; // in A
@@ -261,18 +253,17 @@
     c.fff = 30;
   }
   ''');
-    return findElementReferences('fff; // in B', false).then((_) {
-      expect(searchElement.kind, ElementKind.FIELD);
-      assertHasResult(SearchResultKind.DECLARATION, 'fff; // in A');
-      assertHasResult(SearchResultKind.DECLARATION, 'fff; // in B');
-      assertHasResult(SearchResultKind.DECLARATION, 'fff; // in C');
-      assertHasResult(SearchResultKind.WRITE, 'fff = 10;');
-      assertHasResult(SearchResultKind.WRITE, 'fff = 20;');
-      assertHasResult(SearchResultKind.WRITE, 'fff = 30;');
-    });
+    await findElementReferences('fff; // in B', false);
+    expect(searchElement.kind, ElementKind.FIELD);
+    assertHasResult(SearchResultKind.DECLARATION, 'fff; // in A');
+    assertHasResult(SearchResultKind.DECLARATION, 'fff; // in B');
+    assertHasResult(SearchResultKind.DECLARATION, 'fff; // in C');
+    assertHasResult(SearchResultKind.WRITE, 'fff = 10;');
+    assertHasResult(SearchResultKind.WRITE, 'fff = 20;');
+    assertHasResult(SearchResultKind.WRITE, 'fff = 30;');
   }
 
-  test_hierarchy_method() {
+  test_hierarchy_method() async {
     addTestFile('''
 class A {
   mmm() {} // in A
@@ -289,15 +280,14 @@
   c.mmm(30);
 }
 ''');
-    return findElementReferences('mmm() {} // in B', false).then((_) {
-      expect(searchElement.kind, ElementKind.METHOD);
-      assertHasResult(SearchResultKind.INVOCATION, 'mmm(10)');
-      assertHasResult(SearchResultKind.INVOCATION, 'mmm(20)');
-      assertHasResult(SearchResultKind.INVOCATION, 'mmm(30)');
-    });
+    await findElementReferences('mmm() {} // in B', false);
+    expect(searchElement.kind, ElementKind.METHOD);
+    assertHasResult(SearchResultKind.INVOCATION, 'mmm(10)');
+    assertHasResult(SearchResultKind.INVOCATION, 'mmm(20)');
+    assertHasResult(SearchResultKind.INVOCATION, 'mmm(30)');
   }
 
-  test_label() {
+  test_label() async {
     addTestFile('''
 main() {
 myLabel:
@@ -309,16 +299,15 @@
   }
 }
 ''');
-    return findElementReferences('myLabel; // break', false).then((_) {
-      expect(searchElement.kind, ElementKind.LABEL);
-      expect(results, hasLength(3));
-      assertHasResult(SearchResultKind.DECLARATION, 'myLabel:');
-      assertHasResult(SearchResultKind.REFERENCE, 'myLabel; // continue');
-      assertHasResult(SearchResultKind.REFERENCE, 'myLabel; // break');
-    });
+    await findElementReferences('myLabel; // break', false);
+    expect(searchElement.kind, ElementKind.LABEL);
+    expect(results, hasLength(3));
+    assertHasResult(SearchResultKind.DECLARATION, 'myLabel:');
+    assertHasResult(SearchResultKind.REFERENCE, 'myLabel; // continue');
+    assertHasResult(SearchResultKind.REFERENCE, 'myLabel; // break');
   }
 
-  test_localVariable() {
+  test_localVariable() async {
     addTestFile('''
 main() {
   var vvv = 1;
@@ -328,18 +317,17 @@
   vvv();
 }
 ''');
-    return findElementReferences('vvv = 1', false).then((_) {
-      expect(searchElement.kind, ElementKind.LOCAL_VARIABLE);
-      expect(results, hasLength(5));
-      assertHasResult(SearchResultKind.DECLARATION, 'vvv = 1');
-      assertHasResult(SearchResultKind.READ, 'vvv);');
-      assertHasResult(SearchResultKind.READ_WRITE, 'vvv += 3');
-      assertHasResult(SearchResultKind.WRITE, 'vvv = 2');
-      assertHasResult(SearchResultKind.INVOCATION, 'vvv();');
-    });
+    await findElementReferences('vvv = 1', false);
+    expect(searchElement.kind, ElementKind.LOCAL_VARIABLE);
+    expect(results, hasLength(5));
+    assertHasResult(SearchResultKind.DECLARATION, 'vvv = 1');
+    assertHasResult(SearchResultKind.READ, 'vvv);');
+    assertHasResult(SearchResultKind.READ_WRITE, 'vvv += 3');
+    assertHasResult(SearchResultKind.WRITE, 'vvv = 2');
+    assertHasResult(SearchResultKind.INVOCATION, 'vvv();');
   }
 
-  test_method() {
+  test_method() async {
     addTestFile('''
 class A {
   mmm(p) {}
@@ -353,17 +341,16 @@
   print(a.mmm); // in main()
 }
 ''');
-    return findElementReferences('mmm(p) {}', false).then((_) {
-      expect(searchElement.kind, ElementKind.METHOD);
-      expect(results, hasLength(4));
-      assertHasResult(SearchResultKind.INVOCATION, 'mmm(1);');
-      assertHasResult(SearchResultKind.REFERENCE, 'mmm); // in m()');
-      assertHasResult(SearchResultKind.INVOCATION, 'mmm(10);');
-      assertHasResult(SearchResultKind.REFERENCE, 'mmm); // in main()');
-    });
+    await findElementReferences('mmm(p) {}', false);
+    expect(searchElement.kind, ElementKind.METHOD);
+    expect(results, hasLength(4));
+    assertHasResult(SearchResultKind.INVOCATION, 'mmm(1);');
+    assertHasResult(SearchResultKind.REFERENCE, 'mmm); // in m()');
+    assertHasResult(SearchResultKind.INVOCATION, 'mmm(10);');
+    assertHasResult(SearchResultKind.REFERENCE, 'mmm); // in main()');
   }
 
-  test_method_propagatedType() {
+  test_method_propagatedType() async {
     addTestFile('''
 class A {
   mmm(p) {}
@@ -374,26 +361,24 @@
   print(a.mmm);
 }
 ''');
-    return findElementReferences('mmm(p) {}', false).then((_) {
-      expect(searchElement.kind, ElementKind.METHOD);
-      expect(results, hasLength(2));
-      assertHasResult(SearchResultKind.INVOCATION, 'mmm(10);');
-      assertHasResult(SearchResultKind.REFERENCE, 'mmm);');
-    });
+    await findElementReferences('mmm(p) {}', false);
+    expect(searchElement.kind, ElementKind.METHOD);
+    expect(results, hasLength(2));
+    assertHasResult(SearchResultKind.INVOCATION, 'mmm(10);');
+    assertHasResult(SearchResultKind.REFERENCE, 'mmm);');
   }
 
-  test_noElement() {
+  test_noElement() async {
     addTestFile('''
 main() {
   print(noElement);
 }
 ''');
-    return findElementReferences('noElement', false).then((_) {
-      expect(searchId, isNull);
-    });
+    await findElementReferences('noElement', false);
+    expect(searchId, isNull);
   }
 
-  test_oneUnit_twoLibraries() {
+  test_oneUnit_twoLibraries() async {
     var pathA = '/project/bin/libA.dart';
     var pathB = '/project/bin/libB.dart';
     var codeA = '''
@@ -416,25 +401,24 @@
 part of lib;
 fff(p) {}
 ''');
-    return findElementReferences('fff(p) {}', false).then((_) {
-      expect(searchElement.kind, ElementKind.FUNCTION);
-      expect(results, hasLength(2));
-      findResult(
-          SearchResultKind.INVOCATION,
-          pathA,
-          codeA.indexOf('fff(1)'),
-          3,
-          true);
-      findResult(
-          SearchResultKind.INVOCATION,
-          pathB,
-          codeB.indexOf('fff(2)'),
-          3,
-          true);
-    });
+    await findElementReferences('fff(p) {}', false);
+    expect(searchElement.kind, ElementKind.FUNCTION);
+    expect(results, hasLength(2));
+    findResult(
+        SearchResultKind.INVOCATION,
+        pathA,
+        codeA.indexOf('fff(1)'),
+        3,
+        true);
+    findResult(
+        SearchResultKind.INVOCATION,
+        pathB,
+        codeB.indexOf('fff(2)'),
+        3,
+        true);
   }
 
-  test_oneUnit_zeroLibraries() {
+  test_oneUnit_zeroLibraries() async {
     addTestFile('''
 part of lib;
 fff(p) {}
@@ -442,12 +426,11 @@
   fff(10);
 }
 ''');
-    return findElementReferences('fff(p) {}', false).then((_) {
-      expect(results, isEmpty);
-    });
+    await findElementReferences('fff(p) {}', false);
+    expect(results, isEmpty);
   }
 
-  test_parameter() {
+  test_parameter() async {
     addTestFile('''
 main(ppp) {
   print(ppp);
@@ -456,18 +439,17 @@
   ppp();
 }
 ''');
-    return findElementReferences('ppp) {', false).then((_) {
-      expect(searchElement.kind, ElementKind.PARAMETER);
-      expect(results, hasLength(5));
-      assertHasResult(SearchResultKind.DECLARATION, 'ppp) {');
-      assertHasResult(SearchResultKind.READ, 'ppp);');
-      assertHasResult(SearchResultKind.READ_WRITE, 'ppp += 3');
-      assertHasResult(SearchResultKind.WRITE, 'ppp = 2');
-      assertHasResult(SearchResultKind.INVOCATION, 'ppp();');
-    });
+    await findElementReferences('ppp) {', false);
+    expect(searchElement.kind, ElementKind.PARAMETER);
+    expect(results, hasLength(5));
+    assertHasResult(SearchResultKind.DECLARATION, 'ppp) {');
+    assertHasResult(SearchResultKind.READ, 'ppp);');
+    assertHasResult(SearchResultKind.READ_WRITE, 'ppp += 3');
+    assertHasResult(SearchResultKind.WRITE, 'ppp = 2');
+    assertHasResult(SearchResultKind.INVOCATION, 'ppp();');
   }
 
-  test_path_inConstructor_named() {
+  test_path_inConstructor_named() async {
     addTestFile('''
 library my_lib;
 class A {}
@@ -477,18 +459,17 @@
   }
 }
 ''');
-    return findElementReferences('A {}', false).then((_) {
-      assertHasResult(SearchResultKind.REFERENCE, 'A a = null;');
-      expect(getPathString(result.path), '''
+    await findElementReferences('A {}', false);
+    assertHasResult(SearchResultKind.REFERENCE, 'A a = null;');
+    expect(getPathString(result.path), '''
 LOCAL_VARIABLE a
 CONSTRUCTOR named
 CLASS B
 COMPILATION_UNIT test.dart
 LIBRARY my_lib''');
-    });
   }
 
-  test_path_inConstructor_unnamed() {
+  test_path_inConstructor_unnamed() async {
     addTestFile('''
 library my_lib;
 class A {}
@@ -498,18 +479,17 @@
   }
 }
 ''');
-    return findElementReferences('A {}', false).then((_) {
-      assertHasResult(SearchResultKind.REFERENCE, 'A a = null;');
-      expect(getPathString(result.path), '''
+    await findElementReferences('A {}', false);
+    assertHasResult(SearchResultKind.REFERENCE, 'A a = null;');
+    expect(getPathString(result.path), '''
 LOCAL_VARIABLE a
 CONSTRUCTOR 
 CLASS B
 COMPILATION_UNIT test.dart
 LIBRARY my_lib''');
-    });
   }
 
-  test_path_inFunction() {
+  test_path_inFunction() async {
     addTestFile('''
 library my_lib;
 class A {}
@@ -517,17 +497,16 @@
   A a = null;
 }
 ''');
-    return findElementReferences('A {}', false).then((_) {
-      assertHasResult(SearchResultKind.REFERENCE, 'A a = null;');
-      expect(getPathString(result.path), '''
+    await findElementReferences('A {}', false);
+    assertHasResult(SearchResultKind.REFERENCE, 'A a = null;');
+    expect(getPathString(result.path), '''
 LOCAL_VARIABLE a
 FUNCTION main
 COMPILATION_UNIT test.dart
 LIBRARY my_lib''');
-    });
   }
 
-  test_potential_disabled() {
+  test_potential_disabled() async {
     addTestFile('''
 class A {
   test(p) {}
@@ -537,13 +516,12 @@
   p.test(2);
 }
 ''');
-    return findElementReferences('test(p) {}', false).then((_) {
-      assertHasResult(SearchResultKind.INVOCATION, 'test(1);');
-      assertNoResult(SearchResultKind.INVOCATION, 'test(2);');
-    });
+    await findElementReferences('test(p) {}', false);
+    assertHasResult(SearchResultKind.INVOCATION, 'test(1);');
+    assertNoResult(SearchResultKind.INVOCATION, 'test(2);');
   }
 
-  test_potential_field() {
+  test_potential_field() async {
     addTestFile('''
 class A {
   var test; // declaration
@@ -554,23 +532,22 @@
   print(p.test); // p
 }
 ''');
-    return findElementReferences('test; // declaration', true).then((_) {
-      {
-        assertHasResult(SearchResultKind.WRITE, 'test = 1;');
-        expect(result.isPotential, isFalse);
-      }
-      {
-        assertHasResult(SearchResultKind.WRITE, 'test = 2;');
-        expect(result.isPotential, isTrue);
-      }
-      {
-        assertHasResult(SearchResultKind.READ, 'test); // p');
-        expect(result.isPotential, isTrue);
-      }
-    });
+    await findElementReferences('test; // declaration', true);
+    {
+      assertHasResult(SearchResultKind.WRITE, 'test = 1;');
+      expect(result.isPotential, isFalse);
+    }
+    {
+      assertHasResult(SearchResultKind.WRITE, 'test = 2;');
+      expect(result.isPotential, isTrue);
+    }
+    {
+      assertHasResult(SearchResultKind.READ, 'test); // p');
+      expect(result.isPotential, isTrue);
+    }
   }
 
-  test_potential_method() {
+  test_potential_method() async {
     addTestFile('''
 class A {
   test(p) {}
@@ -580,19 +557,18 @@
   p.test(2);
 }
 ''');
-    return findElementReferences('test(p) {}', true).then((_) {
-      {
-        assertHasResult(SearchResultKind.INVOCATION, 'test(1);');
-        expect(result.isPotential, isFalse);
-      }
-      {
-        assertHasResult(SearchResultKind.INVOCATION, 'test(2);');
-        expect(result.isPotential, isTrue);
-      }
-    });
+    await findElementReferences('test(p) {}', true);
+    {
+      assertHasResult(SearchResultKind.INVOCATION, 'test(1);');
+      expect(result.isPotential, isFalse);
+    }
+    {
+      assertHasResult(SearchResultKind.INVOCATION, 'test(2);');
+      expect(result.isPotential, isTrue);
+    }
   }
 
-  test_potential_method_definedInSubclass() {
+  test_potential_method_definedInSubclass() async {
     addTestFile('''
 class Base {
   methodInBase() {
@@ -609,14 +585,13 @@
   b.test(3);
 }
 ''');
-    return findElementReferences('test(_) {} // of Derived', true).then((_) {
-      assertHasRef(SearchResultKind.INVOCATION, 'test(1);', true);
-      assertHasRef(SearchResultKind.INVOCATION, 'test(2);', false);
-      assertHasRef(SearchResultKind.INVOCATION, 'test(3);', true);
-    });
+    await findElementReferences('test(_) {} // of Derived', true);
+    assertHasRef(SearchResultKind.INVOCATION, 'test(1);', true);
+    assertHasRef(SearchResultKind.INVOCATION, 'test(2);', false);
+    assertHasRef(SearchResultKind.INVOCATION, 'test(3);', true);
   }
 
-  test_prefix() {
+  test_prefix() async {
     addTestFile('''
 import 'dart:async' as ppp;
 main() {
@@ -624,18 +599,17 @@
   ppp.Stream b;
 }
 ''');
-    return findElementReferences("ppp;", false).then((_) {
-      expect(searchElement.kind, ElementKind.PREFIX);
-      expect(searchElement.name, 'ppp');
-      expect(searchElement.location.startLine, 1);
-      expect(results, hasLength(3));
-      assertHasResult(SearchResultKind.DECLARATION, 'ppp;');
-      assertHasResult(SearchResultKind.REFERENCE, 'ppp.Future');
-      assertHasResult(SearchResultKind.REFERENCE, 'ppp.Stream');
-    });
+    await findElementReferences("ppp;", false);
+    expect(searchElement.kind, ElementKind.PREFIX);
+    expect(searchElement.name, 'ppp');
+    expect(searchElement.location.startLine, 1);
+    expect(results, hasLength(3));
+    assertHasResult(SearchResultKind.DECLARATION, 'ppp;');
+    assertHasResult(SearchResultKind.REFERENCE, 'ppp.Future');
+    assertHasResult(SearchResultKind.REFERENCE, 'ppp.Stream');
   }
 
-  test_prefix_null() {
+  test_prefix_null() async {
     addTestFile('''
 import 'dart:async';
 main() {
@@ -643,12 +617,11 @@
   Stream b;
 }
 ''');
-    return findElementReferences("import ", false).then((_) {
-      expect(searchElement, isNull);
-    });
+    await findElementReferences("import ", false);
+    expect(searchElement, isNull);
   }
 
-  test_topLevelVariable_explicit() {
+  test_topLevelVariable_explicit() async {
     addTestFile('''
 var vvv = 1;
 main() {
@@ -658,18 +631,17 @@
   vvv();
 }
 ''');
-    return findElementReferences('vvv = 1', false).then((_) {
-      expect(searchElement.kind, ElementKind.TOP_LEVEL_VARIABLE);
-      expect(results, hasLength(5));
-      assertHasResult(SearchResultKind.DECLARATION, 'vvv = 1;');
-      assertHasResult(SearchResultKind.READ, 'vvv);');
-      assertHasResult(SearchResultKind.WRITE, 'vvv += 3');
-      assertHasResult(SearchResultKind.WRITE, 'vvv = 2');
-      assertHasResult(SearchResultKind.INVOCATION, 'vvv();');
-    });
+    await findElementReferences('vvv = 1', false);
+    expect(searchElement.kind, ElementKind.TOP_LEVEL_VARIABLE);
+    expect(results, hasLength(5));
+    assertHasResult(SearchResultKind.DECLARATION, 'vvv = 1;');
+    assertHasResult(SearchResultKind.READ, 'vvv);');
+    assertHasResult(SearchResultKind.WRITE, 'vvv += 3');
+    assertHasResult(SearchResultKind.WRITE, 'vvv = 2');
+    assertHasResult(SearchResultKind.INVOCATION, 'vvv();');
   }
 
-  test_topLevelVariable_implicit() {
+  test_topLevelVariable_implicit() async {
     addTestFile('''
 get vvv => null;
 set vvv(x) {}
@@ -678,58 +650,57 @@
   vvv = 1;
 }
 ''');
-    return findElementReferences('vvv =>', false).then((_) {
+    {
+      await findElementReferences('vvv =>', false);
       expect(searchElement.kind, ElementKind.TOP_LEVEL_VARIABLE);
       expect(results, hasLength(2));
       assertHasResult(SearchResultKind.READ, 'vvv);');
       assertHasResult(SearchResultKind.WRITE, 'vvv = 1;');
-      return findElementReferences('vvv(x) {}', false);
-    }).then((_) {
+    }
+    {
+      await findElementReferences('vvv(x) {}', false);
       expect(results, hasLength(2));
       assertHasResult(SearchResultKind.READ, 'vvv);');
       assertHasResult(SearchResultKind.WRITE, 'vvv = 1;');
-    });
+    }
   }
 
-  test_typeReference_class() {
+  test_typeReference_class() async {
     addTestFile('''
 main() {
   int a = 1;
   int b = 2;
 }
 ''');
-    return findElementReferences('int a', false).then((_) {
-      expect(searchElement.kind, ElementKind.CLASS);
-      assertHasResult(SearchResultKind.REFERENCE, 'int a');
-      assertHasResult(SearchResultKind.REFERENCE, 'int b');
-    });
+    await findElementReferences('int a', false);
+    expect(searchElement.kind, ElementKind.CLASS);
+    assertHasResult(SearchResultKind.REFERENCE, 'int a');
+    assertHasResult(SearchResultKind.REFERENCE, 'int b');
   }
 
-  test_typeReference_functionType() {
+  test_typeReference_functionType() async {
     addTestFile('''
 typedef F();
 main(F f) {
 }
 ''');
-    return findElementReferences('F()', false).then((_) {
-      expect(searchElement.kind, ElementKind.FUNCTION_TYPE_ALIAS);
-      expect(results, hasLength(1));
-      assertHasResult(SearchResultKind.REFERENCE, 'F f');
-    });
+    await findElementReferences('F()', false);
+    expect(searchElement.kind, ElementKind.FUNCTION_TYPE_ALIAS);
+    expect(results, hasLength(1));
+    assertHasResult(SearchResultKind.REFERENCE, 'F f');
   }
 
-  test_typeReference_typeVariable() {
+  test_typeReference_typeVariable() async {
     addTestFile('''
 class A<T> {
   T f;
   T m() => null;
 }
 ''');
-    return findElementReferences('T> {', false).then((_) {
-      expect(searchElement.kind, ElementKind.TYPE_PARAMETER);
-      expect(results, hasLength(2));
-      assertHasResult(SearchResultKind.REFERENCE, 'T f;');
-      assertHasResult(SearchResultKind.REFERENCE, 'T m()');
-    });
+    await findElementReferences('T> {', false);
+    expect(searchElement.kind, ElementKind.TYPE_PARAMETER);
+    expect(results, hasLength(2));
+    assertHasResult(SearchResultKind.REFERENCE, 'T f;');
+    assertHasResult(SearchResultKind.REFERENCE, 'T m()');
   }
 }
diff --git a/pkg/analysis_server/test/search/member_declarations_test.dart b/pkg/analysis_server/test/search/member_declarations_test.dart
index 2fb7946..2c379d0 100644
--- a/pkg/analysis_server/test/search/member_declarations_test.dart
+++ b/pkg/analysis_server/test/search/member_declarations_test.dart
@@ -28,24 +28,14 @@
     }
   }
 
-  void assertNoDeclaration(ElementKind kind, String className) {
-    result = findTopLevelResult(kind, className);
-    if (result != null) {
-      fail('Unexpected: kind=$kind in="$className"\nin\n' + results.join('\n'));
-    }
-  }
-
-  Future findMemberDeclarations(String name) {
-    return waitForTasksFinished().then((_) {
-      Request request =
-          new SearchFindMemberDeclarationsParams(name).toRequest('0');
-      Response response = handleSuccessfulRequest(request);
-      var result =
-          new SearchFindMemberDeclarationsResult.fromResponse(response);
-      searchId = result.id;
-      results.clear();
-      return waitForSearchResults();
-    });
+  Future findMemberDeclarations(String name) async {
+    await waitForTasksFinished();
+    Request request =
+        new SearchFindMemberDeclarationsParams(name).toRequest('0');
+    Response response = await waitResponse(request);
+    var result = new SearchFindMemberDeclarationsResult.fromResponse(response);
+    searchId = result.id;
+    return waitForSearchResults();
   }
 
   SearchResult findTopLevelResult(ElementKind kind, String enclosingClass) {
@@ -59,7 +49,7 @@
     return null;
   }
 
-  test_localVariable() {
+  test_localVariable() async {
     addTestFile('''
 class A {
   main() {
@@ -67,12 +57,11 @@
   }
 }
 ''');
-    return findMemberDeclarations('foo').then((_) {
-      expect(results, isEmpty);
-    });
+    await findMemberDeclarations('foo');
+    expect(results, isEmpty);
   }
 
-  test_localVariable_forIn() {
+  test_localVariable_forIn() async {
     addTestFile('''
 class A {
   main() {
@@ -81,12 +70,11 @@
   }
 }
 ''');
-    return findMemberDeclarations('foo').then((_) {
-      expect(results, isEmpty);
-    });
+    await findMemberDeclarations('foo');
+    expect(results, isEmpty);
   }
 
-  test_methodField() {
+  test_methodField() async {
     addTestFile('''
 class A {
   foo() {}
@@ -96,14 +84,13 @@
   int foo;
 }
 ''');
-    return findMemberDeclarations('foo').then((_) {
-      expect(results, hasLength(2));
-      assertHasDeclaration(ElementKind.METHOD, 'A');
-      assertHasDeclaration(ElementKind.FIELD, 'B');
-    });
+    await findMemberDeclarations('foo');
+    expect(results, hasLength(2));
+    assertHasDeclaration(ElementKind.METHOD, 'A');
+    assertHasDeclaration(ElementKind.FIELD, 'B');
   }
 
-  test_methodGetter() {
+  test_methodGetter() async {
     addTestFile('''
 class A {
   foo() {}
@@ -113,14 +100,13 @@
   get foo => null;
 }
 ''');
-    return findMemberDeclarations('foo').then((_) {
-      expect(results, hasLength(2));
-      assertHasDeclaration(ElementKind.METHOD, 'A');
-      assertHasDeclaration(ElementKind.GETTER, 'B');
-    });
+    await findMemberDeclarations('foo');
+    expect(results, hasLength(2));
+    assertHasDeclaration(ElementKind.METHOD, 'A');
+    assertHasDeclaration(ElementKind.GETTER, 'B');
   }
 
-  test_methodGetterSetter() {
+  test_methodGetterSetter() async {
     addTestFile('''
 class A {
   foo() {}
@@ -131,15 +117,14 @@
   set foo(x) {}
 }
 ''');
-    return findMemberDeclarations('foo').then((_) {
-      expect(results, hasLength(3));
-      assertHasDeclaration(ElementKind.METHOD, 'A');
-      assertHasDeclaration(ElementKind.GETTER, 'B');
-      assertHasDeclaration(ElementKind.SETTER, 'B');
-    });
+    await findMemberDeclarations('foo');
+    expect(results, hasLength(3));
+    assertHasDeclaration(ElementKind.METHOD, 'A');
+    assertHasDeclaration(ElementKind.GETTER, 'B');
+    assertHasDeclaration(ElementKind.SETTER, 'B');
   }
 
-  test_methodMethod() {
+  test_methodMethod() async {
     addTestFile('''
 class A {
   foo() {}
@@ -149,14 +134,13 @@
   foo() {}
 }
 ''');
-    return findMemberDeclarations('foo').then((_) {
-      expect(results, hasLength(2));
-      assertHasDeclaration(ElementKind.METHOD, 'A');
-      assertHasDeclaration(ElementKind.METHOD, 'B');
-    });
+    await findMemberDeclarations('foo');
+    expect(results, hasLength(2));
+    assertHasDeclaration(ElementKind.METHOD, 'A');
+    assertHasDeclaration(ElementKind.METHOD, 'B');
   }
 
-  test_methodSetter() {
+  test_methodSetter() async {
     addTestFile('''
 class A {
   foo() {}
@@ -166,10 +150,9 @@
   set foo(x) {}
 }
 ''');
-    return findMemberDeclarations('foo').then((_) {
-      expect(results, hasLength(2));
-      assertHasDeclaration(ElementKind.METHOD, 'A');
-      assertHasDeclaration(ElementKind.SETTER, 'B');
-    });
+    await findMemberDeclarations('foo');
+    expect(results, hasLength(2));
+    assertHasDeclaration(ElementKind.METHOD, 'A');
+    assertHasDeclaration(ElementKind.SETTER, 'B');
   }
 }
diff --git a/pkg/analysis_server/test/search/member_references_test.dart b/pkg/analysis_server/test/search/member_references_test.dart
index e2d1caa..9f34375 100644
--- a/pkg/analysis_server/test/search/member_references_test.dart
+++ b/pkg/analysis_server/test/search/member_references_test.dart
@@ -26,18 +26,15 @@
     expect(result.isPotential, isPotential);
   }
 
-  Future findMemberReferences(String name) {
-    return waitForTasksFinished().then((_) {
-      Request request =
-          new SearchFindMemberReferencesParams(name).toRequest('0');
-      Response response = handleSuccessfulRequest(request);
-      searchId = new SearchFindMemberReferencesResult.fromResponse(response).id;
-      results.clear();
-      return waitForSearchResults();
-    });
+  Future findMemberReferences(String name) async {
+    await waitForTasksFinished();
+    Request request = new SearchFindMemberReferencesParams(name).toRequest('0');
+    Response response = await waitResponse(request);
+    searchId = new SearchFindMemberReferencesResult.fromResponse(response).id;
+    return waitForSearchResults();
   }
 
-  test_fields_explicit() {
+  test_fields_explicit() async {
     addTestFile('''
 class A {
   var foo;
@@ -58,19 +55,18 @@
   print(b.foo); // unresolved B
 }
 ''');
-    return findMemberReferences('foo').then((_) {
-      assertHasRef(SearchResultKind.WRITE, 'foo = 1;', false);
-      assertHasRef(SearchResultKind.WRITE, 'foo = 2;', false);
-      assertHasRef(SearchResultKind.READ, 'foo); // resolved A', false);
-      assertHasRef(SearchResultKind.READ, 'foo); // resolved B', false);
-      assertHasRef(SearchResultKind.WRITE, 'foo = 10;', true);
-      assertHasRef(SearchResultKind.WRITE, 'foo = 20;', true);
-      assertHasRef(SearchResultKind.READ, 'foo); // unresolved A', true);
-      assertHasRef(SearchResultKind.READ, 'foo); // unresolved B', true);
-    });
+    await findMemberReferences('foo');
+    assertHasRef(SearchResultKind.WRITE, 'foo = 1;', false);
+    assertHasRef(SearchResultKind.WRITE, 'foo = 2;', false);
+    assertHasRef(SearchResultKind.READ, 'foo); // resolved A', false);
+    assertHasRef(SearchResultKind.READ, 'foo); // resolved B', false);
+    assertHasRef(SearchResultKind.WRITE, 'foo = 10;', true);
+    assertHasRef(SearchResultKind.WRITE, 'foo = 20;', true);
+    assertHasRef(SearchResultKind.READ, 'foo); // unresolved A', true);
+    assertHasRef(SearchResultKind.READ, 'foo); // unresolved B', true);
   }
 
-  test_fields_implicit() {
+  test_fields_implicit() async {
     addTestFile('''
 class A {
   get foo => null;
@@ -87,15 +83,14 @@
   print(b.foo); // unresolved B
 }
 ''');
-    return findMemberReferences('foo').then((_) {
-      assertHasRef(SearchResultKind.READ, 'foo); // resolved A', false);
-      assertHasRef(SearchResultKind.READ, 'foo); // resolved B', false);
-      assertHasRef(SearchResultKind.READ, 'foo); // unresolved A', true);
-      assertHasRef(SearchResultKind.READ, 'foo); // unresolved B', true);
-    });
+    await findMemberReferences('foo');
+    assertHasRef(SearchResultKind.READ, 'foo); // resolved A', false);
+    assertHasRef(SearchResultKind.READ, 'foo); // resolved B', false);
+    assertHasRef(SearchResultKind.READ, 'foo); // unresolved A', true);
+    assertHasRef(SearchResultKind.READ, 'foo); // unresolved B', true);
   }
 
-  test_methods() {
+  test_methods() async {
     addTestFile('''
 class A {
   foo() {}
@@ -112,11 +107,10 @@
   b.foo(20);
 }
 ''');
-    return findMemberReferences('foo').then((_) {
-      assertHasRef(SearchResultKind.INVOCATION, 'foo(1)', false);
-      assertHasRef(SearchResultKind.INVOCATION, 'foo(2)', false);
-      assertHasRef(SearchResultKind.INVOCATION, 'foo(10)', true);
-      assertHasRef(SearchResultKind.INVOCATION, 'foo(20)', true);
-    });
+    await findMemberReferences('foo');
+    assertHasRef(SearchResultKind.INVOCATION, 'foo(1)', false);
+    assertHasRef(SearchResultKind.INVOCATION, 'foo(2)', false);
+    assertHasRef(SearchResultKind.INVOCATION, 'foo(10)', true);
+    assertHasRef(SearchResultKind.INVOCATION, 'foo(20)', true);
   }
 }
diff --git a/pkg/analysis_server/test/search/top_level_declarations_test.dart b/pkg/analysis_server/test/search/top_level_declarations_test.dart
index 26ec55a..a2d4cf0 100644
--- a/pkg/analysis_server/test/search/top_level_declarations_test.dart
+++ b/pkg/analysis_server/test/search/top_level_declarations_test.dart
@@ -35,16 +35,14 @@
     }
   }
 
-  Future findTopLevelDeclarations(String pattern) {
-    return waitForTasksFinished().then((_) {
-      Request request =
-          new SearchFindTopLevelDeclarationsParams(pattern).toRequest('0');
-      Response response = handleSuccessfulRequest(request);
-      searchId =
-          new SearchFindTopLevelDeclarationsResult.fromResponse(response).id;
-      results.clear();
-      return waitForSearchResults();
-    });
+  Future findTopLevelDeclarations(String pattern) async {
+    await waitForTasksFinished();
+    Request request =
+        new SearchFindTopLevelDeclarationsParams(pattern).toRequest('0');
+    Response response = await waitResponse(request);
+    searchId =
+        new SearchFindTopLevelDeclarationsResult.fromResponse(response).id;
+    return waitForSearchResults();
   }
 
   SearchResult findTopLevelResult(ElementKind kind, String name) {
@@ -57,7 +55,7 @@
     return null;
   }
 
-  test_startEndPattern() {
+  test_startEndPattern() async {
     addTestFile('''
 class A {} // A
 class B = Object with A;
@@ -66,13 +64,12 @@
 var E = null;
 class ABC {}
 ''');
-    return findTopLevelDeclarations('^[A-E]\$').then((_) {
-      assertHasDeclaration(ElementKind.CLASS, 'A');
-      assertHasDeclaration(ElementKind.CLASS, 'B');
-      assertHasDeclaration(ElementKind.FUNCTION_TYPE_ALIAS, 'C');
-      assertHasDeclaration(ElementKind.FUNCTION, 'D');
-      assertHasDeclaration(ElementKind.TOP_LEVEL_VARIABLE, 'E');
-      assertNoDeclaration(ElementKind.CLASS, 'ABC');
-    });
+    await findTopLevelDeclarations('^[A-E]\$');
+    assertHasDeclaration(ElementKind.CLASS, 'A');
+    assertHasDeclaration(ElementKind.CLASS, 'B');
+    assertHasDeclaration(ElementKind.FUNCTION_TYPE_ALIAS, 'C');
+    assertHasDeclaration(ElementKind.FUNCTION, 'D');
+    assertHasDeclaration(ElementKind.TOP_LEVEL_VARIABLE, 'E');
+    assertNoDeclaration(ElementKind.CLASS, 'ABC');
   }
 }
diff --git a/pkg/analysis_server/test/search/type_hierarchy_test.dart b/pkg/analysis_server/test/search/type_hierarchy_test.dart
index c2d2bad..e799f37 100644
--- a/pkg/analysis_server/test/search/type_hierarchy_test.dart
+++ b/pkg/analysis_server/test/search/type_hierarchy_test.dart
@@ -38,73 +38,74 @@
     createProject();
   }
 
-  test_bad_function() {
+  test_bad_function() async {
     addTestFile('''
 main() {
 }
 ''');
-    return waitForTasksFinished().then((_) {
-      return _getTypeHierarchy('main() {').then((items) {
-        expect(items, isNull);
-      });
-    });
+    List<TypeHierarchyItem> items = await _getTypeHierarchy('main() {');
+    expect(items, isNull);
   }
 
-  test_bad_recursion() {
+  test_bad_noElement() async {
+    addTestFile('''
+main() {
+  /* target */
+}
+''');
+    List<TypeHierarchyItem> items = await _getTypeHierarchy('/* target */');
+    expect(items, isNull);
+  }
+
+  test_bad_recursion() async {
     addTestFile('''
 class A extends B {
 }
 class B extends A {
 }
 ''');
-    return waitForTasksFinished().then((_) {
-      return _getTypeHierarchy('B extends A').then((items) {
-        expect(_toJson(items), [{
-            'classElement': {
-              'kind': 'CLASS',
-              'name': 'B',
-              'location': anything,
-              'flags': 0
-            },
-            'superclass': 1,
-            'interfaces': [],
-            'mixins': [],
-            'subclasses': []
-          }, {
-            'classElement': {
-              'kind': 'CLASS',
-              'name': 'A',
-              'location': anything,
-              'flags': 0
-            },
-            'superclass': 0,
-            'interfaces': [],
-            'mixins': [],
-            'subclasses': [1]
-          }]);
-      });
-    });
+    List<TypeHierarchyItem> items = await _getTypeHierarchy('B extends A');
+    expect(_toJson(items), [{
+        'classElement': {
+          'kind': 'CLASS',
+          'name': 'B',
+          'location': anything,
+          'flags': 0
+        },
+        'superclass': 1,
+        'interfaces': [],
+        'mixins': [],
+        'subclasses': []
+      }, {
+        'classElement': {
+          'kind': 'CLASS',
+          'name': 'A',
+          'location': anything,
+          'flags': 0
+        },
+        'superclass': 0,
+        'interfaces': [],
+        'mixins': [],
+        'subclasses': [1]
+      }]);
   }
 
-  test_class_displayName() {
+  test_class_displayName() async {
     addTestFile('''
 class A<T> {
 }
 class B extends A<int> {
 }
 ''');
-    return waitForTasksFinished().then((_) {
-      return _getTypeHierarchy('B extends').then((items) {
-        var itemB = items[0];
-        var itemA = items[itemB.superclass];
-        expect(itemA.classElement.name, 'A');
-        expect(itemB.classElement.name, 'B');
-        expect(itemA.displayName, 'A<int>');
-      });
-    });
+    List<TypeHierarchyItem> items = await _getTypeHierarchy('B extends');
+    var itemB = items[0];
+    var itemA = items[itemB.superclass];
+    expect(itemA.classElement.name, 'A');
+    expect(itemB.classElement.name, 'B');
+    expect(itemA.displayName, 'A<int>');
   }
 
-  test_class_extends_fileAndPackageUris() {
+  test_class_extends_fileAndPackageUris() async {
     // prepare packages
     String pkgFile = '/packages/pkgA/libA.dart';
     resourceProvider.newFile(pkgFile, '''
@@ -125,17 +126,14 @@
         []).toRequest('0');
     handleSuccessfulRequest(request);
     // test A type hierarchy
-    return waitForTasksFinished().then((_) {
-      return _getTypeHierarchy('A {}').then((items) {
-        Set<String> names = _toClassNames(items);
-        expect(names, contains('A'));
-        expect(names, contains('B'));
-        expect(names, contains('C'));
-      });
-    });
+    List<TypeHierarchyItem> items = await _getTypeHierarchy('A {}');
+    Set<String> names = _toClassNames(items);
+    expect(names, contains('A'));
+    expect(names, contains('B'));
+    expect(names, contains('C'));
   }
 
-  test_class_extendsTypeA() {
+  test_class_extendsTypeA() async {
     addTestFile('''
 class A {}
 class B extends A {
@@ -143,57 +141,54 @@
 class C extends B {
 }
 ''');
-    return waitForTasksFinished().then((_) {
-      return _getTypeHierarchy('A {}').then((items) {
-        expect(_toJson(items), [{
-            'classElement': {
-              'kind': 'CLASS',
-              'name': 'A',
-              'location': anything,
-              'flags': 0
-            },
-            'superclass': 1,
-            'interfaces': [],
-            'mixins': [],
-            'subclasses': [2]
-          }, {
-            'classElement': {
-              'kind': 'CLASS',
-              'name': 'Object',
-              'location': anything,
-              'flags': 0
-            },
-            'interfaces': [],
-            'mixins': [],
-            'subclasses': []
-          }, {
-            'classElement': {
-              'kind': 'CLASS',
-              'name': 'B',
-              'location': anything,
-              'flags': 0
-            },
-            'superclass': 0,
-            'interfaces': [],
-            'mixins': [],
-            'subclasses': [3]
-          }, {
-            'classElement': {
-              'kind': 'CLASS',
-              'name': 'C',
-              'location': anything,
-              'flags': 0
-            },
-            'superclass': 2,
-            'interfaces': [],
-            'mixins': [],
-            'subclasses': []
-          }]);
-      });
-    });
+    List<TypeHierarchyItem> items = await _getTypeHierarchy('A {}');
+    expect(_toJson(items), [{
+        'classElement': {
+          'kind': 'CLASS',
+          'name': 'A',
+          'location': anything,
+          'flags': 0
+        },
+        'superclass': 1,
+        'interfaces': [],
+        'mixins': [],
+        'subclasses': [2]
+      }, {
+        'classElement': {
+          'kind': 'CLASS',
+          'name': 'Object',
+          'location': anything,
+          'flags': 0
+        },
+        'interfaces': [],
+        'mixins': [],
+        'subclasses': []
+      }, {
+        'classElement': {
+          'kind': 'CLASS',
+          'name': 'B',
+          'location': anything,
+          'flags': 0
+        },
+        'superclass': 0,
+        'interfaces': [],
+        'mixins': [],
+        'subclasses': [3]
+      }, {
+        'classElement': {
+          'kind': 'CLASS',
+          'name': 'C',
+          'location': anything,
+          'flags': 0
+        },
+        'superclass': 2,
+        'interfaces': [],
+        'mixins': [],
+        'subclasses': []
+      }]);
   }
 
-  test_class_extendsTypeB() {
+  test_class_extendsTypeB() async {
     addTestFile('''
 class A {
 }
@@ -202,57 +197,54 @@
 class C extends B {
 }
 ''');
-    return waitForTasksFinished().then((_) {
-      return _getTypeHierarchy('B extends').then((items) {
-        expect(_toJson(items), [{
-            'classElement': {
-              'kind': 'CLASS',
-              'name': 'B',
-              'location': anything,
-              'flags': 0
-            },
-            'superclass': 1,
-            'interfaces': [],
-            'mixins': [],
-            'subclasses': [3]
-          }, {
-            'classElement': {
-              'kind': 'CLASS',
-              'name': 'A',
-              'location': anything,
-              'flags': 0
-            },
-            'superclass': 2,
-            'interfaces': [],
-            'mixins': [],
-            'subclasses': []
-          }, {
-            'classElement': {
-              'kind': 'CLASS',
-              'name': 'Object',
-              'location': anything,
-              'flags': 0
-            },
-            'interfaces': [],
-            'mixins': [],
-            'subclasses': []
-          }, {
-            'classElement': {
-              'kind': 'CLASS',
-              'name': 'C',
-              'location': anything,
-              'flags': 0
-            },
-            'superclass': 0,
-            'interfaces': [],
-            'mixins': [],
-            'subclasses': []
-          }]);
-      });
-    });
+    List<TypeHierarchyItem> items = await _getTypeHierarchy('B extends');
+    expect(_toJson(items), [{
+        'classElement': {
+          'kind': 'CLASS',
+          'name': 'B',
+          'location': anything,
+          'flags': 0
+        },
+        'superclass': 1,
+        'interfaces': [],
+        'mixins': [],
+        'subclasses': [3]
+      }, {
+        'classElement': {
+          'kind': 'CLASS',
+          'name': 'A',
+          'location': anything,
+          'flags': 0
+        },
+        'superclass': 2,
+        'interfaces': [],
+        'mixins': [],
+        'subclasses': []
+      }, {
+        'classElement': {
+          'kind': 'CLASS',
+          'name': 'Object',
+          'location': anything,
+          'flags': 0
+        },
+        'interfaces': [],
+        'mixins': [],
+        'subclasses': []
+      }, {
+        'classElement': {
+          'kind': 'CLASS',
+          'name': 'C',
+          'location': anything,
+          'flags': 0
+        },
+        'superclass': 0,
+        'interfaces': [],
+        'mixins': [],
+        'subclasses': []
+      }]);
   }
 
-  test_class_extendsTypeC() {
+  test_class_extendsTypeC() async {
     addTestFile('''
 class A {
 }
@@ -261,57 +253,54 @@
 class C extends B {
 }
 ''');
-    return waitForTasksFinished().then((_) {
-      return _getTypeHierarchy('C extends').then((items) {
-        expect(_toJson(items), [{
-            'classElement': {
-              'kind': 'CLASS',
-              'name': 'C',
-              'location': anything,
-              'flags': 0
-            },
-            'superclass': 1,
-            'interfaces': [],
-            'mixins': [],
-            'subclasses': []
-          }, {
-            'classElement': {
-              'kind': 'CLASS',
-              'name': 'B',
-              'location': anything,
-              'flags': 0
-            },
-            'superclass': 2,
-            'interfaces': [],
-            'mixins': [],
-            'subclasses': []
-          }, {
-            'classElement': {
-              'kind': 'CLASS',
-              'name': 'A',
-              'location': anything,
-              'flags': 0
-            },
-            'superclass': 3,
-            'interfaces': [],
-            'mixins': [],
-            'subclasses': []
-          }, {
-            'classElement': {
-              'kind': 'CLASS',
-              'name': 'Object',
-              'location': anything,
-              'flags': 0
-            },
-            'interfaces': [],
-            'mixins': [],
-            'subclasses': []
-          }]);
-      });
-    });
+    List<TypeHierarchyItem> items = await _getTypeHierarchy('C extends');
+    expect(_toJson(items), [{
+        'classElement': {
+          'kind': 'CLASS',
+          'name': 'C',
+          'location': anything,
+          'flags': 0
+        },
+        'superclass': 1,
+        'interfaces': [],
+        'mixins': [],
+        'subclasses': []
+      }, {
+        'classElement': {
+          'kind': 'CLASS',
+          'name': 'B',
+          'location': anything,
+          'flags': 0
+        },
+        'superclass': 2,
+        'interfaces': [],
+        'mixins': [],
+        'subclasses': []
+      }, {
+        'classElement': {
+          'kind': 'CLASS',
+          'name': 'A',
+          'location': anything,
+          'flags': 0
+        },
+        'superclass': 3,
+        'interfaces': [],
+        'mixins': [],
+        'subclasses': []
+      }, {
+        'classElement': {
+          'kind': 'CLASS',
+          'name': 'Object',
+          'location': anything,
+          'flags': 0
+        },
+        'interfaces': [],
+        'mixins': [],
+        'subclasses': []
+      }]);
   }
 
-  test_class_implementsTypes() {
+  test_class_implementsTypes() async {
     addTestFile('''
 class MA {}
 class MB {}
@@ -320,57 +309,54 @@
 class T implements MA, MB {
 }
 ''');
-    return waitForTasksFinished().then((_) {
-      return _getTypeHierarchy('T implements').then((items) {
-        expect(_toJson(items), [{
-            'classElement': {
-              'kind': 'CLASS',
-              'name': 'T',
-              'location': anything,
-              'flags': 0
-            },
-            'superclass': 1,
-            'interfaces': [2, 3],
-            'mixins': [],
-            'subclasses': []
-          }, {
-            'classElement': {
-              'kind': 'CLASS',
-              'name': 'Object',
-              'location': anything,
-              'flags': 0
-            },
-            'interfaces': [],
-            'mixins': [],
-            'subclasses': []
-          }, {
-            'classElement': {
-              'kind': 'CLASS',
-              'name': 'MA',
-              'location': anything,
-              'flags': 0
-            },
-            'superclass': 1,
-            'interfaces': [],
-            'mixins': [],
-            'subclasses': []
-          }, {
-            'classElement': {
-              'kind': 'CLASS',
-              'name': 'MB',
-              'location': anything,
-              'flags': 0
-            },
-            'superclass': 1,
-            'interfaces': [],
-            'mixins': [],
-            'subclasses': []
-          }]);
-      });
-    });
+    List<TypeHierarchyItem> items = await _getTypeHierarchy('T implements');
+    expect(_toJson(items), [{
+        'classElement': {
+          'kind': 'CLASS',
+          'name': 'T',
+          'location': anything,
+          'flags': 0
+        },
+        'superclass': 1,
+        'interfaces': [2, 3],
+        'mixins': [],
+        'subclasses': []
+      }, {
+        'classElement': {
+          'kind': 'CLASS',
+          'name': 'Object',
+          'location': anything,
+          'flags': 0
+        },
+        'interfaces': [],
+        'mixins': [],
+        'subclasses': []
+      }, {
+        'classElement': {
+          'kind': 'CLASS',
+          'name': 'MA',
+          'location': anything,
+          'flags': 0
+        },
+        'superclass': 1,
+        'interfaces': [],
+        'mixins': [],
+        'subclasses': []
+      }, {
+        'classElement': {
+          'kind': 'CLASS',
+          'name': 'MB',
+          'location': anything,
+          'flags': 0
+        },
+        'superclass': 1,
+        'interfaces': [],
+        'mixins': [],
+        'subclasses': []
+      }]);
   }
 
-  test_class_withTypes() {
+  test_class_withTypes() async {
     addTestFile('''
 class MA {}
 class MB {}
@@ -379,57 +365,54 @@
 class T extends Object with MA, MB {
 }
 ''');
-    return waitForTasksFinished().then((_) {
-      return _getTypeHierarchy('T extends Object').then((items) {
-        expect(_toJson(items), [{
-            'classElement': {
-              'kind': 'CLASS',
-              'name': 'T',
-              'location': anything,
-              'flags': 0
-            },
-            'superclass': 1,
-            'interfaces': [],
-            'mixins': [2, 3],
-            'subclasses': []
-          }, {
-            'classElement': {
-              'kind': 'CLASS',
-              'name': 'Object',
-              'location': anything,
-              'flags': 0
-            },
-            'interfaces': [],
-            'mixins': [],
-            'subclasses': []
-          }, {
-            'classElement': {
-              'kind': 'CLASS',
-              'name': 'MA',
-              'location': anything,
-              'flags': 0
-            },
-            'superclass': 1,
-            'interfaces': [],
-            'mixins': [],
-            'subclasses': []
-          }, {
-            'classElement': {
-              'kind': 'CLASS',
-              'name': 'MB',
-              'location': anything,
-              'flags': 0
-            },
-            'superclass': 1,
-            'interfaces': [],
-            'mixins': [],
-            'subclasses': []
-          }]);
-      });
-    });
+    List<TypeHierarchyItem> items = await _getTypeHierarchy('T extends Object');
+    expect(_toJson(items), [{
+        'classElement': {
+          'kind': 'CLASS',
+          'name': 'T',
+          'location': anything,
+          'flags': 0
+        },
+        'superclass': 1,
+        'interfaces': [],
+        'mixins': [2, 3],
+        'subclasses': []
+      }, {
+        'classElement': {
+          'kind': 'CLASS',
+          'name': 'Object',
+          'location': anything,
+          'flags': 0
+        },
+        'interfaces': [],
+        'mixins': [],
+        'subclasses': []
+      }, {
+        'classElement': {
+          'kind': 'CLASS',
+          'name': 'MA',
+          'location': anything,
+          'flags': 0
+        },
+        'superclass': 1,
+        'interfaces': [],
+        'mixins': [],
+        'subclasses': []
+      }, {
+        'classElement': {
+          'kind': 'CLASS',
+          'name': 'MB',
+          'location': anything,
+          'flags': 0
+        },
+        'superclass': 1,
+        'interfaces': [],
+        'mixins': [],
+        'subclasses': []
+      }]);
   }
 
-  test_member_getter() {
+  test_member_getter() async {
     addTestFile('''
 class A {
   get test => null; // in A
@@ -443,31 +426,29 @@
   get test => null; // in D
 }
 ''');
-    return waitForTasksFinished().then((_) {
-      return _getTypeHierarchy('test => null; // in B').then((items) {
-        TypeHierarchyItem itemB = items[0];
-        TypeHierarchyItem itemA = items[itemB.superclass];
-        TypeHierarchyItem itemC = items[itemB.subclasses[0]];
-        TypeHierarchyItem itemD = items[itemC.subclasses[0]];
-        expect(itemA.classElement.name, 'A');
-        expect(itemB.classElement.name, 'B');
-        expect(itemC.classElement.name, 'C');
-        expect(itemD.classElement.name, 'D');
-        expect(
-            itemA.memberElement.location.offset,
-            findOffset('test => null; // in A'));
-        expect(
-            itemB.memberElement.location.offset,
-            findOffset('test => null; // in B'));
-        expect(itemC.memberElement, isNull);
-        expect(
-            itemD.memberElement.location.offset,
-            findOffset('test => null; // in D'));
-      });
-    });
+    List<TypeHierarchyItem> items =
+        await _getTypeHierarchy('test => null; // in B');
+    TypeHierarchyItem itemB = items[0];
+    TypeHierarchyItem itemA = items[itemB.superclass];
+    TypeHierarchyItem itemC = items[itemB.subclasses[0]];
+    TypeHierarchyItem itemD = items[itemC.subclasses[0]];
+    expect(itemA.classElement.name, 'A');
+    expect(itemB.classElement.name, 'B');
+    expect(itemC.classElement.name, 'C');
+    expect(itemD.classElement.name, 'D');
+    expect(
+        itemA.memberElement.location.offset,
+        findOffset('test => null; // in A'));
+    expect(
+        itemB.memberElement.location.offset,
+        findOffset('test => null; // in B'));
+    expect(itemC.memberElement, isNull);
+    expect(
+        itemD.memberElement.location.offset,
+        findOffset('test => null; // in D'));
   }
 
-  test_member_method() {
+  test_member_method() async {
     addTestFile('''
 class A {
   test() {} // in A
@@ -481,31 +462,29 @@
   test() {} // in D
 }
 ''');
-    return waitForTasksFinished().then((_) {
-      return _getTypeHierarchy('test() {} // in B').then((items) {
-        var itemB = items[0];
-        var itemA = items[itemB.superclass];
-        var itemC = items[itemB.subclasses[0]];
-        var itemD = items[itemC.subclasses[0]];
-        expect(itemA.classElement.name, 'A');
-        expect(itemB.classElement.name, 'B');
-        expect(itemC.classElement.name, 'C');
-        expect(itemD.classElement.name, 'D');
-        expect(
-            itemA.memberElement.location.offset,
-            findOffset('test() {} // in A'));
-        expect(
-            itemB.memberElement.location.offset,
-            findOffset('test() {} // in B'));
-        expect(itemC.memberElement, isNull);
-        expect(
-            itemD.memberElement.location.offset,
-            findOffset('test() {} // in D'));
-      });
-    });
+    List<TypeHierarchyItem> items =
+        await _getTypeHierarchy('test() {} // in B');
+    var itemB = items[0];
+    var itemA = items[itemB.superclass];
+    var itemC = items[itemB.subclasses[0]];
+    var itemD = items[itemC.subclasses[0]];
+    expect(itemA.classElement.name, 'A');
+    expect(itemB.classElement.name, 'B');
+    expect(itemC.classElement.name, 'C');
+    expect(itemD.classElement.name, 'D');
+    expect(
+        itemA.memberElement.location.offset,
+        findOffset('test() {} // in A'));
+    expect(
+        itemB.memberElement.location.offset,
+        findOffset('test() {} // in B'));
+    expect(itemC.memberElement, isNull);
+    expect(
+        itemD.memberElement.location.offset,
+        findOffset('test() {} // in D'));
   }
 
-  test_member_operator() {
+  test_member_operator() async {
     addTestFile('''
 class A {
   operator ==(x) => null; // in A
@@ -519,31 +498,29 @@
   operator ==(x) => null; // in D
 }
 ''');
-    return waitForTasksFinished().then((_) {
-      return _getTypeHierarchy('==(x) => null; // in B').then((items) {
-        var itemB = items[0];
-        var itemA = items[itemB.superclass];
-        var itemC = items[itemB.subclasses[0]];
-        var itemD = items[itemC.subclasses[0]];
-        expect(itemA.classElement.name, 'A');
-        expect(itemB.classElement.name, 'B');
-        expect(itemC.classElement.name, 'C');
-        expect(itemD.classElement.name, 'D');
-        expect(
-            itemA.memberElement.location.offset,
-            findOffset('==(x) => null; // in A'));
-        expect(
-            itemB.memberElement.location.offset,
-            findOffset('==(x) => null; // in B'));
-        expect(itemC.memberElement, isNull);
-        expect(
-            itemD.memberElement.location.offset,
-            findOffset('==(x) => null; // in D'));
-      });
-    });
+    List<TypeHierarchyItem> items =
+        await _getTypeHierarchy('==(x) => null; // in B');
+    var itemB = items[0];
+    var itemA = items[itemB.superclass];
+    var itemC = items[itemB.subclasses[0]];
+    var itemD = items[itemC.subclasses[0]];
+    expect(itemA.classElement.name, 'A');
+    expect(itemB.classElement.name, 'B');
+    expect(itemC.classElement.name, 'C');
+    expect(itemD.classElement.name, 'D');
+    expect(
+        itemA.memberElement.location.offset,
+        findOffset('==(x) => null; // in A'));
+    expect(
+        itemB.memberElement.location.offset,
+        findOffset('==(x) => null; // in B'));
+    expect(itemC.memberElement, isNull);
+    expect(
+        itemD.memberElement.location.offset,
+        findOffset('==(x) => null; // in D'));
   }
 
-  test_member_setter() {
+  test_member_setter() async {
     addTestFile('''
 class A {
   set test(x) {} // in A
@@ -557,28 +534,26 @@
   set test(x) {} // in D
 }
 ''');
-    return waitForTasksFinished().then((_) {
-      return _getTypeHierarchy('test(x) {} // in B').then((items) {
-        var itemB = items[0];
-        var itemA = items[itemB.superclass];
-        var itemC = items[itemB.subclasses[0]];
-        var itemD = items[itemC.subclasses[0]];
-        expect(itemA.classElement.name, 'A');
-        expect(itemB.classElement.name, 'B');
-        expect(itemC.classElement.name, 'C');
-        expect(itemD.classElement.name, 'D');
-        expect(
-            itemA.memberElement.location.offset,
-            findOffset('test(x) {} // in A'));
-        expect(
-            itemB.memberElement.location.offset,
-            findOffset('test(x) {} // in B'));
-        expect(itemC.memberElement, isNull);
-        expect(
-            itemD.memberElement.location.offset,
-            findOffset('test(x) {} // in D'));
-      });
-    });
+    List<TypeHierarchyItem> items =
+        await _getTypeHierarchy('test(x) {} // in B');
+    var itemB = items[0];
+    var itemA = items[itemB.superclass];
+    var itemC = items[itemB.subclasses[0]];
+    var itemD = items[itemC.subclasses[0]];
+    expect(itemA.classElement.name, 'A');
+    expect(itemB.classElement.name, 'B');
+    expect(itemC.classElement.name, 'C');
+    expect(itemD.classElement.name, 'D');
+    expect(
+        itemA.memberElement.location.offset,
+        findOffset('test(x) {} // in A'));
+    expect(
+        itemB.memberElement.location.offset,
+        findOffset('test(x) {} // in B'));
+    expect(itemC.memberElement, isNull);
+    expect(
+        itemD.memberElement.location.offset,
+        findOffset('test(x) {} // in D'));
   }
 
   Request _createGetTypeHierarchyRequest(String search) {
@@ -587,12 +562,13 @@
         findOffset(search)).toRequest(requestId);
   }
 
-  Future<List<TypeHierarchyItem>> _getTypeHierarchy(String search) {
+  Future<List<TypeHierarchyItem>> _getTypeHierarchy(String search) async {
+    await waitForTasksFinished();
     Request request = _createGetTypeHierarchyRequest(search);
-    return serverChannel.sendRequest(request).then((Response response) {
-      return new SearchGetTypeHierarchyResult.fromResponse(
-          response).hierarchyItems;
-    });
+    Response response = await serverChannel.sendRequest(request);
+    expect(serverErrors, isEmpty);
+    return new SearchGetTypeHierarchyResult.fromResponse(
+        response).hierarchyItems;
   }
 
   List _toJson(List<TypeHierarchyItem> items) {
diff --git a/pkg/analysis_server/test/services/completion/completion_target_test.dart b/pkg/analysis_server/test/services/completion/completion_target_test.dart
new file mode 100644
index 0000000..8decbb7
--- /dev/null
+++ b/pkg/analysis_server/test/services/completion/completion_target_test.dart
@@ -0,0 +1,107 @@
+// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library test.services.completion.target;
+
+import 'package:analysis_server/src/services/completion/completion_target.dart';
+import 'package:analyzer/src/generated/ast.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:unittest/unittest.dart';
+
+import '../../abstract_context.dart';
+import '../../reflective_tests.dart';
+
+main() {
+  groupSep = ' | ';
+  runReflectiveTests(CompletionTargetTest);
+}
+
+@reflectiveTest
+class CompletionTargetTest extends AbstractContextTest {
+  int completionOffset;
+  CompletionTarget target;
+
+  void addTestSource(String content) {
+    expect(completionOffset, isNull, reason: 'Call addTestSource exactly once');
+    completionOffset = content.indexOf('^');
+    expect(completionOffset, isNot(equals(-1)), reason: 'missing ^');
+    int nextOffset = content.indexOf('^', completionOffset + 1);
+    expect(nextOffset, equals(-1), reason: 'too many ^');
+    content = content.substring(0, completionOffset) +
+        content.substring(completionOffset + 1);
+    Source testSource = addSource('/test.dart', content);
+    CompilationUnit unit = context.parseCompilationUnit(testSource);
+    target = new CompletionTarget.forOffset(unit, completionOffset);
+  }
+
+  test_AsExpression_identifier() {
+    // SimpleIdentifier  TypeName  AsExpression
+    addTestSource('class A {var b; X _c; foo() {var a; (a^ as String).foo();}');
+    expect(target.entity.toString(), 'a as String');
+    expect(target.containingNode.toString(), '(a as String)');
+  }
+
+  test_AsExpression_keyword() {
+    // SimpleIdentifier  TypeName  AsExpression
+    addTestSource('class A {var b; X _c; foo() {var a; (a ^as String).foo();}');
+    expect(target.entity.toString(), 'as');
+    expect(target.containingNode.toString(), 'a as String');
+  }
+
+  test_AsExpression_keyword2() {
+    // SimpleIdentifier  TypeName  AsExpression
+    addTestSource('class A {var b; X _c; foo() {var a; (a a^s String).foo();}');
+    expect(target.entity.toString(), 'as');
+    expect(target.containingNode.toString(), 'a as String');
+  }
+
+  test_AsExpression_keyword3() {
+    // SimpleIdentifier  TypeName  AsExpression
+    addTestSource('class A {var b; X _c; foo() {var a; (a as^ String).foo();}');
+    expect(target.entity.toString(), 'as');
+    expect(target.containingNode.toString(), 'a as String');
+  }
+
+  test_AsExpression_type() {
+    // SimpleIdentifier  TypeName  AsExpression
+    addTestSource('class A {var b; X _c; foo() {var a; (a as ^String).foo();}');
+    expect(target.entity.toString(), 'String');
+    expect(target.containingNode.toString(), 'a as String');
+  }
+
+  test_InstanceCreationExpression_keyword() {
+    // InstanceCreationExpression  ExpressionStatement  Block
+    addTestSource('class C {foo(){var f; {var x;} new^ }}');
+    expect(target.entity.toString(), 'new ();');
+    expect(target.containingNode.toString(), '{var f; {var x;} new ();}');
+  }
+
+  test_InstanceCreationExpression_keyword2() {
+    // InstanceCreationExpression  ExpressionStatement  Block
+    addTestSource('class C {foo(){var f; {var x;} new^ C();}}');
+    expect(target.entity.toString(), 'new C();');
+    expect(target.containingNode.toString(), '{var f; {var x;} new C();}');
+  }
+
+  test_InstanceCreationExpression_identifier() {
+    // InstanceCreationExpression  ExpressionStatement  Block
+    addTestSource('class C {foo(){var f; {var x;} new ^C();}}');
+    expect(target.entity.toString(), 'C');
+    expect(target.containingNode.toString(), 'new C()');
+  }
+
+  test_VariableDeclaration_lhs_identifier_after() {
+    // VariableDeclaration  VariableDeclarationList
+    addTestSource('main() {int b^ = 1;}');
+    expect(target.entity.toString(), 'b = 1');
+    expect(target.containingNode.toString(), 'int b = 1');
+  }
+
+  test_VariableDeclaration_lhs_identifier_before() {
+    // VariableDeclaration  VariableDeclarationList
+    addTestSource('main() {int ^b = 1;}');
+    expect(target.entity.toString(), 'b = 1');
+    expect(target.containingNode.toString(), 'int b = 1');
+  }
+}
diff --git a/pkg/analysis_server/test/services/completion/completion_test_util.dart b/pkg/analysis_server/test/services/completion/completion_test_util.dart
index 6f14dc2..783d1a0 100644
--- a/pkg/analysis_server/test/services/completion/completion_test_util.dart
+++ b/pkg/analysis_server/test/services/completion/completion_test_util.dart
@@ -10,7 +10,6 @@
     ElementKind;
 import 'package:analysis_server/src/protocol.dart' hide Element, ElementKind;
 import 'package:analysis_server/src/services/completion/completion_manager.dart';
-import 'package:analysis_server/src/services/completion/completion_target.dart';
 import 'package:analysis_server/src/services/completion/dart_completion_cache.dart';
 import 'package:analysis_server/src/services/completion/dart_completion_manager.dart';
 import 'package:analysis_server/src/services/completion/imported_computer.dart';
@@ -45,6 +44,7 @@
   bool _computeFastCalled = false;
   DartCompletionRequest request;
   DartCompletionCache cache;
+  DartCompletionManager _completionManager;
 
   void addResolvedUnit(String file, String code) {
     Source source = addSource(file, code);
@@ -485,13 +485,16 @@
 
   bool computeFast() {
     _computeFastCalled = true;
-    testUnit = context.parseCompilationUnit(testSource);
-    completionNode =
-        new NodeLocator.con1(completionOffset).searchWithin(testUnit);
-    request.unit = testUnit;
-    request.node = completionNode;
-    request.target = new CompletionTarget.forOffset(testUnit, completionOffset);
-    return computer.computeFast(request);
+    _completionManager = new DartCompletionManager(
+        context,
+        searchEngine,
+        testSource,
+        cache,
+        [computer]);
+    var result = _completionManager.computeFast(request);
+    expect(request.replacementOffset, isNotNull);
+    expect(request.replacementLength, isNotNull);
+    return result.isEmpty;
   }
 
   Future computeFull(assertFunction(bool result), {bool fullAnalysis: true}) {
@@ -531,16 +534,6 @@
             request.unit = unit;
             request.node =
                 new NodeLocator.con1(completionOffset).searchWithin(unit);
-            if (request.node is SimpleIdentifier) {
-              request.replacementOffset = request.node.offset;
-              request.replacementLength = request.node.length;
-            } else {
-              request.replacementOffset = request.offset;
-              request.replacementLength = 0;
-            }
-            if (request.replacementOffset == null) {
-              fail('expected non null');
-            }
             resolved = true;
             if (!fullAnalysis) {
               break;
@@ -891,6 +884,8 @@
       void main() {expect(^)}''');
     computeFast();
     return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset);
+      expect(request.replacementLength, 0);
       assertNoSuggestions(kind: CompletionSuggestionKind.ARGUMENT_LIST);
       assertSuggestLocalFunction('bar', 'String');
       assertSuggestImportedFunction('hasLength', 'bool');
@@ -917,6 +912,8 @@
       void main() {expect(^)}''');
     computeFast();
     return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset);
+      expect(request.replacementLength, 0);
       assertNoSuggestions(kind: CompletionSuggestionKind.ARGUMENT_LIST);
       assertSuggestLocalFunction('bar', 'String');
       assertSuggestImportedFunction('hasLength', 'bool');
@@ -943,6 +940,8 @@
       void main() {expect(^)}''');
     computeFast();
     return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset);
+      expect(request.replacementLength, 0);
       assertNoSuggestions(kind: CompletionSuggestionKind.ARGUMENT_LIST);
       assertSuggestLocalFunction('bar', 'String');
       assertSuggestImportedFunction('hasLength', 'bool');
@@ -969,6 +968,8 @@
       String bar() => true;''');
     computeFast();
     return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset);
+      expect(request.replacementLength, 0);
       assertNoSuggestions(kind: CompletionSuggestionKind.ARGUMENT_LIST);
       assertSuggestLocalFunction('bar', 'String');
       assertSuggestImportedFunction('hasLength', 'bool');
@@ -993,6 +994,8 @@
       void main() {expect(foo: ^)}''');
     computeFast();
     return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset);
+      expect(request.replacementLength, 0);
       assertSuggestLocalFunction('bar', 'String');
       assertSuggestImportedFunction('hasLength', 'bool');
       assertNotSuggested('main');
@@ -1005,6 +1008,8 @@
       class A {var b; X _c; foo() {var a; (a as ^).foo();}''');
     computeFast();
     return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset);
+      expect(request.replacementLength, 0);
       assertNotSuggested('b');
       assertNotSuggested('_c');
       assertSuggestImportedClass('Object');
@@ -1029,6 +1034,8 @@
     addTestSource('class A {} main() {int a; int b = ^}');
     computeFast();
     return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset);
+      expect(request.replacementLength, 0);
       assertSuggestLocalVariable('a', 'int');
       assertSuggestLocalFunction('main', null);
       assertSuggestLocalClass('A');
@@ -1045,6 +1052,8 @@
         ^ b = 1;}''');
     computeFast();
     return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset);
+      expect(request.replacementLength, 0);
       assertSuggestLocalClass('A');
       assertSuggestImportedClass('int');
       // TODO (danrubel) When entering 1st of 2 identifiers on assignment LHS
@@ -1068,6 +1077,8 @@
         b = 1;}''');
     computeFast();
     return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset);
+      expect(request.replacementLength, 0);
       assertSuggestLocalClass('A');
       assertSuggestImportedClass('int');
       // Allow non-types preceding an identifier on LHS of assignment
@@ -1088,6 +1099,8 @@
         int^ b = 1;}''');
     computeFast();
     return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset - 3);
+      expect(request.replacementLength, 3);
       assertSuggestLocalClass('A');
       assertSuggestImportedClass('int');
       // TODO (danrubel) When entering 1st of 2 identifiers on assignment LHS
@@ -1111,6 +1124,8 @@
         b = 1;}''');
     computeFast();
     return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset - 1);
+      expect(request.replacementLength, 1);
       assertSuggestLocalClass('A');
       assertSuggestImportedClass('int');
       // Allow non-types preceding an identifier on LHS of assignment
@@ -1126,9 +1141,11 @@
     // SimpleIdentifier  AwaitExpression  ExpressionStatement
     addTestSource('''
       class A {int x; int y() => 0;}
-      main(){A a; await ^}''');
+      main() async {A a; await ^}''');
     computeFast();
     return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset);
+      expect(request.replacementLength, 0);
       assertSuggestLocalVariable('a', 'A');
       assertSuggestLocalFunction('main', null);
       assertSuggestLocalClass('A');
@@ -1142,6 +1159,8 @@
     addTestSource('main() {int a = 1, b = ^ + 2;}');
     computeFast();
     return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset);
+      expect(request.replacementLength, 0);
       assertSuggestLocalVariable('a', 'int');
       assertSuggestImportedClass('Object');
       assertNotSuggested('b');
@@ -1154,6 +1173,8 @@
     addTestSource('main() {int a = 1, b = 2 + ^;}');
     computeFast();
     return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset);
+      expect(request.replacementLength, 0);
       assertSuggestLocalVariable('a', 'int');
       assertSuggestImportedClass('Object');
       assertNotSuggested('b');
@@ -1204,6 +1225,8 @@
       class Z { }''');
     computeFast();
     return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset);
+      expect(request.replacementLength, 0);
 
       assertSuggestLocalClass('X');
       assertSuggestLocalClass('Z');
@@ -1284,6 +1307,8 @@
       class Z { }''');
     computeFast();
     return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset - 1);
+      expect(request.replacementLength, 1);
 
       assertSuggestLocalClass('X');
       assertSuggestLocalClass('Z');
@@ -1340,6 +1365,8 @@
       class A extends E implements I with M {a() {^}}''');
     computeFast();
     return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset);
+      expect(request.replacementLength, 0);
       // TODO (danrubel) prefer fields over getters
       // If add `get e1;` to interface I
       // then suggestions include getter e1 rather than field e1
@@ -1367,6 +1394,8 @@
       class A extends E implements I with M {a() {^}}''');
     computeFast();
     return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset);
+      expect(request.replacementLength, 0);
       assertSuggestLocalField('e1', null);
       assertSuggestLocalField('f1', null);
       assertSuggestLocalField('i1', 'int');
@@ -1393,6 +1422,8 @@
       main() {A a; a.^.z}''');
     computeFast();
     return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset);
+      expect(request.replacementLength, 0);
       assertSuggestInvocationField('b', null);
       assertSuggestInvocationField('_c', 'X');
       assertNotSuggested('Object');
@@ -1415,6 +1446,8 @@
       main() {A a; a..^z}''');
     computeFast();
     return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset);
+      expect(request.replacementLength, 1);
       assertSuggestInvocationField('b', null);
       assertSuggestInvocationField('_c', 'X');
       assertNotSuggested('Object');
@@ -1437,6 +1470,8 @@
       main() {A a; a..^ return}''');
     computeFast();
     return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset);
+      expect(request.replacementLength, 0);
       assertSuggestInvocationField('b', null);
       assertSuggestInvocationField('_c', 'X');
       assertNotSuggested('Object');
@@ -1456,6 +1491,8 @@
       main() {A a; a^..b}''');
     computeFast();
     return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset - 1);
+      expect(request.replacementLength, 1);
       assertNotSuggested('b');
       assertNotSuggested('_c');
       assertSuggestLocalVariable('a', 'A');
@@ -1472,6 +1509,8 @@
     addTestSource('class A {a() {try{var x;} on E catch (e) {^}}}');
     computeFast();
     return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset);
+      expect(request.replacementLength, 0);
       assertSuggestParameter('e', 'E');
       assertSuggestLocalMethod('a', 'A', null);
       assertSuggestImportedClass('Object');
@@ -1484,6 +1523,8 @@
     addTestSource('class A {a() {try{var x;} catch (e, s) {^}}}');
     computeFast();
     return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset);
+      expect(request.replacementLength, 0);
       assertSuggestParameter('e', null);
       assertSuggestParameter('s', 'StackTrace');
       assertSuggestLocalMethod('a', 'A', null);
@@ -1503,6 +1544,8 @@
       A T;''');
     computeFast();
     return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset);
+      expect(request.replacementLength, 0);
       CompletionSuggestion suggestionA = assertSuggestLocalClass(
           'A',
           relevance: COMPLETION_RELEVANCE_LOW,
@@ -1584,6 +1627,8 @@
       class A {var b; X _c; foo() {A a; if (^) something}}''');
     computeFast();
     return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset);
+      expect(request.replacementLength, 0);
       assertSuggestLocalField('b', null);
       assertSuggestLocalField('_c', 'X');
       assertSuggestImportedClass('Object');
@@ -1598,6 +1643,8 @@
       main() {var a; if (a.^) something}''');
     computeFast();
     return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset);
+      expect(request.replacementLength, 0);
       assertSuggestInvocationMethod('toString', 'Object', 'String');
       //TODO (danrubel) type for '_c' should be 'X' not null
       assertNotSuggested('Object');
@@ -1620,6 +1667,8 @@
       main() {new X.^}''');
     computeFast();
     return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset);
+      expect(request.replacementLength, 0);
       assertSuggestNamedConstructor('c', 'X');
       assertNotSuggested('F1');
       assertNotSuggested('T1');
@@ -1643,6 +1692,8 @@
       main() {new X.^}''');
     computeFast();
     return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset);
+      expect(request.replacementLength, 0);
       assertSuggestNamedConstructor('c', 'X');
       assertNotSuggested('F1');
       assertNotSuggested('T1');
@@ -1659,6 +1710,8 @@
       main() {new String.fr^omCharCodes([]);}''');
     computeFast();
     return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset - 2);
+      expect(request.replacementLength, 13);
       assertSuggestNamedConstructor('fromCharCodes', 'String');
       assertNotSuggested('isEmpty');
       assertNotSuggested('isNotEmpty');
@@ -1678,6 +1731,8 @@
       main() {new X.^}''');
     computeFast();
     return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset);
+      expect(request.replacementLength, 0);
       assertSuggestNamedConstructor('c', 'X');
       assertSuggestNamedConstructor('_d', 'X');
       assertNotSuggested('F1');
@@ -1697,6 +1752,8 @@
       main() {new X.^}''');
     computeFast();
     return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset);
+      expect(request.replacementLength, 0);
       assertSuggestNamedConstructor('c', 'X');
       assertSuggestNamedConstructor('_d', 'X');
       assertNotSuggested('F1');
@@ -1719,6 +1776,8 @@
       class C {foo(){^} void bar() {}}''');
     computeFast();
     return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset);
+      expect(request.replacementLength, 0);
       assertSuggestImportedClass('A');
       assertSuggestImportedFunction('F1', '_B', false);
       assertSuggestLocalClass('C');
@@ -1777,6 +1836,8 @@
     addTestSource('main(args) {for (int foo in bar) {^}}');
     computeFast();
     return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset);
+      expect(request.replacementLength, 0);
       assertSuggestLocalVariable('foo', 'int');
       assertSuggestImportedClass('Object');
     });
@@ -1787,6 +1848,8 @@
     addTestSource('main(args) {for (foo in bar) {^}}');
     computeFast();
     return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset);
+      expect(request.replacementLength, 0);
       assertSuggestLocalVariable('foo', null);
       assertSuggestImportedClass('Object');
     });
@@ -1800,6 +1863,8 @@
       class A {a(^) { }}''');
     computeFast();
     return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset);
+      expect(request.replacementLength, 0);
       assertSuggestLocalFunction('foo', null);
       assertSuggestLocalMethod('a', 'A', null);
       assertSuggestLocalClass('A');
@@ -1814,6 +1879,8 @@
     addTestSource('main(args) {for (int i; i < 10; ++i) {^}}');
     computeFast();
     return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset);
+      expect(request.replacementLength, 0);
       assertSuggestLocalVariable('i', 'int');
       assertSuggestImportedClass('Object');
     });
@@ -1824,6 +1891,8 @@
     addTestSource('main() {for (int index = 0; i^)}');
     computeFast();
     return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset - 1);
+      expect(request.replacementLength, 1);
       assertSuggestLocalVariable('index', 'int');
     });
   }
@@ -1833,6 +1902,8 @@
     addTestSource('main() {List a; for (^)}');
     computeFast();
     return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset);
+      expect(request.replacementLength, 0);
       assertSuggestLocalVariable('a', 'List');
       assertSuggestImportedClass('Object');
       assertSuggestImportedClass('int');
@@ -1844,6 +1915,8 @@
     addTestSource('main() {for (int index = 0; index < 10; i^)}');
     computeFast();
     return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset - 1);
+      expect(request.replacementLength, 1);
       assertSuggestLocalVariable('index', 'int');
     });
   }
@@ -1855,6 +1928,8 @@
       main() {for (int index = 0; index < 10; ++i^)}''');
     computeFast();
     return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset - 1);
+      expect(request.replacementLength, 1);
       assertSuggestLocalVariable('index', 'int');
       assertSuggestLocalFunction('main', null);
       assertNotSuggested('bar');
@@ -1868,6 +1943,8 @@
       String foo(List args) {x.then((R b) {^});}''');
     computeFast();
     return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset);
+      expect(request.replacementLength, 0);
       var f = assertSuggestLocalFunction('foo', 'String', false);
       if (f != null) {
         expect(f.element.isPrivate, isFalse);
@@ -1886,6 +1963,8 @@
       main(){var a; if (^)}''');
     computeFast();
     return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset);
+      expect(request.replacementLength, 0);
       assertSuggestLocalVariable('a', null);
       assertSuggestLocalFunction('main', null);
       assertSuggestLocalClass('A');
@@ -1918,6 +1997,8 @@
       class C {foo(){var f; {var x;} new ^}}''');
     computeFast();
     return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset);
+      expect(request.replacementLength, 0);
       assertSuggestImportedClass('Object');
       assertSuggestImportedClass('A');
       assertSuggestLocalClass('B');
@@ -1937,6 +2018,8 @@
     addTestSource('main() {String name; print("hello \$^");}');
     computeFast();
     return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset);
+      expect(request.replacementLength, 0);
       assertSuggestLocalVariable('name', 'String');
       assertSuggestImportedClass('Object');
     });
@@ -1958,6 +2041,8 @@
     addTestSource('main() {String name; print("hello \${name.^}");}');
     computeFast();
     return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset);
+      expect(request.replacementLength, 0);
       assertSuggestInvocationGetter('length', 'int');
       assertNotSuggested('name');
       assertNotSuggested('Object');
@@ -1989,6 +2074,8 @@
       main() {var x; if (x is ^) { }}''');
     computeFast();
     return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset);
+      expect(request.replacementLength, 0);
       assertSuggestImportedClass('X');
       assertSuggestLocalClass('Y');
       assertNotSuggested('x');
@@ -2006,6 +2093,8 @@
       main(){var a; if (^ is A)}''');
     computeFast();
     return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset);
+      expect(request.replacementLength, 0);
       assertSuggestLocalVariable('a', null);
       assertSuggestLocalFunction('main', null);
       assertSuggestLocalFunction('foo', null);
@@ -2022,6 +2111,8 @@
       main(){var a; if (a is ^)}''');
     computeFast();
     return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset);
+      expect(request.replacementLength, 0);
       assertNotSuggested('a');
       assertNotSuggested('main');
       assertSuggestLocalClass('A');
@@ -2036,6 +2127,8 @@
       main(){var a; if (a is Obj^)}''');
     computeFast();
     return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset - 3);
+      expect(request.replacementLength, 3);
       assertNotSuggested('a');
       assertNotSuggested('main');
       assertSuggestLocalClass('A');
@@ -2043,6 +2136,35 @@
     });
   }
 
+  test_keyword() {
+    addSource('/testB.dart', '''
+      lib B;
+      int newT1;
+      int T1;
+      nowIsIt() { }
+      class X {factory X.c(); factory X._d(); z() {}}''');
+    addTestSource('''
+      import "/testB.dart";
+      String newer() {}
+      var m;
+      main() {new^ X.c();}''');
+    computeFast();
+    return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset - 3);
+      expect(request.replacementLength, 3);
+      assertNotSuggested('c');
+      assertNotSuggested('_d');
+      // Imported suggestion are filtered by 1st character
+      assertSuggestImportedFunction('nowIsIt', null);
+      assertNotSuggested('T1');
+      // TODO (danrubel) this really should be TopLevelVar not getter/setter
+      assertSuggestTopLevelVarGetterSetter('newT1', 'int');
+      assertNotSuggested('z');
+      assertSuggestLocalTopLevelVar('m', 'dynamic');
+      assertSuggestLocalFunction('newer', 'String');
+    });
+  }
+
   test_Literal_string() {
     // SimpleStringLiteral  ExpressionStatement  Block
     addTestSource('class A {a() {"hel^lo"}}');
@@ -2057,6 +2179,8 @@
     addTestSource('class A {@deprecated X get f => 0; Z a() {^} get _g => 1;}');
     computeFast();
     return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset);
+      expect(request.replacementLength, 0);
       CompletionSuggestion methodA = assertSuggestLocalMethod('a', 'A', 'Z');
       if (methodA != null) {
         expect(methodA.element.isDeprecated, isFalse);
@@ -2084,6 +2208,8 @@
     addTestSource('class A {@deprecated X f; Z _a() {^} var _g;}');
     computeFast();
     return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset);
+      expect(request.replacementLength, 0);
       CompletionSuggestion methodA = assertSuggestLocalMethod('_a', 'A', 'Z');
       if (methodA != null) {
         expect(methodA.element.isDeprecated, isFalse);
@@ -2114,6 +2240,8 @@
     addTestSource('class A {@deprecated Z a(X x, _, b, {y: boo}) {^}}');
     computeFast();
     return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset);
+      expect(request.replacementLength, 0);
       CompletionSuggestion methodA = assertSuggestLocalMethod(
           'a',
           'A',
@@ -2140,6 +2268,8 @@
       class A {Z a(X x, [int y=1]) {^}}''');
     computeFast();
     return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset);
+      expect(request.replacementLength, 0);
       assertSuggestLocalFunction('foo', null);
       assertSuggestLocalFunction('bar', 'void');
       assertSuggestLocalMethod('a', 'A', 'Z');
@@ -2163,6 +2293,8 @@
       class X{}''');
     computeFast();
     return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset);
+      expect(request.replacementLength, 0);
       assertSuggestInvocationGetter('f', 'X');
       assertSuggestInvocationGetter('_g', null);
       assertNotSuggested('b');
@@ -2200,6 +2332,8 @@
       main() {new ^}''');
     computeFast();
     return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset);
+      expect(request.replacementLength, 0);
       assertSuggestLocalClass('B');
       assertSuggestImportedClass('Object');
       assertSuggestImportedClass('X');
@@ -2231,6 +2365,8 @@
       var m;''');
     computeFast();
     return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset);
+      expect(request.replacementLength, 0);
       assertSuggestLocalClass('A');
       assertSuggestImportedClass('Object');
       assertSuggestImportedClass('X');
@@ -2266,6 +2402,8 @@
       main() {A.^}''');
     computeFast();
     return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset);
+      expect(request.replacementLength, 0);
       assertSuggestInvocationField('scA', 'String');
       assertSuggestInvocationField('scB', 'int');
       assertSuggestInvocationField('scI', null);
@@ -2305,6 +2443,8 @@
       main() {A a; a.^}''');
     computeFast();
     return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset);
+      expect(request.replacementLength, 0);
       assertSuggestInvocationField('sc', 'int');
       assertSuggestInvocationField('b', null, isDeprecated: true);
       assertNotSuggested('_c');
@@ -2338,6 +2478,8 @@
       class X{}''');
     computeFast();
     return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset);
+      expect(request.replacementLength, 0);
       assertSuggestInvocationField('sc', 'int');
       assertSuggestInvocationField('b', null);
       assertSuggestInvocationField('_c', 'X');
@@ -2371,6 +2513,8 @@
       main() {b.^}''');
     computeFast();
     return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset);
+      expect(request.replacementLength, 0);
       assertSuggestInvocationClass('X');
       assertSuggestInvocationClass('Y');
       assertSuggestInvocationTopLevelVar('T1', null);
@@ -2394,6 +2538,8 @@
       foo(X x) {x.^}''');
     computeFast();
     return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset);
+      expect(request.replacementLength, 0);
       assertSuggestInvocationField('y', 'M');
       assertNotSuggested('_z');
       assertNotSuggested('==');
@@ -2410,6 +2556,8 @@
       class X {foo(){A^.bar}}''');
     computeFast();
     return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset - 1);
+      expect(request.replacementLength, 1);
       assertSuggestImportedClass('A');
       assertSuggestLocalClass('X');
       assertSuggestLocalMethod('foo', 'X', null);
@@ -2423,6 +2571,8 @@
     addTestSource('class A {String x; int get foo {x.^}');
     computeFast();
     return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset);
+      expect(request.replacementLength, 0);
       assertSuggestInvocationGetter('isEmpty', 'bool');
       assertSuggestInvocationMethod('compareTo', 'Comparable', 'int');
     });
@@ -2433,6 +2583,8 @@
     addTestSource('class A {String x; int get foo {x.^ int y = 0;}');
     computeFast();
     return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset);
+      expect(request.replacementLength, 0);
       assertSuggestInvocationGetter('isEmpty', 'bool');
       assertSuggestInvocationMethod('compareTo', 'Comparable', 'int');
     });
@@ -2443,6 +2595,8 @@
     addTestSource('class A {a() {"hello".to^String().length}}');
     computeFast();
     return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset - 2);
+      expect(request.replacementLength, 8);
       assertSuggestInvocationGetter('length', 'int');
       assertNotSuggested('A');
       assertNotSuggested('a');
@@ -2456,6 +2610,8 @@
     addTestSource('class A {a() {"hello".length.^}}');
     computeFast();
     return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset);
+      expect(request.replacementLength, 0);
       assertSuggestInvocationGetter('isEven', 'bool');
       assertNotSuggested('A');
       assertNotSuggested('a');
@@ -2480,6 +2636,8 @@
       class X{}''');
     computeFast();
     return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset);
+      expect(request.replacementLength, 0);
       assertSuggestInvocationField('b', null);
       assertSuggestInvocationField('_c', 'X');
       assertSuggestInvocationGetter('d', 'X');
@@ -2515,6 +2673,8 @@
       class X{}''');
     computeFast();
     return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset);
+      expect(request.replacementLength, 0);
       assertSuggestInvocationField('b', null);
       assertSuggestInvocationField('_c', 'X');
       assertSuggestInvocationGetter('d', 'X');
@@ -2586,6 +2746,8 @@
       class C {bar(){var f; {var x;} var e = ^}}''');
     computeFast();
     return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset);
+      expect(request.replacementLength, 0);
       assertSuggestImportedClass('X');
       assertNotSuggested('_B');
       assertSuggestLocalClass('Y');
@@ -2613,6 +2775,8 @@
       class C {bar(){var f; {var x;} var e = ^ var g}}''');
     computeFast();
     return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset);
+      expect(request.replacementLength, 0);
       assertSuggestImportedClass('X');
       assertSuggestImportedFunction('foo1', null);
       assertNotSuggested('bar1');
diff --git a/pkg/analysis_server/test/services/completion/imported_computer_test.dart b/pkg/analysis_server/test/services/completion/imported_computer_test.dart
index 74338da..9c20f67 100644
--- a/pkg/analysis_server/test/services/completion/imported_computer_test.dart
+++ b/pkg/analysis_server/test/services/completion/imported_computer_test.dart
@@ -478,6 +478,32 @@
     });
   }
 
+  test_mixin_ordering() {
+    // TODO(paulberry): The mixins are visited in the correct order, so we see
+    // M2.m() before M1.m(), as we should.  But the second (shadowed) result
+    // isn't being thrown out as it should.
+    addSource('/libA.dart', '''
+class B {}
+class M1 {
+  void m() {}
+}
+class M2 {
+  void m() {}
+}
+''');
+    addTestSource('''
+import '/libA.dart';
+class C extends B with M1, M2 {
+  void f() {
+    ^
+  }
+}
+''');
+    return computeFull((bool result) {
+      assertSuggestMethod('m', 'M2', 'void');
+    });
+  }
+
   /**
    * Ensure that completions in one context don't appear in another
    */
diff --git a/pkg/analysis_server/test/services/completion/keyword_computer_test.dart b/pkg/analysis_server/test/services/completion/keyword_computer_test.dart
index c2156c6..9075d36 100644
--- a/pkg/analysis_server/test/services/completion/keyword_computer_test.dart
+++ b/pkg/analysis_server/test/services/completion/keyword_computer_test.dart
@@ -21,8 +21,8 @@
 @reflectiveTest
 class KeywordComputerTest extends AbstractCompletionTest {
 
-  void assertSuggestKeywords(Iterable<Keyword> expectedKeywords,
-      [int relevance = COMPLETION_RELEVANCE_DEFAULT]) {
+  void assertSuggestKeywords(Iterable<Keyword> expectedKeywords, [int relevance
+      = COMPLETION_RELEVANCE_DEFAULT]) {
     Set<Keyword> actualKeywords = new Set<Keyword>();
     request.suggestions.forEach((CompletionSuggestion s) {
       if (s.kind == CompletionSuggestionKind.KEYWORD) {
@@ -34,7 +34,7 @@
             fail('Duplicate keyword suggested: ${s.completion}');
           }
         }
-        expect(s.relevance, equals(relevance));
+        expect(s.relevance, equals(relevance), reason: k.toString());
         expect(s.selectionOffset, equals(s.completion.length));
         expect(s.selectionLength, equals(0));
         expect(s.isDeprecated, equals(false));
@@ -79,6 +79,54 @@
         COMPLETION_RELEVANCE_HIGH);
   }
 
+  test_after_class2() {
+    addTestSource('class A {} c^');
+    expect(computeFast(), isTrue);
+    assertSuggestKeywords(
+        [
+            Keyword.ABSTRACT,
+            Keyword.CLASS,
+            Keyword.CONST,
+            Keyword.FINAL,
+            Keyword.TYPEDEF,
+            Keyword.VAR],
+        COMPLETION_RELEVANCE_HIGH);
+  }
+
+  test_after_import() {
+    addTestSource('import foo; ^');
+    expect(computeFast(), isTrue);
+    assertSuggestKeywords(
+        [
+            Keyword.ABSTRACT,
+            Keyword.CLASS,
+            Keyword.CONST,
+            Keyword.EXPORT,
+            Keyword.FINAL,
+            Keyword.IMPORT,
+            Keyword.PART,
+            Keyword.TYPEDEF,
+            Keyword.VAR],
+        COMPLETION_RELEVANCE_HIGH);
+  }
+
+  test_after_import2() {
+    addTestSource('import foo; c^');
+    expect(computeFast(), isTrue);
+    assertSuggestKeywords(
+        [
+            Keyword.ABSTRACT,
+            Keyword.CLASS,
+            Keyword.CONST,
+            Keyword.EXPORT,
+            Keyword.FINAL,
+            Keyword.IMPORT,
+            Keyword.PART,
+            Keyword.TYPEDEF,
+            Keyword.VAR],
+        COMPLETION_RELEVANCE_HIGH);
+  }
+
   test_before_import() {
     addTestSource('^ import foo;');
     expect(computeFast(), isTrue);
@@ -95,6 +143,22 @@
         COMPLETION_RELEVANCE_HIGH);
   }
 
+  test_class2() {
+    addTestSource('class A e^');
+    expect(computeFast(), isTrue);
+    assertSuggestKeywords(
+        [Keyword.EXTENDS, Keyword.IMPLEMENTS],
+        COMPLETION_RELEVANCE_HIGH);
+  }
+
+  test_class3() {
+    addTestSource('class A e^ { }');
+    expect(computeFast(), isTrue);
+    assertSuggestKeywords(
+        [Keyword.EXTENDS, Keyword.IMPLEMENTS],
+        COMPLETION_RELEVANCE_HIGH);
+  }
+
   test_class_extends() {
     addTestSource('class A extends foo ^');
     expect(computeFast(), isTrue);
@@ -103,6 +167,22 @@
         COMPLETION_RELEVANCE_HIGH);
   }
 
+  test_class_extends2() {
+    addTestSource('class A extends foo i^');
+    expect(computeFast(), isTrue);
+    assertSuggestKeywords(
+        [Keyword.IMPLEMENTS, Keyword.WITH],
+        COMPLETION_RELEVANCE_HIGH);
+  }
+
+  test_class_extends3() {
+    addTestSource('class A extends foo i^ { }');
+    expect(computeFast(), isTrue);
+    assertSuggestKeywords(
+        [Keyword.IMPLEMENTS, Keyword.WITH],
+        COMPLETION_RELEVANCE_HIGH);
+  }
+
   test_class_extends_name() {
     addTestSource('class A extends ^');
     expect(computeFast(), isTrue);
@@ -115,6 +195,24 @@
     assertSuggestKeywords([Keyword.EXTENDS], COMPLETION_RELEVANCE_HIGH);
   }
 
+  test_class_implements2() {
+    addTestSource('class A e^ implements foo');
+    expect(computeFast(), isTrue);
+    // TODO (danrubel) refinement: don't suggest implements
+    assertSuggestKeywords(
+        [Keyword.EXTENDS, Keyword.IMPLEMENTS],
+        COMPLETION_RELEVANCE_HIGH);
+  }
+
+  test_class_implements3() {
+    addTestSource('class A e^ implements foo { }');
+    expect(computeFast(), isTrue);
+    // TODO (danrubel) refinement: don't suggest implements
+    assertSuggestKeywords(
+        [Keyword.EXTENDS, Keyword.IMPLEMENTS],
+        COMPLETION_RELEVANCE_HIGH);
+  }
+
   test_class_implements_name() {
     addTestSource('class A implements ^');
     expect(computeFast(), isTrue);
@@ -127,6 +225,24 @@
     assertSuggestKeywords([]);
   }
 
+  test_class_with() {
+    addTestSource('class A extends foo with bar ^');
+    expect(computeFast(), isTrue);
+    assertSuggestKeywords([Keyword.IMPLEMENTS], COMPLETION_RELEVANCE_HIGH);
+  }
+
+  test_class_with2() {
+    addTestSource('class A extends foo with bar i^');
+    expect(computeFast(), isTrue);
+    assertSuggestKeywords([Keyword.IMPLEMENTS], COMPLETION_RELEVANCE_HIGH);
+  }
+
+  test_class_with3() {
+    addTestSource('class A extends foo with bar i^ { }');
+    expect(computeFast(), isTrue);
+    assertSuggestKeywords([Keyword.IMPLEMENTS], COMPLETION_RELEVANCE_HIGH);
+  }
+
   test_class_with_name() {
     addTestSource('class A extends foo with ^');
     expect(computeFast(), isTrue);
@@ -177,6 +293,32 @@
             Keyword.WHILE]);
   }
 
+  test_function_body2() {
+    addTestSource('main() {{}^}');
+    expect(computeFast(), isTrue);
+    assertSuggestKeywords(
+        [
+            Keyword.ASSERT,
+            Keyword.CASE,
+            Keyword.CONTINUE,
+            Keyword.DO,
+            Keyword.FACTORY,
+            Keyword.FINAL,
+            Keyword.FOR,
+            Keyword.IF,
+            Keyword.NEW,
+            Keyword.RETHROW,
+            Keyword.RETURN,
+            Keyword.SUPER,
+            Keyword.SWITCH,
+            Keyword.THIS,
+            Keyword.THROW,
+            Keyword.TRY,
+            Keyword.VAR,
+            Keyword.VOID,
+            Keyword.WHILE]);
+  }
+
   test_in_class() {
     addTestSource('class A {^}');
     expect(computeFast(), isTrue);
diff --git a/pkg/analysis_server/test/services/completion/local_computer_test.dart b/pkg/analysis_server/test/services/completion/local_computer_test.dart
index 2a8e869..86b54ab 100644
--- a/pkg/analysis_server/test/services/completion/local_computer_test.dart
+++ b/pkg/analysis_server/test/services/completion/local_computer_test.dart
@@ -61,6 +61,27 @@
         isDeprecated: isDeprecated);
   }
 
+  fail_mixin_ordering() {
+    // TODO(paulberry): Duplicates aren't being removed, so we see both M1.m()
+    // and M2.m().
+    addTestSource('''
+class B {}
+class M1 {
+  void m() {}
+}
+class M2 {
+  void m() {}
+}
+class C extends B with M1, M2 {
+  void f() {
+    ^
+  }
+}
+''');
+    expect(computeFast(), isTrue);
+    assertSuggestMethod('m', 'M2', 'void');
+  }
+
   @override
   void setUpComputer() {
     computer = new LocalComputer();
diff --git a/pkg/analysis_server/test/services/completion/optype_test.dart b/pkg/analysis_server/test/services/completion/optype_test.dart
index eb37281..9e6d8e0 100644
--- a/pkg/analysis_server/test/services/completion/optype_test.dart
+++ b/pkg/analysis_server/test/services/completion/optype_test.dart
@@ -153,7 +153,7 @@
 
   test_AwaitExpression() {
     // SimpleIdentifier  AwaitExpression  ExpressionStatement
-    addTestSource('main(){A a; await ^}');
+    addTestSource('main() async {A a; await ^}');
     assertOpType(returnValue: true, typeNames: true);
   }
 
@@ -473,6 +473,24 @@
     assertOpType(typeNames: true);
   }
 
+  test_InstanceCreationExpression_keyword() {
+    // InstanceCreationExpression  ExpressionStatement  Block
+    addTestSource('class C {foo(){var f; {var x;} new^ }}');
+    assertOpType(
+        returnValue: true,
+        typeNames: true,
+        voidReturn: true);
+  }
+
+  test_InstanceCreationExpression_keyword2() {
+    // InstanceCreationExpression  ExpressionStatement  Block
+    addTestSource('class C {foo(){var f; {var x;} new^ C();}}');
+    assertOpType(
+        returnValue: true,
+        typeNames: true,
+        voidReturn: true);
+  }
+
   test_InterpolationExpression() {
     // SimpleIdentifier  InterpolationExpression  StringInterpolation
     addTestSource('main() {String name; print("hello \$^");}');
diff --git a/pkg/analysis_server/test/services/completion/test_all.dart b/pkg/analysis_server/test/services/completion/test_all.dart
index e1fb92c..ef908ff 100644
--- a/pkg/analysis_server/test/services/completion/test_all.dart
+++ b/pkg/analysis_server/test/services/completion/test_all.dart
@@ -10,6 +10,7 @@
 import 'combinator_computer_test.dart' as combinator_test;
 import 'completion_computer_test.dart' as completion_computer_test;
 import 'completion_manager_test.dart' as completion_manager_test;
+import 'completion_target_test.dart' as completion_target_test;
 import 'imported_computer_test.dart' as imported_test;
 import 'invocation_computer_test.dart' as invocation_test;
 import 'keyword_computer_test.dart' as keyword_test;
@@ -24,6 +25,7 @@
     combinator_test.main();
     completion_computer_test.main();
     completion_manager_test.main();
+    completion_target_test.main();
     imported_test.main();
     keyword_test.main();
     invocation_test.main();
diff --git a/pkg/analysis_server/test/services/dependencies/library_dependencies_test.dart b/pkg/analysis_server/test/services/dependencies/library_dependencies_test.dart
index 60fb7a0..8cdb9e2 100644
--- a/pkg/analysis_server/test/services/dependencies/library_dependencies_test.dart
+++ b/pkg/analysis_server/test/services/dependencies/library_dependencies_test.dart
@@ -19,7 +19,7 @@
 @reflectiveTest
 class LibraryDependenciesTest extends AbstractContextTest {
 
-  test_Dependencies() {
+  test_LibraryDependencies() {
     addSource('/lib1.dart', 'import "lib2.dart";');
     addSource('/lib2.dart', 'import "lib1.dart";');
     addSource('/lib3.dart', 'import "lib2.dart";');
@@ -44,8 +44,11 @@
     expect(libs, contains('/lib6.dart'));
   }
 
+  test_PackageMaps() {
+    //TODO(pquitslund): add test
+  }
+
   void _performAnalysis() {
     while (context.performAnalysisTask().hasMoreWork);
   }
 }
-
diff --git a/pkg/analysis_server/test/services/refactoring/convert_getter_to_method_test.dart b/pkg/analysis_server/test/services/refactoring/convert_getter_to_method_test.dart
index 9a07846..643079a 100644
--- a/pkg/analysis_server/test/services/refactoring/convert_getter_to_method_test.dart
+++ b/pkg/analysis_server/test/services/refactoring/convert_getter_to_method_test.dart
@@ -89,6 +89,36 @@
 ''');
   }
 
+  test_change_multipleFiles() {
+    indexUnit('/other.dart', r'''
+class A {
+  int get test => 1;
+}
+''');
+    indexTestUnit('''
+import 'other.dart';
+class B extends A {
+  int get test => 2;
+}
+main(A a, B b) {
+  a.test;
+  b.test;
+}
+''');
+    _createRefactoringForString('test => 2');
+    // apply refactoring
+    return _assertSuccessfulRefactoring('''
+import 'other.dart';
+class B extends A {
+  int test() => 2;
+}
+main(A a, B b) {
+  a.test();
+  b.test();
+}
+''');
+  }
+
   test_checkInitialConditions_syntheticGetter() {
     indexTestUnit('''
 int test = 42;
diff --git a/pkg/analysis_server/test/services/refactoring/convert_method_to_getter_test.dart b/pkg/analysis_server/test/services/refactoring/convert_method_to_getter_test.dart
index 21fdbe0..a4216f0 100644
--- a/pkg/analysis_server/test/services/refactoring/convert_method_to_getter_test.dart
+++ b/pkg/analysis_server/test/services/refactoring/convert_method_to_getter_test.dart
@@ -89,6 +89,36 @@
 ''');
   }
 
+  test_change_multipleFiles() {
+    indexUnit('/other.dart', r'''
+class A {
+  int test() => 1;
+}
+''');
+    indexTestUnit('''
+import 'other.dart';
+class B extends A {
+  int test() => 2;
+}
+main(A a, B b) {
+  a.test();
+  b.test();
+}
+''');
+    _createRefactoringForString('test() => 2');
+    // apply refactoring
+    return _assertSuccessfulRefactoring('''
+import 'other.dart';
+class B extends A {
+  int get test => 2;
+}
+main(A a, B b) {
+  a.test;
+  b.test;
+}
+''');
+  }
+
   test_checkInitialConditions_alreadyGetter() {
     indexTestUnit('''
 int get test => 42;
diff --git a/pkg/analysis_server/tool/spec/spec_input.html b/pkg/analysis_server/tool/spec/spec_input.html
index a91174d..37c4ea7 100644
--- a/pkg/analysis_server/tool/spec/spec_input.html
+++ b/pkg/analysis_server/tool/spec/spec_input.html
@@ -1,3 +1,4 @@
+
 <html>
   <head>
     <meta charset="UTF-8"/>
@@ -5,12 +6,13 @@
   </head>
   <body>
     <h1>Analysis Server API Specification</h1>
-    <h1 style="color:#999999">WORKING DRAFT - Version <version>0.3</version></h1>
+    <h1 style="color:#999999">Version <version>1.0.0</version></h1>
     <p>
-      This document contains a specification of the API provided by
-      the analysis server. The API in this document is currently under
-      development and should be expected to change. In some cases
-      those changes will be substantial.
+      This document contains a specification of the API provided by the
+      analysis server.  The API in this document is currently under
+      development.  Changes to the API will be accompanied by an update to the
+      protocol version number according to the principles of semantic
+      versioning <a href="http://semver.org/">http://semver.org/</a>.
     </p>
     <h2>Overview</h2>
     <p>
@@ -369,19 +371,35 @@
         </result>
       </request>
       <request method="getLibraryDependencies">
-            <p>
-              Return a list of all of the libraries referenced by any files in
-              existing analysis roots.
-            </p>
-            <result>
-                <field name="libraries">
-                    <list><ref>FilePath</ref></list>
-                    <p>
-                      A list of the paths of library elements referenced by
-                      files in existing analysis roots.
-                    </p>
-                </field>
-            </result>
+        <p>
+          Return library dependency information for use in client-side indexing
+          and package URI resolution.
+        </p>
+        <result>
+          <field name="libraries">
+            <list><ref>FilePath</ref></list>
+              <p>
+                A list of the paths of library elements referenced by
+                files in existing analysis roots.
+              </p>
+            </field>
+            <field name="packageMap">
+              <map>
+                <key><ref>String</ref></key>
+                <value>
+                  <map>
+                    <key><ref>String</ref></key>
+                    <value><list><ref>FilePath</ref></list></value>
+                  </map>
+                </value>
+              </map>
+              <p>
+                A mapping from context source roots to package maps which map
+                package names to source directories for use in client-side
+                package URI resolution.
+              </p>
+            </field>
+        </result>
       </request>
       <request method="getNavigation">
         <p>
@@ -458,10 +476,13 @@
       </request>
       <request method="setAnalysisRoots">
         <p>
-          Sets the root paths used to determine which files to
-          analyze. The set of files to be analyzed are all of the
-          files in one of the root paths that are not also in one of
-          the excluded paths.
+          Sets the root paths used to determine which files to analyze. The set
+          of files to be analyzed are all of the files in one of the root paths
+          that are not either explicitly or implicitly excluded. A file is
+          explicitly excluded if it is in one of the excluded paths. A file is
+          implicitly excluded if it is in a subdirectory of one of the root
+          paths where the name of the subdirectory starts with a period (that
+          is, a hidden directory).
         </p>
         <p>
           Note that this request determines the set of requested
@@ -1283,13 +1304,17 @@
           <field name="selectionOffset">
             <ref>int</ref>
             <p>
-              The offset of the current selection in the file.
+              The offset of the current selection in the file. In case
+              preserving, selection information is not required, 0 can be
+              specified for both selection offset and length.
             </p>
           </field>
           <field name="selectionLength">
             <ref>int</ref>
             <p>
-              The length of the current selection in the file.
+              The length of the current selection in the file. In case
+              preserving, selection information is not required, 0 can be
+              specified for both selection offset and length.
             </p>
           </field>
           <!--
@@ -1437,6 +1462,11 @@
         <p>
           Get the changes required to perform a refactoring.
         </p>
+        <p>
+          If another refactoring request is received during the processing
+          of this one, an error of type <tt>REFACTORING_REQUEST_CANCELLED</tt>
+          will be generated.
+        </p>
         <params>
           <field name="kind">
             <ref>RefactoringKind</ref>
@@ -1634,6 +1664,24 @@
         <p>
           Exactly one of the file and uri fields must be provided.
         </p>
+        <p>
+          If the file field is provided and the value is not the path of a file
+          (either the file does not exist or the path references something other
+          than a file), then an error of type <tt>MAP_URI_INVALID_FILE</tt> will
+          be generated.
+        </p>
+        <p>
+          If the uri field is provided and the value is not a valid URI or if
+          the URI references something that is not a file (either a file that
+          does not exist or something other than a file), then an error of type
+          <tt>MAP_URI_INVALID_URI</tt> will be generated.
+        </p>
+        <p>
+          If the contextRoot used to create the execution context is not a file
+          (either the file does not exist or the path references something other
+          than a file), then an error of type <tt>INVALID_EXECUTION_CONTEXT</tt>
+          will be generated.
+        </p>
         <params>
           <field name="id">
             <ref>ExecutionContextId</ref>
@@ -3045,6 +3093,13 @@
             </p>
           </value>
           <value>
+            <code>REFACTORING_REQUEST_CANCELLED</code>
+            <p>
+              Another refactoring request was received during processing of
+              this one.
+            </p>
+          </value>
+          <value>
             <code>SERVER_ALREADY_STARTED</code>
             <p>
               The analysis server has already been started (and hence
diff --git a/pkg/analyzer/example/resolver_driver.dart b/pkg/analyzer/example/resolver_driver.dart
old mode 100644
new mode 100755
index 0992b76..44d9635
--- a/pkg/analyzer/example/resolver_driver.dart
+++ b/pkg/analyzer/example/resolver_driver.dart
@@ -11,26 +11,40 @@
 import 'package:analyzer/src/generated/java_io.dart';
 import 'package:analyzer/src/generated/sdk.dart' show DartSdk;
 import 'package:analyzer/src/generated/sdk_io.dart' show DirectoryBasedDartSdk;
+import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/source_io.dart';
 
-main(List<String> args) {
+const _usage =
+    'Usage: resolve_driver <path_to_sdk> <file_to_resolve> [<packages_root>]';
+
+void main(List<String> args) {
   print('working dir ${new File('.').resolveSymbolicLinksSync()}');
 
-  if (args.length != 2) {
-    print('Usage: resolve_driver [path_to_sdk] [file_to_resolve]');
+  if (args.length < 2 || args.length > 3) {
+    print(_usage);
     exit(0);
   }
 
+  String packageRoot;
+  if (args.length == 3) {
+    packageRoot = args[2];
+  }
+
   JavaSystemIO.setProperty("com.google.dart.sdk", args[0]);
   DartSdk sdk = DirectoryBasedDartSdk.defaultSdk;
 
-  AnalysisContext context = AnalysisEngine.instance.createAnalysisContext();
-  context.sourceFactory =
-      new SourceFactory([new DartUriResolver(sdk), new FileUriResolver()]);
+  var resolvers = [new DartUriResolver(sdk), new FileUriResolver()];
+
+  if (packageRoot != null) {
+    var packageDirectory = new JavaFile(packageRoot);
+    resolvers.add(new PackageUriResolver([packageDirectory]));
+  }
+
+  AnalysisContext context = AnalysisEngine.instance.createAnalysisContext()
+    ..sourceFactory = new SourceFactory(resolvers);
+
   Source source = new FileBasedSource.con1(new JavaFile(args[1]));
-  //
-  ChangeSet changeSet = new ChangeSet();
-  changeSet.addedSource(source);
+  ChangeSet changeSet = new ChangeSet()..addedSource(source);
   context.applyChanges(changeSet);
   LibraryElement libElement = context.computeLibraryElement(source);
   print("libElement: $libElement");
@@ -43,19 +57,20 @@
 
 class _ASTVisitor extends GeneralizingAstVisitor {
   visitNode(AstNode node) {
-    String text = '${node.runtimeType} : <"$node">';
+    var lines = <String>['${node.runtimeType} : <"$node">'];
     if (node is SimpleIdentifier) {
       Element element = node.staticElement;
       if (element != null) {
-        text += " element: ${element.runtimeType}";
+        lines.add('  element: ${element.runtimeType}');
         LibraryElement library = element.library;
         if (library != null) {
-          text +=
-              " from ${element.library.definingCompilationUnit.source.fullName}";
+          var fullName =
+              element.library.definingCompilationUnit.source.fullName;
+          lines.add("  from $fullName");
         }
       }
     }
-    print(text);
+    print(lines.join('\n'));
     return super.visitNode(node);
   }
 }
diff --git a/pkg/analyzer/lib/file_system/memory_file_system.dart b/pkg/analyzer/lib/file_system/memory_file_system.dart
index 8c3edc2..b038f45eb 100644
--- a/pkg/analyzer/lib/file_system/memory_file_system.dart
+++ b/pkg/analyzer/lib/file_system/memory_file_system.dart
@@ -212,7 +212,7 @@
 /**
  * An in-memory implementation of [Source].
  */
-class _MemoryFileSource implements Source {
+class _MemoryFileSource extends Source {
   final _MemoryFile _file;
 
   final Uri uri;
diff --git a/pkg/analyzer/lib/source/package_map_resolver.dart b/pkg/analyzer/lib/source/package_map_resolver.dart
index de2c673..2f70b86 100644
--- a/pkg/analyzer/lib/source/package_map_resolver.dart
+++ b/pkg/analyzer/lib/source/package_map_resolver.dart
@@ -6,6 +6,7 @@
 
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/util/asserts.dart' as asserts;
 
 
 /**
@@ -35,7 +36,10 @@
    * [packageMap] is a table mapping package names to the paths of the
    * directories containing the package
    */
-  PackageMapUriResolver(this.resourceProvider, this.packageMap);
+  PackageMapUriResolver(this.resourceProvider, this.packageMap) {
+    asserts.notNull(resourceProvider);
+    asserts.notNull(packageMap);
+  }
 
   @override
   Source resolveAbsolute(Uri uri) {
diff --git a/pkg/analyzer/lib/src/error_formatter.dart b/pkg/analyzer/lib/src/error_formatter.dart
index fad6112..b64dfc6 100644
--- a/pkg/analyzer/lib/src/error_formatter.dart
+++ b/pkg/analyzer/lib/src/error_formatter.dart
@@ -103,6 +103,7 @@
     int errorCount = 0;
     int warnCount = 0;
     int hintCount = 0;
+    int lintCount = 0;
     for (AnalysisError error in errors) {
       ErrorSeverity severity =
           AnalyzerImpl.computeSeverity(error, options.enableTypeChecks);
@@ -118,6 +119,8 @@
             warnCount++;
           }
         }
+      } else if (error.errorCode.type == ErrorType.LINT) {
+        lintCount++;
       }
       formatError(errorToLine, error);
     }
@@ -126,6 +129,7 @@
       var hasErrors = errorCount != 0;
       var hasWarns = warnCount != 0;
       var hasHints = hintCount != 0;
+      var hasLints = lintCount != 0;
       bool hasContent = false;
       if (hasErrors) {
         out.write(errorCount);
@@ -135,7 +139,7 @@
       }
       if (hasWarns) {
         if (hasContent) {
-          if (!hasHints) {
+          if (!hasHints && !hasLints) {
             out.write(' and ');
           } else {
             out.write(", ");
@@ -148,13 +152,26 @@
       }
       if (hasHints) {
         if (hasContent) {
-          out.write(" and ");
+          if (!hasLints) {
+            out.write(' and ');
+          } else {
+            out.write(", ");
+          }
         }
         out.write(hintCount);
         out.write(' ');
         out.write(pluralize("hint", hintCount));
         hasContent = true;
       }
+      if (hasLints) {
+        if (hasContent) {
+          out.write(" and ");
+        }
+        out.write(lintCount);
+        out.write(' ');
+        out.write(pluralize("lint", lintCount));
+        hasContent = true;
+      }
       if (hasContent) {
         out.writeln(" found.");
       } else {
diff --git a/pkg/analyzer/lib/src/generated/ast.dart b/pkg/analyzer/lib/src/generated/ast.dart
index eb65e96..9f83af4 100644
--- a/pkg/analyzer/lib/src/generated/ast.dart
+++ b/pkg/analyzer/lib/src/generated/ast.dart
@@ -7934,7 +7934,12 @@
       ..add(_parameters);
 
   @override
-  Token get endToken => identifier.endToken;
+  Token get endToken {
+    if (_parameters != null) {
+      return _parameters.endToken;
+    }
+    return identifier.endToken;
+  }
 
   @override
   bool get isConst =>
diff --git a/pkg/analyzer/lib/src/generated/element.dart b/pkg/analyzer/lib/src/generated/element.dart
index 49cc609..337dc99 100644
--- a/pkg/analyzer/lib/src/generated/element.dart
+++ b/pkg/analyzer/lib/src/generated/element.dart
@@ -1084,7 +1084,7 @@
       }
     }
     while (currentElement != null && visitedClasses.add(currentElement)) {
-      for (InterfaceType mixin in currentElement.mixins) {
+      for (InterfaceType mixin in currentElement.mixins.reversed) {
         ClassElement mixinElement = mixin.element;
         if (mixinElement != null) {
           PropertyAccessorElement element = mixinElement.getGetter(getterName);
@@ -1117,7 +1117,7 @@
       }
     }
     while (currentElement != null && visitedClasses.add(currentElement)) {
-      for (InterfaceType mixin in currentElement.mixins) {
+      for (InterfaceType mixin in currentElement.mixins.reversed) {
         ClassElement mixinElement = mixin.element;
         if (mixinElement != null) {
           MethodElement element = mixinElement.getMethod(methodName);
@@ -1150,7 +1150,7 @@
       }
     }
     while (currentElement != null && visitedClasses.add(currentElement)) {
-      for (InterfaceType mixin in currentElement.mixins) {
+      for (InterfaceType mixin in currentElement.mixins.reversed) {
         ClassElement mixinElement = mixin.element;
         if (mixinElement != null) {
           PropertyAccessorElement element = mixinElement.getSetter(setterName);
@@ -1797,7 +1797,8 @@
       String message;
       String name = displayName;
       if (name != null && !name.isEmpty) {
-        message = 'Found constructor element named $name with no enclosing element';
+        message =
+            'Found constructor element named $name with no enclosing element';
       } else {
         message = 'Found unnamed constructor element with no enclosing element';
       }
@@ -6628,7 +6629,7 @@
   @override
   PropertyAccessorElement lookUpGetterInSuperclass(String getterName,
       LibraryElement library) {
-    for (InterfaceType mixin in mixins) {
+    for (InterfaceType mixin in mixins.reversed) {
       PropertyAccessorElement element = mixin.getGetter(getterName);
       if (element != null && element.isAccessibleIn(library)) {
         return element;
@@ -6644,7 +6645,7 @@
       if (element != null && element.isAccessibleIn(library)) {
         return element;
       }
-      for (InterfaceType mixin in supertype.mixins) {
+      for (InterfaceType mixin in supertype.mixins.reversed) {
         element = mixin.getGetter(getterName);
         if (element != null && element.isAccessibleIn(library)) {
           return element;
@@ -6668,7 +6669,7 @@
   @override
   MethodElement lookUpMethodInSuperclass(String methodName,
       LibraryElement library) {
-    for (InterfaceType mixin in mixins) {
+    for (InterfaceType mixin in mixins.reversed) {
       MethodElement element = mixin.getMethod(methodName);
       if (element != null && element.isAccessibleIn(library)) {
         return element;
@@ -6684,7 +6685,7 @@
       if (element != null && element.isAccessibleIn(library)) {
         return element;
       }
-      for (InterfaceType mixin in supertype.mixins) {
+      for (InterfaceType mixin in supertype.mixins.reversed) {
         element = mixin.getMethod(methodName);
         if (element != null && element.isAccessibleIn(library)) {
           return element;
@@ -6709,7 +6710,7 @@
   @override
   PropertyAccessorElement lookUpSetterInSuperclass(String setterName,
       LibraryElement library) {
-    for (InterfaceType mixin in mixins) {
+    for (InterfaceType mixin in mixins.reversed) {
       PropertyAccessorElement element = mixin.getSetter(setterName);
       if (element != null && element.isAccessibleIn(library)) {
         return element;
@@ -6725,7 +6726,7 @@
       if (element != null && element.isAccessibleIn(library)) {
         return element;
       }
-      for (InterfaceType mixin in supertype.mixins) {
+      for (InterfaceType mixin in supertype.mixins.reversed) {
         element = mixin.getSetter(setterName);
         if (element != null && element.isAccessibleIn(library)) {
           return element;
diff --git a/pkg/analyzer/lib/src/generated/element_resolver.dart b/pkg/analyzer/lib/src/generated/element_resolver.dart
index 2b5bf19..9ecb232 100644
--- a/pkg/analyzer/lib/src/generated/element_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/element_resolver.dart
@@ -1706,7 +1706,7 @@
         return getter;
       }
     }
-    for (InterfaceType mixinType in targetType.mixins) {
+    for (InterfaceType mixinType in targetType.mixins.reversed) {
       PropertyAccessorElement getter =
           _lookUpGetterInInterfaces(mixinType, true, getterName, visitedInterfaces);
       if (getter != null) {
@@ -1799,7 +1799,7 @@
         return member;
       }
     }
-    for (InterfaceType mixinType in targetType.mixins) {
+    for (InterfaceType mixinType in targetType.mixins.reversed) {
       ExecutableElement member = _lookUpGetterOrMethodInInterfaces(
           mixinType,
           true,
@@ -1897,7 +1897,7 @@
         return method;
       }
     }
-    for (InterfaceType mixinType in targetType.mixins) {
+    for (InterfaceType mixinType in targetType.mixins.reversed) {
       MethodElement method =
           _lookUpMethodInInterfaces(mixinType, true, methodName, visitedInterfaces);
       if (method != null) {
@@ -2018,7 +2018,7 @@
         return setter;
       }
     }
-    for (InterfaceType mixinType in targetType.mixins) {
+    for (InterfaceType mixinType in targetType.mixins.reversed) {
       PropertyAccessorElement setter =
           _lookUpSetterInInterfaces(mixinType, true, setterName, visitedInterfaces);
       if (setter != null) {
diff --git a/pkg/analyzer/lib/src/generated/engine.dart b/pkg/analyzer/lib/src/generated/engine.dart
index 9b47fe2..fbd1d39 100644
--- a/pkg/analyzer/lib/src/generated/engine.dart
+++ b/pkg/analyzer/lib/src/generated/engine.dart
@@ -968,6 +968,11 @@
   Source _coreLibrarySource;
 
   /**
+   * A source representing the async library.
+   */
+  Source _asyncLibrarySource;
+
+  /**
    * The partition that contains analysis results that are not shared with other contexts.
    */
   CachePartition _privatePartition;
@@ -1117,6 +1122,7 @@
     this._options.incremental = options.incremental;
     this._options.incrementalApi = options.incrementalApi;
     this._options.incrementalValidation = options.incrementalValidation;
+    this._options.lint = options.lint;
     this._options.preserveComments = options.preserveComments;
     _generateSdkErrors = options.generateSdkErrors;
     if (needsRecompute) {
@@ -1402,6 +1408,7 @@
     factory.context = this;
     _sourceFactory = factory;
     _coreLibrarySource = _sourceFactory.forUri(DartSdk.DART_CORE);
+    _asyncLibrarySource = _sourceFactory.forUri(DartSdk.DART_ASYNC);
     _cache = createCacheFromSourceFactory(factory);
     _invalidateAllLocalResolutionInformation(true);
   }
@@ -1476,7 +1483,15 @@
     if (coreElement == null) {
       throw new AnalysisException("Could not create an element for dart:core");
     }
-    return new TypeProviderImpl(coreElement);
+    Source asyncSource = sourceFactory.forUri(DartSdk.DART_ASYNC);
+    if (asyncSource == null) {
+      throw new AnalysisException("Could not create a source for dart:async");
+    }
+    LibraryElement asyncElement = computeLibraryElement(asyncSource);
+    if (asyncElement == null) {
+      throw new AnalysisException("Could not create an element for dart:async");
+    }
+    return new TypeProviderImpl(coreElement, asyncElement);
   }
 
   @override
@@ -5356,6 +5371,31 @@
     AnalysisContextImpl_this._neededForResolution = null;
   }
 
+  bool _addDependency(ResolvableLibrary dependant, Source dependency,
+      List<ResolvableLibrary> dependencyList) {
+    if (dependant.librarySource == dependency) {
+      // Don't add a dependency of a library on itself; there's no point.
+      return true;
+    }
+    ResolvableLibrary importedLibrary = _libraryMap[dependency];
+    if (importedLibrary == null) {
+      importedLibrary = _createLibraryOrNull(dependency);
+      if (importedLibrary != null) {
+        _computeLibraryDependencies(importedLibrary);
+        if (_taskData != null) {
+          return false;
+        }
+      }
+    }
+    if (importedLibrary != null) {
+      if (dependencyList != null) {
+        dependencyList.add(importedLibrary);
+      }
+      _dependencyGraph.addEdge(dependant, importedLibrary);
+    }
+    return true;
+  }
+
   /**
    * Recursively traverse the libraries reachable from the given library, creating instances of
    * the class [Library] to represent them, and record the references in the library
@@ -5398,87 +5438,55 @@
   void _computeLibraryDependenciesFromDirectives(ResolvableLibrary library,
       List<Source> importedSources, List<Source> exportedSources) {
     int importCount = importedSources.length;
-    if (importCount > 0) {
-      List<ResolvableLibrary> importedLibraries = new List<ResolvableLibrary>();
-      bool explicitlyImportsCore = false;
-      for (int i = 0; i < importCount; i++) {
-        Source importedSource = importedSources[i];
-        if (importedSource == AnalysisContextImpl_this._coreLibrarySource) {
-          explicitlyImportsCore = true;
-        }
-        ResolvableLibrary importedLibrary = _libraryMap[importedSource];
-        if (importedLibrary == null) {
-          importedLibrary = _createLibraryOrNull(importedSource);
-          if (importedLibrary != null) {
-            _computeLibraryDependencies(importedLibrary);
-            if (_taskData != null) {
-              return;
-            }
-          }
-        }
-        if (importedLibrary != null) {
-          importedLibraries.add(importedLibrary);
-          _dependencyGraph.addEdge(library, importedLibrary);
-        }
+    List<ResolvableLibrary> importedLibraries = new List<ResolvableLibrary>();
+    bool explicitlyImportsCore = false;
+    bool importsAsync = false;
+    for (int i = 0; i < importCount; i++) {
+      Source importedSource = importedSources[i];
+      if (importedSource == AnalysisContextImpl_this._coreLibrarySource) {
+        explicitlyImportsCore = true;
+      } else if (importedSource ==
+          AnalysisContextImpl_this._asyncLibrarySource) {
+        importsAsync = true;
       }
-      library.explicitlyImportsCore = explicitlyImportsCore;
-      if (!explicitlyImportsCore &&
-          AnalysisContextImpl_this._coreLibrarySource != library.librarySource) {
-        ResolvableLibrary importedLibrary =
-            _libraryMap[AnalysisContextImpl_this._coreLibrarySource];
-        if (importedLibrary == null) {
-          importedLibrary =
-              _createLibraryOrNull(AnalysisContextImpl_this._coreLibrarySource);
-          if (importedLibrary != null) {
-            _computeLibraryDependencies(importedLibrary);
-            if (_taskData != null) {
-              return;
-            }
-          }
-        }
-        if (importedLibrary != null) {
-          importedLibraries.add(importedLibrary);
-          _dependencyGraph.addEdge(library, importedLibrary);
-        }
-      }
-      library.importedLibraries = importedLibraries;
-    } else {
-      library.explicitlyImportsCore = false;
-      ResolvableLibrary importedLibrary =
-          _libraryMap[AnalysisContextImpl_this._coreLibrarySource];
-      if (importedLibrary == null) {
-        importedLibrary =
-            _createLibraryOrNull(AnalysisContextImpl_this._coreLibrarySource);
-        if (importedLibrary != null) {
-          _computeLibraryDependencies(importedLibrary);
-          if (_taskData != null) {
-            return;
-          }
-        }
-      }
-      if (importedLibrary != null) {
-        _dependencyGraph.addEdge(library, importedLibrary);
-        library.importedLibraries = <ResolvableLibrary>[importedLibrary];
+      if (!_addDependency(library, importedSource, importedLibraries)) {
+        return;
       }
     }
+    library.explicitlyImportsCore = explicitlyImportsCore;
+    if (!explicitlyImportsCore) {
+      if (!_addDependency(
+          library,
+          AnalysisContextImpl_this._coreLibrarySource,
+          importedLibraries)) {
+        return;
+      }
+    }
+    if (!importsAsync) {
+      // Add a dependency on async to ensure that the Future element will be
+      // built before we generate errors and warnings for async methods.  Also
+      // include it in importedLibraries, so that it will be picked up by
+      // LibraryResolver2._buildLibraryMap().
+      // TODO(paulberry): this is a bit of a hack, since the async library
+      // isn't actually being imported.  Also, it's not clear whether it should
+      // be necessary: in theory, dart:core already (indirectly) imports
+      // dart:async, so if core has been built, async should have been built
+      // too.  However, removing this code causes unit test failures.
+      if (!_addDependency(
+          library,
+          AnalysisContextImpl_this._asyncLibrarySource,
+          importedLibraries)) {
+        return;
+      }
+    }
+    library.importedLibraries = importedLibraries;
     int exportCount = exportedSources.length;
     if (exportCount > 0) {
       List<ResolvableLibrary> exportedLibraries = new List<ResolvableLibrary>();
       for (int i = 0; i < exportCount; i++) {
         Source exportedSource = exportedSources[i];
-        ResolvableLibrary exportedLibrary = _libraryMap[exportedSource];
-        if (exportedLibrary == null) {
-          exportedLibrary = _createLibraryOrNull(exportedSource);
-          if (exportedLibrary != null) {
-            _computeLibraryDependencies(exportedLibrary);
-            if (_taskData != null) {
-              return;
-            }
-          }
-        }
-        if (exportedLibrary != null) {
-          exportedLibraries.add(exportedLibrary);
-          _dependencyGraph.addEdge(library, exportedLibrary);
+        if (!_addDependency(library, exportedSource, exportedLibraries)) {
+          return;
         }
       }
       library.exportedLibraries = exportedLibraries;
diff --git a/pkg/analyzer/lib/src/generated/error.dart b/pkg/analyzer/lib/src/generated/error.dart
index f9411ef..7801e2e 100644
--- a/pkg/analyzer/lib/src/generated/error.dart
+++ b/pkg/analyzer/lib/src/generated/error.dart
@@ -3284,6 +3284,33 @@
           "Map literal requires exactly two type arguments or none, but {0} found");
 
   /**
+   * 9 Functions: It is a static warning if the declared return type of a
+   * function marked async* may not be assigned to Stream.
+   */
+  static const StaticTypeWarningCode ILLEGAL_ASYNC_GENERATOR_RETURN_TYPE =
+      const StaticTypeWarningCode(
+          'ILLEGAL_ASYNC_GENERATOR_RETURN_TYPE',
+          "Functions marked 'async*' must have a return type assignable to 'Stream'");
+
+  /**
+   * 9 Functions: It is a static warning if the declared return type of a
+   * function marked async may not be assigned to Future.
+   */
+  static const StaticTypeWarningCode ILLEGAL_ASYNC_RETURN_TYPE =
+      const StaticTypeWarningCode(
+          'ILLEGAL_ASYNC_RETURN_TYPE',
+          "Functions marked 'async' must have a return type assignable to 'Future'");
+
+  /**
+   * 9 Functions: It is a static warning if the declared return type of a
+   * function marked sync* may not be assigned to Iterable.
+   */
+  static const StaticTypeWarningCode ILLEGAL_SYNC_GENERATOR_RETURN_TYPE =
+      const StaticTypeWarningCode(
+          'ILLEGAL_SYNC_GENERATOR_RETURN_TYPE',
+          "Functions marked 'sync*' must have a return type assignable to 'Iterable'");
+
+  /**
    * 12.18 Assignment: Let <i>T</i> be the static type of <i>e<sub>1</sub></i>.
    * It is a static type warning if <i>T</i> does not have an accessible
    * instance setter named <i>v=</i>.
@@ -3716,6 +3743,29 @@
           "The type '{0}' is declared with {1} type parameters, but {2} type arguments were given");
 
   /**
+   * 17.16.1 Yield: Let T be the static type of e [the expression to the right
+   * of "yield"] and let f be the immediately enclosing function.  It is a
+   * static type warning if either:
+   *
+   * - the body of f is marked async* and the type Stream<T> may not be
+   *   assigned to the declared return type of f.
+   *
+   * - the body of f is marked sync* and the type Iterable<T> may not be
+   *   assigned to the declared return type of f.
+   *
+   * 17.16.2 Yield-Each: Let T be the static type of e [the expression to the
+   * right of "yield*"] and let f be the immediately enclosing function.  It is
+   * a static type warning if T may not be assigned to the declared return type
+   * of f.  If f is synchronous it is a static type warning if T may not be
+   * assigned to Iterable.  If f is asynchronous it is a static type warning if
+   * T may not be assigned to Stream.
+   */
+  static const StaticTypeWarningCode YIELD_OF_INVALID_TYPE =
+      const StaticTypeWarningCode(
+          'YIELD_OF_INVALID_TYPE',
+          "The type '{0}' implied by the 'yield' expression must be assignable to '{1}'");
+
+  /**
    * Initialize a newly created error code to have the given [name]. The message
    * associated with the error will be created from the given [message]
    * template. The correction associated with the error will be created from the
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index 4b83983c..50bba03 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -677,6 +677,7 @@
             CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER);
       }
       _checkForTypeAnnotationDeferredClass(returnType);
+      _checkForIllegalReturnType(returnType);
       return super.visitFunctionDeclaration(node);
     } finally {
       _enclosingFunction = outerFunction;
@@ -862,6 +863,7 @@
       _checkForConcreteClassWithAbstractMember(node);
       _checkForAllInvalidOverrideErrorCodesForMethod(node);
       _checkForTypeAnnotationDeferredClass(returnTypeName);
+      _checkForIllegalReturnType(returnTypeName);
       return super.visitMethodDeclaration(node);
     } finally {
       _enclosingFunction = previousFunction;
@@ -1095,7 +1097,9 @@
 
   @override
   Object visitYieldStatement(YieldStatement node) {
-    if (!_inGenerator) {
+    if (_inGenerator) {
+      _checkForYieldOfInvalidType(node.expression, node.star != null);
+    } else {
       CompileTimeErrorCode errorCode;
       if (node.star != null) {
         errorCode = CompileTimeErrorCode.YIELD_EACH_IN_NON_GENERATOR;
@@ -1793,7 +1797,8 @@
     }
     // RETURN_WITHOUT_VALUE
     if (returnExpression == null) {
-      if (VoidTypeImpl.instance.isAssignableTo(expectedReturnType)) {
+      if (_inGenerator ||
+          _computeReturnTypeForMethod(null).isAssignableTo(expectedReturnType)) {
         return false;
       }
       _hasReturnWithoutValue = true;
@@ -3478,6 +3483,43 @@
   }
 
   /**
+   * If the current function is async, async*, or sync*, verify that its
+   * declared return type is assignable to Future, Stream, or Iterable,
+   * respectively.  If not, report the error using [node].
+   */
+  void _checkForIllegalReturnType(TypeName node) {
+    if (node == null) {
+      // No declared return type, so the return type must be dynamic, which is
+      // assignable to everything.
+      return;
+    }
+    if (_enclosingFunction.isAsynchronous) {
+      if (_enclosingFunction.isGenerator) {
+        if (!_enclosingFunction.returnType.isAssignableTo(
+            _typeProvider.streamDynamicType)) {
+          _errorReporter.reportErrorForNode(
+              StaticTypeWarningCode.ILLEGAL_ASYNC_GENERATOR_RETURN_TYPE,
+              node);
+        }
+      } else {
+        if (!_enclosingFunction.returnType.isAssignableTo(
+            _typeProvider.futureDynamicType)) {
+          _errorReporter.reportErrorForNode(
+              StaticTypeWarningCode.ILLEGAL_ASYNC_RETURN_TYPE,
+              node);
+        }
+      }
+    } else if (_enclosingFunction.isGenerator) {
+      if (!_enclosingFunction.returnType.isAssignableTo(
+          _typeProvider.iterableDynamicType)) {
+        _errorReporter.reportErrorForNode(
+            StaticTypeWarningCode.ILLEGAL_SYNC_GENERATOR_RETURN_TYPE,
+            node);
+      }
+    }
+  }
+
+  /**
    * This verifies that the passed implements clause does not implement classes that are deferred.
    *
    * @param node the implements clause to test
@@ -5171,7 +5213,13 @@
     if (_enclosingFunction == null) {
       return false;
     }
-    DartType staticReturnType = getStaticType(returnExpression);
+    if (_inGenerator) {
+      // "return expression;" is disallowed in generators, but this is checked
+      // elsewhere.  Bare "return" is always allowed in generators regardless
+      // of the return type.  So no need to do any further checking.
+      return false;
+    }
+    DartType staticReturnType = _computeReturnTypeForMethod(returnExpression);
     if (expectedReturnType.isVoid) {
       if (staticReturnType.isVoid ||
           staticReturnType.isDynamic ||
@@ -5184,22 +5232,6 @@
           [staticReturnType, expectedReturnType, _enclosingFunction.displayName]);
       return true;
     }
-    if (_enclosingFunction.isAsynchronous && !_enclosingFunction.isGenerator) {
-      // TODO(brianwilkerson) Figure out how to get the type "Future" so that we
-      // can build the type we need to test against.
-//            InterfaceType impliedType = "Future<" + flatten(staticReturnType) + ">"
-//            if (impliedType.isAssignableTo(expectedReturnType)) {
-//              return false;
-//            }
-//            errorReporter.reportTypeErrorForNode(
-//                StaticTypeWarningCode.RETURN_OF_INVALID_TYPE,
-//                returnExpression,
-//                impliedType,
-//                expectedReturnType.getDisplayName(),
-//                enclosingFunction.getDisplayName());
-//            return true;
-      return false;
-    }
     if (staticReturnType.isAssignableTo(expectedReturnType)) {
       return false;
     }
@@ -5720,6 +5752,58 @@
   }
 
   /**
+   * Check for a type mis-match between the yielded type and the declared
+   * return type of a generator function.
+   *
+   * This method should only be called in generator functions.
+   */
+  bool _checkForYieldOfInvalidType(Expression yieldExpression,
+      bool isYieldEach) {
+    assert(_inGenerator);
+    if (_enclosingFunction == null) {
+      return false;
+    }
+    DartType declaredReturnType = _enclosingFunction.returnType;
+    DartType staticYieldedType = getStaticType(yieldExpression);
+    DartType impliedReturnType;
+    if (isYieldEach) {
+      impliedReturnType = staticYieldedType;
+    } else if (_enclosingFunction.isAsynchronous) {
+      impliedReturnType =
+          _typeProvider.streamType.substitute4(<DartType>[staticYieldedType]);
+    } else {
+      impliedReturnType =
+          _typeProvider.iterableType.substitute4(<DartType>[staticYieldedType]);
+    }
+    if (!impliedReturnType.isAssignableTo(declaredReturnType)) {
+      _errorReporter.reportTypeErrorForNode(
+          StaticTypeWarningCode.YIELD_OF_INVALID_TYPE,
+          yieldExpression,
+          [impliedReturnType, declaredReturnType]);
+      return true;
+    }
+    if (isYieldEach) {
+      // Since the declared return type might have been "dynamic", we need to
+      // also check that the implied return type is assignable to generic
+      // Stream/Iterable.
+      DartType requiredReturnType;
+      if (_enclosingFunction.isAsynchronous) {
+        requiredReturnType = _typeProvider.streamDynamicType;
+      } else {
+        requiredReturnType = _typeProvider.iterableDynamicType;
+      }
+      if (!impliedReturnType.isAssignableTo(requiredReturnType)) {
+        _errorReporter.reportTypeErrorForNode(
+            StaticTypeWarningCode.YIELD_OF_INVALID_TYPE,
+            yieldExpression,
+            [impliedReturnType, requiredReturnType]);
+        return true;
+      }
+    }
+    return false;
+  }
+
+  /**
    * This verifies that if the given class declaration implements the class Function that it has a
    * concrete implementation of the call method.
    *
@@ -5789,6 +5873,26 @@
     return hasProblem;
   }
 
+  DartType _computeReturnTypeForMethod(Expression returnExpression) {
+    // This method should never be called for generators, since generators are
+    // never allowed to contain return statements with expressions.
+    assert(!_inGenerator);
+    if (returnExpression == null) {
+      if (_enclosingFunction.isAsynchronous) {
+        return _typeProvider.futureNullType;
+      } else {
+        return VoidTypeImpl.instance;
+      }
+    }
+    DartType staticReturnType = getStaticType(returnExpression);
+    if (staticReturnType != null &&
+        _enclosingFunction.isAsynchronous &&
+        staticReturnType.element != _typeProvider.futureType.element) {
+      return _typeProvider.futureType.substitute4(<DartType>[staticReturnType]);
+    }
+    return staticReturnType;
+  }
+
   /**
    * Return the error code that should be used when the given class references itself directly.
    *
diff --git a/pkg/analyzer/lib/src/generated/incremental_resolver.dart b/pkg/analyzer/lib/src/generated/incremental_resolver.dart
index b009946..152bb47 100644
--- a/pkg/analyzer/lib/src/generated/incremental_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/incremental_resolver.dart
@@ -272,6 +272,7 @@
     _assertCompatibleParameters(
         node.functionExpression.parameters,
         element.parameters);
+    _assertBodyModifiers(node.functionExpression.body, element);
     // matches, update the existing element
     ExecutableElement newElement = node.element;
     node.name.staticElement = element;
@@ -345,6 +346,7 @@
       _assertEquals(node.isStatic, element.isStatic);
       _assertSameType(node.returnType, element.returnType);
       _assertCompatibleParameters(node.parameters, element.parameters);
+      _assertBodyModifiers(node.body, element);
       _removedElements.remove(element);
       // matches, update the existing element
       node.name.staticElement = element;
@@ -422,6 +424,15 @@
     _assertSameTypes(nodes, types);
   }
 
+  /**
+   * Asserts that [body] has async / generator modifiers compatible with the
+   * given [element].
+   */
+  void _assertBodyModifiers(FunctionBody body, ExecutableElementImpl element) {
+    _assertEquals(body.isSynchronous, element.isSynchronous);
+    _assertEquals(body.isGenerator, element.isGenerator);
+  }
+
   void _assertCombinators(List<Combinator> nodeCombinators,
       List<NamespaceCombinator> elementCombinators) {
     // prepare shown/hidden names in the element
diff --git a/pkg/analyzer/lib/src/generated/parser.dart b/pkg/analyzer/lib/src/generated/parser.dart
index ed538c4..3787d75 100644
--- a/pkg/analyzer/lib/src/generated/parser.dart
+++ b/pkg/analyzer/lib/src/generated/parser.dart
@@ -3674,6 +3674,12 @@
    */
   SimpleIdentifier parseSimpleIdentifier() {
     if (_matchesIdentifier()) {
+      String lexeme = _currentToken.lexeme;
+      if ((_inAsync || _inGenerator) &&
+          (lexeme == 'async' || lexeme == 'await' || lexeme == 'yield')) {
+        _reportErrorForCurrentToken(
+            ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER);
+      }
       return new SimpleIdentifier(getAndAdvance());
     }
     _reportErrorForCurrentToken(ParserErrorCode.MISSING_IDENTIFIER);
@@ -6078,6 +6084,9 @@
     } else {
       name = _createSyntheticIdentifier();
     }
+    if (commentAndMetadata.metadata.isNotEmpty) {
+      _reportErrorForNode(ParserErrorCode.ANNOTATION_ON_ENUM_CONSTANT, commentAndMetadata.metadata[0]);
+    }
     return new EnumConstantDeclaration(
         commentAndMetadata.comment,
         commentAndMetadata.metadata,
@@ -6104,7 +6113,7 @@
     Token rightBracket = null;
     if (_matches(TokenType.OPEN_CURLY_BRACKET)) {
       leftBracket = _expect(TokenType.OPEN_CURLY_BRACKET);
-      if (_matchesIdentifier()) {
+      if (_matchesIdentifier() || _matches(TokenType.AT)) {
         constants.add(_parseEnumConstantDeclaration());
       } else if (_matches(TokenType.COMMA) &&
           _tokenMatchesIdentifier(_peek())) {
@@ -8612,7 +8621,7 @@
     } else if (_matches(TokenType.PLUS)) {
       _reportErrorForCurrentToken(ParserErrorCode.MISSING_IDENTIFIER);
       return _createSyntheticIdentifier();
-    } else if (_matchesString(_AWAIT)) {
+    } else if (_inAsync && _matchesString(_AWAIT)) {
       return _parseAwaitExpression();
     }
     return _parsePostfixExpression();
@@ -10009,6 +10018,10 @@
       'ABSTRACT_TYPEDEF',
       "Type aliases cannot be declared to be 'abstract'");
 
+  static const ParserErrorCode ANNOTATION_ON_ENUM_CONSTANT = const ParserErrorCode(
+      'ANNOTATION_ON_ENUM_CONSTANT',
+      "Enum constants cannot have annotations");
+
   static const ParserErrorCode ASSERT_DOES_NOT_TAKE_ASSIGNMENT =
       const ParserErrorCode(
           'ASSERT_DOES_NOT_TAKE_ASSIGNMENT',
@@ -10029,6 +10042,16 @@
           'ASSERT_DOES_NOT_TAKE_RETHROW',
           "Assert cannot be called on rethrows");
 
+  /**
+   * 16.32 Identifier Reference: It is a compile-time error if any of the
+   * identifiers async, await, or yield is used as an identifier in a function
+   * body marked with either async, async*, or sync*.
+   */
+  static const ParserErrorCode ASYNC_KEYWORD_USED_AS_IDENTIFIER =
+      const ParserErrorCode(
+          'ASYNC_KEYWORD_USED_AS_IDENTIFIER',
+          "The keywords 'async', 'await', and 'yield' may not be used as identifiers in an asynchronous or generator function.");
+
   static const ParserErrorCode BREAK_OUTSIDE_OF_LOOP = const ParserErrorCode(
       'BREAK_OUTSIDE_OF_LOOP',
       "A break statement cannot be used outside of a loop or switch statement");
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index ae4bded..9f3ab6d 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -61,11 +61,18 @@
   final ErrorReporter _errorReporter;
 
   /**
+   * The type Future<Null>, which is needed for determining whether it is safe
+   * to have a bare "return;" in an async method.
+   */
+  final InterfaceType _futureNullType;
+
+  /**
    * Create a new instance of the [BestPracticesVerifier].
    *
    * @param errorReporter the error reporter
    */
-  BestPracticesVerifier(this._errorReporter);
+  BestPracticesVerifier(this._errorReporter, TypeProvider typeProvider)
+      : _futureNullType = typeProvider.futureNullType;
 
   @override
   Object visitArgumentList(ArgumentList node) {
@@ -558,6 +565,9 @@
    * statement on all branches. At the end of blocks with no return, Dart implicitly returns
    * `null`, avoiding these implicit returns is considered a best practice.
    *
+   * Note: for async functions/methods, this hint only applies when the
+   * function has a return type that Future<Null> is not assignable to.
+   *
    * @param node the binary expression to check
    * @param body the function body
    * @return `true` if and only if a hint code is generated on the passed node
@@ -572,11 +582,20 @@
     if (body is! BlockFunctionBody) {
       return false;
     }
+    // Generators are never required to have a return statement.
+    if (body.isGenerator) {
+      return false;
+    }
     // Check that the type is resolvable, and is not "void"
     DartType returnTypeType = returnType.type;
     if (returnTypeType == null || returnTypeType.isVoid) {
       return false;
     }
+    // For async, give no hint if Future<Null> is assignable to the return
+    // type.
+    if (body.isAsynchronous && _futureNullType.isAssignableTo(returnTypeType)) {
+      return false;
+    }
     // Check the block for a return statement, if not, create the hint
     BlockFunctionBody blockFunctionBody = body as BlockFunctionBody;
     if (!blockFunctionBody.accept(new ExitDetector())) {
@@ -3888,6 +3907,10 @@
       _nodeExits(node.leftHandSide) || _nodeExits(node.rightHandSide);
 
   @override
+  bool visitAwaitExpression(AwaitExpression node) =>
+      _nodeExits(node.expression);
+
+  @override
   bool visitBinaryExpression(BinaryExpression node) {
     Expression lhsExpression = node.leftOperand;
     sc.TokenType operatorType = node.operator.type;
@@ -4179,6 +4202,18 @@
           return false;
         }
       }
+      // All of the members exit, determine whether there are possible cases
+      // that are not caught by the members.
+      DartType type = node.expression == null ? null : node.expression.bestType;
+      if (type is InterfaceType) {
+        ClassElement element = type.element;
+        if (element != null && element.isEnum) {
+          // If some of the enum values are not covered, then a warning will
+          // have already been generated, so there's no point in generating a
+          // hint.
+          return true;
+        }
+      }
       return hasDefault;
     } finally {
       _enclosingBlockContainsBreak = outerBreakValue;
@@ -4393,7 +4428,7 @@
 class HintGenerator {
   final List<CompilationUnit> _compilationUnits;
 
-  final AnalysisContext _context;
+  final InternalAnalysisContext _context;
 
   final AnalysisErrorListener _errorListener;
 
@@ -4458,7 +4493,8 @@
       unit.accept(new Dart2JSVerifier(errorReporter));
     }
     // Dart best practices
-    unit.accept(new BestPracticesVerifier(errorReporter));
+    unit.accept(
+        new BestPracticesVerifier(errorReporter, _context.typeProvider));
     unit.accept(new OverrideVerifier(_manager, errorReporter));
     // Find to-do comments
     new ToDoFinder(errorReporter).findIn(unit);
@@ -5960,11 +5996,13 @@
       }
     }
     //
-    // Include the members from the mixins in the resultMap
+    // Include the members from the mixins in the resultMap.  If there are
+    // multiple mixins, visit them in the order listed so that methods in later
+    // mixins will overwrite identically-named methods in earlier mixins.
     //
     List<InterfaceType> mixins = classElt.mixins;
-    for (int i = mixins.length - 1; i >= 0; i--) {
-      ClassElement mixinElement = mixins[i].element;
+    for (InterfaceType mixin in mixins) {
+      ClassElement mixinElement = mixin.element;
       if (mixinElement != null) {
         if (!visitedClasses.contains(mixinElement)) {
           visitedClasses.add(mixinElement);
@@ -5974,11 +6012,11 @@
             //
             // Substitute the super types down the hierarchy.
             //
-            _substituteTypeParametersDownHierarchy(mixins[i], map);
+            _substituteTypeParametersDownHierarchy(mixin, map);
             //
             // Include the members from the superclass in the resultMap.
             //
-            _recordMapWithClassMembers(map, mixins[i], false);
+            _recordMapWithClassMembers(map, mixin, false);
             //
             // Add the members from map into result map.
             //
@@ -7688,11 +7726,21 @@
   Source _coreLibrarySource;
 
   /**
+   * A Source object representing the async library (dart:async).
+   */
+  Source _asyncLibrarySource;
+
+  /**
    * The object representing the core library.
    */
   Library _coreLibrary;
 
   /**
+   * The object representing the async library.
+   */
+  Library _asyncLibrary;
+
+  /**
    * The object used to access the types from the core library.
    */
   TypeProvider _typeProvider;
@@ -7716,6 +7764,8 @@
     this._errorListener = new RecordingErrorListener();
     _coreLibrarySource =
         analysisContext.sourceFactory.forUri(DartSdk.DART_CORE);
+    _asyncLibrarySource =
+        analysisContext.sourceFactory.forUri(DartSdk.DART_ASYNC);
   }
 
   /**
@@ -7767,7 +7817,7 @@
     Library targetLibrary = _createLibraryWithUnit(librarySource, unit);
     _coreLibrary = _libraryMap[_coreLibrarySource];
     if (_coreLibrary == null) {
-      // This will be true unless the library being analyzed is the core
+      // This will only happen if the library being analyzed is the core
       // library.
       _coreLibrary = createLibrary(_coreLibrarySource);
       if (_coreLibrary == null) {
@@ -7776,6 +7826,17 @@
             _coreLibrarySource);
       }
     }
+    _asyncLibrary = _libraryMap[_asyncLibrarySource];
+    if (_asyncLibrary == null) {
+      // This will only happen if the library being analyzed is the async
+      // library.
+      _asyncLibrary = createLibrary(_asyncLibrarySource);
+      if (_asyncLibrary == null) {
+        LibraryResolver2.missingAsyncLibrary(
+            analysisContext,
+            _asyncLibrarySource);
+      }
+    }
     //
     // Compute the set of libraries that need to be resolved together.
     //
@@ -7802,8 +7863,12 @@
     if (coreElement == null) {
       throw new AnalysisException("Could not resolve dart:core");
     }
+    LibraryElement asyncElement = _asyncLibrary.libraryElement;
+    if (asyncElement == null) {
+      throw new AnalysisException("Could not resolve dart:async");
+    }
     _buildDirectiveModels();
-    _typeProvider = new TypeProviderImpl(coreElement);
+    _typeProvider = new TypeProviderImpl(coreElement, asyncElement);
     _buildTypeAliases();
     _buildTypeHierarchies();
     //
@@ -7847,7 +7912,7 @@
     Library targetLibrary = createLibrary(librarySource);
     _coreLibrary = _libraryMap[_coreLibrarySource];
     if (_coreLibrary == null) {
-      // This will be true unless the library being analyzed is the core
+      // This should only happen if the library being analyzed is the core
       // library.
       _coreLibrary = _createLibraryOrNull(_coreLibrarySource);
       if (_coreLibrary == null) {
@@ -7856,6 +7921,17 @@
             _coreLibrarySource);
       }
     }
+    _asyncLibrary = _libraryMap[_asyncLibrarySource];
+    if (_asyncLibrary == null) {
+      // This should only happen if the library being analyzed is the async
+      // library.
+      _asyncLibrary = _createLibraryOrNull(_asyncLibrarySource);
+      if (_asyncLibrary == null) {
+        LibraryResolver2.missingAsyncLibrary(
+            analysisContext,
+            _asyncLibrarySource);
+      }
+    }
     //
     // Compute the set of libraries that need to be resolved together.
     //
@@ -7884,8 +7960,12 @@
     if (coreElement == null) {
       throw new AnalysisException("Could not resolve dart:core");
     }
+    LibraryElement asyncElement = _asyncLibrary.libraryElement;
+    if (asyncElement == null) {
+      throw new AnalysisException("Coulb not resolve dart:async");
+    }
     _buildDirectiveModels();
-    _typeProvider = new TypeProviderImpl(coreElement);
+    _typeProvider = new TypeProviderImpl(coreElement, asyncElement);
     _buildEnumMembers();
     _buildTypeAliases();
     _buildTypeHierarchies();
@@ -7964,13 +8044,21 @@
   void _addToDependencyMap(Library library, HashMap<Library,
       List<Library>> dependencyMap, Set<Library> visitedLibraries) {
     if (visitedLibraries.add(library)) {
+      bool asyncFound = false;
       for (Library referencedLibrary in library.importsAndExports) {
         _addDependencyToMap(dependencyMap, library, referencedLibrary);
         _addToDependencyMap(referencedLibrary, dependencyMap, visitedLibraries);
+        if (identical(referencedLibrary, _asyncLibrary)) {
+          asyncFound = true;
+        }
       }
       if (!library.explicitlyImportsCore && !identical(library, _coreLibrary)) {
         _addDependencyToMap(dependencyMap, library, _coreLibrary);
       }
+      if (!asyncFound && !identical(library, _asyncLibrary)) {
+        _addDependencyToMap(dependencyMap, library, _asyncLibrary);
+        _addToDependencyMap(_asyncLibrary, dependencyMap, visitedLibraries);
+      }
     }
   }
 
@@ -8337,10 +8425,14 @@
       List<Source> importedSources, List<Source> exportedSources) {
     List<Library> importedLibraries = new List<Library>();
     bool explicitlyImportsCore = false;
+    bool importsAsync = false;
     for (Source importedSource in importedSources) {
       if (importedSource == _coreLibrarySource) {
         explicitlyImportsCore = true;
       }
+      if (importedSource == _asyncLibrarySource) {
+        importsAsync = true;
+      }
       Library importedLibrary = _libraryMap[importedSource];
       if (importedLibrary == null) {
         importedLibrary = _createLibraryOrNull(importedSource);
@@ -8377,6 +8469,15 @@
         }
       }
     }
+    if (!importsAsync && _asyncLibrarySource != library.librarySource) {
+      Library importedLibrary = _libraryMap[_asyncLibrarySource];
+      if (importedLibrary == null) {
+        importedLibrary = _createLibraryOrNull(_asyncLibrarySource);
+        if (importedLibrary != null) {
+          _computeLibraryDependencies(importedLibrary);
+        }
+      }
+    }
   }
 
   /**
@@ -8558,11 +8659,21 @@
   Source _coreLibrarySource;
 
   /**
+   * A source object representing the async library (dart:async).
+   */
+  Source _asyncLibrarySource;
+
+  /**
    * The object representing the core library.
    */
   ResolvableLibrary _coreLibrary;
 
   /**
+   * The object representing the async library.
+   */
+  ResolvableLibrary _asyncLibrary;
+
+  /**
    * The object used to access the types from the core library.
    */
   TypeProvider _typeProvider;
@@ -8587,6 +8698,8 @@
     this._errorListener = new RecordingErrorListener();
     _coreLibrarySource =
         analysisContext.sourceFactory.forUri(DartSdk.DART_CORE);
+    _asyncLibrarySource =
+        analysisContext.sourceFactory.forUri(DartSdk.DART_ASYNC);
   }
 
   /**
@@ -8625,6 +8738,7 @@
     _libraryMap = _buildLibraryMap();
     ResolvableLibrary targetLibrary = _libraryMap[librarySource];
     _coreLibrary = _libraryMap[_coreLibrarySource];
+    _asyncLibrary = _libraryMap[_asyncLibrarySource];
     //
     // Build the element models representing the libraries being resolved.
     // This is done in three steps:
@@ -8648,8 +8762,12 @@
     if (coreElement == null) {
       missingCoreLibrary(analysisContext, _coreLibrarySource);
     }
+    LibraryElement asyncElement = _asyncLibrary.libraryElement;
+    if (asyncElement == null) {
+      missingAsyncLibrary(analysisContext, _asyncLibrarySource);
+    }
     _buildDirectiveModels();
-    _typeProvider = new TypeProviderImpl(coreElement);
+    _typeProvider = new TypeProviderImpl(coreElement, asyncElement);
     _buildEnumMembers();
     _buildTypeAliases();
     _buildTypeHierarchies();
@@ -9066,6 +9184,16 @@
   }
 
   /**
+   * Report that the async library could not be resolved in the given
+   * [analysisContext] and throw an exception.  [asyncLibrarySource] is the source
+   * representing the async library.
+   */
+  static void missingAsyncLibrary(AnalysisContext analysisContext,
+      Source asyncLibrarySource) {
+    throw new AnalysisException("Could not resolve dart:async");
+  }
+
+  /**
    * Report that the core library could not be resolved in the given analysis context and throw an
    * exception.
    *
@@ -13298,6 +13426,21 @@
   InterfaceType get functionType;
 
   /**
+   * Return the type representing 'Future<dynamic>'.
+   */
+  InterfaceType get futureDynamicType;
+
+  /**
+   * Return the type representing 'Future<Null>'.
+   */
+  InterfaceType get futureNullType;
+
+  /**
+   * Return the type representing the built-in type 'Future'.
+   */
+  InterfaceType get futureType;
+
+  /**
    * Return the type representing the built-in type 'int'.
    *
    * @return the type representing the built-in type 'int'
@@ -13305,6 +13448,16 @@
   InterfaceType get intType;
 
   /**
+   * Return the type representing the type 'Iterable<dynamic>'.
+   */
+  InterfaceType get iterableDynamicType;
+
+  /**
+   * Return the type representing the built-in type 'Iterable'.
+   */
+  InterfaceType get iterableType;
+
+  /**
    * Return the type representing the built-in type 'List'.
    *
    * @return the type representing the built-in type 'List'
@@ -13347,6 +13500,16 @@
   InterfaceType get stackTraceType;
 
   /**
+   * Return the type representing 'Stream<dynamic>'.
+   */
+  InterfaceType get streamDynamicType;
+
+  /**
+   * Return the type representing the built-in type 'Stream'.
+   */
+  InterfaceType get streamType;
+
+  /**
    * Return the type representing the built-in type 'String'.
    *
    * @return the type representing the built-in type 'String'
@@ -13409,11 +13572,36 @@
   InterfaceType _functionType;
 
   /**
+   * The type representing 'Future<dynamic>'.
+   */
+  InterfaceType _futureDynamicType;
+
+  /**
+   * The type representing 'Future<Null>'.
+   */
+  InterfaceType _futureNullType;
+
+  /**
+   * The type representing the built-in type 'Future'.
+   */
+  InterfaceType _futureType;
+
+  /**
    * The type representing the built-in type 'int'.
    */
   InterfaceType _intType;
 
   /**
+   * The type representing 'Iterable<dynamic>'.
+   */
+  InterfaceType _iterableDynamicType;
+
+  /**
+   * The type representing the built-in type 'Iterable'.
+   */
+  InterfaceType _iterableType;
+
+  /**
    * The type representing the built-in type 'List'.
    */
   InterfaceType _listType;
@@ -13444,6 +13632,16 @@
   InterfaceType _stackTraceType;
 
   /**
+   * The type representing 'Stream<dynamic>'.
+   */
+  InterfaceType _streamDynamicType;
+
+  /**
+   * The type representing the built-in type 'Stream'.
+   */
+  InterfaceType _streamType;
+
+  /**
    * The type representing the built-in type 'String'.
    */
   InterfaceType _stringType;
@@ -13468,8 +13666,8 @@
    *
    * @param coreLibrary the element representing the core library (dart:core).
    */
-  TypeProviderImpl(LibraryElement coreLibrary) {
-    _initializeFrom(coreLibrary);
+  TypeProviderImpl(LibraryElement coreLibrary, LibraryElement asyncLibrary) {
+    _initializeFrom(coreLibrary, asyncLibrary);
   }
 
   @override
@@ -13491,9 +13689,24 @@
   InterfaceType get functionType => _functionType;
 
   @override
+  InterfaceType get futureDynamicType => _futureDynamicType;
+
+  @override
+  InterfaceType get futureNullType => _futureNullType;
+
+  @override
+  InterfaceType get futureType => _futureType;
+
+  @override
   InterfaceType get intType => _intType;
 
   @override
+  InterfaceType get iterableDynamicType => _iterableDynamicType;
+
+  @override
+  InterfaceType get iterableType => _iterableType;
+
+  @override
   InterfaceType get listType => _listType;
 
   @override
@@ -13512,6 +13725,12 @@
   InterfaceType get stackTraceType => _stackTraceType;
 
   @override
+  InterfaceType get streamDynamicType => _streamDynamicType;
+
+  @override
+  InterfaceType get streamType => _streamType;
+
+  @override
   InterfaceType get stringType => _stringType;
 
   @override
@@ -13546,26 +13765,36 @@
    *
    * @param library the library containing the definitions of the core types
    */
-  void _initializeFrom(LibraryElement library) {
-    Namespace namespace =
-        new NamespaceBuilder().createPublicNamespaceForLibrary(library);
-    _boolType = _getType(namespace, "bool");
+  void _initializeFrom(LibraryElement coreLibrary,
+      LibraryElement asyncLibrary) {
+    Namespace coreNamespace =
+        new NamespaceBuilder().createPublicNamespaceForLibrary(coreLibrary);
+    Namespace asyncNamespace =
+        new NamespaceBuilder().createPublicNamespaceForLibrary(asyncLibrary);
+    _boolType = _getType(coreNamespace, "bool");
     _bottomType = BottomTypeImpl.instance;
-    _deprecatedType = _getType(namespace, "Deprecated");
-    _doubleType = _getType(namespace, "double");
+    _deprecatedType = _getType(coreNamespace, "Deprecated");
+    _doubleType = _getType(coreNamespace, "double");
     _dynamicType = DynamicTypeImpl.instance;
-    _functionType = _getType(namespace, "Function");
-    _intType = _getType(namespace, "int");
-    _listType = _getType(namespace, "List");
-    _mapType = _getType(namespace, "Map");
-    _nullType = _getType(namespace, "Null");
-    _numType = _getType(namespace, "num");
-    _objectType = _getType(namespace, "Object");
-    _stackTraceType = _getType(namespace, "StackTrace");
-    _stringType = _getType(namespace, "String");
-    _symbolType = _getType(namespace, "Symbol");
-    _typeType = _getType(namespace, "Type");
+    _functionType = _getType(coreNamespace, "Function");
+    _futureType = _getType(asyncNamespace, "Future");
+    _intType = _getType(coreNamespace, "int");
+    _iterableType = _getType(coreNamespace, "Iterable");
+    _listType = _getType(coreNamespace, "List");
+    _mapType = _getType(coreNamespace, "Map");
+    _nullType = _getType(coreNamespace, "Null");
+    _numType = _getType(coreNamespace, "num");
+    _objectType = _getType(coreNamespace, "Object");
+    _stackTraceType = _getType(coreNamespace, "StackTrace");
+    _streamType = _getType(asyncNamespace, "Stream");
+    _stringType = _getType(coreNamespace, "String");
+    _symbolType = _getType(coreNamespace, "Symbol");
+    _typeType = _getType(coreNamespace, "Type");
     _undefinedType = UndefinedTypeImpl.instance;
+    _futureDynamicType = _futureType.substitute4(<DartType>[_dynamicType]);
+    _futureNullType = _futureType.substitute4(<DartType>[_nullType]);
+    _iterableDynamicType = _iterableType.substitute4(<DartType>[_dynamicType]);
+    _streamDynamicType = _streamType.substitute4(<DartType>[_dynamicType]);
   }
 }
 
diff --git a/pkg/analyzer/lib/src/generated/source.dart b/pkg/analyzer/lib/src/generated/source.dart
index f503831..01bff35 100644
--- a/pkg/analyzer/lib/src/generated/source.dart
+++ b/pkg/analyzer/lib/src/generated/source.dart
@@ -10,6 +10,10 @@
 import "dart:math" as math;
 import 'dart:collection';
 
+import 'package:analyzer/file_system/file_system.dart';
+import 'package:analyzer/source/package_map_resolver.dart';
+import 'package:analyzer/task/model.dart';
+
 import 'engine.dart';
 import 'java_core.dart';
 import 'java_engine.dart';
@@ -306,7 +310,7 @@
 /**
  * An implementation of an non-existing [Source].
  */
-class NonExistingSource implements Source {
+class NonExistingSource extends Source {
   final String _name;
 
   final UriKind uriKind;
@@ -379,7 +383,7 @@
  * retained so that if those files are created at a later date the long-lived sources representing
  * those files will know that they now exist.
  */
-abstract class Source {
+abstract class Source implements AnalysisTarget {
   /**
    * An empty list of sources.
    */
@@ -406,6 +410,9 @@
    */
   String get encoding;
 
+  @override
+  Source get source => this;
+
   /**
    * Return the full (long) version of the name that can be displayed to the user to denote this
    * source. For example, for a source representing a file this would typically be the absolute path
@@ -595,6 +602,14 @@
     this._localSourcePredicate = localSourcePredicate;
   }
 
+  /// A table mapping package names to paths of directories containing
+  /// the package (or [null] if there is no registered package URI resolver).
+  Map<String, List<Folder>> get packageMap {
+    PackageMapUriResolver resolver =
+        _resolvers.firstWhere((r) => r is PackageMapUriResolver, orElse: () => null);
+    return resolver != null ? resolver.packageMap : null;
+  }
+
   /**
    * Return a source object representing the given absolute URI, or `null` if the URI is not a
    * valid URI or if it is not an absolute URI.
diff --git a/pkg/analyzer/lib/src/generated/source_io.dart b/pkg/analyzer/lib/src/generated/source_io.dart
index ba147e3a..e0078d5 100644
--- a/pkg/analyzer/lib/src/generated/source_io.dart
+++ b/pkg/analyzer/lib/src/generated/source_io.dart
@@ -86,8 +86,7 @@
 /**
  * Instances of the class `FileBasedSource` implement a source that represents a file.
  */
-class FileBasedSource implements Source {
-
+class FileBasedSource extends Source {
   /**
    * A function that changes the way that files are read off of disk.
    */
diff --git a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
index ff88128..99a51ce 100644
--- a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
+++ b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
@@ -1391,10 +1391,24 @@
   DartType
       _computeStaticReturnTypeOfFunctionExpression(FunctionExpression node) {
     FunctionBody body = node.body;
-    if (body is ExpressionFunctionBody) {
-      return _getStaticType(body.expression);
+    if (body.isGenerator) {
+      if (body.isAsynchronous) {
+        return _typeProvider.streamDynamicType;
+      } else {
+        return _typeProvider.iterableDynamicType;
+      }
     }
-    return _dynamicType;
+    DartType type;
+    if (body is ExpressionFunctionBody) {
+      type = _getStaticType(body.expression);
+    } else {
+      type = _dynamicType;
+    }
+    if (body.isAsynchronous) {
+      return _typeProvider.futureType.substitute4(<DartType>[type]);
+    } else {
+      return type;
+    }
   }
 
   /**
diff --git a/pkg/analyzer/lib/src/generated/testing/element_factory.dart b/pkg/analyzer/lib/src/generated/testing/element_factory.dart
index ba009ad..17f814e 100644
--- a/pkg/analyzer/lib/src/generated/testing/element_factory.dart
+++ b/pkg/analyzer/lib/src/generated/testing/element_factory.dart
@@ -164,9 +164,7 @@
     // Finish building the enum.
     //
     enumElement.fields = fields;
-
-
-        // Client code isn't allowed to invoke the constructor, so we do not model it.
+    // Client code isn't allowed to invoke the constructor, so we do not model it.
     return enumElement;
   }
 
@@ -497,7 +495,7 @@
     variable.getter = getter;
     FunctionTypeImpl getterType = new FunctionTypeImpl.con1(getter);
     getter.type = getterType;
-    if (!isFinal) {
+    if (!isConst && !isFinal) {
       PropertyAccessorElementImpl setter =
           new PropertyAccessorElementImpl.forVariable(variable);
       setter.setter = true;
diff --git a/pkg/analyzer/lib/src/generated/testing/test_type_provider.dart b/pkg/analyzer/lib/src/generated/testing/test_type_provider.dart
index a176816..0d90489 100644
--- a/pkg/analyzer/lib/src/generated/testing/test_type_provider.dart
+++ b/pkg/analyzer/lib/src/generated/testing/test_type_provider.dart
@@ -47,11 +47,31 @@
   InterfaceType _functionType;
 
   /**
+   * The type representing 'Future<dynamic>'
+   */
+  InterfaceType _futureDynamicType;
+
+  /**
+   * The type representing 'Future<Null>'
+   */
+  InterfaceType _futureNullType;
+
+  /**
+   * The type representing the built-in type 'Future'
+   */
+  InterfaceType _futureType;
+
+  /**
    * The type representing the built-in type 'int'.
    */
   InterfaceType _intType;
 
   /**
+   * The type representing 'Iterable<dynamic>'
+   */
+  InterfaceType _iterableDynamicType;
+
+  /**
    * The type representing the built-in type 'Iterable'.
    */
   InterfaceType _iterableType;
@@ -92,6 +112,16 @@
   InterfaceType _stackTraceType;
 
   /**
+   * The type representing 'Stream<dynamic>'.
+   */
+  InterfaceType _streamDynamicType;
+
+  /**
+   * The type representing the built-in type 'Stream'.
+   */
+  InterfaceType _streamType;
+
+  /**
    * The type representing the built-in type 'String'.
    */
   InterfaceType _stringType;
@@ -172,6 +202,30 @@
   }
 
   @override
+  InterfaceType get futureDynamicType {
+    if (_futureDynamicType == null) {
+      _futureDynamicType = futureType.substitute4(<DartType>[dynamicType]);
+    }
+    return _futureDynamicType;
+  }
+
+  @override
+  InterfaceType get futureNullType {
+    if (_futureNullType == null) {
+      _futureNullType = futureType.substitute4(<DartType>[nullType]);
+    }
+    return _futureNullType;
+  }
+
+  @override
+  InterfaceType get futureType {
+    if (_futureType == null) {
+      _futureType = ElementFactory.classElement2("Future", ["T"]).type;
+    }
+    return _futureType;
+  }
+
+  @override
   InterfaceType get intType {
     if (_intType == null) {
       _initializeNumericTypes();
@@ -179,18 +233,29 @@
     return _intType;
   }
 
+  @override
+  InterfaceType get iterableDynamicType {
+    if (_iterableDynamicType == null) {
+      _iterableDynamicType = iterableType.substitute4(<DartType>[dynamicType]);
+    }
+    return _iterableDynamicType;
+  }
+
+  @override
   InterfaceType get iterableType {
     if (_iterableType == null) {
       ClassElementImpl iterableElement =
           ElementFactory.classElement2("Iterable", ["E"]);
       _iterableType = iterableElement.type;
       DartType eType = iterableElement.typeParameters[0].type;
-      iterableElement.accessors = <PropertyAccessorElement>[
-          ElementFactory.getterElement(
-              "iterator",
-              false,
-              iteratorType.substitute4(<DartType>[eType])),
-          ElementFactory.getterElement("last", false, eType)];
+      _setAccessors(
+          iterableElement,
+          <PropertyAccessorElement>[
+              ElementFactory.getterElement(
+                  "iterator",
+                  false,
+                  iteratorType.substitute4(<DartType>[eType])),
+              ElementFactory.getterElement("last", false, eType)]);
       _propagateTypeArguments(iterableElement);
     }
     return _iterableType;
@@ -202,8 +267,10 @@
           ElementFactory.classElement2("Iterator", ["E"]);
       _iteratorType = iteratorElement.type;
       DartType eType = iteratorElement.typeParameters[0].type;
-      iteratorElement.accessors = <PropertyAccessorElement>[
-          ElementFactory.getterElement("current", false, eType)];
+      _setAccessors(
+          iteratorElement,
+          <PropertyAccessorElement>[
+              ElementFactory.getterElement("current", false, eType)]);
       _propagateTypeArguments(iteratorElement);
     }
     return _iteratorType;
@@ -221,8 +288,10 @@
       InterfaceType iterableType =
           this.iterableType.substitute4(<DartType>[eType]);
       listElement.interfaces = <InterfaceType>[iterableType];
-      listElement.accessors = <PropertyAccessorElement>[
-          ElementFactory.getterElement("length", false, intType)];
+      _setAccessors(
+          listElement,
+          <PropertyAccessorElement>[
+              ElementFactory.getterElement("length", false, intType)]);
       listElement.methods = <MethodElement>[
           ElementFactory.methodElement("[]", eType, [intType]),
           ElementFactory.methodElement("[]=", VoidTypeImpl.instance, [intType, eType]),
@@ -240,8 +309,10 @@
       _mapType = mapElement.type;
       DartType kType = mapElement.typeParameters[0].type;
       DartType vType = mapElement.typeParameters[1].type;
-      mapElement.accessors = <PropertyAccessorElement>[
-          ElementFactory.getterElement("length", false, intType)];
+      _setAccessors(
+          mapElement,
+          <PropertyAccessorElement>[
+              ElementFactory.getterElement("length", false, intType)]);
       mapElement.methods = <MethodElement>[
           ElementFactory.methodElement("[]", vType, [objectType]),
           ElementFactory.methodElement("[]=", VoidTypeImpl.instance, [kType, vType])];
@@ -277,9 +348,11 @@
           ElementFactory.methodElement("toString", stringType),
           ElementFactory.methodElement("==", boolType, [_objectType]),
           ElementFactory.methodElement("noSuchMethod", dynamicType, [dynamicType])];
-      objectElement.accessors = <PropertyAccessorElement>[
-          ElementFactory.getterElement("hashCode", false, intType),
-          ElementFactory.getterElement("runtimeType", false, typeType)];
+      _setAccessors(
+          objectElement,
+          <PropertyAccessorElement>[
+              ElementFactory.getterElement("hashCode", false, intType),
+              ElementFactory.getterElement("runtimeType", false, typeType)]);
     }
     return _objectType;
   }
@@ -293,17 +366,35 @@
   }
 
   @override
+  InterfaceType get streamDynamicType {
+    if (_streamDynamicType == null) {
+      _streamDynamicType = streamType.substitute4(<DartType>[dynamicType]);
+    }
+    return _streamDynamicType;
+  }
+
+  @override
+  InterfaceType get streamType {
+    if (_streamType == null) {
+      _streamType = ElementFactory.classElement2("Stream", ["T"]).type;
+    }
+    return _streamType;
+  }
+
+  @override
   InterfaceType get stringType {
     if (_stringType == null) {
       _stringType = ElementFactory.classElement2("String").type;
       ClassElementImpl stringElement = _stringType.element as ClassElementImpl;
-      stringElement.accessors = <PropertyAccessorElement>[
-          ElementFactory.getterElement("isEmpty", false, boolType),
-          ElementFactory.getterElement("length", false, intType),
-          ElementFactory.getterElement(
-              "codeUnits",
-              false,
-              listType.substitute4(<DartType>[intType]))];
+      _setAccessors(
+          stringElement,
+          <PropertyAccessorElement>[
+              ElementFactory.getterElement("isEmpty", false, boolType),
+              ElementFactory.getterElement("length", false, intType),
+              ElementFactory.getterElement(
+                  "codeUnits",
+                  false,
+                  listType.substitute4(<DartType>[intType]))]);
       stringElement.methods = <MethodElement>[
           ElementFactory.methodElement("+", _stringType, [_stringType]),
           ElementFactory.methodElement("toLowerCase", _stringType),
@@ -479,4 +570,15 @@
       functionType.typeArguments = typeArguments;
     }
   }
+
+  /**
+   * Set the accessors for the given class [element] to the given [accessors]
+   * and also set the fields to those that correspond to the accessors.
+   */
+  void _setAccessors(ClassElementImpl element,
+      List<PropertyAccessorElement> accessors) {
+    element.accessors = accessors;
+    element.fields = accessors.map(
+        (PropertyAccessorElement accessor) => accessor.variable).toList();
+  }
 }
diff --git a/pkg/analyzer/lib/src/services/formatter_impl.dart b/pkg/analyzer/lib/src/services/formatter_impl.dart
index 8cc329d..ff1e30a 100644
--- a/pkg/analyzer/lib/src/services/formatter_impl.dart
+++ b/pkg/analyzer/lib/src/services/formatter_impl.dart
@@ -507,6 +507,7 @@
   }
 
   visitBlockFunctionBody(BlockFunctionBody node) {
+    token(node.keyword, followedBy: nonBreakingSpace);
     visit(node.block);
   }
 
@@ -769,6 +770,24 @@
     }
   }
 
+  visitEnumConstantDeclaration(EnumConstantDeclaration node){
+    visit(node.name);
+  }
+
+  visitEnumDeclaration(EnumDeclaration node){
+    visitMemberMetadata(node.metadata);
+    token(node.keyword);
+    space();
+    visit(node.name);
+    space();
+    token(node.leftBracket);
+    newlines();
+    indent();
+    visitCommaSeparatedNodes(node.constants);
+    newlines();
+    token(node.rightBracket, precededBy: unindent);
+  }
+
   visitExportDirective(ExportDirective node) {
     visitDirectiveMetadata(node.metadata);
     token(node.keyword);
@@ -782,6 +801,7 @@
 
   visitExpressionFunctionBody(ExpressionFunctionBody node) {
     int weight = lastSpaceWeight++;
+    token(node.keyword, followedBy: nonBreakingSpace);
     token(node.functionDefinition);
     levelSpace(weight);
     visit(node.expression);
@@ -1839,14 +1859,4 @@
   }
 
   String toString() => writer.toString();
-
-  @override
-  visitEnumConstantDeclaration(EnumConstantDeclaration node) {
-    // TODO: implement visitEnumConstantDeclaration
-  }
-
-  @override
-  visitEnumDeclaration(EnumDeclaration node) {
-    // TODO: implement visitEnumDeclaration
-  }
 }
diff --git a/pkg/analyzer/lib/src/string_source.dart b/pkg/analyzer/lib/src/string_source.dart
index 789e74c..0d2a9b7 100644
--- a/pkg/analyzer/lib/src/string_source.dart
+++ b/pkg/analyzer/lib/src/string_source.dart
@@ -8,7 +8,7 @@
 import 'generated/source.dart';
 
 /// An implementation of [Source] that's based on an in-memory Dart string.
-class StringSource implements Source {
+class StringSource extends Source {
   final String _contents;
   final String fullName;
   final int modificationStamp;
diff --git a/pkg/analyzer/lib/src/task/dart.dart b/pkg/analyzer/lib/src/task/dart.dart
new file mode 100644
index 0000000..9c741a6
--- /dev/null
+++ b/pkg/analyzer/lib/src/task/dart.dart
@@ -0,0 +1,314 @@
+// Copyright (c) 2015, 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 analyzer.src.task.dart;
+
+import 'dart:collection';
+
+import 'package:analyzer/src/generated/ast.dart';
+import 'package:analyzer/src/generated/element.dart';
+import 'package:analyzer/src/generated/engine.dart' hide AnalysisTask;
+import 'package:analyzer/src/generated/error.dart';
+import 'package:analyzer/src/generated/java_engine.dart';
+import 'package:analyzer/src/generated/parser.dart';
+import 'package:analyzer/src/generated/resolver.dart';
+import 'package:analyzer/src/generated/scanner.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/task/general.dart';
+import 'package:analyzer/task/dart.dart';
+import 'package:analyzer/task/general.dart';
+import 'package:analyzer/task/model.dart';
+
+/**
+ * A task that builds a compilation unit element for a single compilation unit.
+ */
+class BuildCompilationUnitElementTask extends SourceBasedAnalysisTask {
+  /**
+   * The name of the input whose value is the line information for the
+   * compilation unit.
+   */
+  static const String LINE_INFO_INPUT_NAME = "lineInfo";
+
+  /**
+   * The name of the input whose value is the AST for the compilation unit.
+   */
+  static const String PARSED_UNIT_INPUT_NAME = "parsedUnit";
+
+  /**
+   * The task descriptor describing this kind of task.
+   */
+  static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
+      'BUILD_COMPILATION_UNIT_ELEMENT',
+      createTask,
+      buildInputs,
+      <ResultDescriptor>[COMPILATION_UNIT_ELEMENT, BUILT_UNIT]);
+
+  /**
+   * Initialize a newly created task to build a compilation unit element for
+   * the given [target] in the given [context].
+   */
+  BuildCompilationUnitElementTask(InternalAnalysisContext context,
+      AnalysisTarget target)
+      : super(context, target);
+
+  @override
+  TaskDescriptor get descriptor => DESCRIPTOR;
+
+  @override
+  void internalPerform() {
+    Source source = getRequiredSource();
+    CompilationUnit unit = getRequiredInput(PARSED_UNIT_INPUT_NAME);
+
+    CompilationUnitBuilder builder = new CompilationUnitBuilder();
+    CompilationUnitElement element = builder.buildCompilationUnit(source, unit);
+
+    outputs[COMPILATION_UNIT_ELEMENT] = element;
+    outputs[BUILT_UNIT] = unit;
+  }
+
+  /**
+   * Return a map from the names of the inputs of this kind of task to the task
+   * input descriptors describing those inputs for a task with the given [target].
+   */
+  static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
+    return <String, TaskInput>{
+      PARSED_UNIT_INPUT_NAME: PARSED_UNIT.inputFor(target)
+    };
+  }
+
+  /**
+   * Create a [BuildCompilationUnitElementTask] based on the given [target] in
+   * the given [context].
+   */
+  static BuildCompilationUnitElementTask createTask(AnalysisContext context,
+      AnalysisTarget target) {
+    return new BuildCompilationUnitElementTask(context, target);
+  }
+}
+
+/**
+ * A task that parses the content of a Dart file, producing an AST structure.
+ */
+class ParseDartTask extends SourceBasedAnalysisTask {
+  /**
+   * The name of the input whose value is the line information produced for the
+   * file.
+   */
+  static const String LINE_INFO_INPUT_NAME = "lineInfo";
+
+  /**
+   * The name of the input whose value is the token stream produced for the file.
+   */
+  static const String TOKEN_STREAM_INPUT_NAME = "tokenStream";
+
+  /**
+   * The task descriptor describing this kind of task.
+   */
+  static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
+      'PARSE_DART',
+      createTask,
+      buildInputs,
+      <ResultDescriptor>[
+          EXPORTED_LIBRARIES,
+          IMPORTED_LIBRARIES,
+          INCLUDED_PARTS,
+          PARSE_ERRORS,
+          PARSED_UNIT,
+          SOURCE_KIND]);
+
+  /**
+   * Initialize a newly created task to parse the content of the Dart file
+   * associated with the given [target] in the given [context].
+   */
+  ParseDartTask(InternalAnalysisContext context, AnalysisTarget target)
+      : super(context, target);
+
+  @override
+  TaskDescriptor get descriptor => DESCRIPTOR;
+
+  @override
+  void internalPerform() {
+    Source source = getRequiredSource();
+    LineInfo lineInfo = getRequiredInput(LINE_INFO_INPUT_NAME);
+    Token tokenStream = getRequiredInput(TOKEN_STREAM_INPUT_NAME);
+
+    RecordingErrorListener errorListener = new RecordingErrorListener();
+    Parser parser = new Parser(source, errorListener);
+    AnalysisOptions options = context.analysisOptions;
+    parser.parseFunctionBodies = options.analyzeFunctionBodies;
+    CompilationUnit unit = parser.parseCompilationUnit(tokenStream);
+    unit.lineInfo = lineInfo;
+
+    bool hasNonPartOfDirective = false;
+    bool hasPartOfDirective = false;
+    HashSet<Source> exportedSources = new HashSet<Source>();
+    HashSet<Source> importedSources = new HashSet<Source>();
+    HashSet<Source> includedSources = new HashSet<Source>();
+    for (Directive directive in unit.directives) {
+      if (directive is PartOfDirective) {
+        hasPartOfDirective = true;
+      } else {
+        hasNonPartOfDirective = true;
+        if (directive is UriBasedDirective) {
+          Source referencedSource =
+              resolveDirective(context, source, directive, errorListener);
+          if (referencedSource != null) {
+            if (directive is ExportDirective) {
+              exportedSources.add(referencedSource);
+            } else if (directive is ImportDirective) {
+              importedSources.add(referencedSource);
+            } else if (directive is PartDirective) {
+              if (referencedSource != source) {
+                includedSources.add(referencedSource);
+              }
+            } else {
+              throw new AnalysisException(
+                  "$runtimeType failed to handle a ${directive.runtimeType}");
+            }
+          }
+        }
+      }
+    }
+    SourceKind sourceKind = SourceKind.LIBRARY;
+    if (!hasNonPartOfDirective && hasPartOfDirective) {
+      sourceKind = SourceKind.PART;
+    }
+
+    outputs[EXPORTED_LIBRARIES] = exportedSources.toList();
+    outputs[IMPORTED_LIBRARIES] = importedSources.toList();
+    outputs[INCLUDED_PARTS] = includedSources.toList();
+    outputs[PARSE_ERRORS] = errorListener.getErrorsForSource(source);
+    outputs[PARSED_UNIT] = unit;
+    outputs[SOURCE_KIND] = sourceKind;
+  }
+
+  /**
+   * Return a map from the names of the inputs of this kind of task to the task
+   * input descriptors describing those inputs for a task with the given [target].
+   */
+  static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
+    return <String, TaskInput>{
+      LINE_INFO_INPUT_NAME: LINE_INFO.inputFor(target),
+      TOKEN_STREAM_INPUT_NAME: TOKEN_STREAM.inputFor(target)
+    };
+  }
+
+  /**
+   * Create a [ParseDartTask] based on the given [target] in the given
+   * [context].
+   */
+  static ParseDartTask createTask(AnalysisContext context,
+      AnalysisTarget target) {
+    return new ParseDartTask(context, target);
+  }
+
+  /**
+   * Return the result of resolving the URI of the given URI-based [directive]
+   * against the URI of the given library, or `null` if the URI is not valid.
+   *
+   * Resolution is to be performed in the given [context]. Errors should be
+   * reported to the [errorListener].
+   */
+  static Source resolveDirective(AnalysisContext context, Source librarySource,
+      UriBasedDirective directive, AnalysisErrorListener errorListener) {
+    StringLiteral uriLiteral = directive.uri;
+    String uriContent = uriLiteral.stringValue;
+    if (uriContent != null) {
+      uriContent = uriContent.trim();
+      directive.uriContent = uriContent;
+    }
+    UriValidationCode code = directive.validate();
+    if (code == null) {
+      String encodedUriContent = Uri.encodeFull(uriContent);
+      Source source =
+          context.sourceFactory.resolveUri(librarySource, encodedUriContent);
+      directive.source = source;
+      return source;
+    }
+    if (code == UriValidationCode.URI_WITH_DART_EXT_SCHEME) {
+      return null;
+    }
+    if (code == UriValidationCode.URI_WITH_INTERPOLATION) {
+      errorListener.onError(
+          new AnalysisError.con2(
+              librarySource,
+              uriLiteral.offset,
+              uriLiteral.length,
+              CompileTimeErrorCode.URI_WITH_INTERPOLATION));
+      return null;
+    }
+    if (code == UriValidationCode.INVALID_URI) {
+      errorListener.onError(
+          new AnalysisError.con2(
+              librarySource,
+              uriLiteral.offset,
+              uriLiteral.length,
+              CompileTimeErrorCode.INVALID_URI,
+              [uriContent]));
+      return null;
+    }
+    throw new AnalysisException('Failed to handle validation code: $code');
+  }
+}
+
+/**
+ * A task that scans the content of a file, producing a set of Dart tokens.
+ */
+class ScanDartTask extends SourceBasedAnalysisTask {
+  /**
+   * The name of the input whose value is the content of the file.
+   */
+  static const String CONTENT_INPUT_NAME = "content";
+
+  /**
+   * The task descriptor describing this kind of task.
+   */
+  static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
+      'SCAN_DART',
+      createTask,
+      buildInputs,
+      <ResultDescriptor>[LINE_INFO, SCAN_ERRORS, TOKEN_STREAM]);
+
+  /**
+   * Initialize a newly created task to access the content of the source
+   * associated with the given [target] in the given [context].
+   */
+  ScanDartTask(InternalAnalysisContext context, AnalysisTarget target)
+      : super(context, target);
+
+  @override
+  TaskDescriptor get descriptor => DESCRIPTOR;
+
+  @override
+  void internalPerform() {
+    Source source = getRequiredSource();
+    String content = getRequiredInput(CONTENT_INPUT_NAME);
+
+    RecordingErrorListener errorListener = new RecordingErrorListener();
+    Scanner scanner =
+        new Scanner(source, new CharSequenceReader(content), errorListener);
+    scanner.preserveComments = context.analysisOptions.preserveComments;
+    outputs[TOKEN_STREAM] = scanner.tokenize();
+    outputs[LINE_INFO] = new LineInfo(scanner.lineStarts);
+    outputs[SCAN_ERRORS] = errorListener.getErrorsForSource(source);
+  }
+
+  /**
+   * Return a map from the names of the inputs of this kind of task to the task
+   * input descriptors describing those inputs for a task with the given [target].
+   */
+  static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
+    return <String, TaskInput>{
+      CONTENT_INPUT_NAME: CONTENT.inputFor(target)
+    };
+  }
+
+  /**
+   * Create a [ScanDartTask] based on the given [target] in the given [context].
+   */
+  static ScanDartTask createTask(AnalysisContext context,
+      AnalysisTarget target) {
+    return new ScanDartTask(context, target);
+  }
+}
diff --git a/pkg/analyzer/lib/src/task/general.dart b/pkg/analyzer/lib/src/task/general.dart
index 25feb6f..5cb31ed 100644
--- a/pkg/analyzer/lib/src/task/general.dart
+++ b/pkg/analyzer/lib/src/task/general.dart
@@ -13,7 +13,7 @@
  * A task that gets the contents of the source associated with an analysis
  * target.
  */
-class GetContentTask extends AnalysisTask {
+class GetContentTask extends SourceBasedAnalysisTask {
   /**
    * The task descriptor describing this kind of task.
    */
@@ -31,15 +31,6 @@
       : super(context, target);
 
   @override
-  String get description {
-    Source source = target.source;
-    if (source == null) {
-      return "get contents of <unknown source>";
-    }
-    return "get contents of ${source.fullName}";
-  }
-
-  @override
   TaskDescriptor get descriptor => DESCRIPTOR;
 
   @override
@@ -68,3 +59,23 @@
     return new GetContentTask(context, target);
   }
 }
+
+/**
+ * A base class for analysis tasks whose target is expected to be a source.
+ */
+abstract class SourceBasedAnalysisTask extends AnalysisTask {
+  /**
+   * Initialize a newly created task to perform analysis within the given
+   * [context] in order to produce results for the given [target].
+   */
+  SourceBasedAnalysisTask(AnalysisContext context, AnalysisTarget target)
+      : super(context, target);
+
+  @override
+  String get description {
+    Source source = target.source;
+    String sourceName =
+        target.source == null ? '<unknown source>' : source.fullName;
+    return '${descriptor.name} for source $sourceName';
+  }
+}
diff --git a/pkg/analyzer/lib/src/task/targets.dart b/pkg/analyzer/lib/src/task/targets.dart
deleted file mode 100644
index 8c55f51..0000000
--- a/pkg/analyzer/lib/src/task/targets.dart
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright (c) 2015, 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 analyzer.src.task.targets;
-
-import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer/task/model.dart';
-
-/**
- * A `SourceTarget` is a [Source] that can be used as an [AnalysisTarget].
- */
-class SourceTarget implements AnalysisTarget {
-  /**
-   * The source being represented as a target.
-   */
-  final Source source;
-
-  /**
-   * Initialize a newly created target to represent the given [source].
-   */
-  SourceTarget(this.source);
-
-  @override
-  int get hashCode => source.hashCode;
-
-  @override
-  bool operator ==(Object object) {
-    return object is SourceTarget && object.source == source;
-  }
-}
diff --git a/pkg/analyzer/lib/src/util/asserts.dart b/pkg/analyzer/lib/src/util/asserts.dart
new file mode 100644
index 0000000..a53e7e6
--- /dev/null
+++ b/pkg/analyzer/lib/src/util/asserts.dart
@@ -0,0 +1,20 @@
+// Copyright (c) 2015, 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 engine.utilities.asserts;
+
+/**
+ * Ensures that the given [value] is not null.
+ * Otherwise throws an [ArgumentError].
+ * An optional [description] is used in the error message.
+ */
+void notNull(Object value, [String description]) {
+  if (value == null) {
+    if (description == null) {
+      throw new ArgumentError('Must not be null');
+    } else {
+      throw new ArgumentError('Must not be null: $description');
+    }
+  }
+}
diff --git a/pkg/analyzer/lib/task/model.dart b/pkg/analyzer/lib/task/model.dart
index 7254f19..a00b215 100644
--- a/pkg/analyzer/lib/task/model.dart
+++ b/pkg/analyzer/lib/task/model.dart
@@ -251,6 +251,11 @@
   CreateTaskInputs get createTaskInputs;
 
   /**
+   * Return the name of the task being described.
+   */
+  String get name;
+
+  /**
    * Return a list of the analysis results that will be computed by this task.
    */
   List<ResultDescriptor> get results;
diff --git a/pkg/analyzer/pubspec.yaml b/pkg/analyzer/pubspec.yaml
index 6dab3e8..6c686bb 100644
--- a/pkg/analyzer/pubspec.yaml
+++ b/pkg/analyzer/pubspec.yaml
@@ -1,5 +1,5 @@
 name: analyzer
-version: 0.23.0-dev.14
+version: 0.23.0
 author: Dart Team <misc@dartlang.org>
 description: Static analyzer for Dart.
 homepage: http://www.dartlang.org
diff --git a/pkg/analyzer/test/generated/all_the_rest_test.dart b/pkg/analyzer/test/generated/all_the_rest_test.dart
index 3c1f95b..e4e8404 100644
--- a/pkg/analyzer/test/generated/all_the_rest_test.dart
+++ b/pkg/analyzer/test/generated/all_the_rest_test.dart
@@ -58,6 +58,7 @@
   runReflectiveTests(ErrorReporterTest);
   runReflectiveTests(ErrorSeverityTest);
   runReflectiveTests(ExitDetectorTest);
+  runReflectiveTests(ExitDetectorTest2);
   runReflectiveTests(FileBasedSourceTest);
   runReflectiveTests(FileUriResolverTest);
   runReflectiveTests(HtmlParserTest);
@@ -6849,7 +6850,11 @@
   }
 }
 
-
+/**
+ * Tests for the [ExitDetector] that do not require that the AST be resolved.
+ *
+ * See [ExitDetectorTest2] for tests that require the AST to be resolved.
+ */
 @reflectiveTest
 class ExitDetectorTest extends ParserTestCase {
   void fail_doStatement_continue_with_label() {
@@ -6892,6 +6897,14 @@
     _assertTrue("v = throw '';");
   }
 
+  void test_await_false() {
+    _assertFalse("await x;");
+  }
+
+  void test_await_throw_true() {
+    _assertTrue("bool b = await (throw '' || true);");
+  }
+
   void test_binaryExpression_and() {
     _assertFalse("a && b;");
   }
@@ -7339,6 +7352,98 @@
   }
 }
 
+/**
+ * Tests for the [ExitDetector] that require that the AST be resolved.
+ *
+ * See [ExitDetectorTest] for tests that do not require the AST to be resolved.
+ */
+@reflectiveTest
+class ExitDetectorTest2 extends ResolverTestCase {
+  void test_switch_withEnum_false_noDefault() {
+    Source source = addSource(r'''
+enum E { A, B }
+String f(E e) {
+  var x;
+  switch (e) {
+    case A:
+      x = 'A';
+    case B:
+      x = 'B';
+  }
+  return x;
+}
+''');
+    LibraryElement element = resolve(source);
+    CompilationUnit unit = resolveCompilationUnit(source, element);
+    FunctionDeclaration function = unit.declarations.last;
+    BlockFunctionBody body = function.functionExpression.body;
+    Statement statement = body.block.statements[1];
+    expect(statement.accept(new ExitDetector()), false);
+  }
+
+  void test_switch_withEnum_false_withDefault() {
+    Source source = addSource(r'''
+enum E { A, B }
+String f(E e) {
+  var x;
+  switch (e) {
+    case A:
+      x = 'A';
+    default:
+      x = '?';
+  }
+  return x;
+}
+''');
+    LibraryElement element = resolve(source);
+    CompilationUnit unit = resolveCompilationUnit(source, element);
+    FunctionDeclaration function = unit.declarations.last;
+    BlockFunctionBody body = function.functionExpression.body;
+    Statement statement = body.block.statements[1];
+    expect(statement.accept(new ExitDetector()), false);
+  }
+
+  void test_switch_withEnum_true_noDefault() {
+    Source source = addSource(r'''
+enum E { A, B }
+String f(E e) {
+  switch (e) {
+    case A:
+      return 'A';
+    case B:
+      return 'B';
+  }
+}
+''');
+    LibraryElement element = resolve(source);
+    CompilationUnit unit = resolveCompilationUnit(source, element);
+    FunctionDeclaration function = unit.declarations.last;
+    BlockFunctionBody body = function.functionExpression.body;
+    Statement statement = body.block.statements[0];
+    expect(statement.accept(new ExitDetector()), true);
+  }
+
+  void test_switch_withEnum_true_withDefault() {
+    Source source = addSource(r'''
+enum E { A, B }
+String f(E e) {
+  switch (e) {
+    case A:
+      return 'A';
+    default:
+      return '?';
+  }
+}
+''');
+    LibraryElement element = resolve(source);
+    CompilationUnit unit = resolveCompilationUnit(source, element);
+    FunctionDeclaration function = unit.declarations.last;
+    BlockFunctionBody body = function.functionExpression.body;
+    Statement statement = body.block.statements[0];
+    expect(statement.accept(new ExitDetector()), true);
+  }
+}
+
 
 @reflectiveTest
 class FileBasedSourceTest {
@@ -7364,27 +7469,6 @@
     expect(source1 == source2, isTrue);
   }
 
-  void test_getEncoding() {
-    SourceFactory factory = new SourceFactory([new FileUriResolver()]);
-    String fullPath = "/does/not/exist.dart";
-    JavaFile file = FileUtilities2.createFile(fullPath);
-    FileBasedSource source = new FileBasedSource.con1(file);
-    expect(factory.fromEncoding(source.encoding), source);
-  }
-
-  void test_getFullName() {
-    String fullPath = "/does/not/exist.dart";
-    JavaFile file = FileUtilities2.createFile(fullPath);
-    FileBasedSource source = new FileBasedSource.con1(file);
-    expect(source.fullName, file.getAbsolutePath());
-  }
-
-  void test_getShortName() {
-    JavaFile file = FileUtilities2.createFile("/does/not/exist.dart");
-    FileBasedSource source = new FileBasedSource.con1(file);
-    expect(source.shortName, "exist.dart");
-  }
-
   void test_fileReadMode() {
     expect(FileBasedSource.fileReadMode('a'), 'a');
     expect(FileBasedSource.fileReadMode('a\n'), 'a\n');
@@ -7427,6 +7511,27 @@
     FileBasedSource.fileReadMode = (String s) => s;
   }
 
+  void test_getEncoding() {
+    SourceFactory factory = new SourceFactory([new FileUriResolver()]);
+    String fullPath = "/does/not/exist.dart";
+    JavaFile file = FileUtilities2.createFile(fullPath);
+    FileBasedSource source = new FileBasedSource.con1(file);
+    expect(factory.fromEncoding(source.encoding), source);
+  }
+
+  void test_getFullName() {
+    String fullPath = "/does/not/exist.dart";
+    JavaFile file = FileUtilities2.createFile(fullPath);
+    FileBasedSource source = new FileBasedSource.con1(file);
+    expect(source.fullName, file.getAbsolutePath());
+  }
+
+  void test_getShortName() {
+    JavaFile file = FileUtilities2.createFile("/does/not/exist.dart");
+    FileBasedSource source = new FileBasedSource.con1(file);
+    expect(source.shortName, "exist.dart");
+  }
+
   void test_hashCode() {
     JavaFile file1 = FileUtilities2.createFile("/does/not/exist.dart");
     JavaFile file2 = FileUtilities2.createFile("/does/not/exist.dart");
diff --git a/pkg/analyzer/test/generated/ast_test.dart b/pkg/analyzer/test/generated/ast_test.dart
index 3bfa906..7fc025d 100644
--- a/pkg/analyzer/test/generated/ast_test.dart
+++ b/pkg/analyzer/test/generated/ast_test.dart
@@ -28,6 +28,7 @@
   runReflectiveTests(ClassTypeAliasTest);
   runReflectiveTests(ConstantEvaluatorTest);
   runReflectiveTests(ConstructorDeclarationTest);
+  runReflectiveTests(FieldFormalParameterTest);
   runReflectiveTests(IndexExpressionTest);
   runReflectiveTests(NodeListTest);
   runReflectiveTests(NodeLocatorTest);
@@ -663,6 +664,19 @@
 }
 
 @reflectiveTest
+class FieldFormalParameterTest extends EngineTestCase {
+  void test_endToken_noParameters() {
+    FieldFormalParameter parameter = AstFactory.fieldFormalParameter2('field');
+    expect(parameter.endToken, parameter.identifier.endToken);
+  }
+
+  void test_endToken_parameters() {
+    FieldFormalParameter parameter = AstFactory.fieldFormalParameter(null, null, 'field', AstFactory.formalParameterList([]));
+    expect(parameter.endToken, parameter.parameters.endToken);
+  }
+}
+
+@reflectiveTest
 class IndexExpressionTest extends EngineTestCase {
   void test_inGetterContext_assignment_compound_left() {
     IndexExpression expression = AstFactory.indexExpression(
diff --git a/pkg/analyzer/test/generated/compile_time_error_code_test.dart b/pkg/analyzer/test/generated/compile_time_error_code_test.dart
index 968adec..095c419 100644
--- a/pkg/analyzer/test/generated/compile_time_error_code_test.dart
+++ b/pkg/analyzer/test/generated/compile_time_error_code_test.dart
@@ -20,6 +20,32 @@
 
 @reflectiveTest
 class CompileTimeErrorCodeTest extends ResolverTestCase {
+  void fail_awaitInWrongContext_sync() {
+    // This test requires better error recovery than we currently have. In
+    // particular, we need to be able to distinguish between an await expression
+    // in the wrong context, and the use of 'await' as an identifier.
+    Source source = addSource(r'''
+f(x) {
+  return await x;
+}''');
+    resolve(source);
+    assertErrors(source, [CompileTimeErrorCode.AWAIT_IN_WRONG_CONTEXT]);
+    verify([source]);
+  }
+
+  void fail_awaitInWrongContext_syncStar() {
+    // This test requires better error recovery than we currently have. In
+    // particular, we need to be able to distinguish between an await expression
+    // in the wrong context, and the use of 'await' as an identifier.
+    Source source = addSource(r'''
+f(x) sync* {
+  yield await x;
+}''');
+    resolve(source);
+    assertErrors(source, [CompileTimeErrorCode.AWAIT_IN_WRONG_CONTEXT]);
+    verify([source]);
+  }
+
   void fail_compileTimeConstantRaisesException() {
     Source source = addSource(r'''
 ''');
@@ -220,6 +246,300 @@
     verify([source]);
   }
 
+  void test_async_used_as_identifier_in_annotation() {
+    Source source = addSource('''
+const int async = 0;
+f() async {
+  g(@async x) {}
+  g(0);
+}
+''');
+    resolve(source);
+    assertErrors(source, [ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER]);
+    verify([source]);
+  }
+
+  void test_async_used_as_identifier_in_argument_label() {
+    Source source = addSource('''
+@proxy
+class C {}
+f() async {
+  new C().g(async: 0);
+}
+''');
+    resolve(source);
+    assertErrors(source, [ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER]);
+    // Note: we don't call verify([source]) because verify() doesn't understand
+    // about @proxy.
+  }
+
+  void test_async_used_as_identifier_in_async_method() {
+    Source source = addSource('''
+f() async {
+  var async = 1;
+}
+''');
+    resolve(source);
+    assertErrors(source, [ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER]);
+    verify([source]);
+  }
+
+  void test_async_used_as_identifier_in_async_star_method() {
+    Source source = addSource('''
+f() async* {
+  var async = 1;
+}
+''');
+    resolve(source);
+    assertErrors(source, [ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER]);
+    verify([source]);
+  }
+
+  void test_async_used_as_identifier_in_break_statement() {
+    Source source = addSource('''
+f() async {
+  while (true) {
+    break async;
+  }
+}
+''');
+    resolve(source);
+    assertErrors(
+        source,
+        [
+            ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER,
+            CompileTimeErrorCode.LABEL_UNDEFINED]);
+    // Note: we don't call verify([source]) because the reference to the
+    // "async" label is unresolved.
+  }
+
+  void test_async_used_as_identifier_in_cascaded_invocation() {
+    Source source = addSource('''
+class C {
+  int async() => 1;
+}
+f() async {
+  return new C()..async();
+}
+''');
+    resolve(source);
+    assertErrors(source, [ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER]);
+    verify([source]);
+  }
+
+  void test_async_used_as_identifier_in_cascaded_setter_invocation() {
+    Source source = addSource('''
+class C {
+  void set async(int i) {}
+}
+f() async {
+  return new C()..async = 1;
+}
+''');
+    resolve(source);
+    assertErrors(source, [ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER]);
+    verify([source]);
+  }
+
+  void test_async_used_as_identifier_in_catch_exception_argument() {
+    Source source = addSource('''
+g() {}
+f() async {
+  try {
+    g();
+  } catch (async) { }
+}
+''');
+    resolve(source);
+    assertErrors(source, [ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER]);
+    verify([source]);
+  }
+
+  void test_async_used_as_identifier_in_catch_stacktrace_argument() {
+    Source source = addSource('''
+g() {}
+f() async {
+  try {
+    g();
+  } catch (e, async) { }
+}
+''');
+    resolve(source);
+    assertErrors(source, [ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER]);
+    verify([source]);
+  }
+
+  void test_async_used_as_identifier_in_continue_statement() {
+    Source source = addSource('''
+f() async {
+  while (true) {
+    continue async;
+  }
+}
+''');
+    resolve(source);
+    assertErrors(
+        source,
+        [
+            ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER,
+            CompileTimeErrorCode.LABEL_UNDEFINED]);
+    // Note: we don't call verify([source]) because the reference to the
+    // "async" label is unresolved.
+  }
+
+  void test_async_used_as_identifier_in_for_statement() {
+    Source source = addSource('''
+var async;
+f() async {
+  for (async in []) {}
+}
+''');
+    resolve(source);
+    assertErrors(source, [ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER]);
+    verify([source]);
+  }
+
+  void test_async_used_as_identifier_in_formal_parameter_name() {
+    Source source = addSource('''
+f() async {
+  g(int async) {}
+  g(0);
+}
+''');
+    resolve(source);
+    assertErrors(source, [ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER]);
+    verify([source]);
+  }
+
+  void test_async_used_as_identifier_in_getter_name() {
+    Source source = addSource('''
+class C {
+  int get async => 1;
+}
+f() async {
+  return new C().async;
+}
+''');
+    resolve(source);
+    assertErrors(source, [ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER]);
+    verify([source]);
+  }
+
+  void test_async_used_as_identifier_in_invocation() {
+    Source source = addSource('''
+class C {
+  int async() => 1;
+}
+f() async {
+  return new C().async();
+}
+''');
+    resolve(source);
+    assertErrors(source, [ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER]);
+    verify([source]);
+  }
+
+  void test_async_used_as_identifier_in_local_function_name() {
+    Source source = addSource('''
+f() async {
+  int async() => null;
+}
+''');
+    resolve(source);
+    assertErrors(source, [ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER]);
+    verify([source]);
+  }
+
+  void test_async_used_as_identifier_in_prefix() {
+    Source source = addSource('''
+import 'dart:async' as async;
+f() async {
+  return new async.Future.value(0);
+}
+''');
+    resolve(source);
+    assertErrors(source, [ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER]);
+    verify([source]);
+  }
+
+  void test_async_used_as_identifier_in_setter_name() {
+    Source source = addSource('''
+class C {
+  void set async(int i) {}
+}
+f() async {
+  new C().async = 1;
+}
+''');
+    resolve(source);
+    assertErrors(source, [ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER]);
+    verify([source]);
+  }
+
+  void test_async_used_as_identifier_in_statement_label() {
+    Source source = addSource('''
+f() async {
+  async: g();
+}
+g() {}
+''');
+    resolve(source);
+    assertErrors(source, [ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER]);
+    verify([source]);
+  }
+
+  void test_async_used_as_identifier_in_string_interpolation() {
+    Source source = addSource(r'''
+int async = 1;
+f() async {
+  return "$async";
+}
+''');
+    resolve(source);
+    assertErrors(source, [ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER]);
+    verify([source]);
+  }
+
+  void test_async_used_as_identifier_in_suffix() {
+    addNamedSource("/lib1.dart", r'''
+library lib1;
+int async;
+''');
+    Source source = addSource('''
+import 'lib1.dart' as l;
+f() async {
+  return l.async;
+}
+''');
+    resolve(source);
+    assertErrors(source, [ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER]);
+    verify([source]);
+  }
+
+  void test_async_used_as_identifier_in_switch_label() {
+    Source source = addSource('''
+f() async {
+  switch (0) {
+    async: case 0: break;
+  }
+}
+''');
+    resolve(source);
+    assertErrors(source, [ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER]);
+    verify([source]);
+  }
+
+  void test_async_used_as_identifier_in_sync_star_method() {
+    Source source = addSource('''
+f() sync* {
+  var async = 1;
+}
+''');
+    resolve(source);
+    assertErrors(source, [ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER]);
+    verify([source]);
+  }
+
   void test_asyncForInWrongContext() {
     Source source = addSource(r'''
 f(list) {
@@ -231,23 +551,36 @@
     verify([source]);
   }
 
-  void test_awaitInWrongContext_sync() {
-    Source source = addSource(r'''
-f(x) {
-  return await x;
-}''');
+  void test_await_used_as_identifier_in_async_method() {
+    Source source = addSource('''
+f() async {
+  var await = 1;
+}
+''');
     resolve(source);
-    assertErrors(source, [CompileTimeErrorCode.AWAIT_IN_WRONG_CONTEXT]);
+    assertErrors(source, [ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER]);
     verify([source]);
   }
 
-  void test_awaitInWrongContext_syncStar() {
-    Source source = addSource(r'''
-f(x) sync* {
-  yield await x;
-}''');
+  void test_await_used_as_identifier_in_async_star_method() {
+    Source source = addSource('''
+f() async* {
+  var await = 1;
+}
+''');
     resolve(source);
-    assertErrors(source, [CompileTimeErrorCode.AWAIT_IN_WRONG_CONTEXT]);
+    assertErrors(source, [ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER]);
+    verify([source]);
+  }
+
+  void test_await_used_as_identifier_in_sync_star_method() {
+    Source source = addSource('''
+f() sync* {
+  var await = 1;
+}
+''');
+    resolve(source);
+    assertErrors(source, [ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER]);
     verify([source]);
   }
 
@@ -647,8 +980,7 @@
 import 'lib1.dart' deferred as a;
 main() {
   const a.A();
-}'''],
-          <ErrorCode>[CompileTimeErrorCode.CONST_DEFERRED_CLASS]);
+}'''], <ErrorCode>[CompileTimeErrorCode.CONST_DEFERRED_CLASS]);
   }
 
   void test_constDeferredClass_namedConstructor() {
@@ -661,8 +993,7 @@
 import 'lib1.dart' deferred as a;
 main() {
   const a.A.b();
-}'''],
-          <ErrorCode>[CompileTimeErrorCode.CONST_DEFERRED_CLASS]);
+}'''], <ErrorCode>[CompileTimeErrorCode.CONST_DEFERRED_CLASS]);
   }
 
   void test_constEval_newInstance_constConstructor() {
@@ -5341,6 +5672,39 @@
     verify([source]);
   }
 
+  void test_yield_used_as_identifier_in_async_method() {
+    Source source = addSource('''
+f() async {
+  var yield = 1;
+}
+''');
+    resolve(source);
+    assertErrors(source, [ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER]);
+    verify([source]);
+  }
+
+  void test_yield_used_as_identifier_in_async_star_method() {
+    Source source = addSource('''
+f() async* {
+  var yield = 1;
+}
+''');
+    resolve(source);
+    assertErrors(source, [ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER]);
+    verify([source]);
+  }
+
+  void test_yield_used_as_identifier_in_sync_star_method() {
+    Source source = addSource('''
+f() sync* {
+  var yield = 1;
+}
+''');
+    resolve(source);
+    assertErrors(source, [ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER]);
+    verify([source]);
+  }
+
   void _check_constEvalThrowsException_binary_null(String expr, bool resolved) {
     Source source = addSource("const C = $expr;");
     resolve(source);
diff --git a/pkg/analyzer/test/generated/element_test.dart b/pkg/analyzer/test/generated/element_test.dart
index 399d8c4..e89fb06 100644
--- a/pkg/analyzer/test/generated/element_test.dart
+++ b/pkg/analyzer/test/generated/element_test.dart
@@ -3110,6 +3110,33 @@
     expect(typeB.lookUpGetter(getterName, library), same(getterG));
   }
 
+  void test_lookUpGetter_mixin_shadowing() {
+    //
+    // class B {}
+    // class M1 { get g {} }
+    // class M2 { get g {} }
+    // class C extends B with M1, M2 {}
+    //
+    TestTypeProvider typeProvider = new TestTypeProvider();
+    String getterName = 'g';
+    ClassElementImpl classB = ElementFactory.classElement2('B');
+    ClassElementImpl classM1 = ElementFactory.classElement2('M1');
+    PropertyAccessorElementImpl getterM1g =
+        ElementFactory.getterElement(getterName, false, typeProvider.dynamicType);
+    classM1.accessors = <PropertyAccessorElement>[getterM1g];
+    ClassElementImpl classM2 = ElementFactory.classElement2('M2');
+    PropertyAccessorElementImpl getterM2g =
+        ElementFactory.getterElement(getterName, false, typeProvider.dynamicType);
+    classM2.accessors = <PropertyAccessorElement>[getterM2g];
+    ClassElementImpl classC = ElementFactory.classElement('C', classB.type);
+    classC.mixins = <InterfaceType>[classM1.type, classM2.type];
+    LibraryElementImpl library =
+        ElementFactory.library(createAnalysisContext(), "lib");
+    CompilationUnitElementImpl unit = library.definingCompilationUnit;
+    unit.types = <ClassElement>[classB, classM1, classM2, classC];
+    expect(classC.type.lookUpGetter(getterName, library), getterM2g);
+  }
+
   void test_lookUpGetter_recursive() {
     //
     // class A extends B {}
@@ -3173,6 +3200,32 @@
     expect(typeB.lookUpMethod(methodName, library), same(methodM));
   }
 
+  void test_lookUpMethod_mixin_shadowing() {
+    //
+    // class B {}
+    // class M1 { m() {} }
+    // class M2 { m() {} }
+    // class C extends B with M1, M2 {}
+    //
+    String methodName = 'm';
+    ClassElementImpl classB = ElementFactory.classElement2('B');
+    ClassElementImpl classM1 = ElementFactory.classElement2('M1');
+    MethodElementImpl methodM1m =
+        ElementFactory.methodElement(methodName, null);
+    classM1.methods = <MethodElement>[methodM1m];
+    ClassElementImpl classM2 = ElementFactory.classElement2('M2');
+    MethodElementImpl methodM2m =
+        ElementFactory.methodElement(methodName, null);
+    classM2.methods = <MethodElement>[methodM2m];
+    ClassElementImpl classC = ElementFactory.classElement('C', classB.type);
+    classC.mixins = <InterfaceType>[classM1.type, classM2.type];
+    LibraryElementImpl library =
+        ElementFactory.library(createAnalysisContext(), "lib");
+    CompilationUnitElementImpl unit = library.definingCompilationUnit;
+    unit.types = <ClassElement>[classB, classM1, classM2, classC];
+    expect(classC.type.lookUpMethod(methodName, library), methodM2m);
+  }
+
   void test_lookUpMethod_parameterized() {
     //
     // class A<E> { E m(E p) {} }
@@ -3275,6 +3328,33 @@
     expect(typeB.lookUpSetter(setterName, library), same(setterS));
   }
 
+  void test_lookUpSetter_mixin_shadowing() {
+    //
+    // class B {}
+    // class M1 { set s() {} }
+    // class M2 { set s() {} }
+    // class C extends B with M1, M2 {}
+    //
+    TestTypeProvider typeProvider = new TestTypeProvider();
+    String setterName = 's';
+    ClassElementImpl classB = ElementFactory.classElement2('B');
+    ClassElementImpl classM1 = ElementFactory.classElement2('M1');
+    PropertyAccessorElementImpl setterM1g =
+        ElementFactory.setterElement(setterName, false, typeProvider.dynamicType);
+    classM1.accessors = <PropertyAccessorElement>[setterM1g];
+    ClassElementImpl classM2 = ElementFactory.classElement2('M2');
+    PropertyAccessorElementImpl setterM2g =
+        ElementFactory.getterElement(setterName, false, typeProvider.dynamicType);
+    classM2.accessors = <PropertyAccessorElement>[setterM2g];
+    ClassElementImpl classC = ElementFactory.classElement('C', classB.type);
+    classC.mixins = <InterfaceType>[classM1.type, classM2.type];
+    LibraryElementImpl library =
+        ElementFactory.library(createAnalysisContext(), "lib");
+    CompilationUnitElementImpl unit = library.definingCompilationUnit;
+    unit.types = <ClassElement>[classB, classM1, classM2, classC];
+    expect(classC.type.lookUpGetter(setterName, library), setterM2g);
+  }
+
   void test_lookUpSetter_recursive() {
     //
     // class A extends B {}
diff --git a/pkg/analyzer/test/generated/engine_test.dart b/pkg/analyzer/test/generated/engine_test.dart
index 9951999..a30c5f6 100644
--- a/pkg/analyzer/test/generated/engine_test.dart
+++ b/pkg/analyzer/test/generated/engine_test.dart
@@ -1691,8 +1691,8 @@
         _context.getResolvedCompilationUnit2(libBSource, libBSource),
         isNotNull,
         reason: "libB resolved 2");
-    AnalysisErrorInfo errors = _context.getErrors(htmlSource);
     // TODO (danrubel) commented out to fix red bots
+//    AnalysisErrorInfo errors = _context.getErrors(htmlSource);
 //    expect(
 //        !_hasAnalysisErrorWithErrorSeverity(errors),
 //        isTrue,
diff --git a/pkg/analyzer/test/generated/incremental_resolver_test.dart b/pkg/analyzer/test/generated/incremental_resolver_test.dart
index 2c8f00a..90106a9 100644
--- a/pkg/analyzer/test/generated/incremental_resolver_test.dart
+++ b/pkg/analyzer/test/generated/incremental_resolver_test.dart
@@ -620,6 +620,38 @@
 ''');
   }
 
+  void test_false_function_async_add() {
+    _assertDoesNotMatch(r'''
+main() {}
+''', r'''
+main() async {}
+''');
+  }
+
+  void test_false_function_async_remove() {
+    _assertDoesNotMatch(r'''
+main() async {}
+''', r'''
+main() {}
+''');
+  }
+
+  void test_false_function_generator_add() {
+    _assertDoesNotMatch(r'''
+main() async {}
+''', r'''
+main() async* {}
+''');
+  }
+
+  void test_false_function_generator_remove() {
+    _assertDoesNotMatch(r'''
+main() async* {}
+''', r'''
+main() async {}
+''');
+  }
+
   void test_false_functionTypeAlias_list_add() {
     _assertDoesNotMatch(r'''
 typedef A(int pa);
@@ -925,6 +957,54 @@
 ''');
   }
 
+  void test_false_method_async_add() {
+    _assertDoesNotMatchOK(r'''
+class A {
+  m() {}
+}
+''', r'''
+class A {
+  m() async {}
+}
+''');
+  }
+
+  void test_false_method_async_remove() {
+    _assertDoesNotMatchOK(r'''
+class A {
+  m() async {}
+}
+''', r'''
+class A {
+  m() {}
+}
+''');
+  }
+
+  void test_false_method_generator_add() {
+    _assertDoesNotMatchOK(r'''
+class A {
+  m() async {}
+}
+''', r'''
+class A {
+  m() async* {}
+}
+''');
+  }
+
+  void test_false_method_generator_remove() {
+    _assertDoesNotMatchOK(r'''
+class A {
+  m() async* {}
+}
+''', r'''
+class A {
+  m() async {}
+}
+''');
+  }
+
   void test_false_method_list_add() {
     _assertDoesNotMatchOK(r'''
 class A {
@@ -1775,6 +1855,18 @@
 ''');
   }
 
+  void test_true_method_async() {
+    _assertMatches(r'''
+class A {
+  m() async {}
+}
+''', r'''
+class A {
+  m() async {}
+}
+''');
+  }
+
   void test_true_method_list_reorder() {
     _assertMatches(r'''
 class A {
diff --git a/pkg/analyzer/test/generated/non_error_resolver_test.dart b/pkg/analyzer/test/generated/non_error_resolver_test.dart
index 2264443..680045a 100644
--- a/pkg/analyzer/test/generated/non_error_resolver_test.dart
+++ b/pkg/analyzer/test/generated/non_error_resolver_test.dart
@@ -295,6 +295,229 @@
     verify([source]);
   }
 
+  void test_async_dynamic_with_return() {
+    Source source = addSource('''
+dynamic f() async {
+  return;
+}
+''');
+    resolve(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
+  void test_async_dynamic_with_return_value() {
+    Source source = addSource('''
+dynamic f() async {
+  return 5;
+}
+''');
+    resolve(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
+  void test_async_dynamic_without_return() {
+    Source source = addSource('''
+dynamic f() async {}
+''');
+    resolve(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
+  void test_async_expression_function_type() {
+    Source source = addSource('''
+import 'dart:async';
+typedef Future<int> F(int i);
+main() {
+  F f = (int i) async => i;
+}
+''');
+    resolve(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
+  void test_async_future_dynamic_with_return() {
+    Source source = addSource('''
+import 'dart:async';
+Future<dynamic> f() async {
+  return;
+}
+''');
+    resolve(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
+  void test_async_future_dynamic_with_return_value() {
+    Source source = addSource('''
+import 'dart:async';
+Future<dynamic> f() async {
+  return 5;
+}
+''');
+    resolve(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
+  void test_async_future_dynamic_without_return() {
+    Source source = addSource('''
+import 'dart:async';
+Future<dynamic> f() async {}
+''');
+    resolve(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
+  void test_async_future_int_with_return_future_int() {
+    Source source = addSource('''
+import 'dart:async';
+Future<int> f() async {
+  return new Future<int>.value(5);
+}
+''');
+    resolve(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
+  void test_async_future_int_with_return_value() {
+    Source source = addSource('''
+import 'dart:async';
+Future<int> f() async {
+  return 5;
+}
+''');
+    resolve(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
+  void test_async_future_null_with_return() {
+    Source source = addSource('''
+import 'dart:async';
+Future<Null> f() async {
+  return;
+}
+''');
+    resolve(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
+  void test_async_future_null_without_return() {
+    Source source = addSource('''
+import 'dart:async';
+Future<Null> f() async {}
+''');
+    resolve(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
+  void test_async_future_object_with_return() {
+    Source source = addSource('''
+import 'dart:async';
+Future<Object> f() async {
+  return;
+}
+''');
+    resolve(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
+  void test_async_future_object_with_return_value() {
+    Source source = addSource('''
+import 'dart:async';
+Future<Object> f() async {
+  return 5;
+}
+''');
+    resolve(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
+  void test_async_future_object_without_return() {
+    Source source = addSource('''
+import 'dart:async';
+Future<Object> f() async {}
+''');
+    resolve(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
+  void test_async_future_with_return() {
+    Source source = addSource('''
+import 'dart:async';
+Future f() async {
+  return;
+}
+''');
+    resolve(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
+  void test_async_future_with_return_value() {
+    Source source = addSource('''
+import 'dart:async';
+Future f() async {
+  return 5;
+}
+''');
+    resolve(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
+  void test_async_future_without_return() {
+    Source source = addSource('''
+import 'dart:async';
+Future f() async {}
+''');
+    resolve(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
+  void test_async_with_return() {
+    Source source = addSource('''
+f() async {
+  return;
+}
+''');
+    resolve(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
+  void test_async_with_return_value() {
+    Source source = addSource('''
+f() async {
+  return 5;
+}
+''');
+    resolve(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
+  void test_async_without_return() {
+    Source source = addSource('''
+f() async {}
+''');
+    resolve(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
   void test_asyncForInWrongContext_async() {
     Source source = addSource(r'''
 f(list) async {
@@ -782,8 +1005,7 @@
 import 'lib1.dart' deferred as a;
 main() {
   new a.A.b();
-}'''],
-          <ErrorCode>[]);
+}'''], <ErrorCode>[]);
   }
 
   void test_constEval_functionTypeLiteral() {
@@ -1058,6 +1280,27 @@
     verify([source]);
   }
 
+  void test_empty_generator_async() {
+    Source source = addSource('''
+import 'dart:async';
+Stream<int> f() async* {
+}
+''');
+    resolve(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
+  void test_empty_generator_sync() {
+    Source source = addSource('''
+Iterable<int> f() sync* {
+}
+''');
+    resolve(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
   void test_expectedOneListTypeArgument() {
     Source source = addSource(r'''
 main() {
@@ -2519,8 +2762,29 @@
 import 'lib1.dart' deferred as other;
 main() {
   other.loadLibrary().then((_) => other.foo());
-}'''],
-          <ErrorCode>[]);
+}'''], <ErrorCode>[]);
+  }
+
+  void test_local_generator_async() {
+    Source source = addSource('''
+f() {
+  return () async* { yield 0; };
+}
+''');
+    resolve(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
+  void test_local_generator_sync() {
+    Source source = addSource('''
+f() {
+  return () sync* { yield 0; };
+}
+''');
+    resolve(source);
+    assertNoErrors(source);
+    verify([source]);
   }
 
   void test_mapKeyTypeNotAssignable() {
@@ -3809,6 +4073,29 @@
     verify([source]);
   }
 
+  void test_return_in_generator_async() {
+    Source source = addSource('''
+import 'dart:async';
+Stream<int> f() async* {
+  return;
+}
+''');
+    resolve(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
+  void test_return_in_generator_sync() {
+    Source source = addSource('''
+Iterable<int> f() sync* {
+  return;
+}
+''');
+    resolve(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
   void test_returnInGenerativeConstructor() {
     Source source = addSource(r'''
 class A {
@@ -3977,8 +4264,7 @@
 import 'lib1.dart' deferred as lib1;
 import 'lib2.dart' as lib;
 import 'lib3.dart' as lib;
-main() { lib1.f1(); lib.f2(); lib.f3(); }'''],
-          <ErrorCode>[]);
+main() { lib1.f1(); lib.f2(); lib.f3(); }'''], <ErrorCode>[]);
   }
 
   void test_staticAccessToInstanceMember_annotation() {
@@ -4747,21 +5033,240 @@
     verify([source]);
   }
 
-  void test_yieldEachInNonGenerator_asyncStar() {
-    Source source = addSource(r'''
-f() async* {
-  yield* 0;
-}''');
+  void test_yield_async_to_dynamic_type() {
+    Source source = addSource('''
+dynamic f() async* {
+  yield 3;
+}
+''');
     resolve(source);
     assertNoErrors(source);
     verify([source]);
   }
 
-  void test_yieldEachInNonGenerator_syncStar() {
-    Source source = addSource(r'''
+  void test_yield_async_to_generic_type() {
+    Source source = addSource('''
+import 'dart:async';
+Stream f() async* {
+  yield 3;
+}
+''');
+    resolve(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
+  void test_yield_async_to_parameterized_type() {
+    Source source = addSource('''
+import 'dart:async';
+Stream<int> f() async* {
+  yield 3;
+}
+''');
+    resolve(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
+  void test_yield_async_to_untyped() {
+    Source source = addSource('''
+f() async* {
+  yield 3;
+}
+''');
+    resolve(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
+  void test_yield_each_async_dynamic_to_dynamic() {
+    Source source = addSource('''
+f() async* {
+  yield* g();
+}
+g() => null;
+''');
+    resolve(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
+  void test_yield_each_async_dynamic_to_stream() {
+    Source source = addSource('''
+import 'dart:async';
+Stream f() async* {
+  yield* g();
+}
+g() => null;
+''');
+    resolve(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
+  void test_yield_each_async_dynamic_to_typed_stream() {
+    Source source = addSource('''
+import 'dart:async';
+Stream<int> f() async* {
+  yield* g();
+}
+g() => null;
+''');
+    resolve(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
+  void test_yield_each_async_stream_to_dynamic() {
+    Source source = addSource('''
+import 'dart:async';
+f() async* {
+  yield* g();
+}
+Stream g() => null;
+''');
+    resolve(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
+  void test_yield_each_async_typed_stream_to_dynamic() {
+    Source source = addSource('''
+import 'dart:async';
+f() async* {
+  yield* g();
+}
+Stream<int> g() => null;
+''');
+    resolve(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
+  void test_yield_each_async_typed_stream_to_typed_stream() {
+    Source source = addSource('''
+import 'dart:async';
+Stream<int> f() async* {
+  yield* g();
+}
+Stream<int> g() => null;
+''');
+    resolve(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
+  void test_yield_each_sync_dynamic_to_dynamic() {
+    Source source = addSource('''
 f() sync* {
-  yield* 0;
-}''');
+  yield* g();
+}
+g() => null;
+''');
+    resolve(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
+  void test_yield_each_sync_dynamic_to_iterable() {
+    Source source = addSource('''
+Iterable f() sync* {
+  yield* g();
+}
+g() => null;
+''');
+    resolve(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
+  void test_yield_each_sync_dynamic_to_typed_iterable() {
+    Source source = addSource('''
+Iterable<int> f() sync* {
+  yield* g();
+}
+g() => null;
+''');
+    resolve(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
+  void test_yield_each_sync_iterable_to_dynamic() {
+    Source source = addSource('''
+f() sync* {
+  yield* g();
+}
+Iterable g() => null;
+''');
+    resolve(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
+  void test_yield_each_sync_typed_iterable_to_dynamic() {
+    Source source = addSource('''
+f() sync* {
+  yield* g();
+}
+Iterable<int> g() => null;
+''');
+    resolve(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
+  void test_yield_each_sync_typed_iterable_to_typed_iterable() {
+    Source source = addSource('''
+Iterable<int> f() sync* {
+  yield* g();
+}
+Iterable<int> g() => null;
+''');
+    resolve(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
+  void test_yield_sync_to_dynamic_type() {
+    Source source = addSource('''
+dynamic f() sync* {
+  yield 3;
+}
+''');
+    resolve(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
+  void test_yield_sync_to_generic_type() {
+    Source source = addSource('''
+Iterable f() sync* {
+  yield 3;
+}
+''');
+    resolve(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
+  void test_yield_sync_to_parameterized_type() {
+    Source source = addSource('''
+Iterable<int> f() sync* {
+  yield 3;
+}
+''');
+    resolve(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
+  void test_yield_sync_to_untyped() {
+    Source source = addSource('''
+f() sync* {
+  yield 3;
+}
+''');
     resolve(source);
     assertNoErrors(source);
     verify([source]);
diff --git a/pkg/analyzer/test/generated/parser_test.dart b/pkg/analyzer/test/generated/parser_test.dart
index ac43b31..db3753c 100644
--- a/pkg/analyzer/test/generated/parser_test.dart
+++ b/pkg/analyzer/test/generated/parser_test.dart
@@ -779,6 +779,18 @@
         [ParserErrorCode.ABSTRACT_TYPEDEF]);
   }
 
+  void test_annotationOnEnumConstant_first() {
+    ParserTestCase.parseCompilationUnit(
+        "enum E { @override C }",
+        [ParserErrorCode.ANNOTATION_ON_ENUM_CONSTANT]);
+  }
+
+  void test_annotationOnEnumConstant_middle() {
+    ParserTestCase.parseCompilationUnit(
+        "enum E { C, @override D, E }",
+        [ParserErrorCode.ANNOTATION_ON_ENUM_CONSTANT]);
+  }
+
   void test_assertDoesNotTakeAssignment() {
     ParserTestCase.parse4(
         "parseAssertStatement",
@@ -5165,6 +5177,39 @@
  */
 @reflectiveTest
 class SimpleParserTest extends ParserTestCase {
+  void fail_parseAwaitExpression_inSync() {
+    // This test requires better error recovery than we currently have. In
+    // particular, we need to be able to distinguish between an await expression
+    // in the wrong context, and the use of 'await' as an identifier.
+    MethodDeclaration method = ParserTestCase.parse(
+        "parseClassMember",
+        <Object>["C"],
+        "m() { return await x + await y; }");
+    FunctionBody body = method.body;
+    EngineTestCase.assertInstanceOf(
+        (obj) => obj is BlockFunctionBody,
+        BlockFunctionBody,
+        body);
+    Statement statement = (body as BlockFunctionBody).block.statements[0];
+    EngineTestCase.assertInstanceOf(
+        (obj) => obj is ReturnStatement,
+        ReturnStatement,
+        statement);
+    Expression expression = (statement as ReturnStatement).expression;
+    EngineTestCase.assertInstanceOf(
+        (obj) => obj is BinaryExpression,
+        BinaryExpression,
+        expression);
+    EngineTestCase.assertInstanceOf(
+        (obj) => obj is AwaitExpression,
+        AwaitExpression,
+        (expression as BinaryExpression).leftOperand);
+    EngineTestCase.assertInstanceOf(
+        (obj) => obj is AwaitExpression,
+        AwaitExpression,
+        (expression as BinaryExpression).rightOperand);
+  }
+
   void fail_parseCommentReference_this() {
     // This fails because we are returning null from the method and asserting
     // that the return value is not null.
@@ -5762,36 +5807,6 @@
         statement);
   }
 
-  void test_parseAwaitExpression_inSync() {
-    MethodDeclaration method = ParserTestCase.parse(
-        "parseClassMember",
-        <Object>["C"],
-        "m() { return await x + await y; }");
-    FunctionBody body = method.body;
-    EngineTestCase.assertInstanceOf(
-        (obj) => obj is BlockFunctionBody,
-        BlockFunctionBody,
-        body);
-    Statement statement = (body as BlockFunctionBody).block.statements[0];
-    EngineTestCase.assertInstanceOf(
-        (obj) => obj is ReturnStatement,
-        ReturnStatement,
-        statement);
-    Expression expression = (statement as ReturnStatement).expression;
-    EngineTestCase.assertInstanceOf(
-        (obj) => obj is BinaryExpression,
-        BinaryExpression,
-        expression);
-    EngineTestCase.assertInstanceOf(
-        (obj) => obj is AwaitExpression,
-        AwaitExpression,
-        (expression as BinaryExpression).leftOperand);
-    EngineTestCase.assertInstanceOf(
-        (obj) => obj is AwaitExpression,
-        AwaitExpression,
-        (expression as BinaryExpression).rightOperand);
-  }
-
   void test_parseBitwiseAndExpression_normal() {
     BinaryExpression expression =
         ParserTestCase.parse4("parseBitwiseAndExpression", "x & y");
@@ -7844,6 +7859,11 @@
     expect(list.arguments, hasLength(1));
   }
 
+  void test_parseExpression_nonAwait() {
+    MethodInvocation expression = ParserTestCase.parseExpression("await()");
+    expect(expression.methodName.name, 'await');
+  }
+
   void test_parseExpression_superMethodInvocation() {
     MethodInvocation invocation =
         ParserTestCase.parse4("parseExpression", "super.m()");
diff --git a/pkg/analyzer/test/generated/resolver_test.dart b/pkg/analyzer/test/generated/resolver_test.dart
index 380829c..17c8e69 100644
--- a/pkg/analyzer/test/generated/resolver_test.dart
+++ b/pkg/analyzer/test/generated/resolver_test.dart
@@ -23,8 +23,9 @@
 import 'package:analyzer/src/generated/source_io.dart';
 import 'package:analyzer/src/generated/static_type_analyzer.dart';
 import 'package:analyzer/src/generated/testing/ast_factory.dart';
-import 'package:analyzer/src/generated/testing/test_type_provider.dart';
 import 'package:analyzer/src/generated/testing/element_factory.dart';
+import 'package:analyzer/src/generated/testing/test_type_provider.dart';
+import 'package:analyzer/src/generated/testing/token_factory.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart';
 import 'package:unittest/unittest.dart';
 
@@ -126,6 +127,8 @@
         provider.doubleType.element,
         provider.functionType.element,
         provider.intType.element,
+        provider.iterableType.element,
+        provider.iteratorType.element,
         provider.listType.element,
         provider.mapType.element,
         provider.nullType.element,
@@ -161,9 +164,7 @@
             provider.deprecatedType);
     coreUnit.accessors = <PropertyAccessorElement>[
         proxyTopLevelVariableElt.getter,
-        proxyTopLevelVariableElt.setter,
-        deprecatedTopLevelVariableElt.getter,
-        deprecatedTopLevelVariableElt.setter];
+        deprecatedTopLevelVariableElt.getter];
     coreUnit.topLevelVariables = <TopLevelVariableElement>[
         proxyTopLevelVariableElt,
         deprecatedTopLevelVariableElt];
@@ -200,8 +201,9 @@
     FunctionTypeAliasElementImpl aliasElement =
         new FunctionTypeAliasElementImpl.forNode(null);
     aliasElement.synthetic = true;
-    aliasElement.shareParameters(parameters);
+    aliasElement.parameters = parameters;
     aliasElement.returnType = provider.dynamicType;
+    aliasElement.enclosingElement = asyncUnit;
     FunctionTypeImpl aliasType = new FunctionTypeImpl.con2(aliasElement);
     aliasElement.shareTypeParameters(futureElement.typeParameters);
     aliasType.typeArguments = futureElement.type.typeArguments;
@@ -253,6 +255,8 @@
             [provider.stringType])];
     canvasElement.accessors = <PropertyAccessorElement>[
         ElementFactory.getterElement("context2D", false, context2dElement.type)];
+    canvasElement.fields = canvasElement.accessors.map(
+        (PropertyAccessorElement accessor) => accessor.variable).toList();
     ClassElementImpl documentElement =
         ElementFactory.classElement("Document", elementType);
     ClassElementImpl htmlDocumentElement =
@@ -3072,6 +3076,16 @@
     verify([source]);
   }
 
+  void test_missingReturn_async() {
+    Source source = addSource('''
+import 'dart:async';
+Future<int> f() async {}
+''');
+    resolve(source);
+    assertErrors(source, [HintCode.MISSING_RETURN]);
+    verify([source]);
+  }
+
   void test_missingReturn_function() {
     Source source = addSource("int f() {}");
     resolve(source);
@@ -4606,6 +4620,29 @@
     _assertNoErrors(classB);
   }
 
+  void test_getMapOfMembersInheritedFromClasses_method_with_two_mixins() {
+    // class A1 { int m(); }
+    // class A2 { int m(); }
+    // class B extends Object with A1, A2 {}
+    ClassElementImpl classA1 = ElementFactory.classElement2("A1");
+    String methodName = "m";
+    MethodElement methodA1M =
+        ElementFactory.methodElement(methodName, _typeProvider.intType);
+    classA1.methods = <MethodElement>[methodA1M];
+    ClassElementImpl classA2 = ElementFactory.classElement2("A2");
+    MethodElement methodA2M =
+        ElementFactory.methodElement(methodName, _typeProvider.intType);
+    classA2.methods = <MethodElement>[methodA2M];
+    ClassElementImpl classB = ElementFactory.classElement2("B");
+    classB.mixins = <InterfaceType>[classA1.type, classA2.type];
+    MemberMap mapB =
+        _inheritanceManager.getMapOfMembersInheritedFromClasses(classB);
+    expect(mapB.get(methodName), same(methodA2M));
+    _assertNoErrors(classA1);
+    _assertNoErrors(classA2);
+    _assertNoErrors(classB);
+  }
+
   void test_getMapOfMembersInheritedFromInterfaces_accessor_extends() {
     // class A { int get g; }
     // class B extends A {}
@@ -6045,12 +6082,16 @@
 
   Source _coreLibrarySource;
 
+  Source _asyncLibrarySource;
+
   @override
   void setUp() {
     super.setUp();
     _resolver = new LibraryResolver2(analysisContext2);
     _coreLibrarySource =
         analysisContext2.sourceFactory.forUri(DartSdk.DART_CORE);
+    _asyncLibrarySource =
+        analysisContext2.sourceFactory.forUri(DartSdk.DART_ASYNC);
   }
 
   void test_imports_relative() {
@@ -6066,10 +6107,13 @@
     ResolvableLibrary coreLib = _createResolvableLibrary(_coreLibrarySource);
     coreLib.libraryElement = analysisContext2.computeLibraryElement(
         _coreLibrarySource) as LibraryElementImpl;
+    ResolvableLibrary asyncLib = _createResolvableLibrary(_asyncLibrarySource);
+    asyncLib.libraryElement = analysisContext2.computeLibraryElement(
+        _asyncLibrarySource) as LibraryElementImpl;
     ResolvableLibrary libA = _createResolvableLibrary(sourceA);
     ResolvableLibrary libB = _createResolvableLibrary(sourceB);
-    libA.importedLibraries = <ResolvableLibrary>[coreLib, libB];
-    libB.importedLibraries = <ResolvableLibrary>[coreLib, libA];
+    libA.importedLibraries = <ResolvableLibrary>[coreLib, asyncLib, libB];
+    libB.importedLibraries = <ResolvableLibrary>[coreLib, asyncLib, libA];
     cycle.add(libA);
     cycle.add(libB);
     LibraryElement library = _resolver.resolveLibrary(sourceA, cycle);
@@ -6329,6 +6373,24 @@
 
 @reflectiveTest
 class NonHintCodeTest extends ResolverTestCase {
+  void fail_propagatedFieldType() {
+    // From dartbug.com/20019
+    Source source = addSource(r'''
+class A { }
+class X<T> {
+  final x = new List<T>();
+}
+class Z {
+  final X<A> y = new X<A>();
+  foo() {
+    y.x.add(new A());
+  }
+}''');
+    resolve(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
   void test_deadCode_deadBlock_conditionalElse_debugConst() {
     Source source = addSource(r'''
 const bool DEBUG = true;
@@ -6551,8 +6613,7 @@
 f() {}''', r'''
 library root;
 import 'lib1.dart' deferred as lib1;
-main() { lib1.f(); }'''],
-          ErrorCode.EMPTY_LIST);
+main() { lib1.f(); }'''], ErrorCode.EMPTY_LIST);
   }
 
   void test_issue20904BuggyTypePromotionAtIfJoin_1() {
@@ -6755,24 +6816,6 @@
     verify([source]);
   }
 
-  void fail_propagatedFieldType() {
-    // From dartbug.com/20019
-    Source source = addSource(r'''
-class A { }
-class X<T> {
-  final x = new List<T>();
-}
-class Z {
-  final X<A> y = new X<A>();
-  foo() {
-    y.x.add(new A());
-  }
-}''');
-    resolve(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
   void test_proxy_annotation_prefixed() {
     Source source = addSource(r'''
 library L;
@@ -7880,13 +7923,6 @@
     return null;
   }
 
-  void resolveWithErrors(List<String> strSources, List<ErrorCode> codes) {
-    // Analysis and assertions
-    Source source = resolveSources(strSources);
-    assertErrors(source, codes);
-    verify([source]);
-  }
-
   void resolveWithAndWithoutExperimental(List<String> strSources,
       List<ErrorCode> codesWithoutExperimental,
       List<ErrorCode> codesWithExperimental) {
@@ -7906,6 +7942,13 @@
     verify([source]);
   }
 
+  void resolveWithErrors(List<String> strSources, List<ErrorCode> codes) {
+    // Analysis and assertions
+    Source source = resolveSources(strSources);
+    assertErrors(source, codes);
+    verify([source]);
+  }
+
   @override
   void setUp() {
     reset();
@@ -8036,6 +8079,44 @@
 
 @reflectiveTest
 class SimpleResolverTest extends ResolverTestCase {
+  void fail_getter_and_setter_fromMixins_property_access() {
+    // TODO(paulberry): it appears that auxiliaryElements isn't properly set on
+    // a SimpleIdentifier that's inside a property access.  This bug should be
+    // fixed.
+    Source source = addSource('''
+class B {}
+class M1 {
+  get x => null;
+  set x(value) {}
+}
+class M2 {
+  get x => null;
+  set x(value) {}
+}
+class C extends B with M1, M2 {}
+void main() {
+  new C().x += 1;
+}
+''');
+    LibraryElement library = resolve(source);
+    assertNoErrors(source);
+    verify([source]);
+    // Verify that both the getter and setter for "x" in "new C().x" refer to
+    // the accessors defined in M2.
+    FunctionDeclaration main =
+        library.definingCompilationUnit.functions[0].node;
+    BlockFunctionBody body = main.functionExpression.body;
+    ExpressionStatement stmt = body.block.statements[0];
+    AssignmentExpression assignment = stmt.expression;
+    PropertyAccess propertyAccess = assignment.leftHandSide;
+    expect(
+        propertyAccess.propertyName.staticElement.enclosingElement.name,
+        'M2');
+    expect(
+        propertyAccess.propertyName.auxiliaryElements.staticElement.enclosingElement.name,
+        'M2');
+  }
+
   void fail_staticInvocation() {
     Source source = addSource(r'''
 class A {
@@ -8734,6 +8815,97 @@
     verify([source]);
   }
 
+  void test_getter_and_setter_fromMixins_bare_identifier() {
+    Source source = addSource('''
+class B {}
+class M1 {
+  get x => null;
+  set x(value) {}
+}
+class M2 {
+  get x => null;
+  set x(value) {}
+}
+class C extends B with M1, M2 {
+  void f() {
+    x += 1;
+  }
+}
+''');
+    LibraryElement library = resolve(source);
+    assertNoErrors(source);
+    verify([source]);
+    // Verify that both the getter and setter for "x" in C.f() refer to the
+    // accessors defined in M2.
+    ClassElement classC = library.definingCompilationUnit.types[3];
+    MethodDeclaration f = classC.getMethod('f').node;
+    BlockFunctionBody body = f.body;
+    ExpressionStatement stmt = body.block.statements[0];
+    AssignmentExpression assignment = stmt.expression;
+    SimpleIdentifier leftHandSide = assignment.leftHandSide;
+    expect(leftHandSide.staticElement.enclosingElement.name, 'M2');
+    expect(
+        leftHandSide.auxiliaryElements.staticElement.enclosingElement.name,
+        'M2');
+  }
+
+  void test_getter_fromMixins_bare_identifier() {
+    Source source = addSource('''
+class B {}
+class M1 {
+  get x => null;
+}
+class M2 {
+  get x => null;
+}
+class C extends B with M1, M2 {
+  f() {
+    return x;
+  }
+}
+''');
+    LibraryElement library = resolve(source);
+    assertNoErrors(source);
+    verify([source]);
+    // Verify that the getter for "x" in C.f() refers to the getter defined in
+    // M2.
+    ClassElement classC = library.definingCompilationUnit.types[3];
+    MethodDeclaration f = classC.getMethod('f').node;
+    BlockFunctionBody body = f.body;
+    ReturnStatement stmt = body.block.statements[0];
+    SimpleIdentifier x = stmt.expression;
+    expect(x.staticElement.enclosingElement.name, 'M2');
+  }
+
+  void test_getter_fromMixins_property_access() {
+    Source source = addSource('''
+class B {}
+class M1 {
+  get x => null;
+}
+class M2 {
+  get x => null;
+}
+class C extends B with M1, M2 {}
+void main() {
+  var y = new C().x;
+}
+''');
+    LibraryElement library = resolve(source);
+    assertNoErrors(source);
+    verify([source]);
+    // Verify that the getter for "x" in "new C().x" refers to the getter
+    // defined in M2.
+    FunctionDeclaration main =
+        library.definingCompilationUnit.functions[0].node;
+    BlockFunctionBody body = main.functionExpression.body;
+    VariableDeclarationStatement stmt = body.block.statements[0];
+    PropertyAccess propertyAccess = stmt.variables.variables[0].initializer;
+    expect(
+        propertyAccess.propertyName.staticElement.enclosingElement.name,
+        'M2');
+  }
+
   void test_getterAndSetterWithDifferentTypes() {
     Source source = addSource(r'''
 class A {
@@ -9228,6 +9400,87 @@
     verify([source]);
   }
 
+  void test_method_fromMixins() {
+    Source source = addSource('''
+class B {}
+class M1 {
+  void f() {}
+}
+class M2 {
+  void f() {}
+}
+class C extends B with M1, M2 {}
+void main() {
+  new C().f();
+}
+''');
+    LibraryElement library = resolve(source);
+    assertNoErrors(source);
+    verify([source]);
+    // Verify that the "f" in "new C().f()" refers to the "f" defined in M2.
+    FunctionDeclaration main =
+        library.definingCompilationUnit.functions[0].node;
+    BlockFunctionBody body = main.functionExpression.body;
+    ExpressionStatement stmt = body.block.statements[0];
+    MethodInvocation expr = stmt.expression;
+    expect(expr.methodName.staticElement.enclosingElement.name, 'M2');
+  }
+
+  void test_method_fromMixins_bare_identifier() {
+    Source source = addSource('''
+class B {}
+class M1 {
+  void f() {}
+}
+class M2 {
+  void f() {}
+}
+class C extends B with M1, M2 {
+  void g() {
+    f();
+  }
+}
+''');
+    LibraryElement library = resolve(source);
+    assertNoErrors(source);
+    verify([source]);
+    // Verify that the call to f() in C.g() refers to the method defined in M2.
+    ClassElement classC = library.definingCompilationUnit.types[3];
+    MethodDeclaration g = classC.getMethod('g').node;
+    BlockFunctionBody body = g.body;
+    ExpressionStatement stmt = body.block.statements[0];
+    MethodInvocation invocation = stmt.expression;
+    SimpleIdentifier methodName = invocation.methodName;
+    expect(methodName.staticElement.enclosingElement.name, 'M2');
+  }
+
+  void test_method_fromMixins_invked_from_outside_class() {
+    Source source = addSource('''
+class B {}
+class M1 {
+  void f() {}
+}
+class M2 {
+  void f() {}
+}
+class C extends B with M1, M2 {}
+void main() {
+  new C().f();
+}
+''');
+    LibraryElement library = resolve(source);
+    assertNoErrors(source);
+    verify([source]);
+    // Verify that the call to f() in "new C().f()" refers to the method
+    // defined in M2.
+    FunctionDeclaration main =
+        library.definingCompilationUnit.functions[0].node;
+    BlockFunctionBody body = main.functionExpression.body;
+    ExpressionStatement stmt = body.block.statements[0];
+    MethodInvocation invocation = stmt.expression;
+    expect(invocation.methodName.staticElement.enclosingElement.name, 'M2');
+  }
+
   void test_method_fromSuperclassMixin() {
     Source source = addSource(r'''
 class A {
@@ -9289,6 +9542,65 @@
     assertNoErrors(source);
   }
 
+  void test_setter_fromMixins_bare_identifier() {
+    Source source = addSource('''
+class B {}
+class M1 {
+  set x(value) {}
+}
+class M2 {
+  set x(value) {}
+}
+class C extends B with M1, M2 {
+  void f() {
+    x = 1;
+  }
+}
+''');
+    LibraryElement library = resolve(source);
+    assertNoErrors(source);
+    verify([source]);
+    // Verify that the setter for "x" in C.f() refers to the setter defined in
+    // M2.
+    ClassElement classC = library.definingCompilationUnit.types[3];
+    MethodDeclaration f = classC.getMethod('f').node;
+    BlockFunctionBody body = f.body;
+    ExpressionStatement stmt = body.block.statements[0];
+    AssignmentExpression assignment = stmt.expression;
+    SimpleIdentifier leftHandSide = assignment.leftHandSide;
+    expect(leftHandSide.staticElement.enclosingElement.name, 'M2');
+  }
+
+  void test_setter_fromMixins_property_access() {
+    Source source = addSource('''
+class B {}
+class M1 {
+  set x(value) {}
+}
+class M2 {
+  set x(value) {}
+}
+class C extends B with M1, M2 {}
+void main() {
+  new C().x = 1;
+}
+''');
+    LibraryElement library = resolve(source);
+    assertNoErrors(source);
+    verify([source]);
+    // Verify that the setter for "x" in "new C().x" refers to the setter
+    // defined in M2.
+    FunctionDeclaration main =
+        library.definingCompilationUnit.functions[0].node;
+    BlockFunctionBody body = main.functionExpression.body;
+    ExpressionStatement stmt = body.block.statements[0];
+    AssignmentExpression assignment = stmt.expression;
+    PropertyAccess propertyAccess = assignment.leftHandSide;
+    expect(
+        propertyAccess.propertyName.staticElement.enclosingElement.name,
+        'M2');
+  }
+
   void test_setter_inherited() {
     Source source = addSource(r'''
 class A {
@@ -9694,6 +10006,40 @@
     _listener.assertNoErrors();
   }
 
+  void test_visitFunctionExpression_generator_async() {
+    // () async* {}
+    BlockFunctionBody body = AstFactory.blockFunctionBody2();
+    body.keyword = TokenFactory.tokenFromString('async');
+    body.star = TokenFactory.tokenFromType(TokenType.STAR);
+    FunctionExpression node =
+        _resolvedFunctionExpression(AstFactory.formalParameterList([]), body);
+    DartType resultType = _analyze(node);
+    _assertFunctionType(
+        _typeProvider.streamDynamicType,
+        null,
+        null,
+        null,
+        resultType);
+    _listener.assertNoErrors();
+  }
+
+  void test_visitFunctionExpression_generator_sync() {
+    // () sync* {}
+    BlockFunctionBody body = AstFactory.blockFunctionBody2();
+    body.keyword = TokenFactory.tokenFromString('sync');
+    body.star = TokenFactory.tokenFromType(TokenType.STAR);
+    FunctionExpression node =
+        _resolvedFunctionExpression(AstFactory.formalParameterList([]), body);
+    DartType resultType = _analyze(node);
+    _assertFunctionType(
+        _typeProvider.iterableDynamicType,
+        null,
+        null,
+        null,
+        resultType);
+    _listener.assertNoErrors();
+  }
+
   void test_visitFunctionExpression_named_block() {
     // ({p1 : 0, p2 : 0}) {}
     DartType dynamicType = _typeProvider.dynamicType;
@@ -11191,6 +11537,101 @@
 
 @reflectiveTest
 class TypePropagationTest extends ResolverTestCase {
+  void fail_finalPropertyInducingVariable_classMember_instance() {
+    addNamedSource("/lib.dart", r'''
+class A {
+  final v = 0;
+}''');
+    String code = r'''
+import 'lib.dart';
+f(A a) {
+  return a.v; // marker
+}''';
+    _assertTypeOfMarkedExpression(
+        code,
+        typeProvider.dynamicType,
+        typeProvider.intType);
+  }
+
+  void fail_finalPropertyInducingVariable_classMember_instance_inherited() {
+    addNamedSource("/lib.dart", r'''
+class A {
+  final v = 0;
+}''');
+    String code = r'''
+import 'lib.dart';
+class B extends A {
+  m() {
+    return v; // marker
+  }
+}''';
+    _assertTypeOfMarkedExpression(
+        code,
+        typeProvider.dynamicType,
+        typeProvider.intType);
+  }
+
+  void
+      fail_finalPropertyInducingVariable_classMember_instance_propagatedTarget() {
+    addNamedSource("/lib.dart", r'''
+class A {
+  final v = 0;
+}''');
+    String code = r'''
+import 'lib.dart';
+f(p) {
+  if (p is A) {
+    return p.v; // marker
+  }
+}''';
+    _assertTypeOfMarkedExpression(
+        code,
+        typeProvider.dynamicType,
+        typeProvider.intType);
+  }
+
+  void fail_finalPropertyInducingVariable_classMember_static() {
+    addNamedSource("/lib.dart", r'''
+class A {
+  static final V = 0;
+}''');
+    String code = r'''
+import 'lib.dart';
+f() {
+  return A.V; // marker
+}''';
+    _assertTypeOfMarkedExpression(
+        code,
+        typeProvider.dynamicType,
+        typeProvider.intType);
+  }
+
+  void fail_finalPropertyInducingVariable_topLevelVaraible_prefixed() {
+    addNamedSource("/lib.dart", "final V = 0;");
+    String code = r'''
+import 'lib.dart' as p;
+f() {
+  var v2 = p.V; // marker prefixed
+}''';
+    _assertTypeOfMarkedExpression(
+        code,
+        typeProvider.dynamicType,
+        typeProvider.intType);
+  }
+
+  void fail_finalPropertyInducingVariable_topLevelVaraible_simple() {
+    addNamedSource("/lib.dart", "final V = 0;");
+    String code = r'''
+import 'lib.dart';
+f() {
+  return V; // marker simple
+}''';
+    _assertTypeOfMarkedExpression(
+        code,
+        typeProvider.dynamicType,
+        typeProvider.intType);
+  }
+
   void fail_mergePropagatedTypesAtJoinPoint_1() {
     // https://code.google.com/p/dart/issues/detail?id=19929
     _assertTypeOfMarkedExpression(r'''
@@ -11477,101 +11918,6 @@
     expect(identifier.propagatedType.name, "CanvasRenderingContext2D");
   }
 
-  void fail_finalPropertyInducingVariable_classMember_instance() {
-    addNamedSource("/lib.dart", r'''
-class A {
-  final v = 0;
-}''');
-    String code = r'''
-import 'lib.dart';
-f(A a) {
-  return a.v; // marker
-}''';
-    _assertTypeOfMarkedExpression(
-        code,
-        typeProvider.dynamicType,
-        typeProvider.intType);
-  }
-
-  void fail_finalPropertyInducingVariable_classMember_instance_inherited() {
-    addNamedSource("/lib.dart", r'''
-class A {
-  final v = 0;
-}''');
-    String code = r'''
-import 'lib.dart';
-class B extends A {
-  m() {
-    return v; // marker
-  }
-}''';
-    _assertTypeOfMarkedExpression(
-        code,
-        typeProvider.dynamicType,
-        typeProvider.intType);
-  }
-
-  void
-      fail_finalPropertyInducingVariable_classMember_instance_propagatedTarget() {
-    addNamedSource("/lib.dart", r'''
-class A {
-  final v = 0;
-}''');
-    String code = r'''
-import 'lib.dart';
-f(p) {
-  if (p is A) {
-    return p.v; // marker
-  }
-}''';
-    _assertTypeOfMarkedExpression(
-        code,
-        typeProvider.dynamicType,
-        typeProvider.intType);
-  }
-
-  void fail_finalPropertyInducingVariable_classMember_static() {
-    addNamedSource("/lib.dart", r'''
-class A {
-  static final V = 0;
-}''');
-    String code = r'''
-import 'lib.dart';
-f() {
-  return A.V; // marker
-}''';
-    _assertTypeOfMarkedExpression(
-        code,
-        typeProvider.dynamicType,
-        typeProvider.intType);
-  }
-
-  void fail_finalPropertyInducingVariable_topLevelVaraible_prefixed() {
-    addNamedSource("/lib.dart", "final V = 0;");
-    String code = r'''
-import 'lib.dart' as p;
-f() {
-  var v2 = p.V; // marker prefixed
-}''';
-    _assertTypeOfMarkedExpression(
-        code,
-        typeProvider.dynamicType,
-        typeProvider.intType);
-  }
-
-  void fail_finalPropertyInducingVariable_topLevelVaraible_simple() {
-    addNamedSource("/lib.dart", "final V = 0;");
-    String code = r'''
-import 'lib.dart';
-f() {
-  return V; // marker simple
-}''';
-    _assertTypeOfMarkedExpression(
-        code,
-        typeProvider.dynamicType,
-        typeProvider.intType);
-  }
-
   void test_forEach() {
     String code = r'''
 main() {
@@ -12679,10 +13025,14 @@
     InterfaceType numType = _classElement("num", objectType).type;
     InterfaceType doubleType = _classElement("double", numType).type;
     InterfaceType functionType = _classElement("Function", objectType).type;
+    InterfaceType futureType = _classElement("Future", objectType, ["T"]).type;
     InterfaceType intType = _classElement("int", numType).type;
+    InterfaceType iterableType =
+        _classElement("Iterable", objectType, ["T"]).type;
     InterfaceType listType = _classElement("List", objectType, ["E"]).type;
     InterfaceType mapType = _classElement("Map", objectType, ["K", "V"]).type;
     InterfaceType stackTraceType = _classElement("StackTrace", objectType).type;
+    InterfaceType streamType = _classElement("Stream", objectType, ["T"]).type;
     InterfaceType stringType = _classElement("String", objectType).type;
     InterfaceType symbolType = _classElement("Symbol", objectType).type;
     InterfaceType typeType = _classElement("Type", objectType).type;
@@ -12693,6 +13043,7 @@
         doubleType.element,
         functionType.element,
         intType.element,
+        iterableType.element,
         listType.element,
         mapType.element,
         objectType.element,
@@ -12700,19 +13051,28 @@
         stringType.element,
         symbolType.element,
         typeType.element];
+    CompilationUnitElementImpl asyncUnit =
+        new CompilationUnitElementImpl("async.dart");
+    asyncUnit.types = <ClassElement>[futureType.element, streamType.element];
+    AnalysisContextImpl context = new AnalysisContextImpl();
     LibraryElementImpl coreLibrary = new LibraryElementImpl.forNode(
-        new AnalysisContextImpl(),
+        context,
         AstFactory.libraryIdentifier2(["dart.core"]));
     coreLibrary.definingCompilationUnit = coreUnit;
+    LibraryElementImpl asyncLibrary = new LibraryElementImpl.forNode(
+        context,
+        AstFactory.libraryIdentifier2(["dart.async"]));
+    asyncLibrary.definingCompilationUnit = asyncUnit;
     //
     // Create a type provider and ensure that it can return the expected types.
     //
-    TypeProviderImpl provider = new TypeProviderImpl(coreLibrary);
+    TypeProviderImpl provider = new TypeProviderImpl(coreLibrary, asyncLibrary);
     expect(provider.boolType, same(boolType));
     expect(provider.bottomType, isNotNull);
     expect(provider.doubleType, same(doubleType));
     expect(provider.dynamicType, isNotNull);
     expect(provider.functionType, same(functionType));
+    expect(provider.futureType, same(futureType));
     expect(provider.intType, same(intType));
     expect(provider.listType, same(listType));
     expect(provider.mapType, same(mapType));
diff --git a/pkg/analyzer/test/generated/static_type_warning_code_test.dart b/pkg/analyzer/test/generated/static_type_warning_code_test.dart
index 0ceb9d4..bf70201 100644
--- a/pkg/analyzer/test/generated/static_type_warning_code_test.dart
+++ b/pkg/analyzer/test/generated/static_type_warning_code_test.dart
@@ -90,6 +90,78 @@
     verify([source]);
   }
 
+  void test_illegal_return_type_async_function() {
+    Source source = addSource('''
+int f() async {}
+''');
+    resolve(source);
+    assertErrors(
+        source,
+        [StaticTypeWarningCode.ILLEGAL_ASYNC_RETURN_TYPE, HintCode.MISSING_RETURN]);
+    verify([source]);
+  }
+
+  void test_illegal_return_type_async_generator_function() {
+    Source source = addSource('''
+int f() async* {}
+''');
+    resolve(source);
+    assertErrors(
+        source,
+        [StaticTypeWarningCode.ILLEGAL_ASYNC_GENERATOR_RETURN_TYPE]);
+    verify([source]);
+  }
+
+  void test_illegal_return_type_async_generator_method() {
+    Source source = addSource('''
+class C {
+  int f() async* {}
+}
+''');
+    resolve(source);
+    assertErrors(
+        source,
+        [StaticTypeWarningCode.ILLEGAL_ASYNC_GENERATOR_RETURN_TYPE]);
+    verify([source]);
+  }
+
+  void test_illegal_return_type_async_method() {
+    Source source = addSource('''
+class C {
+  int f() async {}
+}
+''');
+    resolve(source);
+    assertErrors(
+        source,
+        [StaticTypeWarningCode.ILLEGAL_ASYNC_RETURN_TYPE, HintCode.MISSING_RETURN]);
+    verify([source]);
+  }
+
+  void test_illegal_return_type_sync_generator_function() {
+    Source source = addSource('''
+int f() sync* {}
+''');
+    resolve(source);
+    assertErrors(
+        source,
+        [StaticTypeWarningCode.ILLEGAL_SYNC_GENERATOR_RETURN_TYPE]);
+    verify([source]);
+  }
+
+  void test_illegal_return_type_sync_generator_method() {
+    Source source = addSource('''
+class C {
+  int f() sync* {}
+}
+''');
+    resolve(source);
+    assertErrors(
+        source,
+        [StaticTypeWarningCode.ILLEGAL_SYNC_GENERATOR_RETURN_TYPE]);
+    verify([source]);
+  }
+
   void test_inconsistentMethodInheritance_paramCount() {
     Source source = addSource(r'''
 abstract class A {
@@ -567,6 +639,45 @@
     verify([source]);
   }
 
+  void test_returnOfInvalidType_async_future_int_mismatches_future_null() {
+    Source source = addSource('''
+import 'dart:async';
+Future<Null> f() async {
+  return 5;
+}
+''');
+    resolve(source);
+    assertErrors(source, [StaticTypeWarningCode.RETURN_OF_INVALID_TYPE]);
+    verify([source]);
+  }
+
+  void test_returnOfInvalidType_async_future_int_mismatches_future_string() {
+    Source source = addSource('''
+import 'dart:async';
+Future<String> f() async {
+  return 5;
+}
+''');
+    resolve(source);
+    assertErrors(source, [StaticTypeWarningCode.RETURN_OF_INVALID_TYPE]);
+    verify([source]);
+  }
+
+  void test_returnOfInvalidType_async_future_int_mismatches_int() {
+    Source source = addSource('''
+int f() async {
+  return 5;
+}
+''');
+    resolve(source);
+    assertErrors(
+        source,
+        [
+            StaticTypeWarningCode.RETURN_OF_INVALID_TYPE,
+            StaticTypeWarningCode.ILLEGAL_ASYNC_RETURN_TYPE]);
+    verify([source]);
+  }
+
   void test_returnOfInvalidType_expressionFunctionBody_function() {
     Source source = addSource("int f() => '0';");
     resolve(source);
@@ -1618,4 +1729,135 @@
         [StaticTypeWarningCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS]);
     verify([source]);
   }
+
+  void test_yield_async_to_basic_type() {
+    Source source = addSource('''
+int f() async* {
+  yield 3;
+}
+''');
+    resolve(source);
+    assertErrors(
+        source,
+        [
+            StaticTypeWarningCode.YIELD_OF_INVALID_TYPE,
+            StaticTypeWarningCode.ILLEGAL_ASYNC_GENERATOR_RETURN_TYPE]);
+    verify([source]);
+  }
+
+  void test_yield_async_to_iterable() {
+    Source source = addSource('''
+Iterable<int> f() async* {
+  yield 3;
+}
+''');
+    resolve(source);
+    assertErrors(
+        source,
+        [
+            StaticTypeWarningCode.YIELD_OF_INVALID_TYPE,
+            StaticTypeWarningCode.ILLEGAL_ASYNC_GENERATOR_RETURN_TYPE]);
+    verify([source]);
+  }
+
+  void test_yield_async_to_mistyped_stream() {
+    Source source = addSource('''
+import 'dart:async';
+Stream<int> f() async* {
+  yield "foo";
+}
+''');
+    resolve(source);
+    assertErrors(source, [StaticTypeWarningCode.YIELD_OF_INVALID_TYPE]);
+    verify([source]);
+  }
+
+  void test_yield_each_async_non_stream() {
+    Source source = addSource('''
+f() async* {
+  yield* 0;
+}
+''');
+    resolve(source);
+    assertErrors(source, [StaticTypeWarningCode.YIELD_OF_INVALID_TYPE]);
+    verify([source]);
+  }
+
+  void test_yield_each_async_to_mistyped_stream() {
+    Source source = addSource('''
+import 'dart:async';
+Stream<int> f() async* {
+  yield* g();
+}
+Stream<String> g() => null;
+''');
+    resolve(source);
+    assertErrors(source, [StaticTypeWarningCode.YIELD_OF_INVALID_TYPE]);
+    verify([source]);
+  }
+
+  void test_yield_each_sync_non_iterable() {
+    Source source = addSource('''
+f() sync* {
+  yield* 0;
+}
+''');
+    resolve(source);
+    assertErrors(source, [StaticTypeWarningCode.YIELD_OF_INVALID_TYPE]);
+    verify([source]);
+  }
+
+  void test_yield_each_sync_to_mistyped_iterable() {
+    Source source = addSource('''
+Iterable<int> f() sync* {
+  yield* g();
+}
+Iterable<String> g() => null;
+''');
+    resolve(source);
+    assertErrors(source, [StaticTypeWarningCode.YIELD_OF_INVALID_TYPE]);
+    verify([source]);
+  }
+
+  void test_yield_sync_to_basic_type() {
+    Source source = addSource('''
+int f() sync* {
+  yield 3;
+}
+''');
+    resolve(source);
+    assertErrors(
+        source,
+        [
+            StaticTypeWarningCode.YIELD_OF_INVALID_TYPE,
+            StaticTypeWarningCode.ILLEGAL_SYNC_GENERATOR_RETURN_TYPE]);
+    verify([source]);
+  }
+
+  void test_yield_sync_to_mistyped_iterable() {
+    Source source = addSource('''
+Iterable<int> f() sync* {
+  yield "foo";
+}
+''');
+    resolve(source);
+    assertErrors(source, [StaticTypeWarningCode.YIELD_OF_INVALID_TYPE]);
+    verify([source]);
+  }
+
+  void test_yield_sync_to_stream() {
+    Source source = addSource('''
+import 'dart:async';
+Stream<int> f() sync* {
+  yield 3;
+}
+''');
+    resolve(source);
+    assertErrors(
+        source,
+        [
+            StaticTypeWarningCode.YIELD_OF_INVALID_TYPE,
+            StaticTypeWarningCode.ILLEGAL_SYNC_GENERATOR_RETURN_TYPE]);
+    verify([source]);
+  }
 }
diff --git a/pkg/analyzer/test/generated/static_warning_code_test.dart b/pkg/analyzer/test/generated/static_warning_code_test.dart
index 0f379ad..df69a54 100644
--- a/pkg/analyzer/test/generated/static_warning_code_test.dart
+++ b/pkg/analyzer/test/generated/static_warning_code_test.dart
@@ -1407,8 +1407,7 @@
 class A {}''', r'''
 library lib;
 import 'lib1.dart' deferred as p;
-var a = new p.A();'''],
-          <ErrorCode>[StaticWarningCode.IMPORT_OF_NON_LIBRARY]);
+var a = new p.A();'''], <ErrorCode>[StaticWarningCode.IMPORT_OF_NON_LIBRARY]);
   }
 
   void test_inconsistentMethodInheritanceGetterAndMethod() {
@@ -2945,6 +2944,18 @@
     verify([source]);
   }
 
+  void test_returnWithoutValue_async() {
+    Source source = addSource('''
+import 'dart:async';
+Future<int> f() async {
+  return;
+}
+''');
+    resolve(source);
+    assertErrors(source, [StaticWarningCode.RETURN_WITHOUT_VALUE]);
+    verify([source]);
+  }
+
   void test_returnWithoutValue_factoryConstructor() {
     Source source = addSource("class A { factory A() { return; } }");
     resolve(source);
@@ -3066,8 +3077,7 @@
 import 'lib1.dart' deferred as a;
 f(var v) {
   v as a.A;
-}'''],
-          <ErrorCode>[StaticWarningCode.TYPE_ANNOTATION_DEFERRED_CLASS]);
+}'''], <ErrorCode>[StaticWarningCode.TYPE_ANNOTATION_DEFERRED_CLASS]);
   }
 
   void test_typeAnnotationDeferredClass_catchClause() {
@@ -3080,8 +3090,7 @@
   try {
   } on a.A {
   }
-}'''],
-          <ErrorCode>[StaticWarningCode.TYPE_ANNOTATION_DEFERRED_CLASS]);
+}'''], <ErrorCode>[StaticWarningCode.TYPE_ANNOTATION_DEFERRED_CLASS]);
   }
 
   void test_typeAnnotationDeferredClass_fieldFormalParameter() {
@@ -3093,8 +3102,7 @@
 class C {
   var v;
   C(a.A this.v);
-}'''],
-          <ErrorCode>[StaticWarningCode.TYPE_ANNOTATION_DEFERRED_CLASS]);
+}'''], <ErrorCode>[StaticWarningCode.TYPE_ANNOTATION_DEFERRED_CLASS]);
   }
 
   void test_typeAnnotationDeferredClass_functionDeclaration_returnType() {
@@ -3126,8 +3134,7 @@
 import 'lib1.dart' deferred as a;
 f(var v) {
   bool b = v is a.A;
-}'''],
-          <ErrorCode>[StaticWarningCode.TYPE_ANNOTATION_DEFERRED_CLASS]);
+}'''], <ErrorCode>[StaticWarningCode.TYPE_ANNOTATION_DEFERRED_CLASS]);
   }
 
   void test_typeAnnotationDeferredClass_methodDeclaration_returnType() {
@@ -3138,8 +3145,7 @@
 import 'lib1.dart' deferred as a;
 class C {
   a.A m() { return null; }
-}'''],
-          <ErrorCode>[StaticWarningCode.TYPE_ANNOTATION_DEFERRED_CLASS]);
+}'''], <ErrorCode>[StaticWarningCode.TYPE_ANNOTATION_DEFERRED_CLASS]);
   }
 
   void test_typeAnnotationDeferredClass_simpleFormalParameter() {
@@ -3148,8 +3154,7 @@
 class A {}''', r'''
 library root;
 import 'lib1.dart' deferred as a;
-f(a.A v) {}'''],
-          <ErrorCode>[StaticWarningCode.TYPE_ANNOTATION_DEFERRED_CLASS]);
+f(a.A v) {}'''], <ErrorCode>[StaticWarningCode.TYPE_ANNOTATION_DEFERRED_CLASS]);
   }
 
   void test_typeAnnotationDeferredClass_typeArgumentList() {
@@ -3159,8 +3164,7 @@
 library root;
 import 'lib1.dart' deferred as a;
 class C<E> {}
-C<a.A> c;'''],
-          <ErrorCode>[StaticWarningCode.TYPE_ANNOTATION_DEFERRED_CLASS]);
+C<a.A> c;'''], <ErrorCode>[StaticWarningCode.TYPE_ANNOTATION_DEFERRED_CLASS]);
   }
 
   void test_typeAnnotationDeferredClass_typeArgumentList2() {
@@ -3192,8 +3196,7 @@
 class A {}''', r'''
 library root;
 import 'lib1.dart' deferred as a;
-a.A v;'''],
-          <ErrorCode>[StaticWarningCode.TYPE_ANNOTATION_DEFERRED_CLASS]);
+a.A v;'''], <ErrorCode>[StaticWarningCode.TYPE_ANNOTATION_DEFERRED_CLASS]);
   }
 
   void test_typeParameterReferencedByStatic_field() {
diff --git a/pkg/analyzer/test/generated/test_support.dart b/pkg/analyzer/test/generated/test_support.dart
index 3344dfc..b4ea7b2 100644
--- a/pkg/analyzer/test/generated/test_support.dart
+++ b/pkg/analyzer/test/generated/test_support.dart
@@ -560,7 +560,7 @@
 }
 
 
-class TestSource implements Source {
+class TestSource extends Source {
   String _name;
   String _contents;
   int modificationStamp = 0;
diff --git a/pkg/analyzer/test/services/data/cu_tests.data b/pkg/analyzer/test/services/data/cu_tests.data
index 06dddef..9f9e803 100644
--- a/pkg/analyzer/test/services/data/cu_tests.data
+++ b/pkg/analyzer/test/services/data/cu_tests.data
@@ -307,3 +307,19 @@
   A(this.a0123456789012345678901234, this.b0123456789012345678901234,
       this.c0123456789012345678901234, this.d0123456789012345678901234);
 }
+>>>
+main() async {
+}
+<<<
+main() async {
+}
+>>>
+main()  async  => 0;
+<<<
+main() async => 0;
+>>>
+enum Foo { BAR, BAZ }
+<<<
+enum Foo {
+  BAR, BAZ
+}
diff --git a/pkg/analyzer/test/services/test_utils.dart b/pkg/analyzer/test/services/test_utils.dart
index 4db8219..a0fb2d1 100644
--- a/pkg/analyzer/test/services/test_utils.dart
+++ b/pkg/analyzer/test/services/test_utils.dart
@@ -4,14 +4,47 @@
 
 library test_utils;
 
+import 'package:analyzer/src/generated/ast.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:analyzer/src/generated/error.dart';
+import 'package:analyzer/src/generated/parser.dart';
+import 'package:analyzer/src/generated/scanner.dart';
+import 'package:analyzer/src/generated/source.dart';
 import 'package:unittest/unittest.dart';
 
-import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer/src/generated/error.dart';
-import 'package:analyzer/src/generated/scanner.dart';
-import 'package:analyzer/src/generated/ast.dart';
-import 'package:analyzer/src/generated/parser.dart';
+
+/// Parse the given [source] as a statement and assert, if provided, that
+/// exactly a given set of [expectedErrorCodes] are encountered.
+Statement parseStatement(String source, [List<ErrorCode> expectedErrorCodes]) {
+
+  var listener = new _GatheringErrorListener();
+  var reader = new CharSequenceReader(source);
+  var scanner = new Scanner(null, reader, listener);
+  listener.setLineInfo(new _TestSource(), scanner.lineStarts);
+
+  var token = scanner.tokenize();
+  var parser = new Parser(null, listener);
+  var statement = parser.parseStatement(token);
+  expect(statement, isNotNull);
+
+  if (expectedErrorCodes != null) {
+    listener.expectErrors(expectedErrorCodes);
+  }
+
+  return statement;
+}
+
+
+Set<_MapEntry> _getMapEntrySet(Map m) {
+  var result = new Set();
+  m.forEach((k, v) {
+    result.add(new _MapEntry(k, v));
+  });
+  return result;
+}
+
+
+_unsupported() => throw new _UnsupportedOperationException();
 
 
 /// Instances of the class [_GatheringErrorListener] implement an error listener
@@ -23,18 +56,6 @@
   /// A table mapping sources to the line information for the source.
   final Map<Source, LineInfo> _lineInfoMap = new Map<Source, LineInfo>();
 
-  void onError(AnalysisError error) {
-    _errors.add(error);
-  }
-
-
-  /// Sets the line information associated with the given source to the given
-  /// information.
-  void setLineInfo(Source source, List<int> lineStarts) {
-    _lineInfoMap[source] = new LineInfo(lineStarts);
-  }
-
-
   /// Asserts that the number of errors that have been gathered matches the
   /// number of errors that are given and that they have the expected error
   /// codes. The order in which the errors were gathered is ignored.
@@ -122,15 +143,18 @@
     }
   }
 
-}
+
+  void onError(AnalysisError error) {
+    _errors.add(error);
+  }
 
 
-Set<_MapEntry> _getMapEntrySet(Map m) {
-  var result = new Set();
-  m.forEach((k, v) {
-    result.add(new _MapEntry(k, v));
-  });
-  return result;
+  /// Sets the line information associated with the given source to the given
+  /// information.
+  void setLineInfo(Source source, List<int> lineStarts) {
+    _lineInfoMap[source] = new LineInfo(lineStarts);
+  }
+
 }
 
 
@@ -142,63 +166,38 @@
   V getValue() => _value;
 }
 
+class _TestSource extends Source {
 
-class _TestSource implements Source {
-
-  bool operator == (Object object) => object is _TestSource;
+  TimestampedData<String> get contents => _unsupported();
 
   AnalysisContext get context => _unsupported();
 
-  void getContentsToReceiver(Source_ContentReceiver receiver) => _unsupported();
+  String get encoding => _unsupported();
 
   String get fullName => _unsupported();
 
+  bool get isInSystemLibrary => _unsupported();
+
+  int get modificationStamp => _unsupported();
+
   String get shortName => _unsupported();
 
-  String get encoding => _unsupported();
-
-  int get modificationStamp =>_unsupported();
+  Uri get uri => _unsupported();
 
   UriKind get uriKind => _unsupported();
 
+  bool operator ==(Object object) => object is _TestSource;
+
   bool exists() => true;
 
-  bool get isInSystemLibrary => _unsupported();
-
-  Uri get uri => _unsupported();
+  void getContentsToReceiver(Source_ContentReceiver receiver) => _unsupported();
 
   Source resolve(String uri) => _unsupported();
 
   Uri resolveRelativeUri(Uri uri) => _unsupported();
-
-  TimestampedData<String> get contents => _unsupported();
 }
 
 
-_unsupported() => throw new _UnsupportedOperationException();
-
 class _UnsupportedOperationException implements Exception {
   String toString() => 'UnsupportedOperationException';
 }
-
-
-/// Parse the given [source] as a statement and assert, if provided, that
-/// exactly a given set of [expectedErrorCodes] are encountered.
-Statement parseStatement(String source, [List<ErrorCode> expectedErrorCodes]) {
-
-  var listener = new _GatheringErrorListener();
-  var reader = new CharSequenceReader(source);
-  var scanner = new Scanner(null, reader, listener);
-  listener.setLineInfo(new _TestSource(), scanner.lineStarts);
-
-  var token = scanner.tokenize();
-  var parser = new Parser(null, listener);
-  var statement = parser.parseStatement(token);
-  expect(statement, isNotNull);
-
-  if (expectedErrorCodes != null) {
-    listener.expectErrors(expectedErrorCodes);
-  }
-
-  return statement;
-}
diff --git a/pkg/analyzer/test/source/package_map_resolver_test.dart b/pkg/analyzer/test/source/package_map_resolver_test.dart
index b7a644a..a12e361 100644
--- a/pkg/analyzer/test/source/package_map_resolver_test.dart
+++ b/pkg/analyzer/test/source/package_map_resolver_test.dart
@@ -10,48 +10,16 @@
 import 'package:analyzer/src/generated/source.dart';
 import 'package:unittest/unittest.dart';
 
+import '../reflective_tests.dart';
+
 
 main() {
   groupSep = ' | ';
-  group('PackageMapUriResolverTest', () {
-    test('isPackageUri', () {
-      new _PackageMapUriResolverTest().test_isPackageUri();
-    });
-    test('isPackageUri_null_scheme', () {
-      new _PackageMapUriResolverTest().test_isPackageUri_null_scheme();
-    });
-    test('isPackageUri_other_scheme', () {
-      new _PackageMapUriResolverTest().test_isPackageUri_other_scheme();
-    });
-    test('resolve_multiple_folders', () {
-      new _PackageMapUriResolverTest().test_resolve_multiple_folders();
-    });
-    test('resolve_nonPackage', () {
-      new _PackageMapUriResolverTest().test_resolve_nonPackage();
-    });
-    test('resolve_OK', () {
-      new _PackageMapUriResolverTest().test_resolve_OK();
-    });
-    test('resolve_package_invalid_leadingSlash', () {
-      var inst = new _PackageMapUriResolverTest();
-      inst.test_resolve_package_invalid_leadingSlash();
-    });
-    test('resolve_package_invalid_noSlash', () {
-      new _PackageMapUriResolverTest().test_resolve_package_invalid_noSlash();
-    });
-    test('resolve_package_invalid_onlySlash', () {
-      new _PackageMapUriResolverTest().test_resolve_package_invalid_onlySlash();
-    });
-    test('resolve_package_notInMap', () {
-      new _PackageMapUriResolverTest().test_resolve_package_notInMap();
-    });
-    test('restoreAbsolute_OK', () {
-      new _PackageMapUriResolverTest().test_restoreAbsolute();
-    });
-  });
+  runReflectiveTests(_PackageMapUriResolverTest);
 }
 
 
+@reflectiveTest
 class _PackageMapUriResolverTest {
   static const Map EMPTY_MAP = const <String, List<Folder>>{};
   MemoryResourceProvider provider = new MemoryResourceProvider();
@@ -74,6 +42,18 @@
     expect(PackageMapUriResolver.isPackageUri(uri), isFalse);
   }
 
+  void test_new_null_packageMap() {
+    expect(() {
+      new PackageMapUriResolver(provider, null);
+    }, throws);
+  }
+
+  void test_new_null_resourceProvider() {
+    expect(() {
+      new PackageMapUriResolver(null, <String, List<Folder>>{});
+    }, throws);
+  }
+
   void test_resolve_multiple_folders() {
     const pkgFileA = '/part1/lib/libA.dart';
     const pkgFileB = '/part2/lib/libB.dart';
diff --git a/pkg/analyzer/test/src/task/dart_test.dart b/pkg/analyzer/test/src/task/dart_test.dart
new file mode 100644
index 0000000..95a8fe5
--- /dev/null
+++ b/pkg/analyzer/test/src/task/dart_test.dart
@@ -0,0 +1,306 @@
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library test.src.task.dart_test;
+
+import 'package:analyzer/src/generated/engine.dart' hide AnalysisTask,
+    ParseDartTask, ScanDartTask;
+import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/task/dart.dart';
+import 'package:analyzer/task/dart.dart';
+import 'package:analyzer/task/general.dart';
+import 'package:analyzer/task/model.dart';
+import 'package:unittest/unittest.dart';
+
+import '../../generated/resolver_test.dart';
+import '../../generated/test_support.dart';
+import '../../reflective_tests.dart';
+
+main() {
+  groupSep = ' | ';
+  runReflectiveTests(BuildCompilationUnitElementTaskTest);
+  runReflectiveTests(ParseDartTaskTest);
+  runReflectiveTests(ScanDartTaskTest);
+}
+
+@reflectiveTest
+class BuildCompilationUnitElementTaskTest extends EngineTestCase {
+  test_buildInputs() {
+    AnalysisTarget target = new TestSource();
+    Map<String, TaskInput> inputs =
+        BuildCompilationUnitElementTask.buildInputs(target);
+    expect(inputs, isNotNull);
+    expect(inputs, hasLength(1));
+    expect(
+        inputs[BuildCompilationUnitElementTask.PARSED_UNIT_INPUT_NAME],
+        isNotNull);
+  }
+
+  test_constructor() {
+    AnalysisContext context = AnalysisContextFactory.contextWithCore();
+    AnalysisTarget target = new TestSource();
+    BuildCompilationUnitElementTask task =
+        new BuildCompilationUnitElementTask(context, target);
+    expect(task, isNotNull);
+    expect(task.context, context);
+    expect(task.target, target);
+  }
+
+  test_createTask() {
+    AnalysisContext context = AnalysisContextFactory.contextWithCore();
+    AnalysisTarget target = new TestSource();
+    BuildCompilationUnitElementTask task =
+        BuildCompilationUnitElementTask.createTask(context, target);
+    expect(task, isNotNull);
+    expect(task.context, context);
+    expect(task.target, target);
+  }
+
+  test_description() {
+    AnalysisTarget target = new TestSource();
+    BuildCompilationUnitElementTask task =
+        new BuildCompilationUnitElementTask(null, target);
+    expect(task.description, isNotNull);
+  }
+
+  test_descriptor() {
+    TaskDescriptor descriptor = BuildCompilationUnitElementTask.DESCRIPTOR;
+    expect(descriptor, isNotNull);
+  }
+
+  test_perform_library() {
+    BuildCompilationUnitElementTask task = _performBuildTask(r'''
+library lib;
+import 'lib2.dart';
+export 'lib3.dart';
+part 'part.dart';
+class A {''');
+
+    expect(task.caughtException, isNull);
+    Map<ResultDescriptor<dynamic>, dynamic> outputs = task.outputs;
+    expect(outputs, hasLength(2));
+    expect(outputs[COMPILATION_UNIT_ELEMENT], isNotNull);
+    expect(outputs[BUILT_UNIT], isNotNull);
+  }
+
+  BuildCompilationUnitElementTask _performBuildTask(String content) {
+    InternalAnalysisContext context = AnalysisContextFactory.contextWithCore();
+    AnalysisTarget target = new TestSource();
+
+    ScanDartTask scanTask = new ScanDartTask(context, target);
+    scanTask.inputs = {
+      ScanDartTask.CONTENT_INPUT_NAME: content
+    };
+    scanTask.perform();
+    Map<ResultDescriptor, dynamic> scanOutputs = scanTask.outputs;
+
+    ParseDartTask parseTask = new ParseDartTask(context, target);
+    parseTask.inputs = {
+      ParseDartTask.LINE_INFO_INPUT_NAME: scanOutputs[LINE_INFO],
+      ParseDartTask.TOKEN_STREAM_INPUT_NAME: scanOutputs[TOKEN_STREAM]
+    };
+    parseTask.perform();
+    Map<ResultDescriptor, dynamic> parseOutputs = parseTask.outputs;
+
+    BuildCompilationUnitElementTask buildTask =
+        new BuildCompilationUnitElementTask(context, target);
+    buildTask.inputs = {
+      BuildCompilationUnitElementTask.PARSED_UNIT_INPUT_NAME:
+          parseOutputs[PARSED_UNIT]
+    };
+    buildTask.perform();
+
+    return buildTask;
+  }
+}
+
+@reflectiveTest
+class ParseDartTaskTest extends EngineTestCase {
+  test_buildInputs() {
+    AnalysisTarget target = new TestSource();
+    Map<String, TaskInput> inputs = ParseDartTask.buildInputs(target);
+    expect(inputs, isNotNull);
+    expect(inputs, hasLength(2));
+    expect(inputs[ParseDartTask.LINE_INFO_INPUT_NAME], isNotNull);
+    expect(inputs[ParseDartTask.TOKEN_STREAM_INPUT_NAME], isNotNull);
+  }
+
+  test_constructor() {
+    AnalysisContext context = AnalysisContextFactory.contextWithCore();
+    AnalysisTarget target = new TestSource();
+    ParseDartTask task = new ParseDartTask(context, target);
+    expect(task, isNotNull);
+    expect(task.context, context);
+    expect(task.target, target);
+  }
+
+  test_createTask() {
+    AnalysisContext context = AnalysisContextFactory.contextWithCore();
+    AnalysisTarget target = new TestSource();
+    ParseDartTask task = ParseDartTask.createTask(context, target);
+    expect(task, isNotNull);
+    expect(task.context, context);
+    expect(task.target, target);
+  }
+
+  test_description() {
+    AnalysisTarget target = new TestSource();
+    ParseDartTask task = new ParseDartTask(null, target);
+    expect(task.description, isNotNull);
+  }
+
+  test_descriptor() {
+    TaskDescriptor descriptor = ParseDartTask.DESCRIPTOR;
+    expect(descriptor, isNotNull);
+  }
+
+  test_perform() {
+    ParseDartTask task = _performParseTask(r'''
+part of lib;
+class B {}''');
+
+    expect(task.caughtException, isNull);
+    Map<ResultDescriptor<dynamic>, dynamic> outputs = task.outputs;
+    expect(outputs, hasLength(6));
+    expect(outputs[EXPORTED_LIBRARIES], hasLength(0));
+    expect(outputs[IMPORTED_LIBRARIES], hasLength(0));
+    expect(outputs[INCLUDED_PARTS], hasLength(0));
+    expect(outputs[PARSE_ERRORS], hasLength(0));
+    expect(outputs[PARSED_UNIT], isNotNull);
+    expect(outputs[SOURCE_KIND], SourceKind.PART);
+  }
+
+  test_perform_invalidDirectives() {
+    ParseDartTask task = _performParseTask(r'''
+library lib;
+import '/does/not/exist.dart';
+import '://invaliduri.dart';
+export '${a}lib3.dart';
+part 'part.dart';
+class A {}''');
+
+    expect(task.caughtException, isNull);
+    Map<ResultDescriptor<dynamic>, dynamic> outputs = task.outputs;
+    expect(outputs, hasLength(6));
+    expect(outputs[EXPORTED_LIBRARIES], hasLength(0));
+    expect(outputs[IMPORTED_LIBRARIES], hasLength(1));
+    expect(outputs[INCLUDED_PARTS], hasLength(1));
+    expect(outputs[PARSE_ERRORS], hasLength(2));
+    expect(outputs[PARSED_UNIT], isNotNull);
+    expect(outputs[SOURCE_KIND], SourceKind.LIBRARY);
+  }
+
+  test_perform_library() {
+    ParseDartTask task = _performParseTask(r'''
+library lib;
+import 'lib2.dart';
+export 'lib3.dart';
+part 'part.dart';
+class A {''');
+
+    expect(task.caughtException, isNull);
+    Map<ResultDescriptor<dynamic>, dynamic> outputs = task.outputs;
+    expect(outputs, hasLength(6));
+    expect(outputs[EXPORTED_LIBRARIES], hasLength(1));
+    expect(outputs[IMPORTED_LIBRARIES], hasLength(1));
+    expect(outputs[INCLUDED_PARTS], hasLength(1));
+    expect(outputs[PARSE_ERRORS], hasLength(1));
+    expect(outputs[PARSED_UNIT], isNotNull);
+    expect(outputs[SOURCE_KIND], SourceKind.LIBRARY);
+  }
+
+  ParseDartTask _performParseTask(String content) {
+    InternalAnalysisContext context = AnalysisContextFactory.contextWithCore();
+    AnalysisTarget target = new TestSource();
+
+    ScanDartTask scanTask = new ScanDartTask(context, target);
+    scanTask.inputs = {
+      ScanDartTask.CONTENT_INPUT_NAME: content
+    };
+    scanTask.perform();
+    Map<ResultDescriptor, dynamic> scanOutputs = scanTask.outputs;
+
+    ParseDartTask parseTask = new ParseDartTask(context, target);
+    parseTask.inputs = {
+      ParseDartTask.LINE_INFO_INPUT_NAME: scanOutputs[LINE_INFO],
+      ParseDartTask.TOKEN_STREAM_INPUT_NAME: scanOutputs[TOKEN_STREAM]
+    };
+    parseTask.perform();
+    return parseTask;
+  }
+}
+
+@reflectiveTest
+class ScanDartTaskTest extends EngineTestCase {
+  test_buildInputs() {
+    AnalysisTarget target = new TestSource();
+    Map<String, TaskInput> inputs = ScanDartTask.buildInputs(target);
+    expect(inputs, isNotNull);
+    expect(inputs, hasLength(1));
+    expect(inputs[ScanDartTask.CONTENT_INPUT_NAME], isNotNull);
+  }
+
+  test_constructor() {
+    AnalysisContext context = AnalysisContextFactory.contextWithCore();
+    AnalysisTarget target = new TestSource();
+    ScanDartTask task = new ScanDartTask(context, target);
+    expect(task, isNotNull);
+    expect(task.context, context);
+    expect(task.target, target);
+  }
+
+  test_createTask() {
+    AnalysisContext context = AnalysisContextFactory.contextWithCore();
+    AnalysisTarget target = new TestSource();
+    ScanDartTask task = ScanDartTask.createTask(context, target);
+    expect(task, isNotNull);
+    expect(task.context, context);
+    expect(task.target, target);
+  }
+
+  test_description() {
+    AnalysisTarget target = new TestSource();
+    ScanDartTask task = new ScanDartTask(null, target);
+    expect(task.description, isNotNull);
+  }
+
+  test_descriptor() {
+    TaskDescriptor descriptor = ScanDartTask.DESCRIPTOR;
+    expect(descriptor, isNotNull);
+  }
+
+  test_perform_errors() {
+    ScanDartTask scanTask = _performScanTask('import "');
+
+    expect(scanTask.caughtException, isNull);
+    Map<ResultDescriptor, dynamic> scanOutputs = scanTask.outputs;
+    expect(scanOutputs, hasLength(3));
+    expect(scanOutputs[LINE_INFO], isNotNull);
+    expect(scanOutputs[SCAN_ERRORS], hasLength(1));
+    expect(scanOutputs[TOKEN_STREAM], isNotNull);
+  }
+
+  test_perform_noErrors() {
+    ScanDartTask scanTask = _performScanTask('class A {}');
+
+    expect(scanTask.caughtException, isNull);
+    Map<ResultDescriptor, dynamic> scanOutputs = scanTask.outputs;
+    expect(scanOutputs, hasLength(3));
+    expect(scanOutputs[LINE_INFO], isNotNull);
+    expect(scanOutputs[SCAN_ERRORS], hasLength(0));
+    expect(scanOutputs[TOKEN_STREAM], isNotNull);
+  }
+
+  ScanDartTask _performScanTask(String content) {
+    AnalysisContext context = AnalysisContextFactory.contextWithCore();
+    AnalysisTarget target = new TestSource();
+
+    ScanDartTask scanTask = new ScanDartTask(context, target);
+    scanTask.inputs = {
+      ScanDartTask.CONTENT_INPUT_NAME: content
+    };
+    scanTask.perform();
+    return scanTask;
+  }
+}
diff --git a/pkg/analyzer/test/src/task/inputs_test.dart b/pkg/analyzer/test/src/task/inputs_test.dart
index 4f9ba16..685a206 100644
--- a/pkg/analyzer/test/src/task/inputs_test.dart
+++ b/pkg/analyzer/test/src/task/inputs_test.dart
@@ -6,12 +6,11 @@
 
 import 'package:analyzer/src/task/inputs.dart';
 import 'package:analyzer/src/task/model.dart';
-import 'package:analyzer/src/task/targets.dart';
+import 'package:analyzer/task/model.dart';
 import 'package:unittest/unittest.dart';
 
 import '../../generated/test_support.dart';
 import '../../reflective_tests.dart';
-import 'package:analyzer/task/model.dart';
 
 main() {
   groupSep = ' | ';
@@ -24,7 +23,7 @@
 
 @reflectiveTest
 class ListBasedTaskInputBuilderTest extends EngineTestCase {
-  static final SourceTarget target1 = new SourceTarget(null);
+  static final AnalysisTarget target1 = new TestSource();
   static final ResultDescriptorImpl result1 =
       new ResultDescriptorImpl('result1', null);
   static final ResultDescriptorImpl result2 =
@@ -39,12 +38,6 @@
     expect(builder.input, input);
   }
 
-  test_currentResult_afterOneMoveNext() {
-    ListBasedTaskInputBuilder builder = new ListBasedTaskInputBuilder(input);
-    builder.moveNext();
-    expect(builder.currentResult, result1);
-  }
-
   test_currentResult_afterComplete() {
     ListBasedTaskInputBuilder builder = new ListBasedTaskInputBuilder(input);
     builder.moveNext();
@@ -53,17 +46,17 @@
     expect(builder.currentResult, null);
   }
 
+  test_currentResult_afterOneMoveNext() {
+    ListBasedTaskInputBuilder builder = new ListBasedTaskInputBuilder(input);
+    builder.moveNext();
+    expect(builder.currentResult, result1);
+  }
+
   test_currentResult_beforeMoveNext() {
     ListBasedTaskInputBuilder builder = new ListBasedTaskInputBuilder(input);
     expect(builder.currentResult, null);
   }
 
-  test_currentTarget_afterOneMoveNext() {
-    ListBasedTaskInputBuilder builder = new ListBasedTaskInputBuilder(input);
-    builder.moveNext();
-    expect(builder.currentTarget, target1);
-  }
-
   test_currentTarget_afterComplete() {
     ListBasedTaskInputBuilder builder = new ListBasedTaskInputBuilder(input);
     builder.moveNext();
@@ -72,6 +65,12 @@
     expect(builder.currentTarget, null);
   }
 
+  test_currentTarget_afterOneMoveNext() {
+    ListBasedTaskInputBuilder builder = new ListBasedTaskInputBuilder(input);
+    builder.moveNext();
+    expect(builder.currentTarget, target1);
+  }
+
   test_currentTarget_beforeMoveNext() {
     ListBasedTaskInputBuilder builder = new ListBasedTaskInputBuilder(input);
     expect(builder.currentTarget, null);
@@ -90,15 +89,9 @@
     }, throwsStateError);
   }
 
-  test_inputValue_afterOneMoveNext() {
-    ListBasedTaskInputBuilder builder = new ListBasedTaskInputBuilder(input);
-    builder.moveNext();
-    expect(() => builder.inputValue, throwsStateError);
-  }
-
   test_inputValue_afterComplete() {
-    SourceTarget target2 = new SourceTarget(null);
-    SourceTarget target3 = new SourceTarget(null);
+    AnalysisTarget target2 = new TestSource();
+    AnalysisTarget target3 = new TestSource();
     String value2 = 'value2';
     String value3 = 'value3';
     ListBasedTaskInputBuilder builder = new ListBasedTaskInputBuilder(input);
@@ -117,6 +110,12 @@
     expect(list[1], value3);
   }
 
+  test_inputValue_afterOneMoveNext() {
+    ListBasedTaskInputBuilder builder = new ListBasedTaskInputBuilder(input);
+    builder.moveNext();
+    expect(() => builder.inputValue, throwsStateError);
+  }
+
   test_inputValue_beforeMoveNext() {
     ListBasedTaskInputBuilder builder = new ListBasedTaskInputBuilder(input);
     expect(() => builder.inputValue, throwsStateError);
@@ -139,7 +138,7 @@
 
 @reflectiveTest
 class ListBasedTaskInputTest extends EngineTestCase {
-  static final SourceTarget target = new SourceTarget(null);
+  static final AnalysisTarget target = new TestSource();
   static final ResultDescriptorImpl result =
       new ResultDescriptorImpl('result', null);
 
@@ -162,7 +161,7 @@
 
 @reflectiveTest
 class SimpleTaskInputBuilderTest extends EngineTestCase {
-  static final SourceTarget target = new SourceTarget(null);
+  static final AnalysisTarget target = new TestSource();
   static final ResultDescriptorImpl result =
       new ResultDescriptorImpl('result', null);
   static final SimpleTaskInput input = new SimpleTaskInput(target, result);
@@ -173,12 +172,6 @@
     expect(builder.input, input);
   }
 
-  test_currentResult_afterOneMoveNext() {
-    SimpleTaskInputBuilder builder = new SimpleTaskInputBuilder(input);
-    builder.moveNext();
-    expect(builder.currentResult, result);
-  }
-
   test_currentResult_afterComplete() {
     SimpleTaskInputBuilder builder = new SimpleTaskInputBuilder(input);
     builder.moveNext();
@@ -187,17 +180,17 @@
     expect(builder.currentResult, null);
   }
 
+  test_currentResult_afterOneMoveNext() {
+    SimpleTaskInputBuilder builder = new SimpleTaskInputBuilder(input);
+    builder.moveNext();
+    expect(builder.currentResult, result);
+  }
+
   test_currentResult_beforeMoveNext() {
     SimpleTaskInputBuilder builder = new SimpleTaskInputBuilder(input);
     expect(builder.currentResult, null);
   }
 
-  test_currentTarget_afterOneMoveNext() {
-    SimpleTaskInputBuilder builder = new SimpleTaskInputBuilder(input);
-    builder.moveNext();
-    expect(builder.currentTarget, target);
-  }
-
   test_currentTarget_afterComplete() {
     SimpleTaskInputBuilder builder = new SimpleTaskInputBuilder(input);
     builder.moveNext();
@@ -206,6 +199,12 @@
     expect(builder.currentTarget, null);
   }
 
+  test_currentTarget_afterOneMoveNext() {
+    SimpleTaskInputBuilder builder = new SimpleTaskInputBuilder(input);
+    builder.moveNext();
+    expect(builder.currentTarget, target);
+  }
+
   test_currentTarget_beforeMoveNext() {
     SimpleTaskInputBuilder builder = new SimpleTaskInputBuilder(input);
     expect(builder.currentTarget, null);
@@ -224,12 +223,6 @@
     }, throwsStateError);
   }
 
-  test_inputValue_afterOneMoveNext() {
-    SimpleTaskInputBuilder builder = new SimpleTaskInputBuilder(input);
-    builder.moveNext();
-    expect(() => builder.inputValue, throwsStateError);
-  }
-
   test_inputValue_afterComplete() {
     SimpleTaskInputBuilder builder = new SimpleTaskInputBuilder(input);
     builder.moveNext();
@@ -239,6 +232,12 @@
     expect(builder.inputValue, value);
   }
 
+  test_inputValue_afterOneMoveNext() {
+    SimpleTaskInputBuilder builder = new SimpleTaskInputBuilder(input);
+    builder.moveNext();
+    expect(() => builder.inputValue, throwsStateError);
+  }
+
   test_inputValue_beforeMoveNext() {
     SimpleTaskInputBuilder builder = new SimpleTaskInputBuilder(input);
     expect(() => builder.inputValue, throwsStateError);
@@ -261,7 +260,7 @@
 
 @reflectiveTest
 class SimpleTaskInputTest extends EngineTestCase {
-  static final SourceTarget target = new SourceTarget(null);
+  static final AnalysisTarget target = new TestSource();
   static final ResultDescriptorImpl result =
       new ResultDescriptorImpl('result', null);
 
@@ -280,7 +279,7 @@
 
 @reflectiveTest
 class TopLevelTaskInputBuilderTest extends EngineTestCase {
-  static final SourceTarget target = new SourceTarget(null);
+  static final AnalysisTarget target = new TestSource();
   static final ResultDescriptorImpl result1 =
       new ResultDescriptorImpl('result1', null);
   static final ResultDescriptorImpl result2 =
@@ -296,17 +295,6 @@
     expect(builder.inputDescriptors, inputDescriptors);
   }
 
-  test_currentResult_afterOneMoveNext() {
-    Map<String, TaskInput> inputDescriptors = {
-      'one': input1,
-      'two': input2
-    };
-    TopLevelTaskInputBuilder builder =
-        new TopLevelTaskInputBuilder(inputDescriptors);
-    builder.moveNext();
-    expect(builder.currentResult, result1);
-  }
-
   test_currentResult_afterComplete() {
     Map<String, TaskInput> inputDescriptors = {
       'one': input1
@@ -319,6 +307,17 @@
     expect(builder.currentResult, null);
   }
 
+  test_currentResult_afterOneMoveNext() {
+    Map<String, TaskInput> inputDescriptors = {
+      'one': input1,
+      'two': input2
+    };
+    TopLevelTaskInputBuilder builder =
+        new TopLevelTaskInputBuilder(inputDescriptors);
+    builder.moveNext();
+    expect(builder.currentResult, result1);
+  }
+
   test_currentResult_beforeMoveNext() {
     Map<String, TaskInput> inputDescriptors = {};
     TopLevelTaskInputBuilder builder =
@@ -326,16 +325,6 @@
     expect(builder.currentResult, null);
   }
 
-  test_currentTarget_afterOneMoveNext() {
-    Map<String, TaskInput> inputDescriptors = {
-      'one': input1
-    };
-    TopLevelTaskInputBuilder builder =
-        new TopLevelTaskInputBuilder(inputDescriptors);
-    builder.moveNext();
-    expect(builder.currentTarget, target);
-  }
-
   test_currentTarget_afterComplete() {
     Map<String, TaskInput> inputDescriptors = {
       'one': input1
@@ -348,6 +337,16 @@
     expect(builder.currentTarget, null);
   }
 
+  test_currentTarget_afterOneMoveNext() {
+    Map<String, TaskInput> inputDescriptors = {
+      'one': input1
+    };
+    TopLevelTaskInputBuilder builder =
+        new TopLevelTaskInputBuilder(inputDescriptors);
+    builder.moveNext();
+    expect(builder.currentTarget, target);
+  }
+
   test_currentTarget_beforeMoveNext() {
     Map<String, TaskInput> inputDescriptors = {};
     TopLevelTaskInputBuilder builder =
@@ -376,16 +375,6 @@
     }, throwsStateError);
   }
 
-  test_inputValue_afterOneMoveNext() {
-    Map<String, TaskInput> inputDescriptors = {
-      'one': input1
-    };
-    TopLevelTaskInputBuilder builder =
-        new TopLevelTaskInputBuilder(inputDescriptors);
-    builder.moveNext();
-    expect(() => builder.inputValue, throwsStateError);
-  }
-
   test_inputValue_afterComplete() {
     String key1 = 'one';
     String key2 = 'two';
@@ -410,6 +399,16 @@
     expect(inputs, containsPair(key2, value2));
   }
 
+  test_inputValue_afterOneMoveNext() {
+    Map<String, TaskInput> inputDescriptors = {
+      'one': input1
+    };
+    TopLevelTaskInputBuilder builder =
+        new TopLevelTaskInputBuilder(inputDescriptors);
+    builder.moveNext();
+    expect(() => builder.inputValue, throwsStateError);
+  }
+
   test_inputValue_beforeMoveNext() {
     Map<String, TaskInput> inputDescriptors = {};
     TopLevelTaskInputBuilder builder =
diff --git a/pkg/analyzer/test/src/task/manager_test.dart b/pkg/analyzer/test/src/task/manager_test.dart
index 3d02ac6..5cd171a 100644
--- a/pkg/analyzer/test/src/task/manager_test.dart
+++ b/pkg/analyzer/test/src/task/manager_test.dart
@@ -6,7 +6,6 @@
 
 import 'package:analyzer/src/generated/java_engine.dart';
 import 'package:analyzer/src/task/manager.dart';
-import 'package:analyzer/src/task/targets.dart';
 import 'package:analyzer/task/model.dart';
 import 'package:unittest/unittest.dart';
 
@@ -57,13 +56,13 @@
     TaskDescriptor descriptor =
         new TaskDescriptor('task', null, null, [result1]);
     manager.addTaskDescriptor(descriptor);
-    AnalysisTarget target = new SourceTarget(null);
+    AnalysisTarget target = new TestSource();
     expect(manager.findTask(target, result1), descriptor);
   }
 
   test_findTask_empty() {
     TaskManager manager = new TaskManager();
-    AnalysisTarget target = new SourceTarget(null);
+    AnalysisTarget target = new TestSource();
     expect(
         () => manager.findTask(target, result1),
         throwsA(new isInstanceOf<AnalysisException>()));
@@ -81,7 +80,7 @@
         new TaskDescriptor('task3', null, null, [result2]);
     manager.addTaskDescriptor(descriptor3);
 
-    AnalysisTarget target = new SourceTarget(null);
+    AnalysisTarget target = new TestSource();
     TaskDescriptor task = manager.findTask(target, result1);
     expect(task == descriptor1 || task == descriptor2, true);
   }
@@ -91,7 +90,7 @@
     TaskDescriptor descriptor =
         new TaskDescriptor('task', null, null, [result1]);
     manager.addTaskDescriptor(descriptor);
-    AnalysisTarget target = new SourceTarget(null);
+    AnalysisTarget target = new TestSource();
     expect(
         () => manager.findTask(target, result2),
         throwsA(new isInstanceOf<AnalysisException>()));
diff --git a/pkg/analyzer/test/src/task/model_test.dart b/pkg/analyzer/test/src/task/model_test.dart
index 9fdf41e..88b5915 100644
--- a/pkg/analyzer/test/src/task/model_test.dart
+++ b/pkg/analyzer/test/src/task/model_test.dart
@@ -6,9 +6,7 @@
 
 import 'package:analyzer/src/generated/engine.dart' hide AnalysisTask;
 import 'package:analyzer/src/generated/java_engine.dart';
-import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/task/model.dart';
-import 'package:analyzer/src/task/targets.dart';
 import 'package:analyzer/task/model.dart';
 import 'package:unittest/unittest.dart';
 
@@ -27,7 +25,7 @@
 @reflectiveTest
 class AnalysisTaskTest extends EngineTestCase {
   test_getRequiredInput_missingKey() {
-    SourceTarget target = new SourceTarget(new TestSource());
+    AnalysisTarget target = new TestSource();
     AnalysisTask task = new TestAnalysisTask(null, target);
     task.inputs = {
       'a': 'b'
@@ -38,7 +36,7 @@
   }
 
   test_getRequiredInput_noInputs() {
-    SourceTarget target = new SourceTarget(new TestSource());
+    AnalysisTarget target = new TestSource();
     AnalysisTask task = new TestAnalysisTask(null, target);
     expect(
         () => task.getRequiredInput('x'),
@@ -46,7 +44,7 @@
   }
 
   test_getRequiredInput_valid() {
-    SourceTarget target = new SourceTarget(new TestSource());
+    AnalysisTarget target = new TestSource();
     AnalysisTask task = new TestAnalysisTask(null, target);
     String key = 'a';
     String value = 'b';
@@ -57,10 +55,9 @@
   }
 
   test_getRequiredSource() {
-    Source source = new TestSource();
-    SourceTarget target = new SourceTarget(source);
+    AnalysisTarget target = new TestSource();
     AnalysisTask task = new TestAnalysisTask(null, target);
-    expect(task.getRequiredSource(), source);
+    expect(task.getRequiredSource(), target);
   }
 }
 
@@ -114,7 +111,7 @@
   }
 
   test_inputFor() {
-    SourceTarget target = new SourceTarget(null);
+    AnalysisTarget target = new TestSource();
     ResultDescriptorImpl result = new ResultDescriptorImpl('result', null);
     TaskInput input = result.inputFor(target);
     expect(input, isNotNull);
@@ -151,7 +148,7 @@
     TaskDescriptorImpl descriptor =
         new TaskDescriptorImpl('name', buildTask, createTaskInputs, results);
     AnalysisContext context = null;
-    SourceTarget target = new SourceTarget(null);
+    AnalysisTarget target = new TestSource();
     Map<String, dynamic> inputs = {};
     AnalysisTask createTask = descriptor.createTask(context, target, inputs);
     expect(createTask, isNotNull);
diff --git a/pkg/analyzer/test/src/task/targets_test.dart b/pkg/analyzer/test/src/task/targets_test.dart
deleted file mode 100644
index eb25284..0000000
--- a/pkg/analyzer/test/src/task/targets_test.dart
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library test.src.task.targets_test;
-
-import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer/src/task/targets.dart';
-import 'package:unittest/unittest.dart';
-
-import '../../generated/test_support.dart';
-import '../../reflective_tests.dart';
-
-main() {
-  groupSep = ' | ';
-  runReflectiveTests(SourceTargetTest);
-}
-
-@reflectiveTest
-class SourceTargetTest extends EngineTestCase {
-  test_create() {
-    Source source = new TestSource();
-    SourceTarget target = new SourceTarget(source);
-    expect(target, isNotNull);
-    expect(target.source, source);
-  }
-}
diff --git a/pkg/analyzer/test/src/task/test_all.dart b/pkg/analyzer/test/src/task/test_all.dart
index 86c790f..12fccc4 100644
--- a/pkg/analyzer/test/src/task/test_all.dart
+++ b/pkg/analyzer/test/src/task/test_all.dart
@@ -6,18 +6,18 @@
 
 import 'package:unittest/unittest.dart';
 
+import 'dart_test.dart' as dart_test;
 import 'inputs_test.dart' as inputs_test;
 import 'manager_test.dart' as manager_test;
 import 'model_test.dart' as model_test;
-import 'targets_test.dart' as targets_test;
 
 /// Utility for manually running all tests.
 main() {
   groupSep = ' | ';
   group('task tests', () {
+    dart_test.main();
     inputs_test.main();
     manager_test.main();
     model_test.main();
-    targets_test.main();
   });
 }
diff --git a/pkg/analyzer/test/src/test_all.dart b/pkg/analyzer/test/src/test_all.dart
index d29d023..4f8b2a5 100644
--- a/pkg/analyzer/test/src/test_all.dart
+++ b/pkg/analyzer/test/src/test_all.dart
@@ -7,11 +7,13 @@
 import 'package:unittest/unittest.dart';
 
 import 'task/test_all.dart' as task;
+import 'util/test_all.dart' as util;
 
 /// Utility for manually running all tests.
 main() {
   groupSep = ' | ';
-  group('generated tests', () {
+  group('src tests', () {
     task.main();
+    util.main();
   });
 }
diff --git a/pkg/analyzer/test/src/util/asserts_test.dart b/pkg/analyzer/test/src/util/asserts_test.dart
new file mode 100644
index 0000000..0e76eb5
--- /dev/null
+++ b/pkg/analyzer/test/src/util/asserts_test.dart
@@ -0,0 +1,32 @@
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library test.src.util.asserts;
+
+import 'package:analyzer/src/util/asserts.dart';
+import 'package:unittest/unittest.dart';
+
+import '../../reflective_tests.dart';
+
+
+main() {
+  groupSep = ' | ';
+  runReflectiveTests(AnalysisTaskTest);
+}
+
+
+@reflectiveTest
+class AnalysisTaskTest {
+  void test_notNull_notNull() {
+    notNull(this);
+  }
+
+  void test_notNull_null_hasDescription() {
+    expect(() => notNull(null, 'desc'), throwsArgumentError);
+  }
+
+  void test_notNull_null_noDescription() {
+    expect(() => notNull(null), throwsArgumentError);
+  }
+}
diff --git a/pkg/analyzer/test/src/util/test_all.dart b/pkg/analyzer/test/src/util/test_all.dart
new file mode 100644
index 0000000..88de6e4
--- /dev/null
+++ b/pkg/analyzer/test/src/util/test_all.dart
@@ -0,0 +1,17 @@
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library test.src.util;
+
+import 'package:unittest/unittest.dart';
+
+import 'asserts_test.dart' as asserts_test;
+
+/// Utility for manually running all tests.
+main() {
+  groupSep = ' | ';
+  group('task tests', () {
+    asserts_test.main();
+  });
+}
diff --git a/pkg/analyzer2dart/lib/src/cps_generator.dart b/pkg/analyzer2dart/lib/src/cps_generator.dart
index 03cc77a..11c8a84 100644
--- a/pkg/analyzer2dart/lib/src/cps_generator.dart
+++ b/pkg/analyzer2dart/lib/src/cps_generator.dart
@@ -45,6 +45,19 @@
     VariableDeclaration variableDeclaration = node;

     return visitor.handleFieldDeclaration(element, variableDeclaration);

   }

+

+  @override

+  ir.ExecutableDefinition visitConstructorElement(

+      analyzer.ConstructorElement element) {

+    CpsGeneratingVisitor visitor = new CpsGeneratingVisitor(converter, element);

+    if (!element.isFactory) {

+      ConstructorDeclaration constructorDeclaration = node;

+      return visitor.handleConstructorDeclaration(

+          element, constructorDeclaration);

+    }

+    // TODO(johnniwinther): Support factory constructors.

+    return null;

+  }

 }

 

 /// Visitor that converts analyzer AST nodes into CPS ir nodes.

@@ -64,6 +77,25 @@
 

   ir.Node visit(AstNode node) => node.accept(this);

 

+  ir.ConstructorDefinition handleConstructorDeclaration(

+      analyzer.ConstructorElement constructor, ConstructorDeclaration node) {

+    FunctionBody body = node.body;

+    dart2js.ConstructorElement element = converter.convertElement(constructor);

+    return withBuilder(

+        new DartIrBuilder(DART_CONSTANT_SYSTEM,

+                          element,

+                          // TODO(johnniwinther): Supported closure variables.

+                          new NullCapturedVariableInfo()),

+        () {

+      irBuilder.buildFunctionHeader(

+          constructor.parameters.map(converter.convertElement));

+      // Visit the body directly to avoid processing the signature as

+      // expressions.

+      visit(node.body);

+      return irBuilder.makeConstructorDefinition(const [], const []);

+    });

+  }

+

   ir.FieldDefinition handleFieldDeclaration(

       analyzer.PropertyInducingElement field, VariableDeclaration node) {

     dart2js.FieldElement element = converter.convertElement(field);

diff --git a/pkg/analyzer2dart/lib/src/dart_backend.dart b/pkg/analyzer2dart/lib/src/dart_backend.dart
index dc39688..8a932e9 100644
--- a/pkg/analyzer2dart/lib/src/dart_backend.dart
+++ b/pkg/analyzer2dart/lib/src/dart_backend.dart
@@ -77,13 +77,6 @@
   }
 
   @override
-  void reportFatalError(Spannable node,
-                        MessageKind errorCode,
-                        [Map arguments = const {}]) {
-    // TODO: implement reportFatalError
-  }
-
-  @override
   void reportHint(Spannable node,
                   MessageKind errorCode,
                   [Map arguments = const {}]) {
diff --git a/pkg/analyzer2dart/lib/src/element_converter.dart b/pkg/analyzer2dart/lib/src/element_converter.dart
index b3ce83e..4b97325 100644
--- a/pkg/analyzer2dart/lib/src/element_converter.dart
+++ b/pkg/analyzer2dart/lib/src/element_converter.dart
@@ -8,10 +8,10 @@
 library analyzer2dart.element_converter;
 
 import 'package:compiler/src/elements/elements.dart' as dart2js;
-import 'package:compiler/src/elements/modelx.dart' as modelx;
 import 'package:compiler/src/util/util.dart' as util;
 import 'package:compiler/src/dart_types.dart' as dart2js;
 import 'package:analyzer/src/generated/element.dart' as analyzer;
+import 'package:analyzer/src/generated/utilities_dart.dart';
 
 part 'modely.dart';
 
diff --git a/pkg/analyzer2dart/lib/src/modely.dart b/pkg/analyzer2dart/lib/src/modely.dart
index 6cc1f50..200a75b 100644
--- a/pkg/analyzer2dart/lib/src/modely.dart
+++ b/pkg/analyzer2dart/lib/src/modely.dart
@@ -237,9 +237,6 @@
   void addToScope(element, listener) => unsupported('addToScope');
 
   @override
-  void set canUseNative(bool value) => unsupported('canUseNative');
-
-  @override
   bool get canUseNative => unsupported('canUseNative');
 
   @override
@@ -340,10 +337,14 @@
   // TODO(johnniwinther): Ensure the correct semantics of this.
   @override
   bool get isAbstract => false;
+
+  @override
+  dart2js.ClassElement get enclosingClass => null;
 }
 
 abstract class FunctionElementMixin
     implements ElementY, dart2js.FunctionElement {
+  analyzer.ExecutableElement get element;
 
   // TODO(johnniwinther): Ensure the correct semantics of this.
   @override
@@ -369,6 +370,14 @@
 
   @override
   get asyncMarker => unsupported('asyncMarker');
+
+  @override
+  List<dart2js.ParameterElement> get parameters {
+    return element.parameters.map(converter.convertElement).toList();
+  }
+
+  @override
+  dart2js.FunctionType get type => converter.convertType(element.type);
 }
 
 class TopLevelFunctionElementY extends ElementY
@@ -382,9 +391,6 @@
   @override
   dart2js.ElementKind get kind => dart2js.ElementKind.FUNCTION;
 
-  @override
-  dart2js.FunctionType get type => converter.convertType(element.type);
-
   TopLevelFunctionElementY(ElementConverter converter,
                            analyzer.FunctionElement element)
       : super(converter, element);
@@ -402,9 +408,6 @@
   dart2js.ElementKind get kind => dart2js.ElementKind.FUNCTION;
 
   @override
-  dart2js.FunctionType get type => converter.convertType(element.type);
-
-  @override
   bool get isAbstract => false;
 
   @override
@@ -436,6 +439,12 @@
   @override
   bool get isConst => false;
 
+  @override
+  bool get isNamed => element.parameterKind == ParameterKind.NAMED;
+
+  @override
+  bool get isOptional => element.parameterKind.isOptional;
+
   ParameterElementY(ElementConverter converter,
                     analyzer.ParameterElement element)
       : super(converter, element) {
@@ -483,7 +492,6 @@
 
   @override
   get typeVariables => unsupported('typeVariables');
-
 }
 
 class ClassElementY extends TypeDeclarationElementY
@@ -496,6 +504,50 @@
   @override
   bool get isObject => element.type.isObject;
 
+  // TODO(johnniwinther): Ensure the correct semantics.
+  // TODO(paulberry,brianwilkerson): [ClassElement.isTypedef] should probably
+  // be renamed to [ClassElement.isNamedMixinApplication].
+  @override
+  bool get isMixinApplication => element.isTypedef;
+
+  @override
+  bool get isUnnamedMixinApplication => false;
+
+  @override
+  bool get isEnumClass => element.isEnum;
+
+  @override
+  bool get isAbstract => element.isAbstract;
+
+  // TODO(johnniwinther): Semantic difference: Dart2js points to unnamed
+  // mixin applications, analyzer points to the type in the extends clause or
+  // Object if omitted.
+  @override
+  dart2js.DartType get supertype {
+    return element.supertype != null
+        ? converter.convertType(element.supertype)
+        : null;
+  }
+
+  @override
+  util.Link<dart2js.DartType> get interfaces {
+    // TODO(johnniwinther): Support interfaces.
+    return const util.Link<dart2js.DartType>();
+  }
+
+  // TODO(johnniwinther): Support generic classes.
+  @override
+  List<dart2js.DartType> get typeVariables => const [];
+
+  @override
+  bool get isStatic => false;
+
+  @override
+  bool get isTopLevel => true;
+
+  @override
+  dart2js.ClassElement get enclosingClass => this;
+
   ClassElementY(ElementConverter converter, analyzer.ClassElement element)
       : super(converter, element);
 
@@ -581,18 +633,12 @@
   bool implementsInterface(intrface) => unsupported('implementsInterface');
 
   @override
-  get interfaces => unsupported('interfaces');
-
-  @override
   bool get isProxy => unsupported('isProxy');
 
   @override
   bool isSubclassOf(cls) => unsupported('isSubclassOf');
 
   @override
-  get isUnnamedMixinApplication => unsupported('isUnnamedMixinApplication');
-
-  @override
   localLookup(String elementName) => unsupported('localLookup');
 
   @override
@@ -634,29 +680,13 @@
   void reverseBackendMembers() => unsupported('reverseBackendMembers');
 
   @override
-  void setDefaultConstructor(constructor, compiler) {
-    unsupported('setDefaultConstructor');
-  }
-
-  @override
   dart2js.ClassElement get superclass => unsupported('superclass');
 
-  // TODO(johnniwinther): Semantic difference: Dart2js points to unnamed
-  // mixin applications, analyzer points to the type in the extends clause or
-  // Object if omitted.
-  @override
-  dart2js.DartType get supertype => unsupported('supertype');
-
   @override
   int get supertypeLoadState => unsupported('supertypeLoadState');
 
   @override
-  validateConstructorLookupResults(selector,  result, noMatch) {
-    unsupported('validateConstructorLookupResults');
-  }
-
-  @override
-  bool get isEnumClass => unsupported('isEnum');
+  dart2js.ConstructorElement lookupDefaultConstructor() => unsupported('lookupDefaultConstructor');
 }
 
 class TypedefElementY extends TypeDeclarationElementY
@@ -755,23 +785,45 @@
   dart2js.DartType get type => unsupported('type');
 }
 
-class ConstructorElementY extends ElementY
-    with AnalyzableElementY,
-         AstElementY,
-         FunctionElementMixin
-    implements dart2js.ConstructorElement {
+abstract class ClassMemberMixin implements ElementY {
+  analyzer.ClassMemberElement get element;
 
-  analyzer.ConstructorElement get element => super.element;
+  @override
+  dart2js.ClassElement get contextClass => enclosingClass;
 
   @override
   dart2js.ClassElement get enclosingClass {
     return converter.convertElement(element.enclosingElement);
   }
 
+  @override
+  bool get isClassMember => true;
+}
+
+class ConstructorElementY extends ElementY
+    with AnalyzableElementY,
+         AstElementY,
+         FunctionElementMixin,
+         ClassMemberMixin
+    implements dart2js.ConstructorElement {
+
+  analyzer.ConstructorElement get element => super.element;
+
   // TODO(johnniwinther): Support redirecting/factory constructors.
   @override
   dart2js.ElementKind get kind => dart2js.ElementKind.GENERATIVE_CONSTRUCTOR;
 
+  // TODO(johnniwinther): Support factory constructors.
+  @override
+  bool get isFactoryConstructor => false;
+
+  // TODO(johnniwinther): Support redirecting factory constructors.
+  @override
+  bool get isRedirectingFactory => false;
+
+  @override
+  bool get isStatic => false;
+
   ConstructorElementY(ElementConverter converter,
                       analyzer.ConstructorElement element)
       : super(converter, element);
@@ -789,11 +841,5 @@
   get immediateRedirectionTarget => unsupported('immediateRedirectionTarget');
 
   @override
-  bool get isRedirectingFactory => unsupported('isRedirectingFactory');
-
-  @override
   get nestedClosures => unsupported('nestedClosures');
-
-  @override
-  get type => unsupported('type');
 }
diff --git a/pkg/analyzer2dart/test/end2end_data.dart b/pkg/analyzer2dart/test/end2end_data.dart
index 50eafcd..b1c6ac3 100644
--- a/pkg/analyzer2dart/test/end2end_data.dart
+++ b/pkg/analyzer2dart/test/end2end_data.dart
@@ -817,4 +817,15 @@
 }
 '''),
   ]),
+
+  const Group('Constructors', const <TestSpec>[
+    const TestSpec('''
+class C {
+  C() {}
+}
+main() {
+  return new C();
+}
+'''),
+  ]),
 ];
diff --git a/pkg/analyzer2dart/test/mock_sdk.dart b/pkg/analyzer2dart/test/mock_sdk.dart
index fd66b7b..8cebd44 100644
--- a/pkg/analyzer2dart/test/mock_sdk.dart
+++ b/pkg/analyzer2dart/test/mock_sdk.dart
@@ -58,7 +58,9 @@
 }
 const Object deprecated = const Deprecated("next release");
 
-abstract class List<E> extends Object {
+abstract class Iterable<E> {}
+
+abstract class List<E> extends Object implements Iterable {
   void add(E value);
   E operator [](int index);
   void operator []=(int index, E value);
@@ -75,7 +77,7 @@
   static const _MockSdkLibrary LIB_ASYNC =
       const _MockSdkLibrary('async', '/lib/async/async.dart', '''
 library dart.async;
-class Future {
+class Future<T> {
   static Future wait(List<Future> futures) => null;
 }
 
diff --git a/pkg/analyzer2dart/test/sexpr_data.dart b/pkg/analyzer2dart/test/sexpr_data.dart
index 699192a..646a42a 100644
--- a/pkg/analyzer2dart/test/sexpr_data.dart
+++ b/pkg/analyzer2dart/test/sexpr_data.dart
@@ -23,7 +23,7 @@
     const TestSpec('''
 main() {}
 ''', '''
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetPrim (v0 (Constant (Null)))
     (InvokeContinuation return (v0))))
 '''),
@@ -34,7 +34,7 @@
   foo();
 }
 ''', '''
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetCont ((k0 (v0)
       (LetPrim (v1 (Constant (Null)))
         (InvokeContinuation return (v1)))))
@@ -48,7 +48,7 @@
   return 0;
 }
 ''', '''
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetPrim (v0 (Constant (Int 0)))
     (InvokeContinuation return (v0))))
 '''),
@@ -58,7 +58,7 @@
   return 1.5;
 }
 ''', '''
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetPrim (v0 (Constant (Double 1.5)))
     (InvokeContinuation return (v0))))
 '''),
@@ -68,7 +68,7 @@
   return true;
 }
 ''', '''
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetPrim (v0 (Constant (Bool true)))
     (InvokeContinuation return (v0))))
 '''),
@@ -78,7 +78,7 @@
   return false;
 }
 ''', '''
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetPrim (v0 (Constant (Bool false)))
     (InvokeContinuation return (v0))))
 '''),
@@ -88,7 +88,7 @@
   return "a";
 }
 ''', '''
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetPrim (v0 (Constant (String "a")))
     (InvokeContinuation return (v0))))
 '''),
@@ -98,7 +98,7 @@
     const TestSpec('''
 main(args) {}
 ''', '''
-(FunctionDefinition main (args) return ()
+(FunctionDefinition main (args) return
   (LetPrim (v0 (Constant (Null)))
     (InvokeContinuation return (v0))))
 '''),
@@ -106,7 +106,7 @@
     const TestSpec('''
 main(a, b) {}
 ''', '''
-(FunctionDefinition main (a b) return ()
+(FunctionDefinition main (a b) return
   (LetPrim (v0 (Constant (Null)))
     (InvokeContinuation return (v0))))
 '''),
@@ -119,7 +119,7 @@
   foo(null);
 }
 ''', '''
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetPrim (v0 (Constant (Null)))
     (LetCont ((k0 (v1)
         (LetPrim (v2 (Constant (Null)))
@@ -135,7 +135,7 @@
   bar(0, "");
 }
 ''', '''
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetPrim (v0 (Constant (Null)))
     (LetCont ((k0 (v1)
         (LetPrim (v2 (Constant (Int 0)))
@@ -153,7 +153,7 @@
   return foo(null);
 }
 ''', '''
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetPrim (v0 (Constant (Null)))
     (LetCont ((k0 (v1)
         (InvokeContinuation return (v1))))
@@ -168,7 +168,7 @@
   return a;
 }
 ''', '''
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetPrim (v0 (Constant (Null)))
     (InvokeContinuation return (v0))))
 '''),
@@ -179,7 +179,7 @@
   return a;
 }
 ''', '''
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetPrim (v0 (Constant (Int 0)))
     (InvokeContinuation return (v0))))
 '''),
@@ -189,7 +189,7 @@
   return a;
 }
 ''', '''
-(FunctionDefinition main (a) return ()
+(FunctionDefinition main (a) return
   (InvokeContinuation return (a)))
 '''),
     ]),
@@ -202,7 +202,7 @@
   return a;
 }
 ''', '''
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetPrim (v0 (Constant (Null)))
     (LetPrim (v1 (Constant (Int 10)))
       (InvokeContinuation return (v1)))))
@@ -215,7 +215,7 @@
   return a;
 }
 ''', '''
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetPrim (v0 (Constant (Int 0)))
     (LetPrim (v1 (Constant (Int 10)))
       (InvokeContinuation return (v1)))))
@@ -230,7 +230,7 @@
   return a;
 }
 ''', '''
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetPrim (v0 (Constant (Int 0)))
     (LetCont ((k0 (v1)
         (LetPrim (v2 (Constant (String "")))
@@ -248,7 +248,7 @@
   return a;
 }
 ''', '''
-(FunctionDefinition main (a) return ()
+(FunctionDefinition main (a) return
   (LetCont ((k0 (v0)
       (LetPrim (v1 (Constant (String "")))
         (LetCont ((k1 (v2)
@@ -266,7 +266,7 @@
   return a;
 }
 ''', '''
-(FunctionDefinition main (a) return ()
+(FunctionDefinition main (a) return
   (LetCont ((k0 (v0)
       (LetCont ((k1 (v1)
           (InvokeContinuation return (v0))))
@@ -286,7 +286,7 @@
   return a.foo;
 }
 ''', '''
-(FunctionDefinition main (a) return ()
+(FunctionDefinition main (a) return
   (LetCont ((k0 (v0)
       (InvokeContinuation return (v0))))
     (InvokeMethod a foo () k0)))
@@ -298,7 +298,7 @@
   return a.foo;
 }
 ''', '''
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetPrim (v0 (Constant (String "")))
     (LetCont ((k0 (v1)
         (InvokeContinuation return (v1))))
@@ -312,7 +312,7 @@
   return a.foo(0);
 }
 ''', '''
-(FunctionDefinition main (a) return ()
+(FunctionDefinition main (a) return
   (LetPrim (v0 (Constant (Int 0)))
     (LetCont ((k0 (v1)
         (InvokeContinuation return (v1))))
@@ -325,7 +325,7 @@
   return a.foo(0, 1);
 }
 ''', '''
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetPrim (v0 (Constant (String "")))
     (LetPrim (v1 (Constant (Int 0)))
       (LetPrim (v2 (Constant (Int 1)))
@@ -341,7 +341,7 @@
   return 0 + "";
 }
 ''', '''
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetPrim (v0 (Constant (Int 0)))
     (LetPrim (v1 (Constant (String "")))
       (LetCont ((k0 (v2)
@@ -354,7 +354,7 @@
   return 0 - "";
 }
 ''', '''
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetPrim (v0 (Constant (Int 0)))
     (LetPrim (v1 (Constant (String "")))
       (LetCont ((k0 (v2)
@@ -367,7 +367,7 @@
   return 0 * "";
 }
 ''', '''
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetPrim (v0 (Constant (Int 0)))
     (LetPrim (v1 (Constant (String "")))
       (LetCont ((k0 (v2)
@@ -380,7 +380,7 @@
   return 0 / "";
 }
 ''', '''
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetPrim (v0 (Constant (Int 0)))
     (LetPrim (v1 (Constant (String "")))
       (LetCont ((k0 (v2)
@@ -393,7 +393,7 @@
   return 0 ~/ "";
 }
 ''', '''
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetPrim (v0 (Constant (Int 0)))
     (LetPrim (v1 (Constant (String "")))
       (LetCont ((k0 (v2)
@@ -406,7 +406,7 @@
   return 0 < "";
 }
 ''', '''
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetPrim (v0 (Constant (Int 0)))
     (LetPrim (v1 (Constant (String "")))
       (LetCont ((k0 (v2)
@@ -419,7 +419,7 @@
   return 0 <= "";
 }
 ''', '''
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetPrim (v0 (Constant (Int 0)))
     (LetPrim (v1 (Constant (String "")))
       (LetCont ((k0 (v2)
@@ -432,7 +432,7 @@
   return 0 > "";
 }
 ''', '''
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetPrim (v0 (Constant (Int 0)))
     (LetPrim (v1 (Constant (String "")))
       (LetCont ((k0 (v2)
@@ -445,7 +445,7 @@
   return 0 >= "";
 }
 ''', '''
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetPrim (v0 (Constant (Int 0)))
     (LetPrim (v1 (Constant (String "")))
       (LetCont ((k0 (v2)
@@ -458,7 +458,7 @@
   return 0 << "";
 }
 ''', '''
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetPrim (v0 (Constant (Int 0)))
     (LetPrim (v1 (Constant (String "")))
       (LetCont ((k0 (v2)
@@ -471,7 +471,7 @@
   return 0 >> "";
 }
 ''', '''
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetPrim (v0 (Constant (Int 0)))
     (LetPrim (v1 (Constant (String "")))
       (LetCont ((k0 (v2)
@@ -484,7 +484,7 @@
   return 0 & "";
 }
 ''', '''
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetPrim (v0 (Constant (Int 0)))
     (LetPrim (v1 (Constant (String "")))
       (LetCont ((k0 (v2)
@@ -497,7 +497,7 @@
   return 0 | "";
 }
 ''', '''
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetPrim (v0 (Constant (Int 0)))
     (LetPrim (v1 (Constant (String "")))
       (LetCont ((k0 (v2)
@@ -510,7 +510,7 @@
   return 0 ^ "";
 }
 ''', '''
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetPrim (v0 (Constant (Int 0)))
     (LetPrim (v1 (Constant (String "")))
       (LetCont ((k0 (v2)
@@ -523,7 +523,7 @@
   return 0 == "";
 }
 ''', '''
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetPrim (v0 (Constant (Int 0)))
     (LetPrim (v1 (Constant (String "")))
       (LetCont ((k0 (v2)
@@ -536,7 +536,7 @@
   return 0 != "";
 }
 ''', '''
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetPrim (v0 (Constant (Int 0)))
     (LetPrim (v1 (Constant (String "")))
       (LetCont ((k0 (v2)
@@ -557,7 +557,7 @@
   return 0 && "";
 }
 ''', '''
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetPrim (v0 (Constant (Int 0)))
     (LetCont ((k0 (v1)
         (InvokeContinuation return (v1))))
@@ -581,7 +581,7 @@
   return 0 || "";
 }
 ''', '''
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetPrim (v0 (Constant (Int 0)))
     (LetCont ((k0 (v1)
         (InvokeContinuation return (v1))))
@@ -605,7 +605,7 @@
   return 0 + "" * 2;
 }
 ''', '''
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetPrim (v0 (Constant (Int 0)))
     (LetPrim (v1 (Constant (String "")))
       (LetPrim (v2 (Constant (Int 2)))
@@ -621,7 +621,7 @@
   return 0 * "" + 2;
 }
 ''', '''
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetPrim (v0 (Constant (Int 0)))
     (LetPrim (v1 (Constant (String "")))
       (LetCont ((k0 (v2)
@@ -641,7 +641,7 @@
   }
 }
 ''', '''
-(FunctionDefinition main (a) return ()
+(FunctionDefinition main (a) return
   (LetCont ((k0 ()
       (LetPrim (v0 (Constant (Null)))
         (InvokeContinuation return (v0)))))
@@ -664,7 +664,7 @@
   }
 }
 ''', '''
-(FunctionDefinition main (a) return ()
+(FunctionDefinition main (a) return
   (LetCont ((k0 ()
       (LetPrim (v0 (Constant (Null)))
         (InvokeContinuation return (v0)))))
@@ -691,7 +691,7 @@
   }
 }
 ''', '''
-(FunctionDefinition main (a) return ()
+(FunctionDefinition main (a) return
   (LetCont ((k0 ()
       (LetPrim (v0 (Constant (Null)))
         (InvokeContinuation return (v0)))))
@@ -718,7 +718,7 @@
   return a ? print(0) : print(1);
 }
 ''', '''
-(FunctionDefinition main (a) return ()
+(FunctionDefinition main (a) return
   (LetCont ((k0 (v0)
       (InvokeContinuation return (v0))))
     (LetCont ((k1 ()
@@ -744,7 +744,7 @@
   return 1;
 }
 ''', '''
-(FunctionDefinition main (a) return ()
+(FunctionDefinition main (a) return
   (LetPrim (v0 (Constant (Int 0)))
     (InvokeContinuation return (v0))))
 '''),
@@ -760,7 +760,7 @@
   }
 }
 ''', '''
-(FunctionDefinition main (a) return ()
+(FunctionDefinition main (a) return
   (LetCont ((k0 ()
       (LetPrim (v0 (Constant (Int 0)))
         (InvokeContinuation return (v0))))
@@ -783,7 +783,7 @@
   }
 }
 ''', '''
-(FunctionDefinition main (a) return ()
+(FunctionDefinition main (a) return
   (LetCont ((k0 ()
       (LetPrim (v0 (Constant (Int 0)))
         (LetCont ((k1 (v1)
@@ -806,7 +806,7 @@
   new Object();
 }
 ''', '''
-(FunctionDefinition main (a) return ()
+(FunctionDefinition main (a) return
   (LetCont ((k0 (v0)
       (LetPrim (v1 (Constant (Null)))
         (InvokeContinuation return (v1)))))
@@ -818,7 +818,7 @@
   new Deprecated("");
 }
 ''', '''
-(FunctionDefinition main (a) return ()
+(FunctionDefinition main (a) return
   (LetPrim (v0 (Constant (String "")))
     (LetCont ((k0 (v1)
         (LetPrim (v2 (Constant (Null)))
@@ -833,7 +833,7 @@
   return [];
 }
 ''', '''
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetPrim (v0 (LiteralList ()))
     (InvokeContinuation return (v0))))
 '''),
@@ -843,7 +843,7 @@
   return [0];
 }
 ''', '''
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetPrim (v0 (Constant (Int 0)))
     (LetPrim (v1 (LiteralList (v0)))
       (InvokeContinuation return (v1)))))
@@ -854,7 +854,7 @@
   return [0, 1, a];
 }
 ''', '''
-(FunctionDefinition main (a) return ()
+(FunctionDefinition main (a) return
   (LetPrim (v0 (Constant (Int 0)))
     (LetPrim (v1 (Constant (Int 1)))
       (LetPrim (v2 (LiteralList (v0 v1 a)))
@@ -866,7 +866,7 @@
   return [0, [1], [a, [3]]];
 }
 ''', '''
-(FunctionDefinition main (a) return ()
+(FunctionDefinition main (a) return
   (LetPrim (v0 (Constant (Int 0)))
     (LetPrim (v1 (Constant (Int 1)))
       (LetPrim (v2 (LiteralList (v1)))
@@ -884,7 +884,7 @@
   return {};
 }
 ''', '''
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetPrim (v0 (LiteralMap () ()))
     (InvokeContinuation return (v0))))
 '''),
@@ -894,7 +894,7 @@
   return {"a": 0};
 }
 ''', '''
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetPrim (v0 (Constant (String "a")))
     (LetPrim (v1 (Constant (Int 0)))
       (LetPrim (v2 (LiteralMap (v0) (v1)))
@@ -906,7 +906,7 @@
   return {"a": 0, "b": 1, "c": a};
 }
 ''', '''
-(FunctionDefinition main (a) return ()
+(FunctionDefinition main (a) return
   (LetPrim (v0 (Constant (String "a")))
     (LetPrim (v1 (Constant (Int 0)))
       (LetPrim (v2 (Constant (String "b")))
@@ -921,7 +921,7 @@
   return {0: "a", 1: {2: "b"}, a: {3: "c"}};
 }
 ''', '''
-(FunctionDefinition main (a) return ()
+(FunctionDefinition main (a) return
   (LetPrim (v0 (Constant (Int 0)))
     (LetPrim (v1 (Constant (String "a")))
       (LetPrim (v2 (Constant (Int 1)))
@@ -942,7 +942,7 @@
   for (;;) {}
 }
 ''', '''
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetCont ((rec k0 ()
       (LetPrim (v0 (Constant (Bool true)))
         (LetCont ((k1 ()
@@ -961,7 +961,7 @@
   }
 }
 ''', '''
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetPrim (v0 (Constant (Int 0)))
     (LetCont ((rec k0 (v1)
         (LetPrim (v2 (Constant (Int 10)))
@@ -988,7 +988,7 @@
   }
 }
 ''', '''
-(FunctionDefinition main (i) return ()
+(FunctionDefinition main (i) return
   (LetPrim (v0 (Constant (Int 0)))
     (LetCont ((rec k0 (v1)
         (LetPrim (v2 (Constant (Int 10)))
@@ -1015,7 +1015,7 @@
   while (true) {}
 }
 ''', '''
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetCont ((rec k0 ()
       (LetPrim (v0 (Constant (Bool true)))
         (LetCont ((k1 ()
@@ -1036,7 +1036,7 @@
   }
 }
 ''', '''
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetPrim (v0 (Constant (Int 0)))
     (LetCont ((rec k0 (v1)
         (LetPrim (v2 (Constant (Int 10)))
@@ -1063,7 +1063,7 @@
   return a is String;
 }
 ''', '''
-(FunctionDefinition main (a) return ()
+(FunctionDefinition main (a) return
   (LetCont ((k0 (v0)
       (InvokeContinuation return (v0))))
     (TypeOperator is a String k0)))
@@ -1074,7 +1074,7 @@
   return a is List<String>;
 }
 ''', '''
-(FunctionDefinition main (a) return ()
+(FunctionDefinition main (a) return
   (LetCont ((k0 (v0)
       (InvokeContinuation return (v0))))
     (TypeOperator is a List<String> k0)))
@@ -1085,7 +1085,7 @@
   return a is Comparator<String>;
 }
 ''', '''
-(FunctionDefinition main (a) return ()
+(FunctionDefinition main (a) return
   (LetCont ((k0 (v0)
       (InvokeContinuation return (v0))))
     (TypeOperator is a Comparator<String> k0)))
@@ -1096,7 +1096,7 @@
   return a is! String;
 }
 ''', '''
-(FunctionDefinition main (a) return ()
+(FunctionDefinition main (a) return
   (LetCont ((k0 (v0)
       (LetCont ((k1 (v1)
           (InvokeContinuation return (v1))))
@@ -1115,7 +1115,7 @@
   return a as String;
 }
 ''', '''
-(FunctionDefinition main (a) return ()
+(FunctionDefinition main (a) return
   (LetCont ((k0 (v0)
       (InvokeContinuation return (v0))))
     (TypeOperator as a String k0)))
@@ -1132,7 +1132,7 @@
   }
 }
 ''', '''
-(FunctionDefinition main (a) return ()
+(FunctionDefinition main (a) return
   (LetCont ((k0 (v0)
       (LetCont ((rec k1 (v1)
           (LetCont ((k2 (v2)
@@ -1161,7 +1161,7 @@
   }
 }
 ''', '''
-(FunctionDefinition main (a) return ()
+(FunctionDefinition main (a) return
   (LetCont ((k0 (v0)
       (LetCont ((rec k1 (v1)
           (LetCont ((k2 (v2)
@@ -1192,7 +1192,7 @@
   }
 }
 ''', '''
-(FunctionDefinition main (a) return ()
+(FunctionDefinition main (a) return
   (LetPrim (v0 (Constant (Null)))
     (LetCont ((k0 (v1)
         (LetCont ((rec k1 (v2 v3)
@@ -1220,9 +1220,9 @@
   return local();
 }
 ''', '''
-(FunctionDefinition main (a) return ()
+(FunctionDefinition main (a) return
   (LetPrim (v0 (CreateFunction
-      (FunctionDefinition local () return ()
+      (FunctionDefinition local () return
         (LetPrim (v1 (Constant (Null)))
           (InvokeContinuation return (v1))))))
     (LetCont ((k0 (v2)
@@ -1237,9 +1237,9 @@
   return l();
 }
 ''', '''
-(FunctionDefinition main (a) return ()
+(FunctionDefinition main (a) return
   (LetPrim (v0 (CreateFunction
-      (FunctionDefinition local () return ()
+      (FunctionDefinition local () return
         (LetPrim (v1 (Constant (Null)))
           (InvokeContinuation return (v1))))))
     (LetCont ((k0 (v2)
@@ -1252,9 +1252,9 @@
   return () {}();
 }
 ''', '''
-(FunctionDefinition main (a) return ()
+(FunctionDefinition main (a) return
   (LetPrim (v0 (CreateFunction
-      (FunctionDefinition  () return ()
+      (FunctionDefinition  () return
         (LetPrim (v1 (Constant (Null)))
           (InvokeContinuation return (v1))))))
     (LetCont ((k0 (v2)
@@ -1268,20 +1268,20 @@
   return c();
 }
 ''', '''
-(FunctionDefinition main (a) return ()
+(FunctionDefinition main (a) return
   (LetCont ((k0 (v0)
       (LetCont ((k1 (v1)
           (InvokeContinuation return (v1))))
         (InvokeMethod v0 call () k1))))
     (LetCont ((k2 ()
         (LetPrim (v2 (CreateFunction
-            (FunctionDefinition  () return ()
+            (FunctionDefinition  () return
               (LetPrim (v3 (Constant (Int 0)))
                 (InvokeContinuation return (v3))))))
           (InvokeContinuation k0 (v2))))
               (k3 ()
         (LetPrim (v4 (CreateFunction
-            (FunctionDefinition  () return ()
+            (FunctionDefinition  () return
               (LetPrim (v5 (Constant (Int 1)))
                 (InvokeContinuation return (v5))))))
           (InvokeContinuation k0 (v4)))))
@@ -1297,7 +1297,7 @@
 }
 ''', const {
       'main': '''
-(FunctionDefinition main (args) return ()
+(FunctionDefinition main (args) return
   (LetCont ((k0 (v0)
       (InvokeContinuation return (v0))))
     (InvokeStatic field () k0)))
@@ -1313,7 +1313,7 @@
 }
 ''', const {
       'main': '''
-(FunctionDefinition main (args) return ()
+(FunctionDefinition main (args) return
   (LetCont ((k0 (v0)
       (InvokeContinuation return (v0))))
     (InvokeStatic field () k0)))
@@ -1331,7 +1331,7 @@
 }
 ''', const {
       'main': '''
-(FunctionDefinition main (args) return ()
+(FunctionDefinition main (args) return
   (LetCont ((k0 (v0)
       (InvokeContinuation return (v0))))
     (InvokeStatic field () k0)))
@@ -1349,7 +1349,7 @@
   return field;
 }
 ''', '''
-(FunctionDefinition main (args) return ()
+(FunctionDefinition main (args) return
   (LetCont ((k0 (v0)
       (LetCont ((k1 (v1)
           (LetCont ((k2 (v2)
@@ -1368,11 +1368,11 @@
   print(getFoo());
 }
 ''', '''
-(FunctionDefinition main (x foo) return (foo)
+(FunctionDefinition main (x foo) return
   (LetCont ((k0 (v0)
       (LetPrim (v1 (CreateFunction
-          (FunctionDefinition getFoo () return ()
-            (LetPrim (v2 (GetClosureVariable foo))
+          (FunctionDefinition getFoo () return
+            (LetPrim (v2 (GetMutableVariable foo))
               (InvokeContinuation return (v2))))))
         (LetCont ((k1 (v3)
             (LetCont ((k2 (v4)
@@ -1383,4 +1383,27 @@
     (InvokeStatic print (x) k0)))
 ''', skipInAnalyzerFrontend: true)
   ]),
+
+  const Group('Constructors', const <TestSpec>[
+    const TestSpec('''
+class C {
+  C() {}
+}
+main() {
+  return new C();
+}
+''',
+    const {
+'main': '''
+(FunctionDefinition main () return
+  (LetCont ((k0 (v0)
+      (InvokeContinuation return (v0))))
+    (InvokeConstructor C () k0)))
+''',
+'C.': '''
+(FunctionDefinition  () return
+  (LetPrim (v0 (Constant (Null)))
+    (InvokeContinuation return (v0))))
+'''}),
+  ]),
 ];
diff --git a/pkg/analyzer2dart/test/sexpr_test.dart b/pkg/analyzer2dart/test/sexpr_test.dart
index 9a1790d..e4f83ee 100644
--- a/pkg/analyzer2dart/test/sexpr_test.dart
+++ b/pkg/analyzer2dart/test/sexpr_test.dart
@@ -38,28 +38,40 @@
   ClosedWorld world = driver.computeWorld(entryPoint);
   ConvertedWorld convertedWorld = convertWorld(world);
 
-  void checkOutput(dart2js.Element element, String expectedOutput) {
+  void checkOutput(String elementName,
+                   dart2js.Element element,
+                   String expectedOutput) {
     expectedOutput = expectedOutput.trim();
     String output = convertedWorld.getIr(element)
         .accept(new SExpressionStringifier());
     expect(output, equals(expectedOutput),
-        reason: 'Input:\n$input\n'
-                'Expected:\n$expectedOutput\n'
-                'Actual:\n$output');
+        reason: "\nInput:\n${result.input}\n"
+                "Expected for '$elementName':\n$expectedOutput\n"
+                "Actual for '$elementName':\n$output\n");
   }
 
   if (result.output is String) {
-    checkOutput(convertedWorld.mainFunction, result.output);
+    checkOutput('main', convertedWorld.mainFunction, result.output);
   } else {
     assert(result.output is Map<String, String>);
     dart2js.LibraryElement mainLibrary = convertedWorld.mainFunction.library;
     result.output.forEach((String elementName, String output) {
+      bool found = false;
+      List<String> names = <String>[];
       convertedWorld.resolvedElements.forEach((dart2js.Element element) {
-        if (element.name == elementName &&
-            element.library == mainLibrary) {
-          checkOutput(element, output);
+        if (element.library == mainLibrary) {
+          String name = element.name;
+          if (element.enclosingClass != null) {
+            name = '${element.enclosingClass.name}.$name';
+          }
+          if (name == elementName) {
+            checkOutput(elementName, element, output);
+            found = true;
+          }
+          names.add(name);
         }
       });
+      expect(found, isTrue, reason: "'$elementName' not found in $names.");
     });
   }
 }
diff --git a/pkg/compiler/lib/src/apiimpl.dart b/pkg/compiler/lib/src/apiimpl.dart
index ab20472..8ce30bb 100644
--- a/pkg/compiler/lib/src/apiimpl.dart
+++ b/pkg/compiler/lib/src/apiimpl.dart
@@ -85,7 +85,6 @@
             enableExperimentalMirrors:
                 hasOption(options, '--enable-experimental-mirrors'),
             enableAsyncAwait: hasOption(options, '--enable-async'),
-            enableEnums: hasOption(options, '--enable-enum'),
             generateCodeWithCompileTimeErrors:
                 hasOption(options, '--generate-code-with-compile-time-errors'),
             allowNativeExtensions:
@@ -107,7 +106,7 @@
       throw new ArgumentError("[packageRoot] must end with a /.");
     }
     if (!analyzeOnly) {
-      if (enableAsyncAwait) {
+      if (enableAsyncAwait && emitJavaScript) {
         throw new ArgumentError(
             "--enable-async is currently only supported with --analyze-only");
       }
diff --git a/pkg/compiler/lib/src/compile_time_constants.dart b/pkg/compiler/lib/src/compile_time_constants.dart
index 271ff8d..5fb178d 100644
--- a/pkg/compiler/lib/src/compile_time_constants.dart
+++ b/pkg/compiler/lib/src/compile_time_constants.dart
@@ -1043,19 +1043,16 @@
         assert(superClass != null);
         assert(superClass.resolutionState == STATE_DONE);
 
-        Selector selector =
-            new Selector.callDefaultConstructor(enclosingClass.library);
-
         FunctionElement targetConstructor =
-            superClass.lookupConstructor(selector);
-        if (targetConstructor == null) {
-          compiler.internalError(functionNode,
-              "No default constructor available.");
+            superClass.lookupDefaultConstructor();
+        // If we do not find a default constructor, an error was reported
+        // already and compilation will fail anyway. So just ignore that case.
+        if (targetConstructor != null) {
+          Selector selector = new Selector.callDefaultConstructor();
+          List<AstConstant> compiledArguments = evaluateArgumentsToConstructor(
+              functionNode, selector, const Link<Node>(), targetConstructor);
+          evaluateSuperOrRedirectSend(compiledArguments, targetConstructor);
         }
-        List<AstConstant> compiledArguments =
-            evaluateArgumentsToConstructor(
-                functionNode, selector, const Link<Node>(), targetConstructor);
-        evaluateSuperOrRedirectSend(compiledArguments, targetConstructor);
       }
     }
   }
diff --git a/pkg/compiler/lib/src/compiler.dart b/pkg/compiler/lib/src/compiler.dart
index 6b15e9b..173f421 100644
--- a/pkg/compiler/lib/src/compiler.dart
+++ b/pkg/compiler/lib/src/compiler.dart
@@ -251,6 +251,9 @@
   /// Backend callback methods for the resolution phase.
   ResolutionCallbacks get resolutionCallbacks;
 
+  // TODO(johnniwinther): Move this to the JavaScriptBackend.
+  String get patchVersion => null;
+
   /// Set of classes that need to be considered for reflection although not
   /// otherwise visible during resolution.
   Iterable<ClassElement> classesRequiredForReflection = const [];
@@ -740,8 +743,8 @@
   /// `true` if async/await features are supported.
   final bool enableAsyncAwait;
 
-  /// `true` if enum declarations are supported.
-  final bool enableEnums;
+  /// `true` if the compiler uses the [JavaScriptBackend].
+  final bool emitJavaScript;
 
   /// If `true`, some values are cached for reuse in incremental compilation.
   /// Incremental compilation is basically calling [run] more than once.
@@ -800,8 +803,8 @@
   ConstantValue proxyConstant;
 
   // TODO(johnniwinther): Move this to the JavaScriptBackend.
-  /// The constant for the [patch] variable defined in dart:_js_helper.
-  ConstantValue patchConstant;
+  /// The class for patch annotation defined in dart:_js_helper.
+  ClassElement patchAnnotationClass;
 
   // TODO(johnniwinther): Move this to the JavaScriptBackend.
   ClassElement nativeAnnotationClass;
@@ -922,6 +925,7 @@
   static const int NO_SUCH_METHOD_ARG_COUNT = 1;
   static const String CREATE_INVOCATION_MIRROR =
       'createInvocationMirror';
+  static const String FROM_ENVIRONMENT = 'fromEnvironment';
 
   static const String RUNTIME_TYPE = 'runtimeType';
 
@@ -938,8 +942,6 @@
       Compiler.NO_SUCH_METHOD, null, Compiler.NO_SUCH_METHOD_ARG_COUNT);
   final Selector symbolValidatedConstructorSelector = new Selector.call(
       'validated', null, 1);
-  final Selector fromEnvironmentSelector = new Selector.callConstructor(
-      'fromEnvironment', null, 2);
 
   bool enabledNoSuchMethod = false;
   bool enabledRuntimeType = false;
@@ -1005,13 +1007,14 @@
             this.suppressWarnings: false,
             bool hasIncrementalSupport: false,
             this.enableExperimentalMirrors: false,
-            this.enableAsyncAwait: false,
-            this.enableEnums: false,
+            bool enableAsyncAwait: false,
             this.allowNativeExtensions: false,
             this.generateCodeWithCompileTimeErrors: false,
             api.CompilerOutputProvider outputProvider,
             List<String> strips: const []})
-      : this.disableTypeInferenceFlag =
+      : this.emitJavaScript = emitJavaScript,
+        this.enableAsyncAwait = enableAsyncAwait || !emitJavaScript,
+        this.disableTypeInferenceFlag =
           disableTypeInferenceFlag || !emitJavaScript,
         this.analyzeOnly =
             analyzeOnly || analyzeSignaturesOnly || analyzeAllFlag,
@@ -1245,6 +1248,7 @@
     } else if (uri == DART_NATIVE_TYPED_DATA) {
       typedDataClass = findRequiredElement(library, 'NativeTypedData');
     } else if (uri == js_backend.JavaScriptBackend.DART_JS_HELPER) {
+      patchAnnotationClass = findRequiredElement(library, '_Patch');
       nativeAnnotationClass = findRequiredElement(library, 'Native');
     }
     return backend.onLibraryScanned(library, loader);
@@ -1327,14 +1331,6 @@
           resolver.constantCompiler.compileConstant(
               coreLibrary.find('proxy')).value;
 
-      // TODO(johnniwinther): Move this to the JavaScript backend.
-      LibraryElement jsHelperLibrary = loadedLibraries.getLibrary(
-              js_backend.JavaScriptBackend.DART_JS_HELPER);
-      if (jsHelperLibrary != null) {
-        patchConstant = resolver.constantCompiler.compileConstant(
-            jsHelperLibrary.find('patch')).value;
-      }
-
       if (preserveComments) {
         return libraryLoader.loadLibrary(DART_MIRRORS)
             .then((LibraryElement libraryElement) {
@@ -1354,6 +1350,10 @@
     return element;
   }
 
+  // TODO(johnniwinther): Move this to [PatchParser] when it is moved to the
+  // [JavaScriptBackend]. Currently needed for testing.
+  String get patchVersion => backend.patchVersion;
+
   void onClassResolved(ClassElement cls) {
     if (mirrorSystemClass == cls) {
       mirrorSystemGetNameFunction =
@@ -1362,16 +1362,17 @@
       symbolConstructor = cls.constructors.head;
     } else if (symbolImplementationClass == cls) {
       symbolValidatedConstructor = symbolImplementationClass.lookupConstructor(
-          symbolValidatedConstructorSelector);
+          symbolValidatedConstructorSelector.name);
     } else if (mirrorsUsedClass == cls) {
       mirrorsUsedConstructor = cls.constructors.head;
     } else if (intClass == cls) {
-      intEnvironment = intClass.lookupConstructor(fromEnvironmentSelector);
+      intEnvironment = intClass.lookupConstructor(FROM_ENVIRONMENT);
     } else if (stringClass == cls) {
       stringEnvironment =
-          stringClass.lookupConstructor(fromEnvironmentSelector);
+          stringClass.lookupConstructor(FROM_ENVIRONMENT);
     } else if (boolClass == cls) {
-      boolEnvironment = boolClass.lookupConstructor(fromEnvironmentSelector);
+      boolEnvironment =
+          boolClass.lookupConstructor(FROM_ENVIRONMENT);
     }
   }
 
@@ -1409,19 +1410,13 @@
   Element _unnamedListConstructor;
   Element get unnamedListConstructor {
     if (_unnamedListConstructor != null) return _unnamedListConstructor;
-    Selector callConstructor = new Selector.callConstructor(
-        "", listClass.library);
-    return _unnamedListConstructor =
-        listClass.lookupConstructor(callConstructor);
+    return _unnamedListConstructor = listClass.lookupDefaultConstructor();
   }
 
   Element _filledListConstructor;
   Element get filledListConstructor {
     if (_filledListConstructor != null) return _filledListConstructor;
-    Selector callConstructor = new Selector.callConstructor(
-        "filled", listClass.library);
-    return _filledListConstructor =
-        listClass.lookupConstructor(callConstructor);
+    return _filledListConstructor = listClass.lookupConstructor("filled");
   }
 
   /**
@@ -2123,7 +2118,7 @@
       : this.compiler = compiler,
         watch = (compiler.verbose) ? new Stopwatch() : null;
 
-  String get name => 'Unknown task';
+  String get name => "Unknown task '${this.runtimeType}'";
   int get timing => (watch != null) ? watch.elapsedMilliseconds : 0;
 
   int get timingMicroseconds => (watch != null) ? watch.elapsedMicroseconds : 0;
diff --git a/pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart b/pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart
index 2de6fd1..f883b9b 100644
--- a/pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart
+++ b/pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart
@@ -248,10 +248,6 @@
   /// or put it in its box, if necessary.
   void _createFunctionParameter(ParameterElement parameterElement);
 
-  /// Returns the list of closure variables declared in the given function or
-  /// field initializer.
-  List<ir.ClosureVariable> _getDeclaredClosureVariables(ExecutableElement elm);
-
   /// Creates an access to the receiver from the current (or enclosing) method.
   ///
   /// If inside a closure class, [buildThis] will redirect access through
@@ -608,8 +604,7 @@
       ir.RunnableBody body = makeRunnableBody();
       return new ir.FunctionDefinition(
           element, state.functionParameters, body,
-          state.localConstants, defaults,
-          _getDeclaredClosureVariables(element));
+          state.localConstants, defaults);
     }
   }
 
@@ -628,8 +623,7 @@
     ir.RunnableBody body = makeRunnableBody();
     return new ir.ConstructorDefinition(
         element, state.functionParameters, body, initializers,
-        state.localConstants, defaults,
-        _getDeclaredClosureVariables(element));
+        state.localConstants, defaults);
   }
 
   /// Create a super invocation where the method name and the argument structure
@@ -1529,34 +1523,24 @@
 
 /// Shared state between DartIrBuilders within the same method.
 class DartIrBuilderSharedState {
-  /// Maps local variables to their corresponding [ClosureVariable] object.
-  final Map<Local, ir.ClosureVariable> local2closure =
-      <Local, ir.ClosureVariable>{};
+  /// Maps local variables to their corresponding [MutableVariable] object.
+  final Map<Local, ir.MutableVariable> local2mutable =
+      <Local, ir.MutableVariable>{};
 
-  /// Maps functions to the list of closure variables declared in that function.
-  final Map<ExecutableElement, List<ir.ClosureVariable>> function2closures =
-      <ExecutableElement, List<ir.ClosureVariable>>{};
+  final DartCapturedVariableInfo capturedVariables;
 
-  final DartCapturedVariableInfo closureVariables;
-
-  /// Returns the closure variables declared in the given function.
-  List<ir.ClosureVariable> getClosureList(ExecutableElement element) {
-    return function2closures.putIfAbsent(element, () => <ir.ClosureVariable>[]);
+  /// Creates a [MutableVariable] for the given local.
+  void makeMutableVariable(Local local) {
+    ir.MutableVariable variable =
+        new ir.MutableVariable(local.executableContext, local);
+    local2mutable[local] = variable;
   }
 
-  /// Creates a closure variable for the given local.
-  void makeClosureVariable(Local local) {
-    ir.ClosureVariable variable =
-        new ir.ClosureVariable(local.executableContext, local);
-    local2closure[local] = variable;
-    getClosureList(local.executableContext).add(variable);
-  }
+  /// [MutableVariable]s that should temporarily be treated as registers.
+  final Set<Local> registerizedMutableVariables = new Set<Local>();
 
-  /// Closure variables that should temporarily be treated as registers.
-  final Set<Local> registerizedClosureVariables = new Set<Local>();
-
-  DartIrBuilderSharedState(this.closureVariables) {
-    closureVariables.capturedVariables.forEach(makeClosureVariable);
+  DartIrBuilderSharedState(this.capturedVariables) {
+    capturedVariables.capturedVariables.forEach(makeMutableVariable);
   }
 }
 
@@ -1565,8 +1549,8 @@
 /// Inner functions are represented by a [FunctionDefinition] with the
 /// IR for the inner function nested inside.
 ///
-/// Captured variables are translated to ref cells (see [ClosureVariable])
-/// using [GetClosureVariable] and [SetClosureVariable].
+/// Captured variables are translated to ref cells (see [MutableVariable])
+/// using [GetMutableVariable] and [SetMutableVariable].
 class DartIrBuilder extends IrBuilder {
   final DartIrBuilderSharedState dartState;
 
@@ -1575,20 +1559,20 @@
 
   DartIrBuilder(ConstantSystem constantSystem,
                 ExecutableElement currentElement,
-                DartCapturedVariableInfo  closureVariables)
-      : dartState = new DartIrBuilderSharedState(closureVariables) {
+                DartCapturedVariableInfo capturedVariables)
+      : dartState = new DartIrBuilderSharedState(capturedVariables) {
     _init(constantSystem, currentElement);
   }
 
-  /// True if [local] should currently be accessed from a [ClosureVariable].
-  bool isInClosureVariable(Local local) {
-    return dartState.local2closure.containsKey(local) &&
-           !dartState.registerizedClosureVariables.contains(local);
+  /// True if [local] should currently be accessed from a [MutableVariable].
+  bool isInMutableVariable(Local local) {
+    return dartState.local2mutable.containsKey(local) &&
+           !dartState.registerizedMutableVariables.contains(local);
   }
 
-  /// Gets the [ClosureVariable] containing the value of [local].
-  ir.ClosureVariable getClosureVariable(Local local) {
-    return dartState.local2closure[local];
+  /// Gets the [MutableVariable] containing the value of [local].
+  ir.MutableVariable getMutableVariable(Local local) {
+    return dartState.local2mutable[local];
   }
 
   void _enterScope(ClosureScope scope) {
@@ -1603,11 +1587,11 @@
                                 List<LocalElement> loopVariables) {
     assert(scope == null);
     for (LocalElement loopVariable in loopVariables) {
-      if (dartState.local2closure.containsKey(loopVariable)) {
+      if (dartState.local2mutable.containsKey(loopVariable)) {
         // Temporarily keep the loop variable in a primitive.
         // The loop variable will be added to environment when
         // [declareLocalVariable] is called.
-        dartState.registerizedClosureVariables.add(loopVariable);
+        dartState.registerizedMutableVariables.add(loopVariable);
       }
     }
   }
@@ -1616,12 +1600,11 @@
                          List<LocalElement> loopVariables) {
     assert(scope == null);
     for (LocalElement loopVariable in loopVariables) {
-      if (dartState.local2closure.containsKey(loopVariable)) {
-        // Move from primitive into ClosureVariable.
-        dartState.registerizedClosureVariables.remove(loopVariable);
-        add(new ir.SetClosureVariable(getClosureVariable(loopVariable),
-                                      environment.lookup(loopVariable),
-                                      isDeclaration: true));
+      if (dartState.local2mutable.containsKey(loopVariable)) {
+        // Move from [Primitive] into [MutableVariable].
+        dartState.registerizedMutableVariables.remove(loopVariable);
+        add(new ir.LetMutable(getMutableVariable(loopVariable),
+                              environment.lookup(loopVariable)));
       }
     }
   }
@@ -1634,12 +1617,12 @@
     // and then the environments for the initializer and update will be
     // joined at the head of the body.
     for (LocalElement loopVariable in loopVariables) {
-      if (isInClosureVariable(loopVariable)) {
-        ir.ClosureVariable closureVariable = getClosureVariable(loopVariable);
-        ir.Primitive get = new ir.GetClosureVariable(closureVariable);
+      if (isInMutableVariable(loopVariable)) {
+        ir.MutableVariable mutableVariable = getMutableVariable(loopVariable);
+        ir.Primitive get = new ir.GetMutableVariable(mutableVariable);
         add(new ir.LetPrim(get));
         environment.update(loopVariable, get);
-        dartState.registerizedClosureVariables.add(loopVariable);
+        dartState.registerizedMutableVariables.add(loopVariable);
       }
     }
   }
@@ -1647,8 +1630,8 @@
   void _createFunctionParameter(ParameterElement parameterElement) {
     ir.Parameter parameter = new ir.Parameter(parameterElement);
     _parameters.add(parameter);
-    if (isInClosureVariable(parameterElement)) {
-      state.functionParameters.add(getClosureVariable(parameterElement));
+    if (isInMutableVariable(parameterElement)) {
+      state.functionParameters.add(getMutableVariable(parameterElement));
     } else {
       state.functionParameters.add(parameter);
       environment.extend(parameterElement, parameter);
@@ -1661,10 +1644,9 @@
     if (initialValue == null) {
       initialValue = buildNullLiteral();
     }
-    if (isInClosureVariable(variableElement)) {
-      add(new ir.SetClosureVariable(getClosureVariable(variableElement),
-                                    initialValue,
-                                    isDeclaration: true));
+    if (isInMutableVariable(variableElement)) {
+      add(new ir.LetMutable(getMutableVariable(variableElement),
+                            initialValue));
     } else {
       initialValue.useElementAsHint(variableElement);
       environment.extend(variableElement, initialValue);
@@ -1675,8 +1657,8 @@
   void declareLocalFunction(LocalFunctionElement functionElement,
                             ir.FunctionDefinition definition) {
     assert(isOpen);
-    if (isInClosureVariable(functionElement)) {
-      ir.ClosureVariable variable = getClosureVariable(functionElement);
+    if (isInMutableVariable(functionElement)) {
+      ir.MutableVariable variable = getMutableVariable(functionElement);
       add(new ir.DeclareFunction(variable, definition));
     } else {
       ir.CreateFunction prim = new ir.CreateFunction(definition);
@@ -1696,11 +1678,11 @@
   /// Create a read access of [local].
   ir.Primitive buildLocalGet(LocalElement local) {
     assert(isOpen);
-    if (isInClosureVariable(local)) {
+    if (isInMutableVariable(local)) {
       // Do not use [local] as a hint on [result]. The variable should always
       // be inlined, but the hint prevents it.
       ir.Primitive result =
-          new ir.GetClosureVariable(getClosureVariable(local));
+          new ir.GetMutableVariable(getMutableVariable(local));
       add(new ir.LetPrim(result));
       return result;
     } else {
@@ -1711,8 +1693,8 @@
   /// Create a write access to [local] with the provided [value].
   ir.Primitive buildLocalSet(LocalElement local, ir.Primitive value) {
     assert(isOpen);
-    if (isInClosureVariable(local)) {
-      add(new ir.SetClosureVariable(getClosureVariable(local), value));
+    if (isInMutableVariable(local)) {
+      add(new ir.SetMutableVariable(getMutableVariable(local), value));
     } else {
       value.useElementAsHint(local);
       environment.update(local, value);
@@ -1720,11 +1702,6 @@
     return value;
   }
 
-  List<ir.ClosureVariable> _getDeclaredClosureVariables(
-      ExecutableElement element) {
-    return dartState.getClosureList(element);
-  }
-
   ir.Primitive buildThis() {
     ir.Primitive thisPrim = new ir.This();
     add(new ir.LetPrim(thisPrim));
@@ -1928,11 +1905,6 @@
     environment.update(scope.box, newBox);
   }
 
-  List<ir.ClosureVariable> _getDeclaredClosureVariables(
-      ExecutableElement element) {
-    return <ir.ClosureVariable>[];
-  }
-
   ir.Primitive buildThis() {
     if (jsState.receiver != null) return jsState.receiver;
     ir.Primitive thisPrim = new ir.This();
diff --git a/pkg/compiler/lib/src/cps_ir/cps_ir_builder_visitor.dart b/pkg/compiler/lib/src/cps_ir/cps_ir_builder_visitor.dart
index ec796da..9eafea6 100644
--- a/pkg/compiler/lib/src/cps_ir/cps_ir_builder_visitor.dart
+++ b/pkg/compiler/lib/src/cps_ir/cps_ir_builder_visitor.dart
@@ -237,13 +237,12 @@
       ClassElement enclosingClass = element.enclosingClass;
       if (!enclosingClass.isObject) {
         ClassElement superClass = enclosingClass.superclass;
-        Selector selector =
-            new Selector.callDefaultConstructor(enclosingClass.library);
-        FunctionElement target = superClass.lookupConstructor(selector);
+        FunctionElement target = superClass.lookupDefaultConstructor();
         if (target == null) {
           compiler.internalError(superClass,
               "No default constructor available.");
         }
+        Selector selector = new Selector.callDefaultConstructor();
         result.add(irBuilder.makeSuperInitializer(target,
                                                   <ir.RunnableBody>[],
                                                   selector));
@@ -1372,9 +1371,7 @@
     // If no super() or this() was found, also call default superconstructor.
     if (!hasConstructorCall && !enclosingClass.isObject) {
       ClassElement superClass = enclosingClass.superclass;
-      Selector selector =
-          new Selector.callDefaultConstructor(enclosingClass.library);
-      FunctionElement target = superClass.lookupConstructor(selector);
+      FunctionElement target = superClass.lookupDefaultConstructor();
       if (target == null) {
         compiler.internalError(superClass, "No default constructor available.");
       }
diff --git a/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart b/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart
index 00e3252..d1f51fc 100644
--- a/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart
+++ b/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart
@@ -13,7 +13,6 @@
 import '../universe/universe.dart' show Selector, SelectorKind;
 import '../dart_types.dart' show DartType, GenericType;
 import '../cps_ir/optimizers.dart';
-import '../closure.dart' show ClosureClassElement;
 
 abstract class Node {
   /// A pointer to the parent node. Is null until set by optimization passes.
@@ -108,7 +107,7 @@
 /// Binding a value (primitive or constant): 'let val x = V in E'.  The bound
 /// value is in scope in the body.
 /// During one-pass construction a LetVal with an empty body is used to
-/// represent one-level context 'let val x = V in []'.
+/// represent the one-hole context 'let val x = V in []'.
 class LetPrim extends Expression implements InteriorNode {
   final Primitive primitive;
   Expression body;
@@ -134,7 +133,7 @@
 /// The bound continuations are in scope in the body and the continuation
 /// parameters are in scope in the respective continuation bodies.
 /// During one-pass construction a LetCont whose first continuation has an empty
-/// body is used to represent the one-level context
+/// body is used to represent the one-hole context
 /// 'let cont ... k(v) = [] ... in E'.
 class LetCont extends Expression implements InteriorNode {
   List<Continuation> continuations;
@@ -155,6 +154,30 @@
   accept(Visitor visitor) => visitor.visitLetCont(this);
 }
 
+/// Binding mutable variables.
+///
+/// let mutable v = P in E
+///
+/// [MutableVariable]s can be seen as ref cells that are not first-class
+/// values.  They are therefore not [Primitive]s and not bound by [LetPrim]
+/// to prevent unrestricted use of references to them.  During one-pass
+/// construction, a [LetMutable] with an empty body is use to represent the
+/// one-hole context 'let mutable v = P in []'.
+class LetMutable extends Expression implements InteriorNode {
+  final MutableVariable variable;
+  final Reference<Primitive> value;
+  Expression body;
+
+  LetMutable(this.variable, Primitive value)
+      : this.value = new Reference<Primitive>(value);
+
+  Expression plug(Expression expr) {
+    return body = expr;
+  }
+
+  accept(Visitor visitor) => visitor.visitLetMutable(this);
+}
+
 abstract class Invoke {
   Selector get selector;
   List<Reference<Primitive>> get arguments;
@@ -197,37 +220,70 @@
   accept(Visitor visitor) => visitor.visitInvokeStatic(this);
 }
 
+/// A [CallingConvention] codifies how arguments are matched to parameters when
+/// emitting code for a function call.
+class CallingConvention {
+  final String name;
+  const CallingConvention(this.name);
+  /// The normal way of calling a Dart function: Positional arguments are
+  /// matched with (mandatory and optional) positionals parameters from left to
+  /// right and named arguments are matched by name.
+  static const CallingConvention DART = const CallingConvention("Dart call");
+  /// Intercepted calls have an additional first argument that is the actual
+  /// receiver of the call.  See the documentation of [Interceptor] for more
+  /// information.
+  static const CallingConvention JS_INTERCEPTED =
+      const CallingConvention("intercepted JavaScript call");
+}
+
 /// Invoke a method, operator, getter, setter, or index getter/setter.
 /// Converting a method to a function object is treated as a getter invocation.
 class InvokeMethod extends Expression implements Invoke {
   Reference<Primitive> receiver;
-  final Selector selector;
+  Selector selector;
+  CallingConvention callingConvention;
   final Reference<Continuation> continuation;
   final List<Reference<Primitive>> arguments;
 
   InvokeMethod(Primitive receiver,
                Selector selector,
-               Continuation cont,
-               List<Primitive> args)
+               Continuation continuation,
+               List<Primitive> arguments)
       : this.internal(new Reference<Primitive>(receiver),
                       selector,
-                      new Reference<Continuation>(cont),
-                      _referenceList(args));
+                      new Reference<Continuation>(continuation),
+                      _referenceList(arguments));
 
   InvokeMethod.internal(this.receiver,
                         this.selector,
                         this.continuation,
-                        this.arguments) {
-    assert(selector != null);
-    assert(selector.kind == SelectorKind.CALL ||
-           selector.kind == SelectorKind.OPERATOR ||
-           (selector.kind == SelectorKind.GETTER && arguments.isEmpty) ||
-           (selector.kind == SelectorKind.SETTER && arguments.length == 1) ||
-           (selector.kind == SelectorKind.INDEX && arguments.length == 1) ||
-           (selector.kind == SelectorKind.INDEX && arguments.length == 2));
+                        this.arguments,
+                        [this.callingConvention = CallingConvention.DART]) {
+    assert(isValid);
   }
 
-  bool get isIntercepted => receiver.definition is Interceptor;
+  /// Returns whether the arguments match the selector under the given calling
+  /// convention.
+  ///
+  /// This check is designed to be used in an assert, as it also checks that the
+  /// selector, arguments, and calling convention have meaningful values.
+  bool get isValid {
+    if (selector == null || callingConvention == null) return false;
+    if (callingConvention != CallingConvention.DART &&
+        callingConvention != CallingConvention.JS_INTERCEPTED) {
+      return false;
+    }
+    int numberOfArguments =
+        callingConvention == CallingConvention.JS_INTERCEPTED
+            ? arguments.length - 1
+            : arguments.length;
+    return selector.kind == SelectorKind.CALL ||
+           selector.kind == SelectorKind.OPERATOR ||
+           (selector.kind == SelectorKind.GETTER && numberOfArguments == 0) ||
+           (selector.kind == SelectorKind.SETTER && numberOfArguments == 1) ||
+           (selector.kind == SelectorKind.INDEX && numberOfArguments == 1) ||
+           (selector.kind == SelectorKind.INDEX && numberOfArguments == 2);
+  }
 
   accept(Visitor visitor) => visitor.visitInvokeMethod(this);
 }
@@ -351,54 +407,38 @@
   accept(Visitor visitor) => visitor.visitConcatenateStrings(this);
 }
 
-/// Gets the value from a closure variable.
+/// Gets the value from a [MutableVariable].
 ///
-/// Closure variables can be seen as ref cells that are not first-class values.
-/// A [LetPrim] with a [GetClosureVariable] can then be seen as:
+/// [MutableVariable]s can be seen as ref cells that are not first-class
+/// values.  A [LetPrim] with a [GetMutableVariable] can then be seen as:
 ///
 ///   let prim p = ![variable] in [body]
 ///
-class GetClosureVariable extends Primitive {
-  final Reference<ClosureVariable> variable;
+class GetMutableVariable extends Primitive {
+  final Reference<MutableVariable> variable;
 
-  GetClosureVariable(ClosureVariable variable)
-      : this.variable = new Reference<ClosureVariable>(variable);
+  GetMutableVariable(MutableVariable variable)
+      : this.variable = new Reference<MutableVariable>(variable);
 
-  accept(Visitor visitor) => visitor.visitGetClosureVariable(this);
+  accept(Visitor visitor) => visitor.visitGetMutableVariable(this);
 }
 
-/// Assign or declare a closure variable.
+/// Assign a [MutableVariable].
 ///
-/// Closure variables can be seen as ref cells that are not first-class values.
-/// If [isDeclaration], this can seen as a let binding:
+/// [MutableVariable]s can be seen as ref cells that are not first-class
+/// values.  This can be seen as a dereferencing assignment:
 ///
-///   let [variable] = ref [value] in [body]
-///
-/// And otherwise, it can be seen as a dereferencing assignment:
-///
-///   { ![variable] := [value]; [body] }
-///
-/// Closure variables without a declaring [SetClosureVariable] are implicitly
-/// declared at the entry to the [variable]'s enclosing function.
-class SetClosureVariable extends Expression implements InteriorNode {
-  final Reference<ClosureVariable> variable;
+///   { [variable] := [value]; [body] }
+class SetMutableVariable extends Expression implements InteriorNode {
+  final Reference<MutableVariable> variable;
   final Reference<Primitive> value;
   Expression body;
 
-  /// If true, this declares a new copy of the closure variable. If so, all
-  /// uses of the closure variable must occur in the [body].
-  ///
-  /// There can be at most one declaration per closure variable. If there is no
-  /// declaration, only one copy exists (per function execution). It is best to
-  /// avoid declaring closure variables if it is not necessary.
-  final bool isDeclaration;
+  SetMutableVariable(MutableVariable variable, Primitive value)
+      : this.variable = new Reference<MutableVariable>(variable),
+        this.value = new Reference<Primitive>(value);
 
-  SetClosureVariable(ClosureVariable variable, Primitive value,
-                     {this.isDeclaration : false })
-      : this.value = new Reference<Primitive>(value),
-        this.variable = new Reference<ClosureVariable>(variable);
-
-  accept(Visitor visitor) => visitor.visitSetClosureVariable(this);
+  accept(Visitor visitor) => visitor.visitSetMutableVariable(this);
 
   Expression plug(Expression expr) {
     assert(body == null);
@@ -406,21 +446,20 @@
   }
 }
 
-/// Create a potentially recursive function and store it in a closure variable.
-/// The function can access itself using [GetClosureVariable] on [variable].
-/// There must not exist a [SetClosureVariable] to [variable].
+/// Create a potentially recursive function and store it in a [MutableVariable].
+/// The function can access itself using [GetMutableVariable] on [variable].
+/// There must not exist a [SetMutableVariable] to [variable].
 ///
 /// This can be seen as a let rec binding:
 ///
 ///   let rec [variable] = [definition] in [body]
 ///
 class DeclareFunction extends Expression implements InteriorNode {
-  final Reference<ClosureVariable> variable;
+  final MutableVariable variable;
   final FunctionDefinition definition;
   Expression body;
 
-  DeclareFunction(ClosureVariable variable, this.definition)
-      : this.variable = new Reference<ClosureVariable>(variable);
+  DeclareFunction(this.variable, this.definition);
 
   Expression plug(Expression expr) {
     assert(body == null);
@@ -634,7 +673,7 @@
   // FunctionDefinition, parameters have an index into the list of parameters
   // bound by the parent.  This gives constant-time access to the continuation
   // from the parent.
-  int parent_index;
+  int parentIndex;
 
   accept(Visitor visitor) => visitor.visitParameter(this);
 }
@@ -704,15 +743,15 @@
   bool get hasInitializer => body != null;
 }
 
-/// Identifies a closure variable.
-class ClosureVariable extends Definition {
-  /// Body of code that declares this closure variable.
+/// Identifies a mutable variable.
+class MutableVariable extends Definition {
+  /// Body of source code that declares this mutable variable.
   ExecutableElement host;
   Entity hint;
 
-  ClosureVariable(this.host, this.hint);
+  MutableVariable(this.host, this.hint);
 
-  accept(Visitor v) => v.visitClosureVariable(this);
+  accept(Visitor v) => v.visitMutableVariable(this);
 }
 
 class RunnableBody extends InteriorNode {
@@ -727,7 +766,7 @@
 class FunctionDefinition extends Node
     implements ExecutableDefinition {
   final FunctionElement element;
-  /// Mixed list of [Parameter]s and [ClosureVariable]s.
+  /// Mixed list of [Parameter]s and [MutableVariable]s.
   final List<Definition> parameters;
   final RunnableBody body;
   final List<ConstDeclaration> localConstants;
@@ -735,22 +774,17 @@
   /// Values for optional parameters.
   final List<ConstantExpression> defaultParameterValues;
 
-  /// Closure variables declared by this function.
-  final List<ClosureVariable> closureVariables;
-
   FunctionDefinition(this.element,
       this.parameters,
       this.body,
       this.localConstants,
-      this.defaultParameterValues,
-      this.closureVariables);
+      this.defaultParameterValues);
 
   FunctionDefinition.abstract(this.element,
                               this.parameters,
                               this.defaultParameterValues)
       : body = null,
-        localConstants = const <ConstDeclaration>[],
-        closureVariables = const <ClosureVariable>[];
+        localConstants = const <ConstDeclaration>[];
 
   accept(Visitor visitor) => visitor.visitFunctionDefinition(this);
   applyPass(Pass pass) => pass.rewriteFunctionDefinition(this);
@@ -787,10 +821,9 @@
                         RunnableBody body,
                         this.initializers,
                         List<ConstDeclaration> localConstants,
-                        List<ConstantExpression> defaultParameterValues,
-                        List<ClosureVariable> closureVariables)
+                        List<ConstantExpression> defaultParameterValues)
       : super(element, parameters, body, localConstants,
-              defaultParameterValues, closureVariables);
+              defaultParameterValues);
 
   // 'Abstract' here means "has no body" and is used to represent external
   // constructors.
@@ -836,6 +869,7 @@
   // Expressions.
   T visitLetPrim(LetPrim node) => visitExpression(node);
   T visitLetCont(LetCont node) => visitExpression(node);
+  T visitLetMutable(LetMutable node) => visitExpression(node);
   T visitInvokeStatic(InvokeStatic node) => visitExpression(node);
   T visitInvokeContinuation(InvokeContinuation node) => visitExpression(node);
   T visitInvokeMethod(InvokeMethod node) => visitExpression(node);
@@ -844,7 +878,7 @@
   T visitConcatenateStrings(ConcatenateStrings node) => visitExpression(node);
   T visitBranch(Branch node) => visitExpression(node);
   T visitTypeOperator(TypeOperator node) => visitExpression(node);
-  T visitSetClosureVariable(SetClosureVariable node) => visitExpression(node);
+  T visitSetMutableVariable(SetMutableVariable node) => visitExpression(node);
   T visitDeclareFunction(DeclareFunction node) => visitExpression(node);
   T visitSetField(SetField node) => visitExpression(node);
 
@@ -855,10 +889,10 @@
   T visitThis(This node) => visitPrimitive(node);
   T visitReifyTypeVar(ReifyTypeVar node) => visitPrimitive(node);
   T visitCreateFunction(CreateFunction node) => visitPrimitive(node);
-  T visitGetClosureVariable(GetClosureVariable node) => visitPrimitive(node);
+  T visitGetMutableVariable(GetMutableVariable node) => visitPrimitive(node);
   T visitParameter(Parameter node) => visitPrimitive(node);
   T visitContinuation(Continuation node) => visitDefinition(node);
-  T visitClosureVariable(ClosureVariable node) => visitDefinition(node);
+  T visitMutableVariable(MutableVariable node) => visitDefinition(node);
   T visitGetField(GetField node) => visitDefinition(node);
   T visitCreateBox(CreateBox node) => visitDefinition(node);
   T visitCreateInstance(CreateInstance node) => visitDefinition(node);
@@ -947,6 +981,14 @@
     visit(node.body);
   }
 
+  processLetMutable(LetMutable node) {}
+  visitLetMutable(LetMutable node) {
+    processLetMutable(node);
+    visit(node.variable);
+    processReference(node.value);
+    visit(node.body);
+  }
+
   processInvokeStatic(InvokeStatic node) {}
   visitInvokeStatic(InvokeStatic node) {
     processInvokeStatic(node);
@@ -1006,9 +1048,10 @@
     processReference(node.receiver);
   }
 
-  processSetClosureVariable(SetClosureVariable node) {}
-  visitSetClosureVariable(SetClosureVariable node) {
-    processSetClosureVariable(node);
+  processSetMutableVariable(SetMutableVariable node) {}
+  visitSetMutableVariable(SetMutableVariable node) {
+    processSetMutableVariable(node);
+    processReference(node.variable);
     processReference(node.value);
     visit(node.body);
   }
@@ -1016,6 +1059,7 @@
   processDeclareFunction(DeclareFunction node) {}
   visitDeclareFunction(DeclareFunction node) {
     processDeclareFunction(node);
+    visit(node.variable);
     visit(node.definition);
     visit(node.body);
   }
@@ -1052,14 +1096,14 @@
     visit(node.definition);
   }
 
-  processClosureVariable(node) {}
-  visitClosureVariable(ClosureVariable node) {
-    processClosureVariable(node);
+  processMutableVariable(node) {}
+  visitMutableVariable(MutableVariable node) {
+    processMutableVariable(node);
   }
 
-  processGetClosureVariable(GetClosureVariable node) {}
-  visitGetClosureVariable(GetClosureVariable node) {
-    processGetClosureVariable(node);
+  processGetMutableVariable(GetMutableVariable node) {}
+  visitGetMutableVariable(GetMutableVariable node) {
+    processGetMutableVariable(node);
   }
 
   processParameter(Parameter node) {}
@@ -1231,6 +1275,11 @@
     visit(node.body);
   }
 
+  void visitLetMutable(LetMutable node) {
+    visit(node.body);
+    visitReference(node.value);
+  }
+
   void visitInvokeStatic(InvokeStatic node) {
     node.arguments.forEach(visitReference);
   }
@@ -1289,10 +1338,10 @@
     new RegisterAllocator().visit(node.definition);
   }
 
-  void visitGetClosureVariable(GetClosureVariable node) {
+  void visitGetMutableVariable(GetMutableVariable node) {
   }
 
-  void visitSetClosureVariable(SetClosureVariable node) {
+  void visitSetMutableVariable(SetMutableVariable node) {
     visit(node.body);
     visitReference(node.value);
   }
diff --git a/pkg/compiler/lib/src/cps_ir/cps_ir_nodes_sexpr.dart b/pkg/compiler/lib/src/cps_ir/cps_ir_nodes_sexpr.dart
index a23b683..d5000f1 100644
--- a/pkg/compiler/lib/src/cps_ir/cps_ir_nodes_sexpr.dart
+++ b/pkg/compiler/lib/src/cps_ir/cps_ir_nodes_sexpr.dart
@@ -34,8 +34,8 @@
     return namer.nameParameter(node);
   }
 
-  String visitClosureVariable(ClosureVariable node) {
-    return namer.getName(node);
+  String visitMutableVariable(MutableVariable node) {
+    return namer.nameMutableVariable(node);
   }
 
   /// Main entry point for creating a [String] from a [Node].  All recursive
@@ -48,12 +48,10 @@
   String visitFunctionDefinition(FunctionDefinition node) {
     String name = node.element.name;
     namer.setReturnContinuation(node.body.returnContinuation);
-    String closureVariables =
-        node.closureVariables.map(namer.nameClosureVariable).join(' ');
     String parameters = node.parameters.map(visit).join(' ');
     String body = indentBlock(() => visit(node.body.body));
-    return '$indentation(FunctionDefinition $name ($parameters) return'
-        ' ($closureVariables)\n$body)';
+    return '$indentation(FunctionDefinition $name ($parameters) return\n'
+        '$body)';
   }
 
   String visitFieldDefinition(FieldDefinition node) {
@@ -103,6 +101,13 @@
     return '$indentation($LetCont ($conts)\n$body)';
   }
 
+  String visitLetMutable(LetMutable node) {
+    String name = visit(node.variable);
+    String value = access(node.value);
+    String body = indentBlock(() => visit(node.body));
+    return '$indentation(LetMutable ($name $value)\n$body)';
+  }
+
   String formatArguments(Invoke node) {
     int positionalArgumentCount = node.selector.positionalArgumentCount;
     List<String> args = new List<String>();
@@ -196,14 +201,14 @@
     return '(Unexpected Continuation)';
   }
 
-  String visitGetClosureVariable(GetClosureVariable node) {
-    return '(GetClosureVariable ${visit(node.variable.definition)})';
+  String visitGetMutableVariable(GetMutableVariable node) {
+    return '(GetMutableVariable ${access(node.variable)})';
   }
 
-  String visitSetClosureVariable(SetClosureVariable node) {
+  String visitSetMutableVariable(SetMutableVariable node) {
     String value = access(node.value);
     String body = indentBlock(() => visit(node.body));
-    return '$indentation(SetClosureVariable ${visit(node.variable.definition)} '
+    return '$indentation(SetMutableVariable ${access(node.variable)} '
            '$value\n$body)';
   }
 
@@ -226,9 +231,9 @@
   }
 
   String visitDeclareFunction(DeclareFunction node) {
+    String name = visit(node.variable);
     String function = indentBlock(() => visit(node.definition));
     String body = indentBlock(() => visit(node.body));
-    String name = namer.getName(node.variable.definition);
     return '$indentation(DeclareFunction $name =\n'
            '$function in\n'
            '$body)';
@@ -249,7 +254,7 @@
 
   String visitGetField(GetField node) {
     String object = access(node.object);
-    String field = node.field.toString();
+    String field = node.field.name;
     return '(GetField $object $field)';
   }
 
@@ -270,7 +275,7 @@
   }
 
   String visitInterceptor(Interceptor node) {
-    return '(Interceptor ${node.input})';
+    return '(Interceptor ${access(node.input)})';
   }
 }
 
@@ -348,7 +353,7 @@
     return _names[parameter] = parameter.hint.name;
   }
 
-  String nameClosureVariable(ClosureVariable variable) {
+  String nameMutableVariable(MutableVariable variable) {
     assert(!_names.containsKey(variable));
     return _names[variable] = variable.hint.name;
   }
diff --git a/pkg/compiler/lib/src/cps_ir/cps_ir_tracer.dart b/pkg/compiler/lib/src/cps_ir/cps_ir_tracer.dart
index 23e6b3b..2fc8597 100644
--- a/pkg/compiler/lib/src/cps_ir/cps_ir_tracer.dart
+++ b/pkg/compiler/lib/src/cps_ir/cps_ir_tracer.dart
@@ -120,6 +120,12 @@
     visit(node.body);
   }
 
+  visitLetMutable(cps_ir.LetMutable node) {
+    String id = names.name(node.variable);
+    printStmt(id, "${node.runtimeType} $id = ${formatReference(node.value)}");
+    visit(node.body);
+  }
+
   visitInvokeStatic(cps_ir.InvokeStatic node) {
     String dummy = names.name(node);
     String callName = node.selector.name;
@@ -208,17 +214,17 @@
     printStmt(dummy, "Branch $condition ($trueCont, $falseCont)");
   }
 
-  visitSetClosureVariable(cps_ir.SetClosureVariable node) {
+  visitSetMutableVariable(cps_ir.SetMutableVariable node) {
     String dummy = names.name(node);
     String variable = names.name(node.variable.definition);
     String value = formatReference(node.value);
-    printStmt(dummy, 'SetClosureVariable $variable = $value');
+    printStmt(dummy, '${node.runtimeType} $variable := $value');
     visit(node.body);
   }
 
   visitDeclareFunction(cps_ir.DeclareFunction node) {
     String dummy = names.name(node);
-    String variable = names.name(node.variable.definition);
+    String variable = names.name(node.variable);
     printStmt(dummy, 'DeclareFunction $variable');
     visit(node.body);
   }
@@ -242,8 +248,8 @@
     return "Parameter ${names.name(node)}";
   }
 
-  visitClosureVariable(cps_ir.ClosureVariable node) {
-    return "ClosureVariable ${names.name(node)}";
+  visitMutableVariable(cps_ir.MutableVariable node) {
+    return "${node.runtimeType} ${names.name(node)}";
   }
 
   visitContinuation(cps_ir.Continuation node) {
@@ -301,9 +307,9 @@
     return "CreateFunction ${node.definition.element.name}";
   }
 
-  visitGetClosureVariable(cps_ir.GetClosureVariable node) {
+  visitGetMutableVariable(cps_ir.GetMutableVariable node) {
     String variable = names.name(node.variable.definition);
-    return 'GetClosureVariable $variable';
+    return '${node.runtimeType} $variable';
   }
 
   visitRunnableBody(cps_ir.RunnableBody node) {}
@@ -337,7 +343,7 @@
     if (x is cps_ir.Parameter) return 'r';
     if (x is cps_ir.Continuation || x is cps_ir.FunctionDefinition) return 'B';
     if (x is cps_ir.Primitive) return 'v';
-    if (x is cps_ir.ClosureVariable) return 'c';
+    if (x is cps_ir.MutableVariable) return 'c';
     return 'x';
   }
 
@@ -456,7 +462,7 @@
     addEdgeToContinuation(exp.continuation);
   }
 
-  visitSetClosureVariable(cps_ir.SetClosureVariable exp) {
+  visitSetMutableVariable(cps_ir.SetMutableVariable exp) {
     visit(exp.body);
   }
 
diff --git a/pkg/compiler/lib/src/cps_ir/shrinking_reductions.dart b/pkg/compiler/lib/src/cps_ir/shrinking_reductions.dart
index e161922..61a72fa 100644
--- a/pkg/compiler/lib/src/cps_ir/shrinking_reductions.dart
+++ b/pkg/compiler/lib/src/cps_ir/shrinking_reductions.dart
@@ -200,7 +200,7 @@
 
     Parameter parameter = task.node;
     Continuation continuation = parameter.parent;
-    int index = parameter.parent_index;
+    int index = parameter.parentIndex;
 
     // Remove the index'th argument from each invocation.
     Reference<Continuation> current = continuation.firstRef;
@@ -230,7 +230,7 @@
     for (int i = index; i < parameters.length - 1; ++i) {
       Parameter p = parameters[i + 1];
       parameters[i] = p;
-      p.parent_index = i;
+      p.parentIndex = i;
     }
     parameters.removeLast();
 
@@ -468,7 +468,7 @@
     int index = 0;
     node.parameters.forEach((Definition parameter) {
       parameter.parent = node;
-      if (parameter is Parameter) parameter.parent_index = index++;
+      if (parameter is Parameter) parameter.parentIndex = index++;
     });
   }
 
@@ -480,9 +480,9 @@
   processConstructorDefinition(ConstructorDefinition node) {
     node.body.parent = node;
     int index = 0;
-    node.parameters.forEach((Parameter parameter) {
+    node.parameters.forEach((Definition parameter) {
       parameter.parent = node;
-      parameter.parent_index = index++;
+      if (parameter is Parameter) parameter.parentIndex = index++;
     });
     node.initializers.forEach((Initializer i) => i.parent = node);
   }
@@ -512,6 +512,12 @@
     node.body.parent = node;
   }
 
+  processLetMutable(LetMutable node) {
+    node.variable.parent = node;
+    node.value.parent = node;
+    node.body.parent = node;
+  }
+
   processInvokeStatic(InvokeStatic node) {
     node.arguments.forEach((Reference ref) => ref.parent = node);
     node.continuation.parent = node;
@@ -555,12 +561,14 @@
     node.receiver.parent = node;
   }
 
-  processSetClosureVariable(SetClosureVariable node) {
+  processSetMutableVariable(SetMutableVariable node) {
+    node.variable.parent = node;
     node.body.parent = node;
     node.value.parent = node;
   }
 
   processDeclareFunction(DeclareFunction node) {
+    node.variable.parent = node;
     node.definition.parent = node;
     node.body.parent = node;
   }
@@ -587,7 +595,7 @@
     int index = 0;
     node.parameters.forEach((Parameter parameter) {
       parameter.parent = node;
-      parameter.parent_index = index++;
+      parameter.parentIndex = index++;
     });
   }
 
@@ -618,6 +626,10 @@
     node.object.parent = node;
   }
 
+  processGetMutableVariable(GetMutableVariable node) {
+    node.variable.parent = node;
+  }
+
   processCreateInstance(CreateInstance node) {
     node.arguments.forEach((Reference ref) => ref.parent = node);
   }
diff --git a/pkg/compiler/lib/src/cps_ir/type_propagation.dart b/pkg/compiler/lib/src/cps_ir/type_propagation.dart
index c6dd7ab..c90f777 100644
--- a/pkg/compiler/lib/src/cps_ir/type_propagation.dart
+++ b/pkg/compiler/lib/src/cps_ir/type_propagation.dart
@@ -415,7 +415,8 @@
 
   void visitNode(Node node) {
     internalError(NO_LOCATION_SPANNABLE,
-        "_TypePropagationVisitor is stale, add missing visit overrides");
+        "_TypePropagationVisitor is stale,"
+        " add missing visit overrides ($node)");
   }
 
   void visitRunnableBody(RunnableBody node) {
@@ -445,6 +446,11 @@
     setReachable(node.body);
   }
 
+  void visitLetMutable(LetMutable node) {
+    setValue(node.variable, getValue(node.value.definition));
+    setReachable(node.body);
+  }
+
   void visitInvokeStatic(InvokeStatic node) {
     Continuation cont = node.continuation.definition;
     setReachable(cont);
@@ -667,7 +673,8 @@
     }
   }
 
-  void visitSetClosureVariable(SetClosureVariable node) {
+  void visitSetMutableVariable(SetMutableVariable node) {
+    setValue(node.variable.definition, getValue(node.value.definition));
     setReachable(node.body);
   }
 
@@ -710,11 +717,28 @@
     setValue(node, constantValue(constant, typeSystem.functionType));
   }
 
-  void visitGetClosureVariable(GetClosureVariable node) {
-    setValue(node, nonConst());
+  void visitGetMutableVariable(GetMutableVariable node) {
+    setValue(node, getValue(node.variable.definition));
   }
 
-  void visitClosureVariable(ClosureVariable node) {
+  void visitMutableVariable(MutableVariable node) {
+    // [MutableVariable]s are bound either as parameters to
+    // [FunctionDefinition]s, by [LetMutable], or by [DeclareFunction].
+    if (node.parent is FunctionDefinition) {
+      // Just like immutable parameters, the values of mutable parameters are
+      // never constant.
+      // TODO(karlklose): remove reference to the element model.
+      Entity source = node.hint;
+      T type = (source is ParameterElement)
+          ? typeSystem.getParameterType(source)
+          : typeSystem.dynamicType;
+      setValue(node, nonConst(type));
+    } else if (node.parent is LetMutable || node.parent is DeclareFunction) {
+      // Mutable values bound by LetMutable or DeclareFunction could have
+      // known values.
+    } else {
+      internalError(node.hint, "Unexpected parent of MutableVariable");
+    }
   }
 
   void visitParameter(Parameter node) {
@@ -723,24 +747,18 @@
     T type = (source is ParameterElement) ? typeSystem.getParameterType(source)
         : typeSystem.dynamicType;
     if (node.parent is FunctionDefinition) {
-      // Functions may escape and thus their parameters must be initialized to
-      // NonConst.
+      // Functions may escape and thus their parameters must be non-constant.
       setValue(node, nonConst(type));
     } else if (node.parent is Continuation) {
-      // Continuations on the other hand are local, and parameters are
-      // initialized to Unknown.
-      setValue(node, unknown());
+      // Continuations on the other hand are local, and parameters can have
+      // some other abstract value than non-constant.
     } else {
       internalError(node.hint, "Unexpected parent of Parameter");
     }
   }
 
   void visitContinuation(Continuation node) {
-    node.parameters.forEach((Parameter p) {
-      // TODO(karlklose): join parameter types from use sites.
-      setValue(p, unknown());
-      defWorkset.add(p);
-    });
+    node.parameters.forEach(visit);
 
     if (node.body != null) {
       setReachable(node.body);
diff --git a/pkg/compiler/lib/src/dart2js.dart b/pkg/compiler/lib/src/dart2js.dart
index fc3b766..4aad6af 100644
--- a/pkg/compiler/lib/src/dart2js.dart
+++ b/pkg/compiler/lib/src/dart2js.dart
@@ -341,7 +341,12 @@
     new OptionHandler('--csp', passThrough),
     new OptionHandler('--enable-experimental-mirrors', passThrough),
     new OptionHandler('--enable-async', setEnableAsync),
-    new OptionHandler('--enable-enum', passThrough),
+    new OptionHandler('--enable-enum', (_) {
+      diagnosticHandler.info(
+          "Option '--enable-enum' is no longer needed. "
+          "Enums are supported by default.",
+          api.Diagnostic.HINT);
+    }),
     new OptionHandler('--allow-native-extensions', setAllowNativeExtensions),
     new OptionHandler('--generate-code-with-compile-time-errors', passThrough),
 
@@ -405,7 +410,7 @@
   }
   if (analyzeAll) analyzeOnly = true;
   if (!analyzeOnly) {
-    if (enableAsyncAwait) {
+    if (enableAsyncAwait && outputLanguage != OUTPUT_LANGUAGE_DART) {
       helpAndFail("Option '--enable-async' is currently only supported in "
                   "combination with the '--analyze-only' option.");
     }
diff --git a/pkg/compiler/lib/src/dart2js_stress.dart b/pkg/compiler/lib/src/dart2js_stress.dart
index fce57f2..7daedea 100644
--- a/pkg/compiler/lib/src/dart2js_stress.dart
+++ b/pkg/compiler/lib/src/dart2js_stress.dart
@@ -7,8 +7,6 @@
 
 const ITERATIONS_FLAG_PREFIX = "--iterations=";
 void main(List<String> args) {
-  print("Reminder: for best performance, "
-        "dart2js should be run with the VM flag --heap_growth_rate=512");
   Stopwatch sw = new Stopwatch();
   int count = 0;
   int maxCount = null;
diff --git a/pkg/compiler/lib/src/dart_backend/backend.dart b/pkg/compiler/lib/src/dart_backend/backend.dart
index 18cfaae..90baf1b 100644
--- a/pkg/compiler/lib/src/dart_backend/backend.dart
+++ b/pkg/compiler/lib/src/dart_backend/backend.dart
@@ -233,7 +233,7 @@
         computeElementAst: computeElementAst,
         shouldOutput: shouldOutput,
         isSafeToRemoveTypeDeclarations: isSafeToRemoveTypeDeclarations,
-        sortElements: sortElements,
+        sortElements: Elements.sortedByPosition,
         mirrorRenamer: mirrorRenamer,
         mainFunction: compiler.mainFunction,
         outputUri: compiler.outputUri);
@@ -468,9 +468,6 @@
   return compareBy((e) => e.position.charOffset)(e0, e1);
 }
 
-List<Element> sortElements(Iterable<Element> elements) =>
-    sorted(elements, compareElements);
-
 /// [ConstantCompilerTask] for compilation of constants for the Dart backend.
 ///
 /// Since this task needs no distinction between frontend and backend constants
diff --git a/pkg/compiler/lib/src/dart_backend/backend_ast_to_frontend_ast.dart b/pkg/compiler/lib/src/dart_backend/backend_ast_to_frontend_ast.dart
index c2381f6..373ccfd 100644
--- a/pkg/compiler/lib/src/dart_backend/backend_ast_to_frontend_ast.dart
+++ b/pkg/compiler/lib/src/dart_backend/backend_ast_to_frontend_ast.dart
@@ -139,6 +139,7 @@
   final Token withToken = makeIdToken('with');
   final Token implementsToken = makeIdToken('implements');
   final Token typedefToken = makeIdToken('typedef');
+  final Token enumToken = makeIdToken('enum');
 
   static tree.Identifier makeIdentifier(String name) {
     return new tree.Identifier(
@@ -1060,6 +1061,8 @@
   tree.Node makeNodeForClassElement(elements.ClassElement cls) {
     if (cls.isMixinApplication) {
       return makeNamedMixinApplication(cls);
+    } else if (cls.isEnumClass) {
+      return makeEnum(cls);
     } else {
       return makeClassNode(cls);
     }
@@ -1181,6 +1184,14 @@
         interfaces, classToken, semicolon);
   }
 
+  tree.Enum makeEnum(elements.EnumClassElement cls) {
+    return new tree.Enum(
+        enumToken,
+        makeIdentifier(cls.name),
+        makeList(',', cls.enumValues.map((e) => makeIdentifier(e.name)),
+                 open: openBrace, close: closeBrace));
+  }
+
   /// Creates a [tree.ClassNode] node for [cls].
   tree.ClassNode makeClassNode(elements.ClassElement cls) {
     assert(dart2js.invariant(cls, !cls.isUnnamedMixinApplication,
diff --git a/pkg/compiler/lib/src/dart_backend/dart_backend.dart b/pkg/compiler/lib/src/dart_backend/dart_backend.dart
index 32be177..e498d5a 100644
--- a/pkg/compiler/lib/src/dart_backend/dart_backend.dart
+++ b/pkg/compiler/lib/src/dart_backend/dart_backend.dart
@@ -23,7 +23,6 @@
 import 'backend_ast_emitter.dart' as backend_ast_emitter;
 import 'backend_ast_nodes.dart' as backend_ast;
 import 'backend_ast_to_frontend_ast.dart' as backend2frontend;
-import '../tracer.dart';
 import '../../compiler.dart' show CompilerOutputProvider;
 
 import '../scanner/scannerlib.dart' show StringToken,
@@ -32,7 +31,6 @@
                                          CLOSE_PAREN_INFO,
                                          SEMICOLON_INFO,
                                          IDENTIFIER_INFO;
-import '../js_backend/codegen/glue.dart';
 
 part 'backend.dart';
 part 'renamer.dart';
diff --git a/pkg/compiler/lib/src/dart_backend/outputter.dart b/pkg/compiler/lib/src/dart_backend/outputter.dart
index 45da8e9..07d5a4e 100644
--- a/pkg/compiler/lib/src/dart_backend/outputter.dart
+++ b/pkg/compiler/lib/src/dart_backend/outputter.dart
@@ -96,7 +96,8 @@
       };
     }
 
-    libraryInfo = LibraryInfo.processLibraries(libraries, resolvedElements);
+    libraryInfo = LibraryInfo.processLibraries(
+        listener, libraries, resolvedElements);
 
     elementInfo = ElementInfoProcessor.createElementInfo(
         instantiatedClasses,
@@ -162,7 +163,7 @@
     makePlaceholders(element) {
       collector.collect(element);
 
-      if (element.isClass) {
+      if (element.isClass && !element.isEnumClass) {
         elementInfo.classMembers[element].forEach(makePlaceholders);
       }
     }
@@ -228,6 +229,7 @@
               this.userLibraries);
 
   static LibraryInfo processLibraries(
+      DiagnosticListener listener,
       Iterable<LibraryElement> libraries,
       Iterable<AstElement> resolvedElements) {
     Set<String> fixedStaticNames = new Set<String>();
@@ -276,17 +278,37 @@
         }
       }
     }
+
+    // Map to keep track of names of enum classes. Since these cannot be renamed
+    // we ensure that they are unique.
+    Map<String, ClassElement> enumClassMap = <String, ClassElement>{};
+
     // As of now names of named optionals are not renamed. Therefore add all
     // field names used as named optionals into [fixedMemberNames].
     for (final element in resolvedElements) {
       if (!element.isConstructor) continue;
-      Link<Element> optionalParameters =
-          element.functionSignature.optionalParameters;
-      for (final optional in optionalParameters) {
-        if (!optional.isInitializingFormal) continue;
-        fixedDynamicNames.add(optional.name);
+      for (ParameterElement parameter in element.parameters) {
+        if (parameter.isInitializingFormal && parameter.isNamed) {
+          fixedDynamicNames.add(parameter.name);
+        }
+      }
+      ClassElement cls = element.enclosingClass;
+      if (cls != null && cls.isEnumClass) {
+        fixedDynamicNames.add('index');
+
+        ClassElement existingEnumClass =
+            enumClassMap.putIfAbsent(cls.name, () => cls);
+        if (existingEnumClass != cls) {
+          listener.reportError(cls, MessageKind.GENERIC,
+              {'text': "Duplicate enum names are not supported in dart2dart."});
+          listener.reportInfo(existingEnumClass, MessageKind.GENERIC,
+              {'text': "This is the other declaration of '${cls.name}'."});
+        }
       }
     }
+
+    fixedStaticNames.addAll(enumClassMap.keys);
+
     // The VM will automatically invoke the call method of objects
     // that are invoked as functions. Make sure to not rename that.
     fixedDynamicNames.add('call');
@@ -409,18 +431,17 @@
   }
 
   void addMember(element) {
-    ElementAst elementAst = parseElementAst(element);
     if (element.isClassMember) {
       ClassElement enclosingClass = element.enclosingClass;
       assert(enclosingClass.isClass);
-      assert(enclosingClass.isTopLevel);
       assert(shouldOutput(enclosingClass));
       addClass(enclosingClass);
       classMembers[enclosingClass].add(element);
-      processElement(element, elementAst);
+      if (enclosingClass.isEnumClass) return;
+      processElement(element, parseElementAst(element));
     } else {
       if (element.isTopLevel) {
-        addTopLevel(element, elementAst);
+        addTopLevel(element, parseElementAst(element));
       }
     }
   }
@@ -448,12 +469,16 @@
        bool enableMinification: false}) {
     for (Element element in elementInfo.topLevelElements) {
       topLevelNodes.add(elementInfo.elementAsts[element].ast);
-      if (element.isClass && !element.isMixinApplication) {
+      if (element.isClass) {
+        ClassElement cls = element;
+        if (cls.isMixinApplication || cls.isEnumClass) {
+          continue;
+        }
         final members = <Node>[];
-        for (Element member in elementInfo.classMembers[element]) {
+        for (Element member in elementInfo.classMembers[cls]) {
           members.add(elementInfo.elementAsts[member].ast);
         }
-        memberNodes[elementInfo.elementAsts[element].ast] = members;
+        memberNodes[elementInfo.elementAsts[cls].ast] = members;
       }
     }
 
diff --git a/pkg/compiler/lib/src/dart_backend/placeholder_collector.dart b/pkg/compiler/lib/src/dart_backend/placeholder_collector.dart
index 7b69462..9f9a2b8 100644
--- a/pkg/compiler/lib/src/dart_backend/placeholder_collector.dart
+++ b/pkg/compiler/lib/src/dart_backend/placeholder_collector.dart
@@ -189,7 +189,6 @@
       FunctionElement element, FunctionExpression node) {
     if (element.isConstructor) {
       ConstructorElement constructor = element;
-      DartType type = element.enclosingClass.thisType.asRaw();
       tryMakeConstructorPlaceholder(node.name, element);
       RedirectingFactoryBody bodyAsRedirectingFactoryBody =
           node.body.asRedirectingFactoryBody();
@@ -197,7 +196,6 @@
         // Factory redirection.
         FunctionElement redirectTarget = constructor.immediateRedirectionTarget;
         assert(redirectTarget != null && redirectTarget != element);
-        type = redirectTarget.enclosingClass.thisType.asRaw();
         tryMakeConstructorPlaceholder(
             bodyAsRedirectingFactoryBody.constructorReference,
             redirectTarget);
@@ -345,6 +343,14 @@
     if (library.isPlatformLibrary && !element.isTopLevel) {
       return;
     }
+
+    ClassElement cls = element.enclosingClass;
+    if (cls != null && cls.isEnumClass) {
+      // Enums and enum values cannot be changed, since the semantics of
+      // `toString` is defined by the names of the declarations.
+      return;
+    }
+
     if (element.isGetter || element.isSetter) {
       element = (element as FunctionElement).abstractField;
     }
diff --git a/pkg/compiler/lib/src/dart_types.dart b/pkg/compiler/lib/src/dart_types.dart
index 5a60a72..713cbc1 100644
--- a/pkg/compiler/lib/src/dart_types.dart
+++ b/pkg/compiler/lib/src/dart_types.dart
@@ -218,7 +218,7 @@
 
   DartType unalias(Compiler compiler) => this;
 
-  DartType get typeVariableOccurrence => this;
+  TypeVariableType get typeVariableOccurrence => this;
 
   void forEachTypeVariable(f(TypeVariableType variable)) {
     f(this);
@@ -661,7 +661,7 @@
 
   DartType unalias(Compiler compiler) => this;
 
-  DartType get typeVariableOccurrence {
+  TypeVariableType get typeVariableOccurrence {
     TypeVariableType typeVariableType = returnType.typeVariableOccurrence;
     if (typeVariableType != null) return typeVariableType;
 
diff --git a/pkg/compiler/lib/src/elements/elements.dart b/pkg/compiler/lib/src/elements/elements.dart
index c676422..a055e95 100644
--- a/pkg/compiler/lib/src/elements/elements.dart
+++ b/pkg/compiler/lib/src/elements/elements.dart
@@ -349,6 +349,8 @@
   Element get enclosingClassOrCompilationUnit;
   Element get outermostEnclosingMemberOrTopLevel;
 
+  // TODO(johnniwinther): Replace uses of this with [enclosingClass] when
+  // [ClosureClassElement] has been removed.
   /// The enclosing class that defines the type environment for this element.
   ClassElement get contextClass;
 
@@ -1053,6 +1055,12 @@
 
   /// The function on which this parameter is declared.
   FunctionElement get functionDeclaration;
+
+  /// `true` if this parameter is named.
+  bool get isNamed;
+
+  /// `true` if this parameter is optional.
+  bool get isOptional;
 }
 
 /// A formal parameter on a function or constructor that introduces a local
@@ -1133,6 +1141,9 @@
 
   bool get hasFunctionSignature;
 
+  /// The parameters of this functions.
+  List<ParameterElement> get parameters;
+
   /// The type of this function.
   FunctionType get type;
 
@@ -1374,11 +1385,8 @@
   Element lookupSuperMemberInLibrary(String memberName,
                                      LibraryElement library);
 
-  Element validateConstructorLookupResults(Selector selector,
-                                           Element result,
-                                           Element noMatch(Element));
-
-  Element lookupConstructor(Selector selector, [Element noMatch(Element)]);
+  ConstructorElement lookupDefaultConstructor();
+  ConstructorElement lookupConstructor(String name);
 
   void forEachMember(void f(ClassElement enclosingClass, Element member),
                      {bool includeBackendMembers: false,
diff --git a/pkg/compiler/lib/src/elements/modelx.dart b/pkg/compiler/lib/src/elements/modelx.dart
index 0531a73..caa87de 100644
--- a/pkg/compiler/lib/src/elements/modelx.dart
+++ b/pkg/compiler/lib/src/elements/modelx.dart
@@ -299,6 +299,7 @@
   get type => unsupported();
   get cachedNode => unsupported();
   get functionSignature => unsupported();
+  get parameters => unsupported();
   get patch => null;
   get origin => this;
   get immediateRedirectionTarget => unsupported();
@@ -1358,7 +1359,7 @@
 
   ExecutableElement get executableContext => enclosingElement;
 
-  ExecutableElement get memberContext => executableContext.memberContext;
+  MemberElement get memberContext => executableContext.memberContext;
 
   bool get isLocal => true;
 }
@@ -1532,12 +1533,16 @@
 abstract class ParameterElementX extends FormalElementX
   with PatchMixin<ParameterElement> implements ParameterElement {
   final Expression initializer;
+  final bool isOptional;
+  final bool isNamed;
 
   ParameterElementX(ElementKind elementKind,
                     FunctionElement functionDeclaration,
                     VariableDefinitions definitions,
                     Identifier identifier,
-                    this.initializer)
+                    this.initializer,
+                    {this.isOptional: false,
+                     this.isNamed: false})
       : super(elementKind, functionDeclaration, definitions, identifier);
 
   FunctionElement get functionDeclaration => enclosingElement;
@@ -1553,12 +1558,17 @@
 
 class LocalParameterElementX extends ParameterElementX
     implements LocalParameterElement {
+
+
   LocalParameterElementX(FunctionElement functionDeclaration,
                          VariableDefinitions definitions,
                          Identifier identifier,
-                         Expression initializer)
+                         Expression initializer,
+                         {bool isOptional: false,
+                          bool isNamed: false})
       : super(ElementKind.PARAMETER, functionDeclaration,
-              definitions, identifier, initializer);
+              definitions, identifier, initializer,
+              isOptional: isOptional, isNamed: isNamed);
 }
 
 /// Parameters in constructors that directly initialize fields. For example:
@@ -1571,9 +1581,12 @@
                              VariableDefinitions variables,
                              Identifier identifier,
                              Expression initializer,
-                             this.fieldElement)
+                             this.fieldElement,
+                             {bool isOptional: false,
+                              bool isNamed: false})
       : super(ElementKind.INITIALIZING_FORMAL, constructorDeclaration,
-              variables, identifier, initializer);
+              variables, identifier, initializer,
+              isOptional: isOptional, isNamed: isNamed);
 
   accept(ElementVisitor visitor) => visitor.visitFieldParameterElement(this);
 
@@ -1806,6 +1819,14 @@
     return functionSignatureCache;
   }
 
+  List<ParameterElement> get parameters {
+    // TODO(johnniwinther): Store the list directly, possibly by using List
+    // instead of Link in FunctionSignature.
+    List<ParameterElement> list = <ParameterElement>[];
+    functionSignature.forEachParameter((e) => list.add(e));
+    return list;
+  }
+
   FunctionType computeType(Compiler compiler) {
     if (typeCache != null) return typeCache;
     typeCache = computeSignature(compiler).type;
@@ -2400,24 +2421,22 @@
     return false;
   }
 
-  Element validateConstructorLookupResults(Selector selector,
-                                           Element result,
-                                           Element noMatch(Element)) {
-    if (result == null
-        || !result.isConstructor
-        || (isPrivateName(selector.name)
-            && result.library != selector.library)) {
-      result = noMatch != null ? noMatch(result) : null;
+  ConstructorElement lookupDefaultConstructor() {
+    ConstructorElement constructor = lookupConstructor("");
+    // This method might be called on constructors that have not been
+    // resolved. As we query the live world, we return `null` in such cases
+    // as no default constructor exists in the live world.
+    if (constructor != null &&
+        constructor.hasFunctionSignature &&
+        constructor.functionSignature.requiredParameterCount == 0) {
+      return constructor;
     }
-    return result;
+    return null;
   }
 
-  // TODO(aprelev@gmail.com): Peter believes that it would be great to
-  // make noMatch a required argument. Peter's suspicion is that most
-  // callers of this method would benefit from using the noMatch method.
-  Element lookupConstructor(Selector selector, [Element noMatch(Element)]) {
-    Element result = localLookup(selector.name);
-    return validateConstructorLookupResults(selector, result, noMatch);
+  ConstructorElement lookupConstructor(String name) {
+    Element result = localLookup(name);
+    return result != null && result.isConstructor ? result : null;
   }
 
   Link<Element> get constructors {
diff --git a/pkg/compiler/lib/src/inferrer/concrete_types_inferrer.dart b/pkg/compiler/lib/src/inferrer/concrete_types_inferrer.dart
index 129f49c..4f95214 100644
--- a/pkg/compiler/lib/src/inferrer/concrete_types_inferrer.dart
+++ b/pkg/compiler/lib/src/inferrer/concrete_types_inferrer.dart
@@ -1201,10 +1201,10 @@
         jsArrayClass.lookupMember('removeLast');
     List<String> typePreservingOps = const ['+', '-', '*'];
     listConstructor =
-        compiler.listClass.lookupConstructor(
-            new Selector.callConstructor(
-                '',
-                compiler.listClass.library)).implementation;
+        compiler.listClass.lookupDefaultConstructor();
+    if (listConstructor != null) {
+      listConstructor = listConstructor.implementation;
+    }
     emptyConcreteType = new ConcreteType.empty(compiler.maxConcreteTypeSize,
                                                baseTypes);
     nullConcreteType = singletonConcreteType(const NullBaseType());
diff --git a/pkg/compiler/lib/src/inferrer/node_tracer.dart b/pkg/compiler/lib/src/inferrer/node_tracer.dart
index 6534bbe..c54ddfc 100644
--- a/pkg/compiler/lib/src/inferrer/node_tracer.dart
+++ b/pkg/compiler/lib/src/inferrer/node_tracer.dart
@@ -75,7 +75,7 @@
   static const int MAX_ANALYSIS_COUNT = 16;
   final Setlet<Element> analyzedElements = new Setlet<Element>();
 
-  TracerVisitor(this.tracedType, inferrer)
+  TracerVisitor(this.tracedType, TypeGraphInferrerEngine inferrer)
       : this.inferrer = inferrer, this.compiler = inferrer.compiler;
 
   // Work list that gets populated with [TypeInformation] that could
diff --git a/pkg/compiler/lib/src/inferrer/simple_types_inferrer.dart b/pkg/compiler/lib/src/inferrer/simple_types_inferrer.dart
index 0a3060e..dea26fa 100644
--- a/pkg/compiler/lib/src/inferrer/simple_types_inferrer.dart
+++ b/pkg/compiler/lib/src/inferrer/simple_types_inferrer.dart
@@ -556,9 +556,7 @@
         if (!isConstructorRedirect
             && !seenSuperConstructorCall
             && !cls.isObject) {
-          Selector selector =
-              new Selector.callDefaultConstructor(analyzedElement.library);
-          FunctionElement target = cls.superclass.lookupConstructor(selector);
+          FunctionElement target = cls.superclass.lookupDefaultConstructor();
           analyzeSuperConstructorCall(target, new ArgumentsTypes([], {}));
           synthesizeForwardingCall(analyzedElement, target);
         }
diff --git a/pkg/compiler/lib/src/io/line_column_provider.dart b/pkg/compiler/lib/src/io/line_column_provider.dart
index 5aa700c..4d17583 100644
--- a/pkg/compiler/lib/src/io/line_column_provider.dart
+++ b/pkg/compiler/lib/src/io/line_column_provider.dart
@@ -18,20 +18,19 @@
 /// [CodeOutputListener] that collects line information.

 class LineColumnCollector extends CodeOutputListener

     implements LineColumnProvider {

-  int lastLineStart = 0;

+  int length = 0;

   List<int> lineStarts = <int>[0];

 

   void _collect(String text) {

-    int offset = lastLineStart;

     int index = 0;

     while (index < text.length) {

       // Unix uses '\n' and Windows uses '\r\n', so this algorithm works for

       // both platforms.

       index = text.indexOf('\n', index) + 1;

       if (index <= 0) break;

-      lastLineStart = offset + index;

-      lineStarts.add(lastLineStart);

+      lineStarts.add(length + index);

     }

+    length += text.length;

   }

 

   @override

@@ -43,7 +42,7 @@
   int getLine(int offset) {

     List<int> starts = lineStarts;

     if (offset < 0 || starts.last <= offset) {

-      throw 'bad position #$offset in buffer with length ${lineStarts.last}.';

+      throw 'bad position #$offset in buffer with length ${length}.';

     }

     int first = 0;

     int count = starts.length;

@@ -68,6 +67,11 @@
 

   @override

   void onDone(int length) {

-    lineStarts.add(length);

+    lineStarts.add(length + 1);

+    this.length = length;

+  }

+

+  String toString() {

+    return 'lineStarts=$lineStarts,length=$length';

   }

 }

diff --git a/pkg/compiler/lib/src/js_backend/backend.dart b/pkg/compiler/lib/src/js_backend/backend.dart
index 975581c..edb9c57 100644
--- a/pkg/compiler/lib/src/js_backend/backend.dart
+++ b/pkg/compiler/lib/src/js_backend/backend.dart
@@ -91,6 +91,8 @@
     'IterableMixinWorkaround': const <String>['forEach'],
   };
 
+  String get patchVersion => USE_NEW_EMITTER ? 'new' : 'old';
+
   /// List of [FunctionElement]s that we want to inline always.  This list is
   /// filled when resolution is complete by looking up in [internalLibrary].
   List<FunctionElement> functionsToAlwaysInline;
@@ -844,15 +846,16 @@
           // The constructor is on the patch class, but dart2js unit tests don't
           // have a patch class.
           ClassElement implementation = cls.patch != null ? cls.patch : cls;
-          return implementation.lookupConstructor(
-            new Selector.callConstructor(
-                name, mapLiteralClass.library, arity),
-            (element) {
-              compiler.internalError(mapLiteralClass,
-                  "Map literal class $mapLiteralClass missing "
-                  "'$name' constructor"
-                  "  ${mapLiteralClass.constructors}");
-            });
+          ConstructorElement ctor = implementation.lookupConstructor(name);
+          if (ctor == null
+              || (isPrivateName(name)
+                  && ctor.library != mapLiteralClass.library)) {
+            compiler.internalError(mapLiteralClass,
+                                   "Map literal class $mapLiteralClass missing "
+                                   "'$name' constructor"
+                                   "  ${mapLiteralClass.constructors}");
+          }
+          return ctor;
         }
         mapLiteralConstructor = getFactory('_literal', 1);
         mapLiteralConstructorEmpty = getFactory('_empty', 0);
diff --git a/pkg/compiler/lib/src/js_backend/codegen/codegen.dart b/pkg/compiler/lib/src/js_backend/codegen/codegen.dart
index d97abb4..f930b90 100644
--- a/pkg/compiler/lib/src/js_backend/codegen/codegen.dart
+++ b/pkg/compiler/lib/src/js_backend/codegen/codegen.dart
@@ -170,12 +170,24 @@
                                   Element target,
                                   List<js.Expression> arguments) {
     registry.registerStaticInvocation(target.declaration);
-    js.Expression elementAccess = glue.staticFunctionAccess(target);
-    List<js.Expression> compiledArguments =
-        selector.makeArgumentsList(target.implementation,
-                                   arguments,
-                                   compileConstant);
-    return new js.Call(elementAccess, compiledArguments);
+    if (target == glue.getInterceptorMethod) {
+      // This generates a call to the specialized interceptor function, which
+      // does not have a specialized element yet, but is emitted as a stub from
+      // the emitter in [InterceptorStubGenerator].
+      // TODO(karlklose): Either change [InvokeStatic] to take an [Entity]
+      //   instead of an [Element] and model the getInterceptor functions as
+      //   [Entity]s or add a specialized Tree-IR node for interceptor calls.
+      registry.registerUseInterceptor();
+      js.VariableUse interceptorLibrary = glue.getInterceptorLibrary();
+      return js.propertyCall(interceptorLibrary, selector.name, arguments);
+    } else {
+      js.Expression elementAccess = glue.staticFunctionAccess(target);
+      List<js.Expression> compiledArguments =
+          selector.makeArgumentsList(target.implementation,
+                                     arguments,
+                                     compileConstant);
+      return new js.Call(elementAccess, compiledArguments);
+    }
   }
 
   @override
@@ -189,10 +201,19 @@
 
   void registerMethodInvoke(tree_ir.InvokeMethod node) {
     Selector selector = node.selector;
-    // TODO(sigurdm): We should find a better place to register the call.
-    Selector call = new Selector.callClosureFrom(selector);
-    registry.registerDynamicInvocation(call);
-    registry.registerDynamicInvocation(selector);
+    if (selector.isGetter) {
+      registry.registerDynamicGetter(selector);
+    } else if (selector.isSetter) {
+      registry.registerDynamicSetter(selector);
+    } else {
+      assert(invariant(CURRENT_ELEMENT_SPANNABLE,
+          selector.isCall || selector.isOperator || selector.isIndex,
+          message: 'unexpected kind ${selector.kind}'));
+      // TODO(sigurdm): We should find a better place to register the call.
+      Selector call = new Selector.callClosureFrom(selector);
+      registry.registerDynamicInvocation(call);
+      registry.registerDynamicInvocation(selector);
+    }
   }
 
   @override
diff --git a/pkg/compiler/lib/src/js_backend/codegen/glue.dart b/pkg/compiler/lib/src/js_backend/codegen/glue.dart
index 11f6494..2b86147 100644
--- a/pkg/compiler/lib/src/js_backend/codegen/glue.dart
+++ b/pkg/compiler/lib/src/js_backend/codegen/glue.dart
@@ -11,7 +11,6 @@
 import '../../constants/values.dart';
 import '../../elements/elements.dart';
 import '../../constants/expressions.dart';
-import '../../closure.dart' show ClosureClassElement;
 
 /// Encapsulates the dependencies of the function-compiler to the compiler,
 /// backend and emitter.
@@ -103,4 +102,15 @@
         hasBeenInstantiated: hasBeenInstantiated);
   }
 
+
+  String getInterceptorName(Set<ClassElement> interceptedClasses) {
+    return _backend.namer.getInterceptorName(
+        getInterceptorMethod,
+        interceptedClasses);
+  }
+
+  js.Expression getInterceptorLibrary() {
+    return new js.VariableUse(
+        _backend.namer.globalObjectFor(_backend.interceptorsLibrary));
+  }
 }
diff --git a/pkg/compiler/lib/src/js_backend/codegen/js_tree_builder.dart b/pkg/compiler/lib/src/js_backend/codegen/js_tree_builder.dart
index 9b8ed20..ac76882 100644
--- a/pkg/compiler/lib/src/js_backend/codegen/js_tree_builder.dart
+++ b/pkg/compiler/lib/src/js_backend/codegen/js_tree_builder.dart
@@ -42,10 +42,12 @@
 
   Expression visitInterceptor(cps_ir.Interceptor node) {
     Element getInterceptor = _glue.getInterceptorMethod;
+    String name = _glue.getInterceptorName(node.interceptedClasses);
+    Selector selector = new Selector.call(name, null, 1);
     _glue.registerUseInterceptorInCodegen();
     return new InvokeStatic(
         getInterceptor,
-        new Selector.fromElement(getInterceptor),
+        selector,
         <Expression>[getVariableReference(node.input)]);
   }
 
diff --git a/pkg/compiler/lib/src/js_backend/codegen/task.dart b/pkg/compiler/lib/src/js_backend/codegen/task.dart
index 69be520..d50f32a 100644
--- a/pkg/compiler/lib/src/js_backend/codegen/task.dart
+++ b/pkg/compiler/lib/src/js_backend/codegen/task.dart
@@ -20,7 +20,6 @@
     ForwardingTypeMask;
 import '../../scanner/scannerlib.dart' as scanner;
 import '../../elements/elements.dart';
-import '../../closure.dart';
 import '../../js/js.dart' as js;
 import '../../io/source_map_builder.dart';
 import '../../tree_ir/tree_ir_builder.dart' as tree_builder;
@@ -62,8 +61,10 @@
   js.Fun compile(CodegenWorkItem work) {
     types = new TypeMaskSystem(compiler);
     AstElement element = work.element;
+    JavaScriptBackend backend = compiler.backend;
     return compiler.withCurrentElement(element, () {
-      if (element.library.isPlatformLibrary) {
+      if (element.library.isPlatformLibrary ||
+          element.library == backend.interceptorsLibrary) {
         compiler.log('Using SSA compiler for platform element $element');
         return fallbackCompiler.compile(work);
       }
@@ -105,6 +106,13 @@
     if (cpsNode == null) {
       giveUp('unable to build cps definition of $element');
     }
+    if (element.isInstanceMember && !element.isGenerativeConstructorBody) {
+      Selector selector = new Selector.fromElement(cpsNode.element);
+      if (glue.isInterceptedSelector(selector)) {
+        giveUp('cannot compile methods that need interceptor calling '
+            'convention.');
+      }
+    }
     traceGraph("IR Builder", cpsNode);
     new UnsugarVisitor(glue).rewrite(cpsNode);
     traceGraph("Unsugaring", cpsNode);
diff --git a/pkg/compiler/lib/src/js_backend/codegen/unsugar.dart b/pkg/compiler/lib/src/js_backend/codegen/unsugar.dart
index 4433c6f..a071b47 100644
--- a/pkg/compiler/lib/src/js_backend/codegen/unsugar.dart
+++ b/pkg/compiler/lib/src/js_backend/codegen/unsugar.dart
@@ -6,9 +6,9 @@
 import '../../cps_ir/optimizers.dart';
 import '../../constants/expressions.dart';
 import '../../constants/values.dart';
-import '../../elements/elements.dart' show ClassElement, FieldElement;
+import '../../elements/elements.dart' show ClassElement, FieldElement, Element;
 import '../../js_backend/codegen/glue.dart';
-import '../../dart2jslib.dart' show Selector;
+import '../../dart2jslib.dart' show Selector, World;
 
 /// Rewrites the initial CPS IR to make Dart semantics explicit and inserts
 /// special nodes that respect JavaScript behavior.
@@ -49,21 +49,19 @@
 
   processInvokeMethod(InvokeMethod node) {
     Selector selector = node.selector;
+    // TODO(karlklose):  should we rewrite all selectors?
     if (!_glue.isInterceptedSelector(selector)) return;
 
-    if (!selector.isCall && !selector.isOperator) {
-      // TODO(karlklose): handle special selectors.
-      return;
-    }
-
+    Primitive receiver = node.receiver.definition;
     Set<ClassElement> interceptedClasses =
         _glue.getInterceptedClassesOn(selector);
     _glue.registerSpecializedGetInterceptor(interceptedClasses);
 
-    Primitive receiver = node.receiver.definition;
     Primitive intercepted = new Interceptor(receiver, interceptedClasses);
     insertLetPrim(intercepted, node);
     node.arguments.insert(0, node.receiver);
+    node.callingConvention = CallingConvention.JS_INTERCEPTED;
+    assert(node.isValid);
     node.receiver = new Reference<Primitive>(intercepted);
   }
 
diff --git a/pkg/compiler/lib/src/js_backend/js_backend.dart b/pkg/compiler/lib/src/js_backend/js_backend.dart
index 20e3840..2019f66 100644
--- a/pkg/compiler/lib/src/js_backend/js_backend.dart
+++ b/pkg/compiler/lib/src/js_backend/js_backend.dart
@@ -19,7 +19,12 @@
 import '../js/js.dart' as jsAst;
 import '../js/js.dart' show js;
 import '../js_emitter/js_emitter.dart'
-    show Emitter, CodeEmitterTask, ClassBuilder, MetadataEmitter;
+    show Emitter,
+         CodeEmitterTask,
+         ClassBuilder,
+         MetadataCollector,
+         USE_NEW_EMITTER;
+
 import '../library_loader.dart' show LibraryLoader, LoadedLibraries;
 import '../native/native.dart' as native;
 import '../ssa/ssa.dart';
@@ -31,6 +36,7 @@
 
 import '../elements/visitor.dart' show
     ElementVisitor;
+
 import '../js_backend/codegen/task.dart';
 import 'patch_resolver.dart';
 
diff --git a/pkg/compiler/lib/src/js_backend/namer.dart b/pkg/compiler/lib/src/js_backend/namer.dart
index 7508513..ac39658 100644
--- a/pkg/compiler/lib/src/js_backend/namer.dart
+++ b/pkg/compiler/lib/src/js_backend/namer.dart
@@ -289,6 +289,8 @@
 
   String get isolateName => 'Isolate';
   String get isolatePropertiesName => r'$isolateProperties';
+  String get noSuchMethodName => publicInstanceMethodNameByArity(
+      Compiler.NO_SUCH_METHOD, Compiler.NO_SUCH_METHOD_ARG_COUNT);
   /**
    * Some closures must contain their name. The name is stored in
    * [STATIC_CLOSURE_NAME_NAME].
@@ -865,7 +867,7 @@
   }
 
   String getStaticClosureName(Element element) {
-    assert(Elements.isStaticOrTopLevelFunction(element));
+    assert(invariant(element, Elements.isStaticOrTopLevelFunction(element)));
     return getMappedGlobalName("${getNameX(element)}\$closure");
   }
 
diff --git a/pkg/compiler/lib/src/js_backend/type_variable_handler.dart b/pkg/compiler/lib/src/js_backend/type_variable_handler.dart
index 60bf70f..18d7f67 100644
--- a/pkg/compiler/lib/src/js_backend/type_variable_handler.dart
+++ b/pkg/compiler/lib/src/js_backend/type_variable_handler.dart
@@ -36,7 +36,7 @@
 
   ClassElement get typeVariableClass => backend.typeVariableClass;
   CodeEmitterTask get task => backend.emitter;
-  MetadataEmitter get emitter => task.oldEmitter.metadataEmitter;
+  MetadataCollector get metadataCollector => task.metadataCollector;
   Compiler get compiler => backend.compiler;
 
   void registerClassWithTypeVariables(ClassElement cls) {
@@ -78,7 +78,7 @@
               new DartString.literal(currentTypeVariable.name)));
       ConstantExpression bound = new PrimitiveConstantExpression(
           backend.constantSystem.createInt(
-              emitter.reifyType(typeVariableElement.bound)));
+              metadataCollector.reifyType(typeVariableElement.bound)));
       ConstantExpression type = backend.constants.createTypeConstant(cls);
       List<AstConstant> arguments =
           [wrapConstant(type), wrapConstant(name), wrapConstant(bound)];
@@ -129,7 +129,7 @@
   }
 
   /**
-   * Adds [c] to [emitter.globalMetadata] and returns the index pointing to
+   * Adds [c] to [emitter.metadataCollector] and returns the index pointing to
    * the entry.
    *
    * If the corresponding type variable has already been encountered an
@@ -142,16 +142,16 @@
     int index;
     if (typeVariableConstants.containsKey(variable)) {
       index = typeVariableConstants[variable];
-      emitter.globalMetadata[index] = name;
+      metadataCollector.globalMetadata[index] = name;
     } else {
-      index = emitter.addGlobalMetadata(name);
+      index = metadataCollector.addGlobalMetadata(name);
       typeVariableConstants[variable] = index;
     }
     return index;
   }
 
   /**
-   * Returns the index pointing to the constant in [emitter.globalMetadata]
+   * Returns the index pointing to the constant in [emitter.metadataCollector]
    * representing this type variable.
    *
    * If the constant has not yet been constructed, an entry is  allocated in
@@ -166,8 +166,9 @@
     }
 
     // TODO(15613): Remove quotes.
-    emitter.globalMetadata.add('"Placeholder for ${variable}"');
-    return typeVariableConstants[variable] = emitter.globalMetadata.length - 1;
+    metadataCollector.globalMetadata.add('"Placeholder for ${variable}"');
+    return typeVariableConstants[variable] =
+        metadataCollector.globalMetadata.length - 1;
   }
 
   List<int> typeVariablesOf(ClassElement classElement) {
diff --git a/pkg/compiler/lib/src/js_emitter/class_stub_generator.dart b/pkg/compiler/lib/src/js_emitter/class_stub_generator.dart
index d7e1578..01e74555 100644
--- a/pkg/compiler/lib/src/js_emitter/class_stub_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/class_stub_generator.dart
@@ -111,4 +111,177 @@
 
     return generatedStubs;
   }
+
+  Map<String, Selector> computeSelectorsForNsmHandlers() {
+
+    Map<String, Selector> jsNames = <String, Selector>{};
+
+    // Do not generate no such method handlers if there is no class.
+    if (compiler.codegenWorld.directlyInstantiatedClasses.isEmpty) {
+      return jsNames;
+    }
+
+    void addNoSuchMethodHandlers(String ignore, Set<Selector> selectors) {
+      TypeMask objectSubclassTypeMask =
+          new TypeMask.subclass(compiler.objectClass, compiler.world);
+
+      for (Selector selector in selectors) {
+        TypeMask mask = selector.mask;
+        if (mask == null) mask = objectSubclassTypeMask;
+
+        if (!mask.needsNoSuchMethodHandling(selector, compiler.world)) {
+          continue;
+        }
+        String jsName = namer.invocationMirrorInternalName(selector);
+        jsNames[jsName] = selector;
+      }
+    }
+
+    compiler.codegenWorld.invokedNames.forEach(addNoSuchMethodHandlers);
+    compiler.codegenWorld.invokedGetters.forEach(addNoSuchMethodHandlers);
+    compiler.codegenWorld.invokedSetters.forEach(addNoSuchMethodHandlers);
+    return jsNames;
+  }
+
+  StubMethod generateStubForNoSuchMethod(String name, Selector selector) {
+    // Values match JSInvocationMirror in js-helper library.
+    int type = selector.invocationMirrorKind;
+    List<String> parameterNames =
+        new List.generate(selector.argumentCount, (i) => '\$$i');
+
+    List<jsAst.Expression> argNames =
+        selector.getOrderedNamedArguments().map((String name) =>
+            js.string(name)).toList();
+
+    String methodName = selector.invocationMirrorMemberName;
+    String internalName = namer.invocationMirrorInternalName(selector);
+
+    assert(backend.isInterceptedName(Compiler.NO_SUCH_METHOD));
+    jsAst.Expression expression =
+        js('''this.#noSuchMethodName(this,
+                    #createInvocationMirror(#methodName,
+                                            #internalName,
+                                            #type,
+                                            #arguments,
+                                            #namedArguments))''',
+           {'noSuchMethodName': namer.noSuchMethodName,
+            'createInvocationMirror':
+                backend.emitter.staticFunctionAccess(
+                    backend.getCreateInvocationMirror()),
+            'methodName':
+                js.string(compiler.enableMinification
+                    ? internalName : methodName),
+            'internalName': js.string(internalName),
+            'type': js.number(type),
+            'arguments':
+                new jsAst.ArrayInitializer(parameterNames.map(js).toList()),
+            'namedArguments': new jsAst.ArrayInitializer(argNames)});
+
+    jsAst.Expression function;
+    if (backend.isInterceptedName(selector.name)) {
+      function = js(r'function($receiver, #) { return # }',
+                              [parameterNames, expression]);
+    } else {
+      function = js(r'function(#) { return # }', [parameterNames, expression]);
+    }
+    return new StubMethod(name, function);
+  }
+}
+
+/// Creates two JavaScript functions: `tearOffGetter` and `tearOff`.
+///
+/// `tearOffGetter` is internal and only used by `tearOff`.
+///
+/// `tearOff` takes the following arguments:
+///   * `funcs`: a list of functions. These are the functions representing the
+///    member that is torn off. There can be more than one, since a member
+///    can have several stubs.
+///    Each function must have the `$callName` property set.
+///   * `reflectionInfo`: contains reflective information, and the function
+///    type. TODO(floitsch): point to where this is specified.
+///   * `isStatic`.
+///   * `name`.
+///   * `isIntercepted.
+List<jsAst.Statement> buildTearOffCode(JavaScriptBackend backend) {
+  Namer namer = backend.namer;
+  Compiler compiler = backend.compiler;
+
+  Element closureFromTearOff = backend.findHelper('closureFromTearOff');
+  String tearOffAccessText;
+  jsAst.Expression tearOffAccessExpression;
+  String tearOffGlobalObjectName;
+  String tearOffGlobalObject;
+  if (closureFromTearOff != null) {
+    // We need both the AST that references [closureFromTearOff] and a string
+    // for the NoCsp version that constructs a function.
+    tearOffAccessExpression =
+        backend.emitter.staticFunctionAccess(closureFromTearOff);
+    tearOffAccessText =
+        jsAst.prettyPrint(tearOffAccessExpression, compiler).getText();
+    tearOffGlobalObjectName = tearOffGlobalObject =
+        namer.globalObjectFor(closureFromTearOff);
+  } else {
+    // Default values for mocked-up test libraries.
+    tearOffAccessText =
+        r'''function() { throw 'Helper \'closureFromTearOff\' missing.' }''';
+    tearOffAccessExpression = js(tearOffAccessText);
+    tearOffGlobalObjectName = 'MissingHelperFunction';
+    tearOffGlobalObject = '($tearOffAccessText())';
+  }
+
+  jsAst.Statement tearOffGetter;
+  if (!compiler.useContentSecurityPolicy) {
+    // This template is uncached because it is constructed from code fragments
+    // that can change from compilation to compilation.  Some of these could be
+    // avoided, except for the string literals that contain the compiled access
+    // path to 'closureFromTearOff'.
+    tearOffGetter = js.uncachedStatementTemplate('''
+function tearOffGetter(funcs, reflectionInfo, name, isIntercepted) {
+  return isIntercepted
+      ? new Function("funcs", "reflectionInfo", "name",
+                     "$tearOffGlobalObjectName", "c",
+          "return function tearOff_" + name + (functionCounter++) + "(x) {" +
+            "if (c === null) c = $tearOffAccessText(" +
+                "this, funcs, reflectionInfo, false, [x], name);" +
+                "return new c(this, funcs[0], x, name);" +
+                "}")(funcs, reflectionInfo, name, $tearOffGlobalObject, null)
+      : new Function("funcs", "reflectionInfo", "name",
+                     "$tearOffGlobalObjectName", "c",
+          "return function tearOff_" + name + (functionCounter++)+ "() {" +
+            "if (c === null) c = $tearOffAccessText(" +
+                "this, funcs, reflectionInfo, false, [], name);" +
+                "return new c(this, funcs[0], null, name);" +
+                "}")(funcs, reflectionInfo, name, $tearOffGlobalObject, null);
+}''').instantiate([]);
+  } else {
+    tearOffGetter = js.statement('''
+      function tearOffGetter(funcs, reflectionInfo, name, isIntercepted) {
+        var cache = null;
+        return isIntercepted
+            ? function(x) {
+                if (cache === null) cache = #(
+                    this, funcs, reflectionInfo, false, [x], name);
+                return new cache(this, funcs[0], x, name);
+              }
+            : function() {
+                if (cache === null) cache = #(
+                    this, funcs, reflectionInfo, false, [], name);
+                return new cache(this, funcs[0], null, name);
+              };
+      }''', [tearOffAccessExpression, tearOffAccessExpression]);
+  }
+
+  jsAst.Statement tearOff = js.statement('''
+    function tearOff(funcs, reflectionInfo, isStatic, name, isIntercepted) {
+      var cache;
+      return isStatic
+          ? function() {
+              if (cache === void 0) cache = #tearOff(
+                  this, funcs, reflectionInfo, true, [], name).prototype;
+              return cache;
+            }
+          : tearOffGetter(funcs, reflectionInfo, name, isIntercepted);
+    }''',  {'tearOff': tearOffAccessExpression});
+
+  return <jsAst.Statement>[tearOffGetter, tearOff];
 }
diff --git a/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart b/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart
index e7d9421..e384d93 100644
--- a/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart
+++ b/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart
@@ -17,6 +17,7 @@
   final Namer namer;
   final TypeTestRegistry typeTestRegistry;
   NativeEmitter nativeEmitter;
+  MetadataCollector metadataCollector;
   OldEmitter oldEmitter;
   Emitter emitter;
 
@@ -37,7 +38,7 @@
   /// This flag is updated in [computeNeededConstants].
   bool outputContainsConstantList = false;
 
-  final List<ClassElement> nativeClasses = <ClassElement>[];
+  final List<ClassElement> nativeClassesAndSubclasses = <ClassElement>[];
 
   /// Records if a type variable is read dynamically for type tests.
   final Set<TypeVariableElement> readTypeVariables =
@@ -51,13 +52,16 @@
       : super(compiler),
         this.namer = namer,
         this.typeTestRegistry = new TypeTestRegistry(compiler) {
+    nativeEmitter = new NativeEmitter(this);
     oldEmitter = new OldEmitter(compiler, namer, generateSourceMap, this);
     emitter = USE_NEW_EMITTER
-        ? new new_js_emitter.Emitter(compiler, namer)
+        ? new new_js_emitter.Emitter(compiler, namer, nativeEmitter)
         : oldEmitter;
-    nativeEmitter = new NativeEmitter(this);
+    metadataCollector = new MetadataCollector(compiler, emitter);
   }
 
+  String get name => 'Code emitter';
+
   /// Returns the closure expression of a static function.
   jsAst.Expression isolateStaticClosureAccess(FunctionElement element) {
     return emitter.isolateStaticClosureAccess(element);
@@ -338,13 +342,11 @@
       if (Elements.isNativeOrExtendsNative(element) &&
           !typeTestRegistry.rtiNeededClasses.contains(element)) {
         // For now, native classes and related classes cannot be deferred.
-        nativeClasses.add(element);
-        if (!element.isNative) {
-          assert(invariant(element,
-                           !compiler.deferredLoadTask.isDeferred(element)));
-          outputClassLists.putIfAbsent(compiler.deferredLoadTask.mainOutputUnit,
-              () => new List<ClassElement>()).add(element);
-        }
+        nativeClassesAndSubclasses.add(element);
+        assert(invariant(element,
+                         !compiler.deferredLoadTask.isDeferred(element)));
+        outputClassLists.putIfAbsent(compiler.deferredLoadTask.mainOutputUnit,
+            () => new List<ClassElement>()).add(element);
       } else {
         outputClassLists.putIfAbsent(
             compiler.deferredLoadTask.outputUnitForElement(element),
diff --git a/pkg/compiler/lib/src/js_emitter/interceptor_stub_generator.dart b/pkg/compiler/lib/src/js_emitter/interceptor_stub_generator.dart
index ee78a5f..9f10524 100644
--- a/pkg/compiler/lib/src/js_emitter/interceptor_stub_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/interceptor_stub_generator.dart
@@ -11,6 +11,8 @@
 
   InterceptorStubGenerator(this.compiler, this.namer, this.backend);
 
+  Emitter get emitter => backend.emitter.emitter;
+
   jsAst.Expression generateGetInterceptorMethod(Set<ClassElement> classes) {
     jsAst.Expression interceptorFor(ClassElement cls) {
       return backend.emitter.interceptorPrototypeAccess(cls);
@@ -316,4 +318,56 @@
          optimizedPath,
          globalObject, getInterceptorName, invocationName, parameterNames]);
   }
-}
\ No newline at end of file
+
+  jsAst.ArrayInitializer generateTypeToInterceptorMap() {
+    // TODO(sra): Perhaps inject a constant instead?
+    CustomElementsAnalysis analysis = backend.customElementsAnalysis;
+    if (!analysis.needsTable) return null;
+
+    List<jsAst.Expression> elements = <jsAst.Expression>[];
+    JavaScriptConstantCompiler handler = backend.constants;
+    List<ConstantValue> constants =
+        handler.getConstantsForEmission(emitter.compareConstants);
+    for (ConstantValue constant in constants) {
+      if (constant is TypeConstantValue) {
+        TypeConstantValue typeConstant = constant;
+        Element element = typeConstant.representedType.element;
+        if (element is ClassElement) {
+          ClassElement classElement = element;
+          if (!analysis.needsClass(classElement)) continue;
+
+          elements.add(emitter.constantReference(constant));
+          elements.add(backend.emitter.interceptorClassAccess(classElement));
+
+          // Create JavaScript Object map for by-name lookup of generative
+          // constructors.  For example, the class A has three generative
+          // constructors
+          //
+          //     class A {
+          //       A() {}
+          //       A.foo() {}
+          //       A.bar() {}
+          //     }
+          //
+          // Which are described by the map
+          //
+          //     {"": A.A$, "foo": A.A$foo, "bar": A.A$bar}
+          //
+          // We expect most of the time the map will be a singleton.
+          var properties = [];
+          for (Element member in analysis.constructors(classElement)) {
+            properties.add(
+                new jsAst.Property(
+                    js.string(member.name),
+                    backend.emitter.staticFunctionAccess(member)));
+          }
+
+          var map = new jsAst.ObjectInitializer(properties);
+          elements.add(map);
+        }
+      }
+    }
+
+    return new jsAst.ArrayInitializer(elements);
+  }
+}
diff --git a/pkg/compiler/lib/src/js_emitter/js_emitter.dart b/pkg/compiler/lib/src/js_emitter/js_emitter.dart
index ce6441c..f4f172c 100644
--- a/pkg/compiler/lib/src/js_emitter/js_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/js_emitter.dart
@@ -44,7 +44,6 @@
     JavaScriptBackend,
     JavaScriptConstantCompiler,
     Namer,
-    NativeEmitter,
     RuntimeTypes,
     Substitution,
     TypeCheck,
@@ -93,8 +92,10 @@
 part 'code_emitter_task.dart';
 part 'helpers.dart';
 part 'interceptor_stub_generator.dart';
+part 'metadata_collector.dart';
 part 'native_emitter.dart';
 part 'native_generator.dart';
+part 'parameter_stub_generator.dart';
 part 'type_test_generator.dart';
 part 'type_test_registry.dart';
 
@@ -105,6 +106,5 @@
 part 'old_emitter/declarations.dart';
 part 'old_emitter/emitter.dart';
 part 'old_emitter/interceptor_emitter.dart';
-part 'old_emitter/metadata_emitter.dart';
 part 'old_emitter/nsm_emitter.dart';
 part 'old_emitter/reflection_data_parser.dart';
diff --git a/pkg/compiler/lib/src/js_emitter/old_emitter/metadata_emitter.dart b/pkg/compiler/lib/src/js_emitter/metadata_collector.dart
similarity index 62%
rename from pkg/compiler/lib/src/js_emitter/old_emitter/metadata_emitter.dart
rename to pkg/compiler/lib/src/js_emitter/metadata_collector.dart
index 4366c6d..5319a87 100644
--- a/pkg/compiler/lib/src/js_emitter/old_emitter/metadata_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/metadata_collector.dart
@@ -4,17 +4,25 @@
 
 part of dart2js.js_emitter;
 
-class MetadataEmitter extends CodeEmitterHelper {
+class MetadataCollector {
+  final Compiler _compiler;
+  final Emitter _emitter;
+
   /// A list of JS expressions that represent metadata, parameter names and
   /// type, and return types.
   final List<String> globalMetadata = [];
 
   /// A map used to canonicalize the entries of globalMetadata.
-  final Map<String, int> globalMetadataMap = <String, int>{};
+  final Map<String, int> _globalMetadataMap = <String, int>{};
 
-  bool mustEmitMetadataFor(Element element) {
-    return backend.mustRetainMetadata &&
-        backend.referencedFromMirrorSystem(element);
+  MetadataCollector(this._compiler, this._emitter);
+
+  JavaScriptBackend get _backend => _compiler.backend;
+  TypeVariableHandler get _typeVariableHandler => _backend.typeVariableHandler;
+
+  bool _mustEmitMetadataFor(Element element) {
+    return _backend.mustRetainMetadata &&
+        _backend.referencedFromMirrorSystem(element);
   }
 
   /// The metadata function returns the metadata associated with
@@ -24,8 +32,8 @@
   /// annotated with itself.  The metadata function is used by
   /// mirrors_patch to implement DeclarationMirror.metadata.
   jsAst.Fun buildMetadataFunction(Element element) {
-    if (!mustEmitMetadataFor(element)) return null;
-    return compiler.withCurrentElement(element, () {
+    if (!_mustEmitMetadataFor(element)) return null;
+    return _compiler.withCurrentElement(element, () {
       List<jsAst.Expression> metadata = <jsAst.Expression>[];
       Link link = element.metadata;
       // TODO(ahe): Why is metadata sometimes null?
@@ -33,11 +41,11 @@
         for (; !link.isEmpty; link = link.tail) {
           MetadataAnnotation annotation = link.head;
           ConstantExpression constant =
-              backend.constants.getConstantForMetadata(annotation);
+              _backend.constants.getConstantForMetadata(annotation);
           if (constant == null) {
-            compiler.internalError(annotation, 'Annotation value is null.');
+            _compiler.internalError(annotation, 'Annotation value is null.');
           } else {
-            metadata.add(emitter.constantReference(constant.value));
+            metadata.add(_emitter.constantReference(constant.value));
           }
         }
       }
@@ -53,11 +61,11 @@
     List<int> defaultValues = <int>[];
     for (ParameterElement element in signature.optionalParameters) {
       ConstantExpression constant =
-          backend.constants.getConstantForVariable(element);
+          _backend.constants.getConstantForVariable(element);
       String stringRepresentation = (constant == null)
           ? "null"
           : jsAst.prettyPrint(
-              emitter.constantReference(constant.value), compiler).getText();
+              _emitter.constantReference(constant.value), _compiler).getText();
       defaultValues.add(addGlobalMetadata(stringRepresentation));
     }
     return defaultValues;
@@ -65,31 +73,31 @@
 
   int reifyMetadata(MetadataAnnotation annotation) {
     ConstantExpression constant =
-        backend.constants.getConstantForMetadata(annotation);
+        _backend.constants.getConstantForMetadata(annotation);
     if (constant == null) {
-      compiler.internalError(annotation, 'Annotation value is null.');
+      _compiler.internalError(annotation, 'Annotation value is null.');
       return -1;
     }
     return addGlobalMetadata(
         jsAst.prettyPrint(
-            emitter.constantReference(constant.value), compiler).getText());
+            _emitter.constantReference(constant.value), _compiler).getText());
   }
 
   int reifyType(DartType type) {
     jsAst.Expression representation =
-        backend.rti.getTypeRepresentation(
+        _backend.rti.getTypeRepresentation(
             type,
             (variable) {
               return js.number(
-                  emitter.typeVariableHandler.reifyTypeVariable(
+                  _typeVariableHandler.reifyTypeVariable(
                       variable.element));
             },
             (TypedefType typedef) {
-              return backend.isAccessibleByReflection(typedef.element);
+              return _backend.isAccessibleByReflection(typedef.element);
             });
 
     return addGlobalMetadata(
-        jsAst.prettyPrint(representation, compiler).getText());
+        jsAst.prettyPrint(representation, _compiler).getText());
   }
 
   int reifyName(String name) {
@@ -97,32 +105,15 @@
   }
 
   int addGlobalMetadata(String string) {
-    return globalMetadataMap.putIfAbsent(string, () {
+    return _globalMetadataMap.putIfAbsent(string, () {
       globalMetadata.add(string);
       return globalMetadata.length - 1;
     });
   }
 
-  void emitMetadata(CodeOutput output) {
-    String metadataAccess = emitter.generateEmbeddedGlobalAccessString(
-          embeddedNames.METADATA);
-    output.add('$metadataAccess$_=$_[');
-    for (String metadata in globalMetadata) {
-      if (metadata is String) {
-        if (metadata != 'null') {
-          output.add(metadata);
-        }
-      } else {
-        throw 'Unexpected value in metadata: ${Error.safeToString(metadata)}';
-      }
-      output.add(',$n');
-    }
-    output.add('];$n');
-  }
-
   List<int> computeMetadata(FunctionElement element) {
-    return compiler.withCurrentElement(element, () {
-      if (!mustEmitMetadataFor(element)) return const <int>[];
+    return _compiler.withCurrentElement(element, () {
+      if (!_mustEmitMetadataFor(element)) return const <int>[];
       List<int> metadata = <int>[];
       Link link = element.metadata;
       // TODO(ahe): Why is metadata sometimes null?
diff --git a/pkg/compiler/lib/src/js_emitter/model.dart b/pkg/compiler/lib/src/js_emitter/model.dart
index 7d011ad..313fb80 100644
--- a/pkg/compiler/lib/src/js_emitter/model.dart
+++ b/pkg/compiler/lib/src/js_emitter/model.dart
@@ -9,19 +9,46 @@
 
 import '../deferred_load.dart' show OutputUnit;
 
+import 'js_emitter.dart' show MetadataCollector;
+
 import '../common.dart';
 
 class Program {
   final List<Fragment> fragments;
-  final List<Class> nativeClasses;
   final bool outputContainsConstantList;
+  final bool outputContainsNativeClasses;
   /// A map from load id to the list of fragments that need to be loaded.
   final Map<String, List<Fragment>> loadMap;
 
+  // If this field is not `null` then its value must be emitted in the embedded
+  // global `TYPE_TO_INTERCEPTOR_MAP`. The map references constants and classes.
+  final js.Expression typeToInterceptorMap;
+
+  // TODO(floitsch): we should store the metadata directly instead of storing
+  // the collector. However, the old emitter still updates the data.
+  final MetadataCollector _metadataCollector;
+
   Program(this.fragments,
-          this.nativeClasses,
-          this.outputContainsConstantList,
-          this.loadMap);
+          this.loadMap,
+          this.typeToInterceptorMap,
+          this._metadataCollector,
+          {this.outputContainsNativeClasses,
+           this.outputContainsConstantList}) {
+    assert(outputContainsNativeClasses != null);
+    assert(outputContainsConstantList != null);
+  }
+
+  /// A list of pretty-printed JavaScript expressions.
+  ///
+  /// This list must be emitted in the `METADATA` embedded global.
+  /// The list references constants and must hence be emitted after constants
+  /// have been initialized.
+  ///
+  /// Note: the metadata is derived from the task's `metadataCollector`. The
+  /// list must not be emitted before all operations on it are done. For
+  /// example, the old emitter generates metadata when emitting reflection
+  /// data.
+  List<String> get metadata => _metadataCollector.globalMetadata;
 
   bool get isSplit => fragments.length > 1;
   Iterable<Fragment> get deferredFragments => fragments.skip(1);
@@ -178,7 +205,12 @@
   final List<Method> methods;
   final List<Field> fields;
   final List<StubMethod> isChecks;
+
+  /// Stub methods for this class that are call stubs for getters.
   final List<StubMethod> callStubs;
+
+  /// noSuchMethod stubs in the special case that the class is Object.
+  final List<StubMethod> noSuchMethodStubs;
   final List<Field> staticFieldsForReflection;
   final bool onlyForRti;
   final bool isDirectlyInstantiated;
@@ -191,11 +223,15 @@
   /// Whether the class must be evaluated eagerly.
   bool isEager = false;
 
+  /// Data that must be emitted with the class for native interop.
+  String nativeInfo;
+
   Class(this.element, this.name, this.holder,
         this.methods,
         this.fields,
         this.staticFieldsForReflection,
         this.callStubs,
+        this.noSuchMethodStubs,
         this.isChecks,
         this.functionTypeIndex,
         {this.onlyForRti,
@@ -236,6 +272,7 @@
               instanceFields,
               staticFieldsForReflection,
               callStubs,
+              const <StubMethod>[],
               isChecks, functionTypeIndex,
               onlyForRti: onlyForRti,
               isDirectlyInstantiated: isDirectlyInstantiated,
@@ -287,35 +324,120 @@
   bool get needsInterceptedSetter => setterFlags > 1;
 }
 
-class Method {
+abstract class Method {
   /// The element should only be used during the transition to the new model.
   /// Uses indicate missing information in the model.
   final Element element;
-
   final String name;
   final js.Expression code;
-  final bool needsTearOff;
 
-  Method(this.element, this.name, this.code, {this.needsTearOff}) {
+  Method(this.element, this.name, this.code);
+}
+
+/// A method that corresponds to a method in the original Dart program.
+class DartMethod extends Method {
+  final bool needsTearOff;
+  final String tearOffName;
+  final List<ParameterStubMethod> parameterStubs;
+  final bool canBeApplied;
+  final bool canBeReflected;
+  final DartType type;
+
+  // If this method can be torn off, contains the name of the corresponding
+  // call method. For example, for the member `foo$1$name` it would be
+  // `call$1$name` (in unminified mode).
+  final String callName;
+
+  DartMethod(Element element, String name, js.Expression code,
+             this.parameterStubs, this.callName, this.type,
+             {this.needsTearOff, this.tearOffName, this.canBeApplied,
+             this.canBeReflected})
+      : super(element, name, code) {
     assert(needsTearOff != null);
+    assert(!needsTearOff || tearOffName != null);
+    assert(canBeApplied != null);
+    assert(canBeReflected != null);
   }
 }
 
+class InstanceMethod extends DartMethod {
+  /// An alternative name for this method. This is used to model calls to
+  /// a method via `super`. If [aliasName] is non-null, the emitter has to
+  /// ensure that this method is registered on the prototype under both [name]
+  /// and [aliasName].
+  final String aliasName;
+  final bool isClosure;
+
+
+  InstanceMethod(Element element, String name, js.Expression code,
+                 List<ParameterStubMethod> parameterStubs,
+                 String callName, DartType type,
+                 {bool needsTearOff,
+                  String tearOffName,
+                  this.aliasName,
+                  bool canBeApplied,
+                  bool canBeReflected,
+       this.isClosure})
+      : super(element, name, code, parameterStubs, callName, type,
+              needsTearOff: needsTearOff,
+              tearOffName: tearOffName,
+              canBeApplied: canBeApplied,
+              canBeReflected: canBeReflected) {
+    assert(isClosure != null);
+  }
+}
+
+/// A method that is generated by the backend and has not direct correspondence
+/// to a method in the original Dart program. Examples are getter and setter
+/// stubs and stubs to dispatch calls to methods with optional parameters.
 class StubMethod extends Method {
   StubMethod(String name, js.Expression code,
-             {bool needsTearOff, Element element })
-      : super(element, name, code, needsTearOff: needsTearOff);
+             {Element element})
+      : super(element, name, code);
 }
 
-class StaticMethod extends Method {
+/// A stub that adapts and redirects to the main method (the one containing)
+/// the actual code.
+///
+/// For example, given a method `foo$2(x, [y: 499])` a possible parameter
+/// stub-method could be `foo$1(x) => foo$2(x, 499)`.
+///
+/// ParameterStubMethods are always attached to (static or instance) methods.
+class ParameterStubMethod extends StubMethod {
+  /// The `call` name of this stub.
+  ///
+  /// When an instance method is torn off, it is invoked as a `call` member and
+  /// not it's original name anymore. The [callName] provides the stub's
+  /// name when it is used this way.
+  ///
+  /// If a stub's member can not be torn off, the [callName] is `null`.
+  String callName;
+
+  ParameterStubMethod(String name, this.callName, js.Expression code)
+      : super(name, code);
+}
+
+abstract class StaticMethod implements Method {
+  Holder get holder;
+}
+
+class StaticDartMethod extends DartMethod implements StaticMethod {
   final Holder holder;
-  StaticMethod(Element element, String name, this.holder, js.Expression code,
-               {bool needsTearOff})
-      : super(element, name, code, needsTearOff: needsTearOff);
+
+  StaticDartMethod(Element element, String name, this.holder,
+                   js.Expression code, List<ParameterStubMethod> parameterStubs,
+                   String callName, DartType type,
+                   {bool needsTearOff, String tearOffName, bool canBeApplied,
+                    bool canBeReflected})
+      : super(element, name, code, parameterStubs, callName, type,
+              needsTearOff: needsTearOff,
+              tearOffName : tearOffName,
+              canBeApplied : canBeApplied,
+              canBeReflected : canBeReflected);
 }
 
-class StaticStubMethod extends StaticMethod {
-  StaticStubMethod(String name, Holder holder, js.Expression code,
-                   {bool needsTearOff})
-      : super(null, name, holder, code, needsTearOff: needsTearOff);
+class StaticStubMethod extends StubMethod implements StaticMethod {
+  Holder holder;
+  StaticStubMethod(String name, this.holder, js.Expression code)
+      : super(name, code);
 }
diff --git a/pkg/compiler/lib/src/js_emitter/native_emitter.dart b/pkg/compiler/lib/src/js_emitter/native_emitter.dart
index 90c2521..ecde823 100644
--- a/pkg/compiler/lib/src/js_emitter/native_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/native_emitter.dart
@@ -43,11 +43,14 @@
   }
 
   /**
-   * Prepares native classes for emission. Returns the reduced list of classes.
+   * Prepares native classes for emission. Returns the unneeded classes.
    *
    * Removes trivial classes (that can be represented by a super type) and
    * generates properties that have to be added to classes (native or not).
    *
+   * Updates the `nativeInfo` field of the given classes. This data
+   * must be emitted with the corresponding classes.
+   *
    * The interceptors are filtered to avoid emitting trivial interceptors.  For
    * example, if the program contains no code that can distinguish between the
    * numerous subclasses of `Element` then we can pretend that `Element` is a
@@ -60,22 +63,16 @@
    * improves performance when more classes can be treated as leaves.
    *
    * [classes] contains native classes, mixin applications, and user subclasses
-   * of native classes.  *Only* the native classes are returned. The order of
-   * the returned classes is unchanged. (That is, the returned output might
-   * just have classes removed).
-   *
-   * [allAdditionalProperties] is used to collect properties that are pushed up
-   * from the above optimizations onto a non-native class, e.g, `Interceptor`.
+   * of native classes.
    */
-  List<Class> prepareNativeClasses(
-      List<Class> classes,
-      Map<Class, Map<String, jsAst.Expression>> allAdditionalProperties) {
-    // Compute a pre-order traversal of the subclass forest.  We actually want a
-    // post-order traversal but it is easier to compute the pre-order and use it
-    // in reverse.
+  Set<Class> prepareNativeClasses(List<Class> classes) {
+    assert(classes.every((Class cls) => cls != null));
 
     hasNativeClasses = classes.isNotEmpty;
 
+    // Compute a pre-order traversal of the subclass forest.  We actually want a
+    // post-order traversal but it is easier to compute the pre-order and use it
+    // in reverse.
     List<Class> preOrder = <Class>[];
     Set<Class> seen = new Set<Class>();
 
@@ -209,10 +206,8 @@
         String encoding = sb.toString();
 
         if (cls.isNative || encoding != '') {
-          Map<String, jsAst.Expression> properties =
-              allAdditionalProperties.putIfAbsent(cls,
-                  () => new Map<String, jsAst.Expression>());
-          properties[backend.namer.nativeSpecProperty] = js.string(encoding);
+          assert(cls.nativeInfo == null);
+          cls.nativeInfo = encoding;
         }
       }
       generateClassInfo(jsInterceptorClass);
@@ -229,8 +224,8 @@
     //assert(!classElement.hasBackendMembers);
 
     return classes
-        .where((Class cls) => cls.isNative && neededClasses.contains(cls))
-        .toList();
+        .where((Class cls) => cls.isNative && !neededClasses.contains(cls))
+        .toSet();
   }
 
   /**
@@ -278,12 +273,6 @@
         !cls.fields.any(needsAccessor);
   }
 
-  void finishGenerateNativeClasses() {
-    // TODO(sra): Put specialized version of getNativeMethods on
-    // `Object.prototype` to avoid checking in `getInterceptor` and
-    // specializations.
-  }
-
   void potentiallyConvertDartClosuresToJs(
       List<jsAst.Statement> statements,
       FunctionElement member,
@@ -349,6 +338,8 @@
       arguments = argumentsBuffer.sublist(1,
           indexOfLastOptionalArgumentInParameters + 1);
     } else {
+      // Native methods that are not intercepted must be static.
+      assert(invariant(member, member.isStatic));
       receiver = js('this');
       arguments = argumentsBuffer.sublist(0,
           indexOfLastOptionalArgumentInParameters + 1);
@@ -395,42 +386,95 @@
     return isSupertypeOfNativeClass(element);
   }
 
-  void assembleCode(CodeOutput targetOutput) {
-    List<jsAst.Property> objectProperties = <jsAst.Property>[];
-
-    jsAst.Property addProperty(String name, jsAst.Expression value) {
-      jsAst.Property prop = new jsAst.Property(js.string(name), value);
-      objectProperties.add(prop);
-      return prop;
-    }
-
-    if (hasNativeClasses) {
-      // If the native emitter has been asked to take care of the
-      // noSuchMethod handlers, we do that now.
-      if (handleNoSuchMethod) {
-        emitterTask.oldEmitter.nsmEmitter.emitNoSuchMethodHandlers(addProperty);
-      }
-    }
-
-    // If we have any properties to add to Object.prototype, we run
-    // through them and add them using defineProperty.
-    if (!objectProperties.isEmpty) {
-      jsAst.Expression init = js(r'''
-          (function(table) {
-            for(var key in table)
-              #(Object.prototype, key, table[key]);
-           })(#)''',
-          [ defPropFunction,
-            new jsAst.ObjectInitializer(objectProperties)]);
-
-      if (emitterTask.compiler.enableMinification) {
-        targetOutput.add(';');
-      }
-      targetOutput.addBuffer(jsAst.prettyPrint(
-          new jsAst.ExpressionStatement(init), compiler));
-      targetOutput.add('\n');
-    }
-
-    targetOutput.add('\n');
+  /// Returns a JavaScript template that fills the embedded globals referenced
+  /// by [interceptorsByTagAccess] and [leafTagsAccess].
+  ///
+  /// This code must be invoked for every class that has a native info before
+  /// the program starts.
+  ///
+  /// The [infoAccess] parameter must evaluate to an expression that contains
+  /// the info (as a JavaScript string).
+  ///
+  /// The [constructorAccess] parameter must evaluate to an expression that
+  /// contains the constructor of the class. The constructor's prototype must
+  /// be set up.
+  ///
+  /// The [subclassReadGenerator] function must evaluate to a JS expression
+  /// that returns a reference to the constructor (with evaluated prototype)
+  /// of the given JS expression.
+  ///
+  /// The [interceptorsByTagAccess] must point to the embedded global
+  /// [embeddedNames.INTERCEPTORS_BY_TAG] and must be initialized with an empty
+  /// JS Object (used as a map).
+  ///
+  /// Similarly, the [leafTagsAccess] must point to the embedded global
+  /// [embeddedNames.LEAF_TAGS] and must be initialized with an empty JS Object
+  /// (used as a map).
+  ///
+  /// Both variables are passed in (instead of creating the access here) to
+  /// make sure the caller is aware of these globals.
+  jsAst.Statement buildNativeInfoHandler(
+      jsAst.Expression infoAccess,
+      jsAst.Expression constructorAccess,
+      jsAst.Expression subclassReadGenerator(jsAst.Expression subclass),
+      jsAst.Expression interceptorsByTagAccess,
+      jsAst.Expression leafTagsAccess) {
+    jsAst.Expression subclassRead =
+        subclassReadGenerator(js('subclasses[i]', []));
+    return js.statement('''
+          // The native info looks like this:
+          //
+          // HtmlElement: {
+          //     "%": "HTMLDivElement|HTMLAnchorElement;HTMLElement;FancyButton"
+          //
+          // The first two semicolon-separated parts contain dispatch tags, the
+          // third contains the JavaScript names for classes.
+          //
+          // The tags indicate that JavaScript objects with the dispatch tags
+          // (usually constructor names) HTMLDivElement, HTMLAnchorElement and
+          // HTMLElement all map to the Dart native class named HtmlElement.
+          // The first set is for effective leaf nodes in the hierarchy, the
+          // second set is non-leaf nodes.
+          //
+          // The third part contains the JavaScript names of Dart classes that
+          // extend the native class. Here, FancyButton extends HtmlElement, so
+          // the runtime needs to know that window.HTMLElement.prototype is the
+          // prototype that needs to be extended in creating the custom element.
+          //
+          // The information is used to build tables referenced by
+          // getNativeInterceptor and custom element support.
+          {
+            var nativeSpec = #info.split(";");
+            if (nativeSpec[0]) {
+              var tags = nativeSpec[0].split("|");
+              for (var i = 0; i < tags.length; i++) {
+                #interceptorsByTagAccess[tags[i]] = #constructor;
+                #leafTagsAccess[tags[i]] = true;
+              }
+            }
+            if (nativeSpec[1]) {
+              tags = nativeSpec[1].split("|");
+              if (#allowNativesSubclassing) {
+                if (nativeSpec[2]) {
+                  var subclasses = nativeSpec[2].split("|");
+                  for (var i = 0; i < subclasses.length; i++) {
+                    var subclass = #subclassRead;
+                    subclass.#nativeSuperclassTagName = tags[0];
+                  }
+                }
+                for (i = 0; i < tags.length; i++) {
+                  #interceptorsByTagAccess[tags[i]] = #constructor;
+                  #leafTagsAccess[tags[i]] = false;
+                }
+              }
+            }
+          }
+    ''', {'info': infoAccess,
+          'constructor': constructorAccess,
+          'subclassRead': subclassRead,
+          'interceptorsByTagAccess': interceptorsByTagAccess,
+          'leafTagsAccess': leafTagsAccess,
+          'nativeSuperclassTagName': embeddedNames.NATIVE_SUPERCLASS_TAG_NAME,
+          'allowNativesSubclassing': true});
   }
 }
diff --git a/pkg/compiler/lib/src/js_emitter/new_emitter/emitter.dart b/pkg/compiler/lib/src/js_emitter/new_emitter/emitter.dart
index 98691d2..c37d533 100644
--- a/pkg/compiler/lib/src/js_emitter/new_emitter/emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/new_emitter/emitter.dart
@@ -11,7 +11,13 @@
 import '../../elements/elements.dart' show FieldElement;
 import '../../js/js.dart' as js;
 
-import '../../js_backend/js_backend.dart' show Namer, JavaScriptBackend;
+import '../../js_backend/js_backend.dart' show
+    JavaScriptBackend,
+    Namer;
+
+import '../js_emitter.dart' show
+    NativeEmitter;
+
 import '../js_emitter.dart' as emitterTask show
     Emitter;
 
@@ -20,10 +26,10 @@
   final Namer namer;
   final ModelEmitter _emitter;
 
-  Emitter(Compiler compiler, Namer namer)
+  Emitter(Compiler compiler, Namer namer, NativeEmitter nativeEmitter)
       : this._compiler = compiler,
         this.namer = namer,
-        _emitter = new ModelEmitter(compiler, namer);
+        _emitter = new ModelEmitter(compiler, namer, nativeEmitter);
 
   @override
   int emitProgram(ProgramBuilder programBuilder) {
@@ -128,9 +134,10 @@
   }
 
   @override
-  js.PropertyAccess interceptorClassAccess(ClassElement element) {
-    // Interceptors are eagerly constructed. It's safe to just access them.
-    return _globalPropertyAccess(element);
+  js.Expression interceptorClassAccess(ClassElement element) {
+    // Some interceptors are eagerly constructed. However, native interceptors
+    // aren't.
+    return js.js('#.ensureResolved()', _globalPropertyAccess(element));
   }
 
   @override
diff --git a/pkg/compiler/lib/src/js_emitter/new_emitter/model_emitter.dart b/pkg/compiler/lib/src/js_emitter/new_emitter/model_emitter.dart
index a2b1c62..30d81ed 100644
--- a/pkg/compiler/lib/src/js_emitter/new_emitter/model_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/new_emitter/model_emitter.dart
@@ -5,26 +5,38 @@
 library dart2js.new_js_emitter.model_emitter;
 
 import '../../dart2jslib.dart' show Compiler;
+import '../../dart_types.dart' show DartType;
 import '../../js/js.dart' as js;
 import '../../js_backend/js_backend.dart' show
     JavaScriptBackend,
     Namer,
     ConstantEmitter;
 
+import '../js_emitter.dart' show
+    NativeEmitter;
+
 import 'package:_internal/compiler/js_lib/shared/embedded_names.dart' show
     DEFERRED_LIBRARY_URIS,
     DEFERRED_LIBRARY_HASHES,
+    GET_TYPE_FROM_NAME,
     INITIALIZE_LOADED_HUNK,
+    INTERCEPTORS_BY_TAG,
     IS_HUNK_INITIALIZED,
-    IS_HUNK_LOADED;
+    IS_HUNK_LOADED,
+    LEAF_TAGS,
+    MANGLED_GLOBAL_NAMES,
+    METADATA,
+    TYPE_TO_INTERCEPTOR_MAP;
 
-import '../js_emitter.dart' show NativeGenerator;
+import '../js_emitter.dart' show NativeGenerator, buildTearOffCode;
 import '../model.dart';
 
+
 class ModelEmitter {
   final Compiler compiler;
   final Namer namer;
   final ConstantEmitter constantEmitter;
+  final NativeEmitter nativeEmitter;
 
   JavaScriptBackend get backend => compiler.backend;
 
@@ -34,7 +46,7 @@
 
   static const String deferredExtension = "part.js";
 
-  ModelEmitter(Compiler compiler, Namer namer)
+  ModelEmitter(Compiler compiler, Namer namer, this.nativeEmitter)
       : this.compiler = compiler,
         this.namer = namer,
         constantEmitter =
@@ -86,34 +98,70 @@
     elements.add(
         emitLazilyInitializedStatics(fragment.staticLazilyInitializedFields));
 
-    js.Statement nativeBoilerplate;
+    js.Expression code = new js.ArrayInitializer(elements);
+
+    Map<String, dynamic> holes =
+      {'deferredInitializer': emitDeferredInitializerGlobal(program.loadMap),
+       'holders': emitHolders(fragment.holders),
+         'tearOff': buildTearOffCode(backend),
+         'parseFunctionDescriptor':
+           js.js.statement(parseFunctionDescriptorBoilerplate),
+       'cyclicThrow':
+         backend.emitter.staticFunctionAccess(backend.getCyclicThrowHelper()),
+       'outputContainsConstantList': program.outputContainsConstantList,
+       'embeddedGlobals': emitEmbeddedGlobals(program),
+       'constants': emitConstants(fragment.constants),
+       'staticNonFinals':
+         emitStaticNonFinalFields(fragment.staticNonFinalFields),
+       'operatorIsPrefix': js.string(namer.operatorIsPrefix),
+       'eagerClasses': emitEagerClassInitializations(fragment.libraries),
+       'main': fragment.main,
+       'code': code};
+
+    holes.addAll(nativeHoles(program));
+
+    return js.js.statement(boilerplate, holes);
+  }
+
+  Map<String, dynamic> nativeHoles(Program program) {
+    Map<String, dynamic> nativeHoles = <String, dynamic>{};
+
+    js.Statement nativeIsolateAffinityTagInitialization;
     if (NativeGenerator.needsIsolateAffinityTagInitialization(backend)) {
-      nativeBoilerplate =
+      nativeIsolateAffinityTagInitialization =
           NativeGenerator.generateIsolateAffinityTagInitialization(
               backend,
               generateEmbeddedGlobalAccess,
               // TODO(floitsch): convertToFastObject.
               js.js("(function(x) { return x; })", []));
     } else {
-      nativeBoilerplate = js.js.statement(";");
+      nativeIsolateAffinityTagInitialization = js.js.statement(";");
     }
+    nativeHoles['nativeIsolateAffinityTagInitialization'] =
+        nativeIsolateAffinityTagInitialization;
 
-    js.Expression code = new js.ArrayInitializer(elements);
 
-    return js.js.statement(
-        boilerplate,
-        {'deferredInitializer': emitDeferredInitializerGlobal(program.loadMap),
-         'holders': emitHolders(fragment.holders),
-         'cyclicThrow':
-           backend.emitter.staticFunctionAccess(backend.getCyclicThrowHelper()),
-         'outputContainsConstantList': program.outputContainsConstantList,
-         'embeddedGlobals': emitEmbeddedGlobals(program.loadMap),
-         'constants': emitConstants(fragment.constants),
-         'staticNonFinals': emitStaticNonFinalFields(fragment.staticNonFinalFields),
-         'nativeBoilerplate': nativeBoilerplate,
-         'eagerClasses': emitEagerClassInitializations(fragment.libraries),
-         'main': fragment.main,
-         'code': code});
+    js.Expression nativeInfoAccess = js.js('nativeInfo', []);
+    js.Expression constructorAccess = js.js('constructor', []);
+    Function subclassReadGenerator = (js.Expression subclass) {
+      return js.js('holdersMap[#][#].ensureResolved()', [subclass, subclass]);
+    };
+    js.Expression interceptorsByTagAccess =
+        generateEmbeddedGlobalAccess(INTERCEPTORS_BY_TAG);
+    js.Expression leafTagsAccess =
+        generateEmbeddedGlobalAccess(LEAF_TAGS);
+    js.Statement nativeInfoHandler = nativeEmitter.buildNativeInfoHandler(
+        nativeInfoAccess,
+        constructorAccess,
+        subclassReadGenerator,
+        interceptorsByTagAccess,
+        leafTagsAccess);
+
+    nativeHoles['hasNativeClasses'] = program.outputContainsNativeClasses;
+    nativeHoles['hasNoNativeClasses'] = !program.outputContainsNativeClasses;
+    nativeHoles['nativeInfoHandler'] = nativeInfoHandler;
+
+    return nativeHoles;
   }
 
   js.Block emitHolders(List<Holder> holders) {
@@ -135,7 +183,8 @@
                     new js.ObjectInitializer(const []))).toList())),
         js.js.statement('var holders = #', new js.ArrayInitializer(
             holders.map((e) => new js.VariableUse(e.name))
-                   .toList(growable: false)))
+                   .toList(growable: false))),
+        js.js.statement('var holdersMap = Object.create(null)')
     ];
     return new js.Block(statements);
   }
@@ -146,15 +195,34 @@
     return js.js.uncachedExpressionTemplate('makeConstList(#)');
   }
 
-  js.Block emitEmbeddedGlobals(Map<String, List<Fragment>> loadMap) {
+  js.Block emitEmbeddedGlobals(Program program) {
     List<js.Property> globals = <js.Property>[];
 
-    if (loadMap.isNotEmpty) {
-      globals.addAll(emitLoadUrisAndHashes(loadMap));
+    if (program.loadMap.isNotEmpty) {
+      globals.addAll(emitLoadUrisAndHashes(program.loadMap));
       globals.add(emitIsHunkLoadedFunction());
       globals.add(emitInitializeLoadedHunk());
     }
 
+    if (program.typeToInterceptorMap != null) {
+      globals.add(new js.Property(js.string(TYPE_TO_INTERCEPTOR_MAP),
+                                  program.typeToInterceptorMap));
+    }
+
+    globals.add(new js.Property(js.string(MANGLED_GLOBAL_NAMES),
+                                js.js('Object.create(null)', [])));
+
+    globals.add(emitGetTypeFromName());
+
+    globals.add(emitMetadata(program));
+
+    if (program.outputContainsNativeClasses) {
+      globals.add(new js.Property(js.string(INTERCEPTORS_BY_TAG),
+                                  js.js('Object.create(null)', [])));
+      globals.add(new js.Property(js.string(LEAF_TAGS),
+                                  js.js('Object.create(null)', [])));
+    }
+
     js.ObjectInitializer globalsObject = new js.ObjectInitializer(globals);
 
     List<js.Statement> statements =
@@ -216,6 +284,22 @@
     return new js.Property(js.string(INITIALIZE_LOADED_HUNK), function);
   }
 
+  js.Property emitGetTypeFromName() {
+    js.Expression function =
+        js.js( """function(name) {
+                    return holdersMap[name][name].ensureResolved();
+                  }""");
+    return new js.Property(js.string(GET_TYPE_FROM_NAME), function);
+  }
+
+  js.Property emitMetadata(Program program) {
+    String metadataList = "[${program.metadata.join(",")}]";
+    js.Expression metadata =
+        js.js.uncachedExpressionTemplate(metadataList).instantiate([]);
+
+    return new js.Property(js.string(METADATA), metadata);
+  }
+
   js.Expression emitDeferredFragment(DeferredFragment fragment,
                                      List<Holder> holders) {
     // TODO(floitsch): initialize eager classes.
@@ -270,11 +354,26 @@
     return new js.Block(instantiations);
   }
 
+  // This string should be referenced wherever JavaScript code makes assumptions
+  // on the mixin format.
+  static final String nativeInfoDescription =
+      "A class is encoded as follows:"
+      "   [name, class-code, holder-index], or "
+      "   [name, class-code, native-info, holder-index].";
+
   js.Expression emitLibrary(Library library) {
-    Iterable staticDescriptors = library.statics.expand((e) =>
-        [ js.string(e.name), js.number(e.holder.index), emitStaticMethod(e) ]);
-    Iterable classDescriptors = library.classes.expand((e) =>
-        [ js.string(e.name), js.number(e.holder.index), emitClass(e) ]);
+    Iterable staticDescriptors = library.statics.expand(emitStaticMethod);
+
+    Iterable classDescriptors = library.classes.expand((Class cls) {
+      js.LiteralString name = js.string(cls.name);
+      js.LiteralNumber holderIndex = js.number(cls.holder.index);
+      js.Expression emittedClass = emitClass(cls);
+      if (cls.nativeInfo == null) {
+        return [name, emittedClass, holderIndex];
+      } else {
+        return [name, emittedClass, js.string(cls.nativeInfo), holderIndex];
+      }
+    });
 
     js.Expression staticArray =
         new js.ArrayInitializer(staticDescriptors.toList(growable: false));
@@ -314,8 +413,8 @@
 
     js.Expression fieldName = js.string(field.name);
     js.Expression code = js.js(getterTemplateFor(field.getterFlags), fieldName);
-    String getterName = "${namer.getterPrefix}${field.name}";
-    return new StubMethod(getterName, code, needsTearOff: false);
+    String getterName = "${namer.getterPrefix}${field.accessorName}";
+    return new StubMethod(getterName, code);
   }
 
   Method _generateSetter(Field field) {
@@ -330,7 +429,7 @@
     js.Expression fieldName = js.string(field.name);
     js.Expression code = js.js(setterTemplateFor(field.setterFlags), fieldName);
     String setterName = "${namer.setterPrefix}${field.name}";
-    return new StubMethod(setterName, code, needsTearOff: false);
+    return new StubMethod(setterName, code);
   }
 
   Iterable<Method> _generateGettersSetters(Class cls) {
@@ -363,10 +462,14 @@
     }
     Iterable<Method> methods = cls.methods;
     Iterable<Method> isChecks = cls.isChecks;
+    Iterable<Method> callStubs = cls.callStubs;
+    Iterable<Method> noSuchMethodStubs = cls.noSuchMethodStubs;
     Iterable<Method> gettersSetters = _generateGettersSetters(cls);
     Iterable<Method> allMethods =
-        [methods, isChecks, gettersSetters].expand((x) => x);
-    elements.addAll(allMethods.expand((e) => [js.string(e.name), e.code]));
+        [methods, isChecks, callStubs, noSuchMethodStubs, gettersSetters]
+            .expand((x) => x);
+    elements.addAll(allMethods.expand(emitInstanceMethod));
+
     return unparse(compiler, new js.ArrayInitializer(elements));
   }
 
@@ -375,8 +478,144 @@
     return unparse(compiler, field.code);
   }
 
-  js.Expression emitStaticMethod(StaticMethod method) {
-    return unparse(compiler, method.code);
+  /// JavaScript code template that implements parsing of a function descriptor.
+  /// Descriptors are used in place of the actual JavaScript function
+  /// definition in the output if additional information needs to be passed to
+  /// facilitate the generation of tearOffs at runtime. The format is an array
+  /// with the following fields:
+  ///
+  /// [Method.code]
+  /// [DartMethod.callName]
+  /// [DartMethod.tearOffName]
+  /// [JavaScriptBackend.isInterceptedMethod]
+  /// functionType
+  /// [InstanceMethod.aliasName]
+  ///
+  /// followed by
+  ///
+  /// [ParameterStubMethod.name]
+  /// [ParameterStubMethod.code]
+  ///
+  /// for each stub in [DartMethod.parameterStubs].
+
+  static final String parseFunctionDescriptorBoilerplate = r"""
+function parseFunctionDescriptor(proto, name, descriptor) {
+  if (descriptor instanceof Array) {
+    proto[name] = descriptor[0];
+    var funs = [descriptor[0]];
+    funs[0].$callName = descriptor[1];
+    for (var pos = 6; pos < descriptor.length; pos += 3) {
+      var stub = descriptor[pos + 2];
+      stub.$callName = descriptor[pos + 1];
+      proto[descriptor[pos]] = stub;
+      funs.push(stub);
+    }
+    if (descriptor[2] != null) {
+      var isIntercepted = descriptor[3];
+      var reflectionInfo = descriptor[4];
+      proto[descriptor[2]] = 
+          tearOff(funs, reflectionInfo, false, name, isIntercepted);
+    }
+    // Install the alias for super calls on the prototype chain.
+    if (descriptor[5] != null) {
+      proto[descriptor[5]] = descriptor[0];
+    }
+  } else {
+    proto[name] = descriptor;
+  }
+}
+""";
+
+  js.Expression _generateFunctionType(DartType memberType) {
+    if (memberType.containsTypeVariables) {
+      js.Expression thisAccess = js.js(r'this.$receiver');
+      return backend.rti.getSignatureEncoding(memberType, thisAccess);
+    } else {
+      return js.number(backend.emitter.metadataCollector.reifyType(memberType));
+    }
+  }
+
+  Iterable<js.Expression> emitInstanceMethod(Method method) {
+
+    List<js.Expression> makeNameCodePair(Method method) {
+      return [js.string(method.name), method.code];
+    }
+
+    List<js.Expression> makeNameCallNameCodeTriplet(ParameterStubMethod stub) {
+      js.Expression callName = stub.callName == null
+          ? new js.LiteralNull()
+          : js.string(stub.callName);
+      return [js.string(stub.name), callName, stub.code];
+    }
+
+    if (method is InstanceMethod) {
+      if (method.needsTearOff || method.aliasName != null) {
+        /// See [parseFunctionDescriptorBoilerplate] for a full description of
+        /// the format.
+        // [name, [function, callName, tearOffName, isIntercepted, functionType,
+        //     aliasName, stub1_name, stub1_callName, stub1_code, ...]
+        bool isIntercepted = backend.isInterceptedMethod(method.element);
+        var data = [method.code];
+        data.add(js.string(method.callName));
+        data.add(js.string(method.tearOffName));
+        data.add(new js.LiteralBool(isIntercepted));
+        data.add(_generateFunctionType(method.type));
+        if (method.aliasName != null) {
+          data.add(js.string(method.aliasName));
+        } else {
+          data.add(new js.LiteralNull());
+        }
+        data.addAll(method.parameterStubs.expand(makeNameCallNameCodeTriplet));
+        return [js.string(method.name), new js.ArrayInitializer(data)];
+      } else {
+        // TODO(floitsch): not the most efficient way...
+        return ([method]..addAll(method.parameterStubs))
+            .expand(makeNameCodePair);
+      }
+    } else {
+      return makeNameCodePair(method);
+    }
+  }
+
+  Iterable<js.Expression> emitStaticMethod(StaticMethod method) {
+    js.Expression holderIndex = js.number(method.holder.index);
+    List<js.Expression> output = <js.Expression>[];
+
+    void _addMethod(Method method) {
+      js.Expression unparsed = unparse(compiler, method.code);
+      output.add(js.string(method.name));
+      output.add(holderIndex);
+      output.add(unparsed);
+    }
+
+    List<js.Expression> makeNameCallNameCodeTriplet(ParameterStubMethod stub) {
+      js.Expression callName = stub.callName == null
+          ? new js.LiteralNull()
+          : js.string(stub.callName);
+      return [js.string(stub.name), callName, unparse(compiler, stub.code)];
+    }
+
+    _addMethod(method);
+    // TODO(floitsch): can there be anything else than a StaticDartMethod?
+    if (method is StaticDartMethod) {
+      if (method.needsTearOff) {
+        /// The format emitted is the same as for the parser specified at
+        /// [parseFunctionDescriptorBoilerplate] except for the missing
+        /// field whether the method is intercepted.
+        // [name, [function, callName, tearOffName, functionType,
+        //     stub1_name, stub1_callName, stub1_code, ...]
+        var data = [unparse(compiler, method.code)];
+        data.add(js.string(method.callName));
+        data.add(js.string(method.tearOffName));
+        data.add(_generateFunctionType(method.type));
+        data.addAll(method.parameterStubs.expand(makeNameCallNameCodeTriplet));
+        return [js.string(method.name), holderIndex,
+                new js.ArrayInitializer(data)];
+      } else {
+        method.parameterStubs.forEach(_addMethod);
+      }
+    }
+    return output;
   }
 
   static final String boilerplate = """
@@ -385,9 +624,12 @@
 #deferredInitializer;
 
 !function(start, program) {
-
   // Initialize holder objects.
   #holders;
+  var nativeInfos = Object.create(null);
+
+  // Counter to generate unique names for tear offs.
+  var functionCounter = 0;
 
   function setupProgram() {
     for (var i = 0; i < program.length - 1; i++) {
@@ -405,8 +647,27 @@
 
     var classes = library[1];
     for (var i = 0; i < classes.length; i += 3) {
-      var holderIndex = classes[i + 1];
-      setupClass(classes[i], holders[holderIndex], classes[i + 2]);
+      var name = classes[i];
+      var cls = classes[i + 1];
+
+      if (#hasNativeClasses) {
+        // $nativeInfoDescription.
+        var indexOrNativeInfo = classes[i + 2];
+        if (typeof indexOrNativeInfo == "number") {
+          var holderIndex = classes[i + 2];
+        } else {
+          nativeInfos[name] = indexOrNativeInfo;
+          holderIndex = classes[i + 3];
+          i++;
+        }
+      }
+
+      if (#hasNoNativeClasses) {
+        var holderIndex = classes[i + 2];
+      }
+
+      holdersMap[name] = holders[holderIndex];
+      setupClass(name, holders[holderIndex], cls);
     }
   }
 
@@ -421,11 +682,50 @@
   }
 
   function setupStatic(name, holder, descriptor) {
-    holder[name] = function() {
-      var method = compile(name, descriptor);
-      holder[name] = method;
-      return method.apply(this, arguments);
-    };
+    if (typeof descriptor == 'string') {
+      holder[name] = function() {
+        var method = compile(name, descriptor);
+        holder[name] = method;
+        return method.apply(this, arguments);
+      };
+    } else {
+      // Parse the tear off information and generate compile handlers.
+      // TODO(herhut): Share parser with instance methods.      
+      function compileAllStubs() {
+        var funs;
+        var fun = compile(name, descriptor[0]);
+        fun.\$callName = descriptor[1];
+        holder[name] = fun;
+        funs = [fun];
+        for (var pos = 4; pos < descriptor.length; pos += 3) {
+          var stubName = descriptor[pos];
+          fun = compile(stubName, descriptor[pos + 2]);
+          fun.\$callName = descriptor[pos + 1];
+          holder[stubName] = fun;
+          funs.push(fun);
+        }
+        if (descriptor[2] != null) {  // tear-off name.
+          // functions, reflectionInfo, isStatic, name, isIntercepted.
+          holder[descriptor[2]] = 
+              tearOff(funs, descriptor[3], true, name, false);
+        }
+      }
+
+      function setupCompileAllAndDelegateStub(name) {
+        holder[name] = function() {
+          compileAllStubs();
+          return holder[name].apply(this, arguments);
+        };
+      }
+
+      setupCompileAllAndDelegateStub(name);
+      for (var pos = 4; pos < descriptor.length; pos += 3) {
+        setupCompileAllAndDelegateStub(descriptor[pos]);
+      }
+      if (descriptor[2] != null) {  // tear-off name.
+        setupCompileAllAndDelegateStub(descriptor[2])
+      }
+    }
   }
 
   function setupLazyStatic(name, getterName, holder, descriptor) {
@@ -473,6 +773,10 @@
     holder[name] = patch;
   }
 
+  #tearOff;
+
+  #parseFunctionDescriptor;
+
   function compileConstructor(name, descriptor) {
     descriptor = compile(name, descriptor);
     var prototype = determinePrototype(descriptor);
@@ -481,16 +785,17 @@
     if (typeof descriptor[2] !== 'function') {
       constructor = compileMixinConstructor(name, prototype, descriptor);
       for (var i = 4; i < descriptor.length; i += 2) {
-        prototype[descriptor[i]] = descriptor[i + 1];
+        parseFunctionDescriptor(prototype, descriptor, descriptor[i + 1]);
       }
     } else {
       constructor = descriptor[2];
       for (var i = 3; i < descriptor.length; i += 2) {
-        prototype[descriptor[i]] = descriptor[i + 1];
+        parseFunctionDescriptor(prototype, descriptor[i], descriptor[i + 1]);
       }
     }
     constructor.builtin\$cls = name;  // Needed for RTI.
     constructor.prototype = prototype;
+    prototype[#operatorIsPrefix + name] = constructor;
     prototype.constructor = constructor;
     return constructor;
   }
@@ -546,19 +851,36 @@
     }
   }
 
+  if (#hasNativeClasses) {
+    function handleNativeClassInfos() {
+      for (var nativeClass in nativeInfos) {
+        var constructor = holdersMap[nativeClass][nativeClass].ensureResolved();
+        var nativeInfo = nativeInfos[nativeClass];
+        #nativeInfoHandler;
+      }
+    }
+  }
+
   setupProgram();
 
+  // Initialize constants.
+  #constants;
+
   // Initialize globals.
   #embeddedGlobals;
 
-  // Initialize constants.
-  #constants;
+  // TODO(floitsch): this order means that native classes may not be
+  // referenced from constants. I'm mostly afraid of things like using them as
+  // generic arguments (which should be fine, but maybe there are other
+  // similar things).
+  // Initialize natives.
+  if (#hasNativeClasses) handleNativeClassInfos();
 
   // Initialize static non-final fields.
   #staticNonFinals;
 
   // Add native boilerplate code.
-  #nativeBoilerplate;
+  #nativeIsolateAffinityTagInitialization;
 
   // Initialize eager classes.
   #eagerClasses;
diff --git a/pkg/compiler/lib/src/js_emitter/old_emitter/class_emitter.dart b/pkg/compiler/lib/src/js_emitter/old_emitter/class_emitter.dart
index 88c5f61..216b7d0 100644
--- a/pkg/compiler/lib/src/js_emitter/old_emitter/class_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/old_emitter/class_emitter.dart
@@ -12,9 +12,7 @@
   /**
    * Documentation wanted -- johnniwinther
    */
-  void emitClass(Class cls,
-                 ClassBuilder enclosingBuilder,
-                 Map<String, jsAst.Expression> additionalProperties) {
+  void emitClass(Class cls, ClassBuilder enclosingBuilder) {
     ClassElement classElement = cls.element;
 
     assert(invariant(classElement, classElement.isDeclaration));
@@ -43,9 +41,7 @@
     emitInstanceMembers(cls, builder);
     emitCallStubs(cls, builder);
     emitRuntimeTypeInformation(cls, builder);
-    if (additionalProperties != null) {
-      additionalProperties.forEach(builder.addProperty);
-    }
+    emitNativeInfo(cls, builder);
 
     if (classElement == backend.closureClass) {
       // We add a special getter here to allow for tearing off a closure from
@@ -123,7 +119,7 @@
       bool needsFieldsForConstructor = !emitStatics && !classIsNative;
       if (needsFieldsForConstructor || needsAccessor) {
         var metadata =
-            emitter.metadataEmitter.buildMetadataFunction(fieldElement);
+            task.metadataCollector.buildMetadataFunction(fieldElement);
         if (metadata != null) {
           hasMetadata = true;
         } else {
@@ -167,7 +163,7 @@
         }
         if (backend.isAccessibleByReflection(fieldElement)) {
           DartType type = fieldElement.type;
-          reflectionMarker = '-${emitter.metadataEmitter.reifyType(type)}';
+          reflectionMarker = '-${task.metadataCollector.reifyType(type)}';
         }
         String builtFieldname = '$fieldName$fieldCode$reflectionMarker';
         builder.addField(builtFieldname);
@@ -236,16 +232,16 @@
 
     if (cls.onlyForRti || cls.isMixinApplication) return;
 
-    void visitMember(ClassElement enclosing, Element member) {
-      assert(invariant(classElement, member.isDeclaration));
-      if (member.isInstanceMember) {
-        emitter.containerBuilder.addMember(member, builder);
-      }
+    // TODO(herhut): This is a no-op. Should it be removed?
+    for (Field field in cls.fields) {
+      emitter.containerBuilder.addMemberField(field, builder);
     }
 
-    classElement.implementation.forEachMember(
-        visitMember,
-        includeBackendMembers: true);
+    for (Method method in cls.methods) {
+      assert(invariant(classElement, method.element.isDeclaration));
+      assert(invariant(classElement, method.element.isInstanceMember));
+      emitter.containerBuilder.addMemberMethod(method, builder);
+    }
 
     if (identical(classElement, compiler.objectClass)
         && compiler.enabledNoSuchMethod) {
@@ -271,13 +267,19 @@
     }
   }
 
+  void emitNativeInfo(Class cls, ClassBuilder builder) {
+    if (cls.nativeInfo != null) {
+      builder.addProperty(namer.nativeSpecProperty, js.string(cls.nativeInfo));
+    }
+  }
+
   void emitClassBuilderWithReflectionData(Class cls,
                                           ClassBuilder classBuilder,
                                           ClassBuilder enclosingBuilder) {
     ClassElement classElement = cls.element;
     String className = cls.name;
 
-    var metadata = emitter.metadataEmitter.buildMetadataFunction(classElement);
+    var metadata = task.metadataCollector.buildMetadataFunction(classElement);
     if (metadata != null) {
       classBuilder.addProperty("@", metadata);
     }
@@ -330,10 +332,10 @@
       } else {
         List<int> types = <int>[];
         if (classElement.supertype != null) {
-          types.add(emitter.metadataEmitter.reifyType(classElement.supertype));
+          types.add(task.metadataCollector.reifyType(classElement.supertype));
         }
         for (DartType interface in classElement.interfaces) {
-          types.add(emitter.metadataEmitter.reifyType(interface));
+          types.add(task.metadataCollector.reifyType(interface));
         }
         enclosingBuilder.addProperty("+$reflectionName",
             new jsAst.ArrayInitializer(types.map(js.number).toList()));
diff --git a/pkg/compiler/lib/src/js_emitter/old_emitter/code_emitter_helper.dart b/pkg/compiler/lib/src/js_emitter/old_emitter/code_emitter_helper.dart
index 31ee925..568e2515 100644
--- a/pkg/compiler/lib/src/js_emitter/old_emitter/code_emitter_helper.dart
+++ b/pkg/compiler/lib/src/js_emitter/old_emitter/code_emitter_helper.dart
@@ -11,6 +11,8 @@
 
   JavaScriptBackend get backend => emitter.backend;
 
+  CodeEmitterTask get task => emitter.task;
+
   Compiler get compiler => emitter.compiler;
 
   String get n => emitter.n;
diff --git a/pkg/compiler/lib/src/js_emitter/old_emitter/container_builder.dart b/pkg/compiler/lib/src/js_emitter/old_emitter/container_builder.dart
index e79e424..ac8fdf7 100644
--- a/pkg/compiler/lib/src/js_emitter/old_emitter/container_builder.dart
+++ b/pkg/compiler/lib/src/js_emitter/old_emitter/container_builder.dart
@@ -9,359 +9,36 @@
 /// Initially, it is just a placeholder for code that is moved from
 /// [CodeEmitterTask].
 class ContainerBuilder extends CodeEmitterHelper {
-  bool needsSuperGetter(FunctionElement element) =>
-    compiler.codegenWorld.methodsNeedingSuperGetter.contains(element);
 
-  /**
-   * Generate stubs to handle invocation of methods with optional
-   * arguments.
-   *
-   * A method like [: foo([x]) :] may be invoked by the following
-   * calls: [: foo(), foo(1), foo(x: 1) :]. See the sources of this
-   * function for detailed examples.
-   */
-  void addParameterStub(FunctionElement member,
-                        Selector selector,
-                        AddStubFunction addStub,
-                        Set<String> alreadyGenerated) {
+  void addMemberMethod(DartMethod method, ClassBuilder builder) {
+    FunctionElement member = method.element;
+    String name = method.name;
     FunctionSignature parameters = member.functionSignature;
-    int positionalArgumentCount = selector.positionalArgumentCount;
-    if (positionalArgumentCount == parameters.parameterCount) {
-      assert(selector.namedArgumentCount == 0);
-      return;
-    }
-    if (parameters.optionalParametersAreNamed
-        && selector.namedArgumentCount == parameters.optionalParameterCount) {
-      // If the selector has the same number of named arguments as the element,
-      // we don't need to add a stub. The call site will hit the method
-      // directly.
-      return;
-    }
-    JavaScriptConstantCompiler handler = backend.constants;
-    List<String> names = selector.getOrderedNamedArguments();
+    jsAst.Expression code = method.code;
+    bool needsStubs = method.parameterStubs.isNotEmpty;
+    bool canBeApplied = method.canBeApplied;
+    bool canBeReflected = method.canBeReflected;
+    bool canTearOff = method.needsTearOff;
+    String tearOffName = method.tearOffName;
+    bool isClosure = method is InstanceMethod && method.isClosure;
+    String superAlias = method is InstanceMethod ? method.aliasName : null;
+    bool hasSuperAlias = superAlias != null;
 
-    String invocationName = namer.invocationName(selector);
-    if (alreadyGenerated.contains(invocationName)) return;
-    alreadyGenerated.add(invocationName);
-
-    bool isInterceptedMethod = backend.isInterceptedMethod(member);
-
-    // If the method is intercepted, we need to also pass the actual receiver.
-    int extraArgumentCount = isInterceptedMethod ? 1 : 0;
-    // Use '$receiver' to avoid clashes with other parameter names. Using
-    // '$receiver' works because [:namer.safeName:] used for getting parameter
-    // names never returns a name beginning with a single '$'.
-    String receiverArgumentName = r'$receiver';
-
-    // The parameters that this stub takes.
-    List<jsAst.Parameter> parametersBuffer =
-        new List<jsAst.Parameter>(selector.argumentCount + extraArgumentCount);
-    // The arguments that will be passed to the real method.
-    List<jsAst.Expression> argumentsBuffer =
-        new List<jsAst.Expression>(
-            parameters.parameterCount + extraArgumentCount);
-
-    int count = 0;
-    if (isInterceptedMethod) {
-      count++;
-      parametersBuffer[0] = new jsAst.Parameter(receiverArgumentName);
-      argumentsBuffer[0] = js('#', receiverArgumentName);
-      emitter.interceptorEmitter.interceptorInvocationNames.add(invocationName);
-    }
-
-    int optionalParameterStart = positionalArgumentCount + extraArgumentCount;
-    // Includes extra receiver argument when using interceptor convention
-    int indexOfLastOptionalArgumentInParameters = optionalParameterStart - 1;
-
-    int parameterIndex = 0;
-    parameters.orderedForEachParameter((ParameterElement element) {
-      String jsName = backend.namer.safeName(element.name);
-      assert(jsName != receiverArgumentName);
-      if (count < optionalParameterStart) {
-        parametersBuffer[count] = new jsAst.Parameter(jsName);
-        argumentsBuffer[count] = js('#', jsName);
-      } else {
-        int index = names.indexOf(element.name);
-        if (index != -1) {
-          indexOfLastOptionalArgumentInParameters = count;
-          // The order of the named arguments is not the same as the
-          // one in the real method (which is in Dart source order).
-          argumentsBuffer[count] = js('#', jsName);
-          parametersBuffer[optionalParameterStart + index] =
-              new jsAst.Parameter(jsName);
-        } else {
-          ConstantExpression constant = handler.getConstantForVariable(element);
-          if (constant == null) {
-            argumentsBuffer[count] =
-                emitter.constantReference(new NullConstantValue());
-          } else {
-            ConstantValue value = constant.value;
-            if (!value.isNull) {
-              // If the value is the null constant, we should not pass it
-              // down to the native method.
-              indexOfLastOptionalArgumentInParameters = count;
-            }
-            argumentsBuffer[count] = emitter.constantReference(value);
-          }
-        }
-      }
-      count++;
-    });
-
-    var body;  // List or jsAst.Statement.
-    if (member.hasFixedBackendName) {
-      body = emitter.nativeEmitter.generateParameterStubStatements(
-          member, isInterceptedMethod, invocationName,
-          parametersBuffer, argumentsBuffer,
-          indexOfLastOptionalArgumentInParameters);
-    } else if (member.isInstanceMember) {
-      if (needsSuperGetter(member)) {
-        ClassElement superClass = member.enclosingClass;
-        String methodName = namer.getNameOfInstanceMember(member);
-        // When redirecting, we must ensure that we don't end up in a subclass.
-        // We thus can't just invoke `this.foo$1.call(filledInArguments)`.
-        // Instead we need to call the statically resolved target.
-        //   `<class>.prototype.bar$1.call(this, argument0, ...)`.
-        body = js.statement(
-            'return #.#.call(this, #);',
-            [backend.emitter.prototypeAccess(superClass,
-                                             hasBeenInstantiated: true),
-             methodName,
-             argumentsBuffer]);
-      } else {
-        body = js.statement(
-            'return this.#(#);',
-            [namer.getNameOfInstanceMember(member), argumentsBuffer]);
-      }
-    } else {
-      body = js.statement('return #(#)',
-          [emitter.staticFunctionAccess(member), argumentsBuffer]);
-    }
-
-    jsAst.Fun function = js('function(#) { #; }', [parametersBuffer, body]);
-
-    addStub(selector, function);
-  }
-
-  void addParameterStubs(FunctionElement member, AddStubFunction defineStub,
-                         [bool canTearOff = false]) {
-    if (member.enclosingElement.isClosure) {
-      ClosureClassElement cls = member.enclosingElement;
-      if (cls.supertype.element == backend.boundClosureClass) {
-        compiler.internalError(cls.methodElement, 'Bound closure1.');
-      }
-      if (cls.methodElement.isInstanceMember) {
-        compiler.internalError(cls.methodElement, 'Bound closure2.');
-      }
-    }
-
-    // We fill the lists depending on the selector. For example,
-    // take method foo:
-    //    foo(a, b, {c, d});
-    //
-    // We may have multiple ways of calling foo:
-    // (1) foo(1, 2);
-    // (2) foo(1, 2, c: 3);
-    // (3) foo(1, 2, d: 4);
-    // (4) foo(1, 2, c: 3, d: 4);
-    // (5) foo(1, 2, d: 4, c: 3);
-    //
-    // What we generate at the call sites are:
-    // (1) foo$2(1, 2);
-    // (2) foo$3$c(1, 2, 3);
-    // (3) foo$3$d(1, 2, 4);
-    // (4) foo$4$c$d(1, 2, 3, 4);
-    // (5) foo$4$c$d(1, 2, 3, 4);
-    //
-    // The stubs we generate are (expressed in Dart):
-    // (1) foo$2(a, b) => foo$4$c$d(a, b, null, null)
-    // (2) foo$3$c(a, b, c) => foo$4$c$d(a, b, c, null);
-    // (3) foo$3$d(a, b, d) => foo$4$c$d(a, b, null, d);
-    // (4) No stub generated, call is direct.
-    // (5) No stub generated, call is direct.
-    //
-    // We need to pay attention if this stub is for a function that has been
-    // invoked from a subclass. Then we cannot just redirect, since that
-    // would invoke the methods of the subclass. We have to compile to:
-    // (1) foo$2(a, b) => MyClass.foo$4$c$d.call(this, a, b, null, null)
-    // (2) foo$3$c(a, b, c) => MyClass.foo$4$c$d(this, a, b, c, null);
-    // (3) foo$3$d(a, b, d) => MyClass.foo$4$c$d(this, a, b, null, d);
-
-    Set<Selector> selectors = member.isInstanceMember
-        ? compiler.codegenWorld.invokedNames[member.name]
-        : null; // No stubs needed for static methods.
-
-    /// Returns all closure call selectors renamed to match this member.
-    Set<Selector> callSelectorsAsNamed() {
-      if (!canTearOff) return null;
-      Set<Selector> callSelectors = compiler.codegenWorld.invokedNames[
-          namer.closureInvocationSelectorName];
-      if (callSelectors == null) return null;
-      return callSelectors.map((Selector callSelector) {
-        return new Selector.call(
-            member.name, member.library,
-            callSelector.argumentCount, callSelector.namedArguments);
-      }).toSet();
-    }
-    if (selectors == null) {
-      selectors = callSelectorsAsNamed();
-      if (selectors == null) return;
-    } else {
-      Set<Selector> callSelectors = callSelectorsAsNamed();
-      if (callSelectors != null) {
-        selectors = selectors.union(callSelectors);
-      }
-    }
-    Set<Selector> untypedSelectors = new Set<Selector>();
-    if (selectors != null) {
-      for (Selector selector in selectors) {
-        if (!selector.appliesUnnamed(member, compiler.world)) continue;
-        if (untypedSelectors.add(selector.asUntyped)) {
-          // TODO(ahe): Is the last argument to [addParameterStub] needed?
-          addParameterStub(member, selector, defineStub, new Set<String>());
-        }
-      }
-    }
-    if (canTearOff) {
-      selectors = compiler.codegenWorld.invokedNames[
-          namer.closureInvocationSelectorName];
-      if (selectors != null) {
-        for (Selector selector in selectors) {
-          selector = new Selector.call(
-              member.name, member.library,
-              selector.argumentCount, selector.namedArguments);
-          if (!selector.appliesUnnamed(member, compiler.world)) continue;
-          if (untypedSelectors.add(selector)) {
-            // TODO(ahe): Is the last argument to [addParameterStub] needed?
-            addParameterStub(member, selector, defineStub, new Set<String>());
-          }
-        }
-      }
-    }
-  }
-
-  void addMember(Element member, ClassBuilder builder) {
-    assert(invariant(member, member.isDeclaration));
-
-    if (member.isField) {
-      addMemberField(member, builder);
-    } else if (member.isFunction ||
-               member.isGenerativeConstructorBody ||
-               member.isGenerativeConstructor ||
-               member.isAccessor) {
-      addMemberMethod(member, builder);
-    } else {
-      compiler.internalError(member,
-          'Unexpected kind: "${member.kind}".');
-    }
-  }
-
-  void addMemberMethod(FunctionElement member, ClassBuilder builder) {
-    MemberInfo info = analyzeMemberMethod(member);
-    if (info != null) {
-      addMemberMethodFromInfo(info, builder);
-    }
-  }
-
-  MemberInfo analyzeMemberMethod(FunctionElement member) {
-    if (member.isAbstract) return null;
-    jsAst.Expression code = backend.generatedCode[member];
-    if (code == null) return null;
-    String name = namer.getNameOfMember(member);
-
-    FunctionSignature parameters = member.functionSignature;
-    bool needsStubs = !parameters.optionalParameters.isEmpty;
-    bool canTearOff = false;
-    bool isClosure = false;
-    bool isNotApplyTarget = !member.isFunction ||
-                            member.isConstructor ||
-                            member.isAccessor;
-    String tearOffName;
-
-
-    final bool canBeReflected = backend.isAccessibleByReflection(member) ||
-        // During incremental compilation, we have to assume that reflection
-        // *might* get enabled.
-        compiler.hasIncrementalSupport;
-
-    if (isNotApplyTarget) {
-      canTearOff = false;
-    } else if (member.isInstanceMember) {
-      if (member.enclosingClass.isClosure) {
-        canTearOff = false;
-        isClosure = true;
-      } else {
-        // Careful with operators.
-        canTearOff =
-            compiler.codegenWorld.hasInvokedGetter(member, compiler.world) ||
-            (canBeReflected && !member.isOperator);
-        assert(!needsSuperGetter(member) || canTearOff);
-        tearOffName = namer.getterName(member);
-      }
-    } else {
-      canTearOff =
-          compiler.codegenWorld.staticFunctionsNeedingGetter.contains(member) ||
-          canBeReflected;
-      tearOffName = namer.getStaticClosureName(member);
-    }
-    final bool canBeApplied = compiler.enabledFunctionApply &&
-                              compiler.world.getMightBePassedToApply(member);
-
-    final bool hasSuperAlias = backend.isAliasedSuperMember(member);
-
-    final bool needStructuredInfo =
+    bool needStructuredInfo =
         canTearOff || canBeReflected || canBeApplied || hasSuperAlias;
 
-
-    if (canTearOff) {
-      assert(invariant(member, !member.isGenerativeConstructor));
-      assert(invariant(member, !member.isGenerativeConstructorBody));
-      assert(invariant(member, !member.isConstructor));
-    }
-
-    return new MemberInfo(
-        member,
-        name,
-        parameters,
-        code,
-        needsStubs: needsStubs,
-        canTearOff: canTearOff,
-        isClosure: isClosure,
-        tearOffName: tearOffName,
-        canBeReflected: canBeReflected,
-        canBeApplied: canBeApplied,
-        hasSuperAlias: hasSuperAlias,
-        needStructuredInfo: needStructuredInfo
-    );
-  }
-
-  void addMemberMethodFromInfo(MemberInfo info, ClassBuilder builder) {
-    final FunctionElement member = info.member;
-    String name = info.name;
-    final FunctionSignature parameters = info.parameters;
-    jsAst.Expression code = info.code;
-    final bool needsStubs = info.needsStubs;
-    final bool canTearOff = info.canTearOff;
-    final bool isClosure = info.isClosure;
-    final String tearOffName = info.tearOffName;
-    final bool canBeReflected = info.canBeReflected;
-    final bool canBeApplied = info.canBeApplied;
-    final bool needStructuredInfo = info.needStructuredInfo;
-    final bool hasSuperAlias = info.hasSuperAlias;
-
     emitter.interceptorEmitter.recordMangledNameOfMemberMethod(member, name);
 
     if (!needStructuredInfo) {
       compiler.dumpInfoTask.registerElementAst(member,
           builder.addProperty(name, code));
-      if (needsStubs) {
-        addParameterStubs(
-            member,
-            (Selector selector, jsAst.Fun function) {
-              compiler.dumpInfoTask.registerElementAst(member,
-                  builder.addProperty(namer.invocationName(selector),
-                                      function));
-            });
+
+      for (ParameterStubMethod stub in method.parameterStubs) {
+        assert(stub.callName == null);
+        jsAst.Property property = builder.addProperty(stub.name, stub.code);
+        compiler.dumpInfoTask.registerElementAst(member, property);
+        emitter.interceptorEmitter
+            .recordMangledNameOfMemberMethod(member, stub.name);
       }
       return;
     }
@@ -398,14 +75,13 @@
     List<jsAst.Expression> expressions = <jsAst.Expression>[];
 
     // Create the optional aliasing entry if this method is called via super.
-    if (backend.isAliasedSuperMember(member)) {
-      expressions.add(new jsAst.LiteralString(
-          '"${namer.getNameOfAliasedSuperMember(member)}"'));
+    if (hasSuperAlias) {
+      expressions.add(new jsAst.LiteralString('"${superAlias}"'));
     }
 
     expressions.add(code);
 
-    final bool onlyNeedsSuperAlias =
+    bool onlyNeedsSuperAlias =
         !(canTearOff || canBeReflected || canBeApplied || needsStubs);
 
     if (onlyNeedsSuperAlias) {
@@ -417,9 +93,8 @@
     }
 
     String callSelectorString = 'null';
-    if (member.isFunction) {
-      Selector callSelector = new Selector.fromElement(member).toCallSelector();
-      callSelectorString = '"${namer.invocationName(callSelector)}"';
+    if (method.callName != null) {
+      callSelectorString = '"${method.callName}"';
     }
 
     // On [requiredParameterCount], the lower bit is set if this method can be
@@ -433,46 +108,34 @@
     // TODO(sra): Don't use LiteralString for non-strings.
     List tearOffInfo = [new jsAst.LiteralString(callSelectorString)];
 
-    if (needsStubs || canTearOff) {
-      addParameterStubs(member, (Selector selector, jsAst.Fun function) {
-        expressions.add(function);
-        if (member.isInstanceMember) {
-          Set invokedSelectors =
-              compiler.codegenWorld.invokedNames[member.name];
-            expressions.add(js.string(namer.invocationName(selector)));
-        } else {
-          expressions.add(js('null'));
-          // TOOD(ahe): Since we know when reading static data versus instance
-          // data, we can eliminate this element.
-        }
-        Set<Selector> callSelectors = compiler.codegenWorld.invokedNames[
-            namer.closureInvocationSelectorName];
-        Selector callSelector = selector.toCallSelector();
-        String callSelectorString = 'null';
-        if (canTearOff && callSelectors != null &&
-            callSelectors.contains(callSelector)) {
-          callSelectorString = '"${namer.invocationName(callSelector)}"';
-        }
-        tearOffInfo.add(new jsAst.LiteralString(callSelectorString));
-      }, canTearOff);
+    for (ParameterStubMethod stub in method.parameterStubs) {
+      String invocationName = stub.name;
+      emitter.interceptorEmitter
+          .recordMangledNameOfMemberMethod(member, invocationName);
+
+      expressions.add(stub.code);
+      if (member.isInstanceMember) {
+        expressions.add(js.string(invocationName));
+      } else {
+        // TOOD(floitsch): Since we know when reading static data versus
+        // instance data, we can eliminate this element.
+        expressions.add(js('null'));
+      }
+      String callName = stub.callName;
+      String callSelectorString = (callName == null) ? 'null' : '"$callName"';
+      tearOffInfo.add(new jsAst.LiteralString(callSelectorString));
     }
 
     jsAst.Expression memberTypeExpression;
     if (canTearOff || canBeReflected) {
-      DartType memberType;
-      if (member.isGenerativeConstructorBody) {
-        var body = member;
-        memberType = body.constructor.type;
-      } else {
-        memberType = member.type;
-      }
+      DartType memberType = method.type;
       if (memberType.containsTypeVariables) {
         jsAst.Expression thisAccess = js(r'this.$receiver');
         memberTypeExpression =
             backend.rti.getSignatureEncoding(memberType, thisAccess);
       } else {
         memberTypeExpression =
-            js.number(emitter.metadataEmitter.reifyType(memberType));
+            js.number(task.metadataCollector.reifyType(memberType));
       }
     } else {
       memberTypeExpression = js('null');
@@ -485,20 +148,20 @@
         ..add(js.number(requiredParameterCount))
         ..add(js.number(optionalParameterCount))
         ..add(memberTypeExpression)
-        ..addAll(emitter.metadataEmitter
+        ..addAll(task.metadataCollector
             .reifyDefaultArguments(member).map(js.number));
 
     if (canBeReflected || canBeApplied) {
       parameters.forEachParameter((Element parameter) {
         expressions.add(
-            js.number(emitter.metadataEmitter.reifyName(parameter.name)));
+            js.number(task.metadataCollector.reifyName(parameter.name)));
         if (backend.mustRetainMetadata) {
           Iterable<int> metadataIndices =
               parameter.metadata.map((MetadataAnnotation annotation) {
             ConstantValue constant =
                 backend.constants.getConstantForMetadata(annotation).value;
             backend.constants.addCompileTimeConstantForEmission(constant);
-            return emitter.metadataEmitter.reifyMetadata(annotation);
+            return task.metadataCollector.reifyMetadata(annotation);
           });
           expressions.add(new jsAst.ArrayInitializer(
               metadataIndices.map(js.number).toList()));
@@ -518,7 +181,7 @@
       }
       expressions
           ..add(reflectionName)
-          ..addAll(emitter.metadataEmitter
+          ..addAll(task.metadataCollector
               .computeMetadata(member).map(js.number));
     } else if (isClosure && canBeApplied) {
       expressions.add(js.string(namer.privateName(member.library,
@@ -531,60 +194,7 @@
         builder.addProperty(name, arrayInit));
   }
 
-  void addMemberField(VariableElement member, ClassBuilder builder) {
+  void addMemberField(Field field, ClassBuilder builder) {
     // For now, do nothing.
   }
 }
-
-class MemberInfo {
-  final FunctionElement member;
-
-  final String name;
-
-  final FunctionSignature parameters;
-
-  final jsAst.Expression code;
-
-  final bool needsStubs;
-
-  final bool canTearOff;
-
-  final bool isClosure;
-
-  final String tearOffName;
-
-  final bool canBeReflected;
-
-  final bool canBeApplied;
-
-  final bool needStructuredInfo;
-
-  final bool hasSuperAlias;
-
-  MemberInfo(
-      this.member,
-      this.name,
-      this.parameters,
-      this.code,
-      {this.needsStubs,
-       this.canTearOff,
-       this.isClosure,
-       this.tearOffName,
-       this.canBeReflected,
-       this.canBeApplied,
-       this.hasSuperAlias,
-       this.needStructuredInfo}) {
-    assert(member != null);
-    assert(name != null);
-    assert(parameters != null);
-    assert(code != null);
-    assert(needsStubs != null);
-    assert(canTearOff != null);
-    assert(isClosure != null);
-    assert(tearOffName != null || !canTearOff);
-    assert(canBeReflected != null);
-    assert(canBeApplied != null);
-    assert(hasSuperAlias != null);
-    assert(needStructuredInfo != null);
-  }
-}
diff --git a/pkg/compiler/lib/src/js_emitter/old_emitter/declarations.dart b/pkg/compiler/lib/src/js_emitter/old_emitter/declarations.dart
index 8177da7..4c2a922 100644
--- a/pkg/compiler/lib/src/js_emitter/old_emitter/declarations.dart
+++ b/pkg/compiler/lib/src/js_emitter/old_emitter/declarations.dart
@@ -8,11 +8,6 @@
 const DEBUG_FAST_OBJECTS = false;
 
 /**
- * Call-back for adding stub [function] for [selector].
- */
-typedef void AddStubFunction(Selector selector, jsAst.Fun function);
-
-/**
  * Call-back for adding property with [name] and [value].
  */
 typedef jsAst.Property AddPropertyFunction(String name, jsAst.Expression value);
diff --git a/pkg/compiler/lib/src/js_emitter/old_emitter/emitter.dart b/pkg/compiler/lib/src/js_emitter/old_emitter/emitter.dart
index aaca01c..25d4b43 100644
--- a/pkg/compiler/lib/src/js_emitter/old_emitter/emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/old_emitter/emitter.dart
@@ -13,7 +13,6 @@
   final ClassEmitter classEmitter = new ClassEmitter();
   final NsmEmitter nsmEmitter = new NsmEmitter();
   final InterceptorEmitter interceptorEmitter = new InterceptorEmitter();
-  final MetadataEmitter metadataEmitter = new MetadataEmitter();
 
   // TODO(johnniwinther): Wrap these fields in a caching strategy.
   final Set<ConstantValue> cachedEmittedConstants;
@@ -47,14 +46,10 @@
       => task.outputClassLists;
   Map<OutputUnit, List<ConstantValue>> get outputConstantLists
       => task.outputConstantLists;
-  List<ClassElement> get nativeClasses => task.nativeClasses;
   final Map<String, String> mangledFieldNames = <String, String>{};
   final Map<String, String> mangledGlobalFieldNames = <String, String>{};
   final Set<String> recordedMangledNames = new Set<String>();
 
-  final Map<Class, Map<String, jsAst.Expression>> additionalProperties =
-      new Map<Class, Map<String, jsAst.Expression>>();
-
   List<TypedefElement> get typedefsNeededForReflection =>
       task.typedefsNeededForReflection;
 
@@ -106,7 +101,6 @@
     classEmitter.emitter = this;
     nsmEmitter.emitter = this;
     interceptorEmitter.emitter = this;
-    metadataEmitter.emitter = this;
   }
 
   List<jsAst.Node> cspPrecompiledFunctionFor(OutputUnit outputUnit) {
@@ -324,7 +318,7 @@
     bool hasIsolateSupport = compiler.hasIsolateSupport;
     String fieldNamesProperty = FIELD_NAMES_PROPERTY_NAME;
 
-    jsAst.Expression defineClass = js('''
+    jsAst.Expression defineClass = js(r'''
         function(name, fields) {
           var accessors = [];
 
@@ -339,23 +333,25 @@
             if (#hasIsolateSupport) { fieldNames += "'" + field + "',"; }
             var parameter = "parameter_" + field;
             str += parameter;
-            body += ("this." + field + " = " + parameter + ";\\n");
+            body += ("this." + field + " = " + parameter + ";\n");
           }
-          str += ") {\\n" + body + "}\\n";
-          str += name + ".builtin\$cls=\\"" + name + "\\";\\n";
-          str += "\$desc=\$collectedClasses." + name + ";\\n";
-          str += "if(\$desc instanceof Array) \$desc = \$desc[1];\\n";
-          str += name + ".prototype = \$desc;\\n";
+          str += ") {\n" + body + "}\n";
+          str += name + ".builtin$cls=\"" + name + "\";\n";
+          str += "$desc=$collectedClasses." + name + ";\n";
+          str += "if($desc instanceof Array) $desc = \$desc[1];\n";
+          str += name + ".prototype = $desc;\n";
           if (typeof defineClass.name != "string") {
-            str += name + ".name=\\"" + name + "\\";\\n";
+            str += name + ".name=\"" + name + "\";\n";
           }
           if (#hasIsolateSupport) {
-            str += name + ".$fieldNamesProperty=[" + fieldNames + "];\\n";
+            str += name + "." + #fieldNamesProperty + "=[" + fieldNames
+                   + "];\n";
           }
           str += accessors.join("");
 
           return str;
-        }''', { 'hasIsolateSupport': hasIsolateSupport });
+        }''', { 'hasIsolateSupport': hasIsolateSupport,
+                'fieldNamesProperty': js.string(fieldNamesProperty)});
 
     // Declare a function called "generateAccessor".  This is used in
     // defineClassFunction.
@@ -426,6 +422,7 @@
               // Fix up the the Dart Object class' prototype.
               var prototype = constructor.prototype;
               prototype.constructor = constructor;
+              prototype.#isObject = constructor;
               return prototype;
             }
             tmp.prototype = superConstructor.prototype;
@@ -436,12 +433,16 @@
                 object[member] = properties[member];
               }
             }
+            // Use a function for `true` here, as functions are stored in the
+            // hidden class and not as properties in the object.
+            object[#operatorIsPrefix + constructor.name] = constructor;
             object.constructor = constructor;
             constructor.prototype = object;
             return object;
           };
         }()
-      ''');
+      ''', { 'operatorIsPrefix' : js.string(namer.operatorIsPrefix),
+             'isObject' : namer.operatorIs(compiler.objectClass) });
     if (compiler.hasIncrementalSupport) {
       result = js(
           r'#.inheritFrom = #', [namer.accessIncrementalHelper, result]);
@@ -449,15 +450,26 @@
     return js(r'var inheritFrom = #', [result]);
   }
 
-  jsAst.Statement buildFinishClass() {
+  jsAst.Statement buildFinishClass(bool hasNativeClasses) {
     String specProperty = '"${namer.nativeSpecProperty}"';  // "%"
 
     jsAst.Expression finishedClassesAccess =
         generateEmbeddedGlobalAccess(embeddedNames.FINISHED_CLASSES);
+
+    jsAst.Expression nativeInfoAccess = js('prototype[$specProperty]', []);
+    jsAst.Expression constructorAccess = js('constructor', []);
+    Function subclassReadGenerator =
+        (jsAst.Expression subclass) => js('allClasses[#]', subclass);
     jsAst.Expression interceptorsByTagAccess =
         generateEmbeddedGlobalAccess(embeddedNames.INTERCEPTORS_BY_TAG);
     jsAst.Expression leafTagsAccess =
         generateEmbeddedGlobalAccess(embeddedNames.LEAF_TAGS);
+    jsAst.Statement nativeInfoHandler = nativeEmitter.buildNativeInfoHandler(
+        nativeInfoAccess,
+        constructorAccess,
+        subclassReadGenerator,
+        interceptorsByTagAccess,
+        leafTagsAccess);
 
     return js.statement('''
     {
@@ -504,63 +516,14 @@
         var constructor = allClasses[cls];
         var prototype = inheritFrom(constructor, superConstructor);
 
-        if (#hasNativeClasses) {
-          // The property looks like this:
-          //
-          // HtmlElement: {
-          //     "%": "HTMLDivElement|HTMLAnchorElement;HTMLElement;FancyButton"
-          //
-          // The first two semicolon-separated parts contain dispatch tags, the
-          // third contains the JavaScript names for classes.
-          //
-          // The tags indicate that JavaScript objects with the dispatch tags
-          // (usually constructor names) HTMLDivElement, HTMLAnchorElement and
-          // HTMLElement all map to the Dart native class named HtmlElement.
-          // The first set is for effective leaf nodes in the hierarchy, the
-          // second set is non-leaf nodes.
-          //
-          // The third part contains the JavaScript names of Dart classes that
-          // extend the native class. Here, FancyButton extends HtmlElement, so
-          // the runtime needs to know that window.HTMLElement.prototype is the
-          // prototype that needs to be extended in creating the custom element.
-          //
-          // The information is used to build tables referenced by
-          // getNativeInterceptor and custom element support.
-          if (Object.prototype.hasOwnProperty.call(prototype, $specProperty)) {
-            var nativeSpec = prototype[$specProperty].split(";");
-            if (nativeSpec[0]) {
-              var tags = nativeSpec[0].split("|");
-              for (var i = 0; i < tags.length; i++) {
-                #interceptorsByTagAccess[tags[i]] = constructor;
-                #leafTagsAccess[tags[i]] = true;
-              }
-            }
-            if (nativeSpec[1]) {
-              tags = nativeSpec[1].split("|");
-              if (#allowNativesSubclassing) {
-                if (nativeSpec[2]) {
-                  var subclasses = nativeSpec[2].split("|");
-                  for (var i = 0; i < subclasses.length; i++) {
-                    var subclass = allClasses[subclasses[i]];
-                    subclass.#nativeSuperclassTagName = tags[0];
-                  }
-                }
-                for (i = 0; i < tags.length; i++) {
-                  #interceptorsByTagAccess[tags[i]] = constructor;
-                  #leafTagsAccess[tags[i]] = false;
-                }
-              }
-            }
-          }
-        }
+        if (#hasNativeClasses)
+          if (Object.prototype.hasOwnProperty.call(prototype, $specProperty))
+            #nativeInfoHandler
       }
     }''', {'finishedClassesAccess': finishedClassesAccess,
            'needsMixinSupport': needsMixinSupport,
-           'hasNativeClasses': nativeClasses.isNotEmpty,
-           'nativeSuperclassTagName': embeddedNames.NATIVE_SUPERCLASS_TAG_NAME,
-           'interceptorsByTagAccess': interceptorsByTagAccess,
-           'leafTagsAccess': leafTagsAccess,
-           'allowNativesSubclassing': true});
+           'hasNativeClasses': hasNativeClasses,
+           'nativeInfoHandler': nativeInfoHandler});
   }
 
   void emitFinishIsolateConstructorInvocation(CodeOutput output) {
@@ -722,8 +685,7 @@
         ClassBuilder cachedBuilder =
             cachedClassBuilders.putIfAbsent(classElement, () {
               ClassBuilder builder = new ClassBuilder(classElement, namer);
-              classEmitter.emitClass(
-                  cls, builder, additionalProperties[cls]);
+              classEmitter.emitClass(cls, builder);
               return builder;
             });
         invariant(classElement, cachedBuilder.fields.isEmpty);
@@ -732,22 +694,21 @@
         invariant(classElement, cachedBuilder.fieldMetadata == null);
         enclosingBuilder.properties.addAll(cachedBuilder.properties);
       } else {
-        classEmitter.emitClass(
-            cls, enclosingBuilder, additionalProperties[cls]);
+        classEmitter.emitClass(cls, enclosingBuilder);
       }
     });
   }
 
   void emitStaticFunctions(Iterable<Method> staticFunctions) {
     if (staticFunctions == null) return;
-    // We need to filter out null-elements for the interceptors.
-    Iterable<Element> elements = staticFunctions
-        .where((Method method) => method.element != null)
-        .map((Method method) => method.element);
 
-    for (Element element in elements) {
+    for (Method method in staticFunctions) {
+      Element element = method.element;
+      // We need to filter out null-elements for the interceptors.
+      // TODO(floitsch): use the precomputed interceptors here.
+      if (element == null) continue;
       ClassBuilder builder = new ClassBuilder(element, namer);
-      containerBuilder.addMember(element, builder);
+      containerBuilder.addMemberMethod(method, builder);
       getElementDescriptor(element).properties.addAll(builder.properties);
     }
   }
@@ -833,6 +794,23 @@
             code]);
   }
 
+  void emitMetadata(List<String> globalMetadata, CodeOutput output) {
+    String metadataAccess =
+        generateEmbeddedGlobalAccessString(embeddedNames.METADATA);
+    output.add('$metadataAccess$_=$_[');
+    for (String metadata in globalMetadata) {
+      if (metadata is String) {
+        if (metadata != 'null') {
+          output.add(metadata);
+        }
+      } else {
+        throw 'Unexpected value in metadata: ${Error.safeToString(metadata)}';
+      }
+      output.add(',$n');
+    }
+    output.add('];$n');
+  }
+
   bool isConstantInlinedOrAlreadyEmitted(ConstantValue constant) {
     if (constant.isFunction) return true;    // Already emitted.
     if (constant.isPrimitive) return true;   // Inlined.
@@ -1024,6 +1002,8 @@
     String isolate = namer.currentIsolate;
     jsAst.Expression allClassesAccess =
         generateEmbeddedGlobalAccess(embeddedNames.ALL_CLASSES);
+    jsAst.Expression getTypeFromNameAccess =
+        generateEmbeddedGlobalAccess(embeddedNames.GET_TYPE_FROM_NAME);
     jsAst.Expression interceptorsByTagAccess =
         generateEmbeddedGlobalAccess(embeddedNames.INTERCEPTORS_BY_TAG);
     jsAst.Expression leafTagsAccess =
@@ -1039,6 +1019,7 @@
       function init() {
         $isolateProperties = Object.create(null);
         #allClasses = Object.create(null);
+        #getTypeFromName = function(name) {return #allClasses[name];};
         #interceptorsByTag = Object.create(null);
         #leafTags = Object.create(null);
         #finishedClasses = Object.create(null);
@@ -1131,6 +1112,7 @@
       }
 
       }''', {'allClasses': allClassesAccess,
+            'getTypeFromName': getTypeFromNameAccess,
             'interceptorsByTag': interceptorsByTagAccess,
             'leafTags': leafTagsAccess,
             'finishedClasses': finishedClassesAccess,
@@ -1202,7 +1184,7 @@
         library.getLibraryName() :
         "";
 
-    jsAst.Fun metadata = metadataEmitter.buildMetadataFunction(library);
+    jsAst.Fun metadata = task.metadataCollector.buildMetadataFunction(library);
 
     jsAst.ObjectInitializer initializers = descriptor.toObjectInitializer();
 
@@ -1271,7 +1253,7 @@
       LibraryElement library = typedef.library;
       // TODO(karlklose): add a TypedefBuilder and move this code there.
       DartType type = typedef.alias;
-      int typeIndex = metadataEmitter.reifyType(type);
+      int typeIndex = task.metadataCollector.reifyType(type);
       ClassBuilder builder = new ClassBuilder(typedef, namer);
       builder.addProperty(embeddedNames.TYPEDEF_TYPE_PROPERTY_NAME,
                           js.number(typeIndex));
@@ -1375,8 +1357,7 @@
   }
 
   void emitMainOutputUnit(Program program,
-                          Map<OutputUnit, String> deferredLoadHashes,
-                          CodeBuffer nativeBuffer) {
+                          Map<OutputUnit, String> deferredLoadHashes) {
     Fragment mainFragment = program.fragments.first;
     OutputUnit mainOutputUnit = mainFragment.outputUnit;
 
@@ -1489,10 +1470,11 @@
       elementDescriptors.remove(library);
     }
 
+    bool hasNativeClasses = program.outputContainsNativeClasses;
     mainOutput
         ..addBuffer(
             jsAst.prettyPrint(
-                getReflectionDataParser(this, backend),
+                getReflectionDataParser(this, backend, hasNativeClasses),
                 compiler))
         ..add(n);
 
@@ -1527,13 +1509,12 @@
     // Static field initializations require the classes and compile-time
     // constants to be set up.
     emitStaticNonFinalFieldInitializations(mainOutput, mainOutputUnit);
-    interceptorEmitter.emitMapTypeToInterceptor(mainOutput);
+    interceptorEmitter.emitTypeToInterceptorMap(program, mainOutput);
     emitLazilyInitializedStaticFields(mainOutput);
 
     mainOutput.add('\n');
-    mainOutput.addBuffer(nativeBuffer);
 
-    metadataEmitter.emitMetadata(mainOutput);
+    emitMetadata(task.metadataCollector.globalMetadata, mainOutput);
 
     isolateProperties = isolatePropertiesName;
     // The following code should not use the short-hand for the
@@ -1765,32 +1746,6 @@
     return emitDeferredCode(program, outputBuffers);
   }
 
-  CodeBuffer buildNativesBuffer(Program program) {
-    // Emit native classes on [nativeBuffer].
-    // TODO(johnniwinther): Avoid creating a [CodeBuffer].
-    final CodeBuffer nativeBuffer = new CodeBuffer();
-
-    if (program.nativeClasses.isEmpty) return nativeBuffer;
-
-
-    addComment('Native classes', nativeBuffer);
-
-    List<Class> neededClasses =
-        nativeEmitter.prepareNativeClasses(program.nativeClasses,
-                                           additionalProperties);
-
-    for (Class cls in neededClasses) {
-      assert(cls.isNative);
-      ClassBuilder enclosingBuilder = getElementDescriptor(cls.element);
-      emitClass(cls, enclosingBuilder);
-    }
-
-    nativeEmitter.finishGenerateNativeClasses();
-    nativeEmitter.assembleCode(nativeBuffer);
-
-    return nativeBuffer;
-  }
-
   int emitProgram(ProgramBuilder programBuilder) {
     Program program = programBuilder.buildProgram(
         storeFunctionTypesInMetadata: true);
@@ -1805,8 +1760,7 @@
     // itself.
     Map<OutputUnit, String> deferredLoadHashes =
         emitDeferredOutputUnits(program);
-    CodeBuffer nativeBuffer = buildNativesBuffer(program);
-    emitMainOutputUnit(program, deferredLoadHashes, nativeBuffer);
+    emitMainOutputUnit(program, deferredLoadHashes);
 
     if (backend.requiresPreamble &&
         !backend.htmlLibraryIsLoaded) {
diff --git a/pkg/compiler/lib/src/js_emitter/old_emitter/interceptor_emitter.dart b/pkg/compiler/lib/src/js_emitter/old_emitter/interceptor_emitter.dart
index 189d392..6db7c71 100644
--- a/pkg/compiler/lib/src/js_emitter/old_emitter/interceptor_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/old_emitter/interceptor_emitter.dart
@@ -72,7 +72,6 @@
     // (which can easily be identified).
     if (!compiler.enabledInvokeOn) return null;
 
-    int index = 0;
     List<String> invocationNames = interceptorInvocationNames.toList()..sort();
     List<jsAst.Property> properties =
         new List<jsAst.Property>(invocationNames.length);
@@ -84,63 +83,17 @@
   }
 
   /**
-   * Emit initializer for [mapTypeToInterceptor] data structure used by
-   * [findInterceptorForType].  See declaration of [mapTypeToInterceptor] in
+   * Emit initializer for `typeToInterceptorMap` data structure used by
+   * `findInterceptorForType`.  See declaration of `typeToInterceptor` in
    * `interceptors.dart`.
    */
-  void emitMapTypeToInterceptor(CodeOutput output) {
-    // TODO(sra): Perhaps inject a constant instead?
-    CustomElementsAnalysis analysis = backend.customElementsAnalysis;
-    if (!analysis.needsTable) return;
+  void emitTypeToInterceptorMap(Program program, CodeOutput output) {
+    jsAst.Expression array = program.typeToInterceptorMap;
+    if (array == null) return;
 
-    List<jsAst.Expression> elements = <jsAst.Expression>[];
-    JavaScriptConstantCompiler handler = backend.constants;
-    List<ConstantValue> constants =
-        handler.getConstantsForEmission(emitter.compareConstants);
-    for (ConstantValue constant in constants) {
-      if (constant is TypeConstantValue) {
-        TypeConstantValue typeConstant = constant;
-        Element element = typeConstant.representedType.element;
-        if (element is ClassElement) {
-          ClassElement classElement = element;
-          if (!analysis.needsClass(classElement)) continue;
-
-          elements.add(emitter.constantReference(constant));
-          elements.add(backend.emitter.interceptorClassAccess(classElement));
-
-          // Create JavaScript Object map for by-name lookup of generative
-          // constructors.  For example, the class A has three generative
-          // constructors
-          //
-          //     class A {
-          //       A() {}
-          //       A.foo() {}
-          //       A.bar() {}
-          //     }
-          //
-          // Which are described by the map
-          //
-          //     {"": A.A$, "foo": A.A$foo, "bar": A.A$bar}
-          //
-          // We expect most of the time the map will be a singleton.
-          var properties = [];
-          for (Element member in analysis.constructors(classElement)) {
-            properties.add(
-                new jsAst.Property(
-                    js.string(member.name),
-                    backend.emitter.staticFunctionAccess(member)));
-          }
-
-          var map = new jsAst.ObjectInitializer(properties);
-          elements.add(map);
-        }
-      }
-    }
-
-    jsAst.ArrayInitializer array = new jsAst.ArrayInitializer(elements);
-    jsAst.Expression mapTypeToInterceptor = emitter
-        .generateEmbeddedGlobalAccess(embeddedNames.MAP_TYPE_TO_INTERCEPTOR);
-    jsAst.Expression assignment = js('# = #', [mapTypeToInterceptor, array]);
+    jsAst.Expression typeToInterceptorMap = emitter
+        .generateEmbeddedGlobalAccess(embeddedNames.TYPE_TO_INTERCEPTOR_MAP);
+    jsAst.Expression assignment = js('# = #', [typeToInterceptorMap, array]);
 
     output.addBuffer(jsAst.prettyPrint(assignment, compiler));
     output.add(N);
diff --git a/pkg/compiler/lib/src/js_emitter/old_emitter/nsm_emitter.dart b/pkg/compiler/lib/src/js_emitter/old_emitter/nsm_emitter.dart
index 3096ff7..93f866b 100644
--- a/pkg/compiler/lib/src/js_emitter/old_emitter/nsm_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/old_emitter/nsm_emitter.dart
@@ -19,102 +19,40 @@
   static const MAX_MINIFIED_LENGTH_FOR_DIFF_ENCODING = 4;
 
   void emitNoSuchMethodHandlers(AddPropertyFunction addProperty) {
-    // Do not generate no such method handlers if there is no class.
-    if (compiler.codegenWorld.directlyInstantiatedClasses.isEmpty) return;
 
-    String noSuchMethodName = namer.publicInstanceMethodNameByArity(
-        Compiler.NO_SUCH_METHOD, Compiler.NO_SUCH_METHOD_ARG_COUNT);
+    ClassStubGenerator generator =
+        new ClassStubGenerator(compiler, namer, backend);
 
     // Keep track of the JavaScript names we've already added so we
     // do not introduce duplicates (bad for code size).
-    Map<String, Selector> addedJsNames = new Map<String, Selector>();
-
-    void addNoSuchMethodHandlers(String ignore, Set<Selector> selectors) {
-      // Cache the object class and type.
-      ClassElement objectClass = compiler.objectClass;
-      DartType objectType = objectClass.rawType;
-
-      for (Selector selector in selectors) {
-        TypeMask mask = selector.mask;
-        if (mask == null) {
-          mask = new TypeMask.subclass(compiler.objectClass, compiler.world);
-        }
-
-        if (!mask.needsNoSuchMethodHandling(selector, compiler.world)) continue;
-        String jsName = namer.invocationMirrorInternalName(selector);
-        addedJsNames[jsName] = selector;
-        String reflectionName = emitter.getReflectionName(selector, jsName);
-        if (reflectionName != null) {
-          emitter.mangledFieldNames[jsName] = reflectionName;
-        }
-      }
-    }
-
-    compiler.codegenWorld.invokedNames.forEach(addNoSuchMethodHandlers);
-    compiler.codegenWorld.invokedGetters.forEach(addNoSuchMethodHandlers);
-    compiler.codegenWorld.invokedSetters.forEach(addNoSuchMethodHandlers);
+    Map<String, Selector> addedJsNames
+        = generator.computeSelectorsForNsmHandlers();
 
     // Set flag used by generateMethod helper below.  If we have very few
     // handlers we use addProperty for them all, rather than try to generate
     // them at runtime.
     bool haveVeryFewNoSuchMemberHandlers =
         (addedJsNames.length < VERY_FEW_NO_SUCH_METHOD_HANDLERS);
-
-    jsAst.Expression generateMethod(String jsName, Selector selector) {
-      // Values match JSInvocationMirror in js-helper library.
-      int type = selector.invocationMirrorKind;
-      List<String> parameterNames =
-          new List.generate(selector.argumentCount, (i) => '\$$i');
-
-      List<jsAst.Expression> argNames =
-          selector.getOrderedNamedArguments().map((String name) =>
-              js.string(name)).toList();
-
-      String methodName = selector.invocationMirrorMemberName;
-      String internalName = namer.invocationMirrorInternalName(selector);
-      String reflectionName = emitter.getReflectionName(selector, internalName);
-      if (!haveVeryFewNoSuchMemberHandlers &&
-          isTrivialNsmHandler(type, argNames, selector, internalName) &&
-          reflectionName == null) {
-        trivialNsmHandlers.add(selector);
-        return null;
-      }
-
-      assert(backend.isInterceptedName(Compiler.NO_SUCH_METHOD));
-      jsAst.Expression expression =
-          js('''this.#noSuchMethodName(this,
-                    #createInvocationMirror(#methodName,
-                                            #internalName,
-                                            #type,
-                                            #arguments,
-                                            #namedArguments))''',
-             {'noSuchMethodName': noSuchMethodName,
-              'createInvocationMirror':
-                  backend.emitter.staticFunctionAccess(
-                      backend.getCreateInvocationMirror()),
-              'methodName':
-                  js.string(compiler.enableMinification
-                      ? internalName : methodName),
-              'internalName': js.string(internalName),
-              'type': js.number(type),
-              'arguments':
-                  new jsAst.ArrayInitializer(parameterNames.map(js).toList()),
-              'namedArguments': new jsAst.ArrayInitializer(argNames)});
-
-      if (backend.isInterceptedName(selector.name)) {
-        return js(r'function($receiver, #) { return # }',
-                  [parameterNames, expression]);
-      } else {
-        return js(r'function(#) { return # }', [parameterNames, expression]);
-      }
-    }
-
     for (String jsName in addedJsNames.keys.toList()..sort()) {
       Selector selector = addedJsNames[jsName];
-      jsAst.Expression method = generateMethod(jsName, selector);
-      if (method != null) {
-        addProperty(jsName, method);
-        String reflectionName = emitter.getReflectionName(selector, jsName);
+      String reflectionName = emitter.getReflectionName(selector, jsName);
+
+      if (reflectionName != null) {
+        emitter.mangledFieldNames[jsName] = reflectionName;
+      }
+
+      List<jsAst.Expression> argNames =
+               selector.getOrderedNamedArguments().map((String name) =>
+                   js.string(name)).toList();
+      int type = selector.invocationMirrorKind;
+      if (!haveVeryFewNoSuchMemberHandlers &&
+          isTrivialNsmHandler(type, argNames, selector, jsName) &&
+          reflectionName == null) {
+        trivialNsmHandlers.add(selector);
+      } else {
+        StubMethod method =
+            generator.generateStubForNoSuchMethod(jsName, selector);
+        addProperty(method.name, method.code);
         if (reflectionName != null) {
           bool accessible = compiler.world.allFunctions.filter(selector).any(
               (Element e) => backend.isAccessibleByReflection(e));
@@ -281,8 +219,6 @@
     ClassElement objectClass = compiler.objectClass;
     jsAst.Expression createInvocationMirror = backend.emitter
         .staticFunctionAccess(backend.getCreateInvocationMirror());
-    String noSuchMethodName = namer.publicInstanceMethodNameByArity(
-        Compiler.NO_SUCH_METHOD, Compiler.NO_SUCH_METHOD_ARG_COUNT);
     var type = 0;
     if (useDiffEncoding) {
       statements.add(js.statement('''{
@@ -386,7 +322,7 @@
         }
       }''', {
           'sliceOffsetParams': sliceOffsetParams,
-          'noSuchMethodName': noSuchMethodName,
+          'noSuchMethodName': namer.noSuchMethodName,
           'createInvocationMirror': createInvocationMirror,
           'names': minify ? 'shortNames' : 'longNames',
           'sliceOffsetArguments': sliceOffsetArguments}));
diff --git a/pkg/compiler/lib/src/js_emitter/old_emitter/reflection_data_parser.dart b/pkg/compiler/lib/src/js_emitter/old_emitter/reflection_data_parser.dart
index 9eacb14..ae053a1 100644
--- a/pkg/compiler/lib/src/js_emitter/old_emitter/reflection_data_parser.dart
+++ b/pkg/compiler/lib/src/js_emitter/old_emitter/reflection_data_parser.dart
@@ -18,12 +18,12 @@
 String get parseReflectionDataName => 'parseReflectionData';
 
 jsAst.Expression getReflectionDataParser(OldEmitter oldEmitter,
-                                         JavaScriptBackend backend) {
+                                         JavaScriptBackend backend,
+                                         bool hasNativeClasses) {
   Namer namer = backend.namer;
   Compiler compiler = backend.compiler;
   CodeEmitterTask emitter = backend.emitter;
 
-  String metadataField = '"${namer.metadataField}"';
   String reflectableField = namer.reflectableField;
   String reflectionInfoField = namer.reflectionInfoField;
   String reflectionNameField = namer.reflectionNameField;
@@ -352,8 +352,6 @@
   jsAst.Expression allClassesAccess =
       emitter.generateEmbeddedGlobalAccess(embeddedNames.ALL_CLASSES);
 
-  String specProperty = '"${namer.nativeSpecProperty}"';  // "%"
-
   // Class descriptions are collected in a JS object.
   // 'finishClasses' takes all collected descriptions and sets up
   // the prototype.
@@ -414,7 +412,7 @@
 }''', {'allClasses': allClassesAccess,
        'debugFastObjects': DEBUG_FAST_OBJECTS,
        'isTreeShakingDisabled': backend.isTreeShakingDisabled,
-       'finishClassFunction': oldEmitter.buildFinishClass(),
+       'finishClassFunction': oldEmitter.buildFinishClass(hasNativeClasses),
        'trivialNsmHandlers': oldEmitter.buildTrivialNsmHandlers(),
        'inCspMode': compiler.useContentSecurityPolicy,
        'notInCspMode': !compiler.useContentSecurityPolicy});
@@ -456,91 +454,6 @@
       'needsStructuredMemberInfo': oldEmitter.needsStructuredMemberInfo});
 }
 
-
-List<jsAst.Statement> buildTearOffCode(JavaScriptBackend backend) {
-  Namer namer = backend.namer;
-  Compiler compiler = backend.compiler;
-
-  Element closureFromTearOff = backend.findHelper('closureFromTearOff');
-  String tearOffAccessText;
-  jsAst.Expression tearOffAccessExpression;
-  String tearOffGlobalObjectName;
-  String tearOffGlobalObject;
-  if (closureFromTearOff != null) {
-    // We need both the AST that references [closureFromTearOff] and a string
-    // for the NoCsp version that constructs a function.
-    tearOffAccessExpression =
-        backend.emitter.staticFunctionAccess(closureFromTearOff);
-    tearOffAccessText =
-        jsAst.prettyPrint(tearOffAccessExpression, compiler).getText();
-    tearOffGlobalObjectName = tearOffGlobalObject =
-        namer.globalObjectFor(closureFromTearOff);
-  } else {
-    // Default values for mocked-up test libraries.
-    tearOffAccessText =
-        r'''function() { throw 'Helper \'closureFromTearOff\' missing.' }''';
-    tearOffAccessExpression = js(tearOffAccessText);
-    tearOffGlobalObjectName = 'MissingHelperFunction';
-    tearOffGlobalObject = '($tearOffAccessText())';
-  }
-
-  jsAst.Statement tearOffGetter;
-  if (!compiler.useContentSecurityPolicy) {
-    // This template is uncached because it is constructed from code fragments
-    // that can change from compilation to compilation.  Some of these could be
-    // avoided, except for the string literals that contain the compiled access
-    // path to 'closureFromTearOff'.
-    tearOffGetter = js.uncachedStatementTemplate('''
-        function tearOffGetter(funcs, reflectionInfo, name, isIntercepted) {
-          return isIntercepted
-              ? new Function("funcs", "reflectionInfo", "name",
-                             "$tearOffGlobalObjectName", "c",
-                  "return function tearOff_" + name + (functionCounter++)+ "(x) {" +
-                    "if (c === null) c = $tearOffAccessText(" +
-                        "this, funcs, reflectionInfo, false, [x], name);" +
-                    "return new c(this, funcs[0], x, name);" +
-                  "}")(funcs, reflectionInfo, name, $tearOffGlobalObject, null)
-              : new Function("funcs", "reflectionInfo", "name",
-                             "$tearOffGlobalObjectName", "c",
-                  "return function tearOff_" + name + (functionCounter++)+ "() {" +
-                    "if (c === null) c = $tearOffAccessText(" +
-                        "this, funcs, reflectionInfo, false, [], name);" +
-                    "return new c(this, funcs[0], null, name);" +
-                  "}")(funcs, reflectionInfo, name, $tearOffGlobalObject, null);
-        }''').instantiate([]);
-  } else {
-    tearOffGetter = js.statement('''
-        function tearOffGetter(funcs, reflectionInfo, name, isIntercepted) {
-          var cache = null;
-          return isIntercepted
-              ? function(x) {
-                  if (cache === null) cache = #(
-                      this, funcs, reflectionInfo, false, [x], name);
-                  return new cache(this, funcs[0], x, name);
-                }
-              : function() {
-                  if (cache === null) cache = #(
-                      this, funcs, reflectionInfo, false, [], name);
-                  return new cache(this, funcs[0], null, name);
-                };
-        }''', [tearOffAccessExpression, tearOffAccessExpression]);
-  }
-
-  jsAst.Statement tearOff = js.statement('''
-    function tearOff(funcs, reflectionInfo, isStatic, name, isIntercepted) {
-      var cache;
-      return isStatic
-          ? function() {
-              if (cache === void 0) cache = #tearOff(
-                  this, funcs, reflectionInfo, true, [], name).prototype;
-              return cache;
-            }
-          : tearOffGetter(funcs, reflectionInfo, name, isIntercepted);
-    }''',  {'tearOff': tearOffAccessExpression});
-
-  return <jsAst.Statement>[tearOffGetter, tearOff];
-}
-
 String readString(String array, String index) {
   return readChecked(
       array, index, 'result != null && typeof result != "string"', 'string');
diff --git a/pkg/compiler/lib/src/js_emitter/parameter_stub_generator.dart b/pkg/compiler/lib/src/js_emitter/parameter_stub_generator.dart
new file mode 100644
index 0000000..3649219
--- /dev/null
+++ b/pkg/compiler/lib/src/js_emitter/parameter_stub_generator.dart
@@ -0,0 +1,280 @@
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of dart2js.js_emitter;
+
+class ParameterStubGenerator {
+  static final Set<Selector> emptySelectorSet = new Set<Selector>();
+
+  final Namer namer;
+  final Compiler compiler;
+  final JavaScriptBackend backend;
+
+  ParameterStubGenerator(this.compiler, this.namer, this.backend);
+
+  Emitter get emitter => backend.emitter.emitter;
+  CodeEmitterTask get emitterTask => backend.emitter;
+
+  bool needsSuperGetter(FunctionElement element) =>
+    compiler.codegenWorld.methodsNeedingSuperGetter.contains(element);
+
+  /**
+   * Generates stubs to handle invocation of methods with optional
+   * arguments.
+   *
+   * A method like `foo([x])` may be invoked by the following
+   * calls: `foo(), foo(1), foo(x: 1)`. This method generates the stub for the
+   * given [selector] and returns the generated [ParameterStubMethod].
+   *
+   * Returns null if no stub is needed.
+   *
+   * Members may be invoked in two ways: directly, or through a closure. In the
+   * latter case the caller invokes the closure's `call` method. This method
+   * accepts two selectors. The returned stub method has the corresponding
+   * name [ParameterStubMethod.name] and [ParameterStubMethod.callName] set if
+   * the input selector is non-null (and the member needs a stub).
+   */
+  ParameterStubMethod generateParameterStub(FunctionElement member,
+                                            Selector selector,
+                                            Selector callSelector) {
+    FunctionSignature parameters = member.functionSignature;
+    int positionalArgumentCount = selector.positionalArgumentCount;
+    if (positionalArgumentCount == parameters.parameterCount) {
+      assert(selector.namedArgumentCount == 0);
+      return null;
+    }
+    if (parameters.optionalParametersAreNamed
+        && selector.namedArgumentCount == parameters.optionalParameterCount) {
+      // If the selector has the same number of named arguments as the element,
+      // we don't need to add a stub. The call site will hit the method
+      // directly.
+      return null;
+    }
+    JavaScriptConstantCompiler handler = backend.constants;
+    List<String> names = selector.getOrderedNamedArguments();
+
+    bool isInterceptedMethod = backend.isInterceptedMethod(member);
+
+    // If the method is intercepted, we need to also pass the actual receiver.
+    int extraArgumentCount = isInterceptedMethod ? 1 : 0;
+    // Use '$receiver' to avoid clashes with other parameter names. Using
+    // '$receiver' works because [:namer.safeName:] used for getting parameter
+    // names never returns a name beginning with a single '$'.
+    String receiverArgumentName = r'$receiver';
+
+    // The parameters that this stub takes.
+    List<jsAst.Parameter> parametersBuffer =
+        new List<jsAst.Parameter>(selector.argumentCount + extraArgumentCount);
+    // The arguments that will be passed to the real method.
+    List<jsAst.Expression> argumentsBuffer =
+        new List<jsAst.Expression>(
+            parameters.parameterCount + extraArgumentCount);
+
+    int count = 0;
+    if (isInterceptedMethod) {
+      count++;
+      parametersBuffer[0] = new jsAst.Parameter(receiverArgumentName);
+      argumentsBuffer[0] = js('#', receiverArgumentName);
+    }
+
+    int optionalParameterStart = positionalArgumentCount + extraArgumentCount;
+    // Includes extra receiver argument when using interceptor convention
+    int indexOfLastOptionalArgumentInParameters = optionalParameterStart - 1;
+
+    int parameterIndex = 0;
+    parameters.orderedForEachParameter((ParameterElement element) {
+      String jsName = backend.namer.safeName(element.name);
+      assert(jsName != receiverArgumentName);
+      if (count < optionalParameterStart) {
+        parametersBuffer[count] = new jsAst.Parameter(jsName);
+        argumentsBuffer[count] = js('#', jsName);
+      } else {
+        int index = names.indexOf(element.name);
+        if (index != -1) {
+          indexOfLastOptionalArgumentInParameters = count;
+          // The order of the named arguments is not the same as the
+          // one in the real method (which is in Dart source order).
+          argumentsBuffer[count] = js('#', jsName);
+          parametersBuffer[optionalParameterStart + index] =
+              new jsAst.Parameter(jsName);
+        } else {
+          ConstantExpression constant = handler.getConstantForVariable(element);
+          if (constant == null) {
+            argumentsBuffer[count] =
+                emitter.constantReference(new NullConstantValue());
+          } else {
+            ConstantValue value = constant.value;
+            if (!value.isNull) {
+              // If the value is the null constant, we should not pass it
+              // down to the native method.
+              indexOfLastOptionalArgumentInParameters = count;
+            }
+            argumentsBuffer[count] = emitter.constantReference(value);
+          }
+        }
+      }
+      count++;
+    });
+
+    var body;  // List or jsAst.Statement.
+    if (member.hasFixedBackendName) {
+      body = emitterTask.nativeEmitter.generateParameterStubStatements(
+          member, isInterceptedMethod, namer.invocationName(selector),
+          parametersBuffer, argumentsBuffer,
+          indexOfLastOptionalArgumentInParameters);
+    } else if (member.isInstanceMember) {
+      if (needsSuperGetter(member)) {
+        ClassElement superClass = member.enclosingClass;
+        String methodName = namer.getNameOfInstanceMember(member);
+        // When redirecting, we must ensure that we don't end up in a subclass.
+        // We thus can't just invoke `this.foo$1.call(filledInArguments)`.
+        // Instead we need to call the statically resolved target.
+        //   `<class>.prototype.bar$1.call(this, argument0, ...)`.
+        body = js.statement(
+            'return #.#.call(this, #);',
+            [backend.emitter.prototypeAccess(superClass,
+                                             hasBeenInstantiated: true),
+             methodName,
+             argumentsBuffer]);
+      } else {
+        body = js.statement(
+            'return this.#(#);',
+            [namer.getNameOfInstanceMember(member), argumentsBuffer]);
+      }
+    } else {
+      body = js.statement('return #(#)',
+          [emitter.staticFunctionAccess(member), argumentsBuffer]);
+    }
+
+    jsAst.Fun function = js('function(#) { #; }', [parametersBuffer, body]);
+
+    String name = namer.invocationName(selector);
+    String callName =
+        (callSelector != null) ? namer.invocationName(callSelector) : null;
+    return new ParameterStubMethod(name, callName, function);
+  }
+
+  // We fill the lists depending on possible/invoked selectors. For example,
+  // take method foo:
+  //    foo(a, b, {c, d});
+  //
+  // We may have multiple ways of calling foo:
+  // (1) foo(1, 2);
+  // (2) foo(1, 2, c: 3);
+  // (3) foo(1, 2, d: 4);
+  // (4) foo(1, 2, c: 3, d: 4);
+  // (5) foo(1, 2, d: 4, c: 3);
+  //
+  // What we generate at the call sites are:
+  // (1) foo$2(1, 2);
+  // (2) foo$3$c(1, 2, 3);
+  // (3) foo$3$d(1, 2, 4);
+  // (4) foo$4$c$d(1, 2, 3, 4);
+  // (5) foo$4$c$d(1, 2, 3, 4);
+  //
+  // The stubs we generate are (expressed in Dart):
+  // (1) foo$2(a, b) => foo$4$c$d(a, b, null, null)
+  // (2) foo$3$c(a, b, c) => foo$4$c$d(a, b, c, null);
+  // (3) foo$3$d(a, b, d) => foo$4$c$d(a, b, null, d);
+  // (4) No stub generated, call is direct.
+  // (5) No stub generated, call is direct.
+  //
+  // We need to pay attention if this stub is for a function that has been
+  // invoked from a subclass. Then we cannot just redirect, since that
+  // would invoke the methods of the subclass. We have to compile to:
+  // (1) foo$2(a, b) => MyClass.foo$4$c$d.call(this, a, b, null, null)
+  // (2) foo$3$c(a, b, c) => MyClass.foo$4$c$d(this, a, b, c, null);
+  // (3) foo$3$d(a, b, d) => MyClass.foo$4$c$d(this, a, b, null, d);
+  List<ParameterStubMethod> generateParameterStubs(FunctionElement member,
+                                                 {bool canTearOff: true}) {
+    if (member.enclosingElement.isClosure) {
+      ClosureClassElement cls = member.enclosingElement;
+      if (cls.supertype.element == backend.boundClosureClass) {
+        compiler.internalError(cls.methodElement, 'Bound closure1.');
+      }
+      if (cls.methodElement.isInstanceMember) {
+        compiler.internalError(cls.methodElement, 'Bound closure2.');
+      }
+    }
+
+    // The set of selectors that apply to `member`. For example, for
+    // a member `foo(x, [y])` the following selectors may apply:
+    // `foo(x)`, and `foo(x, y)`.
+    Set<Selector> selectors;
+    // The set of selectors that apply to `member` if it's name was `call`.
+    // This happens when a member is torn off. In that case calls to the
+    // function use the name `call`, and we must be able to handle every
+    // `call` invocation that matches the signature. For example, for
+    // a member `foo(x, [y])` the following selectors would be possible
+    // call-selectors: `call(x)`, and `call(x, y)`.
+    Set<Selector> callSelectors;
+
+    // Only instance members (not static methods) need stubs.
+    if (member.isInstanceMember) {
+        selectors = compiler.codegenWorld.invokedNames[member.name];
+    }
+
+    if (canTearOff) {
+      String call = namer.closureInvocationSelectorName;
+      callSelectors = compiler.codegenWorld.invokedNames[call];
+    }
+
+    assert(emptySelectorSet.isEmpty);
+    if (selectors == null) selectors = emptySelectorSet;
+    if (callSelectors == null) callSelectors = emptySelectorSet;
+
+    List<ParameterStubMethod> stubs = <ParameterStubMethod>[];
+
+    if (selectors.isEmpty && callSelectors.isEmpty) {
+      return stubs;
+    }
+
+    // For every call-selector the corresponding selector with the name of the
+    // member.
+    //
+    // For example, for the call-selector `call(x, y)` the renamed selector
+    // for member `foo` would be `foo(x, y)`.
+    Set<Selector> renamedCallSelectors =
+        callSelectors.isEmpty ? emptySelectorSet : new Set<Selector>();
+
+    Set<Selector> untypedSelectors = new Set<Selector>();
+
+    // Start with the callSelectors since they imply the generation of the
+    // non-call version.
+    for (Selector selector in callSelectors) {
+      Selector renamedSelector = new Selector.call(
+          member.name, member.library,
+          selector.argumentCount, selector.namedArguments);
+      renamedCallSelectors.add(renamedSelector);
+
+      if (!renamedSelector.appliesUnnamed(member, compiler.world)) continue;
+
+      if (untypedSelectors.add(renamedSelector.asUntyped)) {
+        ParameterStubMethod stub =
+            generateParameterStub(member, renamedSelector, selector);
+        if (stub != null) {
+          stubs.add(stub);
+        }
+      }
+    }
+
+    // Now run through the actual member selectors (eg. `foo$2(x, y)` and not
+    // `call$2(x, y)`. Some of them have already been generated because of the
+    // call-selectors (and they are in the renamedCallSelectors set.
+    for (Selector selector in selectors) {
+      if (renamedCallSelectors.contains(selector)) continue;
+      if (!selector.appliesUnnamed(member, compiler.world)) continue;
+
+      if (untypedSelectors.add(selector.asUntyped)) {
+        ParameterStubMethod stub =
+            generateParameterStub(member, selector, null);
+        if (stub != null) {
+          stubs.add(stub);
+        }
+      }
+    }
+
+    return stubs;
+  }
+}
diff --git a/pkg/compiler/lib/src/js_emitter/program_builder.dart b/pkg/compiler/lib/src/js_emitter/program_builder.dart
index 4e2f555..a6d6fe8 100644
--- a/pkg/compiler/lib/src/js_emitter/program_builder.dart
+++ b/pkg/compiler/lib/src/js_emitter/program_builder.dart
@@ -19,6 +19,7 @@
     ClassStubGenerator,
     CodeEmitterTask,
     InterceptorStubGenerator,
+    ParameterStubGenerator,
     TypeTestGenerator,
     TypeTestProperties;
 
@@ -58,6 +59,8 @@
   /// update field-initializers to point to the ConstantModel.
   final Map<ConstantValue, Constant> _constants = <ConstantValue, Constant>{};
 
+  Set<Class> _unneededNativeClasses;
+
   Program buildProgram({bool storeFunctionTypesInMetadata: false}) {
     this._storeFunctionTypesInMetadata = storeFunctionTypesInMetadata;
     // Note: In rare cases (mostly tests) output units can be empty. This
@@ -74,20 +77,12 @@
     // $ holder so we have to register that. Can we track if we have to?
     _registry.registerHolder(r'$');
 
-    MainFragment mainOutput = _buildMainOutput(_registry.mainLibrariesMap);
-    Iterable<Fragment> deferredOutputs = _registry.deferredLibrariesMap
-        .map((librariesMap) => _buildDeferredOutput(mainOutput, librariesMap));
-
-    List<Fragment> outputs = new List<Fragment>(_registry.librariesMapCount);
-    outputs[0] = mainOutput;
-    outputs.setAll(1, deferredOutputs);
-
-    List<Class> nativeClasses = _task.nativeClasses
-        .map((ClassElement classElement) {
-          Class result = _classes[classElement];
-          return (result == null) ? _buildClass(classElement) : result;
-        })
-        .toList();
+    // We need to run the native-preparation before we build the output. The
+    // preparation code, in turn needs the classes to be set up.
+    // We thus build the classes before building their containers.
+    _task.outputClassLists.forEach((OutputUnit _, List<ClassElement> classes) {
+      classes.forEach(_buildClass);
+    });
 
     // Resolve the superclass references after we've processed all the classes.
     _classes.forEach((ClassElement element, Class c) {
@@ -101,12 +96,33 @@
       }
     });
 
+    List<Class> nativeClasses = _task.nativeClassesAndSubclasses
+        .map((ClassElement classElement) => _classes[classElement])
+        .toList();
+
+    _unneededNativeClasses =
+        _task.nativeEmitter.prepareNativeClasses(nativeClasses);
+
+    MainFragment mainOutput = _buildMainOutput(_registry.mainLibrariesMap);
+    Iterable<Fragment> deferredOutputs = _registry.deferredLibrariesMap
+        .map((librariesMap) => _buildDeferredOutput(mainOutput, librariesMap));
+
+    List<Fragment> outputs = new List<Fragment>(_registry.librariesMapCount);
+    outputs[0] = mainOutput;
+    outputs.setAll(1, deferredOutputs);
+
     _markEagerClasses();
 
-    return new Program(outputs,
-                       nativeClasses,
-                       _task.outputContainsConstantList,
-                       _buildLoadMap());
+    bool containsNativeClasses =
+        nativeClasses.length != _unneededNativeClasses.length;
+
+    return new Program(
+        outputs,
+        _buildLoadMap(),
+        _buildTypeToInterceptorMap(),
+        _task.metadataCollector,
+        outputContainsNativeClasses: containsNativeClasses,
+        outputContainsConstantList: _task.outputContainsConstantList);
   }
 
   void _markEagerClasses() {
@@ -115,11 +131,6 @@
 
   /// Builds a map from loadId to outputs-to-load.
   Map<String, List<Fragment>> _buildLoadMap() {
-    List<OutputUnit> convertHunks(List<OutputUnit> hunks) {
-      return hunks.map((OutputUnit unit) => _outputs[unit])
-          .toList(growable: false);
-    }
-
     Map<String, List<Fragment>> loadMap = <String, List<Fragment>>{};
     _compiler.deferredLoadTask.hunksToLoad
         .forEach((String loadId, List<OutputUnit> outputUnits) {
@@ -130,6 +141,12 @@
     return loadMap;
   }
 
+  js.Expression _buildTypeToInterceptorMap() {
+    InterceptorStubGenerator stubGenerator =
+        new InterceptorStubGenerator(_compiler, namer, backend);
+    return stubGenerator.generateTypeToInterceptorMap();
+  }
+
   MainFragment _buildMainOutput(LibrariesMap librariesMap) {
     // Construct the main output from the libraries and the registered holders.
     MainFragment result = new MainFragment(
@@ -211,7 +228,6 @@
   }
 
   StaticField _buildLazyField(Element element) {
-    JavaScriptConstantCompiler handler = backend.constants;
     js.Expression code = backend.generatedCode[element];
     // The code is null if we ended up not needing the lazily
     // initialized field after all because of constant folding
@@ -252,7 +268,9 @@
 
     List<Class> classes = elements
         .where((e) => e is ClassElement)
-        .map(_buildClass)
+        .map((ClassElement classElement) => _classes[classElement])
+        .where((Class cls) =>
+            !cls.isNative || !_unneededNativeClasses.contains(cls))
         .toList(growable: false);
 
     bool visitStatics = true;
@@ -262,25 +280,19 @@
                        staticFieldsForReflection);
   }
 
-  /// HACK for Try.
+  /// HACK for Incremental Compilation.
   ///
   /// Returns a class that contains the fields of a class.
-  Class buildClassWithFieldsForTry(ClassElement element) {
-    bool onlyForRti = _task.typeTestRegistry.rtiNeededClasses.contains(element);
+  Class buildFieldsHackForIncrementalCompilation(ClassElement element) {
+    assert(_compiler.hasIncrementalSupport);
 
-    List<Field> instanceFields =
-        onlyForRti ? const <Field>[] : _buildFields(element, false);
-
+    List<Field> instanceFields = _buildFields(element, false);
     String name = namer.getNameOfClass(element);
-    String holderName = namer.globalObjectFor(element);
-    Holder holder = _registry.registerHolder(holderName);
-    bool isInstantiated =
-        _compiler.codegenWorld.directlyInstantiatedClasses.contains(element);
 
     return new Class(
-        element, name, holder, [], instanceFields, [], [], [], null,
-        isDirectlyInstantiated: isInstantiated,
-        onlyForRti: onlyForRti,
+        element, name, null, [], instanceFields, [], [], [], [], null,
+        isDirectlyInstantiated: true,
+        onlyForRti: false,
         isNative: element.isNative);
   }
 
@@ -290,23 +302,26 @@
     List<Method> methods = [];
     List<StubMethod> callStubs = <StubMethod>[];
 
+    ClassStubGenerator classStubGenerator =
+        new ClassStubGenerator(_compiler, namer, backend);
+
     void visitMember(ClassElement enclosing, Element member) {
       assert(invariant(element, member.isDeclaration));
       assert(invariant(element, element == enclosing));
 
       if (Elements.isNonAbstractInstanceMember(member)) {
         js.Expression code = backend.generatedCode[member];
-        // TODO(kasperl): Figure out under which conditions code is null.
-        if (code != null) methods.add(_buildMethod(member, code));
+        // TODO(herhut): Remove once _buildMethod can no longer return null.
+        Method method = _buildMethod(member);
+        if (method != null) methods.add(method);
       }
       if (member.isGetter || member.isField) {
         Set<Selector> selectors =
             _compiler.codegenWorld.invokedNames[member.name];
         if (selectors != null && !selectors.isEmpty) {
-          ClassStubGenerator generator =
-              new ClassStubGenerator(_compiler, namer, backend);
+
           Map<String, js.Expression> callStubsForMember =
-              generator.generateCallStubsForGetter(member, selectors);
+              classStubGenerator.generateCallStubsForGetter(member, selectors);
           callStubsForMember.forEach((String name, js.Expression code) {
             callStubs.add(_buildStubMethod(name, code, element: member));
           });
@@ -314,6 +329,17 @@
       }
     }
 
+    List<StubMethod> noSuchMethodStubs = <StubMethod>[];
+    if (element == _compiler.objectClass) {
+      Map<String, Selector> selectors =
+          classStubGenerator.computeSelectorsForNsmHandlers();
+      selectors.forEach((String name, Selector selector) {
+        noSuchMethodStubs
+            .add(classStubGenerator.generateStubForNoSuchMethod(name,
+                                                                selector));
+      });
+    }
+
     ClassElement implementation = element.implementation;
 
     // MixinApplications run through the members of their mixin. Here, we are
@@ -364,6 +390,7 @@
                          name, holder, methods, instanceFields,
                          staticFieldsForReflection,
                          callStubs,
+                         noSuchMethodStubs,
                          isChecks,
                          typeTests.functionTypeIndex,
                          isDirectlyInstantiated: isInstantiated,
@@ -374,10 +401,107 @@
     return result;
   }
 
-  Method _buildMethod(FunctionElement element, js.Expression code) {
+  bool _methodNeedsStubs(FunctionElement method) {
+    return !method.functionSignature.optionalParameters.isEmpty;
+  }
+
+  bool _methodCanBeReflected(FunctionElement method) {
+    return backend.isAccessibleByReflection(method) ||
+        // During incremental compilation, we have to assume that reflection
+        // *might* get enabled.
+        _compiler.hasIncrementalSupport;
+  }
+
+  bool _methodCanBeApplied(FunctionElement method) {
+    return _compiler.enabledFunctionApply &&
+        _compiler.world.getMightBePassedToApply(method);
+  }
+
+  // TODO(herhut): Refactor incremental compilation and remove method.
+  Method buildMethodHackForIncrementalCompilation(FunctionElement element) {
+    assert(_compiler.hasIncrementalSupport);
+    if (element.isInstanceMember) {
+      return _buildMethod(element);
+    } else {
+      return _buildStaticMethod(element);
+    }
+  }
+
+  DartMethod _buildMethod(FunctionElement element) {
     String name = namer.getNameOfInstanceMember(element);
-    // TODO(floitsch): compute `needsTearOff`.
-    return new Method(element, name, code, needsTearOff: false);
+    js.Expression code = backend.generatedCode[element];
+
+    // TODO(kasperl): Figure out under which conditions code is null.
+    if (code == null) return null;
+
+    bool canTearOff = false;
+    String tearOffName;
+    bool isClosure = false;
+    bool isNotApplyTarget = !element.isFunction || element.isAccessor;
+
+    bool canBeReflected = _methodCanBeReflected(element);
+    bool needsStubs = _methodNeedsStubs(element);
+    bool canBeApplied = _methodCanBeApplied(element);
+
+    String aliasName = backend.isAliasedSuperMember(element)
+        ? namer.getNameOfAliasedSuperMember(element)
+        : null;
+
+    if (isNotApplyTarget) {
+      canTearOff = false;
+    } else {
+      if (element.enclosingClass.isClosure) {
+        canTearOff = false;
+        isClosure = true;
+      } else {
+        // Careful with operators.
+        canTearOff = universe.hasInvokedGetter(element, _compiler.world) ||
+            (canBeReflected && !element.isOperator);
+        assert(canTearOff ||
+               !universe.methodsNeedingSuperGetter.contains(element));
+        tearOffName = namer.getterName(element);
+      }
+    }
+
+    if (canTearOff) {
+      assert(invariant(element, !element.isGenerativeConstructor));
+      assert(invariant(element, !element.isGenerativeConstructorBody));
+      assert(invariant(element, !element.isConstructor));
+    }
+
+    String callName = null;
+    if (canTearOff) {
+      Selector callSelector =
+          new Selector.fromElement(element).toCallSelector();
+      callName = namer.invocationName(callSelector);
+    }
+
+    DartType memberType;
+    if (element.isGenerativeConstructorBody) {
+      // TODO(herhut): Why does this need to be normalized away? We never need
+      //               this information anyway as they cannot be torn off or
+      //               reflected.
+      var body = element;
+      memberType = body.constructor.type;
+    } else {
+      memberType = element.type;
+    }
+
+    return new InstanceMethod(element, name, code,
+        _generateParameterStubs(element, canTearOff), callName, memberType,
+        needsTearOff: canTearOff, tearOffName: tearOffName,
+        isClosure: isClosure, aliasName: aliasName,
+        canBeApplied: canBeApplied, canBeReflected: canBeReflected);
+  }
+
+  List<ParameterStubMethod> _generateParameterStubs(FunctionElement element,
+                                                    bool canTearOff) {
+
+    if (!_methodNeedsStubs(element)) return const <ParameterStubMethod>[];
+
+    ParameterStubGenerator generator =
+        new ParameterStubGenerator(_compiler, namer, backend);
+    return generator.generateParameterStubs(element, canTearOff: canTearOff);
   }
 
   /// Builds a stub method.
@@ -386,8 +510,7 @@
   /// attribution.
   Method _buildStubMethod(String name, js.Expression code,
                           {Element element}) {
-    // TODO(floitsch): compute `needsTearOff`.
-    return new StubMethod(name, code, needsTearOff: false, element: element);
+    return new StubMethod(name, code, element: element);
   }
 
   // The getInterceptor methods directly access the prototype of classes.
@@ -404,7 +527,7 @@
     }
   }
 
-  Iterable<StaticMethod> _generateGetInterceptorMethods() {
+  Iterable<StaticStubMethod> _generateGetInterceptorMethods() {
     InterceptorStubGenerator stubGenerator =
         new InterceptorStubGenerator(_compiler, namer, backend);
 
@@ -417,8 +540,7 @@
     return names.map((String name) {
       Set<ClassElement> classes = specializedGetInterceptors[name];
       js.Expression code = stubGenerator.generateGetInterceptorMethod(classes);
-      // TODO(floitsch): compute `needsTearOff`.
-      return new StaticStubMethod(name, holder, code, needsTearOff: false);
+      return new StaticStubMethod(name, holder, code);
     });
   }
 
@@ -468,7 +590,7 @@
     return fields;
   }
 
-  Iterable<StaticMethod> _generateOneShotInterceptors() {
+  Iterable<StaticStubMethod> _generateOneShotInterceptors() {
     InterceptorStubGenerator stubGenerator =
         new InterceptorStubGenerator(_compiler, namer, backend);
 
@@ -478,20 +600,41 @@
     List<String> names = backend.oneShotInterceptors.keys.toList()..sort();
     return names.map((String name) {
       js.Expression code = stubGenerator.generateOneShotInterceptor(name);
-      return new StaticStubMethod(name, holder, code, needsTearOff: false);
+      return new StaticStubMethod(name, holder, code);
     });
   }
 
-  StaticMethod _buildStaticMethod(FunctionElement element) {
+  StaticDartMethod _buildStaticMethod(FunctionElement element) {
     String name = namer.getNameOfMember(element);
     String holder = namer.globalObjectFor(element);
     js.Expression code = backend.generatedCode[element];
-    bool needsTearOff =
-        universe.staticFunctionsNeedingGetter.contains(element);
-    // TODO(floitsch): add tear-off name: namer.getStaticClosureName(element).
-    return new StaticMethod(element,
-                            name, _registry.registerHolder(holder), code,
-                            needsTearOff: needsTearOff);
+
+    bool isApplyTarget = !element.isConstructor && !element.isAccessor;
+    bool canBeApplied = _methodCanBeApplied(element);
+    bool canBeReflected = _methodCanBeReflected(element);
+
+    bool needsTearOff = isApplyTarget &&
+        (canBeReflected ||
+            universe.staticFunctionsNeedingGetter.contains(element));
+
+    String tearOffName =
+        needsTearOff ? namer.getStaticClosureName(element) : null;
+
+    String callName = null;
+    if (needsTearOff) {
+      Selector callSelector =
+          new Selector.fromElement(element).toCallSelector();
+      callName = namer.invocationName(callSelector);
+    }
+
+    return new StaticDartMethod(element,
+                                name, _registry.registerHolder(holder), code,
+                                _generateParameterStubs(element, needsTearOff),
+                                callName, element.type,
+                                needsTearOff: needsTearOff,
+                                tearOffName: tearOffName,
+                                canBeApplied: canBeApplied,
+                                canBeReflected: canBeReflected);
   }
 
   void _registerConstants(OutputUnit outputUnit,
diff --git a/pkg/compiler/lib/src/js_emitter/type_test_generator.dart b/pkg/compiler/lib/src/js_emitter/type_test_generator.dart
index f4b184f..bb2b0b9 100644
--- a/pkg/compiler/lib/src/js_emitter/type_test_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/type_test_generator.dart
@@ -28,7 +28,6 @@
   TypeTestGenerator(this.compiler, this.emitterTask, this.namer);
 
   JavaScriptBackend get backend => compiler.backend;
-  OldEmitter get oldEmitter => emitterTask.oldEmitter;
   TypeTestRegistry get typeTestRegistry => emitterTask.typeTestRegistry;
 
   Set<ClassElement> get checkedClasses =>
@@ -57,12 +56,16 @@
 
     TypeTestProperties result = new TypeTestProperties();
 
+    /// Generates an is-test if the test is not inherited from a superclass
+    /// This assumes that for every class an is-tests is generated
+    /// dynamically at runtime. We also always generate tests against
+    /// native classes.
+    /// TODO(herhut): Generate tests for native classes dynamically, as well.
     void generateIsTest(Element other) {
-      if (other == compiler.objectClass && other != classElement) {
-        // Avoid emitting `$isObject` on all classes but [Object].
-        return;
+      if (classElement.isNative ||
+          !classElement.isSubclassOf(other)) {
+        result.properties[namer.operatorIs(other)] = js('1');
       }
-      result.properties[namer.operatorIs(other)] = js('true');
     }
 
     void generateFunctionTypeSignature(FunctionElement method,
@@ -82,7 +85,8 @@
       }
 
       if (storeFunctionTypeInMetadata && !type.containsTypeVariables) {
-        result.functionTypeIndex = oldEmitter.metadataEmitter.reifyType(type);
+        result.functionTypeIndex =
+            emitterTask.metadataCollector.reifyType(type);
       } else {
         RuntimeTypes rti = backend.rti;
         jsAst.Expression encoding = rti.getSignatureEncoding(type, thisAccess);
@@ -96,7 +100,7 @@
       RuntimeTypes rti = backend.rti;
       jsAst.Expression expression;
       bool needsNativeCheck =
-          oldEmitter.nativeEmitter.requiresNativeIsCheck(cls);
+          emitterTask.nativeEmitter.requiresNativeIsCheck(cls);
       expression = rti.getSupertypeSubstitution(classElement, cls);
       if (expression == null && (emitNull || needsNativeCheck)) {
         expression = new jsAst.LiteralNull();
@@ -108,8 +112,7 @@
 
     void generateTypeCheck(TypeCheck check) {
       ClassElement checkedClass = check.cls;
-      // We must not call [generateIsTest] since we also want is$Object.
-      result.properties[namer.operatorIs(checkedClass)] = js('true');
+      generateIsTest(checkedClass);
       Substitution substitution = check.substitution;
       if (substitution != null) {
         jsAst.Expression body = substitution.getCode(backend.rti);
diff --git a/pkg/compiler/lib/src/patch_parser.dart b/pkg/compiler/lib/src/patch_parser.dart
index 80bf4c4..c6e90d5 100644
--- a/pkg/compiler/lib/src/patch_parser.dart
+++ b/pkg/compiler/lib/src/patch_parser.dart
@@ -135,9 +135,10 @@
 import 'util/util.dart';
 
 class PatchParserTask extends CompilerTask {
-  PatchParserTask(Compiler compiler): super(compiler);
   final String name = "Patching Parser";
 
+  PatchParserTask(Compiler compiler): super(compiler);
+
   /**
    * Scans a library patch file, applies the method patches and
    * injections to the library, and returns a list of class
@@ -181,38 +182,51 @@
     });
   }
 
-  void parsePatchClassNode(PartialClassElement element) {
+  void parsePatchClassNode(PartialClassElement cls) {
     // Parse [PartialClassElement] using a "patch"-aware parser instead
     // of calling its [parseNode] method.
-    if (element.cachedNode != null) return;
+    if (cls.cachedNode != null) return;
 
-    measure(() => compiler.withCurrentElement(element, () {
-      MemberListener listener = new MemberListener(compiler, element);
+    measure(() => compiler.withCurrentElement(cls, () {
+      MemberListener listener = new PatchMemberListener(compiler, cls);
       Parser parser = new PatchClassElementParser(listener);
       try {
-        Token token = parser.parseTopLevelDeclaration(element.beginToken);
-        assert(identical(token, element.endToken.next));
-      } on ParserError catch (e) {
+        Token token = parser.parseTopLevelDeclaration(cls.beginToken);
+        assert(identical(token, cls.endToken.next));
+      } on ParserError catch (e, s) {
         // No need to recover from a parser error in platform libraries, user
         // will never see this if the libraries are tested correctly.
         compiler.internalError(
-            element, "Parser error in patch file: $e");
+            cls, "Parser error in patch file: $e");
       }
-      element.cachedNode = listener.popNode();
+      cls.cachedNode = listener.popNode();
       assert(listener.nodes.isEmpty);
-
-      Link<Element> patches = element.localMembers;
-      applyContainerPatch(element.origin, patches);
     }));
   }
+}
 
-  void applyContainerPatch(ClassElement originClass,
-                           Link<Element> patches) {
-    for (Element patch in patches) {
-      if (!isPatchElement(compiler, patch)) continue;
+class PatchMemberListener extends MemberListener {
+  final Compiler compiler;
 
-      Element origin = originClass.localLookup(patch.name);
-      patchElement(compiler, origin, patch);
+  PatchMemberListener(Compiler compiler, ClassElement enclosingClass)
+      : this.compiler = compiler,
+        super(compiler, enclosingClass);
+
+  @override
+  void addMember(Element patch) {
+    addMetadata(patch);
+
+    PatchVersion patchVersion = getPatchVersion(compiler, patch);
+    if (patchVersion != null) {
+      if (patchVersion.isActive(compiler.patchVersion)) {
+        Element origin = enclosingClass.origin.localLookup(patch.name);
+        patchElement(compiler, origin, patch);
+        enclosingClass.addMember(patch, listener);
+      } else {
+        // Skip this element.
+      }
+    } else {
+      enclosingClass.addMember(patch, listener);
     }
   }
 }
@@ -239,13 +253,23 @@
     : this.compiler = compiler,
       super(compiler, patchElement, idGenerator);
 
+  @override
   void pushElement(Element patch) {
-    super.pushElement(patch);
-    if (isPatchElement(compiler, patch)) {
-      LibraryElement originLibrary = compilationUnitElement.library;
-      assert(originLibrary.isPatched);
-      Element origin = originLibrary.localLookup(patch.name);
-      patchElement(listener, origin, patch);
+    popMetadata(patch);
+
+    PatchVersion patchVersion = getPatchVersion(compiler, patch);
+    if (patchVersion != null) {
+      if (patchVersion.isActive(compiler.patchVersion)) {
+        LibraryElement originLibrary = compilationUnitElement.library;
+        assert(originLibrary.isPatched);
+        Element origin = originLibrary.localLookup(patch.name);
+        patchElement(listener, origin, patch);
+        compilationUnitElement.addMember(patch, listener);
+      } else {
+        // Skip this element.
+      }
+    } else {
+      compilationUnitElement.addMember(patch, listener);
     }
   }
 }
@@ -320,12 +344,13 @@
 ///   if it looks correct,
 /// - setup a deferred action to check that the annotation has a valid constant
 ///   value and report an internal error if not.
-abstract class EagerAnnotationHandler {
+abstract class EagerAnnotationHandler<T> {
   /// Checks that [annotation] looks like a matching annotation and optionally
-  /// applies actions on [element]. Returns `true` if the annotation matched.
-  bool apply(Compiler compiler,
-             Element element,
-             MetadataAnnotation annotation);
+  /// applies actions on [element]. Returns a non-null annotation marker if the
+  /// annotation matched and should be validated.
+  T apply(Compiler compiler,
+          Element element,
+          MetadataAnnotation annotation);
 
   /// Checks that the annotation value is valid.
   void validate(Compiler compiler,
@@ -334,16 +359,17 @@
                 ConstantValue constant);
 
 
-  /// Checks [element] for metadata matching the [handler]. Return `true` if
-  /// matching metadata was found.
-  static bool checkAnnotation(Compiler compiler,
+  /// Checks [element] for metadata matching the [handler]. Return a non-null
+  /// annotation marker matching metadata was found.
+  static checkAnnotation(Compiler compiler,
                               Element element,
                               EagerAnnotationHandler handler) {
     for (Link<MetadataAnnotation> link = element.metadata;
          !link.isEmpty;
          link = link.tail) {
       MetadataAnnotation annotation = link.head;
-      if (handler.apply(compiler, element, annotation)) {
+      var result = handler.apply(compiler, element, annotation);
+      if (result != null) {
         // TODO(johnniwinther): Perform this check in
         // [Compiler.onLibrariesLoaded].
         compiler.enqueuer.resolution.addDeferredAction(element, () {
@@ -351,16 +377,16 @@
           handler.validate(
               compiler, element, annotation, annotation.constant.value);
         });
-        return true;
+        return result;
       }
     }
-    return false;
+    return null;
   }
 }
 
 /// Annotation handler for pre-resolution detection of `@Native(...)`
 /// annotations.
-class NativeAnnotationHandler implements EagerAnnotationHandler {
+class NativeAnnotationHandler implements EagerAnnotationHandler<String> {
   const NativeAnnotationHandler();
 
   String getNativeAnnotation(MetadataAnnotation annotation) {
@@ -375,7 +401,7 @@
     return null;
   }
 
-  bool apply(Compiler compiler,
+  String apply(Compiler compiler,
              Element element,
              MetadataAnnotation annotation) {
     if (element.isClass) {
@@ -383,10 +409,10 @@
       if (native != null) {
         ClassElementX declaration = element.declaration;
         declaration.setNative(native);
-        return true;
+        return native;
       }
     }
-    return false;
+    return null;
   }
 
   void validate(Compiler compiler,
@@ -401,25 +427,36 @@
 }
 
 /// Annotation handler for pre-resolution detection of `@patch` annotations.
-class PatchAnnotationHandler implements EagerAnnotationHandler {
+class PatchAnnotationHandler implements EagerAnnotationHandler<PatchVersion> {
   const PatchAnnotationHandler();
 
-  bool isPatchAnnotation(MetadataAnnotation annotation) {
-    return annotation.beginToken != null &&
-           annotation.beginToken.next.value == 'patch';
+  PatchVersion getPatchVersion(MetadataAnnotation annotation) {
+    if (annotation.beginToken != null) {
+      if (annotation.beginToken.next.value == 'patch') {
+        return const PatchVersion(null);
+      } else if (annotation.beginToken.next.value == 'patch_old') {
+        return const PatchVersion('old');
+      } else if (annotation.beginToken.next.value == 'patch_new') {
+        return const PatchVersion('new');
+      }
+    }
+    return null;
   }
 
-  bool apply(Compiler compiler,
-             Element element,
-             MetadataAnnotation annotation) {
-    return isPatchAnnotation(annotation);
+  @override
+  PatchVersion apply(Compiler compiler,
+                     Element element,
+                     MetadataAnnotation annotation) {
+    return getPatchVersion(annotation);
   }
 
+  @override
   void validate(Compiler compiler,
                 Element element,
                 MetadataAnnotation annotation,
                 ConstantValue constant) {
-    if (constant != compiler.patchConstant) {
+    if (constant.getType(compiler.coreTypes).element !=
+            compiler.patchAnnotationClass) {
       compiler.internalError(annotation, 'Invalid patch annotation.');
     }
   }
@@ -520,8 +557,17 @@
   origin.applyPatch(patch);
 }
 
-// TODO(johnniwinther): Add unittest when patch is (real) metadata.
-bool isPatchElement(Compiler compiler, Element element) {
+PatchVersion getPatchVersion(Compiler compiler, Element element) {
   return EagerAnnotationHandler.checkAnnotation(compiler, element,
       const PatchAnnotationHandler());
 }
+
+class PatchVersion {
+  final String tag;
+
+  const PatchVersion(this.tag);
+
+  bool isActive(String patchTag) => tag == null || tag == patchTag;
+
+  String toString() => 'PatchVersion($tag)';
+}
\ No newline at end of file
diff --git a/pkg/compiler/lib/src/resolution/members.dart b/pkg/compiler/lib/src/resolution/members.dart
index d33f3f0..206a035 100644
--- a/pkg/compiler/lib/src/resolution/members.dart
+++ b/pkg/compiler/lib/src/resolution/members.dart
@@ -500,10 +500,6 @@
         compiler.reportError(asyncModifier,
             MessageKind.EXPERIMENTAL_ASYNC_AWAIT,
             {'modifier': element.asyncMarker});
-      } else if (!compiler.analyzeOnly) {
-        compiler.reportError(asyncModifier,
-            MessageKind.EXPERIMENTAL_ASYNC_AWAIT,
-            {'modifier': element.asyncMarker});
       }
 
       if (asyncModifier.isAsynchronous) {
@@ -520,11 +516,19 @@
         compiler.reportError(asyncModifier,
             MessageKind.ASYNC_MODIFIER_ON_CONSTRUCTOR,
             {'modifier': element.asyncMarker});
-      } else if (functionExpression.body.asReturn() != null &&
+      } else {
+        if (element.isSetter) {
+          compiler.reportError(asyncModifier,
+              MessageKind.ASYNC_MODIFIER_ON_SETTER,
+              {'modifier': element.asyncMarker});
+
+        }
+        if (functionExpression.body.asReturn() != null &&
                  element.asyncMarker.isYielding) {
-        compiler.reportError(asyncModifier,
-            MessageKind.YIELDING_MODIFIER_ON_ARROW_BODY,
-            {'modifier': element.asyncMarker});
+          compiler.reportError(asyncModifier,
+              MessageKind.YIELDING_MODIFIER_ON_ARROW_BODY,
+              {'modifier': element.asyncMarker});
+        }
       }
     }
   }
@@ -1465,7 +1469,7 @@
     Selector constructorSelector =
         visitor.getRedirectingThisOrSuperConstructorSelector(call);
     FunctionElement calledConstructor =
-        lookupTarget.lookupConstructor(constructorSelector);
+        lookupTarget.lookupConstructor(constructorSelector.name);
 
     final bool isImplicitSuperCall = false;
     final String className = lookupTarget.name;
@@ -1500,10 +1504,9 @@
       ClassElement lookupTarget = getSuperOrThisLookupTarget(constructor,
                                                              isSuperCall,
                                                              functionNode);
-      Selector constructorSelector = new Selector.callDefaultConstructor(
-          visitor.enclosingElement.library);
+      Selector constructorSelector = new Selector.callDefaultConstructor();
       Element calledConstructor = lookupTarget.lookupConstructor(
-          constructorSelector);
+          constructorSelector.name);
 
       final String className = lookupTarget.name;
       final bool isImplicitSuperCall = true;
@@ -2316,8 +2319,7 @@
           constructorName,
           enclosingElement.library);
     } else {
-      return new Selector.callDefaultConstructor(
-          enclosingElement.library);
+      return new Selector.callDefaultConstructor();
     }
   }
 
@@ -2333,7 +2335,7 @@
       Selector selector =
           getRedirectingThisOrSuperConstructorSelector(initializers.head);
       final ClassElement classElement = constructor.enclosingClass;
-      return classElement.lookupConstructor(selector);
+      return classElement.lookupConstructor(selector.name);
     }
     return null;
   }
@@ -4268,10 +4270,6 @@
 
   @override
   DartType visitEnum(Enum node) {
-    if (!compiler.enableEnums) {
-      compiler.reportError(node, MessageKind.EXPERIMENTAL_ENUMS);
-    }
-
     if (element == null) {
       throw compiler.internalError(node, 'element is null');
     }
@@ -4800,9 +4798,10 @@
     throw 'not supported';
   }
 
-  failOrReturnErroneousElement(Element enclosing, Node diagnosticNode,
-                               String targetName, MessageKind kind,
-                               Map arguments) {
+  failOrReturnErroneousConstructorElement(
+      Element enclosing, Node diagnosticNode,
+      String targetName, MessageKind kind,
+      Map arguments) {
     if (kind == MessageKind.CANNOT_FIND_CONSTRUCTOR) {
       registry.registerThrowNoSuchMethod();
     } else {
@@ -4813,29 +4812,20 @@
     } else {
       compiler.reportWarning(diagnosticNode, kind, arguments);
     }
-    return new ErroneousElementX(kind, arguments, targetName, enclosing);
-  }
-
-  Selector createConstructorSelector(String constructorName) {
-    return constructorName == ''
-        ? new Selector.callDefaultConstructor(
-            resolver.enclosingElement.library)
-        : new Selector.callConstructor(
-            constructorName,
-            resolver.enclosingElement.library);
+    return new ErroneousConstructorElementX(
+        kind, arguments, targetName, enclosing);
   }
 
   FunctionElement resolveConstructor(ClassElement cls,
                                      Node diagnosticNode,
                                      String constructorName) {
     cls.ensureResolved(compiler);
-    Selector selector = createConstructorSelector(constructorName);
-    Element result = cls.lookupConstructor(selector);
+    Element result = cls.lookupConstructor(constructorName);
     if (result == null) {
       String fullConstructorName = Elements.constructorNameForDiagnostics(
               cls.name,
               constructorName);
-      return failOrReturnErroneousElement(
+      return failOrReturnErroneousConstructorElement(
           cls,
           diagnosticNode,
           fullConstructorName,
@@ -4872,7 +4862,7 @@
         // The unnamed constructor may not exist, so [e] may become unresolved.
         element = resolveConstructor(cls, diagnosticNode, '');
       } else {
-        element = failOrReturnErroneousElement(
+        element = failOrReturnErroneousConstructorElement(
             element, diagnosticNode, element.name, MessageKind.NOT_A_TYPE,
             {'node': diagnosticNode});
       }
@@ -4922,7 +4912,7 @@
       element = prefix.lookupLocalMember(name.source);
       element = Elements.unwrap(element, compiler, node);
       if (element == null) {
-        return failOrReturnErroneousElement(
+        return failOrReturnErroneousConstructorElement(
             resolver.enclosingElement, name,
             name.source,
             MessageKind.CANNOT_RESOLVE,
@@ -4943,9 +4933,10 @@
     registry.useElement(node, element);
     // TODO(johnniwinther): Change errors to warnings, cf. 11.11.1.
     if (element == null) {
-      return failOrReturnErroneousElement(resolver.enclosingElement, node, name,
-                                          MessageKind.CANNOT_RESOLVE,
-                                          {'name': name});
+      return failOrReturnErroneousConstructorElement(
+          resolver.enclosingElement, node, name,
+          MessageKind.CANNOT_RESOLVE,
+          {'name': name});
     } else if (element.isErroneous) {
       return element;
     } else if (element.isTypedef) {
diff --git a/pkg/compiler/lib/src/resolution/signatures.dart b/pkg/compiler/lib/src/resolution/signatures.dart
index 8260d8b..530be43 100644
--- a/pkg/compiler/lib/src/resolution/signatures.dart
+++ b/pkg/compiler/lib/src/resolution/signatures.dart
@@ -126,7 +126,7 @@
     }
   }
 
-  Element visitIdentifier(Identifier node) {
+  FormalElementX visitIdentifier(Identifier node) {
     return createParameter(node, null);
   }
 
@@ -160,7 +160,8 @@
     FormalElementX parameter;
     if (createRealParameters) {
       parameter = new LocalParameterElementX(
-        enclosingElement, currentDefinitions, name, initializer);
+        enclosingElement, currentDefinitions, name, initializer,
+        isOptional: isOptionalParameter, isNamed: optionalParametersAreNamed);
     } else {
       parameter = new FormalElementX(
         ElementKind.PARAMETER, enclosingElement, currentDefinitions, name);
@@ -198,7 +199,8 @@
             name, enclosingElement.enclosingClass);
       }
       element = new InitializingFormalElementX(enclosingElement,
-          currentDefinitions, name, initializer, fieldElement);
+          currentDefinitions, name, initializer, fieldElement,
+          isOptional: isOptionalParameter, isNamed: optionalParametersAreNamed);
       computeParameterType(element, fieldElement);
     }
     return element;
diff --git a/pkg/compiler/lib/src/scanner/class_element_parser.dart b/pkg/compiler/lib/src/scanner/class_element_parser.dart
index ccd251d..27c7b9f 100644
--- a/pkg/compiler/lib/src/scanner/class_element_parser.dart
+++ b/pkg/compiler/lib/src/scanner/class_element_parser.dart
@@ -99,16 +99,16 @@
 }
 
 class MemberListener extends NodeListener {
-  final ClassElement enclosingElement;
+  final ClassElement enclosingClass;
 
   MemberListener(DiagnosticListener listener,
-                 Element enclosingElement)
-      : this.enclosingElement = enclosingElement,
+                 ClassElement enclosingElement)
+      : this.enclosingClass = enclosingElement,
         super(listener, enclosingElement.compilationUnit);
 
   bool isConstructorName(Node nameNode) {
-    if (enclosingElement == null ||
-        enclosingElement.kind != ElementKind.CLASS) {
+    if (enclosingClass == null ||
+        enclosingClass.kind != ElementKind.CLASS) {
       return false;
     }
     String name;
@@ -118,7 +118,7 @@
       Send send = nameNode.asSend();
       name = send.receiver.asIdentifier().source;
     }
-    return enclosingElement.name == name;
+    return enclosingClass.name == name;
   }
 
   // TODO(johnniwinther): Remove this method.
@@ -138,10 +138,10 @@
       bool isUnary = identical(operator.token.next.next.stringValue, ')');
       return Elements.constructOperatorName(operator.source, isUnary);
     } else {
-      if (receiver == null || receiver.source != enclosingElement.name) {
+      if (receiver == null || receiver.source != enclosingClass.name) {
         listener.reportError(send.receiver,
                                  MessageKind.INVALID_CONSTRUCTOR_NAME,
-                                 {'name': enclosingElement.name});
+                                 {'name': enclosingClass.name});
       }
       return selector.source;
     }
@@ -162,7 +162,7 @@
           name, beginToken, endToken,
           ElementKind.GENERATIVE_CONSTRUCTOR,
           method.modifiers,
-          enclosingElement);
+          enclosingClass);
     } else {
       ElementKind kind = ElementKind.FUNCTION;
       if (getOrSet != null) {
@@ -171,7 +171,7 @@
       }
       memberElement =
           new PartialFunctionElement(name, beginToken, getOrSet, endToken,
-                                     kind, method.modifiers, enclosingElement,
+                                     kind, method.modifiers, enclosingClass,
                                      !method.hasBody());
     }
     addMember(memberElement);
@@ -184,10 +184,10 @@
     String name = getMethodNameHack(method.name);
     Identifier singleIdentifierName = method.name.asIdentifier();
     if (singleIdentifierName != null && singleIdentifierName.source == name) {
-      if (name != enclosingElement.name) {
+      if (name != enclosingClass.name) {
         listener.reportError(singleIdentifierName,
                                  MessageKind.INVALID_UNNAMED_CONSTRUCTOR_NAME,
-                                 {'name': enclosingElement.name});
+                                 {'name': enclosingClass.name});
       }
     }
     ElementKind kind = ElementKind.FUNCTION;
@@ -195,7 +195,7 @@
         name, beginToken, endToken,
         ElementKind.FUNCTION,
         method.modifiers,
-        enclosingElement);
+        enclosingClass);
     addMember(memberElement);
   }
 
@@ -207,11 +207,11 @@
     pushNode(null);
     void buildFieldElement(Identifier name, VariableList fields) {
       Element element =
-          new FieldElementX(name, enclosingElement, fields);
+          new FieldElementX(name, enclosingClass, fields);
       addMember(element);
     }
     buildFieldElements(modifiers, variableDefinitions.definitions,
-                       enclosingElement,
+                       enclosingClass,
                        buildFieldElement, beginToken, endToken,
                        hasParseError);
   }
@@ -226,12 +226,16 @@
     pushNode(null);
   }
 
-  void addMember(Element memberElement) {
+  void addMetadata(Element memberElement) {
     for (Link link = metadata; !link.isEmpty; link = link.tail) {
       memberElement.addMetadata(link.head);
     }
     metadata = const Link<MetadataAnnotation>();
-    enclosingElement.addMember(memberElement, listener);
+  }
+
+  void addMember(Element memberElement) {
+    addMetadata(memberElement);
+    enclosingClass.addMember(memberElement, listener);
   }
 
   void endMetadata(Token beginToken, Token periodBeforeName, Token endToken) {
diff --git a/pkg/compiler/lib/src/scanner/parser.dart b/pkg/compiler/lib/src/scanner/parser.dart
index 2d7efe9..fb49196 100644
--- a/pkg/compiler/lib/src/scanner/parser.dart
+++ b/pkg/compiler/lib/src/scanner/parser.dart
@@ -41,10 +41,11 @@
 class Parser {
   final Listener listener;
   bool mayParseFunctionExpressions = true;
-  bool yieldIsKeyword = false;
-  bool awaitIsKeyword = false;
+  bool yieldIsKeyword;
+  bool awaitIsKeyword;
 
-  Parser(this.listener);
+  Parser(this.listener,
+         {this.yieldIsKeyword: false, this.awaitIsKeyword: false});
 
   Token parseUnit(Token token) {
     listener.beginCompilationUnit(token);
@@ -684,6 +685,12 @@
     if (identifiers.isEmpty) {
       return listener.expectedDeclaration(start);
     }
+    Token afterName = identifiers.head;
+    identifiers = identifiers.tail;
+
+    if (identifiers.isEmpty) {
+      return listener.expectedDeclaration(start);
+    }
     Token name = identifiers.head;
     identifiers = identifiers.tail;
     Token getOrSet;
@@ -702,7 +709,7 @@
       }
     }
 
-    token = name.next;
+    token = afterName;
     bool isField;
     while (true) {
       // Loop to allow the listener to rewrite the token stream for
@@ -866,6 +873,7 @@
                             Token type,
                             Token getOrSet,
                             Token name) {
+
     Token externalModifier;
     for (Token modifier in modifiers) {
       if (externalModifier == null && optional('external', modifier)) {
@@ -905,19 +913,68 @@
     return token;
   }
 
+  /// Looks ahead to find the name of a member. Returns a link of the modifiers,
+  /// set/get, (operator) name, and either the start of the method body or the
+  /// end of the declaration.
+  ///
+  /// Examples:
+  ///
+  ///     int get foo;
+  /// results in
+  ///     [';', 'foo', 'get', 'int']
+  ///
+  ///
+  ///     static const List<int> foo = null;
+  /// results in
+  ///     ['=', 'foo', 'List', 'const', 'static']
+  ///
+  ///
+  ///     get foo async* { return null }
+  /// results in
+  ///     ['{', 'foo', 'get']
+  ///
+  ///
+  ///     operator *(arg) => null;
+  /// results in
+  ///     ['(', '*', 'operator']
+  ///
   Link<Token> findMemberName(Token token) {
     Token start = token;
     Link<Token> identifiers = const Link<Token>();
-    while (!identical(token.kind, EOF_TOKEN)) {
+
+    // `true` if 'get' has been seen.
+    bool isGetter = false;
+    // `true` if an identifier has been seen after 'get'.
+    bool hasName = false;
+
+    while (token.kind != EOF_TOKEN) {
       String value = token.stringValue;
-      if ((identical(value, '(')) || (identical(value, '{'))
-          || (identical(value, '=>'))) {
+      if (value == 'get') {
+        isGetter = true;
+      } else if (hasName &&
+                 (value == 'sync' || value == 'async')) {
+        // Skip.
+        token = token.next;
+        value = token.stringValue;
+        if (value == '*') {
+          // Skip.
+          token = token.next;
+        }
+        continue;
+      } else if (value == '(' ||
+                 value == '{' ||
+                 value == '=>') {
         // A method.
+        identifiers = identifiers.prepend(token);
         return identifiers;
-      } else if ((identical(value, '=')) || (identical(value, ';'))
-          || (identical(value, ','))) {
+      } else if (value == '=' ||
+                 value == ';' ||
+                 value == ',') {
         // A field or abstract getter.
+        identifiers = identifiers.prepend(token);
         return identifiers;
+      } else if (isGetter) {
+        hasName = true;
       }
       identifiers = identifiers.prepend(token);
       if (isValidTypeReference(token)) {
@@ -1114,8 +1171,13 @@
     if (identifiers.isEmpty) {
       return listener.expectedDeclaration(start);
     }
+    Token afterName = identifiers.head;
+    identifiers = identifiers.tail;
+
+    if (identifiers.isEmpty) {
+      return listener.expectedDeclaration(start);
+    }
     Token name = identifiers.head;
-    Token afterName = name.next;
     identifiers = identifiers.tail;
     if (!identifiers.isEmpty) {
       if (optional('operator', identifiers.head)) {
@@ -1302,14 +1364,27 @@
   Token parseFunction(Token token, Token getOrSet) {
     listener.beginFunction(token);
     token = parseModifiers(token);
-    if (identical(getOrSet, token)) token = token.next;
-    if (optional('operator', token)) {
+    if (identical(getOrSet, token)) {
+      // get <name>  => ...
+      token = token.next;
+      listener.handleNoType(token);
+      listener.beginFunctionName(token);
+      if (optional('operator', token)) {
+        token = parseOperatorName(token);
+      } else {
+        token = parseIdentifier(token);
+      }
+    } else if (optional('operator', token)) {
+      // operator <op> (...
       listener.handleNoType(token);
       listener.beginFunctionName(token);
       token = parseOperatorName(token);
     } else {
+      // <type>? <get>? <name>
       token = parseReturnTypeOpt(token);
-      if (identical(getOrSet, token)) token = token.next;
+      if (identical(getOrSet, token)) {
+        token = token.next;
+      }
       listener.beginFunctionName(token);
       if (optional('operator', token)) {
         token = parseOperatorName(token);
@@ -2398,7 +2473,8 @@
     Token awaitToken = token;
     listener.beginAwaitExpression(awaitToken);
     token = expect('await', token);
-    token = parseUnaryExpression(token, allowCascades);
+    token = parsePrecedenceExpression(token, POSTFIX_PRECEDENCE,
+                                      allowCascades);
     listener.endAwaitExpression(awaitToken, token);
     return token;
   }
diff --git a/pkg/compiler/lib/src/ssa/builder.dart b/pkg/compiler/lib/src/ssa/builder.dart
index 1b10d11..43798cd 100644
--- a/pkg/compiler/lib/src/ssa/builder.dart
+++ b/pkg/compiler/lib/src/ssa/builder.dart
@@ -1908,14 +1908,13 @@
       if (!enclosingClass.isObject) {
         assert(superClass != null);
         assert(superClass.resolutionState == STATE_DONE);
-        Selector selector =
-            new Selector.callDefaultConstructor(enclosingClass.library);
         // TODO(johnniwinther): Should we find injected constructors as well?
-        FunctionElement target = superClass.lookupConstructor(selector);
+        FunctionElement target = superClass.lookupDefaultConstructor();
         if (target == null) {
           compiler.internalError(superClass,
               "No default constructor available.");
         }
+        Selector selector = new Selector.callDefaultConstructor();
         List<HInstruction> arguments =
             selector.makeArgumentsList2(const Link<ast.Node>(),
                                         target.implementation,
diff --git a/pkg/compiler/lib/src/tree/unparser.dart b/pkg/compiler/lib/src/tree/unparser.dart
index 3ac6a9b..1d9c690 100644
--- a/pkg/compiler/lib/src/tree/unparser.dart
+++ b/pkg/compiler/lib/src/tree/unparser.dart
@@ -253,8 +253,18 @@
       unparseNodeListFrom(node.initializers, node.initializers.nodes,
           spaces: true);
     }
-    visit(node.asyncModifier);
-    if (node.body != null && node.body is! EmptyStatement) space();
+    if (node.asyncModifier != null) {
+      if (node.getOrSet != null) {
+        write(' ');
+      } else {
+        // Space is optional if this is not a getter.
+        space();
+      }
+      visit(node.asyncModifier);
+    }
+    if (node.body != null && node.body is! EmptyStatement) {
+      space();
+    }
     visit(node.body);
   }
 
@@ -394,11 +404,13 @@
   }
 
   visitYield(Yield node) {
-    write(node.yieldToken);
-    write(node.starToken);
+    write(node.yieldToken.value);
+    if (node.starToken != null) {
+      write(node.starToken.value);
+    }
     space();
     visit(node.expression);
-    write(node.endToken);
+    write(node.endToken.value);
   }
 
 
diff --git a/pkg/compiler/lib/src/tree_ir/tree_ir_builder.dart b/pkg/compiler/lib/src/tree_ir/tree_ir_builder.dart
index 3a017d9..2f7e5fe 100644
--- a/pkg/compiler/lib/src/tree_ir/tree_ir_builder.dart
+++ b/pkg/compiler/lib/src/tree_ir/tree_ir_builder.dart
@@ -49,9 +49,9 @@
   /// Maps variable/parameter elements to the Tree variables that represent it.
   final Map<Local, List<Variable>> local2variables = <Local, List<Variable>>{};
 
-  /// Like [local2variables], except for closure variables.
-  final Map<cps_ir.ClosureVariable, Variable> local2closure =
-      <cps_ir.ClosureVariable, Variable>{};
+  /// Like [local2variables], except for mutable variables.
+  final Map<cps_ir.MutableVariable, Variable> local2mutable =
+      <cps_ir.MutableVariable, Variable>{};
 
   // Continuations with more than one use are replaced with Tree labels.  This
   // is the mapping from continuations to labels.
@@ -72,12 +72,22 @@
   /// variables.
   Variable phiTempVar;
 
-  Variable getClosureVariable(cps_ir.ClosureVariable irVariable) {
+  Variable addMutableVariable(cps_ir.MutableVariable irVariable) {
     if (irVariable.host != currentElement) {
-      return parent.getClosureVariable(irVariable);
+      return parent.addMutableVariable(irVariable);
     }
-    return local2closure.putIfAbsent(irVariable,
-        () => new Variable(currentElement, irVariable.hint));
+    assert(!local2mutable.containsKey(irVariable));
+    Variable variable = new Variable(currentElement, irVariable.hint);
+    local2mutable[irVariable] = variable;
+    return variable;
+  }
+
+  Variable getMutableVariableReference(
+        cps_ir.Reference<cps_ir.MutableVariable> reference) {
+    if (reference.definition.host != currentElement) {
+      return parent.getMutableVariableReference(reference);
+    }
+    return local2mutable[reference.definition];
   }
 
   /// Obtains the variable representing the given primitive. Returns null for
@@ -137,11 +147,11 @@
     return new FieldDefinition(node.element, body);
   }
 
-  Variable getFunctionParameter(cps_ir.Definition variable) {
+  Variable addFunctionParameter(cps_ir.Definition variable) {
     if (variable is cps_ir.Parameter) {
       return getVariable(variable);
     } else {
-      return getClosureVariable(variable as cps_ir.ClosureVariable);
+      return addMutableVariable(variable as cps_ir.MutableVariable);
     }
   }
 
@@ -149,7 +159,7 @@
     currentElement = node.element;
     List<Variable> parameters = <Variable>[];
     for (cps_ir.Definition p in node.parameters) {
-      Variable parameter = getFunctionParameter(p);
+      Variable parameter = addFunctionParameter(p);
       assert(parameter != null);
       ++parameter.writeCount; // Being a parameter counts as a write.
       parameters.add(parameter);
@@ -170,7 +180,7 @@
     currentElement = node.element;
     List<Variable> parameters = <Variable>[];
     for (cps_ir.Definition p in node.parameters) {
-      Variable parameter = getFunctionParameter(p);
+      Variable parameter = addFunctionParameter(p);
       assert(parameter != null);
       ++parameter.writeCount; // Being a parameter counts as a write.
       parameters.add(parameter);
@@ -431,19 +441,24 @@
     }
   }
 
-  Expression visitGetClosureVariable(cps_ir.GetClosureVariable node) {
-    return getClosureVariable(node.variable.definition);
+  Statement visitLetMutable(cps_ir.LetMutable node) {
+    Variable variable = addMutableVariable(node.variable);
+    Expression value = getVariableReference(node.value);
+    return new Assign(variable, value, visit(node.body), isDeclaration: true);
   }
 
-  Statement visitSetClosureVariable(cps_ir.SetClosureVariable node) {
-    Variable variable = getClosureVariable(node.variable.definition);
+  Expression visitGetMutableVariable(cps_ir.GetMutableVariable node) {
+    return getMutableVariableReference(node.variable);
+  }
+
+  Statement visitSetMutableVariable(cps_ir.SetMutableVariable node) {
+    Variable variable = getMutableVariableReference(node.variable);
     Expression value = getVariableReference(node.value);
-    return new Assign(variable, value, visit(node.body),
-                      isDeclaration: node.isDeclaration);
+    return new Assign(variable, value, visit(node.body));
   }
 
   Statement visitDeclareFunction(cps_ir.DeclareFunction node) {
-    Variable variable = getClosureVariable(node.variable.definition);
+    Variable variable = addMutableVariable(node.variable);
     FunctionDefinition function = makeSubFunction(node.definition);
     return new FunctionDeclaration(variable, function, visit(node.body));
   }
diff --git a/pkg/compiler/lib/src/tree_ir/tree_ir_nodes.dart b/pkg/compiler/lib/src/tree_ir/tree_ir_nodes.dart
index ab74fa1..1921450 100644
--- a/pkg/compiler/lib/src/tree_ir/tree_ir_nodes.dart
+++ b/pkg/compiler/lib/src/tree_ir/tree_ir_nodes.dart
@@ -12,7 +12,6 @@
 import '../universe/universe.dart';
 import '../universe/universe.dart' show Selector;
 import 'optimization/optimization.dart';
-import '../closure.dart' show ClosureClassElement;
 
 // The Tree language is the target of translation out of the CPS-based IR.
 //
@@ -493,9 +492,10 @@
   Variable variable;
   Expression definition;
 
-  /// If true, this declares a new copy of the closure variable.
-  /// The consequences are similar to [cps_ir.SetClosureVariable].
-  /// All uses of the variable must be nested inside the [next] statement.
+  /// If true, this assignes to a fresh variable scoped to the [next]
+  /// statement.
+  ///
+  /// Variable declarations themselves are hoisted to function level.
   bool isDeclaration;
 
   Assign(this.variable, this.definition, this.next,
diff --git a/pkg/compiler/lib/src/typechecker.dart b/pkg/compiler/lib/src/typechecker.dart
index 26272a9..f338269 100644
--- a/pkg/compiler/lib/src/typechecker.dart
+++ b/pkg/compiler/lib/src/typechecker.dart
@@ -1601,17 +1601,28 @@
     return const DynamicType();
   }
 
-  DartType visitAwait(Await node) {
-    DartType expressionType = analyze(node.expression);
-    DartType resultType = expressionType;
-    if (expressionType is InterfaceType) {
-      InterfaceType futureType =
-          expressionType.asInstanceOf(compiler.futureClass);
+  /// Flatten [type] by recursively removing enclosing `Future` annotations.
+  ///
+  /// For instance:
+  ///     flatten(T) = T
+  ///     flatten(Future<T>) = T
+  ///     flatten(Future<Future<T>>) = T
+  ///
+  /// This method is used in the static typing of await and type checking of
+  /// return.
+  DartType flatten(DartType type) {
+    if (type is InterfaceType) {
+      InterfaceType futureType = type.asInstanceOf(compiler.futureClass);
       if (futureType != null) {
-        resultType = futureType.typeArguments.first;
+        return flatten(futureType.typeArguments.first);
       }
     }
-    return resultType;
+    return type;
+  }
+
+  DartType visitAwait(Await node) {
+    DartType expressionType = analyze(node.expression);
+    return flatten(expressionType);
   }
 
   DartType visitYield(Yield node) {
diff --git a/pkg/compiler/lib/src/universe/universe.dart b/pkg/compiler/lib/src/universe/universe.dart
index b731637..a7ddbb0 100644
--- a/pkg/compiler/lib/src/universe/universe.dart
+++ b/pkg/compiler/lib/src/universe/universe.dart
@@ -116,7 +116,9 @@
   Iterable<DartType> get instantiatedTypes => _instantiatedTypes;
 
   /// Returns `true` if [cls] is considered to be instantiated, either directly,
-  /// through subclasses or throught subtypes.
+  /// through subclasses or through subtypes. The latter case only contains
+  /// spurious information from instatiations through factory constructors and
+  /// mixins.
   // TODO(johnniwinther): Improve semantic precision.
   bool isInstantiated(ClassElement cls) {
     return _allInstantiatedClasses.contains(cls);
@@ -324,6 +326,8 @@
       return new Selector.getter(name, element.library);
     } else if (element.isField) {
       return new Selector.getter(name, element.library);
+    } else if (element.isConstructor) {
+      return new Selector.callConstructor(name, element.library);
     } else {
       throw new SpannableAssertionFailure(
           element, "Can't get selector from $element");
@@ -379,8 +383,8 @@
       => new Selector(SelectorKind.CALL, name, library,
                       arity, namedArguments);
 
-  factory Selector.callDefaultConstructor(LibraryElement library)
-      => new Selector(SelectorKind.CALL, "", library, 0);
+  factory Selector.callDefaultConstructor()
+      => new Selector(SelectorKind.CALL, "", null, 0);
 
   bool get isGetter => identical(kind, SelectorKind.GETTER);
   bool get isSetter => identical(kind, SelectorKind.SETTER);
diff --git a/pkg/compiler/lib/src/use_unused_api.dart b/pkg/compiler/lib/src/use_unused_api.dart
index 2713e0d..4945189 100644
--- a/pkg/compiler/lib/src/use_unused_api.dart
+++ b/pkg/compiler/lib/src/use_unused_api.dart
@@ -25,7 +25,9 @@
 import 'inferrer/type_graph_inferrer.dart' as type_graph_inferrer;
 import 'io/code_output.dart' as io;
 import 'js/js.dart' as js;
+import 'js_backend/js_backend.dart' as js_backend;
 import 'js_emitter/js_emitter.dart' as js_emitter;
+import 'js_emitter/program_builder.dart' as program_builder;
 import 'source_file_provider.dart' as source_file_provider;
 import 'ssa/ssa.dart' as ssa;
 import 'tree/tree.dart' as tree;
@@ -53,6 +55,7 @@
   useJs(new js.Blob(null));
   useJs(new js.NamedFunction(null, null));
   useJs(new js.ArrayHole());
+  useJsBackend(null);
   useConcreteTypesInferrer(null);
   useColor();
   useFilenames();
@@ -65,6 +68,7 @@
   useTypes();
   useCodeEmitterTask(null);
   useScript(null);
+  useProgramBuilder(null);
 }
 
 useApi() {
@@ -170,6 +174,10 @@
   node.asVariableUse();
 }
 
+useJsBackend(js_backend.JavaScriptBackend backend) {
+  backend.assembleCode(null);
+}
+
 useConcreteTypesInferrer(concrete_types_inferrer.ConcreteTypesInferrer c) {
   c.debug();
 }
@@ -274,3 +282,8 @@
 useScript(dart2jslib.Script script) {
   script.copyWithFile(null);
 }
+
+useProgramBuilder(program_builder.ProgramBuilder builder) {
+  builder.buildMethodHackForIncrementalCompilation(null);
+  builder.buildFieldsHackForIncrementalCompilation(null);
+}
diff --git a/pkg/compiler/lib/src/warnings.dart b/pkg/compiler/lib/src/warnings.dart
index f2f5449..c788276 100644
--- a/pkg/compiler/lib/src/warnings.dart
+++ b/pkg/compiler/lib/src/warnings.dart
@@ -812,7 +812,6 @@
   static const MessageKind CANNOT_EXTEND_ENUM = const MessageKind(
       "Class '#{className}' can't extend the type '#{enumType}' because "
       "it is declared by an enum.",
-      options: const ['--enable-enum'],
       howToFix: "Try making '#{enumType}' a normal class or removing the "
         "'extends' clause.",
       examples: const ["""
@@ -823,7 +822,6 @@
   static const MessageKind CANNOT_IMPLEMENT_ENUM = const MessageKind(
       "Class '#{className}' can't implement the type '#{enumType}' "
       "because it is declared by an enum.",
-      options: const ['--enable-enum'],
       howToFix: "Try making '#{enumType}' a normal class or removing the "
         "type from the 'implements' clause.",
       examples: const ["""
@@ -834,7 +832,6 @@
   static const MessageKind CANNOT_MIXIN_ENUM = const MessageKind(
       "Class '#{className}' can't mixin the type '#{enumType}' because it "
       "is declared by an enum.",
-      options: const ['--enable-enum'],
       howToFix: "Try making '#{enumType}' a normal class or removing the "
         "type from the 'with' clause.",
       examples: const ["""
@@ -844,7 +841,6 @@
 
   static const MessageKind CANNOT_INSTANTIATE_ENUM = const MessageKind(
       "Enum type '#{enumName}' cannot be instantiated.",
-      options: const ['--enable-enum'],
       howToFix: "Try making '#{enumType}' a normal class or use an enum "
                 "constant.",
       examples: const ["""
@@ -855,7 +851,6 @@
 
   static const MessageKind EMPTY_ENUM_DECLARATION = const MessageKind(
       "Enum '#{enumName}' must contain at least one value.",
-      options: const ['--enable-enum'],
       howToFix: "Try adding an enum constant or making #{enumName} a "
                 "normal class.",
       examples: const ["""
@@ -864,7 +859,6 @@
 
   static const MessageKind MISSING_ENUM_CASES = const MessageKind(
       "Missing enum constants in switch statement: #{enumValues}.",
-      options: const ['--enable-enum'],
       howToFix: "Try adding the missing constants or a default case.",
       examples: const ["""
 enum Enum { A, B }
@@ -2081,15 +2075,6 @@
     " require a preamble file located in:\n"
     "  <sdk>/lib/_internal/compiler/js_lib/preambles.");
 
-
-  static const MessageKind EXPERIMENTAL_ENUMS = const MessageKind(
-      "Experimental language feature 'enums' is not supported.",
-      howToFix: "Use option '--enable-enum' to use enum declarations.",
-      examples: const ["""
-enum Enum { A, B, C }
-main() => print(Enum.A);
-"""]);
-
   static const MessageKind EXPERIMENTAL_ASYNC_AWAIT = const MessageKind(
       "Experimental language feature 'async/await' is not supported.");
 
@@ -2159,6 +2144,17 @@
 }
 main() => new A.a();"""]);
 
+  static const MessageKind ASYNC_MODIFIER_ON_SETTER =
+      const MessageKind(
+          "The modifier '#{modifier}' is not allowed on setters.",
+          options: const ['--enable-async'],
+          howToFix: "Try removing the '#{modifier}' modifier.",
+          examples: const ["""
+class A {
+  set foo(v) async {}
+}
+main() => new A().foo = 0;"""]);
+
   static const MessageKind YIELDING_MODIFIER_ON_ARROW_BODY =
       const MessageKind(
           "The modifier '#{modifier}' is not allowed on methods implemented "
diff --git a/pkg/crypto/lib/src/hash_utils.dart b/pkg/crypto/lib/src/hash_utils.dart
index c39ddd0..12bcb0d 100644
--- a/pkg/crypto/lib/src/hash_utils.dart
+++ b/pkg/crypto/lib/src/hash_utils.dart
@@ -103,8 +103,8 @@
   }
 
   // Convert a 32-bit word to four bytes.
-  Uint32List _wordToBytes(int word) {
-    Uint32List bytes = new Uint32List(_BYTES_PER_WORD);
+  List<int> _wordToBytes(int word) {
+    List bytes = new List<int>(_BYTES_PER_WORD);
     bytes[0] = (word >> (_bigEndianWords ? 24 : 0)) & _MASK_8;
     bytes[1] = (word >> (_bigEndianWords ? 16 : 8)) & _MASK_8;
     bytes[2] = (word >> (_bigEndianWords ? 8 : 16)) & _MASK_8;
diff --git a/pkg/dart2js_incremental/lib/caching_compiler.dart b/pkg/dart2js_incremental/lib/caching_compiler.dart
index 7a88715..7c7d341 100644
--- a/pkg/dart2js_incremental/lib/caching_compiler.dart
+++ b/pkg/dart2js_incremental/lib/caching_compiler.dart
@@ -132,15 +132,14 @@
         ..outputBuffers.clear()
         ..isolateProperties = null
         ..classesCollector = null
-        ..nativeClasses.clear()
         ..mangledFieldNames.clear()
         ..mangledGlobalFieldNames.clear()
         ..recordedMangledNames.clear()
-        ..additionalProperties.clear()
         ..clearCspPrecompiledNodes()
         ..elementDescriptors.clear();
 
     backend.emitter
+        ..nativeClassesAndSubclasses.clear()
         ..outputContainsConstantList = false
         ..neededClasses.clear()
         ..outputClassLists.clear()
diff --git a/pkg/dart2js_incremental/lib/library_updater.dart b/pkg/dart2js_incremental/lib/library_updater.dart
index f0dc55a..217abdb 100644
--- a/pkg/dart2js_incremental/lib/library_updater.dart
+++ b/pkg/dart2js_incremental/lib/library_updater.dart
@@ -67,7 +67,9 @@
     computeMixinClass;
 
 import 'package:compiler/src/js_emitter/model.dart' show
-    Class;
+    Class,
+    Method;
+
 import 'package:compiler/src/js_emitter/program_builder.dart' show
     ProgramBuilder;
 
@@ -152,13 +154,14 @@
   }
 
   void _captureState(Compiler compiler) {
-    _emittedClasses = new Set.from(compiler.backend.emitter.neededClasses);
+    JavaScriptBackend backend = compiler.backend;
+    _emittedClasses = new Set.from(backend.emitter.neededClasses);
 
     _directlyInstantiatedClasses =
         new Set.from(compiler.codegenWorld.directlyInstantiatedClasses);
 
     List<ConstantValue> constants =
-        compiler.backend.emitter.outputConstantLists[
+        backend.emitter.outputConstantLists[
             compiler.deferredLoadTask.mainOutputUnit];
     if (constants == null) constants = <ConstantValue>[];
     _compiledConstants = new Set<ConstantValue>.identity()..addAll(constants);
@@ -931,17 +934,18 @@
   }
 
   jsAst.Node computeMethodUpdateJs(Element element) {
-    MemberInfo info = containerBuilder.analyzeMemberMethod(element);
-    if (info == null) {
+    Method member = new ProgramBuilder(compiler, namer, emitter)
+        .buildMethodHackForIncrementalCompilation(element);
+    if (member == null) {
       compiler.internalError(element, '${element.runtimeType}');
     }
     ClassBuilder builder = new ClassBuilder(element, namer);
-    containerBuilder.addMemberMethodFromInfo(info, builder);
+    containerBuilder.addMemberMethod(member, builder);
     jsAst.Node partialDescriptor =
         builder.toObjectInitializer(emitClassDescriptor: false);
 
-    String name = info.name;
-    jsAst.Node function = info.code;
+    String name = member.name;
+    jsAst.Node function = member.code;
     bool isStatic = !element.isInstanceMember;
 
     /// Either a global object (non-instance members) or a prototype (instance
@@ -1475,7 +1479,7 @@
 
   List<String> computeFields(ClassElement classElement) {
     Class cls = new ProgramBuilder(compiler, namer, emitter)
-        .buildClassWithFieldsForTry(classElement);
+        .buildFieldsHackForIncrementalCompilation(classElement);
     // TODO(ahe): Rewrite for new emitter.
     ClassBuilder builder = new ClassBuilder(classElement, namer);
     classEmitter.emitFields(cls, builder);
diff --git a/pkg/fixnum/lib/src/int32.dart b/pkg/fixnum/lib/src/int32.dart
index f7e24aa..09317b6 100644
--- a/pkg/fixnum/lib/src/int32.dart
+++ b/pkg/fixnum/lib/src/int32.dart
@@ -284,7 +284,7 @@
     return false;
   }
 
-  int compareTo(Comparable other) {
+  int compareTo(IntX other) {
     if (other is Int64) {
       return this.toInt64().compareTo(other);
     }
diff --git a/pkg/fixnum/lib/src/int64.dart b/pkg/fixnum/lib/src/int64.dart
index de30656..603065c 100644
--- a/pkg/fixnum/lib/src/int64.dart
+++ b/pkg/fixnum/lib/src/int64.dart
@@ -469,7 +469,9 @@
     return false;
   }
 
-  int compareTo(Comparable other) {
+  int compareTo(IntX other) =>_compareTo(other);
+
+  int _compareTo(other) {
     Int64 o = _promote(other);
     int signa = _h >> (_BITS2 - 1);
     int signb = o._h >> (_BITS2 - 1);
@@ -494,21 +496,10 @@
     return 0;
   }
 
-  bool operator <(other) {
-    return this.compareTo(other) < 0;
-  }
-
-  bool operator <=(other) {
-    return this.compareTo(other) <= 0;
-  }
-
-  bool operator >(other) {
-    return this.compareTo(other) > 0;
-  }
-
-  bool operator >=(other) {
-    return this.compareTo(other) >= 0;
-  }
+  bool operator <(other) => _compareTo(other) < 0;
+  bool operator <=(other) => _compareTo(other) <= 0;
+  bool operator >(other) => this._compareTo(other) > 0;
+  bool operator >=(other) => _compareTo(other) >= 0;
 
   bool get isEven => (_l & 0x1) == 0;
   bool get isMaxValue => (_h == _MASK2 >> 1) && _m == _MASK && _l == _MASK;
diff --git a/pkg/fixnum/lib/src/intx.dart b/pkg/fixnum/lib/src/intx.dart
index 859cb95..7adbf0c 100644
--- a/pkg/fixnum/lib/src/intx.dart
+++ b/pkg/fixnum/lib/src/intx.dart
@@ -7,7 +7,7 @@
 /**
  * A fixed-precision integer.
  */
-abstract class IntX implements Comparable {
+abstract class IntX implements Comparable<IntX> {
 
   /** Addition operator. */
   IntX operator +(other);
@@ -80,8 +80,6 @@
    */
   IntX shiftRightUnsigned(int shiftAmount);
 
-  int compareTo(Comparable other);
-
   /**
    * Returns `true` if and only if [other] is an int or IntX equal in
    * value to this integer.
diff --git a/pkg/fixnum/pubspec.yaml b/pkg/fixnum/pubspec.yaml
index 2d54f85..ac9418e 100644
--- a/pkg/fixnum/pubspec.yaml
+++ b/pkg/fixnum/pubspec.yaml
@@ -1,5 +1,5 @@
 name: fixnum
-version: 0.9.1
+version: 0.10.0
 author: Dart Team <misc@dartlang.org>
 description: Library for 32- and 64-bit fixed size integers.
 homepage: http://www.dartlang.org
diff --git a/pkg/pkg.status b/pkg/pkg.status
index 00d94ee..35af9a7 100644
--- a/pkg/pkg.status
+++ b/pkg/pkg.status
@@ -11,6 +11,9 @@
 */*/*/*/packages/*/*: Skip
 */*/*/*/*/packages/*/*: Skip
 
+[ $compiler != dartanalyzer && $compiler != dart2analyzer ]
+docgen/test/inherited_comments_test: Fail # issue 22233
+
 [ $compiler == none && ($runtime == drt || $runtime == dartium || $runtime == ContentShellOnAndroid) ]
 third_party/angular_tests/browser_test/*: Skip # github perf_api.dart issue 5
 third_party/angular_tests/browser_test/core_dom/shadow_root_options: Fail # Issue 19329
@@ -30,6 +33,9 @@
 docgen/test/*: Skip # Slow
 third_party/html5lib/test/tokenizer_test: Skip  # Times out
 
+[ $runtime == vm && $system == windows]
+analysis_server/test/analysis/get_errors_test: Skip # runtime error, Issue 22180
+
 [ $runtime == vm && ( $arch == simarm || $arch == simmips ) ]
 docgen/test/*: Skip # Too slow
 third_party/html5lib/test/tokenizer_test: Pass, Slow
@@ -49,7 +55,7 @@
 analyzer/test/generated/static_type_warning_code_test: Pass, Slow
 analyzer/test/generated/compile_time_error_code_test: Pass, Slow
 
-analyzer/test/enum_test: Fail # Issue 21323
+analyzer/test/enum_test: Slow, Pass, Fail # Issue 21323
 
 analysis_server/test/*: Skip # Issue 22161
 analysis_server/test/search/element_references_test: Pass, Slow
@@ -176,6 +182,19 @@
 [ $compiler == dartanalyzer || $compiler == dart2analyzer ]
 third_party/angular_tests/vm_test: StaticWarning # Uses removed APIs. See issue 18733.
 
+[ $compiler == dartanalyzer ]
+analysis_server/test/edit/sort_members_test: StaticWarning # Issue 22252
+analysis_server/test/edit/assists_test: StaticWarning # Issue 22252
+analysis_server/test/edit/format_test: StaticWarning # Issue 22252
+analysis_server/test/edit/refactoring_test: StaticWarning # Issue 22252
+analysis_server/test/edit/fixes_test: StaticWarning # Issue 22252
+analysis_server/test/socket_server_test: StaticWarning # Issue 22252
+analysis_server/test/search/type_hierarchy_test: StaticWarning # Issue 22252
+analysis_server/test/search/top_level_declarations_test: StaticWarning # Issue 22252
+analysis_server/test/search/member_references_test: StaticWarning # Issue 22252
+analysis_server/test/search/member_declarations_test: StaticWarning # Issue 22252
+analysis_server/test/search/element_references_test: StaticWarning # Issue 22252
+
 [ $runtime == safari || $runtime == safarimobilesim || $runtime == chrome || $runtime == ff || $ie ]
 # Various issues due to limited browser testing in Angular.
 third_party/angular_tests/*: Skip
diff --git a/pkg/utf/lib/src/list_range.dart b/pkg/utf/lib/src/list_range.dart
index 7889796..2f3b34d 100644
--- a/pkg/utf/lib/src/list_range.dart
+++ b/pkg/utf/lib/src/list_range.dart
@@ -48,9 +48,9 @@
   bool moveNext();
   int get current;
   int get position;
-  void backup([by]);
+  void backup([int by]);
   int get remaining;
-  void skip([count]);
+  void skip([int count]);
 }
 
 class _ListRangeIteratorImpl implements ListRangeIterator {
diff --git a/pkg/utf/lib/src/utf/utf_stream.dart b/pkg/utf/lib/src/utf/utf_stream.dart
index 2b460d0..0936616 100644
--- a/pkg/utf/lib/src/utf/utf_stream.dart
+++ b/pkg/utf/lib/src/utf/utf_stream.dart
@@ -78,7 +78,7 @@
     }
   }
 
-  void addError(Object error, [StackTrace stackTrace]) {
+  void addError(error, [StackTrace stackTrace]) {
     _outSink.addError(error, stackTrace);
   }
 
@@ -189,7 +189,7 @@
     _outSink.add(_processString(data));
   }
 
-  void addError(Object error, [StackTrace stackTrace]) {
+  void addError(error, [StackTrace stackTrace]) {
     _outSink.addError(error, stackTrace);
   }
 
@@ -203,7 +203,7 @@
  */
 class Utf8EncoderTransformer extends _StringEncoder {
   List<int> _processString(String string) {
-    var bytes = [];
+    var bytes = <int>[];
     int pos = 0;
     List<int> codepoints = utf16CodeUnitsToCodepoints(string.codeUnits);
     int length = codepoints.length;
diff --git a/pkg/utf/pubspec.yaml b/pkg/utf/pubspec.yaml
index a3fd334..519bed4 100644
--- a/pkg/utf/pubspec.yaml
+++ b/pkg/utf/pubspec.yaml
@@ -1,5 +1,5 @@
 name: utf
-version: 0.9.0+1
+version: 0.9.0+2
 author: Dart Team <misc@dartlang.org>
 description: >
  A Unicode library. Intended for advanced use where the built-in facilities
diff --git a/runtime/BUILD.gn b/runtime/BUILD.gn
index 440b574..040b902 100644
--- a/runtime/BUILD.gn
+++ b/runtime/BUILD.gn
@@ -76,6 +76,7 @@
     "--quiet",
     "--output", rebase_path(output, root_build_dir),
     "--input", rebase_path("vm/version_in.cc", root_build_dir),
+    "--ignore_svn_revision",
   ]
 }
 
diff --git a/runtime/bin/BUILD.gn b/runtime/bin/BUILD.gn
index 467579e..23c9746 100644
--- a/runtime/bin/BUILD.gn
+++ b/runtime/bin/BUILD.gn
@@ -151,9 +151,15 @@
   sources = [
     "gen_snapshot.cc",
     # Very limited native resolver provided.
+    "builtin_common.cc",
     "builtin_gen_snapshot.cc",
     "builtin.cc",
     "builtin.h",
+    "platform_android.cc",
+    "platform_linux.cc",
+    "platform_macos.cc",
+    "platform_win.cc",
+    "platform.h",
     # Include generated source files.
     "$target_gen_dir/builtin_gen.cc",
     "$target_gen_dir/io_gen.cc",
diff --git a/runtime/bin/bin.gypi b/runtime/bin/bin.gypi
index 9ddd1a8..0d92b4d 100644
--- a/runtime/bin/bin.gypi
+++ b/runtime/bin/bin.gypi
@@ -176,6 +176,105 @@
         }],
       ],
     },
+    # This is a combination of libdart_io, libdart_builtin, and vmservice bits.
+    # The dart_io is built without support for secure sockets.
+    {
+      'target_name': 'libvmservice_io',
+      'type': 'static_library',
+      'toolsets': ['host', 'target'],
+      'include_dirs': [
+        '..',
+        '../include',
+      ],
+      'includes': [
+        'io_impl_sources.gypi',
+        'builtin_impl_sources.gypi',
+      ],
+      'dependencies': [
+        'generate_builtin_cc_file#host',
+        'generate_io_cc_file#host',
+        'generate_io_patch_cc_file#host',
+        'generate_snapshot_file#host',
+        'generate_resources_cc_file#host',
+      ],
+      'sources': [
+        'builtin_common.cc',
+        'builtin_natives.cc',
+        'builtin_nolib.cc',
+        'builtin.h',
+        'dartutils.cc',
+        'dartutils.h',
+        'io_natives.cc',
+        'io_natives.h',
+        'log_android.cc',
+        'log_linux.cc',
+        'log_macos.cc',
+        'log_win.cc',
+        'vmservice_dartium.h',
+        'vmservice_dartium.cc',
+        'vmservice_impl.cc',
+        'vmservice_impl.h',
+        '<(resources_cc_file)',
+        '<(snapshot_cc_file)',
+      ],
+      'sources/': [
+        ['exclude', '_test\\.(cc|h)$'],
+      ],
+      'conditions': [
+        ['dart_io_support==1 and dart_io_secure_socket==1', {
+          'dependencies': [
+            'bin/net/ssl.gyp:libssl_dart',
+          ],
+        }],
+        ['dart_io_secure_socket==0', {
+          'defines': [
+            'DART_IO_SECURE_SOCKET_DISABLED'
+          ],
+        }],
+        ['OS=="win"', {
+          'sources/' : [
+            ['exclude', 'fdutils.h'],
+          ],
+          # TODO(antonm): fix the implementation.
+          # Current implementation accepts char* strings
+          # and therefore fails to compile once _UNICODE is
+          # enabled.  That should be addressed using -A
+          # versions of functions and adding necessary conversions.
+          'configurations': {
+            'Common_Base': {
+              'msvs_configuration_attributes': {
+                'CharacterSet': '0',
+              },
+            },
+          },
+          'link_settings': {
+            'libraries': [ '-liphlpapi.lib', '-lws2_32.lib', '-lRpcrt4.lib' ],
+          },
+        }],
+        ['OS=="mac"', {
+          'link_settings': {
+            'libraries': [
+              '$(SDKROOT)/System/Library/Frameworks/CoreFoundation.framework',
+              '$(SDKROOT)/System/Library/Frameworks/CoreServices.framework',
+            ],
+          },
+        }],
+        ['OS=="linux"', {
+          'link_settings': {
+            'libraries': [
+              '-ldl',
+            ],
+          },
+        }],
+        ['OS=="android"', {
+          'link_settings': {
+            'libraries': [
+              '-ldl',
+            ],
+          },
+        }],
+      ],
+    },
     {
       'target_name': 'libdart_io',
       'type': 'static_library',
@@ -191,11 +290,21 @@
         'io_natives.cc',
       ],
       'conditions': [
-        ['dart_io_support==1', {
+        ['dart_io_support==1 and dart_io_secure_socket==1', {
           'dependencies': [
             'bin/net/ssl.gyp:libssl_dart',
           ],
         }],
+        ['dart_io_support==1 and dart_io_secure_socket==0', {
+          'dependencies': [
+            'bin/net/zlib.gyp:zlib_dart',
+          ],
+        }],
+        ['dart_io_secure_socket==0', {
+          'defines': [
+            'DART_IO_SECURE_SOCKET_DISABLED'
+          ],
+        }],
         ['OS=="win"', {
           'link_settings': {
             'libraries': [ '-liphlpapi.lib' ],
@@ -281,13 +390,22 @@
         'gen_snapshot.cc',
         # Very limited native resolver provided.
         'builtin_gen_snapshot.cc',
+        'builtin_common.cc',
         'builtin.cc',
         'builtin.h',
+        'platform_android.cc',
+        'platform_linux.cc',
+        'platform_macos.cc',
+        'platform_win.cc',
+        'platform.h',
         # Include generated source files.
         '<(builtin_cc_file)',
         '<(io_cc_file)',
         '<(io_patch_cc_file)',
       ],
+      'defines': [
+        'PLATFORM_DISABLE_SOCKET'
+      ],
       'conditions': [
         ['OS=="win"', {
           'link_settings': {
@@ -443,11 +561,11 @@
       ],
       'sources': [
         'main.cc',
+        'builtin_common.cc',
         'builtin_natives.cc',
         'builtin_nolib.cc',
         'builtin.h',
         'io_natives.h',
-        'vmservice.h',
         'vmservice_impl.cc',
         'vmservice_impl.h',
         '<(snapshot_cc_file)',
@@ -494,11 +612,11 @@
       ],
       'sources': [
         'main.cc',
-        'builtin.cc',
+        'builtin_common.cc',
         'builtin_natives.cc',
+        'builtin.cc',
         'builtin.h',
         'io_natives.h',
-        'vmservice.h',
         'vmservice_impl.cc',
         'vmservice_impl.h',
         # Include generated source files.
@@ -547,11 +665,11 @@
       ],
       'sources': [
         'main.cc',
-        'builtin.cc',
+        'builtin_common.cc',
         'builtin_natives.cc',
+        'builtin.cc',
         'builtin.h',
         'io_natives.h',
-        'vmservice.h',
         'vmservice_impl.cc',
         'vmservice_impl.h',
         # Include generated source files.
@@ -608,6 +726,7 @@
       ],
       'sources': [
         'run_vm_tests.cc',
+        'builtin_common.cc',
         'builtin_natives.cc',
         'builtin_nolib.cc',
         'builtin.h',
diff --git a/runtime/bin/builtin.cc b/runtime/bin/builtin.cc
index 723ad54..dab5a0f 100644
--- a/runtime/bin/builtin.cc
+++ b/runtime/bin/builtin.cc
@@ -8,6 +8,7 @@
 
 #include "bin/builtin.h"
 #include "bin/dartutils.h"
+#include "bin/platform.h"
 
 namespace dart {
 namespace bin {
@@ -19,6 +20,7 @@
     DartUtils::kIOLibPatchURL, io_patch_paths_, true },
 };
 
+Dart_Port Builtin::load_port_ = ILLEGAL_PORT;
 
 // Patch all the specified patch files in the array 'patch_files' into the
 // library specified in 'library'.
diff --git a/runtime/bin/builtin.dart b/runtime/bin/builtin.dart
index 155dc1f..a741da9 100644
--- a/runtime/bin/builtin.dart
+++ b/runtime/bin/builtin.dart
@@ -3,9 +3,92 @@
 // BSD-style license that can be found in the LICENSE file.
 
 library builtin;
-import 'dart:io';
 import 'dart:async';
 import 'dart:convert';
+import 'dart:isolate';
+
+
+//////////////////////
+/* Support for loading within the isolate via dart:io */
+import 'dart:io';
+
+// Enable by setting the #define LOAD_VIA_SERVICE_ISOLATE (see dartutils.cc)
+bool _load_via_service_isolate = false;
+
+var _httpClient;
+void _httpGet(int tag,
+              Uri uri,
+              String libraryUri,
+              loadCallback(List<int> data)) {
+  if (_httpClient == null) {
+    _httpClient = new HttpClient()..maxConnectionsPerHost = 6;
+  }
+  _httpClient.getUrl(uri)
+    .then((HttpClientRequest request) => request.close())
+    .then((HttpClientResponse response) {
+      var builder = new BytesBuilder(copy: false);
+      response.listen(
+          builder.add,
+          onDone: () {
+            if (response.statusCode != 200) {
+              var msg = 'Failure getting $uri: '
+                        '${response.statusCode} ${response.reasonPhrase}';
+              _asyncLoadError(tag, uri.toString(), libraryUri, msg);
+            }
+            loadCallback(builder.takeBytes());
+          },
+          onError: (error) {
+            _asyncLoadError(tag, uri.toString(), libraryUri, error);
+          });
+    })
+    .catchError((error) {
+      _asyncLoadError(tag, uri.toString(), libraryUri, error);
+    });
+  // TODO(floitsch): remove this line. It's just here to push an event on the
+  // event loop so that we invoke the scheduled microtasks. Also remove the
+  // import of dart:async when this line is not needed anymore.
+  Timer.run(() {});
+}
+
+
+void _cleanup() {
+  if (_httpClient != null) {
+    _httpClient.close();
+    _httpClient = null;
+ }
+}
+
+_loadDataAsyncDartIO(int tag,
+                       String uri,
+                       String libraryUri,
+                       Uri resourceUri) {
+  _startingOneLoadRequest(uri);
+  if ((resourceUri.scheme == 'http') || (resourceUri.scheme == 'https')) {
+    _httpGet(tag, resourceUri, libraryUri, (data) {
+      _loadScript(tag, uri, libraryUri, data);
+    });
+  } else {
+    var sourceFile = new File(resourceUri.toFilePath());
+    sourceFile.readAsBytes().then((data) {
+      _loadScript(tag, uri, libraryUri, data);
+    },
+    onError: (e) {
+      _asyncLoadError(tag, uri, libraryUri, e);
+    });
+  }
+}
+
+//////////////////////
+
+/* See Dart_LibraryTag in dart_api.h */
+const Dart_kScriptTag = null;
+const Dart_kImportTag = 0;
+const Dart_kSourceTag = 1;
+const Dart_kCanonicalizeUrl = 2;
+
+// Dart native extension scheme.
+const _DART_EXT = 'dart-ext:';
+
 // import 'root_library'; happens here from C Code
 
 // The root library (aka the script) is imported into this library. The
@@ -13,33 +96,34 @@
 // root library's namespace.
 Function _getMainClosure() => main;
 
+// A port for communicating with the service isolate for I/O.
+SendPort _loadPort;
+
+const _logBuiltin = false;
 
 // Corelib 'print' implementation.
 void _print(arg) {
   _Logger._printString(arg.toString());
 }
 
-
 class _Logger {
   static void _printString(String s) native "Logger_PrintString";
 }
 
-
 _getPrintClosure() => _print;
 
-const _logBuiltin = false;
+_getCurrentDirectoryPath() native "Directory_Current";
 
 // Corelib 'Uri.base' implementation.
 Uri _uriBase() {
-  return new Uri.file(Directory.current.path + "/");
+  return new Uri.file(_getCurrentDirectoryPath() + "/");
 }
 
-
 _getUriBaseClosure() => _uriBase;
 
 
 // Are we running on Windows?
-var _isWindows = false;
+var _isWindows;
 var _workingWindowsDrivePrefix;
 // The current working directory
 var _workingDirectoryUri;
@@ -49,12 +133,6 @@
 // The directory to look in to resolve "package:" scheme URIs.
 var _packageRoot;
 
-
-void _setWindows() {
-  _isWindows = true;
-}
-
-
 _sanitizeWindowsPath(path) {
   // For Windows we need to massage the paths a bit according to
   // http://blogs.msdn.com/b/ie/archive/2006/12/06/file-uris-in-windows.aspx
@@ -79,6 +157,22 @@
   return fixedPath;
 }
 
+_trimWindowsPath(path) {
+  // Convert /X:/ to X:/.
+  if (_isWindows == false) {
+    // Do nothing when not running Windows.
+    return path;
+  }
+  if (!path.startsWith('/') || (path.length < 3)) {
+    return path;
+  }
+  // Match '/?:'.
+  if ((path[0] == '/') && (path[2] == ':')) {
+    // Remove leading '/'.
+    return path.substring(1);
+  }
+  return path;
+}
 
 _enforceTrailingSlash(uri) {
   // Ensure we have a trailing slash character.
@@ -118,6 +212,8 @@
       packageRoot.startsWith('https:')) {
     _packageRoot = _workingDirectoryUri.resolve(packageRoot);
   } else {
+    packageRoot = _sanitizeWindowsPath(packageRoot);
+    packageRoot = _trimWindowsPath(packageRoot);
     _packageRoot = _workingDirectoryUri.resolveUri(new Uri.file(packageRoot));
   }
   if (_logBuiltin) {
@@ -126,6 +222,26 @@
 }
 
 
+// Given a uri with a 'package' scheme, return a Uri that is prefixed with
+// the package root.
+Uri _resolvePackageUri(Uri uri) {
+  if (!uri.host.isEmpty) {
+    var path = '${uri.host}${uri.path}';
+    var right = 'package:$path';
+    var wrong = 'package://$path';
+
+    throw "URIs using the 'package:' scheme should look like "
+          "'$right', not '$wrong'.";
+  }
+
+  var packageRoot = _packageRoot == null ?
+                    _entryPointScript.resolve('packages/') :
+                    _packageRoot;
+  return packageRoot.resolve(uri.path);
+}
+
+
+
 String _resolveScriptUri(String scriptName) {
   if (_workingDirectoryUri == null) {
     throw 'No current working directory set.';
@@ -147,8 +263,8 @@
   return _entryPointScript.toString();
 }
 
-const _DART_EXT = 'dart-ext:';
 
+// Function called by standalone embedder to resolve uris.
 String _resolveUri(String base, String userString) {
   if (_logBuiltin) {
     _print('# Resolving: $userString from $base');
@@ -162,6 +278,127 @@
   }
 }
 
+Uri _createUri(String userUri) {
+  var uri = Uri.parse(userUri);
+  switch (uri.scheme) {
+    case '':
+    case 'file':
+    case 'http':
+    case 'https':
+      return uri;
+    case 'package':
+      return _resolvePackageUri(uri);
+    default:
+      // Only handling file, http[s], and package URIs
+      // in standalone binary.
+      if (_logBuiltin) {
+        _print('# Unknown scheme (${uri.scheme}) in $uri.');
+      }
+      throw 'Not a known scheme: $uri';
+  }
+}
+
+int _numOutstandingLoadRequests = 0;
+void _finishedOneLoadRequest(String uri) {
+  assert(_numOutstandingLoadRequests > 0);
+  _numOutstandingLoadRequests--;
+  if (_logBuiltin) {
+    _print("Loading of $uri finished, "
+           "${_numOutstandingLoadRequests} requests remaining");
+  }
+  if (_numOutstandingLoadRequests == 0) {
+    _signalDoneLoading();
+    _cleanup();
+  }
+}
+
+void _startingOneLoadRequest(String uri) {
+  assert(_numOutstandingLoadRequests >= 0);
+  _numOutstandingLoadRequests++;
+  if (_logBuiltin) {
+    _print("Loading of $uri started, "
+           "${_numOutstandingLoadRequests} requests outstanding");
+  }
+}
+
+class LoadError extends Error {
+  final String message;
+  LoadError(this.message);
+
+  String toString() => 'Load Error: $message';
+}
+
+void _signalDoneLoading() native "Builtin_DoneLoading";
+void _loadScriptCallback(int tag, String uri, String libraryUri, List<int> data)
+    native "Builtin_LoadScript";
+void _asyncLoadErrorCallback(uri, libraryUri, error)
+    native "Builtin_AsyncLoadError";
+
+void _loadScript(int tag, String uri, String libraryUri, List<int> data) {
+  // TODO: Currently a compilation error while loading the script is
+  // fatal for the isolate. _loadScriptCallback() does not return and
+  // the _numOutstandingLoadRequests counter remains out of sync.
+  _loadScriptCallback(tag, uri, libraryUri, data);
+  _finishedOneLoadRequest(uri);
+}
+
+void _asyncLoadError(tag, uri, libraryUri, error) {
+  if (_logBuiltin) {
+    _print("_asyncLoadError($uri), error: $error");
+  }
+  if (tag == Dart_kImportTag) {
+    // When importing a library, the libraryUri is the imported
+    // uri.
+    libraryUri = uri;
+  }
+  _asyncLoadErrorCallback(uri, libraryUri, new LoadError(error));
+  _finishedOneLoadRequest(uri);
+}
+
+
+_loadDataAsyncLoadPort(int tag,
+                       String uri,
+                       String libraryUri,
+                       Uri resourceUri) {
+  var receivePort = new ReceivePort();
+  receivePort.first.then((dataOrError) {
+    if (dataOrError is List<int>) {
+      _loadScript(tag, uri, libraryUri, dataOrError);
+    } else {
+      _asyncLoadError(tag, uri, libraryUri, dataOrError);
+    }
+  }).catchError((e) {
+    _asyncLoadError(tag, uri, libraryUri, e.toString());
+  });
+
+  try {
+    var msg = [receivePort.sendPort, resourceUri.toString()];
+    _loadPort.send(msg);
+    _startingOneLoadRequest(uri);
+  } catch (e) {
+    if (_logBuiltin) {
+      _print("Exception when communicating with service isolate: $e");
+    }
+    _asyncLoadError(tag, uri, libraryUri, e.toString());
+    receivePort.close();
+  }
+}
+
+// Asynchronously loads script data through a http[s] or file uri.
+_loadDataAsync(int tag, String uri, String libraryUri) {
+  if (tag == Dart_kScriptTag) {
+    uri = _resolveScriptUri(uri);
+  }
+
+  Uri resourceUri = _createUri(uri);
+
+  if (_load_via_service_isolate) {
+    _loadDataAsyncLoadPort(tag, uri, libraryUri, resourceUri);
+  } else {
+    _loadDataAsyncDartIO(tag, uri, libraryUri, resourceUri);
+  }
+
+}
 
 // Returns either a file path or a URI starting with http[s]:, as a String.
 String _filePathFromUri(String userUri) {
@@ -190,156 +427,15 @@
   }
 }
 
+String _nativeLibraryExtension() native "Builtin_NativeLibraryExtension";
 
-Uri _resolvePackageUri(Uri uri) {
-  if (!uri.host.isEmpty) {
-    var path = '${uri.host}${uri.path}';
-    var right = 'package:$path';
-    var wrong = 'package://$path';
+String _platformExtensionFileName(String name) {
+  var extension = _nativeLibraryExtension();
 
-    throw "URIs using the 'package:' scheme should look like "
-          "'$right', not '$wrong'.";
-  }
-
-  var packageRoot = _packageRoot == null ?
-                    _entryPointScript.resolve('packages/') :
-                    _packageRoot;
-  return packageRoot.resolve(uri.path);
-}
-
-
-int _numOutstandingLoadRequests = 0;
-var _httpClient;
-
-void _httpGet(Uri uri, String libraryUri, loadCallback(List<int> data)) {
-  if (_httpClient == null) {
-    _httpClient = new HttpClient()..maxConnectionsPerHost = 6;
-  }
-  _httpClient.getUrl(uri)
-    .then((HttpClientRequest request) => request.close())
-    .then((HttpClientResponse response) {
-      var builder = new BytesBuilder(copy: false);
-      response.listen(
-          builder.add,
-          onDone: () {
-            if (response.statusCode != 200) {
-              var msg = 'Failure getting $uri: '
-                        '${response.statusCode} ${response.reasonPhrase}';
-              _asyncLoadError(uri.toString(), libraryUri, msg);
-            }
-            loadCallback(builder.takeBytes());
-          },
-          onError: (error) {
-            _asyncLoadError(uri.toString(), libraryUri, error);
-          });
-    })
-    .catchError((error) {
-      _asyncLoadError(uri.toString(), libraryUri, error);
-    });
-  // TODO(floitsch): remove this line. It's just here to push an event on the
-  // event loop so that we invoke the scheduled microtasks. Also remove the
-  // import of dart:async when this line is not needed anymore.
-  Timer.run(() {});
-}
-
-
-void _signalDoneLoading() native "Builtin_DoneLoading";
-
-void _cleanup() {
-  if (_httpClient != null) {
-    _httpClient.close();
-    _httpClient = null;
-  }
-}
-
-void _loadScriptCallback(int tag, String uri, String libraryUri, List<int> data)
-    native "Builtin_LoadScript";
-
-void _loadScript(int tag, String uri, String libraryUri, List<int> data) {
-  // TODO: Currently a compilation error while loading the script is
-  // fatal for the isolate. _loadScriptCallback() does not return and
-  // the _numOutstandingLoadRequests counter remains out of sync.
-  _loadScriptCallback(tag, uri, libraryUri, data);
-  assert(_numOutstandingLoadRequests > 0);
-  _numOutstandingLoadRequests--;
-  if (_logBuiltin) {
-    _print("native Builtin_LoadScript($uri) completed, "
-           "${_numOutstandingLoadRequests} requests remaining");
-  }
-  if (_numOutstandingLoadRequests == 0) {
-    _signalDoneLoading();
-    _cleanup();
-  }
-}
-
-
-void _asyncLoadErrorCallback(uri, libraryUri, error)
-    native "Builtin_AsyncLoadError";
-
-void _asyncLoadError(uri, libraryUri, error) {
-  assert(_numOutstandingLoadRequests > 0);
-  if (_logBuiltin) {
-    _print("_asyncLoadError($uri), error: $error");
-  }
-  _numOutstandingLoadRequests--;
-  _asyncLoadErrorCallback(uri, libraryUri, error);
-  if (_numOutstandingLoadRequests == 0) {
-    _signalDoneLoading();
-    _cleanup();
-  }
-}
-
-
-// Create a Uri of 'userUri'. If the input uri is a package uri, then the
-// package uri is resolved.
-Uri _createUri(String userUri) {
-  var uri = Uri.parse(userUri);
-  if (_logBuiltin) {
-    _print('# Creating uri for: $uri');
-  }
-
-  switch (uri.scheme) {
-    case '':
-    case 'file':
-    case 'http':
-    case 'https':
-      return uri;
-    case 'package':
-      return _resolvePackageUri(uri);
-    default:
-      // Only handling file, http[s], and package URIs
-      // in standalone binary.
-      if (_logBuiltin) {
-        _print('# Unknown scheme (${uri.scheme}) in $uri.');
-      }
-      throw 'Not a known scheme: $uri';
-  }
-}
-
-
-// Asynchronously loads script data through a http[s] or file uri.
-_loadDataAsync(int tag, String uri, String libraryUri) {
-  if (tag == null) {
-    uri = _resolveScriptUri(uri);
-  }
-  Uri resourceUri = _createUri(uri);
-  _numOutstandingLoadRequests++;
-  if (_logBuiltin) {
-    _print("_loadDataAsync($uri), "
-           "${_numOutstandingLoadRequests} requests outstanding");
-  }
-  if ((resourceUri.scheme == 'http') || (resourceUri.scheme == 'https')) {
-    _httpGet(resourceUri, libraryUri, (data) {
-      _loadScript(tag, uri, libraryUri, data);
-    });
+  if (_isWindows) {
+    return '$name.$extension';
   } else {
-    var sourceFile = new File(resourceUri.toFilePath());
-    sourceFile.readAsBytes().then((data) {
-      _loadScript(tag, uri, libraryUri, data);
-    },
-    onError: (e) {
-      _asyncLoadError(uri, libraryUri, e);
-    });
+    return 'lib$name.$extension';
   }
 }
 
@@ -358,7 +454,7 @@
     throw 'Unexpected internal error: Extension URI $userUri contains \\';
   }
 
-  String filename;
+
   String name;
   String path;  // Will end in '/'.
   int index = userUri.lastIndexOf('/');
@@ -373,19 +469,7 @@
   }
 
   path = _filePathFromUri(path);
-
-  if (Platform.isLinux || Platform.isAndroid) {
-    filename = 'lib$name.so';
-  } else if (Platform.isMacOS) {
-    filename = 'lib$name.dylib';
-  } else if (Platform.isWindows) {
-    filename = '$name.dll';
-  } else {
-    if (_logBuiltin) {
-      _print('Native extensions not supported on ${Platform.operatingSystem}');
-    }
-    throw 'Native extensions not supported on ${Platform.operatingSystem}';
-  }
+  var filename = _platformExtensionFileName(name);
 
   return [path, filename, name];
 }
diff --git a/runtime/bin/builtin.h b/runtime/bin/builtin.h
index 32fde81..a943dc8 100644
--- a/runtime/bin/builtin.h
+++ b/runtime/bin/builtin.h
@@ -49,6 +49,8 @@
   // load it.
   static Dart_Handle LoadAndCheckLibrary(BuiltinLibraryId id);
 
+  static void SetLoadPort(Dart_Port port);
+
  private:
   // Map specified URI to an actual file name from 'source_paths' and read
   // the file.
@@ -64,6 +66,7 @@
   static const char* _builtin_source_paths_[];
   static const char* io_source_paths_[];
   static const char* io_patch_paths_[];
+  static Dart_Port load_port_;
 
   typedef struct {
     const char* url_;
diff --git a/runtime/bin/builtin_common.cc b/runtime/bin/builtin_common.cc
new file mode 100644
index 0000000..da754a5
--- /dev/null
+++ b/runtime/bin/builtin_common.cc
@@ -0,0 +1,37 @@
+// Copyright (c) 2015, 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 <stdio.h>
+
+#include "include/dart_api.h"
+
+#include "bin/builtin.h"
+#include "bin/dartutils.h"
+#include "bin/platform.h"
+
+namespace dart {
+namespace bin {
+
+void Builtin::SetLoadPort(Dart_Port port) {
+  load_port_ = port;
+  ASSERT(load_port_ != ILLEGAL_PORT);
+  Dart_Handle field_name = DartUtils::NewString("_loadPort");
+  ASSERT(!Dart_IsError(field_name));
+  Dart_Handle builtin_lib =
+      Builtin::LoadAndCheckLibrary(Builtin::kBuiltinLibrary);
+  ASSERT(!Dart_IsError(builtin_lib));
+  Dart_Handle send_port = Dart_GetField(builtin_lib, field_name);
+  ASSERT(!Dart_IsError(send_port));
+  if (!Dart_IsNull(send_port)) {
+    // Already created and set.
+    return;
+  }
+  send_port = Dart_NewSendPort(load_port_);
+  ASSERT(!Dart_IsError(send_port));
+  Dart_Handle result = Dart_SetField(builtin_lib, field_name, send_port);
+  ASSERT(!Dart_IsError(result));
+}
+
+}  // namespace bin
+}  // namespace dart
diff --git a/runtime/bin/builtin_impl_sources.gypi b/runtime/bin/builtin_impl_sources.gypi
index 87bc58f..e778ca7 100644
--- a/runtime/bin/builtin_impl_sources.gypi
+++ b/runtime/bin/builtin_impl_sources.gypi
@@ -13,6 +13,7 @@
     'crypto_linux.cc',
     'crypto_macos.cc',
     'crypto_win.cc',
+    'builtin_common.cc',
     'dartutils.cc',
     'dartutils.h',
     'dbg_connection.cc',
diff --git a/runtime/bin/builtin_natives.cc b/runtime/bin/builtin_natives.cc
index efa61c4..63a5fb0 100644
--- a/runtime/bin/builtin_natives.cc
+++ b/runtime/bin/builtin_natives.cc
@@ -68,6 +68,7 @@
   V(Builtin_LoadScript, 4)                                                     \
   V(Builtin_AsyncLoadError, 3)                                                 \
   V(Builtin_DoneLoading, 0)                                                    \
+  V(Builtin_NativeLibraryExtension, 0)                                         \
 
 
 BUILTIN_NATIVE_LIST(DECLARE_FUNCTION);
diff --git a/runtime/bin/builtin_nolib.cc b/runtime/bin/builtin_nolib.cc
index 1662cd6..182b268 100644
--- a/runtime/bin/builtin_nolib.cc
+++ b/runtime/bin/builtin_nolib.cc
@@ -20,6 +20,7 @@
   { DartUtils::kIOLibURL, NULL, NULL, NULL, true  },
 };
 
+Dart_Port Builtin::load_port_ = ILLEGAL_PORT;
 
 Dart_Handle Builtin::Source(BuiltinLibraryId id) {
   return DartUtils::NewError("Unreachable code in Builtin::Source (%d).", id);
diff --git a/runtime/bin/common_patch.dart b/runtime/bin/common_patch.dart
index 7d9a120..d794cb6 100644
--- a/runtime/bin/common_patch.dart
+++ b/runtime/bin/common_patch.dart
@@ -7,10 +7,6 @@
       native "Crypto_GetRandomBytes";
 }
 
-
-// Provide a closure which will allocate a Timer object to be able to hook
-// up the Timer interface in dart:isolate with the implementation here.
-_getTimerFactoryClosure() {
-  runTimerClosure = _Timer._handleTimeout;
-  return _Timer._factory;
-}
+_setupHooks() {
+  VMLibraryHooks.eventHandlerSendData = _EventHandler._sendData;
+}
\ No newline at end of file
diff --git a/runtime/bin/dartutils.cc b/runtime/bin/dartutils.cc
index c2eb2e0..5778489 100644
--- a/runtime/bin/dartutils.cc
+++ b/runtime/bin/dartutils.cc
@@ -15,6 +15,7 @@
 #include "bin/extensions.h"
 #include "bin/file.h"
 #include "bin/io_buffer.h"
+#include "bin/platform.h"
 #include "bin/socket.h"
 #include "bin/utils.h"
 
@@ -46,6 +47,10 @@
 }
 
 
+// Experimental flag that offloads all script loading I/O onto
+// the service isolate. Disabled for now.
+// #define LOAD_VIA_SERVICE_ISOLATE
+
 const char* DartUtils::MapLibraryUrl(CommandLineOptions* url_mapping,
                                      const char* url_string) {
   ASSERT(url_mapping != NULL);
@@ -477,6 +482,15 @@
 Dart_Handle DartUtils::LoadScript(const char* script_uri,
                                   Dart_Handle builtin_lib) {
   Dart_Handle uri = Dart_NewStringFromCString(script_uri);
+
+#if defined(LOAD_VIA_SERVICE_ISOLATE)
+  Dart_Port load_port = Dart_ServiceWaitForLoadPort();
+  if (load_port == ILLEGAL_PORT) {
+    return NewDartUnsupportedError("Service did not return load port.");
+  }
+  Builtin::SetLoadPort(load_port);
+#endif
+
   return LoadDataAsync_Invoke(Dart_Null(), uri, Dart_Null(), builtin_lib);
 }
 
@@ -590,96 +604,159 @@
 }
 
 
+void FUNCTION_NAME(Builtin_NativeLibraryExtension)(Dart_NativeArguments args) {
+  const char* suffix = Platform::LibraryExtension();
+  ASSERT(suffix != NULL);
+  Dart_Handle res = Dart_NewStringFromCString(suffix);
+  if (Dart_IsError(res)) {
+    Dart_PropagateError(res);
+  }
+  Dart_SetReturnValue(args, res);
+}
+
+
+void DartUtils::PrepareBuiltinLibrary(Dart_Handle builtin_lib,
+                                      Dart_Handle internal_lib,
+                                      bool is_service_isolate,
+                                      const char* package_root) {
+  // Setup the internal library's 'internalPrint' function.
+  Dart_Handle print = Dart_Invoke(
+      builtin_lib, NewString("_getPrintClosure"), 0, NULL);
+  DART_CHECK_VALID(print);
+  Dart_Handle result =
+      Dart_SetField(internal_lib, NewString("_printClosure"), print);
+  DART_CHECK_VALID(result);
+
+  if (!is_service_isolate) {
+    result =
+        Dart_SetField(builtin_lib, NewString("_isWindows"),
+                      IsWindowsHost() ? Dart_True() : Dart_False());
+    DART_CHECK_VALID(result);
+  }
+
+#if defined(LOAD_VIA_SERVICE_ISOLATE)
+  result = Dart_SetField(builtin_lib, NewString("_load_via_service_isolate"),
+                         Dart_True());
+  DART_CHECK_VALID(result);
+#endif
+
+  if (!is_service_isolate) {
+    // Set current working directory.
+    result = SetWorkingDirectory(builtin_lib);
+    DART_CHECK_VALID(result);
+  }
+
+  // Set up package root if specified.
+  if (package_root != NULL) {
+    result = NewString(package_root);
+    DART_CHECK_VALID(result);
+    const int kNumArgs = 1;
+    Dart_Handle dart_args[kNumArgs];
+    dart_args[0] = result;
+    result = Dart_Invoke(builtin_lib,
+                         NewString("_setPackageRoot"),
+                         kNumArgs,
+                         dart_args);
+    DART_CHECK_VALID(result);
+  }
+}
+
+
+void DartUtils::PrepareCoreLibrary(Dart_Handle core_lib,
+                                   Dart_Handle builtin_lib,
+                                   bool is_service_isolate) {
+  if (!is_service_isolate) {
+    // Setup the 'Uri.base' getter in dart:core.
+    Dart_Handle uri_base = Dart_Invoke(
+        builtin_lib, NewString("_getUriBaseClosure"), 0, NULL);
+    DART_CHECK_VALID(uri_base);
+    Dart_Handle result = Dart_SetField(core_lib,
+                                       NewString("_uriBaseClosure"),
+                                       uri_base);
+    DART_CHECK_VALID(result);
+  }
+}
+
+
+void DartUtils::PrepareAsyncLibrary(Dart_Handle async_lib,
+                                    Dart_Handle isolate_lib) {
+  Dart_Handle schedule_immediate_closure =
+      Dart_Invoke(isolate_lib, NewString("_getIsolateScheduleImmediateClosure"),
+                  0, NULL);
+  Dart_Handle args[1];
+  args[0] = schedule_immediate_closure;
+  DART_CHECK_VALID(Dart_Invoke(
+      async_lib, NewString("_setScheduleImmediateClosure"), 1, args));
+}
+
+
+void DartUtils::PrepareIOLibrary(Dart_Handle io_lib) {
+  DART_CHECK_VALID(Dart_Invoke(io_lib, NewString("_setupHooks"), 0, NULL));
+}
+
+
+void DartUtils::PrepareIsolateLibrary(Dart_Handle isolate_lib) {
+  DART_CHECK_VALID(Dart_Invoke(isolate_lib, NewString("_setupHooks"), 0, NULL));
+}
+
+
 Dart_Handle DartUtils::PrepareForScriptLoading(const char* package_root,
+                                               bool is_service_isolate,
                                                Dart_Handle builtin_lib) {
   // First ensure all required libraries are available.
-  Dart_Handle url = NewString(kAsyncLibURL);
+  Dart_Handle url = NewString(kCoreLibURL);
+  DART_CHECK_VALID(url);
+  Dart_Handle core_lib = Dart_LookupLibrary(url);
+  DART_CHECK_VALID(core_lib);
+  url = NewString(kAsyncLibURL);
   DART_CHECK_VALID(url);
   Dart_Handle async_lib = Dart_LookupLibrary(url);
   DART_CHECK_VALID(async_lib);
+  url = NewString(kIsolateLibURL);
+  DART_CHECK_VALID(url);
+  Dart_Handle isolate_lib = Dart_LookupLibrary(url);
+  DART_CHECK_VALID(isolate_lib);
+  url = NewString(kInternalLibURL);
+  DART_CHECK_VALID(url);
+  Dart_Handle internal_lib = Dart_LookupLibrary(url);
+  DART_CHECK_VALID(internal_lib);
   Dart_Handle io_lib = Builtin::LoadAndCheckLibrary(Builtin::kIOLibrary);
+  DART_CHECK_VALID(io_lib);
 
   // We need to ensure that all the scripts loaded so far are finalized
   // as we are about to invoke some Dart code below to setup closures.
   Dart_Handle result = Dart_FinalizeLoading(false);
   DART_CHECK_VALID(result);
 
-  // Setup the internal library's 'internalPrint' function.
-  Dart_Handle print = Dart_Invoke(
-      builtin_lib, NewString("_getPrintClosure"), 0, NULL);
-  url = NewString(kInternalLibURL);
-  DART_CHECK_VALID(url);
-  Dart_Handle internal_lib = Dart_LookupLibrary(url);
-  DART_CHECK_VALID(internal_lib);
-  result = Dart_SetField(internal_lib,
-                         NewString("_printClosure"),
-                         print);
-  DART_CHECK_VALID(result);
-
-  // Setup the 'timer' factory.
-  Dart_Handle timer_closure =
-      Dart_Invoke(io_lib, NewString("_getTimerFactoryClosure"), 0, NULL);
-  Dart_Handle args[1];
-  args[0] = timer_closure;
-  DART_CHECK_VALID(Dart_Invoke(
-      async_lib, NewString("_setTimerFactoryClosure"), 1, args));
-
-  // Setup the 'scheduleImmediate' closure.
-  url = NewString(kIsolateLibURL);
-  DART_CHECK_VALID(url);
-  Dart_Handle isolate_lib = Dart_LookupLibrary(url);
-  DART_CHECK_VALID(isolate_lib);
-  Dart_Handle schedule_immediate_closure =
-      Dart_Invoke(isolate_lib, NewString("_getIsolateScheduleImmediateClosure"),
-                  0, NULL);
-  args[0] = schedule_immediate_closure;
-  DART_CHECK_VALID(Dart_Invoke(
-      async_lib, NewString("_setScheduleImmediateClosure"), 1, args));
-
-  // Setup the corelib 'Uri.base' getter.
-  url = NewString(kCoreLibURL);
-  DART_CHECK_VALID(url);
-  Dart_Handle corelib = Dart_LookupLibrary(url);
-  DART_CHECK_VALID(corelib);
-  Dart_Handle uri_base = Dart_Invoke(
-      builtin_lib, NewString("_getUriBaseClosure"), 0, NULL);
-  DART_CHECK_VALID(uri_base);
-  result = Dart_SetField(corelib,
-                         NewString("_uriBaseClosure"),
-                         uri_base);
-  DART_CHECK_VALID(result);
-
-  if (IsWindowsHost()) {
-    // Set running on Windows flag.
-    result = Dart_Invoke(builtin_lib, NewString("_setWindows"), 0, NULL);
-    if (Dart_IsError(result)) {
-      return result;
-    }
-  }
-
-  // Set current working directory.
-  result = SetWorkingDirectory(builtin_lib);
-  if (Dart_IsError(result)) {
-    return result;
-  }
-
-  // Set up package root if specified.
-  if (package_root != NULL) {
-    result = NewString(package_root);
-    if (!Dart_IsError(result)) {
-      const int kNumArgs = 1;
-      Dart_Handle dart_args[kNumArgs];
-      dart_args[0] = result;
-      return Dart_Invoke(builtin_lib,
-                         NewString("_setPackageRoot"),
-                         kNumArgs,
-                         dart_args);
-    }
-  }
+  PrepareBuiltinLibrary(builtin_lib,
+                        internal_lib,
+                        is_service_isolate,
+                        package_root);
+  PrepareAsyncLibrary(async_lib, isolate_lib);
+  PrepareCoreLibrary(core_lib, builtin_lib, is_service_isolate);
+  PrepareIsolateLibrary(isolate_lib);
+  PrepareIOLibrary(io_lib);
   return result;
 }
 
 
+void DartUtils::SetupIOLibrary(const char* script_uri) {
+  Dart_Handle io_lib_url = NewString(kIOLibURL);
+  DART_CHECK_VALID(io_lib_url);
+  Dart_Handle io_lib = Dart_LookupLibrary(io_lib_url);
+  DART_CHECK_VALID(io_lib);
+  Dart_Handle platform_type = GetDartType(DartUtils::kIOLibURL, "_Platform");
+  DART_CHECK_VALID(platform_type);
+  Dart_Handle script_name = NewString("_nativeScript");
+  DART_CHECK_VALID(script_name);
+  Dart_Handle dart_script = NewString(script_uri);
+  DART_CHECK_VALID(dart_script);
+  Dart_Handle set_script_name =
+      Dart_SetField(platform_type, script_name, dart_script);
+  DART_CHECK_VALID(set_script_name);
+}
+
+
 bool DartUtils::PostNull(Dart_Port port_id) {
   // Post a message with just the null object.
   return Dart_PostCObject(port_id, CObject::Null()->AsApiCObject());
@@ -769,6 +846,13 @@
 }
 
 
+Dart_Handle DartUtils::NewDartUnsupportedError(const char* message) {
+  return NewDartExceptionWithMessage(kCoreLibURL,
+                                     "UnsupportedError",
+                                     message);
+}
+
+
 Dart_Handle DartUtils::NewDartIOException(const char* exception_name,
                                           const char* message,
                                           Dart_Handle os_error) {
diff --git a/runtime/bin/dartutils.h b/runtime/bin/dartutils.h
index 9b6557c..0b3e817 100644
--- a/runtime/bin/dartutils.h
+++ b/runtime/bin/dartutils.h
@@ -124,8 +124,21 @@
                                        Dart_Handle url);
   static Dart_Handle LoadScript(const char* script_uri,
                                 Dart_Handle builtin_lib);
+  static void PrepareBuiltinLibrary(Dart_Handle builtin_lib,
+                                    Dart_Handle internal_lib,
+                                    bool is_service_isolate,
+                                    const char* package_root);
+  static void PrepareCoreLibrary(Dart_Handle core_lib,
+                                 Dart_Handle builtin_lib,
+                                 bool is_service_isolate);
+  static void PrepareAsyncLibrary(Dart_Handle async_lib,
+                                  Dart_Handle isolate_lib);
+  static void PrepareIOLibrary(Dart_Handle io_lib);
+  static void PrepareIsolateLibrary(Dart_Handle isolate_lib);
   static Dart_Handle PrepareForScriptLoading(const char* package_root,
+                                             bool is_service_isolate,
                                              Dart_Handle builtin_lib);
+  static void SetupIOLibrary(const char* script_uri);
 
   static bool PostNull(Dart_Port port_id);
   static bool PostInt32(Dart_Port port_id, int32_t value);
@@ -145,6 +158,7 @@
                                                  const char* exception_name,
                                                  const char* message);
   static Dart_Handle NewDartArgumentError(const char* message);
+  static Dart_Handle NewDartUnsupportedError(const char* message);
   static Dart_Handle NewDartIOException(const char* exception_name,
                                         const char* message,
                                         Dart_Handle os_error);
diff --git a/runtime/bin/file_patch.dart b/runtime/bin/file_patch.dart
index 2ca3e58..36e5b57 100644
--- a/runtime/bin/file_patch.dart
+++ b/runtime/bin/file_patch.dart
@@ -64,7 +64,7 @@
 
   StreamController _broadcastController;
 
-  /* patch */ static Stream<FileSystemEvent> watch(
+  /* patch */ static Stream<FileSystemEvent> _watch(
       String path, int events, bool recursive) {
     if (Platform.isLinux) {
       return new _InotifyFileSystemWatcher(path, events, recursive).stream;
diff --git a/runtime/bin/gen_snapshot.cc b/runtime/bin/gen_snapshot.cc
index ff2d3b8..719b2b5 100644
--- a/runtime/bin/gen_snapshot.cc
+++ b/runtime/bin/gen_snapshot.cc
@@ -515,8 +515,7 @@
                        DartUtils::ReadFile,
                        DartUtils::WriteFile,
                        DartUtils::CloseFile,
-                       DartUtils::EntropySource,
-                       NULL)) {
+                       DartUtils::EntropySource)) {
     Log::PrintErr("VM initialization failed\n");
     return 255;
   }
@@ -554,7 +553,8 @@
 
     // Prepare for script loading by setting up the 'print' and 'timer'
     // closures and setting up 'package root' for URI resolution.
-    result = DartUtils::PrepareForScriptLoading(package_root, builtin_lib);
+    result =
+        DartUtils::PrepareForScriptLoading(package_root, false, builtin_lib);
     CHECK_RESULT(result);
     Dart_ExitScope();
 
diff --git a/runtime/bin/io_impl_sources.gypi b/runtime/bin/io_impl_sources.gypi
index 390b4ef..9236ec7 100644
--- a/runtime/bin/io_impl_sources.gypi
+++ b/runtime/bin/io_impl_sources.gypi
@@ -59,9 +59,22 @@
   ],
   'conditions': [
     ['dart_io_support==1', {
+      'conditions': [
+        ['dart_io_secure_socket==1', {
+          'sources!' : [
+            'secure_socket_unsupported.cc',
+          ],
+        }, {  # else dart_io_secure_socket == 0
+          'sources!' : [
+            'net/nss_memio.cc',
+            'net/nss_memio.h',
+            'secure_socket.cc',
+            'secure_socket.h',
+          ],
+        }],
+      ],
       'sources!' : [
         'filter_unsupported.cc',
-        'secure_socket_unsupported.cc',
         'io_service_unsupported.cc',
       ],
     },{  # else dart_io_support == 0
diff --git a/runtime/bin/io_natives.cc b/runtime/bin/io_natives.cc
index f8503a3..9756284 100644
--- a/runtime/bin/io_natives.cc
+++ b/runtime/bin/io_natives.cc
@@ -46,7 +46,7 @@
   V(Platform_GetVersion, 0)                                                    \
   V(Process_Start, 11)                                                         \
   V(Process_Wait, 5)                                                           \
-  V(Process_Kill, 3)                                                           \
+  V(Process_KillPid, 2)                                                        \
   V(Process_SetExitCode, 1)                                                    \
   V(Process_GetExitCode, 0)                                                    \
   V(Process_Exit, 1)                                                           \
diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc
index ed47263..251108d 100644
--- a/runtime/bin/main.cc
+++ b/runtime/bin/main.cc
@@ -546,6 +546,7 @@
     return NULL;                                                               \
   }                                                                            \
 
+
 // Returns true on success, false on failure.
 static Dart_Isolate CreateIsolateAndSetupHelper(const char* script_uri,
                                                 const char* main,
@@ -554,8 +555,14 @@
                                                 bool* is_compile_error) {
   ASSERT(script_uri != NULL);
   IsolateData* isolate_data = new IsolateData(script_uri, package_root);
-  Dart_Isolate isolate = Dart_CreateIsolate(
-      script_uri, main, snapshot_buffer, isolate_data, error);
+  Dart_Isolate isolate = NULL;
+
+  isolate = Dart_CreateIsolate(script_uri,
+                               main,
+                               snapshot_buffer,
+                               isolate_data,
+                               error);
+
   if (isolate == NULL) {
     return NULL;
   }
@@ -572,8 +579,16 @@
   Dart_Handle result = Dart_SetLibraryTagHandler(DartUtils::LibraryTagHandler);
   CHECK_RESULT(result);
 
-  result = Dart_SetEnvironmentCallback(EnvironmentCallback);
-  CHECK_RESULT(result);
+  if (Dart_IsServiceIsolate(isolate)) {
+    // If this is the service isolate, load embedder specific bits and return.
+    if (!VmService::Setup(vm_service_server_ip, vm_service_server_port)) {
+      *error = strdup(VmService::GetErrorMessage());
+      return NULL;
+    }
+    Dart_ExitScope();
+    Dart_ExitIsolate();
+    return isolate;
+  }
 
   // Load the specified application script into the newly created isolate.
 
@@ -586,9 +601,13 @@
 
   // Prepare for script loading by setting up the 'print' and 'timer'
   // closures and setting up 'package root' for URI resolution.
-  result = DartUtils::PrepareForScriptLoading(package_root, builtin_lib);
+  result = DartUtils::PrepareForScriptLoading(package_root, false, builtin_lib);
   CHECK_RESULT(result);
 
+  result = Dart_SetEnvironmentCallback(EnvironmentCallback);
+  CHECK_RESULT(result);
+
+  // Load the script.
   result = DartUtils::LoadScript(script_uri, builtin_lib);
   CHECK_RESULT(result);
 
@@ -597,20 +616,8 @@
   CHECK_RESULT(result);
 
   Platform::SetPackageRoot(package_root);
-  Dart_Handle io_lib_url = DartUtils::NewString(DartUtils::kIOLibURL);
-  CHECK_RESULT(io_lib_url);
-  Dart_Handle io_lib = Dart_LookupLibrary(io_lib_url);
-  CHECK_RESULT(io_lib);
-  Dart_Handle platform_type = DartUtils::GetDartType(DartUtils::kIOLibURL,
-                                                     "_Platform");
-  CHECK_RESULT(platform_type);
-  Dart_Handle script_name = DartUtils::NewString("_nativeScript");
-  CHECK_RESULT(script_name);
-  Dart_Handle dart_script = DartUtils::NewString(script_uri);
-  CHECK_RESULT(dart_script);
-  Dart_Handle set_script_name =
-      Dart_SetField(platform_type, script_name, dart_script);
-  CHECK_RESULT(set_script_name);
+
+  DartUtils::SetupIOLibrary(script_uri);
 
   // Make the isolate runnable so that it is ready to handle messages.
   Dart_ExitScope();
@@ -646,7 +653,11 @@
     }
   }
   if (package_root == NULL) {
-    package_root = parent_isolate_data->package_root;
+    if (parent_isolate_data != NULL) {
+      package_root = parent_isolate_data->package_root;
+    } else {
+      package_root = ".";
+    }
   }
   return CreateIsolateAndSetupHelper(script_uri,
                                      main,
@@ -656,50 +667,6 @@
 }
 
 
-#define CHECK_RESULT(result)                                                   \
-  if (Dart_IsError(result)) {                                                  \
-    *error = strdup(Dart_GetError(result));                                    \
-    Dart_ExitScope();                                                          \
-    Dart_ShutdownIsolate();                                                    \
-    return NULL;                                                               \
-  }                                                                            \
-
-static Dart_Isolate CreateServiceIsolate(void* data, char** error) {
-  const char* script_uri = DartUtils::kVMServiceLibURL;
-  IsolateData* isolate_data = new IsolateData(script_uri, NULL);
-  Dart_Isolate isolate =
-      Dart_CreateIsolate(script_uri, "main", snapshot_buffer, isolate_data,
-                         error);
-  if (isolate == NULL) {
-    return NULL;
-  }
-  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);
-  CHECK_RESULT(result);
-  result = Dart_SetEnvironmentCallback(EnvironmentCallback);
-  CHECK_RESULT(result);
-  // Prepare builtin and its dependent libraries for use to resolve URIs.
-  Dart_Handle builtin_lib =
-      Builtin::LoadAndCheckLibrary(Builtin::kBuiltinLibrary);
-  CHECK_RESULT(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(NULL, builtin_lib);
-  CHECK_RESULT(result);
-
-  Dart_ExitScope();
-  Dart_ExitIsolate();
-  return isolate;
-}
-
-#undef CHECK_RESULT
-
 static void PrintVersion() {
   Log::PrintErr("Dart VM version: %s\n", Dart_VersionString());
 }
@@ -980,21 +947,22 @@
 
   Dart_SetVMFlags(vm_options.count(), vm_options.arguments());
 
+  // Start event handler.
+  EventHandler::Start();
+
   // Initialize the Dart VM.
   if (!Dart_Initialize(CreateIsolateAndSetup, NULL, NULL, ShutdownIsolate,
                        DartUtils::OpenFile,
                        DartUtils::ReadFile,
                        DartUtils::WriteFile,
                        DartUtils::CloseFile,
-                       DartUtils::EntropySource,
-                       CreateServiceIsolate)) {
+                       DartUtils::EntropySource)) {
     fprintf(stderr, "%s", "VM initialization failed\n");
     fflush(stderr);
     exit(kErrorExitCode);
   }
 
-  // Start event handler.
-  EventHandler::Start();
+
 
   // Start the debugger wire protocol handler if necessary.
   if (start_debugger) {
@@ -1004,23 +972,12 @@
     if (print_msg) {
       Log::Print("Debugger listening on port %d\n", debug_port);
     }
+  } else {
+    DebuggerConnectionHandler::InitForVmService();
   }
 
-  ASSERT(Dart_CurrentIsolate() == NULL);
-  // Start the VM service isolate, if necessary.
-  if (start_vm_service) {
-    if (!start_debugger) {
-      DebuggerConnectionHandler::InitForVmService();
-    }
-    bool r = VmService::Start(vm_service_server_ip, vm_service_server_port);
-    if (!r) {
-      Log::PrintErr("Could not start VM Service isolate %s\n",
-                    VmService::GetErrorMessage());
-    }
-    Dart_RegisterIsolateServiceRequestCallback(
+  Dart_RegisterIsolateServiceRequestCallback(
         "io", &ServiceRequestHandler, NULL);
-  }
-  ASSERT(Dart_CurrentIsolate() == NULL);
 
   // Call CreateIsolateAndSetup which creates an isolate and loads up
   // the specified application script.
diff --git a/runtime/bin/platform.h b/runtime/bin/platform.h
index ca723ae3..78cb33d 100644
--- a/runtime/bin/platform.h
+++ b/runtime/bin/platform.h
@@ -24,6 +24,11 @@
   // deallocated by the caller.
   static const char* OperatingSystem();
 
+  // Returns a string representing the operating system's shared library
+  // extension (e.g. 'so', 'dll', ...). The returned string should not be
+  // deallocated by the caller.
+  static const char* LibraryExtension();
+
   // Extracts the local hostname.
   static bool LocalHostname(char* buffer, intptr_t buffer_length);
 
diff --git a/runtime/bin/platform_android.cc b/runtime/bin/platform_android.cc
index b30e46d..b1e7d33 100644
--- a/runtime/bin/platform_android.cc
+++ b/runtime/bin/platform_android.cc
@@ -42,6 +42,11 @@
 }
 
 
+const char* Platform::LibraryExtension() {
+  return "so";
+}
+
+
 bool Platform::LocalHostname(char *buffer, intptr_t buffer_length) {
   return gethostname(buffer, buffer_length) == 0;
 }
diff --git a/runtime/bin/platform_linux.cc b/runtime/bin/platform_linux.cc
index 7f37936..f6dfaa1 100644
--- a/runtime/bin/platform_linux.cc
+++ b/runtime/bin/platform_linux.cc
@@ -42,6 +42,11 @@
 }
 
 
+const char* Platform::LibraryExtension() {
+  return "so";
+}
+
+
 bool Platform::LocalHostname(char *buffer, intptr_t buffer_length) {
   return gethostname(buffer, buffer_length) == 0;
 }
diff --git a/runtime/bin/platform_macos.cc b/runtime/bin/platform_macos.cc
index 365caf1..55ccd21 100644
--- a/runtime/bin/platform_macos.cc
+++ b/runtime/bin/platform_macos.cc
@@ -43,6 +43,11 @@
 }
 
 
+const char* Platform::LibraryExtension() {
+  return "dylib";
+}
+
+
 bool Platform::LocalHostname(char *buffer, intptr_t buffer_length) {
   return gethostname(buffer, buffer_length) == 0;
 }
diff --git a/runtime/bin/platform_win.cc b/runtime/bin/platform_win.cc
index d56c971..97d54cc 100644
--- a/runtime/bin/platform_win.cc
+++ b/runtime/bin/platform_win.cc
@@ -32,9 +32,18 @@
 }
 
 
+const char* Platform::LibraryExtension() {
+  return "dll";
+}
+
+
 bool Platform::LocalHostname(char *buffer, intptr_t buffer_length) {
+#if defined(PLATFORM_DISABLE_SOCKET)
+  return false;
+#else
   if (!Socket::Initialize()) return false;
   return gethostname(buffer, buffer_length) == 0;
+#endif
 }
 
 
diff --git a/runtime/bin/process.cc b/runtime/bin/process.cc
index 5203530..88ace0e 100644
--- a/runtime/bin/process.cc
+++ b/runtime/bin/process.cc
@@ -118,7 +118,8 @@
       return;
     }
   }
-  bool detached = DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 5));
+  int64_t mode =
+      DartUtils::GetInt64ValueCheckRange(Dart_GetNativeArgument(args, 5), 0, 2);
   Dart_Handle stdin_handle = Dart_GetNativeArgument(args, 6);
   Dart_Handle stdout_handle = Dart_GetNativeArgument(args, 7);
   Dart_Handle stderr_handle = Dart_GetNativeArgument(args, 8);
@@ -132,7 +133,7 @@
                                   working_directory,
                                   string_environment,
                                   environment_length,
-                                  detached,
+                                  static_cast<ProcessStartMode>(mode),
                                   &process_stdout,
                                   &process_stdin,
                                   &process_stderr,
@@ -140,10 +141,12 @@
                                   &exit_event,
                                   &os_error_message);
   if (error_code == 0) {
-    if (!detached) {
+    if (mode != kDetached) {
       Socket::SetSocketIdNativeField(stdin_handle, process_stdin);
       Socket::SetSocketIdNativeField(stdout_handle, process_stdout);
       Socket::SetSocketIdNativeField(stderr_handle, process_stderr);
+    }
+    if (mode == kNormal) {
       Socket::SetSocketIdNativeField(exit_handle, exit_event);
     }
     Process::SetProcessIdNativeField(process, pid);
@@ -151,7 +154,10 @@
     DartUtils::SetIntegerField(
         status_handle, "_errorCode", error_code);
     DartUtils::SetStringField(
-        status_handle, "_errorMessage", os_error_message);
+        status_handle,
+        "_errorMessage",
+        os_error_message != NULL ? os_error_message
+                                 : "Cannot get error message");
   }
   delete[] string_args;
   delete[] string_environment;
@@ -198,11 +204,9 @@
 }
 
 
-void FUNCTION_NAME(Process_Kill)(Dart_NativeArguments args) {
-  Dart_Handle process = Dart_GetNativeArgument(args, 1);
-  intptr_t pid = -1;
-  Process::GetProcessIdNativeField(process, &pid);
-  intptr_t signal = DartUtils::GetIntptrValue(Dart_GetNativeArgument(args, 2));
+void FUNCTION_NAME(Process_KillPid)(Dart_NativeArguments args) {
+  intptr_t pid = DartUtils::GetIntptrValue(Dart_GetNativeArgument(args, 0));
+  intptr_t signal = DartUtils::GetIntptrValue(Dart_GetNativeArgument(args, 1));
   bool success = Process::Kill(pid, signal);
   Dart_SetReturnValue(args, Dart_NewBoolean(success));
 }
diff --git a/runtime/bin/process.h b/runtime/bin/process.h
index 1892122..b6babd3 100644
--- a/runtime/bin/process.h
+++ b/runtime/bin/process.h
@@ -77,6 +77,14 @@
 };
 
 
+// To be kept in sync with ProcessStartMode consts in sdk/lib/io/process.dart.
+enum ProcessStartMode {
+  kNormal = 0,
+  kDetached = 1,
+  kDetachedWithStdio = 2,
+};
+
+
 class Process {
  public:
   // Start a new process providing access to stdin, stdout, stderr and
@@ -87,7 +95,7 @@
                    const char* working_directory,
                    char* environment[],
                    intptr_t environment_length,
-                   bool detached,
+                   ProcessStartMode mode,
                    intptr_t* in,
                    intptr_t* out,
                    intptr_t* err,
diff --git a/runtime/bin/process_android.cc b/runtime/bin/process_android.cc
index 58faa04..bb91cbb 100644
--- a/runtime/bin/process_android.cc
+++ b/runtime/bin/process_android.cc
@@ -230,56 +230,519 @@
 Monitor* ExitCodeHandler::monitor_ = new Monitor();
 
 
-static void SetChildOsErrorMessage(char** os_error_message) {
-  const int kBufferSize = 1024;
-  char error_message[kBufferSize];
-  strerror_r(errno, error_message, kBufferSize);
-  *os_error_message = strdup(error_message);
-}
+class ProcessStarter {
+ public:
+  ProcessStarter(const char* path,
+                 char* arguments[],
+                 intptr_t arguments_length,
+                 const char* working_directory,
+                 char* environment[],
+                 intptr_t environment_length,
+                 ProcessStartMode mode,
+                 intptr_t* in,
+                 intptr_t* out,
+                 intptr_t* err,
+                 intptr_t* id,
+                 intptr_t* exit_event,
+                 char** os_error_message)
+      : path_(path),
+        working_directory_(working_directory),
+        mode_(mode),
+        in_(in),
+        out_(out),
+        err_(err),
+        id_(id),
+        exit_event_(exit_event),
+        os_error_message_(os_error_message) {
+    read_in_[0] = -1;
+    read_in_[1] = -1;
+    read_err_[0] = -1;
+    read_err_[1] = -1;
+    write_out_[0] = -1;
+    write_out_[1] = -1;
+    exec_control_[0] = -1;
+    exec_control_[1] = -1;
+
+    program_arguments_ = new char*[arguments_length + 2];
+    program_arguments_[0] = const_cast<char*>(path_);
+    for (int i = 0; i < arguments_length; i++) {
+      program_arguments_[i + 1] = arguments[i];
+    }
+    program_arguments_[arguments_length + 1] = NULL;
+
+    program_environment_ = NULL;
+    if (environment != NULL) {
+      program_environment_ = new char*[environment_length + 1];
+      for (int i = 0; i < environment_length; i++) {
+        program_environment_[i] = environment[i];
+      }
+      program_environment_[environment_length] = NULL;
+    }
+  }
 
 
-static void ReportChildError(int exec_control_fd) {
-  // In the case of failure in the child process write the errno and
-  // the OS error message to the exec control pipe and exit.
-  int child_errno = errno;
-  const int kBufferSize = 1024;
-  char os_error_message[kBufferSize];
-  strerror_r(errno, os_error_message, kBufferSize);
-  ASSERT(sizeof(child_errno) == sizeof(errno));
-  int bytes_written =
+  ~ProcessStarter() {
+    delete[] program_arguments_;
+    delete[] program_environment_;
+  }
+
+
+  int Start() {
+    // Create pipes required.
+    int err = CreatePipes();
+    if (err != 0) return err;
+
+    // Fork to create the new process.
+    pid_t pid = TEMP_FAILURE_RETRY(fork());
+    if (pid < 0) {
+      // Failed to fork.
+      return CleanupAndReturnError();
+    } else if (pid == 0) {
+      // This runs in the new process.
+      NewProcess();
+    }
+
+    // This runs in the original process.
+
+    // Be sure to listen for exit-codes, now we have a child-process.
+    ExitCodeHandler::ProcessStarted();
+
+    // Register the child process if not detached.
+    if (mode_ == kNormal) {
+      err = RegisterProcess(pid);
+      if (err != 0) return err;
+    }
+
+    // Notify child process to start. This is done to delay the call to exec
+    // until the process is registered above, and we are ready to receive the
+    // exit code.
+    char msg = '1';
+    int bytes_written =
+        FDUtils::WriteToBlocking(read_in_[1], &msg, sizeof(msg));
+    if (bytes_written != sizeof(msg)) {
+      return CleanupAndReturnError();
+    }
+
+    // Read the result of executing the child process.
+    VOID_TEMP_FAILURE_RETRY(close(exec_control_[1]));
+    exec_control_[1] = -1;
+    if (mode_ == kNormal) {
+      err = ReadExecResult();
+    } else {
+      err = ReadDetachedExecResult(&pid);
+    }
+    VOID_TEMP_FAILURE_RETRY(close(exec_control_[0]));
+    exec_control_[0] = -1;
+
+    // Return error code if any failures.
+    if (err != 0) {
+      if (mode_ == kNormal) {
+        // Since exec() failed, we're not interested in the exit code.
+        // We close the reading side of the exit code pipe here.
+        // GetProcessExitCodes will get a broken pipe error when it
+        // tries to write to the writing side of the pipe and it will
+        // ignore the error.
+        VOID_TEMP_FAILURE_RETRY(close(*exit_event_));
+        *exit_event_ = -1;
+      }
+      CloseAllPipes();
+      return err;
+    }
+
+    if (mode_ != kDetached) {
+      // Connect stdio, stdout and stderr.
+      FDUtils::SetNonBlocking(read_in_[0]);
+      *in_ = read_in_[0];
+      VOID_TEMP_FAILURE_RETRY(close(read_in_[1]));
+      FDUtils::SetNonBlocking(write_out_[1]);
+      *out_ = write_out_[1];
+      VOID_TEMP_FAILURE_RETRY(close(write_out_[0]));
+      FDUtils::SetNonBlocking(read_err_[0]);
+      *err_ = read_err_[0];
+      VOID_TEMP_FAILURE_RETRY(close(read_err_[1]));
+    } else {
+      // Close all fds.
+      VOID_TEMP_FAILURE_RETRY(close(read_in_[0]));
+      VOID_TEMP_FAILURE_RETRY(close(read_in_[1]));
+      ASSERT(write_out_[0] == -1);
+      ASSERT(write_out_[1] == -1);
+      ASSERT(read_err_[0] == -1);
+      ASSERT(read_err_[1] == -1);
+    }
+    ASSERT(exec_control_[0] == -1);
+    ASSERT(exec_control_[1] == -1);
+
+    *id_ = pid;
+    return 0;
+  }
+
+ private:
+  int CreatePipes() {
+    int result;
+    result = TEMP_FAILURE_RETRY(pipe(exec_control_));
+    if (result < 0) {
+      return CleanupAndReturnError();
+    }
+    FDUtils::SetCloseOnExec(exec_control_[0]);
+    FDUtils::SetCloseOnExec(exec_control_[1]);
+
+    // For a detached process the pipe to connect stdout is still used for
+    // signaling when to do the first fork.
+    result = TEMP_FAILURE_RETRY(pipe(read_in_));
+    if (result < 0) {
+      return CleanupAndReturnError();
+    }
+    FDUtils::SetCloseOnExec(read_in_[0]);
+
+    // For detached processes the pipe to connect stderr and stdin are not used.
+    if (mode_ != kDetached) {
+      result = TEMP_FAILURE_RETRY(pipe(read_err_));
+      if (result < 0) {
+        return CleanupAndReturnError();
+      }
+      FDUtils::SetCloseOnExec(read_err_[0]);
+
+      result = TEMP_FAILURE_RETRY(pipe(write_out_));
+      if (result < 0) {
+        return CleanupAndReturnError();
+      }
+      FDUtils::SetCloseOnExec(write_out_[1]);
+    }
+
+    return 0;
+  }
+
+
+  void NewProcess() {
+    // Wait for parent process before setting up the child process.
+    char msg;
+    int bytes_read = FDUtils::ReadFromBlocking(read_in_[0], &msg, sizeof(msg));
+    if (bytes_read != sizeof(msg)) {
+      perror("Failed receiving notification message");
+      exit(1);
+    }
+    if (mode_ == kNormal) {
+      ExecProcess();
+    } else {
+      ExecDetachedProcess();
+    }
+  }
+
+
+  void ExecProcess() {
+    VOID_TEMP_FAILURE_RETRY(close(write_out_[1]));
+    VOID_TEMP_FAILURE_RETRY(close(read_in_[0]));
+    VOID_TEMP_FAILURE_RETRY(close(read_err_[0]));
+    VOID_TEMP_FAILURE_RETRY(close(exec_control_[0]));
+
+    if (TEMP_FAILURE_RETRY(dup2(write_out_[0], STDIN_FILENO)) == -1) {
+      ReportChildError();
+    }
+    VOID_TEMP_FAILURE_RETRY(close(write_out_[0]));
+
+    if (TEMP_FAILURE_RETRY(dup2(read_in_[1], STDOUT_FILENO)) == -1) {
+      ReportChildError();
+    }
+    VOID_TEMP_FAILURE_RETRY(close(read_in_[1]));
+
+    if (TEMP_FAILURE_RETRY(dup2(read_err_[1], STDERR_FILENO)) == -1) {
+      ReportChildError();
+    }
+    VOID_TEMP_FAILURE_RETRY(close(read_err_[1]));
+
+    if (working_directory_ != NULL &&
+        TEMP_FAILURE_RETRY(chdir(working_directory_)) == -1) {
+      ReportChildError();
+    }
+
+    if (program_environment_ != NULL) {
+      environ = program_environment_;
+    }
+
+    VOID_TEMP_FAILURE_RETRY(
+        execvp(path_, const_cast<char* const*>(program_arguments_)));
+
+    ReportChildError();
+  }
+
+
+  void ExecDetachedProcess() {
+    if (mode_ == kDetached) {
+      ASSERT(write_out_[0] == -1);
+      ASSERT(write_out_[1] == -1);
+      ASSERT(read_err_[0] == -1);
+      ASSERT(read_err_[1] == -1);
+      // For a detached process the pipe to connect stdout is only used for
+      // signaling when to do the first fork.
+      VOID_TEMP_FAILURE_RETRY(close(read_in_[0]));
+      read_in_[0] = -1;
+      VOID_TEMP_FAILURE_RETRY(close(read_in_[1]));
+      read_in_[1] = -1;
+    } else {
+      // Don't close any fds if keeping stdio open to the detached process.
+      ASSERT(mode_ == kDetachedWithStdio);
+    }
+    // Fork once more to start a new session.
+    pid_t pid = TEMP_FAILURE_RETRY(fork());
+    if (pid < 0) {
+      ReportChildError();
+    } else if (pid == 0) {
+      // Start a new session.
+      if (TEMP_FAILURE_RETRY(setsid()) == -1) {
+        ReportChildError();
+      } else {
+        // Do a final fork to not be the session leader.
+        pid = TEMP_FAILURE_RETRY(fork());
+        if (pid < 0) {
+          ReportChildError();
+        } else if (pid == 0) {
+          if (mode_ == kDetached) {
+            SetupDetached();
+          } else {
+            SetupDetachedWithStdio();
+          }
+
+          if (working_directory_ != NULL &&
+              TEMP_FAILURE_RETRY(chdir(working_directory_)) == -1) {
+            ReportChildError();
+          }
+
+          // Report the final PID and do the exec.
+          ReportPid(getpid());  // getpid cannot fail.
+          VOID_TEMP_FAILURE_RETRY(
+              execvp(path_, const_cast<char* const*>(program_arguments_)));
+          ReportChildError();
+        } else {
+          // Exit the intermeiate process.
+          exit(0);
+        }
+      }
+    } else {
+      // Exit the intermeiate process.
+      exit(0);
+    }
+  }
+
+
+  int RegisterProcess(pid_t pid) {
+    int result;
+    int event_fds[2];
+    result = TEMP_FAILURE_RETRY(pipe(event_fds));
+    if (result < 0) {
+      return CleanupAndReturnError();
+    }
+    FDUtils::SetCloseOnExec(event_fds[0]);
+    FDUtils::SetCloseOnExec(event_fds[1]);
+
+    ProcessInfoList::AddProcess(pid, event_fds[1]);
+    *exit_event_ = event_fds[0];
+    FDUtils::SetNonBlocking(event_fds[0]);
+    return 0;
+  }
+
+
+  int ReadExecResult() {
+    int child_errno;
+    int bytes_read = -1;
+    // Read exec result from child. If no data is returned the exec was
+    // successful and the exec call closed the pipe. Otherwise the errno
+    // is written to the pipe.
+    bytes_read =
+        FDUtils::ReadFromBlocking(
+            exec_control_[0], &child_errno, sizeof(child_errno));
+    if (bytes_read == sizeof(child_errno)) {
+      ReadChildError();
+      return child_errno;
+    } else if (bytes_read == -1) {
+      return errno;
+    }
+    return 0;
+  }
+
+
+  int ReadDetachedExecResult(pid_t *pid) {
+    int child_errno;
+    int bytes_read = -1;
+    // Read exec result from child. If only pid data is returned the exec was
+    // successful and the exec call closed the pipe. Otherwise the errno
+    // is written to the pipe as well.
+    int result[2];
+    bytes_read =
+        FDUtils::ReadFromBlocking(
+            exec_control_[0], result, sizeof(result));
+    if (bytes_read == sizeof(int)) {
+      *pid = result[0];
+    } else if (bytes_read == 2 * sizeof(int)) {
+      *pid = result[0];
+      child_errno = result[1];
+      ReadChildError();
+      return child_errno;
+    } else if (bytes_read == -1) {
+      return errno;
+    }
+    return 0;
+  }
+
+
+  void SetupDetached() {
+    ASSERT(mode_ == kDetached);
+
+    // Close all open file descriptors except for exec_control_[1].
+    int max_fds = sysconf(_SC_OPEN_MAX);
+    if (max_fds == -1) max_fds = _POSIX_OPEN_MAX;
+    for (int fd = 0; fd < max_fds; fd++) {
+      if (fd != exec_control_[1]) {
+        VOID_TEMP_FAILURE_RETRY(close(fd));
+      }
+    }
+
+    // Re-open stdin, stdout and stderr and connect them to /dev/null.
+    // The loop above should already have closed all of them, so
+    // creating new file descriptors should start at STDIN_FILENO.
+    int fd = TEMP_FAILURE_RETRY(open("/dev/null", O_RDWR));
+    if (fd != STDIN_FILENO) {
+      ReportChildError();
+    }
+    if (TEMP_FAILURE_RETRY(dup2(STDIN_FILENO, STDOUT_FILENO)) !=
+        STDOUT_FILENO) {
+      ReportChildError();
+    }
+    if (TEMP_FAILURE_RETRY(dup2(STDIN_FILENO, STDERR_FILENO)) !=
+        STDERR_FILENO) {
+      ReportChildError();
+    }
+  }
+
+  void SetupDetachedWithStdio() {
+    // Close all open file descriptors except for
+    // exec_control_[1], write_out_[0], read_in_[1] and
+    // read_err_[1].
+    int max_fds = sysconf(_SC_OPEN_MAX);
+    if (max_fds == -1) max_fds = _POSIX_OPEN_MAX;
+    for (int fd = 0; fd < max_fds; fd++) {
+      if (fd != exec_control_[1] &&
+          fd != write_out_[0] &&
+          fd != read_in_[1] &&
+          fd != read_err_[1]) {
+        VOID_TEMP_FAILURE_RETRY(close(fd));
+      }
+    }
+
+    if (TEMP_FAILURE_RETRY(dup2(write_out_[0], STDIN_FILENO)) == -1) {
+      ReportChildError();
+    }
+    VOID_TEMP_FAILURE_RETRY(close(write_out_[0]));
+
+    if (TEMP_FAILURE_RETRY(dup2(read_in_[1], STDOUT_FILENO)) == -1) {
+      ReportChildError();
+    }
+    VOID_TEMP_FAILURE_RETRY(close(read_in_[1]));
+
+    if (TEMP_FAILURE_RETRY(dup2(read_err_[1], STDERR_FILENO)) == -1) {
+      ReportChildError();
+    }
+    VOID_TEMP_FAILURE_RETRY(close(read_err_[1]));
+  }
+
+
+  int CleanupAndReturnError() {
+    int actual_errno = errno;
+    // If CleanupAndReturnError is called without an actual errno make
+    // sure to return an error anyway.
+    if (actual_errno == 0) actual_errno = EPERM;
+    SetChildOsErrorMessage();
+    CloseAllPipes();
+    return actual_errno;
+  }
+
+
+  void SetChildOsErrorMessage() {
+    const int kBufferSize = 1024;
+    char error_message[kBufferSize];
+    strerror_r(errno, error_message, kBufferSize);
+    *os_error_message_ = strdup(error_message);
+  }
+
+
+  void ReportChildError() {
+    // In the case of failure in the child process write the errno and
+    // the OS error message to the exec control pipe and exit.
+    int child_errno = errno;
+    const int kBufferSize = 1024;
+    char os_error_message[kBufferSize];
+    strerror_r(errno, os_error_message, kBufferSize);
+    int bytes_written =
+        FDUtils::WriteToBlocking(
+            exec_control_[1], &child_errno, sizeof(child_errno));
+    if (bytes_written == sizeof(child_errno)) {
       FDUtils::WriteToBlocking(
-          exec_control_fd, &child_errno, sizeof(child_errno));
-  if (bytes_written == sizeof(child_errno)) {
-    FDUtils::WriteToBlocking(
-        exec_control_fd, os_error_message, strlen(os_error_message) + 1);
+          exec_control_[1], os_error_message, strlen(os_error_message) + 1);
+    }
+    VOID_TEMP_FAILURE_RETRY(close(exec_control_[1]));
+    exit(1);
   }
-  VOID_TEMP_FAILURE_RETRY(close(exec_control_fd));
-  exit(1);
-}
 
 
-static void ReportPid(int exec_control_fd, int pid) {
-  // In the case of starting a detached process the actual pid of that process
-  // is communicated using the exec control pipe.
-  int bytes_written =
-      FDUtils::WriteToBlocking(exec_control_fd, &pid, sizeof(pid));
-  ASSERT(bytes_written == sizeof(int));
-  USE(bytes_written);
-}
-
-
-static void ReadChildError(int exec_control_fd, char** error_message) {
-  const int kMaxMessageSize = 256;
-  char* message = static_cast<char*>(malloc(kMaxMessageSize));
-  if (message != NULL) {
-    FDUtils::ReadFromBlocking(exec_control_fd, message, kMaxMessageSize);
-    message[kMaxMessageSize - 1] = '\0';
-    *error_message = message;
-  } else {
-    static const char* no_message = "Cannot get error message, out of memory";
-    *error_message = const_cast<char*>(no_message);
+  void ReportPid(int pid) {
+    // In the case of starting a detached process the actual pid of that process
+    // is communicated using the exec control pipe.
+    int bytes_written =
+        FDUtils::WriteToBlocking(exec_control_[1], &pid, sizeof(pid));
+    ASSERT(bytes_written == sizeof(int));
+    USE(bytes_written);
   }
-}
+
+
+  void ReadChildError() {
+    const int kMaxMessageSize = 256;
+    char* message = static_cast<char*>(malloc(kMaxMessageSize));
+    if (message != NULL) {
+      FDUtils::ReadFromBlocking(exec_control_[0], message, kMaxMessageSize);
+      message[kMaxMessageSize - 1] = '\0';
+      *os_error_message_ = message;
+    } else {
+      // Could not get error message. It will be NULL.
+      ASSERT(*os_error_message_ == NULL);
+    }
+  }
+
+
+  void ClosePipe(int* fds) {
+    for (int i = 0; i < 2; i++) {
+      if (fds[i] != -1) {
+        VOID_TEMP_FAILURE_RETRY(close(fds[i]));
+        fds[i] = -1;
+      }
+    }
+  }
+
+
+  void CloseAllPipes() {
+    ClosePipe(exec_control_);
+    ClosePipe(read_in_);
+    ClosePipe(read_err_);
+    ClosePipe(write_out_);
+  }
+
+
+  int read_in_[2];  // Pipe for stdout to child process.
+  int read_err_[2];  // Pipe for stderr to child process.
+  int write_out_[2];  // Pipe for stdin to child process.
+  int exec_control_[2];  // Pipe to get the result from exec.
+
+  char** program_arguments_;
+  char** program_environment_;
+
+  const char* path_;
+  const char* working_directory_;
+  ProcessStartMode mode_;
+  intptr_t* in_;
+  intptr_t* out_;
+  intptr_t* err_;
+  intptr_t* id_;
+  intptr_t* exit_event_;
+  char** os_error_message_;
+};
 
 
 int Process::Start(const char* path,
@@ -288,310 +751,27 @@
                    const char* working_directory,
                    char* environment[],
                    intptr_t environment_length,
-                   bool detach,
+                   ProcessStartMode mode,
                    intptr_t* in,
                    intptr_t* out,
                    intptr_t* err,
                    intptr_t* id,
                    intptr_t* exit_event,
                    char** os_error_message) {
-  pid_t pid;
-  int read_in[2] = {-1, -1};  // Pipe for stdout to child process.
-  int read_err[2] = {-1, -1};  // Pipe for stderr to child process.
-  int write_out[2] = {-1, -1};  // Pipe for stdin to child process.
-  int exec_control[2] = {-1, -1};  // Pipe to get the result from exec.
-  int result;
-
-  result = TEMP_FAILURE_RETRY(pipe(exec_control));
-  if (result < 0) {
-    SetChildOsErrorMessage(os_error_message);
-    Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message);
-    return errno;
-  }
-  FDUtils::SetCloseOnExec(exec_control[0]);
-  FDUtils::SetCloseOnExec(exec_control[1]);
-
-  // For a detached process the pipe to connect stdout is still used for
-  // signaling when to do the first fork.
-  result = TEMP_FAILURE_RETRY(pipe(read_in));
-  if (result < 0) {
-    SetChildOsErrorMessage(os_error_message);
-    VOID_TEMP_FAILURE_RETRY(close(exec_control[0]));
-    VOID_TEMP_FAILURE_RETRY(close(exec_control[1]));
-    Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message);
-    return errno;
-  }
-  FDUtils::SetCloseOnExec(read_in[0]);
-
-  // For detached processes the pipe to connect stderr and stdin are not used.
-  if (!detach) {
-    result = TEMP_FAILURE_RETRY(pipe(read_err));
-    if (result < 0) {
-      SetChildOsErrorMessage(os_error_message);
-      VOID_TEMP_FAILURE_RETRY(close(exec_control[0]));
-      VOID_TEMP_FAILURE_RETRY(close(exec_control[1]));
-      VOID_TEMP_FAILURE_RETRY(close(read_in[0]));
-      VOID_TEMP_FAILURE_RETRY(close(read_in[1]));
-      Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message);
-      return errno;
-    }
-    FDUtils::SetCloseOnExec(read_err[0]);
-
-    result = TEMP_FAILURE_RETRY(pipe(write_out));
-    if (result < 0) {
-      SetChildOsErrorMessage(os_error_message);
-      VOID_TEMP_FAILURE_RETRY(close(exec_control[0]));
-      VOID_TEMP_FAILURE_RETRY(close(exec_control[1]));
-      VOID_TEMP_FAILURE_RETRY(close(read_in[0]));
-      VOID_TEMP_FAILURE_RETRY(close(read_in[1]));
-      VOID_TEMP_FAILURE_RETRY(close(read_err[0]));
-      VOID_TEMP_FAILURE_RETRY(close(read_err[1]));
-      Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message);
-      return errno;
-    }
-    FDUtils::SetCloseOnExec(write_out[1]);
-  }
-
-  char** program_arguments = new char*[arguments_length + 2];
-  program_arguments[0] = const_cast<char*>(path);
-  for (int i = 0; i < arguments_length; i++) {
-    program_arguments[i + 1] = arguments[i];
-  }
-  program_arguments[arguments_length + 1] = NULL;
-
-  char** program_environment = NULL;
-  if (environment != NULL) {
-    program_environment = new char*[environment_length + 1];
-    for (int i = 0; i < environment_length; i++) {
-      program_environment[i] = environment[i];
-    }
-    program_environment[environment_length] = NULL;
-  }
-
-  pid = TEMP_FAILURE_RETRY(fork());
-  if (pid < 0) {
-    SetChildOsErrorMessage(os_error_message);
-    delete[] program_arguments;
-    VOID_TEMP_FAILURE_RETRY(close(exec_control[0]));
-    VOID_TEMP_FAILURE_RETRY(close(exec_control[1]));
-    VOID_TEMP_FAILURE_RETRY(close(read_in[0]));
-    VOID_TEMP_FAILURE_RETRY(close(read_in[1]));
-    if (!detach) {
-      VOID_TEMP_FAILURE_RETRY(close(read_err[0]));
-      VOID_TEMP_FAILURE_RETRY(close(read_err[1]));
-      VOID_TEMP_FAILURE_RETRY(close(write_out[0]));
-      VOID_TEMP_FAILURE_RETRY(close(write_out[1]));
-    }
-    return errno;
-  } else if (pid == 0) {
-    // Wait for parent process before setting up the child process.
-    char msg;
-    int bytes_read = FDUtils::ReadFromBlocking(read_in[0], &msg, sizeof(msg));
-    if (bytes_read != sizeof(msg)) {
-      perror("Failed receiving notification message");
-      exit(1);
-    }
-    if (detach) {
-      // For a detached process the pipe to connect stdout is only used for
-      // signaling when to do the first fork.
-      VOID_TEMP_FAILURE_RETRY(close(read_in[0]));
-      VOID_TEMP_FAILURE_RETRY(close(read_in[1]));
-      // Fork once more to start a new session.
-      pid = TEMP_FAILURE_RETRY(fork());
-      if (pid < 0) {
-        ReportChildError(exec_control[1]);
-      } else if (pid == 0) {
-        // Start a new session.
-        if (TEMP_FAILURE_RETRY(setsid()) == -1) {
-          ReportChildError(exec_control[1]);
-        } else {
-          // Do a final fork to not be the session leader.
-          pid = TEMP_FAILURE_RETRY(fork());
-          if (pid < 0) {
-            ReportChildError(exec_control[1]);
-          } else if (pid == 0) {
-            // Close all open file descriptors except for exec_control[1].
-            int max_fds = sysconf(_SC_OPEN_MAX);
-            if (max_fds == -1) max_fds = _POSIX_OPEN_MAX;
-            for (int fd = 0; fd < max_fds; fd++) {
-              if (fd != exec_control[1]) {
-                VOID_TEMP_FAILURE_RETRY(close(fd));
-              }
-            }
-
-            // Re-open stdin, stdout and stderr and connect them to /dev/null.
-            // The loop above should already have closed all of them, so
-            // creating new file descriptors should start at STDIN_FILENO.
-            int fd = TEMP_FAILURE_RETRY(open("/dev/null", O_RDWR));
-            if (fd != STDIN_FILENO) {
-              ReportChildError(exec_control[1]);
-            }
-            if (TEMP_FAILURE_RETRY(dup2(STDIN_FILENO, STDOUT_FILENO)) !=
-                STDOUT_FILENO) {
-              ReportChildError(exec_control[1]);
-            }
-            if (TEMP_FAILURE_RETRY(dup2(STDIN_FILENO, STDERR_FILENO)) !=
-                STDERR_FILENO) {
-              ReportChildError(exec_control[1]);
-            }
-
-            // Report the final PID and do the exec.
-            ReportPid(exec_control[1], getpid());  // getpid cannot fail.
-            VOID_TEMP_FAILURE_RETRY(
-                execvp(path, const_cast<char* const*>(program_arguments)));
-            ReportChildError(exec_control[1]);
-          } else {
-            exit(0);
-          }
-        }
-      } else {
-        exit(0);
-      }
-    } else {
-      VOID_TEMP_FAILURE_RETRY(close(write_out[1]));
-      VOID_TEMP_FAILURE_RETRY(close(read_in[0]));
-      VOID_TEMP_FAILURE_RETRY(close(read_err[0]));
-      VOID_TEMP_FAILURE_RETRY(close(exec_control[0]));
-
-      if (TEMP_FAILURE_RETRY(dup2(write_out[0], STDIN_FILENO)) == -1) {
-        ReportChildError(exec_control[1]);
-      }
-      VOID_TEMP_FAILURE_RETRY(close(write_out[0]));
-
-      if (TEMP_FAILURE_RETRY(dup2(read_in[1], STDOUT_FILENO)) == -1) {
-        ReportChildError(exec_control[1]);
-      }
-      VOID_TEMP_FAILURE_RETRY(close(read_in[1]));
-
-      if (TEMP_FAILURE_RETRY(dup2(read_err[1], STDERR_FILENO)) == -1) {
-        ReportChildError(exec_control[1]);
-      }
-      VOID_TEMP_FAILURE_RETRY(close(read_err[1]));
-
-      if (working_directory != NULL && chdir(working_directory) == -1) {
-        ReportChildError(exec_control[1]);
-      }
-
-      if (program_environment != NULL) {
-        environ = program_environment;
-      }
-
-      VOID_TEMP_FAILURE_RETRY(
-          execvp(path, const_cast<char* const*>(program_arguments)));
-
-      ReportChildError(exec_control[1]);
-    }
-  }
-
-  // Be sure to listen for exit-codes, now we have a child-process.
-  ExitCodeHandler::ProcessStarted();
-
-  // The arguments and environment for the spawned process are not needed
-  // any longer.
-  delete[] program_arguments;
-  delete[] program_environment;
-
-  if (!detach) {
-    int event_fds[2];
-    result = pipe(event_fds);
-    if (result < 0) {
-      SetChildOsErrorMessage(os_error_message);
-      VOID_TEMP_FAILURE_RETRY(close(read_in[0]));
-      VOID_TEMP_FAILURE_RETRY(close(read_in[1]));
-      VOID_TEMP_FAILURE_RETRY(close(read_err[0]));
-      VOID_TEMP_FAILURE_RETRY(close(read_err[1]));
-      VOID_TEMP_FAILURE_RETRY(close(write_out[0]));
-      VOID_TEMP_FAILURE_RETRY(close(write_out[1]));
-      Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message);
-      return errno;
-    }
-    FDUtils::SetCloseOnExec(event_fds[0]);
-    FDUtils::SetCloseOnExec(event_fds[1]);
-
-    ProcessInfoList::AddProcess(pid, event_fds[1]);
-    *exit_event = event_fds[0];
-    FDUtils::SetNonBlocking(event_fds[0]);
-  }
-
-  // Notify child process to start.
-  char msg = '1';
-  result = FDUtils::WriteToBlocking(read_in[1], &msg, sizeof(msg));
-  if (result != sizeof(msg)) {
-    perror("Failed sending notification message");
-  }
-
-  VOID_TEMP_FAILURE_RETRY(close(exec_control[1]));
-  bool failed = false;
-  int child_errno;
-  int bytes_read = -1;
-  ASSERT(sizeof(child_errno) == sizeof(errno));
-  if (!detach) {
-    // Read exec result from child. If no data is returned the exec was
-    // successful and the exec call closed the pipe. Otherwise the errno
-    // is written to the pipe.
-    bytes_read =
-        FDUtils::ReadFromBlocking(
-            exec_control[0], &child_errno, sizeof(child_errno));
-    if (bytes_read == sizeof(child_errno)) {
-      ReadChildError(exec_control[0], os_error_message);
-      failed = true;
-    }
-  } else {
-    // Read exec result from child. If only pid data is returned the exec was
-    // successful and the exec call closed the pipe. Otherwise the errno
-    // is written to the pipe as well.
-    int result[2];
-    ASSERT(sizeof(int) == sizeof(child_errno));
-    bytes_read =
-        FDUtils::ReadFromBlocking(
-            exec_control[0], result, sizeof(result));
-    if (bytes_read == sizeof(int)) {
-      pid = result[0];
-    } else if (bytes_read == 2 * sizeof(int)) {
-      pid = result[0];
-      child_errno = result[1];
-      ReadChildError(exec_control[0], os_error_message);
-      failed = true;
-    }
-  }
-  VOID_TEMP_FAILURE_RETRY(close(exec_control[0]));
-
-  // Return error code if any failures.
-  if (failed) {
-    if (!detach) {
-      VOID_TEMP_FAILURE_RETRY(close(read_in[0]));
-      VOID_TEMP_FAILURE_RETRY(close(read_in[1]));
-      VOID_TEMP_FAILURE_RETRY(close(read_err[0]));
-      VOID_TEMP_FAILURE_RETRY(close(read_err[1]));
-      VOID_TEMP_FAILURE_RETRY(close(write_out[0]));
-      VOID_TEMP_FAILURE_RETRY(close(write_out[1]));
-
-      // Since exec() failed, we're not interested in the exit code.
-      // We close the reading side of the exit code pipe here.
-      // GetProcessExitCodes will get a broken pipe error when it tries to write
-      // to the writing side of the pipe and it will ignore the error.
-      VOID_TEMP_FAILURE_RETRY(close(*exit_event));
-      *exit_event = -1;
-    }
-    if (bytes_read == -1) {
-      return errno;  // Read failed.
-    } else {
-      return child_errno;  // Exec failed.
-    }
-  }
-
-  FDUtils::SetNonBlocking(read_in[0]);
-  *in = read_in[0];
-  VOID_TEMP_FAILURE_RETRY(close(read_in[1]));
-  FDUtils::SetNonBlocking(write_out[1]);
-  *out = write_out[1];
-  VOID_TEMP_FAILURE_RETRY(close(write_out[0]));
-  FDUtils::SetNonBlocking(read_err[0]);
-  *err = read_err[0];
-  VOID_TEMP_FAILURE_RETRY(close(read_err[1]));
-
-  *id = pid;
-  return 0;
+  ProcessStarter starter(path,
+                         arguments,
+                         arguments_length,
+                         working_directory,
+                         environment,
+                         environment_length,
+                         mode,
+                         in,
+                         out,
+                         err,
+                         id,
+                         exit_event,
+                         os_error_message);
+  return starter.Start();
 }
 
 
diff --git a/runtime/bin/process_linux.cc b/runtime/bin/process_linux.cc
index 3b56f0a..a511cd9 100644
--- a/runtime/bin/process_linux.cc
+++ b/runtime/bin/process_linux.cc
@@ -229,55 +229,518 @@
 Monitor* ExitCodeHandler::monitor_ = new Monitor();
 
 
-static void SetChildOsErrorMessage(char** os_error_message) {
-  const int kBufferSize = 1024;
-  char error_buf[kBufferSize];
-  *os_error_message = strdup(strerror_r(errno, error_buf, kBufferSize));
-}
+class ProcessStarter {
+ public:
+  ProcessStarter(const char* path,
+                 char* arguments[],
+                 intptr_t arguments_length,
+                 const char* working_directory,
+                 char* environment[],
+                 intptr_t environment_length,
+                 ProcessStartMode mode,
+                 intptr_t* in,
+                 intptr_t* out,
+                 intptr_t* err,
+                 intptr_t* id,
+                 intptr_t* exit_event,
+                 char** os_error_message)
+      : path_(path),
+        working_directory_(working_directory),
+        mode_(mode),
+        in_(in),
+        out_(out),
+        err_(err),
+        id_(id),
+        exit_event_(exit_event),
+        os_error_message_(os_error_message) {
+    read_in_[0] = -1;
+    read_in_[1] = -1;
+    read_err_[0] = -1;
+    read_err_[1] = -1;
+    write_out_[0] = -1;
+    write_out_[1] = -1;
+    exec_control_[0] = -1;
+    exec_control_[1] = -1;
+
+    program_arguments_ = new char*[arguments_length + 2];
+    program_arguments_[0] = const_cast<char*>(path_);
+    for (int i = 0; i < arguments_length; i++) {
+      program_arguments_[i + 1] = arguments[i];
+    }
+    program_arguments_[arguments_length + 1] = NULL;
+
+    program_environment_ = NULL;
+    if (environment != NULL) {
+      program_environment_ = new char*[environment_length + 1];
+      for (int i = 0; i < environment_length; i++) {
+        program_environment_[i] = environment[i];
+      }
+      program_environment_[environment_length] = NULL;
+    }
+  }
 
 
-static void ReportChildError(int exec_control_fd) {
-  // In the case of failure in the child process write the errno and
-  // the OS error message to the exec control pipe and exit.
-  int child_errno = errno;
-  const int kBufferSize = 1024;
-  char error_buf[kBufferSize];
-  char* os_error_message = strerror_r(errno, error_buf, kBufferSize);
-  ASSERT(sizeof(child_errno) == sizeof(errno));
-  int bytes_written =
+  ~ProcessStarter() {
+    delete[] program_arguments_;
+    delete[] program_environment_;
+  }
+
+
+  int Start() {
+    // Create pipes required.
+    int err = CreatePipes();
+    if (err != 0) return err;
+
+    // Fork to create the new process.
+    pid_t pid = TEMP_FAILURE_RETRY(fork());
+    if (pid < 0) {
+      // Failed to fork.
+      return CleanupAndReturnError();
+    } else if (pid == 0) {
+      // This runs in the new process.
+      NewProcess();
+    }
+
+    // This runs in the original process.
+
+    // Be sure to listen for exit-codes, now we have a child-process.
+    ExitCodeHandler::ProcessStarted();
+
+    // Register the child process if not detached.
+    if (mode_ == kNormal) {
+      err = RegisterProcess(pid);
+      if (err != 0) return err;
+    }
+
+    // Notify child process to start. This is done to delay the call to exec
+    // until the process is registered above, and we are ready to receive the
+    // exit code.
+    char msg = '1';
+    int bytes_written =
+        FDUtils::WriteToBlocking(read_in_[1], &msg, sizeof(msg));
+    if (bytes_written != sizeof(msg)) {
+      return CleanupAndReturnError();
+    }
+
+    // Read the result of executing the child process.
+    VOID_TEMP_FAILURE_RETRY(close(exec_control_[1]));
+    exec_control_[1] = -1;
+    if (mode_ == kNormal) {
+      err = ReadExecResult();
+    } else {
+      err = ReadDetachedExecResult(&pid);
+    }
+    VOID_TEMP_FAILURE_RETRY(close(exec_control_[0]));
+    exec_control_[0] = -1;
+
+    // Return error code if any failures.
+    if (err != 0) {
+      if (mode_ == kNormal) {
+        // Since exec() failed, we're not interested in the exit code.
+        // We close the reading side of the exit code pipe here.
+        // GetProcessExitCodes will get a broken pipe error when it
+        // tries to write to the writing side of the pipe and it will
+        // ignore the error.
+        VOID_TEMP_FAILURE_RETRY(close(*exit_event_));
+        *exit_event_ = -1;
+      }
+      CloseAllPipes();
+      return err;
+    }
+
+    if (mode_ != kDetached) {
+      // Connect stdio, stdout and stderr.
+      FDUtils::SetNonBlocking(read_in_[0]);
+      *in_ = read_in_[0];
+      VOID_TEMP_FAILURE_RETRY(close(read_in_[1]));
+      FDUtils::SetNonBlocking(write_out_[1]);
+      *out_ = write_out_[1];
+      VOID_TEMP_FAILURE_RETRY(close(write_out_[0]));
+      FDUtils::SetNonBlocking(read_err_[0]);
+      *err_ = read_err_[0];
+      VOID_TEMP_FAILURE_RETRY(close(read_err_[1]));
+    } else {
+      // Close all fds.
+      VOID_TEMP_FAILURE_RETRY(close(read_in_[0]));
+      VOID_TEMP_FAILURE_RETRY(close(read_in_[1]));
+      ASSERT(write_out_[0] == -1);
+      ASSERT(write_out_[1] == -1);
+      ASSERT(read_err_[0] == -1);
+      ASSERT(read_err_[1] == -1);
+    }
+    ASSERT(exec_control_[0] == -1);
+    ASSERT(exec_control_[1] == -1);
+
+    *id_ = pid;
+    return 0;
+  }
+
+ private:
+  int CreatePipes() {
+    int result;
+    result = TEMP_FAILURE_RETRY(pipe(exec_control_));
+    if (result < 0) {
+      return CleanupAndReturnError();
+    }
+    FDUtils::SetCloseOnExec(exec_control_[0]);
+    FDUtils::SetCloseOnExec(exec_control_[1]);
+
+    // For a detached process the pipe to connect stdout is still used for
+    // signaling when to do the first fork.
+    result = TEMP_FAILURE_RETRY(pipe(read_in_));
+    if (result < 0) {
+      return CleanupAndReturnError();
+    }
+    FDUtils::SetCloseOnExec(read_in_[0]);
+
+    // For detached processes the pipe to connect stderr and stdin are not used.
+    if (mode_ != kDetached) {
+      result = TEMP_FAILURE_RETRY(pipe(read_err_));
+      if (result < 0) {
+        return CleanupAndReturnError();
+      }
+      FDUtils::SetCloseOnExec(read_err_[0]);
+
+      result = TEMP_FAILURE_RETRY(pipe(write_out_));
+      if (result < 0) {
+        return CleanupAndReturnError();
+      }
+      FDUtils::SetCloseOnExec(write_out_[1]);
+    }
+
+    return 0;
+  }
+
+
+  void NewProcess() {
+    // Wait for parent process before setting up the child process.
+    char msg;
+    int bytes_read = FDUtils::ReadFromBlocking(read_in_[0], &msg, sizeof(msg));
+    if (bytes_read != sizeof(msg)) {
+      perror("Failed receiving notification message");
+      exit(1);
+    }
+    if (mode_ == kNormal) {
+      ExecProcess();
+    } else {
+      ExecDetachedProcess();
+    }
+  }
+
+
+  void ExecProcess() {
+    VOID_TEMP_FAILURE_RETRY(close(write_out_[1]));
+    VOID_TEMP_FAILURE_RETRY(close(read_in_[0]));
+    VOID_TEMP_FAILURE_RETRY(close(read_err_[0]));
+    VOID_TEMP_FAILURE_RETRY(close(exec_control_[0]));
+
+    if (TEMP_FAILURE_RETRY(dup2(write_out_[0], STDIN_FILENO)) == -1) {
+      ReportChildError();
+    }
+    VOID_TEMP_FAILURE_RETRY(close(write_out_[0]));
+
+    if (TEMP_FAILURE_RETRY(dup2(read_in_[1], STDOUT_FILENO)) == -1) {
+      ReportChildError();
+    }
+    VOID_TEMP_FAILURE_RETRY(close(read_in_[1]));
+
+    if (TEMP_FAILURE_RETRY(dup2(read_err_[1], STDERR_FILENO)) == -1) {
+      ReportChildError();
+    }
+    VOID_TEMP_FAILURE_RETRY(close(read_err_[1]));
+
+    if (working_directory_ != NULL &&
+        TEMP_FAILURE_RETRY(chdir(working_directory_)) == -1) {
+      ReportChildError();
+    }
+
+    if (program_environment_ != NULL) {
+      environ = program_environment_;
+    }
+
+    VOID_TEMP_FAILURE_RETRY(
+        execvp(path_, const_cast<char* const*>(program_arguments_)));
+
+    ReportChildError();
+  }
+
+
+  void ExecDetachedProcess() {
+    if (mode_ == kDetached) {
+      ASSERT(write_out_[0] == -1);
+      ASSERT(write_out_[1] == -1);
+      ASSERT(read_err_[0] == -1);
+      ASSERT(read_err_[1] == -1);
+      // For a detached process the pipe to connect stdout is only used for
+      // signaling when to do the first fork.
+      VOID_TEMP_FAILURE_RETRY(close(read_in_[0]));
+      read_in_[0] = -1;
+      VOID_TEMP_FAILURE_RETRY(close(read_in_[1]));
+      read_in_[1] = -1;
+    } else {
+      // Don't close any fds if keeping stdio open to the detached process.
+      ASSERT(mode_ == kDetachedWithStdio);
+    }
+    // Fork once more to start a new session.
+    pid_t pid = TEMP_FAILURE_RETRY(fork());
+    if (pid < 0) {
+      ReportChildError();
+    } else if (pid == 0) {
+      // Start a new session.
+      if (TEMP_FAILURE_RETRY(setsid()) == -1) {
+        ReportChildError();
+      } else {
+        // Do a final fork to not be the session leader.
+        pid = TEMP_FAILURE_RETRY(fork());
+        if (pid < 0) {
+          ReportChildError();
+        } else if (pid == 0) {
+          if (mode_ == kDetached) {
+            SetupDetached();
+          } else {
+            SetupDetachedWithStdio();
+          }
+
+          if (working_directory_ != NULL &&
+              TEMP_FAILURE_RETRY(chdir(working_directory_)) == -1) {
+            ReportChildError();
+          }
+
+          // Report the final PID and do the exec.
+          ReportPid(getpid());  // getpid cannot fail.
+          VOID_TEMP_FAILURE_RETRY(
+              execvp(path_, const_cast<char* const*>(program_arguments_)));
+          ReportChildError();
+        } else {
+          // Exit the intermeiate process.
+          exit(0);
+        }
+      }
+    } else {
+      // Exit the intermeiate process.
+      exit(0);
+    }
+  }
+
+
+  int RegisterProcess(pid_t pid) {
+    int result;
+    int event_fds[2];
+    result = TEMP_FAILURE_RETRY(pipe(event_fds));
+    if (result < 0) {
+      return CleanupAndReturnError();
+    }
+    FDUtils::SetCloseOnExec(event_fds[0]);
+    FDUtils::SetCloseOnExec(event_fds[1]);
+
+    ProcessInfoList::AddProcess(pid, event_fds[1]);
+    *exit_event_ = event_fds[0];
+    FDUtils::SetNonBlocking(event_fds[0]);
+    return 0;
+  }
+
+
+  int ReadExecResult() {
+    int child_errno;
+    int bytes_read = -1;
+    // Read exec result from child. If no data is returned the exec was
+    // successful and the exec call closed the pipe. Otherwise the errno
+    // is written to the pipe.
+    bytes_read =
+        FDUtils::ReadFromBlocking(
+            exec_control_[0], &child_errno, sizeof(child_errno));
+    if (bytes_read == sizeof(child_errno)) {
+      ReadChildError();
+      return child_errno;
+    } else if (bytes_read == -1) {
+      return errno;
+    }
+    return 0;
+  }
+
+
+  int ReadDetachedExecResult(pid_t *pid) {
+    int child_errno;
+    int bytes_read = -1;
+    // Read exec result from child. If only pid data is returned the exec was
+    // successful and the exec call closed the pipe. Otherwise the errno
+    // is written to the pipe as well.
+    int result[2];
+    bytes_read =
+        FDUtils::ReadFromBlocking(
+            exec_control_[0], result, sizeof(result));
+    if (bytes_read == sizeof(int)) {
+      *pid = result[0];
+    } else if (bytes_read == 2 * sizeof(int)) {
+      *pid = result[0];
+      child_errno = result[1];
+      ReadChildError();
+      return child_errno;
+    } else if (bytes_read == -1) {
+      return errno;
+    }
+    return 0;
+  }
+
+
+  void SetupDetached() {
+    ASSERT(mode_ == kDetached);
+
+    // Close all open file descriptors except for exec_control_[1].
+    int max_fds = sysconf(_SC_OPEN_MAX);
+    if (max_fds == -1) max_fds = _POSIX_OPEN_MAX;
+    for (int fd = 0; fd < max_fds; fd++) {
+      if (fd != exec_control_[1]) {
+        VOID_TEMP_FAILURE_RETRY(close(fd));
+      }
+    }
+
+    // Re-open stdin, stdout and stderr and connect them to /dev/null.
+    // The loop above should already have closed all of them, so
+    // creating new file descriptors should start at STDIN_FILENO.
+    int fd = TEMP_FAILURE_RETRY(open("/dev/null", O_RDWR));
+    if (fd != STDIN_FILENO) {
+      ReportChildError();
+    }
+    if (TEMP_FAILURE_RETRY(dup2(STDIN_FILENO, STDOUT_FILENO)) !=
+        STDOUT_FILENO) {
+      ReportChildError();
+    }
+    if (TEMP_FAILURE_RETRY(dup2(STDIN_FILENO, STDERR_FILENO)) !=
+        STDERR_FILENO) {
+      ReportChildError();
+    }
+  }
+
+  void SetupDetachedWithStdio() {
+    // Close all open file descriptors except for
+    // exec_control_[1], write_out_[0], read_in_[1] and
+    // read_err_[1].
+    int max_fds = sysconf(_SC_OPEN_MAX);
+    if (max_fds == -1) max_fds = _POSIX_OPEN_MAX;
+    for (int fd = 0; fd < max_fds; fd++) {
+      if (fd != exec_control_[1] &&
+          fd != write_out_[0] &&
+          fd != read_in_[1] &&
+          fd != read_err_[1]) {
+        VOID_TEMP_FAILURE_RETRY(close(fd));
+      }
+    }
+
+    if (TEMP_FAILURE_RETRY(dup2(write_out_[0], STDIN_FILENO)) == -1) {
+      ReportChildError();
+    }
+    VOID_TEMP_FAILURE_RETRY(close(write_out_[0]));
+
+    if (TEMP_FAILURE_RETRY(dup2(read_in_[1], STDOUT_FILENO)) == -1) {
+      ReportChildError();
+    }
+    VOID_TEMP_FAILURE_RETRY(close(read_in_[1]));
+
+    if (TEMP_FAILURE_RETRY(dup2(read_err_[1], STDERR_FILENO)) == -1) {
+      ReportChildError();
+    }
+    VOID_TEMP_FAILURE_RETRY(close(read_err_[1]));
+  }
+
+
+  int CleanupAndReturnError() {
+    int actual_errno = errno;
+    // If CleanupAndReturnError is called without an actual errno make
+    // sure to return an error anyway.
+    if (actual_errno == 0) actual_errno = EPERM;
+    SetChildOsErrorMessage();
+    CloseAllPipes();
+    return actual_errno;
+  }
+
+
+  void SetChildOsErrorMessage() {
+    const int kBufferSize = 1024;
+    char error_buf[kBufferSize];
+    *os_error_message_ = strdup(strerror_r(errno, error_buf, kBufferSize));
+  }
+
+
+  void ReportChildError() {
+    // In the case of failure in the child process write the errno and
+    // the OS error message to the exec control pipe and exit.
+    int child_errno = errno;
+    const int kBufferSize = 1024;
+    char error_buf[kBufferSize];
+    char* os_error_message = strerror_r(errno, error_buf, kBufferSize);
+    int bytes_written =
+        FDUtils::WriteToBlocking(
+            exec_control_[1], &child_errno, sizeof(child_errno));
+    if (bytes_written == sizeof(child_errno)) {
       FDUtils::WriteToBlocking(
-          exec_control_fd, &child_errno, sizeof(child_errno));
-  if (bytes_written == sizeof(child_errno)) {
-    FDUtils::WriteToBlocking(
-        exec_control_fd, os_error_message, strlen(os_error_message) + 1);
+          exec_control_[1], os_error_message, strlen(os_error_message) + 1);
+    }
+    VOID_TEMP_FAILURE_RETRY(close(exec_control_[1]));
+    exit(1);
   }
-  VOID_TEMP_FAILURE_RETRY(close(exec_control_fd));
-  exit(1);
-}
 
 
-static void ReportPid(int exec_control_fd, int pid) {
-  // In the case of starting a detached process the actual pid of that process
-  // is communicated using the exec control pipe.
-  int bytes_written =
-      FDUtils::WriteToBlocking(exec_control_fd, &pid, sizeof(pid));
-  ASSERT(bytes_written == sizeof(int));
-  USE(bytes_written);
-}
-
-
-static void ReadChildError(int exec_control_fd, char** error_message) {
-  const int kMaxMessageSize = 256;
-  char* message = static_cast<char*>(malloc(kMaxMessageSize));
-  if (message != NULL) {
-    FDUtils::ReadFromBlocking(exec_control_fd, message, kMaxMessageSize);
-    message[kMaxMessageSize - 1] = '\0';
-    *error_message = message;
-  } else {
-    static const char* no_message = "Cannot get error message, out of memory";
-    *error_message = const_cast<char*>(no_message);
+  void ReportPid(int pid) {
+    // In the case of starting a detached process the actual pid of that process
+    // is communicated using the exec control pipe.
+    int bytes_written =
+        FDUtils::WriteToBlocking(exec_control_[1], &pid, sizeof(pid));
+    ASSERT(bytes_written == sizeof(int));
+    USE(bytes_written);
   }
-}
+
+
+  void ReadChildError() {
+    const int kMaxMessageSize = 256;
+    char* message = static_cast<char*>(malloc(kMaxMessageSize));
+    if (message != NULL) {
+      FDUtils::ReadFromBlocking(exec_control_[0], message, kMaxMessageSize);
+      message[kMaxMessageSize - 1] = '\0';
+      *os_error_message_ = message;
+    } else {
+      // Could not get error message. It will be NULL.
+      ASSERT(*os_error_message_ == NULL);
+    }
+  }
+
+
+  void ClosePipe(int* fds) {
+    for (int i = 0; i < 2; i++) {
+      if (fds[i] != -1) {
+        VOID_TEMP_FAILURE_RETRY(close(fds[i]));
+        fds[i] = -1;
+      }
+    }
+  }
+
+
+  void CloseAllPipes() {
+    ClosePipe(exec_control_);
+    ClosePipe(read_in_);
+    ClosePipe(read_err_);
+    ClosePipe(write_out_);
+  }
+
+
+  int read_in_[2];  // Pipe for stdout to child process.
+  int read_err_[2];  // Pipe for stderr to child process.
+  int write_out_[2];  // Pipe for stdin to child process.
+  int exec_control_[2];  // Pipe to get the result from exec.
+
+  char** program_arguments_;
+  char** program_environment_;
+
+  const char* path_;
+  const char* working_directory_;
+  ProcessStartMode mode_;
+  intptr_t* in_;
+  intptr_t* out_;
+  intptr_t* err_;
+  intptr_t* id_;
+  intptr_t* exit_event_;
+  char** os_error_message_;
+};
 
 
 int Process::Start(const char* path,
@@ -286,310 +749,27 @@
                    const char* working_directory,
                    char* environment[],
                    intptr_t environment_length,
-                   bool detach,
+                   ProcessStartMode mode,
                    intptr_t* in,
                    intptr_t* out,
                    intptr_t* err,
                    intptr_t* id,
                    intptr_t* exit_event,
                    char** os_error_message) {
-  pid_t pid;
-  int read_in[2] = {-1, -1};  // Pipe for stdout to child process.
-  int read_err[2] = {-1, -1};  // Pipe for stderr to child process.
-  int write_out[2] = {-1, -1};  // Pipe for stdin to child process.
-  int exec_control[2] = {-1, -1};  // Pipe to get the result from exec.
-  int result;
-
-  result = TEMP_FAILURE_RETRY(pipe(exec_control));
-  if (result < 0) {
-    SetChildOsErrorMessage(os_error_message);
-    Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message);
-    return errno;
-  }
-  FDUtils::SetCloseOnExec(exec_control[0]);
-  FDUtils::SetCloseOnExec(exec_control[1]);
-
-  // For a detached process the pipe to connect stdout is still used for
-  // signaling when to do the first fork.
-  result = TEMP_FAILURE_RETRY(pipe(read_in));
-  if (result < 0) {
-    SetChildOsErrorMessage(os_error_message);
-    VOID_TEMP_FAILURE_RETRY(close(exec_control[0]));
-    VOID_TEMP_FAILURE_RETRY(close(exec_control[1]));
-    Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message);
-    return errno;
-  }
-  FDUtils::SetCloseOnExec(read_in[0]);
-
-  // For detached processes the pipe to connect stderr and stdin are not used.
-  if (!detach) {
-    result = TEMP_FAILURE_RETRY(pipe(read_err));
-    if (result < 0) {
-      SetChildOsErrorMessage(os_error_message);
-      VOID_TEMP_FAILURE_RETRY(close(exec_control[0]));
-      VOID_TEMP_FAILURE_RETRY(close(exec_control[1]));
-      VOID_TEMP_FAILURE_RETRY(close(read_in[0]));
-      VOID_TEMP_FAILURE_RETRY(close(read_in[1]));
-      Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message);
-      return errno;
-    }
-    FDUtils::SetCloseOnExec(read_err[0]);
-
-    result = TEMP_FAILURE_RETRY(pipe(write_out));
-    if (result < 0) {
-      SetChildOsErrorMessage(os_error_message);
-      VOID_TEMP_FAILURE_RETRY(close(exec_control[0]));
-      VOID_TEMP_FAILURE_RETRY(close(exec_control[1]));
-      VOID_TEMP_FAILURE_RETRY(close(read_in[0]));
-      VOID_TEMP_FAILURE_RETRY(close(read_in[1]));
-      VOID_TEMP_FAILURE_RETRY(close(read_err[0]));
-      VOID_TEMP_FAILURE_RETRY(close(read_err[1]));
-      Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message);
-      return errno;
-    }
-    FDUtils::SetCloseOnExec(write_out[1]);
-  }
-
-  char** program_arguments = new char*[arguments_length + 2];
-  program_arguments[0] = const_cast<char*>(path);
-  for (int i = 0; i < arguments_length; i++) {
-    program_arguments[i + 1] = arguments[i];
-  }
-  program_arguments[arguments_length + 1] = NULL;
-
-  char** program_environment = NULL;
-  if (environment != NULL) {
-    program_environment = new char*[environment_length + 1];
-    for (int i = 0; i < environment_length; i++) {
-      program_environment[i] = environment[i];
-    }
-    program_environment[environment_length] = NULL;
-  }
-
-  pid = TEMP_FAILURE_RETRY(fork());
-  if (pid < 0) {
-    SetChildOsErrorMessage(os_error_message);
-    delete[] program_arguments;
-    VOID_TEMP_FAILURE_RETRY(close(exec_control[0]));
-    VOID_TEMP_FAILURE_RETRY(close(exec_control[1]));
-    VOID_TEMP_FAILURE_RETRY(close(read_in[0]));
-    VOID_TEMP_FAILURE_RETRY(close(read_in[1]));
-    if (!detach) {
-      VOID_TEMP_FAILURE_RETRY(close(read_err[0]));
-      VOID_TEMP_FAILURE_RETRY(close(read_err[1]));
-      VOID_TEMP_FAILURE_RETRY(close(write_out[0]));
-      VOID_TEMP_FAILURE_RETRY(close(write_out[1]));
-    }
-    return errno;
-  } else if (pid == 0) {
-    // Wait for parent process before setting up the child process.
-    char msg;
-    int bytes_read = FDUtils::ReadFromBlocking(read_in[0], &msg, sizeof(msg));
-    if (bytes_read != sizeof(msg)) {
-      perror("Failed receiving notification message");
-      exit(1);
-    }
-    if (detach) {
-      // For a detached process the pipe to connect stdout is only used for
-      // signaling when to do the first fork.
-      VOID_TEMP_FAILURE_RETRY(close(read_in[0]));
-      VOID_TEMP_FAILURE_RETRY(close(read_in[1]));
-      // Fork once more to start a new session.
-      pid = TEMP_FAILURE_RETRY(fork());
-      if (pid < 0) {
-        ReportChildError(exec_control[1]);
-      } else if (pid == 0) {
-        // Start a new session.
-        if (TEMP_FAILURE_RETRY(setsid()) == -1) {
-          ReportChildError(exec_control[1]);
-        } else {
-          // Do a final fork to not be the session leader.
-          pid = TEMP_FAILURE_RETRY(fork());
-          if (pid < 0) {
-            ReportChildError(exec_control[1]);
-          } else if (pid == 0) {
-            // Close all open file descriptors except for exec_control[1].
-            int max_fds = sysconf(_SC_OPEN_MAX);
-            if (max_fds == -1) max_fds = _POSIX_OPEN_MAX;
-            for (int fd = 0; fd < max_fds; fd++) {
-              if (fd != exec_control[1]) {
-                VOID_TEMP_FAILURE_RETRY(close(fd));
-              }
-            }
-
-            // Re-open stdin, stdout and stderr and connect them to /dev/null.
-            // The loop above should already have closed all of them, so
-            // creating new file descriptors should start at STDIN_FILENO.
-            int fd = TEMP_FAILURE_RETRY(open("/dev/null", O_RDWR));
-            if (fd != STDIN_FILENO) {
-              ReportChildError(exec_control[1]);
-            }
-            if (TEMP_FAILURE_RETRY(dup2(STDIN_FILENO, STDOUT_FILENO)) !=
-                STDOUT_FILENO) {
-              ReportChildError(exec_control[1]);
-            }
-            if (TEMP_FAILURE_RETRY(dup2(STDIN_FILENO, STDERR_FILENO)) !=
-                STDERR_FILENO) {
-              ReportChildError(exec_control[1]);
-            }
-
-            // Report the final PID and do the exec.
-            ReportPid(exec_control[1], getpid());  // getpid cannot fail.
-            VOID_TEMP_FAILURE_RETRY(
-                execvp(path, const_cast<char* const*>(program_arguments)));
-            ReportChildError(exec_control[1]);
-          } else {
-            exit(0);
-          }
-        }
-      } else {
-        exit(0);
-      }
-    } else {
-      VOID_TEMP_FAILURE_RETRY(close(write_out[1]));
-      VOID_TEMP_FAILURE_RETRY(close(read_in[0]));
-      VOID_TEMP_FAILURE_RETRY(close(read_err[0]));
-      VOID_TEMP_FAILURE_RETRY(close(exec_control[0]));
-
-      if (TEMP_FAILURE_RETRY(dup2(write_out[0], STDIN_FILENO)) == -1) {
-        ReportChildError(exec_control[1]);
-      }
-      VOID_TEMP_FAILURE_RETRY(close(write_out[0]));
-
-      if (TEMP_FAILURE_RETRY(dup2(read_in[1], STDOUT_FILENO)) == -1) {
-        ReportChildError(exec_control[1]);
-      }
-      VOID_TEMP_FAILURE_RETRY(close(read_in[1]));
-
-      if (TEMP_FAILURE_RETRY(dup2(read_err[1], STDERR_FILENO)) == -1) {
-        ReportChildError(exec_control[1]);
-      }
-      VOID_TEMP_FAILURE_RETRY(close(read_err[1]));
-
-      if (working_directory != NULL && chdir(working_directory) == -1) {
-        ReportChildError(exec_control[1]);
-      }
-
-      if (program_environment != NULL) {
-        environ = program_environment;
-      }
-
-      VOID_TEMP_FAILURE_RETRY(
-          execvp(path, const_cast<char* const*>(program_arguments)));
-
-      ReportChildError(exec_control[1]);
-    }
-  }
-
-  // Be sure to listen for exit-codes, now we have a child-process.
-  ExitCodeHandler::ProcessStarted();
-
-  // The arguments and environment for the spawned process are not needed
-  // any longer.
-  delete[] program_arguments;
-  delete[] program_environment;
-
-  if (!detach) {
-    int event_fds[2];
-    result = pipe(event_fds);
-    if (result < 0) {
-      SetChildOsErrorMessage(os_error_message);
-      VOID_TEMP_FAILURE_RETRY(close(read_in[0]));
-      VOID_TEMP_FAILURE_RETRY(close(read_in[1]));
-      VOID_TEMP_FAILURE_RETRY(close(read_err[0]));
-      VOID_TEMP_FAILURE_RETRY(close(read_err[1]));
-      VOID_TEMP_FAILURE_RETRY(close(write_out[0]));
-      VOID_TEMP_FAILURE_RETRY(close(write_out[1]));
-      Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message);
-      return errno;
-    }
-    FDUtils::SetCloseOnExec(event_fds[0]);
-    FDUtils::SetCloseOnExec(event_fds[1]);
-
-    ProcessInfoList::AddProcess(pid, event_fds[1]);
-    *exit_event = event_fds[0];
-    FDUtils::SetNonBlocking(event_fds[0]);
-  }
-
-  // Notify child process to start.
-  char msg = '1';
-  result = FDUtils::WriteToBlocking(read_in[1], &msg, sizeof(msg));
-  if (result != sizeof(msg)) {
-    perror("Failed sending notification message");
-  }
-
-  VOID_TEMP_FAILURE_RETRY(close(exec_control[1]));
-  bool failed = false;
-  int child_errno;
-  int bytes_read = -1;
-  ASSERT(sizeof(child_errno) == sizeof(errno));
-  if (!detach) {
-    // Read exec result from child. If no data is returned the exec was
-    // successful and the exec call closed the pipe. Otherwise the errno
-    // is written to the pipe.
-    bytes_read =
-        FDUtils::ReadFromBlocking(
-            exec_control[0], &child_errno, sizeof(child_errno));
-    if (bytes_read == sizeof(child_errno)) {
-      ReadChildError(exec_control[0], os_error_message);
-      failed = true;
-    }
-  } else {
-    // Read exec result from child. If only pid data is returned the exec was
-    // successful and the exec call closed the pipe. Otherwise the errno
-    // is written to the pipe as well.
-    int result[2];
-    ASSERT(sizeof(int) == sizeof(child_errno));
-    bytes_read =
-        FDUtils::ReadFromBlocking(
-            exec_control[0], result, sizeof(result));
-    if (bytes_read == sizeof(int)) {
-      pid = result[0];
-    } else if (bytes_read == 2 * sizeof(int)) {
-      pid = result[0];
-      child_errno = result[1];
-      ReadChildError(exec_control[0], os_error_message);
-      failed = true;
-    }
-  }
-  VOID_TEMP_FAILURE_RETRY(close(exec_control[0]));
-
-  // Return error code if any failures.
-  if (failed) {
-    if (!detach) {
-      VOID_TEMP_FAILURE_RETRY(close(read_in[0]));
-      VOID_TEMP_FAILURE_RETRY(close(read_in[1]));
-      VOID_TEMP_FAILURE_RETRY(close(read_err[0]));
-      VOID_TEMP_FAILURE_RETRY(close(read_err[1]));
-      VOID_TEMP_FAILURE_RETRY(close(write_out[0]));
-      VOID_TEMP_FAILURE_RETRY(close(write_out[1]));
-
-      // Since exec() failed, we're not interested in the exit code.
-      // We close the reading side of the exit code pipe here.
-      // GetProcessExitCodes will get a broken pipe error when it tries to write
-      // to the writing side of the pipe and it will ignore the error.
-      VOID_TEMP_FAILURE_RETRY(close(*exit_event));
-      *exit_event = -1;
-    }
-    if (bytes_read == -1) {
-      return errno;  // Read failed.
-    } else {
-      return child_errno;  // Exec failed.
-    }
-  }
-
-  FDUtils::SetNonBlocking(read_in[0]);
-  *in = read_in[0];
-  VOID_TEMP_FAILURE_RETRY(close(read_in[1]));
-  FDUtils::SetNonBlocking(write_out[1]);
-  *out = write_out[1];
-  VOID_TEMP_FAILURE_RETRY(close(write_out[0]));
-  FDUtils::SetNonBlocking(read_err[0]);
-  *err = read_err[0];
-  VOID_TEMP_FAILURE_RETRY(close(read_err[1]));
-
-  *id = pid;
-  return 0;
+  ProcessStarter starter(path,
+                         arguments,
+                         arguments_length,
+                         working_directory,
+                         environment,
+                         environment_length,
+                         mode,
+                         in,
+                         out,
+                         err,
+                         id,
+                         exit_event,
+                         os_error_message);
+  return starter.Start();
 }
 
 
@@ -711,7 +891,7 @@
 
 
 bool Process::Kill(intptr_t id, int signal) {
-  return kill(id, signal) != -1;
+  return (TEMP_FAILURE_RETRY(kill(id, signal)) != -1);
 }
 
 
diff --git a/runtime/bin/process_macos.cc b/runtime/bin/process_macos.cc
index a6d9301..d24a599 100644
--- a/runtime/bin/process_macos.cc
+++ b/runtime/bin/process_macos.cc
@@ -7,6 +7,7 @@
 
 #include "bin/process.h"
 
+#include <crt_externs.h>  // NOLINT
 #include <errno.h>  // NOLINT
 #include <fcntl.h>  // NOLINT
 #include <poll.h>  // NOLINT
@@ -24,8 +25,6 @@
 #include "platform/signal_blocker.h"
 
 
-extern char **environ;
-
 
 namespace dart {
 namespace bin {
@@ -230,56 +229,522 @@
 Monitor* ExitCodeHandler::monitor_ = new Monitor();
 
 
-static void SetChildOsErrorMessage(char** os_error_message) {
-  const int kBufferSize = 1024;
-  char error_message[kBufferSize];
-  strerror_r(errno, error_message, kBufferSize);
-  *os_error_message = strdup(error_message);
-}
+class ProcessStarter {
+ public:
+  ProcessStarter(const char* path,
+                 char* arguments[],
+                 intptr_t arguments_length,
+                 const char* working_directory,
+                 char* environment[],
+                 intptr_t environment_length,
+                 ProcessStartMode mode,
+                 intptr_t* in,
+                 intptr_t* out,
+                 intptr_t* err,
+                 intptr_t* id,
+                 intptr_t* exit_event,
+                 char** os_error_message)
+      : path_(path),
+        working_directory_(working_directory),
+        mode_(mode),
+        in_(in),
+        out_(out),
+        err_(err),
+        id_(id),
+        exit_event_(exit_event),
+        os_error_message_(os_error_message) {
+    read_in_[0] = -1;
+    read_in_[1] = -1;
+    read_err_[0] = -1;
+    read_err_[1] = -1;
+    write_out_[0] = -1;
+    write_out_[1] = -1;
+    exec_control_[0] = -1;
+    exec_control_[1] = -1;
+
+    program_arguments_ = new char*[arguments_length + 2];
+    program_arguments_[0] = const_cast<char*>(path_);
+    for (int i = 0; i < arguments_length; i++) {
+      program_arguments_[i + 1] = arguments[i];
+    }
+    program_arguments_[arguments_length + 1] = NULL;
+
+    program_environment_ = NULL;
+    if (environment != NULL) {
+      program_environment_ = new char*[environment_length + 1];
+      for (int i = 0; i < environment_length; i++) {
+        program_environment_[i] = environment[i];
+      }
+      program_environment_[environment_length] = NULL;
+    }
+  }
 
 
-static void ReportChildError(int exec_control_fd) {
-  // In the case of failure in the child process write the errno and
-  // the OS error message to the exec control pipe and exit.
-  int child_errno = errno;
-  const int kBufferSize = 1024;
-  char os_error_message[kBufferSize];
-  strerror_r(errno, os_error_message, kBufferSize);
-  ASSERT(sizeof(child_errno) == sizeof(errno));
-  int bytes_written =
+  ~ProcessStarter() {
+    delete[] program_arguments_;
+    delete[] program_environment_;
+  }
+
+
+  int Start() {
+    // Create pipes required.
+    int err = CreatePipes();
+    if (err != 0) return err;
+
+    // Fork to create the new process.
+    pid_t pid = TEMP_FAILURE_RETRY(fork());
+    if (pid < 0) {
+      // Failed to fork.
+      return CleanupAndReturnError();
+    } else if (pid == 0) {
+      // This runs in the new process.
+      NewProcess();
+    }
+
+    // This runs in the original process.
+
+    // Be sure to listen for exit-codes, now we have a child-process.
+    ExitCodeHandler::ProcessStarted();
+
+    // Register the child process if not detached.
+    if (mode_ == kNormal) {
+      err = RegisterProcess(pid);
+      if (err != 0) return err;
+    }
+
+    // Notify child process to start. This is done to delay the call to exec
+    // until the process is registered above, and we are ready to receive the
+    // exit code.
+    char msg = '1';
+    int bytes_written =
+        FDUtils::WriteToBlocking(read_in_[1], &msg, sizeof(msg));
+    if (bytes_written != sizeof(msg)) {
+      return CleanupAndReturnError();
+    }
+
+    // Read the result of executing the child process.
+    VOID_TEMP_FAILURE_RETRY(close(exec_control_[1]));
+    exec_control_[1] = -1;
+    if (mode_ == kNormal) {
+      err = ReadExecResult();
+    } else {
+      err = ReadDetachedExecResult(&pid);
+    }
+    VOID_TEMP_FAILURE_RETRY(close(exec_control_[0]));
+    exec_control_[0] = -1;
+
+    // Return error code if any failures.
+    if (err != 0) {
+      if (mode_ == kNormal) {
+        // Since exec() failed, we're not interested in the exit code.
+        // We close the reading side of the exit code pipe here.
+        // GetProcessExitCodes will get a broken pipe error when it
+        // tries to write to the writing side of the pipe and it will
+        // ignore the error.
+        VOID_TEMP_FAILURE_RETRY(close(*exit_event_));
+        *exit_event_ = -1;
+      }
+      CloseAllPipes();
+      return err;
+    }
+
+    if (mode_ != kDetached) {
+      // Connect stdio, stdout and stderr.
+      FDUtils::SetNonBlocking(read_in_[0]);
+      *in_ = read_in_[0];
+      VOID_TEMP_FAILURE_RETRY(close(read_in_[1]));
+      FDUtils::SetNonBlocking(write_out_[1]);
+      *out_ = write_out_[1];
+      VOID_TEMP_FAILURE_RETRY(close(write_out_[0]));
+      FDUtils::SetNonBlocking(read_err_[0]);
+      *err_ = read_err_[0];
+      VOID_TEMP_FAILURE_RETRY(close(read_err_[1]));
+    } else {
+      // Close all fds.
+      VOID_TEMP_FAILURE_RETRY(close(read_in_[0]));
+      VOID_TEMP_FAILURE_RETRY(close(read_in_[1]));
+      ASSERT(write_out_[0] == -1);
+      ASSERT(write_out_[1] == -1);
+      ASSERT(read_err_[0] == -1);
+      ASSERT(read_err_[1] == -1);
+    }
+    ASSERT(exec_control_[0] == -1);
+    ASSERT(exec_control_[1] == -1);
+
+    *id_ = pid;
+    return 0;
+  }
+
+ private:
+  int CreatePipes() {
+    int result;
+    result = TEMP_FAILURE_RETRY(pipe(exec_control_));
+    if (result < 0) {
+      return CleanupAndReturnError();
+    }
+    FDUtils::SetCloseOnExec(exec_control_[0]);
+    FDUtils::SetCloseOnExec(exec_control_[1]);
+
+    // For a detached process the pipe to connect stdout is still used for
+    // signaling when to do the first fork.
+    result = TEMP_FAILURE_RETRY(pipe(read_in_));
+    if (result < 0) {
+      return CleanupAndReturnError();
+    }
+    FDUtils::SetCloseOnExec(read_in_[0]);
+
+    // For detached processes the pipe to connect stderr and stdin are not used.
+    if (mode_ != kDetached) {
+      result = TEMP_FAILURE_RETRY(pipe(read_err_));
+      if (result < 0) {
+        return CleanupAndReturnError();
+      }
+      FDUtils::SetCloseOnExec(read_err_[0]);
+
+      result = TEMP_FAILURE_RETRY(pipe(write_out_));
+      if (result < 0) {
+        return CleanupAndReturnError();
+      }
+      FDUtils::SetCloseOnExec(write_out_[1]);
+    }
+
+    return 0;
+  }
+
+
+  void NewProcess() {
+    // Wait for parent process before setting up the child process.
+    char msg;
+    int bytes_read = FDUtils::ReadFromBlocking(read_in_[0], &msg, sizeof(msg));
+    if (bytes_read != sizeof(msg)) {
+      perror("Failed receiving notification message");
+      exit(1);
+    }
+    if (mode_ == kNormal) {
+      ExecProcess();
+    } else {
+      ExecDetachedProcess();
+    }
+  }
+
+
+  void ExecProcess() {
+    VOID_TEMP_FAILURE_RETRY(close(write_out_[1]));
+    VOID_TEMP_FAILURE_RETRY(close(read_in_[0]));
+    VOID_TEMP_FAILURE_RETRY(close(read_err_[0]));
+    VOID_TEMP_FAILURE_RETRY(close(exec_control_[0]));
+
+    if (TEMP_FAILURE_RETRY(dup2(write_out_[0], STDIN_FILENO)) == -1) {
+      ReportChildError();
+    }
+    VOID_TEMP_FAILURE_RETRY(close(write_out_[0]));
+
+    if (TEMP_FAILURE_RETRY(dup2(read_in_[1], STDOUT_FILENO)) == -1) {
+      ReportChildError();
+    }
+    VOID_TEMP_FAILURE_RETRY(close(read_in_[1]));
+
+    if (TEMP_FAILURE_RETRY(dup2(read_err_[1], STDERR_FILENO)) == -1) {
+      ReportChildError();
+    }
+    VOID_TEMP_FAILURE_RETRY(close(read_err_[1]));
+
+    if (working_directory_ != NULL &&
+        TEMP_FAILURE_RETRY(chdir(working_directory_)) == -1) {
+      ReportChildError();
+    }
+
+    if (program_environment_ != NULL) {
+      // On MacOS you have to do a bit of magic to get to the
+      // environment strings.
+      char*** environ = _NSGetEnviron();
+      *environ = program_environment_;
+    }
+
+    VOID_TEMP_FAILURE_RETRY(
+        execvp(path_, const_cast<char* const*>(program_arguments_)));
+
+    ReportChildError();
+  }
+
+
+  void ExecDetachedProcess() {
+    if (mode_ == kDetached) {
+      ASSERT(write_out_[0] == -1);
+      ASSERT(write_out_[1] == -1);
+      ASSERT(read_err_[0] == -1);
+      ASSERT(read_err_[1] == -1);
+      // For a detached process the pipe to connect stdout is only used for
+      // signaling when to do the first fork.
+      VOID_TEMP_FAILURE_RETRY(close(read_in_[0]));
+      read_in_[0] = -1;
+      VOID_TEMP_FAILURE_RETRY(close(read_in_[1]));
+      read_in_[1] = -1;
+    } else {
+      // Don't close any fds if keeping stdio open to the detached process.
+      ASSERT(mode_ == kDetachedWithStdio);
+    }
+    // Fork once more to start a new session.
+    pid_t pid = TEMP_FAILURE_RETRY(fork());
+    if (pid < 0) {
+      ReportChildError();
+    } else if (pid == 0) {
+      // Start a new session.
+      if (TEMP_FAILURE_RETRY(setsid()) == -1) {
+        ReportChildError();
+      } else {
+        // Do a final fork to not be the session leader.
+        pid = TEMP_FAILURE_RETRY(fork());
+        if (pid < 0) {
+          ReportChildError();
+        } else if (pid == 0) {
+          if (mode_ == kDetached) {
+            SetupDetached();
+          } else {
+            SetupDetachedWithStdio();
+          }
+
+          if (working_directory_ != NULL &&
+              TEMP_FAILURE_RETRY(chdir(working_directory_)) == -1) {
+            ReportChildError();
+          }
+
+          // Report the final PID and do the exec.
+          ReportPid(getpid());  // getpid cannot fail.
+          VOID_TEMP_FAILURE_RETRY(
+              execvp(path_, const_cast<char* const*>(program_arguments_)));
+          ReportChildError();
+        } else {
+          // Exit the intermeiate process.
+          exit(0);
+        }
+      }
+    } else {
+      // Exit the intermeiate process.
+      exit(0);
+    }
+  }
+
+
+  int RegisterProcess(pid_t pid) {
+    int result;
+    int event_fds[2];
+    result = TEMP_FAILURE_RETRY(pipe(event_fds));
+    if (result < 0) {
+      return CleanupAndReturnError();
+    }
+    FDUtils::SetCloseOnExec(event_fds[0]);
+    FDUtils::SetCloseOnExec(event_fds[1]);
+
+    ProcessInfoList::AddProcess(pid, event_fds[1]);
+    *exit_event_ = event_fds[0];
+    FDUtils::SetNonBlocking(event_fds[0]);
+    return 0;
+  }
+
+
+  int ReadExecResult() {
+    int child_errno;
+    int bytes_read = -1;
+    // Read exec result from child. If no data is returned the exec was
+    // successful and the exec call closed the pipe. Otherwise the errno
+    // is written to the pipe.
+    bytes_read =
+        FDUtils::ReadFromBlocking(
+            exec_control_[0], &child_errno, sizeof(child_errno));
+    if (bytes_read == sizeof(child_errno)) {
+      ReadChildError();
+      return child_errno;
+    } else if (bytes_read == -1) {
+      return errno;
+    }
+    return 0;
+  }
+
+
+  int ReadDetachedExecResult(pid_t *pid) {
+    int child_errno;
+    int bytes_read = -1;
+    // Read exec result from child. If only pid data is returned the exec was
+    // successful and the exec call closed the pipe. Otherwise the errno
+    // is written to the pipe as well.
+    int result[2];
+    bytes_read =
+        FDUtils::ReadFromBlocking(
+            exec_control_[0], result, sizeof(result));
+    if (bytes_read == sizeof(int)) {
+      *pid = result[0];
+    } else if (bytes_read == 2 * sizeof(int)) {
+      *pid = result[0];
+      child_errno = result[1];
+      ReadChildError();
+      return child_errno;
+    } else if (bytes_read == -1) {
+      return errno;
+    }
+    return 0;
+  }
+
+
+  void SetupDetached() {
+    ASSERT(mode_ == kDetached);
+
+    // Close all open file descriptors except for exec_control_[1].
+    int max_fds = sysconf(_SC_OPEN_MAX);
+    if (max_fds == -1) max_fds = _POSIX_OPEN_MAX;
+    for (int fd = 0; fd < max_fds; fd++) {
+      if (fd != exec_control_[1]) {
+        VOID_TEMP_FAILURE_RETRY(close(fd));
+      }
+    }
+
+    // Re-open stdin, stdout and stderr and connect them to /dev/null.
+    // The loop above should already have closed all of them, so
+    // creating new file descriptors should start at STDIN_FILENO.
+    int fd = TEMP_FAILURE_RETRY(open("/dev/null", O_RDWR));
+    if (fd != STDIN_FILENO) {
+      ReportChildError();
+    }
+    if (TEMP_FAILURE_RETRY(dup2(STDIN_FILENO, STDOUT_FILENO)) !=
+        STDOUT_FILENO) {
+      ReportChildError();
+    }
+    if (TEMP_FAILURE_RETRY(dup2(STDIN_FILENO, STDERR_FILENO)) !=
+        STDERR_FILENO) {
+      ReportChildError();
+    }
+  }
+
+  void SetupDetachedWithStdio() {
+    // Close all open file descriptors except for
+    // exec_control_[1], write_out_[0], read_in_[1] and
+    // read_err_[1].
+    int max_fds = sysconf(_SC_OPEN_MAX);
+    if (max_fds == -1) max_fds = _POSIX_OPEN_MAX;
+    for (int fd = 0; fd < max_fds; fd++) {
+      if (fd != exec_control_[1] &&
+          fd != write_out_[0] &&
+          fd != read_in_[1] &&
+          fd != read_err_[1]) {
+        VOID_TEMP_FAILURE_RETRY(close(fd));
+      }
+    }
+
+    if (TEMP_FAILURE_RETRY(dup2(write_out_[0], STDIN_FILENO)) == -1) {
+      ReportChildError();
+    }
+    VOID_TEMP_FAILURE_RETRY(close(write_out_[0]));
+
+    if (TEMP_FAILURE_RETRY(dup2(read_in_[1], STDOUT_FILENO)) == -1) {
+      ReportChildError();
+    }
+    VOID_TEMP_FAILURE_RETRY(close(read_in_[1]));
+
+    if (TEMP_FAILURE_RETRY(dup2(read_err_[1], STDERR_FILENO)) == -1) {
+      ReportChildError();
+    }
+    VOID_TEMP_FAILURE_RETRY(close(read_err_[1]));
+  }
+
+
+  int CleanupAndReturnError() {
+    int actual_errno = errno;
+    // If CleanupAndReturnError is called without an actual errno make
+    // sure to return an error anyway.
+    if (actual_errno == 0) actual_errno = EPERM;
+    SetChildOsErrorMessage();
+    CloseAllPipes();
+    return actual_errno;
+  }
+
+
+  void SetChildOsErrorMessage() {
+    const int kBufferSize = 1024;
+    char error_message[kBufferSize];
+    strerror_r(errno, error_message, kBufferSize);
+    *os_error_message_ = strdup(error_message);
+  }
+
+
+  void ReportChildError() {
+    // In the case of failure in the child process write the errno and
+    // the OS error message to the exec control pipe and exit.
+    int child_errno = errno;
+    const int kBufferSize = 1024;
+    char os_error_message[kBufferSize];
+    strerror_r(errno, os_error_message, kBufferSize);
+    int bytes_written =
+        FDUtils::WriteToBlocking(
+            exec_control_[1], &child_errno, sizeof(child_errno));
+    if (bytes_written == sizeof(child_errno)) {
       FDUtils::WriteToBlocking(
-          exec_control_fd, &child_errno, sizeof(child_errno));
-  if (bytes_written == sizeof(child_errno)) {
-    FDUtils::WriteToBlocking(
-        exec_control_fd, os_error_message, strlen(os_error_message) + 1);
+          exec_control_[1], os_error_message, strlen(os_error_message) + 1);
+    }
+    VOID_TEMP_FAILURE_RETRY(close(exec_control_[1]));
+    exit(1);
   }
-  VOID_TEMP_FAILURE_RETRY(close(exec_control_fd));
-  exit(1);
-}
 
 
-static void ReportPid(int exec_control_fd, int pid) {
-  // In the case of starting a detached process the actual pid of that process
-  // is communicated using the exec control pipe.
-  int bytes_written =
-      FDUtils::WriteToBlocking(exec_control_fd, &pid, sizeof(pid));
-  ASSERT(bytes_written == sizeof(int));
-  USE(bytes_written);
-}
-
-
-static void ReadChildError(int exec_control_fd, char** error_message) {
-  const int kMaxMessageSize = 256;
-  char* message = static_cast<char*>(malloc(kMaxMessageSize));
-  if (message != NULL) {
-    FDUtils::ReadFromBlocking(exec_control_fd, message, kMaxMessageSize);
-    message[kMaxMessageSize - 1] = '\0';
-    *error_message = message;
-  } else {
-    static const char* no_message = "Cannot get error message, out of memory";
-    *error_message = const_cast<char*>(no_message);
+  void ReportPid(int pid) {
+    // In the case of starting a detached process the actual pid of that process
+    // is communicated using the exec control pipe.
+    int bytes_written =
+        FDUtils::WriteToBlocking(exec_control_[1], &pid, sizeof(pid));
+    ASSERT(bytes_written == sizeof(int));
+    USE(bytes_written);
   }
-}
+
+
+  void ReadChildError() {
+    const int kMaxMessageSize = 256;
+    char* message = static_cast<char*>(malloc(kMaxMessageSize));
+    if (message != NULL) {
+      FDUtils::ReadFromBlocking(exec_control_[0], message, kMaxMessageSize);
+      message[kMaxMessageSize - 1] = '\0';
+      *os_error_message_ = message;
+    } else {
+      // Could not get error message. It will be NULL.
+      ASSERT(*os_error_message_ == NULL);
+    }
+  }
+
+
+  void ClosePipe(int* fds) {
+    for (int i = 0; i < 2; i++) {
+      if (fds[i] != -1) {
+        VOID_TEMP_FAILURE_RETRY(close(fds[i]));
+        fds[i] = -1;
+      }
+    }
+  }
+
+
+  void CloseAllPipes() {
+    ClosePipe(exec_control_);
+    ClosePipe(read_in_);
+    ClosePipe(read_err_);
+    ClosePipe(write_out_);
+  }
+
+
+  int read_in_[2];  // Pipe for stdout to child process.
+  int read_err_[2];  // Pipe for stderr to child process.
+  int write_out_[2];  // Pipe for stdin to child process.
+  int exec_control_[2];  // Pipe to get the result from exec.
+
+  char** program_arguments_;
+  char** program_environment_;
+
+  const char* path_;
+  const char* working_directory_;
+  ProcessStartMode mode_;
+  intptr_t* in_;
+  intptr_t* out_;
+  intptr_t* err_;
+  intptr_t* id_;
+  intptr_t* exit_event_;
+  char** os_error_message_;
+};
 
 
 int Process::Start(const char* path,
@@ -288,314 +753,27 @@
                    const char* working_directory,
                    char* environment[],
                    intptr_t environment_length,
-                   bool detach,
+                   ProcessStartMode mode,
                    intptr_t* in,
                    intptr_t* out,
                    intptr_t* err,
                    intptr_t* id,
                    intptr_t* exit_event,
                    char** os_error_message) {
-  pid_t pid;
-  int read_in[2] = {-1, -1};  // Pipe for stdout to child process.
-  int read_err[2] = {-1, -1};  // Pipe for stderr to child process.
-  int write_out[2] = {-1, -1};  // Pipe for stdin to child process.
-  int exec_control[2] = {-1, -1};  // Pipe to get the result from exec.
-  int result;
-
-  result = TEMP_FAILURE_RETRY(pipe(exec_control));
-  if (result < 0) {
-    SetChildOsErrorMessage(os_error_message);
-    Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message);
-    return errno;
-  }
-  FDUtils::SetCloseOnExec(exec_control[0]);
-  FDUtils::SetCloseOnExec(exec_control[1]);
-
-  // For a detached process the pipe to connect stdout is still used for
-  // signaling when to do the first fork.
-  result = TEMP_FAILURE_RETRY(pipe(read_in));
-  if (result < 0) {
-    SetChildOsErrorMessage(os_error_message);
-    VOID_TEMP_FAILURE_RETRY(close(exec_control[0]));
-    VOID_TEMP_FAILURE_RETRY(close(exec_control[1]));
-    Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message);
-    return errno;
-  }
-  FDUtils::SetCloseOnExec(read_in[0]);
-
-  // For detached processes the pipe to connect stderr and stdin are not used.
-  if (!detach) {
-    result = TEMP_FAILURE_RETRY(pipe(read_err));
-    if (result < 0) {
-      SetChildOsErrorMessage(os_error_message);
-      VOID_TEMP_FAILURE_RETRY(close(exec_control[0]));
-      VOID_TEMP_FAILURE_RETRY(close(exec_control[1]));
-      VOID_TEMP_FAILURE_RETRY(close(read_in[0]));
-      VOID_TEMP_FAILURE_RETRY(close(read_in[1]));
-      Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message);
-      return errno;
-    }
-    FDUtils::SetCloseOnExec(read_err[0]);
-
-    result = TEMP_FAILURE_RETRY(pipe(write_out));
-    if (result < 0) {
-      SetChildOsErrorMessage(os_error_message);
-      VOID_TEMP_FAILURE_RETRY(close(exec_control[0]));
-      VOID_TEMP_FAILURE_RETRY(close(exec_control[1]));
-      VOID_TEMP_FAILURE_RETRY(close(read_in[0]));
-      VOID_TEMP_FAILURE_RETRY(close(read_in[1]));
-      VOID_TEMP_FAILURE_RETRY(close(read_err[0]));
-      VOID_TEMP_FAILURE_RETRY(close(read_err[1]));
-      Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message);
-      return errno;
-    }
-    FDUtils::SetCloseOnExec(write_out[1]);
-  }
-
-  char** program_arguments = new char*[arguments_length + 2];
-  program_arguments[0] = const_cast<char*>(path);
-  for (int i = 0; i < arguments_length; i++) {
-    program_arguments[i + 1] = arguments[i];
-  }
-  program_arguments[arguments_length + 1] = NULL;
-
-  char** program_environment = NULL;
-  if (environment != NULL) {
-    program_environment = new char*[environment_length + 1];
-    for (int i = 0; i < environment_length; i++) {
-      program_environment[i] = environment[i];
-    }
-    program_environment[environment_length] = NULL;
-  }
-
-  pid = TEMP_FAILURE_RETRY(fork());
-  if (pid < 0) {
-    SetChildOsErrorMessage(os_error_message);
-    delete[] program_arguments;
-    VOID_TEMP_FAILURE_RETRY(close(exec_control[0]));
-    VOID_TEMP_FAILURE_RETRY(close(exec_control[1]));
-    VOID_TEMP_FAILURE_RETRY(close(read_in[0]));
-    VOID_TEMP_FAILURE_RETRY(close(read_in[1]));
-    if (detach) {
-      VOID_TEMP_FAILURE_RETRY(close(read_err[0]));
-      VOID_TEMP_FAILURE_RETRY(close(read_err[1]));
-      VOID_TEMP_FAILURE_RETRY(close(write_out[0]));
-      VOID_TEMP_FAILURE_RETRY(close(write_out[1]));
-    }
-    return errno;
-  } else if (pid == 0) {
-    // Wait for parent process before setting up the child process.
-    char msg;
-    int bytes_read = FDUtils::ReadFromBlocking(read_in[0], &msg, sizeof(msg));
-    if (bytes_read != sizeof(msg)) {
-      perror("Failed receiving notification message");
-      exit(1);
-    }
-    if (detach) {
-      // For a detached process the pipe to connect stdout is only used for
-      // signaling when to do the first fork.
-      VOID_TEMP_FAILURE_RETRY(close(read_in[0]));
-      VOID_TEMP_FAILURE_RETRY(close(read_in[1]));
-      // Fork once more to start a new session.
-      pid = TEMP_FAILURE_RETRY(fork());
-      if (pid < 0) {
-        ReportChildError(exec_control[1]);
-      } else if (pid == 0) {
-        // Start a new session.
-        if (TEMP_FAILURE_RETRY(setsid()) == -1) {
-          ReportChildError(exec_control[1]);
-        } else {
-          // Do a final fork to not be the session leader.
-          pid = TEMP_FAILURE_RETRY(fork());
-          if (pid < 0) {
-            ReportChildError(exec_control[1]);
-          } else if (pid == 0) {
-            // Close all open file descriptors except for exec_control[1].
-            int max_fds = sysconf(_SC_OPEN_MAX);
-            if (max_fds == -1) max_fds = _POSIX_OPEN_MAX;
-            for (int fd = 0; fd < max_fds; fd++) {
-              if (fd != exec_control[1]) {
-                VOID_TEMP_FAILURE_RETRY(close(fd));
-              }
-            }
-
-            // Re-open stdin, stdout and stderr and connect them to /dev/null.
-            // The loop above should already have closed all of them, so
-            // creating new file descriptors should start at STDIN_FILENO.
-            int fd = TEMP_FAILURE_RETRY(open("/dev/null", O_RDWR));
-            if (fd != STDIN_FILENO) {
-              ReportChildError(exec_control[1]);
-            }
-            if (TEMP_FAILURE_RETRY(dup2(STDIN_FILENO, STDOUT_FILENO)) !=
-                STDOUT_FILENO) {
-              ReportChildError(exec_control[1]);
-            }
-            if (TEMP_FAILURE_RETRY(dup2(STDIN_FILENO, STDERR_FILENO)) !=
-                STDERR_FILENO) {
-              ReportChildError(exec_control[1]);
-            }
-
-            // Report the final PID and do the exec.
-            ReportPid(exec_control[1], getpid());  // getpid cannot fail.
-            VOID_TEMP_FAILURE_RETRY(
-                execvp(path, const_cast<char* const*>(program_arguments)));
-            ReportChildError(exec_control[1]);
-          } else {
-            exit(0);
-          }
-        }
-      } else {
-        exit(0);
-      }
-    } else {
-      VOID_TEMP_FAILURE_RETRY(close(write_out[1]));
-      VOID_TEMP_FAILURE_RETRY(close(read_in[0]));
-      VOID_TEMP_FAILURE_RETRY(close(read_err[0]));
-      VOID_TEMP_FAILURE_RETRY(close(exec_control[0]));
-
-      if (TEMP_FAILURE_RETRY(dup2(write_out[0], STDIN_FILENO)) == -1) {
-        ReportChildError(exec_control[1]);
-      }
-      VOID_TEMP_FAILURE_RETRY(close(write_out[0]));
-
-      if (TEMP_FAILURE_RETRY(dup2(read_in[1], STDOUT_FILENO)) == -1) {
-        ReportChildError(exec_control[1]);
-      }
-      VOID_TEMP_FAILURE_RETRY(close(read_in[1]));
-
-      if (TEMP_FAILURE_RETRY(dup2(read_err[1], STDERR_FILENO)) == -1) {
-        ReportChildError(exec_control[1]);
-      }
-      VOID_TEMP_FAILURE_RETRY(close(read_err[1]));
-
-      if (working_directory != NULL &&
-          TEMP_FAILURE_RETRY(chdir(working_directory)) == -1) {
-        ReportChildError(exec_control[1]);
-      }
-
-      if (program_environment != NULL) {
-        environ = program_environment;
-      }
-
-      VOID_TEMP_FAILURE_RETRY(
-          execvp(path, const_cast<char* const*>(program_arguments)));
-
-      ReportChildError(exec_control[1]);
-    }
-  }
-
-  // Be sure to listen for exit-codes, now we have a child-process.
-  ExitCodeHandler::ProcessStarted();
-
-  // The arguments and environment for the spawned process are not needed
-  // any longer.
-  delete[] program_arguments;
-  delete[] program_environment;
-
-  if (!detach) {
-    int event_fds[2];
-    result = TEMP_FAILURE_RETRY(pipe(event_fds));
-    if (result < 0) {
-      SetChildOsErrorMessage(os_error_message);
-      VOID_TEMP_FAILURE_RETRY(close(read_in[0]));
-      VOID_TEMP_FAILURE_RETRY(close(read_in[1]));
-      VOID_TEMP_FAILURE_RETRY(close(read_err[0]));
-      VOID_TEMP_FAILURE_RETRY(close(read_err[1]));
-      VOID_TEMP_FAILURE_RETRY(close(write_out[0]));
-      VOID_TEMP_FAILURE_RETRY(close(write_out[1]));
-      Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message);
-      return errno;
-    }
-    FDUtils::SetCloseOnExec(event_fds[0]);
-    FDUtils::SetCloseOnExec(event_fds[1]);
-
-    ProcessInfoList::AddProcess(pid, event_fds[1]);
-    *exit_event = event_fds[0];
-    FDUtils::SetNonBlocking(event_fds[0]);
-  }
-
-  // Notify child process to start.
-  char msg = '1';
-  result = FDUtils::WriteToBlocking(read_in[1], &msg, sizeof(msg));
-  if (result != sizeof(msg)) {
-    perror("Failed sending notification message");
-  }
-
-  // Read exec result from child. If no data is returned the exec was
-  // successful and the exec call closed the pipe. Otherwise the errno
-  // is written to the pipe.
-  VOID_TEMP_FAILURE_RETRY(close(exec_control[1]));
-  bool failed = false;
-  int child_errno;
-  int bytes_read = -1;
-  ASSERT(sizeof(child_errno) == sizeof(errno));
-  if (!detach) {
-    // Read exec result from child. If no data is returned the exec was
-    // successful and the exec call closed the pipe. Otherwise the errno
-    // is written to the pipe.
-    bytes_read =
-        FDUtils::ReadFromBlocking(
-            exec_control[0], &child_errno, sizeof(child_errno));
-    if (bytes_read == sizeof(child_errno)) {
-      ReadChildError(exec_control[0], os_error_message);
-      failed = true;
-    }
-  } else {
-    // Read exec result from child. If only pid data is returned the exec was
-    // successful and the exec call closed the pipe. Otherwise the errno
-    // is written to the pipe as well.
-    int result[2];
-    ASSERT(sizeof(int) == sizeof(child_errno));
-    bytes_read =
-        FDUtils::ReadFromBlocking(
-            exec_control[0], result, sizeof(result));
-    if (bytes_read == sizeof(int)) {
-      pid = result[0];
-    } else if (bytes_read == 2 * sizeof(int)) {
-      pid = result[0];
-      child_errno = result[1];
-      ReadChildError(exec_control[0], os_error_message);
-      failed = true;
-    }
-  }
-  VOID_TEMP_FAILURE_RETRY(close(exec_control[0]));
-
-  // Return error code if any failures.
-  if (failed) {
-    if (!detach) {
-      VOID_TEMP_FAILURE_RETRY(close(read_in[0]));
-      VOID_TEMP_FAILURE_RETRY(close(read_in[1]));
-      VOID_TEMP_FAILURE_RETRY(close(read_err[0]));
-      VOID_TEMP_FAILURE_RETRY(close(read_err[1]));
-      VOID_TEMP_FAILURE_RETRY(close(write_out[0]));
-      VOID_TEMP_FAILURE_RETRY(close(write_out[1]));
-
-      // Since exec() failed, we're not interested in the exit code.
-      // We close the reading side of the exit code pipe here.
-      // GetProcessExitCodes will get a broken pipe error when it tries to write
-      // to the writing side of the pipe and it will ignore the error.
-      VOID_TEMP_FAILURE_RETRY(close(*exit_event));
-      *exit_event = -1;
-    }
-    if (bytes_read == -1) {
-      return errno;  // Read failed.
-    } else {
-      return child_errno;  // Exec failed.
-    }
-  }
-
-  FDUtils::SetNonBlocking(read_in[0]);
-  *in = read_in[0];
-  VOID_TEMP_FAILURE_RETRY(close(read_in[1]));
-  FDUtils::SetNonBlocking(write_out[1]);
-  *out = write_out[1];
-  VOID_TEMP_FAILURE_RETRY(close(write_out[0]));
-  FDUtils::SetNonBlocking(read_err[0]);
-  *err = read_err[0];
-  VOID_TEMP_FAILURE_RETRY(close(read_err[1]));
-
-  *id = pid;
-  return 0;
+  ProcessStarter starter(path,
+                         arguments,
+                         arguments_length,
+                         working_directory,
+                         environment,
+                         environment_length,
+                         mode,
+                         in,
+                         out,
+                         err,
+                         id,
+                         exit_event,
+                         os_error_message);
+  return starter.Start();
 }
 
 
diff --git a/runtime/bin/process_patch.dart b/runtime/bin/process_patch.dart
index d188381..0cffb5a 100644
--- a/runtime/bin/process_patch.dart
+++ b/runtime/bin/process_patch.dart
@@ -22,14 +22,14 @@
        Map<String, String> environment,
        bool includeParentEnvironment: true,
        bool runInShell: false,
-       bool detach: false}) {
+       ProcessStartMode mode: ProcessStartMode.NORMAL}) {
     _ProcessImpl process = new _ProcessImpl(executable,
                                             arguments,
                                             workingDirectory,
                                             environment,
                                             includeParentEnvironment,
                                             runInShell,
-                                            detach);
+                                            mode);
     return process._start();
   }
 
@@ -70,6 +70,15 @@
                                          stdoutEncoding,
                                          stderrEncoding);
   }
+
+  /* patch */ static bool killPid(
+      int pid, [ProcessSignal signal = ProcessSignal.SIGTERM]) {
+    if (signal is! ProcessSignal) {
+      throw new ArgumentError(
+          "Argument 'signal' must be a ProcessSignal");
+    }
+    return _ProcessUtils._killPid(pid, signal._signalNumber);
+  }
 }
 
 
@@ -132,6 +141,8 @@
   /* patch */ static int _getExitCode() native "Process_GetExitCode";
   /* patch */ static void _sleep(int millis) native "Process_Sleep";
   /* patch */ static int _pid(Process process) native "Process_Pid";
+  static bool _killPid(int pid, int signal)
+      native "Process_KillPid";
   /* patch */ static Stream<ProcessSignal> _watchSignal(ProcessSignal signal) {
     if (signal != ProcessSignal.SIGHUP &&
         signal != ProcessSignal.SIGINT &&
@@ -176,7 +187,7 @@
                Map<String, String> environment,
                bool includeParentEnvironment,
                bool runInShell,
-               bool detach) : super() {
+               ProcessStartMode mode) : super() {
     _processes[_serviceId] = this;
     if (runInShell) {
       arguments = _getShellArguments(path, arguments);
@@ -233,13 +244,12 @@
       });
     }
 
-    if (detach is !bool) {
-      throw new ArgumentError("Detach is not a boolean: $detach");
+    if (mode is !ProcessStartMode) {
+      throw new ArgumentError("Mode is not a ProcessStartMode: $mode");
     }
-    _detach = detach;
+    _mode = mode;
 
-
-    if (!detach) {
+    if (mode != ProcessStartMode.DETACHED) {
       // stdin going to process.
       _stdin = new _StdSink(new _Socket._writePipe());
       _stdin._sink._owner = this;
@@ -249,6 +259,8 @@
       // stderr coming from process.
       _stderr = new _StdStream(new _Socket._readPipe());
       _stderr._stream._owner = this;
+    }
+    if (mode == ProcessStartMode.NORMAL) {
       _exitHandler = new _Socket._readPipe();
     }
     _ended = false;
@@ -374,7 +386,7 @@
 
   Future<Process> _start() {
     var completer = new Completer();
-    if (!_detach) {
+    if (_mode == ProcessStartMode.NORMAL) {
       _exitCode = new Completer<int>();
     }
     // TODO(ager): Make the actual process starting really async instead of
@@ -386,11 +398,15 @@
                        _arguments,
                        _workingDirectory,
                        _environment,
-                       _detach,
-                       _detach ? null : _stdin._sink._nativeSocket,
-                       _detach ? null : _stdout._stream._nativeSocket,
-                       _detach ? null : _stderr._stream._nativeSocket,
-                       _detach ? null : _exitHandler._nativeSocket,
+                       _mode.index,
+                       _mode == ProcessStartMode.DETACHED
+                           ? null : _stdin._sink._nativeSocket,
+                       _mode == ProcessStartMode.DETACHED
+                           ? null : _stdout._stream._nativeSocket,
+                       _mode == ProcessStartMode.DETACHED
+                           ? null : _stderr._stream._nativeSocket,
+                       _mode != ProcessStartMode.NORMAL
+                           ? null : _exitHandler._nativeSocket,
                        status);
       if (!success) {
         completer.completeError(
@@ -405,7 +421,7 @@
 
       // Setup an exit handler to handle internal cleanup and possible
       // callback when a process terminates.
-      if (!_detach) {
+      if (_mode == ProcessStartMode.NORMAL) {
         int exitDataRead = 0;
         final int EXIT_DATA_SIZE = 8;
         List<int> exitDataBuffer = new List<int>(EXIT_DATA_SIZE);
@@ -448,7 +464,7 @@
                                 _arguments,
                                 _workingDirectory,
                                 _environment,
-                                false,
+                                ProcessStartMode.NORMAL.index,
                                 _stdin._sink._nativeSocket,
                                 _stdout._stream._nativeSocket,
                                 _stderr._stream._nativeSocket,
@@ -485,7 +501,7 @@
                     List<String> arguments,
                     String workingDirectory,
                     List<String> environment,
-                    bool detach,
+                    int mode,
                     _NativeSocket stdin,
                     _NativeSocket stdout,
                     _NativeSocket stderr,
@@ -518,18 +534,16 @@
     }
     assert(_started);
     if (_ended) return false;
-    return _kill(this, signal._signalNumber);
+    return _ProcessUtils._killPid(pid, signal._signalNumber);
   }
 
-  bool _kill(Process p, int signal) native "Process_Kill";
-
   int get pid => _ProcessUtils._pid(this);
 
   String _path;
   List<String> _arguments;
   String _workingDirectory;
   List<String> _environment;
-  bool _detach;
+  ProcessStartMode _mode;
   // Private methods of Socket are used by _in, _out, and _err.
   _StdSink _stdin;
   _StdStream _stdout;
@@ -608,7 +622,7 @@
                                  environment,
                                  includeParentEnvironment,
                                  runInShell,
-                                 false);
+                                 ProcessStartMode.NORMAL);
   return process._runAndWait(stdoutEncoding, stderrEncoding);
 }
 
diff --git a/runtime/bin/process_win.cc b/runtime/bin/process_win.cc
index 8d6b992..d57cde0 100644
--- a/runtime/bin/process_win.cc
+++ b/runtime/bin/process_win.cc
@@ -399,293 +399,329 @@
 }
 
 
+class ProcessStarter {
+ public:
+  ProcessStarter(const char* path,
+                 char* arguments[],
+                 intptr_t arguments_length,
+                 const char* working_directory,
+                 char* environment[],
+                 intptr_t environment_length,
+                 ProcessStartMode mode,
+                 intptr_t* in,
+                 intptr_t* out,
+                 intptr_t* err,
+                 intptr_t* id,
+                 intptr_t* exit_handler,
+                 char** os_error_message)
+      : path_(path),
+        working_directory_(working_directory),
+        mode_(mode),
+        in_(in),
+        out_(out),
+        err_(err),
+        id_(id),
+        exit_handler_(exit_handler),
+        os_error_message_(os_error_message) {
+    stdin_handles_[kReadHandle] = INVALID_HANDLE_VALUE;
+    stdin_handles_[kWriteHandle] = INVALID_HANDLE_VALUE;
+    stdout_handles_[kReadHandle] = INVALID_HANDLE_VALUE;
+    stdout_handles_[kWriteHandle] = INVALID_HANDLE_VALUE;
+    stderr_handles_[kReadHandle] = INVALID_HANDLE_VALUE;
+    stderr_handles_[kWriteHandle] = INVALID_HANDLE_VALUE;
+    exit_handles_[kReadHandle] = INVALID_HANDLE_VALUE;
+    exit_handles_[kWriteHandle] = INVALID_HANDLE_VALUE;
+
+    // Transform input strings to system format.
+    const wchar_t* system_path = StringUtils::Utf8ToWide(path_);
+    wchar_t** system_arguments = new wchar_t*[arguments_length];
+    for (int i = 0; i < arguments_length; i++) {
+       system_arguments[i] = StringUtils::Utf8ToWide(arguments[i]);
+    }
+
+    // Compute command-line length.
+    int command_line_length = wcslen(system_path);
+    for (int i = 0; i < arguments_length; i++) {
+      command_line_length += wcslen(system_arguments[i]);
+    }
+    // Account for null termination and one space per argument.
+    command_line_length += arguments_length + 1;
+
+    // Put together command-line string.
+    command_line_ = new wchar_t[command_line_length];
+    int len = 0;
+    int remaining = command_line_length;
+    int written =
+        _snwprintf(command_line_ + len, remaining, L"%s", system_path);
+    len += written;
+    remaining -= written;
+    ASSERT(remaining >= 0);
+    for (int i = 0; i < arguments_length; i++) {
+      written =
+          _snwprintf(
+              command_line_ + len, remaining, L" %s", system_arguments[i]);
+      len += written;
+      remaining -= written;
+      ASSERT(remaining >= 0);
+    }
+    free(const_cast<wchar_t*>(system_path));
+    for (int i = 0; i < arguments_length; i++) free(system_arguments[i]);
+    delete[] system_arguments;
+
+    // Create environment block if an environment is supplied.
+    environment_block_ = NULL;
+    if (environment != NULL) {
+      wchar_t** system_environment = new wchar_t*[environment_length];
+      // Convert environment strings to system strings.
+      for (intptr_t i = 0; i < environment_length; i++) {
+        system_environment[i] = StringUtils::Utf8ToWide(environment[i]);
+      }
+
+      // An environment block is a sequence of zero-terminated strings
+      // followed by a block-terminating zero char.
+      intptr_t block_size = 1;
+      for (intptr_t i = 0; i < environment_length; i++) {
+        block_size += wcslen(system_environment[i]) + 1;
+      }
+      environment_block_ = new wchar_t[block_size];
+      intptr_t block_index = 0;
+      for (intptr_t i = 0; i < environment_length; i++) {
+        intptr_t len = wcslen(system_environment[i]);
+        intptr_t result = _snwprintf(environment_block_ + block_index,
+                                     len,
+                                     L"%s",
+                                     system_environment[i]);
+        ASSERT(result == len);
+        block_index += len;
+        environment_block_[block_index++] = '\0';
+      }
+      // Block-terminating zero char.
+      environment_block_[block_index++] = '\0';
+      ASSERT(block_index == block_size);
+      for (intptr_t i = 0; i < environment_length; i++) {
+        free(system_environment[i]);
+      }
+      delete[] system_environment;
+    }
+
+    system_working_directory_ = NULL;
+    if (working_directory_ != NULL) {
+      system_working_directory_ = StringUtils::Utf8ToWide(working_directory_);
+    }
+
+    attribute_list_ = NULL;
+  }
+
+
+  ~ProcessStarter() {
+    // Deallocate command-line and environment block strings.
+    delete[] command_line_;
+    delete[] environment_block_;
+    if (system_working_directory_ != NULL) {
+      free(const_cast<wchar_t*>(system_working_directory_));
+    }
+    if (attribute_list_ != NULL) {
+      delete_proc_thread_attr_list(attribute_list_);
+      free(attribute_list_);
+    }
+  }
+
+
+  int Start() {
+    // Create pipes required.
+    int err = CreatePipes();
+    if (err != 0) return err;
+
+    // Setup info structures.
+    STARTUPINFOEXW startup_info;
+    ZeroMemory(&startup_info, sizeof(startup_info));
+    startup_info.StartupInfo.cb = sizeof(startup_info);
+    startup_info.StartupInfo.hStdInput = stdin_handles_[kReadHandle];
+    startup_info.StartupInfo.hStdOutput = stdout_handles_[kWriteHandle];
+    startup_info.StartupInfo.hStdError = stderr_handles_[kWriteHandle];
+    startup_info.StartupInfo.dwFlags = STARTF_USESTDHANDLES;
+
+    bool supports_proc_thread_attr_lists = EnsureInitialized();
+    if (supports_proc_thread_attr_lists) {
+      // Setup the handles to inherit. We only want to inherit the three handles
+      // for stdin, stdout and stderr.
+      SIZE_T size = 0;
+      // The call to determine the size of an attribute list always fails with
+      // ERROR_INSUFFICIENT_BUFFER and that error should be ignored.
+      if (!init_proc_thread_attr_list(NULL, 1, 0, &size) &&
+          GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
+        return CleanupAndReturnError();
+      }
+      attribute_list_ =
+          reinterpret_cast<LPPROC_THREAD_ATTRIBUTE_LIST>(malloc(size));
+      ZeroMemory(attribute_list_, size);
+      if (!init_proc_thread_attr_list(attribute_list_, 1, 0, &size)) {
+        return CleanupAndReturnError();
+      }
+      static const int kNumInheritedHandles = 3;
+      HANDLE inherited_handles[kNumInheritedHandles] =
+          { stdin_handles_[kReadHandle],
+            stdout_handles_[kWriteHandle],
+            stderr_handles_[kWriteHandle] };
+      if (!update_proc_thread_attr(attribute_list_,
+                                   0,
+                                   PROC_THREAD_ATTRIBUTE_HANDLE_LIST,
+                                   inherited_handles,
+                                   kNumInheritedHandles * sizeof(HANDLE),
+                                   NULL,
+                                   NULL)) {
+        return CleanupAndReturnError();
+      }
+      startup_info.lpAttributeList = attribute_list_;
+    }
+
+    PROCESS_INFORMATION process_info;
+    ZeroMemory(&process_info, sizeof(process_info));
+
+    // Create process.
+    DWORD creation_flags =
+        EXTENDED_STARTUPINFO_PRESENT | CREATE_UNICODE_ENVIRONMENT;
+    if (mode_ != kNormal) {
+      creation_flags |= DETACHED_PROCESS;
+    }
+    BOOL result = CreateProcessW(NULL,   // ApplicationName
+                                 command_line_,
+                                 NULL,   // ProcessAttributes
+                                 NULL,   // ThreadAttributes
+                                 TRUE,   // InheritHandles
+                                 creation_flags,
+                                 environment_block_,
+                                 system_working_directory_,
+                                 reinterpret_cast<STARTUPINFOW*>(&startup_info),
+                                 &process_info);
+
+    if (result == 0) {
+      return CleanupAndReturnError();
+    }
+
+    CloseHandle(stdin_handles_[kReadHandle]);
+    CloseHandle(stdout_handles_[kWriteHandle]);
+    CloseHandle(stderr_handles_[kWriteHandle]);
+    if (mode_ == kNormal) {
+      ProcessInfoList::AddProcess(process_info.dwProcessId,
+                                  process_info.hProcess,
+                                  exit_handles_[kWriteHandle]);
+    }
+    if (mode_ != kDetached) {
+      // Connect the three stdio streams.
+      FileHandle* stdin_handle = new FileHandle(stdin_handles_[kWriteHandle]);
+      FileHandle* stdout_handle = new FileHandle(stdout_handles_[kReadHandle]);
+      FileHandle* stderr_handle = new FileHandle(stderr_handles_[kReadHandle]);
+      *in_ = reinterpret_cast<intptr_t>(stdout_handle);
+      *out_ = reinterpret_cast<intptr_t>(stdin_handle);
+      *err_ = reinterpret_cast<intptr_t>(stderr_handle);
+      if (mode_ == kNormal) {
+        FileHandle* exit_handle = new FileHandle(exit_handles_[kReadHandle]);
+        *exit_handler_ = reinterpret_cast<intptr_t>(exit_handle);
+      }
+    }
+
+    CloseHandle(process_info.hThread);
+
+    // Return process id.
+    *id_ = process_info.dwProcessId;
+    return 0;
+  }
+
+
+  int CreatePipes() {
+    // Generate unique pipe names for the four named pipes needed.
+    wchar_t pipe_names[4][kMaxPipeNameSize];
+    int status = GenerateNames<4>(pipe_names);
+    if (status != 0) {
+      SetOsErrorMessage(os_error_message_);
+      Log::PrintErr("UuidCreateSequential failed %d\n", status);
+      return status;
+    }
+
+    if (mode_ != kDetached) {
+      // Open pipes for stdin, stdout, stderr and for communicating the exit
+      // code.
+      if (!CreateProcessPipe(stdin_handles_, pipe_names[0], kInheritRead) ||
+          !CreateProcessPipe(stdout_handles_, pipe_names[1], kInheritWrite) ||
+          !CreateProcessPipe(stderr_handles_, pipe_names[2], kInheritWrite)) {
+        return CleanupAndReturnError();
+      }
+      // Only open exit code pipe for non detached processes.
+      if (mode_ == kNormal) {
+        if (!CreateProcessPipe(exit_handles_, pipe_names[3], kInheritNone)) {
+          return CleanupAndReturnError();
+        }
+      }
+    } else {
+      // Open NUL for stdin, stdout and stderr.
+      if ((stdin_handles_[kReadHandle] = OpenNul()) == INVALID_HANDLE_VALUE ||
+          (stdout_handles_[kWriteHandle] = OpenNul()) == INVALID_HANDLE_VALUE ||
+          (stderr_handles_[kWriteHandle] = OpenNul()) == INVALID_HANDLE_VALUE) {
+        return CleanupAndReturnError();
+      }
+    }
+    return 0;
+  }
+
+
+  int CleanupAndReturnError() {
+    int error_code = SetOsErrorMessage(os_error_message_);
+    CloseProcessPipes(
+        stdin_handles_, stdout_handles_, stderr_handles_, exit_handles_);
+    return error_code;
+  }
+
+
+  HANDLE stdin_handles_[2];
+  HANDLE stdout_handles_[2];
+  HANDLE stderr_handles_[2];
+  HANDLE exit_handles_[2];
+
+  const wchar_t* system_working_directory_;
+  wchar_t* command_line_;
+  wchar_t* environment_block_;
+  LPPROC_THREAD_ATTRIBUTE_LIST attribute_list_;
+
+  const char* path_;
+  const char* working_directory_;
+  ProcessStartMode mode_;
+  intptr_t* in_;
+  intptr_t* out_;
+  intptr_t* err_;
+  intptr_t* id_;
+  intptr_t* exit_handler_;
+  char** os_error_message_;
+};
+
+
 int Process::Start(const char* path,
                    char* arguments[],
                    intptr_t arguments_length,
                    const char* working_directory,
                    char* environment[],
                    intptr_t environment_length,
-                   bool detach,
+                   ProcessStartMode mode,
                    intptr_t* in,
                    intptr_t* out,
                    intptr_t* err,
                    intptr_t* id,
                    intptr_t* exit_handler,
                    char** os_error_message) {
-  HANDLE stdin_handles[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE };
-  HANDLE stdout_handles[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE };
-  HANDLE stderr_handles[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE };
-  HANDLE exit_handles[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE };
-
-  // Generate unique pipe names for the four named pipes needed.
-  wchar_t pipe_names[4][kMaxPipeNameSize];
-  int status = GenerateNames<4>(pipe_names);
-  if (status != 0) {
-    SetOsErrorMessage(os_error_message);
-    Log::PrintErr("UuidCreateSequential failed %d\n", status);
-    return status;
-  }
-
-  if (!detach) {
-    // Open pipes for stdin, stdout, stderr and for communicating the exit
-    // code.
-    if (!CreateProcessPipe(stdin_handles, pipe_names[0], kInheritRead)) {
-      int error_code = SetOsErrorMessage(os_error_message);
-      CloseProcessPipes(
-          stdin_handles, stdout_handles, stderr_handles, exit_handles);
-      return error_code;
-    }
-    if (!CreateProcessPipe(stdout_handles, pipe_names[1], kInheritWrite)) {
-      int error_code = SetOsErrorMessage(os_error_message);
-      CloseProcessPipes(
-          stdin_handles, stdout_handles, stderr_handles, exit_handles);
-      return error_code;
-    }
-    if (!CreateProcessPipe(stderr_handles, pipe_names[2], kInheritWrite)) {
-      int error_code = SetOsErrorMessage(os_error_message);
-      CloseProcessPipes(
-          stdin_handles, stdout_handles, stderr_handles, exit_handles);
-      return error_code;
-    }
-    if (!CreateProcessPipe(exit_handles, pipe_names[3], kInheritNone)) {
-      int error_code = SetOsErrorMessage(os_error_message);
-      CloseProcessPipes(
-          stdin_handles, stdout_handles, stderr_handles, exit_handles);
-      return error_code;
-    }
-  } else {
-    // Open NUL for stdin, stdout and stderr.
-    stdin_handles[kReadHandle] = OpenNul();
-    if (stdin_handles[kReadHandle] == INVALID_HANDLE_VALUE) {
-      int error_code = SetOsErrorMessage(os_error_message);
-      CloseProcessPipes(
-          stdin_handles, stdout_handles, stderr_handles, exit_handles);
-      return error_code;
-    }
-    stdout_handles[kWriteHandle] = OpenNul();
-    if (stdout_handles[kWriteHandle] == INVALID_HANDLE_VALUE) {
-      int error_code = SetOsErrorMessage(os_error_message);
-      CloseProcessPipes(
-          stdin_handles, stdout_handles, stderr_handles, exit_handles);
-      return error_code;
-    }
-    stderr_handles[kWriteHandle] = OpenNul();
-    if (stderr_handles[kWriteHandle] == INVALID_HANDLE_VALUE) {
-      int error_code = SetOsErrorMessage(os_error_message);
-      CloseProcessPipes(
-          stdin_handles, stdout_handles, stderr_handles, exit_handles);
-      return error_code;
-    }
-  }
-
-  // Setup info structures.
-  STARTUPINFOEXW startup_info;
-  ZeroMemory(&startup_info, sizeof(startup_info));
-  startup_info.StartupInfo.cb = sizeof(startup_info);
-  startup_info.StartupInfo.hStdInput = stdin_handles[kReadHandle];
-  startup_info.StartupInfo.hStdOutput = stdout_handles[kWriteHandle];
-  startup_info.StartupInfo.hStdError = stderr_handles[kWriteHandle];
-  startup_info.StartupInfo.dwFlags = STARTF_USESTDHANDLES;
-
-  LPPROC_THREAD_ATTRIBUTE_LIST attribute_list = NULL;
-
-  bool supports_proc_thread_attr_lists = EnsureInitialized();
-  if (supports_proc_thread_attr_lists) {
-    // Setup the handles to inherit. We only want to inherit the three handles
-    // for stdin, stdout and stderr.
-    SIZE_T size = 0;
-    // The call to determine the size of an attribute list always fails with
-    // ERROR_INSUFFICIENT_BUFFER and that error should be ignored.
-    if (!init_proc_thread_attr_list(NULL, 1, 0, &size) &&
-        GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
-      int error_code = SetOsErrorMessage(os_error_message);
-      CloseProcessPipes(
-          stdin_handles, stdout_handles, stderr_handles, exit_handles);
-      return error_code;
-    }
-    attribute_list =
-        reinterpret_cast<LPPROC_THREAD_ATTRIBUTE_LIST>(malloc(size));
-    ZeroMemory(attribute_list, size);
-    if (!init_proc_thread_attr_list(attribute_list, 1, 0, &size)) {
-      int error_code = SetOsErrorMessage(os_error_message);
-      CloseProcessPipes(
-          stdin_handles, stdout_handles, stderr_handles, exit_handles);
-      free(attribute_list);
-      return error_code;
-    }
-    static const int kNumInheritedHandles = 3;
-    HANDLE inherited_handles[kNumInheritedHandles] =
-        { stdin_handles[kReadHandle],
-          stdout_handles[kWriteHandle],
-          stderr_handles[kWriteHandle] };
-    if (!update_proc_thread_attr(attribute_list,
-                                 0,
-                                 PROC_THREAD_ATTRIBUTE_HANDLE_LIST,
-                                 inherited_handles,
-                                 kNumInheritedHandles * sizeof(HANDLE),
-                                 NULL,
-                                 NULL)) {
-      delete_proc_thread_attr_list(attribute_list);
-      int error_code = SetOsErrorMessage(os_error_message);
-      CloseProcessPipes(
-          stdin_handles, stdout_handles, stderr_handles, exit_handles);
-      free(attribute_list);
-      return error_code;
-    }
-    startup_info.lpAttributeList = attribute_list;
-  }
-
-  PROCESS_INFORMATION process_info;
-  ZeroMemory(&process_info, sizeof(process_info));
-
-  // Transform input strings to system format.
-  const wchar_t* system_path = StringUtils::Utf8ToWide(path);
-  wchar_t** system_arguments = new wchar_t*[arguments_length];
-  for (int i = 0; i < arguments_length; i++) {
-     system_arguments[i] = StringUtils::Utf8ToWide(arguments[i]);
-  }
-
-  // Compute command-line length.
-  int command_line_length = wcslen(system_path);
-  for (int i = 0; i < arguments_length; i++) {
-    command_line_length += wcslen(system_arguments[i]);
-  }
-  // Account for null termination and one space per argument.
-  command_line_length += arguments_length + 1;
-  static const int kMaxCommandLineLength = 32768;
-  if (command_line_length > kMaxCommandLineLength) {
-    int error_code = SetOsErrorMessage(os_error_message);
-    CloseProcessPipes(
-        stdin_handles, stdout_handles, stderr_handles, exit_handles);
-    free(const_cast<wchar_t*>(system_path));
-    for (int i = 0; i < arguments_length; i++) free(system_arguments[i]);
-    delete[] system_arguments;
-    if (supports_proc_thread_attr_lists) {
-      delete_proc_thread_attr_list(attribute_list);
-      free(attribute_list);
-    }
-    return error_code;
-  }
-
-  // Put together command-line string.
-  wchar_t* command_line = new wchar_t[command_line_length];
-  int len = 0;
-  int remaining = command_line_length;
-  int written = _snwprintf(command_line + len, remaining, L"%s", system_path);
-  len += written;
-  remaining -= written;
-  ASSERT(remaining >= 0);
-  for (int i = 0; i < arguments_length; i++) {
-    written =
-        _snwprintf(command_line + len, remaining, L" %s", system_arguments[i]);
-    len += written;
-    remaining -= written;
-    ASSERT(remaining >= 0);
-  }
-  free(const_cast<wchar_t*>(system_path));
-  for (int i = 0; i < arguments_length; i++) free(system_arguments[i]);
-  delete[] system_arguments;
-
-  // Create environment block if an environment is supplied.
-  wchar_t* environment_block = NULL;
-  if (environment != NULL) {
-    wchar_t** system_environment = new wchar_t*[environment_length];
-    // Convert environment strings to system strings.
-    for (intptr_t i = 0; i < environment_length; i++) {
-      system_environment[i] = StringUtils::Utf8ToWide(environment[i]);
-    }
-
-    // An environment block is a sequence of zero-terminated strings
-    // followed by a block-terminating zero char.
-    intptr_t block_size = 1;
-    for (intptr_t i = 0; i < environment_length; i++) {
-      block_size += wcslen(system_environment[i]) + 1;
-    }
-    environment_block = new wchar_t[block_size];
-    intptr_t block_index = 0;
-    for (intptr_t i = 0; i < environment_length; i++) {
-      intptr_t len = wcslen(system_environment[i]);
-      intptr_t result = _snwprintf(environment_block + block_index,
-                                   len,
-                                   L"%s",
-                                   system_environment[i]);
-      ASSERT(result == len);
-      block_index += len;
-      environment_block[block_index++] = '\0';
-    }
-    // Block-terminating zero char.
-    environment_block[block_index++] = '\0';
-    ASSERT(block_index == block_size);
-    for (intptr_t i = 0; i < environment_length; i++) {
-      free(system_environment[i]);
-    }
-    delete[] system_environment;
-  }
-
-  const wchar_t* system_working_directory = NULL;
-  if (working_directory != NULL) {
-    system_working_directory = StringUtils::Utf8ToWide(working_directory);
-  }
-
-  // Create process.
-  DWORD creation_flags =
-      EXTENDED_STARTUPINFO_PRESENT | CREATE_UNICODE_ENVIRONMENT;
-  if (detach) {
-    creation_flags |= DETACHED_PROCESS;
-  }
-  BOOL result = CreateProcessW(NULL,   // ApplicationName
-                               command_line,
-                               NULL,   // ProcessAttributes
-                               NULL,   // ThreadAttributes
-                               TRUE,   // InheritHandles
-                               creation_flags,
-                               environment_block,
-                               system_working_directory,
-                               reinterpret_cast<STARTUPINFOW*>(&startup_info),
-                               &process_info);
-  // Deallocate command-line and environment block strings.
-  delete[] command_line;
-  delete[] environment_block;
-  if (system_working_directory != NULL) {
-    free(const_cast<wchar_t*>(system_working_directory));
-  }
-
-  if (supports_proc_thread_attr_lists) {
-    delete_proc_thread_attr_list(attribute_list);
-    free(attribute_list);
-  }
-
-  if (result == 0) {
-    int error_code = SetOsErrorMessage(os_error_message);
-    CloseProcessPipes(
-        stdin_handles, stdout_handles, stderr_handles, exit_handles);
-    return error_code;
-  }
-
-  CloseHandle(stdin_handles[kReadHandle]);
-  CloseHandle(stdout_handles[kWriteHandle]);
-  CloseHandle(stderr_handles[kWriteHandle]);
-  if (!detach) {
-    ProcessInfoList::AddProcess(process_info.dwProcessId,
-                                process_info.hProcess,
-                                exit_handles[kWriteHandle]);
-
-    // Connect the three std streams.
-    FileHandle* stdin_handle = new FileHandle(stdin_handles[kWriteHandle]);
-    FileHandle* stdout_handle = new FileHandle(stdout_handles[kReadHandle]);
-    FileHandle* stderr_handle = new FileHandle(stderr_handles[kReadHandle]);
-    FileHandle* exit_handle = new FileHandle(exit_handles[kReadHandle]);
-    *in = reinterpret_cast<intptr_t>(stdout_handle);
-    *out = reinterpret_cast<intptr_t>(stdin_handle);
-    *err = reinterpret_cast<intptr_t>(stderr_handle);
-    *exit_handler = reinterpret_cast<intptr_t>(exit_handle);
-  }
-
-  CloseHandle(process_info.hThread);
-
-  // Return process id.
-  *id = process_info.dwProcessId;
-  return 0;
+  ProcessStarter starter(path,
+                         arguments,
+                         arguments_length,
+                         working_directory,
+                         environment,
+                         environment_length,
+                         mode,
+                         in,
+                         out,
+                         err,
+                         id,
+                         exit_handler,
+                         os_error_message);
+  return starter.Start();
 }
 
 
diff --git a/runtime/bin/resources_sources.gypi b/runtime/bin/resources_sources.gypi
index a1bb648..1469d82 100644
--- a/runtime/bin/resources_sources.gypi
+++ b/runtime/bin/resources_sources.gypi
@@ -6,6 +6,7 @@
 {
   'sources': [
 # Standalone VM service sources.
+    'vmservice/loader.dart',
     'vmservice/resources.dart',
     'vmservice/server.dart',
     'vmservice/vmservice_io.dart',
diff --git a/runtime/bin/run_vm_tests.cc b/runtime/bin/run_vm_tests.cc
index 187d60e..9688457 100644
--- a/runtime/bin/run_vm_tests.cc
+++ b/runtime/bin/run_vm_tests.cc
@@ -102,7 +102,6 @@
                                        dart::bin::DartUtils::ReadFile,
                                        dart::bin::DartUtils::WriteFile,
                                        dart::bin::DartUtils::CloseFile,
-                                       NULL,
                                        NULL);
   ASSERT(err_msg == NULL);
   // Apply the filter to all registered tests.
diff --git a/runtime/bin/secure_socket.h b/runtime/bin/secure_socket.h
index eb77fe2..e5d7608 100644
--- a/runtime/bin/secure_socket.h
+++ b/runtime/bin/secure_socket.h
@@ -10,10 +10,14 @@
 #include <stdio.h>
 #include <sys/types.h>
 
+#if !defined(DART_IO_SECURE_SOCKET_DISABLED)
 #include <prinit.h>
 #include <prerror.h>
 #include <prnetdb.h>
 #include <ssl.h>
+#else
+struct PRFileDesc;
+#endif
 
 #include "bin/builtin.h"
 #include "bin/dartutils.h"
diff --git a/runtime/bin/secure_socket_unsupported.cc b/runtime/bin/secure_socket_unsupported.cc
index ff7cce6..231b71e 100644
--- a/runtime/bin/secure_socket_unsupported.cc
+++ b/runtime/bin/secure_socket_unsupported.cc
@@ -98,5 +98,15 @@
   Dart_ThrowException(DartUtils::NewDartArgumentError(
       "Secure Sockets unsupported on this platform"));
 }
+
+class SSLFilter {
+ public:
+  static CObject* ProcessFilterRequest(const CObjectArray& request);
+};
+
+CObject* SSLFilter::ProcessFilterRequest(const CObjectArray& request) {
+  return CObject::IllegalArgumentError();
+}
+
 }  // namespace bin
 }  // namespace dart
diff --git a/runtime/bin/vmservice.h b/runtime/bin/vmservice.h
deleted file mode 100644
index 4dcf93f..0000000
--- a/runtime/bin/vmservice.h
+++ /dev/null
@@ -1,17 +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.
-
-#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/loader.dart b/runtime/bin/vmservice/loader.dart
new file mode 100644
index 0000000..6d81f04
--- /dev/null
+++ b/runtime/bin/vmservice/loader.dart
@@ -0,0 +1,60 @@
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of vmservice_io;
+
+var _httpClient;
+
+void _loadHttp(sendPort, uri) {
+  if (_httpClient == null) {
+    _httpClient = new HttpClient()..maxConnectionsPerHost = 6;
+  }
+  _httpClient.getUrl(uri)
+    .then((HttpClientRequest request) => request.close())
+    .then((HttpClientResponse response) {
+      var builder = new BytesBuilder(copy: false);
+      response.listen(
+          builder.add,
+          onDone: () {
+            if (response.statusCode != 200) {
+              var msg = 'Failure getting $uri: '
+                        '${response.statusCode} ${response.reasonPhrase}';
+              sendPort.send(msg);
+            } else {
+              sendPort.send(builder.takeBytes());
+            }
+          },
+          onError: (e) {
+            sendPort.send(e.toString());
+          });
+    })
+    .catchError((e) {
+      sendPort.send(e.toString());
+    });
+  // It's just here to push an event on the event loop so that we invoke the
+  // scheduled microtasks.
+  Timer.run(() {});
+}
+
+void _loadFile(sendPort, path) {
+  var sourceFile = new File(path);
+  sourceFile.readAsBytes().then((data) {
+    sendPort.send(data);
+  },
+  onError: (e) {
+    sendPort.send(e.toString());
+  });
+}
+
+_processLoadRequest(request) {
+  var sp = request[0];
+  var uri = Uri.parse(request[1]);
+  if (uri.scheme == 'file') {
+    _loadFile(sp, uri.toFilePath());
+  } else if ((uri.scheme == 'http') || (uri.scheme == 'https')) {
+    _loadHttp(sp, uri);
+  } else {
+    sp.send('Unknown scheme for $uri');
+  }
+}
\ No newline at end of file
diff --git a/runtime/bin/vmservice/resources.dart b/runtime/bin/vmservice/resources.dart
index cfc28a2..0930fdc 100644
--- a/runtime/bin/vmservice/resources.dart
+++ b/runtime/bin/vmservice/resources.dart
@@ -47,4 +47,4 @@
   Resource.resources[name] = resource;
 }
 
-void _triggerResourceLoad() native "VMServiceIO_TriggerResourceLoad";
+void _triggerResourceLoad() native "VMServiceIO_TriggerResourceLoad";
\ No newline at end of file
diff --git a/runtime/bin/vmservice/server.dart b/runtime/bin/vmservice/server.dart
index c21f242..46cff7b 100644
--- a/runtime/bin/vmservice/server.dart
+++ b/runtime/bin/vmservice/server.dart
@@ -30,20 +30,29 @@
         socket.close(NOT_MAP_ERROR_CODE, 'Message must be a JSON map.');
         return;
       }
-      var seq = map['seq'];
-      onMessage(seq, new Message.fromUri(Uri.parse(map['request'])));
+      var serial = map['id'];
+
+      // If the map contains 'params' then this is a JsonRPC message.
+      // We are currently in the process of switching the vmservice over to
+      // JsonRPC.
+      if (map['params'] != null) {
+        onMessage(serial, new Message.fromJsonRpc(map['method'],
+                                                  map['params']));
+      } else {
+        onMessage(serial, new Message.fromUri(Uri.parse(map['method'])));
+      }
     } else {
       socket.close(BINARY_MESSAGE_ERROR_CODE, 'Message must be a string.');
     }
   }
 
-  void post(var seq, dynamic response) {
+  void post(var serial, dynamic response) {
     try {
       Map map = {
-        'seq': seq,
+        'id': serial,
         'response': response
       };
-      if (seq == null && response is! String) {
+      if (serial == null && response is! String) {
         socket.add(response);
       } else {
         socket.add(JSON.encode(map));
@@ -69,7 +78,7 @@
 
   HttpRequestClient(this.request, service) : super(service);
 
-  void post(var seq, String response) {
+  void post(var serial, String response) {
     request.response..headers.contentType = jsonContentType
                     ..write(response)
                     ..close();
@@ -165,15 +174,17 @@
     return HttpServer.bind(_ip, _port).then((s) {
       _server = s;
       _server.listen(_requestHandler);
+      var ip = _server.address.address.toString();
       if (_displayMessages) {
-        var ip = _server.address.address.toString();
         var port = _server.port.toString();
         print('Observatory listening on http://$ip:$port');
       }
       // Server is up and running.
+      _notifyServerState(ip, _server.port);
       return this;
     }).catchError((e, st) {
       print('Could not start Observatory HTTP server:\n$e\n$st\n');
+      _notifyServerState("", 0);
       return this;
     });
   }
@@ -195,12 +206,17 @@
         print('Observatory no longer listening on http://$ip:$port');
       }
       _server = null;
+      _notifyServerState("", 0);
       return this;
     }).catchError((e, st) {
       _server = null;
       print('Could not shutdown Observatory HTTP server:\n$e\n$st\n');
+      _notifyServerState("", 0);
       return this;
     });
   }
 
 }
+
+void _notifyServerState(String ip, int port)
+    native "VMServiceIO_NotifyServerState";
\ No newline at end of file
diff --git a/runtime/bin/vmservice/vmservice_dartium.dart b/runtime/bin/vmservice/vmservice_dartium.dart
deleted file mode 100644
index 99f04fa..0000000
--- a/runtime/bin/vmservice/vmservice_dartium.dart
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library vmservice_dartium;
-
-import 'dart:isolate';
-import 'vmservice.dart';
-
-// The receive port that isolate startup / shutdown messages are delivered on.
-RawReceivePort _receivePort;
-// The receive port that service request messages are delivered on.
-RawReceivePort _requestPort;
-
-// The native method that is called to post the response back to DevTools.
-void postResponse(String response, int cookie) native "VMService_PostResponse";
-
-/// Dartium recieves messages through the _requestPort and posts
-/// responses via postResponse. It has a single persistent client.
-class DartiumClient extends Client {
-  DartiumClient(port, service) : super(service) {
-    port.handler = ((message) {
-      if (message == null) {
-        return;
-      }
-      if (message is! List) {
-        return;
-      }
-      if (message.length != 2) {
-        return;
-      }
-      if (message[0] is! String) {
-        return;
-      }
-      var uri = Uri.parse(message[0]);
-      var cookie = message[1];
-      onMessage(cookie, new Message.fromUri(uri));
-    });
-  }
-
-  void post(var seq, String response) {
-    postResponse(response, seq);
-  }
-
-  dynamic toJson() {
-    var map = super.toJson();
-    map['type'] = 'DartiumClient';
-  }
-}
-
-
-main() {
-  // Create VmService.
-  var service = new VMService();
-  _receivePort = service.receivePort;
-  _requestPort = new RawReceivePort();
-  new DartiumClient(_requestPort, service);
-}
diff --git a/runtime/bin/vmservice/vmservice_io.dart b/runtime/bin/vmservice/vmservice_io.dart
index c04d485..2d99e17 100644
--- a/runtime/bin/vmservice/vmservice_io.dart
+++ b/runtime/bin/vmservice/vmservice_io.dart
@@ -10,6 +10,7 @@
 import 'dart:isolate';
 import 'dart:vmservice';
 
+part 'loader.dart';
 part 'resources.dart';
 part 'server.dart';
 
@@ -21,6 +22,8 @@
 
 bool _isWindows = false;
 
+var _signalWatch;
+
 // HTTP servr.
 Server server;
 Future<Server> serverFuture;
@@ -54,18 +57,27 @@
   }
 }
 
-void _registerSignalHandler(Stream signalWatch(ProcessSignal signal)) {
+void _registerSignalHandler() {
   if (_isWindows) {
     // Cannot register for signals on Windows.
     return;
   }
-  signalWatch(ProcessSignal.SIGQUIT).listen(_onSignal);
+  _signalWatch(ProcessSignal.SIGQUIT).listen(_onSignal);
 }
 
-main(Stream signalWatch(ProcessSignal signal)) {
+const _shortDelay = const Duration(milliseconds: 10);
+
+main() {
   if (_autoStart) {
     _bootServer();
     server.startup();
+    // It's just here to push an event on the event loop so that we invoke the
+    // scheduled microtasks.
+    Timer.run(() {});
   }
-  _registerSignalHandler(signalWatch);
+  scriptLoadPort.handler = _processLoadRequest;
+  // Register signal handler after a small delay to avoid stalling main
+  // isolate startup.
+  new Timer(_shortDelay, _registerSignalHandler);
+  return scriptLoadPort;
 }
diff --git a/runtime/bin/vmservice_dartium.cc b/runtime/bin/vmservice_dartium.cc
new file mode 100644
index 0000000..986aa92
--- /dev/null
+++ b/runtime/bin/vmservice_dartium.cc
@@ -0,0 +1,103 @@
+// Copyright (c) 2015, 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_dartium.h"
+
+#include "bin/builtin.h"
+#include "bin/dartutils.h"
+#include "bin/eventhandler.h"
+#include "bin/platform.h"
+#include "bin/thread.h"
+#include "bin/vmservice_impl.h"
+
+namespace dart {
+namespace bin {
+
+#define CHECK_RESULT(result)                                                   \
+  if (Dart_IsError(result)) {                                                  \
+    fprintf(stderr, "CHECK_RESULT failed: %s", Dart_GetError(result));         \
+    Dart_ExitScope();                                                          \
+    Dart_ShutdownIsolate();                                                    \
+    return 0;                                                                  \
+  }                                                                            \
+
+
+
+// snapshot_buffer points to a snapshot if we link in a snapshot otherwise
+// it is initialized to NULL.
+extern const uint8_t* snapshot_buffer;
+
+static const char* DEFAULT_VM_SERVICE_SERVER_IP = "127.0.0.1";
+static const int DEFAULT_VM_SERVICE_SERVER_PORT = 0;
+
+void VmServiceServer::Bootstrap() {
+  if (!Platform::Initialize()) {
+    fprintf(stderr, "Platform::Initialize() failed\n");
+  }
+  DartUtils::SetOriginalWorkingDirectory();
+  Thread::InitOnce();
+  EventHandler::Start();
+}
+
+
+Dart_Isolate VmServiceServer::CreateIsolate() {
+  ASSERT(snapshot_buffer != NULL);
+  // Create the isolate.
+  char* error = 0;
+  Dart_Isolate isolate = Dart_CreateIsolate(DART_VM_SERVICE_ISOLATE_NAME,
+                                            "main",
+                                            dart::bin::snapshot_buffer,
+                                            NULL,
+                                            &error);
+  if (!isolate) {
+    fprintf(stderr, "Dart_CreateIsolate failed: %s\n", error);
+    return 0;
+  }
+
+  Dart_EnterScope();
+  Builtin::SetNativeResolver(Builtin::kBuiltinLibrary);
+  Builtin::SetNativeResolver(Builtin::kIOLibrary);
+
+  Dart_Handle builtin_lib =
+      Builtin::LoadAndCheckLibrary(Builtin::kBuiltinLibrary);
+  CHECK_RESULT(builtin_lib);
+
+  Dart_Handle result;
+
+  // Prepare for script loading by setting up the 'print' and 'timer'
+  // closures and setting up 'package root' for URI resolution.
+  result = DartUtils::PrepareForScriptLoading(NULL, true, builtin_lib);
+  CHECK_RESULT(result);
+
+  ASSERT(Dart_IsServiceIsolate(isolate));
+  if (!VmService::Setup(DEFAULT_VM_SERVICE_SERVER_IP,
+                        DEFAULT_VM_SERVICE_SERVER_PORT)) {
+    fprintf(stderr,
+            "Vmservice::Setup failed: %s\n", VmService::GetErrorMessage());
+    isolate = NULL;
+  }
+  Dart_ExitScope();
+  Dart_ExitIsolate();
+  return isolate;
+}
+
+
+const char* VmServiceServer::GetServerIP() {
+  return VmService::GetServerIP();
+}
+
+
+intptr_t VmServiceServer::GetServerPort() {
+  return VmService::GetServerPort();
+}
+
+
+/* DISALLOW_ALLOCATION */
+void VmServiceServer::operator delete(void* pointer)  {
+  fprintf(stderr, "unreachable code\n");
+  abort();
+}
+
+}  // namespace bin
+}  // namespace dart
diff --git a/runtime/bin/vmservice_dartium.h b/runtime/bin/vmservice_dartium.h
new file mode 100644
index 0000000..95aa24c
--- /dev/null
+++ b/runtime/bin/vmservice_dartium.h
@@ -0,0 +1,38 @@
+// Copyright (c) 2015, 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_DARTIUM_H_
+#define BIN_VMSERVICE_DARTIUM_H_
+
+/* In order to avoid conflicts / issues with blink, no headers are included */
+
+#include <dart_api.h>
+#include <cstddef>
+
+namespace dart {
+namespace bin {
+
+class VmServiceServer {
+ public:
+  static void Bootstrap();
+  static Dart_Isolate CreateIsolate();
+
+  static const char* GetServerIP();
+  static intptr_t GetServerPort();
+
+/* DISALLOW_ALLOCATION */
+  void operator delete(void* pointer);
+ private:
+  void* operator new(size_t size);
+
+/* DISALLOW_IMPLICIT_CONSTRUCTORS */
+  VmServiceServer();
+  VmServiceServer(const VmServiceServer&);
+  void operator=(const VmServiceServer&);
+};
+
+}  // namespace bin
+}  // namespace dart
+
+#endif  // BIN_VMSERVICE_DARTIUM_H_
diff --git a/runtime/bin/vmservice_impl.cc b/runtime/bin/vmservice_impl.cc
index 18f06c1..1b9654b 100644
--- a/runtime/bin/vmservice_impl.cc
+++ b/runtime/bin/vmservice_impl.cc
@@ -11,6 +11,7 @@
 #include "bin/isolate_data.h"
 #include "bin/platform.h"
 #include "bin/thread.h"
+#include "bin/utils.h"
 #include "platform/json.h"
 
 namespace dart {
@@ -94,6 +95,32 @@
 }
 
 
+void NotifyServerState(Dart_NativeArguments args) {
+  Dart_EnterScope();
+  const char* ip_chars;
+  Dart_Handle ip_arg = Dart_GetNativeArgument(args, 0);
+  if (Dart_IsError(ip_arg)) {
+    VmService::SetServerIPAndPort("", 0);
+    Dart_ExitScope();
+    return;
+  }
+  Dart_Handle result = Dart_StringToCString(ip_arg, &ip_chars);
+  if (Dart_IsError(result)) {
+    VmService::SetServerIPAndPort("", 0);
+    Dart_ExitScope();
+    return;
+  }
+  Dart_Handle port_arg = Dart_GetNativeArgument(args, 1);
+  if (Dart_IsError(port_arg)) {
+    VmService::SetServerIPAndPort("", 0);
+    Dart_ExitScope();
+    return;
+  }
+  int64_t port = DartUtils::GetInt64ValueCheckRange(port_arg, 0, 65535);
+  VmService::SetServerIPAndPort(ip_chars, port);
+  Dart_ExitScope();
+}
+
 struct VmServiceIONativeEntry {
   const char* name;
   int num_arguments;
@@ -103,6 +130,7 @@
 
 static VmServiceIONativeEntry _VmServiceIONativeEntries[] = {
   {"VMServiceIO_TriggerResourceLoad", 0, TriggerResourceLoad},
+  {"VMServiceIO_NotifyServerState", 2, NotifyServerState},
 };
 
 
@@ -128,37 +156,36 @@
 
 
 const char* VmService::error_msg_ = NULL;
+char VmService::server_ip_[kServerIpStringBufferSize];
+intptr_t VmService::server_port_ = 0;
 
-bool VmService::Start(const char *server_ip, intptr_t server_port) {
-  bool r = _Start(server_ip, server_port);
-  if (!r) {
-    return r;
-  }
-  // Start processing messages in a new thread.
-  Thread::Start(ThreadMain, static_cast<uword>(NULL));
-  return true;
-}
+bool VmService::Setup(const char* server_ip, intptr_t server_port) {
+  Dart_Isolate isolate = Dart_CurrentIsolate();
+  ASSERT(isolate != NULL);
+  SetServerIPAndPort("", 0);
 
-
-bool VmService::_Start(const char *server_ip, intptr_t server_port) {
-  ASSERT(Dart_CurrentIsolate() == NULL);
-  Dart_Isolate isolate = Dart_GetServiceIsolate(NULL);
-  if (isolate == NULL) {
-    error_msg_ = "Dart_GetServiceIsolate failed.";
-    return false;
-  }
-  Dart_EnterIsolate(isolate);
-  Dart_EnterScope();
-  // Install our own library tag handler.
-  Dart_SetLibraryTagHandler(LibraryTagHandler);
   Dart_Handle result;
-  Dart_Handle library;
-  library = LoadScript(kVMServiceIOLibraryScriptResourceName);
-  // Expect a library.
+
+  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(NULL, true, builtin_lib);
+  SHUTDOWN_ON_ERROR(result);
+
+  // Load main script.
+  Dart_SetLibraryTagHandler(LibraryTagHandler);
+  Dart_Handle library = LoadScript(kVMServiceIOLibraryScriptResourceName);
   ASSERT(library != Dart_Null());
   SHUTDOWN_ON_ERROR(library);
+  result = Dart_SetNativeResolver(library, VmServiceIONativeResolver, NULL);
+  SHUTDOWN_ON_ERROR(result);
   result = Dart_FinalizeLoading(false);
-  ASSERT(!Dart_IsError(result));
+  SHUTDOWN_ON_ERROR(result);
+
+  // Make runnable.
   Dart_ExitScope();
   Dart_ExitIsolate();
   bool retval = Dart_IsolateMakeRunnable(isolate);
@@ -168,13 +195,13 @@
     error_msg_ = "Invalid isolate state - Unable to make it runnable.";
     return false;
   }
-
   Dart_EnterIsolate(isolate);
   Dart_EnterScope();
+
   library = Dart_RootLibrary();
-  result = Dart_SetNativeResolver(library, VmServiceIONativeResolver, NULL);
-  ASSERT(!Dart_IsError(result));
-  // Set requested TCP port.
+  SHUTDOWN_ON_ERROR(library);
+
+  // Set HTTP server state.
   DartUtils::SetStringField(library, "_ip", server_ip);
   // If we have a port specified, start the server immediately.
   bool auto_start = server_port >= 0;
@@ -183,33 +210,37 @@
     // port when the HTTP server is started.
     server_port = 0;
   }
-  // Set initial state.
   DartUtils::SetIntegerField(library, "_port", server_port);
-  Dart_SetField(library,
-                DartUtils::NewString("_autoStart"),
-                Dart_NewBoolean(auto_start));
-  // We cannot register for signals on windows.
+  result = Dart_SetField(library,
+                         DartUtils::NewString("_autoStart"),
+                         Dart_NewBoolean(auto_start));
+  SHUTDOWN_ON_ERROR(result);
+
+  // Are we running on Windows?
 #if defined(TARGET_OS_WINDOWS)
   Dart_Handle is_windows = Dart_True();
 #else
   Dart_Handle is_windows = Dart_False();
 #endif
-  Dart_SetField(library, DartUtils::NewString("_isWindows"), is_windows);
-
+  result =
+      Dart_SetField(library, DartUtils::NewString("_isWindows"), is_windows);
+  SHUTDOWN_ON_ERROR(result);
 
   // Get _getWatchSignalInternal from dart:io.
   Dart_Handle dart_io_str = Dart_NewStringFromCString(DartUtils::kIOLibURL);
+  SHUTDOWN_ON_ERROR(dart_io_str);
   Dart_Handle io_lib = Dart_LookupLibrary(dart_io_str);
+  SHUTDOWN_ON_ERROR(io_lib);
   Dart_Handle function_name =
       Dart_NewStringFromCString("_getWatchSignalInternal");
+  SHUTDOWN_ON_ERROR(function_name);
   Dart_Handle signal_watch = Dart_Invoke(io_lib, function_name, 0, NULL);
-  // Invoke main.
-  result = Dart_Invoke(library, DartUtils::NewString("main"), 1, &signal_watch);
-  SHUTDOWN_ON_ERROR(result);
-
-  Dart_ExitScope();
-  Dart_ExitIsolate();
-
+  SHUTDOWN_ON_ERROR(signal_watch);
+  Dart_Handle field_name = Dart_NewStringFromCString("_signalWatch");
+  SHUTDOWN_ON_ERROR(field_name);
+  result =
+      Dart_SetField(library, field_name, signal_watch);
+  SHUTDOWN_ON_ERROR(field_name);
   return true;
 }
 
@@ -219,6 +250,16 @@
 }
 
 
+void VmService::SetServerIPAndPort(const char* ip, intptr_t port) {
+  if (ip == NULL) {
+    ip = "";
+  }
+  strncpy(server_ip_, ip, kServerIpStringBufferSize);
+  server_ip_[kServerIpStringBufferSize - 1] = '\0';
+  server_port_ = port;
+}
+
+
 Dart_Handle VmService::GetSource(const char* name) {
   const intptr_t kBufferSize = 512;
   char buffer[kBufferSize];
@@ -337,20 +378,5 @@
 }
 
 
-void VmService::ThreadMain(uword parameters) {
-  ASSERT(Dart_CurrentIsolate() == NULL);
-  Dart_Isolate service_isolate = Dart_GetServiceIsolate(NULL);
-  Dart_EnterIsolate(service_isolate);
-  Dart_EnterScope();
-  Dart_Handle result = Dart_RunLoop();
-  if (Dart_IsError(result)) {
-    printf("Service exited with an error:\n%s\n", Dart_GetError(result));
-  }
-  Dart_ExitScope();
-  Dart_ExitIsolate();
-}
-
-
-
 }  // namespace bin
 }  // namespace dart
diff --git a/runtime/bin/vmservice_impl.h b/runtime/bin/vmservice_impl.h
index dde2036..e53c752 100644
--- a/runtime/bin/vmservice_impl.h
+++ b/runtime/bin/vmservice_impl.h
@@ -5,7 +5,7 @@
 #ifndef BIN_VMSERVICE_IMPL_H_
 #define BIN_VMSERVICE_IMPL_H_
 
-#include "bin/vmservice.h"
+#include "include/dart_api.h"
 
 #include "platform/globals.h"
 
@@ -14,13 +14,27 @@
 
 class VmService {
  public:
-  // Returns false if service could not be started.
-  static bool Start(const char *server_ip, intptr_t server_port);
+  static bool Setup(const char* server_ip, intptr_t server_port);
+
   // Error message if startup failed.
   static const char* GetErrorMessage();
 
+  // HTTP server's IP.
+  static const char* GetServerIP() {
+    return &server_ip_[0];
+  }
+
+  // HTTP server's port.
+  static intptr_t GetServerPort() {
+    return server_port_;
+  }
+
  private:
-  static bool _Start(const char *server_ip, intptr_t server_port);
+  static const intptr_t kServerIpStringBufferSize = 256;
+  friend void TriggerResourceLoad(Dart_NativeArguments args);
+  friend void NotifyServerState(Dart_NativeArguments args);
+
+  static void SetServerIPAndPort(const char* ip, intptr_t port);
   static Dart_Handle GetSource(const char* name);
   static Dart_Handle LoadScript(const char* name);
   static Dart_Handle LoadSource(Dart_Handle library, const char* name);
@@ -29,10 +43,10 @@
   static Dart_Handle LibraryTagHandler(Dart_LibraryTag tag, Dart_Handle library,
                                        Dart_Handle url);
 
-  friend void TriggerResourceLoad(Dart_NativeArguments args);
-
-  static void ThreadMain(uword parameters);
   static const char* error_msg_;
+  static char server_ip_[kServerIpStringBufferSize];
+  static intptr_t server_port_;
+
   DISALLOW_ALLOCATION();
   DISALLOW_IMPLICIT_CONSTRUCTORS(VmService);
 };
diff --git a/runtime/include/dart_api.h b/runtime/include/dart_api.h
index a22449d..f28b53a 100755
--- a/runtime/include/dart_api.h
+++ b/runtime/include/dart_api.h
@@ -737,34 +737,6 @@
                                                    void* callback_data,
                                                    char** error);
 
-
-/**
- * The service isolate creation and initialization callback function.
- *
- * This callback, provided by the embedder, is called when the vm
- * needs to create the service isolate. The callback should create an isolate
- * by calling Dart_CreateIsolate and prepare the isolate to be used as
- * the service isolate.
- *
- * When the function returns NULL, it is the responsibility of this
- * function to ensure that Dart_ShutdownIsolate has been called if
- * required.
- *
- * When the function returns NULL, the function should set *error to
- * a malloc-allocated buffer containing a useful error message.  The
- * caller of this function (the vm) will make sure that the buffer is
- * freed.
- *
- *
- * \param error A structure into which the embedder can place a
- *   C string containing an error message in the case of failures.
- *
- * \return The embedder returns NULL if the creation and
- *   initialization was not successful and the isolate if successful.
- */
-typedef Dart_Isolate (*Dart_ServiceIsolateCreateCalback)(void* callback_data,
-                                                         char** error);
-
 /**
  * An isolate interrupt callback function.
  *
@@ -873,8 +845,7 @@
     Dart_FileReadCallback file_read,
     Dart_FileWriteCallback file_write,
     Dart_FileCloseCallback file_close,
-    Dart_EntropySource entropy_source,
-    Dart_ServiceIsolateCreateCalback service_create);
+    Dart_EntropySource entropy_source);
 
 /**
  * Cleanup state in the VM before process termination.
@@ -1006,6 +977,19 @@
  * "pure" dart isolate. Implement and document. */
 
 /**
+ * Enables/Disables strict compilation for the current Isolate.
+ * Strict compilation includes:
+ * - type-checking
+ * - asserts
+ * - errors on bad types
+ * - errors on bad overrides
+ *
+ * This call requires there to be a current isolate, and requires that there has
+ * not yet been any compilation for the current Isolate.
+ */
+DART_EXPORT Dart_Handle Dart_IsolateSetStrictCompilation(bool value);
+
+/**
  * Creates a full snapshot of the current isolate heap.
  *
  * A full snapshot is a compact representation of the dart heap state and
@@ -2757,29 +2741,26 @@
  * =======
  */
 
+
+#define DART_VM_SERVICE_ISOLATE_NAME "vm-service"
+
 /**
- * Returns the Service isolate initialized and with the dart:vmservice library
- * loaded and booted.
+ * Returns true if isolate is the service isolate.
  *
- * This will call the embedder provided Dart_ServiceIsolateCreateCalback to
- * create the isolate.
+ * \param isolate An isolate
  *
- * After obtaining the service isolate the embedder specific glue code can
- * be loaded in and the isolate can be run by the embedder.
- *
- * NOTE: It is not safe to call this from multiple threads concurrently.
- *
- * \return Returns NULL if an error occurred.
+ * \return Returns true if 'isolate' is the service isolate.
  */
-DART_EXPORT Dart_Isolate Dart_GetServiceIsolate(void* callback_data);
+DART_EXPORT bool Dart_IsServiceIsolate(Dart_Isolate isolate);
 
 
 /**
- * Returns true if the service is enabled. False otherwise.
+ * Returns the port that script load requests should be sent on.
  *
- *  \return Returns true if service is running.
+ * \return Returns the port for load requests or ILLEGAL_PORT if the service
+ * isolate failed to startup or does not support load requests.
  */
-DART_EXPORT bool Dart_IsServiceRunning();
+DART_EXPORT Dart_Port Dart_ServiceWaitForLoadPort();
 
 
 /**
diff --git a/runtime/lib/async_patch.dart b/runtime/lib/async_patch.dart
new file mode 100644
index 0000000..682ee8b
--- /dev/null
+++ b/runtime/lib/async_patch.dart
@@ -0,0 +1,6 @@
+// Copyright (c) 2015, 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:_internal";
+
diff --git a/runtime/lib/async_sources.gypi b/runtime/lib/async_sources.gypi
index 896e508..4b906a6 100644
--- a/runtime/lib/async_sources.gypi
+++ b/runtime/lib/async_sources.gypi
@@ -5,6 +5,7 @@
 # This file contains all sources for the dart:async library.
 {
   'sources': [
+    'async_patch.dart',
     'deferred_load_patch.dart',
     'schedule_microtask_patch.dart',
     'timer_patch.dart',
diff --git a/runtime/lib/bigint.dart b/runtime/lib/bigint.dart
index a22bb51..07c6d80 100644
--- a/runtime/lib/bigint.dart
+++ b/runtime/lib/bigint.dart
@@ -38,91 +38,88 @@
  * and disclaimer.
  */
 
+// A big integer number is represented by a sign, an array of 32-bit unsigned
+// integers in little endian format, and a number of used digits in that array.
+// The code makes sure that an even number of digits is always accessible and
+// meaningful, so that pairs of digits can be processed as 64-bit unsigned
+// numbers on a 64-bit platform. This requires the initialization of a leading
+// zero if the number of used digits is odd.
 class _Bigint extends _IntegerImplementation implements int {
   // Bits per digit.
-  static const int DIGIT_BITS = 32;
-  static const int DIGIT_BASE = 1 << DIGIT_BITS;
-  static const int DIGIT_MASK = (1 << DIGIT_BITS) - 1;
+  static const int _DIGIT_BITS = 32;
+  static const int _DIGIT_BASE = 1 << _DIGIT_BITS;
+  static const int _DIGIT_MASK = (1 << _DIGIT_BITS) - 1;
 
   // Bits per half digit.
-  static const int DIGIT2_BITS = DIGIT_BITS >> 1;
-  static const int DIGIT2_MASK = (1 << DIGIT2_BITS) - 1;
-
-  // Allocate extra digits so the bigint can be reused.
-  static const int EXTRA_DIGITS = 4;
+  static const int _DIGIT2_BITS = _DIGIT_BITS >> 1;
+  static const int _DIGIT2_MASK = (1 << _DIGIT2_BITS) - 1;
 
   // Min and max of non bigint values.
-  static const int MIN_INT64 = (-1) << 63;
-  static const int MAX_INT64 = 0x7fffffffffffffff;
+  static const int _MIN_INT64 = (-1) << 63;
+  static const int _MAX_INT64 = 0x7fffffffffffffff;
 
   // Bigint constant values.
   // Note: Not declared as final in order to satisfy optimizer, which expects
   // constants to be in canonical form (Smi).
-  static _Bigint ONE = new _Bigint._fromInt(1);
-
-  // Digit conversion table for parsing.
-  static final Map<int, int> DIGIT_TABLE = _createDigitTable();
+  static _Bigint _MINUS_ONE = new _Bigint._fromInt(-1);
+  static _Bigint _ZERO = new _Bigint._fromInt(0);
+  static _Bigint _ONE = new _Bigint._fromInt(1);
 
   // Internal data structure.
-  // TODO(regis): Remove the 3 native setters below and provide a constructor
-  // taking all 3 field values, which is equivalent to making the fields final.
   bool get _neg native "Bigint_getNeg";
-  void set _neg(bool value) native "Bigint_setNeg";
   int get _used native "Bigint_getUsed";
-  void set _used(int value) native "Bigint_setUsed";
   Uint32List get _digits native "Bigint_getDigits";
-  void set _digits(Uint32List value) native "Bigint_setDigits";
 
-  // Factory returning an instance initialized to value 0.
-  factory _Bigint() native "Bigint_allocate";
+  // Factory returning an instance initialized with the given field values.
+  // The 'digits' array is first clamped and 'used' is reduced accordingly.
+  // A leading zero digit may be initialized to guarantee that digit pairs can
+  // be processed as 64-bit values on 64-bit platforms.
+  factory _Bigint(bool neg, int used, Uint32List digits)
+      native "Bigint_allocate";
 
   // Factory returning an instance initialized to an integer value no larger
   // than a Mint.
   factory _Bigint._fromInt(int i) {
     assert(i is! _Bigint);
-    bool neg;
+    var neg;
     var l, h;
     if (i < 0) {
       neg = true;
-      if (i == MIN_INT64) {
+      if (i == _MIN_INT64) {
         l = 0;
         h = 0x80000000;
       } else {
-        l = (-i) & DIGIT_MASK;
-        h = (-i) >> DIGIT_BITS;
+        l = (-i) & _DIGIT_MASK;
+        h = (-i) >> _DIGIT_BITS;
       }
     } else {
       neg = false;
-      l = i & DIGIT_MASK;
-      h = i >> DIGIT_BITS;
+      l = i & _DIGIT_MASK;
+      h = i >> _DIGIT_BITS;
     }
-    var result = new _Bigint();
-    result._ensureLength(2);
-    result._neg = neg;
-    result._used = 2;
-    result._digits[0] = l;
-    result._digits[1] = h;
-    result._clamp();
-    return result;
+    var digits = new Uint32List(2);
+    digits[0] = l;
+    digits[1] = h;
+    return new _Bigint(neg, 2, digits);
   }
 
-  // Create digit conversion table for parsing.
-  static Map<int, int> _createDigitTable() {
-    Map table = new HashMap();
-    int digit, value;
-    digit = "0".codeUnitAt(0);
-    for(value = 0; value <= 9; ++value) table[digit++] = value;
-    digit = "a".codeUnitAt(0);
-    for(value = 10; value < 36; ++value) table[digit++] = value;
-    digit = "A".codeUnitAt(0);
-    for(value = 10; value < 36; ++value) table[digit++] = value;
-    return table;
+  // Allocate an array of the given length (+1 for at least one leading zero
+  // digit if odd) and copy digits[from..to-1] starting at index 0, followed by
+  // leading zero digits.
+  static Uint32List _cloneDigits(Uint32List digits, int from, int to,
+                                 int length) {
+    length += length & 1;  // Even number of digits.
+    var r_digits = new Uint32List(length);
+    var n = to - from;
+    for (var i = 0; i < n; i++) {
+      r_digits[i] = digits[from + i];
+    }
+    return r_digits;
   }
 
   // Return most compact integer (i.e. possibly Smi or Mint).
-  // TODO(regis): Intrinsify.
   int _toValidInt() {
-    assert(DIGIT_BITS == 32);  // Otherwise this code needs to be revised.
+    assert(_DIGIT_BITS == 32);  // Otherwise this code needs to be revised.
     var used = _used;
     if (used == 0) return 0;
     var digits = _digits;
@@ -132,74 +129,37 @@
       if (digits[1] > 0x80000000) return this;
       if (digits[1] == 0x80000000) {
         if (digits[0] > 0) return this;
-        return MIN_INT64;
+        return _MIN_INT64;
       }
-      return -((digits[1] << DIGIT_BITS) | digits[0]);
+      return -((digits[1] << _DIGIT_BITS) | digits[0]);
     }
     if (digits[1] >= 0x80000000) return this;
-    return (digits[1] << DIGIT_BITS) | digits[0];
+    return (digits[1] << _DIGIT_BITS) | digits[0];
   }
 
   // Conversion from int to bigint.
   _Bigint _toBigint() => this;
 
-  // Make sure at least 'length' _digits are allocated.
-  // Copy existing and used _digits if reallocation is necessary.
-  // Avoid preserving _digits unnecessarily by calling this function with a
-  // meaningful _used field.
-  void _ensureLength(int length) {
-    length++;  // Account for leading zero for 64-bit processing.
-    var digits = _digits;
-    if (length > digits.length) {
-      var new_digits = new Uint32List(length + EXTRA_DIGITS);
-      _digits = new_digits;
-      var used = _used;
-      if (used > 0) {
-        var i = used + 1;  // Copy leading zero for 64-bit processing.
-        while (--i >= 0) {
-          new_digits[i] = digits[i];
-        }
-      }
+  // Return -this.
+  _Bigint _negate() {
+    var used = _used;
+    if (used == 0) {
+      return this;
     }
+    return new _Bigint(!_neg, used, _digits);
   }
 
-  // Clamp off excess high _digits.
-  void _clamp() {
-    var used = _used;
-    if (used > 0) {
-      var digits = _digits;
-      if (digits[used - 1] == 0) {
-        do {
-          --used;
-        } while (used > 0 && digits[used - 1] == 0);
-        _used = used;
-      }
-      digits[used] = 0;  // Set leading zero for 64-bit processing.
+  // Return abs(this).
+  _Bigint _abs() {
+    var neg = _neg;
+    if (!neg) {
+      return this;
     }
-  }
-
-  // Copy this to r.
-  void _copyTo(_Bigint r) {
-    var used = _used;
-    if (used > 0) {
-      // We could set r._used to 0 in order to avoid preserving digits. However,
-      // it would be wrong to do so if this === r. Checking is too expensive.
-      // This case does not occur in the current implementation, but we want to
-      // remain safe.
-      r._ensureLength(used);
-      var digits = _digits;
-      var r_digits = r._digits;
-      var i = used + 1;  // Copy leading zero for 64-bit processing.
-      while (--i >= 0) {
-        r_digits[i] = digits[i];
-      }
-    }
-    r._used = used;
-    r._neg = _neg;
+    return new _Bigint(!neg, _used, _digits);
   }
 
   // Return the bit length of digit x.
-  int _nbits(int x) {
+  static int _nbits(int x) {
     var r = 1, t;
     if ((t = x >> 16) != 0) { x = t; r += 16; }
     if ((t = x >> 8) != 0) { x = t; r += 8; }
@@ -209,162 +169,212 @@
     return r;
   }
 
-  // r = this << n*DIGIT_BITS.
-  void _dlShiftTo(int n, _Bigint r) {
+  // Return this << n*_DIGIT_BITS.
+  _Bigint _dlShift(int n) {
     var used = _used;
     if (used == 0) {
-      r._used = 0;
-      r._neg = false;
-      return;
+      return _ZERO;
     }
     var r_used = used + n;
-    r._ensureLength(r_used);
     var digits = _digits;
-    var r_digits = r._digits;
-    var i = used + 1;  // Copy leading zero for 64-bit processing.
+    var r_digits = new Uint32List(r_used + (r_used & 1));
+    var i = used;
     while (--i >= 0) {
       r_digits[i + n] = digits[i];
     }
+    return new _Bigint(_neg, r_used, r_digits);
+  }
+
+  // r_digits[0..r_used-1] = x_digits[0..x_used-1] << n*_DIGIT_BITS.
+  // Return r_used.
+  static int _dlShiftDigits(Uint32List x_digits, int x_used, int n,
+                            Uint32List r_digits) {
+    if (x_used == 0) {
+      return 0;
+    }
+    if (n == 0 && r_digits == x_digits) {
+      return x_used;
+    }
+    var r_used = x_used + n;
+    assert(r_digits.length >= r_used + (r_used & 1));
+    var i = x_used;
+    while (--i >= 0) {
+      r_digits[i + n] = x_digits[i];
+    }
     i = n;
     while (--i >= 0) {
       r_digits[i] = 0;
     }
-    r._used = r_used;
-    r._neg = _neg;
+    if (r_used.isOdd) {
+      r_digits[r_used] = 0;
+    }
+    return r_used;
   }
 
-  // r = this >> n*DIGIT_BITS.
-  void _drShiftTo(int n, _Bigint r) {
+  // Return this >> n*_DIGIT_BITS.
+  _Bigint _drShift(int n) {
     var used = _used;
     if (used == 0) {
-      r._used = 0;
-      r._neg = false;
-      return;
+      return _ZERO;
     }
     var r_used = used - n;
     if (r_used <= 0) {
-      if (_neg) {
-        // Set r to -1.
-        r._used = 0;  // No digits to preserve.
-        r._ensureLength(1);
-        r._neg = true;
-        r._used = 1;
-        r._digits[0] = 1;
-        r._digits[1] = 0;  // Set leading zero for 64-bit processing.
-      } else {
-        // Set r to 0.
-        r._neg = false;
-        r._used = 0;
-      }
-      return;
+      return _neg ? _MINUS_ONE : _ZERO;
     }
-    r._ensureLength(r_used);
     var digits = _digits;
-    var r_digits = r._digits;
-    for (var i = n; i < used + 1; i++) {  // Copy leading zero for 64-bit proc.
+    var r_digits = new Uint32List(r_used + (r_used & 1));
+    for (var i = n; i < used; i++) {
       r_digits[i - n] = digits[i];
     }
-    r._used = r_used;
-    r._neg = _neg;
+    var r = new _Bigint(_neg, r_used, r_digits);
     if (_neg) {
       // Round down if any bit was shifted out.
       for (var i = 0; i < n; i++) {
         if (digits[i] != 0) {
-          r._subTo(ONE, r);
-          break;
+          return r._sub(_ONE);
         }
       }
     }
+    return r;
   }
 
-  // r = this << n.
-  void _lShiftTo(int n, _Bigint r) {
-    var ds = n ~/ DIGIT_BITS;
-    var bs = n % DIGIT_BITS;
-    if (bs == 0) {
-      _dlShiftTo(ds, r);
-      return;
+  // r_digits[0..r_used-1] = x_digits[0..x_used-1] >> n*_DIGIT_BITS.
+  // Return r_used.
+  static int _drShiftDigits(Uint32List x_digits, int x_used, int n,
+                            Uint32List r_digits) {
+    var r_used = x_used - n;
+    if (r_used <= 0) {
+      return 0;
     }
-    var cbs = DIGIT_BITS - bs;
+    assert(r_digits.length >= r_used + (r_used & 1));
+    for (var i = n; i < x_used; i++) {
+      r_digits[i - n] = x_digits[i];
+    }
+    if (r_used.isOdd) {
+      r_digits[r_used] = 0;
+    }
+    return r_used;
+  }
+
+  // Return this << n.
+  _Bigint _lShift(int n) {
+    var ds = n ~/ _DIGIT_BITS;
+    var bs = n % _DIGIT_BITS;
+    if (bs == 0) {
+      return _dlShift(ds);
+    }
+    var cbs = _DIGIT_BITS - bs;
     var bm = (1 << cbs) - 1;
     var r_used = _used + ds + 1;
-    r._ensureLength(r_used);
     var digits = _digits;
-    var r_digits = r._digits;
+    var r_digits = new Uint32List(r_used + (r_used & 1));
     var c = 0;
     var i = _used;
     while (--i >= 0) {
       r_digits[i + ds + 1] = (digits[i] >> cbs) | c;
       c = (digits[i] & bm) << bs;
     }
+    r_digits[ds] = c;
+    return new _Bigint(_neg, r_used, r_digits);
+  }
+
+  // r_digits[0..r_used-1] = x_digits[0..x_used-1] << n.
+  // Return r_used.
+  static int _lShiftDigits(Uint32List x_digits, int x_used, int n,
+                           Uint32List r_digits) {
+    var ds = n ~/ _DIGIT_BITS;
+    var bs = n % _DIGIT_BITS;
+    if (bs == 0) {
+      return _dlShiftDigits(x_digits, x_used, ds, r_digits);
+    }
+    var cbs = _DIGIT_BITS - bs;
+    var bm = (1 << cbs) - 1;
+    var r_used = x_used + ds + 1;
+    assert(r_digits.length >= r_used + (r_used & 1));
+    var c = 0;
+    var i = x_used;
+    while (--i >= 0) {
+      r_digits[i + ds + 1] = (x_digits[i] >> cbs) | c;
+      c = (x_digits[i] & bm) << bs;
+    }
+    r_digits[ds] = c;
     i = ds;
     while (--i >= 0) {
       r_digits[i] = 0;
     }
-    r_digits[ds] = c;
-    r._used = r_used;
-    r._neg = _neg;
-    r._clamp();
+    if (r_used.isOdd) {
+      r_digits[r_used] = 0;
+    }
+    return r_used;
   }
 
-  // r = this >> n.
-  void _rShiftTo(int n, _Bigint r) {
-    var ds = n ~/ DIGIT_BITS;
-    var bs = n % DIGIT_BITS;
+  // Return this >> n.
+  _Bigint _rShift(int n) {
+    var ds = n ~/ _DIGIT_BITS;
+    var bs = n % _DIGIT_BITS;
     if (bs == 0) {
-      _drShiftTo(ds, r);
-      return;
+      return _drShift(ds);
     }
     var r_used = _used - ds;
     if (r_used <= 0) {
-      if (_neg) {
-        // Set r to -1.
-        r._neg = true;
-        r._used = 0;  // No digits to preserve.
-        r._ensureLength(1);
-        r._used = 1;
-        r._digits[0] = 1;
-        r._digits[1] = 0;  // Set leading zero for 64-bit processing.
-      } else {
-        // Set r to 0.
-        r._neg = false;
-        r._used = 0;
-      }
-      return;
+      return _neg ? _MINUS_ONE : _ZERO;
     }
-    var cbs = DIGIT_BITS - bs;
+    var cbs = _DIGIT_BITS - bs;
     var bm = (1 << bs) - 1;
-    r._ensureLength(r_used);
     var digits = _digits;
-    var r_digits = r._digits;
+    var r_digits = new Uint32List(r_used + (r_used & 1));
     r_digits[0] = digits[ds] >> bs;
     var used = _used;
     for (var i = ds + 1; i < used; i++) {
       r_digits[i - ds - 1] |= (digits[i] & bm) << cbs;
       r_digits[i - ds] = digits[i] >> bs;
     }
-    r._neg = _neg;
-    r._used = r_used;
-    r._clamp();
+    var r = new _Bigint(_neg, r_used, r_digits);
     if (_neg) {
       // Round down if any bit was shifted out.
       if ((digits[ds] & bm) != 0) {
-        r._subTo(ONE, r);
-        return;
+        return r._sub(_ONE);
       }
       for (var i = 0; i < ds; i++) {
         if (digits[i] != 0) {
-          r._subTo(ONE, r);
-          return;
+          return r._sub(_ONE);
         }
       }
     }
+    return r;
+  }
+
+  // r_digits[0..r_used-1] = x_digits[0..x_used-1] >> n.
+  // Return r_used.
+  static int _rShiftDigits(Uint32List x_digits, int x_used, int n,
+                           Uint32List r_digits) {
+    var ds = n ~/ _DIGIT_BITS;
+    var bs = n % _DIGIT_BITS;
+    if (bs == 0) {
+      return _drShiftDigits(x_digits, x_used, ds, r_digits);
+    }
+    var r_used = x_used - ds;
+    if (r_used <= 0) {
+      return 0;
+    }
+    var cbs = _DIGIT_BITS - bs;
+    var bm = (1 << bs) - 1;
+    assert(r_digits.length >= r_used + (r_used & 1));
+    r_digits[0] = x_digits[ds] >> bs;
+    for (var i = ds + 1; i < x_used; i++) {
+      r_digits[i - ds - 1] |= (x_digits[i] & bm) << cbs;
+      r_digits[i - ds] = x_digits[i] >> bs;
+    }
+    if (r_used.isOdd) {
+      r_digits[r_used] = 0;
+    }
+    return r_used;
   }
 
   // Return 0 if abs(this) == abs(a).
   // Return a positive number if abs(this) > abs(a).
   // Return a negative number if abs(this) < abs(a).
-  int _absCompareTo(_Bigint a) {
+  int _absCompare(_Bigint a) {
     var r = _used - a._used;
     if (r == 0) {
       var i = _used;
@@ -378,124 +388,133 @@
   // Return 0 if this == a.
   // Return a positive number if this > a.
   // Return a negative number if this < a.
-  int _compareTo(_Bigint a) {
-    var r;
+  int _compare(_Bigint a) {
     if (_neg == a._neg) {
-      r = _absCompareTo(a);
-      if (_neg) {
-        r = -r;
-      }
-    } else if (_neg) {
-      r = -1;
-    } else {
-      r = 1;
+      var r = _absCompare(a);
+      return _neg ? -r : r;
+    }
+    return _neg ? -1 : 1;
+  }
+
+  // Compare digits[0..used-1] with a_digits[0..a_used-1].
+  // Return 0 if equal.
+  // Return a positive number if larger.
+  // Return a negative number if smaller.
+  static int _compareDigits(Uint32List digits, int used,
+                            Uint32List a_digits, int a_used) {
+    var r = used - a_used;
+    if (r == 0) {
+      var i = a_used;
+      while (--i >= 0 && (r = digits[i] - a_digits[i]) == 0);
     }
     return r;
   }
 
   // r_digits[0..used] = digits[0..used-1] + a_digits[0..a_used-1].
   // used >= a_used > 0.
+  // Note: Intrinsics on 64-bit platforms process digit pairs at even indices.
   static void _absAdd(Uint32List digits, int used,
                       Uint32List a_digits, int a_used,
                       Uint32List r_digits) {
+    assert(used >= a_used && a_used > 0);
+    // Verify that digit pairs are accessible for 64-bit processing.
+    assert(digits.length > ((used - 1) | 1));
+    assert(a_digits.length > ((a_used - 1) | 1));
+    assert(r_digits.length > (used | 1));
     var c = 0;
     for (var i = 0; i < a_used; i++) {
       c += digits[i] + a_digits[i];
-      r_digits[i] = c & DIGIT_MASK;
-      c >>= DIGIT_BITS;
+      r_digits[i] = c & _DIGIT_MASK;
+      c >>= _DIGIT_BITS;
     }
     for (var i = a_used; i < used; i++) {
       c += digits[i];
-      r_digits[i] = c & DIGIT_MASK;
-      c >>= DIGIT_BITS;
+      r_digits[i] = c & _DIGIT_MASK;
+      c >>= _DIGIT_BITS;
     }
     r_digits[used] = c;
   }
 
   // r_digits[0..used-1] = digits[0..used-1] - a_digits[0..a_used-1].
   // used >= a_used > 0.
+  // Note: Intrinsics on 64-bit platforms process digit pairs at even indices.
   static void _absSub(Uint32List digits, int used,
                       Uint32List a_digits, int a_used,
                       Uint32List r_digits) {
+    assert(used >= a_used && a_used > 0);
+    // Verify that digit pairs are accessible for 64-bit processing.
+    assert(digits.length > ((used - 1) | 1));
+    assert(a_digits.length > ((a_used - 1) | 1));
+    assert(r_digits.length > ((used - 1) | 1));
     var c = 0;
     for (var i = 0; i < a_used; i++) {
       c += digits[i] - a_digits[i];
-      r_digits[i] = c & DIGIT_MASK;
-      c >>= DIGIT_BITS;
+      r_digits[i] = c & _DIGIT_MASK;
+      c >>= _DIGIT_BITS;
     }
     for (var i = a_used; i < used; i++) {
       c += digits[i];
-      r_digits[i] = c & DIGIT_MASK;
-      c >>= DIGIT_BITS;
+      r_digits[i] = c & _DIGIT_MASK;
+      c >>= _DIGIT_BITS;
     }
   }
 
-  // r = abs(this) + abs(a).
-  void _absAddTo(_Bigint a, _Bigint r) {
+  // Return abs(this) + abs(a) with sign set according to neg.
+  _Bigint _absAddSetSign(_Bigint a, bool neg) {
     var used = _used;
     var a_used = a._used;
     if (used < a_used) {
-      a._absAddTo(this, r);
-      return;
+      return a._absAddSetSign(this, neg);
     }
     if (used == 0) {
-      // Set r to 0.
-      r._neg = false;
-      r._used = 0;
-      return;
+      assert(!neg);
+      return _ZERO;
     }
     if (a_used == 0) {
-      _copyTo(r);
-      return;
+      return _neg == neg ? this : this._negate();
     }
-    r._ensureLength(used + 1);
-    _absAdd(_digits, used, a._digits, a_used, r._digits);
-    r._used = used + 1;
-    r._clamp();
+    var r_used = used + 1;
+    var r_digits = new Uint32List(r_used + (r_used & 1));
+    _absAdd(_digits, used, a._digits, a_used, r_digits);
+    return new _Bigint(neg, r_used, r_digits);
   }
 
-  // r = abs(this) - abs(a), with abs(this) >= abs(a).
-  void _absSubTo(_Bigint a, _Bigint r) {
-    assert(_absCompareTo(a) >= 0);
+  // Return abs(this) - abs(a) with sign set according to neg.
+  // Requirement: abs(this) >= abs(a).
+  _Bigint _absSubSetSign(_Bigint a, bool neg) {
+    assert(_absCompare(a) >= 0);
     var used = _used;
     if (used == 0) {
-      // Set r to 0.
-      r._neg = false;
-      r._used = 0;
-      return;
+      assert(!neg);
+      return _ZERO;
     }
     var a_used = a._used;
     if (a_used == 0) {
-      _copyTo(r);
-      return;
+      return _neg == neg ? this : this._negate();
     }
-    r._ensureLength(used);
-    _absSub(_digits, used, a._digits, a_used, r._digits);
-    r._used = used;
-    r._clamp();
+    var r_digits = new Uint32List(used + (used & 1));
+    _absSub(_digits, used, a._digits, a_used, r_digits);
+    return new _Bigint(neg, used, r_digits);
   }
 
-  // r = abs(this) & abs(a).
-  void _absAndTo(_Bigint a, _Bigint r) {
+  // Return abs(this) & abs(a) with sign set according to neg.
+  _Bigint _absAndSetSign(_Bigint a, bool neg) {
     var r_used = (_used < a._used) ? _used : a._used;
-    r._ensureLength(r_used);
     var digits = _digits;
     var a_digits = a._digits;
-    var r_digits = r._digits;
+    var r_digits = new Uint32List(r_used + (r_used & 1));
     for (var i = 0; i < r_used; i++) {
       r_digits[i] = digits[i] & a_digits[i];
     }
-    r._used = r_used;
-    r._clamp();
+    return new _Bigint(neg, r_used, r_digits);
   }
 
-  // r = abs(this) &~ abs(a).
-  void _absAndNotTo(_Bigint a, _Bigint r) {
+  // Return abs(this) &~ abs(a) with sign set according to neg.
+  _Bigint _absAndNotSetSign(_Bigint a, bool neg) {
     var r_used = _used;
-    r._ensureLength(r_used);
     var digits = _digits;
     var a_digits = a._digits;
-    var r_digits = r._digits;
+    var r_digits = new Uint32List(r_used + (r_used & 1));
     var m = (r_used < a._used) ? r_used : a._used;
     for (var i = 0; i < m; i++) {
       r_digits[i] = digits[i] &~ a_digits[i];
@@ -503,19 +522,17 @@
     for (var i = m; i < r_used; i++) {
       r_digits[i] = digits[i];
     }
-    r._used = r_used;
-    r._clamp();
+    return new _Bigint(neg, r_used, r_digits);
   }
 
-  // r = abs(this) | abs(a).
-  void _absOrTo(_Bigint a, _Bigint r) {
+  // Return abs(this) | abs(a) with sign set according to neg.
+  _Bigint _absOrSetSign(_Bigint a, bool neg) {
     var used = _used;
     var a_used = a._used;
     var r_used = (used > a_used) ? used : a_used;
-    r._ensureLength(r_used);
     var digits = _digits;
     var a_digits = a._digits;
-    var r_digits = r._digits;
+    var r_digits = new Uint32List(r_used + (r_used & 1));
     var l, m;
     if (used < a_used) {
       l = a;
@@ -531,19 +548,17 @@
     for (var i = m; i < r_used; i++) {
       r_digits[i] = l_digits[i];
     }
-    r._used = r_used;
-    r._clamp();
+    return new _Bigint(neg, r_used, r_digits);
   }
 
-  // r = abs(this) ^ abs(a).
-  void _absXorTo(_Bigint a, _Bigint r) {
+  // Return abs(this) ^ abs(a) with sign set according to neg.
+  _Bigint _absXorSetSign(_Bigint a, bool neg) {
     var used = _used;
     var a_used = a._used;
     var r_used = (used > a_used) ? used : a_used;
-    r._ensureLength(r_used);
     var digits = _digits;
     var a_digits = a._digits;
-    var r_digits = r._digits;
+    var r_digits = new Uint32List(r_used + (r_used & 1));
     var l, m;
     if (used < a_used) {
       l = a;
@@ -559,29 +574,22 @@
     for (var i = m; i < r_used; i++) {
       r_digits[i] = l_digits[i];
     }
-    r._used = r_used;
-    r._clamp();
+    return new _Bigint(neg, r_used, r_digits);
   }
 
-  // Return r = this & a.
-  _Bigint _andTo(_Bigint a, _Bigint r) {
+  // Return this & a.
+  _Bigint _and(_Bigint a) {
     if (_neg == a._neg) {
       if (_neg) {
         // (-this) & (-a) == ~(this-1) & ~(a-1)
         //                == ~((this-1) | (a-1))
         //                == -(((this-1) | (a-1)) + 1)
-        _Bigint t1 = new _Bigint();
-        _absSubTo(ONE, t1);
-        _Bigint a1 = new _Bigint();
-        a._absSubTo(ONE, a1);
-        t1._absOrTo(a1, r);
-        r._absAddTo(ONE, r);
-        r._neg = true;  // r cannot be zero if this and a are negative.
-        return r;
+        _Bigint t1 = _absSubSetSign(_ONE, true);
+        _Bigint a1 = a._absSubSetSign(_ONE, true);
+        // Result cannot be zero if this and a are negative.
+        return t1._absOrSetSign(a1, true)._absAddSetSign(_ONE, true);
       }
-      _absAndTo(a, r);
-      r._neg = false;
-      return r;
+      return _absAndSetSign(a, false);
     }
     // _neg != a._neg
     var p, n;
@@ -593,71 +601,50 @@
       n = a;
     }
     // p & (-n) == p & ~(n-1) == p &~ (n-1)
-    _Bigint n1 = new _Bigint();
-    n._absSubTo(ONE, n1);
-    p._absAndNotTo(n1, r);
-    r._neg = false;
-    return r;
+    _Bigint n1 = n._absSubSetSign(_ONE, false);
+    return p._absAndNotSetSign(n1, false);
   }
 
-  // Return r = this &~ a.
-  _Bigint _andNotTo(_Bigint a, _Bigint r) {
+  // Return this &~ a.
+  _Bigint _andNot(_Bigint a) {
     if (_neg == a._neg) {
       if (_neg) {
         // (-this) &~ (-a) == ~(this-1) &~ ~(a-1)
         //                 == ~(this-1) & (a-1)
         //                 == (a-1) &~ (this-1)
-        _Bigint t1 = new _Bigint();
-        _absSubTo(ONE, t1);
-        _Bigint a1 = new _Bigint();
-        a._absSubTo(ONE, a1);
-        a1._absAndNotTo(t1, r);
-        r._neg = false;
-        return r;
+        _Bigint t1 = _absSubSetSign(_ONE, true);
+        _Bigint a1 = a._absSubSetSign(_ONE, true);
+        return a1._absAndNotSetSign(t1, false);
       }
-      _absAndNotTo(a, r);
-      r._neg = false;
-      return r;
+      return _absAndNotSetSign(a, false);
     }
     if (_neg) {
       // (-this) &~ a == ~(this-1) &~ a
       //              == ~(this-1) & ~a
       //              == ~((this-1) | a)
       //              == -(((this-1) | a) + 1)
-      _Bigint t1 = new _Bigint();
-      _absSubTo(ONE, t1);
-      t1._absOrTo(a, r);
-      r._absAddTo(ONE, r);
-      r._neg = true;  // r cannot be zero if this is negative and a is positive.
-      return r;
+      _Bigint t1 = _absSubSetSign(_ONE, true);
+      // Result cannot be zero if this is negative and a is positive.
+      return t1._absOrSetSign(a, true)._absAddSetSign(_ONE, true);
     }
     // this &~ (-a) == this &~ ~(a-1) == this & (a-1)
-    _Bigint a1 = new _Bigint();
-    a._absSubTo(ONE, a1);
-    _absAndTo(a1, r);
-    r._neg = false;
-    return r;
+    _Bigint a1 = a._absSubSetSign(_ONE, true);
+    return _absAndSetSign(a1, false);
   }
 
-  // Return r = this | a.
-  _Bigint _orTo(_Bigint a, _Bigint r) {
+  // Return this | a.
+  _Bigint _or(_Bigint a) {
     if (_neg == a._neg) {
       if (_neg) {
         // (-this) | (-a) == ~(this-1) | ~(a-1)
         //                == ~((this-1) & (a-1))
         //                == -(((this-1) & (a-1)) + 1)
-        _Bigint t1 = new _Bigint();
-        _absSubTo(ONE, t1);
-        _Bigint a1 = new _Bigint();
-        a._absSubTo(ONE, a1);
-        t1._absAndTo(a1, r);
-        r._absAddTo(ONE, r);
-        r._neg = true;  // r cannot be zero if this and a are negative.
-        return r;
+        _Bigint t1 = _absSubSetSign(_ONE, true);
+        _Bigint a1 = a._absSubSetSign(_ONE, true);
+        // Result cannot be zero if this and a are negative.
+        return t1._absAndSetSign(a1, true)._absAddSetSign(_ONE, true);
       }
-      _absOrTo(a, r);
-      r._neg = false;
-      return r;
+      return _absOrSetSign(a, false);
     }
     // _neg != a._neg
     var p, n;
@@ -669,30 +656,21 @@
       n = a;
     }
     // p | (-n) == p | ~(n-1) == ~((n-1) &~ p) == -(~((n-1) &~ p) + 1)
-    _Bigint n1 = new _Bigint();
-    n._absSubTo(ONE, n1);
-    n1._absAndNotTo(p, r);
-    r._absAddTo(ONE, r);
-    r._neg = true;  // r cannot be zero if only one of this or a is negative.
-    return r;
+    _Bigint n1 = n._absSubSetSign(_ONE, true);
+    // Result cannot be zero if only one of this or a is negative.
+    return n1._absAndNotSetSign(p, true)._absAddSetSign(_ONE, true);
   }
 
-  // Return r = this ^ a.
-  _Bigint _xorTo(_Bigint a, _Bigint r) {
+  // Return this ^ a.
+  _Bigint _xor(_Bigint a) {
     if (_neg == a._neg) {
       if (_neg) {
         // (-this) ^ (-a) == ~(this-1) ^ ~(a-1) == (this-1) ^ (a-1)
-        _Bigint t1 = new _Bigint();
-        _absSubTo(ONE, t1);
-        _Bigint a1 = new _Bigint();
-        a._absSubTo(ONE, a1);
-        t1._absXorTo(a1, r);
-        r._neg = false;
-        return r;
+        _Bigint t1 = _absSubSetSign(_ONE, true);
+        _Bigint a1 = a._absSubSetSign(_ONE, true);
+        return t1._absXorSetSign(a1, false);
       }
-      _absXorTo(a, r);
-      r._neg = false;
-      return r;
+      return _absXorSetSign(a, false);
     }
     // _neg != a._neg
     var p, n;
@@ -704,68 +682,52 @@
       n = a;
     }
     // p ^ (-n) == p ^ ~(n-1) == ~(p ^ (n-1)) == -((p ^ (n-1)) + 1)
-    _Bigint n1 = new _Bigint();
-    n._absSubTo(ONE, n1);
-    p._absXorTo(n1, r);
-    r._absAddTo(ONE, r);
-    r._neg = true;  // r cannot be zero if only one of this or a is negative.
-    return r;
+    _Bigint n1 = n._absSubSetSign(_ONE, true);
+    // Result cannot be zero if only one of this or a is negative.
+    return p._absXorSetSign(n1, true)._absAddSetSign(_ONE, true);
   }
 
-  // Return r = ~this.
-  _Bigint _notTo(_Bigint r) {
+  // Return ~this.
+  _Bigint _not() {
     if (_neg) {
       // ~(-this) == ~(~(this-1)) == this-1
-      _absSubTo(ONE, r);
-      r._neg = false;
-      return r;
+      return _absSubSetSign(_ONE, false);
     }
     // ~this == -this-1 == -(this+1)
-    _absAddTo(ONE, r);
-    r._neg = true;  // r cannot be zero if this is positive.
-    return r;
+    // Result cannot be zero if this is positive.
+    return _absAddSetSign(_ONE, true);
   }
 
-  // Return r = this + a.
-  _Bigint _addTo(_Bigint a, _Bigint r) {
-    var r_neg = _neg;
-    if (_neg == a._neg) {
+  // Return this + a.
+  _Bigint _add(_Bigint a) {
+    var neg = _neg;
+    if (neg == a._neg) {
       // this + a == this + a
       // (-this) + (-a) == -(this + a)
-      _absAddTo(a, r);
-    } else {
-      // this + (-a) == this - a == -(this - a)
-      // (-this) + a == a - this == -(this - a)
-      if (_absCompareTo(a) >= 0) {
-        _absSubTo(a, r);
-      } else {
-        r_neg = !r_neg;
-        a._absSubTo(this, r);
-      }
+      return _absAddSetSign(a, neg);
     }
-  	r._neg = r_neg;
-    return r;
+    // this + (-a) == this - a == -(this - a)
+    // (-this) + a == a - this == -(this - a)
+    if (_absCompare(a) >= 0) {
+      return _absSubSetSign(a, neg);
+    }
+    return a._absSubSetSign(this, !neg);
   }
 
-  // Return r = this - a.
-  _Bigint _subTo(_Bigint a, _Bigint r) {
-  	var r_neg = _neg;
-    if (_neg != a._neg) {
-  		// this - (-a) == this + a
-  		// (-this) - a == -(this + a)
-      _absAddTo(a, r);
-  	} else {
-  		// this - a == this - a == -(this - a)
-  		// (-this) - (-a) == a - this == -(this - a)
-      if (_absCompareTo(a) >= 0) {
-        _absSubTo(a, r);
-  		} else {
-        r_neg = !r_neg;
-        a._absSubTo(this, r);
-      }
+  // Return this - a.
+  _Bigint _sub(_Bigint a) {
+    var neg = _neg;
+    if (neg != a._neg) {
+      // this - (-a) == this + a
+      // (-this) - a == -(this + a)
+      return _absAddSetSign(a, neg);
     }
-  	r._neg = r_neg;
-    return r;
+    // this - a == this - a == -(this - a)
+    // (-this) - (-a) == a - this == -(this - a)
+    if (_absCompare(a) >= 0) {
+      return _absSubSetSign(a, neg);
+    }
+    return a._absSubSetSign(this, !neg);
   }
 
   // Multiply and accumulate.
@@ -776,32 +738,35 @@
   // Operation:
   //   a_digits[j..j+n] += x_digits[xi]*m_digits[i..i+n-1].
   //   return 1.
-  // Note: intrinsics on 64-bit platform may process a digit pair:
-  //   a_digits[j..j+n] += x_digits[xi..xi+1]*m_digits[i..i+n-1].
-  //   return 2.
+  // Note: Intrinsics on 64-bit platforms process digit pairs at even indices
+  //   and return 2.
   static int _mulAdd(Uint32List x_digits, int xi,
                      Uint32List m_digits, int i,
                      Uint32List a_digits, int j, int n) {
+    // Verify that digit pairs are accessible for 64-bit processing.
+    assert(x_digits.length > (xi | 1));
+    assert(m_digits.length > ((i + n - 1) | 1));
+    assert(a_digits.length > ((j + n) | 1));
     int x = x_digits[xi];
     if (x == 0) {
       // No-op if x is 0.
       return 1;
     }
     int c = 0;
-    int xl = x & DIGIT2_MASK;
-    int xh = x >> DIGIT2_BITS;
+    int xl = x & _DIGIT2_MASK;
+    int xh = x >> _DIGIT2_BITS;
     while (--n >= 0) {
-      int l = m_digits[i] & DIGIT2_MASK;
-      int h = m_digits[i++] >> DIGIT2_BITS;
+      int l = m_digits[i] & _DIGIT2_MASK;
+      int h = m_digits[i++] >> _DIGIT2_BITS;
       int m = xh*l + h*xl;
-      l = xl*l + ((m & DIGIT2_MASK) << DIGIT2_BITS) + a_digits[j] + c;
-      c = (l >> DIGIT_BITS) + (m >> DIGIT2_BITS) + xh*h;
-      a_digits[j++] = l & DIGIT_MASK;
+      l = xl*l + ((m & _DIGIT2_MASK) << _DIGIT2_BITS) + a_digits[j] + c;
+      c = (l >> _DIGIT_BITS) + (m >> _DIGIT2_BITS) + xh*h;
+      a_digits[j++] = l & _DIGIT_MASK;
     }
     while (c != 0) {
       int l = a_digits[j] + c;
-      c = l >> DIGIT_BITS;
-      a_digits[j++] = l & DIGIT_MASK;
+      c = l >> _DIGIT_BITS;
+      a_digits[j++] = l & _DIGIT_MASK;
     }
     return 1;
   }
@@ -814,39 +779,40 @@
   //   a_digits[2*i..i+used-1] += x_digits[i]*x_digits[i] +
   //                              2*x_digits[i]*x_digits[i+1..used-1].
   //   return 1.
-  // Note: intrinsics on 64-bit platform may process a digit pair:
-  //   a_digits[2*i..i+used-1] += x_digits[i..i+1]*x_digits[i..i+1] +
-  //                              2*x_digits[i..i+1]*x_digits[i+2..used-1].
-  //   return 2.
+  // Note: Intrinsics on 64-bit platforms process digit pairs at even indices
+  //   and return 2.
   static int _sqrAdd(Uint32List x_digits, int i,
                      Uint32List a_digits, int used) {
+    // Verify that digit pairs are accessible for 64-bit processing.
+    assert(x_digits.length > ((used - 1) | 1));
+    assert(a_digits.length > ((i + used - 1) | 1));
     int x = x_digits[i];
     if (x == 0) return 1;
     int j = 2*i;
     int c = 0;
-    int xl = x & DIGIT2_MASK;
-    int xh = x >> DIGIT2_BITS;
+    int xl = x & _DIGIT2_MASK;
+    int xh = x >> _DIGIT2_BITS;
     int m = 2*xh*xl;
-    int l = xl*xl + ((m & DIGIT2_MASK) << DIGIT2_BITS) + a_digits[j];
-    c = (l >> DIGIT_BITS) + (m >> DIGIT2_BITS) + xh*xh;
-    a_digits[j] = l & DIGIT_MASK;
+    int l = xl*xl + ((m & _DIGIT2_MASK) << _DIGIT2_BITS) + a_digits[j];
+    c = (l >> _DIGIT_BITS) + (m >> _DIGIT2_BITS) + xh*xh;
+    a_digits[j] = l & _DIGIT_MASK;
     x <<= 1;
-    xl = x & DIGIT2_MASK;
-    xh = x >> DIGIT2_BITS;
+    xl = x & _DIGIT2_MASK;
+    xh = x >> _DIGIT2_BITS;
     int n = used - i - 1;
     int k = i + 1;
     j++;
     while (--n >= 0) {
-      int l = x_digits[k] & DIGIT2_MASK;
-      int h = x_digits[k++] >> DIGIT2_BITS;
+      int l = x_digits[k] & _DIGIT2_MASK;
+      int h = x_digits[k++] >> _DIGIT2_BITS;
       int m = xh*l + h*xl;
-      l = xl*l + ((m & DIGIT2_MASK) << DIGIT2_BITS) + a_digits[j] + c;
-      c = (l >> DIGIT_BITS) + (m >> DIGIT2_BITS) + xh*h;
-      a_digits[j++] = l & DIGIT_MASK;
+      l = xl*l + ((m & _DIGIT2_MASK) << _DIGIT2_BITS) + a_digits[j] + c;
+      c = (l >> _DIGIT_BITS) + (m >> _DIGIT2_BITS) + xh*h;
+      a_digits[j++] = l & _DIGIT_MASK;
     }
     c += a_digits[i + used];
-    if (c >= DIGIT_BASE) {
-      a_digits[i + used] = c - DIGIT_BASE;
+    if (c >= _DIGIT_BASE) {
+      a_digits[i + used] = c - _DIGIT_BASE;
       a_digits[i + used + 1] = 1;
     } else {
       a_digits[i + used] = c;
@@ -854,60 +820,83 @@
     return 1;
   }
 
-  // r = this * a.
-  void _mulTo(_Bigint a, _Bigint r) {
+  // Return this * a.
+  _Bigint _mul(_Bigint a) {
     // TODO(regis): Use karatsuba multiplication when appropriate.
     var used = _used;
     var a_used = a._used;
     if (used == 0 || a_used == 0) {
-      r._used = 0;
-      r._neg = false;
-      return;
+      return _ZERO;
     }
     var r_used = used + a_used;
-    r._ensureLength(r_used);
     var digits = _digits;
     var a_digits = a._digits;
-    var r_digits = r._digits;
-    r._used = r_used;
-    var i = r_used + 1;  // Set leading zero for 64-bit processing.
+    var r_digits = new Uint32List(r_used + (r_used & 1));
+    var i = 0;
+    while (i < a_used) {
+      i += _mulAdd(a_digits, i, digits, 0, r_digits, i, used);
+    }
+    return new _Bigint(_neg != a._neg, r_used, r_digits);
+  }
+
+  // r_digits[0..r_used-1] = x_digits[0..x_used-1]*a_digits[0..a_used-1].
+  // Return r_used = x_used + a_used.
+  static int _mulDigits(Uint32List x_digits, int x_used,
+                        Uint32List a_digits, int a_used,
+                        Uint32List r_digits) {
+    var r_used = x_used + a_used;
+    var i = r_used + (r_used & 1);
+    assert(r_digits.length >= i);
     while (--i >= 0) {
       r_digits[i] = 0;
     }
     i = 0;
     while (i < a_used) {
-      i += _mulAdd(a_digits, i, digits, 0, r_digits, i, used);
+      i += _mulAdd(a_digits, i, x_digits, 0, r_digits, i, x_used);
     }
-    r._clamp();
-    r._neg = r._used > 0 && _neg != a._neg;  // Zero cannot be negative.
+    return r_used;
   }
 
-  // r = this^2, r != this.
-  void _sqrTo(_Bigint r) {
+  // Return this^2.
+  _Bigint _sqr() {
     var used = _used;
     if (used == 0) {
-      r._used = 0;
-      r._neg = false;
-      return;
+      return _ZERO;
     }
     var r_used = 2 * used;
-    r._ensureLength(r_used);
     var digits = _digits;
-    var r_digits = r._digits;
-    var i = r_used + 1;  // Set leading zero for 64-bit processing.
+    var r_digits = new Uint32List(r_used);
+    // Since r_used is even, no need for a leading zero for 64-bit processing.
+    var i = 0;
+    while (i < used - 1) {
+      i += _sqrAdd(digits, i, r_digits, used);
+    }
+    // The last step is already done if digit pairs were processed above.
+    if (i < used) {
+      _mulAdd(digits, i, digits, i, r_digits, 2*i, 1);
+    }
+    return new _Bigint(false, r_used, r_digits);
+  }
+
+  // r_digits[0..r_used-1] = x_digits[0..x_used-1]*x_digits[0..x_used-1].
+  // Return r_used = 2*x_used.
+  static int _sqrDigits(Uint32List x_digits, int x_used, Uint32List r_digits) {
+    var r_used = 2 * x_used;
+    assert(r_digits.length >= r_used);
+    // Since r_used is even, no need for a leading zero for 64-bit processing.
+    var i = r_used;
     while (--i >= 0) {
       r_digits[i] = 0;
     }
     i = 0;
-    while (i < used - 1) {
-      i += _sqrAdd(digits, i, r_digits, used);
+    while (i < x_used - 1) {
+      i += _sqrAdd(x_digits, i, r_digits, x_used);
     }
-    if (r_used > 0) {
-      _mulAdd(digits, i, digits, i, r_digits, 2*i, 1);
+    // The last step is already done if digit pairs were processed above.
+    if (i < x_used) {
+      _mulAdd(x_digits, i, x_digits, i, r_digits, 2*i, 1);
     }
-    r._used = r_used;
-    r._neg = false;
-    r._clamp();
+    return r_used;
   }
 
   // Indices of the arguments of _estQuotientDigit.
@@ -923,18 +912,20 @@
   // Operation:
   //   Estimate args[_QD] = digits[i-1..i] ~/ args[_YT]
   //   return 1
-  // Note: intrinsics on 64-bit platform may process a digit pair:
+  // Note: Intrinsics on 64-bit platforms process a digit pair (i always odd):
   //   Estimate args[_QD.._QD_HI] = digits[i-3..i] ~/ args[_YT_LO.._YT]
   //   return 2
   static int _estQuotientDigit(Uint32List args, Uint32List digits, int i) {
+    // Verify that digit pairs are accessible for 64-bit processing.
+    assert(digits.length >= 4);
     if (digits[i] == args[_YT]) {
-      args[_QD] = DIGIT_MASK;
+      args[_QD] = _DIGIT_MASK;
     } else {
       // Chop off one bit, since a Mint cannot hold 2 DIGITs.
-      var qd = ((digits[i] << (DIGIT_BITS - 1)) | (digits[i - 1] >> 1))
+      var qd = ((digits[i] << (_DIGIT_BITS - 1)) | (digits[i - 1] >> 1))
           ~/ (args[_YT] >> 1);
-      if (qd > DIGIT_MASK) {
-        args[_QD] = DIGIT_MASK;
+      if (qd > _DIGIT_MASK) {
+        args[_QD] = _DIGIT_MASK;
       } else {
         args[_QD] = qd;
       }
@@ -942,71 +933,70 @@
     return 1;
   }
 
+  // Return trunc(this / a), a != 0.
+  _Bigint _div(_Bigint a) {
+    return _divRem(a, true);
+  }
 
-  // Truncating division and remainder.
-  // If q != null, q = trunc(this / a).
-  // If r != null, r = this - a * trunc(this / a).
-  void _divRemTo(_Bigint a, _Bigint q, _Bigint r) {
-    if (a._used == 0) return;
+  // Return this - a * trunc(this / a), a != 0.
+  _Bigint _rem(_Bigint a) {
+    return _divRem(a, false);
+  }
+
+  // Return trunc(this / a), a != 0, if div == true.
+  // Return this - a * trunc(this / a), a != 0, if div == false.
+  _Bigint _divRem(_Bigint a, bool div) {
+    assert(a._used > 0);
     if (_used < a._used) {
-      if (q != null) {
-        // Set q to 0.
-        q._neg = false;
-        q._used = 0;
-      }
-      if (r != null) {
-        _copyTo(r);
-      }
-      return;
+      return div ? _ZERO : this;
     }
-    if (r == null) {
-      r = new _Bigint();
-    }
-    var y = new _Bigint();  // Normalized modulus.
-    var nsh = DIGIT_BITS - _nbits(a._digits[a._used - 1]);
+    var nsh = _DIGIT_BITS - _nbits(a._digits[a._used - 1]);
     // For 64-bit processing, make sure y has an even number of digits.
-    if ((a._used & 1) == 1) {
-      nsh += DIGIT_BITS;
+    if (a._used.isOdd) {
+      nsh += _DIGIT_BITS;
     }
+    var y;  // Normalized positive divisor.
+    var r;  // Concatenated positive quotient and normalized positive remainder.
     if (nsh > 0) {
-      a._lShiftTo(nsh, y);
-      _lShiftTo(nsh, r);
+      y = a._lShift(nsh)._abs();
+      r = _lShift(nsh)._abs();
     }
     else {
-      a._copyTo(y);
-      _copyTo(r);
+      y = a._abs();
+      r = _abs();
     }
-    // We consider this and a positive. Ignore the copied sign.
-    y._neg = false;
-    r._neg = false;
     var y_used = y._used;
-    assert((y_used & 1) == 0);
     var y_digits = y._digits;
     Uint32List args = new Uint32List(4);
     args[_YT_LO] = y_digits[y_used - 2];
     args[_YT] = y_digits[y_used - 1];
-    var r_digits = r._digits;
-    var i = r._used;
-    if ((i & 1) == 1) {
-      // For 64-bit processing, make sure r has an even number of digits.
-      r_digits[i++] = 0;
-    }
+    var r_used = r._used;
+    // For 64-bit processing, make sure y_used, i, and j are even.
+    assert(y_used.isEven);
+    var i = r_used + (r_used & 1);
     var j = i - y_used;
-    _Bigint t = (q == null) ? new _Bigint() : q;
-    y._dlShiftTo(j, t);
-    if (r._compareTo(t) >= 0) {
-      r_digits[r._used++] = 1;
-      r_digits[r._used] = 0;  // Set leading zero for 64-bit processing.
-      r._subTo(t, r);
+    var t = y._dlShift(j);
+    if (r._compare(t) >= 0) {
+      assert(i == r_used);
+      r = r._or(_ONE._dlShift(r_used++))._sub(t);
+      assert(r._used == r_used && (i + 1) == r_used);
     }
-    ONE._dlShiftTo(y_used, t);
-    t._subTo(y, y);  // Negate y so we can replace sub with _mulAdd later.
-    while (y._used < y_used) {
-      y_digits[y._used++] = 0;
+    // Negate y so we can later use _mulAdd instead of non-existent _mulSub.
+    y = _ONE._dlShift(y_used)._sub(y);
+    if (y._used < y_used) {
+      y_digits = _cloneDigits(y._digits, 0, y._used, y_used);
+    } else {
+      y_digits = y._digits;
     }
-    y_digits[y._used] = 0;  // Set leading zero for 64-bit processing.
+    // y_digits is read-only and has y_used digits (possibly including several
+    // leading zeros) plus a leading zero for 64-bit processing.
+    var r_digits = _cloneDigits(r._digits, 0, r._used, i + 1);
+    // r_digits is modified during iteration.
+    // r_digits[0..y_used-1] is the current remainder.
+    // r_digits[y_used..r_used-1] is the current quotient.
+    --i;
     while (j > 0) {
-      var d0 = _estQuotientDigit(args, r_digits, --i);
+      var d0 = _estQuotientDigit(args, r_digits, i);
       j -= d0;
       var d1 = _mulAdd(args, _QD, y_digits, 0, r_digits, j, y_used);
       // _estQuotientDigit and _mulAdd must agree on the number of digits to
@@ -1014,25 +1004,29 @@
       assert(d0 == d1);
       if (d0 == 1) {
         if (r_digits[i] < args[_QD]) {
-          y._dlShiftTo(j, t);
-          r._subTo(t, r);
+          var t = y._dlShift(j);
+          var t_digits = t._digits;
+          var t_used = t._used;
+          _absSub(r_digits, r_used, t_digits, t_used, r_digits);
           while (r_digits[i] < --args[_QD]) {
-            r._subTo(t, r);
+            _absSub(r_digits, r_used, t_digits, t_used, r_digits);
           }
         }
       } else {
         assert(d0 == 2);
         assert(r_digits[i] <= args[_QD_HI]);
         if ((r_digits[i] < args[_QD_HI]) || (r_digits[i-1] < args[_QD])) {
-          y._dlShiftTo(j, t);
-          r._subTo(t, r);
+          var t = y._dlShift(j);
+          var t_digits = t._digits;
+          var t_used = t._used;
+          _absSub(r_digits, r_used, t_digits, t_used, r_digits);
           if (args[_QD] == 0) {
             --args[_QD_HI];
           }
           --args[_QD];
           assert(r_digits[i] <= args[_QD_HI]);
           while ((r_digits[i] < args[_QD_HI]) || (r_digits[i-1] < args[_QD])) {
-            r._subTo(t, r);
+            _absSub(r_digits, r_used, t_digits, t_used, r_digits);
             if (args[_QD] == 0) {
               --args[_QD_HI];
             }
@@ -1040,45 +1034,141 @@
             assert(r_digits[i] <= args[_QD_HI]);
           }
         }
-        --i;
       }
+      i -= d0;
     }
-    if (q != null) {
-      r._drShiftTo(y_used, q);
-      if (_neg != a._neg && q._used > 0) {
-        q._neg = !q._neg;
+    if (div) {
+      // Return quotient, i.e. r_digits[y_used..r_used-1] with proper sign.
+      r_digits = _cloneDigits(r_digits, y_used, r_used, r_used - y_used);
+      r = new _Bigint(false, r_used - y_used, r_digits);
+      if (_neg != a._neg && r._used > 0) {
+        r = r._negate();
       }
+      return r;
     }
-    r._used = y_used;
-    r._clamp();
+    // Return remainder, i.e. denormalized r_digits[0..y_used-1] with
+    // proper sign.
+    r_digits = _cloneDigits(r_digits, 0, y_used, y_used);
+    r = new _Bigint(false, y_used, r_digits);
     if (nsh > 0) {
-      r._rShiftTo(nsh, r);  // Denormalize remainder.
+      r = r._rShift(nsh);  // Denormalize remainder.
     }
     if (_neg && r._used > 0) {
-      r._neg = !r._neg;
+      r = r._negate();
     }
+    return r;
+  }
+
+  // Customized version of _rem() minimizing allocations for use in reduction.
+  // Input:
+  //   x_digits[0..x_used-1]: positive dividend.
+  //   y_digits[0..y_used-1]: normalized positive divisor.
+  //   ny_digits[0..y_used-1]: negated y_digits.
+  //   nsh: normalization shift amount.
+  //   yt_qd: top y digit(s) and place holder for estimated quotient digit(s).
+  //   t_digits: temp array of 2*y_used digits.
+  //   r_digits: result digits array large enough to temporarily hold
+  //             concatenated quotient and normalized remainder.
+  // Output:
+  //   r_digits[0..r_used-1]: positive remainder.
+  // Returns r_used.
+  static int _remDigits(Uint32List x_digits, int x_used,
+                        Uint32List y_digits, int y_used, Uint32List ny_digits,
+                        int nsh,
+                        Uint32List yt_qd,
+                        Uint32List t_digits,
+                        Uint32List r_digits) {
+    assert(y_used > 0 && x_used >= y_used);
+    // Initialize r_digits to normalized positive dividend.
+    var r_used = _lShiftDigits(x_digits, x_used, nsh, r_digits);
+    // For 64-bit processing, make sure y_used, i, and j are even.
+    assert(y_used.isEven);
+    var i = r_used + (r_used & 1);
+    var j = i - y_used;
+    var t_used = _dlShiftDigits(y_digits, y_used, j, t_digits);
+    // Explicit first division step in case normalized dividend is larger or
+    // equal to shifted normalized divisor.
+    if (_compareDigits(r_digits, r_used, t_digits, t_used) >= 0) {
+      assert(i == r_used);
+      r_digits[r_used++] = 1;  // Quotient = 1.
+      r_digits[r_used] = 0;  // Leading zero.
+      // Subtract divisor from remainder.
+      _absSub(r_digits, r_used, t_digits, t_used, r_digits);
+    }
+    // Negated y_digits passed in ny_digits allow the use of _mulAdd instead of
+    // unimplemented _mulSub.
+    // ny_digits is read-only and has y_used digits (possibly including several
+    // leading zeros) plus a leading zero for 64-bit processing.
+    // r_digits is modified during iteration.
+    // r_digits[0..y_used-1] is the current remainder.
+    // r_digits[y_used..r_used-1] is the current quotient.
+    --i;
+    while (j > 0) {
+      var d0 = _estQuotientDigit(yt_qd, r_digits, i);
+      j -= d0;
+      var d1 = _mulAdd(yt_qd, _QD, ny_digits, 0, r_digits, j, y_used);
+      // _estQuotientDigit and _mulAdd must agree on the number of digits to
+      // process.
+      assert(d0 == d1);
+      if (d0 == 1) {
+        if (r_digits[i] < yt_qd[_QD]) {
+          var t_used = _dlShiftDigits(ny_digits, y_used, j, t_digits);
+          _absSub(r_digits, r_used, t_digits, t_used, r_digits);
+          while (r_digits[i] < --yt_qd[_QD]) {
+            _absSub(r_digits, r_used, t_digits, t_used, r_digits);
+          }
+        }
+      } else {
+        assert(d0 == 2);
+        assert(r_digits[i] <= yt_qd[_QD_HI]);
+        if ((r_digits[i] < yt_qd[_QD_HI]) || (r_digits[i-1] < yt_qd[_QD])) {
+          var t_used = _dlShiftDigits(ny_digits, y_used, j, t_digits);
+          _absSub(r_digits, r_used, t_digits, t_used, r_digits);
+          if (yt_qd[_QD] == 0) {
+            --yt_qd[_QD_HI];
+          }
+          --yt_qd[_QD];
+          assert(r_digits[i] <= yt_qd[_QD_HI]);
+          while ((r_digits[i] < yt_qd[_QD_HI]) ||
+                 (r_digits[i-1] < yt_qd[_QD])) {
+            _absSub(r_digits, r_used, t_digits, t_used, r_digits);
+            if (yt_qd[_QD] == 0) {
+              --yt_qd[_QD_HI];
+            }
+            --yt_qd[_QD];
+            assert(r_digits[i] <= yt_qd[_QD_HI]);
+          }
+        }
+      }
+      i -= d0;
+    }
+    // Return remainder, i.e. denormalized r_digits[0..y_used-1].
+    r_used = y_used;
+    if (nsh > 0) {
+      // Denormalize remainder.
+      r_used = _rShiftDigits(r_digits, r_used, nsh, r_digits);
+    }
+    return r_used;
   }
 
   int get _identityHashCode {
     return this;
   }
   int operator ~() {
-    _Bigint result = new _Bigint();
-    _notTo(result);
-    return result._toValidInt();
+    return _not()._toValidInt();
   }
 
   int get bitLength {
     if (_used == 0) return 0;
     if (_neg) return (~this).bitLength;
-    return DIGIT_BITS*(_used - 1) + _nbits(_digits[_used - 1]);
+    return _DIGIT_BITS*(_used - 1) + _nbits(_digits[_used - 1]);
   }
 
   // This method must support smi._toBigint()._shrFromInt(int).
   int _shrFromInt(int other) {
     if (_used == 0) return other;  // Shift amount is zero.
     if (_neg) throw "negative shift amount";  // TODO(regis): What exception?
-    assert(DIGIT_BITS == 32);  // Otherwise this code needs to be revised.
+    assert(_DIGIT_BITS == 32);  // Otherwise this code needs to be revised.
     var shift;
     if ((_used > 2) || ((_used == 2) && (_digits[1] > 0x10000000))) {
       if (other < 0) {
@@ -1087,11 +1177,9 @@
         return 0;
       }
     } else {
-      shift = ((_used == 2) ? (_digits[1] << DIGIT_BITS) : 0) + _digits[0];
+      shift = ((_used == 2) ? (_digits[1] << _DIGIT_BITS) : 0) + _digits[0];
     }
-    _Bigint result = new _Bigint();
-    other._toBigint()._rShiftTo(shift, result);
-    return result._toValidInt();
+    return other._toBigint()._rShift(shift)._toValidInt();
   }
 
   // This method must support smi._toBigint()._shlFromInt(int).
@@ -1099,16 +1187,14 @@
   int _shlFromInt(int other) {
     if (_used == 0) return other;  // Shift amount is zero.
     if (_neg) throw "negative shift amount";  // TODO(regis): What exception?
-    assert(DIGIT_BITS == 32);  // Otherwise this code needs to be revised.
+    assert(_DIGIT_BITS == 32);  // Otherwise this code needs to be revised.
     var shift;
     if (_used > 2 || (_used == 2 && _digits[1] > 0x10000000)) {
       throw new OutOfMemoryError();
     } else {
-      shift = ((_used == 2) ? (_digits[1] << DIGIT_BITS) : 0) + _digits[0];
+      shift = ((_used == 2) ? (_digits[1] << _DIGIT_BITS) : 0) + _digits[0];
     }
-    _Bigint result = new _Bigint();
-    other._toBigint()._lShiftTo(shift, result);
-    return result._toValidInt();
+    return other._toBigint()._lShift(shift)._toValidInt();
   }
 
   // Overriden operators and methods.
@@ -1155,13 +1241,7 @@
   // End of operator shortcuts.
 
   int operator -() {
-    if (_used == 0) {
-      return this;
-    }
-    var r = new _Bigint();
-    _copyTo(r);
-    r._neg = !_neg;
-    return r._toValidInt();
+    return _negate()._toValidInt();
   }
 
   int get sign {
@@ -1177,7 +1257,7 @@
     final bitsPerChar = radix.bitLength - 1;
     final firstcx = _neg ? 1 : 0;  // Index of first char in str after the sign.
     final lastdx = _used - 1;  // Index of last digit in bigint.
-    final bitLength = lastdx*DIGIT_BITS + _nbits(_digits[lastdx]);
+    final bitLength = lastdx*_DIGIT_BITS + _nbits(_digits[lastdx]);
     // Index of char in str. Initialize with str length.
     var cx = firstcx + (bitLength + bitsPerChar - 1) ~/ bitsPerChar;
     _OneByteString str = _OneByteString._allocate(cx);
@@ -1187,17 +1267,17 @@
     var bx = 0;  // Bit index in bigint digit.
     do {
       var ch;
-      if (bx > (DIGIT_BITS - bitsPerChar)) {
+      if (bx > (_DIGIT_BITS - bitsPerChar)) {
         ch = _digits[dx++] >> bx;
-        bx += bitsPerChar - DIGIT_BITS;
+        bx += bitsPerChar - _DIGIT_BITS;
         if (dx <= lastdx) {
           ch |= (_digits[dx] & ((1 << bx) - 1)) << (bitsPerChar - bx);
         }
       } else {
         ch = (_digits[dx] >> bx) & mask;
         bx += bitsPerChar;
-        if (bx >= DIGIT_BITS) {
-          bx -= DIGIT_BITS;
+        if (bx >= _DIGIT_BITS) {
+          bx -= _DIGIT_BITS;
           dx++;
         }
       }
@@ -1211,135 +1291,134 @@
     if (count is! _Smi) {
       _shlFromInt(count);  // Throws out of memory exception.
     }
-    assert(DIGIT_BITS == 32);  // Otherwise this code needs to be revised.
+    assert(_DIGIT_BITS == 32);  // Otherwise this code needs to be revised.
     if (count > 31) return 0;
     return (_digits[0] << count) & mask;
   }
 
   int _bitAndFromInteger(int other) {
-    _Bigint result = new _Bigint();
-    other._toBigint()._andTo(this, result);
-    return result._toValidInt();
+    return other._toBigint()._and(this)._toValidInt();
   }
   int _bitOrFromInteger(int other) {
-    _Bigint result = new _Bigint();
-    other._toBigint()._orTo(this, result);
-    return result._toValidInt();
+    return other._toBigint()._or(this)._toValidInt();
   }
   int _bitXorFromInteger(int other) {
-    _Bigint result = new _Bigint();
-    other._toBigint()._xorTo(this, result);
-    return result._toValidInt();
+    return other._toBigint()._xor(this)._toValidInt();
   }
   int _addFromInteger(int other) {
-    _Bigint result = new _Bigint();
-    other._toBigint()._addTo(this, result);
-    return result._toValidInt();
+    return other._toBigint()._add(this)._toValidInt();
   }
   int _subFromInteger(int other) {
-    _Bigint result = new _Bigint();
-    other._toBigint()._subTo(this, result);
-    return result._toValidInt();
+    return other._toBigint()._sub(this)._toValidInt();
   }
   int _mulFromInteger(int other) {
-    _Bigint result = new _Bigint();
-    other._toBigint()._mulTo(this, result);
-    return result._toValidInt();
+    return other._toBigint()._mul(this)._toValidInt();
   }
   int _truncDivFromInteger(int other) {
-    _Bigint result = new _Bigint();
-    other._toBigint()._divRemTo(this, result, null);
-    return result._toValidInt();
+    return other._toBigint()._div(this)._toValidInt();
   }
   int _moduloFromInteger(int other) {
-    _Bigint result = new _Bigint();
-    other._toBigint()._divRemTo(this, null, result);
+    _Bigint result = other._toBigint()._rem(this);
     if (result._neg) {
       if (_neg) {
-        result._subTo(this, result);
+        result = result._sub(this);
       } else {
-        result._addTo(this, result);
+        result = result._add(this);
       }
     }
     return result._toValidInt();
   }
   int _remainderFromInteger(int other) {
-    _Bigint result = new _Bigint();
-    other._toBigint()._divRemTo(this, null, result);
-    return result._toValidInt();
+    return other._toBigint()._rem(this)._toValidInt();
   }
   bool _greaterThanFromInteger(int other) {
-    return other._toBigint()._compareTo(this) > 0;
+    return other._toBigint()._compare(this) > 0;
   }
   bool _equalToInteger(int other) {
-    return other._toBigint()._compareTo(this) == 0;
+    return other._toBigint()._compare(this) == 0;
   }
 
-  // TODO(regis): Make this method private once the plumbing to invoke it from
-  // dart:math is in place. Move the argument checking to dart:math.
-  // Return pow(this, e) % m.
+  // Return pow(this, e) % m, with e >= 0, m > 0.
   int modPow(int e, int m) {
-    if (e is! int) throw new ArgumentError(e);
-    if (m is! int) throw new ArgumentError(m);
-    int i = e.bitLength;
-    if (i <= 0) return 1;
+    if (e is! int || e < 0) throw new ArgumentError(e);
+    if (m is! int || m <= 0) throw new ArgumentError(m);
+    final m_used = m._used;
+    final m_used2p2 = 2*m_used + 1 + 1;  // +1 for leading zero.
+    final e_bitlen = e.bitLength;
+    if (e_bitlen <= 0) return 1;
     if ((e is! _Bigint) || m.isEven) {
-      _Reduction z = (i < 8 || m.isEven) ? new _Classic(m) : new _Montgomery(m);
+      _Reduction z = (e_bitlen < 8 || m.isEven) ?
+          new _Classic(m) : new _Montgomery(m);
       // TODO(regis): Should we use Barrett reduction for an even modulus?
-      var r = new _Bigint();
-      var r2 = new _Bigint();
-      var g = z._convert(this);
-      i--;
-      g._copyTo(r);
+      var m_used = m._used;
+      var r_digits = new Uint32List(m_used2p2);
+      var r2_digits = new Uint32List(m_used2p2);
+      var g_digits = new Uint32List(m_used + (m_used & 1));
+      var g_used = z._convert(this, g_digits);
+      // Initialize r with g.
+      var j = g_used + (g_used & 1);  // Copy leading zero if any.
+      while (--j >= 0) {
+        r_digits[j] = g_digits[j];
+      }
+      var r_used = g_used;
+      var r2_used;
+      var i = e_bitlen - 1;
       while (--i >= 0) {
-        z._sqrTo(r, r2);
+        r2_used = z._sqr(r_digits, r_used, r2_digits);
         if ((e & (1 << i)) != 0) {
-          z._mulTo(r2, g, r);
+          r_used = z._mul(r2_digits, r2_used, g_digits, g_used, r_digits);
         } else {
-          var t = r;
-          r = r2;
-          r2 = t;
+          var t_digits = r_digits;
+          var t_used = r_used;
+          r_digits = r2_digits;
+          r_used = r2_used;
+          r2_digits = t_digits;
+          r2_used = t_used;
         }
       }
-      return z._revert(r)._toValidInt();
+      return z._revert(r_digits, r_used)._toValidInt();
     }
     var k;
-    // TODO(regis): Are these values of k really optimal for our implementation?
-    if (i < 18) k = 1;
-    else if (i < 48) k = 3;
-    else if (i < 144) k = 4;
-    else if (i < 768) k = 5;
+    if (e_bitlen < 18) k = 1;
+    else if (e_bitlen < 48) k = 3;
+    else if (e_bitlen < 144) k = 4;
+    else if (e_bitlen < 768) k = 5;
     else k = 6;
     _Reduction z = new _Montgomery(m);
     var n = 3;
-    var k1 = k - 1;
-    var km = (1 << k) - 1;
-    List g = new List(km + 1);
-    g[1] = z._convert(this);
+    final k1 = k - 1;
+    final km = (1 << k) - 1;
+    List g_digits = new List(km + 1);
+    List g_used = new List(km + 1);
+    g_digits[1] = new Uint32List(m_used + (m_used & 1));
+    g_used[1] = z._convert(this, g_digits[1]);
     if (k > 1) {
-      var g2 = new _Bigint();
-      z._sqrTo(g[1], g2);
+      var g2_digits = new Uint32List(m_used2p2);
+      var g2_used = z._sqr(g_digits[1], g_used[1], g2_digits);
       while (n <= km) {
-        g[n] = new _Bigint();
-        z._mulTo(g2, g[n - 2], g[n]);
+        g_digits[n] = new Uint32List(m_used2p2);
+        g_used[n] = z._mul(g2_digits, g2_used,
+                           g_digits[n - 2], g_used[n - 2],
+                           g_digits[n]);
         n += 2;
       }
     }
-    var j = e._used - 1;
     var w;
     var is1 = true;
-    var r = new _Bigint._fromInt(1);
-    var r2 = new _Bigint();
-    var t;
+    var r_digits = _ONE._digits;
+    var r_used = _ONE._used;
+    var r2_digits = new Uint32List(m_used2p2);
+    var r2_used;
     var e_digits = e._digits;
-    i = _nbits(e_digits[j]) - 1;
+    var j = e._used - 1;
+    var i = _nbits(e_digits[j]) - 1;
     while (j >= 0) {
       if (i >= k1) {
         w = (e_digits[j] >> (i - k1)) & km;
       } else {
         w = (e_digits[j] & ((1 << (i + 1)) - 1)) << (k1 - i);
         if (j > 0) {
-          w |= e_digits[j - 1] >> (DIGIT_BITS + i - k1);
+          w |= e_digits[j - 1] >> (_DIGIT_BITS + i - k1);
         }
       }
       n = k;
@@ -1348,56 +1427,72 @@
         --n;
       }
       if ((i -= n) < 0) {
-        i += DIGIT_BITS;
+        i += _DIGIT_BITS;
         --j;
       }
       if (is1) {  // r == 1, don't bother squaring or multiplying it.
-        g[w]._copyTo(r);
+        r_digits = new Uint32List(m_used2p2);
+        r_used = g_used[w];
+        var gw_digits = g_digits[w];
+        var ri = r_used + (r_used & 1);  // Copy leading zero if any.
+        while (--ri >= 0) {
+          r_digits[ri] = gw_digits[ri];
+        }
         is1 = false;
       }
       else {
         while (n > 1) {
-          z._sqrTo(r, r2);
-          z._sqrTo(r2, r);
+          r2_used = z._sqr(r_digits, r_used, r2_digits);
+          r_used = z._sqr(r2_digits, r2_used, r_digits);
           n -= 2;
         }
         if (n > 0) {
-          z._sqrTo(r, r2);
+          r2_used = z._sqr(r_digits, r_used, r2_digits);
         } else {
-          t = r;
-          r = r2;
-          r2 = t;
+          var t_digits = r_digits;
+          var t_used = r_used;
+          r_digits = r2_digits;
+          r_used = r2_used;
+          r2_digits = t_digits;
+          r2_used = t_used;
         }
-        z._mulTo(r2,g[w], r);
+        r_used = z._mul(r2_digits, r2_used, g_digits[w], g_used[w], r_digits);
       }
-
       while (j >= 0 && (e_digits[j] & (1 << i)) == 0) {
-        z._sqrTo(r, r2);
-        t = r;
-        r = r2;
-        r2 = t;
+        r2_used = z._sqr(r_digits, r_used, r2_digits);
+        var t_digits = r_digits;
+        var t_used = r_used;
+        r_digits = r2_digits;
+        r_used = r2_used;
+        r2_digits = t_digits;
+        r2_used = t_used;
         if (--i < 0) {
-          i = DIGIT_BITS - 1;
+          i = _DIGIT_BITS - 1;
           --j;
         }
       }
     }
-    return z._revert(r)._toValidInt();
+    assert(!is1);
+    return z._revert(r_digits, r_used)._toValidInt();
   }
 }
 
 // Interface for modular reduction.
 class _Reduction {
-  _Bigint _convert(_Bigint x);
-  _Bigint _revert(_Bigint x);
-  void _mulTo(_Bigint x, _Bigint y, _Bigint r);
-  void _sqrTo(_Bigint x, _Bigint r);
+  // Return the number of digits used by r_digits.
+  int _convert(_Bigint x, Uint32List r_digits);
+  int _mul(Uint32List x_digits, int x_used,
+           Uint32List y_digits, int y_used, Uint32List r_digits);
+  int _sqr(Uint32List x_digits, int x_used, Uint32List r_digits);
+
+  // Return x reverted to _Bigint.
+  _Bigint _revert(Uint32List x_digits, int x_used);
 }
 
 // Montgomery reduction on _Bigint.
 class _Montgomery implements _Reduction {
-  _Bigint _m;
-  int _mused2;
+  _Bigint _m;  // Modulus.
+  int _mused2p2;
   Uint32List _args;
   int _digits_per_step;  // Number of digits processed in one step. 1 or 2.
   static const int _X = 0;  // Index of x.
@@ -1409,7 +1504,7 @@
 
   _Montgomery(m) {
     _m = m._toBigint();
-    _mused2 = 2*_m._used;
+    _mused2p2 = 2*_m._used + 2;
     _args = new Uint32List(6);
     // Determine if we can process digit pairs by calling an intrinsic.
     _digits_per_step = _mulMod(_args, _args, 0);
@@ -1423,7 +1518,7 @@
     }
   }
 
-  // Calculates -1/x % DIGIT_BASE, x is 32-bit digit.
+  // Calculates -1/x % _DIGIT_BASE, x is 32-bit digit.
   //         xy == 1 (mod m)
   //         xy =  1+km
   //   xy(2-xy) = (1+km)(1-km)
@@ -1433,25 +1528,24 @@
   // Should reduce x and y(2-xy) by m^2 at each step to keep size bounded.
   //
   // Operation:
-  //   args[_RHO] = 1/args[_X] mod DIGIT_BASE.
+  //   args[_RHO] = 1/args[_X] mod _DIGIT_BASE.
   static void _invDigit(Uint32List args) {
     var x = args[_X];
     var y = x & 3;    // y == 1/x mod 2^2
     y = (y*(2 - (x & 0xf)*y)) & 0xf;  // y == 1/x mod 2^4
     y = (y*(2 - (x & 0xff)*y)) & 0xff;  // y == 1/x mod 2^8
     y = (y*(2 - (((x & 0xffff)*y) & 0xffff))) & 0xffff; // y == 1/x mod 2^16
-    // Last step - calculate inverse mod DIGIT_BASE directly;
-    // Assumes 16 < DIGIT_BITS <= 32 and assumes ability to handle 48-bit ints.
-    y = (y*(2 - x*y % _Bigint.DIGIT_BASE)) % _Bigint.DIGIT_BASE;
-    // y == 1/x mod DIGIT_BASE
+    // Last step - calculate inverse mod _DIGIT_BASE directly;
+    // Assumes 16 < _DIGIT_BITS <= 32 and assumes ability to handle 48-bit ints.
+    y = (y*(2 - x*y % _Bigint._DIGIT_BASE)) % _Bigint._DIGIT_BASE;
+    // y == 1/x mod _DIGIT_BASE
     y = -y;  // We really want the negative inverse.
-    args[_RHO] = y & _Bigint.DIGIT_MASK;
+    args[_RHO] = y & _Bigint._DIGIT_MASK;
   }
 
-
-  // Calculates -1/x % DIGIT_BASE^2, x is a pair of 32-bit digits.
+  // Calculates -1/x % _DIGIT_BASE^2, x is a pair of 32-bit digits.
   // Operation:
-  //   args[_RHO.._RHO_HI] = 1/args[_X.._X_HI] mod DIGIT_BASE^2.
+  //   args[_RHO.._RHO_HI] = 1/args[_X.._X_HI] mod _DIGIT_BASE^2.
   static void _invDigitPair(Uint32List args) {
     var xl = args[_X];  // Lower 32-bit digit of x.
     var y = xl & 3;    // y == 1/x mod 2^2
@@ -1459,60 +1553,66 @@
     y = (y*(2 - (xl & 0xff)*y)) & 0xff;  // y == 1/x mod 2^8
     y = (y*(2 - (((xl & 0xffff)*y) & 0xffff))) & 0xffff;  // y == 1/x mod 2^16
     y = (y*(2 - ((xl*y) & 0xffffffff))) & 0xffffffff;  // y == 1/x mod 2^32
-    var x = (args[_X_HI] << _Bigint.DIGIT_BITS) | xl;
+    var x = (args[_X_HI] << _Bigint._DIGIT_BITS) | xl;
     y = (y*(2 - ((x*y) & 0xffffffffffffffff))) & 0xffffffffffffffff;
-    // y == 1/x mod DIGIT_BASE^2
+    // y == 1/x mod _DIGIT_BASE^2
     y = -y;  // We really want the negative inverse.
-    args[_RHO] = y & _Bigint.DIGIT_MASK;
-    args[_RHO_HI] = (y >> _Bigint.DIGIT_BITS) & _Bigint.DIGIT_MASK;
+    args[_RHO] = y & _Bigint._DIGIT_MASK;
+    args[_RHO_HI] = (y >> _Bigint._DIGIT_BITS) & _Bigint._DIGIT_MASK;
   }
 
-
   // Operation:
-  //   args[_MU] = args[_RHO]*digits[i] mod DIGIT_BASE.
+  //   args[_MU] = args[_RHO]*digits[i] mod _DIGIT_BASE.
   //   return 1.
-  // Note: intrinsics on 64-bit platform may process a digit pair:
-  //   args[_MU.._MU_HI] = args[_RHO.._RHO_HI]*digits[i..i+1] mod DIGIT_BASE^2.
+  // Note: Intrinsics on 64-bit platforms process digit pairs at even indices:
+  //   args[_MU.._MU_HI] = args[_RHO.._RHO_HI]*digits[i..i+1] mod _DIGIT_BASE^2.
   //   return 2.
   static int _mulMod(Uint32List args, Uint32List digits, int i) {
-    const int MU_MASK = (1 << (_Bigint.DIGIT_BITS - _Bigint.DIGIT2_BITS)) - 1;
-    var rhol = args[_RHO] & _Bigint.DIGIT2_MASK;
-    var rhoh = args[_RHO] >> _Bigint.DIGIT2_BITS;
-    var dh = digits[i] >> _Bigint.DIGIT2_BITS;
-    var dl = digits[i] & _Bigint.DIGIT2_MASK;
+    // Verify that digit pairs are accessible for 64-bit processing.
+    assert(digits.length > (i | 1));
+    const int MU_MASK = (1 << (_Bigint._DIGIT_BITS - _Bigint._DIGIT2_BITS)) - 1;
+    var rhol = args[_RHO] & _Bigint._DIGIT2_MASK;
+    var rhoh = args[_RHO] >> _Bigint._DIGIT2_BITS;
+    var dh = digits[i] >> _Bigint._DIGIT2_BITS;
+    var dl = digits[i] & _Bigint._DIGIT2_MASK;
     args[_MU] =
-        (dl*rhol + (((dl*rhoh + dh*rhol) & MU_MASK) << _Bigint.DIGIT2_BITS))
-        & _Bigint.DIGIT_MASK;
+        (dl*rhol + (((dl*rhoh + dh*rhol) & MU_MASK) << _Bigint._DIGIT2_BITS))
+        & _Bigint._DIGIT_MASK;
     return 1;
   }
 
-  // Return x*R mod _m
-  _Bigint _convert(_Bigint x) {
-    var r = new _Bigint();
-    x.abs()._dlShiftTo(_m._used, r);
-    r._divRemTo(_m, null, r);
+  // r = x*R mod _m.
+  // Return r_used.
+  int _convert(_Bigint x, Uint32List r_digits) {
+    var r = x._abs()._dlShift(_m._used)._rem(_m);
     if (x._neg && !r._neg && r._used > 0) {
-      _m._subTo(r, r);
+      r = _m._sub(r);
     }
-    return r;
+    var used = r._used;
+    var digits = r._digits;
+    var i = used + (used & 1);
+    while (--i >= 0) {
+      r_digits[i] = digits[i];
+    }
+    return used;
   }
 
-  // Return x/R mod _m
-  _Bigint _revert(_Bigint x) {
-    var r = new _Bigint();
-    x._copyTo(r);
-    _reduce(r);
-    return r;
+  _Bigint _revert(Uint32List x_digits, int x_used) {
+    var r_digits = new Uint32List(_mused2p2);
+    var i = x_used + (x_used & 1);
+    while (--i >= 0) {
+      r_digits[i] = x_digits[i];
+    }
+    var r_used = _reduce(r_digits, x_used);
+    return new _Bigint(false, r_used, r_digits);
   }
 
-  // x = x/R mod _m
-  void _reduce(_Bigint x) {
-    x._ensureLength(_mused2 + 1);
-    var x_digits = x._digits;
-    while (x._used <= _mused2) {  // Pad x so _mulAdd has enough room later.
-      x_digits[x._used++] = 0;
+  // x = x/R mod _m.
+  // Return x_used.
+  int _reduce(Uint32List x_digits, int x_used) {
+    while (x_used < _mused2p2) {  // Pad x so _mulAdd has enough room later.
+      x_digits[x_used++] = 0;
     }
-    x_digits[x._used] = 0;  // Set leading zero for 64-bit processing.
     var m_used = _m._used;
     var m_digits = _m._digits;
     var i = 0;
@@ -1523,61 +1623,125 @@
       assert(d == _digits_per_step);
       i += d;
     }
-    x._clamp();
-    x._drShiftTo(m_used, x);
-    if (x._compareTo(_m) >= 0) {
-      x._subTo(_m, x);
+    // Clamp x.
+    while (x_used > 0 && x_digits[x_used - 1] == 0) {
+      --x_used;
     }
+    x_used = _Bigint._drShiftDigits(x_digits, x_used, m_used, x_digits);
+    if (_Bigint._compareDigits(x_digits, x_used, m_digits, m_used) >= 0) {
+      _Bigint._absSub(x_digits, x_used, m_digits, m_used, x_digits);
+    }
+    // Clamp x.
+    while (x_used > 0 && x_digits[x_used - 1] == 0) {
+      --x_used;
+    }
+    return x_used;
   }
 
-  // r = x^2/R mod _m ; x != r
-  void _sqrTo(_Bigint x, _Bigint r) {
-    x._sqrTo(r);
-    _reduce(r);
+  int _sqr(Uint32List x_digits, int x_used, Uint32List r_digits) {
+    var r_used = _Bigint._sqrDigits(x_digits, x_used, r_digits);
+    return _reduce(r_digits, r_used);
   }
 
-  // r = x*y/R mod _m ; x, y != r
-  void _mulTo(_Bigint x, _Bigint y, _Bigint r) {
-    x._mulTo(y, r);
-    _reduce(r);
+  int _mul(Uint32List x_digits, int x_used,
+           Uint32List y_digits, int y_used,
+           Uint32List r_digits) {
+    var r_used = _Bigint._mulDigits(x_digits, x_used,
+                                    y_digits, y_used,
+                                    r_digits);
+    return _reduce(r_digits, r_used);
   }
 }
 
 // Modular reduction using "classic" algorithm.
 class _Classic implements _Reduction {
-  _Bigint _m;
+  _Bigint _m;  // Modulus.
+  _Bigint _norm_m;  // Normalized _m.
+  Uint32List _neg_norm_m_digits;  // Negated _norm_m digits.
+  int _m_nsh;  // Normalization shift amount.
+  Uint32List _mt_qd;  // Top _norm_m digit(s) and place holder for
+                      // estimated quotient digit(s).
+  Uint32List _t_digits;  // Temporary digits used during reduction.
 
   _Classic(int m) {
     _m = m._toBigint();
-  }
-
-  _Bigint _convert(_Bigint x) {
-    if (x._neg || x._compareTo(_m) >= 0) {
-      var r = new _Bigint();
-      x._divRemTo(_m, null, r);
-      if (x._neg && !r._neg && r._used > 0) {
-        _m._subTo(r, r);
-      }
-      return r;
+    // Preprocess arguments to _remDigits.
+    var nsh = _Bigint._DIGIT_BITS - _Bigint._nbits(_m._digits[_m._used - 1]);
+    // For 64-bit processing, make sure _norm_m_digits has an even number of
+    // digits.
+    if (_m._used.isOdd) {
+      nsh += _Bigint._DIGIT_BITS;
     }
-    return x;
+    _m_nsh = nsh;
+    _norm_m = _m._lShift(nsh);
+    var nm_used = _norm_m._used;
+    assert(nm_used.isEven);
+    _mt_qd = new Uint32List(4);
+    _mt_qd[_Bigint._YT_LO] = _norm_m._digits[nm_used - 2];
+    _mt_qd[_Bigint._YT] = _norm_m._digits[nm_used - 1];
+    // Negate _norm_m so we can use _mulAdd instead of unimplemented _mulSub.
+    var neg_norm_m = _Bigint._ONE._dlShift(nm_used)._sub(_norm_m);
+    if (neg_norm_m._used < nm_used) {
+      _neg_norm_m_digits =
+          _Bigint._cloneDigits(neg_norm_m._digits, 0, nm_used, nm_used);
+    } else {
+      _neg_norm_m_digits = neg_norm_m._digits;
+    }
+    // _neg_norm_m_digits is read-only and has nm_used digits (possibly
+    // including several leading zeros) plus a leading zero for 64-bit
+    // processing.
+    _t_digits = new Uint32List(2*nm_used);
   }
 
-  _Bigint _revert(_Bigint x) {
-    return x;
+  int _convert(_Bigint x, Uint32List r_digits) {
+    var digits;
+    var used;
+    if (x._neg || x._compare(_m) >= 0) {
+      var r = x.rem(_m);
+      if (x._neg && !r._neg && r._used > 0) {
+        r = _m._sub(r);
+      }
+      assert(!r._neg);
+      used = r._used;
+      digits = r._digits;
+    } else {
+      used = x._used;
+      digits = x._digits;
+    }
+    var i = used + (used + 1);  // Copy leading zero if any.
+    while (--i >= 0) {
+      r_digits[i] = digits[i];
+    }
+    return used;
   }
 
-  void _reduce(_Bigint x) {
-    x._divRemTo(_m, null, x);
+  _Bigint _revert(Uint32List x_digits, int x_used) {
+    return new _Bigint(false, x_used, x_digits);
   }
 
-  void _sqrTo(_Bigint x, _Bigint r) {
-    x._sqrTo(r);
-    _reduce(r);
+  int _reduce(Uint32List x_digits, int x_used) {
+    // The function _remDigits(...) is optimized for reduction and equivalent to
+    // calling _convert(_revert(x_digits, x_used)._rem(_m), x_digits);
+    return _Bigint._remDigits(x_digits, x_used,
+                              _norm_m._digits, _norm_m._used,
+                              _neg_norm_m_digits,
+                              _m_nsh,
+                              _mt_qd,
+                              _t_digits,
+                              x_digits);
   }
 
-  void _mulTo(_Bigint x, _Bigint y, _Bigint r) {
-    x._mulTo(y, r);
-    _reduce(r);
+  int _sqr(Uint32List x_digits, int x_used, Uint32List r_digits) {
+    var r_used = _Bigint._sqrDigits(x_digits, x_used, r_digits);
+    return _reduce(r_digits, r_used);
+  }
+
+  int _mul(Uint32List x_digits, int x_used,
+           Uint32List y_digits, int y_used,
+           Uint32List r_digits) {
+    var r_used = _Bigint._mulDigits(x_digits, x_used,
+                                    y_digits, y_used,
+                                    r_digits);
+    return _reduce(r_digits, r_used);
   }
 }
diff --git a/runtime/lib/core_patch.dart b/runtime/lib/core_patch.dart
index c824217..71d59b3 100644
--- a/runtime/lib/core_patch.dart
+++ b/runtime/lib/core_patch.dart
@@ -5,10 +5,10 @@
 import "dart:math";
 import "dart:typed_data";
 
-// We need to pass the exception object as second parameter to the continuation.
-// See vm/ast_transformer.cc for usage.
+// We need to pass the exception and stack trace objects as second and third
+// parameter to the continuation.  See vm/ast_transformer.cc for usage.
 void  _asyncCatchHelper(catchFunction, continuation) {
-  catchFunction((e) => continuation(null, e));
+  catchFunction((e, s) => continuation(null, e, s));
 }
 
 // The members of this class are cloned and added to each class that
diff --git a/runtime/lib/integers.cc b/runtime/lib/integers.cc
index d9f9e06..c44d18d 100644
--- a/runtime/lib/integers.cc
+++ b/runtime/lib/integers.cc
@@ -409,46 +409,25 @@
 }
 
 
-DEFINE_NATIVE_ENTRY(Bigint_setNeg, 2) {
-  const Bigint& bigint = Bigint::CheckedHandle(arguments->NativeArgAt(0));
-  const Bool& neg = Bool::CheckedHandle(arguments->NativeArgAt(1));
-  bigint.set_neg(neg);
-  return Object::null();
-}
-
-
 DEFINE_NATIVE_ENTRY(Bigint_getUsed, 1) {
   const Bigint& bigint = Bigint::CheckedHandle(arguments->NativeArgAt(0));
   return bigint.used();
 }
 
 
-DEFINE_NATIVE_ENTRY(Bigint_setUsed, 2) {
-  const Bigint& bigint = Bigint::CheckedHandle(arguments->NativeArgAt(0));
-  const Smi& used = Smi::CheckedHandle(arguments->NativeArgAt(1));
-  bigint.set_used(used);
-  return Object::null();
-}
-
-
 DEFINE_NATIVE_ENTRY(Bigint_getDigits, 1) {
   const Bigint& bigint = Bigint::CheckedHandle(arguments->NativeArgAt(0));
   return bigint.digits();
 }
 
 
-DEFINE_NATIVE_ENTRY(Bigint_setDigits, 2) {
-  const Bigint& bigint = Bigint::CheckedHandle(arguments->NativeArgAt(0));
-  const TypedData& digits = TypedData::CheckedHandle(arguments->NativeArgAt(1));
+DEFINE_NATIVE_ENTRY(Bigint_allocate, 4) {
+  // First arg is null type arguments, since class Bigint is not parameterized.
+  const Bool& neg = Bool::CheckedHandle(arguments->NativeArgAt(1));
+  const Smi& used = Smi::CheckedHandle(arguments->NativeArgAt(2));
+  const TypedData& digits = TypedData::CheckedHandle(arguments->NativeArgAt(3));
   ASSERT(!digits.IsNull());
-  bigint.set_digits(digits);
-  return Object::null();
-}
-
-
-DEFINE_NATIVE_ENTRY(Bigint_allocate, 1) {
-  // Argument is null type arguments, since class Bigint is not parameterized.
-  return Bigint::New();
+  return Bigint::New(neg.value(), used.Value(), digits);
 }
 
 }  // namespace dart
diff --git a/runtime/lib/integers.dart b/runtime/lib/integers.dart
index 48f6dc1..26a996d 100644
--- a/runtime/lib/integers.dart
+++ b/runtime/lib/integers.dart
@@ -265,12 +265,10 @@
 
   _leftShiftWithMask32(count, mask)  native "Integer_leftShiftWithMask32";
 
-  // TODO(regis): Make this method private once the plumbing to invoke it from
-  // dart:math is in place. Move the argument checking to dart:math.
   // Return pow(this, e) % m.
   int modPow(int e, int m) {
-    if (e is! int) throw new ArgumentError(e);
-    if (m is! int) throw new ArgumentError(m);
+    if (e is! int || e < 0) throw new ArgumentError(e);
+    if (m is! int || m <= 0) throw new ArgumentError(m);
     if (e is _Bigint || m is _Bigint) {
       return _toBigint().modPow(e, m);
     }
diff --git a/runtime/lib/internal_patch.dart b/runtime/lib/internal_patch.dart
index 14bc69d..0da1bc2 100644
--- a/runtime/lib/internal_patch.dart
+++ b/runtime/lib/internal_patch.dart
@@ -5,6 +5,13 @@
 patch List makeListFixedLength(List growableList)
     native "Internal_makeListFixedLength";
 
-// TODO(iposva): Move bulk of timer implementation into async.
-// Used by the message handler to run timers
-var runTimerClosure = null;
+class VMLibraryHooks {
+  // Example: "dart:isolate _Timer._factory"
+  static var timerFactory;
+  // Example: "dart:io _EventHandler._sendData"
+  static var eventHandlerSendData;
+}
+
+patch class CodeUnits {
+  static final int cid = ClassID.getID(new CodeUnits(""));
+}
diff --git a/runtime/lib/isolate.cc b/runtime/lib/isolate.cc
index ac7a9aa..23b942a 100644
--- a/runtime/lib/isolate.cc
+++ b/runtime/lib/isolate.cc
@@ -16,6 +16,7 @@
 #include "vm/object_store.h"
 #include "vm/port.h"
 #include "vm/resolver.h"
+#include "vm/service.h"
 #include "vm/snapshot.h"
 #include "vm/symbols.h"
 #include "vm/unicode.h"
@@ -102,12 +103,15 @@
   GET_NON_NULL_NATIVE_ARGUMENT(Instance, obj, arguments->NativeArgAt(1));
 
   uint8_t* data = NULL;
-  bool can_send_any_object = (isolate->origin_id() == port.origin_id());
+
+  const Dart_Port destination_port_id = port.Id();
+  const bool can_send_any_object = isolate->origin_id() == port.origin_id();
+
   MessageWriter writer(&data, &allocator, can_send_any_object);
   writer.WriteMessage(obj);
 
   // TODO(turnidge): Throw an exception when the return value is false?
-  PortMap::PostMessage(new Message(port.Id(),
+  PortMap::PostMessage(new Message(destination_port_id,
                                    data, writer.BytesWritten(),
                                    Message::kNormalPriority));
   return Object::null();
diff --git a/runtime/lib/isolate_patch.dart b/runtime/lib/isolate_patch.dart
index b0383d8..9a74438 100644
--- a/runtime/lib/isolate_patch.dart
+++ b/runtime/lib/isolate_patch.dart
@@ -141,11 +141,8 @@
     // so that we can run the immediate callbacks.
     handler(message);
     _runPendingImmediateCallback();
-
     // Event was handled. Now run expired timers.
-    if (runTimerClosure != null) {
-      runTimerClosure(_runPendingImmediateCallback);
-    }
+    _Timer._handleTimeout();
   }
 
   // Call into the VM to close the VM maintained mappings.
diff --git a/runtime/lib/isolate_sources.gypi b/runtime/lib/isolate_sources.gypi
index 373158f..d54fadf 100644
--- a/runtime/lib/isolate_sources.gypi
+++ b/runtime/lib/isolate_sources.gypi
@@ -7,5 +7,6 @@
   'sources': [
     'isolate_patch.dart',
     'isolate.cc',
+    'timer_impl.dart',
   ],
 }
diff --git a/runtime/lib/object.cc b/runtime/lib/object.cc
index 278cb09..da6c08e 100644
--- a/runtime/lib/object.cc
+++ b/runtime/lib/object.cc
@@ -259,7 +259,7 @@
           location, instance_type_name, type_name,
           dst_name, Object::null_string());
     } else {
-      ASSERT(FLAG_enable_type_checks);
+      ASSERT(Isolate::Current()->TypeChecksEnabled());
       bound_error_message = String::New(bound_error.ToErrorCString());
       Exceptions::CreateAndThrowTypeError(
           location, instance_type_name, Symbols::Empty(),
diff --git a/runtime/lib/string.cc b/runtime/lib/string.cc
index 2dd69e5..c72f14f 100644
--- a/runtime/lib/string.cc
+++ b/runtime/lib/string.cc
@@ -407,6 +407,92 @@
 }
 
 
+DEFINE_NATIVE_ENTRY(TwoByteString_allocateFromTwoByteList, 3) {
+  Instance& list = Instance::CheckedHandle(arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Smi, start_obj, arguments->NativeArgAt(1));
+  GET_NON_NULL_NATIVE_ARGUMENT(Smi, end_obj, arguments->NativeArgAt(2));
+
+  intptr_t start = start_obj.Value();
+  intptr_t end = end_obj.Value();
+  if (start < 0) {
+    Exceptions::ThrowArgumentError(start_obj);
+  }
+  intptr_t length = end - start;
+  if (length < 0) {
+    Exceptions::ThrowArgumentError(end_obj);
+  }
+
+  Heap::Space space = isolate->heap()->SpaceForAllocation(kTwoByteStringCid);
+  if (list.IsTypedData()) {
+    const TypedData& array = TypedData::Cast(list);
+    if (array.ElementType() != kUint16ArrayElement) {
+      Exceptions::ThrowArgumentError(list);
+    }
+    if (end > array.Length()) {
+      Exceptions::ThrowArgumentError(end_obj);
+    }
+    return TwoByteString::New(array, start * sizeof(uint16_t), length, space);
+  } else if (list.IsExternalTypedData()) {
+    const ExternalTypedData& array = ExternalTypedData::Cast(list);
+    if (array.ElementType() != kUint16ArrayElement) {
+      Exceptions::ThrowArgumentError(list);
+    }
+    if (end > array.Length()) {
+      Exceptions::ThrowArgumentError(end_obj);
+    }
+    return TwoByteString::New(array, start * sizeof(uint16_t), length, space);
+  } else if (RawObject::IsTypedDataViewClassId(list.GetClassId())) {
+    const intptr_t cid = list.GetClassId();
+    if (cid != kTypedDataUint16ArrayViewCid) {
+      Exceptions::ThrowArgumentError(list);
+    }
+    if (end > Smi::Value(TypedDataView::Length(list))) {
+      Exceptions::ThrowArgumentError(end_obj);
+    }
+    const Instance& data_obj = Instance::Handle(isolate,
+                                                TypedDataView::Data(list));
+    intptr_t data_offset = Smi::Value(TypedDataView::OffsetInBytes(list));
+    if (data_obj.IsTypedData()) {
+      const TypedData& array = TypedData::Cast(data_obj);
+      return TwoByteString::New(array, data_offset + start * sizeof(uint16_t),
+                                length, space);
+    } else if (data_obj.IsExternalTypedData()) {
+      const ExternalTypedData& array = ExternalTypedData::Cast(data_obj);
+      return TwoByteString::New(array, data_offset + start * sizeof(uint16_t),
+                                length, space);
+    }
+  } else if (list.IsArray()) {
+    const Array& array = Array::Cast(list);
+    if (end > array.Length()) {
+      Exceptions::ThrowArgumentError(end_obj);
+    }
+    const String& string = String::Handle(isolate,
+                                          TwoByteString::New(length, space));
+    for (int i = 0; i < length; i++) {
+      intptr_t value =
+          Smi::Value(reinterpret_cast<RawSmi*>(array.At(start + i)));
+      TwoByteString::SetCharAt(string, i, value);
+    }
+    return string.raw();
+  } else if (list.IsGrowableObjectArray()) {
+    const GrowableObjectArray& array = GrowableObjectArray::Cast(list);
+    if (end > array.Length()) {
+      Exceptions::ThrowArgumentError(end_obj);
+    }
+    const String& string = String::Handle(isolate,
+                                          TwoByteString::New(length, space));
+    for (int i = 0; i < length; i++) {
+      intptr_t value =
+          Smi::Value(reinterpret_cast<RawSmi*>(array.At(start + i)));
+      TwoByteString::SetCharAt(string, i, value);
+    }
+    return string.raw();
+  }
+  UNREACHABLE();
+  return Object::null();
+}
+
+
 DEFINE_NATIVE_ENTRY(String_getHashCode, 1) {
   const String& receiver = String::CheckedHandle(arguments->NativeArgAt(0));
   intptr_t hash_val = receiver.Hash();
diff --git a/runtime/lib/string_patch.dart b/runtime/lib/string_patch.dart
index f22b6e1..9d938c5 100644
--- a/runtime/lib/string_patch.dart
+++ b/runtime/lib/string_patch.dart
@@ -2,10 +2,18 @@
 // 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.
 
+const int _maxAscii = 0x7f;
+const int _maxLatin1 = 0xff;
+const int _maxUtf16 = 0xffff;
+const int _maxUnicode = 0x10ffff;
+
 patch class String {
   /* patch */ factory String.fromCharCodes(Iterable<int> charCodes,
                                            [int start = 0, int end]) {
-    return _StringBase.createFromCharCodes(charCodes, start, end);
+    if (charCodes is! Iterable) throw new ArgumentError.value(charCodes, "charCodes");
+    if (start is! int) throw new ArgumentError.value(start, "start");
+    if (end != null && end is! int) throw new ArgumentError.value(end, "end");
+    return _StringBase.createFromCharCodes(charCodes, start, end, null);
   }
 
   /* patch */ factory String.fromCharCode(int charCode) {
@@ -80,11 +88,19 @@
   int get hashCode native "String_getHashCode";
 
   /**
-   *  Create the most efficient string representation for specified
-   *  [codePoints].
+   * Create the most efficient string representation for specified
+   * [charCodes].
+   *
+   * Only uses the character codes betwen index [start] and index [end] of
+   * `charCodes`. They must satisfy `0 <= start <= end <= charCodes.length`.
+   *
+   * The [limit] is an upper limit on the character codes in the iterable.
+   * It's `null` if unknown.
    */
   static String createFromCharCodes(Iterable<int> charCodes,
-                                    int start, int end) {
+                                    int start, int end,
+                                    int limit) {
+    if (start == null) throw new ArgumentError.notNull("start");
     if (charCodes == null) throw new ArgumentError(charCodes);
     // TODO(srdjan): Also skip copying of wide typed arrays.
     final ccid = ClassID.getID(charCodes);
@@ -93,68 +109,102 @@
         (ccid != ClassID.cidGrowableObjectArray) &&
         (ccid != ClassID.cidImmutableArray)) {
       if (charCodes is Uint8List) {
-        isOneByteString = true;
-      } else {
-        // Treat charCodes as Iterable.
-        if (start < 0) throw new RangeError.range(start, 0, charCodes.length);
-        if (end != null && end < start) {
-          throw new RangeError.range(end, start, charCodes.length);
-        }
-        var it = charCodes.iterator;
-        for (int i = 0; i < start; i++) {
-          if (!it.moveNext()) {
-            throw new RangeError.range(start, 0, i);
-          }
-        }
-        int bits = 0;  // Bitwise or of all char codes in list.
-        var list = [];
-        if (end == null) {
-          while (it.moveNext()) {
-            int code = it.current;
-            bits |= code;
-            list.add(code);
-          }
-        } else {
-          for (int i = start; i < end; i++) {
-            if (!it.moveNext()) {
-              throw new RangeError.range(end, start, i);
-            }
-            int code = it.current;
-            bits |= code;
-            list.add(code);
-          }
-        }
-        charCodes = list;
-        isOneByteString = (bits >= 0 && bits <= 0xff);
-        start = 0;
-        end = list.length;
+        end = RangeError.checkValidRange(start, end, charCodes.length);
+        return _createOneByteString(charCodes, start, end - start);
+      } else if (charCodes is! Uint16List) {
+        return _createStringFromIterable(charCodes, start, end);
       }
     }
     int codeCount = charCodes.length;
-    if (start < 0 || start > codeCount) {
-      throw new RangeError.range(start, 0, codeCount);
-    }
-    if (end == null) {
-      end = codeCount;
-    } else if (end < start || end > codeCount) {
-      throw new RangeError.range(end, start, codeCount);
-    }
+    end = RangeError.checkValidRange(start, end, codeCount);
     final len = end - start;
-    if (!isOneByteString) {
-      for (int i = start; i < end; i++) {
-        int e = charCodes[i];
-        if (e is! _Smi) throw new ArgumentError(e);
-        // Is e Latin1?
-        if ((e < 0) || (e > 0xFF)) {
-          return _createFromCodePoints(charCodes, start, end);
-        }
+    if (len == 0) return "";
+    if (limit == null) {
+      limit = _scanCodeUnits(charCodes, start, end);
+    }
+    if (limit < 0) {
+      throw new ArgumentError(charCodes);
+    }
+    if (limit <= _maxLatin1) {
+      return _createOneByteString(charCodes, start, len);
+    }
+    if (limit <= _maxUtf16) {
+      return _TwoByteString._allocateFromTwoByteList(charCodes, start, end);
+    }
+    // TODO(lrn): Consider passing limit to _createFromCodePoints, because
+    // the function is currently fully generic and doesn't know that its
+    // charCodes are not all Latin-1 or Utf-16.
+    return _createFromCodePoints(charCodes, start, end);
+  }
+
+  static int _scanCodeUnits(List<int> charCodes, int start, int end) {
+    int bits = 0;
+    for (int i = start; i < end; i++) {
+      int code = charCodes[i];
+      if (code is! _Smi) throw new ArgumentError(charCodes);
+      bits |= code;
+    }
+    return bits;
+  }
+
+  static String _createStringFromIterable(Iterable<int> charCodes,
+                                          int start, int end) {
+    // Treat charCodes as Iterable.
+    if (charCodes is EfficientLength) {
+      int length = charCodes.length;
+      end = RangeError.checkValidRange(start, end, length);
+      List charCodeList = new List.from(charCodes.take(end).skip(start),
+                                        growable: false);
+      return createFromCharCodes(charCodeList, 0, charCodeList.length, null);
+    }
+    // Don't know length of iterable, so iterate and see if all the values
+    // are there.
+    if (start < 0) throw new RangeError.range(start, 0, charCodes.length);
+    var it = charCodes.iterator;
+    for (int i = 0; i < start; i++) {
+      if (!it.moveNext()) {
+        throw new RangeError.range(start, 0, i);
       }
     }
-    // Allocate a one byte string. When the list is 128 entries or longer,
-    // it's faster to perform a runtime-call.
-    if (len >= 128) {
-      return _OneByteString._allocateFromOneByteList(charCodes, start, end);
+    List charCodeList;
+    int bits = 0;  // Bitwise-or of all char codes in list.
+    if (end == null) {
+      var list = [];
+      while (it.moveNext()) {
+        int code = it.current;
+        bits |= code;
+        list.add(code);
+      }
+      charCodeList = makeListFixedLength(list);
+    } else {
+      if (end < start) {
+        throw new RangeError.range(end, start, charCodes.length);
+      }
+      int len = end - start;
+      var list = new List(len);
+      for (int i = 0; i < len; i++) {
+        if (!it.moveNext()) {
+          throw new RangeError.range(end, start, start + i);
+        }
+        int code = it.current;
+        bits |= code;
+        list[i] = code;
+      }
+      charCodeList = list;
     }
+    int length = charCodeList.length;
+    if (bits < 0) {
+      throw new ArgumentError(charCodes);
+    }
+    bool isOneByteString = (bits <= _maxLatin1);
+    if (isOneByteString) {
+      return _createOneByteString(charCodeList, 0, length);
+    }
+    return createFromCharCodes(charCodeList, 0, length, bits);
+  }
+
+  static String _createOneByteString(List<int> charCodes, int start, int len) {
+    // It's always faster to do this in Dart than to call into the runtime.
     var s = _OneByteString._allocate(len);
     for (int i = 0; i < len; i++) {
       s._setAt(i, charCodes[start + i]);
@@ -162,6 +212,12 @@
     return s;
   }
 
+  static String _createTwoByteString(List<int> charCodes, int start, int len) {
+    // TODO(lrn): Create string without scanning charCodes again - all values
+    // in the [start..end] range are uint16 values.
+    return _createFromCodePoints(charCodes, start, end);
+  }
+
   static String _createFromCodePoints(List<int> codePoints, int start, int end)
       native "StringBase_createFromCodePoints";
 
@@ -828,7 +884,7 @@
     return result;
   }
 
-  List<int> get codeUnits => new _CodeUnits(this);
+  List<int> get codeUnits => new CodeUnits(this);
 
   Runes get runes => new Runes(this);
 
@@ -1140,6 +1196,9 @@
         "_TwoByteString can only be allocated by the VM");
   }
 
+  static String _allocateFromTwoByteList(List list, int start, int end)
+      native "TwoByteString_allocateFromTwoByteList";
+
   bool _isWhitespace(int codeUnit) {
     return _StringBase._isTwoByteWhitespace(codeUnit);
   }
@@ -1212,17 +1271,3 @@
   final String input;
   final String pattern;
 }
-
-/**
- * An [Iterable] of the UTF-16 code units of a [String] in index order.
- */
-class _CodeUnits extends Object with ListMixin<int>,
-                                     UnmodifiableListMixin<int> {
-  /** The string that this is the code units of. */
-  String _string;
-
-  _CodeUnits(this._string);
-
-  int get length => _string.length;
-  int operator[](int i) => _string.codeUnitAt(i);
-}
diff --git a/sdk/lib/io/timer_impl.dart b/runtime/lib/timer_impl.dart
similarity index 97%
rename from sdk/lib/io/timer_impl.dart
rename to runtime/lib/timer_impl.dart
index c785cfc..4df37cd 100644
--- a/sdk/lib/io/timer_impl.dart
+++ b/runtime/lib/timer_impl.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-part of dart.io;
-
 // Timer heap implemented as a array-based binary heap[0].
 // This allows for O(1) `first`, O(log(n)) `remove`/`removeFirst` and O(log(n))
 // `add`.
@@ -263,7 +261,7 @@
       // No pending timers: Close the receive port and let the event handler
       // know.
       if (_receivePort != null) {
-        _EventHandler._sendData(null, _sendPort, _NO_TIMER);
+        VMLibraryHooks.eventHandlerSendData(null, _sendPort, _NO_TIMER);
         _shutdownTimerHandler();
       }
     } else {
@@ -281,14 +279,14 @@
         var wakeupTime = _heap.first._wakeupTime;
         if ((_scheduledWakeupTime == null) ||
             (wakeupTime != _scheduledWakeupTime)) {
-          _EventHandler._sendData(null, _sendPort, wakeupTime);
+          VMLibraryHooks.eventHandlerSendData(null, _sendPort, wakeupTime);
           _scheduledWakeupTime = wakeupTime;
         }
       }
     }
   }
 
-  static void _handleTimeout(pendingImmediateCallback) {
+  static void _handleTimeout() {
     // Fast exit if no timers have been scheduled.
     if (_heap.isEmpty && (_firstZeroTimer == null)) {
       assert(_receivePort == null);
@@ -398,7 +396,7 @@
             timer._addTimerToHeap();
           }
           // Execute pending micro tasks.
-          pendingImmediateCallback();
+          _runPendingImmediateCallback();
         }
       }
     } finally {
@@ -439,3 +437,7 @@
     return new _Timer(milliSeconds, callback);
   }
 }
+
+_setupHooks() {
+  VMLibraryHooks.timerFactory = _Timer._factory;
+}
diff --git a/runtime/lib/timer_patch.dart b/runtime/lib/timer_patch.dart
index 07755b2..f975daa 100644
--- a/runtime/lib/timer_patch.dart
+++ b/runtime/lib/timer_patch.dart
@@ -4,6 +4,10 @@
 
 patch class Timer {
   /*patch*/ static Timer _createTimer(Duration duration, void callback()) {
+    // TODO(iposva): Remove _TimerFactory and use VMLibraryHooks exclusively.
+    if (_TimerFactory._factory == null) {
+      _TimerFactory._factory = VMLibraryHooks.timerFactory;
+    }
     if (_TimerFactory._factory == null) {
       throw new UnsupportedError("Timer interface not supported.");
     }
@@ -14,6 +18,10 @@
 
   /*patch*/ static Timer _createPeriodicTimer(Duration duration,
                                               void callback(Timer timer)) {
+    // TODO(iposva): Remove _TimerFactory and use VMLibraryHooks exclusively.
+    if (_TimerFactory._factory == null) {
+      _TimerFactory._factory = VMLibraryHooks.timerFactory;
+    }
     if (_TimerFactory._factory == null) {
       throw new UnsupportedError("Timer interface not supported.");
     }
@@ -27,12 +35,8 @@
                                    void callback(Timer timer),
                                    bool repeating);
 
+// Warning: Dartium sets _TimerFactory._factory instead of setting things up
+// through VMLibraryHooks.timerFactory.
 class _TimerFactory {
   static _TimerFactoryClosure _factory;
 }
-
-// TODO(ahe): Warning: this is NOT called by Dartium. Instead, it sets
-// [_TimerFactory._factory] directly.
-void _setTimerFactoryClosure(_TimerFactoryClosure closure) {
-  _TimerFactory._factory = closure;
-}
diff --git a/runtime/lib/typed_data.dart b/runtime/lib/typed_data.dart
index 84905ef..6935e2f 100644
--- a/runtime/lib/typed_data.dart
+++ b/runtime/lib/typed_data.dart
@@ -241,11 +241,19 @@
 
 // Based class for _TypedList that provides common methods for implementing
 // the collection and list interfaces.
-// TODO(13647): Make this extends ListBase<T>
+// This class does not extend ListBase<T> since that would add type arguments
+// to instances of _TypeListBase. Instead the subclasses use type specific
+// mixins (like _IntListMixin, _DoubleListMixin) to implement ListBase<T>.
 abstract class _TypedListBase {
 
   // Method(s) implementing the Collection interface.
-  bool contains(element) => IterableMixinWorkaround.contains(this, element);
+  bool contains(element) {
+    var len = this.length;
+    for (var i = 0; i < len; ++i) {
+      if (this[i] == element) return true;
+    }
+    return false;
+  }
 
   void forEach(void f(element)) {
     var len = this.length;
@@ -255,44 +263,90 @@
   }
 
   String join([String separator = ""]) {
-    return IterableMixinWorkaround.join(this, separator);
+    StringBuffer buffer = new StringBuffer();
+    buffer.writeAll(this, separator);
+    return buffer.toString();
   }
 
   dynamic reduce(dynamic combine(value, element)) {
-    return IterableMixinWorkaround.reduce(this, combine);
+    var len = this.length;
+    if (len == 0) throw IterableElementError.noElement();
+    var i = 0;
+    var value = this[0];
+    for (var i = 1; i < len; ++i) {
+      value = combine(value, this[i]);
+    }
+    return value;
   }
 
   dynamic fold(dynamic initialValue,
                dynamic combine(dynamic initialValue, element)) {
-    return IterableMixinWorkaround.fold(this, initialValue, combine);
+    var len = this.length;
+    for (var i = 0; i < len; ++i) {
+      initialValue = combine(initialValue, this[i]);
+    }
+    return initialValue;
   }
 
-  Iterable map(f(element)) {
-    return IterableMixinWorkaround.mapList(this, f);
-  }
+  Iterable map(f(element)) => new MappedIterable(this, f);
 
-  Iterable expand(Iterable f(element)) {
-    return IterableMixinWorkaround.expand(this, f);
-  }
+  Iterable expand(Iterable f(element)) => new ExpandIterable(this, f);
 
   bool every(bool f(element)) {
-    return IterableMixinWorkaround.every(this, f);
+    var len = this.length;
+    for (var i = 0; i < len; ++i) {
+      if (!f(this[i])) return false;
+    }
+    return true;
   }
 
   bool any(bool f(element)) {
-    return IterableMixinWorkaround.any(this, f);
+    var len = this.length;
+    for (var i = 0; i < len; ++i) {
+      if (f(this[i])) return true;
+    }
+    return false;
   }
 
   dynamic firstWhere(bool test(element), {orElse()}) {
-    return IterableMixinWorkaround.firstWhere(this, test, orElse);
+    var len = this.length;
+    for (var i = 0; i < len; ++i) {
+      var element = this[i];
+      if (test(element)) return element;
+    }
+    if (orElse != null) return orElse();
+    throw IterableElementError.noElement();
   }
 
   dynamic lastWhere(bool test(element), {orElse()}) {
-    return IterableMixinWorkaround.lastWhereList(this, test, orElse);
+    var result = null;
+    var len = this.length;
+    for (var i = len - 1; i >= 0; --i) {
+      var element = this[i];
+      if (test(element)) {
+        return element;
+      }
+    }
+    if (orElse != null) return orElse();
+    throw IterableElementError.noElement();
   }
 
   dynamic singleWhere(bool test(element)) {
-    return IterableMixinWorkaround.singleWhere(this, test);
+    var result = null;
+    bool foundMatching = false;
+    var len = this.length;
+    for (var i = 0; i < len; ++i) {
+      var element = this[i];
+      if (test(element)) {
+        if (foundMatching) {
+          throw IterableElementError.tooMany();
+        }
+        result = element;
+        foundMatching = true;
+      }
+    }
+    if (foundMatching) return result;
+    throw IterableElementError.noElement();
   }
 
   dynamic elementAt(int index) {
@@ -333,19 +387,29 @@
   }
 
   void sort([int compare(a, b)]) {
-    IterableMixinWorkaround.sortList(this, compare);
+    if (compare == null) compare = Comparable.compare;
+    Sort.sort(this, compare);
   }
 
   void shuffle([Random random]) {
-    IterableMixinWorkaround.shuffleList(this, random);
+    if (random == null) random = new Random();
+    var i = this.length;
+    while (i > 1) {
+      int pos = random.nextInt(i);
+      i -= 1;
+      var tmp = this[i];
+      this[i] = this[pos];
+      this[pos] = tmp;
+    }
   }
 
   int indexOf(element, [int start = 0]) {
-    return IterableMixinWorkaround.indexOfList(this, element, start);
+    return Lists.indexOf(this, element, start, this.length);
   }
 
   int lastIndexOf(element, [int start = null]) {
-    return IterableMixinWorkaround.lastIndexOfList(this, element, start);
+    if (start == null) start = this.length - 1;
+    return Lists.lastIndexOf(this, element, start);
   }
 
   void clear() {
@@ -380,18 +444,18 @@
 
   dynamic get first {
     if (length > 0) return this[0];
-    throw new StateError("No elements");
+    throw IterableElementError.noElement();
   }
 
   dynamic get last {
     if (length > 0) return this[length - 1];
-    throw new StateError("No elements");
+    throw IterableElementError.noElement();
   }
 
   dynamic get single {
     if (length == 1) return this[0];
-    if (length == 0) throw new StateError("No elements");
-    throw new StateError("More than one element");
+    if (length == 0) throw IterableElementError.noElement();
+    throw IterableElementError.tooMany();
   }
 
   void removeRange(int start, int end) {
@@ -414,7 +478,7 @@
 
   List sublist(int start, [int end]) {
     if (end == null) end = this.length;
-    int length = end - start;
+    var length = end - start;
     _rangeCheck(this.length, start, length);
     List result = _createList(length);
     result.setRange(0, length, this, start);
@@ -438,7 +502,7 @@
 
     final count = end - start;
     if ((from.length - skipCount) < count) {
-      throw new StateError("Not enough elements");
+      throw IterableElementError.tooFew();
     }
 
     if (from is _TypedListBase) {
@@ -459,17 +523,30 @@
         // an intermediate structure.
         // TODO(srdjan): Optimize to skip copying if the range does not overlap.
         final temp_buffer = new List(count);
-        for (int i = 0; i < count; i++) {
+        for (var i = 0; i < count; i++) {
           temp_buffer[i] = from[skipCount + i];
         }
-        for (int i = start; i < end; i++) {
+        for (var i = start; i < end; i++) {
           this[i] = temp_buffer[i - start];
         }
         return;
       }
     }
-    IterableMixinWorkaround.setRangeList(this, start,
-                                         end, from, skipCount);
+
+    if (count == 0) return;
+    List otherList;
+    int otherStart;
+    if (from is List) {
+      otherList = from;
+      otherStart = skipCount;
+    } else {
+      otherList = from.skip(skipCount).toList(growable: false);
+      otherStart = 0;
+    }
+    if (otherStart + count > otherList.length) {
+      throw IterableElementError.tooFew();
+    }
+    Lists.copy(otherList, otherStart, this, start, count);
   }
 
   void setAll(int index, Iterable iterable) {
@@ -478,7 +555,10 @@
   }
 
   void fillRange(int start, int end, [fillValue]) {
-    IterableMixinWorkaround.fillRangeList(this, start, end, fillValue);
+    RangeError.checkValidRange(start, end, this.length);
+    for (var i = start; i < end; ++i) {
+      this[i] = fillValue;
+    }
   }
 
 
@@ -829,6 +909,24 @@
   Float64x2 _getFloat64x2(int offsetInBytes) native "TypedData_GetFloat64x2";
   void _setFloat64x2(int offsetInBytes, Float64x2 value)
       native "TypedData_SetFloat64x2";
+
+  /**
+   * Stores the [CodeUnits] as UTF-16 units into this TypedData at
+   * positions [start]..[end] (uint16 indices).
+   */
+  void _setCodeUnits(CodeUnits units,
+                     int byteStart, int length, int skipCount) {
+    assert(byteStart + length * Uint16List.BYTES_PER_ELEMENT <= lengthInBytes);
+    String string = CodeUnits.stringOf(units);
+    int sliceEnd = skipCount + length;
+    RangeError.checkValidRange(skipCount, sliceEnd,
+                               string.length,
+                               "skipCount", "skipCount + length");
+    for (int i = 0; i < length; i++) {
+      _setUint16(byteStart + i * Uint16List.BYTES_PER_ELEMENT,
+                 string.codeUnitAt(skipCount + i));
+    }
+  }
 }
 
 
@@ -979,6 +1077,16 @@
     _setIndexedInt16(index, _toInt16(value));
   }
 
+  void setRange(int start, int end, Iterable iterable, [int skipCount = 0]) {
+    if (ClassID.getID(iterable) == CodeUnits.cid) {
+      end = RangeError.checkValidRange(start, end, this.length);
+      int length = end - start;
+      int byteStart = this.offsetInBytes + start * Int16List.BYTES_PER_ELEMENT;
+      _setCodeUnits(iterable, byteStart, length, skipCount);
+    } else {
+      super.setRange(start, end, iterable, skipCount);
+    }
+  }
 
   // Method(s) implementing TypedData interface.
 
@@ -1029,6 +1137,16 @@
     _setIndexedUint16(index, _toUint16(value));
   }
 
+  void setRange(int start, int end, Iterable iterable, [int skipCount = 0]) {
+    if (ClassID.getID(iterable) == CodeUnits.cid) {
+      end = RangeError.checkValidRange(start, end, this.length);
+      int length = end - start;
+      int byteStart = this.offsetInBytes + start * Uint16List.BYTES_PER_ELEMENT;
+      _setCodeUnits(iterable, byteStart, length, skipCount);
+    } else {
+      super.setRange(start, end, iterable, skipCount);
+    }
+  }
 
   // Method(s) implementing the TypedData interface.
 
@@ -2453,7 +2571,7 @@
     return _typedData.buffer;
   }
 
-  final TypedData _typedData;
+  final _TypedList _typedData;
   final int offsetInBytes;
   final int length;
 }
@@ -2633,6 +2751,16 @@
                          _toInt16(value));
   }
 
+  void setRange(int start, int end, Iterable iterable, [int skipCount = 0]) {
+    if (ClassID.getID(iterable) == CodeUnits.cid) {
+      end = RangeError.checkValidRange(start, end, this.length);
+      int length = end - start;
+      int byteStart = this.offsetInBytes + start * Int16List.BYTES_PER_ELEMENT;
+      _typedData._setCodeUnits(iterable, byteStart, length, skipCount);
+    } else {
+      super.setRange(start, end, iterable, skipCount);
+    }
+  }
 
   // Method(s) implementing TypedData interface.
 
@@ -2681,6 +2809,16 @@
                           _toUint16(value));
   }
 
+  void setRange(int start, int end, Iterable iterable, [int skipCount = 0]) {
+    if (ClassID.getID(iterable) == CodeUnits.cid) {
+      end = RangeError.checkValidRange(start, end, this.length);
+      int length = end - start;
+      int byteStart = this.offsetInBytes + start * Uint16List.BYTES_PER_ELEMENT;
+      _typedData._setCodeUnits(iterable, byteStart, length, skipCount);
+    } else {
+      super.setRange(start, end, iterable, skipCount);
+    }
+  }
 
   // Method(s) implementing TypedData interface.
 
@@ -2688,7 +2826,6 @@
     return Uint16List.BYTES_PER_ELEMENT;
   }
 
-
   // Internal utility methods.
 
   Uint16List _createList(int length) {
diff --git a/runtime/observatory/bin/shell.dart b/runtime/observatory/bin/shell.dart
index 31067fa..ef2459c 100644
--- a/runtime/observatory/bin/shell.dart
+++ b/runtime/observatory/bin/shell.dart
@@ -19,15 +19,15 @@
 
 void repl(VM vm, String prefix, String lastResult) {
   print(lastResult);
-  // TODO(koda): Use 'get' when ServiceObjects have more informative toString.
-  vm.getString(prefix + stdin.readLineSync()).then((String result) {
+  // TODO(turnidge): use the non-deprecated api here.
+  vm.getStringDeprecated(prefix + stdin.readLineSync()).then((String result) {
     repl(vm, prefix, result);
   });
 }
 
 void main() {
   String addr = 'ws://localhost:8181/ws';
-  new WebSocketVM(new WebSocketVMTarget(addr)).get('vm').then((VM vm) {
+  new WebSocketVM(new WebSocketVMTarget(addr)).load().then((VM vm) {
     Isolate isolate = vm.isolates.first;
     String prefix = '${isolate.link}';
     repl(vm, prefix, 'prefix $prefix');
diff --git a/runtime/observatory/lib/service_common.dart b/runtime/observatory/lib/service_common.dart
index 18567b7..c082fdf 100644
--- a/runtime/observatory/lib/service_common.dart
+++ b/runtime/observatory/lib/service_common.dart
@@ -54,9 +54,14 @@
 }
 
 class _WebSocketRequest {
-  final String id;
+  final String method;
+  final Map params;
   final Completer<String> completer;
-  _WebSocketRequest(this.id)
+
+   _WebSocketRequest.old(this.method)
+      : params = null, completer = new Completer<String>();
+
+   _WebSocketRequest.rpc(this.method, this.params)
       : completer = new Completer<String>();
 }
 
@@ -123,7 +128,7 @@
     _notifyDisconnect();
   }
 
-  Future<String> getString(String id) {
+  Future<String> getStringDeprecated(String id) {
     if (!_hasInitiatedConnect) {
       _hasInitiatedConnect = true;
       _webSocket.connect(
@@ -137,7 +142,25 @@
     assert(_hasInitiatedConnect);
     // Create request.
     String serial = (_requestSerial++).toString();
-    var request = new _WebSocketRequest(id);
+    var request = new _WebSocketRequest.old(id);
+    if (_webSocket.isOpen) {
+      // Already connected, send request immediately.
+      _sendRequest(serial, request);
+    } else {
+      // Not connected yet, add to delayed requests.
+      _delayedRequests[serial] = request;
+    }
+    return request.completer.future;
+  }
+
+  Future<String> invokeRpcRaw(String method, Map params) {
+    if (!_hasInitiatedConnect) {
+      _hasInitiatedConnect = true;
+      _webSocket.connect(
+          target.networkAddress, _onOpen, _onMessage, _onError, _onClose);
+    }
+    String serial = (_requestSerial++).toString();
+    var request = new _WebSocketRequest.rpc(method, params);
     if (_webSocket.isOpen) {
       // Already connected, send request immediately.
       _sendRequest(serial, request);
@@ -203,7 +226,7 @@
       serial = map['params']['id'].toString();
       response = map['params']['data'];
     } else {
-      serial = map['seq'];
+      serial = map['id'];
       response = map['response'];
     }
     if (serial == null) {
@@ -266,8 +289,8 @@
   /// Send the request over WebSocket.
   void _sendRequest(String serial, _WebSocketRequest request) {
     assert (_webSocket.isOpen);
-    if (!request.id.endsWith('/profile/tag')) {
-      Logger.root.info('GET ${request.id} from ${target.networkAddress}');
+    if (request.method != 'getTagProfile') {
+      Logger.root.info('GET ${request.method} from ${target.networkAddress}');
     }
     // Mark request as pending.
     assert(_pendingRequests.containsKey(serial) == false);
@@ -280,11 +303,13 @@
         'method': 'Dart.observatoryQuery',
         'params': {
           'id': serial,
-          'query': request.id
+          'query': request.method
         }
       });
     } else {
-      message = JSON.encode({'seq': serial, 'request': request.id});
+      message = JSON.encode({'id': serial,
+                             'method': request.method,
+                             'params': request.params});
     }
     // Send message.
     _webSocket.send(message);
diff --git a/runtime/observatory/lib/service_html.dart b/runtime/observatory/lib/service_html.dart
index da5a975..fe5b1c3 100644
--- a/runtime/observatory/lib/service_html.dart
+++ b/runtime/observatory/lib/service_html.dart
@@ -5,7 +5,6 @@
 library service_html;
 
 import 'dart:async';
-import 'dart:convert';
 import 'dart:html';
 import 'dart:typed_data';
 
@@ -28,17 +27,17 @@
     _webSocket.onOpen.listen((Event) => onOpen());
     _webSocket.onMessage.listen((MessageEvent event) => onMessage(event.data));
   }
-  
+
   bool get isOpen => _webSocket.readyState == WebSocket.OPEN;
-  
+
   void send(dynamic data) {
     _webSocket.send(data);
   }
-  
+
   void close() {
     _webSocket.close();
   }
-  
+
   Future<ByteData> nonStringToByteData(dynamic data) {
     assert(data is Blob);
     FileReader fileReader = new FileReader();
@@ -58,46 +57,3 @@
 class WebSocketVM extends CommonWebSocketVM {
   WebSocketVM(WebSocketVMTarget target) : super(target, new _HtmlWebSocket());
 }
-
-// A VM that communicates with the service via posting messages from DevTools.
-class PostMessageVM extends VM {
-  final Completer _connected = new Completer();
-  final Completer _disconnected = new Completer();
-  void disconnect() { /* nope */ }
-  Future get onConnect => _connected.future;
-  Future get onDisconnect => _disconnected.future;
-  final Map<String, Completer> _pendingRequests =
-      new Map<String, Completer>();
-  int _requestSerial = 0;
-
-  PostMessageVM() : super() {
-    window.onMessage.listen(_messageHandler);
-    _connected.complete(this);
-  }
-
-  void _messageHandler(msg) {
-    var id = msg.data['id'];
-    var name = msg.data['name'];
-    var data = msg.data['data'];
-    if (name != 'observatoryData') {
-      return;
-    }
-    var completer = _pendingRequests[id];
-    assert(completer != null);
-    _pendingRequests.remove(id);
-    completer.complete(data);
-  }
-
-  Future<String> getString(String path) {
-    var idString = '$_requestSerial';
-    Map message = {};
-    message['id'] = idString;
-    message['method'] = 'observatoryQuery';
-    message['query'] = '$path';
-    _requestSerial++;
-    var completer = new Completer();
-    _pendingRequests[idString] = completer;
-    window.parent.postMessage(JSON.encode(message), '*');
-    return completer.future;
-  }
-}
diff --git a/runtime/observatory/lib/src/app/application.dart b/runtime/observatory/lib/src/app/application.dart
index a280f4e..cee60ba 100644
--- a/runtime/observatory/lib/src/app/application.dart
+++ b/runtime/observatory/lib/src/app/application.dart
@@ -105,6 +105,9 @@
   void _registerPages() {
     _pageRegistry.add(new ClassTreePage(this));
     _pageRegistry.add(new DebuggerPage(this));
+    _pageRegistry.add(new CpuProfilerPage(this));
+    _pageRegistry.add(new AllocationProfilerPage(this));
+    _pageRegistry.add(new HeapMapPage(this));
     _pageRegistry.add(new VMConnectPage(this));
     _pageRegistry.add(new ErrorViewPage(this));
     _pageRegistry.add(new MetricsPage(this));
@@ -192,13 +195,6 @@
     currentPage = page;
   }
 
-  ObservatoryApplication.devtools(this.rootElement) :
-      locationManager = new HashLocationManager(),
-      targets = null {
-    vm = new PostMessageVM();
-    _initOnce(true);
-  }
-
   ObservatoryApplication(this.rootElement) :
       locationManager = new HashLocationManager(),
       targets = new TargetManager() {
diff --git a/runtime/observatory/lib/src/app/page.dart b/runtime/observatory/lib/src/app/page.dart
index 518946c..2942905 100644
--- a/runtime/observatory/lib/src/app/page.dart
+++ b/runtime/observatory/lib/src/app/page.dart
@@ -59,7 +59,7 @@
       return;
     }
     /// Request url from VM and display it.
-    app.vm.get(url).then((obj) {
+    app.vm.getDeprecated(url).then((obj) {
       ServiceObjectViewElement serviceElement = element;
       serviceElement.object = obj;
     }).catchError((e) {
@@ -71,71 +71,111 @@
   bool canVisit(String url) => true;
 }
 
-/// Class tree page.
-class ClassTreePage extends Page {
-  static const _urlPrefix = 'class-tree/';
-
-  ClassTreePage(app) : super(app);
+class IsolateSuffixPage extends Page {
+  final String pagePrefix;
+  final String elementTagName;
+  String _isolateId;
+  String get isolateId => _isolateId;
+  IsolateSuffixPage(this.pagePrefix, this.elementTagName, app) : super(app);
 
   void onInstall() {
     if (element == null) {
-      element = new Element.tag('class-tree');
+      element = new Element.tag(elementTagName);
     }
   }
 
   void _visit(String url) {
-    assert(element != null);
+    assert(url != null);
     assert(canVisit(url));
-    // ClassTree urls are 'class-tree/isolate-id', chop off prefix, leaving
-    // isolate url.
-    url = url.substring(_urlPrefix.length);
-    /// Request the isolate url.
-    app.vm.get(url).then((isolate) {
+    _isolateId = url.substring(pagePrefix.length);
+  }
+
+  Future<Isolate> getIsolate() {
+    return app.vm.getIsolate(isolateId).catchError((e) {
+      Logger.root.severe('$pagePrefix visit error: $e');
+      return e;
+    });
+  }
+
+  bool canVisit(String url) => url.startsWith(pagePrefix);
+}
+
+
+/// Class tree page.
+class ClassTreePage extends IsolateSuffixPage {
+  ClassTreePage(app) : super('class-tree/', 'class-tree', app);
+
+  void _visit(String url) {
+    super._visit(url);
+    getIsolate().then((isolate) {
       if (element != null) {
         /// Update the page.
         ClassTreeElement page = element;
         page.isolate = isolate;
       }
-    }).catchError((e) {
-      Logger.root.severe('ClassTreePage visit error: $e');
     });
   }
-
-  /// Catch all.
-  bool canVisit(String url) => url.startsWith(_urlPrefix);
 }
 
-class DebuggerPage extends Page {
-  static const _urlPrefix = 'debugger/';
-
-  DebuggerPage(app) : super(app);
-
-  void onInstall() {
-    if (element == null) {
-      element = new Element.tag('debugger-page');
-    }
-  }
+class DebuggerPage extends IsolateSuffixPage {
+  DebuggerPage(app) : super('debugger/', 'debugger-page', app);
 
   void _visit(String url) {
-    assert(element != null);
-    assert(canVisit(url));
-    // Debugger urls are 'debugger/isolate-id', chop off prefix, leaving
-    // isolate url.
-    url = url.substring(_urlPrefix.length);
-    /// Request the isolate url.
-    app.vm.get(url).then((isolate) {
+    super._visit(url);
+    getIsolate().then((isolate) {
       if (element != null) {
         /// Update the page.
         DebuggerPageElement page = element;
         page.isolate = isolate;
       }
-    }).catchError((e) {
-        Logger.root.severe('Unexpected debugger error: $e');
     });
   }
+}
 
-  /// Catch all.
-  bool canVisit(String url) => url.startsWith(_urlPrefix);
+class CpuProfilerPage extends IsolateSuffixPage {
+  CpuProfilerPage(app) : super('profiler/', 'cpu-profile', app);
+
+  void _visit(String url) {
+    super._visit(url);
+    getIsolate().then((isolate) {
+      if (element != null) {
+        /// Update the page.
+        CpuProfileElement page = element;
+        page.isolate = isolate;
+      }
+    });
+  }
+}
+
+class AllocationProfilerPage extends IsolateSuffixPage {
+  AllocationProfilerPage(app)
+      : super('allocation-profiler/', 'heap-profile', app);
+
+  void _visit(String url) {
+    super._visit(url);
+    getIsolate().then((isolate) {
+      if (element != null) {
+        /// Update the page.
+        HeapProfileElement page = element;
+        page.isolate = isolate;
+      }
+    });
+  }
+}
+
+class HeapMapPage extends IsolateSuffixPage {
+  HeapMapPage(app) : super('heap-map/', 'heap-map', app);
+
+  void _visit(String url) {
+    super._visit(url);
+    getIsolate().then((isolate) {
+      if (element != null) {
+        /// Update the page.
+        HeapMapElement page = element;
+        page.isolate = isolate;
+      }
+    });
+  }
 }
 
 class ErrorViewPage extends Page {
@@ -236,7 +276,7 @@
   void _visit(String url) {
     assert(element != null);
     assert(canVisit(url));
-    app.vm.get(_isolateId(url)).then((i) {
+    app.vm.getIsolate(_isolateId(url)).then((i) {
       (element as MetricsPageElement).isolate = i;
     });
   }
diff --git a/runtime/observatory/lib/src/elements/class_view.dart b/runtime/observatory/lib/src/elements/class_view.dart
index e9e08d5..ac49f7a 100644
--- a/runtime/observatory/lib/src/elements/class_view.dart
+++ b/runtime/observatory/lib/src/elements/class_view.dart
@@ -17,15 +17,14 @@
   @observable ObservableList mostRetained;
   ClassViewElement.created() : super.created();
 
-  Future<ServiceObject> eval(String text) {
-    return cls.get("eval?expr=${Uri.encodeComponent(text)}");
+  Future<ServiceObject> eval(String expression) {
+    return cls.isolate.eval(cls, expression);
   }
 
   Future<ServiceObject> reachable(var limit) {
-    return cls.get("instances?limit=$limit")
-        .then((ServiceMap obj) {
-          instances = obj;
-        });
+    return cls.isolate.getInstances(cls, limit).then((ServiceMap obj) {
+      instances = obj;
+    });
   }
   
   Future<ServiceObject> retainedToplist(var limit) {
@@ -40,7 +39,7 @@
 
   // TODO(koda): Add no-arg "calculate-link" instead of reusing "eval-link".
   Future<ServiceObject> retainedSize(var dummy) {
-    return cls.get("retained").then((Instance obj) {
+    return cls.isolate.getRetainedSize(cls).then((Instance obj) {
       retainedBytes = int.parse(obj.valueAsString);
     });
   }
diff --git a/runtime/observatory/lib/src/elements/context_view.dart b/runtime/observatory/lib/src/elements/context_view.dart
index fdc05ec..2d7cf12 100644
--- a/runtime/observatory/lib/src/elements/context_view.dart
+++ b/runtime/observatory/lib/src/elements/context_view.dart
@@ -4,7 +4,6 @@
 
 library context_view_element;
 
-import 'dart:async';
 import 'observatory_element.dart';
 import 'package:observatory/service.dart';
 import 'package:polymer/polymer.dart';
diff --git a/runtime/observatory/lib/src/elements/cpu_profile.dart b/runtime/observatory/lib/src/elements/cpu_profile.dart
index 44b9e0b..154f80f 100644
--- a/runtime/observatory/lib/src/elements/cpu_profile.dart
+++ b/runtime/observatory/lib/src/elements/cpu_profile.dart
@@ -140,7 +140,9 @@
 @CustomTag('cpu-profile')
 class CpuProfileElement extends ObservatoryElement {
   CpuProfileElement.created() : super.created();
-  @published ServiceMap profile;
+  @published Isolate isolate;
+
+  @observable ServiceMap profile;
   @observable bool hideTagsChecked;
   @observable String sampleCount = '';
   @observable String refreshTime = '';
@@ -150,14 +152,52 @@
   @observable String timeSpan = '';
   @reflectable double displayThreshold = 0.0002; // 0.02%.
 
-  @observable String tagSelector = 'uv';
+  @observable String tagSelector = 'UserVM';
 
   final _id = '#tableTree';
   TableTree tree;
 
   static const MICROSECONDS_PER_SECOND = 1000000.0;
 
-  void profileChanged(oldValue) {
+  void isolateChanged(oldValue) {
+    if (isolate == null) {
+      profile = null;
+      return;
+    }
+    isolate.invokeRpc('getCpuProfile', { 'tags': tagSelector })
+      .then((ServiceObject obj) {
+          print(obj);
+          // Assert we got back the a profile.
+          assert(obj.type == 'CpuProfile');
+          profile = obj;
+          _update();
+      });
+  }
+
+  @override
+  void attached() {
+    super.attached();
+    var tableBody = shadowRoot.querySelector('#tableTreeBody');
+    assert(tableBody != null);
+    tree = new TableTree(tableBody, 2);
+    _update();
+  }
+
+  void tagSelectorChanged(oldValue) {
+    isolateChanged(null);
+  }
+
+  void refresh(var done) {
+    isolate.invokeRpc('getCpuProfile', { 'tags': tagSelector })
+      .then((ServiceObject obj) {
+          // Assert we got back the a profile.
+          assert(obj.type == 'CpuProfile');
+          profile = obj;
+          _update();
+      }).whenComplete(done);
+  }
+
+  void _update() {
     if (profile == null) {
       return;
     }
@@ -172,36 +212,6 @@
     displayCutoff = '${(displayThreshold * 100.0).toString()}%';
     profile.isolate.processProfile(profile);
     profile['threshold'] = displayThreshold;
-    _update();
-  }
-
-
-  @override
-  void attached() {
-    super.attached();
-    var tableBody = shadowRoot.querySelector('#tableTreeBody');
-    assert(tableBody != null);
-    tree = new TableTree(tableBody, 2);
-    _update();
-  }
-
-  void tagSelectorChanged(oldValue) {
-    refresh(null);
-  }
-
-  void refresh(var done) {
-    var request = 'profile?tags=$tagSelector';
-    profile.isolate.get(request).then((ServiceMap m) {
-      // Assert we got back the a profile.
-      assert(m.type == 'Profile');
-      profile = m;
-    }).whenComplete(done);
-  }
-
-  void _update() {
-    if (profile == null) {
-      return;
-    }
     _buildTree();
   }
 
diff --git a/runtime/observatory/lib/src/elements/cpu_profile.html b/runtime/observatory/lib/src/elements/cpu_profile.html
index 7955cc1..90b1518 100644
--- a/runtime/observatory/lib/src/elements/cpu_profile.html
+++ b/runtime/observatory/lib/src/elements/cpu_profile.html
@@ -10,8 +10,8 @@
     <link rel="stylesheet" href="css/shared.css">
     <nav-bar>
       <top-nav-menu></top-nav-menu>
-      <isolate-nav-menu isolate="{{ profile.isolate }}"></isolate-nav-menu>
-      <nav-menu link="{{ profile.isolate.relativeLink('profile') }}" anchor="cpu profile" last="{{ true }}"></nav-menu>
+      <isolate-nav-menu isolate="{{ isolate }}"></isolate-nav-menu>
+      <nav-menu link="{{ '/profiler' + isolate.link }}" anchor="cpu profile" last="{{ true }}"></nav-menu>
       <nav-refresh callback="{{ refresh }}"></nav-refresh>
       <nav-control></nav-control>
     </nav-bar>
@@ -131,11 +131,11 @@
          <div class="memberName">Tags</div>
          <div class="memberValue">
           <select value="{{tagSelector}}">
-            <option value="uv">User &gt; VM</option>
-            <option value="u">User</option>
-            <option value="vu">VM &gt; User</option>
-            <option value="v">VM</option>
-            <option value="hide">None</option>
+            <option value="UserVM">User &gt; VM</option>
+            <option value="UserOnly">User</option>
+            <option value="VMUser">VM &gt; User</option>
+            <option value="VMOnly">VM</option>
+            <option value="None">None</option>
           </select>
          </div>
         </div>
diff --git a/runtime/observatory/lib/src/elements/debugger.dart b/runtime/observatory/lib/src/elements/debugger.dart
index 1515bff..f17bacb 100644
--- a/runtime/observatory/lib/src/elements/debugger.dart
+++ b/runtime/observatory/lib/src/elements/debugger.dart
@@ -45,9 +45,9 @@
   @published int activeFrame = 0;
 
   isolateChanged(oldValue) {
-    isolate.get('stacktrace').then((result) {
+    isolate.getStack().then((result) {
         stack = result;
-      });
+    });
   }
 
   DebuggerStackElement.created() : super.created();
diff --git a/runtime/observatory/lib/src/elements/debugger.html b/runtime/observatory/lib/src/elements/debugger.html
index 0eeaaa9..347cba3 100644
--- a/runtime/observatory/lib/src/elements/debugger.html
+++ b/runtime/observatory/lib/src/elements/debugger.html
@@ -54,9 +54,10 @@
 
     <div class="container">
       <nav-bar>
-	<top-nav-menu last="{{ true }}"></top-nav-menu>
-	<isolate-nav-menu isolate="{{ isolate }}" last="{{ true }}">
+        <top-nav-menu></top-nav-menu>
+        <isolate-nav-menu isolate="{{ isolate }}">
 	</isolate-nav-menu>
+        <nav-menu link="{{ '/debugger' + isolate.link) }}" anchor="debugger" last="{{ true }}"></nav-menu>
 	<nav-control></nav-control>
       </nav-bar>
 
@@ -84,7 +85,7 @@
     </template>
     <template if="{{ stack != null }}">
       <ul class="list-group">
-        <template repeat="{{ frame in stack['members'] }}">
+        <template repeat="{{ frame in stack['frames'] }}">
           <li class="list-group-item">
             <debugger-frame frame="{{ frame }}"
                             expand="{{ frame['depth'] == activeFrame }}">
diff --git a/runtime/observatory/lib/src/elements/error_ref.dart b/runtime/observatory/lib/src/elements/error_ref.dart
index 14d364e..d69726b 100644
--- a/runtime/observatory/lib/src/elements/error_ref.dart
+++ b/runtime/observatory/lib/src/elements/error_ref.dart
@@ -5,7 +5,6 @@
 library error_ref_element;
 
 import 'package:polymer/polymer.dart';
-import 'package:observatory/service.dart';
 import 'service_ref.dart';
 
 @CustomTag('error-ref')
diff --git a/runtime/observatory/lib/src/elements/heap_map.dart b/runtime/observatory/lib/src/elements/heap_map.dart
index 1f37c23..2e36c2d 100644
--- a/runtime/observatory/lib/src/elements/heap_map.dart
+++ b/runtime/observatory/lib/src/elements/heap_map.dart
@@ -66,7 +66,8 @@
   static const _MAX_CANVAS_HEIGHT = 6000;
 
   @observable String status;
-  @published ServiceMap fragmentation;
+  @published Isolate isolate;
+  @observable ServiceMap fragmentation;
 
   HeapMapElement.created() : super.created() {
   }
@@ -97,7 +98,11 @@
   void _updateClassList(classList, int freeClassId) {
     for (var member in classList['members']) {
       if (member is! Class) {
-        Logger.root.info('$member');
+        // TODO(turnidge): The printing for some of these non-class
+        // members is broken.  Fix this:
+        //
+        // Logger.root.info('$member');
+        Logger.root.info('Ignoring non-class in class list');
         continue;
       }
       var classId = int.parse(member.id.split('/').last);
@@ -156,7 +161,7 @@
   void _handleClick(MouseEvent event) {
     var address = _objectAt(event.offset).address.toRadixString(16);
     app.locationManager.go(app.locationManager.makeLink(
-        "${fragmentation.isolate.relativeLink('address/$address')}"));
+        "${isolate.relativeLink('address/$address')}"));
   }
 
   void _updateFragmentationData() {
@@ -211,11 +216,24 @@
     });
   }
 
-  void refresh(var done) {
-    if (fragmentation == null) {
+  void isolateChanged(oldValue) {
+    if (isolate == null) {
+      fragmentation = null;
       return;
     }
-    fragmentation.isolate.get('heapmap').then((ServiceMap response) {
+    isolate.invokeRpc('getHeapMap', {}).then((ServiceMap response) {
+      assert(response['type'] == 'HeapMap');
+      fragmentation = response;
+    }).catchError((e, st) {
+      Logger.root.info('$e $st');
+    });
+  }
+
+  void refresh(var done) {
+    if (isolate == null) {
+      return;
+    }
+    isolate.invokeRpc('getHeapMap', {}).then((ServiceMap response) {
       assert(response['type'] == 'HeapMap');
       fragmentation = response;
     }).catchError((e, st) {
@@ -229,4 +247,4 @@
       _updateFragmentationData();
     });
   }
-}
\ No newline at end of file
+}
diff --git a/runtime/observatory/lib/src/elements/heap_profile.dart b/runtime/observatory/lib/src/elements/heap_profile.dart
index a0adf9e..c77f673 100644
--- a/runtime/observatory/lib/src/elements/heap_profile.dart
+++ b/runtime/observatory/lib/src/elements/heap_profile.dart
@@ -42,11 +42,11 @@
   @observable ClassSortedTable classTable;
   var _classTableBody;
 
-  @published ServiceMap profile;
   @published bool autoRefresh = false;
   var _subscription;
 
-  @observable Isolate isolate;
+  @published Isolate isolate;
+  @observable ServiceMap profile;
 
   HeapProfileElement.created() : super.created() {
     // Create pie chart models.
@@ -99,7 +99,7 @@
 
   @override
   void detached() {
-    _subscription.cancel();
+    _subscription.cancel((){});
     super.detached();
   }
   
@@ -112,7 +112,6 @@
   void _updatePieCharts() {
     assert(profile != null);
     _newPieDataTable.clearRows();
-    var isolate = profile.isolate;
     _newPieDataTable.addRow(['Used', isolate.newSpace.used]);
     _newPieDataTable.addRow(['Free',
         isolate.newSpace.capacity - isolate.newSpace.used]);
@@ -259,29 +258,36 @@
     }
   }
 
-  void refresh(var done) {
-    if (profile == null) {
+  void isolateChanged(oldValue) {
+    if (isolate == null) {
+      profile = null;
       return;
     }
-    var isolate = profile.isolate;
-    isolate.get('/allocationprofile').then(_update).whenComplete(done);
+    isolate.invokeRpc('getAllocationProfile', {}).then(_update);
+  }
+
+  void refresh(var done) {
+    if (isolate == null) {
+      return;
+    }
+    isolate.invokeRpc('getAllocationProfile', {})
+        .then(_update).whenComplete(done);
   }
 
   void refreshGC(var done) {
-    if (profile == null) {
+    if (isolate == null) {
       return;
     }
-    var isolate = profile.isolate;
-    isolate.get('/allocationprofile?gc=full').then(_update).whenComplete(done);
+    isolate.invokeRpc('getAllocationProfile', { 'gc': 'full' })
+        .then(_update).whenComplete(done);
   }
 
   void resetAccumulator(var done) {
-    if (profile == null) {
+    if (isolate == null) {
       return;
     }
-    var isolate = profile.isolate;
-    isolate.get('/allocationprofile?reset=true').then(_update).
-                                                 whenComplete(done);
+    isolate.invokeRpc('getAllocationProfile', { 'reset': 'true' })
+        .then(_update).whenComplete(done);
   }
 
   void _update(ServiceMap newProfile) {
@@ -292,7 +298,6 @@
     if (profile == null) {
       return;
     }
-    isolate = profile.isolate;
     isolate.updateHeapsFromMap(profile['heaps']);
     var millis = int.parse(profile['dateLastAccumulatorReset']);
     if (millis != 0) {
@@ -318,7 +323,7 @@
     if (profile == null) {
       return '';
     }
-    var heap = newSpace ? profile.isolate.newSpace : profile.isolate.oldSpace;
+    var heap = newSpace ? isolate.newSpace : isolate.oldSpace;
     var avg = ((heap.totalCollectionTimeInSeconds * 1000.0) / heap.collections);
     return '${avg.toStringAsFixed(2)} ms';
   }
@@ -327,7 +332,7 @@
     if (profile == null) {
       return '';
     }
-    var heap = newSpace ? profile.isolate.newSpace : profile.isolate.oldSpace;
+    var heap = newSpace ? isolate.newSpace : isolate.oldSpace;
     return heap.collections.toString();
   }
 
@@ -335,7 +340,7 @@
     if (profile == null) {
       return '';
     }
-    var heap = newSpace ? profile.isolate.newSpace : profile.isolate.oldSpace;
+    var heap = newSpace ? isolate.newSpace : isolate.oldSpace;
     return '${Utils.formatSeconds(heap.totalCollectionTimeInSeconds)} secs';
   }
 }
diff --git a/runtime/observatory/lib/src/elements/inbound_reference.dart b/runtime/observatory/lib/src/elements/inbound_reference.dart
index 047b833..39c8644 100644
--- a/runtime/observatory/lib/src/elements/inbound_reference.dart
+++ b/runtime/observatory/lib/src/elements/inbound_reference.dart
@@ -23,7 +23,7 @@
   // I.e., inbound references to 'source' for recursive pointer chasing.
   @observable ObservableList inboundReferences;
   Future<ServiceObject> fetchInboundReferences(arg) {
-    return source.isolate.get(source.id + "/inbound_references?limit=$arg")
+    return source.isolate.getInboundReferences(source, arg)
         .then((ServiceMap response) {
           inboundReferences = new ObservableList.from(response['references']);
         });
diff --git a/runtime/observatory/lib/src/elements/instance_view.dart b/runtime/observatory/lib/src/elements/instance_view.dart
index 556a279..96598c78 100644
--- a/runtime/observatory/lib/src/elements/instance_view.dart
+++ b/runtime/observatory/lib/src/elements/instance_view.dart
@@ -15,9 +15,8 @@
 
   InstanceViewElement.created() : super.created();
 
-  Future<ServiceObject> eval(String text) {
-    return instance.isolate.get(
-        instance.id + "/eval?expr=${Uri.encodeComponent(text)}");
+  Future<ServiceObject> eval(String expression) {
+    return instance.isolate.eval(instance, expression);
   }
 
   void refresh(Function onDone) {
diff --git a/runtime/observatory/lib/src/elements/isolate_summary.html b/runtime/observatory/lib/src/elements/isolate_summary.html
index ed3398f..5718cdb 100644
--- a/runtime/observatory/lib/src/elements/isolate_summary.html
+++ b/runtime/observatory/lib/src/elements/isolate_summary.html
@@ -162,17 +162,17 @@
         </div>
         <div class="memberItem">
           <div class="memberValue">
-            See <a on-click="{{ goto }}" _href="{{ gotoLink(isolate.relativeLink('profile')) }}">cpu profile</a>
+            See <a on-click="{{ goto }}" _href="{{ gotoLink('/profiler' + isolate.link) }}">cpu profile</a>
           </div>
         </div>
         <div class="memberItem">
           <div class="memberValue">
-            See <a on-click="{{ goto }}" _href="{{ gotoLink(isolate.relativeLink('allocationprofile')) }}">allocation profile</a>
+            See <a on-click="{{ goto }}" _href="{{ gotoLink('/allocation-profiler' + isolate.link) }}">allocation profile</a>
           </div>
         </div>
         <div class="memberItem">
           <div class="memberValue">
-            See <a on-click="{{ goto }}" _href="{{ gotoLink(isolate.relativeLink('heapmap')) }}">heap map</a>
+            See <a on-click="{{ goto }}" _href="{{ gotoLink('/heap-map' + isolate.link) }}">heap map</a>
           </div>
         </div>
         <div class="memberItem">
diff --git a/runtime/observatory/lib/src/elements/isolate_view.dart b/runtime/observatory/lib/src/elements/isolate_view.dart
index 46478f4..787b1f0 100644
--- a/runtime/observatory/lib/src/elements/isolate_view.dart
+++ b/runtime/observatory/lib/src/elements/isolate_view.dart
@@ -83,9 +83,8 @@
   TagProfileChart tagProfileChart = new TagProfileChart();
   IsolateViewElement.created() : super.created();
 
-  Future<ServiceObject> eval(String text) {
-    return isolate.get(
-        isolate.rootLib.id + "/eval?expr=${Uri.encodeComponent(text)}");
+  Future<ServiceObject> eval(String expression) {
+    return isolate.eval(isolate.rootLib, expression);
   }
 
   void _updateTagProfile() {
@@ -131,7 +130,7 @@
   }
 
   Future pause(_) {
-    return isolate.get("debug/pause").then((result) {
+    return isolate.pause().then((result) {
         // TODO(turnidge): Instead of asserting here, handle errors
         // properly.
         assert(result.type == 'Success');
@@ -140,7 +139,7 @@
   }
 
   Future resume(_) {
-    return isolate.get("resume").then((result) {
+    return isolate.resume().then((result) {
         // TODO(turnidge): Instead of asserting here, handle errors
         // properly.
         assert(result.type == 'Success');
diff --git a/runtime/observatory/lib/src/elements/library_view.dart b/runtime/observatory/lib/src/elements/library_view.dart
index c5e1af2..4a83c16b 100644
--- a/runtime/observatory/lib/src/elements/library_view.dart
+++ b/runtime/observatory/lib/src/elements/library_view.dart
@@ -16,9 +16,8 @@
 
   LibraryViewElement.created() : super.created();
 
-  Future<ServiceObject> eval(String text) {
-    return library.isolate.get(
-        library.id + "/eval?expr=${Uri.encodeComponent(text)}");
+  Future<ServiceObject> eval(String expression) {
+    return library.isolate.eval(library, expression);
   }
 
   void refresh(var done) {
diff --git a/runtime/observatory/lib/src/elements/metrics.dart b/runtime/observatory/lib/src/elements/metrics.dart
index d1e4c66..00b1544 100644
--- a/runtime/observatory/lib/src/elements/metrics.dart
+++ b/runtime/observatory/lib/src/elements/metrics.dart
@@ -4,7 +4,6 @@
 
 library metrics;
 
-import 'dart:async';
 import 'dart:html';
 import 'observatory_element.dart';
 import 'package:observatory/app.dart';
@@ -28,7 +27,7 @@
         (page.selectedMetricId != null)) {
       selectedMetric = isolate.dartMetrics[page.selectedMetricId];
       if (selectedMetric == null) {
-        selectedMetric = isolate.vmMetrics[page.selectedMetricId];
+        selectedMetric = isolate.nativeMetrics[page.selectedMetricId];
       }
     }
     if ((selectedMetric == null) && (isolate != null)) {
@@ -61,7 +60,7 @@
     selectedMetric = isolate.dartMetrics[id];
     if (selectedMetric == null) {
       // Check VM metrics.
-      selectedMetric = isolate.vmMetrics[id];
+      selectedMetric = isolate.nativeMetrics[id];
     }
     if (selectedMetric != null) {
       page.selectedMetricId = id;
diff --git a/runtime/observatory/lib/src/elements/metrics.html b/runtime/observatory/lib/src/elements/metrics.html
index 4dd6f0a..3eb940a 100644
--- a/runtime/observatory/lib/src/elements/metrics.html
+++ b/runtime/observatory/lib/src/elements/metrics.html
@@ -36,7 +36,7 @@
               </li>
             </template>
           </template>
-          <template repeat="{{ metric in isolate.vmMetrics.values }}">
+          <template repeat="{{ metric in isolate.nativeMetrics.values }}">
             <template if="{{ metric == selectedMetric }}">
               <li class="selected">
                 {{ metric.name }}
diff --git a/runtime/observatory/lib/src/elements/nav_bar.html b/runtime/observatory/lib/src/elements/nav_bar.html
index 3e35c88..9ffecd1 100644
--- a/runtime/observatory/lib/src/elements/nav_bar.html
+++ b/runtime/observatory/lib/src/elements/nav_bar.html
@@ -204,14 +204,12 @@
     <nav-menu link="{{ hashLinkWorkaround }}" anchor="{{ isolate.name }}" last="{{ last }}">
       <nav-menu-item link="{{ '/debugger' + isolate.link }}"
                      anchor="debugger"></nav-menu-item>
-      <nav-menu-item link="{{ isolate.relativeLink('profile') }}"
+      <nav-menu-item link="{{ '/profiler' + isolate.link }}"
                      anchor="cpu profile"></nav-menu-item>
-      <nav-menu-item link="{{ isolate.relativeLink('allocationprofile') }}"
+      <nav-menu-item link="{{ '/allocation-profiler' + isolate.link }}"
                      anchor="allocation profile"></nav-menu-item>
-      <nav-menu-item link="{{ isolate.relativeLink('heapmap') }}"
+      <nav-menu-item link="{{ '/heap-map' + isolate.link }}"
                      anchor="heap map"></nav-menu-item>
-      <nav-menu-item link="{{ isolate.relativeLink('debug/breakpoints') }}"
-                     anchor="breakpoints"></nav-menu-item>
       <content></content>
     </nav-menu>
   </template>
diff --git a/runtime/observatory/lib/src/elements/object_common.dart b/runtime/observatory/lib/src/elements/object_common.dart
index 6079530..929ebd6 100644
--- a/runtime/observatory/lib/src/elements/object_common.dart
+++ b/runtime/observatory/lib/src/elements/object_common.dart
@@ -20,21 +20,19 @@
 
   // TODO(koda): Add no-arg "calculate-link" instead of reusing "eval-link".
   Future<ServiceObject> retainedSize(var dummy) {
-    return object.isolate.get(object.id + "/retained")
-        .then((Instance obj) {
-          retainedBytes = int.parse(obj.valueAsString);
-        });
+    return object.isolate.getRetainedSize(object).then((Instance obj) {
+      retainedBytes = int.parse(obj.valueAsString);
+    });
   }
 
-  Future<ServiceObject> retainingPath(var arg) {
-    return object.isolate.get(object.id + "/retaining_path?limit=$arg")
-        .then((ServiceObject obj) {
-          path = obj;
-        });
+  Future<ServiceObject> retainingPath(var limit) {
+    return object.isolate.getRetainingPath(object, limit).then((ServiceObject obj) {
+      path = obj;
+    });
   }
 
-  Future<ServiceObject> fetchInboundReferences(var arg) {
-    return object.isolate.get(object.id + "/inbound_references?limit=$arg")
+  Future<ServiceObject> fetchInboundReferences(var limit) {
+    return object.isolate.getInboundReferences(object, limit)
         .then((ServiceObject obj) {
            inboundReferences = obj;
         });
diff --git a/runtime/observatory/lib/src/elements/observatory_application.dart b/runtime/observatory/lib/src/elements/observatory_application.dart
index a11385f..442f4b0 100644
--- a/runtime/observatory/lib/src/elements/observatory_application.dart
+++ b/runtime/observatory/lib/src/elements/observatory_application.dart
@@ -13,7 +13,6 @@
 /// elements.
 @CustomTag('observatory-application')
 class ObservatoryApplicationElement extends ObservatoryElement {
-  @published bool devtools = false;
   @reflectable ObservatoryApplication app;
 
   ObservatoryApplicationElement.created() : super.created();
@@ -21,10 +20,6 @@
   @override
   void attached() {
     super.attached();
-    if (devtools) {
-      app = new ObservatoryApplication.devtools(this);
-    } else {
-      app = new ObservatoryApplication(this);
-    }
+    app = new ObservatoryApplication(this);
   }
 }
diff --git a/runtime/observatory/lib/src/elements/script_inset.dart b/runtime/observatory/lib/src/elements/script_inset.dart
index f7a0627..f129f71 100644
--- a/runtime/observatory/lib/src/elements/script_inset.dart
+++ b/runtime/observatory/lib/src/elements/script_inset.dart
@@ -155,13 +155,13 @@
     }
     busy = true;
     if (line.bpt == null) {
-      // No breakpoint.  Set it.
-      line.script.isolate.setBreakpoint(line.script, line.line).then((_) {
+      // No breakpoint.  Add it.
+      line.script.isolate.addBreakpoint(line.script, line.line).then((_) {
           busy = false;
       });
     } else {
       // Existing breakpoint.  Remove it.
-      line.script.isolate.clearBreakpoint(line.bpt).then((_) {
+      line.script.isolate.removeBreakpoint(line.bpt).then((_) {
           busy = false;
       });
     }
diff --git a/runtime/observatory/lib/src/service/object.dart b/runtime/observatory/lib/src/service/object.dart
index 5e7ea08..b22a887 100644
--- a/runtime/observatory/lib/src/service/object.dart
+++ b/runtime/observatory/lib/src/service/object.dart
@@ -211,6 +211,13 @@
 
   Future<ServiceObject> _inProgressReload;
 
+  Future<ObservableMap> _fetchDirect() {
+    Map params = {
+      'objectId': id,
+    };
+    return isolate.invokeRpcNoUpgrade('getObject', params);
+  }
+
   /// Reload [this]. Returns a future which completes to [this] or
   /// a [ServiceError].
   Future<ServiceObject> reload() {
@@ -223,7 +230,7 @@
       return new Future.value(this);
     }
     if (_inProgressReload == null) {
-      _inProgressReload = vm.getAsMap(link).then((ObservableMap map) {
+      _inProgressReload = _fetchDirect().then((ObservableMap map) {
           var mapType = _stripRef(map['type']);
           if (mapType != _type) {
             // If the type changes, return a new object instead of
@@ -298,14 +305,19 @@
   }
 
   Future refreshCoverage() {
-    return vm.getAsMap(relativeLink('coverage')).then((ObservableMap map) {
-      var coverageOwner = (type == 'Isolate') ? this : owner;
-      var coverage = new ServiceObject._fromMap(coverageOwner, map);
-      assert(coverage.type == 'CodeCoverage');
-      var coverageList = coverage['coverage'];
-      assert(coverageList != null);
-      processCoverageData(coverageList);
-    });
+    Map params = {};
+    if (this is! Isolate) {
+      params['targetId'] = id;
+    }
+    return isolate.invokeRpcNoUpgrade('getCoverage', params).then(
+        (ObservableMap map) {
+          var coverageOwner = (type == 'Isolate') ? this : owner;
+          var coverage = new ServiceObject._fromMap(coverageOwner, map);
+          assert(coverage.type == 'CodeCoverage');
+          var coverageList = coverage['coverage'];
+          assert(coverageList != null);
+          processCoverageData(coverageList);
+        });
   }
 }
 
@@ -375,7 +387,7 @@
 
       // Extract the owning isolate from the event itself.
       String owningIsolateId = map['isolate']['id'];
-      _getIsolate(owningIsolateId).then((owningIsolate) {
+      getIsolate(owningIsolateId).then((owningIsolate) {
           if (owningIsolate == null) {
             // TODO(koda): Do we care about GC events in VM isolate?
             Logger.root.severe(
@@ -414,7 +426,9 @@
     throw new UnimplementedError();
   }
 
-  Future<ServiceObject> _getIsolate(String isolateId) {
+  // Note that this function does not reload the isolate if it found
+  // in the cache.
+  Future<ServiceObject> getIsolate(String isolateId) {
     if (isolateId == '') {
       return new Future.value(null);
     }
@@ -424,6 +438,9 @@
     }
     // The isolate is not in the cache.  Reload the vm and see if the
     // requested isolate is found.
+    //
+    // TODO(turnidge): We don't want to reload all isolates so much.
+    // Doesn't scale well.  Change this to be more fine-grained.
     return reload().then((result) {
         if (result is! VM) {
           return null;
@@ -433,13 +450,13 @@
       });
   }
 
-  Future<ServiceObject> get(String id) {
+  Future<ServiceObject> getDeprecated(String id) {
     assert(id.startsWith('/') == false);
     // Isolates are handled specially, since they can cache sub-objects.
     if (id.startsWith(_isolatesPrefix)) {
       String isolateId = _parseIsolateId(id);
       String objectId = _parseObjectId(id);
-      return _getIsolate(isolateId).then((isolate) {
+      return getIsolate(isolateId).then((isolate) {
         if (isolate == null) {
           // The isolate does not exist.  Return the VM object instead.
           //
@@ -449,7 +466,7 @@
         if (objectId == null) {
           return isolate.reload();
         } else {
-          return isolate.get(objectId);
+          return isolate.getDeprecated(objectId);
         }
       });
     }
@@ -460,7 +477,7 @@
     }
 
     // Cache miss.  Get the object from the vm directly.
-    return getAsMap(id).then((ObservableMap map) {
+    return _getAsMapDeprecated(id).then((ObservableMap map) {
       var obj = new ServiceObject._fromMap(this, map);
       if (obj.canCache) {
         _cache.putIfAbsent(id, () => obj);
@@ -478,8 +495,13 @@
     try {
       var decoder = new JsonDecoder(_reviver);
       map = decoder.convert(response);
-    } catch (e, st) {
-      return null;
+    } catch (e) {
+      return toObservable({
+        'type': 'ServiceException',
+        'kind': 'JSONDecodeException',
+        'response': map,
+        'message': 'Could not decode JSON: $e',
+      });
     }
     return toObservable(map);
   }
@@ -490,10 +512,9 @@
       return new Future.error(
             new ServiceObject._fromMap(this, toObservable({
         'type': 'ServiceException',
-        'id': '',
-        'kind': 'FormatException',
+        'kind': 'ResponseFormatException',
         'response': map,
-        'message': 'Top level service responses must be service maps.',
+        'message': 'Top level service responses must be service maps: ${map}.',
       })));
     }
     // Preemptively capture ServiceError and ServiceExceptions.
@@ -506,27 +527,12 @@
     return new Future.value(map);
   }
 
-  Future<ObservableMap> _decodeError(e) {
-    return new Future.error(new ServiceObject._fromMap(this, toObservable({
-      'type': 'ServiceException',
-      'id': '',
-      'kind': 'DecodeException',
-      'response':
-          'This is likely a result of a known V8 bug. Although the '
-          'the bug has been fixed the fix may not be in your Chrome'
-          ' version. For more information see dartbug.com/18385. '
-          'Observatory is still functioning and you should try your'
-          ' action again.',
-      'message': 'Could not decode JSON: $e',
-    })));
-  }
-
   /// Gets [id] as an [ObservableMap] from the service directly. If
   /// an error occurs, the future is completed as an error with a
   /// ServiceError or ServiceException. Therefore any chained then() calls
   /// will only receive a map encoding a valid ServiceObject.
-  Future<ObservableMap> getAsMap(String id) {
-    return getString(id).then((response) {
+  Future<ObservableMap> _getAsMapDeprecated(String id) {
+    return getStringDeprecated(id).then((response) {
       var map = _parseJSON(response);
       if (Tracer.current != null) {
         Tracer.current.trace("Received response for ${id}", map:map);
@@ -544,7 +550,48 @@
   }
 
   /// Get [id] as a [String] from the service directly. See [getAsMap].
-  Future<String> getString(String id);
+  Future<String> getStringDeprecated(String id);
+
+  // Implemented in subclass.
+  Future<String> invokeRpcRaw(String method, Map params);
+
+  Future<ObservableMap> invokeRpcNoUpgrade(String method, Map params) {
+    return invokeRpcRaw(method, params).then((String response) {
+      var map = _parseJSON(response);
+      if (Tracer.current != null) {
+        Tracer.current.trace("Received response for ${method}/${params}}",
+                             map:map);
+      }
+
+      // Check for ill-formed responses.
+      return _processMap(map);
+    }).catchError((error) {
+
+      // ServiceError, forward to VM's ServiceError stream.
+      errors.add(error);
+      return new Future.error(error);
+    }, test: (e) => e is ServiceError).catchError((exception) {
+
+      // ServiceException, forward to VM's ServiceException stream.
+      exceptions.add(exception);
+      return new Future.error(exception);
+    }, test: (e) => e is ServiceException);
+  }
+
+  Future<ServiceObject> invokeRpc(String method, Map params) {
+    return invokeRpcNoUpgrade(method, params).then((ObservableMap response) {
+	var obj = new ServiceObject._fromMap(this, response);
+        if (obj.canCache) {
+          _cache.putIfAbsent(id, () => obj);
+        }
+        return obj;
+    });
+  }
+
+  Future<ObservableMap> _fetchDirect() {
+    return invokeRpcNoUpgrade('getVM', {});
+  }
+
   /// Force the VM to disconnect.
   void disconnect();
   /// Completes when the VM first connects.
@@ -707,7 +754,7 @@
     var result = [];
     for (var v in graph.getMostRetained(classId: classId, limit: limit)) {
       var address = v.addressForWordSize(isolate.vm.architectureBits ~/ 8);
-      result.add(isolate.get(
+      result.add(isolate.getDeprecated(
           'address/${address.toRadixString(16)}?ref=true').then((obj) {
         obj.retainedSize = v.retainedSize;
         return new Future(() => obj);
@@ -754,7 +801,7 @@
   }
 
   void processProfile(ServiceMap profile) {
-    assert(profile.type == 'Profile');
+    assert(profile.type == 'CpuProfile');
     var codeTable = new List<Code>();
     var codeRegions = profile['codes'];
     for (var codeRegion in codeRegions) {
@@ -791,14 +838,16 @@
   /// Fetches and builds the class hierarchy for this isolate. Returns the
   /// Object class object.
   Future<Class> getClassHierarchy() {
-    return get('classes').then(_loadClasses).then(_buildClassHierarchy);
+    return invokeRpc('getClassList', {})
+        .then(_loadClasses)
+        .then(_buildClassHierarchy);
   }
 
   /// Given the class list, loads each class.
   Future<List<Class>> _loadClasses(ServiceMap classList) {
     assert(classList.type == 'ClassList');
     var futureClasses = [];
-    for (var cls in classList['members']) {
+    for (var cls in classList['classes']) {
       // Skip over non-class classes.
       if (cls is Class) {
         futureClasses.add(cls.load());
@@ -841,7 +890,7 @@
     return obj;
   }
 
-  Future<ServiceObject> get(String id) {
+  Future<ServiceObject> getDeprecated(String id) {
     // Do not allow null ids or empty ids.
     assert(id != null && id != '');
     var obj = _cache[id];
@@ -849,7 +898,7 @@
       return obj.reload();
     }
     // Cache miss.  Get the object from the vm directly.
-    return vm.getAsMap(relativeLink(id)).then((ObservableMap map) {
+    return vm._getAsMapDeprecated(relativeLink(id)).then((ObservableMap map) {
       var obj = new ServiceObject._fromMap(this, map);
       if (obj.canCache) {
         _cache.putIfAbsent(id, () => obj);
@@ -858,6 +907,37 @@
     });
   }
 
+  Future<ObservableMap> invokeRpcNoUpgrade(String method, Map params) {
+    params['isolate'] = id;
+    return vm.invokeRpcNoUpgrade(method, params);
+  }
+
+  Future<ServiceObject> invokeRpc(String method, Map params) {
+    return invokeRpcNoUpgrade(method, params).then((ObservableMap response) {
+        var obj = new ServiceObject._fromMap(this, response);
+        if (obj.canCache) {
+          _cache.putIfAbsent(id, () => obj);
+        }
+	return obj;
+    });
+  }
+
+  Future<ServiceObject> getObject(String objectId) {
+    assert(objectId != null && objectId != '');
+    var obj = _cache[objectId];
+    if (obj != null) {
+      return obj.reload();
+    }
+    Map params = {
+      'objectId': objectId,
+    };
+    return isolate.invokeRpc('getObject', params);
+  }
+
+  Future<ObservableMap> _fetchDirect() {
+    return invokeRpcNoUpgrade('getIsolate', {});
+  }
+
   @observable Class objectClass;
   @observable final rootClasses = new ObservableList<Class>();
 
@@ -890,8 +970,8 @@
 
   Future<HeapSnapshot> fetchHeapSnapshot() {
     if (_snapshotFetch == null || _snapshotFetch.isCompleted) {
-      get('graph');
       _snapshotFetch = new Completer<HeapSnapshot>();
+      isolate.invokeRpcNoUpgrade('requestHeapSnapshot', {});
     }
     return _snapshotFetch.future;
   }
@@ -986,11 +1066,12 @@
   }
 
   Future<TagProfile> updateTagProfile() {
-    return vm.getAsMap(relativeLink('profile/tag')).then((ObservableMap m) {
-      var seconds = new DateTime.now().millisecondsSinceEpoch / 1000.0;
-      tagProfile._processTagProfile(seconds, m);
-      return tagProfile;
-    });
+    return isolate.invokeRpcNoUpgrade('getTagProfile', {}).then(
+      (ObservableMap map) {
+        var seconds = new DateTime.now().millisecondsSinceEpoch / 1000.0;
+        tagProfile._processTagProfile(seconds, map);
+        return tagProfile;
+      });
   }
 
   @reflectable CodeTrieNode profileTrieRoot;
@@ -1038,6 +1119,7 @@
     return node;
   }
 
+  // TODO(turnidge): Make this an ObservableList instead.
   ServiceMap breakpoints;
 
   void _removeBreakpoint(ServiceMap bpt) {
@@ -1047,8 +1129,10 @@
     if (script.loaded) {
       var line = script.tokenToLine(tokenPos);
       assert(line != null);
-      assert(script.lines[line - 1].bpt == bpt);
-      script.lines[line - 1].bpt = null;
+      if (script.lines[line - 1] != null) {
+        assert(script.lines[line - 1].bpt == bpt);
+        script.lines[line - 1].bpt = null;
+      }
     }
   }
 
@@ -1090,7 +1174,7 @@
     // get stale breakpoints?
     if (_inProgressReloadBpts == null) {
       _inProgressReloadBpts =
-          get('debug/breakpoints').then((newBpts) {
+          invokeRpc('getBreakpoints', {}).then((newBpts) {
               _updateBreakpoints(newBpts);
           }).whenComplete(() {
               _inProgressReloadBpts = null;
@@ -1099,18 +1183,29 @@
     return _inProgressReloadBpts;
   }
 
-  Future<ServiceObject> setBreakpoint(Script script, int line) {
-    return get(script.id + "/setBreakpoint?line=${line}").then((result) {
-        if (result is DartError) {
+  Future<ServiceObject> addBreakpoint(Script script, int line) {
+    // TODO(turnidge): Pass line as an int instead of a string.
+    return invokeRpc('addBreakpoint',
+                     { 'script': script.id, 'line': '$line' }).then((result) {
+        if (result is ServiceMap &&
+            result.type == 'Breakpoint' &&
+            result['resolved'] &&
+            script.loaded &&
+            script.tokenToLine(result['location']['tokenPos']) != line) {
           // Unable to set a breakpoint at desired line.
           script.lines[line - 1].possibleBpt = false;
         }
-        return reloadBreakpoints();
+        // TODO(turnidge): Instead of reloading all of the breakpoints,
+        // rely on events to update the breakpoint list.
+        return reloadBreakpoints().then((_) {
+            return result;
+        });
       });
   }
 
-  Future clearBreakpoint(ServiceMap bpt) {
-    return get('${bpt.id}/clear').then((result) {
+  Future removeBreakpoint(ServiceMap bpt) {
+    return invokeRpc('removeBreakpoint',
+                     { 'breakpointId': bpt.id }).then((result) {
         if (result is DartError) {
           // TODO(turnidge): Handle this more gracefully.
           Logger.root.severe(result.message);
@@ -1126,7 +1221,7 @@
   }
 
   Future pause() {
-    return get("debug/pause").then((result) {
+    return invokeRpc('pause', {}).then((result) {
         if (result is DartError) {
           // TODO(turnidge): Handle this more gracefully.
           Logger.root.severe(result.message);
@@ -1136,7 +1231,7 @@
   }
 
   Future resume() {
-    return get("debug/resume").then((result) {
+    return invokeRpc('resume', {}).then((result) {
         if (result is DartError) {
           // TODO(turnidge): Handle this more gracefully.
           Logger.root.severe(result.message);
@@ -1146,7 +1241,7 @@
   }
 
   Future stepInto() {
-    return get("debug/resume?step=into").then((result) {
+    return invokeRpc('resume', {'step': 'into'}).then((result) {
         if (result is DartError) {
           // TODO(turnidge): Handle this more gracefully.
           Logger.root.severe(result.message);
@@ -1156,7 +1251,7 @@
   }
 
   Future stepOver() {
-    return get("debug/resume?step=over").then((result) {
+    return invokeRpc('resume', {'step': 'over'}).then((result) {
         if (result is DartError) {
           // TODO(turnidge): Handle this more gracefully.
           Logger.root.severe(result.message);
@@ -1166,7 +1261,7 @@
   }
 
   Future stepOut() {
-    return get("debug/resume?step=out").then((result) {
+    return invokeRpc('resume', {'step': 'out'}).then((result) {
         if (result is DartError) {
           // TODO(turnidge): Handle this more gracefully.
           Logger.root.severe(result.message);
@@ -1175,16 +1270,74 @@
       });
   }
 
+  Future<ServiceMap> getStack() {
+    return invokeRpc('getStack', {}).then((result) {
+        if (result is DartError) {
+          // TODO(turnidge): Handle this more gracefully.
+          Logger.root.severe(result.message);
+        }
+        return result;
+      });
+  }
+
+  Future<ServiceObject> eval(ServiceObject target,
+                             String expression) {
+    Map params = {
+      'targetId': target.id,
+      'expression': expression,
+    };
+    return invokeRpc('eval', params);
+  }
+
+  Future<ServiceObject> getRetainedSize(ServiceObject target) {
+    Map params = {
+      'targetId': target.id,
+    };
+    return invokeRpc('getRetainedSize', params);
+  }
+
+  Future<ServiceObject> getRetainingPath(ServiceObject target, var limit) {
+    Map params = {
+      'targetId': target.id,
+      'limit': limit.toString(),
+    };
+    return invokeRpc('getRetainingPath', params);
+  }
+
+  Future<ServiceObject> getInboundReferences(ServiceObject target, var limit) {
+    Map params = {
+      'targetId': target.id,
+      'limit': limit.toString(),
+    };
+    return invokeRpc('getInboundReferences', params);
+  }
+
+  Future<ServiceObject> getTypeArgumentsList(bool onlyWithInstantiations) {
+    Map params = {
+      'onlyWithInstantiations': onlyWithInstantiations,
+    };
+    return invokeRpc('getTypeArgumentsList', params);
+  }
+
+  Future<ServiceObject> getInstances(Class cls, var limit) {
+    Map params = {
+      'classId': cls.id,
+      'limit': limit.toString(),
+    };
+    return invokeRpc('getInstances', params);
+  }
+
   final ObservableMap<String, ServiceMetric> dartMetrics =
       new ObservableMap<String, ServiceMetric>();
 
-  final ObservableMap<String, ServiceMetric> vmMetrics =
+  final ObservableMap<String, ServiceMetric> nativeMetrics =
       new ObservableMap<String, ServiceMetric>();
 
   Future<ObservableMap<String, ServiceMetric>> _refreshMetrics(
-      String id,
+      String metricType,
       ObservableMap<String, ServiceMetric> metricsMap) {
-    return get(id).then((result) {
+    return invokeRpc('getIsolateMetricList',
+                     { 'type': metricType }).then((result) {
       if (result is DartError) {
         // TODO(turnidge): Handle this more gracefully.
         Logger.root.severe(result.message);
@@ -1193,8 +1346,8 @@
       // Clear metrics map.
       metricsMap.clear();
       // Repopulate metrics map.
-      var members = result['members'];
-      for (var metric in members) {
+      var metrics = result['metrics'];
+      for (var metric in metrics) {
         metricsMap[metric.id] = metric;
       }
       return metricsMap;
@@ -1202,15 +1355,15 @@
   }
 
   Future<ObservableMap<String, ServiceMetric>> refreshDartMetrics() {
-    return _refreshMetrics('metrics', dartMetrics);
+    return _refreshMetrics('Dart', dartMetrics);
   }
 
-  Future<ObservableMap<String, ServiceMetric>> refreshVMMetrics() {
-    return _refreshMetrics('metrics/vm', vmMetrics);
+  Future<ObservableMap<String, ServiceMetric>> refreshNativeMetrics() {
+    return _refreshMetrics('Native', nativeMetrics);
   }
 
   Future refreshMetrics() {
-    return refreshDartMetrics().then((_) => refreshVMMetrics());
+    return Future.wait([refreshDartMetrics(), refreshNativeMetrics()]);
   }
 
   String toString() => "Isolate($_id)";
@@ -1572,10 +1725,6 @@
     subclasses.sort(ServiceObject.LexicalSortName);
   }
 
-  Future<ServiceObject> get(String command) {
-    return isolate.get(id + "/$command");
-  }
-
   String toString() => 'Class($vmName)';
 }
 
@@ -2406,8 +2555,6 @@
   void updateProfileData(Map profileData,
                          List<Code> codeTable,
                          int sampleCount) {
-    // Assert we have a CodeRegion entry.
-    assert(profileData['type'] == 'CodeRegion');
     // Assert we are handed profile data for this code object.
     assert(profileData['code'] == this);
     totalSamplesInProfile = sampleCount;
@@ -2675,6 +2822,12 @@
     _removeOld();
   }
 
+  Future<ObservableMap> _fetchDirect() {
+    assert(owner is Isolate);
+    return isolate.invokeRpcNoUpgrade('getIsolateMetric', { 'metricId': id });
+  }
+
+
   void addSample(MetricSample sample) {
     samples.add(sample);
     _removeOld();
@@ -2752,7 +2905,7 @@
 // Returns true if [map] is a service map. i.e. it has the following keys:
 // 'id' and a 'type'.
 bool _isServiceMap(ObservableMap m) {
-  return (m != null) && (m['id'] != null) && (m['type'] != null);
+  return (m != null) && (m['type'] != null);
 }
 
 bool _hasRef(String type) => type.startsWith('@');
diff --git a/runtime/observatory/observatory.gypi b/runtime/observatory/observatory.gypi
index 9461174..bf4723a 100644
--- a/runtime/observatory/observatory.gypi
+++ b/runtime/observatory/observatory.gypi
@@ -172,7 +172,6 @@
         'lib/src/service/object.dart',
         'lib/tracer.dart',
         'web/index.html',
-        'web/index_devtools.html',
         'web/main.dart',
       ],
       'actions': [
@@ -187,8 +186,6 @@
           'outputs': [
             '<(PRODUCT_DIR)/observatory/build/web/index.html',
             '<(PRODUCT_DIR)/observatory/build/web/index.html_bootstrap.dart.js',
-            '<(PRODUCT_DIR)/observatory/build/web/index_devtools.html',
-            '<(PRODUCT_DIR)/observatory/build/web/index_devtools.html_bootstrap.dart.js',
           ],
           'action': [
             'python',
@@ -207,14 +204,10 @@
             '../../tools/observatory_tool.py',
             '<(PRODUCT_DIR)/observatory/build/web/index.html',
             '<(PRODUCT_DIR)/observatory/build/web/index.html_bootstrap.dart.js',
-            '<(PRODUCT_DIR)/observatory/build/web/index_devtools.html',
-            '<(PRODUCT_DIR)/observatory/build/web/index_devtools.html_bootstrap.dart.js',
           ],
           'outputs': [
             '<(PRODUCT_DIR)/observatory/deployed/web/index.html',
             '<(PRODUCT_DIR)/observatory/deployed/web/index.html_bootstrap.dart.js',
-            '<(PRODUCT_DIR)/observatory/deployed/web/index_devtools.html',
-            '<(PRODUCT_DIR)/observatory/deployed/web/index_devtools.html_bootstrap.dart.js',
           ],
           'action': [
             'python',
diff --git a/runtime/observatory/test/classes_test.dart b/runtime/observatory/test/classes_test.dart
index 55d834b..85b64bb 100644
--- a/runtime/observatory/test/classes_test.dart
+++ b/runtime/observatory/test/classes_test.dart
@@ -9,11 +9,17 @@
 var tests = [
 
 (Isolate isolate) =>
-  isolate.get('classes/62').then((Class c) {
+  isolate.getClassHierarchy().then((Class o) {
+    expect(o.name, equals('Object'));
+}),
+
+(Isolate isolate) =>
+  isolate.getObject('classes/62').then((Class c) {
     expect(c.name, equals('_List'));
     expect(c.vmCid, equals(62));
 }),
 
+
 ];
 
 main(args) => runIsolateTests(args, tests);
diff --git a/runtime/observatory/test/code_test.dart b/runtime/observatory/test/code_test.dart
new file mode 100644
index 0000000..c12b6f3
--- /dev/null
+++ b/runtime/observatory/test/code_test.dart
@@ -0,0 +1,86 @@
+// Copyright (c) 2015, 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:observatory/service_io.dart';
+import 'package:unittest/unittest.dart';
+import 'test_helper.dart';
+import 'dart:async';
+
+int counter = 0;
+
+void funcB() {
+  counter++;  // line 13
+  if (counter % 100000000 == 0) {
+    print(counter);
+  }
+}
+
+void funcA() {
+  funcB();
+}
+
+void testFunction() {
+  while (true) {
+    funcA();
+  }
+}
+
+var tests = [
+
+// Go to breakpoint at line 13.
+(Isolate isolate) {
+  return isolate.rootLib.load().then((_) {
+      // Set up a listener to wait for breakpoint events.
+      Completer completer = new Completer();
+      List events = [];
+      isolate.vm.events.stream.listen((ServiceEvent event) {
+        if (event.eventType == 'BreakpointReached') {
+          print('Breakpoint reached');
+          completer.complete();
+        }
+      });
+
+      // Add the breakpoint.
+      var script = isolate.rootLib.scripts[0];
+      var line = 13;
+      return isolate.addBreakpoint(script, line).then((ServiceObject bpt) {
+          return completer.future;  // Wait for breakpoint reached.
+      });
+    });
+},
+
+// Inspect code objects for top two frames.
+(Isolate isolate) {
+  return isolate.getStack().then((ServiceMap stack) {
+      // Make sure we are in the right place.
+      expect(stack.type, equals('Stack'));
+      expect(stack['frames'].length, greaterThanOrEqualTo(3));
+      var frame0 = stack['frames'][0];
+      var frame1 = stack['frames'][1];
+      print(frame0);
+      expect(frame0['function'].name, equals('funcB'));
+      expect(frame1['function'].name, equals('funcA'));
+      var codeId0 = frame0['code'].id;
+      var codeId1 = frame1['code'].id;
+
+      List tests = [];
+      // Load code from frame 0.
+      tests.add(isolate.getObject(codeId0)..then((Code code) {
+            expect(code.type, equals('Code'));
+            expect(code.function.name, equals('funcB'));
+            expect(code.hasDisassembly, equals(true));
+          }));
+      // Load code from frame 0.
+      tests.add(isolate.getObject(codeId1)..then((Code code) {
+            expect(code.type, equals('Code'));
+            expect(code.function.name, equals('funcA'));
+            expect(code.hasDisassembly, equals(true));
+          }));
+      return Future.wait(tests);
+  });
+},
+
+];
+
+main(args) => runIsolateTests(args, tests, testeeConcurrent: testFunction);
diff --git a/runtime/observatory/test/contexts_test.dart b/runtime/observatory/test/contexts_test.dart
index 6eda397..dc0f6e9 100644
--- a/runtime/observatory/test/contexts_test.dart
+++ b/runtime/observatory/test/contexts_test.dart
@@ -4,7 +4,6 @@
 
 library inbound_references_test;
 
-import 'dart:async';
 import 'package:observatory/service_io.dart';
 import 'package:unittest/unittest.dart';
 import 'test_helper.dart';
diff --git a/runtime/observatory/test/coverage_test.dart b/runtime/observatory/test/coverage_test.dart
new file mode 100644
index 0000000..aa5eaf2
--- /dev/null
+++ b/runtime/observatory/test/coverage_test.dart
@@ -0,0 +1,151 @@
+// Copyright (c) 2015, 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:observatory/service_io.dart';
+import 'package:unittest/unittest.dart';
+import 'test_helper.dart';
+import 'dart:async';
+
+int globalVar = 100;
+
+class MyClass {
+  static void myFunction(int value) {
+    print(value);  // line 14
+    if (value < 0) {
+      print("negative");
+    } else {
+      print("positive");
+    }
+  }
+
+  static void otherFunction(int value) {
+    if (value < 0) {
+      print("otherFunction <");
+    } else {
+      print("otherFunction >=");
+    }
+  }
+}
+
+void testFunction() {
+  MyClass.otherFunction(-100);
+  int i = 0;
+  while (true) {
+    if (++i % 100000000 == 0) {
+      MyClass.myFunction(10000);
+    }
+  }
+}
+
+List normalize(List coverage) {
+  // The exact coverage numbers may vary based on how many times
+  // things run.  Normalize the data to 0 or 1.
+  List normalized = [];
+  for (int i = 0; i < coverage.length; i += 2) {
+    normalized.add(coverage[i]);
+    normalized.add(coverage[i+1] == 0 ? 0 : 1);
+  }
+  return normalized;
+}
+
+var tests = [
+
+// Go to breakpoint at line 14.
+(Isolate isolate) {
+  return isolate.rootLib.load().then((_) {
+      // Set up a listener to wait for breakpoint events.
+      Completer completer = new Completer();
+      List events = [];
+      isolate.vm.events.stream.listen((ServiceEvent event) {
+        if (event.eventType == 'BreakpointReached') {
+          print('Breakpoint reached');
+          completer.complete();
+        }
+      });
+
+      // Add the breakpoint.
+      var script = isolate.rootLib.scripts[0];
+      var line = 14;
+      return isolate.addBreakpoint(script, line).then((ServiceObject bpt) {
+          return completer.future;  // Wait for breakpoint reached.
+      });
+    });
+},
+
+// Get coverage for function, class, library, script, and isolate.
+(Isolate isolate) {
+  return isolate.getStack().then((ServiceMap stack) {
+      // Make sure we are in the right place.
+      expect(stack.type, equals('Stack'));
+      expect(stack['frames'].length, greaterThanOrEqualTo(2));
+      expect(stack['frames'][0]['function'].owningClass.name, equals('MyClass'));
+
+      var lib = isolate.rootLib;
+      var func = stack['frames'][0]['function'];
+      expect(func.name, equals('myFunction'));
+      var cls = stack['frames'][0]['function'].owningClass;
+      expect(cls.name, equals('MyClass'));
+
+      List tests = [];
+      // Function
+      tests.add(isolate.invokeRpcNoUpgrade('getCoverage',
+                                           { 'targetId': func.id })
+                .then((Map coverage) {
+                    expect(coverage['type'], equals('CodeCoverage'));
+                    expect(coverage['coverage'].length, equals(1));
+                    expect(normalize(coverage['coverage'][0]['hits']),
+                           equals([14, 1, 15, 1, 16, 0, 18, 1]));
+                }));
+      // Class
+      tests.add(isolate.invokeRpcNoUpgrade('getCoverage',
+                                           { 'targetId': cls.id })
+                .then((Map coverage) {
+                    expect(coverage['type'], equals('CodeCoverage'));
+                    expect(coverage['coverage'].length, equals(1));
+                    expect(normalize(coverage['coverage'][0]['hits']),
+                           equals([14, 1, 15, 1, 16, 0, 18, 1,
+                                   23, 1, 24, 1, 26, 0]));
+                }));
+      // Library
+      tests.add(isolate.invokeRpcNoUpgrade('getCoverage',
+                                           { 'targetId': lib.id })
+                .then((Map coverage) {
+                    expect(coverage['type'], equals('CodeCoverage'));
+                    expect(coverage['coverage'].length, equals(3));
+                    expect(normalize(coverage['coverage'][0]['hits']),
+                           equals([14, 1, 15, 1, 16, 0, 18, 1,
+                                   23, 1, 24, 1, 26, 0]));
+                    expect(normalize(coverage['coverage'][1]['hits']).take(12),
+                           equals([32, 0, 35, 0, 36, 0, 32, 1, 35, 1, 36, 0]));
+                                   
+                }));
+      // Script
+      tests.add(cls.load().then((_) {
+            return isolate.invokeRpcNoUpgrade('getCoverage',
+                                              { 'targetId': cls.script.id })
+                .then((Map coverage) {
+                    expect(coverage['type'], equals('CodeCoverage'));
+                    expect(coverage['coverage'].length, equals(3));
+                    expect(normalize(coverage['coverage'][0]['hits']),
+                           equals([14, 1, 15, 1, 16, 0, 18, 1,
+                                   23, 1, 24, 1, 26, 0]));
+                    expect(normalize(coverage['coverage'][1]['hits']).take(12),
+                           equals([32, 0, 35, 0, 36, 0, 32, 1, 35, 1, 36, 0]));
+                });
+          }));
+      // Isolate
+      tests.add(cls.load().then((_) {
+            return isolate.invokeRpcNoUpgrade('getCoverage', {})
+                .then((Map coverage) {
+                    expect(coverage['type'], equals('CodeCoverage'));
+                    expect(coverage['coverage'].length, greaterThan(100));
+                });
+          }));
+      return Future.wait(tests);
+  });
+},
+
+];
+
+main(args) => runIsolateTests(args, tests, testeeConcurrent: testFunction);
diff --git a/runtime/observatory/test/debugging_test.dart b/runtime/observatory/test/debugging_test.dart
new file mode 100644
index 0000000..7fa5891
--- /dev/null
+++ b/runtime/observatory/test/debugging_test.dart
@@ -0,0 +1,120 @@
+// Copyright (c) 2015, 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:observatory/service_io.dart';
+import 'package:unittest/unittest.dart';
+import 'test_helper.dart';
+import 'dart:async';
+
+void testFunction() {
+  int i = 0;
+  while (true) {
+    if (++i % 100000000 == 0) {
+      print(i);   // line 14
+    }
+  }
+}
+
+var tests = [
+
+// Pause
+(Isolate isolate) {
+  Completer completer = new Completer();
+  isolate.vm.events.stream.listen((ServiceEvent event) {
+    if (event.eventType == 'IsolateInterrupted') {
+      completer.complete();
+    }
+  });
+  isolate.pause();
+  return completer.future;
+},
+
+// Resume
+(Isolate isolate) {
+  return isolate.resume().then((_) {
+      expect(isolate.pauseEvent == null, isTrue);
+  });
+},
+
+// Add breakpoint
+(Isolate isolate) {
+  return isolate.rootLib.load().then((_) {
+      // Set up a listener to wait for breakpoint events.
+      Completer completer = new Completer();
+      List events = [];
+      isolate.vm.events.stream.listen((ServiceEvent event) {
+        if (event.eventType.startsWith('Breakpoint')) {
+          events.add(event);
+        }
+        if (events.length == 2) {
+          expect(events[0].eventType, equals('BreakpointResolved'));
+          expect(events[1].eventType, equals('BreakpointReached'));
+          print('Breakpoint reached');
+          completer.complete();
+        }
+      });
+
+      // Add the breakpoint.
+      var script = isolate.rootLib.scripts[0];
+      return isolate.addBreakpoint(script, 14).then((ServiceObject bpt) {
+          expect(bpt is ServiceMap, isTrue);
+          ServiceMap m = bpt;
+          expect(m.type, equals('Breakpoint'));
+          expect(m['location']['script'].id, equals(script.id));
+          expect(m['location']['tokenPos'], equals(51));
+          expect(isolate.breakpoints.type, equals('BreakpointList'));
+          expect(isolate.breakpoints['breakpoints'].length, equals(1));
+          return completer.future;  // Wait for breakpoint events.
+      });
+    });
+},
+
+// Get the stack trace
+(Isolate isolate) {
+  return isolate.getStack().then((ServiceMap stack) {
+      expect(stack.type, equals('Stack'));
+      expect(stack['frames'].length, greaterThanOrEqualTo(1));
+      expect(stack['frames'][0]['function'].name, equals('testFunction'));
+  });
+},
+
+// Stepping
+(Isolate isolate) {
+  // Set up a listener to wait for breakpoint events.
+  Completer completer = new Completer();
+  List events = [];
+  isolate.vm.events.stream.listen((ServiceEvent event) {
+    if (event.eventType.startsWith('Breakpoint')) {
+      expect(event.eventType, equals('BreakpointReached'));
+    }
+    print('Breakpoint reached');
+    completer.complete();
+  });
+  
+  return isolate.stepInto().then((isolate) {
+    return completer.future;  // Wait for breakpoint events.
+  });
+},
+
+// Get the stack trace again.  We are in 'print'.
+(Isolate isolate) {
+  return isolate.getStack().then((ServiceMap stack) {
+      expect(stack.type, equals('Stack'));
+      expect(stack['frames'].length, greaterThanOrEqualTo(2));
+      expect(stack['frames'][0]['function'].name, equals('print'));
+  });
+},
+
+// Remove breakpoint
+(Isolate isolate) {
+  expect(isolate.breakpoints['breakpoints'].length, equals(1));
+  var bpt = isolate.breakpoints['breakpoints'][0];
+  return isolate.removeBreakpoint(bpt).then((_) {
+      expect(isolate.breakpoints['breakpoints'].length, equals(0));
+  });
+},
+
+];
+
+main(args) => runIsolateTests(args, tests, testeeConcurrent: testFunction);
diff --git a/runtime/observatory/test/echo_test.dart b/runtime/observatory/test/echo_test.dart
index f1b7cc0..6a10e24 100644
--- a/runtime/observatory/test/echo_test.dart
+++ b/runtime/observatory/test/echo_test.dart
@@ -10,18 +10,16 @@
 var tests = [
 
 (Isolate isolate) =>
-  isolate.vm.get('_echo').then((result) {
-    expect(result['type'], equals("message"));
-    expect(result['id'], equals("_echo"));
-    expect(result.owner, equals(isolate.vm));
-}),
+  isolate.vm.invokeRpc('_echo', { 'text': 'hello'}).then((result) {
+    expect(result['type'], equals('_EchoResponse'));
+    expect(result['text'], equals('hello'));
+  }),
 
 (Isolate isolate) =>
-  isolate.get('_echo').then((result) {
-    expect(result['type'], equals("message"));
-    expect(result['id'], equals("_echo"));
-    expect(result.owner, equals(isolate));
-}),
+  isolate.invokeRpc('_echo', { 'text': 'hello'}).then((result) {
+    expect(result['type'], equals('_EchoResponse'));
+    expect(result['text'], equals('hello'));
+  }),
 
 (Isolate isolate) {
   Completer completer = new Completer();
@@ -34,7 +32,7 @@
       completer.complete();
     }
   });
-  isolate.get('_echo/event');
+  isolate.invokeRpc('_triggerEchoEvent', { 'text': 'hello' });
   return completer.future;
 },
 
diff --git a/runtime/observatory/test/eval_test.dart b/runtime/observatory/test/eval_test.dart
new file mode 100644
index 0000000..7c5d77c
--- /dev/null
+++ b/runtime/observatory/test/eval_test.dart
@@ -0,0 +1,94 @@
+// Copyright (c) 2015, 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:observatory/service_io.dart';
+import 'package:unittest/unittest.dart';
+import 'test_helper.dart';
+import 'dart:async';
+
+int globalVar = 100;
+
+class MyClass {
+  static int staticVar = 1000;
+
+  static void printValue(int value) {
+    print(value);   // line 16
+  }
+}
+
+void testFunction() {
+  int i = 0;
+  while (true) {
+    if (++i % 100000000 == 0) {
+      MyClass.printValue(10000);
+    }
+  }
+}
+
+var tests = [
+
+// Go to breakpoint at line 16.
+(Isolate isolate) {
+  return isolate.rootLib.load().then((_) {
+      // Set up a listener to wait for breakpoint events.
+      Completer completer = new Completer();
+      List events = [];
+      isolate.vm.events.stream.listen((ServiceEvent event) {
+        if (event.eventType == 'BreakpointReached') {
+          print('Breakpoint reached');
+          completer.complete();
+        }
+      });
+
+      // Add the breakpoint.
+      var script = isolate.rootLib.scripts[0];
+      var line = 16;
+      return isolate.addBreakpoint(script, line).then((ServiceObject bpt) {
+          return completer.future;  // Wait for breakpoint reached.
+      });
+    });
+},
+
+// Evaluate against library, class, and instance.
+(Isolate isolate) {
+  return isolate.getStack().then((ServiceMap stack) {
+      // Make sure we are in the right place.
+      expect(stack.type, equals('Stack'));
+      expect(stack['frames'].length, greaterThanOrEqualTo(2));
+      expect(stack['frames'][0]['function'].name, equals('printValue'));
+      expect(stack['frames'][0]['function'].owningClass.name, equals('MyClass'));
+
+      var lib = isolate.rootLib;
+      var cls = stack['frames'][0]['function'].owningClass;
+      var instance = stack['frames'][0]['vars'][0]['value'];
+
+      List evals = [];
+      evals.add(isolate.eval(lib, 'globalVar + 5').then((result) {
+            print(result);
+            expect(result.valueAsString, equals('105'));
+          }));
+      evals.add(isolate.eval(lib, 'globalVar + staticVar + 5').then((result) {
+            expect(result.type, equals('Error'));
+          }));
+      evals.add(isolate.eval(cls, 'globalVar + staticVar + 5').then((result) {
+            print(result);
+            expect(result.valueAsString, equals('1105'));
+          }));
+      evals.add(isolate.eval(cls, 'this + 5').then((result) {
+            expect(result.type, equals('Error'));
+          }));
+      evals.add(isolate.eval(instance, 'this + 5').then((result) {
+            print(result);
+            expect(result.valueAsString, equals('10005'));
+          }));
+      evals.add(isolate.eval(instance, 'this + frog').then((result) {
+            expect(result.type, equals('Error'));
+          }));
+      return Future.wait(evals);
+  });
+},
+
+];
+
+main(args) => runIsolateTests(args, tests, testeeConcurrent: testFunction);
diff --git a/runtime/observatory/test/functions_test.dart b/runtime/observatory/test/functions_test.dart
index 678ee94..9290a4b 100644
--- a/runtime/observatory/test/functions_test.dart
+++ b/runtime/observatory/test/functions_test.dart
@@ -23,10 +23,11 @@
     expect(lib.classes.length, equals(1));
     return lib.classes.first.load().then((Class fooClass) {
       expect(fooClass.name, equals('Foo'));
-      return fooClass.get('functions/get%3Aa').then((ServiceFunction func) {
-        expect(func.name, equals('a'));
-        expect(func.kind, equals(FunctionKind.kImplicitGetterFunction));
-      });
+      return isolate.getObject('${fooClass.id}/functions/get%3Aa')
+          .then((ServiceFunction func) {
+              expect(func.name, equals('a'));
+              expect(func.kind, equals(FunctionKind.kImplicitGetterFunction));
+          });
     });
 }),
 
diff --git a/runtime/observatory/test/graph_test.dart b/runtime/observatory/test/graph_test.dart
index 6492781..db16681 100644
--- a/runtime/observatory/test/graph_test.dart
+++ b/runtime/observatory/test/graph_test.dart
@@ -88,11 +88,11 @@
     expect(lib.classes.length, equals(1));
     Class fooClass = lib.classes.first;
     fooId = fooClass.vmCid;
-    isolate.get('graph');
+    isolate.invokeRpcNoUpgrade('requestHeapSnapshot', {});
     return completer.future;
   });
 },
 
 ];
 
-main(args) => runIsolateTests(args, tests, testeeBefore: script);
\ No newline at end of file
+main(args) => runIsolateTests(args, tests, testeeBefore: script);
diff --git a/runtime/observatory/test/inbound_references_test.dart b/runtime/observatory/test/inbound_references_test.dart
index 0d9698c..0586620 100644
--- a/runtime/observatory/test/inbound_references_test.dart
+++ b/runtime/observatory/test/inbound_references_test.dart
@@ -4,7 +4,6 @@
 
 library inbound_references_test;
 
-import 'dart:async';
 import 'package:observatory/service_io.dart';
 import 'package:unittest/unittest.dart';
 import 'test_helper.dart';
@@ -31,8 +30,7 @@
 (Isolate isolate) =>
   isolate.rootLib.load().then((Library lib) {
     Instance e = lib.variables.where((v) => v.name == 'e').single.value;
-    var id = e.id;
-    return isolate.get('/$id/inbound_references?limit=100').then(
+    return isolate.getInboundReferences(e, 100).then(
         (ServiceMap response) {
           List references = response['references'];
           hasReferenceSuchThat(predicate) {
diff --git a/runtime/observatory/test/malformed_test.dart b/runtime/observatory/test/malformed_test.dart
new file mode 100644
index 0000000..76fffb4
--- /dev/null
+++ b/runtime/observatory/test/malformed_test.dart
@@ -0,0 +1,28 @@
+// Copyright (c) 2014, 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:observatory/service_io.dart';
+import 'package:unittest/unittest.dart';
+import 'test_helper.dart';
+
+var tests = [
+
+(Isolate isolate) =>
+  isolate.invokeRpc('_respondWithMalformedJson', { }).then((result) {
+    // Should not execute.
+    expect(true, false);
+  }).catchError((ServiceException exception) {
+    expect(exception.kind, equals('JSONDecodeException'));
+  }),
+
+(Isolate isolate) =>
+  isolate.invokeRpc('_respondWithMalformedObject', { }).then((result) {
+    // Should not execute.
+    expect(true, false);
+  }).catchError((ServiceException exception) {
+    expect(exception.kind, equals('ResponseFormatException'));
+  }),
+];
+
+main(args) => runIsolateTests(args, tests);
\ No newline at end of file
diff --git a/runtime/observatory/test/metrics_test.dart b/runtime/observatory/test/metrics_test.dart
index 8ea13a8..ef227c4 100644
--- a/runtime/observatory/test/metrics_test.dart
+++ b/runtime/observatory/test/metrics_test.dart
@@ -17,27 +17,25 @@
 var tests = [
 
 (Isolate isolate) =>
-  isolate.get('metrics').then((ServiceMap metrics) {
-    expect(metrics['type'], equals('MetricList'));
-    var members = metrics['members'];
-    expect(members, isList);
-    expect(members.length, equals(1));
-    var counter = members[0];
+  isolate.refreshDartMetrics().then((Map metrics) {
+    expect(metrics.length, equals(1));
+    var counter = metrics['metrics/a.b.c'];
     expect(counter.name, equals('a.b.c'));
     expect(counter.value, equals(1234.5));
 }),
 
 (Isolate isolate) =>
-  isolate.get('metrics/a.b.c').then((ServiceMetric counter) {
+  isolate.invokeRpc('getIsolateMetric', { 'metricId': 'metrics/a.b.c' })
+      .then((ServiceMetric counter) {
     expect(counter.name, equals('a.b.c'));
     expect(counter.value, equals(1234.5));
-}),
+  }),
 
 (Isolate isolate) =>
-  isolate.get('metrics/a.b.d').then((DartError err) {
+  isolate.invokeRpc('getIsolateMetric', { 'metricId': 'metrics/a.b.d' })
+      .then((DartError err) {
     expect(err is DartError, isTrue);
-}),
-
+  }),
 ];
 
 main(args) => runIsolateTests(args, tests, testeeBefore: script);
diff --git a/runtime/observatory/test/mirror_references_test.dart b/runtime/observatory/test/mirror_references_test.dart
index b3c782c..d6e5f39 100644
--- a/runtime/observatory/test/mirror_references_test.dart
+++ b/runtime/observatory/test/mirror_references_test.dart
@@ -4,7 +4,6 @@
 
 library vm_references_test;
 
-import 'dart:async';
 import 'dart:mirrors';
 import 'package:observatory/service_io.dart';
 import 'package:unittest/unittest.dart';
diff --git a/runtime/observatory/test/native_metrics_test.dart b/runtime/observatory/test/native_metrics_test.dart
new file mode 100644
index 0000000..39b23d1
--- /dev/null
+++ b/runtime/observatory/test/native_metrics_test.dart
@@ -0,0 +1,41 @@
+import 'package:observatory/service_io.dart';
+import 'package:unittest/unittest.dart';
+import 'test_helper.dart';
+
+import 'dart:profiler';
+
+void script() {
+  var counter = new Counter('a.b.c', 'description');
+  Metrics.register(counter);
+  counter.value = 1234.5;
+}
+
+var tests = [
+
+(Isolate isolate) =>
+    isolate.refreshNativeMetrics().then((Map metrics) {
+      expect(metrics.length, greaterThan(1));
+      expect(metrics.length, greaterThan(1));
+      var foundOldHeapCapacity = metrics.values.any((m) =>
+          m.name == 'heap.old.capacity');
+      expect(foundOldHeapCapacity, equals(true));
+  }),
+
+(Isolate isolate) =>
+  isolate.invokeRpc('getIsolateMetric',
+                    { 'metricId': 'metrics/native/heap.old.used' })
+      .then((ServiceMetric counter) {
+    expect(counter.type, equals('Counter'));
+    expect(counter.name, equals('heap.old.used'));
+  }),
+
+(Isolate isolate) =>
+    isolate.invokeRpc('getIsolateMetric',
+                      { 'metricId': 'metrics/native/doesnotexist' })
+          .then((DartError err) {
+    expect(err is DartError, isTrue);
+  }),
+
+];
+
+main(args) => runIsolateTests(args, tests, testeeBefore: script);
diff --git a/runtime/observatory/test/string_escaping_test.dart b/runtime/observatory/test/string_escaping_test.dart
index 3b73a8c..453eb05 100644
--- a/runtime/observatory/test/string_escaping_test.dart
+++ b/runtime/observatory/test/string_escaping_test.dart
@@ -4,8 +4,6 @@
 
 library string_escaping_test;
 
-import 'dart:async';
-import 'dart:mirrors';
 import 'package:observatory/service_io.dart';
 import 'package:unittest/unittest.dart';
 import 'test_helper.dart';
diff --git a/runtime/observatory/test/test_helper.dart b/runtime/observatory/test/test_helper.dart
index d587e86..11feac8 100644
--- a/runtime/observatory/test/test_helper.dart
+++ b/runtime/observatory/test/test_helper.dart
@@ -94,7 +94,7 @@
     var process = new _TestLauncher();
     process.launch().then((port) {
       String addr = 'ws://localhost:$port/ws';
-      new WebSocketVM(new WebSocketVMTarget(addr)).get('vm')
+      new WebSocketVM(new WebSocketVMTarget(addr)).load()
           .then((VM vm) => vm.isolates.first.load())
           .then((Isolate isolate) =>
               Future.forEach(tests, (test) => test(isolate)))
diff --git a/runtime/observatory/test/type_arguments_test.dart b/runtime/observatory/test/type_arguments_test.dart
new file mode 100644
index 0000000..4b82421
--- /dev/null
+++ b/runtime/observatory/test/type_arguments_test.dart
@@ -0,0 +1,40 @@
+// Copyright (c) 2015, 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:observatory/service_io.dart';
+import 'package:unittest/unittest.dart';
+import 'test_helper.dart';
+
+var tests = [
+(Isolate isolate) =>
+  isolate.getTypeArgumentsList(false).then((ServiceMap allTypeArgs) {
+    var allTypeArgsTableSize = allTypeArgs['canonicalTypeArgumentsTableSize'];
+    var allTypeArgsTableUsed = allTypeArgs['canonicalTypeArgumentsTableUsed'];
+    var allTypeArgsList = allTypeArgs['typeArguments'];
+    expect(allTypeArgsList, isNotNull);
+    // Check size >= used.
+    expect(allTypeArgsTableSize, greaterThanOrEqualTo(allTypeArgsTableUsed));
+    return isolate.getTypeArgumentsList(true).then((ServiceMap instantiatedTypeARgs) {
+      var instantiatedTypeArgsTableSize =
+          instantiatedTypeARgs['canonicalTypeArgumentsTableSize'];
+      var instantiatedTypeArgsTableUsed =
+          instantiatedTypeARgs['canonicalTypeArgumentsTableUsed'];
+      // Check size >= used.
+      expect(instantiatedTypeArgsTableSize,
+             greaterThanOrEqualTo(instantiatedTypeArgsTableUsed));
+      // Check that |instantiated| <= |all|
+      var instantiatedTypeArgsList = instantiatedTypeARgs['typeArguments'];
+      expect(instantiatedTypeArgsList, isNotNull);
+      expect(allTypeArgsList.length,
+             greaterThanOrEqualTo(instantiatedTypeArgsList.length));
+      // Check that we can 'get' this object again.
+      var firstType = allTypeArgsList[0];
+      return isolate.getObject(firstType['id']).then((ServiceMap map) {
+        expect(firstType['name'], map['name']);
+      });
+    });
+  }),
+];
+
+main(args) => runIsolateTests(args, tests);
diff --git a/runtime/observatory/test/vm_metrics_test.dart b/runtime/observatory/test/vm_metrics_test.dart
deleted file mode 100644
index 9a99f09..0000000
--- a/runtime/observatory/test/vm_metrics_test.dart
+++ /dev/null
@@ -1,39 +0,0 @@
-import 'package:observatory/service_io.dart';
-import 'package:unittest/unittest.dart';
-import 'test_helper.dart';
-
-import 'dart:profiler';
-
-void script() {
-  var counter = new Counter('a.b.c', 'description');
-  Metrics.register(counter);
-  counter.value = 1234.5;
-}
-
-var tests = [
-
-(Isolate isolate) =>
-  isolate.get('metrics/vm').then((ServiceMap metrics) {
-    expect(metrics['type'], equals('MetricList'));
-    var members = metrics['members'];
-    expect(members, isList);
-    expect(members.length, greaterThan(1));
-    var foundOldHeapCapacity = members.any((m) =>
-        m.name == 'heap.old.capacity');
-    expect(foundOldHeapCapacity, equals(true));
-}),
-
-(Isolate isolate) =>
-  isolate.get('metrics/vm/heap.old.used').then((ServiceMetric counter) {
-    expect(counter.type, equals('Counter'));
-    expect(counter.name, equals('heap.old.used'));
-}),
-
-(Isolate isolate) =>
-  isolate.get('metrics/vm/doesnotexist').then((DartError err) {
-    expect(err is DartError, isTrue);
-}),
-
-];
-
-main(args) => runIsolateTests(args, tests, testeeBefore: script);
diff --git a/runtime/observatory/test/weak_properties_test.dart b/runtime/observatory/test/weak_properties_test.dart
index 71d5051..c0e3ff7 100644
--- a/runtime/observatory/test/weak_properties_test.dart
+++ b/runtime/observatory/test/weak_properties_test.dart
@@ -4,7 +4,6 @@
 
 library vm_references_test;
 
-import 'dart:async';
 import 'dart:mirrors';
 import 'package:observatory/service_io.dart';
 import 'package:unittest/unittest.dart';
diff --git a/runtime/observatory/web/index_devtools.html b/runtime/observatory/web/index_devtools.html
deleted file mode 100644
index c500c55..0000000
--- a/runtime/observatory/web/index_devtools.html
+++ /dev/null
@@ -1,16 +0,0 @@
-<!DOCTYPE html>
-<html style="height: 100%">
-<head>
-  <title>Dart VM Observatory</title>
-  <meta charset="utf-8">
-  <link rel="import" href="packages/polymer/polymer.html">
-  <script type="text/javascript" src="https://www.google.com/jsapi"></script>
-  <link rel="stylesheet" href="packages/observatory/src/elements/css/shared.css">
-  <link rel="import" href="packages/observatory/elements.html">
-  <script type="application/dart" src="main.dart"></script>
-  <script src="packages/browser/dart.js"></script>
-</head>
-<body style="height:100%">
-  <observatory-application devtools="true"></observatory-application>
-</body>
-</html>
diff --git a/runtime/tools/gyp/runtime-configurations.gypi b/runtime/tools/gyp/runtime-configurations.gypi
index c4b352d..4f88987 100644
--- a/runtime/tools/gyp/runtime-configurations.gypi
+++ b/runtime/tools/gyp/runtime-configurations.gypi
@@ -8,6 +8,7 @@
     # If we have not set dart_io_support to 1 in Dart's all.gypi or common.gypi,
     # then do not build the native libraries supporting  dart:io.
     'dart_io_support%': 0,
+    'dart_io_secure_socket%': 1,
     # Intel VTune related variables.
     'dart_vtune_support%': 0,
     'conditions': [
diff --git a/runtime/vm/ast.cc b/runtime/vm/ast.cc
index f3f0c02..bc70777 100644
--- a/runtime/vm/ast.cc
+++ b/runtime/vm/ast.cc
@@ -515,7 +515,7 @@
   if (field().is_final()) {
     return NULL;
   }
-  if (FLAG_enable_type_checks) {
+  if (Isolate::Current()->TypeChecksEnabled()) {
     rhs = new AssignableNode(
         field().token_pos(),
         rhs,
@@ -574,7 +574,7 @@
     ASSERT(!getter.IsNull() &&
            (getter.kind() == RawFunction::kImplicitStaticFinalGetter));
 #endif
-    if (FLAG_enable_type_checks) {
+    if (Isolate::Current()->TypeChecksEnabled()) {
       rhs = new AssignableNode(
           field.token_pos(),
           rhs,
diff --git a/runtime/vm/ast_transformer.cc b/runtime/vm/ast_transformer.cc
index ccb1333..31d4a57 100644
--- a/runtime/vm/ast_transformer.cc
+++ b/runtime/vm/ast_transformer.cc
@@ -45,7 +45,7 @@
 #undef DEFINE_UNREACHABLE
 
 AwaitTransformer::AwaitTransformer(SequenceNode* preamble,
-                                   ParsedFunction* const parsed_function,
+                                   const ParsedFunction& parsed_function,
                                    LocalScope* function_top)
     : preamble_(preamble),
       temp_cnt_(0),
@@ -131,6 +131,8 @@
       preamble_->scope(), Symbols::AsyncOperationParam());
   LocalVariable* error_param = GetVariableInScope(
       preamble_->scope(), Symbols::AsyncOperationErrorParam());
+  LocalVariable* stack_trace_param = GetVariableInScope(
+      preamble_->scope(), Symbols::AsyncOperationStackTraceParam());
 
   AstNode* transformed_expr = Transform(node->expr());
   preamble_->Add(new(Z) StoreLocalNode(
@@ -212,24 +214,26 @@
   // If this expression is part of a try block, also append the code for
   // restoring the saved try context that lives on the stack.
   const String& async_saved_try_ctx_name =
-      String::Handle(Z, parsed_function_->async_saved_try_ctx_name());
+      String::Handle(Z, parsed_function_.async_saved_try_ctx_name());
   if (!async_saved_try_ctx_name.IsNull()) {
     LocalVariable* async_saved_try_ctx =
         GetVariableInScope(preamble_->scope(), async_saved_try_ctx_name);
     preamble_->Add(new (Z) StoreLocalNode(
         Scanner::kNoSourcePos,
-        parsed_function_->saved_try_ctx(),
+        parsed_function_.saved_try_ctx(),
         new (Z) LoadLocalNode(Scanner::kNoSourcePos, async_saved_try_ctx)));
   }
 
   LoadLocalNode* load_error_param = new (Z) LoadLocalNode(
       Scanner::kNoSourcePos, error_param);
+  LoadLocalNode* load_stack_trace_param = new (Z) LoadLocalNode(
+      Scanner::kNoSourcePos, stack_trace_param);
   SequenceNode* error_ne_null_branch = new (Z) SequenceNode(
       Scanner::kNoSourcePos, ChainNewScope(preamble_->scope()));
   error_ne_null_branch->Add(new (Z) ThrowNode(
       Scanner::kNoSourcePos,
       load_error_param,
-      NULL));
+      load_stack_trace_param));
   preamble_->Add(new (Z) IfNode(
       Scanner::kNoSourcePos,
       new (Z) ComparisonNode(
diff --git a/runtime/vm/ast_transformer.h b/runtime/vm/ast_transformer.h
index 6f2ad4f..423e5fb7 100644
--- a/runtime/vm/ast_transformer.h
+++ b/runtime/vm/ast_transformer.h
@@ -41,7 +41,7 @@
 class AwaitTransformer : public AstNodeVisitor {
  public:
   AwaitTransformer(SequenceNode* preamble,
-                   ParsedFunction* const parsed_function,
+                   const ParsedFunction& parsed_function,
                    LocalScope* function_top);
 
 #define DECLARE_VISIT(BaseName)                                                \
@@ -69,7 +69,7 @@
   SequenceNode* preamble_;
   int32_t temp_cnt_;
   AstNode* result_;
-  ParsedFunction* const parsed_function_;
+  const ParsedFunction& parsed_function_;
   LocalScope* function_top_;
 
   Thread* thread_;
diff --git a/runtime/vm/benchmark_test.cc b/runtime/vm/benchmark_test.cc
index 656c44c..5f67706 100644
--- a/runtime/vm/benchmark_test.cc
+++ b/runtime/vm/benchmark_test.cc
@@ -279,7 +279,7 @@
   const char* path_separator = File::PathSeparator();
   OS::SNPrint(buffer, 2048, packages_path,
               executable_path, path_separator, path_separator);
-  bin::DartUtils::PrepareForScriptLoading(buffer, builtin_lib);
+  bin::DartUtils::PrepareForScriptLoading(buffer, false, builtin_lib);
 }
 
 BENCHMARK(Dart2JSCompileAll) {
diff --git a/runtime/vm/block_scheduler.cc b/runtime/vm/block_scheduler.cc
index 3f902d7..1e2dd98 100644
--- a/runtime/vm/block_scheduler.cc
+++ b/runtime/vm/block_scheduler.cc
@@ -65,7 +65,7 @@
 
 
 void BlockScheduler::AssignEdgeWeights() const {
-  const Code& unoptimized_code = flow_graph()->parsed_function()->code();
+  const Code& unoptimized_code = flow_graph()->parsed_function().code();
   ASSERT(!unoptimized_code.IsNull());
 
   intptr_t entry_count =
diff --git a/runtime/vm/bootstrap_natives.h b/runtime/vm/bootstrap_natives.h
index 2b14eb7..f0de423 100644
--- a/runtime/vm/bootstrap_natives.h
+++ b/runtime/vm/bootstrap_natives.h
@@ -58,12 +58,9 @@
   V(Mint_bitLength, 1)                                                         \
   V(Mint_shlFromInt, 2)                                                        \
   V(Bigint_getNeg, 1)                                                          \
-  V(Bigint_setNeg, 2)                                                          \
   V(Bigint_getUsed, 1)                                                         \
-  V(Bigint_setUsed, 2)                                                         \
   V(Bigint_getDigits, 1)                                                       \
-  V(Bigint_setDigits, 2)                                                       \
-  V(Bigint_allocate, 1)                                                        \
+  V(Bigint_allocate, 4)                                                        \
   V(Double_getIsNegative, 1)                                                   \
   V(Double_getIsInfinite, 1)                                                   \
   V(Double_getIsNaN, 1)                                                        \
@@ -109,6 +106,7 @@
   V(OneByteString_allocate, 1)                                                 \
   V(OneByteString_allocateFromOneByteList, 3)                                  \
   V(OneByteString_setAt, 3)                                                    \
+  V(TwoByteString_allocateFromTwoByteList, 3)                                  \
   V(ExternalOneByteString_getCid, 0)                                           \
   V(String_getHashCode, 1)                                                     \
   V(String_getLength, 1)                                                       \
diff --git a/runtime/vm/class_finalizer.cc b/runtime/vm/class_finalizer.cc
index d229af5..c80e075 100644
--- a/runtime/vm/class_finalizer.cc
+++ b/runtime/vm/class_finalizer.cc
@@ -25,6 +25,7 @@
 DECLARE_FLAG(bool, enable_type_checks);
 DECLARE_FLAG(bool, use_cha);
 
+
 bool ClassFinalizer::AllClassesFinalized() {
   ObjectStore* object_store = Isolate::Current()->object_store();
   const GrowableObjectArray& classes =
@@ -373,7 +374,7 @@
     return;
   }
 
-  if (FLAG_error_on_bad_override) {
+  if (Isolate::Current()->ErrorOnBadOverrideEnabled()) {
     // Verify that the target is compatible with the redirecting factory.
     Error& error = Error::Handle();
     if (!target.HasCompatibleParametersWith(factory, &error)) {
@@ -983,7 +984,7 @@
       TypeArguments::Handle(isolate, parameterized_type.arguments());
   if (!arguments.IsNull() && (arguments.Length() != num_type_parameters)) {
     // Wrong number of type arguments. The type is mapped to the raw type.
-    if (FLAG_error_on_bad_type) {
+    if (Isolate::Current()->ErrorOnBadTypeEnabled()) {
       const String& type_class_name =
           String::Handle(isolate, type_class.Name());
       ReportError(cls, parameterized_type.token_pos(),
@@ -1354,7 +1355,7 @@
            !const_value.IsInstanceOf(type,
                                      Object::null_type_arguments(),
                                      &error))) {
-        if (FLAG_error_on_bad_type) {
+        if (Isolate::Current()->ErrorOnBadTypeEnabled()) {
           const AbstractType& const_value_type = AbstractType::Handle(
               I, const_value.GetType());
           const String& const_value_type_name = String::Handle(
@@ -1417,7 +1418,8 @@
     function ^= array.At(i);
     ResolveAndFinalizeSignature(cls, function);
     name = function.name();
-    if (FLAG_error_on_bad_override &&  // Report signature conflicts only.
+    // Report signature conflicts only.
+    if (Isolate::Current()->ErrorOnBadOverrideEnabled() &&
         !function.is_static() && !function.IsConstructor()) {
       // A constructor cannot override anything.
       for (intptr_t i = 0; i < interfaces.Length(); i++) {
@@ -2565,7 +2567,7 @@
       }
       return;
     }
-    if (FLAG_error_on_bad_type) {
+    if (Isolate::Current()->ErrorOnBadTypeEnabled()) {
       const String& type_class_name = String::Handle(type_class.Name());
       ReportError(cls, type.token_pos(),
                   "wrong number of type arguments for class '%s'",
@@ -2988,7 +2990,7 @@
           prev_error, script, type.token_pos(),
           Report::kMalformedType, Heap::kOld,
           format, args));
-  if (FLAG_error_on_bad_type) {
+  if (Isolate::Current()->ErrorOnBadTypeEnabled()) {
     ReportError(error);
   }
   type.set_error(error);
@@ -3050,7 +3052,7 @@
           Report::kMalboundedType, Heap::kOld,
           format, args));
   va_end(args);
-  if (FLAG_error_on_bad_type) {
+  if (Isolate::Current()->ErrorOnBadTypeEnabled()) {
     ReportError(error);
   }
   type.set_error(error);
diff --git a/runtime/vm/class_finalizer.h b/runtime/vm/class_finalizer.h
index be4c987..5515404 100644
--- a/runtime/vm/class_finalizer.h
+++ b/runtime/vm/class_finalizer.h
@@ -80,7 +80,7 @@
 
   // Return whether processing pending classes (ObjectStore::pending_classes_)
   // failed. The function returns true if the processing was successful.
-  // If processin fails, an error message is set in the sticky error field
+  // If processing fails, an error message is set in the sticky error field
   // in the object store.
   static bool ProcessPendingClasses();
 
diff --git a/runtime/vm/class_table.cc b/runtime/vm/class_table.cc
index c9a817c..d9dfd76 100644
--- a/runtime/vm/class_table.cc
+++ b/runtime/vm/class_table.cc
@@ -195,6 +195,12 @@
   String& name = String::Handle();
 
   for (intptr_t i = 1; i < top_; i++) {
+    if (!HasValidClassAt(i)) {
+      continue;
+    }
+    if (i == kFreeListElement) {
+      continue;
+    }
     cls = At(i);
     if (cls.raw() != reinterpret_cast<RawClass*>(0)) {
       name = cls.Name();
@@ -207,9 +213,8 @@
 void ClassTable::PrintToJSONObject(JSONObject* object) {
   Class& cls = Class::Handle();
   object->AddProperty("type", "ClassList");
-  object->AddProperty("id", "classes");
   {
-    JSONArray members(object, "members");
+    JSONArray members(object, "classes");
     for (intptr_t i = 1; i < top_; i++) {
       if (HasValidClassAt(i)) {
         cls = At(i);
diff --git a/runtime/vm/code_generator.cc b/runtime/vm/code_generator.cc
index b520549..6d97ba5 100644
--- a/runtime/vm/code_generator.cc
+++ b/runtime/vm/code_generator.cc
@@ -227,7 +227,7 @@
   // Code inlined in the caller should have optimized the case where the
   // instantiator can be reused as type argument vector.
   ASSERT(instantiator.IsNull() || !type_arguments.IsUninstantiatedIdentity());
-  if (FLAG_enable_type_checks) {
+  if (Isolate::Current()->TypeChecksEnabled()) {
     Error& bound_error = Error::Handle();
     type_arguments =
         type_arguments.InstantiateAndCanonicalizeFrom(instantiator,
@@ -532,7 +532,7 @@
     }
     String& bound_error_message =  String::Handle();
     if (!bound_error.IsNull()) {
-      ASSERT(FLAG_enable_type_checks);
+      ASSERT(Isolate::Current()->TypeChecksEnabled());
       bound_error_message = String::New(bound_error.ToErrorCString());
     }
     if (src_type_name.Equals(dst_type_name)) {
@@ -739,9 +739,15 @@
   if (getter.IsNull() || getter.IsMethodExtractor()) {
     return false;
   }
-
+  const Class& cache_class = Class::Handle(receiver_class.IsSignatureClass()
+      ? receiver_class.SuperClass()
+      : receiver_class.raw());
+  ASSERT(
+      !receiver_class.IsSignatureClass() ||
+      (receiver_class.SuperClass() == Type::Handle(
+       Isolate::Current()->object_store()->function_impl_type()).type_class()));
   const Function& target_function =
-      Function::Handle(receiver_class.GetInvocationDispatcher(
+      Function::Handle(cache_class.GetInvocationDispatcher(
           target_name,
           arguments_descriptor,
           RawFunction::kInvokeFieldDispatcher));
@@ -1169,7 +1175,7 @@
   }
   if (do_deopt) {
     // TODO(turnidge): Consider using DeoptimizeAt instead.
-    DeoptimizeAll();
+    DeoptimizeFunctionsOnStack();
   }
   if (do_stacktrace) {
     String& var_name = String::Handle();
@@ -1468,7 +1474,7 @@
 
 // Currently checks only that all optimized frames have kDeoptIndex
 // and unoptimized code has the kDeoptAfter.
-void DeoptimizeAll() {
+void DeoptimizeFunctionsOnStack() {
   DartFrameIterator iterator;
   StackFrame* frame = iterator.NextFrame();
   Code& optimized_code = Code::Handle();
diff --git a/runtime/vm/code_generator.h b/runtime/vm/code_generator.h
index 5c0312e..131f7ee 100644
--- a/runtime/vm/code_generator.h
+++ b/runtime/vm/code_generator.h
@@ -54,7 +54,7 @@
 const char* DeoptReasonToCString(ICData::DeoptReasonId deopt_reason);
 
 void DeoptimizeAt(const Code& optimized_code, uword pc);
-void DeoptimizeAll();
+void DeoptimizeFunctionsOnStack();
 
 double DartModulo(double a, double b);
 void SinCos(double arg, double* sin_res, double* cos_res);
diff --git a/runtime/vm/compiler.cc b/runtime/vm/compiler.cc
index 23b60d2..687f566 100644
--- a/runtime/vm/compiler.cc
+++ b/runtime/vm/compiler.cc
@@ -96,7 +96,7 @@
       const ZoneGrowableArray<const ICData*>& ic_data_array,
       intptr_t osr_id) {
     // Build the flow graph.
-    FlowGraphBuilder builder(parsed_function,
+    FlowGraphBuilder builder(*parsed_function,
                              ic_data_array,
                              NULL,  // NULL = not inlining.
                              osr_id);
@@ -134,12 +134,12 @@
     parsed_function->AllocateIrregexpVariables(result.num_stack_locals);
 
     // Build the flow graph.
-    FlowGraphBuilder builder(parsed_function,
+    FlowGraphBuilder builder(*parsed_function,
                              ic_data_array,
                              NULL,  // NULL = not inlining.
                              osr_id);
 
-    return new(isolate_) FlowGraph(parsed_function,
+    return new(isolate_) FlowGraph(*parsed_function,
                                    result.graph_entry,
                                    result.num_blocks);
   }
@@ -686,8 +686,9 @@
       }
 
       Assembler assembler(use_far_branches);
-      FlowGraphCompiler graph_compiler(
-          &assembler, flow_graph, optimized, inline_id_to_function);
+      FlowGraphCompiler graph_compiler(&assembler, flow_graph,
+                                       *parsed_function, optimized,
+                                       inline_id_to_function);
       {
         TimerScope timer(FLAG_compiler_stats,
                          &CompilerStats::graphcompiler_timer,
diff --git a/runtime/vm/constant_propagator.cc b/runtime/vm/constant_propagator.cc
index 7662e8b..8cbb12d 100644
--- a/runtime/vm/constant_propagator.cc
+++ b/runtime/vm/constant_propagator.cc
@@ -740,7 +740,23 @@
       SetValue(instr, non_constant_);
     }
   } else if (IsConstant(value)) {
-    // TODO(kmillikin): Handle instanceof on constants.
+    if (value.IsInstance()) {
+      const Instance& instance = Instance::Cast(value);
+      const AbstractType& checked_type = instr->type();
+      if (instr->instantiator()->BindsToConstantNull() &&
+        instr->instantiator_type_arguments()->BindsToConstantNull()) {
+        const TypeArguments& checked_type_arguments = TypeArguments::Handle();
+        Error& bound_error = Error::Handle();
+        bool is_instance = instance.IsInstanceOf(checked_type,
+                                                 checked_type_arguments,
+                                                 &bound_error);
+        // Can only have bound error with generics.
+        ASSERT(bound_error.IsNull());
+        SetValue(instr, Bool::Get(instr->negate_result()
+                                  ? !is_instance : is_instance));
+        return;
+      }
+    }
     SetValue(instr, non_constant_);
   }
 }
diff --git a/runtime/vm/coverage.cc b/runtime/vm/coverage.cc
index 7344761..69eadca 100644
--- a/runtime/vm/coverage.cc
+++ b/runtime/vm/coverage.cc
@@ -271,7 +271,6 @@
   Class& cls = Class::Handle();
   JSONObject coverage(stream);
   coverage.AddProperty("type", "CodeCoverage");
-  coverage.AddProperty("id", "coverage");
   {
     JSONArray jsarr(&coverage, "coverage");
     for (int i = 0; i < libs.Length(); i++) {
diff --git a/runtime/vm/dart.cc b/runtime/vm/dart.cc
index ac51ad9..2d86044 100644
--- a/runtime/vm/dart.cc
+++ b/runtime/vm/dart.cc
@@ -81,8 +81,7 @@
                            Dart_FileReadCallback file_read,
                            Dart_FileWriteCallback file_write,
                            Dart_FileCloseCallback file_close,
-                           Dart_EntropySource entropy_source,
-                           Dart_ServiceIsolateCreateCalback service_create) {
+                           Dart_EntropySource entropy_source) {
   // TODO(iposva): Fix race condition here.
   if (vm_isolate_ != NULL || !Flags::Initialized()) {
     return "VM already initialized or flags not initialized.";
@@ -143,10 +142,12 @@
 
   Isolate::SetCurrent(NULL);  // Unregister the VM isolate from this thread.
   Isolate::SetCreateCallback(create);
-  Isolate::SetServiceCreateCallback(service_create);
   Isolate::SetInterruptCallback(interrupt);
   Isolate::SetUnhandledExceptionCallback(unhandled);
   Isolate::SetShutdownCallback(shutdown);
+
+  Service::RunService();
+
   return NULL;
 }
 
@@ -260,8 +261,11 @@
     isolate->class_table()->Print();
   }
 
-  isolate->debugger()->NotifyIsolateCreated();
+  Service::MaybeInjectVMServiceLibrary(isolate);
+
   Service::SendIsolateStartupMessage();
+  isolate->debugger()->NotifyIsolateCreated();
+
   // Create tag table.
   isolate->set_tag_table(
       GrowableObjectArray::Handle(GrowableObjectArray::New()));
diff --git a/runtime/vm/dart.h b/runtime/vm/dart.h
index e7d9098..135c6b0 100644
--- a/runtime/vm/dart.h
+++ b/runtime/vm/dart.h
@@ -28,8 +28,7 @@
       Dart_FileReadCallback file_read,
       Dart_FileWriteCallback file_write,
       Dart_FileCloseCallback file_close,
-      Dart_EntropySource entropy_source,
-      Dart_ServiceIsolateCreateCalback service_create);
+      Dart_EntropySource entropy_source);
   static const char* Cleanup();
 
   static Isolate* CreateIsolate(const char* name_prefix);
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index 3bf0457..77af93c 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -1204,12 +1204,10 @@
     Dart_FileReadCallback file_read,
     Dart_FileWriteCallback file_write,
     Dart_FileCloseCallback file_close,
-    Dart_EntropySource entropy_source,
-    Dart_ServiceIsolateCreateCalback service_create) {
+    Dart_EntropySource entropy_source) {
   const char* err_msg = Dart::InitOnce(create, interrupt, unhandled, shutdown,
                                        file_open, file_read, file_write,
-                                       file_close, entropy_source,
-                                       service_create);
+                                       file_close, entropy_source);
   if (err_msg != NULL) {
     OS::PrintErr("Dart_Initialize: %s\n", err_msg);
     return false;
@@ -1252,6 +1250,10 @@
     }
   }
 
+  if (Service::IsServiceIsolateName(script_uri)) {
+    return strdup(script_uri);
+  }
+
   // Skip past any slashes and backslashes in the script uri.
   const char* last_slash = strrchr(script_uri, '/');
   if (last_slash != NULL) {
@@ -1382,6 +1384,18 @@
 }
 
 
+DART_EXPORT Dart_Handle Dart_IsolateSetStrictCompilation(bool value) {
+  CHECK_ISOLATE(Isolate::Current());
+  Isolate* isolate = Isolate::Current();
+  if (isolate->has_compiled()) {
+    return Api::NewError(
+        "%s expects that the isolate has not yet compiled code.", CURRENT_FUNC);
+  }
+  Isolate::Current()->set_strict_compilation(value);
+  return Api::Null();
+}
+
+
 static uint8_t* ApiReallocate(uint8_t* ptr,
                               intptr_t old_size,
                               intptr_t new_size) {
@@ -1521,6 +1535,7 @@
     return error;
   }
   if (FLAG_print_class_table) {
+    HANDLESCOPE(isolate);
     isolate->class_table()->Print();
   }
   return Api::Success();
@@ -3859,6 +3874,8 @@
   // other operations (gc, compilation) are active.
   TIMERSCOPE(isolate, time_dart_execution);
 
+  isolate->set_has_compiled(true);
+
   const String& function_name = Api::UnwrapStringHandle(isolate, name);
   if (function_name.IsNull()) {
     RETURN_TYPE_ERROR(isolate, name, String);
@@ -3884,10 +3901,10 @@
     const Class& cls = Class::Handle(isolate, Type::Cast(obj).type_class());
     const Function& function = Function::Handle(
         isolate,
-        Resolver::ResolveStatic(cls,
-                                function_name,
-                                number_of_arguments,
-                                Object::empty_array()));
+        Resolver::ResolveStaticAllowPrivate(cls,
+                                            function_name,
+                                            number_of_arguments,
+                                            Object::empty_array()));
     if (function.IsNull()) {
       const String& cls_name = String::Handle(isolate, cls.Name());
       return Api::NewError("%s: did not find static method '%s.%s'.",
@@ -5406,13 +5423,14 @@
 
 // --- Service support ---
 
-DART_EXPORT Dart_Isolate Dart_GetServiceIsolate(void* callback_data) {
-  return Api::CastIsolate(Service::GetServiceIsolate(callback_data));
+DART_EXPORT bool Dart_IsServiceIsolate(Dart_Isolate isolate) {
+  Isolate* iso = reinterpret_cast<Isolate*>(isolate);
+  return Service::IsServiceIsolate(iso);
 }
 
 
-DART_EXPORT bool Dart_IsServiceRunning() {
-  return Service::IsRunning();
+DART_EXPORT Dart_Port Dart_ServiceWaitForLoadPort() {
+  return Service::WaitForLoadPort();
 }
 
 
diff --git a/runtime/vm/dart_api_impl_test.cc b/runtime/vm/dart_api_impl_test.cc
index 402257b..7114cd6 100644
--- a/runtime/vm/dart_api_impl_test.cc
+++ b/runtime/vm/dart_api_impl_test.cc
@@ -3580,6 +3580,37 @@
 }
 
 
+TEST_CASE(IsolateSetCheckedMode) {
+  const char* kScriptChars =
+      "int bad1() {\n"
+      "  int foo = 'string';\n"
+      "  return foo;\n"
+      "}\n"
+      "\n"
+      "int good1() {\n"
+      "  int five = 5;\n"
+      "  return five;"
+      "}\n";
+  Dart_Handle result;
+
+  // Create a test library and Load up a test script in it.
+  Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
+  result = Dart_IsolateSetStrictCompilation(true);
+  EXPECT_VALID(result);
+
+  result = Dart_Invoke(lib, NewString("bad1"), 0, NULL);
+  EXPECT_ERROR(result, "Unhandled exception:\n"
+      "type 'String' is not a subtype of type 'int' of 'foo'");
+
+  result = Dart_Invoke(lib, NewString("good1"), 0, NULL);
+  EXPECT_VALID(result);
+
+  result = Dart_IsolateSetStrictCompilation(false);
+  EXPECT_ERROR(result, "Dart_IsolateSetStrictCompilation expects that the "
+                       "isolate has not yet compiled code.");
+}
+
+
 TEST_CASE(DebugName) {
   Dart_Handle debug_name = Dart_DebugName();
   EXPECT_VALID(debug_name);
@@ -5112,7 +5143,7 @@
                "did not find static method 'Methods.staticMethod'");
 
   // Hidden static method.
-  name = PrivateLibName(lib, "_staticMethod");
+  name = NewString("_staticMethod");
   EXPECT(Dart_IsError(Dart_Invoke(lib, name, 1, args)));
   EXPECT(Dart_IsError(Dart_Invoke(instance, name, 1, args)));
   result = Dart_Invoke(type, name, 1, args);
@@ -5141,7 +5172,7 @@
                "2 passed, 1 expected.");
 
   // Hidden top-level method.
-  name = PrivateLibName(lib, "_topMethod");
+  name = NewString("_topMethod");
   EXPECT(Dart_IsError(Dart_Invoke(type, name, 1, args)));
   EXPECT(Dart_IsError(Dart_Invoke(instance, name, 1, args)));
   result = Dart_Invoke(lib, name, 1, args);
@@ -5151,6 +5182,32 @@
 }
 
 
+TEST_CASE(Invoke_PrivateStatic) {
+  const char* kScriptChars =
+      "class Methods {\n"
+      "  static _staticMethod(arg) => 'hidden static $arg';\n"
+      "}\n"
+      "\n";
+
+  // Shared setup.
+  Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
+  Dart_Handle type = Dart_GetType(lib, NewString("Methods"), 0, NULL);
+  Dart_Handle result;
+  EXPECT_VALID(type);
+  Dart_Handle name = NewString("_staticMethod");
+  EXPECT_VALID(name);
+
+  Dart_Handle args[1];
+  args[0] = NewString("!!!");
+  result = Dart_Invoke(type, name, 1, args);
+  EXPECT_VALID(result);
+
+  const char* str = NULL;
+  result = Dart_StringToCString(result, &str);
+  EXPECT_STREQ("hidden static !!!", str);
+}
+
+
 TEST_CASE(Invoke_FunnyArgs) {
   const char* kScriptChars =
       "test(arg) => 'hello $arg';\n";
@@ -7127,8 +7184,11 @@
   if (Dart_CurrentIsolate() != NULL) {
     Dart_ExitIsolate();
   }
-  Dart_Isolate isolate = TestCase::CreateTestIsolate();
+  Dart_Isolate isolate = TestCase::CreateTestIsolate(script_name);
   ASSERT(isolate != NULL);
+  if (Dart_IsServiceIsolate(isolate)) {
+    return isolate;
+  }
   Dart_EnterScope();
   Dart_Handle url = NewString(TestCase::url());
   Dart_Handle source = NewString(kScriptChars);
@@ -8723,4 +8783,100 @@
   EXPECT_EQ(6, value);
 }
 
+TEST_CASE(StringFromExternalTypedData) {
+  const char* kScriptChars =
+    "test(external) {\n"
+    "  var str1 = new String.fromCharCodes(external);\n"
+    "  var str2 = new String.fromCharCodes(new List.from(external));\n"
+    "  if (str2 != str1) throw 'FAIL';\n"
+    "  return str1;\n"
+    "}\n"
+    "testView8(external) {\n"
+    "  return test(external.buffer.asUint8List());\n"
+    "}\n"
+    "testView16(external) {\n"
+    "  return test(external.buffer.asUint16List());\n"
+    "}\n";
+  Dart_Handle lib =
+      TestCase::LoadTestScript(kScriptChars, NULL);
+
+  {
+    uint8_t data[64];
+    for (int i = 0; i < 64; i++) {
+      data[i] = i * 4;
+    }
+    // LATIN-1 in external Uint8List.
+    Dart_Handle external = Dart_NewExternalTypedData(
+        Dart_TypedData_kUint8, data, 64);
+    EXPECT_VALID(external);
+    Dart_Handle dart_args[1];
+    dart_args[0] = external;
+    Dart_Handle result = Dart_Invoke(lib,
+                                     NewString("test"),
+                                     1,
+                                     dart_args);
+    EXPECT_VALID(result);
+    EXPECT(Dart_IsString(result));
+
+    result = Dart_Invoke(lib,
+                         NewString("testView8"),
+                         1,
+                         dart_args);
+    EXPECT_VALID(result);
+    EXPECT(Dart_IsString(result));
+  }
+
+  {
+    uint16_t data[64];
+    for (int i = 0; i < 64; i++) {
+      data[i] = i * 4;
+    }
+    // LATIN-1 in external Uint16List.
+    Dart_Handle external = Dart_NewExternalTypedData(
+        Dart_TypedData_kUint16, data, 64);
+    EXPECT_VALID(external);
+    Dart_Handle dart_args[1];
+    dart_args[0] = external;
+    Dart_Handle result = Dart_Invoke(lib,
+                                     NewString("test"),
+                                     1,
+                                     dart_args);
+    EXPECT_VALID(result);
+    EXPECT(Dart_IsString(result));
+
+    result = Dart_Invoke(lib,
+                         NewString("testView16"),
+                         1,
+                         dart_args);
+    EXPECT_VALID(result);
+    EXPECT(Dart_IsString(result));
+  }
+
+  {
+    uint16_t data[64];
+    for (int i = 0; i < 64; i++) {
+      data[i] = 0x2000 + i * 4;
+    }
+    // Non-LATIN-1 in external Uint16List.
+    Dart_Handle external = Dart_NewExternalTypedData(
+        Dart_TypedData_kUint16, data, 64);
+    EXPECT_VALID(external);
+    Dart_Handle dart_args[1];
+    dart_args[0] = external;
+    Dart_Handle result = Dart_Invoke(lib,
+                                     NewString("test"),
+                                     1,
+                                     dart_args);
+    EXPECT_VALID(result);
+    EXPECT(Dart_IsString(result));
+
+    result = Dart_Invoke(lib,
+                         NewString("testView16"),
+                         1,
+                         dart_args);
+    EXPECT_VALID(result);
+    EXPECT(Dart_IsString(result));
+  }
+}
+
 }  // namespace dart
diff --git a/runtime/vm/debugger.cc b/runtime/vm/debugger.cc
index 8cfa207..e83a1a9 100644
--- a/runtime/vm/debugger.cc
+++ b/runtime/vm/debugger.cc
@@ -170,7 +170,7 @@
   JSONObject jsobj(stream);
   jsobj.AddProperty("type", "Breakpoint");
 
-  jsobj.AddPropertyF("id", "debug/breakpoints/%" Pd "", id());
+  jsobj.AddPropertyF("id", "breakpoints/%" Pd "", id());
   jsobj.AddProperty("breakpointNumber", id());
   jsobj.AddProperty("enabled", IsEnabled());
   jsobj.AddProperty("resolved", IsResolved());
@@ -1066,7 +1066,9 @@
     delete bpt;
   }
   // Signal isolate shutdown event.
-  SignalIsolateEvent(DebuggerEvent::kIsolateShutdown);
+  if (!Service::IsServiceIsolate(isolate_)) {
+    SignalIsolateEvent(DebuggerEvent::kIsolateShutdown);
+  }
 }
 
 
@@ -1122,8 +1124,7 @@
 // that inline the function that contains the newly created breakpoint.
 // We currently don't have this info so we deoptimize all functions.
 void Debugger::DeoptimizeWorld() {
-  // Deoptimize all functions in stack activation frames.
-  DeoptimizeAll();
+  DeoptimizeFunctionsOnStack();
   // Iterate over all classes, deoptimize functions.
   // TODO(hausner): Could possibly be combined with RemoveOptimizedCode()
   const ClassTable& class_table = *isolate_->class_table();
@@ -2254,8 +2255,9 @@
     return;
   }
   isolate_ = isolate;
+
   // Use the isolate's control port as the isolate_id for debugging.
-  // This port will be used as a unique ID to represet the isolate in the
+  // This port will be used as a unique ID to represent the isolate in the
   // debugger wire protocol messages.
   isolate_id_ = isolate->main_port();
   initialized_ = true;
@@ -2264,7 +2266,9 @@
 
 void Debugger::NotifyIsolateCreated() {
   // Signal isolate creation event.
-  SignalIsolateEvent(DebuggerEvent::kIsolateCreated);
+  if (!Service::IsServiceIsolate(isolate_)) {
+    SignalIsolateEvent(DebuggerEvent::kIsolateCreated);
+  }
 }
 
 
diff --git a/runtime/vm/debugger_test.cc b/runtime/vm/debugger_test.cc
index 35dbcab..4c3afa6 100644
--- a/runtime/vm/debugger_test.cc
+++ b/runtime/vm/debugger_test.cc
@@ -69,14 +69,14 @@
     }
     ExpectSubstringF(
         js.ToCString(),
-        "[{\"type\":\"Breakpoint\",\"id\":\"debug\\/breakpoints\\/2\","
+        "[{\"type\":\"Breakpoint\",\"id\":\"breakpoints\\/2\","
         "\"breakpointNumber\":2,\"enabled\":true,\"resolved\":false,"
         "\"location\":{\"type\":\"Location\","
         "\"script\":{\"type\":\"@Script\","
         "\"id\":\"libraries\\/%" Pd "\\/scripts\\/test-lib\","
         "\"name\":\"test-lib\","
         "\"kind\":\"script\"},\"tokenPos\":14}},"
-        "{\"type\":\"Breakpoint\",\"id\":\"debug\\/breakpoints\\/1\","
+        "{\"type\":\"Breakpoint\",\"id\":\"breakpoints\\/1\","
         "\"breakpointNumber\":1,\"enabled\":true,\"resolved\":false,"
         "\"location\":{\"type\":\"Location\","
         "\"script\":{\"type\":\"@Script\","
diff --git a/runtime/vm/flow_graph.cc b/runtime/vm/flow_graph.cc
index ec53580..2cf115c 100644
--- a/runtime/vm/flow_graph.cc
+++ b/runtime/vm/flow_graph.cc
@@ -19,7 +19,7 @@
 DECLARE_FLAG(bool, verify_compiler);
 
 
-FlowGraph::FlowGraph(ParsedFunction* parsed_function,
+FlowGraph::FlowGraph(const ParsedFunction& parsed_function,
                      GraphEntryInstr* graph_entry,
                      intptr_t max_block_id)
   : thread_(Thread::Current()),
@@ -27,8 +27,8 @@
     current_ssa_temp_index_(0),
     max_block_id_(max_block_id),
     parsed_function_(parsed_function),
-    num_copied_params_(parsed_function->num_copied_params()),
-    num_non_copied_params_(parsed_function->num_non_copied_params()),
+    num_copied_params_(parsed_function.num_copied_params()),
+    num_non_copied_params_(parsed_function.num_non_copied_params()),
     graph_entry_(graph_entry),
     preorder_(),
     postorder_(),
@@ -41,8 +41,8 @@
     licm_allowed_(true),
     loop_headers_(NULL),
     loop_invariant_loads_(NULL),
-    guarded_fields_(parsed_function->guarded_fields()),
-    deferred_prefixes_(parsed_function->deferred_prefixes()),
+    guarded_fields_(parsed_function.guarded_fields()),
+    deferred_prefixes_(parsed_function.deferred_prefixes()),
     captured_parameters_(new(zone()) BitVector(zone(), variable_count())) {
   DiscoverBlocks();
 }
@@ -87,7 +87,7 @@
 
 GrowableArray<BlockEntryInstr*>* FlowGraph::CodegenBlockOrder(
     bool is_optimized) {
-  return ShouldReorderBlocks(parsed_function()->function(), is_optimized)
+  return ShouldReorderBlocks(function(), is_optimized)
       ? &optimized_block_order_
       : &reverse_postorder_;
 }
@@ -855,7 +855,7 @@
   if (!IsCompiledForOsr()) {
     for (intptr_t i = parameter_count(); i < variable_count(); ++i) {
       if (i == CurrentContextEnvIndex()) {
-        if (parsed_function()->function().IsClosureFunction()) {
+        if (function().IsClosureFunction()) {
           CurrentContextInstr* context = new CurrentContextInstr();
           context->set_ssa_temp_index(alloc_ssa_temp_index());  // New SSA temp.
           AddToInitialDefinitions(context);
diff --git a/runtime/vm/flow_graph.h b/runtime/vm/flow_graph.h
index ad8256f..b9b932f 100644
--- a/runtime/vm/flow_graph.h
+++ b/runtime/vm/flow_graph.h
@@ -84,22 +84,25 @@
 // Class to encapsulate the construction and manipulation of the flow graph.
 class FlowGraph : public ZoneAllocated {
  public:
-  FlowGraph(ParsedFunction* parsed_function,
+  FlowGraph(const ParsedFunction& parsed_function,
             GraphEntryInstr* graph_entry,
             intptr_t max_block_id);
 
   // Function properties.
-  ParsedFunction* parsed_function() const {
+  const ParsedFunction& parsed_function() const {
     return parsed_function_;
   }
+  const Function& function() const {
+    return parsed_function_.function();
+  }
   intptr_t parameter_count() const {
     return num_copied_params_ + num_non_copied_params_;
   }
   intptr_t variable_count() const {
-    return parameter_count() + parsed_function_->num_stack_locals();
+    return parameter_count() + parsed_function_.num_stack_locals();
   }
   intptr_t num_stack_locals() const {
-    return parsed_function_->num_stack_locals();
+    return parsed_function_.num_stack_locals();
   }
   intptr_t num_copied_params() const {
     return num_copied_params_;
@@ -108,15 +111,15 @@
     return num_non_copied_params_;
   }
   bool IsIrregexpFunction() const {
-    return parsed_function()->function().IsIrregexpFunction();
+    return function().IsIrregexpFunction();
   }
 
   LocalVariable* CurrentContextVar() const {
-    return parsed_function()->current_context_var();
+    return parsed_function().current_context_var();
   }
 
   intptr_t CurrentContextEnvIndex() const {
-    return parsed_function()->current_context_var()->BitIndexIn(
+    return parsed_function().current_context_var()->BitIndexIn(
         num_non_copied_params_);
   }
 
@@ -339,7 +342,7 @@
   intptr_t max_block_id_;
 
   // Flow graph fields.
-  ParsedFunction* parsed_function_;
+  const ParsedFunction& parsed_function_;
   const intptr_t num_copied_params_;
   const intptr_t num_non_copied_params_;
   GraphEntryInstr* graph_entry_;
diff --git a/runtime/vm/flow_graph_allocator.cc b/runtime/vm/flow_graph_allocator.cc
index 5e41375..5613de1 100644
--- a/runtime/vm/flow_graph_allocator.cc
+++ b/runtime/vm/flow_graph_allocator.cc
@@ -2919,8 +2919,7 @@
   }
 
   if (FLAG_print_ssa_liveranges) {
-    const Function& function = flow_graph_.parsed_function()->function();
-
+    const Function& function = flow_graph_.function();
     OS::Print("-- [before ssa allocator] ranges [%s] ---------\n",
               function.ToFullyQualifiedCString());
     PrintLiveRanges();
@@ -2960,7 +2959,7 @@
   entry->set_spill_slot_count(cpu_spill_slot_count_ + double_spill_slot_count);
 
   if (FLAG_print_ssa_liveranges) {
-    const Function& function = flow_graph_.parsed_function()->function();
+    const Function& function = flow_graph_.function();
 
     OS::Print("-- [after ssa allocator] ranges [%s] ---------\n",
               function.ToFullyQualifiedCString());
diff --git a/runtime/vm/flow_graph_builder.cc b/runtime/vm/flow_graph_builder.cc
index 108180a..009c60c 100644
--- a/runtime/vm/flow_graph_builder.cc
+++ b/runtime/vm/flow_graph_builder.cc
@@ -237,18 +237,18 @@
 
 
 FlowGraphBuilder::FlowGraphBuilder(
-    ParsedFunction* parsed_function,
+    const ParsedFunction& parsed_function,
     const ZoneGrowableArray<const ICData*>& ic_data_array,
     InlineExitCollector* exit_collector,
     intptr_t osr_id) :
         parsed_function_(parsed_function),
         ic_data_array_(ic_data_array),
-        num_copied_params_(parsed_function->num_copied_params()),
+        num_copied_params_(parsed_function.num_copied_params()),
         // All parameters are copied if any parameter is.
         num_non_copied_params_((num_copied_params_ == 0)
-            ? parsed_function->function().num_fixed_parameters()
+            ? parsed_function.function().num_fixed_parameters()
             : 0),
-        num_stack_locals_(parsed_function->num_stack_locals()),
+        num_stack_locals_(parsed_function.num_stack_locals()),
         exit_collector_(exit_collector),
         last_used_block_id_(0),  // 0 is used for the graph entry.
         try_index_(CatchClauseNode::kInvalidTryIndex),
@@ -748,13 +748,13 @@
 
 
 Definition* EffectGraphVisitor::BuildStoreExprTemp(Value* value) {
-  return BuildStoreTemp(*owner()->parsed_function()->expression_temp_var(),
+  return BuildStoreTemp(*owner()->parsed_function().expression_temp_var(),
                         value);
 }
 
 
 Definition* EffectGraphVisitor::BuildLoadExprTemp() {
-  return BuildLoadLocal(*owner()->parsed_function()->expression_temp_var());
+  return BuildLoadLocal(*owner()->parsed_function().expression_temp_var());
 }
 
 
@@ -825,13 +825,13 @@
 
 Definition* EffectGraphVisitor::BuildStoreContext(Value* value) {
   return new(I) StoreLocalInstr(
-      *owner()->parsed_function()->current_context_var(), value);
+      *owner()->parsed_function().current_context_var(), value);
 }
 
 
 Definition* EffectGraphVisitor::BuildCurrentContext() {
   return new(I) LoadLocalInstr(
-      *owner()->parsed_function()->current_context_var());
+      *owner()->parsed_function().current_context_var());
 }
 
 
@@ -889,7 +889,8 @@
 
 
 void TestGraphVisitor::ReturnValue(Value* value) {
-  if (FLAG_enable_type_checks || FLAG_enable_asserts) {
+  if (Isolate::Current()->TypeChecksEnabled() ||
+      Isolate::Current()->AssertsEnabled()) {
     value = Bind(new(I) AssertBooleanInstr(condition_token_pos(), value));
   }
   Value* constant_true = Bind(new(I) ConstantInstr(Bool::True()));
@@ -924,7 +925,7 @@
         false));  // No number check.
   } else {
     branch = new(I) BranchInstr(comp);
-    branch->set_is_checked(FLAG_enable_type_checks);
+    branch->set_is_checked(Isolate::Current()->TypeChecksEnabled());
   }
   AddInstruction(branch);
   CloseFragment();
@@ -934,7 +935,7 @@
 
 
 void TestGraphVisitor::MergeBranchWithNegate(BooleanNegateInstr* neg) {
-  ASSERT(!FLAG_enable_type_checks);
+  ASSERT(!Isolate::Current()->TypeChecksEnabled());
   Value* constant_true = Bind(new(I) ConstantInstr(Bool::True()));
   StrictCompareInstr* comp =
       new(I) StrictCompareInstr(condition_token_pos(),
@@ -956,7 +957,7 @@
     MergeBranchWithComparison(comp);
     return;
   }
-  if (!FLAG_enable_type_checks) {
+  if (!Isolate::Current()->TypeChecksEnabled()) {
     BooleanNegateInstr* neg = definition->AsBooleanNegate();
     if (neg != NULL) {
       MergeBranchWithNegate(neg);
@@ -1005,7 +1006,7 @@
 
 
 void EffectGraphVisitor::InlineBailout(const char* reason) const {
-  owner()->parsed_function()->function().set_is_inlinable(false);
+  owner()->function().set_is_inlinable(false);
   if (owner()->IsInlining()) owner()->Bailout(reason);
 }
 
@@ -1019,7 +1020,7 @@
   Value* return_value = for_value.value();
 
   if (node->inlined_finally_list_length() > 0) {
-    LocalVariable* temp = owner()->parsed_function()->finally_return_temp_var();
+    LocalVariable* temp = owner()->parsed_function().finally_return_temp_var();
     ASSERT(temp != NULL);
     Do(BuildStoreLocal(*temp, return_value));
     for (intptr_t i = 0; i < node->inlined_finally_list_length(); i++) {
@@ -1039,13 +1040,13 @@
   // unchained so that captured variables can be inspected.
   // No debugger check is done in native functions or for return
   // statements for which there is no associated source position.
-  const Function& function = owner()->parsed_function()->function();
+  const Function& function = owner()->function();
   if ((node->token_pos() != Scanner::kNoSourcePos) && !function.is_native()) {
     AddInstruction(new(I) DebugStepCheckInstr(node->token_pos(),
                                               RawPcDescriptors::kRuntimeCall));
   }
 
-  if (FLAG_enable_type_checks) {
+  if (Isolate::Current()->TypeChecksEnabled()) {
     const bool is_implicit_dynamic_getter =
         (!function.is_static() &&
         ((function.kind() == RawFunction::kImplicitGetter) ||
@@ -1143,7 +1144,7 @@
     ReturnDefinition(new(I) ConstantInstr(type));
   } else {
     const Class& instantiator_class = Class::ZoneHandle(
-        I, owner()->parsed_function()->function().Owner());
+        I, owner()->function().Owner());
     Value* instantiator_value = BuildInstantiatorTypeArguments(
         node->token_pos(), instantiator_class, NULL);
     ReturnDefinition(new(I) InstantiateTypeInstr(
@@ -1187,7 +1188,7 @@
 
   const bool eliminated = value->Type()->IsAssignableTo(dst_type);
   if (FLAG_trace_type_check_elimination) {
-    FlowGraphPrinter::PrintTypeCheck(*owner()->parsed_function(),
+    FlowGraphPrinter::PrintTypeCheck(owner()->parsed_function(),
                                      token_pos,
                                      value,
                                      dst_type,
@@ -1244,7 +1245,8 @@
     TestGraphVisitor for_left(owner(), node->left()->token_pos());
     node->left()->Visit(&for_left);
     EffectGraphVisitor empty(owner());
-    if (FLAG_enable_type_checks || FLAG_enable_asserts) {
+    if (Isolate::Current()->TypeChecksEnabled() ||
+        Isolate::Current()->AssertsEnabled()) {
       ValueGraphVisitor for_right(owner());
       node->right()->Visit(&for_right);
       Value* right_value = for_right.value();
@@ -1309,7 +1311,8 @@
     ValueGraphVisitor for_right(owner());
     node->right()->Visit(&for_right);
     Value* right_value = for_right.value();
-    if (FLAG_enable_type_checks|| FLAG_enable_asserts) {
+    if (Isolate::Current()->TypeChecksEnabled() ||
+        Isolate::Current()->AssertsEnabled()) {
       right_value =
           for_right.Bind(new(I) AssertBooleanInstr(node->right()->token_pos(),
                                                    right_value));
@@ -1396,7 +1399,7 @@
     PushArgumentInstr** push_instantiator_result,
     PushArgumentInstr** push_instantiator_type_arguments_result) {
   const Class& instantiator_class = Class::Handle(
-      I, owner()->parsed_function()->function().Owner());
+      I, owner()->function().Owner());
   // Since called only when type tested against is not instantiated.
   ASSERT(instantiator_class.NumTypeParameters() > 0);
   Value* instantiator_type_arguments = NULL;
@@ -1426,7 +1429,7 @@
   Value* instantiator = NULL;
   Value* instantiator_type_arguments = NULL;
   const Class& instantiator_class = Class::Handle(
-      I, owner()->parsed_function()->function().Owner());
+      I, owner()->function().Owner());
   // Since called only when type tested against is not instantiated.
   ASSERT(instantiator_class.NumTypeParameters() > 0);
   instantiator = BuildInstantiator(instantiator_class);
@@ -1484,6 +1487,7 @@
 void EffectGraphVisitor::BuildAwaitJump(LocalVariable* old_context,
                                         LocalVariable* continuation_result,
                                         LocalVariable* continuation_error,
+                                        LocalVariable* continuation_stack_trace,
                                         const intptr_t old_ctx_level,
                                         JoinEntryInstr* target) {
   // Building a jump consists of the following actions:
@@ -1500,6 +1504,8 @@
       Bind(BuildLoadLocal(*continuation_result)));
   LocalVariable* temp_error_var = EnterTempLocalScope(
       Bind(BuildLoadLocal(*continuation_error)));
+  LocalVariable* temp_stack_trace_var = EnterTempLocalScope(
+      Bind(BuildLoadLocal(*continuation_stack_trace)));
   // Restore the saved continuation context.
   BuildRestoreContext(*old_context);
 
@@ -1538,7 +1544,18 @@
       Scanner::kNoSourcePos);
   Do(store2);
 
+  context_val = Bind(new(I) LoadLocalInstr(*temp_context_var));
+  store_val = Bind(new(I) LoadLocalInstr(*temp_stack_trace_var));
+  StoreInstanceFieldInstr* store3 = new(I) StoreInstanceFieldInstr(
+      Context::variable_offset(continuation_stack_trace->index()),
+      context_val,
+      store_val,
+      kEmitStoreBarrier,
+      Scanner::kNoSourcePos);
+  Do(store3);
+
   Do(ExitTempLocalScope(temp_context_var));
+  Do(ExitTempLocalScope(temp_stack_trace_var));
   Do(ExitTempLocalScope(temp_error_var));
   Do(ExitTempLocalScope(temp_result_var));
 
@@ -1768,7 +1785,8 @@
         2,
         owner()->ic_data_array());
     if (node->kind() == Token::kNE) {
-      if (FLAG_enable_type_checks || FLAG_enable_asserts) {
+      if (Isolate::Current()->TypeChecksEnabled() ||
+          Isolate::Current()->AssertsEnabled()) {
         Value* value = Bind(result);
         result = new(I) AssertBooleanInstr(node->token_pos(), value);
       }
@@ -1814,7 +1832,8 @@
     node->operand()->Visit(&for_value);
     Append(for_value);
     Value* value = for_value.value();
-    if (FLAG_enable_type_checks || FLAG_enable_asserts) {
+    if (Isolate::Current()->TypeChecksEnabled() ||
+        Isolate::Current()->AssertsEnabled()) {
       value =
           Bind(new(I) AssertBooleanInstr(node->operand()->token_pos(), value));
     }
@@ -2448,8 +2467,7 @@
     ASSERT(!function.HasCode());
     ASSERT(function.context_scope() == ContextScope::null());
     function.set_context_scope(context_scope);
-    const Class& cls = Class::Handle(
-        I, owner()->parsed_function()->function().Owner());
+    const Class& cls = Class::Handle(I, owner()->function().Owner());
     // The closure is now properly setup, add it to the lookup table.
     // It is possible that the compiler creates more than one function
     // object for the same closure, e.g. when inlining nodes from
@@ -2485,7 +2503,7 @@
            Closure::type_arguments_offset());
     ASSERT(cls.instance_size() == Closure::InstanceSize());
     const Class& instantiator_class = Class::Handle(
-        I, owner()->parsed_function()->function().Owner());
+        I, owner()->function().Owner());
     type_arguments = BuildInstantiatorTypeArguments(node->token_pos(),
                                                     instantiator_class,
                                                     NULL);
@@ -2807,8 +2825,7 @@
 
 Value* EffectGraphVisitor::BuildInstantiator(const Class& instantiator_class) {
   ASSERT(instantiator_class.NumTypeParameters() > 0);
-  Function& outer_function =
-      Function::Handle(I, owner()->parsed_function()->function().raw());
+  Function& outer_function = Function::Handle(I, owner()->function().raw());
   while (outer_function.IsLocalFunction()) {
     outer_function = outer_function.parent_function();
   }
@@ -2816,7 +2833,7 @@
     return NULL;
   }
 
-  LocalVariable* instantiator = owner()->parsed_function()->instantiator();
+  LocalVariable* instantiator = owner()->parsed_function().instantiator();
   ASSERT(instantiator != NULL);
   Value* result = Bind(BuildLoadLocal(*instantiator));
   return result;
@@ -2844,8 +2861,7 @@
     type_arguments = type_arguments.Canonicalize();
     return Bind(new(I) ConstantInstr(type_arguments));
   }
-  Function& outer_function =
-      Function::Handle(I, owner()->parsed_function()->function().raw());
+  Function& outer_function = Function::Handle(I, owner()->function().raw());
   while (outer_function.IsLocalFunction()) {
     outer_function = outer_function.parent_function();
   }
@@ -2853,7 +2869,7 @@
     // No instantiator for factories.
     ASSERT(instantiator == NULL);
     LocalVariable* instantiator_var =
-        owner()->parsed_function()->instantiator();
+        owner()->parsed_function().instantiator();
     ASSERT(instantiator_var != NULL);
     return Bind(BuildLoadLocal(*instantiator_var));
   }
@@ -2884,7 +2900,7 @@
   }
   // The type arguments are uninstantiated.
   const Class& instantiator_class = Class::ZoneHandle(
-      I, owner()->parsed_function()->function().Owner());
+      I, owner()->function().Owner());
   Value* instantiator_value =
       BuildInstantiatorTypeArguments(token_pos, instantiator_class, NULL);
   const bool use_instantiator_type_args =
@@ -3190,7 +3206,7 @@
 
 
 void EffectGraphVisitor::VisitNativeBodyNode(NativeBodyNode* node) {
-  const Function& function = owner()->parsed_function()->function();
+  const Function& function = owner()->function();
   if (!function.IsClosureFunction()) {
     MethodRecognizer::Kind kind = MethodRecognizer::RecognizeKind(function);
     switch (kind) {
@@ -3302,23 +3318,6 @@
         load->set_recognized_kind(kind);
         return ReturnDefinition(load);
       }
-      case MethodRecognizer::kBigint_setDigits: {
-        Value* receiver = Bind(BuildLoadThisVar(node->scope()));
-        LocalVariable* value_var =
-            node->scope()->LookupVariable(Symbols::Value(), true);
-        ASSERT(value_var != NULL);
-        Value* value = Bind(new(I) LoadLocalInstr(*value_var));
-        StoreInstanceFieldInstr* store = new(I) StoreInstanceFieldInstr(
-            Bigint::digits_offset(),
-            receiver,
-            value,
-            kEmitStoreBarrier,
-            node->token_pos());
-        Do(store);
-        ConstantInstr* null_const = new(I) ConstantInstr(
-            Object::ZoneHandle(I, Object::null()));
-        return ReturnDefinition(null_const);
-      }
       case MethodRecognizer::kBigint_getUsed: {
         Value* receiver = Bind(BuildLoadThisVar(node->scope()));
         LoadFieldInstr* load = new(I) LoadFieldInstr(
@@ -3330,23 +3329,6 @@
         load->set_recognized_kind(kind);
         return ReturnDefinition(load);
       }
-      case MethodRecognizer::kBigint_setUsed: {
-        Value* receiver = Bind(BuildLoadThisVar(node->scope()));
-        LocalVariable* value_var =
-            node->scope()->LookupVariable(Symbols::Value(), true);
-        ASSERT(value_var != NULL);
-        Value* value = Bind(new(I) LoadLocalInstr(*value_var));
-        StoreInstanceFieldInstr* store = new(I) StoreInstanceFieldInstr(
-            Bigint::used_offset(),
-            receiver,
-            value,
-            kNoStoreBarrier,
-            node->token_pos());
-        Do(store);
-        ConstantInstr* null_const = new(I) ConstantInstr(
-            Object::ZoneHandle(I, Object::null()));
-        return ReturnDefinition(null_const);
-      }
       case MethodRecognizer::kBigint_getNeg: {
         Value* receiver = Bind(BuildLoadThisVar(node->scope()));
         LoadFieldInstr* load = new(I) LoadFieldInstr(
@@ -3358,23 +3340,6 @@
         load->set_recognized_kind(kind);
         return ReturnDefinition(load);
       }
-      case MethodRecognizer::kBigint_setNeg: {
-        Value* receiver = Bind(BuildLoadThisVar(node->scope()));
-        LocalVariable* value_var =
-            node->scope()->LookupVariable(Symbols::Value(), true);
-        ASSERT(value_var != NULL);
-        Value* value = Bind(new(I) LoadLocalInstr(*value_var));
-        StoreInstanceFieldInstr* store = new(I) StoreInstanceFieldInstr(
-            Bigint::neg_offset(),
-            receiver,
-            value,
-            kEmitStoreBarrier,
-            node->token_pos());
-        Do(store);
-        ConstantInstr* null_const = new(I) ConstantInstr(
-            Object::ZoneHandle(I, Object::null()));
-        return ReturnDefinition(null_const);
-      }
       default:
         break;
     }
@@ -3420,7 +3385,7 @@
   node->value()->Visit(&for_value);
   Append(for_value);
   Value* store_value = for_value.value();
-  if (FLAG_enable_type_checks) {
+  if (Isolate::Current()->TypeChecksEnabled()) {
     store_value = BuildAssignableValue(node->value()->token_pos(),
                                        store_value,
                                        node->local().type(),
@@ -3461,7 +3426,7 @@
   node->value()->Visit(&for_value);
   Append(for_value);
   Value* store_value = for_value.value();
-  if (FLAG_enable_type_checks) {
+  if (Isolate::Current()->TypeChecksEnabled()) {
     const AbstractType& type =
         AbstractType::ZoneHandle(I, node->field().type());
     const String& dst_name = String::ZoneHandle(I, node->field().name());
@@ -3711,7 +3676,7 @@
 
 bool EffectGraphVisitor::HasContextScope() const {
   const ContextScope& context_scope = ContextScope::Handle(
-      owner()->parsed_function()->function().context_scope());
+      owner()->function().context_scope());
   return !context_scope.IsNull() && (context_scope.num_variables() > 0);
 }
 
@@ -3740,7 +3705,7 @@
   const intptr_t num_context_variables =
       (scope != NULL) ? scope->num_context_variables() : 0;
   const bool is_top_level_sequence =
-      node == owner()->parsed_function()->node_sequence();
+      node == owner()->parsed_function().node_sequence();
   // The outermost function sequence cannot contain a label.
   ASSERT((node->label() == NULL) || !is_top_level_sequence);
   NestedBlock nested_block(owner(), node);
@@ -3769,7 +3734,7 @@
     // the captured parameters from the frame into the context.
     if (is_top_level_sequence) {
       ASSERT(scope->context_level() == 1);
-      const Function& function = owner()->parsed_function()->function();
+      const Function& function = owner()->function();
       const int num_params = function.NumParameters();
       int param_frame_index = (num_params == function.num_fixed_parameters()) ?
           (kParamEndSlotFromFp + num_params) : kFirstLocalSlotFromFp;
@@ -3807,7 +3772,7 @@
 
   // This check may be deleted if the generated code is leaf.
   // Native functions don't need a stack check at entry.
-  const Function& function = owner()->parsed_function()->function();
+  const Function& function = owner()->function();
   if (is_top_level_sequence && !function.is_native()) {
     // Always allocate CheckOverflowInstr so that deopt-ids match regardless
     // if we inline or not.
@@ -3823,8 +3788,8 @@
     }
   }
 
-  if (FLAG_enable_type_checks && is_top_level_sequence) {
-    const Function& function = owner()->parsed_function()->function();
+  if (Isolate::Current()->TypeChecksEnabled() && is_top_level_sequence) {
+    const Function& function = owner()->function();
     const int num_params = function.NumParameters();
     int pos = 0;
     if (function.IsConstructor()) {
@@ -3856,8 +3821,7 @@
   // If this node sequence is the body of an async closure leave room for a
   // preamble. The preamble is generated after visiting the body.
   GotoInstr* preamble_start = NULL;
-  if (is_top_level_sequence &&
-      (owner()->parsed_function()->function().is_async_closure())) {
+  if (is_top_level_sequence && (owner()->function().is_async_closure())) {
     JoinEntryInstr* preamble_end = new(I) JoinEntryInstr(
         owner()->AllocateBlockId(), owner()->try_index());
     ASSERT(exit() != NULL);
@@ -3882,8 +3846,7 @@
   // Continuation part:
   // After generating the CFG for the body we can create the preamble because we
   // know exactly how many continuation states we need.
-  if (is_top_level_sequence &&
-      (owner()->parsed_function()->function().is_async_closure())) {
+  if (is_top_level_sequence && (owner()->function().is_async_closure())) {
     ASSERT(preamble_start != NULL);
     // We are at the top level. Fetch the corresponding scope.
     LocalScope* top_scope = node->scope();
@@ -3906,6 +3869,8 @@
         Symbols::AsyncOperationParam(), false);
     LocalVariable* continuation_error = top_scope->LookupVariable(
         Symbols::AsyncOperationErrorParam(), false);
+    LocalVariable* continuation_stack_trace = top_scope->LookupVariable(
+        Symbols::AsyncOperationStackTraceParam(), false);
     for (intptr_t i = 0; i < num_await_states; i++) {
       check_jump_count = new(I) ComparisonNode(
           Scanner::kNoSourcePos,
@@ -3921,6 +3886,7 @@
       for_true.BuildAwaitJump(old_context,
                               continuation_result,
                               continuation_error,
+                              continuation_stack_trace,
                               (*owner()->await_levels())[i],
                               (*owner()->await_joins())[i]);
       Join(for_test, for_true, for_false);
@@ -4098,7 +4064,7 @@
   intptr_t args_pos = method_arguments->token_pos();
   LocalVariable* temp = NULL;
   if (save_last_arg) {
-    temp = owner()->parsed_function()->EnsureExpressionTemp();
+    temp = owner()->parsed_function().expression_temp_var();
   }
   ArgumentListNode* args =
       Parser::BuildNoSuchMethodArguments(args_pos,
@@ -4272,10 +4238,10 @@
 FlowGraph* FlowGraphBuilder::BuildGraph() {
   if (FLAG_print_ast) {
     // Print the function ast before IL generation.
-    AstPrinter::PrintFunctionNodes(*parsed_function());
+    AstPrinter::PrintFunctionNodes(parsed_function());
   }
   if (FLAG_print_scopes) {
-    AstPrinter::PrintFunctionScope(*parsed_function());
+    AstPrinter::PrintFunctionScope(parsed_function());
   }
   TargetEntryInstr* normal_entry =
       new(I) TargetEntryInstr(AllocateBlockId(),
@@ -4283,7 +4249,7 @@
   graph_entry_ =
       new(I) GraphEntryInstr(parsed_function(), normal_entry, osr_id_);
   EffectGraphVisitor for_effect(this);
-  parsed_function()->node_sequence()->Visit(&for_effect);
+  parsed_function().node_sequence()->Visit(&for_effect);
   AppendFragment(normal_entry, for_effect);
   // Check that the graph is properly terminated.
   ASSERT(!for_effect.is_open());
@@ -4303,7 +4269,7 @@
 
 void FlowGraphBuilder::PruneUnreachable() {
   ASSERT(osr_id_ != Isolate::kNoDeoptId);
-  Zone* zone = parsed_function()->zone();
+  Zone* zone = parsed_function().zone();
   BitVector* block_marks = new(zone) BitVector(zone, last_used_block_id_ + 1);
   bool found = graph_entry_->PruneUnreachable(this, graph_entry_, NULL, osr_id_,
                                               block_marks);
@@ -4312,7 +4278,7 @@
 
 
 void FlowGraphBuilder::Bailout(const char* reason) const {
-  const Function& function = parsed_function_->function();
+  const Function& function = parsed_function_.function();
   Report::MessageF(Report::kBailout,
                    Script::Handle(function.script()),
                    function.token_pos(),
diff --git a/runtime/vm/flow_graph_builder.h b/runtime/vm/flow_graph_builder.h
index 31c4fbe..fa337d1 100644
--- a/runtime/vm/flow_graph_builder.h
+++ b/runtime/vm/flow_graph_builder.h
@@ -139,18 +139,19 @@
 
 
 // Build a flow graph from a parsed function's AST.
-class FlowGraphBuilder: public ValueObject {
+class FlowGraphBuilder : public ValueObject {
  public:
   // The inlining context is NULL if not inlining.  The osr_id is the deopt
   // id of the OSR entry or Isolate::kNoDeoptId if not compiling for OSR.
-  FlowGraphBuilder(ParsedFunction* parsed_function,
+  FlowGraphBuilder(const ParsedFunction& parsed_function,
                    const ZoneGrowableArray<const ICData*>& ic_data_array,
                    InlineExitCollector* exit_collector,
                    intptr_t osr_id);
 
   FlowGraph* BuildGraph();
 
-  ParsedFunction* parsed_function() const { return parsed_function_; }
+  const ParsedFunction& parsed_function() const { return parsed_function_; }
+  const Function& function() const { return parsed_function_.function(); }
   const ZoneGrowableArray<const ICData*>& ic_data_array() const {
     return ic_data_array_;
   }
@@ -202,11 +203,11 @@
   InlineExitCollector* exit_collector() const { return exit_collector_; }
 
   ZoneGrowableArray<const Field*>* guarded_fields() const {
-    return parsed_function_->guarded_fields();
+    return parsed_function_.guarded_fields();
   }
 
   ZoneGrowableArray<const LibraryPrefix*>* deferred_prefixes() const {
-    return parsed_function_->deferred_prefixes();
+    return parsed_function_.deferred_prefixes();
   }
 
   intptr_t temp_count() const { return temp_count_; }
@@ -228,7 +229,7 @@
   // Returns address where the constant 'value' is stored or 0 if not found.
   static uword FindDoubleConstant(double value);
 
-  Isolate* isolate() const { return parsed_function()->isolate(); }
+  Isolate* isolate() const { return parsed_function().isolate(); }
 
  private:
   friend class NestedStatement;  // Explicit access to nesting_stack_.
@@ -241,7 +242,7 @@
     return parameter_count() + num_stack_locals_;
   }
 
-  ParsedFunction* parsed_function_;
+  const ParsedFunction& parsed_function_;
   const ZoneGrowableArray<const ICData*>& ic_data_array_;
 
   const intptr_t num_copied_params_;
@@ -469,6 +470,7 @@
   void BuildAwaitJump(LocalVariable* old_context,
                       LocalVariable* continuation_result,
                       LocalVariable* continuation_error,
+                      LocalVariable* continuation_stack_trace,
                       const intptr_t old_ctx_level,
                       JoinEntryInstr* target);
 
diff --git a/runtime/vm/flow_graph_compiler.cc b/runtime/vm/flow_graph_compiler.cc
index eb65502..bc7e6b6 100644
--- a/runtime/vm/flow_graph_compiler.cc
+++ b/runtime/vm/flow_graph_compiler.cc
@@ -87,11 +87,12 @@
 FlowGraphCompiler::FlowGraphCompiler(
     Assembler* assembler,
     FlowGraph* flow_graph,
+    const ParsedFunction& parsed_function,
     bool is_optimizing,
     const GrowableArray<const Function*>& inline_id_to_function)
       : isolate_(Isolate::Current()),
         assembler_(assembler),
-        parsed_function_(*flow_graph->parsed_function()),
+        parsed_function_(parsed_function),
         flow_graph_(*flow_graph),
         block_order_(*flow_graph->CodegenBlockOrder(is_optimizing)),
         current_block_(NULL),
@@ -127,6 +128,8 @@
         deopt_id_to_ic_data_(NULL),
         inlined_code_intervals_(NULL),
         inline_id_to_function_(inline_id_to_function) {
+  ASSERT(flow_graph->parsed_function().function().raw() ==
+         parsed_function.function().raw());
   if (!is_optimizing) {
     const intptr_t len = isolate()->deopt_id();
     deopt_id_to_ic_data_ = new(isolate()) ZoneGrowableArray<const ICData*>(len);
@@ -135,7 +138,7 @@
       (*deopt_id_to_ic_data_)[i] = NULL;
     }
     const Array& old_saved_icdata = Array::Handle(isolate(),
-        flow_graph->parsed_function()->function().ic_data_array());
+        flow_graph->function().ic_data_array());
     const intptr_t saved_len =
         old_saved_icdata.IsNull() ? 0 : old_saved_icdata.Length();
     for (intptr_t i = 0; i < saved_len; i++) {
@@ -901,7 +904,7 @@
 void FlowGraphCompiler::TryIntrinsify() {
   // Intrinsification skips arguments checks, therefore disable if in checked
   // mode.
-  if (FLAG_intrinsify && !FLAG_enable_type_checks) {
+  if (FLAG_intrinsify && !I->TypeChecksEnabled()) {
     if (parsed_function().function().kind() == RawFunction::kImplicitGetter) {
       // An implicit getter must have a specific AST structure.
       const SequenceNode& sequence_node = *parsed_function().node_sequence();
@@ -936,7 +939,7 @@
 
   EnterIntrinsicMode();
 
-  Intrinsifier::Intrinsify(&parsed_function(), this);
+  Intrinsifier::Intrinsify(parsed_function(), this);
 
   ExitIntrinsicMode();
   // "Deoptimization" from intrinsic continues here. All deoptimization
@@ -1479,13 +1482,16 @@
 // Returns 'sorted' array in decreasing count order.
 // The expected number of elements to sort is less than 10.
 void FlowGraphCompiler::SortICDataByCount(const ICData& ic_data,
-                                          GrowableArray<CidTarget>* sorted) {
+                                          GrowableArray<CidTarget>* sorted,
+                                          bool drop_smi) {
   ASSERT(ic_data.NumArgsTested() == 1);
   const intptr_t len = ic_data.NumberOfChecks();
   sorted->Clear();
 
   for (int i = 0; i < len; i++) {
-    sorted->Add(CidTarget(ic_data.GetReceiverClassIdAt(i),
+    intptr_t receiver_cid = ic_data.GetReceiverClassIdAt(i);
+    if (drop_smi && (receiver_cid == kSmiCid)) continue;
+    sorted->Add(CidTarget(receiver_cid,
                           &Function::ZoneHandle(ic_data.GetTargetAt(i)),
                           ic_data.GetCountAt(i)));
   }
diff --git a/runtime/vm/flow_graph_compiler.h b/runtime/vm/flow_graph_compiler.h
index d5765f8..ef4fe00 100644
--- a/runtime/vm/flow_graph_compiler.h
+++ b/runtime/vm/flow_graph_compiler.h
@@ -268,6 +268,7 @@
   FlowGraphCompiler(
       Assembler* assembler,
       FlowGraph* flow_graph,
+      const ParsedFunction& parsed_function,
       bool is_optimizing,
       const GrowableArray<const Function*>& inline_id_to_function);
 
@@ -280,7 +281,7 @@
 
   // Accessors.
   Assembler* assembler() const { return assembler_; }
-  ParsedFunction& parsed_function() const { return parsed_function_; }
+  const ParsedFunction& parsed_function() const { return parsed_function_; }
   const GrowableArray<BlockEntryInstr*>& block_order() const {
     return block_order_;
   }
@@ -500,7 +501,8 @@
 
   // Returns 'sorted' array in decreasing count order.
   static void SortICDataByCount(const ICData& ic_data,
-                                GrowableArray<CidTarget>* sorted);
+                                GrowableArray<CidTarget>* sorted,
+                                bool drop_smi);
 
   // Use in unoptimized compilation to preserve/reuse ICData.
   const ICData* GetOrAddInstanceCallICData(intptr_t deopt_id,
@@ -634,7 +636,7 @@
 
   Isolate* isolate_;
   Assembler* assembler_;
-  ParsedFunction& parsed_function_;
+  const ParsedFunction& parsed_function_;
   const FlowGraph& flow_graph_;
   const GrowableArray<BlockEntryInstr*>& block_order_;
 
diff --git a/runtime/vm/flow_graph_compiler_arm.cc b/runtime/vm/flow_graph_compiler_arm.cc
index 5f48473..9bfee14 100644
--- a/runtime/vm/flow_graph_compiler_arm.cc
+++ b/runtime/vm/flow_graph_compiler_arm.cc
@@ -1555,7 +1555,7 @@
   Label match_found;
   const intptr_t len = ic_data.NumberOfChecks();
   GrowableArray<CidTarget> sorted(len);
-  SortICDataByCount(ic_data, &sorted);
+  SortICDataByCount(ic_data, &sorted, /* drop_smi = */ false);
   ASSERT(class_id_reg != R4);
   ASSERT(len > 0);  // Why bother otherwise.
   const Array& arguments_descriptor =
diff --git a/runtime/vm/flow_graph_compiler_arm64.cc b/runtime/vm/flow_graph_compiler_arm64.cc
index dd13d6d..cee93b7 100644
--- a/runtime/vm/flow_graph_compiler_arm64.cc
+++ b/runtime/vm/flow_graph_compiler_arm64.cc
@@ -1511,7 +1511,7 @@
   Label match_found;
   const intptr_t len = ic_data.NumberOfChecks();
   GrowableArray<CidTarget> sorted(len);
-  SortICDataByCount(ic_data, &sorted);
+  SortICDataByCount(ic_data, &sorted, /* drop_smi = */ false);
   ASSERT(class_id_reg != R4);
   ASSERT(len > 0);  // Why bother otherwise.
   const Array& arguments_descriptor =
diff --git a/runtime/vm/flow_graph_compiler_ia32.cc b/runtime/vm/flow_graph_compiler_ia32.cc
index 7771e56..7b98144 100644
--- a/runtime/vm/flow_graph_compiler_ia32.cc
+++ b/runtime/vm/flow_graph_compiler_ia32.cc
@@ -1554,7 +1554,7 @@
   Label match_found;
   const intptr_t len = ic_data.NumberOfChecks();
   GrowableArray<CidTarget> sorted(len);
-  SortICDataByCount(ic_data, &sorted);
+  SortICDataByCount(ic_data, &sorted, /* drop_smi = */ false);
   ASSERT(class_id_reg != EDX);
   ASSERT(len > 0);  // Why bother otherwise.
   const Array& arguments_descriptor =
diff --git a/runtime/vm/flow_graph_compiler_mips.cc b/runtime/vm/flow_graph_compiler_mips.cc
index 9d5320f..8127636 100644
--- a/runtime/vm/flow_graph_compiler_mips.cc
+++ b/runtime/vm/flow_graph_compiler_mips.cc
@@ -1584,7 +1584,7 @@
   Label match_found;
   const intptr_t len = ic_data.NumberOfChecks();
   GrowableArray<CidTarget> sorted(len);
-  SortICDataByCount(ic_data, &sorted);
+  SortICDataByCount(ic_data, &sorted, /* drop_smi = */ false);
   ASSERT(class_id_reg != S4);
   ASSERT(len > 0);  // Why bother otherwise.
   const Array& arguments_descriptor =
diff --git a/runtime/vm/flow_graph_compiler_x64.cc b/runtime/vm/flow_graph_compiler_x64.cc
index d1aeafe..11c6bfc 100644
--- a/runtime/vm/flow_graph_compiler_x64.cc
+++ b/runtime/vm/flow_graph_compiler_x64.cc
@@ -1516,7 +1516,7 @@
   Label match_found;
   const intptr_t len = ic_data.NumberOfChecks();
   GrowableArray<CidTarget> sorted(len);
-  SortICDataByCount(ic_data, &sorted);
+  SortICDataByCount(ic_data, &sorted, /* drop_smi = */ false);
   ASSERT(class_id_reg != R10);
   ASSERT(len > 0);  // Why bother otherwise.
   const Array& arguments_descriptor =
diff --git a/runtime/vm/flow_graph_inliner.cc b/runtime/vm/flow_graph_inliner.cc
index f0ab75e..92f92ad 100644
--- a/runtime/vm/flow_graph_inliner.cc
+++ b/runtime/vm/flow_graph_inliner.cc
@@ -197,7 +197,7 @@
                      FlowGraph* flow_graph)
         : call(call_arg),
           ratio(0.0),
-          caller(&flow_graph->parsed_function()->function()) {}
+          caller(&flow_graph->function()) {}
   };
 
   struct StaticCallInfo {
@@ -207,7 +207,7 @@
     StaticCallInfo(StaticCallInstr* value, FlowGraph* flow_graph)
         : call(value),
           ratio(0.0),
-          caller(&flow_graph->parsed_function()->function()) {}
+          caller(&flow_graph->function()) {}
   };
 
   struct ClosureCallInfo {
@@ -215,7 +215,7 @@
     const Function* caller;
     ClosureCallInfo(ClosureCallInstr* value, FlowGraph* flow_graph)
         : call(value),
-          caller(&flow_graph->parsed_function()->function()) {}
+          caller(&flow_graph->function()) {}
   };
 
   const GrowableArray<InstanceCallInfo>& instance_calls() const {
@@ -291,7 +291,7 @@
       FlowGraph* graph,
       intptr_t depth,
       GrowableArray<InlinedInfo>* inlined_info) {
-    const Function* caller = &graph->parsed_function()->function();
+    const Function* caller = &graph->function();
     Function& target  = Function::ZoneHandle();
     for (BlockIterator block_it = graph->postorder_iterator();
          !block_it.Done();
@@ -358,7 +358,7 @@
             // Method not inlined because inlining too deep and method
             // not recognized.
             if (FLAG_print_inlining_tree) {
-              const Function* caller = &graph->parsed_function()->function();
+              const Function* caller = &graph->function();
               const Function* target =
                   &Function::ZoneHandle(
                       instance_call->ic_data().GetTargetAt(0));
@@ -375,7 +375,7 @@
             // Method not inlined because inlining too deep and method
             // not recognized.
             if (FLAG_print_inlining_tree) {
-              const Function* caller = &graph->parsed_function()->function();
+              const Function* caller = &graph->function();
               const Function* target = &static_call->function();
               inlined_info->Add(InlinedInfo(
                   caller, target, depth + 1, static_call, "Too deep"));
@@ -534,7 +534,7 @@
   void InlineCalls() {
     // If inlining depth is less then one abort.
     if (FLAG_inlining_depth_threshold < 1) return;
-    if (caller_graph_->parsed_function()->function().deoptimization_counter() >=
+    if (caller_graph_->function().deoptimization_counter() >=
         FLAG_deoptimization_counter_inlining_threshold) {
       return;
     }
@@ -686,7 +686,7 @@
       // Build the callee graph.
       InlineExitCollector* exit_collector =
           new(Z) InlineExitCollector(caller_graph_, call);
-      FlowGraphBuilder builder(parsed_function,
+      FlowGraphBuilder builder(*parsed_function,
                                *ic_data_array,
                                exit_collector,
                                Isolate::kNoDeoptId);
@@ -851,7 +851,7 @@
       caller_graph()->AddToDeferredPrefixes(callee_graph->deferred_prefixes());
 
       FlowGraphInliner::SetInliningId(*callee_graph,
-          inliner_->NextInlineId(callee_graph->parsed_function()->function()));
+          inliner_->NextInlineId(callee_graph->function()));
       // We allocate a ZoneHandle for the unoptimized code so that it cannot be
       // disconnected from its function during the rest of compilation.
       Code::ZoneHandle(unoptimized_code.raw());
@@ -1472,10 +1472,12 @@
         FlowGraph::kEffect);
     entry->set_last_instruction(result);
     exit_collector->AddExit(result);
+    ParsedFunction* temp_parsed_function =
+        new ParsedFunction(Thread::Current(), target);
     GraphEntryInstr* graph_entry =
-        new(Z) GraphEntryInstr(NULL,  // No parsed function.
-                                       entry,
-                                       Isolate::kNoDeoptId);  // No OSR id.
+        new(Z) GraphEntryInstr(*temp_parsed_function,
+                               entry,
+                               Isolate::kNoDeoptId);  // No OSR id.
     // Update polymorphic inliner state.
     inlined_entries_.Add(graph_entry);
     exit_collector_->Union(exit_collector);
@@ -1690,7 +1692,9 @@
 
 void PolymorphicInliner::Inline() {
   // Consider the polymorphic variants in order by frequency.
-  FlowGraphCompiler::SortICDataByCount(call_->ic_data(), &variants_);
+  FlowGraphCompiler::SortICDataByCount(call_->ic_data(),
+                                       &variants_,
+                                       /* drop_smi = */ false);
   for (intptr_t var_idx = 0; var_idx < variants_.length(); ++var_idx) {
     const Function& target = *variants_[var_idx].target;
     const intptr_t receiver_cid = variants_[var_idx].cid;
@@ -1733,7 +1737,7 @@
 
 
 void FlowGraphInliner::CollectGraphInfo(FlowGraph* flow_graph, bool force) {
-  const Function& function = flow_graph->parsed_function()->function();
+  const Function& function = flow_graph->function();
   if (force || (function.optimized_instruction_count() == 0)) {
     GraphInfoCollector info;
     info.Collect(*flow_graph);
@@ -1788,7 +1792,7 @@
   // We might later use it for an early bailout from the inlining.
   CollectGraphInfo(flow_graph_);
 
-  const Function& top = flow_graph_->parsed_function()->function();
+  const Function& top = flow_graph_->function();
   if ((FLAG_inlining_filter != NULL) &&
       (strstr(top.ToFullyQualifiedCString(), FLAG_inlining_filter) == NULL)) {
     return;
@@ -1799,7 +1803,7 @@
   if (FLAG_trace_inlining &&
       (FLAG_print_flow_graph || FLAG_print_flow_graph_optimized)) {
     OS::Print("Before Inlining of %s\n", flow_graph_->
-              parsed_function()->function().ToFullyQualifiedCString());
+              function().ToFullyQualifiedCString());
     FlowGraphPrinter printer(*flow_graph_);
     printer.PrintBlocks();
   }
@@ -1816,7 +1820,7 @@
       OS::Print("Inlining growth factor: %f\n", inliner.GrowthFactor());
       if (FLAG_print_flow_graph || FLAG_print_flow_graph_optimized) {
         OS::Print("After Inlining of %s\n", flow_graph_->
-                  parsed_function()->function().ToFullyQualifiedCString());
+                  function().ToFullyQualifiedCString());
         FlowGraphPrinter printer(*flow_graph_);
         printer.PrintBlocks();
       }
diff --git a/runtime/vm/flow_graph_optimizer.cc b/runtime/vm/flow_graph_optimizer.cc
index 2295106..9c780bf 100644
--- a/runtime/vm/flow_graph_optimizer.cc
+++ b/runtime/vm/flow_graph_optimizer.cc
@@ -196,7 +196,7 @@
   // TODO(srdjan): Prevent modification of ICData object that is
   // referenced in assembly code.
   ICData& ic_data = ICData::ZoneHandle(Z, ICData::New(
-      flow_graph_->parsed_function()->function(),
+      flow_graph_->function(),
       call->function_name(),
       args_desc_array,
       call->deopt_id(),
@@ -1199,7 +1199,7 @@
                                    call->GetBlock()->try_index());
   (*entry)->InheritDeoptTarget(I, call);
   Instruction* cursor = *entry;
-  if (FLAG_enable_type_checks) {
+  if (I->TypeChecksEnabled()) {
     // Only type check for the value. A type check for the index is not
     // needed here because we insert a deoptimizing smi-check for the case
     // the index is not a smi.
@@ -2263,7 +2263,7 @@
   if (!FLAG_use_cha) return true;
   Definition* callee_receiver = call->ArgumentAt(0);
   ASSERT(callee_receiver != NULL);
-  const Function& function = flow_graph_->parsed_function()->function();
+  const Function& function = flow_graph_->function();
   if (function.IsDynamicFunction() &&
       callee_receiver->IsParameter() &&
       (callee_receiver->AsParameter()->index() == 0)) {
@@ -3635,7 +3635,7 @@
     case kTypedDataInt16ArrayCid:
     case kTypedDataUint16ArrayCid: {
       // Check that value is always smi.
-      value_check = ICData::New(flow_graph_->parsed_function()->function(),
+      value_check = ICData::New(flow_graph_->function(),
                                 i_call->function_name(),
                                 Object::empty_array(),  // Dummy args. descr.
                                 Isolate::kNoDeoptId,
@@ -3647,7 +3647,7 @@
     case kTypedDataUint32ArrayCid:
       // On 64-bit platforms assume that stored value is always a smi.
       if (kSmiBits >= 32) {
-        value_check = ICData::New(flow_graph_->parsed_function()->function(),
+        value_check = ICData::New(flow_graph_->function(),
                                   i_call->function_name(),
                                   Object::empty_array(),  // Dummy args. descr.
                                   Isolate::kNoDeoptId,
@@ -3658,7 +3658,7 @@
     case kTypedDataFloat32ArrayCid:
     case kTypedDataFloat64ArrayCid: {
       // Check that value is always double.
-      value_check = ICData::New(flow_graph_->parsed_function()->function(),
+      value_check = ICData::New(flow_graph_->function(),
                                 i_call->function_name(),
                                 Object::empty_array(),  // Dummy args. descr.
                                 Isolate::kNoDeoptId,
@@ -3668,7 +3668,7 @@
     }
     case kTypedDataInt32x4ArrayCid: {
       // Check that value is always Int32x4.
-      value_check = ICData::New(flow_graph_->parsed_function()->function(),
+      value_check = ICData::New(flow_graph_->function(),
                                 i_call->function_name(),
                                 Object::empty_array(),  // Dummy args. descr.
                                 Isolate::kNoDeoptId,
@@ -3678,7 +3678,7 @@
     }
     case kTypedDataFloat32x4ArrayCid: {
       // Check that value is always Float32x4.
-      value_check = ICData::New(flow_graph_->parsed_function()->function(),
+      value_check = ICData::New(flow_graph_->function(),
                                 i_call->function_name(),
                                 Object::empty_array(),  // Dummy args. descr.
                                 Isolate::kNoDeoptId,
@@ -4498,7 +4498,7 @@
                                                  const ICData& unary_ic_data) {
   ASSERT((unary_ic_data.NumberOfChecks() > 0) &&
       (unary_ic_data.NumArgsTested() == 1));
-  if (FLAG_enable_type_checks) {
+  if (I->TypeChecksEnabled()) {
     // Checked mode setters are inlined like normal methods by conventional
     // inlining.
     return false;
@@ -4994,8 +4994,7 @@
 
 
 void LICM::OptimisticallySpecializeSmiPhis() {
-  if (!flow_graph()->parsed_function()->function().
-          allows_hoisting_check_class()) {
+  if (!flow_graph()->function().allows_hoisting_check_class()) {
     // Do not hoist any.
     return;
   }
@@ -5017,8 +5016,7 @@
 
 
 void LICM::Optimize() {
-  if (!flow_graph()->parsed_function()->function().
-          allows_hoisting_check_class()) {
+  if (!flow_graph()->function().allows_hoisting_check_class()) {
     // Do not hoist any.
     return;
   }
diff --git a/runtime/vm/flow_graph_range_analysis.cc b/runtime/vm/flow_graph_range_analysis.cc
index 866a38c..ab54a1f 100644
--- a/runtime/vm/flow_graph_range_analysis.cc
+++ b/runtime/vm/flow_graph_range_analysis.cc
@@ -1528,7 +1528,7 @@
 
 void RangeAnalysis::EliminateRedundantBoundsChecks() {
   if (FLAG_array_bounds_check_elimination) {
-    const Function& function = flow_graph_->parsed_function()->function();
+    const Function& function = flow_graph_->function();
     const bool try_generalization =
         function.allows_bounds_check_generalization();
 
diff --git a/runtime/vm/flow_graph_type_propagator.cc b/runtime/vm/flow_graph_type_propagator.cc
index 2fd8919..c550f0d 100644
--- a/runtime/vm/flow_graph_type_propagator.cc
+++ b/runtime/vm/flow_graph_type_propagator.cc
@@ -39,7 +39,7 @@
     types_.Add(NULL);
   }
 
-  if (FLAG_enable_type_checks) {
+  if (Isolate::Current()->TypeChecksEnabled()) {
     asserts_ = new ZoneGrowableArray<AssertAssignableInstr*>(
         flow_graph->current_ssa_temp_index());
     for (intptr_t i = 0; i < flow_graph->current_ssa_temp_index(); i++) {
@@ -121,7 +121,7 @@
 
   const intptr_t rollback_point = rollback_.length();
 
-  if (FLAG_enable_type_checks) {
+  if (Isolate::Current()->TypeChecksEnabled()) {
     StrengthenAsserts(block);
   }
 
@@ -895,7 +895,7 @@
     return CompileType::FromCid(result_cid_);
   }
 
-  if (FLAG_enable_type_checks) {
+  if (Isolate::Current()->TypeChecksEnabled()) {
     // Void functions are known to return null, which is checked at the return
     // from the function.
     const AbstractType& result_type =
@@ -910,7 +910,7 @@
 
 
 CompileType LoadLocalInstr::ComputeType() const {
-  if (FLAG_enable_type_checks) {
+  if (Isolate::Current()->TypeChecksEnabled()) {
     return CompileType::FromAbstractType(local().type());
   }
   return CompileType::Dynamic();
@@ -954,7 +954,7 @@
   intptr_t cid = kDynamicCid;
   AbstractType* abstract_type = NULL;
   const Field& field = this->StaticField();
-  if (FLAG_enable_type_checks) {
+  if (Isolate::Current()->TypeChecksEnabled()) {
     cid = kIllegalCid;
     abstract_type = &AbstractType::ZoneHandle(field.type());
   }
@@ -1009,7 +1009,7 @@
   }
 
   const AbstractType* abstract_type = NULL;
-  if (FLAG_enable_type_checks) {
+  if (Isolate::Current()->TypeChecksEnabled()) {
     ASSERT(!type().HasResolvedTypeClass() ||
            !Field::IsExternalizableCid(Class::Handle(
                 type().type_class()).id()));
diff --git a/runtime/vm/il_printer.h b/runtime/vm/il_printer.h
index 3bcefb9..f311357 100644
--- a/runtime/vm/il_printer.h
+++ b/runtime/vm/il_printer.h
@@ -37,7 +37,7 @@
  public:
   FlowGraphPrinter(const FlowGraph& flow_graph,
                    bool print_locations = false)
-      : function_(flow_graph.parsed_function()->function()),
+      : function_(flow_graph.function()),
         block_order_(flow_graph.reverse_postorder()),
         print_locations_(print_locations) { }
 
diff --git a/runtime/vm/intermediate_language.cc b/runtime/vm/intermediate_language.cc
index 7cf206c..4d1eb87 100644
--- a/runtime/vm/intermediate_language.cc
+++ b/runtime/vm/intermediate_language.cc
@@ -470,7 +470,7 @@
 }
 
 
-GraphEntryInstr::GraphEntryInstr(const ParsedFunction* parsed_function,
+GraphEntryInstr::GraphEntryInstr(const ParsedFunction& parsed_function,
                                  TargetEntryInstr* normal_entry,
                                  intptr_t osr_id)
     : BlockEntryInstr(0, CatchClauseNode::kInvalidTryIndex),
@@ -1940,7 +1940,7 @@
 
 
 Definition* InstantiateTypeArgumentsInstr::Canonicalize(FlowGraph* flow_graph) {
-  return (FLAG_enable_type_checks || HasUses()) ? this : NULL;
+  return (Isolate::Current()->TypeChecksEnabled() || HasUses()) ? this : NULL;
 }
 
 
@@ -3002,7 +3002,7 @@
 Environment* Environment::From(Isolate* isolate,
                                const GrowableArray<Definition*>& definitions,
                                intptr_t fixed_parameter_count,
-                               const ParsedFunction* parsed_function) {
+                               const ParsedFunction& parsed_function) {
   Environment* env =
       new(isolate) Environment(definitions.length(),
                                fixed_parameter_count,
@@ -3261,7 +3261,7 @@
   //   v8 <- StringInterpolate(v2)
 
   // Don't compile-time fold when optimizing the interpolation function itself.
-  if (flow_graph->parsed_function()->function().raw() == CallFunction().raw()) {
+  if (flow_graph->function().raw() == CallFunction().raw()) {
     return this;
   }
 
diff --git a/runtime/vm/intermediate_language.h b/runtime/vm/intermediate_language.h
index 609f89e..9d39bfa 100644
--- a/runtime/vm/intermediate_language.h
+++ b/runtime/vm/intermediate_language.h
@@ -1300,7 +1300,7 @@
 
 class GraphEntryInstr : public BlockEntryInstr {
  public:
-  GraphEntryInstr(const ParsedFunction* parsed_function,
+  GraphEntryInstr(const ParsedFunction& parsed_function,
                   TargetEntryInstr* normal_entry,
                   intptr_t osr_id);
 
@@ -1349,7 +1349,7 @@
   TargetEntryInstr* normal_entry() const { return normal_entry_; }
 
   const ParsedFunction& parsed_function() const {
-    return *parsed_function_;
+    return parsed_function_;
   }
 
   const GrowableArray<CatchBlockEntryInstr*>& catch_entries() const {
@@ -1366,7 +1366,7 @@
   virtual void ClearPredecessors() {}
   virtual void AddPredecessor(BlockEntryInstr* predecessor) { UNREACHABLE(); }
 
-  const ParsedFunction* parsed_function_;
+  const ParsedFunction& parsed_function_;
   TargetEntryInstr* normal_entry_;
   GrowableArray<CatchBlockEntryInstr*> catch_entries_;
   // Indirect targets are blocks reachable only through indirect gotos.
@@ -7921,7 +7921,7 @@
   static Environment* From(Isolate* isolate,
                            const GrowableArray<Definition*>& definitions,
                            intptr_t fixed_parameter_count,
-                           const ParsedFunction* parsed_function);
+                           const ParsedFunction& parsed_function);
 
   void set_locations(Location* locations) {
     ASSERT(locations_ == NULL);
@@ -7967,7 +7967,7 @@
     return fixed_parameter_count_;
   }
 
-  const Code& code() const { return parsed_function_->code(); }
+  const Code& code() const { return parsed_function_.code(); }
 
   Environment* DeepCopy(Isolate* isolate) const {
     return DeepCopy(isolate, Length());
@@ -7996,7 +7996,7 @@
   Environment(intptr_t length,
               intptr_t fixed_parameter_count,
               intptr_t deopt_id,
-              const ParsedFunction* parsed_function,
+              const ParsedFunction& parsed_function,
               Environment* outer)
       : values_(length),
         locations_(NULL),
@@ -8010,7 +8010,7 @@
   Location* locations_;
   const intptr_t fixed_parameter_count_;
   intptr_t deopt_id_;
-  const ParsedFunction* parsed_function_;
+  const ParsedFunction& parsed_function_;
   Environment* outer_;
 
   DISALLOW_COPY_AND_ASSIGN(Environment);
diff --git a/runtime/vm/intermediate_language_arm.cc b/runtime/vm/intermediate_language_arm.cc
index 40cddcf..6dc5ac0 100644
--- a/runtime/vm/intermediate_language_arm.cc
+++ b/runtime/vm/intermediate_language_arm.cc
@@ -379,7 +379,7 @@
   ASSERT(locs->always_calls());
   Label done;
 
-  if (FLAG_enable_type_checks) {
+  if (Isolate::Current()->TypeChecksEnabled()) {
     __ CompareObject(reg, Bool::True());
     __ b(&done, EQ);
     __ CompareObject(reg, Bool::False());
@@ -6029,11 +6029,9 @@
   const Register value = locs()->in(0).reg();
   const Register temp = locs()->temp(0).reg();
   Label is_ok;
-  intptr_t cix = 0;
-  if (unary_checks().GetReceiverClassIdAt(cix) == kSmiCid) {
+  if (unary_checks().GetReceiverClassIdAt(0) == kSmiCid) {
     __ tst(value, Operand(kSmiTagMask));
     __ b(&is_ok, EQ);
-    cix++;  // Skip first check.
   } else {
     __ tst(value, Operand(kSmiTagMask));
     __ b(deopt, EQ);
@@ -6057,10 +6055,15 @@
       __ b(deopt, EQ);
     }
   } else {
-    const intptr_t num_checks = unary_checks().NumberOfChecks();
-    for (intptr_t i = cix; i < num_checks; i++) {
-      ASSERT(unary_checks().GetReceiverClassIdAt(i) != kSmiCid);
-      __ CompareImmediate(temp, unary_checks().GetReceiverClassIdAt(i));
+    GrowableArray<CidTarget> sorted_ic_data;
+    FlowGraphCompiler::SortICDataByCount(unary_checks(),
+                                         &sorted_ic_data,
+                                         /* drop_smi = */ true);
+    const intptr_t num_checks = sorted_ic_data.length();
+    for (intptr_t i = 0; i < num_checks; i++) {
+      const intptr_t cid = sorted_ic_data[i].cid;
+      ASSERT(cid != kSmiCid);
+      __ CompareImmediate(temp, cid);
       if (i == (num_checks - 1)) {
         __ b(deopt, NE);
       } else {
diff --git a/runtime/vm/intermediate_language_arm64.cc b/runtime/vm/intermediate_language_arm64.cc
index 0ecb339..846414a 100644
--- a/runtime/vm/intermediate_language_arm64.cc
+++ b/runtime/vm/intermediate_language_arm64.cc
@@ -366,7 +366,7 @@
   ASSERT(locs->always_calls());
   Label done;
 
-  if (FLAG_enable_type_checks) {
+  if (Isolate::Current()->TypeChecksEnabled()) {
     __ CompareObject(reg, Bool::True(), PP);
     __ b(&done, EQ);
     __ CompareObject(reg, Bool::False(), PP);
@@ -5099,11 +5099,9 @@
   const Register value = locs()->in(0).reg();
   const Register temp = locs()->temp(0).reg();
   Label is_ok;
-  intptr_t cix = 0;
-  if (unary_checks().GetReceiverClassIdAt(cix) == kSmiCid) {
+  if (unary_checks().GetReceiverClassIdAt(0) == kSmiCid) {
     __ tsti(value, Immediate(kSmiTagMask));
     __ b(&is_ok, EQ);
-    cix++;  // Skip first check.
   } else {
     __ tsti(value, Immediate(kSmiTagMask));
     __ b(deopt, EQ);
@@ -5128,10 +5126,15 @@
     }
 
   } else {
-    const intptr_t num_checks = unary_checks().NumberOfChecks();
-    for (intptr_t i = cix; i < num_checks; i++) {
-      ASSERT(unary_checks().GetReceiverClassIdAt(i) != kSmiCid);
-      __ CompareImmediate(temp, unary_checks().GetReceiverClassIdAt(i), PP);
+    GrowableArray<CidTarget> sorted_ic_data;
+    FlowGraphCompiler::SortICDataByCount(unary_checks(),
+                                         &sorted_ic_data,
+                                         /* drop_smi = */ true);
+    const intptr_t num_checks = sorted_ic_data.length();
+    for (intptr_t i = 0; i < num_checks; i++) {
+      const intptr_t cid = sorted_ic_data[i].cid;
+      ASSERT(cid != kSmiCid);
+      __ CompareImmediate(temp, cid, PP);
       if (i == (num_checks - 1)) {
         __ b(deopt, NE);
       } else {
diff --git a/runtime/vm/intermediate_language_ia32.cc b/runtime/vm/intermediate_language_ia32.cc
index 7c73c86..615148a 100644
--- a/runtime/vm/intermediate_language_ia32.cc
+++ b/runtime/vm/intermediate_language_ia32.cc
@@ -251,7 +251,7 @@
   ASSERT(locs->always_calls());
   Label done;
 
-  if (FLAG_enable_type_checks) {
+  if (Isolate::Current()->TypeChecksEnabled()) {
     __ CompareObject(reg, Bool::True());
     __ j(EQUAL, &done, Assembler::kNearJump);
     __ CompareObject(reg, Bool::False());
@@ -5746,11 +5746,9 @@
   Register value = locs()->in(0).reg();
   Register temp = locs()->temp(0).reg();
   Label is_ok;
-  intptr_t cix = 0;
-  if (unary_checks().GetReceiverClassIdAt(cix) == kSmiCid) {
+  if (unary_checks().GetReceiverClassIdAt(0) == kSmiCid) {
     __ testl(value, Immediate(kSmiTagMask));
     __ j(ZERO, &is_ok);
-    cix++;  // Skip first check.
   } else {
     __ testl(value, Immediate(kSmiTagMask));
     __ j(ZERO, deopt);
@@ -5773,11 +5771,16 @@
       __ j(NOT_CARRY, deopt);
     }
   } else {
-    const intptr_t num_checks = unary_checks().NumberOfChecks();
+    GrowableArray<CidTarget> sorted_ic_data;
+    FlowGraphCompiler::SortICDataByCount(unary_checks(),
+                                         &sorted_ic_data,
+                                         /* drop_smi = */ true);
+    const intptr_t num_checks = sorted_ic_data.length();
     const bool use_near_jump = num_checks < 5;
-    for (intptr_t i = cix; i < num_checks; i++) {
-      ASSERT(unary_checks().GetReceiverClassIdAt(i) != kSmiCid);
-      __ cmpl(temp, Immediate(unary_checks().GetReceiverClassIdAt(i)));
+    for (intptr_t i = 0; i < num_checks; i++) {
+      const intptr_t cid = sorted_ic_data[i].cid;
+      ASSERT(cid != kSmiCid);
+      __ cmpl(temp, Immediate(cid));
       if (i == (num_checks - 1)) {
         __ j(NOT_EQUAL, deopt);
       } else {
diff --git a/runtime/vm/intermediate_language_mips.cc b/runtime/vm/intermediate_language_mips.cc
index 9ad50ae..5bf3c7d 100644
--- a/runtime/vm/intermediate_language_mips.cc
+++ b/runtime/vm/intermediate_language_mips.cc
@@ -433,7 +433,7 @@
   ASSERT(locs->always_calls());
   Label done;
 
-  if (FLAG_enable_type_checks) {
+  if (Isolate::Current()->TypeChecksEnabled()) {
     __ BranchEqual(reg, Bool::True(), &done);
     __ BranchEqual(reg, Bool::False(), &done);
   } else {
@@ -4679,11 +4679,9 @@
   Register value = locs()->in(0).reg();
   Register temp = locs()->temp(0).reg();
   Label is_ok;
-  intptr_t cix = 0;
-  if (unary_checks().GetReceiverClassIdAt(cix) == kSmiCid) {
+  if (unary_checks().GetReceiverClassIdAt(0) == kSmiCid) {
     __ andi(CMPRES1, value, Immediate(kSmiTagMask));
     __ beq(CMPRES1, ZR, &is_ok);
-    cix++;  // Skip first check.
   } else {
     __ andi(CMPRES1, value, Immediate(kSmiTagMask));
     __ beq(CMPRES1, ZR, deopt);
@@ -4708,10 +4706,15 @@
       __ beq(mask_reg, ZR, deopt);
     }
   } else {
-    const intptr_t num_checks = unary_checks().NumberOfChecks();
-    for (intptr_t i = cix; i < num_checks; i++) {
-      ASSERT(unary_checks().GetReceiverClassIdAt(i) != kSmiCid);
-      __ LoadImmediate(TMP, unary_checks().GetReceiverClassIdAt(i));
+    GrowableArray<CidTarget> sorted_ic_data;
+    FlowGraphCompiler::SortICDataByCount(unary_checks(),
+                                         &sorted_ic_data,
+                                         /* drop_smi = */ true);
+    const intptr_t num_checks = sorted_ic_data.length();
+    for (intptr_t i = 0; i < num_checks; i++) {
+      const intptr_t cid = sorted_ic_data[i].cid;
+      ASSERT(cid != kSmiCid);
+      __ LoadImmediate(TMP, cid);
       __ subu(CMPRES1, temp, TMP);
       if (i == (num_checks - 1)) {
         __ bne(CMPRES1, ZR, deopt);
diff --git a/runtime/vm/intermediate_language_x64.cc b/runtime/vm/intermediate_language_x64.cc
index 893e662..16af510 100644
--- a/runtime/vm/intermediate_language_x64.cc
+++ b/runtime/vm/intermediate_language_x64.cc
@@ -332,7 +332,7 @@
   ASSERT(locs->always_calls());
   Label done;
 
-  if (FLAG_enable_type_checks) {
+  if (Isolate::Current()->TypeChecksEnabled()) {
     __ CompareObject(reg, Bool::True(), PP);
     __ j(EQUAL, &done, Assembler::kNearJump);
     __ CompareObject(reg, Bool::False(), PP);
@@ -5512,11 +5512,9 @@
   Register value = locs()->in(0).reg();
   Register temp = locs()->temp(0).reg();
   Label is_ok;
-  intptr_t cix = 0;
-  if (unary_checks().GetReceiverClassIdAt(cix) == kSmiCid) {
+  if (unary_checks().GetReceiverClassIdAt(0) == kSmiCid) {
     __ testq(value, Immediate(kSmiTagMask));
     __ j(ZERO, &is_ok);
-    cix++;  // Skip first check.
   } else {
     __ testq(value, Immediate(kSmiTagMask));
     __ j(ZERO, deopt);
@@ -5539,11 +5537,15 @@
       __ j(NOT_CARRY, deopt);
     }
   } else {
-    const intptr_t num_checks = unary_checks().NumberOfChecks();
+    GrowableArray<CidTarget> sorted_ic_data;
+    FlowGraphCompiler::SortICDataByCount(unary_checks(),
+                                         &sorted_ic_data,
+                                         /* drop_smi = */ true);
+    const intptr_t num_checks = sorted_ic_data.length();
     const bool use_near_jump = num_checks < 5;
-    for (intptr_t i = cix; i < num_checks; i++) {
-      ASSERT(unary_checks().GetReceiverClassIdAt(i) != kSmiCid);
-      __ cmpl(temp, Immediate(unary_checks().GetReceiverClassIdAt(i)));
+    for (intptr_t i = 0; i < num_checks; i++) {
+      const intptr_t cid = sorted_ic_data[i].cid;
+      __ cmpl(temp, Immediate(cid));
       if (i == (num_checks - 1)) {
         __ j(NOT_EQUAL, deopt);
       } else {
diff --git a/runtime/vm/intrinsifier.cc b/runtime/vm/intrinsifier.cc
index a9c3994..519ef63 100644
--- a/runtime/vm/intrinsifier.cc
+++ b/runtime/vm/intrinsifier.cc
@@ -24,6 +24,7 @@
 DECLARE_FLAG(bool, code_comments);
 DECLARE_FLAG(bool, print_flow_graph);
 DECLARE_FLAG(bool, print_flow_graph_optimized);
+DECLARE_FLAG(bool, enable_type_checks);
 
 bool Intrinsifier::CanIntrinsify(const Function& function) {
   if (!FLAG_intrinsify) return false;
@@ -123,7 +124,7 @@
 }
 
 
-bool Intrinsifier::GraphIntrinsify(ParsedFunction* parsed_function,
+bool Intrinsifier::GraphIntrinsify(const ParsedFunction& parsed_function,
                                    FlowGraphCompiler* compiler) {
   ZoneGrowableArray<const ICData*>* ic_data_array =
       new ZoneGrowableArray<const ICData*>();
@@ -139,7 +140,7 @@
   GraphEntryInstr* graph_entry = new GraphEntryInstr(
       parsed_function, normal_entry, Isolate::kNoDeoptId);  // No OSR id.
   FlowGraph* graph = new FlowGraph(parsed_function, graph_entry, block_id);
-  const Function& function = parsed_function->function();
+  const Function& function = parsed_function.function();
   switch (function.recognized_kind()) {
 #define EMIT_CASE(class_name, function_name, enum_name, fp)                    \
     case MethodRecognizer::k##enum_name:                                       \
@@ -173,9 +174,9 @@
 }
 
 
-void Intrinsifier::Intrinsify(ParsedFunction* parsed_function,
+void Intrinsifier::Intrinsify(const ParsedFunction& parsed_function,
                               FlowGraphCompiler* compiler) {
-  const Function& function = parsed_function->function();
+  const Function& function = parsed_function.function();
   if (!CanIntrinsify(function)) {
     return;
   }
@@ -205,7 +206,6 @@
     switch (function.recognized_kind()) {
       ALL_INTRINSICS_LIST(EMIT_CASE);
       default:
-        UNREACHABLE();
         break;
     }
   }
@@ -250,7 +250,12 @@
   }
 
   intptr_t TokenPos() {
-    return flow_graph_->parsed_function()->function().token_pos();
+    return flow_graph_->function().token_pos();
+  }
+
+  Definition* AddNullDefinition() {
+    return AddDefinition(
+        new ConstantInstr(Object::ZoneHandle(Object::null())));
   }
 
  private:
@@ -382,8 +387,7 @@
                             Isolate::kNoDeoptId,
                             builder.TokenPos()));
   // Return null.
-  Definition* null_def = builder.AddDefinition(
-      new ConstantInstr(Object::ZoneHandle(Object::null())));
+  Definition* null_def = builder.AddNullDefinition();
   builder.AddIntrinsicReturn(new Value(null_def));
   return true;
 }
@@ -417,8 +421,7 @@
                             Isolate::kNoDeoptId,
                             builder.TokenPos()));
   // Return null.
-  Definition* null_def = builder.AddDefinition(
-      new ConstantInstr(Object::ZoneHandle(Object::null())));
+  Definition* null_def = builder.AddNullDefinition();
   builder.AddIntrinsicReturn(new Value(null_def));
   return true;
 }
@@ -438,13 +441,12 @@
   PrepareIndexedOp(&builder, array, index, TypedData::length_offset());
 
   const ICData& value_check = ICData::ZoneHandle(ICData::New(
-      flow_graph->parsed_function()->function(),
-      String::Handle(flow_graph->parsed_function()->function().name()),
+      flow_graph->function(),
+      String::Handle(flow_graph->function().name()),
       Object::empty_array(),  // Dummy args. descr.
       Isolate::kNoDeoptId,
       1));
-  value_check.AddReceiverCheck(kDoubleCid,
-                               flow_graph->parsed_function()->function());
+  value_check.AddReceiverCheck(kDoubleCid, flow_graph->function());
   builder.AddInstruction(
       new CheckClassInstr(new Value(value),
                           Isolate::kNoDeoptId,
@@ -469,8 +471,7 @@
                             Isolate::kNoDeoptId,
                             builder.TokenPos()));
   // Return null.
-  Definition* null_def = builder.AddDefinition(
-      new ConstantInstr(Object::ZoneHandle(Object::null())));
+  Definition* null_def = builder.AddNullDefinition();
   builder.AddIntrinsicReturn(new Value(null_def));
   return true;
 }
@@ -566,4 +567,127 @@
 }
 
 
+bool Intrinsifier::Build_GrowableArrayGetIndexed(FlowGraph* flow_graph) {
+  GraphEntryInstr* graph_entry = flow_graph->graph_entry();
+  TargetEntryInstr* normal_entry = graph_entry->normal_entry();
+  BlockBuilder builder(flow_graph, normal_entry);
+
+  Definition* index = builder.AddParameter(1);
+  Definition* growable_array = builder.AddParameter(2);
+
+  PrepareIndexedOp(
+      &builder, growable_array, index, GrowableObjectArray::length_offset());
+
+  Definition* backing_store = builder.AddDefinition(
+      new LoadFieldInstr(new Value(growable_array),
+                         GrowableObjectArray::data_offset(),
+                         Type::ZoneHandle(),
+                         builder.TokenPos()));
+  Definition* result = builder.AddDefinition(
+      new LoadIndexedInstr(new Value(backing_store),
+                           new Value(index),
+                           Instance::ElementSizeFor(kArrayCid),  // index scale
+                           kArrayCid,
+                           Isolate::kNoDeoptId,
+                           builder.TokenPos()));
+  builder.AddIntrinsicReturn(new Value(result));
+  return true;
+}
+
+
+bool Intrinsifier::Build_GrowableArraySetIndexed(FlowGraph* flow_graph) {
+  if (Isolate::Current()->TypeChecksEnabled()) {
+    return false;
+  }
+
+  GraphEntryInstr* graph_entry = flow_graph->graph_entry();
+  TargetEntryInstr* normal_entry = graph_entry->normal_entry();
+  BlockBuilder builder(flow_graph, normal_entry);
+
+  Definition* value = builder.AddParameter(1);
+  Definition* index = builder.AddParameter(2);
+  Definition* array = builder.AddParameter(3);
+
+  PrepareIndexedOp(
+      &builder, array, index, GrowableObjectArray::length_offset());
+
+  Definition* backing_store = builder.AddDefinition(
+      new LoadFieldInstr(new Value(array),
+                         GrowableObjectArray::data_offset(),
+                         Type::ZoneHandle(),
+                         builder.TokenPos()));
+
+  builder.AddInstruction(
+      new StoreIndexedInstr(new Value(backing_store),
+                            new Value(index),
+                            new Value(value),
+                            kEmitStoreBarrier,
+                            Instance::ElementSizeFor(kArrayCid),  // index scale
+                            kArrayCid,
+                            Isolate::kNoDeoptId,
+                            builder.TokenPos()));
+  // Return null.
+  Definition* null_def = builder.AddNullDefinition();
+  builder.AddIntrinsicReturn(new Value(null_def));
+  return true;
+}
+
+
+bool Intrinsifier::Build_GrowableArraySetData(FlowGraph* flow_graph) {
+  GraphEntryInstr* graph_entry = flow_graph->graph_entry();
+  TargetEntryInstr* normal_entry = graph_entry->normal_entry();
+  BlockBuilder builder(flow_graph, normal_entry);
+
+  Definition* data = builder.AddParameter(1);
+  Definition* growable_array = builder.AddParameter(2);
+
+  const ICData& value_check = ICData::ZoneHandle(ICData::New(
+      flow_graph->function(),
+      String::Handle(flow_graph->function().name()),
+      Object::empty_array(),  // Dummy args. descr.
+      Isolate::kNoDeoptId,
+      1));
+  value_check.AddReceiverCheck(kArrayCid, flow_graph->function());
+  builder.AddInstruction(
+      new CheckClassInstr(new Value(data),
+                          Isolate::kNoDeoptId,
+                          value_check,
+                          builder.TokenPos()));
+
+  builder.AddInstruction(
+      new StoreInstanceFieldInstr(GrowableObjectArray::data_offset(),
+                                  new Value(growable_array),
+                                  new Value(data),
+                                  kEmitStoreBarrier,
+                                  builder.TokenPos()));
+  // Return null.
+  Definition* null_def = builder.AddNullDefinition();
+  builder.AddIntrinsicReturn(new Value(null_def));
+  return true;
+}
+
+
+bool Intrinsifier::Build_GrowableArraySetLength(FlowGraph* flow_graph) {
+  GraphEntryInstr* graph_entry = flow_graph->graph_entry();
+  TargetEntryInstr* normal_entry = graph_entry->normal_entry();
+  BlockBuilder builder(flow_graph, normal_entry);
+
+  Definition* length = builder.AddParameter(1);
+  Definition* growable_array = builder.AddParameter(2);
+
+  builder.AddInstruction(
+      new CheckSmiInstr(new Value(length),
+                        Isolate::kNoDeoptId,
+                        builder.TokenPos()));
+  builder.AddInstruction(
+      new StoreInstanceFieldInstr(GrowableObjectArray::length_offset(),
+                                  new Value(growable_array),
+                                  new Value(length),
+                                  kNoStoreBarrier,
+                                  builder.TokenPos()));
+  Definition* null_def = builder.AddNullDefinition();
+  builder.AddIntrinsicReturn(new Value(null_def));
+  return true;
+}
+
 }  // namespace dart
diff --git a/runtime/vm/intrinsifier.h b/runtime/vm/intrinsifier.h
index 257cf22..f334446 100644
--- a/runtime/vm/intrinsifier.h
+++ b/runtime/vm/intrinsifier.h
@@ -21,11 +21,11 @@
 
 class Intrinsifier : public AllStatic {
  public:
-  static void Intrinsify(ParsedFunction* parsed_function,
+  static void Intrinsify(const ParsedFunction& parsed_function,
                          FlowGraphCompiler* compiler);
   static void InitializeState();
 
-  static bool GraphIntrinsify(ParsedFunction* parsed_function,
+  static bool GraphIntrinsify(const ParsedFunction& parsed_function,
                               FlowGraphCompiler* compiler);
 
   static intptr_t ParameterSlotFromSp();
diff --git a/runtime/vm/intrinsifier_arm.cc b/runtime/vm/intrinsifier_arm.cc
index c926ce1..54a8692 100644
--- a/runtime/vm/intrinsifier_arm.cc
+++ b/runtime/vm/intrinsifier_arm.cc
@@ -44,7 +44,7 @@
 void Intrinsifier::ObjectArraySetIndexed(Assembler* assembler) {
   Label fall_through;
 
-  if (FLAG_enable_type_checks) {
+  if (Isolate::Current()->TypeChecksEnabled()) {
     const intptr_t type_args_field_offset =
         ComputeObjectArrayTypeArgumentsOffset();
     // Inline simple tests (Smi, null), fallthrough if not positive.
@@ -142,100 +142,12 @@
 }
 
 
-void Intrinsifier::GrowableArrayGetIndexed(Assembler* assembler) {
-  Label fall_through;
-
-  __ ldr(R0, Address(SP, + 0 * kWordSize));  // Index
-  __ ldr(R1, Address(SP, + 1 * kWordSize));  // Array
-
-  __ tst(R0, Operand(kSmiTagMask));
-  __ b(&fall_through, NE);  // Index is not an smi, fall through
-
-  // Range check.
-  __ ldr(R6, FieldAddress(R1, GrowableObjectArray::length_offset()));
-  __ cmp(R0, Operand(R6));
-
-  ASSERT(kSmiTagShift == 1);
-  // array element at R6 + R0 * 2 + Array::data_offset - 1
-  __ ldr(R6, FieldAddress(R1, GrowableObjectArray::data_offset()), CC);  // data
-  __ add(R6, R6, Operand(R0, LSL, 1), CC);
-  __ ldr(R0, FieldAddress(R6, Array::data_offset()), CC);
-  __ bx(LR, CC);
-  __ Bind(&fall_through);
-}
-
-
-// Set value into growable object array at specified index.
-// On stack: growable array (+2), index (+1), value (+0).
-void Intrinsifier::GrowableArraySetIndexed(Assembler* assembler) {
-  if (FLAG_enable_type_checks) {
-    return;
-  }
-  Label fall_through;
-  __ ldr(R1, Address(SP, 1 * kWordSize));  // Index.
-  __ ldr(R0, Address(SP, 2 * kWordSize));  // GrowableArray.
-  __ tst(R1, Operand(kSmiTagMask));
-  __ b(&fall_through, NE);  // Non-smi index.
-  // Range check using _length field.
-  __ ldr(R2, FieldAddress(R0, GrowableObjectArray::length_offset()));
-  __ cmp(R1, Operand(R2));
-  // Runtime throws exception.
-  __ b(&fall_through, CS);
-  __ ldr(R0, FieldAddress(R0, GrowableObjectArray::data_offset()));  // data.
-  __ ldr(R2, Address(SP, 0 * kWordSize));  // Value.
-  // Note that R1 is Smi, i.e, times 2.
-  ASSERT(kSmiTagShift == 1);
-  __ add(R1, R0, Operand(R1, LSL, 1));
-  __ StoreIntoObject(R0, FieldAddress(R1, Array::data_offset()), R2);
-  __ Ret();
-  __ Bind(&fall_through);
-}
-
-
-// Set length of growable object array. The length cannot
-// be greater than the length of the data container.
-// On stack: growable array (+1), length (+0).
-void Intrinsifier::GrowableArraySetLength(Assembler* assembler) {
-  Label fall_through;
-  __ ldr(R0, Address(SP, 1 * kWordSize));  // Growable array.
-  __ ldr(R1, Address(SP, 0 * kWordSize));  // Length value.
-  __ tst(R1, Operand(kSmiTagMask));
-  __ b(&fall_through, NE);  // Non-smi length.
-  __ StoreIntoSmiField(FieldAddress(R0, GrowableObjectArray::length_offset()),
-                       R1);
-  __ Ret();
-  __ Bind(&fall_through);
-}
-
-
-// Set data of growable object array.
-// On stack: growable array (+1), data (+0).
-void Intrinsifier::GrowableArraySetData(Assembler* assembler) {
-  if (FLAG_enable_type_checks) {
-    return;
-  }
-  Label fall_through;
-  __ ldr(R1, Address(SP, 0 * kWordSize));  // Data.
-  // Check that data is an ObjectArray.
-  __ tst(R1, Operand(kSmiTagMask));
-  __ b(&fall_through, EQ);  // Data is Smi.
-  __ CompareClassId(R1, kArrayCid, R0);
-  __ b(&fall_through, NE);
-  __ ldr(R0, Address(SP, 1 * kWordSize));  // Growable array.
-  __ StoreIntoObject(R0,
-                     FieldAddress(R0, GrowableObjectArray::data_offset()),
-                     R1);
-  __ Ret();
-  __ Bind(&fall_through);
-}
-
-
 // Add an element to growable array if it doesn't need to grow, otherwise
 // call into regular code.
 // On stack: growable array (+1), value (+0).
 void Intrinsifier::GrowableArray_add(Assembler* assembler) {
   // In checked mode we need to type-check the incoming argument.
-  if (FLAG_enable_type_checks) {
+  if (Isolate::Current()->TypeChecksEnabled()) {
     return;
   }
   Label fall_through;
@@ -887,27 +799,6 @@
 }
 
 
-void Intrinsifier::Bigint_setNeg(Assembler* assembler) {
-  __ ldrd(R0, Address(SP, 0 * kWordSize));  // R0 = this, R1 = neg value.
-  __ StoreIntoObject(R1, FieldAddress(R1, Bigint::neg_offset()), R0, false);
-  __ Ret();
-}
-
-
-void Intrinsifier::Bigint_setUsed(Assembler* assembler) {
-  __ ldrd(R0, Address(SP, 0 * kWordSize));  // R0 = this, R1 = used value.
-  __ StoreIntoObject(R1, FieldAddress(R1, Bigint::used_offset()), R0);
-  __ Ret();
-}
-
-
-void Intrinsifier::Bigint_setDigits(Assembler* assembler) {
-  __ ldrd(R0, Address(SP, 0 * kWordSize));  // R0 = this, R1 = digits value.
-  __ StoreIntoObject(R1, FieldAddress(R1, Bigint::digits_offset()), R0, false);
-  __ Ret();
-}
-
-
 void Intrinsifier::Bigint_absAdd(Assembler* assembler) {
   // static void _absAdd(Uint32List digits, int used,
   //                     Uint32List a_digits, int a_used,
diff --git a/runtime/vm/intrinsifier_arm64.cc b/runtime/vm/intrinsifier_arm64.cc
index 04ef253..c61db05 100644
--- a/runtime/vm/intrinsifier_arm64.cc
+++ b/runtime/vm/intrinsifier_arm64.cc
@@ -43,7 +43,7 @@
 void Intrinsifier::ObjectArraySetIndexed(Assembler* assembler) {
   Label fall_through;
 
-  if (FLAG_enable_type_checks) {
+  if (Isolate::Current()->TypeChecksEnabled()) {
     const intptr_t type_args_field_offset =
         ComputeObjectArrayTypeArgumentsOffset();
     // Inline simple tests (Smi, null), fallthrough if not positive.
@@ -139,103 +139,12 @@
 }
 
 
-void Intrinsifier::GrowableArrayGetIndexed(Assembler* assembler) {
-  Label fall_through;
-
-  __ ldr(R0, Address(SP, + 0 * kWordSize));  // Index
-  __ ldr(R1, Address(SP, + 1 * kWordSize));  // Array
-
-  __ tsti(R0, Immediate(kSmiTagMask));
-  __ b(&fall_through, NE);  // Index is not an smi, fall through.
-
-  // Range check.
-  __ ldr(R6, FieldAddress(R1, GrowableObjectArray::length_offset()));
-  __ cmp(R0, Operand(R6));
-  __ b(&fall_through, CS);
-
-  ASSERT(kSmiTagShift == 1);
-  // array element at R6 + R0 * 4 + Array::data_offset - 1
-  __ ldr(R6, FieldAddress(R1, GrowableObjectArray::data_offset()));  // Data
-  __ add(R6, R6, Operand(R0, LSL, 2));
-  __ ldr(R0, FieldAddress(R6, Array::data_offset()));
-  __ ret();
-  __ Bind(&fall_through);
-}
-
-
-// Set value into growable object array at specified index.
-// On stack: growable array (+2), index (+1), value (+0).
-void Intrinsifier::GrowableArraySetIndexed(Assembler* assembler) {
-  if (FLAG_enable_type_checks) {
-    return;
-  }
-  Label fall_through;
-  __ ldr(R1, Address(SP, 1 * kWordSize));  // Index.
-  __ ldr(R0, Address(SP, 2 * kWordSize));  // GrowableArray.
-  __ tsti(R1, Immediate(kSmiTagMask));
-  __ b(&fall_through, NE);  // Non-smi index.
-  // Range check using _length field.
-  __ ldr(R2, FieldAddress(R0, GrowableObjectArray::length_offset()));
-  __ cmp(R1, Operand(R2));
-  // Runtime throws exception.
-  __ b(&fall_through, CS);
-  __ ldr(R0, FieldAddress(R0, GrowableObjectArray::data_offset()));  // data.
-  __ ldr(R2, Address(SP, 0 * kWordSize));  // Value.
-  // Note that R1 is Smi, i.e, times 2.
-  ASSERT(kSmiTagShift == 1);
-  __ add(R1, R0, Operand(R1, LSL, 2));
-  __ StoreIntoObject(R0,
-                     FieldAddress(R1, Array::data_offset()),
-                     R2);
-  __ ret();
-  __ Bind(&fall_through);
-}
-
-
-// Set length of growable object array. The length cannot
-// be greater than the length of the data container.
-// On stack: growable array (+1), length (+0).
-void Intrinsifier::GrowableArraySetLength(Assembler* assembler) {
-  Label fall_through;
-  __ ldr(R0, Address(SP, 1 * kWordSize));  // Growable array.
-  __ ldr(R1, Address(SP, 0 * kWordSize));  // Length value.
-  __ tsti(R1, Immediate(kSmiTagMask));  // Check for Smi.
-  __ b(&fall_through, NE);
-  __ str(R1, FieldAddress(R0, GrowableObjectArray::length_offset()));
-  __ ret();
-  __ Bind(&fall_through);
-  // Fall through on non-Smi.
-}
-
-
-// Set data of growable object array.
-// On stack: growable array (+1), data (+0).
-void Intrinsifier::GrowableArraySetData(Assembler* assembler) {
-  if (FLAG_enable_type_checks) {
-    return;
-  }
-  Label fall_through;
-  __ ldr(R1, Address(SP, 0 * kWordSize));  // Data.
-  // Check that data is an ObjectArray.
-  __ tsti(R1, Immediate(kSmiTagMask));
-  __ b(&fall_through, EQ);  // Data is Smi.
-  __ CompareClassId(R1, kArrayCid, kNoPP);
-  __ b(&fall_through, NE);
-  __ ldr(R0, Address(SP, 1 * kWordSize));  // Growable array.
-  __ StoreIntoObject(R0,
-                     FieldAddress(R0, GrowableObjectArray::data_offset()),
-                     R1);
-  __ ret();
-  __ Bind(&fall_through);
-}
-
-
 // Add an element to growable array if it doesn't need to grow, otherwise
 // call into regular code.
 // On stack: growable array (+1), value (+0).
 void Intrinsifier::GrowableArray_add(Assembler* assembler) {
   // In checked mode we need to type-check the incoming argument.
-  if (FLAG_enable_type_checks) {
+  if (Isolate::Current()->TypeChecksEnabled()) {
     return;
   }
   Label fall_through;
@@ -779,30 +688,6 @@
 }
 
 
-void Intrinsifier::Bigint_setNeg(Assembler* assembler) {
-  __ ldr(R0, Address(SP, 0 * kWordSize));
-  __ ldr(R1, Address(SP, 1 * kWordSize));
-  __ StoreIntoObject(R1, FieldAddress(R1, Bigint::neg_offset()), R0, false);
-  __ ret();
-}
-
-
-void Intrinsifier::Bigint_setUsed(Assembler* assembler) {
-  __ ldr(R0, Address(SP, 0 * kWordSize));
-  __ ldr(R1, Address(SP, 1 * kWordSize));
-  __ StoreIntoObject(R1, FieldAddress(R1, Bigint::used_offset()), R0);
-  __ ret();
-}
-
-
-void Intrinsifier::Bigint_setDigits(Assembler* assembler) {
-  __ ldr(R0, Address(SP, 0 * kWordSize));
-  __ ldr(R1, Address(SP, 1 * kWordSize));
-  __ StoreIntoObject(R1, FieldAddress(R1, Bigint::digits_offset()), R0, false);
-  __ ret();
-}
-
-
 void Intrinsifier::Bigint_absAdd(Assembler* assembler) {
   // static void _absAdd(Uint32List digits, int used,
   //                     Uint32List a_digits, int a_used,
@@ -858,9 +743,12 @@
   __ cbnz(&carry_loop, R9);
 
   __ Bind(&last_carry);
-  __ adc(R0, ZR, ZR);
+  Label done;
+  __ b(&done, CC);
+  __ LoadImmediate(R0, 1, kNoPP);
   __ str(R0, Address(R6, 0));
 
+  __ Bind(&done);
   // Returning Object::null() is not required, since this method is private.
   __ ret();
 }
diff --git a/runtime/vm/intrinsifier_ia32.cc b/runtime/vm/intrinsifier_ia32.cc
index 7415188..4fb2397 100644
--- a/runtime/vm/intrinsifier_ia32.cc
+++ b/runtime/vm/intrinsifier_ia32.cc
@@ -49,7 +49,7 @@
 // update. Array length is always a Smi.
 void Intrinsifier::ObjectArraySetIndexed(Assembler* assembler) {
   Label fall_through;
-  if (FLAG_enable_type_checks) {
+  if (Isolate::Current()->TypeChecksEnabled()) {
     const intptr_t type_args_field_offset =
         ComputeObjectArrayTypeArgumentsOffset();
     // Inline simple tests (Smi, null), fallthrough if not positive.
@@ -145,99 +145,12 @@
 }
 
 
-// Access growable object array at specified index.
-// On stack: growable array (+2), index (+1), return-address (+0).
-void Intrinsifier::GrowableArrayGetIndexed(Assembler* assembler) {
-  Label fall_through;
-  __ movl(EBX, Address(ESP, + 1 * kWordSize));  // Index.
-  __ movl(EAX, Address(ESP, + 2 * kWordSize));  // GrowableArray.
-  __ testl(EBX, Immediate(kSmiTagMask));
-  __ j(NOT_ZERO, &fall_through, Assembler::kNearJump);  // Non-smi index.
-  // Range check using _length field.
-  __ cmpl(EBX, FieldAddress(EAX, GrowableObjectArray::length_offset()));
-  // Runtime throws exception.
-  __ j(ABOVE_EQUAL, &fall_through, Assembler::kNearJump);
-  __ movl(EAX, FieldAddress(EAX, GrowableObjectArray::data_offset()));  // data.
-
-  // Note that EBX is Smi, i.e, times 2.
-  ASSERT(kSmiTagShift == 1);
-  __ movl(EAX, FieldAddress(EAX, EBX, TIMES_2, Array::data_offset()));
-  __ ret();
-  __ Bind(&fall_through);
-}
-
-
-// Set value into growable object array at specified index.
-// On stack: growable array (+3), index (+2), value (+1), return-address (+0).
-void Intrinsifier::GrowableArraySetIndexed(Assembler* assembler) {
-  if (FLAG_enable_type_checks) {
-    return;
-  }
-  Label fall_through;
-  __ movl(EBX, Address(ESP, + 2 * kWordSize));  // Index.
-  __ movl(EAX, Address(ESP, + 3 * kWordSize));  // GrowableArray.
-  __ testl(EBX, Immediate(kSmiTagMask));
-  __ j(NOT_ZERO, &fall_through);  // Non-smi index.
-  // Range check using _length field.
-  __ cmpl(EBX, FieldAddress(EAX, GrowableObjectArray::length_offset()));
-  // Runtime throws exception.
-  __ j(ABOVE_EQUAL, &fall_through);
-  __ movl(EAX, FieldAddress(EAX, GrowableObjectArray::data_offset()));  // data.
-  __ movl(EDI, Address(ESP, + 1 * kWordSize));  // Value.
-  // Note that EBX is Smi, i.e, times 2.
-  ASSERT(kSmiTagShift == 1);
-  __ StoreIntoObject(EAX,
-                     FieldAddress(EAX, EBX, TIMES_2, Array::data_offset()),
-                     EDI);
-  __ ret();
-  __ Bind(&fall_through);
-}
-
-
-// Set length of growable object array. The length cannot
-// be greater than the length of the data container.
-// On stack: growable array (+2), length (+1), return-address (+0).
-void Intrinsifier::GrowableArraySetLength(Assembler* assembler) {
-  Label fall_through;
-  __ movl(EAX, Address(ESP, + 2 * kWordSize));  // Growable array.
-  __ movl(EBX, Address(ESP, + 1 * kWordSize));  // Length value.
-  __ testl(EBX, Immediate(kSmiTagMask));
-  __ j(NOT_ZERO, &fall_through, Assembler::kNearJump);  // Non-smi length.
-  FieldAddress length_field(EAX, GrowableObjectArray::length_offset());
-  __ StoreIntoSmiField(length_field, EBX);
-  __ ret();
-  __ Bind(&fall_through);
-}
-
-
-// Set data of growable object array.
-// On stack: growable array (+2), data (+1), return-address (+0).
-void Intrinsifier::GrowableArraySetData(Assembler* assembler) {
-  if (FLAG_enable_type_checks) {
-    return;
-  }
-  Label fall_through;
-  __ movl(EBX, Address(ESP, + 1 * kWordSize));  // Data.
-  // Check that data is an ObjectArray.
-  __ testl(EBX, Immediate(kSmiTagMask));
-  __ j(ZERO, &fall_through);  // Data is Smi.
-  __ CompareClassId(EBX, kArrayCid, EAX);
-  __ j(NOT_EQUAL, &fall_through);
-  __ movl(EAX, Address(ESP, + 2 * kWordSize));  // Growable array.
-  __ StoreIntoObject(EAX,
-                     FieldAddress(EAX, GrowableObjectArray::data_offset()),
-                     EBX);
-  __ ret();
-  __ Bind(&fall_through);
-}
-
-
 // Add an element to growable array if it doesn't need to grow, otherwise
 // call into regular code.
 // On stack: growable array (+2), value (+1), return-address (+0).
 void Intrinsifier::GrowableArray_add(Assembler* assembler) {
   // In checked mode we need to type-check the incoming argument.
-  if (FLAG_enable_type_checks) return;
+  if (Isolate::Current()->TypeChecksEnabled()) return;
 
   Label fall_through;
   __ movl(EAX, Address(ESP, + 2 * kWordSize));  // Array.
@@ -890,31 +803,6 @@
 }
 
 
-void Intrinsifier::Bigint_setNeg(Assembler* assembler) {
-  __ movl(EAX, Address(ESP, + 1 * kWordSize));
-  __ movl(ECX, Address(ESP, + 2 * kWordSize));
-  __ StoreIntoObject(ECX, FieldAddress(ECX, Bigint::neg_offset()), EAX, false);
-  __ ret();
-}
-
-
-void Intrinsifier::Bigint_setUsed(Assembler* assembler) {
-  __ movl(EAX, Address(ESP, + 1 * kWordSize));
-  __ movl(ECX, Address(ESP, + 2 * kWordSize));
-  __ StoreIntoObject(ECX, FieldAddress(ECX, Bigint::used_offset()), EAX);
-  __ ret();
-}
-
-
-void Intrinsifier::Bigint_setDigits(Assembler* assembler) {
-  __ movl(EAX, Address(ESP, + 1 * kWordSize));
-  __ movl(ECX, Address(ESP, + 2 * kWordSize));
-  __ StoreIntoObject(ECX,
-                     FieldAddress(ECX, Bigint::digits_offset()), EAX, false);
-  __ ret();
-}
-
-
 void Intrinsifier::Bigint_absAdd(Assembler* assembler) {
   // static void _absAdd(Uint32List digits, int used,
   //                     Uint32List a_digits, int a_used,
diff --git a/runtime/vm/intrinsifier_mips.cc b/runtime/vm/intrinsifier_mips.cc
index a5db082..a6bff54 100644
--- a/runtime/vm/intrinsifier_mips.cc
+++ b/runtime/vm/intrinsifier_mips.cc
@@ -42,7 +42,7 @@
 void Intrinsifier::ObjectArraySetIndexed(Assembler* assembler) {
   Label fall_through;
 
-  if (FLAG_enable_type_checks) {
+  if (Isolate::Current()->TypeChecksEnabled()) {
     const intptr_t type_args_field_offset =
         ComputeObjectArrayTypeArgumentsOffset();
     // Inline simple tests (Smi, null), fallthrough if not positive.
@@ -134,104 +134,12 @@
 }
 
 
-void Intrinsifier::GrowableArrayGetIndexed(Assembler* assembler) {
-  Label fall_through;
-
-  __ lw(T0, Address(SP, 0 * kWordSize));  // Index
-
-  __ andi(CMPRES1, T0, Immediate(kSmiTagMask));
-  __ bne(CMPRES1, ZR, &fall_through);  // Index is not an smi, fall through
-  __ delay_slot()->lw(T1, Address(SP, 1 * kWordSize));  // Array
-
-  // Range check.
-  __ lw(T2, FieldAddress(T1, GrowableObjectArray::length_offset()));
-  __ BranchUnsignedGreaterEqual(T0, T2, &fall_through);
-
-  __ lw(T2, FieldAddress(T1, GrowableObjectArray::data_offset()));  // data
-
-  ASSERT(kSmiTagShift == 1);
-  // array element at T2 + T0 * 2 + Array::data_offset - 1
-  __ sll(T3, T0, 1);
-  __ addu(T2, T2, T3);
-  __ Ret();
-  __ delay_slot()->lw(V0, FieldAddress(T2, Array::data_offset()));
-  __ Bind(&fall_through);
-}
-
-
-// Set value into growable object array at specified index.
-// On stack: growable array (+2), index (+1), value (+0).
-void Intrinsifier::GrowableArraySetIndexed(Assembler* assembler) {
-  if (FLAG_enable_type_checks) {
-    return;
-  }
-  Label fall_through;
-  __ lw(T1, Address(SP, 1 * kWordSize));  // Index.
-  __ andi(CMPRES1, T1, Immediate(kSmiTagMask));
-  __ bne(CMPRES1, ZR, &fall_through);  // Non-smi index.
-  __ delay_slot()->lw(T0, Address(SP, 2 * kWordSize));  // GrowableArray.
-  // Range check using _length field.
-  __ lw(T2, FieldAddress(T0, GrowableObjectArray::length_offset()));
-  // Runtime throws exception.
-  __ BranchUnsignedGreaterEqual(T1, T2, &fall_through);
-  __ lw(T0, FieldAddress(T0, GrowableObjectArray::data_offset()));  // data.
-  __ lw(T2, Address(SP, 0 * kWordSize));  // Value.
-  // Note that T1 is Smi, i.e, times 2.
-  ASSERT(kSmiTagShift == 1);
-  __ sll(T1, T1, 1);
-  __ addu(T1, T0, T1);
-  __ StoreIntoObject(T0,
-                     FieldAddress(T1, Array::data_offset()),
-                     T2);
-  __ Ret();
-  __ Bind(&fall_through);
-}
-
-
-// Set length of growable object array. The length cannot
-// be greater than the length of the data container.
-// On stack: growable array (+1), length (+0).
-void Intrinsifier::GrowableArraySetLength(Assembler* assembler) {
-  Label fall_through;
-  __ lw(T1, Address(SP, 0 * kWordSize));  // Length value.
-  __ andi(CMPRES1, T1, Immediate(kSmiTagMask));
-  __ bne(CMPRES1, ZR, &fall_through);  // Non-smi length.
-  __ delay_slot()->lw(T0, Address(SP, 1 * kWordSize));  // Growable array.
-  __ Ret();
-  __ delay_slot()->sw(T1,
-      FieldAddress(T0, GrowableObjectArray::length_offset()));
-  __ Bind(&fall_through);
-}
-
-
-// Set data of growable object array.
-// On stack: growable array (+1), data (+0).
-void Intrinsifier::GrowableArraySetData(Assembler* assembler) {
-  if (FLAG_enable_type_checks) {
-    return;
-  }
-  Label fall_through;
-  __ lw(T1, Address(SP, 0 * kWordSize));  // Data.
-  // Check that data is an ObjectArray.
-  __ andi(CMPRES1, T1, Immediate(kSmiTagMask));
-  __ beq(CMPRES1, ZR, &fall_through);  // Data is Smi.
-  __ LoadClassId(CMPRES1, T1);
-  __ BranchNotEqual(CMPRES1, Immediate(kArrayCid), &fall_through);
-  __ lw(T0, Address(SP, 1 * kWordSize));  // Growable array.
-  __ StoreIntoObject(T0,
-                     FieldAddress(T0, GrowableObjectArray::data_offset()),
-                     T1);
-  __ Ret();
-  __ Bind(&fall_through);
-}
-
-
 // Add an element to growable array if it doesn't need to grow, otherwise
 // call into regular code.
 // On stack: growable array (+1), value (+0).
 void Intrinsifier::GrowableArray_add(Assembler* assembler) {
   // In checked mode we need to type-check the incoming argument.
-  if (FLAG_enable_type_checks) return;
+  if (Isolate::Current()->TypeChecksEnabled()) return;
   Label fall_through;
   __ lw(T0, Address(SP, 1 * kWordSize));  // Array.
   __ lw(T1, FieldAddress(T0, GrowableObjectArray::length_offset()));
@@ -873,30 +781,6 @@
 }
 
 
-void Intrinsifier::Bigint_setNeg(Assembler* assembler) {
-  __ lw(T0, Address(SP, 0 * kWordSize));
-  __ lw(T1, Address(SP, 1 * kWordSize));
-  __ StoreIntoObject(T1, FieldAddress(T1, Bigint::neg_offset()), T0, false);
-  __ Ret();
-}
-
-
-void Intrinsifier::Bigint_setUsed(Assembler* assembler) {
-  __ lw(T0, Address(SP, 0 * kWordSize));
-  __ lw(T1, Address(SP, 1 * kWordSize));
-  __ StoreIntoObject(T1, FieldAddress(T1, Bigint::used_offset()), T0);
-  __ Ret();
-}
-
-
-void Intrinsifier::Bigint_setDigits(Assembler* assembler) {
-  __ lw(T0, Address(SP, 0 * kWordSize));
-  __ lw(T1, Address(SP, 1 * kWordSize));
-  __ StoreIntoObject(T1, FieldAddress(T1, Bigint::digits_offset()), T0, false);
-  __ Ret();
-}
-
-
 void Intrinsifier::Bigint_absAdd(Assembler* assembler) {
   // static void _absAdd(Uint32List digits, int used,
   //                     Uint32List a_digits, int a_used,
diff --git a/runtime/vm/intrinsifier_x64.cc b/runtime/vm/intrinsifier_x64.cc
index 223ea5f..a3f40bf 100644
--- a/runtime/vm/intrinsifier_x64.cc
+++ b/runtime/vm/intrinsifier_x64.cc
@@ -33,7 +33,7 @@
 
 
 void Intrinsifier::ObjectArraySetIndexed(Assembler* assembler) {
-  if (FLAG_enable_type_checks) {
+  if (Isolate::Current()->TypeChecksEnabled()) {
     return;
   }
   __ movq(RDX, Address(RSP, + 1 * kWordSize));  // Value.
@@ -97,98 +97,12 @@
 }
 
 
-// Access growable object array at specified index.
-// On stack: growable array (+2), index (+1), return-address (+0).
-void Intrinsifier::GrowableArrayGetIndexed(Assembler* assembler) {
-  Label fall_through;
-  __ movq(RCX, Address(RSP, + 1 * kWordSize));  // Index.
-  __ movq(RAX, Address(RSP, + 2 * kWordSize));  // GrowableArray.
-  __ testq(RCX, Immediate(kSmiTagMask));
-  __ j(NOT_ZERO, &fall_through, Assembler::kNearJump);  // Non-smi index.
-  // Range check using _length field.
-  __ cmpq(RCX, FieldAddress(RAX, GrowableObjectArray::length_offset()));
-  // Runtime throws exception.
-  __ j(ABOVE_EQUAL, &fall_through, Assembler::kNearJump);
-  __ movq(RAX, FieldAddress(RAX, GrowableObjectArray::data_offset()));  // data.
-
-  // Note that RCX is Smi, i.e, times 4.
-  ASSERT(kSmiTagShift == 1);
-  __ movq(RAX, FieldAddress(RAX, RCX, TIMES_4, Array::data_offset()));
-  __ ret();
-  __ Bind(&fall_through);
-}
-
-
-// Set value into growable object array at specified index.
-// On stack: growable array (+3), index (+2), value (+1), return-address (+0).
-void Intrinsifier::GrowableArraySetIndexed(Assembler* assembler) {
-  if (FLAG_enable_type_checks) {
-    return;
-  }
-  __ movq(RDX, Address(RSP, + 1 * kWordSize));  // Value.
-  __ movq(RCX, Address(RSP, + 2 * kWordSize));  // Index.
-  __ movq(RAX, Address(RSP, + 3 * kWordSize));  // GrowableArray.
-  Label fall_through;
-  __ testq(RCX, Immediate(kSmiTagMask));
-  __ j(NOT_ZERO, &fall_through);  // Non-smi index.
-  // Range check using _length field.
-  __ cmpq(RCX, FieldAddress(RAX, GrowableObjectArray::length_offset()));
-  // Runtime throws exception.
-  __ j(ABOVE_EQUAL, &fall_through);
-  __ movq(RAX, FieldAddress(RAX, GrowableObjectArray::data_offset()));  // data.
-  // Note that RCX is Smi, i.e, times 4.
-  ASSERT(kSmiTagShift == 1);
-  __ StoreIntoObject(RAX,
-                     FieldAddress(RAX, RCX, TIMES_4, Array::data_offset()),
-                     RDX);
-  __ ret();
-  __ Bind(&fall_through);
-}
-
-
-// Set length of growable object array. The length cannot
-// be greater than the length of the data container.
-// On stack: growable array (+2), length (+1), return-address (+0).
-void Intrinsifier::GrowableArraySetLength(Assembler* assembler) {
-  Label fall_through;
-  __ movq(RAX, Address(RSP, + 2 * kWordSize));  // Growable array.
-  __ movq(RCX, Address(RSP, + 1 * kWordSize));  // Length value.
-  __ testq(RCX, Immediate(kSmiTagMask));
-  __ j(NOT_ZERO, &fall_through, Assembler::kNearJump);  // Non-smi length.
-  FieldAddress length_field(RAX, GrowableObjectArray::length_offset());
-  __ StoreIntoSmiField(length_field, RCX);
-  __ ret();
-  __ Bind(&fall_through);
-}
-
-
-// Set data of growable object array.
-// On stack: growable array (+2), data (+1), return-address (+0).
-void Intrinsifier::GrowableArraySetData(Assembler* assembler) {
-  if (FLAG_enable_type_checks) {
-    return;
-  }
-  Label fall_through;
-  __ movq(RBX, Address(RSP, + 1 * kWordSize));  /// Data.
-  __ testq(RBX, Immediate(kSmiTagMask));
-  __ j(ZERO, &fall_through);  // Data is Smi.
-  __ CompareClassId(RBX, kArrayCid);
-  __ j(NOT_EQUAL, &fall_through);
-  __ movq(RAX, Address(RSP, + 2 * kWordSize));  // Growable array.
-  __ StoreIntoObject(RAX,
-                     FieldAddress(RAX, GrowableObjectArray::data_offset()),
-                     RBX);
-  __ ret();
-  __ Bind(&fall_through);
-}
-
-
 // Add an element to growable array if it doesn't need to grow, otherwise
 // call into regular code.
 // On stack: growable array (+2), value (+1), return-address (+0).
 void Intrinsifier::GrowableArray_add(Assembler* assembler) {
   // In checked mode we need to check the incoming argument.
-  if (FLAG_enable_type_checks) return;
+  if (Isolate::Current()->TypeChecksEnabled()) return;
   Label fall_through;
   __ movq(RAX, Address(RSP, + 2 * kWordSize));  // Array.
   __ movq(RCX, FieldAddress(RAX, GrowableObjectArray::length_offset()));
@@ -809,31 +723,6 @@
 }
 
 
-void Intrinsifier::Bigint_setNeg(Assembler* assembler) {
-  __ movq(RAX, Address(RSP, + 1 * kWordSize));
-  __ movq(RCX, Address(RSP, + 2 * kWordSize));
-  __ StoreIntoObject(RCX, FieldAddress(RCX, Bigint::neg_offset()), RAX, false);
-  __ ret();
-}
-
-
-void Intrinsifier::Bigint_setUsed(Assembler* assembler) {
-  __ movq(RAX, Address(RSP, + 1 * kWordSize));
-  __ movq(RCX, Address(RSP, + 2 * kWordSize));
-  __ StoreIntoObject(RCX, FieldAddress(RCX, Bigint::used_offset()), RAX);
-  __ ret();
-}
-
-
-void Intrinsifier::Bigint_setDigits(Assembler* assembler) {
-  __ movq(RAX, Address(RSP, + 1 * kWordSize));
-  __ movq(RCX, Address(RSP, + 2 * kWordSize));
-  __ StoreIntoObject(RCX,
-                     FieldAddress(RCX, Bigint::digits_offset()), RAX, false);
-  __ ret();
-}
-
-
 void Intrinsifier::Bigint_absAdd(Assembler* assembler) {
   // static void _absAdd(Uint32List digits, int used,
   //                     Uint32List a_digits, int a_used,
@@ -879,10 +768,12 @@
   __ j(NOT_ZERO, &carry_loop, Assembler::kNearJump);
 
   __ Bind(&last_carry);
-  __ movq(RAX, Immediate(0));
-  __ adcq(RAX, Immediate(0));
-  __ movq(FieldAddress(RBX, RDX, TIMES_8, TypedData::data_offset()), RAX);
+  Label done;
+  __ j(NOT_CARRY, &done);
+  __ movq(FieldAddress(RBX, RDX, TIMES_8, TypedData::data_offset()),
+          Immediate(1));
 
+  __ Bind(&done);
   // Returning Object::null() is not required, since this method is private.
   __ ret();
 }
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index a7e4661..31b8c9e 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -455,6 +455,8 @@
       debugger_(NULL),
       single_step_(false),
       resume_request_(false),
+      has_compiled_(false),
+      strict_compilation_(false),
       random_(),
       simulator_(NULL),
       long_jump_base_(NULL),
@@ -554,7 +556,7 @@
 #undef REUSABLE_HANDLE_INITIALIZERS
 
 Isolate::~Isolate() {
-  delete [] name_;
+  free(name_);
   delete heap_;
   delete object_store_;
   delete api_state_;
@@ -682,9 +684,13 @@
   if (name_prefix == NULL) {
     name_prefix = "isolate";
   }
+  if (Service::IsServiceIsolateName(name_prefix)) {
+    name_ = strdup(name_prefix);
+    return;
+  }
   const char* kFormat = "%s-%lld";
   intptr_t len = OS::SNPrint(NULL, 0, kFormat, name_prefix, main_port()) + 1;
-  name_ = new char[len];
+  name_ = reinterpret_cast<char*>(malloc(len));
   OS::SNPrint(name_, len, kFormat, name_prefix, main_port());
 }
 
@@ -1102,9 +1108,6 @@
     // Dump all accumulated timer data for the isolate.
     timer_list_.ReportTimers();
 
-    // Write out profiler data if requested.
-    Profiler::WriteProfile(this);
-
     // Write out the coverage data if collection has been enabled.
     CodeCoverage::Write(this);
 
@@ -1146,7 +1149,6 @@
 Dart_FileCloseCallback Isolate::file_close_callback_ = NULL;
 Dart_EntropySource Isolate::entropy_source_callback_ = NULL;
 Dart_IsolateInterruptCallback Isolate::vmstats_callback_ = NULL;
-Dart_ServiceIsolateCreateCalback Isolate::service_create_callback_ = NULL;
 
 Monitor* Isolate::isolates_list_monitor_ = NULL;
 Isolate* Isolate::isolates_list_head_ = NULL;
diff --git a/runtime/vm/isolate.h b/runtime/vm/isolate.h
index 3019f47..765f88b 100644
--- a/runtime/vm/isolate.h
+++ b/runtime/vm/isolate.h
@@ -22,6 +22,11 @@
 
 namespace dart {
 
+DECLARE_FLAG(bool, enable_type_checks);
+DECLARE_FLAG(bool, enable_asserts);
+DECLARE_FLAG(bool, error_on_bad_type);
+DECLARE_FLAG(bool, error_on_bad_override);
+
 // Forward declarations.
 class AbstractType;
 class ApiState;
@@ -357,6 +362,24 @@
     return OFFSET_OF(Isolate, single_step_);
   }
 
+  void set_has_compiled(bool value) { has_compiled_ = value; }
+  bool has_compiled() const { return has_compiled_; }
+
+  void set_strict_compilation(bool value) { strict_compilation_ = value; }
+  bool strict_compilation() const { return strict_compilation_; }
+  bool TypeChecksEnabled() {
+    return FLAG_enable_type_checks || strict_compilation_;
+  }
+  bool AssertsEnabled() {
+    return FLAG_enable_asserts || strict_compilation_;
+  }
+  bool ErrorOnBadTypeEnabled() {
+    return FLAG_error_on_bad_type || strict_compilation_;
+  }
+  bool ErrorOnBadOverrideEnabled() {
+    return FLAG_error_on_bad_override || strict_compilation_;
+  }
+
   // Requests that the debugger resume execution.
   void Resume() {
     resume_request_ = true;
@@ -408,13 +431,6 @@
     return create_callback_;
   }
 
-  static void SetServiceCreateCallback(Dart_ServiceIsolateCreateCalback cb) {
-    service_create_callback_ = cb;
-  }
-  static Dart_ServiceIsolateCreateCalback ServiceCreateCallback() {
-    return service_create_callback_;
-  }
-
   static void SetInterruptCallback(Dart_IsolateInterruptCallback cb) {
     interrupt_callback_ = cb;
   }
@@ -656,6 +672,8 @@
   Debugger* debugger_;
   bool single_step_;
   bool resume_request_;
+  bool has_compiled_;
+  bool strict_compilation_;
   Random random_;
   Simulator* simulator_;
   LongJumpScope* long_jump_base_;
@@ -738,7 +756,6 @@
   static Dart_FileCloseCallback file_close_callback_;
   static Dart_EntropySource entropy_source_callback_;
   static Dart_IsolateInterruptCallback vmstats_callback_;
-  static Dart_ServiceIsolateCreateCalback service_create_callback_;
 
   // Manage list of existing isolates.
   static void AddIsolateTolist(Isolate* isolate);
diff --git a/runtime/vm/json_stream.cc b/runtime/vm/json_stream.cc
index ecdd2ae..b525d7f 100644
--- a/runtime/vm/json_stream.cc
+++ b/runtime/vm/json_stream.cc
@@ -73,7 +73,47 @@
     Isolate* isolate = Isolate::Current();
     ASSERT(isolate != NULL);
     const char* isolate_name = isolate->name();
-    OS::Print("Isolate %s processing service request /%s",
+    OS::Print("Isolate %s processing service request %s",
+              isolate_name, command_);
+    for (intptr_t i = 1; i < num_arguments(); i++) {
+      OS::Print("/%s", GetArgument(i));
+    }
+    OS::Print("\n");
+    setup_time_micros_ = OS::GetCurrentTimeMicros();
+  }
+}
+
+
+void JSONStream::SetupNew(Zone* zone,
+                          Dart_Port reply_port,
+                          const String& method,
+                          const Array& option_keys,
+                          const Array& option_values) {
+  set_reply_port(reply_port);
+  command_ = method.ToCString();
+
+  String& string_iterator = String::Handle();
+  if (option_keys.Length() > 0) {
+    ASSERT(option_keys.Length() == option_values.Length());
+    const char** option_keys_native =
+        zone->Alloc<const char*>(option_keys.Length());
+    const char** option_values_native =
+        zone->Alloc<const char*>(option_keys.Length());
+    for (intptr_t i = 0; i < option_keys.Length(); i++) {
+      string_iterator ^= option_keys.At(i);
+      option_keys_native[i] =
+          zone->MakeCopyOfString(string_iterator.ToCString());
+      string_iterator ^= option_values.At(i);
+      option_values_native[i] =
+          zone->MakeCopyOfString(string_iterator.ToCString());
+    }
+    SetOptions(option_keys_native, option_values_native, option_keys.Length());
+  }
+  if (FLAG_trace_service) {
+    Isolate* isolate = Isolate::Current();
+    ASSERT(isolate != NULL);
+    const char* isolate_name = isolate->name();
+    OS::Print("Isolate %s processing service request %s",
               isolate_name, command_);
     for (intptr_t i = 1; i < num_arguments(); i++) {
       OS::Print("/%s", GetArgument(i));
@@ -111,7 +151,7 @@
     Isolate* isolate = Isolate::Current();
     ASSERT(isolate != NULL);
     const char* isolate_name = isolate->name();
-    OS::Print("Isolate %s processed service request /%s",
+    OS::Print("Isolate %s processed service request %s",
               isolate_name, command_);
     for (intptr_t i = 1; i < num_arguments(); i++) {
       OS::Print("/%s", GetArgument(i));
diff --git a/runtime/vm/json_stream.h b/runtime/vm/json_stream.h
index 8b4fc1e..56ecbcc 100644
--- a/runtime/vm/json_stream.h
+++ b/runtime/vm/json_stream.h
@@ -34,6 +34,13 @@
              const GrowableObjectArray& path,
              const Array& option_keys,
              const Array& option_values);
+
+  void SetupNew(Zone* zone,
+                Dart_Port reply_port,
+                const String& method,
+                const Array& param_keys,
+                const Array& param_values);
+
   void PostReply();
 
   TextBuffer* buffer() { return &buffer_; }
@@ -50,6 +57,9 @@
   const char* GetArgument(intptr_t i) const {
     return arguments_[i];
   }
+
+  // TODO(turnidge): Rename "options" to "params".  That is the more
+  // appropriate name for json rpc.
   intptr_t num_options() const { return num_options_; }
   const char* GetOptionKey(intptr_t i) const {
     return option_keys_[i];
@@ -66,6 +76,7 @@
   // otherwise.
   bool OptionIs(const char* key, const char* value) const;
 
+  // TODO(turnidge): Rename "command" to "method".  Better name for json rpc.
   const char* command() const { return command_; }
   const char** arguments() const { return arguments_; }
   const char** option_keys() const { return option_keys_; }
diff --git a/runtime/vm/method_recognizer.h b/runtime/vm/method_recognizer.h
index ba7d014..08260c3 100644
--- a/runtime/vm/method_recognizer.h
+++ b/runtime/vm/method_recognizer.h
@@ -155,15 +155,12 @@
 #define CORE_LIB_INTRINSIC_LIST(V)                                             \
   V(_Smi, ~, Smi_bitNegate, 134149043)                                         \
   V(_Smi, get:bitLength, Smi_bitLength, 869986288)                             \
-  V(_Bigint, set:_neg, Bigint_setNeg, 1924982939)                              \
-  V(_Bigint, set:_used, Bigint_setUsed, 1574448752)                            \
-  V(_Bigint, set:_digits, Bigint_setDigits, 1109140916)                        \
-  V(_Bigint, _absAdd, Bigint_absAdd, 97148049)                                 \
-  V(_Bigint, _absSub, Bigint_absSub, 159012285)                                \
-  V(_Bigint, _mulAdd, Bigint_mulAdd, 1625285265)                               \
-  V(_Bigint, _sqrAdd, Bigint_sqrAdd, 56442243)                                 \
-  V(_Bigint, _estQuotientDigit, Bigint_estQuotientDigit, 1844507489)           \
-  V(_Montgomery, _mulMod, Montgomery_mulMod, 1004817085)                       \
+  V(_Bigint, _absAdd, Bigint_absAdd, 222437051)                                \
+  V(_Bigint, _absSub, Bigint_absSub, 599465997)                                \
+  V(_Bigint, _mulAdd, Bigint_mulAdd, 1696801459)                               \
+  V(_Bigint, _sqrAdd, Bigint_sqrAdd, 1937424317)                               \
+  V(_Bigint, _estQuotientDigit, Bigint_estQuotientDigit, 1873913198)           \
+  V(_Montgomery, _mulMod, Montgomery_mulMod, 2040316431)                       \
   V(_Double, >, Double_greaterThan, 1538121903)                                \
   V(_Double, >=, Double_greaterEqualThan, 1058495718)                          \
   V(_Double, <, Double_lessThan, 62910596)                                     \
@@ -179,10 +176,6 @@
   V(_Double, .fromInteger, DoubleFromInteger, 803258435)                       \
   V(_List, []=, ObjectArraySetIndexed, 1768442583)                             \
   V(_GrowableList, .withData, GrowableArray_Allocate, 536409567)               \
-  V(_GrowableList, [], GrowableArrayGetIndexed, 514434920)                     \
-  V(_GrowableList, []=, GrowableArraySetIndexed, 1698264861)                   \
-  V(_GrowableList, _setLength, GrowableArraySetLength, 1832199634)             \
-  V(_GrowableList, _setData, GrowableArraySetData, 1722254196)                 \
   V(_GrowableList, add, GrowableArray_add, 422087403)                          \
   V(_JSSyntaxRegExp, _ExecuteMatch, JSRegExp_ExecuteMatch, 1654250896)         \
   V(Object, ==, ObjectEquals, 1955975370)                                      \
@@ -288,6 +281,10 @@
   V(_ImmutableList, [], ImmutableArrayGetIndexed, 1585504028)                  \
   V(_GrowableList, get:length, GrowableArrayLength, 778534898)                 \
   V(_GrowableList, get:_capacity, GrowableArrayCapacity, 555169866)            \
+  V(_GrowableList, _setData, GrowableArraySetData, 1722254196)                 \
+  V(_GrowableList, _setLength, GrowableArraySetLength, 1832199634)             \
+  V(_GrowableList, [], GrowableArrayGetIndexed, 514434920)                     \
+  V(_GrowableList, []=, GrowableArraySetIndexed, 1698264861)                   \
   V(_StringBase, get:length, StringBaseLength, 784429419)                      \
 
 #define GRAPH_INTRINSICS_LIST(V)                                               \
@@ -397,20 +394,17 @@
   V(::, tan, MathTan, 982072809)                                               \
   V(Lists, copy, ListsCopy, 605584668)                                         \
   V(_Bigint, get:_neg, Bigint_getNeg, 1151543890)                              \
-  V(_Bigint, set:_neg, Bigint_setNeg, 1924982939)                              \
   V(_Bigint, get:_used, Bigint_getUsed, 1308559334)                            \
-  V(_Bigint, set:_used, Bigint_setUsed, 1574448752)                            \
   V(_Bigint, get:_digits, Bigint_getDigits, 1408092463)                        \
-  V(_Bigint, set:_digits, Bigint_setDigits, 1109140916)                        \
 
 // A list of core function that should never be inlined.
 #define INLINE_BLACK_LIST(V)                                                   \
-  V(_Bigint, _absAdd, Bigint_absAdd, 97148049)                                 \
-  V(_Bigint, _absSub, Bigint_absSub, 159012285)                                \
-  V(_Bigint, _mulAdd, Bigint_mulAdd, 1625285265)                               \
-  V(_Bigint, _sqrAdd, Bigint_sqrAdd, 56442243)                                 \
-  V(_Bigint, _estQuotientDigit, Bigint_estQuotientDigit, 1844507489)           \
-  V(_Montgomery, _mulMod, Montgomery_mulMod, 1004817085)                       \
+  V(_Bigint, _absAdd, Bigint_absAdd, 222437051)                                \
+  V(_Bigint, _absSub, Bigint_absSub, 599465997)                                \
+  V(_Bigint, _mulAdd, Bigint_mulAdd, 1696801459)                               \
+  V(_Bigint, _sqrAdd, Bigint_sqrAdd, 1937424317)                               \
+  V(_Bigint, _estQuotientDigit, Bigint_estQuotientDigit, 1873913198)           \
+  V(_Montgomery, _mulMod, Montgomery_mulMod, 2040316431)                       \
 
 // A list of core functions that internally dispatch based on received id.
 #define POLYMORPHIC_TARGET_LIST(V)                                             \
diff --git a/runtime/vm/metrics.cc b/runtime/vm/metrics.cc
index 7687005..2e768b5 100644
--- a/runtime/vm/metrics.cc
+++ b/runtime/vm/metrics.cc
@@ -81,7 +81,11 @@
   obj.AddProperty("name", name_);
   obj.AddProperty("description", description_);
   obj.AddProperty("unit", UnitString(unit()));
-  obj.AddPropertyF("id", "metrics/vm/%s", name_);
+  if (isolate_ == NULL) {
+    obj.AddPropertyF("id", "vm/metrics/%s", name_);
+  } else {
+    obj.AddPropertyF("id", "metrics/native/%s", name_);
+  }
   // TODO(johnmccutchan): Overflow?
   double value_as_double = static_cast<double>(Value());
   obj.AddProperty("value", value_as_double);
diff --git a/runtime/vm/metrics_test.cc b/runtime/vm/metrics_test.cc
index bfcd469..69fe545 100644
--- a/runtime/vm/metrics_test.cc
+++ b/runtime/vm/metrics_test.cc
@@ -55,7 +55,8 @@
   metric.PrintJSON(&js);
   const char* json = js.ToCString();
   EXPECT_STREQ("{\"type\":\"Counter\",\"name\":\"a.b.c\",\"description\":"
-               "\"foobar\",\"unit\":\"byte\",\"id\":\"metrics\\/vm\\/a.b.c\""
+               "\"foobar\",\"unit\":\"byte\","
+               "\"id\":\"metrics\\/native\\/a.b.c\""
                ",\"value\":99.000000}", json);
 }
 
diff --git a/runtime/vm/native_arguments.h b/runtime/vm/native_arguments.h
index 3f4aac3..938ad80 100644
--- a/runtime/vm/native_arguments.h
+++ b/runtime/vm/native_arguments.h
@@ -51,7 +51,7 @@
   }
 #define DEOPTIMIZE_ALOT                                                        \
   if (FLAG_deoptimize_alot) {                                                  \
-    DeoptimizeAll();                                                           \
+    DeoptimizeFunctionsOnStack();                                              \
   }
 
 #else
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 4a7eb49..8bb0a39 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -5870,7 +5870,7 @@
 
 bool Function::HasCompatibleParametersWith(const Function& other,
                                            Error* bound_error) const {
-  ASSERT(FLAG_error_on_bad_override);
+  ASSERT(Isolate::Current()->ErrorOnBadOverrideEnabled());
   ASSERT((bound_error != NULL) && bound_error->IsNull());
   // Check that this function's signature type is a subtype of the other
   // function's signature type.
@@ -13559,7 +13559,7 @@
     const AbstractType& instantiated_other = AbstractType::Handle(
         isolate, other.InstantiateFrom(other_instantiator, bound_error));
     if ((bound_error != NULL) && !bound_error->IsNull()) {
-      ASSERT(FLAG_enable_type_checks);
+      ASSERT(Isolate::Current()->TypeChecksEnabled());
       return false;
     }
     other_class = instantiated_other.type_class();
@@ -14228,14 +14228,14 @@
   // type and/or malbounded parameter types, which will then be encountered here
   // at run time.
   if (IsMalbounded()) {
-    ASSERT(FLAG_enable_type_checks);
+    ASSERT(Isolate::Current()->TypeChecksEnabled());
     if ((bound_error != NULL) && bound_error->IsNull()) {
       *bound_error = error();
     }
     return false;
   }
   if (other.IsMalbounded()) {
-    ASSERT(FLAG_enable_type_checks);
+    ASSERT(Isolate::Current()->TypeChecksEnabled());
     if ((bound_error != NULL) && bound_error->IsNull()) {
       *bound_error = other.error();
     }
@@ -14442,7 +14442,7 @@
 
 
 bool Type::IsMalbounded() const {
-  if (!FLAG_enable_type_checks) {
+  if (!Isolate::Current()->TypeChecksEnabled()) {
     return false;
   }
   if (raw_ptr()->error_ == LanguageError::null()) {
@@ -14462,7 +14462,7 @@
     return true;
   }
   ASSERT(type_error.kind() == Report::kMalboundedType);
-  return FLAG_enable_type_checks;
+  return Isolate::Current()->TypeChecksEnabled();
 }
 
 
@@ -15439,7 +15439,7 @@
                                                 bound_error,
                                                 trail);
   }
-  if (FLAG_enable_type_checks &&
+  if ((Isolate::Current()->TypeChecksEnabled()) &&
       (bound_error != NULL) && bound_error->IsNull()) {
     AbstractType& upper_bound = AbstractType::Handle(bound());
     ASSERT(!upper_bound.IsObjectType() && !upper_bound.IsDynamicType());
@@ -16361,13 +16361,29 @@
 }
 
 
-void Bigint::set_neg(const Bool& value) const {
-  StorePointer(&raw_ptr()->neg_, value.raw());
+bool Bigint::Neg() const {
+  return Bool::Handle(neg()).value();
 }
 
 
-void Bigint::set_used(const Smi& value) const {
-  StoreSmi(&raw_ptr()->used_, value.raw());
+void Bigint::SetNeg(bool value) const {
+  StorePointer(&raw_ptr()->neg_, Bool::Get(value).raw());
+}
+
+
+intptr_t Bigint::Used() const {
+  return Smi::Value(used());
+}
+
+
+void Bigint::SetUsed(intptr_t value) const {
+  StoreSmi(&raw_ptr()->used_, Smi::New(value));
+}
+
+
+uint32_t Bigint::DigitAt(intptr_t index) const {
+  const TypedData& typed_data = TypedData::Handle(digits());
+  return typed_data.GetUint32(index << 2);
 }
 
 
@@ -16378,35 +16394,22 @@
 }
 
 
-bool Bigint::Neg() const {
-  return Bool::Handle(neg()).value();
+RawTypedData* Bigint::NewDigits(intptr_t length, Heap::Space space) {
+  ASSERT(length > 0);
+  // Account for leading zero for 64-bit processing.
+  return TypedData::New(kTypedDataUint32ArrayCid, length + 1, space);
 }
 
 
-void Bigint::SetNeg(bool value) const {
-  set_neg(Bool::Get(value));
+uint32_t Bigint::DigitAt(const TypedData& digits, intptr_t index) {
+  return digits.GetUint32(index << 2);
 }
 
 
-intptr_t Bigint::Used() const {
-  return Smi::Value(used());
-}
-
-
-void Bigint::SetUsed(intptr_t value) const {
-  set_used(Smi::Handle(Smi::New(value)));
-}
-
-
-uint32_t Bigint::DigitAt(intptr_t index) const {
-  const TypedData& typed_data = TypedData::Handle(digits());
-  return typed_data.GetUint32(index << 2);
-}
-
-
-void Bigint::SetDigitAt(intptr_t index, uint32_t value) const {
-  const TypedData& typed_data = TypedData::Handle(digits());
-  typed_data.SetUint32(index << 2, value);
+void Bigint::SetDigitAt(const TypedData& digits,
+                        intptr_t index,
+                        uint32_t value) {
+  digits.SetUint32(index << 2, value);
 }
 
 
@@ -16468,37 +16471,71 @@
     NoGCScope no_gc;
     result ^= raw;
   }
-  result.set_neg(Bool::Get(false));
-  result.set_used(Smi::Handle(isolate, Smi::New(0)));
+  result.SetNeg(false);
+  result.SetUsed(0);
   result.set_digits(
       TypedData::Handle(isolate, TypedData::EmptyUint32Array(isolate)));
   return result.raw();
 }
 
 
-RawBigint* Bigint::NewFromInt64(int64_t value, Heap::Space space) {
-  const Bigint& result = Bigint::Handle(New(space));
-  result.EnsureLength(2, space);
-  result.SetUsed(2);
-  if (value < 0) {
-    result.SetNeg(true);
-    value = -value;  // No concern about overflow, since sign is captured.
+RawBigint* Bigint::New(bool neg, intptr_t used, const TypedData& digits,
+                       Heap::Space space) {
+  ASSERT((used == 0) ||
+         (!digits.IsNull() && (digits.Length() >= (used + (used & 1)))));
+  Isolate* isolate = Isolate::Current();
+  ASSERT(isolate->object_store()->bigint_class() != Class::null());
+  Bigint& result = Bigint::Handle(isolate);
+  {
+    RawObject* raw = Object::Allocate(Bigint::kClassId,
+                                      Bigint::InstanceSize(),
+                                      space);
+    NoGCScope no_gc;
+    result ^= raw;
   }
-  result.SetDigitAt(0, static_cast<uint32_t>(value));
-  result.SetDigitAt(1, static_cast<uint32_t>(value >> 32));  // value >= 0.
-  result.Clamp();
+  // Clamp the digits array.
+  while ((used > 0) && (digits.GetUint32((used - 1) << 2) == 0)) {
+    --used;
+  }
+  if (used > 0) {
+    if ((used & 1) != 0) {
+      // Set leading zero for 64-bit processing of digit pairs.
+      digits.SetUint32(used << 2, 0);
+    }
+    result.set_digits(digits);
+  } else {
+    neg = false;
+    result.set_digits(
+        TypedData::Handle(isolate, TypedData::EmptyUint32Array(isolate)));
+  }
+  result.SetNeg(neg);
+  result.SetUsed(used);
   return result.raw();
 }
 
 
+RawBigint* Bigint::NewFromInt64(int64_t value, Heap::Space space) {
+  const TypedData& digits = TypedData::Handle(NewDigits(2, space));
+  bool neg;
+  uint64_t abs_value;
+  if (value < 0) {
+    neg = true;
+    abs_value = -value;
+  } else {
+    neg = false;
+    abs_value = value;
+  }
+  SetDigitAt(digits, 0, static_cast<uint32_t>(abs_value));
+  SetDigitAt(digits, 1, static_cast<uint32_t>(abs_value >> 32));
+  return New(neg, 2, digits, space);
+}
+
+
 RawBigint* Bigint::NewFromUint64(uint64_t value, Heap::Space space) {
-  const Bigint& result = Bigint::Handle(New(space));
-  result.EnsureLength(2, space);
-  result.SetUsed(2);
-  result.SetDigitAt(0, static_cast<uint32_t>(value));
-  result.SetDigitAt(1, static_cast<uint32_t>(value >> 32));
-  result.Clamp();
-  return result.raw();
+  const TypedData& digits = TypedData::Handle(NewDigits(2, space));
+  SetDigitAt(digits, 0, static_cast<uint32_t>(value));
+  SetDigitAt(digits, 1, static_cast<uint32_t>(value >> 32));
+  return New(false, 2, digits, space);
 }
 
 
@@ -16506,95 +16543,52 @@
                                        Heap::Space space) {
   ASSERT(kBitsPerDigit == 32);
   ASSERT(shift >= 0);
-  const Bigint& result = Bigint::Handle(New(space));
   const intptr_t digit_shift = shift / kBitsPerDigit;
   const intptr_t bit_shift = shift % kBitsPerDigit;
-  result.EnsureLength(3 + digit_shift, space);
-  result.SetUsed(3 + digit_shift);
+  const intptr_t used = 3 + digit_shift;
+  const TypedData& digits = TypedData::Handle(NewDigits(used, space));
+  bool neg;
   uint64_t abs_value;
   if (value < 0) {
-    result.SetNeg(true);
-    abs_value = -value;  // No concern about overflow, since sign is captured.
+    neg = true;
+    abs_value = -value;
   } else {
+    neg = false;
     abs_value = value;
   }
   for (intptr_t i = 0; i < digit_shift; i++) {
-    result.SetDigitAt(i, 0);
+    SetDigitAt(digits, i, 0);
   }
-  result.SetDigitAt(0 + digit_shift,
-                    static_cast<uint32_t>(abs_value << bit_shift));
-  result.SetDigitAt(1 + digit_shift,
-                    static_cast<uint32_t>(abs_value >> (32 - bit_shift)));
-  result.SetDigitAt(2 + digit_shift,
+  SetDigitAt(digits, 0 + digit_shift,
+             static_cast<uint32_t>(abs_value << bit_shift));
+  SetDigitAt(digits, 1 + digit_shift,
+             static_cast<uint32_t>(abs_value >> (32 - bit_shift)));
+  SetDigitAt(digits, 2 + digit_shift,
       (bit_shift == 0) ? 0
                        : static_cast<uint32_t>(abs_value >> (64 - bit_shift)));
-  result.Clamp();
-  return result.raw();
-}
-
-
-void Bigint::EnsureLength(intptr_t length, Heap::Space space) const {
-  ASSERT(length >= 0);
-  length++;  // Account for leading zero for 64-bit processing.
-  TypedData& old_digits = TypedData::Handle(digits());
-  if (length > old_digits.Length()) {
-    TypedData& new_digits = TypedData::Handle(
-        TypedData::New(kTypedDataUint32ArrayCid, length + kExtraDigits, space));
-    set_digits(new_digits);
-    if (Used() > 0) {
-      TypedData::Copy(new_digits, TypedData::data_offset(),
-                      old_digits, TypedData::data_offset(),
-                      (Used() + 1)*kBytesPerDigit);  // Copy leading zero.
-    }
-  }
-}
-
-
-void Bigint::Clamp() const {
-  intptr_t used = Used();
-  if (used > 0) {
-    if (DigitAt(used - 1) == 0) {
-      do {
-        --used;
-      } while ((used > 0) && (DigitAt(used - 1) == 0));
-      SetUsed(used);
-    }
-    SetDigitAt(used, 0);  // Set leading zero for 64-bit processing.
-  }
-}
-
-
-bool Bigint::IsClamped() const {
-  intptr_t used = Used();
-  return (used == 0) || (DigitAt(used - 1) > 0);
+  return New(neg, used, digits, space);
 }
 
 
 RawBigint* Bigint::NewFromCString(const char* str, Heap::Space space) {
   ASSERT(str != NULL);
-  // If the string starts with '-' recursively restart the whole operation
-  // without the character and then toggle the sign.
+  bool neg = false;
+  TypedData& digits = TypedData::Handle();
   if (str[0] == '-') {
     ASSERT(str[1] != '-');
-    const Bigint& result = Bigint::Handle(NewFromCString(&str[1], space));
-    result.SetNeg(!result.Neg());  // Toggle sign.
-    ASSERT(result.IsZero() || result.IsNegative());
-    ASSERT(result.IsClamped());
-    return result.raw();
+    neg = true;
+    str++;
   }
-
-  // No overflow check needed since overflowing str_length implies that we take
-  // the branch to NewFromDecCString() which contains a check itself.
+  intptr_t used;
   const intptr_t str_length = strlen(str);
   if ((str_length >= 2) &&
       (str[0] == '0') &&
       ((str[1] == 'x') || (str[1] == 'X'))) {
-    const Bigint& result = Bigint::Handle(NewFromHexCString(&str[2], space));
-    ASSERT(result.IsClamped());
-    return result.raw();
+    digits = NewDigitsFromHexCString(&str[2], &used, space);
   } else {
-    return NewFromDecCString(str, space);
+    digits = NewDigitsFromDecCString(str, &used, space);
   }
+  return New(neg, used, digits, space);
 }
 
 
@@ -16627,28 +16621,17 @@
 }
 
 
-RawBigint* Bigint::NewFromHexCString(const char* str, Heap::Space space) {
-  // If the string starts with '-' recursively restart the whole operation
-  // without the character and then toggle the sign.
-  if (str[0] == '-') {
-    ASSERT(str[1] != '-');
-    const Bigint& result = Bigint::Handle(NewFromHexCString(&str[1], space));
-    if (!result.IsZero()) {
-      result.SetNeg(!result.Neg());  // Toggle sign.
-    }
-    ASSERT(result.IsClamped());
-    return result.raw();
-  }
-  const Bigint& result = Bigint::Handle(New(space));
+RawTypedData* Bigint::NewDigitsFromHexCString(const char* str, intptr_t* used,
+                                              Heap::Space space) {
   const int kBitsPerHexDigit = 4;
   const int kHexDigitsPerDigit = 8;
   const int kBitsPerDigit = kBitsPerHexDigit * kHexDigitsPerDigit;
   intptr_t hex_i = strlen(str);  // Terminating byte excluded.
   if ((hex_i <= 0) || (hex_i >= kMaxInt32)) {
-    FATAL("Fatal error in Bigint::NewFromHexCString: string too long or empty");
+    FATAL("Fatal error parsing hex bigint: string too long or empty");
   }
-  result.EnsureLength((hex_i + kHexDigitsPerDigit - 1) / kHexDigitsPerDigit,
-                      space);
+  const intptr_t length = (hex_i + kHexDigitsPerDigit - 1) / kHexDigitsPerDigit;
+  const TypedData& digits = TypedData::Handle(NewDigits(length, space));
   intptr_t used_ = 0;
   uint32_t digit = 0;
   intptr_t bit_i = 0;
@@ -16657,53 +16640,48 @@
     bit_i += kBitsPerHexDigit;
     if (bit_i == kBitsPerDigit) {
       bit_i = 0;
-      result.SetDigitAt(used_++, digit);
+      SetDigitAt(digits, used_++, digit);
       digit = 0;
     }
   }
   if (bit_i != 0) {
-    result.SetDigitAt(used_++, digit);
+    SetDigitAt(digits, used_++, digit);
   }
-  result.SetUsed(used_);
-  result.Clamp();
-  return result.raw();
+  *used = used_;
+  return digits.raw();
 }
 
 
-RawBigint* Bigint::NewFromDecCString(const char* str, Heap::Space space) {
+RawTypedData* Bigint::NewDigitsFromDecCString(const char* str, intptr_t* used,
+                                              Heap::Space space) {
   // Read 9 digits a time. 10^9 < 2^32.
   const int kDecDigitsPerIteration = 9;
   const uint32_t kTenMultiplier = 1000000000;
   ASSERT(kBitsPerDigit == 32);
-
   const intptr_t str_length = strlen(str);
   if ((str_length <= 0) || (str_length >= kMaxInt32)) {
-    FATAL("Fatal error in Bigint::NewFromDecCString: string too long or empty");
+    FATAL("Fatal error parsing dec bigint: string too long or empty");
   }
-  intptr_t str_pos = 0;
-
-  Bigint& result = Bigint::Handle(Bigint::New(space));
   // One decimal digit takes log2(10) bits, i.e. ~3.32192809489 bits.
   // That is a theoretical limit for large numbers.
-  // The extra digits allocated take care of variations (kExtraDigits).
+  // The extra 5 digits allocated take care of variations.
   const int64_t kLog10Dividend = 33219281;
   const int64_t kLog10Divisor = 10000000;
-
-  result.EnsureLength((kLog10Dividend * str_length) /
-                      (kLog10Divisor * kBitsPerDigit) + 1, space);
-
+  const intptr_t length = (kLog10Dividend * str_length) /
+                          (kLog10Divisor * kBitsPerDigit) + 5;
+  const TypedData& digits = TypedData::Handle(NewDigits(length, space));
   // Read first digit separately. This avoids a multiplication and addition.
   // The first digit might also not have kDecDigitsPerIteration decimal digits.
   const intptr_t lsdigit_length = str_length % kDecDigitsPerIteration;
   uint32_t digit = 0;
+  intptr_t str_pos = 0;
   for (intptr_t i = 0; i < lsdigit_length; i++) {
     char c = str[str_pos++];
     ASSERT(('0' <= c) && (c <= '9'));
     digit = digit * 10 + c - '0';
   }
-  result.SetDigitAt(0, digit);
-  intptr_t used = 1;
-
+  SetDigitAt(digits, 0, digit);
+  intptr_t used_ = 1;
   // Read kDecDigitsPerIteration at a time, and store it in 'digit'.
   // Then multiply the temporary result by 10^kDecDigitsPerIteration and add
   // 'digit' to the new result.
@@ -16715,17 +16693,16 @@
       digit = digit * 10 + c - '0';
     }
     // Multiply result with kTenMultiplier and add digit.
-    for (intptr_t i = 0; i < used; i++) {
+    for (intptr_t i = 0; i < used_; i++) {
       uint64_t product =
-          (static_cast<uint64_t>(result.DigitAt(i)) * kTenMultiplier) + digit;
-      result.SetDigitAt(i, static_cast<uint32_t>(product & kDigitMask));
+          (static_cast<uint64_t>(DigitAt(digits, i)) * kTenMultiplier) + digit;
+      SetDigitAt(digits, i, static_cast<uint32_t>(product & kDigitMask));
       digit = static_cast<uint32_t>(product >> kBitsPerDigit);
     }
-    result.SetDigitAt(used++, digit);
+    SetDigitAt(digits, used_++, digit);
   }
-  result.SetUsed(used);
-  result.Clamp();
-  return result.raw();
+  *used = used_;
+  return digits.raw();
 }
 
 
@@ -16775,7 +16752,6 @@
 
 double Bigint::AsDoubleValue() const {
   ASSERT(kBitsPerDigit == 32);
-  ASSERT(IsClamped());
   const intptr_t used = Used();
   if (used == 0) {
     return 0.0;
@@ -17169,10 +17145,15 @@
   ASSERT(begin_index >= 0);
   ASSERT(len >= 0);
   ASSERT((begin_index + len) <= str.Length());
+  if (len == 0) {
+    return;
+  }
   if (str.IsOneByteString()) {
+    NoGCScope no_gc;
+    uint8_t* str_addr = OneByteString::CharAddr(str, begin_index);
     for (intptr_t i = 0; i < len; i++) {
-      NoGCScope no_gc;
-      Add(*OneByteString::CharAddr(str, i + begin_index));
+      Add(*str_addr);
+      str_addr++;
     }
   } else {
     String::CodePointIterator it(str, begin_index, len);
@@ -18665,6 +18646,36 @@
 }
 
 
+RawTwoByteString* TwoByteString::New(const TypedData& other_typed_data,
+                                     intptr_t other_start_index,
+                                     intptr_t other_len,
+                                     Heap::Space space) {
+  const String& result = String::Handle(TwoByteString::New(other_len, space));
+  if (other_len > 0) {
+    NoGCScope no_gc;
+    memmove(TwoByteString::CharAddr(result, 0),
+            other_typed_data.DataAddr(other_start_index),
+            other_len * sizeof(uint16_t));
+  }
+  return TwoByteString::raw(result);
+}
+
+
+RawTwoByteString* TwoByteString::New(const ExternalTypedData& other_typed_data,
+                                     intptr_t other_start_index,
+                                     intptr_t other_len,
+                                     Heap::Space space) {
+  const String& result = String::Handle(TwoByteString::New(other_len, space));
+  if (other_len > 0) {
+    NoGCScope no_gc;
+    memmove(TwoByteString::CharAddr(result, 0),
+            other_typed_data.DataAddr(other_start_index),
+            other_len * sizeof(uint16_t));
+  }
+  return TwoByteString::raw(result);
+}
+
+
 RawTwoByteString* TwoByteString::Concat(const String& str1,
                                         const String& str2,
                                         Heap::Space space) {
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index bbded40..c57f824 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -5579,35 +5579,33 @@
     return RoundedAllocationSize(sizeof(RawBigint));
   }
 
+  // Offsets of fields accessed directly by optimized code.
+  static intptr_t neg_offset() { return OFFSET_OF(RawBigint, neg_); }
+  static intptr_t used_offset() { return OFFSET_OF(RawBigint, used_); }
+  static intptr_t digits_offset() { return OFFSET_OF(RawBigint, digits_); }
+
   // Accessors used by native calls from Dart.
   RawBool* neg() const { return raw_ptr()->neg_; }
-  void set_neg(const Bool& value) const;
-  static intptr_t neg_offset() { return OFFSET_OF(RawBigint, neg_); }
   RawSmi* used() const { return raw_ptr()->used_; }
-  void set_used(const Smi& value) const;
-  static intptr_t used_offset() { return OFFSET_OF(RawBigint, used_); }
   RawTypedData* digits() const { return raw_ptr()->digits_; }
-  void set_digits(const TypedData& value) const;
-  static intptr_t digits_offset() { return OFFSET_OF(RawBigint, digits_); }
 
   // Accessors used by runtime calls from C++.
   bool Neg() const;
-  void SetNeg(bool value) const;
   intptr_t Used() const;
-  void SetUsed(intptr_t value) const;
   uint32_t DigitAt(intptr_t index) const;
-  void SetDigitAt(intptr_t index, uint32_t value) const;
 
   const char* ToDecCString(uword (*allocator)(intptr_t size)) const;
   const char* ToHexCString(uword (*allocator)(intptr_t size)) const;
 
-  static const intptr_t kExtraDigits = 4;  // Same as _Bigint.EXTRA_DIGITS
-  static const intptr_t kBitsPerDigit = 32;  // Same as _Bigint.DIGIT_BITS
+  static const intptr_t kBitsPerDigit = 32;  // Same as _Bigint._DIGIT_BITS
   static const intptr_t kBytesPerDigit = 4;
   static const int64_t kDigitBase = 1LL << kBitsPerDigit;
   static const int64_t kDigitMask = kDigitBase - 1;
 
-  static RawBigint* New(Heap::Space space = Heap::kNew);
+  static RawBigint* New(Heap::Space space = Heap::kNew);  // For snapshots.
+
+  static RawBigint* New(bool neg, intptr_t used, const TypedData& digits,
+                        Heap::Space space = Heap::kNew);
 
   static RawBigint* NewFromInt64(int64_t value,
                                   Heap::Space space = Heap::kNew);
@@ -5625,19 +5623,23 @@
   static RawBigint* NewCanonical(const String& str);
 
  private:
-  static RawBigint* NewFromHexCString(const char* str,
-                                       Heap::Space space = Heap::kNew);
-  static RawBigint* NewFromDecCString(const char* str,
-                                       Heap::Space space = Heap::kNew);
+  void SetNeg(bool value) const;
+  void SetUsed(intptr_t value) const;
+  void set_digits(const TypedData& value) const;
 
-  // Make sure at least 'length' _digits are allocated.
-  // Copy existing _digits if reallocation is necessary.
-  void EnsureLength(intptr_t length, Heap::Space space = Heap::kNew) const;
+  // Convenience helpers.
+  static RawTypedData* NewDigits(intptr_t length,
+                                 Heap::Space space = Heap::kNew);
+  static uint32_t DigitAt(const TypedData& digits, intptr_t index);
+  static void SetDigitAt(const TypedData& digits,
+                         intptr_t index,
+                         uint32_t value);
 
-  // Do not count zero high digits as used.
-  void Clamp() const;
+  static RawTypedData* NewDigitsFromHexCString(const char* str, intptr_t* used,
+                                               Heap::Space space = Heap::kNew);
 
-  bool IsClamped() const;
+  static RawTypedData* NewDigitsFromDecCString(const char* str, intptr_t* used,
+                                               Heap::Space space = Heap::kNew);
 
   static RawBigint* Allocate(intptr_t length, Heap::Space space = Heap::kNew);
 
@@ -6177,6 +6179,16 @@
   static RawTwoByteString* New(const String& str,
                                Heap::Space space);
 
+  static RawTwoByteString* New(const TypedData& other_typed_data,
+                               intptr_t other_start_index,
+                               intptr_t other_len,
+                               Heap::Space space = Heap::kNew);
+
+  static RawTwoByteString* New(const ExternalTypedData& other_typed_data,
+                               intptr_t other_start_index,
+                               intptr_t other_len,
+                               Heap::Space space = Heap::kNew);
+
   static RawTwoByteString* Concat(const String& str1,
                                   const String& str2,
                                   Heap::Space space);
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
index 8790f75..17d5367 100644
--- a/runtime/vm/parser.cc
+++ b/runtime/vm/parser.cc
@@ -361,9 +361,7 @@
       async_temp_scope_(NULL) {
   ASSERT(tokens_iterator_.IsValid());
   ASSERT(!current_function().IsNull());
-  if (FLAG_enable_type_checks) {
-    EnsureExpressionTemp();
-  }
+  EnsureExpressionTemp();
 }
 
 
@@ -1434,11 +1432,21 @@
   ArgumentListNode* no_args = new ArgumentListNode(token_pos);
   LoadLocalNode* receiver = new LoadLocalNode(token_pos, scope->VariableAt(0));
 
+  const Class& function_impl = Class::Handle(Type::Handle(
+      Isolate::Current()->object_store()->function_impl_type()).type_class());
+
+  const Class& owner = Class::Handle(Z, func.Owner());
+  ASSERT(!owner.IsNull());
   const String& name = String::Handle(Z, func.name());
-  const String& getter_name = String::ZoneHandle(Z,
-      Symbols::New(String::Handle(Z, Field::GetterName(name))));
-  InstanceCallNode* getter_call = new(Z) InstanceCallNode(
-      token_pos, receiver, getter_name, no_args);
+  AstNode* function_object = NULL;
+  if (owner.raw() == function_impl.raw() && name.Equals(Symbols::Call())) {
+    function_object = receiver;
+  } else {
+    const String& getter_name = String::ZoneHandle(Z,
+        Symbols::New(String::Handle(Z, Field::GetterName(name))));
+    function_object = new(Z) InstanceCallNode(
+        token_pos, receiver, getter_name, no_args);
+  }
 
   // Pass arguments 1..n to the closure call.
   ArgumentListNode* args = new(Z) ArgumentListNode(token_pos);
@@ -1457,13 +1465,11 @@
   }
   args->set_names(names);
 
-  const Class& owner = Class::Handle(Z, func.Owner());
-  ASSERT(!owner.IsNull());
   AstNode* result = NULL;
-  if (owner.IsSignatureClass() && name.Equals(Symbols::Call())) {
-    result = new ClosureCallNode(token_pos, getter_call, args);
+  if (owner.raw() == function_impl.raw() && name.Equals(Symbols::Call())) {
+    result = new ClosureCallNode(token_pos, function_object, args);
   } else {
-    result = BuildClosureCall(token_pos, getter_call, args);
+    result = BuildClosureCall(token_pos, function_object, args);
   }
 
   ReturnNode* return_node = new ReturnNode(token_pos, result);
@@ -3077,9 +3083,14 @@
     error_param.name = &Symbols::AsyncOperationErrorParam();
     error_param.default_value = &Object::null_instance();
     error_param.type = &dynamic_type;
+    ParamDesc stack_trace_param;
+    stack_trace_param.name = &Symbols::AsyncOperationStackTraceParam();
+    stack_trace_param.default_value = &Object::null_instance();
+    stack_trace_param.type = &dynamic_type;
     params.parameters->Add(result_param);
     params.parameters->Add(error_param);
-    params.num_optional_parameters += 2;
+    params.parameters->Add(stack_trace_param);
+    params.num_optional_parameters += 3;
     params.has_optional_positional_parameters = true;
     SetupDefaultsForOptionalParams(&params, default_parameter_values);
     AddFormalParamsToScope(&params, current_block_->scope);
@@ -3119,7 +3130,7 @@
     // Populate function scope with the formal parameters.
     AddFormalParamsToScope(&params, current_block_->scope);
 
-    if (FLAG_enable_type_checks &&
+    if (I->TypeChecksEnabled() &&
         (current_block_->scope->function_level() > 0)) {
       // We are parsing, but not compiling, a local function.
       // The instantiator may be required at run time for generic type checks.
@@ -6062,8 +6073,13 @@
   error_param.default_value = &Object::null_instance();
   error_param.type = &dynamic_type;
   closure_params.parameters->Add(error_param);
+  ParamDesc stack_trace_param;
+  stack_trace_param.name = &Symbols::AsyncOperationStackTraceParam();
+  stack_trace_param.default_value = &Object::null_instance();
+  stack_trace_param.type = &dynamic_type;
+  closure_params.parameters->Add(stack_trace_param);
   closure_params.has_optional_positional_parameters = true;
-  closure_params.num_optional_parameters += 2;
+  closure_params.num_optional_parameters += 3;
 
   if (is_new_closure) {
     // Add the parameters to the newly created closure.
@@ -6555,7 +6571,7 @@
   bool is_final = (CurrentToken() == Token::kFINAL);
   bool is_const = (CurrentToken() == Token::kCONST);
   const AbstractType& type = AbstractType::ZoneHandle(Z,
-      ParseConstFinalVarOrType(FLAG_enable_type_checks ?
+      ParseConstFinalVarOrType(I->TypeChecksEnabled() ?
           ClassFinalizer::kCanonicalize : ClassFinalizer::kIgnore));
   if (!IsIdentifier()) {
     ReportError("identifier expected");
@@ -7543,8 +7559,8 @@
     // position, which is inside the loop body.
     new_loop_var = true;
     loop_var_type = ParseConstFinalVarOrType(
-       FLAG_enable_type_checks ? ClassFinalizer::kCanonicalize :
-                                 ClassFinalizer::kIgnore);
+       I->TypeChecksEnabled() ? ClassFinalizer::kCanonicalize :
+                                ClassFinalizer::kIgnore);
   }
   intptr_t loop_var_pos = TokenPos();
   const String* loop_var_name = ExpectIdentifier("variable name expected");
@@ -7593,7 +7609,7 @@
   AstNode* await_moveNext = new (Z) AwaitNode(stream_pos, iterator_moveNext);
   OpenBlock();
   AwaitTransformer at(current_block_->statements,
-                      parsed_function(),
+                      *parsed_function(),
                       async_temp_scope_);
   AstNode* transformed_await = at.Transform(await_moveNext);
   SequenceNode* await_preamble = CloseBlock();
@@ -7686,8 +7702,8 @@
     // position, which is inside the loop body.
     new_loop_var = true;
     loop_var_type = ParseConstFinalVarOrType(
-        FLAG_enable_type_checks ? ClassFinalizer::kCanonicalize :
-                                  ClassFinalizer::kIgnore);
+        I->TypeChecksEnabled() ? ClassFinalizer::kCanonicalize :
+                                 ClassFinalizer::kIgnore);
     loop_var_name = ExpectIdentifier("variable name expected");
   }
   ExpectToken(Token::kIN);
@@ -7905,7 +7921,7 @@
   ConsumeToken();  // Consume assert keyword.
   ExpectToken(Token::kLPAREN);
   const intptr_t condition_pos = TokenPos();
-  if (!FLAG_enable_asserts && !FLAG_enable_type_checks) {
+  if (!I->AssertsEnabled() && !I->TypeChecksEnabled()) {
     SkipExpr();
     ExpectToken(Token::kRPAREN);
     return NULL;
@@ -9287,7 +9303,7 @@
     // are created.
     OpenBlock();
     AwaitTransformer at(current_block_->statements,
-                        parsed_function(),
+                        *parsed_function(),
                         async_temp_scope_);
     AstNode* result = at.Transform(expr);
     SequenceNode* preamble = CloseBlock();
@@ -10815,7 +10831,7 @@
                     "include a type variable");
       }
     } else {
-      if (FLAG_error_on_bad_type) {
+      if (I->ErrorOnBadTypeEnabled()) {
         ReportError(type_pos,
                     "a list literal takes one type argument specifying "
                     "the element type");
@@ -10838,7 +10854,7 @@
     while (CurrentToken() != Token::kRBRACK) {
       const intptr_t element_pos = TokenPos();
       AstNode* element = ParseExpr(is_const, kConsumeCascades);
-      if (FLAG_enable_type_checks &&
+      if (I->TypeChecksEnabled() &&
           !is_const &&
           !element_type.IsDynamicType()) {
         element = new(Z) AssignableNode(element_pos,
@@ -10869,7 +10885,7 @@
       // Arguments have been evaluated to a literal value already.
       ASSERT(elem->IsLiteralNode());
       ASSERT(!is_top_level_);  // We cannot check unresolved types.
-      if (FLAG_enable_type_checks &&
+      if (I->TypeChecksEnabled() &&
           !element_type.IsDynamicType() &&
           (!elem->AsLiteralNode()->literal().IsNull() &&
            !elem->AsLiteralNode()->literal().IsInstanceOf(
@@ -11012,7 +11028,7 @@
                     "include a type variable");
       }
     } else {
-      if (FLAG_error_on_bad_type) {
+      if (I->ErrorOnBadTypeEnabled()) {
         ReportError(type_pos,
                     "a map literal takes two type arguments specifying "
                     "the key type and the value type");
@@ -11031,7 +11047,7 @@
     const bool saved_mode = SetAllowFunctionLiterals(true);
     const intptr_t key_pos = TokenPos();
     AstNode* key = ParseExpr(is_const, kConsumeCascades);
-    if (FLAG_enable_type_checks &&
+    if (I->TypeChecksEnabled() &&
         !is_const &&
         !key_type.IsDynamicType()) {
       key = new(Z) AssignableNode(
@@ -11054,7 +11070,7 @@
     const intptr_t value_pos = TokenPos();
     AstNode* value = ParseExpr(is_const, kConsumeCascades);
     SetAllowFunctionLiterals(saved_mode);
-    if (FLAG_enable_type_checks &&
+    if (I->TypeChecksEnabled() &&
         !is_const &&
         !value_type.IsDynamicType()) {
       value = new(Z) AssignableNode(
@@ -11086,7 +11102,7 @@
       // Arguments have been evaluated to a literal value already.
       ASSERT(arg->IsLiteralNode());
       ASSERT(!is_top_level_);  // We cannot check unresolved types.
-      if (FLAG_enable_type_checks) {
+      if (I->TypeChecksEnabled()) {
         if ((i % 2) == 0) {
           // Check key type.
           arg_type = key_type.raw();
@@ -11411,7 +11427,7 @@
         }
         return ThrowTypeError(redirect_type.token_pos(), redirect_type);
       }
-      if (FLAG_enable_type_checks && !redirect_type.IsSubtypeOf(type, NULL)) {
+      if (I->TypeChecksEnabled() && !redirect_type.IsSubtypeOf(type, NULL)) {
         // Additional type checking of the result is necessary.
         type_bound = type.raw();
       }
diff --git a/runtime/vm/parser_test.cc b/runtime/vm/parser_test.cc
index 5b5db0f..71fc503 100644
--- a/runtime/vm/parser_test.cc
+++ b/runtime/vm/parser_test.cc
@@ -215,9 +215,11 @@
     ActivationFrame* frame = stack->FrameAt(i);
     var_desc = frame->code().var_descriptors();
     const char* var_str = SkipIndex(var_desc.ToCString());
+    const char* function_str = String::Handle(
+        frame->function().QualifiedUserVisibleName()).ToCString();
     pos += OS::SNPrint(pos, (kBufferLen - (pos - buffer)),
                        "%s\n%s",
-                       frame->function().ToQualifiedCString(),
+                       function_str,
                        var_str);
     delete [] var_str;
   }
@@ -261,20 +263,20 @@
   EXPECT_VALID(lib);
   EXPECT_STREQ(
       // function f uses one ctx var at (0); doesn't save ctx.
-      "::.main_f\n"
+      "main.f\n"
       " 0 ContextVar    level=0   begin=14  end=28  name=value\n"
       " 1 StackVar      scope=1   begin=16  end=28  name=param\n"
       " 2 CurrentCtx    scope=0   begin=0   end=0"
       "   name=:current_context_var\n"
 
       // Closure call saves current context.
-      "(dynamic, dynamic) => int.call\n"
-      " 0 StackVar      scope=1   begin=0   end=0   name=this\n"
+      "_FunctionImpl.call\n"
+      " 0 StackVar      scope=1   begin=0   end=4   name=this\n"
       " 1 CurrentCtx    scope=0   begin=0   end=0"
       "   name=:current_context_var\n"
 
       // function main uses one ctx var at (1); saves caller ctx.
-      "::.main\n"
+      "main\n"
       " 0 ContextLevel  level=1   scope=1   begin=2   end=37\n"
       " 1 CurrentCtx    scope=0   begin=0   end=0"
       "   name=:current_context_var\n"
@@ -301,21 +303,21 @@
   EXPECT_STREQ(
       // Innermost function uses captured variable 'value' from middle
       // function.
-      "::.a_b_c\n"
+      "a.b.c\n"
       " 0 ContextVar    level=0   begin=20  end=30  name=value\n"
       " 1 CurrentCtx    scope=0   begin=0   end=0"
       "   name=:current_context_var\n"
 
       // Closure call saves current context.
-      "(dynamic) => int.call\n"
-      " 0 StackVar      scope=1   begin=0   end=0   name=this\n"
+      "_FunctionImpl.call\n"
+      " 0 StackVar      scope=1   begin=0   end=4   name=this\n"
       " 1 CurrentCtx    scope=0   begin=0   end=0"
       "   name=:current_context_var\n"
 
       // Middle function saves the entry context.  Notice that this
       // happens here and not in the outermost function.  We always
       // save the entry context at the last possible moment.
-      "::.a_b\n"
+      "a.b\n"
       " 0 ContextLevel  level=1   scope=1   begin=8   end=38\n"
       " 1 CurrentCtx    scope=0   begin=0   end=0"
       "   name=:current_context_var\n"
@@ -323,15 +325,15 @@
       " 3 StackVar      scope=2   begin=18  end=38  name=c\n"
 
       // Closure call saves current context.
-      "(dynamic) => int.call\n"
-      " 0 StackVar      scope=1   begin=0   end=0   name=this\n"
+      "_FunctionImpl.call\n"
+      " 0 StackVar      scope=1   begin=0   end=4   name=this\n"
       " 1 CurrentCtx    scope=0   begin=0   end=0"
       "   name=:current_context_var\n"
 
       // Outermost function neglects to save the entry context.  We
       // don't save the entry context if the function has no captured
       // variables.
-      "::.a\n"
+      "a\n"
       " 0 CurrentCtx    scope=0   begin=0   end=0"
       "   name=:current_context_var\n"
       " 1 StackVar      scope=2   begin=6   end=46  name=b\n",
@@ -360,21 +362,21 @@
 
   EXPECT_STREQ(
       // bb captures only value2 from aa.  No others.
-      "::.a_b_aa_bb\n"
+      "a.b.aa.bb\n"
       " 0 ContextVar    level=0   begin=32  end=42  name=value2\n"
       " 1 CurrentCtx    scope=0   begin=0   end=0"
       "   name=:current_context_var\n"
 
       // Closure call saves current context.
-      "(dynamic) => int.call\n"
-      " 0 StackVar      scope=1   begin=0   end=0   name=this\n"
+      "_FunctionImpl.call\n"
+      " 0 StackVar      scope=1   begin=0   end=4   name=this\n"
       " 1 CurrentCtx    scope=0   begin=0   end=0"
       "   name=:current_context_var\n"
 
       // aa shares value2. Notice that we save the entry ctx instead
       // of chaining from b.  This keeps us from holding onto closures
       // that we would never access.
-      "::.a_b_aa\n"
+      "a.b.aa\n"
       " 0 ContextLevel  level=1   scope=1   begin=20  end=50\n"
       " 1 CurrentCtx    scope=0   begin=0   end=0"
       "   name=:current_context_var\n"
@@ -382,26 +384,26 @@
       " 3 StackVar      scope=2   begin=30  end=50  name=bb\n"
 
       // Closure call saves current context.
-      "(dynamic) => int.call\n"
-      " 0 StackVar      scope=1   begin=0   end=0   name=this\n"
+      "_FunctionImpl.call\n"
+      " 0 StackVar      scope=1   begin=0   end=4   name=this\n"
       " 1 CurrentCtx    scope=0   begin=0   end=0"
       "   name=:current_context_var\n"
 
       // b captures value1 from a.
-      "::.a_b\n"
+      "a.b\n"
       " 0 ContextVar    level=0   begin=14  end=60  name=value1\n"
       " 1 CurrentCtx    scope=0   begin=0   end=0"
       "   name=:current_context_var\n"
       " 2 StackVar      scope=2   begin=18  end=60  name=aa\n"
 
       // Closure call saves current context.
-      "(dynamic) => int.call\n"
-      " 0 StackVar      scope=1   begin=0   end=0   name=this\n"
+      "_FunctionImpl.call\n"
+      " 0 StackVar      scope=1   begin=0   end=4   name=this\n"
       " 1 CurrentCtx    scope=0   begin=0   end=0"
       "   name=:current_context_var\n"
 
       // a shares value1, saves entry ctx.
-      "::.a\n"
+      "a\n"
       " 0 ContextLevel  level=1   scope=1   begin=2   end=68\n"
       " 1 CurrentCtx    scope=0   begin=0   end=0"
       "   name=:current_context_var\n"
@@ -441,15 +443,15 @@
   EXPECT_VALID(lib);
   EXPECT_STREQ(
       // This frame saves the entry context instead of chaining.  Good.
-      "::.doIt_<anonymous closure>\n"
+      "doIt.<anonymous closure>\n"
       " 0 ContextLevel  level=1   scope=1   begin=41  end=62\n"
       " 1 ContextVar    level=1   begin=42  end=62  name=y\n"
       " 2 CurrentCtx    scope=0   begin=0   end=0"
       "   name=:current_context_var\n"
 
       // Closure call saves current context.
-      "(dynamic, dynamic) => dynamic.call\n"
-      " 0 StackVar      scope=1   begin=0   end=0   name=this\n"
+      "_FunctionImpl.call\n"
+      " 0 StackVar      scope=1   begin=0   end=4   name=this\n"
       " 1 CurrentCtx    scope=0   begin=0   end=0"
       "   name=:current_context_var\n"
 
@@ -459,7 +461,7 @@
       "   name=:current_context_var\n"
 
       // No context is saved here since no vars are captured.
-      "::.doIt\n"
+      "doIt\n"
       " 0 CurrentCtx    scope=0   begin=0   end=0"
       "   name=:current_context_var\n"
       " 1 StackVar      scope=2   begin=29  end=77  name=x\n",
@@ -487,20 +489,20 @@
   EXPECT_VALID(lib);
   EXPECT_STREQ(
       // inner function captures variable value.  That's fine.
-      "::.outer_inner\n"
+      "outer.inner\n"
       " 0 ContextVar    level=0   begin=32  end=42  name=value\n"
       " 1 CurrentCtx    scope=0   begin=0   end=0"
       "   name=:current_context_var\n"
 
       // Closure call saves current context.
-      "(dynamic) => int.call\n"
-      " 0 StackVar      scope=1   begin=0   end=0   name=this\n"
+      "_FunctionImpl.call\n"
+      " 0 StackVar      scope=1   begin=0   end=4   name=this\n"
       " 1 CurrentCtx    scope=0   begin=0   end=0"
       "   name=:current_context_var\n"
 
       // The outer function saves the entry context, even though the
       // captured variable is in a loop.  Good.
-      "::.outer\n"
+      "outer\n"
       " 0 CurrentCtx    scope=0   begin=0   end=0"
       "   name=:current_context_var\n"
       " 1 StackVar      scope=3   begin=9   end=50  name=i\n"
@@ -530,17 +532,17 @@
   Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
   EXPECT_VALID(lib);
   EXPECT_STREQ(
-      "::.a_b_c\n"
+      "a.b.c\n"
       " 0 ContextVar    level=0   begin=48  end=60  name=x\n"
       " 1 CurrentCtx    scope=0   begin=0   end=0"
       "   name=:current_context_var\n"
-      "(dynamic) => int.call\n"
-      " 0 StackVar      scope=1   begin=0   end=0   name=this\n"
+      "_FunctionImpl.call\n"
+      " 0 StackVar      scope=1   begin=0   end=4   name=this\n"
       " 1 CurrentCtx    scope=0   begin=0   end=0"
       "   name=:current_context_var\n"
 
       // Doesn't save the entry context.  Chains to parent instead.
-      "::.a_b\n"
+      "a.b\n"
       " 0 ContextVar    level=0   begin=12  end=68  name=x\n"
       " 1 CurrentCtx    scope=0   begin=0   end=0"
       "   name=:current_context_var\n"
@@ -549,12 +551,12 @@
       " 4 ContextVar    level=1   begin=19  end=46  name=i\n"
       " 5 StackVar      scope=4   begin=32  end=46  name=d\n"
 
-      "(dynamic) => dynamic.call\n"
-      " 0 StackVar      scope=1   begin=0   end=0   name=this\n"
+      "_FunctionImpl.call\n"
+      " 0 StackVar      scope=1   begin=0   end=4   name=this\n"
       " 1 CurrentCtx    scope=0   begin=0   end=0"
       "   name=:current_context_var\n"
 
-      "::.a\n"
+      "a\n"
       " 0 ContextLevel  level=1   scope=1   begin=1   end=76\n"
       " 1 CurrentCtx    scope=0   begin=0   end=0"
       "   name=:current_context_var\n"
diff --git a/runtime/vm/profiler.cc b/runtime/vm/profiler.cc
index bf119f5..335d105 100644
--- a/runtime/vm/profiler.cc
+++ b/runtime/vm/profiler.cc
@@ -31,8 +31,6 @@
 #endif
 DEFINE_FLAG(bool, trace_profiled_isolates, false, "Trace profiled isolates.");
 DEFINE_FLAG(bool, trace_profiler, false, "Trace profiler.");
-DEFINE_FLAG(charp, profile_dir, NULL,
-            "Enable writing profile data into specified directory.");
 DEFINE_FLAG(int, profile_period, 1000,
             "Time between profiler samples in microseconds. Minimum 50.");
 DEFINE_FLAG(int, profile_depth, 8,
@@ -541,7 +539,6 @@
 
   void PrintToJSONArray(Isolate* isolate, JSONArray* events, bool full) {
     JSONObject obj(events);
-    obj.AddProperty("type", "CodeRegion");
     obj.AddProperty("kind", KindToCString(kind()));
     obj.AddPropertyF("inclusive_ticks", "%" Pd "", inclusive_ticks());
     obj.AddPropertyF("exclusive_ticks", "%" Pd "", exclusive_ticks());
@@ -1506,7 +1503,7 @@
         ScopeStopwatch sw("CodeTableStream");
         // Serialize to JSON.
         JSONObject obj(stream);
-        obj.AddProperty("type", "Profile");
+        obj.AddProperty("type", "CpuProfile");
         obj.AddProperty("id", "profile");
         obj.AddProperty("samples", samples);
         obj.AddProperty("depth", static_cast<intptr_t>(FLAG_profile_depth));
@@ -1543,47 +1540,6 @@
 }
 
 
-void Profiler::WriteProfile(Isolate* isolate) {
-  if (isolate == NULL) {
-    return;
-  }
-  if (!FLAG_profile) {
-    return;
-  }
-  ASSERT(initialized_);
-  if (FLAG_profile_dir == NULL) {
-    return;
-  }
-  Dart_FileOpenCallback file_open = Isolate::file_open_callback();
-  Dart_FileCloseCallback file_close = Isolate::file_close_callback();
-  Dart_FileWriteCallback file_write = Isolate::file_write_callback();
-  if ((file_open == NULL) || (file_close == NULL) || (file_write == NULL)) {
-    // Embedder has not provided necessary callbacks.
-    return;
-  }
-  // We will be looking up code objects within the isolate.
-  ASSERT(Isolate::Current() == isolate);
-  JSONStream stream(10 * MB);
-  intptr_t pid = OS::ProcessId();
-  PrintJSON(isolate, &stream, true, Profiler::kNoTags);
-  const char* format = "%s/dart-profile-%" Pd "-%" Pd ".json";
-  intptr_t len = OS::SNPrint(NULL, 0, format,
-                             FLAG_profile_dir, pid, isolate->main_port());
-  char* filename = Isolate::Current()->current_zone()->Alloc<char>(len + 1);
-  OS::SNPrint(filename, len + 1, format,
-              FLAG_profile_dir, pid, isolate->main_port());
-  void* f = file_open(filename, true);
-  if (f == NULL) {
-    // Cannot write.
-    return;
-  }
-  TextBuffer* buffer = stream.buffer();
-  ASSERT(buffer != NULL);
-  file_write(buffer->buf(), buffer->length(), f);
-  file_close(f);
-}
-
-
 IsolateProfilerData::IsolateProfilerData(SampleBuffer* sample_buffer,
                                          bool own_sample_buffer) {
   ASSERT(sample_buffer != NULL);
diff --git a/runtime/vm/profiler.h b/runtime/vm/profiler.h
index e669270..0c0bb0a 100644
--- a/runtime/vm/profiler.h
+++ b/runtime/vm/profiler.h
@@ -46,7 +46,6 @@
 
   static void PrintJSON(Isolate* isolate, JSONStream* stream,
                         bool full, TagOrder tag_order);
-  static void WriteProfile(Isolate* isolate);
 
   static SampleBuffer* sample_buffer() {
     return sample_buffer_;
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index 801668b..749ee45 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -497,8 +497,6 @@
 #if defined(DEBUG)
     ValidateOverwrittenPointer(*addr);
 #endif  // DEBUG
-    // Ensure that this object contains the addr.
-    ASSERT(Contains(reinterpret_cast<uword>(addr)));
     VerifiedMemory::Write(const_cast<type*>(addr), value);
     // Filter stores based on source and target.
     if (!value->IsHeapObject()) return;
diff --git a/runtime/vm/raw_object_snapshot.cc b/runtime/vm/raw_object_snapshot.cc
index 3bf9794..49d25ec 100644
--- a/runtime/vm/raw_object_snapshot.cc
+++ b/runtime/vm/raw_object_snapshot.cc
@@ -1366,12 +1366,8 @@
 
   // Allocate context object.
   int32_t num_vars = reader->Read<int32_t>();
-  Context& context = Context::ZoneHandle(reader->isolate(), Context::null());
-  if (kind == Snapshot::kFull) {
-    context = reader->NewContext(num_vars);
-  } else {
-    context = Context::New(num_vars, HEAP_SPACE(kind));
-  }
+  Context& context = Context::ZoneHandle(
+      reader->isolate(), NEW_OBJECT_WITH_LEN(Context, num_vars));
   reader->AddBackRef(object_id, &context, kIsDeserialized);
 
   // Set the object tags.
@@ -1406,8 +1402,6 @@
   // Write out num of variables in the context.
   writer->Write<int32_t>(ptr()->num_variables_);
 
-  // Can't serialize the isolate pointer, we set it implicitly on read.
-
   // Write out all the object pointer fields.
   SnapshotWriterVisitor visitor(writer);
   visitor.VisitPointers(from(), to(ptr()->num_variables_));
@@ -1903,9 +1897,14 @@
     *str_obj = StringType::New(len, HEAP_SPACE(kind));
     str_obj->set_tags(tags);
     str_obj->SetHash(0);  // Will get computed when needed.
+    if (len == 0) {
+      return;
+    }
     NoGCScope no_gc;
+    CharacterType* str_addr = StringType::CharAddr(*str_obj, 0);
     for (intptr_t i = 0; i < len; i++) {
-      *StringType::CharAddr(*str_obj, i) = reader->Read<CharacterType>();
+      *str_addr = reader->Read<CharacterType>();
+      str_addr++;
     }
   }
 }
diff --git a/runtime/vm/regexp_assembler.cc b/runtime/vm/regexp_assembler.cc
index a494b1f..46a9b21 100644
--- a/runtime/vm/regexp_assembler.cc
+++ b/runtime/vm/regexp_assembler.cc
@@ -121,7 +121,7 @@
   // Create and generate all preset blocks.
   entry_block_ =
       new(isolate) GraphEntryInstr(
-        parsed_function_,
+        *parsed_function_,
         new(isolate) TargetEntryInstr(block_id_.Alloc(), kInvalidTryIndex),
         Isolate::kNoDeoptId);
   start_block_ =
diff --git a/runtime/vm/resolver.cc b/runtime/vm/resolver.cc
index 2109ddd..7274efa 100644
--- a/runtime/vm/resolver.cc
+++ b/runtime/vm/resolver.cc
@@ -221,4 +221,36 @@
   return function.raw();
 }
 
+
+RawFunction* Resolver::ResolveStaticAllowPrivate(const Class&  cls,
+                                                 const String& function_name,
+                                                 intptr_t num_arguments,
+                                                 const Array& argument_names) {
+  ASSERT(!cls.IsNull());
+  if (FLAG_trace_resolving) {
+    OS::Print("ResolveStaticAllowPrivate '%s'\n", function_name.ToCString());
+  }
+  const Function& function =
+      Function::Handle(cls.LookupStaticFunctionAllowPrivate(function_name));
+  if (function.IsNull() ||
+      !function.AreValidArguments(num_arguments, argument_names, NULL)) {
+    // Return a null function to signal to the upper levels to throw a
+    // resolution error or maybe throw the error right here.
+    if (FLAG_trace_resolving) {
+      String& error_message = String::Handle(String::New("function not found"));
+      if (!function.IsNull()) {
+        // Obtain more detailed error message.
+        function.AreValidArguments(num_arguments,
+                                   argument_names,
+                                   &error_message);
+      }
+      OS::Print("ResolveStaticAllowPrivate error '%s': %s.\n",
+                function_name.ToCString(),
+                error_message.ToCString());
+    }
+    return Function::null();
+  }
+  return function.raw();
+}
+
 }  // namespace dart
diff --git a/runtime/vm/resolver.h b/runtime/vm/resolver.h
index 32ef3bc..1ea883e 100644
--- a/runtime/vm/resolver.h
+++ b/runtime/vm/resolver.h
@@ -49,11 +49,19 @@
                                     intptr_t num_arguments,
                                     const Array& argument_names);
 
-  // Resolve specified dart static function with specified arity.
+  // Resolve specified dart static function with specified arity. Only resolves
+  // public functions.
   static RawFunction* ResolveStatic(const Class&  cls,
                                     const String& function_name,
                                     intptr_t num_arguments,
                                     const Array& argument_names);
+
+  // Resolve specified dart static function with specified arity. Resolves both
+  // public and private functions.
+  static RawFunction* ResolveStaticAllowPrivate(const Class&  cls,
+                                                const String& function_name,
+                                                intptr_t num_arguments,
+                                                const Array& argument_names);
 };
 
 }  // namespace dart
diff --git a/runtime/vm/service.cc b/runtime/vm/service.cc
index 1aae8ae..25330c4 100644
--- a/runtime/vm/service.cc
+++ b/runtime/vm/service.cc
@@ -14,6 +14,7 @@
 #include "vm/dart_entry.h"
 #include "vm/debugger.h"
 #include "vm/isolate.h"
+#include "vm/lockers.h"
 #include "vm/message.h"
 #include "vm/message_handler.h"
 #include "vm/native_entry.h"
@@ -247,6 +248,82 @@
 }
 
 
+class ScopeStopwatch : public ValueObject {
+ public:
+  explicit ScopeStopwatch(const char* name) : name_(name) {
+    start_ = OS::GetCurrentTimeMicros();
+  }
+
+  int64_t GetElapsed() const {
+    int64_t end = OS::GetCurrentTimeMicros();
+    ASSERT(end >= start_);
+    return end - start_;
+  }
+
+  ~ScopeStopwatch() {
+    int64_t elapsed = GetElapsed();
+    OS::Print("[%" Pd "] %s took %" Pd64 " micros.\n",
+              OS::ProcessId(), name_, elapsed);
+  }
+
+ private:
+  const char* name_;
+  int64_t start_;
+};
+
+
+bool Service::IsRunning() {
+  MonitorLocker ml(monitor_);
+  return (service_port_ != ILLEGAL_PORT) && (service_isolate_ != NULL);
+}
+
+
+void Service::SetServicePort(Dart_Port port) {
+  MonitorLocker ml(monitor_);
+  service_port_ = port;
+}
+
+
+void Service::SetServiceIsolate(Isolate* isolate) {
+  MonitorLocker ml(monitor_);
+  service_isolate_ = isolate;
+}
+
+
+bool Service::HasServiceIsolate() {
+  MonitorLocker ml(monitor_);
+  return service_isolate_ != NULL;
+}
+
+
+bool Service::IsServiceIsolate(Isolate* isolate) {
+  MonitorLocker ml(monitor_);
+  return isolate == service_isolate_;
+}
+
+Dart_Port Service::WaitForLoadPort() {
+  MonitorLocker ml(monitor_);
+
+  while (initializing_ && (load_port_ == ILLEGAL_PORT)) {
+    ml.Wait();
+  }
+
+  return load_port_;
+}
+
+
+Dart_Port Service::LoadPort() {
+  MonitorLocker ml(monitor_);
+  return load_port_;
+}
+
+
+void Service::SetLoadPort(Dart_Port port) {
+  MonitorLocker ml(monitor_);
+  load_port_ = port;
+}
+
+
 void Service::SetEventMask(uint32_t mask) {
   event_mask_ = mask;
 }
@@ -288,7 +365,7 @@
       : IsolateVisitor(),
         register_function_(Function::Handle(service_isolate)),
         service_isolate_(service_isolate) {
-    ASSERT(Isolate::Current() == service_isolate_);
+    ASSERT(Service::IsServiceIsolate(Isolate::Current()));
     // Get library.
     const String& library_url = Symbols::DartVMService();
     ASSERT(!library_url.IsNull());
@@ -304,8 +381,8 @@
   }
 
   virtual void VisitIsolate(Isolate* isolate) {
-    ASSERT(Isolate::Current() == service_isolate_);
-    if ((isolate == service_isolate_) ||
+    ASSERT(Service::IsServiceIsolate(Isolate::Current()));
+    if (Service::IsServiceIsolate(isolate) ||
         (isolate == Dart::vm_isolate())) {
       // We do not register the service or vm isolate.
       return;
@@ -324,6 +401,11 @@
     args.SetAt(2, name);
     Object& r = Object::Handle(service_isolate_);
     r = DartEntry::InvokeFunction(register_function_, args);
+    if (FLAG_trace_service) {
+      OS::Print("vm-service: Isolate %s %" Pd64 " registered.\n",
+                name.ToCString(),
+                port_id);
+    }
     ASSERT(!r.IsError());
   }
 
@@ -348,6 +430,9 @@
   StackZone zone(isolate);
   HANDLESCOPE(isolate);
   {
+    if (FLAG_trace_service) {
+      OS::Print("vm-service: Booting dart:vmservice library.\n");
+    }
     // Boot the dart:vmservice library.
     Dart_EnterScope();
     Dart_Handle url_str =
@@ -359,10 +444,14 @@
     ASSERT(!Dart_IsError(result));
     Dart_Port port = ExtractPort(isolate, result);
     ASSERT(port != ILLEGAL_PORT);
-    Service::set_port(port);
+    Service::SetServicePort(port);
     Dart_ExitScope();
   }
+
   {
+    if (FLAG_trace_service) {
+      OS::Print("vm-service: Registering running isolates.\n");
+    }
     // Register running isolates with service.
     RegisterRunningIsolatesVisitor register_isolates(isolate);
     Isolate::VisitIsolates(&register_isolates);
@@ -408,77 +497,21 @@
   return NULL;
 }
 
-
+const char* Service::kIsolateName = "vm-service";
 EmbedderServiceHandler* Service::isolate_service_handler_head_ = NULL;
 EmbedderServiceHandler* Service::root_service_handler_head_ = NULL;
 Isolate* Service::service_isolate_ = NULL;
-Dart_LibraryTagHandler Service::embedder_provided_handler_ = NULL;
-Dart_Port Service::port_ = ILLEGAL_PORT;
+Dart_Port Service::service_port_ = ILLEGAL_PORT;
+Dart_Port Service::load_port_ = ILLEGAL_PORT;
+Dart_IsolateCreateCallback Service::create_callback_ = NULL;
+Monitor* Service::monitor_ = NULL;
+bool Service::initializing_ = true;
 uint32_t Service::event_mask_ = 0;
 
-Isolate* Service::GetServiceIsolate(void* callback_data) {
-  if (service_isolate_ != NULL) {
-    // Already initialized, return service isolate.
-    return service_isolate_;
-  }
-  Dart_ServiceIsolateCreateCalback create_callback =
-    Isolate::ServiceCreateCallback();
-  if (create_callback == NULL) {
-    return NULL;
-  }
-  Isolate::SetCurrent(NULL);
-  char* error = NULL;
-  Isolate* isolate =
-      reinterpret_cast<Isolate*>(create_callback(callback_data, &error));
-  if (isolate == NULL) {
-    return NULL;
-  }
-  StartIsolateScope isolate_scope(isolate);
-  {
-    // Install the dart:vmservice library.
-    StackZone zone(isolate);
-    HANDLESCOPE(isolate);
-    Library& library =
-        Library::Handle(isolate, isolate->object_store()->root_library());
-    // Isolate is empty.
-    ASSERT(library.IsNull());
-    // Grab embedder tag handler.
-    embedder_provided_handler_ = isolate->library_tag_handler();
-    // Temporarily install our own.
-    isolate->set_library_tag_handler(LibraryTagHandler);
-    // Get script resource.
-    const char* resource = NULL;
-    const char* path = "/vmservice.dart";
-    intptr_t r = Resources::ResourceLookup(path, &resource);
-    ASSERT(r != Resources::kNoSuchInstance);
-    ASSERT(resource != NULL);
-    const String& source_str = String::Handle(
-        String::FromUTF8(reinterpret_cast<const uint8_t*>(resource), r));
-    ASSERT(!source_str.IsNull());
-    const String& url_str = String::Handle(Symbols::DartVMService().raw());
-    library ^= Library::LookupLibrary(url_str);
-    ASSERT(library.IsNull());
-    // Setup library.
-    library = Library::New(url_str);
-    library.Register();
-    const Script& script = Script::Handle(
-      isolate, Script::New(url_str, source_str, RawScript::kLibraryTag));
-    library.SetLoadInProgress();
-    Dart_EnterScope();  // Need to enter scope for tag handler.
-    const Error& error = Error::Handle(isolate,
-                                       Compiler::Compile(library, script));
-    ASSERT(error.IsNull());
-    Dart_Handle result = Dart_FinalizeLoading(false);
-    ASSERT(!Dart_IsError(result));
-    Dart_ExitScope();
 
-    // Install embedder default library tag handler again.
-    isolate->set_library_tag_handler(embedder_provided_handler_);
-    embedder_provided_handler_ = NULL;
-    library.set_native_entry_resolver(VmServiceNativeResolver);
-  }
-  service_isolate_ = reinterpret_cast<Isolate*>(isolate);
-  return service_isolate_;
+bool Service::IsServiceIsolateName(const char* name) {
+  ASSERT(name != NULL);
+  return strcmp(name, kIsolateName) == 0;
 }
 
 
@@ -487,6 +520,9 @@
     return false;
   }
   Isolate* isolate = Isolate::Current();
+  if (IsServiceIsolate(isolate)) {
+    return false;
+  }
   ASSERT(isolate != NULL);
   HANDLESCOPE(isolate);
   const String& name = String::Handle(String::New(isolate->name()));
@@ -501,12 +537,12 @@
   writer.WriteMessage(list);
   intptr_t len = writer.BytesWritten();
   if (FLAG_trace_service) {
-    OS::Print("Isolate %s %" Pd64 " registered with service \n",
+    OS::Print("vm-service: Isolate %s %" Pd64 " registered.\n",
               name.ToCString(),
               Dart_GetMainPortId());
   }
   return PortMap::PostMessage(
-      new Message(port_, data, len, Message::kNormalPriority));
+      new Message(service_port_, data, len, Message::kNormalPriority));
 }
 
 
@@ -515,6 +551,9 @@
     return false;
   }
   Isolate* isolate = Isolate::Current();
+  if (IsServiceIsolate(isolate)) {
+    return false;
+  }
   ASSERT(isolate != NULL);
   HANDLESCOPE(isolate);
   const String& name = String::Handle(String::New(isolate->name()));
@@ -529,12 +568,12 @@
   writer.WriteMessage(list);
   intptr_t len = writer.BytesWritten();
   if (FLAG_trace_service) {
-    OS::Print("Isolate %s %" Pd64 " deregistered with service \n",
+    OS::Print("vm-service: Isolate %s %" Pd64 " deregistered.\n",
               name.ToCString(),
               Dart_GetMainPortId());
   }
   return PortMap::PostMessage(
-      new Message(port_, data, len, Message::kNormalPriority));
+      new Message(service_port_, data, len, Message::kNormalPriority));
 }
 
 
@@ -560,32 +599,22 @@
 }
 
 
-Dart_Handle Service::LibraryTagHandler(Dart_LibraryTag tag, Dart_Handle library,
+Dart_Handle Service::LibraryTagHandler(Dart_LibraryTag tag,
+                                       Dart_Handle library,
                                        Dart_Handle url) {
-  if (!Dart_IsLibrary(library)) {
-    return Dart_NewApiError("not a library");
+  if (tag == Dart_kCanonicalizeUrl) {
+    // url is already canonicalized.
+    return url;
   }
-  if (!Dart_IsString(url)) {
-    return Dart_NewApiError("url is not a string");
+  if (tag != Dart_kSourceTag) {
+    FATAL("Service::LibraryTagHandler encountered an unexpected tag.");
   }
+  ASSERT(tag == Dart_kSourceTag);
   const char* url_string = NULL;
   Dart_Handle result = Dart_StringToCString(url, &url_string);
   if (Dart_IsError(result)) {
     return result;
   }
-  if (tag == Dart_kImportTag) {
-    // Embedder handles all requests for external libraries.
-    if (embedder_provided_handler_ == NULL) {
-      return Dart_NewApiError("Unable to import module as no library tag "
-                              "handler has been provided by embedder");
-    }
-    return embedder_provided_handler_(tag, library, url);
-  }
-  ASSERT((tag == Dart_kSourceTag) || (tag == Dart_kCanonicalizeUrl));
-  if (tag == Dart_kCanonicalizeUrl) {
-    // url is already canonicalized.
-    return url;
-  }
   Dart_Handle source = GetSource(url_string);
   if (Dart_IsError(source)) {
     return source;
@@ -594,6 +623,193 @@
 }
 
 
+void Service::MaybeInjectVMServiceLibrary(Isolate* isolate) {
+  ASSERT(isolate != NULL);
+  ASSERT(isolate->name() != NULL);
+  if (!Service::IsServiceIsolateName(isolate->name())) {
+    // Not service isolate.
+    return;
+  }
+  if (HasServiceIsolate()) {
+    // Service isolate already exists.
+    return;
+  }
+  SetServiceIsolate(isolate);
+
+  StackZone zone(isolate);
+  HANDLESCOPE(isolate);
+
+  // Register dart:vmservice library.
+  const String& url_str = String::Handle(Symbols::DartVMService().raw());
+  const Library& library = Library::Handle(Library::New(url_str));
+  library.Register();
+  library.set_native_entry_resolver(VmServiceNativeResolver);
+
+  // Temporarily install our library tag handler.
+  isolate->set_library_tag_handler(LibraryTagHandler);
+
+  // Get script source.
+  const char* resource = NULL;
+  const char* path = "/vmservice.dart";
+  intptr_t r = Resources::ResourceLookup(path, &resource);
+  ASSERT(r != Resources::kNoSuchInstance);
+  ASSERT(resource != NULL);
+  const String& source_str = String::Handle(
+      String::FromUTF8(reinterpret_cast<const uint8_t*>(resource), r));
+  ASSERT(!source_str.IsNull());
+  const Script& script = Script::Handle(
+    isolate, Script::New(url_str, source_str, RawScript::kLibraryTag));
+
+  // Compile script.
+  Dart_EnterScope();  // Need to enter scope for tag handler.
+  library.SetLoadInProgress();
+  const Error& error = Error::Handle(isolate,
+                                     Compiler::Compile(library, script));
+  ASSERT(error.IsNull());
+  Dart_Handle result = Dart_FinalizeLoading(false);
+  ASSERT(!Dart_IsError(result));
+  Dart_ExitScope();
+
+  // Uninstall our library tag handler.
+  isolate->set_library_tag_handler(NULL);
+}
+
+
+void Service::FinishedInitializing() {
+  MonitorLocker ml(monitor_);
+  initializing_ = false;
+  ml.NotifyAll();
+}
+
+
+static void ShutdownIsolate(uword parameter) {
+  Isolate* isolate = reinterpret_cast<Isolate*>(parameter);
+  ASSERT(Service::IsServiceIsolate(isolate));
+  {
+    // Print the error if there is one.  This may execute dart code to
+    // print the exception object, so we need to use a StartIsolateScope.
+    StartIsolateScope start_scope(isolate);
+    StackZone zone(isolate);
+    HandleScope handle_scope(isolate);
+    Error& error = Error::Handle();
+    error = isolate->object_store()->sticky_error();
+    if (!error.IsNull()) {
+      OS::PrintErr("vm-service: Error: %s\n", error.ToErrorCString());
+    }
+    Dart::RunShutdownCallback();
+  }
+  {
+    // Shut the isolate down.
+    SwitchIsolateScope switch_scope(isolate);
+    Dart::ShutdownIsolate();
+  }
+  Service::SetServiceIsolate(NULL);
+  Service::SetServicePort(ILLEGAL_PORT);
+  if (FLAG_trace_service) {
+    OS::Print("vm-service: Shutdown.\n");
+  }
+}
+
+
+class RunServiceTask : public ThreadPool::Task {
+ public:
+  virtual void Run() {
+    ASSERT(Isolate::Current() == NULL);
+    char* error = NULL;
+    Isolate* isolate = NULL;
+
+    Dart_IsolateCreateCallback create_callback = Service::create_callback();
+    // TODO(johnmccutchan): Support starting up service isolate without embedder
+    // provided isolate creation callback.
+    if (create_callback == NULL) {
+      Service::FinishedInitializing();
+      return;
+    }
+
+    isolate =
+        reinterpret_cast<Isolate*>(create_callback(Service::kIsolateName,
+                                                   NULL,
+                                                   NULL,
+                                                   NULL,
+                                                   &error));
+    if (isolate == NULL) {
+      OS::PrintErr("vm-service: Isolate creation error: %s\n", error);
+      Service::FinishedInitializing();
+      return;
+    }
+
+    Isolate::SetCurrent(NULL);
+
+    RunMain(isolate);
+
+    Service::FinishedInitializing();
+
+    isolate->message_handler()->Run(Dart::thread_pool(),
+                                    NULL,
+                                    ShutdownIsolate,
+                                    reinterpret_cast<uword>(isolate));
+  }
+
+ protected:
+  void RunMain(Isolate* isolate) {
+    StartIsolateScope iso_scope(isolate);
+    StackZone zone(isolate);
+    HANDLESCOPE(isolate);
+    // Invoke main which will return the loadScriptPort.
+    const Library& root_library =
+        Library::Handle(isolate, isolate->object_store()->root_library());
+    if (root_library.IsNull()) {
+      if (FLAG_trace_service) {
+        OS::Print("vm-service: Embedder did not install a script.");
+      }
+      // Service isolate is not supported by embedder.
+      return;
+    }
+    ASSERT(!root_library.IsNull());
+    const String& entry_name = String::Handle(isolate, String::New("main"));
+    ASSERT(!entry_name.IsNull());
+    const Function& entry =
+        Function::Handle(isolate,
+                         root_library.LookupFunctionAllowPrivate(entry_name));
+    if (entry.IsNull()) {
+      // Service isolate is not supported by embedder.
+      if (FLAG_trace_service) {
+        OS::Print("vm-service: Embedder did not provide a main function.");
+      }
+      return;
+    }
+    ASSERT(!entry.IsNull());
+    const Object& result =
+        Object::Handle(isolate,
+                       DartEntry::InvokeFunction(entry,
+                                                 Object::empty_array()));
+    ASSERT(!result.IsNull());
+    if (result.IsError()) {
+      // Service isolate did not initialize properly.
+      if (FLAG_trace_service) {
+        const Error& error = Error::Cast(result);
+        OS::Print("vm-service: Calling main resulted in an error: %s",
+                  error.ToErrorCString());
+      }
+      return;
+    }
+    ASSERT(result.IsReceivePort());
+    const ReceivePort& rp = ReceivePort::Cast(result);
+    Service::SetLoadPort(rp.Id());
+  }
+};
+
+
+void Service::RunService() {
+  ASSERT(monitor_ == NULL);
+  monitor_ = new Monitor();
+  ASSERT(monitor_ != NULL);
+  // Grab the isolate create callback here to avoid race conditions with tests
+  // that change this after Dart_Initialize returns.
+  create_callback_ = Isolate::CreateCallback();
+  Dart::thread_pool()->Run(new RunServiceTask());
+}
+
 // A handler for a per-isolate request.
 //
 // If a handler returns true, the reply is complete and ready to be
@@ -608,6 +824,7 @@
 };
 
 static IsolateMessageHandler FindIsolateMessageHandler(const char* command);
+static IsolateMessageHandler FindIsolateMessageHandlerNew(const char* command);
 
 
 // A handler for a root (vm-global) request.
@@ -624,6 +841,7 @@
 };
 
 static RootMessageHandler FindRootMessageHandler(const char* command);
+static RootMessageHandler FindRootMessageHandlerNew(const char* command);
 
 
 static void PrintArgumentsAndOptions(const JSONObject& obj, JSONStream* js) {
@@ -666,7 +884,6 @@
 
   JSONObject jsobj(js);
   jsobj.AddProperty("type", "Error");
-  jsobj.AddProperty("id", "");
   jsobj.AddProperty("message", buffer);
   PrintArgumentsAndOptions(jsobj, js);
 }
@@ -697,6 +914,65 @@
 }
 
 
+void Service::HandleIsolateMessageNew(Isolate* isolate, const Array& msg) {
+  ASSERT(isolate != NULL);
+  ASSERT(!msg.IsNull());
+
+  {
+    StackZone zone(isolate);
+    HANDLESCOPE(isolate);
+
+    Instance& reply_port = Instance::Handle(isolate);
+    String& method = String::Handle(isolate);
+    Array& param_keys = Array::Handle(isolate);
+    Array& param_values = Array::Handle(isolate);
+    reply_port ^= msg.At(1);
+    method ^= msg.At(2);
+    param_keys ^= msg.At(3);
+    param_values ^= msg.At(4);
+
+    ASSERT(!method.IsNull());
+    ASSERT(!param_keys.IsNull());
+    ASSERT(!param_values.IsNull());
+    ASSERT(param_keys.Length() == param_values.Length());
+
+    if (!reply_port.IsSendPort()) {
+      FATAL("SendPort expected.");
+    }
+
+    IsolateMessageHandler handler =
+        FindIsolateMessageHandlerNew(method.ToCString());
+    {
+      JSONStream js;
+      js.SetupNew(zone.GetZone(), SendPort::Cast(reply_port).Id(),
+                  method, param_keys, param_values);
+      if (handler == NULL) {
+        // Check for an embedder handler.
+        EmbedderServiceHandler* e_handler =
+            FindIsolateEmbedderHandler(method.ToCString());
+        if (e_handler != NULL) {
+          EmbedderHandleMessage(e_handler, &js);
+        } else {
+          if (FindRootMessageHandlerNew(method.ToCString()) != NULL) {
+            PrintError(&js, "%s expects no 'isolate' parameter\n",
+                       method.ToCString());
+          } else {
+            PrintError(&js, "Unrecognized method: %s", method.ToCString());
+          }
+        }
+        js.PostReply();
+      } else {
+        if (handler(isolate, &js)) {
+          // Handler returns true if the reply is ready to be posted.
+          // TODO(johnmccutchan): Support asynchronous replies.
+          js.PostReply();
+        }
+      }
+    }
+  }
+}
+
+
 void Service::HandleIsolateMessage(Isolate* isolate, const Array& msg) {
   ASSERT(isolate != NULL);
   ASSERT(!msg.IsNull());
@@ -708,6 +984,12 @@
     // Message is a list with five entries.
     ASSERT(msg.Length() == 5);
 
+    Object& tmp = Object::Handle(isolate);
+    tmp = msg.At(2);
+    if (tmp.IsString()) {
+      return Service::HandleIsolateMessageNew(isolate, msg);
+    }
+
     Instance& reply_port = Instance::Handle(isolate);
     GrowableObjectArray& path = GrowableObjectArray::Handle(isolate);
     Array& option_keys = Array::Handle(isolate);
@@ -770,16 +1052,11 @@
 }
 
 
-static bool HandleStackTrace(Isolate* isolate, JSONStream* js) {
-  if (js->num_arguments() > 1) {
-    PrintError(js, "Command too long");
-    return true;
-  }
+static bool HandleIsolateGetStack(Isolate* isolate, JSONStream* js) {
   DebuggerStackTrace* stack = isolate->debugger()->StackTrace();
   JSONObject jsobj(js);
-  jsobj.AddProperty("type", "StackTrace");
-  jsobj.AddProperty("id", "stacktrace");
-  JSONArray jsarr(&jsobj, "members");
+  jsobj.AddProperty("type", "Stack");
+  JSONArray jsarr(&jsobj, "frames");
   intptr_t num_frames = stack->Length();
   for (intptr_t i = 0; i < num_frames; i++) {
     ActivationFrame* frame = stack->FrameAt(i);
@@ -794,20 +1071,24 @@
 
 
 static bool HandleCommonEcho(JSONObject* jsobj, JSONStream* js) {
-  jsobj->AddProperty("type", "message");
-  PrintArgumentsAndOptions(*jsobj, js);
+  jsobj->AddProperty("type", "_EchoResponse");
+  if (js->HasOption("text")) {
+    jsobj->AddProperty("text", js->LookupOption("text"));
+  }
   return true;
 }
 
 
-void Service::SendEchoEvent(Isolate* isolate) {
+void Service::SendEchoEvent(Isolate* isolate, const char* text) {
   JSONStream js;
   {
     JSONObject jsobj(&js);
     jsobj.AddProperty("type", "ServiceEvent");
-    jsobj.AddPropertyF("id", "_echoEvent");
     jsobj.AddProperty("eventType", "_Echo");
     jsobj.AddProperty("isolate", isolate);
+    if (text != NULL) {
+      jsobj.AddProperty("text", text);
+    }
   }
   const String& message = String::Handle(String::New(js.ToCString()));
   uint8_t data[] = {0, 128, 255};
@@ -816,12 +1097,15 @@
 }
 
 
+static bool HandleIsolateTriggerEchoEvent(Isolate* isolate, JSONStream* js) {
+  Service::SendEchoEvent(isolate, js->LookupOption("text"));
+  JSONObject jsobj(js);
+  return HandleCommonEcho(&jsobj, js);
+}
+
+
 static bool HandleIsolateEcho(Isolate* isolate, JSONStream* js) {
   JSONObject jsobj(js);
-  jsobj.AddProperty("id", "_echo");
-  if (js->num_arguments() == 2 && strcmp(js->GetArgument(1), "event") == 0) {
-    Service::SendEchoEvent(isolate);
-  }
   return HandleCommonEcho(&jsobj, js);
 }
 
@@ -979,16 +1263,382 @@
 }
 
 
-static bool HandleInboundReferences(Isolate* isolate,
-                                    Object* target,
-                                    intptr_t limit,
-                                    JSONStream* js) {
+static RawObject* LookupObjectId(Isolate* isolate,
+                                 const char* arg,
+                                 ObjectIdRing::LookupResult* kind) {
+  *kind = ObjectIdRing::kValid;
+  if (strncmp(arg, "int-", 4) == 0) {
+    arg += 4;
+    int64_t value = 0;
+    if (!OS::StringToInt64(arg, &value) ||
+        !Smi::IsValid(value)) {
+      *kind = ObjectIdRing::kInvalid;
+      return Object::null();
+    }
+    const Integer& obj =
+        Integer::Handle(isolate, Smi::New(static_cast<intptr_t>(value)));
+    return obj.raw();
+  } else if (strcmp(arg, "bool-true") == 0) {
+    return Bool::True().raw();
+  } else if (strcmp(arg, "bool-false") == 0) {
+    return Bool::False().raw();
+  } else if (strcmp(arg, "null") == 0) {
+    return Object::null();
+  } else if (strcmp(arg, "not-initialized") == 0) {
+    return Object::sentinel().raw();
+  } else if (strcmp(arg, "being-initialized") == 0) {
+    return Object::transition_sentinel().raw();
+  }
+
+  ObjectIdRing* ring = isolate->object_id_ring();
+  ASSERT(ring != NULL);
+  intptr_t id = -1;
+  if (!GetIntegerId(arg, &id)) {
+    *kind = ObjectIdRing::kInvalid;
+    return Object::null();
+  }
+  return ring->GetObjectForId(id, kind);
+}
+
+
+static RawObject* LookupHeapObjectLibraries(Isolate* isolate,
+                                            char** parts, int num_parts) {
+  // Library ids look like "libraries/35"
+  if (num_parts < 2) {
+    return Object::sentinel().raw();
+  }
+  const GrowableObjectArray& libs =
+      GrowableObjectArray::Handle(isolate->object_store()->libraries());
+  ASSERT(!libs.IsNull());
+  intptr_t id = 0;
+  if (!GetIntegerId(parts[1], &id)) {
+    return Object::sentinel().raw();
+  }
+  if ((id < 0) || (id >= libs.Length())) {
+    return Object::sentinel().raw();
+  }
+  Library& lib = Library::Handle();
+  lib ^= libs.At(id);
+  ASSERT(!lib.IsNull());
+  if (num_parts == 2) {
+    return lib.raw();
+  }
+  if (strcmp(parts[2], "scripts") == 0) {
+    // Script ids look like "libraries/35/scripts/library%2Furl.dart"
+    if (num_parts != 4) {
+      return Object::sentinel().raw();
+    }
+    const String& id = String::Handle(String::New(parts[3]));
+    ASSERT(!id.IsNull());
+    // The id is the url of the script % encoded, decode it.
+    const String& requested_url = String::Handle(String::DecodeIRI(id));
+    Script& script = Script::Handle();
+    String& script_url = String::Handle();
+    const Array& loaded_scripts = Array::Handle(lib.LoadedScripts());
+    ASSERT(!loaded_scripts.IsNull());
+    intptr_t i;
+    for (i = 0; i < loaded_scripts.Length(); i++) {
+      script ^= loaded_scripts.At(i);
+      ASSERT(!script.IsNull());
+      script_url ^= script.url();
+      if (script_url.Equals(requested_url)) {
+        return script.raw();
+      }
+    }
+  }
+
+  // Not found.
+  return Object::sentinel().raw();
+}
+
+static RawObject* LookupHeapObjectClasses(Isolate* isolate,
+                                          char** parts, int num_parts) {
+  // Class ids look like: "classes/17"
+  if (num_parts < 2) {
+    return Object::sentinel().raw();
+  }
+  ClassTable* table = isolate->class_table();
+  intptr_t id;
+  if (!GetIntegerId(parts[1], &id) ||
+      !table->IsValidIndex(id)) {
+    return Object::sentinel().raw();
+  }
+  Class& cls = Class::Handle(table->At(id));
+  if (num_parts == 2) {
+    return cls.raw();
+  }
+  if (strcmp(parts[2], "closures") == 0) {
+    // Closure ids look like: "classes/17/closures/11"
+    if (num_parts != 4) {
+      return Object::sentinel().raw();
+    }
+    intptr_t id;
+    if (!GetIntegerId(parts[3], &id)) {
+      return Object::sentinel().raw();
+    }
+    Function& func = Function::Handle();
+    func ^= cls.ClosureFunctionFromIndex(id);
+    if (func.IsNull()) {
+      return Object::sentinel().raw();
+    }
+    return func.raw();
+
+  } else if (strcmp(parts[2], "fields") == 0) {
+    // Field ids look like: "classes/17/fields/11"
+    if (num_parts != 4) {
+      return Object::sentinel().raw();
+    }
+    intptr_t id;
+    if (!GetIntegerId(parts[3], &id)) {
+      return Object::sentinel().raw();
+    }
+    Field& field = Field::Handle(cls.FieldFromIndex(id));
+    if (field.IsNull()) {
+      return Object::sentinel().raw();
+    }
+    return field.raw();
+
+  } else if (strcmp(parts[2], "functions") == 0) {
+    // Function ids look like: "classes/17/functions/11"
+    if (num_parts != 4) {
+      return Object::sentinel().raw();
+    }
+    const char* encoded_id = parts[3];
+    String& id = String::Handle(isolate, String::New(encoded_id));
+    id = String::DecodeIRI(id);
+    if (id.IsNull()) {
+      return Object::sentinel().raw();
+    }
+    Function& func = Function::Handle(cls.LookupFunction(id));
+    if (func.IsNull()) {
+      return Object::sentinel().raw();
+    }
+    return func.raw();
+
+  } else if (strcmp(parts[2], "implicit_closures") == 0) {
+    // Function ids look like: "classes/17/implicit_closures/11"
+    if (num_parts != 4) {
+      return Object::sentinel().raw();
+    }
+    intptr_t id;
+    if (!GetIntegerId(parts[3], &id)) {
+      return Object::sentinel().raw();
+    }
+    Function& func = Function::Handle();
+    func ^= cls.ImplicitClosureFunctionFromIndex(id);
+    if (func.IsNull()) {
+      return Object::sentinel().raw();
+    }
+    return func.raw();
+
+  } else if (strcmp(parts[2], "dispatchers") == 0) {
+    // Dispatcher Function ids look like: "classes/17/dispatchers/11"
+    if (num_parts != 4) {
+      return Object::sentinel().raw();
+    }
+    intptr_t id;
+    if (!GetIntegerId(parts[3], &id)) {
+      return Object::sentinel().raw();
+    }
+    Function& func = Function::Handle();
+    func ^= cls.InvocationDispatcherFunctionFromIndex(id);
+    if (func.IsNull()) {
+      return Object::sentinel().raw();
+    }
+    return func.raw();
+
+  } else if (strcmp(parts[2], "types") == 0) {
+    // Type ids look like: "classes/17/types/11"
+    if (num_parts != 4) {
+      return Object::sentinel().raw();
+    }
+    intptr_t id;
+    if (!GetIntegerId(parts[3], &id)) {
+      return Object::sentinel().raw();
+    }
+    Type& type = Type::Handle();
+    type ^= cls.CanonicalTypeFromIndex(id);
+    if (type.IsNull()) {
+      return Object::sentinel().raw();
+    }
+    return type.raw();
+  }
+
+  // Not found.
+  return Object::sentinel().raw();
+}
+
+
+static RawObject* LookupHeapObjectTypeArguments(Isolate* isolate,
+                                          char** parts, int num_parts) {
+  // TypeArguments ids look like: "typearguments/17"
+  if (num_parts < 2) {
+    return Object::sentinel().raw();
+  }
+  intptr_t id;
+  if (!GetIntegerId(parts[1], &id)) {
+    return Object::sentinel().raw();
+  }
+  ObjectStore* object_store = isolate->object_store();
+  const Array& table = Array::Handle(object_store->canonical_type_arguments());
+  ASSERT(table.Length() > 0);
+  const intptr_t table_size = table.Length() - 1;
+  if ((id < 0) || (id >= table_size) || (table.At(id) == Object::null())) {
+    return Object::sentinel().raw();
+  }
+  return table.At(id);
+}
+
+
+static RawObject* LookupHeapObjectCode(Isolate* isolate,
+                                       char** parts, int num_parts) {
+  if (num_parts != 2) {
+    return Object::sentinel().raw();
+  }
+  uword pc;
+  static const char* kCollectedPrefix = "collected-";
+  static intptr_t kCollectedPrefixLen = strlen(kCollectedPrefix);
+  static const char* kNativePrefix = "native-";
+  static intptr_t kNativePrefixLen = strlen(kNativePrefix);
+  static const char* kReusedPrefix = "reused-";
+  static intptr_t kReusedPrefixLen = strlen(kReusedPrefix);
+  const char* id = parts[1];
+  if (strncmp(kCollectedPrefix, id, kCollectedPrefixLen) == 0) {
+    if (!GetUnsignedIntegerId(&id[kCollectedPrefixLen], &pc, 16)) {
+      return Object::sentinel().raw();
+    }
+    // TODO(turnidge): Return "collected" instead.
+    return Object::null();
+  }
+  if (strncmp(kNativePrefix, id, kNativePrefixLen) == 0) {
+    if (!GetUnsignedIntegerId(&id[kNativePrefixLen], &pc, 16)) {
+      return Object::sentinel().raw();
+    }
+    // TODO(johnmccutchan): Support native Code.
+    return Object::null();
+  }
+  if (strncmp(kReusedPrefix, id, kReusedPrefixLen) == 0) {
+    if (!GetUnsignedIntegerId(&id[kReusedPrefixLen], &pc, 16)) {
+      return Object::sentinel().raw();
+    }
+    // TODO(turnidge): Return "expired" instead.
+    return Object::null();
+  }
+  int64_t timestamp = 0;
+  if (!GetCodeId(id, &timestamp, &pc) || (timestamp < 0)) {
+    return Object::sentinel().raw();
+  }
+  Code& code = Code::Handle(Code::FindCode(pc, timestamp));
+  if (!code.IsNull()) {
+    return code.raw();
+  }
+
+  // Not found.
+  return Object::sentinel().raw();
+}
+
+
+static RawObject* LookupHeapObject(Isolate* isolate,
+                                   const char* id_original,
+                                   ObjectIdRing::LookupResult* result) {
+  char* id = isolate->current_zone()->MakeCopyOfString(id_original);
+
+  // Parse the id by splitting at each '/'.
+  const int MAX_PARTS = 8;
+  char* parts[MAX_PARTS];
+  int num_parts = 0;
+  int i = 0;
+  int start_pos = 0;
+  while (id[i] != '\0') {
+    if (id[i] == '/') {
+      id[i++] = '\0';
+      parts[num_parts++] = &id[start_pos];
+      if (num_parts == MAX_PARTS) {
+        break;
+      }
+      start_pos = i;
+    } else {
+      i++;
+    }
+  }
+  if (num_parts < MAX_PARTS) {
+    parts[num_parts++] = &id[start_pos];
+  }
+
+  if (result != NULL) {
+    *result = ObjectIdRing::kValid;
+  }
+
+  if (strcmp(parts[0], "objects") == 0) {
+    // Object ids look like "objects/1123"
+    Object& obj = Object::Handle(isolate);
+    ObjectIdRing::LookupResult lookup_result;
+    obj = LookupObjectId(isolate, parts[1], &lookup_result);
+    if (lookup_result != ObjectIdRing::kValid) {
+      if (result != NULL) {
+        *result = lookup_result;
+      }
+      return Object::sentinel().raw();
+    }
+    return obj.raw();
+
+  } else if (strcmp(parts[0], "libraries") == 0) {
+    return LookupHeapObjectLibraries(isolate, parts, num_parts);
+  } else if (strcmp(parts[0], "classes") == 0) {
+    return LookupHeapObjectClasses(isolate, parts, num_parts);
+  } else if (strcmp(parts[0], "typearguments") == 0) {
+    return LookupHeapObjectTypeArguments(isolate, parts, num_parts);
+  } else if (strcmp(parts[0], "code") == 0) {
+    return LookupHeapObjectCode(isolate, parts, num_parts);
+  }
+
+  // Not found.
+  return Object::sentinel().raw();
+}
+
+
+static void PrintSentinel(JSONStream* js,
+                          const char* id,
+                          const char* preview) {
+  JSONObject jsobj(js);
+  jsobj.AddProperty("type", "Sentinel");
+  jsobj.AddProperty("id", id);
+  jsobj.AddProperty("valueAsString", preview);
+}
+
+
+static SourceBreakpoint* LookupBreakpoint(Isolate* isolate, const char* id) {
+  size_t end_pos = strcspn(id, "/");
+  const char* rest = NULL;
+  if (end_pos < strlen(id)) {
+    rest = id + end_pos + 1;  // +1 for '/'.
+  }
+  if (strncmp("breakpoints", id, end_pos) == 0) {
+    if (rest == NULL) {
+      return NULL;
+    }
+    intptr_t bpt_id = 0;
+    SourceBreakpoint* bpt = NULL;
+    if (GetIntegerId(rest, &bpt_id)) {
+      bpt = isolate->debugger()->GetBreakpointById(bpt_id);
+    }
+    return bpt;
+  }
+  return NULL;
+}
+
+
+
+
+static bool PrintInboundReferences(Isolate* isolate,
+                                   Object* target,
+                                   intptr_t limit,
+                                   JSONStream* js) {
   ObjectGraph graph(isolate);
   Array& path = Array::Handle(Array::New(limit * 2));
   intptr_t length = graph.InboundReferences(target, path);
   JSONObject jsobj(js);
   jsobj.AddProperty("type", "InboundReferences");
-  jsobj.AddProperty("id", "inbound_references");
   {
     JSONArray elements(&jsobj, "references");
     Object& source = Object::Handle();
@@ -1028,16 +1678,61 @@
 }
 
 
-static bool HandleRetainingPath(Isolate* isolate,
-                                Object* obj,
-                                intptr_t limit,
-                                JSONStream* js) {
+static bool HandleIsolateGetInboundReferences(Isolate* isolate,
+                                              JSONStream* js) {
+  const char* target_id = js->LookupOption("targetId");
+  if (target_id == NULL) {
+    PrintError(js, "Missing 'targetId' option");
+    return true;
+  }
+  const char* limit_cstr = js->LookupOption("limit");
+  if (target_id == NULL) {
+    PrintError(js, "Missing 'limit' option");
+    return true;
+  }
+  intptr_t limit;
+  if (!GetIntegerId(js->LookupOption("limit"), &limit)) {
+    PrintError(js, "Invalid 'limit' option: %s", limit_cstr);
+    return true;
+  }
+
+  Object& obj = Object::Handle(isolate);
+  ObjectIdRing::LookupResult lookup_result;
+  {
+    HANDLESCOPE(isolate);
+    obj = LookupHeapObject(isolate, target_id, &lookup_result);
+  }
+  if (obj.raw() == Object::sentinel().raw()) {
+    if (lookup_result == ObjectIdRing::kCollected) {
+      PrintErrorWithKind(
+          js, "InboundReferencesCollected",
+          "attempt to find a retaining path for a collected object\n",
+          js->num_arguments());
+      return true;
+    } else if (lookup_result == ObjectIdRing::kExpired) {
+      PrintErrorWithKind(
+          js, "InboundReferencesExpired",
+          "attempt to find a retaining path for an expired object\n",
+          js->num_arguments());
+      return true;
+    }
+    PrintError(js, "Invalid 'targetId' value: no object with id '%s'",
+               target_id);
+    return true;
+  }
+  return PrintInboundReferences(isolate, &obj, limit, js);
+}
+
+
+static bool PrintRetainingPath(Isolate* isolate,
+                               Object* obj,
+                               intptr_t limit,
+                               JSONStream* js) {
   ObjectGraph graph(isolate);
   Array& path = Array::Handle(Array::New(limit * 2));
   intptr_t length = graph.RetainingPath(obj, path);
   JSONObject jsobj(js);
   jsobj.AddProperty("type", "RetainingPath");
-  jsobj.AddProperty("id", "retaining_path");
   jsobj.AddProperty("length", length);
   JSONArray elements(&jsobj, "elements");
   Object& element = Object::Handle();
@@ -1075,7 +1770,7 @@
   }
 
   // We nil out the array after generating the response to prevent
-  // reporting suprious references when looking for inbound references
+  // reporting spurious references when looking for inbound references
   // after looking for a retaining path.
   for (intptr_t i = 0; i < limit; ++i) {
     path.SetAt(i * 2, Object::null_object());
@@ -1084,122 +1779,97 @@
   return true;
 }
 
+static bool HandleIsolateGetRetainingPath(Isolate* isolate,
+                                          JSONStream* js) {
+  const char* target_id = js->LookupOption("targetId");
+  if (target_id == NULL) {
+    PrintError(js, "Missing 'targetId' option");
+    return true;
+  }
+  const char* limit_cstr = js->LookupOption("limit");
+  if (target_id == NULL) {
+    PrintError(js, "Missing 'limit' option");
+    return true;
+  }
+  intptr_t limit;
+  if (!GetIntegerId(js->LookupOption("limit"), &limit)) {
+    PrintError(js, "Invalid 'limit' option: %s", limit_cstr);
+    return true;
+  }
 
-// Takes an Object* only because RetainingPath temporarily clears it.
-static bool HandleInstanceCommands(Isolate* isolate,
-                                   Object* obj,
-                                   ObjectIdRing::LookupResult kind,
-                                   JSONStream* js,
-                                   intptr_t arg_pos) {
-  ASSERT(js->num_arguments() > arg_pos);
-  ASSERT(kind != ObjectIdRing::kInvalid);
-  const char* action = js->GetArgument(arg_pos);
-  if (strcmp(action, "eval") == 0) {
-    if (js->num_arguments() > (arg_pos + 1)) {
-      PrintError(js, "expected at most %" Pd " arguments but found %" Pd "\n",
-                 arg_pos + 1,
-                 js->num_arguments());
-      return true;
-    }
-    if (kind == ObjectIdRing::kCollected) {
-      PrintErrorWithKind(js, "EvalCollected",
-                         "attempt to evaluate against collected object\n",
-                         js->num_arguments());
-      return true;
-    }
-    if (kind == ObjectIdRing::kExpired) {
-      PrintErrorWithKind(js, "EvalExpired",
-                         "attempt to evaluate against expired object\n",
-                         js->num_arguments());
-      return true;
-    }
-    if (ContainsNonInstance(*obj)) {
-      PrintError(js, "attempt to evaluate against internal VM object\n");
-      return true;
-    }
-    const char* expr = js->LookupOption("expr");
-    if (expr == NULL) {
-      PrintError(js, "eval expects an 'expr' option\n",
-                 js->num_arguments());
-      return true;
-    }
-    const String& expr_str = String::Handle(isolate, String::New(expr));
-    ASSERT(obj->IsInstance() || obj->IsNull());
-    Instance& instance = Instance::Handle();
-    instance ^= obj->raw();
-    const Object& result =
-        Object::Handle(instance.Evaluate(expr_str,
-                                         Array::empty_array(),
-                                         Array::empty_array()));
-    result.PrintJSON(js, true);
-    return true;
-  } else if (strcmp(action, "retained") == 0) {
-    if (kind == ObjectIdRing::kCollected) {
-      PrintErrorWithKind(
-          js, "RetainedCollected",
-          "attempt to calculate size retained by a collected object\n",
-          js->num_arguments());
-      return true;
-    }
-    if (kind == ObjectIdRing::kExpired) {
-      PrintErrorWithKind(
-          js, "RetainedExpired",
-          "attempt to calculate size retained by an expired object\n",
-          js->num_arguments());
-      return true;
-    }
-    ObjectGraph graph(isolate);
-    intptr_t retained_size = graph.SizeRetainedByInstance(*obj);
-    const Object& result = Object::Handle(Integer::New(retained_size));
-    result.PrintJSON(js, true);
-    return true;
-  } else if (strcmp(action, "retaining_path") == 0) {
-    if (kind == ObjectIdRing::kCollected) {
+  Object& obj = Object::Handle(isolate);
+  ObjectIdRing::LookupResult lookup_result;
+  {
+    HANDLESCOPE(isolate);
+    obj = LookupHeapObject(isolate, target_id, &lookup_result);
+  }
+  if (obj.raw() == Object::sentinel().raw()) {
+    if (lookup_result == ObjectIdRing::kCollected) {
       PrintErrorWithKind(
           js, "RetainingPathCollected",
           "attempt to find a retaining path for a collected object\n",
           js->num_arguments());
       return true;
-    }
-    if (kind == ObjectIdRing::kExpired) {
+    } else if (lookup_result == ObjectIdRing::kExpired) {
       PrintErrorWithKind(
           js, "RetainingPathExpired",
           "attempt to find a retaining path for an expired object\n",
           js->num_arguments());
       return true;
     }
-    intptr_t limit;
-    if (!GetIntegerId(js->LookupOption("limit"), &limit)) {
-      PrintError(js, "retaining_path expects a 'limit' option\n",
-                 js->num_arguments());
-      return true;
-    }
-    return HandleRetainingPath(isolate, obj, limit, js);
-  } else if (strcmp(action, "inbound_references") == 0) {
-    if (kind == ObjectIdRing::kCollected) {
-      PrintErrorWithKind(
-          js, "InboundReferencesCollected",
-          "attempt to find inbound references for a collected object\n",
-          js->num_arguments());
-      return true;
-    }
-    if (kind == ObjectIdRing::kExpired) {
-      PrintErrorWithKind(
-          js, "InboundReferencesExpired",
-          "attempt to find inbound references for an expired object\n",
-          js->num_arguments());
-      return true;
-    }
-    intptr_t limit;
-    if (!GetIntegerId(js->LookupOption("limit"), &limit)) {
-      PrintError(js, "inbound_references expects a 'limit' option\n",
-                 js->num_arguments());
-      return true;
-    }
-    return HandleInboundReferences(isolate, obj, limit, js);
+    PrintError(js, "Invalid 'targetId' value: no object with id '%s'",
+               target_id);
+    return true;
   }
+  return PrintRetainingPath(isolate, &obj, limit, js);
+}
 
-  PrintError(js, "unrecognized action '%s'\n", action);
+
+static bool HandleIsolateGetRetainedSize(Isolate* isolate, JSONStream* js) {
+  const char* target_id = js->LookupOption("targetId");
+  if (target_id == NULL) {
+    PrintError(js, "Missing 'targetId' option");
+    return true;
+  }
+  ObjectIdRing::LookupResult lookup_result;
+  Object& obj = Object::Handle(LookupHeapObject(isolate, target_id,
+                                                &lookup_result));
+  if (obj.raw() == Object::sentinel().raw()) {
+    if (lookup_result == ObjectIdRing::kCollected) {
+      PrintErrorWithKind(
+          js, "RetainedCollected",
+          "attempt to calculate size retained by a collected object\n",
+          js->num_arguments());
+      return true;
+    } else if (lookup_result == ObjectIdRing::kExpired) {
+      PrintErrorWithKind(
+          js, "RetainedExpired",
+          "attempt to calculate size retained by an expired object\n",
+          js->num_arguments());
+      return true;
+    }
+    PrintError(js, "Invalid 'targetId' value: no object with id '%s'",
+               target_id);
+    return true;
+  }
+  if (obj.IsClass()) {
+    const Class& cls = Class::Cast(obj);
+    ObjectGraph graph(isolate);
+    intptr_t retained_size = graph.SizeRetainedByClass(cls.id());
+    const Object& result = Object::Handle(Integer::New(retained_size));
+    result.PrintJSON(js, true);
+    return true;
+  }
+  if (obj.IsInstance() || obj.IsNull()) {
+    // We don't use Instance::Cast here because it doesn't allow null.
+    ObjectGraph graph(isolate);
+    intptr_t retained_size = graph.SizeRetainedByInstance(obj);
+    const Object& result = Object::Handle(Integer::New(retained_size));
+    result.PrintJSON(js, true);
+    return true;
+  }
+  PrintError(js, "Invalid 'targetId' value: id '%s' does not correspond to a "
+             "library, class, or instance", target_id);
   return true;
 }
 
@@ -1226,23 +1896,62 @@
 }
 
 
-static bool HandleClassesEval(Isolate* isolate, const Class& cls,
-                              JSONStream* js) {
-  if (js->num_arguments() > 3) {
-    PrintError(js, "Command too long");
+static bool HandleIsolateEval(Isolate* isolate, JSONStream* js) {
+  const char* target_id = js->LookupOption("targetId");
+  if (target_id == NULL) {
+    PrintError(js, "Missing 'targetId' option");
     return true;
   }
-  const char* expr = js->LookupOption("expr");
+  const char* expr = js->LookupOption("expression");
   if (expr == NULL) {
-    PrintError(js, "eval expects an 'expr' option\n",
-               js->num_arguments());
+    PrintError(js, "Missing 'expression' option");
     return true;
   }
   const String& expr_str = String::Handle(isolate, String::New(expr));
-  const Object& result = Object::Handle(cls.Evaluate(expr_str,
-                                                     Array::empty_array(),
-                                                     Array::empty_array()));
-  result.PrintJSON(js, true);
+  ObjectIdRing::LookupResult lookup_result;
+  Object& obj = Object::Handle(LookupHeapObject(isolate, target_id,
+                                                &lookup_result));
+  if (obj.raw() == Object::sentinel().raw()) {
+    if (lookup_result == ObjectIdRing::kCollected) {
+      PrintSentinel(js, "objects/collected", "<collected>");
+    } else if (lookup_result == ObjectIdRing::kExpired) {
+      PrintSentinel(js, "objects/expired", "<expired>");
+    } else {
+      PrintError(js, "Invalid 'targetId' value: no object with id '%s'",
+                 target_id);
+    }
+    return true;
+  }
+  if (obj.IsLibrary()) {
+    const Library& lib = Library::Cast(obj);
+    const Object& result = Object::Handle(lib.Evaluate(expr_str,
+                                                       Array::empty_array(),
+                                                       Array::empty_array()));
+    result.PrintJSON(js, true);
+    return true;
+  }
+  if (obj.IsClass()) {
+    const Class& cls = Class::Cast(obj);
+    const Object& result = Object::Handle(cls.Evaluate(expr_str,
+                                                       Array::empty_array(),
+                                                       Array::empty_array()));
+    result.PrintJSON(js, true);
+    return true;
+  }
+  if ((obj.IsInstance() || obj.IsNull()) &&
+      !ContainsNonInstance(obj)) {
+    // We don't use Instance::Cast here because it doesn't allow null.
+    Instance& instance = Instance::Handle(isolate);
+    instance ^= obj.raw();
+    const Object& result =
+        Object::Handle(instance.Evaluate(expr_str,
+                                         Array::empty_array(),
+                                         Array::empty_array()));
+    result.PrintJSON(js, true);
+    return true;
+  }
+  PrintError(js, "Invalid 'targetId' value: id '%s' does not correspond to a "
+             "library, class, or instance", target_id);
   return true;
 }
 
@@ -1269,14 +1978,6 @@
 }
 
 
-static bool HandleClassesFunctionsCoverage(
-    Isolate* isolate, const Function& func, JSONStream* js) {
-  FunctionCoverageFilter filter(func);
-  CodeCoverage::PrintJSON(isolate, js, &filter);
-  return true;
-}
-
-
 static bool HandleFunctionSetSource(
     Isolate* isolate, const Class& cls, const Function& func, JSONStream* js) {
   if (js->LookupOption("source") == NULL) {
@@ -1330,9 +2031,7 @@
     return true;
   } else {
     const char* subcommand = js->GetArgument(4);
-    if (strcmp(subcommand, "coverage") == 0) {
-      return HandleClassesFunctionsCoverage(isolate, func, js);
-    } else if (strcmp(subcommand, "set_source") == 0) {
+    if (strcmp(subcommand, "set_source") == 0) {
       return HandleFunctionSetSource(isolate, cls, func, js);
     } else {
       PrintError(js, "Invalid sub command %s", subcommand);
@@ -1401,7 +2100,11 @@
     }
     return true;
   }
-  ASSERT(js->num_arguments() >= 4);
+  if (js->num_arguments() > 4) {
+    PrintError(js, "Command too long");
+    return true;
+  }
+  ASSERT(js->num_arguments() == 4);
   intptr_t id;
   if (!GetIntegerId(js->GetArgument(3), &id)) {
     PrintError(js, "Must specify collection object id: types/id");
@@ -1413,24 +2116,7 @@
     PrintError(js, "Canonical type %" Pd " not found", id);
     return true;
   }
-  if (js->num_arguments() == 4) {
-    type.PrintJSON(js, false);
-    return true;
-  }
-  return HandleInstanceCommands(isolate, &type, ObjectIdRing::kValid, js, 4);
-}
-
-
-static bool HandleClassesRetained(Isolate* isolate, const Class& cls,
-                                  JSONStream* js) {
-  if (js->num_arguments() != 3) {
-    PrintError(js, "Command too long");
-    return true;
-  }
-  ObjectGraph graph(isolate);
-  intptr_t retained_size = graph.SizeRetainedByClass(cls.id());
-  const Object& result = Object::Handle(Integer::New(retained_size));
-  result.PrintJSON(js, true);
+  type.PrintJSON(js, false);
   return true;
 }
 
@@ -1467,18 +2153,30 @@
 };
 
 
-static bool HandleClassesInstances(Isolate* isolate, const Class& cls,
-                                   JSONStream* js) {
-  if (js->num_arguments() != 3) {
-    PrintError(js, "Command too long");
+static bool HandleIsolateGetInstances(Isolate* isolate, JSONStream* js) {
+  const char* target_id = js->LookupOption("classId");
+  if (target_id == NULL) {
+    PrintError(js, "Missing 'classId' option");
+    return true;
+  }
+  const char* limit_cstr = js->LookupOption("limit");
+  if (target_id == NULL) {
+    PrintError(js, "Missing 'limit' option");
     return true;
   }
   intptr_t limit;
   if (!GetIntegerId(js->LookupOption("limit"), &limit)) {
-    PrintError(js, "instances expects a 'limit' option\n",
-               js->num_arguments());
+    PrintError(js, "Invalid 'limit' option: %s", limit_cstr);
     return true;
   }
+  const Object& obj =
+      Object::Handle(LookupHeapObject(isolate, target_id, NULL));
+  if (obj.raw() == Object::sentinel().raw() ||
+      !obj.IsClass()) {
+    PrintError(js, "Invalid 'classId' value: no class with id '%s'", target_id);
+    return true;
+  }
+  const Class& cls = Class::Cast(obj);
   Array& storage = Array::Handle(Array::New(limit));
   GetInstancesVisitor visitor(cls, storage);
   ObjectGraph graph(isolate);
@@ -1501,20 +2199,9 @@
 }
 
 
-static bool HandleClassesCoverage(Isolate* isolate,
-                                  const Class& cls,
-                                  JSONStream* stream) {
-  ClassCoverageFilter cf(cls);
-  CodeCoverage::PrintJSON(isolate, stream, &cf);
-  return true;
-}
-
-
 static bool HandleClasses(Isolate* isolate, JSONStream* js) {
   if (js->num_arguments() == 1) {
-    ClassTable* table = isolate->class_table();
-    JSONObject jsobj(js);
-    table->PrintToJSONObject(&jsobj);
+    PrintError(js, "Invalid number of arguments.");
     return true;
   }
   ASSERT(js->num_arguments() >= 2);
@@ -1534,9 +2221,7 @@
     return true;
   } else if (js->num_arguments() >= 3) {
     const char* second = js->GetArgument(2);
-    if (strcmp(second, "eval") == 0) {
-      return HandleClassesEval(isolate, cls, js);
-    } else if (strcmp(second, "closures") == 0) {
+    if (strcmp(second, "closures") == 0) {
       return HandleClassesClosures(isolate, cls, js);
     } else if (strcmp(second, "fields") == 0) {
       return HandleClassesFields(isolate, cls, js);
@@ -1548,12 +2233,6 @@
       return HandleClassesDispatchers(isolate, cls, js);
     } else if (strcmp(second, "types") == 0) {
       return HandleClassesTypes(isolate, cls, js);
-    } else if (strcmp(second, "retained") == 0) {
-      return HandleClassesRetained(isolate, cls, js);
-    } else if (strcmp(second, "instances") == 0) {
-      return HandleClassesInstances(isolate, cls, js);
-    } else if (strcmp(second, "coverage") == 0) {
-      return HandleClassesCoverage(isolate, cls, js);
     } else {
       PrintError(js, "Invalid sub collection %s", second);
       return true;
@@ -1564,37 +2243,45 @@
 }
 
 
-static bool HandleLibrariesEval(Isolate* isolate, const Library& lib,
-                                JSONStream* js) {
-  if (js->num_arguments() > 3) {
-    PrintError(js, "Command too long");
+static bool HandleIsolateGetCoverage(Isolate* isolate, JSONStream* js) {
+  if (!js->HasOption("targetId")) {
+    CodeCoverage::PrintJSON(isolate, js, NULL);
     return true;
   }
-  const char* expr = js->LookupOption("expr");
-  if (expr == NULL) {
-    PrintError(js, "eval expects an 'expr' option\n",
-               js->num_arguments());
+  const char* target_id = js->LookupOption("targetId");
+  Object& obj = Object::Handle(LookupHeapObject(isolate, target_id, NULL));
+  if (obj.raw() == Object::sentinel().raw()) {
+    PrintError(js, "Invalid 'targetId' value: no object with id '%s'",
+               target_id);
     return true;
   }
-  const String& expr_str = String::Handle(isolate, String::New(expr));
-  const Object& result = Object::Handle(lib.Evaluate(expr_str,
-                                                     Array::empty_array(),
-                                                     Array::empty_array()));
-  result.PrintJSON(js, true);
+  if (obj.IsScript()) {
+    ScriptCoverageFilter sf(Script::Cast(obj));
+    CodeCoverage::PrintJSON(isolate, js, &sf);
+    return true;
+  }
+  if (obj.IsLibrary()) {
+    LibraryCoverageFilter lf(Library::Cast(obj));
+    CodeCoverage::PrintJSON(isolate, js, &lf);
+    return true;
+  }
+  if (obj.IsClass()) {
+    ClassCoverageFilter cf(Class::Cast(obj));
+    CodeCoverage::PrintJSON(isolate, js, &cf);
+    return true;
+  }
+  if (obj.IsFunction()) {
+    FunctionCoverageFilter ff(Function::Cast(obj));
+    CodeCoverage::PrintJSON(isolate, js, &ff);
+    return true;
+  }
+  PrintError(js, "Invalid 'targetId' value: id '%s' does not correspond to a "
+             "script, library, class, or function", target_id);
   return true;
 }
 
 
-static bool HandleLibrariesScriptsCoverage(
-    Isolate* isolate, const Script& script, JSONStream* js) {
-  ScriptCoverageFilter sf(script);
-  CodeCoverage::PrintJSON(isolate, js, &sf);
-  return true;
-}
-
-
-static bool HandleLibrariesScriptsSetBreakpoint(
-    Isolate* isolate, const Script& script, JSONStream* js) {
+static bool HandleIsolateAddBreakpoint(Isolate* isolate, JSONStream* js) {
   if (!js->HasOption("line")) {
     PrintError(js, "Missing 'line' option");
     return true;
@@ -1602,9 +2289,16 @@
   const char* line_option = js->LookupOption("line");
   intptr_t line = -1;
   if (!GetIntegerId(line_option, &line)) {
-    PrintError(js, "Invalid 'line' value: %s", line_option);
+    PrintError(js, "Invalid 'line' value: %s is not an integer", line_option);
     return true;
   }
+  const char* script_id = js->LookupOption("script");
+  Object& obj = Object::Handle(LookupHeapObject(isolate, script_id, NULL));
+  if (obj.raw() == Object::sentinel().raw() || !obj.IsScript()) {
+    PrintError(js, "Invalid 'script' value: no script with id '%s'", script_id);
+    return true;
+  }
+  const Script& script = Script::Cast(obj);
   const String& script_url = String::Handle(script.url());
   SourceBreakpoint* bpt =
       isolate->debugger()->SetBreakpointAtLine(script_url, line);
@@ -1617,6 +2311,30 @@
 }
 
 
+static bool HandleIsolateRemoveBreakpoint(Isolate* isolate, JSONStream* js) {
+  if (!js->HasOption("breakpointId")) {
+    PrintError(js, "Missing 'breakpointId' option");
+    return true;
+  }
+  const char* bpt_id = js->LookupOption("breakpointId");
+  SourceBreakpoint* bpt = LookupBreakpoint(isolate, bpt_id);
+  if (bpt == NULL) {
+    fprintf(stderr, "ERROR1");
+    PrintError(js, "Invalid 'breakpointId' value: no breakpoint with id '%s'",
+               bpt_id);
+    return true;
+  }
+  isolate->debugger()->RemoveBreakpoint(bpt->id());
+
+    fprintf(stderr, "SUCCESS");
+  // TODO(turnidge): Consider whether the 'Success' type is proper.
+  JSONObject jsobj(js);
+  jsobj.AddProperty("type", "Success");
+  jsobj.AddProperty("id", "");
+  return true;
+}
+
+
 static bool HandleLibrariesScripts(Isolate* isolate,
                                    const Library& lib,
                                    JSONStream* js) {
@@ -1648,30 +2366,11 @@
     PrintError(js, "Script %s not found", requested_url.ToCString());
     return true;
   }
-  if (js->num_arguments() == 4) {
-    script.PrintJSON(js, false);
+  if (js->num_arguments() > 4) {
+    PrintError(js, "Command too long");
     return true;
-  } else {
-    const char* subcollection = js->GetArgument(4);
-    if (strcmp(subcollection, "coverage") == 0) {
-      return HandleLibrariesScriptsCoverage(isolate, script, js);
-    } else if (strcmp(subcollection, "setBreakpoint") == 0) {
-      return HandleLibrariesScriptsSetBreakpoint(isolate, script, js);
-    } else {
-      PrintError(js, "Invalid sub collection %s", subcollection);
-      return true;
-    }
   }
-  UNREACHABLE();
-  return true;
-}
-
-
-static bool HandleLibrariesCoverage(Isolate* isolate,
-                                    const Library& lib,
-                                    JSONStream* js) {
-  LibraryCoverageFilter lf(lib);
-  CodeCoverage::PrintJSON(isolate, js, &lf);
+  script.PrintJSON(js, false);
   return true;
 }
 
@@ -1693,12 +2392,8 @@
     return true;
   } else if (js->num_arguments() >= 3) {
     const char* second = js->GetArgument(2);
-    if (strcmp(second, "eval") == 0) {
-      return HandleLibrariesEval(isolate, lib, js);
-    } else if (strcmp(second, "scripts") == 0) {
+    if (strcmp(second, "scripts") == 0) {
       return HandleLibrariesScripts(isolate, lib, js);
-    } else if (strcmp(second, "coverage") == 0) {
-      return HandleLibrariesCoverage(isolate, lib, js);
     } else {
       PrintError(js, "Invalid sub collection %s", second);
       return true;
@@ -1709,54 +2404,6 @@
 }
 
 
-static void PrintSentinel(JSONStream* js,
-                          const char* id,
-                          const char* preview) {
-  JSONObject jsobj(js);
-  jsobj.AddProperty("type", "Sentinel");
-  jsobj.AddProperty("id", id);
-  jsobj.AddProperty("valueAsString", preview);
-}
-
-
-static RawObject* LookupObjectId(Isolate* isolate,
-                                 const char* arg,
-                                 ObjectIdRing::LookupResult* kind) {
-  *kind = ObjectIdRing::kValid;
-  if (strncmp(arg, "int-", 4) == 0) {
-    arg += 4;
-    int64_t value = 0;
-    if (!OS::StringToInt64(arg, &value) ||
-        !Smi::IsValid(value)) {
-      *kind = ObjectIdRing::kInvalid;
-      return Object::null();
-    }
-    const Integer& obj =
-        Integer::Handle(isolate, Smi::New(static_cast<intptr_t>(value)));
-    return obj.raw();
-  } else if (strcmp(arg, "bool-true") == 0) {
-    return Bool::True().raw();
-  } else if (strcmp(arg, "bool-false") == 0) {
-    return Bool::False().raw();
-  } else if (strcmp(arg, "null") == 0) {
-    return Object::null();
-  } else if (strcmp(arg, "not-initialized") == 0) {
-    return Object::sentinel().raw();
-  } else if (strcmp(arg, "being-initialized") == 0) {
-    return Object::transition_sentinel().raw();
-  }
-
-  ObjectIdRing* ring = isolate->object_id_ring();
-  ASSERT(ring != NULL);
-  intptr_t id = -1;
-  if (!GetIntegerId(arg, &id)) {
-    *kind = ObjectIdRing::kInvalid;
-    return Object::null();
-  }
-  return ring->GetObjectForId(id, kind);
-}
-
-
 static RawClass* GetMetricsClass(Isolate* isolate) {
   const Library& prof_lib =
       Library::Handle(isolate, Library::ProfilerLibrary());
@@ -1771,15 +2418,14 @@
 }
 
 
-static bool HandleIsolateMetricsList(Isolate* isolate, JSONStream* js) {
+static bool HandleNativeMetricsList(Isolate* isolate, JSONStream* js) {
   JSONObject obj(js);
   obj.AddProperty("type", "MetricList");
-  obj.AddProperty("id", "metrics/vm");
   {
-    JSONArray members(&obj, "members");
+    JSONArray metrics(&obj, "metrics");
     Metric* current = isolate->metrics_list_head();
     while (current != NULL) {
-      members.AddValue(current);
+      metrics.AddValue(current);
       current = current->next();
     }
   }
@@ -1787,7 +2433,7 @@
 }
 
 
-static bool HandleIsolateMetric(Isolate* isolate,
+static bool HandleNativeMetric(Isolate* isolate,
                                 JSONStream* js,
                                 const char* id) {
   Metric* current = isolate->metrics_list_head();
@@ -1800,12 +2446,12 @@
     }
     current = current->next();
   }
-  PrintError(js, "Metric %s not found\n", id);
+  PrintError(js, "Native Metric %s not found\n", id);
   return true;
 }
 
 
-static bool HandleMetricsList(Isolate* isolate, JSONStream* js) {
+static bool HandleDartMetricsList(Isolate* isolate, JSONStream* js) {
   const Class& metrics_cls = Class::Handle(isolate, GetMetricsClass(isolate));
   const String& print_metrics_name =
       String::Handle(String::New("_printMetrics"));
@@ -1825,7 +2471,7 @@
 }
 
 
-static bool HandleMetric(Isolate* isolate, JSONStream* js, const char* id) {
+static bool HandleDartMetric(Isolate* isolate, JSONStream* js, const char* id) {
   const Class& metrics_cls = Class::Handle(isolate, GetMetricsClass(isolate));
   const String& print_metric_name =
       String::Handle(String::New("_printMetric"));
@@ -1847,39 +2493,77 @@
     buffer->AddString(String::Cast(result).ToCString());
     return true;
   }
-  PrintError(js, "Metric %s not found\n", id);
+  PrintError(js, "Dart Metric %s not found\n", id);
   return true;
 }
 
 
-static bool HandleMetrics(Isolate* isolate, JSONStream* js) {
-  if (js->num_arguments() == 1) {
-    return HandleMetricsList(isolate, js);
-  }
-  ASSERT(js->num_arguments() > 1);
-  const char* arg = js->GetArgument(1);
-  if (strcmp(arg, "vm") == 0) {
-    if (js->num_arguments() == 2) {
-      return HandleIsolateMetricsList(isolate, js);
+static bool HandleIsolateGetMetricList(Isolate* isolate, JSONStream* js) {
+  bool native_metrics = false;
+  if (js->HasOption("type")) {
+    if (js->OptionIs("type", "Native")) {
+      native_metrics = true;
+    } else if (js->OptionIs("type", "Dart")) {
+      native_metrics = false;
     } else {
-      if (js->num_arguments() > 3) {
-        PrintError(js, "Command too long");
-        return true;
-      }
-      return HandleIsolateMetric(isolate, js, js->GetArgument(2));
+      PrintError(js, "Invalid 'type' option value: %s\n",
+                 js->LookupOption("type"));
+      return true;
     }
-  }
-  if (js->num_arguments() > 2) {
-    PrintError(js, "Command too long");
+  } else {
+    PrintError(js, "Expected 'type' option.");
     return true;
   }
-  return HandleMetric(isolate, js, arg);
+  if (native_metrics) {
+    return HandleNativeMetricsList(isolate, js);
+  }
+  return HandleDartMetricsList(isolate, js);
+}
+
+
+static bool HandleIsolateGetMetric(Isolate* isolate, JSONStream* js) {
+  const char* metric_id = js->LookupOption("metricId");
+  if (metric_id == NULL) {
+    PrintError(js, "Expected 'metricId' option.");
+    return true;
+  }
+  // Verify id begins with "metrics/".
+  static const char* kMetricIdPrefix = "metrics/";
+  static intptr_t kMetricIdPrefixLen = strlen(kMetricIdPrefix);
+  if (strncmp(metric_id, kMetricIdPrefix, kMetricIdPrefixLen) != 0) {
+    PrintError(js, "Metric %s not found\n", metric_id);
+  }
+  // Check if id begins with "metrics/native/".
+  static const char* kNativeMetricIdPrefix = "metrics/native/";
+  static intptr_t kNativeMetricIdPrefixLen = strlen(kNativeMetricIdPrefix);
+  const bool native_metric =
+      strncmp(metric_id, kNativeMetricIdPrefix, kNativeMetricIdPrefixLen) == 0;
+  if (native_metric) {
+    const char* id = metric_id + kNativeMetricIdPrefixLen;
+    return HandleNativeMetric(isolate, js, id);
+  }
+  const char* id = metric_id + kMetricIdPrefixLen;
+  return HandleDartMetric(isolate, js, id);
+}
+
+
+static bool HandleVMGetMetricList(JSONStream* js) {
+  return false;
+}
+
+
+static bool HandleVMGetMetric(JSONStream* js) {
+  const char* metric_id = js->LookupOption("metricId");
+  if (metric_id == NULL) {
+    PrintError(js, "Expected 'metricId' option.");
+  }
+  return false;
 }
 
 
 static bool HandleObjects(Isolate* isolate, JSONStream* js) {
   REQUIRE_COLLECTION_ID("objects");
-  if (js->num_arguments() < 2) {
+  if (js->num_arguments() != 2) {
     PrintError(js, "expected at least 2 arguments but found %" Pd "\n",
                js->num_arguments());
     return true;
@@ -1923,21 +2607,19 @@
     PrintError(js, "unrecognized object id '%s'", arg);
     return true;
   }
-  if (js->num_arguments() == 2) {
-    // Print.
-    if (kind == ObjectIdRing::kCollected) {
-      // The object has been collected by the gc.
-      PrintSentinel(js, "objects/collected", "<collected>");
-      return true;
-    } else if (kind == ObjectIdRing::kExpired) {
-      // The object id has expired.
-      PrintSentinel(js, "objects/expired", "<expired>");
-      return true;
-    }
-    obj.PrintJSON(js, false);
+
+  // Print.
+  if (kind == ObjectIdRing::kCollected) {
+    // The object has been collected by the gc.
+    PrintSentinel(js, "objects/collected", "<collected>");
+    return true;
+  } else if (kind == ObjectIdRing::kExpired) {
+    // The object id has expired.
+    PrintSentinel(js, "objects/expired", "<expired>");
     return true;
   }
-  return HandleInstanceCommands(isolate, &obj, kind, js, 2);
+  obj.PrintJSON(js, false);
+  return true;
 }
 
 
@@ -1977,9 +2659,8 @@
 }
 
 
-static bool HandleDebugResume(Isolate* isolate,
-                              const char* step_option,
-                              JSONStream* js) {
+static bool HandleIsolateResume(Isolate* isolate, JSONStream* js) {
+  const char* step_option = js->LookupOption("step");
   if (isolate->message_handler()->paused_on_start()) {
     isolate->message_handler()->set_pause_on_start(false);
     JSONObject jsobj(js);
@@ -2019,78 +2700,22 @@
 }
 
 
-static bool HandleDebug(Isolate* isolate, JSONStream* js) {
-  if (js->num_arguments() == 1) {
-    PrintError(js, "Must specify a subcommand");
-    return true;
-  }
-  const char* command = js->GetArgument(1);
-  if (strcmp(command, "breakpoints") == 0) {
-    if (js->num_arguments() == 2) {
-      // Print breakpoint list.
-      JSONObject jsobj(js);
-      jsobj.AddProperty("type", "BreakpointList");
-      jsobj.AddProperty("id", "debug/breakpoints");
-      JSONArray jsarr(&jsobj, "breakpoints");
-      isolate->debugger()->PrintBreakpointsToJSONArray(&jsarr);
-      return true;
-    } else {
-      intptr_t id = 0;
-      SourceBreakpoint* bpt = NULL;
-      if (GetIntegerId(js->GetArgument(2), &id)) {
-        bpt = isolate->debugger()->GetBreakpointById(id);
-      }
-      if (bpt == NULL) {
-        PrintError(js, "Unrecognized breakpoint id: %s", js->GetArgument(2));
-        return true;
-      }
-      if (js->num_arguments() == 3) {
-        // Print individual breakpoint.
-        bpt->PrintJSON(js);
-        return true;
-      } else if (js->num_arguments() == 4) {
-        const char* sub_command = js->GetArgument(3);
-        if (strcmp(sub_command, "clear") == 0) {
-          // Clear this breakpoint.
-          isolate->debugger()->RemoveBreakpoint(id);
+static bool HandleIsolateGetBreakpoints(Isolate* isolate, JSONStream* js) {
+  JSONObject jsobj(js);
+  jsobj.AddProperty("type", "BreakpointList");
+  JSONArray jsarr(&jsobj, "breakpoints");
+  isolate->debugger()->PrintBreakpointsToJSONArray(&jsarr);
+  return true;
+}
 
-          JSONObject jsobj(js);
-          jsobj.AddProperty("type", "Success");
-          jsobj.AddProperty("id", "");
-          return true;
-        } else {
-          PrintError(js, "Unrecognized subcommand: %s", sub_command);
-          return true;
-        }
-      } else {
-        PrintError(js, "Command too long");
-        return true;
-      }
-    }
-  } else if (strcmp(command, "pause") == 0) {
-    if (js->num_arguments() == 2) {
-      // TODO(turnidge): Don't double-interrupt the isolate here.
-      isolate->ScheduleInterrupts(Isolate::kApiInterrupt);
-      JSONObject jsobj(js);
-      jsobj.AddProperty("type", "Success");
-      jsobj.AddProperty("id", "");
-      return true;
-    } else {
-      PrintError(js, "Command too long");
-      return true;
-    }
-  } else if (strcmp(command, "resume") == 0) {
-    if (js->num_arguments() == 2) {
-      const char* step_option = js->LookupOption("step");
-      return HandleDebugResume(isolate, step_option, js);
-    } else {
-      PrintError(js, "Command too long");
-      return true;
-    }
-  } else {
-    PrintError(js, "Unrecognized subcommand '%s'", js->GetArgument(1));
-    return true;
-  }
+
+static bool HandleIsolatePause(Isolate* isolate, JSONStream* js) {
+  // TODO(turnidge): Don't double-interrupt the isolate here.
+  isolate->ScheduleInterrupts(Isolate::kApiInterrupt);
+  JSONObject jsobj(js);
+  jsobj.AddProperty("type", "Success");
+  jsobj.AddProperty("id", "");
+  return true;
 }
 
 
@@ -2157,37 +2782,30 @@
 }
 
 
-static bool HandleProfile(Isolate* isolate, JSONStream* js) {
-  if (js->num_arguments() == 2) {
-    const char* sub_command = js->GetArgument(1);
-    if (!strcmp(sub_command, "tag")) {
-      {
-        JSONObject miniProfile(js);
-        miniProfile.AddProperty("type", "TagProfile");
-        miniProfile.AddProperty("id", "profile/tag");
-        isolate->vm_tag_counters()->PrintToJSONObject(&miniProfile);
-      }
-      return true;
-    } else {
-      PrintError(js, "Unrecognized subcommand '%s'", sub_command);
-      return true;
-    }
-  }
+static bool HandleIsolateGetTagProfile(Isolate* isolate, JSONStream* js) {
+  JSONObject miniProfile(js);
+  miniProfile.AddProperty("type", "TagProfile");
+  miniProfile.AddProperty("id", "profile/tag");
+  isolate->vm_tag_counters()->PrintToJSONObject(&miniProfile);
+  return true;
+}
+
+static bool HandleIsolateGetCpuProfile(Isolate* isolate, JSONStream* js) {
   // A full profile includes disassembly of all Dart code objects.
   // TODO(johnmccutchan): Add sub command to trigger full code dump.
   bool full_profile = false;
   const char* tags_option = js->LookupOption("tags");
   Profiler::TagOrder tag_order = Profiler::kUserVM;
   if (js->HasOption("tags")) {
-    if (js->OptionIs("tags", "hide")) {
+    if (js->OptionIs("tags", "None")) {
       tag_order = Profiler::kNoTags;
-    } else if (js->OptionIs("tags", "uv")) {
+    } else if (js->OptionIs("tags", "UserVM")) {
       tag_order = Profiler::kUserVM;
-    } else if (js->OptionIs("tags", "u")) {
+    } else if (js->OptionIs("tags", "UserOnly")) {
       tag_order = Profiler::kUser;
-    } else if (js->OptionIs("tags", "vu")) {
+    } else if (js->OptionIs("tags", "VMUser")) {
       tag_order = Profiler::kVMUser;
-    } else if (js->OptionIs("tags", "v")) {
+    } else if (js->OptionIs("tags", "VMOnly")) {
       tag_order = Profiler::kVM;
     } else {
       PrintError(js, "Invalid tags option value: %s\n", tags_option);
@@ -2198,19 +2816,11 @@
   return true;
 }
 
-static bool HandleCoverage(Isolate* isolate, JSONStream* js) {
-  CodeCoverage::PrintJSON(isolate, js, NULL);
-  return true;
-}
 
-
-static bool HandleAllocationProfile(Isolate* isolate, JSONStream* js) {
+static bool HandleIsolateGetAllocationProfile(Isolate* isolate,
+                                              JSONStream* js) {
   bool should_reset_accumulator = false;
   bool should_collect = false;
-  if (js->num_arguments() != 1) {
-    PrintError(js, "Command too long");
-    return true;
-  }
   if (js->HasOption("reset")) {
     if (js->OptionIs("reset", "true")) {
       should_reset_accumulator = true;
@@ -2241,65 +2851,13 @@
 }
 
 
-static bool HandleTypeArguments(Isolate* isolate, JSONStream* js) {
-  ObjectStore* object_store = isolate->object_store();
-  const Array& table = Array::Handle(object_store->canonical_type_arguments());
-  ASSERT(table.Length() > 0);
-  TypeArguments& type_args = TypeArguments::Handle();
-  const intptr_t table_size = table.Length() - 1;
-  const intptr_t table_used = Smi::Value(Smi::RawCast(table.At(table_size)));
-  bool only_with_instantiations = false;
-  if (js->num_arguments() >= 2) {
-    const char* second = js->GetArgument(1);
-    if (strcmp(second, "withinstantiations") == 0) {
-      only_with_instantiations = true;
-      if (js->num_arguments() > 2) {
-        PrintError(js, "Command too long");
-        return true;
-      }
-    }
-  }
-  if ((js->num_arguments() == 1) || only_with_instantiations) {
-    JSONObject jsobj(js);
-    jsobj.AddProperty("type", "TypeArgumentsList");
-    jsobj.AddProperty("table_size", table_size);
-    jsobj.AddProperty("table_used", table_used);
-    JSONArray members(&jsobj, "members");
-    for (intptr_t i = 0; i < table_size; i++) {
-      type_args ^= table.At(i);
-      if (!type_args.IsNull()) {
-        if (!only_with_instantiations || type_args.HasInstantiations()) {
-          members.AddValue(type_args);
-        }
-      }
-    }
-    return true;
-  }
-  ASSERT((js->num_arguments() >= 2) && !only_with_instantiations);
-  intptr_t id;
-  if (!GetIntegerId(js->GetArgument(1), &id)) {
-    // Note that the table index of the canonical type arguments will change
-    // when the table grows. Should we not support this access at all?
-    PrintError(js, "Must specify collection object id: /typearguments/id");
-    return true;
-  }
-  if ((id < 0) || (id >= table_size) || (table.At(id) == Object::null())) {
-    PrintError(js, "%" Pd " is not a valid typearguments id.", id);
-    return true;
-  }
-  type_args ^= table.At(id);
-  type_args.PrintJSON(js, false);
-  return true;
-}
-
-
-static bool HandleHeapMap(Isolate* isolate, JSONStream* js) {
+static bool HandleIsolateGetHeapMap(Isolate* isolate, JSONStream* js) {
   isolate->heap()->PrintHeapMapToJSONStream(isolate, js);
   return true;
 }
 
 
-static bool HandleGraph(Isolate* isolate, JSONStream* js) {
+static bool HandleIsolateRequestHeapSnapshot(Isolate* isolate, JSONStream* js) {
   Service::SendGraphEvent(isolate);
   // TODO(koda): Provide some id that ties this request to async response(s).
   JSONObject jsobj(js);
@@ -2369,7 +2927,8 @@
 }
 
 
-static bool HandleMalformedJson(Isolate* isolate, JSONStream* js) {
+static bool HandleIsolateRespondWithMalformedJson(Isolate* isolate,
+                                                  JSONStream* js) {
   JSONObject jsobj(js);
   jsobj.AddProperty("a", "a");
   JSONObject jsobj1(js);
@@ -2382,7 +2941,8 @@
 }
 
 
-static bool HandleMalformedObject(Isolate* isolate, JSONStream* js) {
+static bool HandleIsolateRespondWithMalformedObject(Isolate* isolate,
+                                                    JSONStream* js) {
   JSONObject jsobj(js);
   jsobj.AddProperty("bart", "simpson");
   return true;
@@ -2390,25 +2950,13 @@
 
 
 static IsolateMessageHandlerEntry isolate_handlers[] = {
-  { "_malformedjson", HandleMalformedJson },
-  { "_malformedobject", HandleMalformedObject },
-  { "_echo", HandleIsolateEcho },
-  { "", HandleIsolate },
-  { "address", HandleAddress },
-  { "allocationprofile", HandleAllocationProfile },
-  { "classes", HandleClasses },
-  { "code", HandleCode },
-  { "coverage", HandleCoverage },
-  { "debug", HandleDebug },
-  { "graph", HandleGraph },
-  { "heapmap", HandleHeapMap },
-  { "libraries", HandleLibraries },
-  { "metrics", HandleMetrics },
-  { "objects", HandleObjects },
-  { "profile", HandleProfile },
-  { "scripts", HandleScripts },
-  { "stacktrace", HandleStackTrace },
-  { "typearguments", HandleTypeArguments },
+  { "", HandleIsolate },                          // getObject
+  { "address", HandleAddress },                   // to do
+  { "classes", HandleClasses },                   // getObject
+  { "code", HandleCode },                         // getObject
+  { "libraries", HandleLibraries },               // getObject
+  { "objects", HandleObjects },                   // getObject
+  { "scripts", HandleScripts },                   // getObject
 };
 
 
@@ -2422,12 +2970,194 @@
     }
   }
   if (FLAG_trace_service) {
+    OS::Print("vm-service: No isolate message handler for <%s>.\n", command);
+  }
+  return NULL;
+}
+
+
+static bool HandleIsolateGetObject(Isolate* isolate, JSONStream* js) {
+  const char* id = js->LookupOption("objectId");
+  if (id == NULL) {
+    // TODO(turnidge): Print the isolate here instead.
+    PrintError(js, "GetObject expects an 'objectId' parameter\n",
+               js->num_arguments());
+    return true;
+  }
+
+  // Handle heap objects.
+  ObjectIdRing::LookupResult lookup_result;
+  const Object& obj =
+      Object::Handle(LookupHeapObject(isolate, id, &lookup_result));
+  if (obj.raw() != Object::sentinel().raw()) {
+    // We found a heap object for this id.  Return it.
+    obj.PrintJSON(js, false);
+    return true;
+  } else if (lookup_result == ObjectIdRing::kCollected) {
+    PrintSentinel(js, "objects/collected", "<collected>");
+  } else if (lookup_result == ObjectIdRing::kExpired) {
+    PrintSentinel(js, "objects/expired", "<expired>");
+  }
+
+  // Handle non-heap objects.
+  SourceBreakpoint* bpt = LookupBreakpoint(isolate, id);
+  if (bpt != NULL) {
+    bpt->PrintJSON(js);
+    return true;
+  }
+
+  PrintError(js, "Unrecognized object id: %s\n", id);
+  return true;
+}
+
+
+static bool HandleIsolateGetClassList(Isolate* isolate, JSONStream* js) {
+  ClassTable* table = isolate->class_table();
+  JSONObject jsobj(js);
+  table->PrintToJSONObject(&jsobj);
+  return true;
+}
+
+
+static bool HandleIsolateGetTypeArgumentsList(Isolate* isolate,
+                                              JSONStream* js) {
+  bool only_with_instantiations = false;
+  if (js->OptionIs("onlyWithInstantiations", "true")) {
+    only_with_instantiations = true;
+  }
+  ObjectStore* object_store = isolate->object_store();
+  const Array& table = Array::Handle(object_store->canonical_type_arguments());
+  ASSERT(table.Length() > 0);
+  TypeArguments& type_args = TypeArguments::Handle();
+  const intptr_t table_size = table.Length() - 1;
+  const intptr_t table_used = Smi::Value(Smi::RawCast(table.At(table_size)));
+  JSONObject jsobj(js);
+  jsobj.AddProperty("type", "TypeArgumentsList");
+  jsobj.AddProperty("canonicalTypeArgumentsTableSize", table_size);
+  jsobj.AddProperty("canonicalTypeArgumentsTableUsed", table_used);
+  JSONArray members(&jsobj, "typeArguments");
+  for (intptr_t i = 0; i < table_size; i++) {
+    type_args ^= table.At(i);
+    if (!type_args.IsNull()) {
+      if (!only_with_instantiations || type_args.HasInstantiations()) {
+        members.AddValue(type_args);
+      }
+    }
+  }
+  return true;
+}
+
+
+static IsolateMessageHandlerEntry isolate_handlers_new[] = {
+  { "getIsolate", HandleIsolate },
+  { "getObject", HandleIsolateGetObject },
+  { "getBreakpoints", HandleIsolateGetBreakpoints },
+  { "pause", HandleIsolatePause },
+  { "resume", HandleIsolateResume },
+  { "getStack", HandleIsolateGetStack },
+  { "getCpuProfile", HandleIsolateGetCpuProfile },
+  { "getTagProfile", HandleIsolateGetTagProfile },
+  { "getAllocationProfile", HandleIsolateGetAllocationProfile },
+  { "getHeapMap", HandleIsolateGetHeapMap },
+  { "addBreakpoint", HandleIsolateAddBreakpoint },
+  { "removeBreakpoint", HandleIsolateRemoveBreakpoint },
+  { "getCoverage", HandleIsolateGetCoverage },
+  { "eval", HandleIsolateEval },
+  { "getRetainedSize", HandleIsolateGetRetainedSize },
+  { "getRetainingPath", HandleIsolateGetRetainingPath },
+  { "getInboundReferences", HandleIsolateGetInboundReferences },
+  { "getInstances", HandleIsolateGetInstances },
+  { "requestHeapSnapshot", HandleIsolateRequestHeapSnapshot },
+  { "getClassList", HandleIsolateGetClassList },
+  { "getTypeArgumentsList", HandleIsolateGetTypeArgumentsList },
+  { "getIsolateMetricList", HandleIsolateGetMetricList },
+  { "getIsolateMetric", HandleIsolateGetMetric },
+  { "_echo", HandleIsolateEcho },
+  { "_triggerEchoEvent", HandleIsolateTriggerEchoEvent },
+  { "_respondWithMalformedJson", HandleIsolateRespondWithMalformedJson },
+  { "_respondWithMalformedObject", HandleIsolateRespondWithMalformedObject },
+};
+
+
+static IsolateMessageHandler FindIsolateMessageHandlerNew(const char* command) {
+  intptr_t num_message_handlers = sizeof(isolate_handlers_new) /
+                                  sizeof(isolate_handlers_new[0]);
+  for (intptr_t i = 0; i < num_message_handlers; i++) {
+    const IsolateMessageHandlerEntry& entry = isolate_handlers_new[i];
+    if (strcmp(command, entry.command) == 0) {
+      return entry.handler;
+    }
+  }
+  if (FLAG_trace_service) {
     OS::Print("Service has no isolate message handler for <%s>\n", command);
   }
   return NULL;
 }
 
 
+void Service::HandleRootMessageNew(const Array& msg) {
+  Isolate* isolate = Isolate::Current();
+  ASSERT(!msg.IsNull());
+
+  {
+    StackZone zone(isolate);
+    HANDLESCOPE(isolate);
+
+    const Array& message = Array::Cast(msg);
+    // Message is a list with five entries.
+    ASSERT(message.Length() == 5);
+
+    Instance& reply_port = Instance::Handle(isolate);
+    String& method = String::Handle(isolate);
+    Array& param_keys = Array::Handle(isolate);
+    Array& param_values = Array::Handle(isolate);
+    reply_port ^= msg.At(1);
+    method ^= msg.At(2);
+    param_keys ^= msg.At(3);
+    param_values ^= msg.At(4);
+
+    ASSERT(!method.IsNull());
+    ASSERT(!param_keys.IsNull());
+    ASSERT(!param_values.IsNull());
+    ASSERT(param_keys.Length() == param_values.Length());
+
+    if (!reply_port.IsSendPort()) {
+      FATAL("SendPort expected.");
+    }
+
+    RootMessageHandler handler =
+        FindRootMessageHandlerNew(method.ToCString());
+    {
+      JSONStream js;
+      js.SetupNew(zone.GetZone(), SendPort::Cast(reply_port).Id(),
+                  method, param_keys, param_values);
+      if (handler == NULL) {
+        // Check for an embedder handler.
+        EmbedderServiceHandler* e_handler =
+            FindRootEmbedderHandler(method.ToCString());
+        if (e_handler != NULL) {
+          EmbedderHandleMessage(e_handler, &js);
+        } else {
+          if (FindIsolateMessageHandlerNew(method.ToCString()) != NULL) {
+            PrintError(&js, "%s expects an 'isolate' parameter\n",
+                       method.ToCString());
+          } else {
+            PrintError(&js, "Unrecognized method: %s", method.ToCString());
+          }
+        }
+        js.PostReply();
+      } else {
+        if (handler(&js)) {
+          // Handler returns true if the reply is ready to be posted.
+          // TODO(johnmccutchan): Support asynchronous replies.
+          js.PostReply();
+        }
+      }
+    }
+  }
+}
+
+
 void Service::HandleRootMessage(const Instance& msg) {
   Isolate* isolate = Isolate::Current();
   ASSERT(!msg.IsNull());
@@ -2441,6 +3171,12 @@
     // Message is a list with five entries.
     ASSERT(message.Length() == 5);
 
+    Object& tmp = Object::Handle(isolate);
+    tmp = message.At(2);
+    if (tmp.IsString()) {
+      return Service::HandleRootMessageNew(message);
+    }
+
     Instance& reply_port = Instance::Handle(isolate);
     GrowableObjectArray& path = GrowableObjectArray::Handle(isolate);
     Array& option_keys = Array::Handle(isolate);
@@ -2502,7 +3238,6 @@
 
 static bool HandleRootEcho(JSONStream* js) {
   JSONObject jsobj(js);
-  jsobj.AddProperty("id", "_echo");
   return HandleCommonEcho(&jsobj, js);
 }
 
@@ -2527,6 +3262,7 @@
 
 
 static bool HandleVM(JSONStream* js) {
+  Isolate* isolate = Isolate::Current();
   JSONObject jsobj(js);
   jsobj.AddProperty("type", "VM");
   jsobj.AddProperty("id", "vm");
@@ -2539,8 +3275,8 @@
   // pids > 53-bits (when consumed by JavaScript).
   // TODO(johnmccutchan): Codify how integers are sent across the service.
   jsobj.AddPropertyF("pid", "%" Pd "", OS::ProcessId());
-  jsobj.AddProperty("assertsEnabled", FLAG_enable_asserts);
-  jsobj.AddProperty("typeChecksEnabled", FLAG_enable_type_checks);
+  jsobj.AddProperty("assertsEnabled", isolate->AssertsEnabled());
+  jsobj.AddProperty("typeChecksEnabled", isolate->TypeChecksEnabled());
   int64_t start_time_micros = Dart::vm_isolate()->start_time();
   int64_t uptime_micros = (OS::GetCurrentTimeMicros() - start_time_micros);
   double seconds = (static_cast<double>(uptime_micros) /
@@ -2593,9 +3329,7 @@
   }
 }
 
-
 static RootMessageHandlerEntry root_handlers[] = {
-  { "_echo", HandleRootEcho },
   { "vm", HandleVM },
   { "flags", HandleFlags },
 };
@@ -2611,7 +3345,31 @@
     }
   }
   if (FLAG_trace_service) {
-    OS::Print("Service has no root message handler for <%s>\n", command);
+    OS::Print("vm-service: No root message handler for <%s>.\n", command);
+  }
+  return NULL;
+}
+
+
+static RootMessageHandlerEntry root_handlers_new[] = {
+  { "getVM", HandleVM },
+  { "getVMMetricList", HandleVMGetMetricList },
+  { "getVMMetric", HandleVMGetMetric },
+  { "_echo", HandleRootEcho },
+};
+
+
+static RootMessageHandler FindRootMessageHandlerNew(const char* command) {
+  intptr_t num_message_handlers = sizeof(root_handlers_new) /
+                                  sizeof(root_handlers_new[0]);
+  for (intptr_t i = 0; i < num_message_handlers; i++) {
+    const RootMessageHandlerEntry& entry = root_handlers_new[i];
+    if (strcmp(command, entry.command) == 0) {
+      return entry.handler;
+    }
+  }
+  if (FLAG_trace_service) {
+    OS::Print("vm-service: No root message handler for <%s>.\n", command);
   }
   return NULL;
 }
@@ -2637,11 +3395,12 @@
   writer.WriteMessage(list);
   intptr_t len = writer.BytesWritten();
   if (FLAG_trace_service) {
-    OS::Print("Pushing event of type %" Pd ", len %" Pd "\n", eventId, len);
+    OS::Print("vm-service: Pushing event of type %" Pd ", len %" Pd "\n",
+              eventId, len);
   }
   // TODO(turnidge): For now we ignore failure to send an event.  Revisit?
   PortMap::PostMessage(
-      new Message(port_, data, len, Message::kNormalPriority));
+      new Message(service_port_, data, len, Message::kNormalPriority));
 }
 
 
diff --git a/runtime/vm/service.h b/runtime/vm/service.h
index a7f8d1e..2816173 100644
--- a/runtime/vm/service.h
+++ b/runtime/vm/service.h
@@ -8,6 +8,7 @@
 #include "include/dart_api.h"
 
 #include "vm/allocation.h"
+#include "vm/os_thread.h"
 
 namespace dart {
 
@@ -24,23 +25,30 @@
 
 class Service : public AllStatic {
  public:
+  static const char* kIsolateName;
+  static bool IsServiceIsolateName(const char* name);
+
   // Handles a message which is not directed to an isolate.
+  static void HandleRootMessageNew(const Array& message);
   static void HandleRootMessage(const Instance& message);
 
   // Handles a message which is directed to a particular isolate.
+  static void HandleIsolateMessageNew(Isolate* isolate, const Array& message);
   static void HandleIsolateMessage(Isolate* isolate, const Array& message);
 
   static Isolate* GetServiceIsolate(void* callback_data);
   static bool SendIsolateStartupMessage();
   static bool SendIsolateShutdownMessage();
 
-  static bool IsRunning() {
-    return port_ != ILLEGAL_PORT;
-  }
+  static bool IsRunning();
+  static void SetServicePort(Dart_Port port);
+  static void SetServiceIsolate(Isolate* isolate);
+  static bool HasServiceIsolate();
+  static bool IsServiceIsolate(Isolate* isolate);
 
-  static void set_port(Dart_Port port) {
-    port_ = port;
-  }
+  static Dart_Port WaitForLoadPort();
+  static Dart_Port LoadPort();
+  static void SetLoadPort(Dart_Port port);
 
   static void SetEventMask(uint32_t mask);
 
@@ -66,13 +74,19 @@
       Dart_ServiceRequestCallback callback,
       void* user_data);
 
-  static bool IsServiceIsolate(Isolate* isolate) {
-    return isolate == service_isolate_;
-  }
-
-  static void SendEchoEvent(Isolate* isolate);
+  static void SendEchoEvent(Isolate* isolate, const char* text);
   static void SendGraphEvent(Isolate* isolate);
 
+  static void MaybeInjectVMServiceLibrary(Isolate* isolate);
+
+  static void RunService();
+
+  static void FinishedInitializing();
+
+  static Dart_IsolateCreateCallback create_callback() {
+    return create_callback_;
+  }
+
  private:
   // These must be kept in sync with service/constants.dart
   static const int kEventFamilyDebug = 0;
@@ -82,11 +96,13 @@
 
   static void EmbedderHandleMessage(EmbedderServiceHandler* handler,
                                     JSONStream* js);
+
   static EmbedderServiceHandler* FindIsolateEmbedderHandler(const char* name);
   static EmbedderServiceHandler* FindRootEmbedderHandler(const char* name);
   static Dart_Handle GetSource(const char* name);
   static Dart_Handle LibraryTagHandler(Dart_LibraryTag tag, Dart_Handle library,
                                        Dart_Handle url);
+
   static void SendEvent(intptr_t eventId, const Object& eventMessage);
   // Does not take ownership of 'data'.
   static void SendEvent(intptr_t eventId,
@@ -97,9 +113,13 @@
   static EmbedderServiceHandler* isolate_service_handler_head_;
   static EmbedderServiceHandler* root_service_handler_head_;
 
+
+  static Dart_IsolateCreateCallback create_callback_;
+  static Monitor* monitor_;
+  static bool initializing_;
   static Isolate* service_isolate_;
-  static Dart_LibraryTagHandler embedder_provided_handler_;
-  static Dart_Port port_;
+  static Dart_Port service_port_;
+  static Dart_Port load_port_;
   static uint32_t event_mask_;
 };
 
diff --git a/runtime/vm/service/message.dart b/runtime/vm/service/message.dart
index 6a7c66b..4b2f80a 100644
--- a/runtime/vm/service/message.dart
+++ b/runtime/vm/service/message.dart
@@ -9,10 +9,16 @@
   bool get completed => _completer.isCompleted;
   /// Future of response.
   Future<String> get response => _completer.future;
-  /// Path.
+
+  final bool isOld;
+
+  // In new messages.
+  final String method;
+
+  // In old messages.
   final List path = new List();
-  /// Options.
-  final Map options = new Map();
+
+  final Map params = new Map();
 
   void _setPath(List<String> pathSegments) {
     if (pathSegments == null) {
@@ -26,30 +32,53 @@
     });
   }
 
-  Message.fromUri(Uri uri) {
+  Message.fromUri(Uri uri) : isOld = true {
     var split = uri.path.split('/');
     if (split.length == 0) {
       setErrorResponse('Invalid uri: $uri.');
       return;
     }
     _setPath(split);
-    options.addAll(uri.queryParameters);
+    params.addAll(uri.queryParameters);
   }
 
-  Message.fromMap(Map map) {
+  Message.fromJsonRpc(this.method, Map rpcParams)
+      : isOld = false {
+    params.addAll(rpcParams);
+  }
+
+  Message.fromMap(Map map) : isOld = true {
     _setPath(map['path']);
+    // TODO - turnidge - change this to params in sender.
     if (map['options'] != null) {
-      options.addAll(map['options']);
+      params.addAll(map['options']);
     }
   }
 
   dynamic toJson() {
     return {
       'path': path,
-      'options': options
+      'params': params
     };
   }
 
+  // Calls toString on all non-String elements of [list]. We do this so all
+  // elements in the list are strings, making consumption by C++ simpler.
+  // This has a side effect that boolean literal values like true become 'true'
+  // and thus indistinguishable from the string literal 'true'.
+  List _makeAllString(List list) {
+    if (list == null) {
+      return null;
+    }
+    for (var i = 0; i < list.length; i++) {
+      if (list[i] is String) {
+        continue;
+      }
+      list[i] = list[i].toString();
+    }
+    return list;
+  }
+
   Future<String> send(SendPort sendPort) {
     final receivePort = new RawReceivePort();
     receivePort.handler = (value) {
@@ -60,12 +89,12 @@
         _completer.complete(value);
       }
     };
-    var keys = options.keys.toList(growable:false);
-    var values = options.values.toList(growable:false);
+    var keys = _makeAllString(params.keys.toList(growable:false));
+    var values = _makeAllString(params.values.toList(growable:false));
     var request = new List(5)
         ..[0] = 0  // Make room for OOB message type.
         ..[1] = receivePort.sendPort
-        ..[2] = path
+        ..[2] = (isOld ? path : method)
         ..[3] = keys
         ..[4] = values;
     sendIsolateServiceMessage(sendPort, request);
@@ -82,12 +111,12 @@
         _completer.complete(value);
       }
     };
-    var keys = options.keys.toList(growable:false);
-    var values = options.values.toList(growable:false);
+    var keys = _makeAllString(params.keys.toList(growable:false));
+    var values = _makeAllString(params.values.toList(growable:false));
     var request = new List(5)
         ..[0] = 0  // Make room for OOB message type.
         ..[1] = receivePort.sendPort
-        ..[2] = path
+        ..[2] = (isOld ? path : method)
         ..[3] = keys
         ..[4] = values;
     sendRootServiceMessage(request);
@@ -105,7 +134,7 @@
         'kind': 'RequestError',
         'message': error,
         'path': path,
-        'options': options
+        'params': params
     }));
   }
 }
diff --git a/runtime/vm/service/protocol.md b/runtime/vm/service/protocol.md
index 2af1967..71b2da1 100644
--- a/runtime/vm/service/protocol.md
+++ b/runtime/vm/service/protocol.md
@@ -148,7 +148,7 @@
 Observatory.
 
 For example, some responses will have the <code>_vmType</code>
-nnnproperty.  This provides the VM-internal type name of an object, and
+property.  This provides the VM-internal type name of an object, and
 is provided only when this type name differs from the
 <code>type</code> property.
 
diff --git a/runtime/vm/service/running_isolates.dart b/runtime/vm/service/running_isolates.dart
index 8c7bc81..124eb90 100644
--- a/runtime/vm/service/running_isolates.dart
+++ b/runtime/vm/service/running_isolates.dart
@@ -26,6 +26,36 @@
   }
 
   Future<String> route(Message message) {
+    if (message.isOld) {
+      return routeOld(message);
+    }
+
+    String isolateParam = message.params['isolate'];
+    int isolateId;
+    if (!isolateParam.startsWith('isolates/')) {
+      message.setErrorResponse('Malformed isolate id $isolateParam');
+      return message.response;
+    }
+    isolateParam = isolateParam.substring('isolates/'.length);
+    if (isolateParam == 'isolates/root') {
+      isolateId = _rootPortId;
+    } else {
+      try {
+        isolateId = int.parse(isolateParam);
+      } catch (e) {
+        message.setErrorResponse('Could not parse isolate id: $e');
+        return message.response;
+      }
+    }
+    var isolate = isolates[isolateId];
+    if (isolate == null) {
+      message.setErrorResponse('Cannot find isolate id: $isolateId');
+      return message.response;
+    }
+    return isolate.route(message);
+  }
+
+  Future<String> routeOld(Message message) {
     if (message.path.length == 0) {
       message.setErrorResponse('No path.');
       return message.response;
diff --git a/runtime/vm/service/service.idl b/runtime/vm/service/service.idl
new file mode 100644
index 0000000..e915378
--- /dev/null
+++ b/runtime/vm/service/service.idl
@@ -0,0 +1,397 @@
+//
+// TODO(turnidge): Finish writing an idl description of the service protocol.
+//
+
+interface Service {
+  // Returns the list of breakpoints for an isolate.
+  getBreakpoints(isolateId string) BreakpointList
+
+  // Adds a breakpoint at the specified line.
+  //
+  // TODO(turnidge): Make line an int instead of a string.
+  addBreakpoint(isolateId string,
+                scriptId string,
+                line string) Breakpoint
+
+  // Removes the specified breakpoint
+  removeBreakpoint(isolateId string, breakpointId string) Response
+
+  // Requests that an isolate pause execution.
+  pause(isolateId string) Response
+
+  // Requests that an isolate resume execution.
+  //
+  // <code>step</code> is optional and indicates whether execution
+  // should single-step.
+  resume(isolateId string, step StepOption) Response
+
+  // Evaluate an expression in the context of some target.
+  eval(isolateId string, targetId string, expression string) InstanceRef
+
+  // Returns the current execution stack for an isolate.
+  getStack(isolateId string) Stack
+
+  // Returns code coverage information for a library, script, class,
+  // or function.
+  getCoverage(isolateId string, targetId string) CodeCoverage
+
+  // Returns a full cpu profile for an isolate.
+  //
+  // <code>tagSelector</code> is optional with default 'UserVM'.
+  getCpuProfile(isolateId string, tags TagSelector) CpuProfile
+
+
+  // Returns a simple tag-based profile for an isolate.
+  getTagProfile(isolateId string) TagProfile
+
+  // Returns an allocation profile for an isolate.
+  //
+  // <code>reset</code> is optional and indicates whether allocation
+  // accumulators should be reset.
+  //
+  // <code>gc</code> is optional and indicates whether a full
+  getAllocationProfile(isolateId string,
+                       reset bool,
+                       gc GCOption) AllocationProfile
+
+  // Returns the heap map for an isolate.
+  getHeapMap(isolateId string) HeapMap
+
+  // Returns how many bytes are retained by some target Class or Instance.
+  getRetainedSize(isolateId string, targetId string) InstanceRef
+
+  // Returns a path demonstrating why an object is retained in memory.
+  //
+  // TODO(turnidge): Make limit an int instead of a string.
+  getRetainingPath(isolateId string,
+                   targetId string,
+                   limit int) RetainingPath
+
+  // Returns a collection of inbound references to some object.
+  //
+  // TODO(turnidge): Make limit an int instead of a string.
+  getInboundReferences(isolateId string,
+                       targetId string,
+                       limit int) InboundReferences
+
+  getClassList(isolateId string) ClassList
+
+  // When <code>onlyWithInstantiations</code> is true, the list only includes
+  // type arguments with instantiations. Otherwise, all type arguments are
+  // returned.
+  getTypeArgumentsList(isolateId string,
+                       onlyWithInstantiations bool) TypeArgumentsList
+
+  getIsolateMetricList(isolateId string,
+                       type MetricSelector) MetricList
+
+  getIsolateMetric(isolateId string,
+                   metricId string) Metric
+
+  getVMMetricList() MetricList
+
+  getVMMetric(metricId string) Metric
+
+  _echo(isolateId string,
+        text string) _EchoResponse
+
+  _echoVM(text string) _EchoResponse
+
+  // Triggers a ServiceEvent with EventType '_Echo'.
+  _triggerEchoEvent(isolateId string,
+                    text string) _EchoResponse
+
+  // Response is bad JSON.
+  _respondWithMalformedJson(isolateId string) Response
+
+  // Response is not an object.
+  _respondWithMalformedObject(isolateId string) Response
+}
+
+
+// Every top level response returned by the Service interface extends
+// <code>Response</code>.  This allows the client to distinguish
+// between different kinds of responses by using the <code>type</code>
+// property.
+struct Response {
+  // Every response returned by the VM Service has the
+  // <code>type</code> property.  This allows the client distinguish
+  // between different kinds of responses.
+  type    string
+
+  // Some responses will have the <code>_vmType</code> property.  This
+  // provides the VM-internal type name of an object, and is provided
+  // only when this type name differs from the <code>type</code>
+  // property.
+  _vmType string [optional]
+}
+
+
+struct _EchoResponse extends Response {
+  text string
+}
+
+
+// Persistent objects in the vm are returned as subclasses of Object.
+struct Object extends Response {
+  // The object <code>id</code> can be used to refer to a persistent
+  // object inside the vm or an isolate.
+  id  string
+}
+
+
+// An <code>Instance</code> represents a Dart-language object.
+struct Instance extends Object {
+  placeholder int
+}
+
+
+// A <code>Breakpoint</code> describes a debugger breakpoint.
+struct Breakpoint extends Object {
+  breakpointNumber int
+  enabled          bool
+  resolved         bool
+  location         Location
+}
+
+
+// References to persistent objects in the vm are returned as
+// subclasses of ObjectRef.
+struct ObjectRef extends Response {
+  // The object <code>id</code> can be used to refer to a persistent
+  // object inside the vm or an isolate.
+  id  string
+}
+
+
+// A <code>CodeRef</code> encodes a reference to a <code>Code</code> object.
+struct CodeRef extends ObjectRef {
+  placeholder int
+}
+
+
+struct ClassRef extends ObjectRef {
+  placeholder int
+}
+
+
+struct TypeArgumentsRef extends ObjectRef {
+  placeholder int
+}
+
+
+// A <code>FunctionRef</code> encodes a reference to a <code>Function</code> object.
+struct FunctionRef extends ObjectRef {
+  placeholder int
+}
+
+
+// A <code>FieldRef</code> encodes a reference to a <code>Field</code> object.
+struct FieldRef extends ObjectRef {
+  placeholder int
+}
+
+
+// A <code>InstanceRef</code> encodes a reference to a <code>Instance</code> object.
+struct InstanceRef extends ObjectRef {
+  placeholder int
+}
+
+
+// A <code>ScriptRef</code> encodes a reference to a <code>Script</code> object.
+struct ScriptRef extends ObjectRef {
+  placeholder int
+}
+
+
+struct Class extends Object {
+  placeholder int
+}
+
+
+struct TypeArguments extends Object {
+  placeholder int
+}
+
+
+// A <code>Location</code> encodes a location withing a dart script.
+//
+// TODO(turnidge): Should this really be broken out as its own type?
+// If so, we should use it more consistently in the api.  For example,
+// in Frame.
+struct Location {
+  script   ScriptRef
+  tokenPos int
+}
+
+
+// A <code>Variable</code> represents one name/value pair from a frame.
+struct Variable {
+  name  string
+  value InstanceRef
+}
+
+
+// A <code>Frame</code> represents one frame from an isolate's stack.
+struct Frame {
+  script   ScriptRef
+  tokenPos int
+  function FunctionRef
+  code     CodeRef
+  vars     []Variable
+}
+
+
+// A <code>Stack</code> represents an isolate's execution stack.
+struct Stack extends Response {
+  frames []Frame
+}
+
+
+struct CodeCoverage extends Response {
+  placeholder int
+}
+
+// A <code>TagProfile</code> is a limited profile encoded as parallel
+// arrays of tag names and tag values.
+struct TagProfile extends Response {
+  names    []string
+  counters []int
+}
+
+
+// A list of <code>Breakpoint</code>
+struct BreakpointList extends Response {
+  breakpoints []Breakpoint
+}
+
+
+// An <code>AllocationProfile</code> encodes an allocation profile.
+struct AllocationProfile extends Response {
+  todo int
+}
+
+
+// A <code>CpuProfile</code> encodes a full cpu profile.
+struct CpuProfile extends Response {
+  samples        int
+  depth          int
+  period         int
+  timeSpan       float
+  exclusive_trie []int
+  codes          []CodeRegion
+}
+
+
+// A <code>CodeRegion</code> represents profiling information for a
+// specific <code>Code</code> object.
+struct CodeRegion {
+  kind            string
+  inclusive_ticks int
+  exclusive_ticks int
+  code            CodeRef
+  ticks           []int
+  callers         []int
+}
+
+// An <code>HeapMap</code> provides a memory view of all heap allocated objects.
+struct HeapMap extends Response {
+  todo int
+}
+
+
+// An <code>HeapMap</code> provides a memory view of all heap allocated objects.
+struct RetainingPath extends Response {
+  length int
+  elements []RetainingPathElement
+}
+
+
+// One entry in a <code>RetainingPath</code>.
+struct RetainingPathElement {
+  index           int
+  element         InstanceRef
+  parentListIndex int [optional]
+  parentField     FieldRef [optional]
+}
+
+
+struct InboundReferences extends Response {
+  length int
+  references []InboundReference
+}
+
+
+// TODO(koda): slot can actually be a string, and integer or a
+// FieldRef.  Fix this to be consistent with RetainingPathElement.
+struct InboundReference {
+  source InstanceRef
+  slot   int
+}
+
+
+struct ClassList extends Response {
+  classes []ClassRef
+}
+
+
+struct TypeArgumentsList extends Response {
+  tableSize int
+  tableUsed int
+  typeArguments []TypeArgumentsRef
+}
+
+
+struct MetricList extends Response {
+  metrics []Metric
+}
+
+
+struct Metric extends Response {
+  name string
+  description string
+}
+
+
+struct Gauge extends Metric {
+  value double
+  min double
+  max double
+}
+
+
+struct Counter extends Metric {
+  value double
+}
+
+
+// A <code>GCOption</code> is used to indicate which form of garbage
+// collection is requested.
+enum GCOption {
+  full
+}
+
+// A <code>StepOption</code> is used to indicate which form of
+// single-stepping is requested.
+enum StepOption {
+  into
+  over
+  out
+}
+
+// A <code>TagSelector</code> is used to indicate which sets of tags
+// should take precedence in a cpu profile.
+enum TagSelector {
+  UserVM
+  UserOnly
+  VMUser
+  VMOnly
+  None
+}
+
+// A <code>MetricSelector</code> is used to indicate which list of metrics
+// should be retrieved from an isolate.
+enum MetricSelector {
+  Dart,
+  Native,
+}
diff --git a/runtime/vm/service/vmservice.dart b/runtime/vm/service/vmservice.dart
index 10e73c9..3c5ed24 100644
--- a/runtime/vm/service/vmservice.dart
+++ b/runtime/vm/service/vmservice.dart
@@ -7,7 +7,6 @@
 import 'dart:async';
 import 'dart:convert';
 import 'dart:isolate';
-import 'dart:typed_data';
 
 part 'client.dart';
 part 'constants.dart';
@@ -106,8 +105,13 @@
     }
   }
 
+  void _notSupported(_) {
+    throw new UnimplementedError('Service script loading not supported.');
+  }
+
   VMService._internal()
       : eventPort = isolateLifecyclePort {
+    scriptLoadPort.handler = _notSupported;
     eventPort.handler = messageHandler;
   }
 
@@ -138,8 +142,14 @@
       _clientCollection(message);
       return message.response;
     }
-    if (message.path[0] == 'isolates') {
-      return runningIsolates.route(message);
+    if (message.isOld) {
+      if (message.path[0] == 'isolates') {
+        return runningIsolates.route(message);
+      }
+    } else {
+      if (message.params['isolate'] != null) {
+        return runningIsolates.route(message);
+      }
     }
     return message.sendToVM();
   }
@@ -158,4 +168,4 @@
 void _setEventMask(int mask)
     native "VMService_SetEventMask";
 
-void _onStart() native "VMService_OnStart";
\ No newline at end of file
+void _onStart() native "VMService_OnStart";
diff --git a/runtime/vm/service_test.cc b/runtime/vm/service_test.cc
index e77eded..ee6659a 100644
--- a/runtime/vm/service_test.cc
+++ b/runtime/vm/service_test.cc
@@ -213,277 +213,6 @@
 }
 
 
-TEST_CASE(Service_StackTrace) {
-  // TODO(turnidge): Extend this test to cover a non-trivial stack trace.
-  const char* kScript =
-      "var port;\n"  // Set to our mock port by C++.
-      "\n"
-      "main() {\n"
-      "}";
-
-  Isolate* isolate = Isolate::Current();
-  Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
-  EXPECT_VALID(lib);
-
-  // Build a mock message handler and wrap it in a dart port.
-  ServiceTestMessageHandler handler;
-  Dart_Port port_id = PortMap::CreatePort(&handler);
-  Dart_Handle port = Api::NewHandle(isolate, SendPort::New(port_id));
-  EXPECT_VALID(port);
-  EXPECT_VALID(Dart_SetField(lib, NewString("port"), port));
-
-  Array& service_msg = Array::Handle();
-
-  // Get the stacktrace.
-  service_msg = Eval(lib, "[0, port, ['stacktrace'], [], []]");
-  Service::HandleIsolateMessage(isolate, service_msg);
-  handler.HandleNextMessage();
-  EXPECT_STREQ(
-      "{\"type\":\"StackTrace\",\"id\":\"stacktrace\",\"members\":[]}",
-      handler.msg());
-
-  // Malformed request.
-  service_msg = Eval(lib, "[0, port, ['stacktrace', 'jamboree'], [], []]");
-  Service::HandleIsolateMessage(isolate, service_msg);
-  handler.HandleNextMessage();
-  EXPECT_STREQ(
-      "{\"type\":\"Error\",\"id\":\"\",\"message\":\"Command too long\","
-      "\"request\":{\"arguments\":[\"stacktrace\",\"jamboree\"],"
-      "\"option_keys\":[],\"option_values\":[]}}",
-      handler.msg());
-}
-
-
-TEST_CASE(Service_DebugBreakpoints) {
-  const char* kScript =
-      "var port;\n"  // Set to our mock port by C++.
-      "\n"
-      "main() {\n"   // We set breakpoint here.
-      "}";
-
-  Isolate* isolate = Isolate::Current();
-  Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
-  EXPECT_VALID(lib);
-  Library& vmlib = Library::Handle();
-  vmlib ^= Api::UnwrapHandle(lib);
-  EXPECT(!vmlib.IsNull());
-
-  // Build a mock message handler and wrap it in a dart port.
-  ServiceTestMessageHandler handler;
-  Dart_Port port_id = PortMap::CreatePort(&handler);
-  Dart_Handle port = Api::NewHandle(isolate, SendPort::New(port_id));
-  EXPECT_VALID(port);
-  EXPECT_VALID(Dart_SetField(lib, NewString("port"), port));
-
-  Array& service_msg = Array::Handle();
-
-  // Add a breakpoint.
-  service_msg = EvalF(lib,
-                     "[0, port, ['libraries', '%" Pd "', "
-                     "'scripts', 'test-lib', 'setBreakpoint'], "
-                      "['line'], ['3']]",
-                      vmlib.index());
-  Service::HandleIsolateMessage(isolate, service_msg);
-  handler.HandleNextMessage();
-  ExpectSubstringF(
-      handler.msg(),
-      "{\"type\":\"Breakpoint\",\"id\":\"debug\\/breakpoints\\/1\","
-      "\"breakpointNumber\":1,\"enabled\":true,\"resolved\":false,"
-      "\"location\":{\"type\":\"Location\","
-      "\"script\":{\"type\":\"@Script\","
-      "\"id\":\"libraries\\/%" Pd "\\/scripts\\/test-lib\","
-      "\"name\":\"test-lib\",\"kind\":\"script\"},"
-      "\"tokenPos\":5}}",
-      vmlib.index());
-
-  // Get the breakpoint list.
-  service_msg = Eval(lib, "[0, port, ['debug', 'breakpoints'], [], []]");
-  Service::HandleIsolateMessage(isolate, service_msg);
-  handler.HandleNextMessage();
-  ExpectSubstringF(
-      handler.msg(),
-      "{\"type\":\"BreakpointList\",\"id\":\"debug\\/breakpoints\","
-      "\"breakpoints\":["
-      "{\"type\":\"Breakpoint\",\"id\":\"debug\\/breakpoints\\/1\","
-      "\"breakpointNumber\":1,\"enabled\":true,\"resolved\":false,"
-      "\"location\":{\"type\":\"Location\","
-      "\"script\":{\"type\":\"@Script\","
-      "\"id\":\"libraries\\/%" Pd "\\/scripts\\/test-lib\","
-      "\"name\":\"test-lib\",\"kind\":\"script\"},"
-      "\"tokenPos\":5}}]}",
-      vmlib.index());
-
-  // Lookup individual breakpoint.
-  service_msg = Eval(lib, "[0, port, ['debug', 'breakpoints', '1'], [], []]");
-  Service::HandleIsolateMessage(isolate, service_msg);
-  handler.HandleNextMessage();
-  ExpectSubstringF(
-      handler.msg(),
-      "{\"type\":\"Breakpoint\",\"id\":\"debug\\/breakpoints\\/1\","
-      "\"breakpointNumber\":1,\"enabled\":true,\"resolved\":false,"
-      "\"location\":{\"type\":\"Location\","
-      "\"script\":{\"type\":\"@Script\","
-      "\"id\":\"libraries\\/%" Pd "\\/scripts\\/test-lib\","
-      "\"name\":\"test-lib\",\"kind\":\"script\"},"
-      "\"tokenPos\":5}}",
-      vmlib.index());
-
-  // Unrecognized breakpoint subcommand.
-  service_msg =
-      Eval(lib, "[0, port, ['debug', 'breakpoints', '1', 'green'], [], []]");
-  Service::HandleIsolateMessage(isolate, service_msg);
-  handler.HandleNextMessage();
-  EXPECT_STREQ("{\"type\":\"Error\",\"id\":\"\","
-                "\"message\":\"Unrecognized subcommand: green\","
-                "\"request\":{\"arguments\":[\"debug\",\"breakpoints\","
-                                            "\"1\",\"green\"],"
-                             "\"option_keys\":[],\"option_values\":[]}}",
-               handler.msg());
-
-  // Clear breakpoint.
-  service_msg =
-      Eval(lib, "[0, port, ['debug', 'breakpoints', '1', 'clear'], [], []]");
-  Service::HandleIsolateMessage(isolate, service_msg);
-  handler.HandleNextMessage();
-  EXPECT_STREQ("{\"type\":\"Success\",\"id\":\"\"}",
-               handler.msg());
-
-  // Get the breakpoint list.
-  service_msg = Eval(lib, "[0, port, ['debug', 'breakpoints'], [], []]");
-  Service::HandleIsolateMessage(isolate, service_msg);
-  handler.HandleNextMessage();
-  EXPECT_STREQ(
-      "{\"type\":\"BreakpointList\",\"id\":\"debug\\/breakpoints\","
-      "\"breakpoints\":[]}",
-      handler.msg());
-
-  // Missing sub-command.
-  service_msg = Eval(lib, "[0, port, ['debug'], [], []]");
-  Service::HandleIsolateMessage(isolate, service_msg);
-  handler.HandleNextMessage();
-  EXPECT_STREQ(
-      "{\"type\":\"Error\",\"id\":\"\","
-       "\"message\":\"Must specify a subcommand\","
-       "\"request\":{\"arguments\":[\"debug\"],\"option_keys\":[],"
-                    "\"option_values\":[]}}",
-      handler.msg());
-
-  // Unrecognized breakpoint.
-  service_msg = Eval(lib,
-                     "[0, port, ['debug', 'breakpoints', '1111'], [], []]");
-  Service::HandleIsolateMessage(isolate, service_msg);
-  handler.HandleNextMessage();
-  EXPECT_STREQ("{\"type\":\"Error\",\"id\":\"\","
-                "\"message\":\"Unrecognized breakpoint id: 1111\","
-                "\"request\":{"
-                    "\"arguments\":[\"debug\",\"breakpoints\",\"1111\"],"
-                    "\"option_keys\":[],\"option_values\":[]}}",
-               handler.msg());
-
-  // Unrecognized subcommand.
-  service_msg = Eval(lib, "[0, port, ['debug', 'nosferatu'], [], []]");
-  Service::HandleIsolateMessage(isolate, service_msg);
-  handler.HandleNextMessage();
-  EXPECT_STREQ("{\"type\":\"Error\",\"id\":\"\","
-                "\"message\":\"Unrecognized subcommand 'nosferatu'\","
-                "\"request\":{\"arguments\":[\"debug\",\"nosferatu\"],"
-                             "\"option_keys\":[],\"option_values\":[]}}",
-               handler.msg());
-}
-
-
-// Globals used to communicate with HandlerPausedEvent.
-static intptr_t pause_line_number = 0;
-static Dart_Handle saved_lib;
-static ServiceTestMessageHandler* saved_handler = NULL;
-
-static void HandlePausedEvent(Dart_IsolateId isolate_id,
-                              intptr_t bp_id,
-                              const Dart_CodeLocation& loc) {
-  Isolate* isolate = Isolate::Current();
-  Debugger* debugger = isolate->debugger();
-
-  // The debugger knows that it is paused, and why.
-  EXPECT(debugger->IsPaused());
-  const DebuggerEvent* event = debugger->PauseEvent();
-  EXPECT(event != NULL);
-  EXPECT(event->type() == DebuggerEvent::kBreakpointReached);
-
-  // Save the last line number seen by this handler.
-  pause_line_number = event->top_frame()->LineNumber();
-
-  // Single step
-  Array& service_msg = Array::Handle();
-  service_msg = Eval(saved_lib,
-                     "[0, port, ['debug', 'resume'], "
-                     "['step'], ['into']]");
-  Service::HandleIsolateMessage(isolate, service_msg);
-  saved_handler->HandleNextMessage();
-  EXPECT_STREQ("{\"type\":\"Success\",\"id\":\"\"}",
-               saved_handler->msg());
-}
-
-
-TEST_CASE(Service_Stepping) {
-  const char* kScript =
-      "var port;\n"  // Set to our mock port by C++.
-      "var value = 0;\n"
-      "\n"
-      "main() {\n"   // We set breakpoint here.
-      "  value++;\n"
-      "  value++;\n"
-      "  value++;\n"
-      "}";           // We step up to here.
-
-  Isolate* isolate = Isolate::Current();
-  Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
-  EXPECT_VALID(lib);
-  Library& vmlib = Library::Handle();
-  vmlib ^= Api::UnwrapHandle(lib);
-  EXPECT(!vmlib.IsNull());
-  saved_lib = lib;
-
-  // Build a mock message handler and wrap it in a dart port.
-  ServiceTestMessageHandler handler;
-  saved_handler = &handler;
-  Dart_Port port_id = PortMap::CreatePort(&handler);
-  Dart_Handle port = Api::NewHandle(isolate, SendPort::New(port_id));
-  EXPECT_VALID(port);
-  EXPECT_VALID(Dart_SetField(lib, NewString("port"), port));
-
-  Array& service_msg = Array::Handle();
-
-  // Add a breakpoint.
-  service_msg = EvalF(lib,
-                      "[0, port, ['libraries', '%" Pd "', "
-                      "'scripts', 'test-lib', 'setBreakpoint'], "
-                      "['line'], ['4']]",
-                      vmlib.index());
-  Service::HandleIsolateMessage(isolate, service_msg);
-  handler.HandleNextMessage();
-  ExpectSubstringF(
-      handler.msg(),
-      "{\"type\":\"Breakpoint\",\"id\":\"debug\\/breakpoints\\/1\","
-      "\"breakpointNumber\":1,\"enabled\":true,\"resolved\":false,"
-      "\"location\":{\"type\":\"Location\","
-      "\"script\":{\"type\":\"@Script\","
-      "\"id\":\"libraries\\/%" Pd "\\/scripts\\/test-lib\","
-      "\"name\":\"test-lib\",\"kind\":\"script\"},"
-      "\"tokenPos\":11}}",
-      vmlib.index());
-
-  pause_line_number = -1;
-  Dart_SetPausedEventHandler(HandlePausedEvent);
-
-  // Run the program.
-  Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL);
-  EXPECT_VALID(result);
-
-  // We were able to step to the last line in main.
-  EXPECT_EQ(8, pause_line_number);
-}
-
-
 TEST_CASE(Service_Objects) {
   // TODO(turnidge): Extend this test to cover a non-trivial stack trace.
   const char* kScript =
@@ -636,75 +365,11 @@
       "\"valueAsString\":\"<expired>\"}",
       handler.msg());
 
-  // expired/eval => error
-  service_msg = Eval(lib, "[0, port, ['objects', 'expired', 'eval'], [], []]");
-  Service::HandleIsolateMessage(isolate, service_msg);
-  handler.HandleNextMessage();
-  handler.filterMsg("_vmName");
-  EXPECT_STREQ(
-      "{\"type\":\"Error\",\"id\":\"\","
-      "\"message\":\"expected at most 2 arguments but found 3\\n\","
-      "\"request\":{\"arguments\":[\"objects\",\"expired\",\"eval\"],"
-      "\"option_keys\":[],\"option_values\":[]}}",
-      handler.msg());
-
-  // int/eval => good
-  service_msg = Eval(lib,
-                     "[0, port, ['objects', 'int-123', 'eval'], "
-                     "['expr'], ['this+99']]");
-  Service::HandleIsolateMessage(isolate, service_msg);
-  handler.HandleNextMessage();
-  handler.filterMsg("_vmName");
-  EXPECT_STREQ(
-      "{\"type\":\"@int\",\"_vmType\":\"@Smi\","
-      "\"class\":{\"type\":\"@Class\",\"id\":\"classes\\/42\","
-      "\"name\":\"_Smi\",},"
-      "\"id\":\"objects\\/int-222\","
-      "\"valueAsString\":\"222\"}",
-      handler.msg());
-
-  // eval returning null works
-  service_msg = Eval(lib,
-                     "[0, port, ['objects', 'int-123', 'eval'], "
-                     "['expr'], ['null']]");
-  Service::HandleIsolateMessage(isolate, service_msg);
-  handler.HandleNextMessage();
-  handler.filterMsg("_vmName");
-  EXPECT_STREQ(
-      "{\"type\":\"@null\",\"id\":\"objects\\/null\","
-      "\"valueAsString\":\"null\"}",
-      handler.msg());
-
-  // object id ring / invalid => expired
-  service_msg = Eval(lib, "[0, port, ['objects', '99999999', 'eval'], "
-                     "['expr'], ['this']]");
-  Service::HandleIsolateMessage(isolate, service_msg);
-  handler.HandleNextMessage();
-  handler.filterMsg("_vmName");
-  EXPECT_STREQ(
-      "{\"type\":\"Error\",\"id\":\"\",\"kind\":\"EvalExpired\","
-      "\"message\":\"attempt to evaluate against expired object\\n\","
-      "\"request\":{\"arguments\":[\"objects\",\"99999999\",\"eval\"],"
-      "\"option_keys\":[\"expr\"],\"option_values\":[\"this\"]}}",
-      handler.msg());
-
-  // Extra arg to eval.
-  service_msg = Eval(lib,
-                     "[0, port, ['objects', 'int-123', 'eval', 'foo'], "
-                     "['expr'], ['this+99']]");
-  Service::HandleIsolateMessage(isolate, service_msg);
-  handler.HandleNextMessage();
-  handler.filterMsg("_vmName");
-  EXPECT_STREQ(
-      "{\"type\":\"Error\",\"id\":\"\","
-      "\"message\":\"expected at most 3 arguments but found 4\\n\","
-      "\"request\":{\"arguments\":[\"objects\",\"int-123\",\"eval\",\"foo\"],"
-      "\"option_keys\":[\"expr\"],\"option_values\":[\"this+99\"]}}",
-      handler.msg());
-
   // Retained by single instance.
-  service_msg = Eval(lib,
-                     "[0, port, ['objects', '$validId', 'retained'], [], []]");
+  service_msg = Eval(
+      lib,
+      "[0, port, 'getRetainedSize', "
+      "['targetId'], ['objects/$validId']]");
   Service::HandleIsolateMessage(isolate, service_msg);
   handler.HandleNextMessage();
   handler.filterMsg("_vmName");
@@ -715,35 +380,23 @@
   // Retaining path to 'arr', limit 1.
   service_msg = Eval(
       lib,
-      "[0, port, ['objects', '$validId', 'retaining_path'], ['limit'], ['1']]");
+      "[0, port, 'getRetainingPath', "
+      "['targetId', 'limit'], ['objects/$validId', '1']]");
   Service::HandleIsolateMessage(isolate, service_msg);
   handler.HandleNextMessage();
   ExpectSubstringF(
       handler.msg(),
-      "{\"type\":\"RetainingPath\",\"id\":\"retaining_path\",\"length\":1,"
+      "{\"type\":\"RetainingPath\",\"length\":1,"
       "\"elements\":[{\"index\":0,\"value\":{\"type\":\"@List\"");
 
   // Retaining path missing limit.
   service_msg = Eval(
       lib,
-      "[0, port, ['objects', '$validId', 'retaining_path'], [], []]");
+      "[0, port, 'getRetainingPath', "
+      "['targetId'], ['objects/$validId']]");
   Service::HandleIsolateMessage(isolate, service_msg);
   handler.HandleNextMessage();
   ExpectSubstringF(handler.msg(), "{\"type\":\"Error\"");
-
-  // eval against list containing an internal object.
-  Object& internal_object = Object::Handle();
-  internal_object = LiteralToken::New();
-  arr.SetAt(0, internal_object);
-  service_msg = Eval(lib,
-                     "[0, port, ['objects', '$validId', 'eval'], "
-                     "['expr'], ['toString()']]");
-  Service::HandleIsolateMessage(isolate, service_msg);
-  handler.HandleNextMessage();
-  ExpectSubstringF(handler.msg(), "\"type\":\"Error\"");
-  ExpectSubstringF(
-      handler.msg(),
-      "\"message\":\"attempt to evaluate against internal VM object\\n\"");
 }
 
 
@@ -817,12 +470,13 @@
   // Retaining path to 'foo0', limit 2.
   service_msg = Eval(
       lib,
-      "[0, port, ['objects', '$id0', 'retaining_path'], ['limit'], ['2']]");
+      "[0, port, 'getRetainingPath', "
+      "['targetId', 'limit'], ['objects/$id0', '2']]");
   Service::HandleIsolateMessage(isolate, service_msg);
   handler.HandleNextMessage();
   ExpectSubstringF(
       handler.msg(),
-      "{\"type\":\"RetainingPath\",\"id\":\"retaining_path\",\"length\":2,"
+      "{\"type\":\"RetainingPath\",\"length\":2,"
       "\"elements\":[{\"index\":0,\"value\":{\"type\":\"@String\"");
   ExpectSubstringF(handler.msg(), "\"parentField\":{\"type\":\"@Field\"");
   ExpectSubstringF(handler.msg(), "\"name\":\"f0\"");
@@ -832,12 +486,13 @@
   // Retaining path to 'foo1', limit 2.
   service_msg = Eval(
       lib,
-      "[0, port, ['objects', '$id1', 'retaining_path'], ['limit'], ['2']]");
+      "[0, port,  'getRetainingPath', "
+      "['targetId', 'limit'], ['objects/$id1', '2']]");
   Service::HandleIsolateMessage(isolate, service_msg);
   handler.HandleNextMessage();
   ExpectSubstringF(
       handler.msg(),
-      "{\"type\":\"RetainingPath\",\"id\":\"retaining_path\",\"length\":2,"
+      "{\"type\":\"RetainingPath\",\"length\":2,"
       "\"elements\":[{\"index\":0,\"value\":{\"type\":\"@String\"");
   ExpectSubstringF(handler.msg(), "\"parentField\":{\"type\":\"@Field\"");
   ExpectSubstringF(handler.msg(), "\"name\":\"f1\"");
@@ -847,12 +502,13 @@
   // Retaining path to 'elem', limit 2.
   service_msg = Eval(
       lib,
-      "[0, port, ['objects', '$idElem', 'retaining_path'], ['limit'], ['2']]");
+      "[0, port, 'getRetainingPath', "
+      "['targetId', 'limit'], ['objects/$idElem', '2']]");
   Service::HandleIsolateMessage(isolate, service_msg);
   handler.HandleNextMessage();
   ExpectSubstringF(
       handler.msg(),
-      "{\"type\":\"RetainingPath\",\"id\":\"retaining_path\",\"length\":2,"
+      "{\"type\":\"RetainingPath\",\"length\":2,"
       "\"elements\":[{\"index\":0,\"value\":{\"type\":\"@String\"");
   ExpectSubstringF(handler.msg(), "\"parentListIndex\":%" Pd, kElemIndex);
   ExpectSubstringF(handler.msg(),
@@ -892,21 +548,6 @@
   handler.HandleNextMessage();
   EXPECT_SUBSTRING("\"type\":\"Library\"", handler.msg());
   EXPECT_SUBSTRING("\"url\":\"test-lib\"", handler.msg());
-
-  // Evaluate an expression from a library.
-  service_msg = EvalF(lib,
-                      "[0, port, ['libraries', '%" Pd "', 'eval'], "
-                      "['expr'], ['libVar - 1']]",
-                      vmlib.index());
-  Service::HandleIsolateMessage(isolate, service_msg);
-  handler.HandleNextMessage();
-  handler.filterMsg("_vmName");
-  EXPECT_STREQ(
-      "{\"type\":\"@int\",\"_vmType\":\"@Smi\","
-      "\"class\":{\"type\":\"@Class\",\"id\":\"classes\\/42\","
-      "\"name\":\"_Smi\",},\"id\":\"objects\\/int-54320\","
-      "\"valueAsString\":\"54320\"}",
-      handler.msg());
 }
 
 
@@ -957,7 +598,7 @@
   Service::HandleIsolateMessage(isolate, service_msg);
   handler.HandleNextMessage();
   EXPECT_STREQ(
-    "{\"type\":\"Error\",\"id\":\"\","
+    "{\"type\":\"Error\","
     "\"message\":\"999999 is not a valid class id.\","
     "\"request\":{\"arguments\":[\"classes\",\"999999\"],"
     "\"option_keys\":[],\"option_values\":[]}}", handler.msg());
@@ -973,21 +614,6 @@
   ExpectSubstringF(handler.msg(), "\"tokenPos\":");
   ExpectSubstringF(handler.msg(), "\"endTokenPos\":");
 
-  // Evaluate an expression from class A.
-  service_msg = EvalF(lib,
-                      "[0, port, ['classes', '%" Pd "', 'eval'], "
-                      "['expr'], ['cobra + 100000']]", cid);
-  Service::HandleIsolateMessage(isolate, service_msg);
-  handler.HandleNextMessage();
-  handler.filterMsg("_vmName");
-  EXPECT_STREQ(
-      "{\"type\":\"@int\",\"_vmType\":\"@Smi\","
-      "\"class\":{\"type\":\"@Class\",\"id\":\"classes\\/42\","
-      "\"name\":\"_Smi\",},"
-      "\"id\":\"objects\\/int-111235\","
-      "\"valueAsString\":\"111235\"}",
-      handler.msg());
-
   // Request function 'b' from class A.
   service_msg = EvalF(lib,
                       "[0, port, ['classes', '%" Pd "', 'functions', 'b'],"
@@ -1015,7 +641,7 @@
   Service::HandleIsolateMessage(isolate, service_msg);
   handler.HandleNextMessage();
   ExpectSubstringF(handler.msg(),
-    "{\"type\":\"Error\",\"id\":\"\",\"message\":\"Invalid sub collection huh\""
+    "{\"type\":\"Error\",\"message\":\"Invalid sub collection huh\""
     ",\"request\":"
     "{\"arguments\":[\"classes\",\"%" Pd "\",\"huh\",\"0\"],\"option_keys\":[],"
     "\"option_values\":[]}}", cid);
@@ -1026,7 +652,7 @@
   Service::HandleIsolateMessage(isolate, service_msg);
   handler.HandleNextMessage();
   ExpectSubstringF(handler.msg(),
-    "{\"type\":\"Error\",\"id\":\"\",\"message\":\"Field 9 not found\","
+    "{\"type\":\"Error\",\"message\":\"Field 9 not found\","
     "\"request\":{\"arguments\":[\"classes\",\"%" Pd "\",\"fields\",\"9\"],"
     "\"option_keys\":[],\"option_values\":[]}}", cid);
 
@@ -1037,7 +663,7 @@
   Service::HandleIsolateMessage(isolate, service_msg);
   handler.HandleNextMessage();
   ExpectSubstringF(handler.msg(),
-    "{\"type\":\"Error\",\"id\":\"\",\"message\":\"Function 9 not found\","
+    "{\"type\":\"Error\",\"message\":\"Function 9 not found\","
     "\"request\":{\"arguments\":[\"classes\",\"%" Pd "\",\"functions\",\"9\"],"
     "\"option_keys\":[],\"option_values\":[]}}", cid);
 
@@ -1049,7 +675,7 @@
   Service::HandleIsolateMessage(isolate, service_msg);
   handler.HandleNextMessage();
   ExpectSubstringF(handler.msg(),
-    "{\"type\":\"Error\",\"id\":\"\",\"message\":\"Command too long\","
+    "{\"type\":\"Error\",\"message\":\"Command too long\","
     "\"request\":"
     "{\"arguments\":[\"classes\",\"%" Pd "\",\"fields\",\"9\",\"x\"],"
     "\"option_keys\":[],\"option_values\":[]}}", cid);
@@ -1061,7 +687,7 @@
   Service::HandleIsolateMessage(isolate, service_msg);
   handler.HandleNextMessage();
   ExpectSubstringF(handler.msg(),
-    "{\"type\":\"Error\",\"id\":\"\","
+    "{\"type\":\"Error\","
     "\"message\":\"Command should have 4 or 5 arguments\","
     "\"request\":"
     "{\"arguments\":[\"classes\",\"%" Pd "\",\"functions\",\"0\",\"x\",\"y\"],"
@@ -1074,7 +700,7 @@
   Service::HandleIsolateMessage(isolate, service_msg);
   handler.HandleNextMessage();
   ExpectSubstringF(handler.msg(),
-    "{\"type\":\"Error\",\"id\":\"\",\"message\":\"Invalid sub command x\","
+    "{\"type\":\"Error\",\"message\":\"Invalid sub command x\","
     "\"request\":"
     "{\"arguments\":[\"classes\",\"%" Pd "\",\"functions\",\"b\",\"x\"],"
     "\"option_keys\":[],\"option_values\":[]}}", cid);
@@ -1084,16 +710,17 @@
   EXPECT(!class_b.IsNull());
   const Instance& b0 = Instance::Handle(Instance::New(class_b));
   const Instance& b1 = Instance::Handle(Instance::New(class_b));
-  service_msg = EvalF(lib, "[0, port, ['classes', '%" Pd "', 'retained'],"
-                      "[], []]", class_b.id());
+  service_msg = EvalF(lib, "[0, port, 'getRetainedSize', "
+                      "['targetId'], ['classes/%" Pd "']]", class_b.id());
   Service::HandleIsolateMessage(isolate, service_msg);
   handler.HandleNextMessage();
   ExpectSubstringF(handler.msg(),
                    "\"id\":\"objects\\/int-%" Pd "\"",
                    b0.raw()->Size() + b1.raw()->Size());
   // ... and list the instances of class B.
-  service_msg = EvalF(lib, "[0, port, ['classes', '%" Pd "', 'instances'],"
-                      "['limit'], ['3']]", class_b.id());
+  service_msg = EvalF(lib, "[0, port, 'getInstances', "
+                      "['classId', 'limit'], ['classes/%" Pd "', '3']]",
+                      class_b.id());
   Service::HandleIsolateMessage(isolate, service_msg);
   handler.HandleNextMessage();
   ExpectSubstringF(handler.msg(), "\"type\":\"InstanceSet\"");
@@ -1111,8 +738,9 @@
   EXPECT((list.At(0) == b0.raw() && list.At(1) == b1.raw()) ||
          (list.At(0) == b1.raw() && list.At(1) == b0.raw()));
   // ... and if limit is 1, we one get one of them.
-  service_msg = EvalF(lib, "[0, port, ['classes', '%" Pd "', 'instances'],"
-                      "['limit'], ['1']]", class_b.id());
+  service_msg = EvalF(lib, "[0, port, 'getInstances', "
+                      "['classId', 'limit'], ['classes/%" Pd "', '1']]",
+                      class_b.id());
   Service::HandleIsolateMessage(isolate, service_msg);
   handler.HandleNextMessage();
   ExpectSubstringF(handler.msg(), "\"totalCount\":2");
@@ -1307,27 +935,11 @@
   Service::HandleIsolateMessage(isolate, service_msg);
   handler.HandleNextMessage();
   ExpectSubstringF(handler.msg(),
-    "{\"type\":\"Error\",\"id\":\"\","
+    "{\"type\":\"Error\","
     "\"message\":\"Canonical type 42 not found\""
     ",\"request\":"
     "{\"arguments\":[\"classes\",\"%" Pd "\",\"types\",\"42\"],"
     "\"option_keys\":[],\"option_values\":[]}}", cid);
-
-  // Request canonical type arguments. Expect <A<bool>> to be listed.
-  service_msg = EvalF(lib, "[0, port, ['typearguments'],"
-                      "[], []]");
-  Service::HandleIsolateMessage(isolate, service_msg);
-  handler.HandleNextMessage();
-  EXPECT_SUBSTRING("\"type\":\"TypeArgumentsList\"", handler.msg());
-  ExpectSubstringF(handler.msg(), "\"name\":\"<A<bool>>\",");
-
-  // Request canonical type arguments with instantiations.
-  service_msg = EvalF(lib,
-                      "[0, port, ['typearguments', 'withinstantiations'],"
-                      "[], []]");
-  Service::HandleIsolateMessage(isolate, service_msg);
-  handler.HandleNextMessage();
-  EXPECT_SUBSTRING("\"type\":\"TypeArgumentsList\"", handler.msg());
 }
 
 
@@ -1383,7 +995,7 @@
   Service::HandleIsolateMessage(isolate, service_msg);
   handler.HandleNextMessage();
   EXPECT_STREQ(
-    "{\"type\":\"Error\",\"id\":\"\",\"message\":\"Malformed code id: 0\","
+    "{\"type\":\"Error\",\"message\":\"Malformed code id: 0\","
     "\"request\":{\"arguments\":[\"code\",\"0\"],"
     "\"option_keys\":[],\"option_values\":[]}}", handler.msg());
 
@@ -1755,281 +1367,6 @@
 }
 
 
-// TODO(zra): Remove when tests are ready to enable.
-#if !defined(TARGET_ARCH_ARM64)
-
-TEST_CASE(Service_Coverage) {
-  const char* kScript =
-      "var port;\n"  // Set to our mock port by C++.
-      "\n"
-      "var x = 7;\n"
-      "main() {\n"
-      "  x = x * x;\n"
-      "  x = x / 13;\n"
-      "}";
-
-  Isolate* isolate = Isolate::Current();
-  Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
-  EXPECT_VALID(lib);
-  Library& vmlib = Library::Handle();
-  vmlib ^= Api::UnwrapHandle(lib);
-  EXPECT(!vmlib.IsNull());
-  Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL);
-  EXPECT_VALID(result);
-
-  // Build a mock message handler and wrap it in a dart port.
-  ServiceTestMessageHandler handler;
-  Dart_Port port_id = PortMap::CreatePort(&handler);
-  Dart_Handle port = Api::NewHandle(isolate, SendPort::New(port_id));
-  EXPECT_VALID(port);
-  EXPECT_VALID(Dart_SetField(lib, NewString("port"), port));
-
-  Array& service_msg = Array::Handle();
-  service_msg = Eval(lib, "[0, port, ['coverage'], [], []]");
-  Service::HandleIsolateMessage(isolate, service_msg);
-  handler.HandleNextMessage();
-
-  char buf[1024];
-  OS::SNPrint(buf, sizeof(buf),
-              "{\"source\":\"test-lib\",\"script\":{\"type\":\"@Script\","
-              "\"id\":\"libraries\\/%" Pd "\\/scripts\\/test-lib\","
-              "\"name\":\"test-lib\","
-              "\"kind\":\"script\"},\"hits\":"
-              "[5,1,6,1]}",
-              vmlib.index());
-  EXPECT_SUBSTRING(buf, handler.msg());
-}
-
-
-TEST_CASE(Service_LibrariesScriptsCoverage) {
-  const char* kScript =
-      "var port;\n"  // Set to our mock port by C++.
-      "\n"
-      "var x = 7;\n"
-      "main() {\n"
-      "  x = x * x;\n"
-      "  x = x / 13;\n"
-      "}";
-
-  Isolate* isolate = Isolate::Current();
-  Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
-  EXPECT_VALID(lib);
-  Library& vmlib = Library::Handle();
-  vmlib ^= Api::UnwrapHandle(lib);
-  EXPECT(!vmlib.IsNull());
-  Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL);
-  EXPECT_VALID(result);
-
-  // Build a mock message handler and wrap it in a dart port.
-  ServiceTestMessageHandler handler;
-  Dart_Port port_id = PortMap::CreatePort(&handler);
-  Dart_Handle port = Api::NewHandle(isolate, SendPort::New(port_id));
-  EXPECT_VALID(port);
-  EXPECT_VALID(Dart_SetField(lib, NewString("port"), port));
-
-  Array& service_msg = Array::Handle();
-  char buf[1024];
-  OS::SNPrint(buf, sizeof(buf),
-      "[0, port, ['libraries', '%" Pd  "', 'scripts', 'test-lib', 'coverage'], "
-      "[], []]",
-      vmlib.index());
-
-  service_msg = Eval(lib, buf);
-  Service::HandleIsolateMessage(isolate, service_msg);
-  handler.HandleNextMessage();
-  OS::SNPrint(buf, sizeof(buf),
-      "{\"type\":\"CodeCoverage\",\"id\":\"coverage\",\"coverage\":["
-      "{\"source\":\"test-lib\",\"script\":{\"type\":\"@Script\","
-      "\"id\":\"libraries\\/%" Pd "\\/scripts\\/test-lib\","
-      "\"name\":\"test-lib\","
-      "\"kind\":\"script\"},\"hits\":[5,1,6,1]}]}", vmlib.index());
-  EXPECT_STREQ(buf, handler.msg());
-}
-
-
-TEST_CASE(Service_LibrariesCoverage) {
-  const char* kScript =
-      "var port;\n"  // Set to our mock port by C++.
-      "\n"
-      "var x = 7;\n"
-      "main() {\n"
-      "  x = x * x;\n"
-      "  x = x / 13;\n"
-      "}";
-
-  Isolate* isolate = Isolate::Current();
-  Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
-  EXPECT_VALID(lib);
-  Library& vmlib = Library::Handle();
-  vmlib ^= Api::UnwrapHandle(lib);
-  EXPECT(!vmlib.IsNull());
-  Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL);
-  EXPECT_VALID(result);
-
-  // Build a mock message handler and wrap it in a dart port.
-  ServiceTestMessageHandler handler;
-  Dart_Port port_id = PortMap::CreatePort(&handler);
-  Dart_Handle port = Api::NewHandle(isolate, SendPort::New(port_id));
-  EXPECT_VALID(port);
-  EXPECT_VALID(Dart_SetField(lib, NewString("port"), port));
-
-  char buf[1024];
-  OS::SNPrint(buf, sizeof(buf),
-              "[0, port, ['libraries', '%" Pd "', 'coverage'], [], []]",
-              vmlib.index());
-
-  Array& service_msg = Array::Handle();
-  service_msg = Eval(lib, buf);
-  Service::HandleIsolateMessage(isolate, service_msg);
-  handler.HandleNextMessage();
-  OS::SNPrint(buf, sizeof(buf),
-              "{\"type\":\"CodeCoverage\",\"id\":\"coverage\",\"coverage\":["
-              "{\"source\":\"test-lib\",\"script\":{\"type\":\"@Script\","
-              "\"id\":\"libraries\\/%" Pd "\\/scripts\\/test-lib\","
-              "\"name\":\"test-lib\","
-              "\"kind\":\"script\"},\"hits\":[5,1,6,1]}]}",
-              vmlib.index());
-  EXPECT_STREQ(buf, handler.msg());
-}
-
-
-TEST_CASE(Service_ClassesCoverage) {
-  const char* kScript =
-      "var port;\n"  // Set to our mock port by C++.
-      "\n"
-      "class Foo {\n"
-      "  var x;\n"
-      "  Foo(this.x);\n"
-      "  bar() {\n"
-      "    x = x * x;\n"
-      "    x = x / 13;\n"
-      "  }\n"
-      "}\n"
-      "main() {\n"
-      "  var foo = new Foo(7);\n"
-      "  foo.bar();\n"
-      "}";
-
-  Isolate* isolate = Isolate::Current();
-  Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
-  EXPECT_VALID(lib);
-  Library& vmlib = Library::Handle();
-  vmlib ^= Api::UnwrapHandle(lib);
-  EXPECT(!vmlib.IsNull());
-  Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL);
-  EXPECT_VALID(result);
-
-  // Build a mock message handler and wrap it in a dart port.
-  ServiceTestMessageHandler handler;
-  Dart_Port port_id = PortMap::CreatePort(&handler);
-  Dart_Handle port = Api::NewHandle(isolate, SendPort::New(port_id));
-  EXPECT_VALID(port);
-  EXPECT_VALID(Dart_SetField(lib, NewString("port"), port));
-
-  // Look up the service id of Foo.
-  const Class& cls = Class::Handle(
-      vmlib.LookupClass(String::Handle(String::New("Foo"))));
-  ASSERT(!cls.IsNull());
-  ClassTable* table = isolate->class_table();
-  intptr_t i;
-  for (i = 1; i < table->NumCids(); i++) {
-    if (table->HasValidClassAt(i) && table->At(i) == cls.raw()) {
-      break;
-    }
-  }
-  ASSERT(i != table->NumCids());
-  char buf[1024];
-  OS::SNPrint(buf, sizeof(buf),
-              "[0, port, ['classes', '%" Pd "', 'coverage'], [], []]", i);
-
-  Array& service_msg = Array::Handle();
-  service_msg = Eval(lib, buf);
-  Service::HandleIsolateMessage(isolate, service_msg);
-  handler.HandleNextMessage();
-  OS::SNPrint(buf, sizeof(buf),
-              "{\"type\":\"CodeCoverage\",\"id\":\"coverage\",\"coverage\":["
-              "{\"source\":\"test-lib\",\"script\":{\"type\":\"@Script\","
-              "\"id\":\"libraries\\/%" Pd "\\/scripts\\/test-lib\","
-              "\"name\":\"test-lib\","
-              "\"kind\":\"script\"},\"hits\":[5,1,7,4,8,3]}]}",
-              vmlib.index());
-  EXPECT_STREQ(buf, handler.msg());
-}
-
-
-TEST_CASE(Service_ClassesFunctionsCoverage) {
-  const char* kScript =
-      "var port;\n"  // Set to our mock port by C++.
-      "\n"
-      "class Foo {\n"
-      "  var x;\n"
-      "  Foo(this.x);\n"
-      "  bar() {\n"
-      "    x = x * x;\n"
-      "    x = x / 13;\n"
-      "  }\n"
-      "  badum(var a) => 4 + a;\n"
-      "}\n"
-      "main() {\n"
-      "  var foo = new Foo(7);\n"
-      "  foo.bar();\n"
-      "}";
-
-  Isolate* isolate = Isolate::Current();
-  Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
-  EXPECT_VALID(lib);
-  Library& vmlib = Library::Handle();
-  vmlib ^= Api::UnwrapHandle(lib);
-  EXPECT(!vmlib.IsNull());
-  Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL);
-  EXPECT_VALID(result);
-
-  // Build a mock message handler and wrap it in a dart port.
-  ServiceTestMessageHandler handler;
-  Dart_Port port_id = PortMap::CreatePort(&handler);
-  Dart_Handle port = Api::NewHandle(isolate, SendPort::New(port_id));
-  EXPECT_VALID(port);
-  EXPECT_VALID(Dart_SetField(lib, NewString("port"), port));
-
-  // Look up the service id of Foo.
-  const Class& cls = Class::Handle(
-      vmlib.LookupClass(String::Handle(String::New("Foo"))));
-  ASSERT(!cls.IsNull());
-  ClassTable* table = isolate->class_table();
-  intptr_t i;
-  for (i = 1; i < table->NumCids(); i++) {
-    if (table->HasValidClassAt(i) && table->At(i) == cls.raw()) {
-      break;
-    }
-  }
-  ASSERT(i != table->NumCids());
-
-  // Look up the service if of the function Foo.bar.
-  const Function& func = Function::Handle(
-      cls.LookupFunction(String::Handle(String::New("bar"))));
-  ASSERT(!func.IsNull());
-
-  char buf[1024];
-  OS::SNPrint(buf, sizeof(buf),
-              "[0, port, ['classes', '%" Pd "', 'functions',"
-              "'bar', 'coverage'], [], []]", i);
-
-  Array& service_msg = Array::Handle();
-  service_msg = Eval(lib, buf);
-  Service::HandleIsolateMessage(isolate, service_msg);
-  handler.HandleNextMessage();
-  OS::SNPrint(buf, sizeof(buf),
-      "{\"type\":\"CodeCoverage\",\"id\":\"coverage\",\"coverage\":["
-      "{\"source\":\"test-lib\",\"script\":{\"type\":\"@Script\","
-      "\"id\":\"libraries\\/%" Pd "\\/scripts\\/test-lib\","
-      "\"name\":\"test-lib\","
-      "\"kind\":\"script\"},\"hits\":[7,4,8,3]}]}", vmlib.index());
-  EXPECT_STREQ(buf, handler.msg());
-}
-
-#endif
-
-
 TEST_CASE(Service_AllocationProfile) {
   const char* kScript =
       "var port;\n"  // Set to our mock port by C++.
@@ -2054,48 +1391,44 @@
   EXPECT_VALID(Dart_SetField(lib, NewString("port"), port));
 
   Array& service_msg = Array::Handle();
-  service_msg = Eval(lib, "[0, port, ['allocationprofile'], [], []]");
+  service_msg = Eval(lib, "[0, port, 'getAllocationProfile', [], []]");
   Service::HandleIsolateMessage(isolate, service_msg);
   handler.HandleNextMessage();
   EXPECT_SUBSTRING("\"type\":\"AllocationProfile\"", handler.msg());
 
-  // Too long.
-  service_msg = Eval(lib, "[0, port, ['allocationprofile', 'foo'], [], []]");
-  Service::HandleIsolateMessage(isolate, service_msg);
-  handler.HandleNextMessage();
-  EXPECT_SUBSTRING("\"type\":\"Error\"", handler.msg());
-
   // Bad gc option.
   service_msg = Eval(lib,
-                     "[0, port, ['allocationprofile'], ['gc'], ['cat']]");
+                     "[0, port, 'getAllocationProfile', "
+                     "['gc'], ['cat']]");
   Service::HandleIsolateMessage(isolate, service_msg);
   handler.HandleNextMessage();
   EXPECT_SUBSTRING("\"type\":\"Error\"", handler.msg());
 
   // Bad reset option.
-  service_msg = Eval(lib,
-                     "[0, port, ['allocationprofile'], ['reset'], ['ff']]");
+  service_msg = Eval(lib, "[0, port, 'getAllocationProfile', "
+                          "['reset'], ['ff']]");
   Service::HandleIsolateMessage(isolate, service_msg);
   handler.HandleNextMessage();
   EXPECT_SUBSTRING("\"type\":\"Error\"", handler.msg());
 
   // Good reset.
   service_msg =
-      Eval(lib, "[0, port, ['allocationprofile'], ['reset'], ['true']]");
+      Eval(lib,
+           "[0, port, 'getAllocationProfile', ['reset'], ['true']]");
   Service::HandleIsolateMessage(isolate, service_msg);
   handler.HandleNextMessage();
   EXPECT_SUBSTRING("\"type\":\"AllocationProfile\"", handler.msg());
 
   // Good GC.
   service_msg =
-      Eval(lib, "[0, port, ['allocationprofile'], ['gc'], ['full']]");
+      Eval(lib, "[0, port, 'getAllocationProfile', ['gc'], ['full']]");
   Service::HandleIsolateMessage(isolate, service_msg);
   handler.HandleNextMessage();
   EXPECT_SUBSTRING("\"type\":\"AllocationProfile\"", handler.msg());
 
   // Good GC and reset.
-  service_msg = Eval(lib,
-      "[0, port, ['allocationprofile'], ['gc', 'reset'], ['full', 'true']]");
+  service_msg = Eval(lib, "[0, port, 'getAllocationProfile', "
+                          "['gc', 'reset'], ['full', 'true']]");
   Service::HandleIsolateMessage(isolate, service_msg);
   handler.HandleNextMessage();
   EXPECT_SUBSTRING("\"type\":\"AllocationProfile\"", handler.msg());
@@ -2121,7 +1454,7 @@
   EXPECT_VALID(Dart_SetField(lib, NewString("port"), port));
 
   Array& service_msg = Array::Handle();
-  service_msg = Eval(lib, "[0, port, ['heapmap'], [], []]");
+  service_msg = Eval(lib, "[0, port, 'getHeapMap', [], []]");
   Service::HandleIsolateMessage(isolate, service_msg);
   handler.HandleNextMessage();
   EXPECT_SUBSTRING("\"type\":\"HeapMap\"", handler.msg());
@@ -2306,19 +1639,21 @@
   EXPECT_VALID(Dart_SetField(lib, NewString("port"), port));
 
   Array& service_msg = Array::Handle();
-  service_msg = Eval(lib, "[0, port, ['profile'], [], []]");
+  service_msg = Eval(lib, "[0, port, 'getCpuProfile', [], []]");
   Service::HandleIsolateMessage(isolate, service_msg);
   handler.HandleNextMessage();
   // Expect profile
-  EXPECT_SUBSTRING("\"type\":\"Profile\"", handler.msg());
+  EXPECT_SUBSTRING("\"type\":\"CpuProfile\"", handler.msg());
 
-  service_msg = Eval(lib, "[0, port, ['profile'], ['tags'], ['hide']]");
+  service_msg =
+      Eval(lib, "[0, port, 'getCpuProfile', ['tags'], ['None']]");
   Service::HandleIsolateMessage(isolate, service_msg);
   handler.HandleNextMessage();
   // Expect profile
-  EXPECT_SUBSTRING("\"type\":\"Profile\"", handler.msg());
+  EXPECT_SUBSTRING("\"type\":\"CpuProfile\"", handler.msg());
 
-  service_msg = Eval(lib, "[0, port, ['profile'], ['tags'], ['hidden']]");
+  service_msg =
+      Eval(lib, "[0, port, 'getCpuProfile', ['tags'], ['Bogus']]");
   Service::HandleIsolateMessage(isolate, service_msg);
   handler.HandleNextMessage();
   // Expect error.
diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h
index c3e7b3e..73e0b18 100644
--- a/runtime/vm/symbols.h
+++ b/runtime/vm/symbols.h
@@ -84,6 +84,7 @@
   V(AsyncOperation, ":async_op")                                               \
   V(AsyncOperationParam, ":async_result")                                      \
   V(AsyncOperationErrorParam, ":async_error_param")                            \
+  V(AsyncOperationStackTraceParam, ":async_stack_trace_param")                 \
   V(AsyncCatchHelper, "_asyncCatchHelper")                                     \
   V(Await, "await")                                                            \
   V(AwaitContextVar, ":await_ctx_var")                                         \
diff --git a/runtime/vm/unit_test.h b/runtime/vm/unit_test.h
index 01aac9d..41695ed 100644
--- a/runtime/vm/unit_test.h
+++ b/runtime/vm/unit_test.h
@@ -264,11 +264,12 @@
                                         Dart_NativeEntryResolver resolver);
   static Dart_Handle lib();
   static const char* url() { return USER_TEST_URI; }
-  static Dart_Isolate CreateTestIsolateFromSnapshot(uint8_t* buffer) {
-    return CreateIsolate(buffer);
+  static Dart_Isolate CreateTestIsolateFromSnapshot(
+      uint8_t* buffer, const char* name = NULL) {
+    return CreateIsolate(buffer, name);
   }
-  static Dart_Isolate CreateTestIsolate() {
-    return CreateIsolate(bin::snapshot_buffer);
+  static Dart_Isolate CreateTestIsolate(const char* name = NULL) {
+    return CreateIsolate(bin::snapshot_buffer, name);
   }
   static Dart_Handle library_handler(Dart_LibraryTag tag,
                                      Dart_Handle library,
@@ -278,9 +279,10 @@
   virtual void Run();
 
  private:
-  static Dart_Isolate CreateIsolate(const uint8_t* buffer) {
+  static Dart_Isolate CreateIsolate(const uint8_t* buffer,
+                                    const char* name) {
     char* err;
-    Dart_Isolate isolate = Dart_CreateIsolate(NULL, NULL, buffer, NULL, &err);
+    Dart_Isolate isolate = Dart_CreateIsolate(name, NULL, buffer, NULL, &err);
     if (isolate == NULL) {
       OS::Print("Creation of isolate failed '%s'\n", err);
       free(err);
diff --git a/sdk/bin/dart2js b/sdk/bin/dart2js
index 4fe517f..f448ba8 100755
--- a/sdk/bin/dart2js
+++ b/sdk/bin/dart2js
@@ -36,12 +36,6 @@
 unset EXTRA_VM_OPTIONS
 declare -a EXTRA_VM_OPTIONS
 
-# Tell the VM to grow the heap more aggressively. This should only
-# be necessary temporarily until the VM is better at detecting how
-# applications use memory.
-# TODO(ahe): Remove this option (http://dartbug.com/6495).
-EXTRA_VM_OPTIONS[${#EXTRA_VM_OPTIONS[@]}]='--heap_growth_rate=512'
-
 case $0 in
   *_developer)
     EXTRA_VM_OPTIONS+=('--checked')
diff --git a/sdk/bin/dart2js.bat b/sdk/bin/dart2js.bat
index daa477a..9e765d9 100644
--- a/sdk/bin/dart2js.bat
+++ b/sdk/bin/dart2js.bat
@@ -26,9 +26,6 @@
   set EXTRA_VM_OPTIONS=%EXTRA_VM_OPTIONS% --checked
 )
 
-rem See comments regarding options below in dart2js shell script.
-set EXTRA_VM_OPTIONS=%EXTRA_VM_OPTIONS% --heap_growth_rate=512
-
 rem We allow extra vm options to be passed in through an environment variable.
 if not "_%DART_VM_OPTIONS%_" == "__" (
   set EXTRA_VM_OPTIONS=%EXTRA_VM_OPTIONS% %DART_VM_OPTIONS%
diff --git a/sdk/bin/dart2js_sdk b/sdk/bin/dart2js_sdk
index 5d7ec9c..36b42a4 100755
--- a/sdk/bin/dart2js_sdk
+++ b/sdk/bin/dart2js_sdk
@@ -43,12 +43,6 @@
   EXTRA_OPTIONS+=("--library-root=$SDK_DIR")
 fi
 
-# Tell the VM to grow the heap more aggressively. This should only
-# be necessary temporarily until the VM is better at detecting how
-# applications use memory.
-# TODO(ahe): Remove this option (http://dartbug.com/6495).
-EXTRA_VM_OPTIONS[${#EXTRA_VM_OPTIONS[@]}]='--heap_growth_rate=512'
-
 case $0 in
   *_developer)
     EXTRA_VM_OPTIONS+=('--checked')
diff --git a/sdk/bin/dart2js_sdk.bat b/sdk/bin/dart2js_sdk.bat
index f5ed1f0..696c713 100755
--- a/sdk/bin/dart2js_sdk.bat
+++ b/sdk/bin/dart2js_sdk.bat
@@ -31,9 +31,6 @@
   set EXTRA_OPTIONS=%EXTRA_OPTIONS% "--library-root=%SDK_DIR%"
 )
 
-rem See comments regarding options below in dart2js shell script.
-set EXTRA_VM_OPTIONS=%EXTRA_VM_OPTIONS% --heap_growth_rate=512
-
 rem We allow extra vm options to be passed in through an environment variable.
 if not "_%DART_VM_OPTIONS%_" == "__" (
   set EXTRA_VM_OPTIONS=%EXTRA_VM_OPTIONS% %DART_VM_OPTIONS%
diff --git a/sdk/lib/_internal/compiler/js_lib/annotations.dart b/sdk/lib/_internal/compiler/js_lib/annotations.dart
index 1e63cf9..435221d 100644
--- a/sdk/lib/_internal/compiler/js_lib/annotations.dart
+++ b/sdk/lib/_internal/compiler/js_lib/annotations.dart
@@ -34,3 +34,18 @@
   final String name;
   const Native(this.name);
 }
+
+class _Patch {
+  final String version;
+
+  const _Patch(this.version);
+}
+
+/// Annotation that marks the declaration as a patch.
+const _Patch patch = const _Patch(null);
+
+/// Annotation that marks the declaration as a patch for the old emitter.
+const _Patch patch_old = const _Patch('old');
+
+/// Annotation that marks the declaration as a patch for the new emitter.
+const _Patch patch_new = const _Patch('new');
diff --git a/sdk/lib/_internal/compiler/js_lib/core_patch.dart b/sdk/lib/_internal/compiler/js_lib/core_patch.dart
index 3fe172b..0485767 100644
--- a/sdk/lib/_internal/compiler/js_lib/core_patch.dart
+++ b/sdk/lib/_internal/compiler/js_lib/core_patch.dart
@@ -6,6 +6,8 @@
 import "dart:_internal" as _symbol_dev;
 import 'dart:_interceptors';
 import 'dart:_js_helper' show patch,
+                              patch_new,
+                              patch_old,
                               checkInt,
                               getRuntimeType,
                               jsonEncodeNative,
@@ -56,7 +58,7 @@
 // Patch for Function implementation.
 @patch
 class Function {
-  @patch
+  @patch_old
   static apply(Function function,
                List positionalArguments,
                [Map<Symbol, dynamic> namedArguments]) {
@@ -65,6 +67,14 @@
         namedArguments == null ? null : _toMangledNames(namedArguments));
   }
 
+  @patch_new
+  static apply(Function function,
+               List positionalArguments,
+               [Map<Symbol, dynamic> namedArguments]) {
+    //TODO(zarah): implement for new emitter.
+    throw new UnsupportedError('Function.apply is currently not supported.');
+  }
+
   static Map<String, dynamic> _toMangledNames(
       Map<Symbol, dynamic> namedArguments) {
     Map<String, dynamic> result = {};
diff --git a/sdk/lib/_internal/compiler/js_lib/interceptors.dart b/sdk/lib/_internal/compiler/js_lib/interceptors.dart
index accb591..7203a7b 100644
--- a/sdk/lib/_internal/compiler/js_lib/interceptors.dart
+++ b/sdk/lib/_internal/compiler/js_lib/interceptors.dart
@@ -6,7 +6,7 @@
 
 import 'dart:_js_embedded_names' show
     DISPATCH_PROPERTY_NAME,
-    MAP_TYPE_TO_INTERCEPTOR;
+    TYPE_TO_INTERCEPTOR_MAP;
 
 import 'dart:collection';
 import 'dart:_internal' hide Symbol;
@@ -185,17 +185,17 @@
  * that are user extensions of native classes where the type occurs as a
  * constant in the program.
  *
- * The compiler, in CustomElementsAnalysis, assumes that [mapTypeToInterceptor]
+ * The compiler, in CustomElementsAnalysis, assumes that [typeToInterceptorMap]
  * is accessed only by code that also calls [findIndexForWebComponentType].  If
  * this assumption is invalidated, the compiler will have to be updated.
  */
-get mapTypeToInterceptor {
-  return JS_EMBEDDED_GLOBAL('', MAP_TYPE_TO_INTERCEPTOR);
+get typeToInterceptorMap {
+  return JS_EMBEDDED_GLOBAL('', TYPE_TO_INTERCEPTOR_MAP);
 }
 
 int findIndexForNativeSubclassType(Type type) {
-  if (JS('bool', '# == null', mapTypeToInterceptor)) return null;
-  List map = JS('JSFixedArray', '#', mapTypeToInterceptor);
+  if (JS('bool', '# == null', typeToInterceptorMap)) return null;
+  List map = JS('JSFixedArray', '#', typeToInterceptorMap);
   for (int i = 0; i + 1 < map.length; i += 3) {
     if (type == map[i]) {
       return i;
@@ -207,7 +207,7 @@
 findInterceptorConstructorForType(Type type) {
   var index = findIndexForNativeSubclassType(type);
   if (index == null) return null;
-  List map = JS('JSFixedArray', '#', mapTypeToInterceptor);
+  List map = JS('JSFixedArray', '#', typeToInterceptorMap);
   return map[index + 1];
 }
 
@@ -220,7 +220,7 @@
 findConstructorForNativeSubclassType(Type type, String name) {
   var index = findIndexForNativeSubclassType(type);
   if (index == null) return null;
-  List map = JS('JSFixedArray', '#', mapTypeToInterceptor);
+  List map = JS('JSFixedArray', '#', typeToInterceptorMap);
   var constructorMap = map[index + 2];
   var constructorFn = JS('', '#[#]', constructorMap, name);
   return constructorFn;
diff --git a/sdk/lib/_internal/compiler/js_lib/io_patch.dart b/sdk/lib/_internal/compiler/js_lib/io_patch.dart
index dace4db..ee38707 100644
--- a/sdk/lib/_internal/compiler/js_lib/io_patch.dart
+++ b/sdk/lib/_internal/compiler/js_lib/io_patch.dart
@@ -276,7 +276,7 @@
        Map<String, String> environment,
        bool includeParentEnvironment: true,
        bool runInShell: false,
-       bool detach: false}) {
+       ProcessStartMode mode: ProcessStartMode.NORMAL}) {
     throw new UnsupportedError("Process.start");
   }
 
@@ -305,6 +305,12 @@
        Encoding stderrEncoding: SYSTEM_ENCODING}) {
     throw new UnsupportedError("Process.runSync");
   }
+
+  @patch
+  static bool killPid(
+      int pid, [ProcessSignal signal = ProcessSignal.SIGTERM]) {
+    throw new UnsupportedError("Process.killPid");
+  }
 }
 
 @patch
@@ -512,7 +518,7 @@
 @patch
 class _FileSystemWatcher {
   @patch
-  static Stream<FileSystemEvent> watch(
+  static Stream<FileSystemEvent> _watch(
       String path, int events, bool recursive) {
     throw new UnsupportedError("_FileSystemWatcher.watch");
   }
diff --git a/sdk/lib/_internal/compiler/js_lib/js_helper.dart b/sdk/lib/_internal/compiler/js_lib/js_helper.dart
index 4cce9fd..7a75198 100644
--- a/sdk/lib/_internal/compiler/js_lib/js_helper.dart
+++ b/sdk/lib/_internal/compiler/js_lib/js_helper.dart
@@ -5,7 +5,7 @@
 library _js_helper;
 
 import 'dart:_js_embedded_names' show
-    ALL_CLASSES,
+    GET_TYPE_FROM_NAME,
     GET_ISOLATE_TAG,
     INTERCEPTED_NAMES,
     INTERCEPTORS_BY_TAG,
@@ -75,15 +75,8 @@
 part 'string_helper.dart';
 part 'js_rti.dart';
 
-class _Patch {
-  const _Patch();
-}
-
-const _Patch patch = const _Patch();
-
-
 /// Marks the internal map in dart2js, so that internal libraries can is-check
-// them.
+/// them.
 abstract class InternalMap {
 }
 
@@ -1963,14 +1956,15 @@
    *
    * Further assumes that [reflectionInfo] is the end of the array created by
    * [dart2js.js_emitter.ContainerBuilder.addMemberMethod] starting with
-   * required parameter count.
+   * required parameter count or, in case of the new emitter, the runtime
+   * representation of the function's type.
    *
    * Caution: this function may be called when building constants.
    * TODO(ahe): Don't call this function when building constants.
    */
   static fromTearOff(receiver,
                      List functions,
-                     List reflectionInfo,
+                     var reflectionInfo,
                      bool isStatic,
                      jsArguments,
                      String propertyName) {
@@ -1984,10 +1978,15 @@
     String name = JS('String|Null', '#.\$stubName', function);
     String callName = JS('String|Null', '#.\$callName', function);
 
-    JS('', '#.\$reflectionInfo = #', function, reflectionInfo);
-    ReflectionInfo info = new ReflectionInfo(function);
+    var functionType;
+    if (reflectionInfo is List) {
+      JS('', '#.\$reflectionInfo = #', function, reflectionInfo);
+      ReflectionInfo info = new ReflectionInfo(function);
+      functionType = info.functionType;
+    } else {
+      functionType = reflectionInfo;
+    }
 
-    var functionType = info.functionType;
 
     // function tmp() {};
     // tmp.prototype = BC.prototype;
@@ -2329,7 +2328,8 @@
   return Closure.fromTearOff(
       receiver,
       JSArray.markFixedList(functions),
-      JSArray.markFixedList(reflectionInfo),
+      reflectionInfo is List ? JSArray.markFixedList(reflectionInfo)
+                             : reflectionInfo,
       JS('bool', '!!#', isStatic),
       jsArguments,
       JS('String', '#', name));
@@ -3148,8 +3148,8 @@
   RuntimeTypePlain(this.name);
 
   toRti() {
-    var allClasses = JS_EMBEDDED_GLOBAL('', ALL_CLASSES);
-    var rti = JS('', '#[#]', allClasses, name);
+    var getTypeFromName = JS_EMBEDDED_GLOBAL('', GET_TYPE_FROM_NAME);
+    var rti = JS('', '#(#)', getTypeFromName, name);
     if (rti == null) throw "no type for '$name'";
     return rti;
   }
@@ -3166,8 +3166,8 @@
 
   toRti() {
     if (rti != null) return rti;
-    var allClasses = JS_EMBEDDED_GLOBAL('', ALL_CLASSES);
-    var result = JS('JSExtendableArray', '[#[#]]', allClasses, name);
+    var getTypeFromName = JS_EMBEDDED_GLOBAL('', GET_TYPE_FROM_NAME);
+    var result = JS('JSExtendableArray', '[#(#)]', getTypeFromName, name);
     if (result[0] == null) {
       throw "no type for '$name<...>'";
     }
diff --git a/sdk/lib/_internal/compiler/js_lib/js_string.dart b/sdk/lib/_internal/compiler/js_lib/js_string.dart
index c7fd9ab..67f37d5 100644
--- a/sdk/lib/_internal/compiler/js_lib/js_string.dart
+++ b/sdk/lib/_internal/compiler/js_lib/js_string.dart
@@ -359,7 +359,7 @@
     return this + padding * delta;
   }
 
-  List<int> get codeUnits => new _CodeUnits(this);
+  List<int> get codeUnits => new CodeUnits(this);
 
   Runes get runes => new Runes(this);
 
@@ -456,16 +456,3 @@
     return JS('String', '#[#]', this, index);
   }
 }
-
-/**
- * An [Iterable] of the UTF-16 code units of a [String] in index order.
- */
-class _CodeUnits extends UnmodifiableListBase<int> {
-  /** The string that this is the code units of. */
-  String _string;
-
-  _CodeUnits(this._string);
-
-  int get length => _string.length;
-  int operator[](int i) => _string.codeUnitAt(i);
-}
diff --git a/sdk/lib/_internal/compiler/js_lib/shared/embedded_names.dart b/sdk/lib/_internal/compiler/js_lib/shared/embedded_names.dart
index bd72f09..aa899bd 100644
--- a/sdk/lib/_internal/compiler/js_lib/shared/embedded_names.dart
+++ b/sdk/lib/_internal/compiler/js_lib/shared/embedded_names.dart
@@ -16,14 +16,17 @@
 const GLOBAL_FUNCTIONS = 'globalFunctions';
 const STATICS = 'statics';
 
-/**
- * If [JSInvocationMirror._invokeOn] is being used, this embedded global
- * contains a JavaScript map with the names of methods that are
- * intercepted.
- */
+/// If [JSInvocationMirror._invokeOn] is being used, this embedded global
+/// contains a JavaScript map with the names of methods that are
+/// intercepted.
 const INTERCEPTED_NAMES = 'interceptedNames';
 
+/// A JS map from mangled global names to their unmangled names.
+///
+/// If the program does not use reflection may be empty (but not null or
+/// undefined).
 const MANGLED_GLOBAL_NAMES = 'mangledGlobalNames';
+
 const MANGLED_NAMES = 'mangledNames';
 const LIBRARIES = 'libraries';
 const FINISHED_CLASSES = 'finishedClasses';
@@ -49,4 +52,8 @@
 const TYPEDEF_PREDICATE_PROPERTY_NAME = r"$$isTypedef";
 const NATIVE_SUPERCLASS_TAG_NAME = r"$nativeSuperclassTag";
 
-const MAP_TYPE_TO_INTERCEPTOR = "mapTypeToInterceptor";
+/// Returns the type given the name of a class.
+/// This function is called by the runtime when computing rti.
+const GET_TYPE_FROM_NAME = 'getTypeFromName';
+const TYPE_TO_INTERCEPTOR_MAP = "typeToInterceptorMap";
+
diff --git a/sdk/lib/_internal/pub/lib/src/barback/transformer_isolate.dart b/sdk/lib/_internal/pub/lib/src/barback/transformer_isolate.dart
index bfd9f66..65ba68f 100644
--- a/sdk/lib/_internal/pub/lib/src/barback/transformer_isolate.dart
+++ b/sdk/lib/_internal/pub/lib/src/barback/transformer_isolate.dart
@@ -93,8 +93,9 @@
         // "package:" URI, so we have to be liberal in what we look for in the
         // error message.
         var missingTransformer = idsToUrls.keys.firstWhere((id) =>
-            firstErrorLine.startsWith("Uncaught Error: Failure getting ") &&
-              firstErrorLine.contains(idsToUrls[id].path),
+            firstErrorLine.startsWith(
+                "Uncaught Error: Load Error: Failure getting ") &&
+            firstErrorLine.contains(idsToUrls[id].path),
             orElse: () => throw error);
         var packageUri = idToPackageUri(idsToAssetIds[missingTransformer]);
 
diff --git a/sdk/lib/_internal/pub/lib/src/pubspec.dart b/sdk/lib/_internal/pub/lib/src/pubspec.dart
index 6781a5c..c772402 100644
--- a/sdk/lib/_internal/pub/lib/src/pubspec.dart
+++ b/sdk/lib/_internal/pub/lib/src/pubspec.dart
@@ -96,9 +96,7 @@
   List<PackageDep> get dependencies {
     if (_dependencies != null) return _dependencies;
     _dependencies = _parseDependencies('dependencies');
-    if (_devDependencies == null) {
-      _checkDependencyOverlap(_dependencies, devDependencies);
-    }
+    _checkDependencyOverlap(_dependencies, _devDependencies);
     return _dependencies;
   }
   List<PackageDep> _dependencies;
@@ -107,9 +105,7 @@
   List<PackageDep> get devDependencies {
     if (_devDependencies != null) return _devDependencies;
     _devDependencies = _parseDependencies('dev_dependencies');
-    if (_dependencies == null) {
-      _checkDependencyOverlap(dependencies, _devDependencies);
-    }
+    _checkDependencyOverlap(_dependencies, _devDependencies);
     return _devDependencies;
   }
   List<PackageDep> _devDependencies;
@@ -334,7 +330,7 @@
           Iterable<PackageDep> dependencyOverrides,
           VersionConstraint sdkConstraint,
           Iterable<Iterable<TransformerConfig>> transformers,
-           Map fields, SourceRegistry sources})
+          Map fields, SourceRegistry sources})
       : _version = version,
         _dependencies = dependencies == null ? null : dependencies.toList(),
         _devDependencies = devDependencies == null ? null :
@@ -517,6 +513,9 @@
   /// dependency.
   void _checkDependencyOverlap(List<PackageDep> dependencies,
       List<PackageDep> devDependencies) {
+    if (dependencies == null) return;
+    if (devDependencies == null) return;
+
     var dependencyNames = dependencies.map((dep) => dep.name).toSet();
     var collisions = dependencyNames.intersection(
         devDependencies.map((dep) => dep.name).toSet());
diff --git a/sdk/lib/_internal/pub/lib/src/solver/backtracking_solver.dart b/sdk/lib/_internal/pub/lib/src/solver/backtracking_solver.dart
index b339dd2..a9b84e3 100644
--- a/sdk/lib/_internal/pub/lib/src/solver/backtracking_solver.dart
+++ b/sdk/lib/_internal/pub/lib/src/solver/backtracking_solver.dart
@@ -126,7 +126,7 @@
   ///
   /// Completes with a list of specific package versions if successful or an
   /// error if it failed to find a solution.
-  Future<SolveResult> solve() async {
+  Future<SolveResult> solve() {
     var stopwatch = new Stopwatch();
 
     _logParameters();
@@ -135,35 +135,40 @@
     var overrides = _overrides.values.toList();
     overrides.sort((a, b) => a.name.compareTo(b.name));
 
-    try {
+    // TODO(nweiz): Use async/await here once
+    // https://github.com/dart-lang/async_await/issues/79 is fixed.
+    return new Future.sync(() {
       stopwatch.start();
 
       // Pre-cache the root package's known pubspec.
       cache.cache(new PackageId.root(root), root.pubspec);
 
       _validateSdkConstraint(root.pubspec);
-      var packages = await _traverseSolution();
+      return _traverseSolution();
+    }).then((packages) {
       var pubspecs = new Map.fromIterable(packages,
           key: (id) => id.name,
           value: (id) => cache.getCachedPubspec(id));
 
-      packages = await Future.wait(
-          packages.map((id) => sources[id.source].resolveId(id)));
-
-      return new SolveResult.success(sources, root, lockFile, packages,
-          overrides, pubspecs, _getAvailableVersions(packages),
-          attemptedSolutions);
-    } on SolveFailure catch (error) {
+      return Future.wait(
+              packages.map((id) => sources[id.source].resolveId(id)))
+          .then((packages) {
+        return new SolveResult.success(sources, root, lockFile, packages,
+            overrides, pubspecs, _getAvailableVersions(packages),
+            attemptedSolutions);
+      });
+    }).catchError((error) {
+      if (error is! SolveFailure) throw error;
       // Wrap a failure in a result so we can attach some other data.
       return new SolveResult.failure(sources, root, lockFile, overrides,
           error, attemptedSolutions);
-    } finally {
+    }).whenComplete(() {
       // Gather some solving metrics.
       var buffer = new StringBuffer();
       buffer.writeln('${runtimeType} took ${stopwatch.elapsed} seconds.');
       buffer.writeln(cache.describeResults());
       log.solver(buffer);
-    }
+    });
   }
 
   /// Generates a map containing all of the known available versions for each
diff --git a/sdk/lib/_internal/pub/lib/src/source/path.dart b/sdk/lib/_internal/pub/lib/src/source/path.dart
index c1fbd52..8786968 100644
--- a/sdk/lib/_internal/pub/lib/src/source/path.dart
+++ b/sdk/lib/_internal/pub/lib/src/source/path.dart
@@ -95,10 +95,14 @@
     // Resolve the path relative to the containing file path, and remember
     // whether the original path was relative or absolute.
     var isRelative = p.isRelative(description);
-    if (p.isRelative(description)) {
-      // Can't handle relative paths coming from pubspecs that are not on the
-      // local file system.
-      assert(containingPath != null);
+    if (isRelative) {
+      // Relative paths coming from pubspecs that are not on the local file
+      // system aren't allowed. This can happen if a hosted or git dependency
+      // has a path dependency.
+      if (containingPath == null) {
+        throw new FormatException('"$description" is a relative path, but this '
+            'isn\'t a local pubspec.');
+      }
 
       description = p.normalize(
           p.join(p.dirname(containingPath), description));
diff --git a/sdk/lib/_internal/pub/test/get/hosted/gets_a_package_with_busted_dev_dependencies_test.dart b/sdk/lib/_internal/pub/test/get/hosted/gets_a_package_with_busted_dev_dependencies_test.dart
new file mode 100644
index 0000000..2b8f2bf
--- /dev/null
+++ b/sdk/lib/_internal/pub/test/get/hosted/gets_a_package_with_busted_dev_dependencies_test.dart
@@ -0,0 +1,32 @@
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library pub_tests;
+
+import '../../../lib/src/exit_codes.dart' as exit_codes;
+import '../../descriptor.dart' as d;
+import '../../test_pub.dart';
+
+main() {
+  initConfig();
+
+  // Regression test for issue 22194.
+  integration('gets a dependency with broken dev dependencies from a pub '
+      'server', () {
+    servePackages((builder) {
+      builder.serve("foo", "1.2.3", pubspec: {
+        "dev_dependencies": {
+          "busted": {"not a real source": null}
+        }
+      });
+    });
+
+    d.appDir({"foo": "1.2.3"}).create();
+
+    pubGet();
+
+    d.cacheDir({"foo": "1.2.3"}).validate();
+    d.packagesDir({"foo": "1.2.3"}).validate();
+  });
+}
diff --git a/sdk/lib/_internal/pub/test/pubspec_test.dart b/sdk/lib/_internal/pub/test/pubspec_test.dart
index 542961d..4fddbd4 100644
--- a/sdk/lib/_internal/pub/test/pubspec_test.dart
+++ b/sdk/lib/_internal/pub/test/pubspec_test.dart
@@ -12,6 +12,7 @@
 import '../lib/src/package.dart';
 import '../lib/src/pubspec.dart';
 import '../lib/src/source.dart';
+import '../lib/src/source/path.dart';
 import '../lib/src/source_registry.dart';
 import 'test_pub.dart';
 
@@ -44,6 +45,7 @@
   group('parse()', () {
     var sources = new SourceRegistry();
     sources.register(new MockSource());
+    sources.register(new PathSource());
 
     var throwsPubspecException =
       throwsA(new isInstanceOf<PubspecException>('PubspecException'));
@@ -160,16 +162,19 @@
     });
 
     test("throws if a package is in dependencies and dev_dependencies", () {
-      var contents = '''
+      expectPubspecException('''
 dependencies:
   foo:
     mock: ok
 dev_dependencies:
   foo:
     mock: ok
-''';
-      expectPubspecException(contents, (pubspec) => pubspec.dependencies);
-      expectPubspecException(contents, (pubspec) => pubspec.devDependencies);
+''', (pubspec) {
+        // This check only triggers if both [dependencies] and [devDependencies]
+        // are accessed.
+        pubspec.dependencies;
+        pubspec.devDependencies;
+      });
     });
 
     test("throws if it dependes on itself", () {
@@ -390,6 +395,16 @@
       expect(pubspec.dependencies, isEmpty);
     });
 
+    test("throws a useful error for unresolvable path dependencies", () {
+      expectPubspecException('''
+name: pkg
+dependencies:
+  from_path: {path: non_local_path}
+''', (pubspec) => pubspec.dependencies,
+          '"non_local_path" is a relative path, but this isn\'t a local '
+          'pubspec.');
+    });
+
     group("environment", () {
       test("defaults to any SDK constraint if environment is omitted", () {
         var pubspec = new Pubspec.parse('', sources);
diff --git a/sdk/lib/_internal/pub/test/transformer/fails_to_load_a_transform_with_an_import_error_test.dart b/sdk/lib/_internal/pub/test/transformer/fails_to_load_a_transform_with_an_import_error_test.dart
index 436f13a..73b1e06 100644
--- a/sdk/lib/_internal/pub/test/transformer/fails_to_load_a_transform_with_an_import_error_test.dart
+++ b/sdk/lib/_internal/pub/test/transformer/fails_to_load_a_transform_with_an_import_error_test.dart
@@ -30,7 +30,8 @@
       createLockFile('myapp', pkg: ['barback']);
       var pub = startPubServe();
       pub.stderr.expect("Unhandled exception:");
-      pub.stderr.expect(startsWith("Uncaught Error: Failure getting "));
+      pub.stderr.expect(
+          startsWith("Uncaught Error: Load Error: Failure getting "));
       pub.shouldExit(1);
     });
   });
diff --git a/sdk/lib/_internal/pub_generated/lib/src/barback/transformer_isolate.dart b/sdk/lib/_internal/pub_generated/lib/src/barback/transformer_isolate.dart
index 13c2ae5..04298d2 100644
--- a/sdk/lib/_internal/pub_generated/lib/src/barback/transformer_isolate.dart
+++ b/sdk/lib/_internal/pub_generated/lib/src/barback/transformer_isolate.dart
@@ -93,7 +93,7 @@
         // error message.
         var missingTransformer = idsToUrls.keys.firstWhere(
             (id) =>
-                firstErrorLine.startsWith("Uncaught Error: Failure getting ") &&
+                firstErrorLine.startsWith("Uncaught Error: Load Error: Failure getting ") &&
                     firstErrorLine.contains(idsToUrls[id].path),
             orElse: () => throw error);
         var packageUri = idToPackageUri(idsToAssetIds[missingTransformer]);
diff --git a/sdk/lib/_internal/pub_generated/lib/src/pubspec.dart b/sdk/lib/_internal/pub_generated/lib/src/pubspec.dart
index 8fb27db..92c068a 100644
--- a/sdk/lib/_internal/pub_generated/lib/src/pubspec.dart
+++ b/sdk/lib/_internal/pub_generated/lib/src/pubspec.dart
@@ -100,9 +100,7 @@
   List<PackageDep> get dependencies {
     if (_dependencies != null) return _dependencies;
     _dependencies = _parseDependencies('dependencies');
-    if (_devDependencies == null) {
-      _checkDependencyOverlap(_dependencies, devDependencies);
-    }
+    _checkDependencyOverlap(_dependencies, _devDependencies);
     return _dependencies;
   }
   List<PackageDep> _dependencies;
@@ -111,9 +109,7 @@
   List<PackageDep> get devDependencies {
     if (_devDependencies != null) return _devDependencies;
     _devDependencies = _parseDependencies('dev_dependencies');
-    if (_dependencies == null) {
-      _checkDependencyOverlap(dependencies, _devDependencies);
-    }
+    _checkDependencyOverlap(_dependencies, _devDependencies);
     return _devDependencies;
   }
   List<PackageDep> _devDependencies;
@@ -549,6 +545,9 @@
   /// dependency.
   void _checkDependencyOverlap(List<PackageDep> dependencies,
       List<PackageDep> devDependencies) {
+    if (dependencies == null) return;
+    if (devDependencies == null) return;
+
     var dependencyNames = dependencies.map((dep) => dep.name).toSet();
     var collisions =
         dependencyNames.intersection(devDependencies.map((dep) => dep.name).toSet());
diff --git a/sdk/lib/_internal/pub_generated/lib/src/solver/backtracking_solver.dart b/sdk/lib/_internal/pub_generated/lib/src/solver/backtracking_solver.dart
index 26341e4..a5bac0f 100644
--- a/sdk/lib/_internal/pub_generated/lib/src/solver/backtracking_solver.dart
+++ b/sdk/lib/_internal/pub_generated/lib/src/solver/backtracking_solver.dart
@@ -127,94 +127,59 @@
   /// Completes with a list of specific package versions if successful or an
   /// error if it failed to find a solution.
   Future<SolveResult> solve() {
-    final completer0 = new Completer();
-    scheduleMicrotask(() {
-      try {
-        var stopwatch = new Stopwatch();
-        _logParameters();
-        var overrides = _overrides.values.toList();
-        overrides.sort(((a, b) {
-          return a.name.compareTo(b.name);
-        }));
-        join0() {
-          completer0.complete();
-        }
-        finally0(cont0) {
-          try {
-            var buffer = new StringBuffer();
-            buffer.writeln('${runtimeType} took ${stopwatch.elapsed} seconds.');
-            buffer.writeln(cache.describeResults());
-            log.solver(buffer);
-            cont0();
-          } catch (e0, s0) {
-            completer0.completeError(e0, s0);
-          }
-        }
-        catch0(error, s1) {
-          try {
-            if (error is SolveFailure) {
-              final v0 = new SolveResult.failure(
-                  sources,
-                  root,
-                  lockFile,
-                  overrides,
-                  error,
-                  attemptedSolutions);
-              finally0(() {
-                completer0.complete(v0);
-              });
-            } else {
-              throw error;
-            }
-          } catch (error, s1) {
-            finally0(() => completer0.completeError(error, s1));
-          }
-        }
-        try {
-          stopwatch.start();
-          cache.cache(new PackageId.root(root), root.pubspec);
-          _validateSdkConstraint(root.pubspec);
-          new Future.value(_traverseSolution()).then((x0) {
-            try {
-              var packages = x0;
-              var pubspecs = new Map.fromIterable(packages, key: ((id) {
-                return id.name;
-              }), value: ((id) {
-                return cache.getCachedPubspec(id);
-              }));
-              new Future.value(Future.wait(packages.map(((id) {
-                return sources[id.source].resolveId(id);
-              })))).then((x1) {
-                try {
-                  packages = x1;
-                  final v1 = new SolveResult.success(
-                      sources,
-                      root,
-                      lockFile,
-                      packages,
-                      overrides,
-                      pubspecs,
-                      _getAvailableVersions(packages),
-                      attemptedSolutions);
-                  finally0(() {
-                    completer0.complete(v1);
-                  });
-                } catch (e1, s2) {
-                  catch0(e1, s2);
-                }
-              }, onError: catch0);
-            } catch (e2, s3) {
-              catch0(e2, s3);
-            }
-          }, onError: catch0);
-        } catch (e3, s4) {
-          catch0(e3, s4);
-        }
-      } catch (e, s) {
-        completer0.completeError(e, s);
-      }
+    var stopwatch = new Stopwatch();
+
+    _logParameters();
+
+    // Sort the overrides by package name to make sure they're deterministic.
+    var overrides = _overrides.values.toList();
+    overrides.sort((a, b) => a.name.compareTo(b.name));
+
+    // TODO(nweiz): Use async/await here once
+    // https://github.com/dart-lang/async_await/issues/79 is fixed.
+    return new Future.sync(() {
+      stopwatch.start();
+
+      // Pre-cache the root package's known pubspec.
+      cache.cache(new PackageId.root(root), root.pubspec);
+
+      _validateSdkConstraint(root.pubspec);
+      return _traverseSolution();
+    }).then((packages) {
+      var pubspecs = new Map.fromIterable(
+          packages,
+          key: (id) => id.name,
+          value: (id) => cache.getCachedPubspec(id));
+
+      return Future.wait(
+          packages.map((id) => sources[id.source].resolveId(id))).then((packages) {
+        return new SolveResult.success(
+            sources,
+            root,
+            lockFile,
+            packages,
+            overrides,
+            pubspecs,
+            _getAvailableVersions(packages),
+            attemptedSolutions);
+      });
+    }).catchError((error) {
+      if (error is! SolveFailure) throw error;
+      // Wrap a failure in a result so we can attach some other data.
+      return new SolveResult.failure(
+          sources,
+          root,
+          lockFile,
+          overrides,
+          error,
+          attemptedSolutions);
+    }).whenComplete(() {
+      // Gather some solving metrics.
+      var buffer = new StringBuffer();
+      buffer.writeln('${runtimeType} took ${stopwatch.elapsed} seconds.');
+      buffer.writeln(cache.describeResults());
+      log.solver(buffer);
     });
-    return completer0.future;
   }
 
   /// Generates a map containing all of the known available versions for each
diff --git a/sdk/lib/_internal/pub_generated/lib/src/source/path.dart b/sdk/lib/_internal/pub_generated/lib/src/source/path.dart
index dc1e802..d6f7b8c 100644
--- a/sdk/lib/_internal/pub_generated/lib/src/source/path.dart
+++ b/sdk/lib/_internal/pub_generated/lib/src/source/path.dart
@@ -97,10 +97,14 @@
     // Resolve the path relative to the containing file path, and remember
     // whether the original path was relative or absolute.
     var isRelative = p.isRelative(description);
-    if (p.isRelative(description)) {
-      // Can't handle relative paths coming from pubspecs that are not on the
-      // local file system.
-      assert(containingPath != null);
+    if (isRelative) {
+      // Relative paths coming from pubspecs that are not on the local file
+      // system aren't allowed. This can happen if a hosted or git dependency
+      // has a path dependency.
+      if (containingPath == null) {
+        throw new FormatException(
+            '"$description" is a relative path, but this ' 'isn\'t a local pubspec.');
+      }
 
       description = p.normalize(p.join(p.dirname(containingPath), description));
     }
diff --git a/sdk/lib/_internal/pub_generated/test/get/hosted/gets_a_package_with_busted_dev_dependencies_test.dart b/sdk/lib/_internal/pub_generated/test/get/hosted/gets_a_package_with_busted_dev_dependencies_test.dart
new file mode 100644
index 0000000..1ca31ec
--- /dev/null
+++ b/sdk/lib/_internal/pub_generated/test/get/hosted/gets_a_package_with_busted_dev_dependencies_test.dart
@@ -0,0 +1,41 @@
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library pub_tests;
+
+import '../../../lib/src/exit_codes.dart' as exit_codes;
+import '../../descriptor.dart' as d;
+import '../../test_pub.dart';
+
+main() {
+  initConfig();
+
+  // Regression test for issue 22194.
+  integration(
+      'gets a dependency with broken dev dependencies from a pub ' 'server',
+      () {
+    servePackages((builder) {
+      builder.serve("foo", "1.2.3", pubspec: {
+        "dev_dependencies": {
+          "busted": {
+            "not a real source": null
+          }
+        }
+      });
+    });
+
+    d.appDir({
+      "foo": "1.2.3"
+    }).create();
+
+    pubGet();
+
+    d.cacheDir({
+      "foo": "1.2.3"
+    }).validate();
+    d.packagesDir({
+      "foo": "1.2.3"
+    }).validate();
+  });
+}
diff --git a/sdk/lib/_internal/pub_generated/test/pubspec_test.dart b/sdk/lib/_internal/pub_generated/test/pubspec_test.dart
index b1a1b76..1418bf9 100644
--- a/sdk/lib/_internal/pub_generated/test/pubspec_test.dart
+++ b/sdk/lib/_internal/pub_generated/test/pubspec_test.dart
@@ -12,6 +12,7 @@
 import '../lib/src/package.dart';
 import '../lib/src/pubspec.dart';
 import '../lib/src/source.dart';
+import '../lib/src/source/path.dart';
 import '../lib/src/source_registry.dart';
 import 'test_pub.dart';
 
@@ -44,6 +45,7 @@
   group('parse()', () {
     var sources = new SourceRegistry();
     sources.register(new MockSource());
+    sources.register(new PathSource());
 
     var throwsPubspecException =
         throwsA(new isInstanceOf<PubspecException>('PubspecException'));
@@ -167,16 +169,19 @@
     });
 
     test("throws if a package is in dependencies and dev_dependencies", () {
-      var contents = '''
+      expectPubspecException('''
 dependencies:
   foo:
     mock: ok
 dev_dependencies:
   foo:
     mock: ok
-''';
-      expectPubspecException(contents, (pubspec) => pubspec.dependencies);
-      expectPubspecException(contents, (pubspec) => pubspec.devDependencies);
+''', (pubspec) {
+        // This check only triggers if both [dependencies] and [devDependencies]
+        // are accessed.
+        pubspec.dependencies;
+        pubspec.devDependencies;
+      });
     });
 
     test("throws if it dependes on itself", () {
@@ -403,6 +408,16 @@
       expect(pubspec.dependencies, isEmpty);
     });
 
+    test("throws a useful error for unresolvable path dependencies", () {
+      expectPubspecException('''
+name: pkg
+dependencies:
+  from_path: {path: non_local_path}
+''',
+          (pubspec) => pubspec.dependencies,
+          '"non_local_path" is a relative path, but this isn\'t a local ' 'pubspec.');
+    });
+
     group("environment", () {
       test("defaults to any SDK constraint if environment is omitted", () {
         var pubspec = new Pubspec.parse('', sources);
diff --git a/sdk/lib/_internal/pub_generated/test/transformer/fails_to_load_a_transform_with_an_import_error_test.dart b/sdk/lib/_internal/pub_generated/test/transformer/fails_to_load_a_transform_with_an_import_error_test.dart
index 6b6df10..3f68f63 100644
--- a/sdk/lib/_internal/pub_generated/test/transformer/fails_to_load_a_transform_with_an_import_error_test.dart
+++ b/sdk/lib/_internal/pub_generated/test/transformer/fails_to_load_a_transform_with_an_import_error_test.dart
@@ -31,7 +31,8 @@
       createLockFile('myapp', pkg: ['barback']);
       var pub = startPubServe();
       pub.stderr.expect("Unhandled exception:");
-      pub.stderr.expect(startsWith("Uncaught Error: Failure getting "));
+      pub.stderr.expect(
+          startsWith("Uncaught Error: Load Error: Failure getting "));
       pub.shouldExit(1);
     });
   });
diff --git a/sdk/lib/async/stream_controller.dart b/sdk/lib/async/stream_controller.dart
index aa45876..0b470b8 100644
--- a/sdk/lib/async/stream_controller.dart
+++ b/sdk/lib/async/stream_controller.dart
@@ -142,10 +142,15 @@
   StreamSink<T> get sink;
 
   /**
-   * Whether the stream is closed for adding more events.
+   * Whether the stream controller is closed for adding more events.
    *
-   * If true, the "done" event might not have fired yet, but it has been
-   * scheduled, and it is too late to add more events.
+   * The controller becomes closed by calling the [close] method.
+   * New events cannot be added, by calling [add] or [addError],
+   * to a closed controller.
+   *
+   * If the controller is closed,
+   * the "done" event might not have been delivered yet,
+   * but it has been scheduled, and it is too late to add more events.
    */
   bool get isClosed;
 
@@ -157,8 +162,8 @@
    * controller is considered paused as well.
    *
    * A broadcast stream controller is never considered paused. It always
-   * forwards its events to all uncanceled listeners, if any, and let them
-   * handle their own pausing.
+   * forwards its events to all uncanceled subscriptions, if any,
+   * and let the subscriptions handle their own pausing and buffering.
    */
   bool get isPaused;
 
diff --git a/sdk/lib/async/stream_impl.dart b/sdk/lib/async/stream_impl.dart
index 394e1c6..3f77294 100644
--- a/sdk/lib/async/stream_impl.dart
+++ b/sdk/lib/async/stream_impl.dart
@@ -1029,6 +1029,7 @@
 
   Future cancel() {
     StreamSubscription subscription = _subscription;
+    if (subscription == null) return null;
     if (_state == _STATE_MOVING) {
       _Future<bool> hasNext = _futureOrPrefetch;
       _clear();
diff --git a/sdk/lib/core/errors.dart b/sdk/lib/core/errors.dart
index 0ac1880..a673406 100644
--- a/sdk/lib/core/errors.dart
+++ b/sdk/lib/core/errors.dart
@@ -157,7 +157,7 @@
    */
   ArgumentError.value(value,
                       [String this.name,
-                       String this.message = "Invalid argument"])
+                       String this.message])
       : invalidValue = value,
         _hasValue = true;
 
@@ -170,19 +170,22 @@
   ArgumentError.notNull([String name])
       : this.value(null, name, "Must not be null");
 
+  // Helper functions for toString overridden in subclasses.
+  String get _errorName => "Invalid argument${name == null ? "(s)" : ""}";
+  String get _errorExplanation => "";
+
   String toString() {
-    if (!_hasValue) {
-      var result = "Invalid arguments(s)";
-      if (message != null) {
-        result = "$result: $message";
-      }
-      return result;
-    }
     String nameString = "";
     if (name != null) {
       nameString = " ($name)";
     }
-    return "$message$nameString: ${Error.safeToString(invalidValue)}";
+    var message = this.message == null ? "" : ": ${this.message}";
+    String prefix = "$_errorName$nameString$message";
+    if (invalidValue == null) return prefix;
+    // If we know the invalid value, we can try to describe the problem.
+    String explanation = _errorExplanation;
+    String errorValue = Error.safeToString(invalidValue);
+    return "$prefix$explanation: $errorValue";
   }
 }
 
@@ -274,7 +277,7 @@
    * `[]` that accepts an index if `0 <= index < length`.
    *
    * If [length] is provided, it is used as the length of the indexable object,
-   * otherwise the length is found as `idexable.length`.
+   * otherwise the length is found as `indexable.length`.
    */
   static void checkValidIndex(int index, var indexable,
                               [String name, int length, String message]) {
@@ -297,18 +300,25 @@
    *
    * The [startName] and [endName] defaults to `"start"` and `"end"`,
    * respectively.
+   *
+   * Returns the actual `end` value, which is `length` if `end` is `null`,
+   * and `end` otherwise.
    */
-  static void checkValidRange(int start, int end, int length,
+  static int checkValidRange(int start, int end, int length,
                               [String startName, String endName,
                                String message]) {
     if (start < 0 || start > length) {
       if (startName == null) startName = "start";
       throw new RangeError.range(start, 0, length, startName, message);
     }
-    if (end != null && (end < start || end > length)) {
-      if (endName == null) endName = "end";
-      throw new RangeError.range(end, start, length, endName, message);
+    if (end != null) {
+      if (end < start || end > length) {
+        if (endName == null) endName = "end";
+        throw new RangeError.range(end, start, length, endName, message);
+      }
+      return end;
     }
+    return length;
   }
 
   /**
@@ -320,9 +330,9 @@
     if (value < 0) throw new RangeError.range(value, 0, null, name, message);
   }
 
-  String toString() {
-    if (!_hasValue) return "RangeError: $message";
-    String value = Error.safeToString(invalidValue);
+  String get _errorName => "RangeError";
+  String get _errorExplanation {
+    assert(_hasValue);
     String explanation = "";
     if (start == null) {
       if (end != null) {
@@ -332,14 +342,14 @@
     } else if (end == null) {
       explanation = ": Not greater than or equal to $start";
     } else if (end > start) {
-      explanation = ": Not in range $start..$end, inclusive.";
+      explanation = ": Not in range $start..$end, inclusive";
     } else if (end < start) {
       explanation = ": Valid value range is empty";
     } else {
       // end == start.
       explanation = ": Only valid value is $start";
     }
-    return "RangeError: $message ($value)$explanation";
+    return explanation;
   }
 }
 
@@ -376,14 +386,15 @@
   int get start => 0;
   int get end => length - 1;
 
-  String toString() {
+  String get _errorName => "RangeError";
+  String get _errorExplanation {
     assert(_hasValue);
     String target = Error.safeToString(indexable);
-    var explanation = "index should be less than $length";
+    var explanation = ": index should be less than $length";
     if (invalidValue < 0) {
-      explanation = "index must not be negative";
+      explanation = ": index must not be negative";
     }
-    return "RangeError: $message ($target[$invalidValue]): $explanation";
+    return explanation;
   }
 }
 
diff --git a/sdk/lib/core/iterable.dart b/sdk/lib/core/iterable.dart
index d4f482b..00d0821 100644
--- a/sdk/lib/core/iterable.dart
+++ b/sdk/lib/core/iterable.dart
@@ -5,12 +5,30 @@
 part of dart.core;
 
 /**
- * An object that uses an [Iterator] to serve objects one at a time.
+ * A collection of values, or "elements", that can be accessed sequentially.
  *
- * You can iterate over all objects served by an Iterable object
- * using the for-in loop construct.
- * For example, you can iterate over all of the keys in a [Map],
- * because Map keys are iterable.
+ * The elements of the iterable are accessed by getting an [Iterator]
+ * using the [iterator] getter, and using it to step through the values.
+ * Stepping with the iterator is done by calling [Iterator.moveNext],
+ * and if the call returns `true`,
+ * the iterator has now moved to the next element,
+ * which is then available as [Iterator.current].
+ * If the call returns `false`, there are no more elements,
+ * and `iterator.currrent` returns `null`.
+ *
+ * You can create more than one iterator from the same `Iterable`.
+ * Each time `iterator` is read, it returns a new iterator,
+ * and different iterators can be stepped through independently,
+ * each giving access to all the elements of the iterable.
+ * The iterators of the same iterable *should* provide the same values
+ * in the same order (unless the underlying collection is modified between
+ * the iterations, which some collections allow).
+ *
+ * You can also iterate over the elements of an `Iterable`
+ * using the for-in loop construct, which uses the `iterator` getter behind the
+ * scenes.
+ * For example, you can iterate over all of the keys of a [Map],
+ * because `Map` keys are iterable.
  *
  *     Map kidsBooks = {'Matilda': 'Roald Dahl',
  *                      'Green Eggs and Ham': 'Dr Seuss',
@@ -19,34 +37,64 @@
  *       print('$book was written by ${kidsBooks[book]}');
  *     }
  *
- * The [List] class and the [Set] class implement this interface,
- * as do classes in the [dart:collection](#dart-collection) library.
+ * The [List] and [Set] classes are both `Iterable`,
+ * as are most classes in the [dart:collection](#dart-collection) library.
  *
- * You can implement Iterable in your own class.
- * If you do, then an instance of your Iterable class
- * can be the right-hand side of a for-in construct.
+ * Some [Iterable] collections can be modified.
+ * Adding an element to a `List` or `Set` will change which elements it
+ * contains, and adding a new key to a `Map` changes the elements of [Map.keys].
+ * Iterators created after the change will provide the new elements, and may
+ * or may not preserve the order of existing elements
+ * (for example, a [HashSet] may completely change its order when a single
+ * element is added).
  *
- * Some subclasss of [Iterable] can be modified. It is generally not allowed
- * to modify such collections while they are being iterated. Doing so will break
- * the iteration, which is typically signalled by throwing a
- * [ConcurrentModificationError] when it is detected.
+ * Changing a collection *while* it is being iterated
+ * is generally *not* allowed.
+ * Doing so will break the iteration, which is typically signalled
+ * by throwing a [ConcurrentModificationError]
+ * the next time [Iterator.moveNext] is called.
+ * The current value of [Iterator.current] getter
+ * should not be affected by the change in the collection,
+ * the `current` value was set by the previous call to [Iterator.moveNext].
+ *
+ * Some iterables compute their elements dynamically every time they are
+ * iterated, like the one returned by [Iterable.generate] or the iterable
+ * returned by a `sync*` generator function. If the computation doesn't depend
+ * on other objects that may change, then the generated sequence should be
+ * the same one every time it's iterated.
+ *
+ * The members of `Iterable`, other than `iterator` itself,
+ * work by looking at the elements of the iterable.
+ * This can be implemented by running through the [iterator], but some classes
+ * may have more efficient ways of finding the result
+ * (like [last] or [length] on a [List], or [contains] on a [Set]).
+ *
+ * The methods that return another `Iterable` (like [map] and [where])
+ * are all *lazy* - they will iterate the original (as necessary)
+ * every time the returned iterable is iterated, and not before.
+ *
+ * Since an iterable may be iterated more than once, it's not recommended to
+ * have detectable side-effects in the iterator.
+ * For methods like [map] and [while], the returned iterable will execute the
+ * argument function on every iteration, so those functions should also not
+ * have side effects.
  */
 abstract class Iterable<E> {
   const Iterable();
 
   /**
-   * Creates an Iterable that generates its elements dynamically.
+   * Creates an `Iterable` that generates its elements dynamically.
    *
-   * The Iterators created by the Iterable count from
-   * zero to [:count - 1:] while iterating, and call [generator]
-   * with that index to create the next value.
+   * An `Iterator` created by [iterator] will count from
+   * zero to [:count - 1:], and call [generator]
+   * with each index in turn to create the next value.
    *
    * If [generator] is omitted, it defaults to an identity function
    * on integers `(int x) => x`, so it should only be omitted if the type
    * parameter allows integer values.
    *
-   * As an Iterable, [:new Iterable.generate(n, generator)):] is equivalent to
-   * [:const [0, ..., n - 1].map(generator):]
+   * As an `Iterable`, `new Iterable.generate(n, generator))` is equivalent to
+   * `const [0, ..., n - 1].map(generator)`.
    */
   factory Iterable.generate(int count, [E generator(int index)]) {
     if (count <= 0) return new EmptyIterable<E>();
@@ -57,20 +105,45 @@
    * Returns a new `Iterator` that allows iterating the elements of this
    * `Iterable`.
    *
-   * Modifying the underlying data after creating the new iterator
-   * may cause an error the next time [Iterator.moveNext] is called.
+   * Iterable classes may specify the iteration order of their elements
+   * (for example [List] always iterate in index order),
+   * or they may leave it unspecified (for example a hash-based [Set]
+   * may iterate in any order).
+   *
+   * Each time `iterator` is read, it returns a new iterator,
+   * which can be used to iterate through all the elements again.
+   * The iterators of the same iterable can be stepped through independently,
+   * but should return the same elements in the same order,
+   * as long as the underlying collection isn't changed.
+   *
+   * Modifying the collection may cause new iterators to produce
+   * different elements, and may change the order of existing elements.
+   * A [List] specifies its iteration order precisely,
+   * so modifying the list changes the iteration order predictably.
+   * A hash-based [Set] may change its iteration order completely
+   * when adding a new element to the set.
+   *
+   * Modifying the underlying collection after creating the new iterator
+   * may cause an error the next time [Iterator.moveNext] is called
+   * on that iterator.
+   * Any *modifiable* iterable class should specify which operations will
+   * break iteration.
    */
   Iterator<E> get iterator;
 
   /**
    * Returns a new lazy [Iterable] with elements that are created by
-   * calling `f` on the elements of this `Iterable`.
+   * calling `f` on each element of this `Iterable` in iteration order.
    *
    * This method returns a view of the mapped elements. As long as the
    * returned [Iterable] is not iterated over, the supplied function [f] will
    * not be invoked. The transformed elements will not be cached. Iterating
    * multiple times over the the returned [Iterable] will invoke the supplied
    * function [f] multiple times on the same element.
+   *
+   * Methods on the returned iterable are allowed to omit calling `f`
+   * on any element where the result isn't needed.
+   * For example, [elementAt] may call `f` only once.
    */
   Iterable map(f(E element));
 
@@ -78,6 +151,9 @@
    * Returns a new lazy [Iterable] with all elements that satisfy the
    * predicate [test].
    *
+   * The matching elements have the same order in the returned iterable
+   * as they have in [iterator].
+   *
    * This method returns a view of the mapped elements. As long as the
    * returned [Iterable] is not iterated over, the supplied function [test] will
    * not be invoked. Iterating will not cache results, and thus iterating
@@ -87,10 +163,10 @@
   Iterable<E> where(bool test(E element));
 
   /**
-   * Expands each element of this [Iterable] into zero or more elements.
+   * Expands each element of this [Iterable]into zero or more elements.
    *
    * The resulting Iterable runs through the elements returned
-   * by [f] for each element of this, in order.
+   * by [f] for each element of this, in iteration order.
    *
    * The returned [Iterable] is lazy, and calls [f] for each element
    * of this every time it's iterated.
@@ -100,17 +176,24 @@
   /**
    * Returns true if the collection contains an element equal to [element].
    *
+   * This operation will check each element in order for being equal to
+   * [element], unless it has a more efficient way to find an element
+   * equal to [element].
+   *
    * The equality used to determine whether [element] is equal to an element of
-   * the iterable, depends on the type of iterable.
+   * the iterable defaults to the [Object.operator==] of the element.
+   *
+   * Some types of iterable may have a different equality used for its elements.
    * For example, a [Set] may have a custom equality
-   * (see, e.g., [Set.identical]) that its `contains` uses.
+   * (see [Set.identical]) that its `contains` uses.
    * Likewise the `Iterable` returned by a [Map.keys] call
-   * will likely use the same equality that the `Map` uses for keys.
+   * should use the same equality that the `Map` uses for keys.
    */
   bool contains(Object element);
 
   /**
-   * Applies the function [f] to each element of this collection.
+   * Applies the function [f] to each element of this collection in iteration
+   * order.
    */
   void forEach(void f(E element));
 
@@ -118,6 +201,19 @@
    * Reduces a collection to a single value by iteratively combining elements
    * of the collection using the provided function.
    *
+   * The iterable must have at least one element.
+   * If it has only one element, that element is returned.
+   *
+   * Otherwise this method starts with the first element from the iterator,
+   * and then combines it with the remaining elements in iteration order,
+   * as if by:
+   *
+   *     E value = iterable.first;
+   *     iterable.skip(1).forEach((element) {
+   *       value = combine(value, element);
+   *     });
+   *     return value;
+   *
    * Example of calculating the sum of an iterable:
    *
    *     iterable.reduce((value, element) => value + element);
@@ -127,11 +223,17 @@
 
   /**
    * Reduces a collection to a single value by iteratively combining each
-   * element of the collection with an existing value using the provided
-   * function.
+   * element of the collection with an existing value
    *
-   * Use [initialValue] as the initial value, and the function [combine] to
-   * create a new value from the previous one and an element.
+   * Uses [initialValue] as the initial value,
+   * then iterates through the elements and updates the value with
+   * each element using the [combine] function, as if by:
+   *
+   *     var value = initialValue;
+   *     for (E element in this) {
+   *       value = combine(value, element);
+   *     }
+   *     return value;
    *
    * Example of calculating the sum of an iterable:
    *
@@ -142,17 +244,20 @@
                dynamic combine(var previousValue, E element));
 
   /**
-   * Returns true if every elements of this collection satisify the
-   * predicate [test]. Returns `false` otherwise.
+   * Checks whether every element of this iterable satisfies [test].
+   *
+   * Checks every element in iteration order, and returns `false` if
+   * any of them make [test] return `false`, otherwise returns `true`.
    */
   bool every(bool test(E element));
 
   /**
    * Converts each element to a [String] and concatenates the strings.
    *
-   * Converts each element to a [String] by calling [Object.toString] on it.
-   * Then concatenates the strings, optionally separated by the [separator]
-   * string.
+   * Iterates through elements of this iterable,
+   * converts each one to a [String] by calling [Object.toString],
+   * and then concatenates the strings, with the
+   * [separator] string interleaved between the elements.
    */
   String join([String separator = ""]) {
     StringBuffer buffer = new StringBuffer();
@@ -161,16 +266,18 @@
   }
 
   /**
-   * Returns true if one element of this collection satisfies the
-   * predicate [test]. Returns false otherwise.
+   * Checks whether any element of this iterable satisfies [test].
+   *
+   * Checks every element in iteration order, and returns `true` if
+   * any of them make [test] return `true`, otherwise returns false.
    */
   bool any(bool test(E element));
 
   /**
    * Creates a [List] containing the elements of this [Iterable].
    *
-   * The elements are in iteration order. The list is fixed-length
-   * if [growable] is false.
+   * The elements are in iteration order.
+   * The list is fixed-length if [growable] is false.
    */
   List<E> toList({ bool growable: true });
 
@@ -178,7 +285,7 @@
    * Creates a [Set] containing the same elements as this iterable.
    *
    * The set may contain fewer elements than the iterable,
-   * if the iterable contains the an element more than once,
+   * if the iterable contains an element more than once,
    * or it contains one or more elements that are equal.
    * The order of the elements in the set is not guaranteed to be the same
    * as for the iterable.
@@ -188,110 +295,141 @@
   /**
    * Returns the number of elements in [this].
    *
-   * Counting all elements may be involve running through all elements and can
+   * Counting all elements may involve iterating through all elements and can
    * therefore be slow.
+   * Some iterables have a more efficient way to find the number of elements.
    */
   int get length;
 
   /**
-   * Returns true if there is no element in this collection.
+   * Returns `true` if there are no elements in this collection.
+   *
+   * May be computed by checking if `iterator.moveNext()` returns `false`.
    */
   bool get isEmpty;
 
   /**
    * Returns true if there is at least one element in this collection.
+   *
+   * May be computed by checking if `iterator.moveNext()` returns `true`.
    */
   bool get isNotEmpty;
 
   /**
-   * Returns an [Iterable] with at most [count] elements.
+   * Returns a lazy iterable of the [count] first elements of this iterable.
    *
    * The returned `Iterable` may contain fewer than `count` elements, if `this`
    * contains fewer than `count` elements.
    *
-   * It is an error if `count` is negative.
+   * The elements can be computed by stepping through [iterator] until [count]
+   * elements have been seen.
+   *
+   * The `count` must not be negative.
    */
   Iterable<E> take(int count);
 
   /**
-   * Returns an Iterable that stops once [test] is not satisfied anymore.
+   * Returns a lazy iterable of the leading elements satisfying [test].
    *
-   * The filtering happens lazily. Every new Iterator of the returned
-   * Iterable starts iterating over the elements of `this`.
+   * The filtering happens lazily. Every new iterator of the returned
+   * iterable starts iterating over the elements of `this`.
    *
-   * When the iterator encounters an element `e` that does not satisfy [test],
-   * it discards `e` and moves into the finished state. That is, it does not
-   * get or provide any more elements.
+   * The elements can be computed by stepping through [iterator] until an
+   * element is found where `test(element)` is false. At that point,
+   * the returned iterable stops (its `moveNext()` returns false).
    */
   Iterable<E> takeWhile(bool test(E value));
 
   /**
-   * Returns an Iterable that skips the first [count] elements.
+   * Returns an Iterable that provides all but the first [count] elements.
    *
+   * When the returned iterable is iterated, it starts iterating over `this`,
+   * first skipping past the initial [count] elements.
    * If `this` has fewer than `count` elements, then the resulting Iterable is
    * empty.
+   * After that, the remaining elements are iterated in the same order as
+   * in this iterable.
    *
-   * It is an error if `count` is negative.
+   * The `count` must not be negative.
    */
   Iterable<E> skip(int count);
 
   /**
-   * Returns an Iterable that skips elements while [test] is satisfied.
+   * Returns an Iterable that skips leading elements while [test] is satisfied.
    *
    * The filtering happens lazily. Every new Iterator of the returned
    * Iterable iterates over all elements of `this`.
    *
-   * As long as the iterator's elements satisfy [test] they are
-   * discarded. Once an element does not satisfy the [test] the iterator stops
-   * testing and uses every later element unconditionally. That is, the elements
-   * of the returned Iterable are the elements of `this` starting from the
-   * first element that does not satisfy [test].
+   * The returned iterable provides elements by iterating this iterable,
+   * but skipping over all initial elements where `test(element)` returns
+   * true. If all elements satisfy `test` the resulting iterable is empty,
+   * otherwise it iterates the remaining elements in their original order,
+   * starting with the first element for which `test(element)` returns false,
    */
   Iterable<E> skipWhile(bool test(E value));
 
   /**
    * Returns the first element.
    *
-   * If `this` is empty throws a [StateError]. Otherwise this method is
-   * equivalent to [:this.elementAt(0):]
+   * Throws a [StateError] if `this` is empty.
+   * Otherwise returs the first element in the iteration order,
+   * equivalent to `(iterator..moveNext())..current`.
    */
   E get first;
 
   /**
    * Returns the last element.
    *
-   * If `this` is empty throws a [StateError].
+   * Throws a [StateError] if `this` is empty.
+   * Otherwise may iterate through the elements and returns the last one
+   * seen.
+   * Some iterables may have more efficient ways to find the last element
+   * (for example a list can directly access the last element,
+   * without iterating through the previous ones).
    */
   E get last;
 
   /**
-   * Returns the single element in `this`.
+   * Checks that this iterable has only one element, and returns that element.
    *
-   * If `this` is empty or has more than one element throws a [StateError].
+   * Throws a [StateError] if `this` is empty or has more than one element.
    */
   E get single;
 
   /**
    * Returns the first element that satisfies the given predicate [test].
    *
-   * If none matches, the result of invoking the [orElse] function is
-   * returned. By default, when [orElse] is `null`, a [StateError] is
-   * thrown.
+   * Iterates through elements and returns the first to satsify [test].
+   *
+   * If no element satisfies [test], the result of invoking the [orElse]
+   * function is returned.
+   * If [orElse] is omitted, it defaults to throwing a [StateError].
    */
   E firstWhere(bool test(E element), { E orElse() });
 
   /**
    * Returns the last element that satisfies the given predicate [test].
    *
-   * If none matches, the result of invoking the [orElse] function is
-   * returned. By default, when [orElse] is `null`, a [StateError] is
-   * thrown.
+   * An iterable that can access its elements directly may check its
+   * elements in any order (for example a list starts by checking the
+   * last element and then moves towards the start of the list).
+   * The default implementation iterates elements in iteration order,
+   * checks `test(element)` for each,
+   * and finally returns that last one that matched.
+   *
+   * If no element satsfies [test], the result of invoking the [orElse]
+   * function is returned.
+   * If [orElse] is omitted, it defaults to throwing a [StateError].
    */
   E lastWhere(bool test(E element), {E orElse()});
 
   /**
-   * Returns the single element that satisfies [test]. If no or more than one
-   * element match then a [StateError] is thrown.
+   * Returns the single element that satisfies [test].
+   *
+   * Checks all elements to see if `test(element)` returns true.
+   * If exactly one element satisfies [test], that element is returned.
+   * Otherwise, if there are no matching elements, or if there is more than
+   * one matching element, a [StateError] is thrown.
    */
   E singleWhere(bool test(E element));
 
@@ -299,10 +437,12 @@
    * Returns the [index]th element.
    *
    * The [index] must be non-negative and less than [length].
+   * Index zero represents the first element (so `iterable.elementAt(0)` is
+   * equivalent to `iterable.first`).
    *
-   * Note: if `this` does not have a deterministic iteration order then the
-   * function may simply return any element without any iteration if there are
-   * at least [index] elements in `this`.
+   * May iterate through the elements in iteration order, skipping the
+   * first `index` elements and returning the next.
+   * Some iterable may have more efficient ways to find the element.
    */
   E elementAt(int index);
 }
diff --git a/sdk/lib/core/iterator.dart b/sdk/lib/core/iterator.dart
index ed7aca9..34a7f49 100644
--- a/sdk/lib/core/iterator.dart
+++ b/sdk/lib/core/iterator.dart
@@ -7,16 +7,17 @@
 /**
  * An interface for getting items, one at a time, from an object.
  *
- * The for-in construct transparently uses Iterator to test for the end
+ * The for-in construct transparently uses `Iterator` to test for the end
  * of the iteration, and to get each item (or _element_).
  *
  * If the object iterated over is changed during the iteration, the
  * behavior is unspecified.
  *
- * The Iterator is initially positioned before the first element. Before
- * accessing the first element the iterator must thus be advanced ([moveNext])
- * to point to the first element. If no element is left, then [moveNext]
- * returns false.
+ * The `Iterator` is initially positioned before the first element.
+ * Before accessing the first element the iterator must thus be advanced using
+ * [moveNext] to point to the first element.
+ * If no element is left, then [moveNext] returns false, [current]
+ * returns `null`, and all further calls to [moveNext] will also return false.
  *
  * A typical usage of an Iterator looks as follows:
  *
@@ -32,20 +33,31 @@
  */
 abstract class Iterator<E> {
   /**
-   * Moves to the next element. Returns true if [current] contains the next
-   * element. Returns false, if no element was left.
+   * Moves to the next element.
+   *
+   * Returns true if [current] contains the next element.
+   * Returns false if no elements are left.
    *
    * It is safe to invoke [moveNext] even when the iterator is already
-   * positioned after the last element. In this case [moveNext] has no effect.
+   * positioned after the last element.
+   * In this case [moveNext] returns false again and has no effect.
+   *
+   * A call to `moveNext` may throw if iteration has been broken by
+   * changing the underlying collection.
    */
   bool moveNext();
 
   /**
    * Returns the current element.
    *
-   * Return [:null:] if the iterator has not yet been moved to the first
-   * element, or if the iterator has been moved after the last element of the
+   * Returns `null` if the iterator has not yet been moved to the first
+   * element, or if the iterator has been moved past the last element of the
    * [Iterable].
+   *
+   * The `current` getter should keep its value until the next call to
+   * [moveNext], even if an underlying collection changes.
+   * After a successful call to `moveNext`, the user doesn't need to cache
+   * the current value, but can keep reading it from the iterator.
    */
   E get current;
 }
diff --git a/sdk/lib/html/dart2js/html_dart2js.dart b/sdk/lib/html/dart2js/html_dart2js.dart
index 9ce36d6..793c36c 100644
--- a/sdk/lib/html/dart2js/html_dart2js.dart
+++ b/sdk/lib/html/dart2js/html_dart2js.dart
@@ -10110,6 +10110,12 @@
       new _CssStyleDeclarationSet(this);
 
   void set classes(Iterable<String> value) {
+    // TODO(sra): This might be faster for Sets:
+    //
+    //     new _MultiElementCssClassSet(this).writeClasses(value)
+    //
+    // as the code below converts the Iterable[value] to a string multiple
+    // times.  Maybe compute the string and set className here.
     _nodeList.forEach((e) => e.classes = value);
   }
 
@@ -10907,6 +10913,8 @@
   CssClassSet get classes => new _ElementCssClassSet(this);
 
   void set classes(Iterable<String> value) {
+    // TODO(sra): Do this without reading the classes in clear() and addAll(),
+    // or writing the classes in clear().
     CssClassSet classSet = classes;
     classSet.clear();
     classSet.addAll(value);
@@ -16587,7 +16595,7 @@
   static Future<String> getString(String url,
       {bool withCredentials, void onProgress(ProgressEvent e)}) {
     return request(url, withCredentials: withCredentials,
-        onProgress: onProgress).then((xhr) => xhr.responseText);
+        onProgress: onProgress).then((HttpRequest xhr) => xhr.responseText);
   }
 
   /**
@@ -30595,6 +30603,7 @@
   @DocsEditable()
   final int outerWidth;
 
+  @JSName('pageXOffset')
   /**
    * The distance this window has been scrolled horizontally.
    *
@@ -30609,8 +30618,9 @@
    */
   @DomName('Window.pageXOffset')
   @DocsEditable()
-  final int pageXOffset;
+  final double _pageXOffset;
 
+  @JSName('pageYOffset')
   /**
    * The distance this window has been scrolled vertically.
    *
@@ -30625,7 +30635,7 @@
    */
   @DomName('Window.pageYOffset')
   @DocsEditable()
-  final int pageYOffset;
+  final double _pageYOffset;
 
   @DomName('Window.parent')
   @DocsEditable()
@@ -31741,6 +31751,14 @@
     _moveTo(p.x, p.y);
   }
 
+  @DomName('Window.pageXOffset')
+  @DocsEditable()
+  int get pageXOffset => JS('num', '#.pageXOffset', this).round();
+
+  @DomName('Window.pageYOffset')
+  @DocsEditable()
+  int get pageYOffset => JS('num', '#.pageYOffset', this).round();
+
   /**
    * The distance this window has been scrolled horizontally.
    *
@@ -31751,8 +31769,11 @@
    * * [scrollX]
    * (https://developer.mozilla.org/en-US/docs/Web/API/Window.scrollX) from MDN.
    */
-  int get scrollX => JS('bool', '("scrollX" in #)', this) ? JS('int',
-      '#.scrollX', this) : document.documentElement.scrollLeft;
+  @DomName('Window.scrollX')
+  @DocsEditable()
+  int get scrollX => JS('bool', '("scrollX" in #)', this) ?
+      JS('num', '#.scrollX', this).round() :
+      document.documentElement.scrollLeft;
 
   /**
    * The distance this window has been scrolled vertically.
@@ -31764,8 +31785,11 @@
    * * [scrollY]
    * (https://developer.mozilla.org/en-US/docs/Web/API/Window.scrollY) from MDN.
    */
-  int get scrollY => JS('bool', '("scrollY" in #)', this) ? JS('int',
-      '#.scrollY', this) : document.documentElement.scrollTop;
+  @DomName('Window.scrollY')
+  @DocsEditable()
+  int get scrollY => JS('bool', '("scrollY" in #)', this) ?
+      JS('num', '#.scrollY', this).round() :
+      document.documentElement.scrollTop;
 }
 
 class _BeforeUnloadEvent extends _WrappedEvent implements BeforeUnloadEvent {
@@ -34499,12 +34523,13 @@
 
   Set<String> readClasses() {
     var s = new LinkedHashSet<String>();
-    _elementCssClassSetIterable.forEach((e) => s.addAll(e.readClasses()));
+    _elementCssClassSetIterable.forEach(
+        (_ElementCssClassSet e) => s.addAll(e.readClasses()));
     return s;
   }
 
   void writeClasses(Set<String> s) {
-    var classes = new List.from(s).join(' ');
+    var classes = s.join(' ');
     for (Element e in _elementIterable) {
       e.className = classes;
     }
@@ -34520,7 +34545,7 @@
    *       className property of this element.
    */
   modify( f(Set<String> s)) {
-    _elementCssClassSetIterable.forEach((e) => e.modify(f));
+    _elementCssClassSetIterable.forEach((_ElementCssClassSet e) => e.modify(f));
   }
 
   /**
@@ -34528,7 +34553,9 @@
    * is.
    */
   bool toggle(String value, [bool shouldAdd]) =>
-      _modifyWithReturnValue((e) => e.toggle(value, shouldAdd));
+      _elementCssClassSetIterable.fold(false,
+          (bool changed, _ElementCssClassSet e) =>
+              e.toggle(value, shouldAdd) || changed);
 
   /**
    * Remove the class [value] from element, and return true on successful
@@ -34537,10 +34564,8 @@
    * This is the Dart equivalent of jQuery's
    * [removeClass](http://api.jquery.com/removeClass/).
    */
-  bool remove(Object value) => _modifyWithReturnValue((e) => e.remove(value));
-
-  bool _modifyWithReturnValue(f) => _elementCssClassSetIterable.fold(
-      false, (prevValue, element) => f(element) || prevValue);
+  bool remove(Object value) => _elementCssClassSetIterable.fold(false,
+      (bool changed, _ElementCssClassSet e) => e.remove(value) || changed);
 }
 
 class _ElementCssClassSet extends CssClassSetImpl {
@@ -34563,7 +34588,6 @@
   }
 
   void writeClasses(Set<String> s) {
-    List list = new List.from(s);
     _element.className = s.join(' ');
   }
 }
diff --git a/sdk/lib/html/dartium/html_dartium.dart b/sdk/lib/html/dartium/html_dartium.dart
index 4c9a376..1504658 100644
--- a/sdk/lib/html/dartium/html_dartium.dart
+++ b/sdk/lib/html/dartium/html_dartium.dart
@@ -11133,6 +11133,12 @@
       new _CssStyleDeclarationSet(this);
 
   void set classes(Iterable<String> value) {
+    // TODO(sra): This might be faster for Sets:
+    //
+    //     new _MultiElementCssClassSet(this).writeClasses(value)
+    //
+    // as the code below converts the Iterable[value] to a string multiple
+    // times.  Maybe compute the string and set className here.
     _nodeList.forEach((e) => e.classes = value);
   }
 
@@ -11929,6 +11935,8 @@
   CssClassSet get classes => new _ElementCssClassSet(this);
 
   void set classes(Iterable<String> value) {
+    // TODO(sra): Do this without reading the classes in clear() and addAll(),
+    // or writing the classes in clear().
     CssClassSet classSet = classes;
     classSet.clear();
     classSet.addAll(value);
@@ -18116,7 +18124,7 @@
   static Future<String> getString(String url,
       {bool withCredentials, void onProgress(ProgressEvent e)}) {
     return request(url, withCredentials: withCredentials,
-        onProgress: onProgress).then((xhr) => xhr.responseText);
+        onProgress: onProgress).then((HttpRequest xhr) => xhr.responseText);
   }
 
   /**
@@ -33199,7 +33207,7 @@
    */
   @DomName('Window.pageXOffset')
   @DocsEditable()
-  int get pageXOffset => _blink.BlinkWindow.instance.pageXOffset_Getter_(this);
+  double get _pageXOffset => _blink.BlinkWindow.instance.pageXOffset_Getter_(this);
 
   /**
    * The distance this window has been scrolled vertically.
@@ -33215,7 +33223,7 @@
    */
   @DomName('Window.pageYOffset')
   @DocsEditable()
-  int get pageYOffset => _blink.BlinkWindow.instance.pageYOffset_Getter_(this);
+  double get _pageYOffset => _blink.BlinkWindow.instance.pageYOffset_Getter_(this);
 
   @DomName('Window.parent')
   @DocsEditable()
@@ -33302,11 +33310,11 @@
 
   @DomName('Window.scrollX')
   @DocsEditable()
-  int get scrollX => _blink.BlinkWindow.instance.scrollX_Getter_(this);
+  double get _scrollX => _blink.BlinkWindow.instance.scrollX_Getter_(this);
 
   @DomName('Window.scrollY')
   @DocsEditable()
-  int get scrollY => _blink.BlinkWindow.instance.scrollY_Getter_(this);
+  double get _scrollY => _blink.BlinkWindow.instance.scrollY_Getter_(this);
 
   /**
    * This window's scroll bars.
@@ -34110,6 +34118,21 @@
     _moveTo(p.x, p.y);
   }
 
+  @DomName('Window.pageXOffset')
+  @DocsEditable()
+  int get pageXOffset => _blink.BlinkWindow.instance.pageXOffset_Getter_(this).round();
+
+  @DomName('Window.pageYOffset')
+  @DocsEditable()
+  int get pageYOffset => _blink.BlinkWindow.instance.pageYOffset_Getter_(this).round();
+
+  @DomName('Window.scrollX')
+  @DocsEditable()
+  int get scrollX => _blink.BlinkWindow.instance.scrollX_Getter_(this).round();
+
+  @DomName('Window.scrollY')
+  @DocsEditable()
+  int get scrollY => _blink.BlinkWindow.instance.scrollY_Getter_(this).round();
 }
 
 
@@ -36966,12 +36989,13 @@
 
   Set<String> readClasses() {
     var s = new LinkedHashSet<String>();
-    _elementCssClassSetIterable.forEach((e) => s.addAll(e.readClasses()));
+    _elementCssClassSetIterable.forEach(
+        (_ElementCssClassSet e) => s.addAll(e.readClasses()));
     return s;
   }
 
   void writeClasses(Set<String> s) {
-    var classes = new List.from(s).join(' ');
+    var classes = s.join(' ');
     for (Element e in _elementIterable) {
       e.className = classes;
     }
@@ -36987,7 +37011,7 @@
    *       className property of this element.
    */
   modify( f(Set<String> s)) {
-    _elementCssClassSetIterable.forEach((e) => e.modify(f));
+    _elementCssClassSetIterable.forEach((_ElementCssClassSet e) => e.modify(f));
   }
 
   /**
@@ -36995,7 +37019,9 @@
    * is.
    */
   bool toggle(String value, [bool shouldAdd]) =>
-      _modifyWithReturnValue((e) => e.toggle(value, shouldAdd));
+      _elementCssClassSetIterable.fold(false,
+          (bool changed, _ElementCssClassSet e) =>
+              e.toggle(value, shouldAdd) || changed);
 
   /**
    * Remove the class [value] from element, and return true on successful
@@ -37004,10 +37030,8 @@
    * This is the Dart equivalent of jQuery's
    * [removeClass](http://api.jquery.com/removeClass/).
    */
-  bool remove(Object value) => _modifyWithReturnValue((e) => e.remove(value));
-
-  bool _modifyWithReturnValue(f) => _elementCssClassSetIterable.fold(
-      false, (prevValue, element) => f(element) || prevValue);
+  bool remove(Object value) => _elementCssClassSetIterable.fold(false,
+      (bool changed, _ElementCssClassSet e) => e.remove(value) || changed);
 }
 
 class _ElementCssClassSet extends CssClassSetImpl {
@@ -37030,7 +37054,6 @@
   }
 
   void writeClasses(Set<String> s) {
-    List list = new List.from(s);
     _element.className = s.join(' ');
   }
 }
diff --git a/sdk/lib/html/html_common/conversions.dart b/sdk/lib/html/html_common/conversions.dart
index 255b3e5..042a784 100644
--- a/sdk/lib/html/html_common/conversions.dart
+++ b/sdk/lib/html/html_common/conversions.dart
@@ -392,8 +392,11 @@
 bool isJavaScriptDate(value) => JS('bool', '# instanceof Date', value);
 bool isJavaScriptRegExp(value) => JS('bool', '# instanceof RegExp', value);
 bool isJavaScriptArray(value) => JS('bool', '# instanceof Array', value);
-bool isJavaScriptSimpleObject(value) =>
-    JS('bool', 'Object.getPrototypeOf(#) === Object.prototype', value);
+bool isJavaScriptSimpleObject(value) {
+  var proto = JS('', 'Object.getPrototypeOf(#)', value);
+  return JS('bool', '# === Object.prototype', proto) ||
+      JS('bool', '# === null', proto);
+}
 bool isImmutableJavaScriptArray(value) =>
     JS('bool', r'!!(#.immutable$list)', value);
 
diff --git a/sdk/lib/html/html_common/css_class_set.dart b/sdk/lib/html/html_common/css_class_set.dart
index 5704bfa..0380d2d 100644
--- a/sdk/lib/html/html_common/css_class_set.dart
+++ b/sdk/lib/html/html_common/css_class_set.dart
@@ -193,6 +193,7 @@
   String elementAt(int index) => readClasses().elementAt(index);
 
   void clear() {
+    // TODO(sra): Do this without reading the classes.
     modify((s) => s.clear());
   }
   // interface Set - END
diff --git a/sdk/lib/internal/internal.dart b/sdk/lib/internal/internal.dart
index 10b9613..3eda7ca 100644
--- a/sdk/lib/internal/internal.dart
+++ b/sdk/lib/internal/internal.dart
@@ -45,3 +45,18 @@
    1000000000000000000000.0,
   10000000000000000000000.0,
 ];
+
+/**
+ * An [Iterable] of the UTF-16 code units of a [String] in index order.
+ */
+class CodeUnits extends UnmodifiableListBase<int> {
+  /** The string that this is the code units of. */
+  final String _string;
+
+  CodeUnits(this._string);
+
+  int get length => _string.length;
+  int operator[](int i) => _string.codeUnitAt(i);
+
+  static String stringOf(CodeUnits u) => u._string;
+}
diff --git a/sdk/lib/io/file_system_entity.dart b/sdk/lib/io/file_system_entity.dart
index 5c15c1c..f392327 100644
--- a/sdk/lib/io/file_system_entity.dart
+++ b/sdk/lib/io/file_system_entity.dart
@@ -439,7 +439,7 @@
    */
   Stream<FileSystemEvent> watch({int events: FileSystemEvent.ALL,
                                  bool recursive: false})
-     => _FileSystemWatcher.watch(_trimTrailingPathSeparators(path),
+     => _FileSystemWatcher._watch(_trimTrailingPathSeparators(path),
                                  events,
                                  recursive);
 
@@ -827,7 +827,7 @@
 
 
 class _FileSystemWatcher {
-  external static Stream<FileSystemEvent> watch(
+  external static Stream<FileSystemEvent> _watch(
       String path, int events, bool recursive);
   external static bool get isSupported;
 }
diff --git a/sdk/lib/io/io.dart b/sdk/lib/io/io.dart
index 4365035..c066b30 100644
--- a/sdk/lib/io/io.dart
+++ b/sdk/lib/io/io.dart
@@ -236,7 +236,6 @@
 part 'socket.dart';
 part 'stdio.dart';
 part 'string_transformer.dart';
-part 'timer_impl.dart';
 part 'secure_socket.dart';
 part 'secure_server_socket.dart';
 part 'websocket.dart';
diff --git a/sdk/lib/io/iolib_sources.gypi b/sdk/lib/io/iolib_sources.gypi
index 5b82147..96900f7 100644
--- a/sdk/lib/io/iolib_sources.gypi
+++ b/sdk/lib/io/iolib_sources.gypi
@@ -30,7 +30,6 @@
     'socket.dart',
     'stdio.dart',
     'string_transformer.dart',
-    'timer_impl.dart',
     'secure_socket.dart',
     'secure_server_socket.dart',
     'websocket.dart',
diff --git a/sdk/lib/io/process.dart b/sdk/lib/io/process.dart
index a977b31..43f6bcd 100644
--- a/sdk/lib/io/process.dart
+++ b/sdk/lib/io/process.dart
@@ -100,6 +100,19 @@
 int get pid => _ProcessUtils._pid(null);
 
 /**
+ * Modes for running a new process.
+ */
+enum ProcessStartMode {
+  /// Normal child process.
+  NORMAL,
+  /// Detached child process with no open communication channel.
+  DETACHED,
+  /// Detached child process with stdin, stdout and stderr still open
+  /// for communication with the child.
+  DETACHED_WITH_STDIO
+}
+
+/**
  * The means to execute a program.
  *
  * Use the static [start] and [run] methods to start a new process.
@@ -248,7 +261,7 @@
    * Users must read all data coming on the [stdout] and [stderr]
    * streams of processes started with [:Process.start:]. If the user
    * does not read all data on the streams the underlying system
-   * resources will not be freed since there is still pending data.
+   * resources will not be released since there is still pending data.
    *
    * The following code uses `Process.start` to grep for `main` in the
    * file `test.dart` on Linux.
@@ -258,12 +271,25 @@
    *       stderr.addStream(process.stderr);
    *     });
    *
-   * If [detach] is `true` a detached process will be created. A
-   * detached process has no connection to its parent, and can
-   * keep running on its own when the parent dies. The only
+   * If [mode] is [ProcessStartMode.NORMAL] (the default) a child
+   * process will be started with `stdin`, `stdout` and `stderr`
+   * connected.
+   *
+   * If `mode` is [ProcessStartMode.DETACHED] a detached process will
+   * be created. A detached process has no connection to its parent,
+   * and can keep running on its own when the parent dies. The only
    * information available from a detached process is its `pid`. There
-   * is no connection to its `stdin`, `stdout` or `stderr` nor will its
-   * exit code become available when it terminates.
+   * is no connection to its `stdin`, `stdout` or `stderr`, nor will
+   * the process' exit code become available when it terminates.
+   *
+   * If `mode` is [ProcessStartMode.DETACHED_WITH_STDIO] a detached
+   * process will be created where the `stdin`, `stdout` and `stderr`
+   * are connected. The creator can communicate with the child through
+   * these. The detached process will keep running even if these
+   * communication channels are closed. The process' exit code will
+   * not become available when it terminated.
+   *
+   * The default value for `mode` is `ProcessStartMode.NORMAL`.
    */
   external static Future<Process> start(
       String executable,
@@ -272,7 +298,7 @@
        Map<String, String> environment,
        bool includeParentEnvironment: true,
        bool runInShell: false,
-       bool detach: false});
+       ProcessStartMode mode: ProcessStartMode.NORMAL});
 
   /**
    * Starts a process and runs it non-interactively to completion. The
@@ -346,6 +372,25 @@
        Encoding stderrEncoding: SYSTEM_ENCODING});
 
   /**
+   * Kills the process with id [pid].
+   *
+   * Where possible, sends the [signal] to the process with id
+   * `pid`. This includes Linux and OS X. The default signal is
+   * [ProcessSignal.SIGTERM] which will normally terminate the
+   * process.
+   *
+   * On platforms without signal support, including Windows, the call
+   * just terminates the process with id `pid` in a platform specific
+   * way, and the `signal` parameter is ignored.
+   *
+   * Returns `true` if the signal is successfully delivered to the
+   * process. Otherwise the signal could not be sent, usually meaning
+   * that the process is already dead.
+   */
+  external static bool killPid(
+      int pid, [ProcessSignal signal = ProcessSignal.SIGTERM]);
+
+  /**
    * Returns the standard output stream of the process as a [:Stream:].
    */
   Stream<List<int>> get stdout;
@@ -366,15 +411,19 @@
   int get pid;
 
   /**
-   * On Linux and Mac OS, [kill] sends [signal] to the process. When the process
-   * terminates as a result of calling [kill], the value for [exitCode] may be a
-   * negative number corresponding to the provided [signal].
+   * Kills the process.
    *
-   * On Windows, [kill] kills the process, ignoring the [signal] flag.
+   * Where possible, sends the [signal] to the process. This includes
+   * Linux and OS X. The default signal is [ProcessSignal.SIGTERM]
+   * which will normally terminate the process.
    *
-   * Returns [:true:] if the signal is successfully sent and process is killed.
-   * Otherwise the signal could not be sent, usually meaning that the process is
-   * already dead.
+   * On platforms without signal support, including Windows, the call
+   * just terminates the process in a platform specific way, and the
+   * `signal` parameter is ignored.
+   *
+   * Returns `true` if the signal is successfully delivered to the
+   * process. Otherwise the signal could not be sent, usually meaning
+   * that the process is already dead.
    */
   bool kill([ProcessSignal signal = ProcessSignal.SIGTERM]);
 }
diff --git a/sdk/lib/profiler/profiler.dart b/sdk/lib/profiler/profiler.dart
index 1834f37b..0081ecf 100644
--- a/sdk/lib/profiler/profiler.dart
+++ b/sdk/lib/profiler/profiler.dart
@@ -186,14 +186,13 @@
   }
 
   static String _printMetrics() {
-    var members = [];
+    var metrics = [];
     for (var metric in _metrics.values) {
-      members.add(metric._toJSON());
+      metrics.add(metric._toJSON());
     }
     var map = {
       'type': 'MetricList',
-      'id': 'metrics',
-      'members': members,
+      'metrics': metrics,
     };
     return JSON.encode(map);
   }
diff --git a/sdk/lib/web_audio/dart2js/web_audio_dart2js.dart b/sdk/lib/web_audio/dart2js/web_audio_dart2js.dart
index 9a47ceb..9524b80 100644
--- a/sdk/lib/web_audio/dart2js/web_audio_dart2js.dart
+++ b/sdk/lib/web_audio/dart2js/web_audio_dart2js.dart
@@ -961,6 +961,17 @@
   // To suppress missing implicit constructor warnings.
   factory ScriptProcessorNode._() { throw new UnsupportedError("Not supported"); }
 
+  /**
+   * Static factory designed to expose `audioprocess` events to event
+   * handlers that are not necessarily instances of [ScriptProcessorNode].
+   *
+   * See [EventStreamProvider] for usage information.
+   */
+  @DomName('ScriptProcessorNode.audioprocessEvent')
+  @DocsEditable()
+  @Experimental() // untriaged
+  static const EventStreamProvider<AudioProcessingEvent> audioProcessEvent = const EventStreamProvider<AudioProcessingEvent>('audioprocess');
+
   @DomName('ScriptProcessorNode.bufferSize')
   @DocsEditable()
   final int bufferSize;
@@ -969,6 +980,19 @@
   @DocsEditable()
   @Experimental() // untriaged
   void setEventListener(EventListener eventListener) native;
+
+  /// Stream of `audioprocess` events handled by this [ScriptProcessorNode].
+/**
+   * Get a Stream that fires events when AudioProcessingEvents occur.
+   * This particular stream is special in that it only allows one listener to a
+   * given stream. Converting the returned Stream [asBroadcast] will likely ruin
+   * the soft-real-time properties which which these events are fired and can
+   * be processed.
+   */
+  @DomName('ScriptProcessorNode.onaudioprocess')
+  @DocsEditable()
+  @Experimental() // untriaged
+  Stream<AudioProcessingEvent> get onAudioProcess => audioProcessEvent.forTarget(this);
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
diff --git a/sdk/lib/web_audio/dartium/web_audio_dartium.dart b/sdk/lib/web_audio/dartium/web_audio_dartium.dart
index 0178795..40547d5 100644
--- a/sdk/lib/web_audio/dartium/web_audio_dartium.dart
+++ b/sdk/lib/web_audio/dartium/web_audio_dartium.dart
@@ -1152,6 +1152,17 @@
   // To suppress missing implicit constructor warnings.
   factory ScriptProcessorNode._() { throw new UnsupportedError("Not supported"); }
 
+  /**
+   * Static factory designed to expose `audioprocess` events to event
+   * handlers that are not necessarily instances of [ScriptProcessorNode].
+   *
+   * See [EventStreamProvider] for usage information.
+   */
+  @DomName('ScriptProcessorNode.audioprocessEvent')
+  @DocsEditable()
+  @Experimental() // untriaged
+  static const EventStreamProvider<AudioProcessingEvent> audioProcessEvent = const EventStreamProvider<AudioProcessingEvent>('audioprocess');
+
   @DomName('ScriptProcessorNode.bufferSize')
   @DocsEditable()
   int get bufferSize => _blink.BlinkScriptProcessorNode.instance.bufferSize_Getter_(this);
@@ -1161,6 +1172,19 @@
   @Experimental() // untriaged
   void setEventListener(EventListener eventListener) => _blink.BlinkScriptProcessorNode.instance.setEventListener_Callback_1_(this, eventListener);
 
+  /// Stream of `audioprocess` events handled by this [ScriptProcessorNode].
+/**
+   * Get a Stream that fires events when AudioProcessingEvents occur.
+   * This particular stream is special in that it only allows one listener to a
+   * given stream. Converting the returned Stream [asBroadcast] will likely ruin
+   * the soft-real-time properties which which these events are fired and can
+   * be processed.
+   */
+  @DomName('ScriptProcessorNode.onaudioprocess')
+  @DocsEditable()
+  @Experimental() // untriaged
+  Stream<AudioProcessingEvent> get onAudioProcess => audioProcessEvent.forTarget(this);
+
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
diff --git a/tests/co19/co19-analyzer.status b/tests/co19/co19-analyzer.status
index 3d3ecf6..f940b1a 100644
--- a/tests/co19/co19-analyzer.status
+++ b/tests/co19/co19-analyzer.status
@@ -4,8 +4,6 @@
 
 [ $compiler == dartanalyzer ]
 
-LibTest/core/RegExp/firstMatch_A01_t01: Fail
-
 # TBF: infinite look: class A {const A();final m = const A();}
 Language/12_Expressions/01_Constants_A17_t03: fail
 
diff --git a/tests/co19/co19-analyzer2.status b/tests/co19/co19-analyzer2.status
index 668753e..4404570 100644
--- a/tests/co19/co19-analyzer2.status
+++ b/tests/co19/co19-analyzer2.status
@@ -4,8 +4,6 @@
 
 [ $compiler == dart2analyzer ]
 
-LibTest/core/RegExp/firstMatch_A01_t01: Fail
-
 # TBF: infinite look: class A {const A();final m = const A();}
 Language/12_Expressions/01_Constants_A17_t03: fail
 
diff --git a/tests/co19/co19-co19.status b/tests/co19/co19-co19.status
index 136e761..a500f54 100644
--- a/tests/co19/co19-co19.status
+++ b/tests/co19/co19-co19.status
@@ -16,6 +16,8 @@
 LibTest/typed_data/ByteData/buffer_A01_t01: Fail # co19 r736 bug - sent comment.
 LayoutTests/fast/mediastream/getusermedia_t01: Fail # co19 issue 738.
 
+LibTest/core/RegExp/firstMatch_A01_t01: Fail # co19 issue 742
+
 # These tests are obsolete and need updating.
 WebPlatformTest/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-002_t01: Skip # Issue 19019
 WebPlatformTest/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-003_t01: Skip # Issue 19019
@@ -50,6 +52,9 @@
 LibTest/core/Expando/Expando_A03_t04: RuntimeError # Issue 17735
 LibTest/core/Expando/Expando_A03_t05: RuntimeError # Issue 17735
 
+LibTest/core/RegExp/Pattern_semantics/firstMatch_DecimalEscape_A01_t02: Fail # co19 issue 740
+LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterEscape_A06_t02: RuntimeError # co19 issue 741
+
 LibTest/isolate/SendPort/send_A02_t02: SKIP # co19 issue 493 (not fixed in r672)
 LibTest/isolate/SendPort/send_A02_t03: SKIP # co19 issue 495 (not fixed in r672)
 
diff --git a/tests/co19/co19-dart2dart.status b/tests/co19/co19-dart2dart.status
index ec87538..8a25345 100644
--- a/tests/co19/co19-dart2dart.status
+++ b/tests/co19/co19-dart2dart.status
@@ -80,12 +80,9 @@
 LibTest/core/Function/Function_class_A01_t01: RuntimeError # co19-roll r623: Please triage this failure
 LibTest/core/Function/apply_A01_t01: RuntimeError # Issue 21673
 LibTest/core/Invocation/memberName_A01_t01: Pass, RuntimeError # co18-roll r607: Please triage this failure
-LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterEscape_A06_t02: Fail
-LibTest/core/RegExp/Pattern_semantics/firstMatch_DecimalEscape_A01_t02: Fail # inherited from VM
-LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t01: Fail # inherited from VM
-LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t05: Fail
-LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t06: Fail
-LibTest/core/RegExp/firstMatch_A01_t01: Fail, OK # co19 issue 294
+LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t01: Fail # inherited from VM. Issue 22200
+LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t05: Fail # inherited from VM. Issue 22200
+LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t06: Fail # inherited from VM. Issue 22200
 LibTest/core/Symbol/Symbol_A01_t03: RuntimeError # co19-roll r607: Please triage this failure
 LibTest/core/Symbol/Symbol_A01_t05: RuntimeError # co19-roll r607: Please triage this failure
 LibTest/core/int/operator_left_shift_A01_t02: Fail, OK # co19 issue 129
diff --git a/tests/co19/co19-dart2js.status b/tests/co19/co19-dart2js.status
index c221ae8..d9c713f 100644
--- a/tests/co19/co19-dart2js.status
+++ b/tests/co19/co19-dart2js.status
@@ -76,7 +76,6 @@
 LibTest/core/List/getRange_A03_t01: RuntimeError, OK # Tests that fail because they use the legacy try-catch syntax. co19 issue 184.
 LibTest/core/List/removeAt_A02_t01: RuntimeError # Issue 1533
 LibTest/core/List/sort_A01_t06: Slow, Pass # Slow tests that needs extra time to finish.
-LibTest/core/RegExp/firstMatch_A01_t01: RuntimeError, OK # co19 issue 294
 LibTest/core/double/INFINITY_A01_t04: RuntimeError # Please triage this failure.
 LibTest/core/double/NEGATIVE_INFINITY_A01_t04: RuntimeError # Please triage this failure.
 LibTest/core/int/hashCode_A01_t01: RuntimeError, OK # co19 issue 308
@@ -367,12 +366,9 @@
 
 [ $compiler == dart2js && $jscl ]
 LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterClassEscape_A03_t01: Fail, Pass # issue 3333
-LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterEscape_A06_t02: RuntimeError # Please triage this failure
-LibTest/core/RegExp/Pattern_semantics/firstMatch_DecimalEscape_A01_t02: RuntimeError # Expect.fail('Some exception expected')
-LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t01: RuntimeError, OK # This is not rejected by V8.
-LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t05: RuntimeError # Expect.fail('Some exception expected')
-LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t06: RuntimeError # Expect.fail('Some exception expected')
-LibTest/core/RegExp/firstMatch_A01_t01: RuntimeError, OK # Bad test, use Match.regexp, not Match.pattern.
+LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t01: RuntimeError, OK # This is not rejected by V8. Issue 22200
+LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t05: RuntimeError # Issue 22200
+LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t06: RuntimeError # Issue 22200
 LibTest/core/int/compareTo_A01_t01: RuntimeError, OK # Requires big int.
 LibTest/core/int/hashCode_A01_t01: RuntimeError, OK # co19 testing missing assertion.
 LibTest/core/int/isEven_A01_t01: RuntimeError, OK # Not in API.
@@ -411,6 +407,8 @@
 LayoutTests/fast/forms/form-submission-create-crash_t01.dart: Skip # Test reloads itself. Issue 18558.
 LayoutTests/fast/forms/formmethod-attribute-button-html_t01: Skip # Test reloads itself. Issue 18558.
 LayoutTests/fast/forms/formmethod-attribute-input-2_t01: Skip # Test reloads itself. Issue 18558.
+LayoutTests/fast/forms/missing-action_t01: Skip # Test reloads itself. Issue 18558.
+LayoutTests/fast/forms/submit-form-with-dirname-attribute_t01: Skip # Test reloads itself. Issue 18558.
 LayoutTests/fast/forms/submit-form-with-dirname-attribute-with-ancestor-dir-attribute_t01: Skip # Test reloads itself. Issue 18558.
 LayoutTests/fast/forms/submit-form-with-dirname-attribute-with-nonhtml-ancestor_t01: Skip # Test reloads itself. Issue 18558.
 LayoutTests/fast/forms/submit-nil-value-field-assert_t01: Skip # Test reloads itself. Issue 18558.
@@ -421,11 +419,9 @@
 Language/12_Expressions/05_Strings_A06_t01: Pass, Slow # Please triage this failure.
 Language/12_Expressions/05_Strings_A06_t01: Pass, Slow # Please triage this failure.
 Language/12_Expressions/17_Getter_Invocation_A07_t02: RuntimeError # Please triage this failure.
-LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterEscape_A06_t02: Fail # Please triage this failure.
-LibTest/core/RegExp/Pattern_semantics/firstMatch_DecimalEscape_A01_t02: Fail # Please triage this failure.
-LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t01: Fail # Please triage this failure.
-LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t05: Fail # Please triage this failure.
-LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t06: Fail # Please triage this failure.
+LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t01: Fail # Issue 22200.
+LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t05: Fail # Issue 22200.
+LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t06: Fail # Issue 22200.
 LibTest/core/Set/removeAll_A01_t02: Pass, Slow # Please triage this failure.
 LibTest/core/int/compareTo_A01_t01: Fail # Please triage this failure.
 LibTest/core/int/operator_left_shift_A01_t01: Fail # Please triage this failure.
@@ -983,6 +979,7 @@
 LayoutTests/fast/writing-mode/flipped-blocks-hit-test-overflow_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/writing-mode/positionForPoint_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/writing-mode/table-hit-test_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/writing-mode/vertical-font-vmtx-units-per-em_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/writing-mode/vertical-inline-block-hittest_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/xmlhttprequest/xmlhttprequest-responseXML-xml-text-responsetype_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/xmlhttprequest/xmlhttprequest-responsetype-arraybuffer_t01: RuntimeError # Please triage this failure
@@ -1005,11 +1002,9 @@
 LayoutTests/fast/xpath/py-dom-xpath/paths_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/xpath/reverse-axes_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/xsl/default-html_t01: RuntimeError # Please triage this failure
-LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterEscape_A06_t02: RuntimeError # Please triage this failure
-LibTest/core/RegExp/Pattern_semantics/firstMatch_DecimalEscape_A01_t02: RuntimeError # Please triage this failure
-LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t01: RuntimeError # Please triage this failure
-LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t05: RuntimeError # Please triage this failure
-LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t06: RuntimeError # Please triage this failure
+LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t01: RuntimeError # Issue 22200
+LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t05: RuntimeError # Issue 22200
+LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t06: RuntimeError # Issue 22200
 LibTest/core/int/compareTo_A01_t01: RuntimeError # Please triage this failure
 LibTest/core/int/operator_left_shift_A01_t01: RuntimeError # Please triage this failure
 LibTest/core/int/operator_remainder_A01_t03: RuntimeError # Please triage this failure
@@ -1782,6 +1777,7 @@
 LayoutTests/fast/css/link-disabled-attr-parser_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/list-item-text-align_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/margin-start-end_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/css/max-device-aspect-ratio_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/css/media-query-recovery_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/modify-ua-rules-from-javascript_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/nested-at-rules_t01: RuntimeError # Please triage this failure
@@ -2599,11 +2595,9 @@
 LayoutTests/fast/xsl/default-html_t01: RuntimeError # Please triage this failure
 LibTest/async/Stream/Stream.periodic_A01_t01: Pass, RuntimeError # Please triage this failure
 LibTest/async/Timer/Timer.periodic_A01_t01: Pass, RuntimeError # Please triage this failure
-LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterEscape_A06_t02: RuntimeError # Please triage this failure
-LibTest/core/RegExp/Pattern_semantics/firstMatch_DecimalEscape_A01_t02: RuntimeError # Please triage this failure
-LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t01: RuntimeError # Please triage this failure
-LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t05: RuntimeError # Please triage this failure
-LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t06: RuntimeError # Please triage this failure
+LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t01: RuntimeError # Issue 22200
+LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t05: RuntimeError # Issue 22200
+LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t06: RuntimeError # Issue 22200
 LibTest/core/double/roundToDouble_A01_t01: Pass, RuntimeError # Passes on ff 35. Please triage this failure
 LibTest/core/double/round_A01_t01: Pass, RuntimeError # Passes on ff 35. Please triage this failure
 LibTest/core/int/compareTo_A01_t01: RuntimeError # Please triage this failure
@@ -3711,6 +3705,7 @@
 LayoutTests/fast/shapes/shape-outside-floats/shape-outside-rounded-boxes_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/shapes/shape-outside-floats/shape-outside-rounded-boxes_t02: RuntimeError # Please triage this failure
 LayoutTests/fast/speechsynthesis/speech-synthesis-cancel_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/speechsynthesis/speech-synthesis-pause-resume_t01: Skip # Times out. Please triage this failure
 LayoutTests/fast/speechsynthesis/speech-synthesis-utterance-uses-voice_t01: Skip # Times out. Please triage this failure
 LayoutTests/fast/speechsynthesis/speech-synthesis-voices_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/storage/disallowed-storage_t01: RuntimeError # Please triage this failure
@@ -3834,11 +3829,9 @@
 LayoutTests/fast/xpath/py-dom-xpath/paths_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/xpath/reverse-axes_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/xsl/default-html_t01: RuntimeError # Please triage this failure
-LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterEscape_A06_t02: RuntimeError # Please triage this failure
-LibTest/core/RegExp/Pattern_semantics/firstMatch_DecimalEscape_A01_t02: RuntimeError # Please triage this failure
-LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t01: RuntimeError # Please triage this failure
-LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t05: RuntimeError # Please triage this failure
-LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t06: RuntimeError # Please triage this failure
+LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t01: RuntimeError # Issue 22200
+LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t05: RuntimeError # Issue 22200
+LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t06: RuntimeError # Issue 22200
 LibTest/core/double/roundToDouble_A01_t01: RuntimeError # Please triage this failure
 LibTest/core/double/round_A01_t01: RuntimeError # Please triage this failure
 LibTest/core/int/compareTo_A01_t01: RuntimeError # Please triage this failure
@@ -4602,6 +4595,7 @@
 LayoutTests/fast/dom/HTMLScriptElement/async-onbeforeload_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/HTMLScriptElement/defer-inline-script_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/HTMLScriptElement/defer-onbeforeload_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/dom/HTMLScriptElement/script-set-src_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/dom/HTMLSelectElement/selected-index-preserved-when-option-text-changes_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/HTMLTemplateElement/cloneNode_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/HTMLTemplateElement/content-outlives-template-crash_t01: RuntimeError # Please triage this failure
@@ -5041,7 +5035,7 @@
 LayoutTests/fast/table/incorrect-colgroup-span-values_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/table/large-shrink-wrapped-width_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/table/margins-perpendicular-containing-block_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/table/min-width-css-block-table_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/table/min-width-css-block-table_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/table/min-width-css-inline-table_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/table/min-width-html-block-table_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/table/min-width-html-inline-table_t01: Pass, RuntimeError # Please triage this failure
@@ -5139,11 +5133,9 @@
 LayoutTests/fast/xsl/default-html_t01: RuntimeError # Please triage this failure
 LibTest/core/List/List_A02_t01: RuntimeError # Please triage this failure
 LibTest/core/List/List_A03_t01: RuntimeError # Please triage this failure
-LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterEscape_A06_t02: RuntimeError # Please triage this failure
-LibTest/core/RegExp/Pattern_semantics/firstMatch_DecimalEscape_A01_t02: RuntimeError # Please triage this failure
-LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t01: RuntimeError # Please triage this failure
-LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t05: RuntimeError # Please triage this failure
-LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t06: RuntimeError # Please triage this failure
+LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t01: RuntimeError # Issue 22200
+LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t05: RuntimeError # Issue 22200
+LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t06: RuntimeError # Issue 22200
 LibTest/core/double/roundToDouble_A01_t01: RuntimeError # Please triage this failure
 LibTest/core/double/round_A01_t01: RuntimeError # Please triage this failure
 LibTest/core/int/compareTo_A01_t01: RuntimeError # Please triage this failure
@@ -5526,13 +5518,17 @@
 
 [ $compiler == dart2js && $runtime == ie10 ]
 Language/12_Expressions/00_Object_Identity/1_Object_Identity_A05_t02: RuntimeError # Please triage this failure
+Language/12_Expressions/17_Getter_Invocation_A03_t02: Skip # Times out. Please triage this failure
 Language/12_Expressions/17_Getter_Invocation_A07_t02: RuntimeError # Please triage this failure
 LayoutTests/fast/alignment/parse-align-items_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/alignment/parse-align-self_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/alignment/parse-justify-self_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/animation/request-animation-frame-cancel_t01: Skip # Times out. Please triage this failure
 LayoutTests/fast/animation/request-animation-frame-cancel2_t01: Skip # Times out. Please triage this failure
+LayoutTests/fast/animation/request-animation-frame-cancel_t01: Skip # Times out. Please triage this failure
 LayoutTests/fast/animation/request-animation-frame-prefix_t01: Skip # Times out. Please triage this failure
+LayoutTests/fast/animation/request-animation-frame-timestamps-advance_t01: Skip # Times out. Please triage this failure
+LayoutTests/fast/animation/request-animation-frame-timestamps_t01: Skip # Times out. Please triage this failure
+LayoutTests/fast/animation/request-animation-frame-within-callback_t01: Skip # Times out. Please triage this failure
 LayoutTests/fast/backgrounds/background-position-parsing-2_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/backgrounds/background-repeat-computed-style_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/backgrounds/background-shorthand-with-backgroundSize-style_t01: RuntimeError # Please triage this failure
@@ -5592,6 +5588,7 @@
 LayoutTests/fast/canvas/canvas-font-ex-units-crash_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/canvas-getImageData-invalid_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/canvas-getImageData-large-crash_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/canvas-getImageData-negative-source_t01: Pass, RuntimeError # Issue 22216
 LayoutTests/fast/canvas/canvas-getImageData-rounding_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/canvas-imageSmoothingEnabled-repaint_t01: Skip # Times out. Please triage this failure
 LayoutTests/fast/canvas/canvas-imageSmoothingEnabled_t01: RuntimeError # Please triage this failure
@@ -5602,21 +5599,31 @@
 LayoutTests/fast/canvas/canvas-lineDash_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/canvas-lose-restore-googol-size_t01: Skip # Times out. Please triage this failure
 LayoutTests/fast/canvas/canvas-lose-restore-max-int-size_t01: Skip # Times out. Please triage this failure
+LayoutTests/fast/canvas/canvas-modify-emptyPath_t01: Pass, RuntimeError # Issue 22216
+LayoutTests/fast/canvas/canvas-pattern-behaviour_t01: Pass, RuntimeError # Issue 22216
 LayoutTests/fast/canvas/canvas-putImageData_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/canvas-resetTransform_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/canvas-resize-after-paint_t01: Skip # Times out. Please triage this failure
+LayoutTests/fast/canvas/canvas-save-restore-with-path_t01: Pass, RuntimeError # Issue 22216
+LayoutTests/fast/canvas/canvas-save-restore_t01: Pass, RuntimeError # Issue 22216
+LayoutTests/fast/canvas/canvas-scale-drawImage-shadow_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/canvas-scale-drawImage-shadow_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/canvas-scale-shadowBlur_t01: Pass, RuntimeError # Issue 22216
 LayoutTests/fast/canvas/canvas-scale-strokePath-shadow_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/canvas-set-properties-with-non-invertible-ctm_t01: Pass, RuntimeError # Issue 22216
 LayoutTests/fast/canvas/canvas-setTransform_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/canvas-transforms-fillRect-shadow_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/canvas-to-canvas_t01: Pass, RuntimeError # Issue 22216
+LayoutTests/fast/canvas/canvas-transforms-fillRect-shadow_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/crash-set-font_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/draw-custom-focus-ring_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/drawImage-with-bad-canvas_t01: Skip # Times out. Please triage this failure
+LayoutTests/fast/canvas/drawImage-with-negative-source-destination_t01: Pass, RuntimeError # Issue 22216
 LayoutTests/fast/canvas/drawImage-with-valid-image_t01: Skip # Times out. Please triage this failure
 LayoutTests/fast/canvas/fallback-content_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/getPutImageDataPairTest_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/pointInPath_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/rgba-parsing_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/set-colors_t01: Pass, RuntimeError # Issue 22216
 LayoutTests/fast/canvas/setWidthResetAfterForcedRender_t01: Skip # Times out. Please triage this failure
 LayoutTests/fast/canvas/webgl/WebGLContextEvent_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/array-bounds-clamping_t01: RuntimeError # Please triage this failure
@@ -5731,7 +5738,9 @@
 LayoutTests/fast/canvas/winding-enumeration_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css-generated-content/block-after_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css-generated-content/malformed-url_t01: Skip # Times out. Please triage this failure
+LayoutTests/fast/css-generated-content/pseudo-animation-before-onload_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/css-generated-content/pseudo-animation-display_t01: Skip # Times out. Please triage this failure
+LayoutTests/fast/css-generated-content/pseudo-animation_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/css-generated-content/pseudo-element-events_t01: Skip # Times out. Please triage this failure
 LayoutTests/fast/css-generated-content/pseudo-transition-event_t01: Skip # Times out. Please triage this failure
 LayoutTests/fast/css-generated-content/pseudo-transition_t01: RuntimeError # Please triage this failure
@@ -5836,7 +5845,7 @@
 LayoutTests/fast/css/dynamic-class-pseudo-elements_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/ex-unit-with-no-x-height_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/first-child-display-change-inverse_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/css/font-face-cache-bug_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/css/font-face-cache-bug_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/css/font-face-insert-link_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/css/font-face-multiple-ranges-for-unicode-range_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/font-face-unicode-range-load_t01: RuntimeError # Please triage this failure
@@ -5875,6 +5884,7 @@
 LayoutTests/fast/css/html-attr-case-sensitivity_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/id-or-class-before-stylesheet_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/image-set-setting_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/css/implicit-attach-marking_t01: Skip # Times out. Please triage this failure
 LayoutTests/fast/css/inherit-initial-shorthand-values_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/inherited-properties-rare-text_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/insertRule-font-face_t01: RuntimeError # Please triage this failure
@@ -5904,6 +5914,7 @@
 LayoutTests/fast/css/link-disabled-attr-parser_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/list-item-text-align_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/margin-start-end_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/css/max-device-aspect-ratio_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/css/media-query-recovery_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/modify-ua-rules-from-javascript_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/nested-at-rules_t01: RuntimeError # Please triage this failure
@@ -5953,7 +5964,7 @@
 LayoutTests/fast/css/remove-class-name_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/resize-value-compared_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/selector-text-escape_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/css/shadow-current-color_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/css/shadow-current-color_t01: Skip # Times out. Please triage this failure
 LayoutTests/fast/css/sheet-collection-link_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/shorthand-priority_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/shorthand-setProperty-important_t01: RuntimeError # Please triage this failure
@@ -5967,9 +5978,9 @@
 LayoutTests/fast/css/style-scoped/style-scoped-shadow-crash_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/style-scoped/style-scoped-with-dom-operation_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/style-scoped/style-scoped-with-important-rule_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/css/stylesheet-enable-first-alternate-link_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/css/stylesheet-enable-first-alternate-link_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/css/stylesheet-enable-first-alternate-on-load-link_t01: Pass, RuntimeError # Please triage this failure
-LayoutTests/fast/css/stylesheet-enable-first-alternate-on-load-sheet_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/css/stylesheet-enable-first-alternate-on-load-sheet_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/css/stylesheet-enable-second-alternate-link_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/css/text-align-initial_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/text-align-webkit-match-parent-parse_t01: RuntimeError # Please triage this failure
@@ -6110,7 +6121,7 @@
 LayoutTests/fast/dom/HTMLOutputElement/htmloutputelement-value_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/HTMLOutputElement/htmloutputelement_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/HTMLProgressElement/set-progress-properties_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/dom/HTMLScriptElement/async-false-inside-async-false-load_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/dom/HTMLScriptElement/async-false-inside-async-false-load_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/dom/HTMLScriptElement/async-inline-script_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/HTMLScriptElement/async-onbeforeload_t01: Skip # Times out. Please triage this failure
 LayoutTests/fast/dom/HTMLScriptElement/defer-inline-script_t01: RuntimeError # Please triage this failure
@@ -6251,7 +6262,7 @@
 LayoutTests/fast/dom/css-delete-doc_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/css-innerHTML_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/css-insert-import-rule-twice_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/dom/css-insert-import-rule_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/dom/css-insert-import-rule_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/dom/css-mediarule-functions_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/css-selectorText_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/css-set-property-exception_t01: RuntimeError # Please triage this failure
@@ -6594,9 +6605,9 @@
 LayoutTests/fast/forms/input-widths_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/forms/listbox-select-all_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/forms/listbox-selection-2_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/forms/menulist-disabled-selected-option_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/forms/menulist-disabled-selected-option_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/forms/menulist-selection-reset_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/forms/menulist-submit-without-selection_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/forms/menulist-submit-without-selection_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/forms/method-attribute_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/forms/multiple-selected-options-innerHTML_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/forms/onchange-change-type_t01: RuntimeError # Please triage this failure
@@ -6956,14 +6967,13 @@
 LayoutTests/fast/xsl/xslt-string-parameters_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/xsl/xslt-transform-to-fragment-crash_t01: RuntimeError # Please triage this failure
 LibTest/async/Stream/Stream.periodic_A01_t01: Pass, RuntimeError # Please triage this failure
-LibTest/async/StreamController/StreamController.broadcast_A04_t01: RuntimeError # Please triage this failure
+LibTest/async/StreamController/StreamController.broadcast_A04_t01: Pass, RuntimeError # Please triage this failure
 LibTest/async/Timer/Timer.periodic_A01_t01: Pass, RuntimeError # Please triage this failure
 LibTest/async/Timer/Timer_A01_t01: Pass, RuntimeError # Please triage this failure
-LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterEscape_A06_t02: RuntimeError # Please triage this failure
-LibTest/core/RegExp/Pattern_semantics/firstMatch_DecimalEscape_A01_t02: RuntimeError # Please triage this failure
-LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t01: RuntimeError # Please triage this failure
-LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t05: RuntimeError # Please triage this failure
-LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t06: RuntimeError # Please triage this failure
+LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t01: RuntimeError # Issue 22200
+LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t05: RuntimeError # Issue 22200
+LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t06: RuntimeError # Issue 22200
+LibTest/core/double/operator_unary_minus_A01_t02: Skip # Times out. Please triage this failure
 LibTest/core/double/roundToDouble_A01_t01: RuntimeError # Please triage this failure
 LibTest/core/double/round_A01_t01: RuntimeError # Please triage this failure
 LibTest/core/double/toStringAsExponential_A01_t04: RuntimeError # Please triage this failure
@@ -6989,6 +6999,7 @@
 LibTest/html/Element/Element.tag_A01_t01: RuntimeError # Please triage this failure
 LibTest/html/Element/addEventListener_A01_t04: Pass, RuntimeError # Please triage this failure
 LibTest/html/Element/attributeChanged_A01_t01: RuntimeError # Please triage this failure
+LibTest/html/Element/blur_A01_t01: Skip # Times out. Please triage this failure
 LibTest/html/Element/dataset_A02_t01: RuntimeError # Please triage this failure
 LibTest/html/Element/enteredView_A01_t01: RuntimeError # Please triage this failure
 LibTest/html/Element/focusEvent_A01_t01: Pass, RuntimeError # Please triage this failure
@@ -7092,7 +7103,9 @@
 LibTest/typed_data/ByteData/ByteData.view_A01_t01: RuntimeError # Please triage this failure
 LibTest/typed_data/ByteData/offsetInBytes_A01_t01: RuntimeError # Please triage this failure
 LibTest/typed_data/Float32x4List/Float32x4List.view_A06_t01: RuntimeError # Please triage this failure
+LibTest/typed_data/Int32List/reduce_A01_t01: Skip # Times out. Please triage this failure
 LibTest/typed_data/Int32x4/operator_OR_A01_t01: RuntimeError # Please triage this failure
+LibTest/typed_data/Uint16List/setAll_A03_t01: Skip # Times out. Please triage this failure
 LibTest/typed_data/Uint8ClampedList/Uint8ClampedList.fromList_A01_t01: RuntimeError # Please triage this failure
 LibTest/typed_data/Uint8ClampedList/Uint8ClampedList.fromList_A01_t02: RuntimeError # Please triage this failure
 LibTest/typed_data/Uint8ClampedList/Uint8ClampedList.view_A01_t01: RuntimeError # Please triage this failure
@@ -7522,12 +7535,14 @@
 WebPlatformTest/webstorage/event_local_key_t01: RuntimeError # Please triage this failure
 WebPlatformTest/webstorage/event_local_newvalue_t01: RuntimeError # Please triage this failure
 WebPlatformTest/webstorage/event_local_oldvalue_t01: RuntimeError # Please triage this failure
+WebPlatformTest/webstorage/event_local_storagearea_t01: Pass, RuntimeError # Please triage this failure
 WebPlatformTest/webstorage/event_local_storageeventinit_t01: Pass, RuntimeError # Please triage this failure
-WebPlatformTest/webstorage/event_local_url_t01: RuntimeError # Please triage this failure
+WebPlatformTest/webstorage/event_local_url_t01: Pass, RuntimeError # Please triage this failure
 WebPlatformTest/webstorage/event_session_key_t01: RuntimeError # Please triage this failure
 WebPlatformTest/webstorage/event_session_newvalue_t01: RuntimeError # Please triage this failure
 WebPlatformTest/webstorage/event_session_oldvalue_t01: RuntimeError # Please triage this failure
 WebPlatformTest/webstorage/event_session_storagearea_t01: RuntimeError # Please triage this failure
+WebPlatformTest/webstorage/event_session_storageeventinit_t01: Pass, RuntimeError # Please triage this failure
 WebPlatformTest/webstorage/event_session_url_t01: RuntimeError # Please triage this failure
 WebPlatformTest/webstorage/storage_builtins_t01: RuntimeError # Please triage this failure
 WebPlatformTest/webstorage/storage_local_setitem_quotaexceedederr_t01: Skip # Times out. Please triage this failure
@@ -7535,12 +7550,24 @@
 WebPlatformTest/webstorage/storage_session_setitem_t01: RuntimeError # Please triage this failure
 
 [ $compiler == dart2js && $runtime == ie11 ]
+Language/05_Variables/05_Variables_A14_t07: Skip # Times out. Please triage this failure
+Language/06_Functions/2_Formal_Parameters_A02_t01: Skip # Times out. Please triage this failure
 Language/12_Expressions/00_Object_Identity/1_Object_Identity_A05_t02: RuntimeError # Please triage this failure
 Language/12_Expressions/17_Getter_Invocation_A07_t02: RuntimeError # Please triage this failure
+Language/12_Expressions/19_Conditional_A06_t04: Skip # Times out. Please triage this failure
+Language/12_Expressions/30_Identifier_Reference_A10_t02: Skip # Times out. Please triage this failure
+Language/13_Statements/03_Variable_Declaration_A01_t18: Skip # Times out. Please triage this failure
+Language/15_Types/4_Interface_Types_A12_t07: Skip # Times out. Please triage this failure
 Language/15_Types/5_Function_Types_A01_t03: Skip # Times out. Please triage this failure
 LayoutTests/fast/alignment/parse-align-items_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/alignment/parse-align-self_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/alignment/parse-justify-self_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/animation/request-animation-frame-cancel2_t01: Skip # Times out. Please triage this failure
+LayoutTests/fast/animation/request-animation-frame-cancel_t01: Skip # Times out. Please triage this failure
+LayoutTests/fast/animation/request-animation-frame-prefix_t01: Skip # Times out. Please triage this failure
+LayoutTests/fast/animation/request-animation-frame-timestamps-advance_t01: Skip # Times out. Please triage this failure
+LayoutTests/fast/animation/request-animation-frame-timestamps_t01: Skip # Times out. Please triage this failure
+LayoutTests/fast/animation/request-animation-frame-within-callback_t01: Skip # Times out. Please triage this failure
 LayoutTests/fast/backgrounds/background-position-parsing-2_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/backgrounds/background-repeat-computed-style_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/backgrounds/background-shorthand-with-backgroundSize-style_t01: RuntimeError # Please triage this failure
@@ -7557,7 +7584,7 @@
 LayoutTests/fast/canvas/DrawImageSinglePixelStretch_t01: Skip # Times out. Please triage this failure
 LayoutTests/fast/canvas/alpha_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/canvas-arc-negative-radius_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/canvas-as-image-incremental-repaint_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/canvas-as-image-incremental-repaint_t01: Skip # Times out. Please triage this failure
 LayoutTests/fast/canvas/canvas-as-image_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/canvas-blend-image_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/canvas-blend-solid_t01: RuntimeError # Please triage this failure
@@ -7583,6 +7610,8 @@
 LayoutTests/fast/canvas/canvas-blending-shadow_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/canvas-blending-text_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/canvas-blending-transforms_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/canvas-composite-alpha_t01: Pass, RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/canvas-composite-text-alpha_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/canvas-css-crazy_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/canvas-currentColor_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/canvas-currentTransform_t01: RuntimeError # Please triage this failure
@@ -7594,8 +7623,9 @@
 LayoutTests/fast/canvas/canvas-font-ex-units-crash_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/canvas-getImageData-invalid_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/canvas-getImageData-large-crash_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/canvas-getImageData-negative-source_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/canvas-getImageData-rounding_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/canvas-imageSmoothingEnabled-repaint_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/canvas-imageSmoothingEnabled-repaint_t01: Skip # Times out. Please triage this failure
 LayoutTests/fast/canvas/canvas-imageSmoothingEnabled_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/canvas-large-dimensions_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/canvas-large-fills_t01: RuntimeError # Please triage this failure
@@ -7603,66 +7633,82 @@
 LayoutTests/fast/canvas/canvas-lineDash_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/canvas-lose-restore-googol-size_t01: Skip # Times out. Please triage this failure
 LayoutTests/fast/canvas/canvas-lose-restore-max-int-size_t01: Skip # Times out. Please triage this failure
+LayoutTests/fast/canvas/canvas-modify-emptyPath_t01: Pass, RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/canvas-pattern-behaviour_t01: Pass, RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/canvas-pattern-modify_t01: Pass, RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/canvas-pattern-transform_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/canvas-putImageData_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/canvas-resetTransform_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/canvas-scale-drawImage-shadow_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/canvas-resize-after-paint_t01: Skip # Times out. Please triage this failure
+LayoutTests/fast/canvas/canvas-save-restore-with-path_t01: Pass, RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/canvas-save-restore_t01: Pass, RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/canvas-scale-drawImage-shadow_t01: Pass, RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/canvas-scale-shadowBlur_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/canvas-scale-strokePath-shadow_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/canvas-set-properties-with-non-invertible-ctm_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/canvas-setTransform_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/canvas-toDataURL-crash_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/canvas-transforms-fillRect-shadow_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/canvas-to-canvas_t01: Pass, RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/canvas-toDataURL-crash_t01: Pass, RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/canvas-transforms-fillRect-shadow_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/crash-set-font_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/draw-custom-focus-ring_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/drawImage-with-bad-canvas_t01: Skip # Times out. Please triage this failure
+LayoutTests/fast/canvas/drawImage-with-negative-source-destination_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/drawImage-with-valid-image_t01: Skip # Times out. Please triage this failure
 LayoutTests/fast/canvas/getPutImageDataPairTest_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/pattern-with-transform_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/pointInPath_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/rgba-parsing_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/WebGLContextEvent_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/set-colors_t01: Pass, RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/setWidthResetAfterForcedRender_t01: Skip # Times out. Please triage this failure
+LayoutTests/fast/canvas/webgl/WebGLContextEvent_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/array-bounds-clamping_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/attrib-location-length-limits_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/bad-arguments-test_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/webgl/attrib-location-length-limits_t01: Pass, RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/webgl/bad-arguments-test_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/buffer-data-array-buffer_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/canvas-2d-webgl-texture_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/canvas-zero-size_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/webgl/canvas-2d-webgl-texture_t01: Pass, RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/webgl/canvas-test_t01: Skip # Times out. Please triage this failure
+LayoutTests/fast/canvas/webgl/canvas-zero-size_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/context-attributes-alpha-depth-stencil-antialias-t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/context-destroyed-crash_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/context-lost-restored_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/context-lost_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/webgl/context-lost_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/copy-tex-image-and-sub-image-2d_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/css-webkit-canvas-repaint_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/css-webkit-canvas_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/draw-arrays-out-of-bounds_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/webgl/draw-arrays-out-of-bounds_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/draw-elements-out-of-bounds_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/draw-webgl-to-canvas-2d_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/drawingbuffer-test_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/error-reporting_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/webgl/drawingbuffer-test_t01: Pass, RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/webgl/error-reporting_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/framebuffer-bindings-unaffected-on-resize_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/framebuffer-object-attachment_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/framebuffer-test_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/functions-returning-strings_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/get-active-test_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/gl-bind-attrib-location-test_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/webgl/functions-returning-strings_t01: Pass, RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/webgl/get-active-test_t01: Pass, RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/webgl/gl-bind-attrib-location-test_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/gl-getstring_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/gl-object-get-calls_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/gl-pixelstorei_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/gl-teximage_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/gl-uniformmatrix4fv_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/gl-vertex-attrib-zero-issues_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/glsl-conformance_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/incorrect-context-object-behaviour_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/webgl/gl-object-get-calls_t01: Pass, RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/webgl/gl-pixelstorei_t01: Pass, RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/webgl/gl-teximage_t01: Skip # Times out. Please triage this failure
+LayoutTests/fast/canvas/webgl/gl-uniformmatrix4fv_t01: Pass, RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/webgl/gl-vertex-attrib-zero-issues_t01: Pass, RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/webgl/glsl-conformance_t01: Pass, RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/webgl/incorrect-context-object-behaviour_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/index-validation-copies-indices_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/index-validation-verifies-too-many-indices_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/index-validation-with-resized-buffer_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/webgl/index-validation-with-resized-buffer_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/index-validation_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/invalid-passed-params_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/null-object-behaviour_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/null-uniform-location_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/webgl/null-object-behaviour_t01: Pass, RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/webgl/null-uniform-location_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/object-deletion-behaviour_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/oes-element-index-uint_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/point-size_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/webgl/point-size_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/premultiplyalpha-test_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/program-test_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/read-pixels-pack-alignment_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/read-pixels-test_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/webgl/program-test_t01: Pass, RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/webgl/read-pixels-pack-alignment_t01: Pass, RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/webgl/read-pixels-test_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/renderer-and-vendor-strings_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-array-buffer-view_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-canvas-rgb565_t01: RuntimeError # Please triage this failure
@@ -7673,43 +7719,46 @@
 LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-image-data-rgba4444_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-image-data-rgba5551_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-image-data_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-image-rgb565_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-image-rgba4444_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-image-rgba5551_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-image_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-video-rgb565_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-video-rgba4444_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-video-rgba5551_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-video_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/tex-image-and-uniform-binding-bugs_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/tex-image-webgl_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-image-rgb565_t01: Skip # Times out. Please triage this failure
+LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-image-rgba4444_t01: Skip # Times out. Please triage this failure
+LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-image-rgba5551_t01: Skip # Times out. Please triage this failure
+LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-image_t01: Skip # Times out. Please triage this failure
+LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-video-rgb565_t01: Skip # Times out. Please triage this failure
+LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-video-rgba4444_t01: Skip # Times out. Please triage this failure
+LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-video-rgba5551_t01: Skip # Times out. Please triage this failure
+LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-video_t01: Skip # Times out. Please triage this failure
+LayoutTests/fast/canvas/webgl/tex-image-and-uniform-binding-bugs_t01: Pass, RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/webgl/tex-image-webgl_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/tex-input-validation_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/tex-sub-image-2d-bad-args_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/tex-sub-image-2d_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/tex-sub-image-cube-maps_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/texImage2DImageDataTest_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/webgl/texImage2DImageDataTest_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/texImageTest_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/texture-active-bind_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/texture-bindings-uneffected-on-resize_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/texture-color-profile_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/texture-complete_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/webgl/texture-active-bind_t01: Pass, RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/webgl/texture-bindings-uneffected-on-resize_t01: Pass, RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/webgl/texture-color-profile_t01: Skip # Times out. Please triage this failure
+LayoutTests/fast/canvas/webgl/texture-complete_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/texture-npot_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/texture-transparent-pixels-initialized_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/triangle_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/uniform-location-length-limits_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/webgl/texture-transparent-pixels-initialized_t01: Skip # Times out. Please triage this failure
+LayoutTests/fast/canvas/webgl/triangle_t01: Pass, RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/webgl/uniform-location-length-limits_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/uniform-location_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/uninitialized-test_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/viewport-unchanged-upon-resize_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/webgl-composite-modes-repaint_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/webgl-composite-modes_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/webgl/viewport-unchanged-upon-resize_t01: Pass, RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/webgl/webgl-composite-modes-repaint_t01: Pass, RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/webgl/webgl-composite-modes_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/webgl-depth-texture_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/webgl-large-texture_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/webgl/webgl-layer-update_t01: Skip # Times out. Please triage this failure
 LayoutTests/fast/canvas/webgl/webgl-specific_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/webgl-texture-binding-preserved_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/webgl/webgl-texture-binding-preserved_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/webgl-unprefixed-context-id_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/winding-enumeration_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css-generated-content/block-after_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css-generated-content/malformed-url_t01: Skip # Times out. Please triage this failure
+LayoutTests/fast/css-generated-content/pseudo-animation_t01: Pass, RuntimeError # Please triage this failure
+LayoutTests/fast/css-generated-content/pseudo-animation-before-onload_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/css-generated-content/pseudo-animation-display_t01: Skip # Times out. Please triage this failure
 LayoutTests/fast/css-generated-content/pseudo-element-events_t01: Skip # Times out. Please triage this failure
 LayoutTests/fast/css-generated-content/pseudo-transition-event_t01: Skip # Times out. Please triage this failure
@@ -7817,6 +7866,7 @@
 LayoutTests/fast/css/ex-unit-with-no-x-height_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/first-child-display-change-inverse_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/font-face-cache-bug_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/css/font-face-insert-link_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/css/font-face-multiple-ranges-for-unicode-range_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/font-face-unicode-range-load_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/font-face-unicode-range-overlap-load_t01: RuntimeError # Please triage this failure
@@ -7853,6 +7903,7 @@
 LayoutTests/fast/css/html-attr-case-sensitivity_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/id-or-class-before-stylesheet_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/image-set-setting_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/css/implicit-attach-marking_t01: Skip # Times out. Please triage this failure
 LayoutTests/fast/css/inherit-initial-shorthand-values_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/inherited-properties-rare-text_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/insertRule-font-face_t01: RuntimeError # Please triage this failure
@@ -7932,7 +7983,7 @@
 LayoutTests/fast/css/remove-class-name_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/resize-value-compared_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/selector-text-escape_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/css/shadow-current-color_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/css/shadow-current-color_t01: Skip # Times out. Please triage this failure
 LayoutTests/fast/css/sheet-collection-link_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/shorthand-priority_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/shorthand-setProperty-important_t01: RuntimeError # Please triage this failure
@@ -7946,8 +7997,8 @@
 LayoutTests/fast/css/style-scoped/style-scoped-shadow-crash_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/style-scoped/style-scoped-with-dom-operation_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/style-scoped/style-scoped-with-important-rule_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/css/stylesheet-enable-first-alternate-link_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/css/stylesheet-enable-first-alternate-on-load-link_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/css/stylesheet-enable-first-alternate-link_t01: Pass, RuntimeError # Please triage this failure
+LayoutTests/fast/css/stylesheet-enable-first-alternate-on-load-link_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/css/stylesheet-enable-first-alternate-on-load-sheet_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/css/stylesheet-enable-second-alternate-link_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/css/text-align-initial_t01: RuntimeError # Please triage this failure
@@ -8105,7 +8156,7 @@
 LayoutTests/fast/dom/HTMLSelectElement/change-multiple-preserve-selection_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/HTMLSelectElement/named-options_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/HTMLSelectElement/selected-index-preserved-when-option-text-changes_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/dom/HTMLStyleElement/programmatically-add-style-with-onerror-handler_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/dom/HTMLStyleElement/programmatically-add-style-with-onerror-handler_t01: Skip # Times out. Please triage this failure
 LayoutTests/fast/dom/HTMLStyleElement/programmatically-add-style-with-onload-handler_t01: Skip # Times out. Please triage this failure
 LayoutTests/fast/dom/HTMLStyleElement/style-onerror-with-existent-and-non-existent-import_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/HTMLStyleElement/style-onerror_t01: RuntimeError # Please triage this failure
@@ -8136,7 +8187,7 @@
 LayoutTests/fast/dom/MutationObserver/weak-callback-gc-crash_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/Node/contains-method_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/Node/fragment-mutation_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/dom/Node/initial-values_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/dom/Node/initial-values_t01: Skip # Times out. Please triage this failure
 LayoutTests/fast/dom/NodeIterator/NodeIterator-basic_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/NodeList/nodelist-moved-to-fragment-2_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/NodeList/nodelist-reachable_t01: RuntimeError # Please triage this failure
@@ -8209,8 +8260,8 @@
 LayoutTests/fast/dom/createElement_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/css-delete-doc_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/css-innerHTML_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/dom/css-insert-import-rule-twice_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/dom/css-insert-import-rule_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/dom/css-insert-import-rule-twice_t01: Pass, RuntimeError # Please triage this failure
+LayoutTests/fast/dom/css-insert-import-rule_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/dom/css-mediarule-functions_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/css-selectorText_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/css-set-property-exception_t01: RuntimeError # Please triage this failure
@@ -8329,7 +8380,7 @@
 LayoutTests/fast/dom/shadow/shadow-aware-shadow-root_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/shadow/shadow-content-crash_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/shadow/shadow-disable_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/dom/shadow/shadow-element-inactive_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/dom/shadow/shadow-element-inactive_t01: Skip # Times out. Please triage this failure
 LayoutTests/fast/dom/shadow/shadow-element_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/shadow/shadow-hierarchy-exception_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/shadow/shadow-removechild-and-blur-event_t01: RuntimeError # Please triage this failure
@@ -8363,6 +8414,7 @@
 LayoutTests/fast/dynamic/crash-generated-quote_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dynamic/crash-generated-text_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dynamic/insertAdjacentElement_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/dynamic/insertAdjacentHTML-allowed-parents_t01: Skip # Times out. Please triage this failure
 LayoutTests/fast/dynamic/recursive-layout_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/encoding/css-charset-dom_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/events/add-event-without-document_t01: RuntimeError # Please triage this failure
@@ -8398,7 +8450,7 @@
 LayoutTests/fast/events/mutation-during-replace-child-2_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/events/mutation-during-replace-child_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/events/nested-event-remove-node-crash_t01: Skip # Times out. Please triage this failure
-LayoutTests/fast/events/overflowchanged-event-raf-timing_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/events/overflowchanged-event-raf-timing_t01: Skip # Times out. Please triage this failure
 LayoutTests/fast/events/scoped/editing-commands_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/events/scroll-during-zoom-change_t01: Skip # Times out. Please triage this failure
 LayoutTests/fast/events/scroll-event-does-not-bubble_t01: RuntimeError # Please triage this failure
@@ -8416,7 +8468,7 @@
 LayoutTests/fast/files/blob-constructor_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/files/blob-parts-slice-test_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/files/blob-slice-test_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/files/file-reader-done-reading-abort_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/files/file-reader-done-reading-abort_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/files/file-reader-methods-illegal-arguments_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/files/read-blob-as-array-buffer_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/files/url-null_t01: RuntimeError # Please triage this failure
@@ -8563,7 +8615,7 @@
 LayoutTests/fast/forms/paste-multiline-text-input_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/forms/plaintext-mode-1_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/forms/radio-checkbox-restore-indeterminate_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/forms/search-popup-crasher_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/forms/search-popup-crasher_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/forms/select-change-popup-to-listbox-in-event-handler_t01: Skip # Times out. Please triage this failure
 LayoutTests/fast/forms/select-clientheight-large-size_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/forms/select-clientheight-with-multiple-attr_t01: RuntimeError # Please triage this failure
@@ -8578,6 +8630,7 @@
 LayoutTests/fast/forms/setrangetext_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/forms/shadow-tree-exposure_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/forms/submit-form-attributes_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/forms/submit-form-with-dirname-attribute_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/forms/textarea-maxlength_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/forms/textarea-no-scroll-on-blur_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/forms/textarea-paste-newline_t01: Skip # Times out. Please triage this failure
@@ -8695,6 +8748,7 @@
 LayoutTests/fast/parser/residual-style-close-across-n-blocks_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/replaced/container-width-zero_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/replaced/iframe-with-percentage-height-within-table-with-anonymous-table-cell_t01: Pass, RuntimeError # Please triage this failure
+LayoutTests/fast/replaced/iframe-with-percentage-height-within-table-with-table-cell-ignore-height_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/replaced/preferred-widths_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/replaced/table-percent-height-text-controls_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/replaced/table-percent-height_t01: RuntimeError # Please triage this failure
@@ -8745,7 +8799,9 @@
 LayoutTests/fast/table/css-table-max-height_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/table/css-table-max-width_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/table/css-table-width-with-border-padding_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/table/hittest-tablecell-bottom-edge_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/table/hittest-tablecell-right-edge_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/table/hittest-tablecell-with-borders-bottom-edge_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/table/hittest-tablecell-with-borders-right-edge_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/table/large-shrink-wrapped-width_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/table/margins-perpendicular-containing-block_t01: RuntimeError # Please triage this failure
@@ -8777,8 +8833,9 @@
 LayoutTests/fast/text/find-russian_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/text/find-soft-hyphen_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/text/find-spaces_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/text/font-ligatures-linebreak-word_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/text/font-ligatures-linebreak_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/text/font-ligature-letter-spacing_t01: Pass, RuntimeError # Please triage this failure
+LayoutTests/fast/text/font-ligatures-linebreak-word_t01: Pass, RuntimeError # Please triage this failure
+LayoutTests/fast/text/font-ligatures-linebreak_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/text/international/cjk-segmentation_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/text/international/iso-8859-8_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/text/international/listbox-width-rtl_t01: RuntimeError # Please triage this failure
@@ -8907,12 +8964,11 @@
 LibTest/async/Stream/Stream.periodic_A01_t01: Pass, RuntimeError # Please triage this failure
 LibTest/async/Timer/Timer.periodic_A01_t01: Pass, RuntimeError # Please triage this failure
 LibTest/async/Timer/Timer_A01_t01: Pass, RuntimeError # Please triage this failure
-LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterEscape_A06_t02: RuntimeError # Please triage this failure
-LibTest/core/RegExp/Pattern_semantics/firstMatch_DecimalEscape_A01_t02: RuntimeError # Please triage this failure
-LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t01: RuntimeError # Please triage this failure
-LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t05: RuntimeError # Please triage this failure
-LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t06: RuntimeError # Please triage this failure
+LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t01: RuntimeError # Issue 22200
+LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t05: RuntimeError # Issue 22200
+LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t06: RuntimeError # Issue 22200
 LibTest/core/Runes/takeWhile_A01_t01: Skip # Times out. Please triage this failure
+LibTest/core/String/split_A01_t02: Skip # Times out. Please triage this failure
 LibTest/core/String/toLowerCase_A01_t02: Skip # Times out. Please triage this failure
 LibTest/core/double/operator_remainder_A02_t01: Skip # Times out. Please triage this failure
 LibTest/core/double/roundToDouble_A01_t01: RuntimeError # Please triage this failure
@@ -8940,6 +8996,7 @@
 LibTest/html/Element/Element.tag_A01_t01: RuntimeError # Please triage this failure
 LibTest/html/Element/addEventListener_A01_t04: Pass, RuntimeError # Please triage this failure
 LibTest/html/Element/attributeChanged_A01_t01: RuntimeError # Please triage this failure
+LibTest/html/Element/blurEvent_A01_t01: Pass, RuntimeError # Please triage this failure
 LibTest/html/Element/blur_A01_t01: Skip # Times out. Please triage this failure
 LibTest/html/Element/borderEdge_A01_t01: RuntimeError # Please triage this failure
 LibTest/html/Element/contentEdge_A01_t01: RuntimeError # Please triage this failure
@@ -8949,6 +9006,7 @@
 LibTest/html/Element/focusEvent_A01_t01: Pass, RuntimeError # Please triage this failure
 LibTest/html/Element/getAttributeNS_A01_t01: RuntimeError # Please triage this failure
 LibTest/html/Element/getAttributeNS_A02_t01: RuntimeError # Please triage this failure
+LibTest/html/Element/getAttribute_A01_t01: Skip # Times out. Please triage this failure
 LibTest/html/Element/getNamespacedAttributes_A01_t01: RuntimeError # Please triage this failure
 LibTest/html/Element/isTagSupported_A01_t01: RuntimeError # Please triage this failure
 LibTest/html/Element/isTagSupported_A01_t02: RuntimeError # Please triage this failure
@@ -8996,6 +9054,7 @@
 LibTest/html/IFrameElement/createFragment_A01_t02: RuntimeError # Please triage this failure
 LibTest/html/IFrameElement/createFragment_A01_t03: RuntimeError # Please triage this failure
 LibTest/html/IFrameElement/createShadowRoot_A01_t01: RuntimeError # Please triage this failure
+LibTest/html/IFrameElement/focus_A01_t01: Pass, RuntimeError # Please triage this failure
 LibTest/html/IFrameElement/getNamespacedAttributes_A01_t01: RuntimeError # Please triage this failure
 LibTest/html/IFrameElement/innerHtml_A01_t01: RuntimeError # Please triage this failure
 LibTest/html/IFrameElement/leftView_A01_t01: RuntimeError # Please triage this failure
@@ -9050,9 +9109,13 @@
 LibTest/typed_data/ByteData/offsetInBytes_A01_t01: RuntimeError # Please triage this failure
 LibTest/typed_data/Float32List/removeWhere_A01_t01: Skip # Times out. Please triage this failure
 LibTest/typed_data/Float32x4List/Float32x4List.view_A06_t01: RuntimeError # Please triage this failure
+LibTest/typed_data/Int32List/lastWhere_A01_t01: Skip # Times out. Please triage this failure
 LibTest/typed_data/Int32x4/operator_OR_A01_t01: RuntimeError # Please triage this failure
 LibTest/typed_data/Int64List/join_A01_t02: Skip # Times out. Please triage this failure
 LibTest/typed_data/Int8List/addAll_A01_t01: Skip # Times out. Please triage this failure
+LibTest/typed_data/Uint64List/any_A01_t01: Skip # Times out. Please triage this failure
+LibTest/typed_data/Uint64List/runtimeType_A01_t01: Skip # Times out. Please triage this failure
+LibTest/typed_data/Uint8ClampedList/skipWhile_A04_t01: Skip # Times out. Please triage this failure
 WebPlatformTest/DOMEvents/approved/ProcessingInstruction.DOMCharacterDataModified_t01: Skip # Times out. Please triage this failure
 WebPlatformTest/DOMEvents/approved/addEventListener.optional.useCapture_t01: RuntimeError # Please triage this failure
 WebPlatformTest/Utils/test/asyncTestFail_t01: RuntimeError # Please triage this failure
@@ -9149,8 +9212,8 @@
 WebPlatformTest/html-templates/template-element/template-as-a-descendant_t01: RuntimeError # Please triage this failure
 WebPlatformTest/html-templates/template-element/template-content-node-document_t01: RuntimeError # Please triage this failure
 WebPlatformTest/html-templates/template-element/template-content_t01: RuntimeError # Please triage this failure
-WebPlatformTest/html/browsers/browsing-the-web/read-media/pageload-image_t01: RuntimeError # Please triage this failure
-WebPlatformTest/html/browsers/browsing-the-web/read-media/pageload-video_t01: RuntimeError # Please triage this failure
+WebPlatformTest/html/browsers/browsing-the-web/read-media/pageload-image_t01: Skip # Times out. Please triage this failure
+WebPlatformTest/html/browsers/browsing-the-web/read-media/pageload-video_t01: Skip # Times out. Please triage this failure
 WebPlatformTest/html/browsers/browsing-the-web/read-text/load-text-plain_t01: RuntimeError # Please triage this failure
 WebPlatformTest/html/dom/documents/dom-tree-accessors/Document.getElementsByClassName-null_t01: RuntimeError # Please triage this failure
 WebPlatformTest/html/dom/documents/dom-tree-accessors/document.body-getter_t01: RuntimeError # Please triage this failure
@@ -9160,6 +9223,7 @@
 WebPlatformTest/html/dom/documents/dom-tree-accessors/document.title_t05: RuntimeError # Please triage this failure
 WebPlatformTest/html/dom/documents/dom-tree-accessors/document.title_t07: RuntimeError # Please triage this failure
 WebPlatformTest/html/dom/documents/dom-tree-accessors/nameditem_t02: RuntimeError # Please triage this failure
+WebPlatformTest/html/dom/documents/dom-tree-accessors/nameditem_t03: Skip # Times out. Please triage this failure
 WebPlatformTest/html/dom/elements/global-attributes/dataset-delete_t01: RuntimeError # Please triage this failure
 WebPlatformTest/html/dom/elements/global-attributes/dataset-get_t01: RuntimeError # Please triage this failure
 WebPlatformTest/html/dom/elements/global-attributes/dataset-set_t01: RuntimeError # Please triage this failure
@@ -9344,8 +9408,8 @@
 WebPlatformTest/webstorage/event_local_key_t01: RuntimeError # Please triage this failure
 WebPlatformTest/webstorage/event_local_newvalue_t01: RuntimeError # Please triage this failure
 WebPlatformTest/webstorage/event_local_oldvalue_t01: RuntimeError # Please triage this failure
-WebPlatformTest/webstorage/event_local_storagearea_t01: RuntimeError # Please triage this failure
-WebPlatformTest/webstorage/event_local_storageeventinit_t01: RuntimeError # Please triage this failure
+WebPlatformTest/webstorage/event_local_storagearea_t01: Pass, RuntimeError # Please triage this failure
+WebPlatformTest/webstorage/event_local_storageeventinit_t01: Pass, RuntimeError # Please triage this failure
 WebPlatformTest/webstorage/event_local_url_t01: RuntimeError # Please triage this failure
 WebPlatformTest/webstorage/event_session_key_t01: RuntimeError # Please triage this failure
 WebPlatformTest/webstorage/event_session_newvalue_t01: RuntimeError # Please triage this failure
diff --git a/tests/co19/co19-dartium.status b/tests/co19/co19-dartium.status
index 80dd6e8..b254d09 100644
--- a/tests/co19/co19-dartium.status
+++ b/tests/co19/co19-dartium.status
@@ -53,6 +53,8 @@
 LayoutTests/fast/forms/form-submission-create-crash_t01.dart: Skip # Test reloads itself. Issue 18558.
 LayoutTests/fast/forms/formmethod-attribute-button-html_t01: Skip # Test reloads itself. Issue 18558.
 LayoutTests/fast/forms/formmethod-attribute-input-2_t01: Skip # Test reloads itself. Issue 18558.
+LayoutTests/fast/forms/missing-action_t01: Skip # Test reloads itself. Issue 18558.
+LayoutTests/fast/forms/submit-form-with-dirname-attribute_t01: Skip # Test reloads itself. Issue 18558.
 LayoutTests/fast/forms/submit-form-with-dirname-attribute-with-ancestor-dir-attribute_t01: Skip # Test reloads itself. Issue 18558.
 LayoutTests/fast/forms/submit-form-with-dirname-attribute-with-nonhtml-ancestor_t01: Skip # Test reloads itself. Issue 18558.
 LayoutTests/fast/forms/submit-nil-value-field-assert_t01: Skip # Test reloads itself. Issue 18558.
@@ -543,11 +545,9 @@
 WebPlatformTest/html/semantics/forms/the-input-element/datetime_t02: RuntimeError # co19-roll r761: Please triage this failure.
 WebPlatformTest/html/semantics/forms/the-input-element/email_t01: RuntimeError # co19-roll r761: Please triage this failure.
 WebPlatformTest/html/semantics/forms/the-input-element/email_t02: RuntimeError # co19-roll r761: Please triage this failure.
-WebPlatformTest/html/semantics/forms/the-input-element/hidden_t01: RuntimeError # co19-roll r761: Please triage this failure.
 WebPlatformTest/html/semantics/forms/the-input-element/input-textselection_t01: RuntimeError # co19-roll r761: Please triage this failure.
 WebPlatformTest/html/semantics/forms/the-input-element/month_t01: RuntimeError # co19-roll r761: Please triage this failure.
 WebPlatformTest/html/semantics/forms/the-input-element/range_t01: RuntimeError # co19-roll r761: Please triage this failure.
-WebPlatformTest/html/semantics/forms/the-input-element/text_t01: RuntimeError # co19-roll r761: Please triage this failure.
 WebPlatformTest/html/semantics/forms/the-input-element/time_t01: RuntimeError # co19-roll r761: Please triage this failure.
 WebPlatformTest/html/semantics/forms/the-input-element/time_t02: RuntimeError # co19-roll r761: Please triage this failure.
 WebPlatformTest/html/semantics/forms/the-input-element/type-change-state_t01: RuntimeError # co19-roll r761: Please triage this failure.
@@ -580,7 +580,7 @@
 WebPlatformTest/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol/t03: RuntimeError # co19-roll r761: Please triage this failure.
 WebPlatformTest/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol/t05: RuntimeError # co19-roll r761: Please triage this failure.
 WebPlatformTest/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol/t06: RuntimeError # co19-roll r761: Please triage this failure.
-WebPlatformTest/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol_t00: RuntimeError # co19-roll r761: Please triage this failure.
+WebPlatformTest/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol/t04: RuntimeError # co19-roll r761: Please triage this failure.
 WebPlatformTest/webstorage/event_constructor_t01: RuntimeError # co19-roll r761: Please triage this failure.
 WebPlatformTest/webstorage/event_constructor_t02: RuntimeError # co19-roll r761: Please triage this failure.
 WebPlatformTest/webstorage/event_local_key_t01: RuntimeError # co19-roll r761: Please triage this failure.
@@ -594,6 +594,7 @@
 LayoutTests/fast/css/font-face-multiple-ranges-for-unicode-range_t01: Pass, RuntimeError # co19-roll r786: Please triage this failure.
 LayoutTests/fast/css-generated-content/malformed-url_t01: RuntimeError # co19-roll r786: Please triage this failure.
 LayoutTests/fast/css-generated-content/pseudo-animation_t01: Pass, RuntimeError # co19-roll r786: Please triage this failure.
+LayoutTests/fast/css-generated-content/pseudo-animation-before-onload_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/css-generated-content/pseudo-element-events_t01: Skip # Timeout. co19-roll r786: Please triage this failure.
 LayoutTests/fast/css-generated-content/pseudo-transition-event_t01: Skip # Timeout. co19-roll r786: Please triage this failure.
 LayoutTests/fast/css-generated-content/pseudo-transition_t01: RuntimeError # co19-roll r786: Please triage this failure.
@@ -818,7 +819,6 @@
 LayoutTests/fast/forms/formmethod-attribute-input-html_t01: Pass, RuntimeError # co19-roll r801: Please triage this failure.
 LayoutTests/fast/forms/input-appearance-elementFromPoint_t01: RuntimeError # co19-roll r801: Please triage this failure.
 LayoutTests/fast/forms/input-hit-test-border_t01: Pass, RuntimeError # co19-roll r801: Please triage this failure.
-LayoutTests/fast/forms/input-stepup-stepdown_t01: RuntimeError # co19-roll r801: Please triage this failure.
 LayoutTests/fast/forms/input-width-height-attributes-without-renderer-loaded-image_t01: RuntimeError # co19-roll r801: Please triage this failure.
 LayoutTests/fast/forms/listbox-select-all_t01: Pass, RuntimeError # co19-roll r801: Please triage this failure.
 LayoutTests/fast/forms/listbox-selection-2_t01: RuntimeError # co19-roll r801: Please triage this failure.
@@ -916,6 +916,9 @@
 LayoutTests/fast/shapes/shape-outside-floats/shape-outside-rounded-boxes_t01: RuntimeError # co19-roll r801: Please triage this failure.
 LayoutTests/fast/shapes/shape-outside-floats/shape-outside-rounded-boxes_t02: RuntimeError # co19-roll r801: Please triage this failure.
 LayoutTests/fast/table/nested-tables-with-div-offset_t01: Pass, RuntimeError # co19-roll r801: Please triage this failure.
+LayoutTests/fast/dom/getElementsByClassName/011_t01: RuntimeError # Chrome 39 roll. Please triage this failure
+LayoutTests/fast/forms/setrangetext_t01: RuntimeError # Chrome 39 roll. Please triage this failure
+
 
 [ $compiler == none && ($runtime == dartium || $runtime == ContentShellOnAndroid ) && $checked ]
 LayoutTests/fast/html/article-element_t01: RuntimeError # co19-roll r706.  Please triage this failure.
@@ -1020,6 +1023,12 @@
 LayoutTests/fast/canvas/canvas-scale-drawImage-shadow_t01: RuntimeError, Pass # co19-roll r761: Please triage this failure.
 LayoutTests/fast/canvas/canvas-scale-fillPath-shadow_t01: RuntimeError, Pass # co19-roll r761: Please triage this failure.
 LayoutTests/fast/canvas/canvas-scale-fillRect-shadow_t01: Skip # Times out. co19-roll r761: Please triage this failure.
+LayoutTests/fast/canvas/canvas-scale-shadowBlur_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/canvas-scale-strokePath-shadow_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/canvas-strokePath-alpha-shadow_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/canvas-strokePath-gradient-shadow_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/canvas-strokeRect-alpha-shadow_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/canvas-strokeRect-gradient-shadow_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/canvas-transforms-fillRect-shadow_t01: RuntimeError, Pass # co19-roll r761: Please triage this failure.
 LayoutTests/fast/canvas/webgl/canvas-test_t01: RuntimeError, Pass # co19-roll r761: Please triage this failure.
 LayoutTests/fast/canvas/webgl/webgl-large-texture_t01: Skip # Times out flakily. co19-roll r761: Please triage this failure.
diff --git a/tests/co19/co19-runtime.status b/tests/co19/co19-runtime.status
index 93dd7e4..54503e7 100644
--- a/tests/co19/co19-runtime.status
+++ b/tests/co19/co19-runtime.status
@@ -5,13 +5,10 @@
 
 [ $compiler == none && ($runtime == vm || $runtime == dartium || $runtime == ContentShellOnAndroid) ]
 
-LibTest/core/RegExp/Pattern_semantics/firstMatch_DecimalEscape_A01_t02: Fail # Issue 12508
-LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t01: Fail # Issue 12508
-LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterEscape_A06_t02: Fail # Issue 12508
-LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t05: Fail # Issue 12508
-LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t06: Fail # Issue 12508
+LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t01: Fail # Issue 22200
+LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t05: Fail # Issue 22200
+LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t06: Fail # Issue 22200
 
-LibTest/core/RegExp/firstMatch_A01_t01: Fail # Issue 12508
 LibTest/core/int/toRadixString_A01_t01: Fail # co19 issue 492
 
 Language/03_Overview/1_Scoping_A02_t28: RuntimeError # Issue 21163
diff --git a/tests/compiler/dart2js/analyze_unused_dart2js_test.dart b/tests/compiler/dart2js/analyze_unused_dart2js_test.dart
index 47ae729..570b528 100644
--- a/tests/compiler/dart2js/analyze_unused_dart2js_test.dart
+++ b/tests/compiler/dart2js/analyze_unused_dart2js_test.dart
@@ -17,10 +17,6 @@
   // Helper methods for debugging should never be called from production code:
   "lib/src/helpers/": const [" is never "],
 
-  // Hack to give try private access:
-  "lib/src/js_emitter/program_builder.dart": const [
-      "The method 'buildClassWithFieldsForTry' is never called"],
-
   // Node.asLiteralBool is never used.
   "lib/src/tree/nodes.dart": const [
       "The method 'asLiteralBool' is never called"],
diff --git a/tests/compiler/dart2js/async_await_syntax_test.dart b/tests/compiler/dart2js/async_await_syntax_test.dart
index e42bda0..8e0e651 100644
--- a/tests/compiler/dart2js/async_await_syntax_test.dart
+++ b/tests/compiler/dart2js/async_await_syntax_test.dart
@@ -8,7 +8,7 @@
 import 'frontend_checker.dart';

 

 const List<String> TESTS = const <String>[

-  'compiler/dart2js/async_await_syntax.dart',

+  'language/async_await_syntax_test.dart',

 ];

 

 void main(List<String> arguments) {

diff --git a/tests/compiler/dart2js/backend_dart/opt_constprop_test.dart b/tests/compiler/dart2js/backend_dart/opt_constprop_test.dart
index 4c8127c..b072aeb 100644
--- a/tests/compiler/dart2js/backend_dart/opt_constprop_test.dart
+++ b/tests/compiler/dart2js/backend_dart/opt_constprop_test.dart
@@ -28,7 +28,7 @@
 //  }
 
 String CP1_IN = """
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetPrim (v0 (Constant (Int 1)))
     (LetPrim (v1 (Constant (Int 1)))
       (LetCont
@@ -44,7 +44,7 @@
         (InvokeMethod v0 == (v1) k0)))))
 """;
 String CP1_OUT = """
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetPrim (v0 (Constant (Int 1)))
     (LetPrim (v1 (Constant (Int 1)))
       (LetCont
@@ -77,7 +77,7 @@
 //  }
 
 String CP2_IN = """
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetPrim (v0 (Constant (Int 1)))
     (LetCont
         ((rec k0 ()
@@ -141,7 +141,7 @@
       (InvokeContinuation k0 ()))))
 """;
 String CP2_OUT = """
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetPrim (v0 (Constant (Int 1)))
     (LetCont
         ((rec k0 ()
@@ -218,7 +218,7 @@
 //  }
 
 String CP3_IN = """
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetPrim (v0 (Constant (Int 1)))
     (LetCont
         ((k0 (v1)
@@ -240,7 +240,7 @@
 // Addition.
 
 String CP4_IN = """
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetPrim (v0 (Constant (Int 1)))
     (LetPrim (v1 (Constant (Int 2)))
       (LetCont
@@ -249,7 +249,7 @@
         (InvokeMethod v0 + (v1) k0)))))
 """;
 String CP4_OUT = """
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetPrim (v0 (Constant (Int 1)))
     (LetPrim (v1 (Constant (Int 2)))
       (LetCont
@@ -262,7 +262,7 @@
 // Array access operator (no optimization).
 
 String CP5_IN = """
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetPrim (v0 (Constant (Int 1)))
     (LetPrim (v1 (Constant (Int 2)))
       (LetCont
@@ -275,7 +275,7 @@
 // Division by 0.
 
 String CP6_IN = """
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetPrim (v0 (Constant (Int 1)))
     (LetPrim (v1 (Constant (Int 0)))
       (LetCont
@@ -284,7 +284,7 @@
         (InvokeMethod v0 / (v1) k0)))))
 """;
 String CP6_OUT = """
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetPrim (v0 (Constant (Int 1)))
     (LetPrim (v1 (Constant (Int 0)))
       (LetCont
@@ -297,7 +297,7 @@
 // Concatenate strings.
 
 String CP7_IN = """
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetPrim (v0 (Constant (String "b")))
     (LetPrim (v1 (Constant (String "d")))
       (LetPrim (v2 (Constant (String "a")))
@@ -312,7 +312,7 @@
               (ConcatenateStrings (v2 v0 v3 v1 v4) k0))))))))
 """;
 String CP7_OUT = """
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetPrim (v0 (Constant (String "b")))
     (LetPrim (v1 (Constant (String "d")))
       (LetPrim (v2 (Constant (String "a")))
@@ -334,7 +334,7 @@
 // Simple branch removal.
 
 String CP8_IN = """
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetPrim (v0 (Constant (Int 1)))
     (LetPrim (v1 (Constant (Int 1)))
       (LetCont
@@ -349,7 +349,7 @@
         (InvokeMethod v0 == (v1) k0)))))
 """;
 String CP8_OUT = """
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetPrim (v0 (Constant (Int 1)))
     (LetPrim (v1 (Constant (Int 1)))
       (LetCont
@@ -368,7 +368,7 @@
 // While loop.
 
 String CP9_IN = """
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetPrim (v0 (Constant (Int 1)))
     (LetCont
         ((rec k0 (v1)
@@ -406,7 +406,7 @@
       (InvokeContinuation k0 (v0)))))
 """;
 String CP9_OUT = """
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetPrim (v0 (Constant (Int 1)))
     (LetCont
         ((rec k0 (v1)
@@ -453,7 +453,7 @@
 //  }
 
 String CP10_IN = """
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetPrim (v0 (Constant (Int 0)))
     (LetCont
         ((rec k0 (v1)
diff --git a/tests/compiler/dart2js/backend_dart/opt_redundant_phi_test.dart b/tests/compiler/dart2js/backend_dart/opt_redundant_phi_test.dart
index deadd77..3007f31 100644
--- a/tests/compiler/dart2js/backend_dart/opt_redundant_phi_test.dart
+++ b/tests/compiler/dart2js/backend_dart/opt_redundant_phi_test.dart
@@ -19,7 +19,7 @@
 // }
 
 String READ_IN_LOOP_IN = """
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetPrim (v0 (Constant (Int 42)))
     (LetPrim (v1 (Constant (Int 0)))
       (LetCont
@@ -49,7 +49,7 @@
 """;
 
 String READ_IN_LOOP_OUT = """
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetPrim (v0 (Constant (Int 42)))
     (LetPrim (v1 (Constant (Int 0)))
       (LetCont
@@ -94,7 +94,7 @@
 // are removed from k5, and only then can k0 be optimized as well.
 
 const String INNER_LOOP_IN = """
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetPrim (v0 (Constant (Int 42)))
     (LetPrim (v1 (Constant (Int 0)))
       (LetCont
@@ -147,7 +147,7 @@
 """;
 
 const String INNER_LOOP_OUT = """
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetPrim (v0 (Constant (Int 42)))
     (LetPrim (v1 (Constant (Int 0)))
       (LetCont
@@ -210,7 +210,7 @@
 // }
 
 String BASIC_LOOP_IN = """
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetPrim (v0 (Constant (Int 0)))
     (LetCont
        ((rec k0 (v1)
@@ -245,7 +245,7 @@
 // IR written by hand since this case is currently not being generated.
 
 String SCOPING_IN = """
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetCont
       ((k0 (v1)
          (InvokeStatic print (v1) return)))
@@ -255,7 +255,7 @@
 """;
 
 String SCOPING_OUT = """
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetPrim (v0 (Constant (Int 0)))
     (LetCont
         ((k0 ()
@@ -268,7 +268,7 @@
 // IR written by hand.
 
 String NEVER_INVOKED_IN = """
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetPrim (v0 (Constant (Int 0)))
     (LetCont
         ((k0 (v1)
diff --git a/tests/compiler/dart2js/backend_dart/opt_shrinking_test.dart b/tests/compiler/dart2js/backend_dart/opt_shrinking_test.dart
index a0c4751..fca6d1e 100644
--- a/tests/compiler/dart2js/backend_dart/opt_shrinking_test.dart
+++ b/tests/compiler/dart2js/backend_dart/opt_shrinking_test.dart
@@ -20,13 +20,13 @@
 //  }
 
 String DEAD_VAL_IN = """
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetPrim (v0 (Constant (Int 42)))
     (LetPrim (v1 (Constant (Int 0)))
       (InvokeContinuation return (v1)))))
 """;
 String DEAD_VAL_OUT = """
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetPrim (v0 (Constant (Int 0)))
     (InvokeContinuation return (v0))))
 """;
@@ -41,7 +41,7 @@
 //  }
 
 String ITERATIVE_DEAD_VAL1_IN = """
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetPrim (v0 (Constant (Int 42)))
     (LetPrim (v1 (Constant (Int 1)))
       (LetCont ((k0 (v2)
@@ -54,17 +54,17 @@
 // Iterative dead-val. IR written by hand.
 
 String ITERATIVE_DEAD_VAL2_IN = """
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetPrim (v0 (Constant (Int 42)))
     (LetPrim (v1
         (CreateFunction
-          (FunctionDefinition f (i) return ()
+          (FunctionDefinition f (i) return
             (InvokeContinuation return (v0)))))
       (LetPrim (v2 (Constant (Int 0)))
         (InvokeContinuation return (v2))))))
 """;
 String ITERATIVE_DEAD_VAL2_OUT = """
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetPrim (v0 (Constant (Int 0)))
     (InvokeContinuation return (v0))))
 """;
@@ -73,7 +73,7 @@
 // IR written by hand.
 
 String DEAD_CONT_IN = """
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetPrim (v4 (Constant (Int 0)))
     (LetCont ((k0 (v0)
                 (InvokeConstructor List () return)))
@@ -85,7 +85,7 @@
         (InvokeStatic print (v4) k1)))))
 """;
 String DEAD_CONT_OUT = """
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetPrim (v0 (Constant (Int 0)))
     (LetCont ((k0 (v1)
                 (LetCont ((k1 (v2)
@@ -98,7 +98,7 @@
 // Iterative dead-cont. IR written by hand.
 
 String ITERATIVE_DEAD_CONT_IN = """
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetPrim (v4 (Constant (Int 0)))
     (LetCont ((k0 (v0)
                 (InvokeConstructor List () return)))
@@ -112,7 +112,7 @@
           (InvokeStatic print (v4) k1))))))
 """;
 String ITERATIVE_DEAD_CONT_OUT = """
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetPrim (v0 (Constant (Int 0)))
     (LetCont ((k0 (v1)
                 (LetCont ((k1 (v2)
@@ -126,7 +126,7 @@
 // IR written by hand.
 
 String BETA_CONT_LIN_IN = """
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetCont ((k0 (v0)
               (LetCont ((k1 (v1)
                           (LetCont ((k2 (v2)
@@ -138,7 +138,7 @@
       (InvokeContinuation k0 (v4)))))
 """;
 String BETA_CONT_LIN_OUT = """
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetPrim (v0 (Constant (Int 0)))
     (LetCont ((k0 (v1)
                 (LetCont ((k1 (v2)
@@ -151,7 +151,7 @@
 // Beta-cont-lin with recursive continuation. IR written by hand.
 
 String RECURSIVE_BETA_CONT_LIN_IN = """
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetCont ((rec k0 (v0)
               (InvokeContinuation rec k0 (v0))))
     (LetPrim (v1 (Constant (Int 0)))
@@ -162,7 +162,7 @@
 // Beta-cont-lin used inside body. IR written by hand.
 
 String USED_BETA_CONT_LIN_IN = """
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetPrim (v0 (Constant (Int 0)))
     (LetCont ((k0 (v1)
                 (LetCont ((k1 (v2)
@@ -173,12 +173,12 @@
                   (InvokeStatic print (v1) k1))))
       (LetPrim (v5
                  (CreateFunction
-                   (FunctionDefinition f () return ()
+                   (FunctionDefinition f () return
                      (InvokeContinuation return (v1)))))
         (InvokeContinuation k0 (v0))))))
 """;
 String USED_BETA_CONT_LIN_OUT = """
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetPrim (v0 (Constant (Int 0)))
     (LetCont ((k0 (v1)
                 (LetCont ((k1 (v2)
@@ -199,7 +199,7 @@
 // TODO(kmillikin): To test continuation eta reduction, use eta redexes that are
 // not overlapping beta redexes.
 String ETA_CONT_IN = """
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetPrim (v0 (Constant (Int 0)))
     (LetCont ((rec k0 (v1)
                 (InvokeContinuation return (v0))))
@@ -207,12 +207,12 @@
                   (InvokeContinuation k0 (v2))))
         (LetPrim (v3
                    (CreateFunction
-                     (FunctionDefinition f () return ()
+                     (FunctionDefinition f () return
                        (InvokeContinuation k0 (v0)))))
           (InvokeContinuation k1 (v0)))))))
 """;
 String ETA_CONT_OUT = """
-(FunctionDefinition main () return ()
+(FunctionDefinition main () return
   (LetPrim (v0 (Constant (Int 0)))
     (InvokeContinuation return (v0))))
 """;
@@ -223,7 +223,7 @@
 
 // Parameter v1 is unused in k0.
 String DEAD_PARAMETER_IN = """
-(FunctionDefinition main (x) return ()
+(FunctionDefinition main (x) return
   (LetCont ((k0 (v0 v1 v2)
               (InvokeStatic foo (v0 v2) return)))
     (LetCont ((k1 ()
@@ -239,7 +239,7 @@
       (Branch (IsTrue x) k1 k2))))
 """;
 String DEAD_PARAMETER_OUT = """
-(FunctionDefinition main (x) return ()
+(FunctionDefinition main (x) return
   (LetCont ((k0 (v0 v1)
               (InvokeStatic foo (v0 v1) return)))
     (LetCont ((k1 ()
@@ -257,7 +257,7 @@
 // Dead parameter reductions can create an eta-cont redex by removing unused
 // continuation parameters and thus creating the eta redex.
 String CREATE_ETA_CONT_IN = """
-(FunctionDefinition main (x) return ()
+(FunctionDefinition main (x) return
   (LetCont ((rec loop (v0)
               (InvokeContinuation rec loop (v0))))
     (LetCont ((created (v1 v2 v3)
@@ -275,7 +275,7 @@
         (Branch (IsTrue x) then else)))))
 """;
 String CREATE_ETA_CONT_OUT = """
-(FunctionDefinition main (x) return ()
+(FunctionDefinition main (x) return
   (LetCont ((rec k0 (v0)
               (InvokeContinuation rec k0 (v0))))
     (LetCont ((k1 ()
diff --git a/tests/compiler/dart2js/backend_dart/sexpr2_test.dart b/tests/compiler/dart2js/backend_dart/sexpr2_test.dart
index 774f142..eef2d35 100644
--- a/tests/compiler/dart2js/backend_dart/sexpr2_test.dart
+++ b/tests/compiler/dart2js/backend_dart/sexpr2_test.dart
@@ -18,22 +18,33 @@
 main() {

   performTests(TEST_DATA, asyncTester, (TestSpec result) {

     return compilerFor(result.input).then((Compiler compiler) {

-      void checkOutput(Element element, String expectedOutput) {

+      void checkOutput(String elementName,

+                       Element element,

+                       String expectedOutput) {

         expectedOutput = expectedOutput.trim();

         String output = compiler.irBuilder.getIr(element)

             .accept(new SExpressionStringifier()).trim();

         Expect.equals(expectedOutput, output,

-            '\nInput:\n${result.input}\n'

-            'Expected:\n$expectedOutput\n'

-            'Actual:\n$output\n');

+            "\nInput:\n${result.input}\n"

+            "Expected for '$elementName':\n$expectedOutput\n"

+            "Actual for '$elementName':\n$output\n");

       }

 

       if (result.output is String) {

-        checkOutput(compiler.mainFunction, result.output);

+        checkOutput('main', compiler.mainFunction, result.output);

       } else {

         assert(result.output is Map<String, String>);

         result.output.forEach((String elementName, String output) {

-          checkOutput(compiler.mainApp.localLookup(elementName), output);

+          Element element;

+          if (elementName.contains('.')) {

+            ClassElement cls = compiler.mainApp.localLookup(

+                elementName.substring(0, elementName.indexOf('.')));

+            element = cls.localLookup(

+                elementName.substring(elementName.indexOf('.') + 1));

+          } else {

+            element = compiler.mainApp.localLookup(elementName);

+          }

+          checkOutput(elementName, element, output);

         });

       }

     });

diff --git a/tests/compiler/dart2js/backend_dart/sexpr_test.dart b/tests/compiler/dart2js/backend_dart/sexpr_test.dart
index 4ab2235..f1a9351 100644
--- a/tests/compiler/dart2js/backend_dart/sexpr_test.dart
+++ b/tests/compiler/dart2js/backend_dart/sexpr_test.dart
@@ -149,13 +149,13 @@
           , "InvokeMethodDirectly"
           , "LetCont"
           , "LetPrim"
-          , "SetClosureVariable"
+          , "SetMutableVariable"
           , "TypeOperator"
 
           // Primitives
           , "Constant"
           , "CreateFunction"
-          , "GetClosureVariable"
+          , "GetMutableVariable"
           , "LiteralList"
           , "LiteralMap"
           // Parameters are encoded by name only and hence are not in this list.
diff --git a/tests/compiler/dart2js/backend_dart/sexpr_unstringifier.dart b/tests/compiler/dart2js/backend_dart/sexpr_unstringifier.dart
index 7e52585..1f2f263 100644
--- a/tests/compiler/dart2js/backend_dart/sexpr_unstringifier.dart
+++ b/tests/compiler/dart2js/backend_dart/sexpr_unstringifier.dart
@@ -124,13 +124,14 @@
   static const String INVOKE_METHOD = "InvokeMethod";
   static const String LET_PRIM = "LetPrim";
   static const String LET_CONT = "LetCont";
-  static const String SET_CLOSURE_VARIABLE = "SetClosureVariable";
+  static const String LET_MUTABLE = "LetMutable";
+  static const String SET_MUTABLE_VARIABLE = "SetMutableVariable";
   static const String TYPE_OPERATOR = "TypeOperator";
 
   // Primitives
   static const String CONSTANT = "Constant";
   static const String CREATE_FUNCTION = "CreateFunction";
-  static const String GET_CLOSURE_VARIABLE = "GetClosureVariable";
+  static const String GET_MUTABLE_VARIABLE = "GetMutableVariable";
   static const String LITERAL_LIST = "LiteralList";
   static const String LITERAL_MAP = "LiteralMap";
   static const String REIFY_TYPE_VAR = "ReifyTypeVar";
@@ -230,8 +231,10 @@
         return parseLetPrim();
       case LET_CONT:
         return parseLetCont();
-      case SET_CLOSURE_VARIABLE:
-        return parseSetClosureVariable();
+      case LET_MUTABLE:
+        return parseLetMutable();
+      case SET_MUTABLE_VARIABLE:
+        return parseSetMutableVariable();
       case TYPE_OPERATOR:
         return parseTypeOperator();
       default:
@@ -254,7 +257,7 @@
     return prims;
   }
 
-  /// (FunctionDefinition name (args cont) body)
+  /// (FunctionDefinition name (parameters) continuation body)
   FunctionDefinition parseFunctionDefinition() {
     tokens.consumeStart(FUNCTION_DEFINITION);
 
@@ -285,25 +288,12 @@
     Continuation cont = name2variable[contName];
     assert(cont != null);
 
-    // [closure-variables]
-    List<ClosureVariable> closureVariables = <ClosureVariable>[];
-    tokens.consumeStart();
-    while (tokens.current != ')') {
-      String varName = tokens.read();
-      ClosureVariable variable =
-          new ClosureVariable(element, new DummyElement(varName));
-      closureVariables.add(variable);
-      name2variable[varName] = variable;
-    }
-    tokens.consumeEnd();
-
     // body
     Expression body = parseExpression();
 
     tokens.consumeEnd();
     return new FunctionDefinition(element, parameters,
-        new RunnableBody(body, cont), null, null,
-        closureVariables);
+        new RunnableBody(body, cont), null, null);
   }
 
   /// (IsTrue arg)
@@ -349,7 +339,7 @@
     tokens.consumeStart(DECLARE_FUNCTION);
 
     // name =
-    ClosureVariable local = name2variable[tokens.read()];
+    MutableVariable local = addMutableVariable(tokens.read());
     tokens.read("=");
 
     // function in
@@ -390,7 +380,7 @@
     String name = tokens.read();
     bool isRecursive = name == "rec";
     if (isRecursive) name = tokens.read();
-    
+
     Continuation cont = name2variable[name];
     assert(cont != null);
 
@@ -503,18 +493,33 @@
     return new LetCont.many(continuations, body);
   }
 
-  /// (SetClosureVariable name value body)
-  SetClosureVariable parseSetClosureVariable() {
-    tokens.consumeStart(SET_CLOSURE_VARIABLE);
+  /// (LetMutable (name value) body)
+  LetMutable parseLetMutable() {
+    tokens.consumeStart(LET_MUTABLE);
 
-    ClosureVariable local = name2variable[tokens.read()];
+    tokens.consumeStart();
+    String name = tokens.read();
+    MutableVariable local = addMutableVariable(name);
+    Primitive value = name2variable[tokens.read()];
+    tokens.consumeEnd();
+
+    Expression body = parseExpression();
+    tokens.consumeEnd();
+    return new LetMutable(local, value)..plug(body);
+  }
+
+  /// (SetMutableVariable name value body)
+  SetMutableVariable parseSetMutableVariable() {
+    tokens.consumeStart(SET_MUTABLE_VARIABLE);
+
+    MutableVariable local = name2variable[tokens.read()];
     Primitive value = name2variable[tokens.read()];
     assert(value != null);
 
     Expression body = parseExpression();
 
     tokens.consumeEnd();
-    return new SetClosureVariable(local, value)
+    return new SetMutableVariable(local, value)
                   ..plug(body);
   }
 
@@ -564,8 +569,8 @@
         return parseConstant();
       case CREATE_FUNCTION:
         return parseCreateFunction();
-      case GET_CLOSURE_VARIABLE:
-        return parseGetClosureVariable();
+      case GET_MUTABLE_VARIABLE:
+        return parseGetMutableVariable();
       case LITERAL_LIST:
         return parseLiteralList();
       case LITERAL_MAP:
@@ -649,14 +654,21 @@
     return new CreateFunction(def);
   }
 
-  /// (GetClosureVariable name)
-  GetClosureVariable parseGetClosureVariable() {
-    tokens.consumeStart(GET_CLOSURE_VARIABLE);
+  MutableVariable addMutableVariable(String name) {
+    assert(!name2variable.containsKey(name));
+    MutableVariable variable =
+        new MutableVariable(new DummyElement(""), new DummyElement(name));
+    name2variable[name] = variable;
+    return variable;
+  }
 
-    ClosureVariable local = name2variable[tokens.read()];
+  /// (GetMutableVariable name)
+  GetMutableVariable parseGetMutableVariable() {
+    tokens.consumeStart(GET_MUTABLE_VARIABLE);
+    MutableVariable local = name2variable[tokens.read()];
     tokens.consumeEnd();
 
-    return new GetClosureVariable(local);
+    return new GetMutableVariable(local);
   }
 
   /// (LiteralList (values))
diff --git a/tests/compiler/dart2js/dart2js.status b/tests/compiler/dart2js/dart2js.status
index 76e1114..4e39fdf 100644
--- a/tests/compiler/dart2js/dart2js.status
+++ b/tests/compiler/dart2js/dart2js.status
@@ -2,6 +2,7 @@
 # for details. All rights reserved. Use of this source code is governed by a
 # BSD-style license that can be found in the LICENSE file.
 
+async_await_syntax_test: Fail # Issue 22260
 boolified_operator_test: Fail # Issue 8001
 
 # simple_function_subtype_test is temporarily(?) disabled due to new method for
diff --git a/tests/compiler/dart2js/deferred_emit_type_checks_test.dart b/tests/compiler/dart2js/deferred_emit_type_checks_test.dart
index f4f8295..2976f7e 100644
--- a/tests/compiler/dart2js/deferred_emit_type_checks_test.dart
+++ b/tests/compiler/dart2js/deferred_emit_type_checks_test.dart
@@ -31,10 +31,10 @@
     String mainOutput = collector.getOutput('', 'js');
     String deferredOutput =  collector.getOutput('out_1', 'part.js');
     String isPrefix = compiler.backend.namer.operatorIsPrefix;
-    Expect.isTrue(deferredOutput.contains('${isPrefix}A: true'),
-        "Deferred output doesn't contain '${isPrefix}A: true':\n"
+    Expect.isTrue(deferredOutput.contains('${isPrefix}A: 1'),
+        "Deferred output doesn't contain '${isPrefix}A: 1':\n"
         "$deferredOutput");
-    Expect.isFalse(mainOutput.contains('${isPrefix}A: true'));
+    Expect.isFalse(mainOutput.contains('${isPrefix}A: 1'));
   }));
 }
 
@@ -52,7 +52,9 @@
 """, "lib.dart": """
 class A<T> {}
 
-A<A> instance = new A<A>();
+class B<T> implements A<T> {}
+
+B<B> instance = new B<B>();
 
 bool f (Object o) {
   return o is A<A>;
diff --git a/tests/compiler/dart2js/deferred_load_graph_segmentation_test.dart b/tests/compiler/dart2js/deferred_load_graph_segmentation_test.dart
index a3ead0b..1927db0 100644
--- a/tests/compiler/dart2js/deferred_load_graph_segmentation_test.dart
+++ b/tests/compiler/dart2js/deferred_load_graph_segmentation_test.dart
@@ -76,9 +76,8 @@
     Expect.notEquals(ou_lib1, ou_lib2);
     Expect.notEquals(ou_lib4_1, ou_lib4_2);
     Expect.notEquals(ou_lib1, ou_lib4_2);
-    // InputElement is native, so it should not appear on a classList
-    Expect.isFalse(outputClassLists[outputUnitForElement(inputElement)]
-        .contains(inputElement));
+    // InputElement is native, so it should be in the mainOutputUnit.
+    Expect.equals(mainOutputUnit, outputUnitForElement(inputElement));
 
     var hunksToLoad = compiler.deferredLoadTask.hunksToLoad;
 
diff --git a/tests/compiler/dart2js/is_test_with_type_parameters_test.dart b/tests/compiler/dart2js/is_test_with_type_parameters_test.dart
new file mode 100644
index 0000000..76847d8
--- /dev/null
+++ b/tests/compiler/dart2js/is_test_with_type_parameters_test.dart
@@ -0,0 +1,44 @@
+// Copyright (c) 2015, 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";
+
+// Tests that is-tests are also available for superclasses if the class is
+// never instantiated and not explicitly tested against.
+
+class A {
+}
+
+class B extends A {
+}
+
+class C<T> implements A {
+}
+
+class D<T,L> {
+}
+
+class F {
+}
+
+class E<T,L> extends D<L,T> {
+}
+
+class G extends F {
+}
+
+main () {
+  var l = [new A(), new B(), new C<E<G, G>>()];
+  Expect.isTrue(l[0] is A);
+  Expect.isTrue(l[1] is B);
+  Expect.isTrue(l[2] is C<D<F, G>>);
+  for (int i = 0; i < l.length; i++) {
+    var e = l[i];
+    Expect.isTrue(e is A);
+    Expect.equals(e is B, i == 1);
+    Expect.isFalse(e is C<String>);
+    Expect.equals(e is C<D<F, G>>, i == 2);
+  }
+}
+
diff --git a/tests/compiler/dart2js/js_backend_cps_ir_closures_test.dart b/tests/compiler/dart2js/js_backend_cps_ir_closures_test.dart
index 068f6d2..100f26d 100644
--- a/tests/compiler/dart2js/js_backend_cps_ir_closures_test.dart
+++ b/tests/compiler/dart2js/js_backend_cps_ir_closures_test.dart
@@ -27,7 +27,7 @@
   a = new V.main_a(box_0);
   x = box_0.x_0;
   v0 = "1";
-  box_0.x_0 = J.getInterceptor(x).$add(x, v0);
+  box_0.x_0 = J.getInterceptor$ns(x).$add(x, v0);
   P.print(a.call$0());
   return null;
 }"""),
@@ -62,7 +62,7 @@
   a = new V.main_closure(box_0);
   x = box_0.x_0;
   v0 = 1;
-  box_0.x_0 = J.getInterceptor(x).$add(x, v0);
+  box_0.x_0 = J.getInterceptor$ns(x).$add(x, v0);
   P.print(a.call$0());
   return null;
 }"""),
@@ -86,7 +86,7 @@
   a = new V.main_closure(box_0);
   x = box_0.x_0;
   v0 = 1;
-  box_0.x_0 = J.getInterceptor(x).$add(x, v0);
+  box_0.x_0 = J.getInterceptor$ns(x).$add(x, v0);
   P.print(a.call$0().call$0());
   return null;
 }"""),
@@ -107,10 +107,10 @@
   i = 0;
   while (true) {
     v0 = 10;
-    if (P.identical(J.getInterceptor(i).$lt(i, v0), true)) {
+    if (P.identical(J.getInterceptor$n(i).$lt(i, v0), true)) {
       a = new V.main_closure(i);
       v1 = 1;
-      i = J.getInterceptor(i).$add(i, v1);
+      i = J.getInterceptor$ns(i).$add(i, v1);
     } else {
       P.print(a.call$0());
       return null;
diff --git a/tests/compiler/dart2js/js_backend_cps_ir_interceptors_test.dart b/tests/compiler/dart2js/js_backend_cps_ir_interceptors_test.dart
index ef56ac0..da56918 100644
--- a/tests/compiler/dart2js/js_backend_cps_ir_interceptors_test.dart
+++ b/tests/compiler/dart2js/js_backend_cps_ir_interceptors_test.dart
@@ -22,9 +22,48 @@
   var g, v0;
   g = 1;
   v0 = 3;
-  P.print(J.getInterceptor(g).$add(g, v0));
+  P.print(J.getInterceptor$ns(g).$add(g, v0));
   return null;
 }"""),
+  const TestEntry("""
+main() {
+  var l = ['hest', ['h', 'e', 's', 't']];
+  print(l.length);
+  for (int i  = 0; i < l.length; i++) {
+    var x = l[i];
+    for (int j = 0; j < x.length; j++) {
+      print(x[j]);
+    }
+  }
+}""",
+r"""
+function() {
+  var l, i, v0, x, j, v1, v2, v3;
+  l = ["hest", ["h", "e", "s", "t"]];
+  P.print(J.getInterceptor$as(l).get$length(l));
+  i = 0;
+  L0:
+    while (true) {
+      v0 = J.getInterceptor$as(l).get$length(l);
+      if (P.identical(J.getInterceptor$n(i).$lt(i, v0), true)) {
+        x = J.getInterceptor$as(l).$index(l, i);
+        j = 0;
+        while (true) {
+          v1 = J.getInterceptor$as(x).get$length(x);
+          if (P.identical(J.getInterceptor$n(j).$lt(j, v1), true)) {
+            P.print(J.getInterceptor$as(x).$index(x, j));
+            v2 = 1;
+            j = J.getInterceptor$ns(j).$add(j, v2);
+          } else {
+            v3 = 1;
+            i = J.getInterceptor$ns(i).$add(i, v3);
+            continue L0;
+          }
+        }
+      } else
+        return null;
+    }
+}"""),
 ];
 
 
diff --git a/tests/compiler/dart2js/js_backend_cps_ir_supercall_test.dart b/tests/compiler/dart2js/js_backend_cps_ir_supercall_test.dart
index 048beec..4ad6e78 100644
--- a/tests/compiler/dart2js/js_backend_cps_ir_supercall_test.dart
+++ b/tests/compiler/dart2js/js_backend_cps_ir_supercall_test.dart
@@ -26,32 +26,34 @@
 function(x) {
   var v0, v1;
   v0 = 10;
-  v1 = J.getInterceptor(x).$add(x, v0);
+  v1 = J.getInterceptor$ns(x).$add(x, v0);
   return V.Base.prototype.m$1.call(this, v1);
 }"""),
 
-const TestEntry.forMethod('function(Sub#+)', """
-class Base {
-  m(x) {
-    print(x+1000);
-  }
-  operator+(x) => m(x+10);
-}
-class Sub extends Base {
-  m(x) => super.m(x+100);
-  operator+(x) => super + (x+1);
-}
-main() {
-  new Sub() + 10000;
-}""",
-r"""
-function(x) {
-  var v0, v1, v2;
-  v0 = 1;
-  v1 = J.getInterceptor(x).$add(x, v0);
-  v2 = this;
-  return V.Base.prototype.$add.call(null, v2, v1);
-}"""),
+  // Reenable when we support compiling functions that
+  // need interceptor calling convention.
+// const TestEntry.forMethod('function(Sub#+)', """
+// class Base {
+//   m(x) {
+//     print(x+1000);
+//   }
+//   operator+(x) => m(x+10);
+// }
+// class Sub extends Base {
+//   m(x) => super.m(x+100);
+//   operator+(x) => super + (x+1);
+// }
+// main() {
+//   new Sub() + 10000;
+// }""",
+// r"""
+// function(x) {
+//   var v0, v1, v2;
+//   v0 = 1;
+//   v1 = J.getInterceptor$ns(x).$add(x, v0);
+//   v2 = this;
+//   return V.Base.prototype.$add.call(null, v2, v1);
+// }"""),
 
 const TestEntry.forMethod('function(Sub#m)', """
 class Base {
@@ -67,7 +69,7 @@
 function(x) {
   var v0;
   v0 = this.field;
-  return J.getInterceptor(x).$add(x, v0);
+  return J.getInterceptor$ns(x).$add(x, v0);
 }"""),
 
 
diff --git a/tests/compiler/dart2js/line_column_provider_test.dart b/tests/compiler/dart2js/line_column_provider_test.dart
new file mode 100644
index 0000000..c1cdded
--- /dev/null
+++ b/tests/compiler/dart2js/line_column_provider_test.dart
@@ -0,0 +1,84 @@
+// Copyright (c) 2015, 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.

+

+// Unittest for the [LineColumnCollector].

+

+import 'package:expect/expect.dart';

+import 'package:compiler/src/io/code_output.dart';

+import 'package:compiler/src/io/line_column_provider.dart';

+

+import 'output_collector.dart';

+

+test(List events, Map<int, List<int>> expectedPositions) {

+  BufferedEventSink sink = new BufferedEventSink();

+  LineColumnProvider lineColumnProvider = new LineColumnCollector();

+  CodeOutput output = new StreamCodeOutput(sink, [lineColumnProvider]);

+  for (var event in events) {

+    if (event is String) {

+      output.add(event);

+    } else if (event is CodeBuffer) {

+      output.addBuffer(event);

+    }

+  }

+  output.close();

+

+  expectedPositions.forEach((int offset, List<int> expectedPosition) {

+    if (expectedPosition == null) {

+      Expect.throws(() => lineColumnProvider.getLine(offset),

+                    (e) => true,

+                    'Expected out-of-bounds offset: $offset\n'

+                    'text:"""${sink.text}"""\n'

+                    'lineColumnProvider:$lineColumnProvider');

+    } else {

+      int line = lineColumnProvider.getLine(offset);

+      int column = lineColumnProvider.getColumn(line, offset);

+      Expect.equals(expectedPosition[0], line,

+          'Unexpected result: $offset -> $expectedPosition = [$line,$column]\n'

+          'text:"""${sink.text}"""\n'

+          'lineColumnProvider:$lineColumnProvider');

+      Expect.equals(expectedPosition[1], column,

+          'Unexpected result: $offset -> $expectedPosition = [$line,$column]\n'

+          'text:"""${sink.text}"""\n'

+          'lineColumnProvider:$lineColumnProvider');

+    }

+  });

+}

+

+main() {

+  test([""], {0: [0, 0], 1: null});

+

+  test([" "], {0: [0, 0], 1: [0, 1], 2: null});

+

+  test(["\n "], {0: [0, 0], 1: [1, 0], 2: [1, 1], 3: null});

+

+  Map positions = {0: [0, 0],

+                   1: [0, 1],

+                   2: [1, 0],

+                   3: [1, 1],

+                   4: [2, 0],

+                   5: [2, 1],

+                   6: null};

+

+  test(["a\nb\nc"], positions);

+

+  test(["a", "\nb\nc"], positions);

+

+  test(["a", "\n", "b\nc"], positions);

+

+  CodeBuffer buffer1 = new CodeBuffer();

+  buffer1.add("a\nb\nc");

+  test([buffer1], positions);

+

+  CodeBuffer buffer2 = new CodeBuffer();

+  buffer2.add("\nb\nc");

+  test(["a", buffer2], positions);

+

+  CodeBuffer buffer3 = new CodeBuffer();

+  buffer3.add("a");

+  test([buffer3, buffer2], positions);

+

+  CodeBuffer buffer4 = new CodeBuffer();

+  buffer4.addBuffer(buffer3);

+  test([buffer4, buffer2], positions);

+}

diff --git a/tests/compiler/dart2js/metadata_test.dart b/tests/compiler/dart2js/metadata_test.dart
index 9b6c42c..62e6fecb 100644
--- a/tests/compiler/dart2js/metadata_test.dart
+++ b/tests/compiler/dart2js/metadata_test.dart
@@ -154,12 +154,9 @@
 
     Uri uri = new Uri(scheme: 'source', path: 'main.dart');
 
-    Uri async = new Uri(scheme: 'dart', path: 'async');
-
     var compiler = compilerFor(source, uri)
         ..registerSource(partUri, partSource)
-        ..registerSource(libUri, libSource)
-        ..registerSource(async, 'class DeferredLibrary {}');
+        ..registerSource(libUri, libSource);
 
     asyncTest(() => compiler.runCompiler(uri).then((_) {
       compiler.enqueuer.resolution.queueIsClosed = false;
diff --git a/tests/compiler/dart2js/mock_compiler.dart b/tests/compiler/dart2js/mock_compiler.dart
index 0c6fa8e..177083d 100644
--- a/tests/compiler/dart2js/mock_compiler.dart
+++ b/tests/compiler/dart2js/mock_compiler.dart
@@ -57,6 +57,7 @@
   final int expectedErrors;
   final Map<String, SourceFile> sourceFiles;
   Node parsedTree;
+  final String testedPatchVersion;
 
   MockCompiler.internal(
       {Map<String, String> coreSource,
@@ -73,11 +74,13 @@
        // affected by inlining support.
        bool disableInlining: true,
        bool trustTypeAnnotations: false,
-       bool enableEnums: false,
+       bool enableAsyncAwait: false,
        int this.expectedWarnings,
        int this.expectedErrors,
-       api.CompilerOutputProvider outputProvider})
+       api.CompilerOutputProvider outputProvider,
+       String patchVersion})
       : sourceFiles = new Map<String, SourceFile>(),
+        testedPatchVersion = patchVersion,
         super(enableTypeAssertions: enableTypeAssertions,
               enableMinification: enableMinification,
               enableConcreteTypeInference: enableConcreteTypeInference,
@@ -89,8 +92,8 @@
               preserveComments: preserveComments,
               trustTypeAnnotations: trustTypeAnnotations,
               showPackageWarnings: true,
-              enableEnums: enableEnums,
-              outputProvider: outputProvider) {
+              outputProvider: outputProvider,
+              enableAsyncAwait: enableAsyncAwait) {
     this.disableInlining = disableInlining;
 
     deferredLoadTask = new MockDeferredLoadTask(this);
@@ -115,6 +118,10 @@
                    buildLibrarySource(DEFAULT_ASYNC_LIBRARY));
   }
 
+  String get patchVersion {
+    return testedPatchVersion != null ? testedPatchVersion : super.patchVersion;
+  }
+
   /// Initialize the mock compiler with an empty main library.
   Future<Uri> init([String mainSource = ""]) {
     Uri uri = new Uri(scheme: "mock");
@@ -267,10 +274,8 @@
   }
 
   /// Create a new [MockCompiler] and apply it asynchronously to [f].
-  static Future create(f(MockCompiler compiler),
-                       {bool enableEnums: false}) {
-    MockCompiler compiler = new MockCompiler.internal(
-        enableEnums: enableEnums);
+  static Future create(f(MockCompiler compiler)) {
+    MockCompiler compiler = new MockCompiler.internal();
     return compiler.init().then((_) => f(compiler));
   }
 }
diff --git a/tests/compiler/dart2js/mock_libraries.dart b/tests/compiler/dart2js/mock_libraries.dart
index a004239..507d123 100644
--- a/tests/compiler/dart2js/mock_libraries.dart
+++ b/tests/compiler/dart2js/mock_libraries.dart
@@ -90,6 +90,7 @@
 import 'dart:_js_helper';
 import 'dart:_interceptors';
 import 'dart:_isolate_helper';
+import 'dart:async';
 ''';
 
 const Map<String, String> DEFAULT_JS_HELPER_LIBRARY = const <String, String>{
@@ -187,7 +188,10 @@
   'numberOrStringSuperTypeCheck': 'numberOrStringSuperTypeCheck(value) {}',
   'numTypeCast': 'numTypeCast(value) {}',
   'numTypeCheck': 'numTypeCheck(value) {}',
-  'patch': 'const patch = 0;',
+  '_Patch': 'class _Patch { final tag; const _Patch(this.tag); }',
+  'patch': 'const patch = const _Patch(null);',
+  'patch_new': 'const patch_new = const _Patch("new");',
+  'patch_old': 'const patch_old = const _Patch("old");',
   'propertyTypeCast': 'propertyTypeCast(x) {}',
   'propertyTypeCheck': 'propertyTypeCheck(value, property) {}',
   'requiresPreamble': 'requiresPreamble() {}',
@@ -359,6 +363,7 @@
 };
 
 const Map<String, String> DEFAULT_ASYNC_LIBRARY = const <String, String>{
+  'DeferredLibrary': 'class DeferredLibrary {}',
   'Future': 'class Future<T> {}',
   'Stream': 'class Stream<T> {}',
 };
diff --git a/tests/compiler/dart2js/patch_test.dart b/tests/compiler/dart2js/patch_test.dart
index 41dec19..167b096 100644
--- a/tests/compiler/dart2js/patch_test.dart
+++ b/tests/compiler/dart2js/patch_test.dart
@@ -13,12 +13,17 @@
 import 'package:compiler/src/elements/modelx.dart';
 
 Future<Compiler> applyPatch(String script, String patch,
-                            {bool analyzeAll: false, bool analyzeOnly: false,
-                             bool runCompiler: false, String main: ""}) {
+                            {bool analyzeAll: false,
+                             bool analyzeOnly: false,
+                             bool runCompiler: false,
+                             String main: "",
+                             String patchVersion}) {
   Map<String, String> core = <String, String>{'script': script};
   MockCompiler compiler = new MockCompiler.internal(coreSource: core,
                                                     analyzeAll: analyzeAll,
-                                                    analyzeOnly: analyzeOnly);
+                                                    analyzeOnly: analyzeOnly,
+                                                    patchVersion: patchVersion);
+  compiler.diagnosticHandler = createHandler(compiler, '');
   var uri = Uri.parse("patch:core");
   compiler.registerSource(uri, "$DEFAULT_PATCH_CORE_SOURCE\n$patch");
   var future;
@@ -66,7 +71,8 @@
     Expect.isNotNull(element.getter);
     element = element.getter;
   }
-  Expect.equals(expectIsPatched, element.isPatched);
+  Expect.equals(expectIsPatched, element.isPatched,
+      'Unexpected: $element.isPatched = ${element.isPatched}');
   if (expectIsPatched) {
     Expect.isNull(element.origin);
     Expect.isNotNull(element.patch);
@@ -127,6 +133,73 @@
   }));
 }
 
+
+testPatchVersioned() {
+  String oldPatch = "test(){return 'string';}";
+  String newPatch = "test(){return 'new and improved string';}";
+
+  String patchSource =
+      """
+      @patch_old $oldPatch 
+      @patch_new $newPatch 
+      """;
+
+  test(String patchVersion,
+       {String patchText,
+        bool expectIsPatched: true,
+        String expectedError,
+        String defaultPatch: '',
+        String expectedInternalError}) {
+    asyncTest(() => applyPatch(
+        "external test();",
+        """
+        $defaultPatch
+        $patchSource
+        """,
+        patchVersion: patchVersion).then((compiler) {
+      Element origin =
+          ensure(compiler, "test", compiler.coreLibrary.find,
+               expectIsPatched: expectIsPatched, checkHasBody: true);
+      if (expectIsPatched) {
+        AstElement patch =
+            ensure(compiler, "test", compiler.coreLibrary.patch.find,
+                expectIsPatch: true, checkHasBody: true);
+        Expect.equals(origin.patch, patch);
+        Expect.equals(patch.origin, origin);
+        Expect.equals(patchText, patch.node.toString());
+      }
+
+      compiler.analyzeElement(origin);
+      compiler.enqueuer.resolution.emptyDeferredTaskQueue();
+
+      Expect.isTrue(compiler.warnings.isEmpty,
+                    "Unexpected warnings: ${compiler.warnings}");
+      if (expectedError != null) {
+        Expect.equals(expectedError,
+                      compiler.errors[0].message.toString());
+      } else {
+        Expect.isTrue(compiler.errors.isEmpty,
+                      "Unexpected errors: ${compiler.errors}");
+      }
+    }).catchError((error) {
+      if (expectedInternalError != null) {
+        Expect.equals(
+            'Internal Error: $expectedInternalError', error.toString());
+      } else {
+        throw error;
+      }
+    }));
+  }
+
+  test('old', patchText: oldPatch);
+  test('new', patchText: newPatch);
+  test('unknown', expectIsPatched: false,
+       expectedError: 'External method without an implementation.');
+  test('old',
+       defaultPatch: "@patch test(){}",
+       expectedInternalError: "Trying to patch a function more than once.");
+}
+
 testPatchConstructor() {
   asyncTest(() => applyPatch(
       """
@@ -871,7 +944,7 @@
   String patch = """
     @patch class B {
       B.patchTarget() : super();
-      factory B.reflectBack() : B.originTarget;
+      factory B.reflectBack() = B.originTarget;
     }
     """;
 
@@ -925,6 +998,8 @@
   testInjectFunction();
   testPatchSignatureCheck();
 
+  testPatchVersioned();
+
   testExternalWithoutImplementationTopLevel();
   testExternalWithoutImplementationMember();
 
diff --git a/tests/compiler/dart2js/private_test.dart b/tests/compiler/dart2js/private_test.dart
index f36513e..df4c40a 100644
--- a/tests/compiler/dart2js/private_test.dart
+++ b/tests/compiler/dart2js/private_test.dart
@@ -131,7 +131,7 @@
   analyze('publicClass = new PublicClass.publicConstructor();');
   // Call private constructor on public class.
   analyze('publicClass = new PublicClass._privateConstructor();',
-      MessageKind.CANNOT_FIND_CONSTRUCTOR);
+      MessageKind.PRIVATE_ACCESS);
   // Read from private field on public class.
   analyze('var value = publicClass._privateField;',
       MessageKind.PRIVATE_ACCESS);
diff --git a/tests/compiler/dart2js/resolver_test.dart b/tests/compiler/dart2js/resolver_test.dart
index cd3d0ff..488bf26 100644
--- a/tests/compiler/dart2js/resolver_test.dart
+++ b/tests/compiler/dart2js/resolver_test.dart
@@ -685,14 +685,7 @@
     compiler.resolveStatement(statement);
     ClassElement classElement = compiler.mainApp.find(className);
     Element element;
-    if (constructor != '') {
-      element = classElement.lookupConstructor(
-          new Selector.callConstructor(constructor, classElement.library));
-    } else {
-      element = classElement.lookupConstructor(
-          new Selector.callDefaultConstructor(classElement.library));
-    }
-
+    element = classElement.lookupConstructor(constructor);
     FunctionExpression tree = (element as FunctionElement).node;
     ResolverVisitor visitor =
         new ResolverVisitor(compiler, element,
@@ -819,7 +812,7 @@
                     'Unexpected warnings: ${compiler.warnings}');
       Expect.equals(1, compiler.errors.length,
                     'Unexpected errors: ${compiler.errors}');
-    }, enableEnums: true),
+    }),
 
     MockCompiler.create((MockCompiler compiler) {
       compiler.parseScript("""enum Enum { A }
@@ -830,7 +823,7 @@
                     'Unexpected warnings: ${compiler.warnings}');
       Expect.equals(0, compiler.errors.length,
                     'Unexpected errors: ${compiler.errors}');
-    }, enableEnums: true),
+    }),
 
     MockCompiler.create((MockCompiler compiler) {
       compiler.parseScript("""enum Enum { A }
@@ -843,7 +836,7 @@
                     compiler.warnings[0].message.kind);
       Expect.equals(0, compiler.errors.length,
                     'Unexpected errors: ${compiler.errors}');
-    }, enableEnums: true),
+    }),
 
     MockCompiler.create((MockCompiler compiler) {
       compiler.parseScript("""enum Enum { A }
@@ -854,7 +847,7 @@
                     'Unexpected warnings: ${compiler.warnings}');
       Expect.equals(0, compiler.errors.length,
                     'Unexpected errors: ${compiler.errors}');
-    }, enableEnums: true),
+    }),
 
     MockCompiler.create((MockCompiler compiler) {
       compiler.parseScript("""enum Enum { A }
@@ -867,7 +860,7 @@
                     'Unexpected errors: ${compiler.errors}');
       Expect.equals(MessageKind.CANNOT_INSTANTIATE_ENUM,
                     compiler.errors[0].message.kind);
-    }, enableEnums: true),
+    }),
 
     MockCompiler.create((MockCompiler compiler) {
       compiler.parseScript("""enum Enum { A }
@@ -880,7 +873,7 @@
                     'Unexpected errors: ${compiler.errors}');
       Expect.equals(MessageKind.CANNOT_INSTANTIATE_ENUM,
                     compiler.errors[0].message.kind);
-    }, enableEnums: true),
+    }),
   ]);
 }
 
diff --git a/tests/compiler/dart2js/source_map_d2js_validity_test.dart b/tests/compiler/dart2js/source_map_d2js_validity_test.dart
index 7fe690c..ac24952 100644
--- a/tests/compiler/dart2js/source_map_d2js_validity_test.dart
+++ b/tests/compiler/dart2js/source_map_d2js_validity_test.dart
@@ -13,18 +13,23 @@
 import 'source_map_validator_helper.dart';
 
 void main() {
+  String mainFile =
+      'tests/compiler/dart2js/source_map_validator_test_file.dart';
   asyncTest(() => createTempDir().then((Directory tmpDir) {
     print(
         'Compiling tests/compiler/dart2js/source_map_validator_test_file.dart');
     Future<CompilationResult> result = entry.internalMain(
-        ['tests/compiler/dart2js/source_map_validator_test_file.dart',
+        [mainFile,
          '-o${tmpDir.path}/out.js',
          '--library-root=sdk']);
       return result.then((CompilationResult result) {
         Compiler compiler = result.compiler;
         Uri uri =
             new Uri.file('${tmpDir.path}/out.js', windows: Platform.isWindows);
-        validateSourceMap(uri, compiler);
+        validateSourceMap(uri,
+                          mainUri: Uri.base.resolve(mainFile),
+                          mainPosition: const Position(13, 1),
+                          compiler: compiler);
 
         print("Deleting '${tmpDir.path}'.");
         tmpDir.deleteSync(recursive: true);
diff --git a/tests/compiler/dart2js/source_map_deferred_d2js_validity_test.dart b/tests/compiler/dart2js/source_map_deferred_d2js_validity_test.dart
index 83a1f82..19c8f71 100644
--- a/tests/compiler/dart2js/source_map_deferred_d2js_validity_test.dart
+++ b/tests/compiler/dart2js/source_map_deferred_d2js_validity_test.dart
@@ -27,8 +27,12 @@
                                    windows: Platform.isWindows);
         Uri deferredUri = new Uri.file('${tmpDir.path}/out.js_1.part.js',
                                        windows: Platform.isWindows);
-        validateSourceMap(mainUri, compiler);
-        validateSourceMap(deferredUri, compiler);
+        validateSourceMap(mainUri,
+                          mainUri: Uri.base.resolve(file),
+                          mainPosition: const Position(7, 1),
+                          compiler: compiler);
+        validateSourceMap(deferredUri,
+                          compiler: compiler);
 
         print("Deleting '${tmpDir.path}'.");
         tmpDir.deleteSync(recursive: true);
diff --git a/tests/compiler/dart2js/source_map_validator_helper.dart b/tests/compiler/dart2js/source_map_validator_helper.dart
index fdd5ac9..e8be063 100644
--- a/tests/compiler/dart2js/source_map_validator_helper.dart
+++ b/tests/compiler/dart2js/source_map_validator_helper.dart
@@ -17,20 +17,27 @@
          AstElement;
 import 'package:compiler/src/io/source_file.dart' show SourceFile;
 
-validateSourceMap(Uri targetUri, [Compiler compiler]) {
+validateSourceMap(Uri targetUri,
+                  {Uri mainUri,
+                   Position mainPosition,
+                   Compiler compiler}) {
   Uri mapUri = getMapUri(targetUri);
+  List<String> targetLines = new File.fromUri(targetUri).readAsLinesSync();
   SingleMapping sourceMap = getSourceMap(mapUri);
   checkFileReferences(targetUri, mapUri, sourceMap);
-  checkIndexReferences(targetUri, mapUri, sourceMap);
+  checkIndexReferences(targetLines, mapUri, sourceMap);
   checkRedundancy(sourceMap);
   if (compiler != null) {
     checkNames(targetUri, mapUri, sourceMap, compiler);
   }
+  if (mainUri != null && mainPosition != null) {
+    checkMainPosition(targetUri, targetLines ,sourceMap, mainUri, mainPosition);
+  }
 }
 
-checkIndexReferences(Uri targetUri, Uri mapUri, SingleMapping sourceMap) {
-  List<String> target =
-      new File.fromUri(targetUri).readAsStringSync().split('\n');
+checkIndexReferences(List<String> targetLines,
+                     Uri mapUri,
+                     SingleMapping sourceMap) {
   int urlsLength = sourceMap.urls.length;
   List<List<String>> sources = new List(urlsLength);
   print('Reading sources');
@@ -41,7 +48,7 @@
 
   sourceMap.lines.forEach((TargetLineEntry line) {
     Expect.isTrue(line.line >= 0);
-    Expect.isTrue(line.line < target.length);
+    Expect.isTrue(line.line < targetLines.length);
     for (TargetEntry entry in line.entries) {
       int urlIndex = entry.sourceUrlId;
 
@@ -163,6 +170,42 @@
   });
 }
 
+RegExp mainSignaturePrefix = new RegExp(r'main: \[?function\(');
+
+// Check that the line pointing to by [mainPosition] in [mainUri] contains
+// the main function signature.
+checkMainPosition(Uri targetUri,
+                  List<String> targetLines,
+                  SingleMapping sourceMap,
+                  Uri mainUri,
+                  Position mainPosition) {
+  bool mainPositionFound = false;
+  sourceMap.lines.forEach((TargetLineEntry lineEntry) {
+    lineEntry.entries.forEach((TargetEntry entry) {
+      if (entry.sourceLine == null || entry.sourceUrlId == null) return;
+      Uri sourceUri = targetUri.resolve(sourceMap.urls[entry.sourceUrlId]);
+      if (sourceUri != mainUri) return;
+      if (entry.sourceLine + 1 == mainPosition.line &&
+          entry.sourceColumn + 1 == mainPosition.column) {
+        Expect.isNotNull(entry.sourceNameId,
+                         "Main position has no name.");
+        String name = sourceMap.names[entry.sourceNameId];
+        Expect.equals('main', name,
+                      "Main position name is not '$name', not 'main'.");
+        String line = targetLines[lineEntry.line];
+        Expect.isTrue(line.contains(mainSignaturePrefix),
+            "Line mapped to main position "
+            "([${lineEntry.line + 1},${entry.column + 1}]) "
+            "expected to contain '${mainSignaturePrefix.pattern}':\n$line\n");
+        mainPositionFound = true;
+      }
+    });
+  });
+  Expect.isTrue(mainPositionFound,
+                'No main position $mainPosition found in $mainUri');
+}
+
+
 sameSourcePoint(TargetEntry entry, TargetEntry otherEntry) {
   return
       (entry.sourceUrlId == otherEntry.sourceUrlId) &&
@@ -216,7 +259,7 @@
   final int line;
   final int column;
 
-  Position(this.line, this.column);
+  const Position(this.line, this.column);
 
   bool operator <=(Position other) {
     return line < other.line ||
diff --git a/tests/compiler/dart2js/type_checker_test.dart b/tests/compiler/dart2js/type_checker_test.dart
index 7f70d7d..387eb82 100644
--- a/tests/compiler/dart2js/type_checker_test.dart
+++ b/tests/compiler/dart2js/type_checker_test.dart
@@ -54,7 +54,8 @@
                 testInitializers,
                 testTypePromotionHints,
                 testFunctionCall,
-                testCascade];
+                testCascade,
+                testAwait];
   asyncTest(() => Future.forEach(tests, (test) => setup(test)));
 }
 
@@ -176,7 +177,7 @@
 """;
 
   check(String code, {warnings}) {
-    MockCompiler compiler = new MockCompiler.internal(enableEnums: true);
+    MockCompiler compiler = new MockCompiler.internal();
     return compiler.init(DECLARATIONS).then((_) {
       analyze(compiler, code, warnings: warnings, flushDeferred: true);
     });
@@ -1999,6 +2000,32 @@
   check('new A()..afunc()()[0] = new C();');
 }
 
+testAwait(MockCompiler compiler) {
+  String script = """class Foo {
+                       void method() async {}
+                       Future<int> asyncInt() => new Future<int>.value(0);
+                       Foo self() => this;
+                     }""";
+  compiler.parseScript(script);
+  ClassElement foo = compiler.mainApp.find("Foo");
+  foo.ensureResolved(compiler);
+  FunctionElement method = foo.lookupLocalMember('method');
+  analyzeIn(compiler, method, "{ await 0; }");
+  analyzeIn(compiler, method, "{ int i = await 0; }");
+  analyzeIn(compiler, method, "{ String s = await 0; }", NOT_ASSIGNABLE);
+  analyzeIn(compiler, method, "{ await asyncInt(); }");
+  analyzeIn(compiler, method, "{ int i = await asyncInt(); }");
+  analyzeIn(compiler, method, "{ String s = await asyncInt(); }",
+            NOT_ASSIGNABLE);
+  analyzeIn(compiler, method, "{ Foo f = self(); }");
+  analyzeIn(compiler, method, "{ Foo f = await self(); }");
+  analyzeIn(compiler, method, "{ Foo f = await self().asyncInt(); }",
+            NOT_ASSIGNABLE);
+  analyzeIn(compiler, method, "{ int i = await self().asyncInt(); }");
+  analyzeIn(compiler, method, "{ String s = await self().asyncInt(); }",
+            NOT_ASSIGNABLE);
+}
+
 const CLASS_WITH_METHODS = '''
 typedef int String2Int(String s);
 
@@ -2079,8 +2106,9 @@
 };
 
 Future setup(test(MockCompiler compiler)) {
-  MockCompiler compiler = new MockCompiler.internal(coreSource: ALT_SOURCE);
-  return compiler.init().then((_) => test(compiler));
+  MockCompiler compiler = new MockCompiler.internal(
+      coreSource: ALT_SOURCE, enableAsyncAwait: true);
+  return compiler.init("import 'dart:async';").then((_) => test(compiler));
 }
 
 DartType analyzeType(MockCompiler compiler, String text) {
@@ -2192,15 +2220,18 @@
 }
 
 analyzeIn(MockCompiler compiler,
-          ExecutableElement element,
+          FunctionElement element,
           String text,
           [expectedWarnings]) {
   if (expectedWarnings == null) expectedWarnings = [];
   if (expectedWarnings is !List) expectedWarnings = [expectedWarnings];
 
+  compiler.resolver.resolve(element);
   Token tokens = scan(text);
   NodeListener listener = new NodeListener(compiler, null);
-  Parser parser = new Parser(listener);
+  Parser parser = new Parser(listener,
+      yieldIsKeyword: element.asyncMarker.isYielding,
+      awaitIsKeyword: element.asyncMarker.isAsync);
   parser.parseStatement(tokens);
   Node node = listener.popNode();
   TreeElements elements = compiler.resolveNodeStatement(node, element);
diff --git a/tests/corelib/range_error_test.dart b/tests/corelib/range_error_test.dart
index 2fdf90f..ccb0cb7 100644
--- a/tests/corelib/range_error_test.dart
+++ b/tests/corelib/range_error_test.dart
@@ -4,73 +4,91 @@
 
 import "package:expect/expect.dart";
 
-// Dart test for testing out of range exceptions on arrays.
+// Dart test for testing out of range exceptions on arrays, and the content
+// of range_error toString().
 
-class RangeErrorTest {
-  static testRead() {
-    testListRead([], 0);
-    testListRead([], -1);
-    testListRead([], 1);
+void main() {
+  testRead();
+  testWrite();
+  testToString();
+}
 
-    var list = [1];
-    testListRead(list, -1);
-    testListRead(list, 1);
+void testRead() {
+  testListRead([], 0);
+  testListRead([], -1);
+  testListRead([], 1);
 
-    list = new List(1);
-    testListRead(list, -1);
-    testListRead(list, 1);
+  var list = [1];
+  testListRead(list, -1);
+  testListRead(list, 1);
 
-    list = new List();
-    testListRead(list, -1);
-    testListRead(list, 0);
-    testListRead(list, 1);
-  }
+  list = new List(1);
+  testListRead(list, -1);
+  testListRead(list, 1);
 
-  static testWrite() {
-    testListWrite([], 0);
-    testListWrite([], -1);
-    testListWrite([], 1);
+  list = new List();
+  testListRead(list, -1);
+  testListRead(list, 0);
+  testListRead(list, 1);
+}
 
-    var list = [1];
-    testListWrite(list, -1);
-    testListWrite(list, 1);
+void testWrite() {
+  testListWrite([], 0);
+  testListWrite([], -1);
+  testListWrite([], 1);
 
-    list = new List(1);
-    testListWrite(list, -1);
-    testListWrite(list, 1);
+  var list = [1];
+  testListWrite(list, -1);
+  testListWrite(list, 1);
 
-    list = new List();
-    testListWrite(list, -1);
-    testListWrite(list, 0);
-    testListWrite(list, 1);
-  }
+  list = new List(1);
+  testListWrite(list, -1);
+  testListWrite(list, 1);
 
-  static testMain() {
-    testRead();
-    testWrite();
-  }
+  list = new List();
+  testListWrite(list, -1);
+  testListWrite(list, 0);
+  testListWrite(list, 1);
+}
 
-  static testListRead(list, index) {
-    var exception = null;
-    try {
-      var e = list[index];
-    } on RangeError catch (e) {
-      exception = e;
+void testToString() {
+  for (var name in [null, "THENAME"]) {
+    for (var message in [null, "THEMESSAGE"]) {
+      var value = 37;
+      for (var re in [
+          new ArgumentError.value(value, name, message),
+          new RangeError.value(value, name, message),
+          new RangeError.index(value, [], name, message),
+          new RangeError.range(value, 0, 24, name, message)
+      ]) {
+        var str = re.toString();
+        if (name != null) Expect.isTrue(str.contains(name), "$name in $str");
+        if (message != null) Expect.isTrue(str.contains(message),
+                                           "$message in $str");
+        Expect.isTrue(str.contains("$value"), "$value in $str");
+        // No empty ':' separated parts - in that case the colon is omitted too.
+        Expect.isFalse(str.contains(new RegExp(":\s*:")));
+      }
     }
-    Expect.equals(true, exception != null);
-  }
-
-  static testListWrite(list, index) {
-    var exception = null;
-    try {
-      list[index] = null;
-    } on RangeError catch (e) {
-      exception = e;
-    }
-    Expect.equals(true, exception != null);
   }
 }
 
-main() {
-  RangeErrorTest.testMain();
+void testListRead(list, index) {
+  var exception = null;
+  try {
+    var e = list[index];
+  } on RangeError catch (e) {
+    exception = e;
+  }
+  Expect.equals(true, exception != null);
+}
+
+void testListWrite(list, index) {
+  var exception = null;
+  try {
+    list[index] = null;
+  } on RangeError catch (e) {
+    exception = e;
+  }
+  Expect.equals(true, exception != null);
 }
diff --git a/tests/corelib/regexp/issue_19193_test.dart b/tests/corelib/regexp/issue_19193_test.dart
new file mode 100644
index 0000000..52746cf
--- /dev/null
+++ b/tests/corelib/regexp/issue_19193_test.dart
@@ -0,0 +1,12 @@
+// Copyright (c) 2015, 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';
+
+// Regression test for http://dartbug.com/19193
+main() {
+  RegExp re = new RegExp(r'.*(a+)+\d');
+  Expect.isTrue("a0aaaaaaaaaaaaa".contains(re));
+  Expect.isTrue("a0aaaaaaaaaaaaaa".contains(re)); // false when using JSCRE.
+}
diff --git a/tests/corelib/string_fromcharcodes_test.dart b/tests/corelib/string_fromcharcodes_test.dart
index b344aca..fc6105f 100644
--- a/tests/corelib/string_fromcharcodes_test.dart
+++ b/tests/corelib/string_fromcharcodes_test.dart
@@ -10,7 +10,8 @@
                                ? new Iterable.generate(count, (x) => values[x])
                                : new Iterable.generate(count, (x) => values);
   test(expect, iter, [start = 0, end]) {
-    Expect.equals(expect, new String.fromCharCodes(iter, start, end));
+    var actual = new String.fromCharCodes(iter, start, end);
+    Expect.equals(expect, actual);
   }
   testThrows(iterable, [start = 0, end]) {
     Expect.throws(() { new String.fromCharCodes(iterable, start, end); });
@@ -199,4 +200,83 @@
   test("abcde" * 199998, megaList, 5, 999995);
   // Large Uint8List.
   test("abcde" * 199998, new Uint8List.fromList(megaList), 5, 999995);
+
+  const cLatin1       = const [0x00, 0xff];
+  const cUtf16        = const [0x00, 0xffff, 0xdfff, 0xdbff, 0xdfff, 0xdbff];
+  const cCodepoints   = const [0x00, 0xffff, 0xdfff, 0x10ffff, 0xdbff];
+  List  gLatin1       = cLatin1.toList(growable: true);
+  List  gUtf16        = cUtf16.toList(growable: true);
+  List  gCodepoints   = cCodepoints.toList(growable: true);
+  List  fLatin1       = cLatin1.toList(growable: false);
+  List  fUtf16        = cUtf16.toList(growable: false);
+  List  fCodepoints   = cCodepoints.toList(growable: false);
+  Uint8List  bLatin1  = new Uint8List(2)..setRange(0, 2, cLatin1);
+  Uint16List wLatin1  = new Uint16List(2)..setRange(0, 2, cLatin1);
+  Uint16List wUtf16   = new Uint16List(6)..setRange(0, 6, cUtf16);
+  Uint32List lLatin1  = new Uint32List(2)..setRange(0, 2, cLatin1);
+  Uint32List lUtf16   = new Uint32List(6)..setRange(0, 6, cUtf16);
+  Uint32List lCodepoints = new Uint32List(5)..setRange(0, 5, cCodepoints);
+  Uint8List bvLatin1  = new Uint8List.view(bLatin1.buffer);
+  Uint16List wvLatin1 = new Uint16List.view(wLatin1.buffer);
+  Uint16List wvUtf16  = new Uint16List.view(wUtf16.buffer);
+  Uint32List lvLatin1 = new Uint32List.view(lLatin1.buffer);
+  Uint32List lvUtf16  = new Uint32List.view(lUtf16.buffer);
+  Uint32List lvCodepoints = new Uint32List.view(lCodepoints.buffer);
+  var buffer = new Uint8List(200).buffer;
+  Uint8List bbLatin1  =
+      new Uint8List.view(buffer, 3, 2)..setAll(0, bLatin1);
+  Uint16List wbLatin1 =
+      new Uint16List.view(buffer, 8, 2)..setAll(0, wLatin1);
+  Uint16List wbUtf16  =
+      new Uint16List.view(buffer, 16, 6)..setAll(0, wUtf16);
+  Uint32List lbLatin1 =
+      new Uint32List.view(buffer, 32, 2)..setAll(0, lLatin1);
+  Uint32List lbUtf16  =
+      new Uint32List.view(buffer, 64, 6)..setAll(0, lUtf16);
+  Uint32List lbCodepoints =
+      new Uint32List.view(buffer, 128, 5)..setAll(0, lCodepoints);
+
+  String sLatin1     = "\x00\xff";
+  String sUnicode    =
+      "\x00\uffff$tailSurrogate$leadSurrogate$tailSurrogate$leadSurrogate";
+  for (int i = 0; i < 2; i++) {
+    for (int j = i + 1; j < 2; j++) {
+      test(sLatin1.substring(i, j), cLatin1, i, j);
+      test(sLatin1.substring(i, j), gLatin1, i, j);
+      test(sLatin1.substring(i, j), fLatin1, i, j);
+      test(sLatin1.substring(i, j), bLatin1, i, j);
+      test(sLatin1.substring(i, j), wLatin1, i, j);
+      test(sLatin1.substring(i, j), lLatin1, i, j);
+      test(sLatin1.substring(i, j), bvLatin1, i, j);
+      test(sLatin1.substring(i, j), wvLatin1, i, j);
+      test(sLatin1.substring(i, j), lvLatin1, i, j);
+      test(sLatin1.substring(i, j), bbLatin1, i, j);
+      test(sLatin1.substring(i, j), wbLatin1, i, j);
+      test(sLatin1.substring(i, j), lbLatin1, i, j);
+    }
+  }
+  for (int i = 0; i < 6; i++) {
+    for (int j = i + 1; j < 6; j++) {
+      test(sUnicode.substring(i, j), cUtf16, i, j);
+      test(sUnicode.substring(i, j), gUtf16, i, j);
+      test(sUnicode.substring(i, j), fUtf16, i, j);
+      test(sUnicode.substring(i, j), wUtf16, i, j);
+      test(sUnicode.substring(i, j), lUtf16, i, j);
+      test(sUnicode.substring(i, j), wvUtf16, i, j);
+      test(sUnicode.substring(i, j), lvUtf16, i, j);
+      test(sUnicode.substring(i, j), wbUtf16, i, j);
+      test(sUnicode.substring(i, j), lbUtf16, i, j);
+    }
+  }
+  for (int i = 0; i < 5; i++) {
+    for (int j = i + 1; j < 5; j++) {
+      int stringEnd = j < 4 ? j : j + 1;
+      test(sUnicode.substring(i, stringEnd), cCodepoints, i, j);
+      test(sUnicode.substring(i, stringEnd), gCodepoints, i, j);
+      test(sUnicode.substring(i, stringEnd), fCodepoints, i, j);
+      test(sUnicode.substring(i, stringEnd), lCodepoints, i, j);
+      test(sUnicode.substring(i, stringEnd), lvCodepoints, i, j);
+      test(sUnicode.substring(i, stringEnd), lbCodepoints, i, j);
+    }
+  }
 }
diff --git a/tests/html/html.status b/tests/html/html.status
index a42bb07..cc9fa8b 100644
--- a/tests/html/html.status
+++ b/tests/html/html.status
@@ -18,6 +18,7 @@
 storage_quota_test/missingenumcheck: Fail
 worker_api_test: Fail # Issue 10223
 two_scripts_htmltest: Fail # Issue 16603
+media_stream_test/constructors: Pass, Crash # Issue 22267
 
 [ $compiler == none && $mode == debug && ($runtime == drt || $runtime == dartium || $runtime == ContentShellOnAndroid) ]
 datalistelement_test: Skip # Issue 20540
@@ -37,15 +38,14 @@
 [ $compiler == dart2js && ($runtime == safari || $runtime == safarimobilesim || $runtime == ff  || $ie) ]
 custom/entered_left_view_test/viewless_document: Fail # Polyfill does not handle this
 
-[ $compiler == none && ($runtime == drt || $runtime == dartium) && $mode == debug && $system == macos]
-audiobuffersourcenode_test: Pass, Fail, Crash # http://crbug.com/256601
-
 [ $compiler == none && $runtime == dartium && $system == macos]
 canvasrenderingcontext2d_test/drawImage_video_element_dataUrl: Pass,Fail # Issue 11834
 
 [ $compiler == none && ($runtime == drt || $runtime == dartium || $runtime == ContentShellOnAndroid) ]
 # postMessage in dartium always transfers the typed array buffer, never a view
 postmessage_structured_test/typed_arrays: Fail
+# Dartium seems to lose the data from the dispatchEvent. 
+postmessage_structured_test/more_primitives: Fail
 async_test: Fail # Background timers not implemented.
 keyboard_event_test: Fail # Issue 13902
 isolates_test: Fail # Issue 13921
@@ -57,8 +57,6 @@
 canvasrenderingcontext2d_test/drawImage_video_element_dataUrl: Skip # Issue 17666
 
 [ $compiler == none && $runtime == ContentShellOnAndroid ]
-audiobuffersourcenode_test/functional: Skip # Causes the following (next) test to time out.  Issue 19127
-audiocontext_test/functional: Skip # Causes the following (next) test to time out.  Issue 19127
 canvasrenderingcontext2d_test/drawImage_video_element: RuntimeError # Issue 19127
 canvasrenderingcontext2d_test/drawImage_video_element_dataUrl: Pass, Fail # Issue 20524
 
@@ -117,9 +115,6 @@
 websql_test: Fail, Pass # Issue 4941: stderr contains a backtrace.
 native_gc_test: Pass, Slow
 
-[ $compiler == dart2js && $runtime == drt && $system == macos]
-audiobuffersourcenode_test: Pass, Fail
-
 [$runtime == ie10 || $runtime == ie11]
 indexeddb_5_test: Fail # Issue 12893
 js_test: Fail # Issue 14246
@@ -133,6 +128,10 @@
 two_scripts_htmltest: Skip # Times out on IE.  Issue 21537
 deferred_multi_app_htmltest: Skip # Times out on IE.  Issue 21537
 localstorage_test: Pass, RuntimeError # Issue 22166
+storage_test: Pass, RuntimeError # Issue 22166
+transition_event_test/functional: Skip # Times out. Issue 22167
+request_animation_frame_test: Skip # Times out. Issue 22167
+postmessage_structured_test/more_primitives: Fail # Does not support the MessageEvent constructor.
 
 [$runtime == ie10 ]
 # IE10 Feature support statuses-
@@ -230,8 +229,6 @@
 [ $runtime == ie10 ]
 custom/document_register_type_extensions_test/construction: Fail # Issue 13193
 custom/element_upgrade_test: Fail # Issue 18247
-request_animation_frame_test: Skip # Times out. Issue 22167
-transition_event_test/functional: Skip # Times out. Issue 22167
 worker_api_test: Fail # IE does not support URL.createObjectURL in web workers.
 
 [ $compiler == dart2js && $runtime == drt && $unchecked ]
@@ -273,7 +270,7 @@
 touchevent_test/supported: Fail
 
 [ $runtime == safari && ($builder_tag == mac10_8 || $builder_tag == mac10_9) ]
-indexeddb_1_test/functional: RuntimeError # Issue 21433
+indexeddb_1_test/functional: Skip # Times out. Issue 21433
 indexeddb_2_test: RuntimeError # Issue 21433
 indexeddb_4_test: RuntimeError # Issue 21433
 indexeddb_5_test: RuntimeError # Issue 21433
@@ -367,7 +364,7 @@
 [ $compiler == dart2js && ($runtime == drt || $runtime ==chrome) ]
 wheelevent_test: Fail # Issue 12958
 
-[ $compiler == dart2js &&  $runtime == chrome && ($system == windows || $system == linux)]
+[ $compiler == dart2js && ($runtime == chrome || $runtime == drt) && ($system == windows || $system == linux)]
 css_test/functional: Fail # Issue 21710
 css_test/supportsPointConversions: Fail # Issue 21710
 
diff --git a/tests/html/postmessage_structured_test.dart b/tests/html/postmessage_structured_test.dart
index 1dc65d7..c42cfed 100644
--- a/tests/html/postmessage_structured_test.dart
+++ b/tests/html/postmessage_structured_test.dart
@@ -136,6 +136,35 @@
     go('cyclic_list', cyclic_list);
   });
 
+  group('more_primitives', () {
+    test('js-to-dart-null-prototype-eventdata', () {
+      // Pass an object with a null prototype from JavaScript.
+      // It should be seen as a Dart Map.
+      final JS_CODE = """
+       // Call anonymous function to create a local scope.
+       (function() {
+          var o = Object.create(null);
+          o.eggs = 3;
+          var foo = new MessageEvent('stuff', {data: o});
+          window.dispatchEvent(foo);
+        })();
+      """;
+      var completed = false;
+      var subscription = null;
+      subscription = window.on['stuff'].listen(expectAsyncUntil(
+          (MessageEvent e) {
+            var data = e.data;
+            if (data is String) return;    // Messages from unit test protocol.
+            completed = true;
+            subscription.cancel();
+            expect(data, isMap);
+            expect(data['eggs'], equals(3));
+          },
+          () => completed));
+      injectSource(JS_CODE);
+    });
+  });
+
   group('typed_arrays', () {
     var array_buffer = new Uint8List(16).buffer;
     var view_a = new Float32List.view(array_buffer, 0, 4);
diff --git a/tests/compiler/dart2js/async_await_syntax.dart b/tests/language/async_await_syntax_test.dart
similarity index 62%
rename from tests/compiler/dart2js/async_await_syntax.dart
rename to tests/language/async_await_syntax_test.dart
index 8c461cf..3c8c38b 100644
--- a/tests/compiler/dart2js/async_await_syntax.dart
+++ b/tests/language/async_await_syntax_test.dart
@@ -1,11 +1,14 @@
-// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
+// Copyright (c) 2015, 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 async/await syntax.
 
+import 'dart:async' show Stream;
+
 var yield = 0;
 var await = 0;
+get st => new Stream.fromIterable([]);
 
 a01a() async => null;                        /// a01a: ok
 a01b() async* => null;                       /// a01b: compile-time error
@@ -37,14 +40,39 @@
   var await = (a) {};                        /// a05f: continued
   await(0);                                  /// a05f: continued
 }                                            /// a05f: continued
-a06a() async { await for (var o in []) {} }  /// a06a: ok
-a06b() sync* { await for (var o in []) {} }  /// a06b: compile-time error
+a06a() async { await for (var o in st) {} }  /// a06a: ok
+a06b() sync* { await for (var o in st) {} }  /// a06b: compile-time error
 a07a() sync* { yield 0; }                    /// a07a: ok
 a07b() sync { yield 0; }                     /// a07b: compile-time error
 a08a() sync* { yield* []; }                  /// a08a: ok
 a08b() sync { yield 0; }                     /// a08b: compile-time error
 a09a() async* { yield 0; }                   /// a09a: ok
-a10a() async* { yield* []; }                 /// a10a: ok
+a10a() async* { yield* []; }                 /// a10a: static type warning
+
+get sync sync {}                             /// a11a: compile-time error
+get sync sync* {}                            /// a11b: ok
+get async async {}                           /// a11c: ok
+get async async* {}                          /// a11d: ok
+
+get sync {}                                  /// a12a: ok
+get sync* {}                                 /// a12b: compile-time error
+get async {}                                 /// a12c: ok
+get async* {}                                /// a12d: compile-time error
+
+int sync;                                    /// a13a: ok
+int sync*;                                   /// a13b: compile-time error
+int async;                                   /// a13c: ok
+int async*;                                  /// a13d: compile-time error
+
+var sync;                                    /// a14a: ok
+var sync*;                                   /// a14b: compile-time error
+var async;                                   /// a14c: ok
+var async*;                                  /// a14d: compile-time error
+
+sync() {}                                    /// a15a: ok
+sync*() {}                                   /// a15b: compile-time error
+async() {}                                   /// a15c: ok
+async*() {}                                  /// a15d: compile-time error
 
 abstract class B {
   b00a() async;   /// b00a: compile-time error
@@ -79,12 +107,37 @@
   b04a() sync* {}                              /// b04a: ok
   b04b() sync {}                               /// b04b: compile-time error
   b05a() async { await 0; }                    /// b05a: ok
-  b06a() async { await for (var o in []) {} }  /// b06a: ok
+  b06a() async { await for (var o in st) {} }  /// b06a: ok
   b06b() async { await for ( ; ; ) {} }        /// b06b: compile-time error
   b07a() sync* { yield 0; }                    /// b07a: ok
   b08a() sync* { yield* []; }                  /// b08a: ok
   b09a() async* { yield 0; }                   /// b09a: ok
-  b10a() async* { yield* []; }                 /// b10a: ok
+  b10a() async* { yield* []; }                 /// b10a: static type warning
+
+  get sync sync {}                             /// b11a: compile-time error
+  get sync sync* {}                            /// b11b: ok
+  get async async {}                           /// b11c: ok
+  get async async* {}                          /// b11d: ok
+
+  get sync {}                                  /// b12a: ok
+  get sync* {}                                 /// b12b: compile-time error
+  get async {}                                 /// b12c: ok
+  get async* {}                                /// b12d: compile-time error
+
+  int sync;                                    /// b13a: ok
+  int sync*;                                   /// b13b: compile-time error
+  int async;                                   /// b13c: ok
+  int async*;                                  /// b13d: compile-time error
+
+  var sync;                                    /// b14a: ok
+  var sync*;                                   /// b14b: compile-time error
+  var async;                                   /// b14c: ok
+  var async*;                                  /// b14d: compile-time error
+
+  sync() {}                                    /// b15a: ok
+  sync*() {}                                   /// b15b: compile-time error
+  async() {}                                   /// b15c: ok
+  async*() {}                                  /// b15d: compile-time error
 }
 
 method1() {
@@ -96,11 +149,11 @@
   c04a() sync* {} c04a();                              /// c04a: ok
   c04b() sync {} c04b();                               /// c04b: compile-time error
   c05a() async { await 0; } c05a();                    /// c05a: ok
-  c06a() async { await for (var o in []) {} } c06a();  /// c06a: ok
+  c06a() async { await for (var o in st) {} } c06a();  /// c06a: ok
   c07a() sync* { yield 0; } c07a();                    /// c07a: ok
   c08a() sync* { yield* []; } c08a();                  /// c08a: ok
   c09a() async* { yield 0; } c09a();                   /// c09a: ok
-  c10a() async* { yield* []; } c10a();                 /// c10a: ok
+  c10a() async* { yield* []; } c10a();                 /// c10a: static type warning
 }
 
 method2() {
@@ -112,17 +165,18 @@
   var d04a = () sync* {}; d04a();                              /// d04a: ok
   var d04b = () sync {}; d04b();                               /// d04b: compile-time error
   var d05a = () async { await 0; }; d05a();                    /// d05a: ok
-  var d06a = () async { await for (var o in []) {} }; d06a();  /// d06a: ok
+  var d06a = () async { await for (var o in st) {} }; d06a();  /// d06a: ok
   var d07a = () sync* { yield 0; }; d07a();                    /// d07a: ok
   var d08a = () sync* { yield* []; }; d08a();                  /// d08a: ok
-  var d08b = () sync* { yield*0+1; }; d08b();                  /// d08b: ok
+  var d08b = () sync* { yield*0+1; }; d08b();                  /// d08b: static type warning
   var d08c = () { yield*0+1; }; d08c();                        /// d08c: ok
   var d09a = () async* { yield 0; }; d09a();                   /// d09a: ok
-  var d10a = () async* { yield* []; }; d10a();                 /// d10a: ok
+  var d10a = () async* { yield* []; }; d10a();                 /// d10a: static type warning
 }
 
 
 void main() {
+  var a;
   var c = new C();
   c = new C.e1(); /// e1: continued
   c = new C.e2(); /// e2: continued
@@ -157,6 +211,26 @@
   a08b();     /// a08b: continued
   a09a();     /// a09a: continued
   a10a();     /// a10a: continued
+  a = sync;   /// a11a: continued
+  a = sync;   /// a11b: continued
+  a = async;  /// a11c: continued
+  a = async;  /// a11d: continued
+  a = sync;   /// a12a: continued
+  a = sync;   /// a12b: continued
+  a = async;  /// a12c: continued
+  a = async;  /// a12d: continued
+  a = sync;   /// a13a: continued
+  a = sync;   /// a13b: continued
+  a = async;  /// a13c: continued
+  a = async;  /// a13d: continued
+  a = sync;   /// a14a: continued
+  a = sync;   /// a14b: continued
+  a = async;  /// a14c: continued
+  a = async;  /// a14d: continued
+  sync();     /// a15a: continued
+  sync();     /// a15b: continued
+  async();    /// a15c: continued
+  async();    /// a15d: continued
 
   c.b00a();   /// b00a: continued
   c.b00b();   /// b00b: continued
@@ -176,6 +250,26 @@
   c.b08a();   /// b08a: continued
   c.b09a();   /// b09a: continued
   c.b10a();   /// b10a: continued
+  a = c.sync;   /// b11a: continued
+  a = c.sync;   /// b11b: continued
+  a = c.async;  /// b11c: continued
+  a = c.async;  /// b11d: continued
+  a = c.sync;   /// b12a: continued
+  a = c.sync;   /// b12b: continued
+  a = c.async;  /// b12c: continued
+  a = c.async;  /// b12d: continued
+  a = c.sync;   /// b13a: continued
+  a = c.sync;   /// b13b: continued
+  a = c.async;  /// b13c: continued
+  a = c.async;  /// b13d: continued
+  a = c.sync;   /// b14a: continued
+  a = c.sync;   /// b14b: continued
+  a = c.async;  /// b14c: continued
+  a = c.async;  /// b14d: continued
+  c.sync();     /// b15a: continued
+  c.sync();     /// b15b: continued
+  c.async();    /// b15c: continued
+  c.async();    /// b15d: continued
 
   method1();
   method2();
diff --git a/tests/language/async_test.dart b/tests/language/async_test.dart
index d1bf80d..c66ea18 100644
--- a/tests/language/async_test.dart
+++ b/tests/language/async_test.dart
@@ -13,7 +13,8 @@
   return 7 + a;
 }
 
-int topLevelWithParameterWrongType(int a) async {
+int /// type-mismatch2: static type warning, dynamic type error
+topLevelWithParameterWrongType(int a) async {
   return 7 + a;
 }
 
@@ -34,8 +35,8 @@
   A.fail() async;  /// constructor2: compile-time error
   factory A.create() async {return null; } /// constructor3: compile-time error
 
-  int someMethod(int param1, int param2, int param3) async => _x + param2;
-  int get getter async { return 5 + _x; }
+  int someMethod(int param1, int param2, int param3) async => _x + param2; /// type-mismatch3: static type warning, dynamic type error
+  int get getter async { return 5 + _x; } /// type-mismatch4: static type warning, dynamic type error
   operator+(A other) async {
     return new A(_x + other._x);
   }
@@ -61,7 +62,7 @@
   Expect.isTrue(asyncReturn is Future);
 
   int a1 = topLevelWithParameter(2);  /// type-mismatch1: static type warning, dynamic type error
-  int a2 = topLevelWithParameterWrongType(2);  /// type-mismatch2: static type warning, dynamic type error
+  int a2 = topLevelWithParameterWrongType(2);  /// type-mismatch2: continued
   asyncReturn = topLevelWithParameter(4);
   Expect.isTrue(asyncReturn is Future);
   asyncReturn.then((int result) => Expect.equals(result, 11));
@@ -81,11 +82,11 @@
 
   A a = new A(13);
 
-  asyncReturn = a.someMethod(1,2,3);  /// type-mismatch3: static type warning, dynamic type error
+  asyncReturn = a.someMethod(1,2,3);  /// type-mismatch3: continued
   Expect.isTrue(asyncReturn is Future);  /// type-mismatch3: continued
   asyncReturn.then((int result) => Expect.equals(result, 15));  /// type-mismatch3: continued
 
-  asyncReturn = a.getter;  /// type-mismatch4: static type warning, dynamic type error
+  asyncReturn = a.getter;  /// type-mismatch4: continued
   Expect.isTrue(asyncReturn is Future);  /// type-mismatch4: continued
   asyncReturn.then((int result) => Expect.equals(result, 18));  /// type-mismatch4: continued
 
@@ -125,4 +126,6 @@
   };
   checkAsync(() async => 4);
 
+  new A.fail(); /// constructor2: continued
+  new A.create(); /// constructor3: continued
 }
diff --git a/tests/language/await_test.dart b/tests/language/await_test.dart
index 33b1b74..cb779d9 100644
--- a/tests/language/await_test.dart
+++ b/tests/language/await_test.dart
@@ -11,21 +11,21 @@
 int globalVariable = 1;
 int topLevelFoo(int param) => 1;
 int get topLevelGetter => globalVariable;
-int set topLevelSetter(val) {
+void set topLevelSetter(val) {
   globalVariable = val;
 }
 
 class C {
   static int staticField = 1;
   static int get staticGetter => staticField;
-  static int set staticSetter(val) {
+  static void set staticSetter(val) {
     staticField = val;
   }
   static int staticFoo(int param) => param;
 
   int field = 1;
   int get getter => field;
-  int set setter(val) {
+  void set setter(val) {
     field = val;
   }
   int foo(int param) => param;
@@ -95,7 +95,7 @@
   Expect.equals(a, "1 1 someString");
   try {
     var c = new C();
-    var d = c.nooooo() + await bar();
+    var d = c.nooooo() + await dummy();
   } catch (e) {}
   var cnt = 2;
   var b = [1,2,3];
@@ -116,7 +116,7 @@
   var e = (a is int) ? await dummy() : 2;
   Expect.equals(e, 2);
   try {
-    var f = (a is intt) ? await dummy() : 2;
+    var f = (a is int) ? await dummy() : 2;
   } catch(e) {}
 }
 
diff --git a/tests/language/enum_duplicate_lib.dart b/tests/language/enum_duplicate_lib.dart
new file mode 100644
index 0000000..b9c84f5
--- /dev/null
+++ b/tests/language/enum_duplicate_lib.dart
@@ -0,0 +1,14 @@
+// Copyright (c) 2015, 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 enum_duplicate_lib;
+
+enum Enum1 {
+  A,
+  B,
+}
+
+class Enum2 {
+  static Iterable get values => ['Enum2.A', 'Enum2.B'];
+}
diff --git a/tests/language/enum_duplicate_test.dart b/tests/language/enum_duplicate_test.dart
new file mode 100644
index 0000000..9222a6f
--- /dev/null
+++ b/tests/language/enum_duplicate_test.dart
@@ -0,0 +1,34 @@
+// Copyright (c) 2015, 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.
+
+// SharedOptions=--enable-enum
+
+// Test for duplicate enums.
+
+library enum_duplicate_test;
+
+import 'package:expect/expect.dart';
+
+import 'enum_duplicate_lib.dart' as lib; /// 01: ok
+import 'enum_duplicate_lib.dart' as lib; /// 02: ok
+
+enum Enum1 {
+  A,
+  B,
+}
+
+enum Enum2 {
+  A,
+  B,
+}
+
+main() {
+  Expect.equals('Enum1.A,Enum1.B', Enum1.values.join(','));
+  Expect.equals('Enum1.A,Enum1.B', lib.Enum1.values.join(',')); /// 01: continued
+  Expect.equals('Enum2.A,Enum2.B', Enum2.values.join(','));
+  Expect.equals('Enum2.A,Enum2.B', lib.Enum2.values.join(',')); /// 02: continued
+}
+
+
+
diff --git a/tests/language/enum_index_test.dart b/tests/language/enum_index_test.dart
new file mode 100644
index 0000000..21a8e0e
--- /dev/null
+++ b/tests/language/enum_index_test.dart
@@ -0,0 +1,32 @@
+// Copyright (c) 2015, 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.
+
+// SharedOptions=--enable-enum
+
+// Test index access for enums.
+
+library enum_index_test;
+
+import 'package:expect/expect.dart';
+
+enum Enum {
+  A,
+  B,
+}
+
+class Class {
+  var index;
+}
+
+main() {
+  test(null, new Class());
+  test(0, Enum.A);
+  test(1, Enum.B);
+}
+
+test(expected, object) {
+  Expect.equals(expected, object.index);
+}
+
+
diff --git a/tests/language/enum_private_lib.dart b/tests/language/enum_private_lib.dart
new file mode 100644
index 0000000..c8fb00f
--- /dev/null
+++ b/tests/language/enum_private_lib.dart
@@ -0,0 +1,10 @@
+// Copyright (c) 2015, 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 enum_private_lib;
+
+enum Enum2 {
+  _A,
+  _B,
+}
diff --git a/tests/language/enum_private_test.dart b/tests/language/enum_private_test.dart
new file mode 100644
index 0000000..e55b0c2
--- /dev/null
+++ b/tests/language/enum_private_test.dart
@@ -0,0 +1,27 @@
+// Copyright (c) 2015, 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.
+
+// SharedOptions=--enable-enum
+
+// Test privacy issue for enums.
+
+library enum_private_test;
+
+import 'package:expect/expect.dart';
+
+import 'enum_private_lib.dart';
+
+enum Enum1 {
+  _A,
+  _B,
+}
+
+main() {
+  Expect.equals('Enum1._A,Enum1._B', Enum1.values.join(','));
+  Expect.equals('Enum2._A,Enum2._B', Enum2.values.join(',')); /// 01: ok
+  Expect.throws(() => Enum2._A, (e) => e is NoSuchMethodError); /// 02: static type warning
+}
+
+
+
diff --git a/tests/language/language.status b/tests/language/language.status
index 4df4177..e87eb35 100644
--- a/tests/language/language.status
+++ b/tests/language/language.status
@@ -7,6 +7,7 @@
 
 [ $compiler == none ]
 built_in_identifier_prefix_test: Fail # Issue 6970
+async_await_syntax_test/b00a: MissingCompileTimeError # Issue 21404
 
 # These bugs refer currently ongoing language discussions.
 constructor_initializer_test/none: Fail # Issue 12633
@@ -18,20 +19,6 @@
 duplicate_export_negative_test: Fail # Issue 6134
 
 [ $compiler == dart2dart ]
-async_control_structures_test: CompileTimeError # Issue 22051
-async_test/none: CompileTimeError # Issue 22051
-async_test/type-mismatch1: CompileTimeError # Issue 22051
-async_test/type-mismatch2: CompileTimeError # Issue 22051
-async_test/type-mismatch3: CompileTimeError # Issue 22051
-async_test/type-mismatch4: CompileTimeError # Issue 22051
-await_backwards_compatibility_test/none: CompileTimeError # Issue 22051
-await_exceptions_test: CompileTimeError # Issue 22051
-await_for_test: CompileTimeError # Issue 22051
-await_future_test: CompileTimeError # Issue 22051
-await_nonfuture_test: CompileTimeError # Issue 22051
-await_regression_test: CompileTimeError # Issue 22051
-await_test: CompileTimeError # Issue 22051
-
 deferred_load_library_wrong_args_test/none: Fail # Issue 17523
 deferred_load_inval_code_test: Fail # Issue 17523
 deferred_not_loaded_check_test: Fail # Issue 17523
@@ -41,21 +28,84 @@
 deferred_closurize_load_library_test: Fail  # Issue 17523
 deferred_inlined_test: Fail  # Issue 17523
 deferred_optimized_test: Fail  # Issue 17523
-enum_test: Crash # Issue 21416/21417
 enum_mirror_test: Skip # Issue 11511.
 
 override_inheritance_mixed_test/08: Fail # Issue 18124
 override_inheritance_mixed_test/09: Fail # Issue 18124
 
-[ $compiler == none || $compiler == dart2dart]
+[ $compiler == none || $compiler == dart2dart ]
 # Non-contractive types are not supported in the vm.
 cyclic_type_test/02: Fail, OK
 cyclic_type_test/04: Fail, OK
 cyclic_type2_test: Fail, OK
 least_upper_bound_expansive_test/*: Fail, OK
 
-compile_time_constant_c_test/01: Fail # Issue 21000
 compile_time_constant12_test: Fail # Issue 21000
+async_await_syntax_test/a07a: CompileTimeError # Issue 21404
+async_await_syntax_test/a08a: CompileTimeError # Issue 21404
+async_await_syntax_test/a09a: CompileTimeError # Issue 21404
+async_await_syntax_test/a10a: CompileTimeError # Issue 21404
+async_await_syntax_test/b07a: CompileTimeError # Issue 21404
+async_await_syntax_test/b08a: CompileTimeError # Issue 21404
+async_await_syntax_test/b09a: CompileTimeError # Issue 21404
+async_await_syntax_test/b10a: CompileTimeError # Issue 21404
+async_await_syntax_test/c07a: CompileTimeError # Issue 21404
+async_await_syntax_test/c08a: CompileTimeError # Issue 21404
+async_await_syntax_test/c09a: CompileTimeError # Issue 21404
+async_await_syntax_test/c10a: CompileTimeError # Issue 21404
+async_await_syntax_test/d07a: CompileTimeError # Issue 21404
+async_await_syntax_test/d08a: CompileTimeError # Issue 21404
+async_await_syntax_test/d08b: CompileTimeError # Issue 21404
+async_await_syntax_test/d09a: CompileTimeError # Issue 21404
+async_await_syntax_test/d10a: CompileTimeError # Issue 21404
+
+[ $compiler == none || ($compiler == dart2dart && $builder_tag != new_backend) ]
+compile_time_constant_c_test/01: Fail # Issue 21000
+async_await_syntax_test/a03a: CompileTimeError # Issue 21404
+async_await_syntax_test/a04a: CompileTimeError # Issue 21404
+async_await_syntax_test/a11b: CompileTimeError # Issue 21404
+async_await_syntax_test/a11d: CompileTimeError # Issue 21404
+async_await_syntax_test/b03a: CompileTimeError # Issue 21404
+async_await_syntax_test/b04a: CompileTimeError # Issue 21404
+async_await_syntax_test/b11b: CompileTimeError # Issue 21404
+async_await_syntax_test/b11d: CompileTimeError # Issue 21404
+async_await_syntax_test/c03a: CompileTimeError # Issue 21404
+async_await_syntax_test/c04a: CompileTimeError # Issue 21404
+async_await_syntax_test/d03a: CompileTimeError # Issue 21404
+async_await_syntax_test/d04a: CompileTimeError # Issue 21404
+
+[ $compiler == none && ($runtime == drt || $runtime == dartium|| $runtime == ContentShellOnAndroid) ]
+async_await_syntax_test/a03a: RuntimeError # Issue 21404
+async_await_syntax_test/a04a: RuntimeError # Issue 21404
+async_await_syntax_test/a07a: RuntimeError # Issue 21404
+async_await_syntax_test/a08a: RuntimeError # Issue 21404
+async_await_syntax_test/a09a: RuntimeError # Issue 21404
+async_await_syntax_test/a10a: RuntimeError # Issue 21404
+async_await_syntax_test/a11b: RuntimeError # Issue 21404
+async_await_syntax_test/a11d: RuntimeError # Issue 21404
+async_await_syntax_test/b00a: Fail  # Issue 21404
+async_await_syntax_test/b03a: RuntimeError # Issue 21404
+async_await_syntax_test/b04a: RuntimeError # Issue 21404
+async_await_syntax_test/b07a: RuntimeError # Issue 21404
+async_await_syntax_test/b08a: RuntimeError # Issue 21404
+async_await_syntax_test/b09a: RuntimeError # Issue 21404
+async_await_syntax_test/b10a: RuntimeError # Issue 21404
+async_await_syntax_test/b11b: RuntimeError # Issue 21404
+async_await_syntax_test/b11d: RuntimeError # Issue 21404
+async_await_syntax_test/c03a: RuntimeError # Issue 21404
+async_await_syntax_test/c04a: RuntimeError # Issue 21404
+async_await_syntax_test/c07a: RuntimeError # Issue 21404
+async_await_syntax_test/c08a: RuntimeError # Issue 21404
+async_await_syntax_test/c09a: RuntimeError # Issue 21404
+async_await_syntax_test/c10a: RuntimeError # Issue 21404
+async_await_syntax_test/d03a: RuntimeError # Issue 21404
+async_await_syntax_test/d04a: RuntimeError # Issue 21404
+async_await_syntax_test/d07a: RuntimeError # Issue 21404
+async_await_syntax_test/d08a: RuntimeError # Issue 21404
+async_await_syntax_test/d08b: RuntimeError # Issue 21404
+async_await_syntax_test/d09a: RuntimeError # Issue 21404
+async_await_syntax_test/d10a: RuntimeError # Issue 21404
+
 
 [ $compiler == none && $runtime == vm ]
 class_keyword_test/02: MissingCompileTimeError # Issue 13627
diff --git a/tests/language/language_analyzer.status b/tests/language/language_analyzer.status
index e53b6c8..242a521 100644
--- a/tests/language/language_analyzer.status
+++ b/tests/language/language_analyzer.status
@@ -10,6 +10,17 @@
 async_test/type-mismatch3: MissingStaticWarning # Issue 22053
 async_test/type-mismatch4: MissingStaticWarning # Issue 22053
 
+async_await_syntax_test/a03b: MissingCompileTimeError # Issue 22234
+async_await_syntax_test/a04c: MissingCompileTimeError # Issue 22234
+async_await_syntax_test/a05c: CompileTimeError
+async_await_syntax_test/a05e: CompileTimeError
+async_await_syntax_test/a05f: MissingCompileTimeError
+async_await_syntax_test/a10a: MissingStaticWarning
+async_await_syntax_test/b10a: MissingStaticWarning
+async_await_syntax_test/c10a: MissingStaticWarning
+async_await_syntax_test/d08b: MissingStaticWarning
+async_await_syntax_test/d10a: MissingStaticWarning
+
 # Runtime negative test. No static errors or warnings.
 closure_call_wrong_argument_count_negative_test: skip
 
diff --git a/tests/language/language_analyzer2.status b/tests/language/language_analyzer2.status
index 05bf994..793472d 100644
--- a/tests/language/language_analyzer2.status
+++ b/tests/language/language_analyzer2.status
@@ -3,12 +3,9 @@
 # BSD-style license that can be found in the LICENSE file.
 
 [ $compiler == dart2analyzer ]
-await_backwards_compatibility_test/none: CompileTimeError # Issue 22052
-await_test: CompileTimeError # Issue 22052
 
-async_test/type-mismatch2: MissingStaticWarning # Issue 22053
-async_test/type-mismatch3: MissingStaticWarning # Issue 22053
-async_test/type-mismatch4: MissingStaticWarning # Issue 22053
+async_await_syntax_test/a03b: MissingCompileTimeError # Issue 22234
+async_await_syntax_test/a04c: MissingCompileTimeError # Issue 22234
 
 # Runtime negative test. No static errors or warnings.
 closure_call_wrong_argument_count_negative_test: skip
diff --git a/tests/language/language_dart2js.status b/tests/language/language_dart2js.status
index d41f150..fd18821 100644
--- a/tests/language/language_dart2js.status
+++ b/tests/language/language_dart2js.status
@@ -15,6 +15,54 @@
 await_nonfuture_test: CompileTimeError # Issue 21411
 await_regression_test: CompileTimeError # Issue 21411
 await_test: CompileTimeError # Issue 21411
+async_await_syntax_test/a01a: CompileTimeError # Issue 21411
+async_await_syntax_test/a02a: CompileTimeError # Issue 21411
+async_await_syntax_test/a03a: CompileTimeError # Issue 21411
+async_await_syntax_test/a04a: CompileTimeError # Issue 21411
+async_await_syntax_test/a05a: CompileTimeError # Issue 21411
+async_await_syntax_test/a05b: CompileTimeError # Issue 21411
+async_await_syntax_test/a06a: CompileTimeError # Issue 21411
+async_await_syntax_test/a07a: CompileTimeError # Issue 21411
+async_await_syntax_test/a08a: CompileTimeError # Issue 21411
+async_await_syntax_test/a09a: CompileTimeError # Issue 21411
+async_await_syntax_test/a10a: CompileTimeError # Issue 21411
+async_await_syntax_test/a11b: CompileTimeError # Issue 21411
+async_await_syntax_test/a11c: CompileTimeError # Issue 21411
+async_await_syntax_test/a11d: CompileTimeError # Issue 21411
+async_await_syntax_test/b01a: CompileTimeError # Issue 21411
+async_await_syntax_test/b02a: CompileTimeError # Issue 21411
+async_await_syntax_test/b03a: CompileTimeError # Issue 21411
+async_await_syntax_test/b04a: CompileTimeError # Issue 21411
+async_await_syntax_test/b05a: CompileTimeError # Issue 21411
+async_await_syntax_test/b06a: CompileTimeError # Issue 21411
+async_await_syntax_test/b07a: CompileTimeError # Issue 21411
+async_await_syntax_test/b08a: CompileTimeError # Issue 21411
+async_await_syntax_test/b09a: CompileTimeError # Issue 21411
+async_await_syntax_test/b10a: CompileTimeError # Issue 21411
+async_await_syntax_test/b11b: CompileTimeError # Issue 21411
+async_await_syntax_test/b11c: CompileTimeError # Issue 21411
+async_await_syntax_test/b11d: CompileTimeError # Issue 21411
+async_await_syntax_test/c01a: CompileTimeError # Issue 21411
+async_await_syntax_test/c02a: CompileTimeError # Issue 21411
+async_await_syntax_test/c03a: CompileTimeError # Issue 21411
+async_await_syntax_test/c04a: CompileTimeError # Issue 21411
+async_await_syntax_test/c05a: CompileTimeError # Issue 21411
+async_await_syntax_test/c06a: CompileTimeError # Issue 21411
+async_await_syntax_test/c07a: CompileTimeError # Issue 21411
+async_await_syntax_test/c08a: CompileTimeError # Issue 21411
+async_await_syntax_test/c09a: CompileTimeError # Issue 21411
+async_await_syntax_test/c10a: CompileTimeError # Issue 21411
+async_await_syntax_test/d01a: CompileTimeError # Issue 21411
+async_await_syntax_test/d02a: CompileTimeError # Issue 21411
+async_await_syntax_test/d03a: CompileTimeError # Issue 21411
+async_await_syntax_test/d04a: CompileTimeError # Issue 21411
+async_await_syntax_test/d05a: CompileTimeError # Issue 21411
+async_await_syntax_test/d06a: CompileTimeError # Issue 21411
+async_await_syntax_test/d07a: CompileTimeError # Issue 21411
+async_await_syntax_test/d08a: CompileTimeError # Issue 21411
+async_await_syntax_test/d08b: CompileTimeError # Issue 21411
+async_await_syntax_test/d09a: CompileTimeError # Issue 21411
+async_await_syntax_test/d10a: CompileTimeError # Issue 21411
 
 [ $compiler == dart2js && $unchecked ]
 async_test/type-mismatch1: CompileTimeError # Issue 21411
@@ -193,6 +241,20 @@
 closure_call_wrong_argument_count_negative_test: Skip
 label_test: Skip
 
+[ $compiler == dart2dart && $builder_tag == new_backend ]
+await_for_test: RuntimeError # Issue 22051
+await_regression_test: RuntimeError # Issue 22051
+async_await_syntax_test/a06a: RuntimeError # Issue 22051
+async_await_syntax_test/b06a: RuntimeError # Issue 22051
+async_await_syntax_test/c06a: RuntimeError # Issue 22051
+async_await_syntax_test/d06a: RuntimeError # Issue 22051
+async_control_structures_test: RuntimeError # Issue 22051
+async_test/none: RuntimeError # Issue 22051
+async_test/type-mismatch1: RuntimeError # Issue 22051
+async_test/type-mismatch2: RuntimeError # Issue 22051
+async_test/type-mismatch3: RuntimeError # Issue 22051
+async_test/type-mismatch4: RuntimeError # Issue 22051
+
 [ $compiler == dart2dart && $builder_tag == new_backend && $minified == true ]
 # This test fails in minified, because the type-argument is
 # renamed, but the symbol naming it it is not.
@@ -208,9 +270,8 @@
 
 [ $compiler == dart2dart ]
 regress_13494_test: Fail # Issue 13494
-enum_const_test/01: Crash # Issue 21681
-enum_const_test/02: Crash # Issue 21681
 
+enum_duplicate_test/01: CompileTimeError # Issue 22169
 
 built_in_identifier_prefix_test: Fail # Issue 6972
 constructor_initializer_test/none: Fail # Issue 12633
diff --git a/tests/lib/async/stream_iterator_double_cancel_test.dart b/tests/lib/async/stream_iterator_double_cancel_test.dart
new file mode 100644
index 0000000..16bb573
--- /dev/null
+++ b/tests/lib/async/stream_iterator_double_cancel_test.dart
@@ -0,0 +1,38 @@
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "dart:async";
+import "package:expect/expect.dart";
+import "package:async_helper/async_helper.dart";
+
+Stream timedStream(int n) {
+  int i = 0;
+  StreamController controller;
+  tick() {
+    if (i >= n) {
+      controller.close();
+      return;
+    }
+    controller.add(i);
+    i++;
+    new Future.delayed(new Duration(milliseconds: 0), tick);
+  }
+  controller = new StreamController(onListen: tick);
+  return controller.stream;
+}
+
+void main() {
+  asyncStart();
+  StreamIterator iterator = new StreamIterator(timedStream(10));
+  helper(more) {
+    if (!more) {
+      // Canceling the already closed iterator should not lead to a crash.
+      iterator.cancel();
+      asyncEnd();
+    } else {
+      iterator.moveNext().then(helper);
+    }
+  }
+  iterator.moveNext().then(helper);
+}
\ No newline at end of file
diff --git a/tests/lib/mirrors/invocation_fuzz_test.dart b/tests/lib/mirrors/invocation_fuzz_test.dart
index 6ff9242..61e7626 100644
--- a/tests/lib/mirrors/invocation_fuzz_test.dart
+++ b/tests/lib/mirrors/invocation_fuzz_test.dart
@@ -23,6 +23,9 @@
   // Don't change the exit code, which may fool the test harness.
   'dart.io.exitCode',
 
+  // Don't kill random other processes.
+  'dart.io.Process.killPid',
+
   // Don't run blocking io calls.
   new RegExp(r".*Sync$"),
 
diff --git a/tests/standalone/io/addlatexhash_test.dart b/tests/standalone/io/addlatexhash_test.dart
index dbefe39..1f189ab 100755
--- a/tests/standalone/io/addlatexhash_test.dart
+++ b/tests/standalone/io/addlatexhash_test.dart
@@ -59,11 +59,7 @@
 // LaTeX source 'addlatexhash_test_src.tex' are identical in groups
 // of eight (so we get 8 identical hash values, then another hash
 // value 8 times, etc.)
-testSameHash() {
-  // set up temporary directory to hold output
-  final tmpDir = Directory.systemTemp.createTempSync("addlatexhash_test");
-  final tmpDirPath = tmpDir.path;
-
+testSameHash(String tmpDirPath) {
   // file names/paths for file containing groups of 8 variants of a paragraph
   const par8timesName = "addlatexhash_test_src";
   const par8timesFileName = "$par8timesName.tex";
@@ -120,11 +116,7 @@
 // does not affect the generated output, as seen via dvi2tty and diff.
 // NB: Not part of normal testing (only local): latex and dvi2tty are
 // not installed in the standard test environment.
-testSameDVI() {
-  // set up /tmp directory to hold output
-  final tmpDir = Directory.systemTemp.createTempSync("addlatexhash_test");
-  final tmpDirPath = tmpDir.path;
-
+testSameDVI(String tmpDirPath) {
   // file names/paths for original spec
   const specName = "dartLangSpec";
   const specFileName = "$specName.tex";
@@ -165,7 +157,7 @@
                        listPath]);
 
   runDvi2tty(dviFile) =>
-      Process.runSync("dvi2tty", [dviFile], workingDirectory: tmpDir.path);
+      Process.runSync("dvi2tty", [dviFile], workingDirectory: tmpDirPath);
 
   chkDvi2tty(file, subject) =>
       checkAction(runDvi2tty(file), "dvitty on $subject failed");
@@ -189,10 +181,24 @@
   }
 }
 
+runWithTempDir(void test(String tempDir)) {
+  final tempDir = Directory.systemTemp.createTempSync("addlatexhash_test");
+  try {
+    test(tempDir.path);
+  }
+  finally {
+    tempDir.delete(recursive: true);
+  }
+}
+
+
 main([args]) {
   testCutMatch();
   testSisp();
-  testSameHash();
+
+  runWithTempDir(testSameHash);
   // latex and dvi2tty are not installed in the standard test environment
-  if (args.length > 0 && args[0] == "local") testSameDVI();
+  if (args.length > 0 && args[0] == "local") {
+    runWithTempDir(testSameDVI);
+  }
 }
diff --git a/tests/standalone/io/process_detached_script.dart b/tests/standalone/io/process_detached_script.dart
index 122831b..6e907598 100644
--- a/tests/standalone/io/process_detached_script.dart
+++ b/tests/standalone/io/process_detached_script.dart
@@ -4,8 +4,19 @@
 //
 // Simple script hanging for testing a detached process.
 
+import 'dart:io';
 import 'dart:isolate';
 
-main() {
+void main(List<String> args) {
   new ReceivePort().listen(print);
+
+  // If an argument 'echo' is passed echo stdin to stdout and stderr.
+  if (args.length == 1 && args[0] == 'echo') {
+    stdin.fold([], (p, e) => p..addAll(e)).then((message) {
+      stdout.add(message);
+      stderr.add(message);
+      stdout.close();
+      stderr.close();
+    });
+  }
 }
diff --git a/tests/standalone/io/process_detached_test.dart b/tests/standalone/io/process_detached_test.dart
index 483b9ca..194e756 100644
--- a/tests/standalone/io/process_detached_test.dart
+++ b/tests/standalone/io/process_detached_test.dart
@@ -16,9 +16,9 @@
   asyncStart();
   var script =
       Platform.script.resolve('process_detached_script.dart').toFilePath();
-  var future = Process.start(Platform.executable, [script], detach: true);
+  var future = Process.start(
+      Platform.executable, [script], mode: ProcessStartMode.DETACHED);
   future.then((process) {
-    print(process.pid);
     Expect.isNotNull(process.pid);
     Expect.isTrue(process.pid is int);
     Expect.isNull(process.exitCode);
@@ -31,10 +31,41 @@
   });
 }
 
+void testWithStdio() {
+  asyncStart();
+  var script =
+      Platform.script.resolve('process_detached_script.dart').toFilePath();
+  var future = Process.start(
+      Platform.executable,
+      [script, 'echo'],
+      mode: ProcessStartMode.DETACHED_WITH_STDIO);
+  future.then((process) {
+    Expect.isNotNull(process.pid);
+    Expect.isTrue(process.pid is int);
+    Expect.isNull(process.exitCode);
+    var message = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
+    process.stdin.add(message);
+    process.stdin.close();
+    var f1 = process.stdout.fold([], (p, e) => p..addAll(e));
+    var f2 = process.stderr.fold([], (p, e) => p..addAll(e));
+    Future.wait([f1, f2])
+        .then((values) {
+          Expect.listEquals(values[0], message);
+          Expect.listEquals(values[1], message);
+        })
+        .whenComplete(() {
+          Expect.isTrue(process.kill());
+        });
+  }).whenComplete(() {
+    asyncEnd();
+  });
+}
+
 void testFailure() {
   asyncStart();
   Directory.systemTemp.createTemp('dart_detached_process').then((temp) {
-    var future = Process.start(temp.path, ['a', 'b'], detach: true);
+    var future = Process.start(
+        temp.path, ['a', 'b'], mode: ProcessStartMode.DETACHED);
     future.then((process) {
       Expect.fail('Starting process from invalid executable succeeded');
     }, onError: (e) {
@@ -48,5 +79,6 @@
 
 main() {
   test();
+  testWithStdio();
   testFailure();
 }
diff --git a/tests/standalone/io/process_kill_test.dart b/tests/standalone/io/process_kill_test.dart
index 6739336..9816d41 100644
--- a/tests/standalone/io/process_kill_test.dart
+++ b/tests/standalone/io/process_kill_test.dart
@@ -5,11 +5,16 @@
 // Process test program to test process communication.
 
 library ProcessKillTest;
+
+import 'dart:io';
+
+import "package:async_helper/async_helper.dart";
 import "package:expect/expect.dart";
-import "dart:io";
+
 import "process_test_util.dart";
 
 testKill() {
+  asyncStart();
   // Start a process that will hang waiting for input until killed.
   Process.start(getProcessTestFileName(), const ["0", "1", "0", "0"]).then((p) {
     p.exitCode.then((exitCode) {
@@ -17,11 +22,28 @@
       Expect.isTrue(exitCode != 0);
       // Killing a process that is already dead returns false.
       Expect.isFalse(p.kill());
+      asyncEnd();
     });
     Expect.isTrue(p.kill());
   });
 }
 
+testKillPid() {
+  asyncStart();
+  // Start a process that will hang waiting for input until killed.
+  Process.start(getProcessTestFileName(), const ["0", "1", "0", "0"]).then((p) {
+    p.exitCode.then((exitCode) {
+      // Process killed from the side so exit code is not 0.
+      Expect.isTrue(exitCode != 0);
+      // Killing a process that is already dead returns false.
+      Expect.isFalse(Process.killPid(p.pid));
+      asyncEnd();
+    });
+    Expect.isTrue(Process.killPid(p.pid));
+  });
+}
+
 main() {
   testKill();
+  testKillPid();
 }
diff --git a/tests/standalone/typed_data_test.dart b/tests/standalone/typed_data_test.dart
index fa467de..1b44624 100644
--- a/tests/standalone/typed_data_test.dart
+++ b/tests/standalone/typed_data_test.dart
@@ -147,6 +147,22 @@
 void testSetRange() {
   testSetRangeHelper(new Uint8List(3));
   testSetRangeHelper(new Uint8ClampedList(3));
+  testSetRangeHelper(new Uint16List(3));
+  testSetRangeHelper(new Int16List(3));
+
+  var list = new Uint8List(4);
+  list.setRange(0, 4, "abcd".codeUnits, 0);
+  Expect.listEquals(list, "abcd".codeUnits);
+  list = new Uint16List(4);
+  list.setRange(0, 4, "abcd".codeUnits, 0);
+  Expect.listEquals(list, "abcd".codeUnits);
+  list.setRange(0, 4, "\xff\u0100\uffff\x00".codeUnits, 0);
+  Expect.listEquals(list, "\xff\u0100\uffff\x00".codeUnits);
+  list = new Int16List(4);
+  list.setRange(0, 4, "abcd".codeUnits, 0);
+  Expect.listEquals(list, "abcd".codeUnits);
+  list.setRange(0, 4, "\xff\u0100\u7fff\x00".codeUnits, 0);
+  Expect.listEquals(list, "\xff\u0100\u7fff\x00".codeUnits);
 }
 
 class C {
@@ -429,6 +445,37 @@
   }
 }
 
+void testStrings() {
+  test(list) {
+    Uint16List uints = new Uint16List(list.length)..setAll(0, list);
+    String string = new String.fromCharCodes(list);
+    for (int i = 0; i < string.length; i++) {
+      for (int j = i; j < string.length; j++) {
+        int length = j - i;
+        {
+          Uint16List copy = new Uint16List(length);
+          copy.setRange(0, length, string.codeUnits, i);
+          Expect.listEquals(uints.sublist(i, j), copy);
+        }
+        {
+          Uint8List buffer = new Uint8List(length * 2 + 8);
+          Uint16List copy = new Uint16List.view(buffer.buffer, 4, length);
+          copy.setRange(0, length, string.codeUnits, i);
+          Expect.listEquals(uints.sublist(i, j), copy);
+        }
+        {
+          String copy = new String.fromCharCodes(uints, i, j);
+          Expect.equals(string.substring(i, j), copy);
+        }
+      }
+    }
+  }
+  test([]);
+  test([0x00, 0x7f, 0xff]);
+  test([0x00, 0xdfff, 0xffff]);
+  test([0xd800, 0xdc00, 0x20, 0xdbff, 0xdfff]);
+}
+
 main() {
   for (int i = 0; i < 20; i++) {
     testCreateUint8TypedData();
@@ -485,4 +532,6 @@
   testViewCreation();
   testWhere();
   testCreationFromList();
+  testStrings();
+  testSetRange();
 }
diff --git a/tests/standalone/vmservice/field_script.dart b/tests/standalone/vmservice/field_script.dart
deleted file mode 100644
index 5016941..0000000
--- a/tests/standalone/vmservice/field_script.dart
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library unknown_command_script;
-
-import 'dart:io';
-import 'dart:typed_data';
-
-class Banana {
-  final Float32List final_fixed_length_list = new Float32List(4);
-  Float32List fixed_length_list = new Float32List(4);
-  String name = '';
-  var a = 44;
-}
-
-
-class BadBanana {
-  final Float32List final_fixed_length_list;
-  final List fixed_length_array = new List(3);
-  num v;
-  final c = 4;
-  BadBanana() : final_fixed_length_list = new Float32List(1);
-  BadBanana.variable() : final_fixed_length_list = new Float32List(2);
-}
-
-main() {
-  for (int i = 0; i < 2000; i++) {
-    Banana b = new Banana();
-    b.name = 'Banana';
-    BadBanana bb = new BadBanana();
-    bb.v = 1.0;
-  }
-  var bb = new BadBanana.variable();
-  bb.v = 2.0;
-  var b = new Banana();
-  b.a = 'foo';
-  print(''); // Print blank line to signal that we are ready.
-  // Wait until signaled from spawning test.
-  stdin.first.then((_) => exit(0));
-}
diff --git a/tests/standalone/vmservice/isolate_bad_class_test.dart b/tests/standalone/vmservice/isolate_bad_class_test.dart
deleted file mode 100644
index e97ef7b..0000000
--- a/tests/standalone/vmservice/isolate_bad_class_test.dart
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library isolate_bad_class_test;
-
-import 'dart:async';
-import 'test_helper.dart';
-import 'package:expect/expect.dart';
-
-class NullCollectionTest extends VmServiceRequestHelper {
-  NullCollectionTest(port, id, collection) :
-      super('http://127.0.0.1:$port/$id/$collection/9999999');
-
-  onRequestCompleted(Map reply) {
-    Expect.equals('Error', reply['type']);
-  }
-}
-
-class BadCollectionTest extends VmServiceRequestHelper {
-  BadCollectionTest(port, id, collection) :
-      super('http://127.0.0.1:$port/$id/$collection');
-
-  onRequestCompleted(Map reply) {
-    Expect.equals('Error', reply['type']);
-  }
-}
-
-class VMTest extends VmServiceRequestHelper {
-  VMTest(port) : super('http://127.0.0.1:$port/vm');
-
-  String _isolateId;
-  onRequestCompleted(Map reply) {
-    VMTester tester = new VMTester(reply);
-    tester.checkIsolateCount(1);
-    _isolateId = tester.getIsolateId(0);
-  }
-}
-
-main() {
-  var process = new TestLauncher('unknown_isolate_command_script.dart');
-  process.launch().then((port) {
-    var test = new VMTest(port);
-    test.makeRequest().then((_) {
-      var badCollectionRequest =
-          new BadCollectionTest(port, test._isolateId,
-                                'foobar').makeRequest();
-      var nullCollectionRequest =
-          new NullCollectionTest(port, test._isolateId,
-                                 'classes').makeRequest();
-      var requests = Future.wait([badCollectionRequest, nullCollectionRequest]);
-      requests.then((_) {
-        process.requestExit();
-      });
-    });
-  });
-}
diff --git a/tests/standalone/vmservice/isolate_bad_object_test.dart b/tests/standalone/vmservice/isolate_bad_object_test.dart
deleted file mode 100644
index 3b399da..0000000
--- a/tests/standalone/vmservice/isolate_bad_object_test.dart
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library isolate_bad_code_test;
-
-import 'dart:async';
-import 'test_helper.dart';
-import 'package:expect/expect.dart';
-
-class ExpiredCollectionTest extends VmServiceRequestHelper {
-  ExpiredCollectionTest(port, id) :
-      super('http://127.0.0.1:$port/$id/objects/50');
-
-  onRequestCompleted(Map reply) {
-    Expect.equals('Sentinel', reply['type']);
-    Expect.equals('<expired>', reply['valueAsString']);
-  }
-}
-
-class BadCollectionTest extends VmServiceRequestHelper {
-  BadCollectionTest(port, id) :
-      super('http://127.0.0.1:$port/$id/objects');
-
-  onRequestCompleted(Map reply) {
-    Expect.equals('Error', reply['type']);
-  }
-}
-
-class VMTest extends VmServiceRequestHelper {
-  VMTest(port) : super('http://127.0.0.1:$port/vm');
-
-  String _isolateId;
-  onRequestCompleted(Map reply) {
-    VMTester tester = new VMTester(reply);
-    tester.checkIsolateCount(1);
-    _isolateId = tester.getIsolateId(0);
-  }
-}
-
-main() {
-  var process = new TestLauncher('unknown_isolate_command_script.dart');
-  process.launch().then((port) {
-    var test = new VMTest(port);
-    test.makeRequest().then((_) {
-      var badCollectionRequest =
-          new BadCollectionTest(port, test._isolateId).makeRequest();
-      var expiredCollectionRequest =
-          new ExpiredCollectionTest(port, test._isolateId).makeRequest();
-      var requests = Future.wait([badCollectionRequest,
-                                  expiredCollectionRequest]);
-      requests.then((_) {
-        process.requestExit();
-      });
-    });
-  });
-}
diff --git a/tests/standalone/vmservice/isolate_class_field_test.dart b/tests/standalone/vmservice/isolate_class_field_test.dart
deleted file mode 100644
index 3ea4466..0000000
--- a/tests/standalone/vmservice/isolate_class_field_test.dart
+++ /dev/null
@@ -1,180 +0,0 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library isolate_class_list_test;
-
-import 'dart:async';
-import 'test_helper.dart';
-import 'package:expect/expect.dart';
-
-class BananaClassTest {
-  int port;
-  String isolate_id;
-  String class_id;
-  BananaClassTest(this.port, this.isolate_id, this.class_id);
-
-  _testFieldA(Map field) {
-    Expect.equals('Field', field['type']);
-    Expect.equals('a', field['name']);
-    Expect.equals(false, field['final']);
-    Expect.equals(false, field['static']);
-    Expect.equals(false, field['const']);
-    Expect.equals('dynamic', field['guardClass']);
-    Expect.equals(true, field['guardNullable']);
-    Expect.equals('variable', field['guardLength']);
-  }
-
-  _testFieldFinalFixedLengthList(Map field) {
-    Expect.equals('Field', field['type']);
-    Expect.equals('final_fixed_length_list', field['name']);
-    Expect.equals('_Float32Array', field['guardClass']['name']);
-    Expect.equals(true, field['final']);
-    Expect.equals(false, field['static']);
-    Expect.equals(false, field['const']);
-    Expect.equals(4, field['guardLength']);
-  }
-
-  _testFieldFixedLengthList(Map field) {
-    Expect.equals('Field', field['type']);
-    Expect.equals('fixed_length_list', field['name']);
-    Expect.equals(false, field['final']);
-    Expect.equals(false, field['static']);
-    Expect.equals(false, field['const']);
-    Expect.equals('_Float32Array', field['guardClass']['name']);
-    Expect.equals('variable', field['guardLength']);
-  }
-
-  _testFieldName(Map field) {
-    Expect.equals('Field', field['type']);
-    Expect.equals('name', field['name']);
-    Expect.equals(false, field['final']);
-    Expect.equals(false, field['static']);
-    Expect.equals(false, field['const']);
-    Expect.equals('_OneByteString', field['guardClass']['name']);
-    Expect.equals(false, field['guardNullable']);
-    Expect.equals('variable', field['guardLength']);
-  }
-
-  Future makeRequest() {
-    var fields = ['final_fixed_length_list', 'fixed_length_list', 'name', 'a'];
-    var helper =
-      new ClassFieldRequestHelper(port, isolate_id, class_id, fields);
-    return helper.makeRequest().then((_) {
-      _testFieldA(helper.fields['a']);
-      _testFieldFinalFixedLengthList(helper.fields['final_fixed_length_list']);
-      _testFieldFixedLengthList(helper.fields['fixed_length_list']);
-      _testFieldName(helper.fields['name']);
-    });
-  }
-}
-
-class BadBananaClassTest {
-  int port;
-  String isolate_id;
-  String class_id;
-  BadBananaClassTest(this.port, this.isolate_id, this.class_id);
-
-  _testFieldV(Map field) {
-    Expect.equals('Field', field['type']);
-    Expect.equals('v', field['name']);
-    Expect.equals(false, field['final']);
-    Expect.equals(false, field['static']);
-    Expect.equals(false, field['const']);
-    Expect.equals('_Double', field['guardClass']['name']);
-    Expect.equals(true, field['guardNullable']);
-    Expect.equals('variable', field['guardLength']);
-  }
-
-  _testFieldC(Map field) {
-    Expect.equals('Field', field['type']);
-    Expect.equals('c', field['name']);
-    Expect.equals(true, field['final']);
-    Expect.equals(false, field['static']);
-    Expect.equals(true, field['final']);
-    Expect.equals('_Smi', field['guardClass']['name']);
-    Expect.equals(false, field['guardNullable']);
-    Expect.equals('variable', field['guardLength']);
-  }
-
-  _testFieldFinalFixedLengthList(Map field) {
-    Expect.equals('Field', field['type']);
-    Expect.equals('final_fixed_length_list', field['name']);
-    Expect.equals('_Float32Array', field['guardClass']['name']);
-    Expect.equals(true, field['final']);
-    Expect.equals(false, field['static']);
-    Expect.equals(false, field['const']);
-    Expect.equals('variable', field['guardLength']);
-  }
-
-  _testFieldFixedLengthArray(Map field) {
-    Expect.equals('Field', field['type']);
-    Expect.equals('fixed_length_array', field['name']);
-    Expect.equals('_List', field['guardClass']['name']);
-    Expect.equals(true, field['final']);
-    Expect.equals(false, field['static']);
-    Expect.equals(false, field['const']);
-    Expect.equals(3, field['guardLength']);
-  }
-
-  Future makeRequest() {
-    var fields = ['final_fixed_length_list', 'fixed_length_array', 'v', 'c'];
-    var helper =
-      new ClassFieldRequestHelper(port, isolate_id, class_id, fields);
-    return helper.makeRequest().then((_) {
-      _testFieldV(helper.fields['v']);
-      _testFieldC(helper.fields['c']);
-      _testFieldFinalFixedLengthList(helper.fields['final_fixed_length_list']);
-      _testFieldFixedLengthArray(helper.fields['fixed_length_array']);
-    });
-  }
-}
-
-class ClassTableTest extends VmServiceRequestHelper {
-  ClassTableTest(port, id) :
-      super('http://127.0.0.1:$port/$id/classes/');
-
-  String banana_class_id;
-  String bad_banana_class_id;
-
-  onRequestCompleted(Map reply) {
-    ClassTableHelper helper = new ClassTableHelper(reply);
-    Expect.isTrue(helper.classExists('Banana'));
-    banana_class_id = helper.classId('Banana');
-    Expect.isTrue(helper.classExists('BadBanana'));
-    bad_banana_class_id = helper.classId('BadBanana');
-  }
-}
-
-class VMTest extends VmServiceRequestHelper {
-  VMTest(port) : super('http://127.0.0.1:$port/vm');
-
-  String _isolateId;
-  onRequestCompleted(Map reply) {
-    VMTester tester = new VMTester(reply);
-    tester.checkIsolateCount(1);
-    _isolateId = tester.getIsolateId(0);
-  }
-}
-
-main() {
-  var process = new TestLauncher('field_script.dart');
-  process.launch().then((port) {
-    var test = new VMTest(port);
-    test.makeRequest().then((_) {
-      var classTableTest = new ClassTableTest(port, test._isolateId);
-      classTableTest.makeRequest().then((_) {
-        var bananaClassTest =
-            new BananaClassTest(port, test._isolateId,
-                                classTableTest.banana_class_id);
-        var badBananaClassTest =
-            new BadBananaClassTest(port, test._isolateId,
-                                   classTableTest.bad_banana_class_id);
-        Future.wait([bananaClassTest.makeRequest(),
-                     badBananaClassTest.makeRequest()]).then((_) {
-          process.requestExit();
-        });
-      });
-    });
-  });
-}
diff --git a/tests/standalone/vmservice/isolate_class_test.dart b/tests/standalone/vmservice/isolate_class_test.dart
deleted file mode 100644
index 6dec9d3..0000000
--- a/tests/standalone/vmservice/isolate_class_test.dart
+++ /dev/null
@@ -1,82 +0,0 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library isolate_class_test;
-
-import 'dart:async';
-import 'test_helper.dart';
-import 'package:expect/expect.dart';
-
-class ClassTest extends VmServiceRequestHelper {
-  ClassTest(port, id, classId) :
-      super('http://127.0.0.1:$port/$id/$classId');
-
-  onRequestCompleted(Map reply) {
-    Expect.equals('Class', reply['type']);
-    Expect.equals('C', reply['name']);
-    Expect.equals('isolate_stacktrace_command_script',
-                  reply['library']['name']);
-  }
-}
-
-class LibraryTest extends VmServiceRequestHelper {
-  LibraryTest(port, id, libId) :
-      super('http://127.0.0.1:$port/$id/$libId');
-
-  String _classId;
-  onRequestCompleted(Map reply) {
-    Expect.equals('Library', reply['type']);
-    Expect.equals('isolate_stacktrace_command_script', reply['name']);
-    Expect.equals(1, reply['classes'].length);
-    Expect.equals('@Class', reply['classes'][0]['type']);
-    Expect.equals('C', reply['classes'][0]['name']);
-    _classId = reply['classes'][0]['id'];
-  }
-}
-
-class IsolateSummaryTest extends VmServiceRequestHelper {
-  IsolateSummaryTest(port, id) :
-      super('http://127.0.0.1:$port/$id/');
-
-  String _libId;
-  onRequestCompleted(Map reply) {
-    Expect.equals('Isolate', reply['type']);
-    Expect.equals('isolate_stacktrace_command_script', reply['rootLib']['name']);
-    _libId = reply['rootLib']['id'];
-  }
-}
-
-class VMTest extends VmServiceRequestHelper {
-  VMTest(port) : super('http://127.0.0.1:$port/vm');
-
-  String _isolateId;
-  onRequestCompleted(Map reply) {
-    VMTester tester = new VMTester(reply);
-    tester.checkIsolateCount(2);
-    // TODO(turnidge): Fragile.  Relies on isolate order in response.
-    _isolateId = tester.getIsolateId(1);
-  }
-}
-
-main() {
-  var process = new TestLauncher('isolate_stacktrace_command_script.dart');
-  process.launch().then((port) {
-    var test = new VMTest(port);
-    test.makeRequest().then((_) {
-      var isolateSummaryTest =
-          new IsolateSummaryTest(port, test._isolateId);
-      isolateSummaryTest.makeRequest().then((_) {
-        var libraryTest = new LibraryTest(port, test._isolateId,
-                                          isolateSummaryTest._libId);
-        libraryTest.makeRequest().then((_) {
-          var classTest = new ClassTest(port, test._isolateId,
-                                        libraryTest._classId);
-          classTest.makeRequest().then((_) {
-            process.requestExit();
-          });
-        });
-      });
-    });
-  });
-}
diff --git a/tests/standalone/vmservice/isolate_code_test.dart b/tests/standalone/vmservice/isolate_code_test.dart
deleted file mode 100644
index 620f43b..0000000
--- a/tests/standalone/vmservice/isolate_code_test.dart
+++ /dev/null
@@ -1,81 +0,0 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library isolate_class_test;
-
-import 'dart:async';
-import 'test_helper.dart';
-import 'package:expect/expect.dart';
-
-class CodeATest extends VmServiceRequestHelper {
-  CodeATest(port, id, codeId) :
-      super('http://127.0.0.1:$port/$id/$codeId');
-
-  onRequestCompleted(Map reply) {
-    Expect.equals('Code', reply['type']);
-    Expect.equals('a', reply['function']['name']);
-    Expect.isTrue(reply['disassembly'].length > 0);
-  }
-}
-
-class CodeCTest extends VmServiceRequestHelper {
-  CodeCTest(port, id, codeId) :
-      super('http://127.0.0.1:$port/$id/$codeId');
-
-  onRequestCompleted(Map reply) {
-    Expect.equals('Code', reply['type']);
-    Expect.equals('c', reply['function']['name']);
-    Expect.isTrue(reply['disassembly'].length > 0);
-  }
-}
-
-class StackTraceTest extends VmServiceRequestHelper {
-  StackTraceTest(port, id) :
-      super('http://127.0.0.1:$port/$id/stacktrace');
-
-  String _aId;
-  String _cId;
-  onRequestCompleted(Map reply) {
-    Expect.equals('StackTrace', reply['type']);
-    List members = reply['members'];
-    Expect.equals('a', members[0]['function']['name']);
-    _aId = members[0]['code']['id'];
-    Expect.equals('c', members[2]['function']['name']);
-    _cId = members[2]['code']['id'];
-  }
-}
-
-class VMTest extends VmServiceRequestHelper {
-  VMTest(port) : super('http://127.0.0.1:$port/vm');
-
-  String _isolateId;
-  onRequestCompleted(Map reply) {
-    VMTester tester = new VMTester(reply);
-    tester.checkIsolateCount(2);
-    // TODO(turnidge): Fragile.  Relies on isolate order in response.
-    _isolateId = tester.getIsolateId(0);
-  }
-}
-
-main() {
-  var process = new TestLauncher('isolate_stacktrace_command_script.dart');
-  process.launch().then((port) {
-    var test = new VMTest(port);
-    test.makeRequest().then((_) {
-      var stackTraceTest =
-          new StackTraceTest(port, test._isolateId);
-      stackTraceTest.makeRequest().then((_) {
-        var codeATest = new CodeATest(port, test._isolateId,
-                                      stackTraceTest._aId);
-        var codeCTest = new CodeCTest(port, test._isolateId,
-                                      stackTraceTest._cId);
-        var requests = Future.wait([codeATest.makeRequest(),
-                                    codeCTest.makeRequest()]);
-        requests.then((_) {
-          process.requestExit();
-        });
-      });
-    });
-  });
-}
diff --git a/tests/standalone/vmservice/isolate_echo_script.dart b/tests/standalone/vmservice/isolate_echo_script.dart
deleted file mode 100644
index a727441..0000000
--- a/tests/standalone/vmservice/isolate_echo_script.dart
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library isolate_echo_script;
-
-import 'dart:io';
-
-main() {
-  print(''); // Print blank line to signal that we are ready.
-
-  // Wait until signaled from spawning test.
-  stdin.first.then((_) => exit(0));
-}
diff --git a/tests/standalone/vmservice/isolate_echo_test.dart b/tests/standalone/vmservice/isolate_echo_test.dart
deleted file mode 100644
index cf0f325..0000000
--- a/tests/standalone/vmservice/isolate_echo_test.dart
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library isolate_echo_test;
-
-import 'test_helper.dart';
-import 'package:expect/expect.dart';
-
-class EchoRequestTest extends VmServiceRequestHelper {
-  EchoRequestTest(port, id) :
-      super('http://127.0.0.1:$port/$id/_echo/foo/bar?a=b&k=&d=e&z=w');
-
-  onRequestCompleted(Map reply) {
-    Expect.equals('message', reply['type']);
-
-    Expect.equals(3, reply['request']['arguments'].length);
-    Expect.equals('_echo', reply['request']['arguments'][0]);
-    Expect.equals('foo', reply['request']['arguments'][1]);
-    Expect.equals('bar', reply['request']['arguments'][2]);
-
-    Expect.equals(4, reply['request']['option_keys'].length);
-    Expect.equals('a', reply['request']['option_keys'][0]);
-    Expect.equals('k', reply['request']['option_keys'][1]);
-    Expect.equals('d', reply['request']['option_keys'][2]);
-    Expect.equals('z', reply['request']['option_keys'][3]);
-
-    Expect.equals(4, reply['request']['option_values'].length);
-    Expect.equals('b', reply['request']['option_values'][0]);
-    Expect.equals('', reply['request']['option_values'][1]);
-    Expect.equals('e', reply['request']['option_values'][2]);
-    Expect.equals('w', reply['request']['option_values'][3]);
-  }
-}
-
-class VMTest extends VmServiceRequestHelper {
-  VMTest(port) : super('http://127.0.0.1:$port/vm');
-
-  String _isolateId;
-  onRequestCompleted(Map reply) {
-    VMTester tester = new VMTester(reply);
-    tester.checkIsolateCount(1);
-    _isolateId = tester.getIsolateId(0);
-  }
-}
-
-
-main() {
-  var process = new TestLauncher('isolate_echo_script.dart');
-  process.launch().then((port) {
-    var test = new VMTest(port);
-    test.makeRequest().then((_) {
-      var echoRequestTest = new EchoRequestTest(port, test._isolateId);
-      echoRequestTest.makeRequest().then((_) {
-        process.requestExit();
-      });
-    });
-  });
-}
diff --git a/tests/standalone/vmservice/isolate_function_test.dart b/tests/standalone/vmservice/isolate_function_test.dart
deleted file mode 100644
index 1531229..0000000
--- a/tests/standalone/vmservice/isolate_function_test.dart
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library isolate_class_test;
-
-import 'dart:async';
-import 'test_helper.dart';
-import 'package:expect/expect.dart';
-
-class MethodTest extends VmServiceRequestHelper {
-  MethodTest(port, id, functionId) :
-      super('http://127.0.0.1:$port/$id/$functionId');
-  onRequestCompleted(Map reply) {
-    Expect.equals('Function', reply['type']);
-    Expect.equals('c', reply['name']);
-    Expect.equals(false, reply['static']);
-  }
-}
-
-class FunctionTest extends VmServiceRequestHelper {
-  FunctionTest(port, id, functionId) :
-      super('http://127.0.0.1:$port/$id/$functionId');
-
-  onRequestCompleted(Map reply) {
-    Expect.equals('Function', reply['type']);
-    Expect.equals('a', reply['name']);
-    Expect.equals(true, reply['static']);
-  }
-}
-
-class StackTraceTest extends VmServiceRequestHelper {
-  StackTraceTest(port, id) :
-      super('http://127.0.0.1:$port/$id/stacktrace');
-
-  String _aId;
-  String _cId;
-  onRequestCompleted(Map reply) {
-    Expect.equals('StackTrace', reply['type']);
-    List members = reply['members'];
-    Expect.equals('a', members[0]['function']['name']);
-    _aId = members[0]['function']['id'];
-    Expect.equals('c', members[2]['function']['name']);
-    _cId = members[2]['function']['id'];
-  }
-}
-
-class VMTest extends VmServiceRequestHelper {
-  VMTest(port) : super('http://127.0.0.1:$port/vm');
-
-  String _isolateId;
-  onRequestCompleted(Map reply) {
-    VMTester tester = new VMTester(reply);
-    tester.checkIsolateCount(2);
-    // TODO(turnidge): Fragile.  Relies on isolate order in response.
-    _isolateId = tester.getIsolateId(0);
-  }
-}
-
-main() {
-  var process = new TestLauncher('isolate_stacktrace_command_script.dart');
-  process.launch().then((port) {
-    var test = new VMTest(port);
-    test.makeRequest().then((_) {
-      var stackTraceTest =
-          new StackTraceTest(port, test._isolateId);
-      stackTraceTest.makeRequest().then((_) {
-        var functionTest = new FunctionTest(port, test._isolateId,
-                                            stackTraceTest._aId);
-        functionTest.makeRequest().then((_) {
-          var methodTest = new MethodTest(port, test._isolateId,
-                                          stackTraceTest._cId);
-          methodTest.makeRequest().then((_) {
-            process.requestExit();
-          });
-        });
-      });
-    });
-  });
-}
diff --git a/tests/standalone/vmservice/isolate_library_test.dart b/tests/standalone/vmservice/isolate_library_test.dart
deleted file mode 100644
index 8ff4649..0000000
--- a/tests/standalone/vmservice/isolate_library_test.dart
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library isolate_library_test;
-
-import 'dart:async';
-import 'test_helper.dart';
-import 'package:expect/expect.dart';
-
-class LibraryTest extends VmServiceRequestHelper {
-  LibraryTest(port, id, libId) :
-      super('http://127.0.0.1:$port/$id/$libId');
-
-  onRequestCompleted(Map reply) {
-    Expect.equals('Library', reply['type']);
-    Expect.equals('isolate_stacktrace_command_script', reply['name']);
-  }
-}
-
-class IsolateSummaryTest extends VmServiceRequestHelper {
-  IsolateSummaryTest(port, id) :
-      super('http://127.0.0.1:$port/$id/');
-
-  String _libId;
-  onRequestCompleted(Map reply) {
-    Expect.equals('Isolate', reply['type']);
-    Expect.equals('isolate_stacktrace_command_script', reply['rootLib']['name']);
-    _libId = reply['rootLib']['id'];
-  }
-}
-
-class VMTest extends VmServiceRequestHelper {
-  VMTest(port) : super('http://127.0.0.1:$port/vm');
-
-  String _isolateId;
-  onRequestCompleted(Map reply) {
-    VMTester tester = new VMTester(reply);
-    tester.checkIsolateCount(2);
-    // TODO(turnidge): Fragile.  Relies on isolate order in response.
-    _isolateId = tester.getIsolateId(1);
-  }
-}
-
-main() {
-  var process = new TestLauncher('isolate_stacktrace_command_script.dart');
-  process.launch().then((port) {
-    var test = new VMTest(port);
-    test.makeRequest().then((_) {
-      var isolateSummaryTest =
-          new IsolateSummaryTest(port, test._isolateId);
-      isolateSummaryTest.makeRequest().then((_) {
-        var libraryTest = new LibraryTest(port, test._isolateId,
-                                          isolateSummaryTest._libId);
-        libraryTest.makeRequest().then((_) {
-          process.requestExit();
-        });
-      });
-    });
-  });
-}
diff --git a/tests/standalone/vmservice/isolate_list_script.dart b/tests/standalone/vmservice/isolate_list_script.dart
deleted file mode 100644
index a9cc79f..0000000
--- a/tests/standalone/vmservice/isolate_list_script.dart
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library isolate_list_script;
-
-import 'dart:io';
-
-main() {
-  print(''); // Print blank line to signal that we are ready.
-
-  // Wait until signaled from spawning test.
-  stdin.first.then((_) => exit(0));
-}
diff --git a/tests/standalone/vmservice/isolate_list_test.dart b/tests/standalone/vmservice/isolate_list_test.dart
deleted file mode 100644
index d432832..0000000
--- a/tests/standalone/vmservice/isolate_list_test.dart
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library isolate_list_test;
-
-import 'test_helper.dart';
-import 'package:expect/expect.dart';
-
-
-class VMTest extends VmServiceRequestHelper {
-  VMTest(port) : super('http://127.0.0.1:$port/vm');
-
-  onRequestCompleted(Map reply) {
-    VMTester tester = new VMTester(reply);
-    tester.checkIsolateCount(1);
-  }
-}
-
-
-main() {
-  var process = new TestLauncher('isolate_list_script.dart');
-  process.launch().then((port) {
-    var test = new VMTest(port);
-    test.makeRequest().then((_) {
-      process.requestExit();
-    });
-  });
-}
diff --git a/tests/standalone/vmservice/isolate_stacktrace_command_script.dart b/tests/standalone/vmservice/isolate_stacktrace_command_script.dart
deleted file mode 100644
index 6524ce5..0000000
--- a/tests/standalone/vmservice/isolate_stacktrace_command_script.dart
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library isolate_stacktrace_command_script;
-
-import 'dart:io';
-import 'dart:isolate';
-
-void a() {
-  int x = 0;
-  print(''); // Print blank line to signal that we are ready.
-  while (true) {
-    x &= x;
-  }
-}
-
-void b() {
-  a();
-}
-
-class C {
-  c() {
-    b();
-  }
-}
-
-void myIsolateName(_) {
-  new C().c();
-}
-
-main() {
-  Isolate.spawn(myIsolateName, null);
-  // Wait until signaled from spawning test.
-  stdin.first.then((_) => exit(0));
-}
diff --git a/tests/standalone/vmservice/isolate_stacktrace_command_test.dart b/tests/standalone/vmservice/isolate_stacktrace_command_test.dart
deleted file mode 100644
index f76b280..0000000
--- a/tests/standalone/vmservice/isolate_stacktrace_command_test.dart
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library isolate_stacktrace_command_test;
-
-import 'test_helper.dart';
-import 'package:expect/expect.dart';
-
-class StacktraceTest extends VmServiceRequestHelper {
-  StacktraceTest(port, id) :
-      super('http://127.0.0.1:$port/$id/stacktrace');
-
-  onRequestCompleted(Map reply) {
-    Expect.equals('StackTrace', reply['type'], 'Not a StackTrace message.');
-    Expect.isTrue(4 <= reply['members'].length, 'Stacktrace is wrong length.');
-    // The number of frames involved in isolate message dispatch is an
-    // implementation detail. Only check that we got all the frames for user
-    // code.
-    Expect.equals('a', reply['members'][0]['function']['name']);
-    Expect.equals('b', reply['members'][1]['function']['name']);
-    Expect.equals('c', reply['members'][2]['function']['name']);
-    Expect.equals('myIsolateName', reply['members'][3]['function']['name']);
-  }
-}
-
-class VMTest extends VmServiceRequestHelper {
-  VMTest(port) : super('http://127.0.0.1:$port/vm');
-
-  String _isolateId;
-  onRequestCompleted(Map reply) {
-    VMTester tester = new VMTester(reply);
-    tester.checkIsolateCount(2);
-    // TODO(turnidge): Fragile.  Relies on isolate order in response.
-    _isolateId = tester.getIsolateId(0);
-  }
-}
-
-
-main() {
-  var process = new TestLauncher('isolate_stacktrace_command_script.dart');
-  process.launch().then((port) {
-    var test = new VMTest(port);
-    test.makeRequest().then((_) {
-      var stacktraceTest = new StacktraceTest(port, test._isolateId);
-      stacktraceTest.makeRequest().then((_) {
-        process.requestExit();
-      });
-    });
-  });
-}
diff --git a/tests/standalone/vmservice/multiple_isolate_list_script.dart b/tests/standalone/vmservice/multiple_isolate_list_script.dart
deleted file mode 100644
index fd83cc5..0000000
--- a/tests/standalone/vmservice/multiple_isolate_list_script.dart
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library multiple_isolate_list_script;
-
-import 'dart:io';
-import 'dart:isolate';
-
-void isolateMain1(_) {
-  // Spawn another isolate.
-  Isolate.spawn(myIsolateName, null);
-}
-
-void myIsolateName(_) {
-  // Stay running.
-  new ReceivePort().first.then((a) { });
-  print(''); // Print blank line to signal that we are ready.
-}
-
-main() {
-  Isolate.spawn(isolateMain1, null);
-  // Wait until signaled from spawning test.
-  stdin.first.then((_) => exit(0));
-}
diff --git a/tests/standalone/vmservice/multiple_isolate_list_test.dart b/tests/standalone/vmservice/multiple_isolate_list_test.dart
deleted file mode 100644
index 017d562..0000000
--- a/tests/standalone/vmservice/multiple_isolate_list_test.dart
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library multiple_isolate_list_test;
-
-import 'test_helper.dart';
-import 'package:expect/expect.dart';
-
-class MultipleIsolateListTest extends VmServiceRequestHelper {
-  MultipleIsolateListTest(port) : super('http://127.0.0.1:$port/vm');
-
-  onRequestCompleted(Map reply) {
-    VMTester tester = new VMTester(reply);
-    tester.checkIsolateCount(2);
-  }
-}
-
-main() {
-  var process = new TestLauncher('multiple_isolate_list_script.dart');
-  process.launch().then((port) {
-    var test = new MultipleIsolateListTest(port);
-    test.makeRequest().then((_) {
-      process.requestExit();
-    });
-  });
-}
diff --git a/tests/standalone/vmservice/test_helper.dart b/tests/standalone/vmservice/test_helper.dart
deleted file mode 100644
index 0d98bfb..0000000
--- a/tests/standalone/vmservice/test_helper.dart
+++ /dev/null
@@ -1,275 +0,0 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library vmservice_test_helper;
-
-import 'dart:async';
-import 'dart:convert';
-import 'dart:io';
-import 'package:expect/expect.dart';
-
-abstract class ServiceWebSocketRequestHelper {
-  final String url;
-  final Completer _completer = new Completer();
-  WebSocket _socket;
-
-  ServiceWebSocketRequestHelper(this.url);
-
-  // Returns [this] when connected.
-  Future connect() {
-    return WebSocket.connect(url).then((ws) {
-      _socket = ws;
-      _socket.listen((message) {
-        var map = JSON.decode(message);
-        var response = JSON.decode(map['response']);
-        onResponse(map['seq'], response);
-      });
-      return this;
-    });
-  }
-
-  void complete() {
-    _completer.complete(this);
-  }
-
-  Future get completed => _completer.future;
-
-  // Must call complete.
-  void onResponse(var seq, Map response);
-  void runTest();
-
-  Future sendMessage(var seq, String request) {
-    var map = {
-      'seq': seq,
-      'request': request
-    };
-    var message = JSON.encode(map);
-    _socket.add(message);
-    return _completer.future;
-  }
-}
-
-abstract class VmServiceRequestHelper {
-  final Uri uri;
-  final HttpClient client;
-
-  VmServiceRequestHelper(String url) :
-      uri = Uri.parse(url),
-      client = new HttpClient();
-
-  Future makeRequest() {
-    print('** GET: $uri');
-    return client.getUrl(uri)
-      .then((HttpClientRequest request) => request.close())
-      .then((HttpClientResponse response) {
-        return response
-            .fold(new BytesBuilder(), (b, d) => b..add(d))
-            .then((builder) {
-              return _requestCompleted(builder.takeBytes(), response);
-            });
-      }).catchError((error) {
-        onRequestFailed(error);
-      });
-  }
-
-  Future _requestCompleted(List<int> data, HttpClientResponse response) {
-    Expect.equals(200, response.statusCode, 'Invalid HTTP Status Code');
-    var replyAsString;
-    try {
-      replyAsString = UTF8.decode(data);
-    } catch (e) {
-      onRequestFailed(e);
-      return null;
-    }
-    print('** Response: $replyAsString');
-    var reply;
-    try {
-      reply = JSON.decode(replyAsString);
-    } catch (e, trace) {
-      onRequestFailed(e);
-      return null;
-    }
-    if (reply is! Map) {
-      onRequestFailed('Reply was not a map: $reply');
-      return null;
-    }
-    if (reply['type'] == null) {
-      onRequestFailed('Reply does not contain a type key: $reply');
-      return null;
-    }
-    var r;
-    try {
-      r = onRequestCompleted(reply);
-    } catch (e) {
-      r = onRequestFailed('Test callback failed: $e');
-    }
-    return r;
-  }
-
-  Future onRequestFailed(dynamic error) {
-    Expect.fail('Failed to make request: $error');
-  }
-
-  Future onRequestCompleted(Map response);
-}
-
-class TestLauncher {
-  final String script;
-  Process process;
-
-  TestLauncher(this.script);
-
-  String get scriptPath {
-    var dartScript = Platform.script.toFilePath();
-    var splitPoint = dartScript.lastIndexOf(Platform.pathSeparator);
-    var scriptDirectory = dartScript.substring(0, splitPoint);
-    return scriptDirectory + Platform.pathSeparator + script;
-  }
-
-  Future<int> launch() {
-    String dartExecutable = Platform.executable;
-    print('** Launching $scriptPath');
-    return Process.start(dartExecutable,
-                         ['--enable-vm-service:0', scriptPath]).then((p) {
-
-      Completer completer = new Completer();
-      process = p;
-      var portNumber;
-      var blank;
-      var first = true;
-      process.stdout.transform(UTF8.decoder)
-                    .transform(new LineSplitter()).listen((line) {
-        if (line.startsWith('Observatory listening on http://')) {
-          RegExp portExp = new RegExp(r"\d+.\d+.\d+.\d+:(\d+)");
-          var port = portExp.firstMatch(line).group(1);
-          portNumber = int.parse(port);
-        }
-        if (line == '') {
-          // Received blank line.
-          blank = true;
-        }
-        if (portNumber != null && blank == true && first == true) {
-          completer.complete(portNumber);
-          // Stop repeat completions.
-          first = false;
-          print('** Signaled to run test queries on $portNumber');
-        }
-        print(line);
-      });
-      process.stderr.transform(UTF8.decoder)
-                    .transform(new LineSplitter()).listen((line) {
-        print(line);
-      });
-      process.exitCode.then((code) {
-        Expect.equals(0, code, 'Launched dart executable exited with error.');
-      });
-      return completer.future;
-    });
-  }
-
-  void requestExit() {
-    print('** Requesting script to exit.');
-    process.stdin.add([32, 13, 10]);
-  }
-}
-
-class VMTester {
-  final Map vm;
-
-  VMTester(this.vm) {
-    // The reply is a VM.
-    Expect.equals('VM', vm['type'], 'Not an VM.');
-  }
-
-  void checkIsolateCount(int n) {
-    Expect.equals(n, vm['isolates'].length, 'Isolate count not $n');
-  }
-
-  void checkIsolateIdExists(String id) {
-    var exists = false;
-    vm['isolates'].forEach((isolate) {
-      if (isolate['id'] == id) {
-        exists = true;
-      }
-    });
-    Expect.isTrue(exists, 'No isolate with id: $id');
-  }
-
-  String getIsolateId(int index) {
-    return vm['isolates'][index]['id'];
-  }
-}
-
-class ClassTableHelper {
-  final Map classTable;
-
-  ClassTableHelper(this.classTable) {
-    Expect.equals('ClassList', classTable['type'], 'Not a ClassTable.');
-  }
-
-  bool classExists(String name) {
-    List members = classTable['members'];
-    for (var i = 0; i < members.length; i++) {
-      Map klass = members[i];
-      if (klass['name'] == name) {
-        return true;
-      }
-    }
-    return false;
-  }
-
-  String classId(String name) {
-    List members = classTable['members'];
-    for (var i = 0; i < members.length; i++) {
-      Map klass = members[i];
-      if (klass['name'] == name) {
-        return klass['id'];
-      }
-    }
-    return null;
-  }
-}
-
-class FieldRequestHelper extends VmServiceRequestHelper {
-  FieldRequestHelper(port, isolate_id, field_id) :
-      super('http://127.0.0.1:$port/$isolate_id/$field_id');
-  Map field;
-  onRequestCompleted(Map reply) {
-    Expect.equals('Field', reply['type']);
-    field = reply;
-    return new Future.value(this);
-  }
-}
-
-class ClassFieldRequestHelper extends VmServiceRequestHelper {
-  final List<String> fieldNames;
-  int port_;
-  String isolate_id_;
-  ClassFieldRequestHelper(port, isolate_id, class_id, this.fieldNames) :
-      super('http://127.0.0.1:$port/$isolate_id/$class_id') {
-    port_ = port;
-    isolate_id_ = isolate_id;
-  }
-  final Map<String, Map> fields = new Map<String, Map>();
-
-  onRequestCompleted(Map reply) {
-    Expect.equals('Class', reply['type']);
-    List<Map> class_fields = reply['fields'];
-    List<Future> requests = new List<Future>();
-    fieldNames.forEach((fn) {
-      class_fields.forEach((f) {
-        if (f['name'] == fn) {
-          var request = new FieldRequestHelper(port_, isolate_id_, f['id']);
-          requests.add(request.makeRequest());
-        }
-      });
-    });
-    return Future.wait(requests).then((a) {
-      a.forEach((FieldRequestHelper field) {
-        fields[field.field['name']] = field.field;
-      });
-      return this;
-    });
-  }
-}
diff --git a/tests/standalone/vmservice/unknown_command_script.dart b/tests/standalone/vmservice/unknown_command_script.dart
deleted file mode 100644
index 7751c89..0000000
--- a/tests/standalone/vmservice/unknown_command_script.dart
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library unknown_command_script;
-
-import 'dart:io';
-
-main() {
-  print(''); // Print blank line to signal that we are ready.
-
-  // Wait until signaled from spawning test.
-  stdin.first.then((_) => exit(0));
-}
diff --git a/tests/standalone/vmservice/unknown_command_test.dart b/tests/standalone/vmservice/unknown_command_test.dart
deleted file mode 100644
index 1c503a6..0000000
--- a/tests/standalone/vmservice/unknown_command_test.dart
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library unknown_command_test;
-
-import 'test_helper.dart';
-import 'package:expect/expect.dart';
-
-class UnknownCommandTest extends VmServiceRequestHelper {
-  UnknownCommandTest(port) : super('http://127.0.0.1:$port/badcommand');
-
-  onRequestCompleted(Map reply) {
-    Expect.equals('Error', reply['type']);
-  }
-}
-
-main() {
-  var process = new TestLauncher('unknown_command_script.dart');
-  process.launch().then((port) {
-    var test = new UnknownCommandTest(port);
-    test.makeRequest().then((_) {
-      process.requestExit();
-    });
-  });
-}
diff --git a/tests/standalone/vmservice/unknown_isolate_command_script.dart b/tests/standalone/vmservice/unknown_isolate_command_script.dart
deleted file mode 100644
index e5870d3..0000000
--- a/tests/standalone/vmservice/unknown_isolate_command_script.dart
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library unknown_isolate_command_script;
-
-import 'dart:io';
-
-main() {
-  print(''); // Print blank line to signal that we are ready.
-
-  // Wait until signaled from spawning test.
-  stdin.first.then((_) => exit(0));
-}
diff --git a/tests/standalone/vmservice/unknown_isolate_command_test.dart b/tests/standalone/vmservice/unknown_isolate_command_test.dart
deleted file mode 100644
index c1c16f2..0000000
--- a/tests/standalone/vmservice/unknown_isolate_command_test.dart
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library isolate_class_table_test;
-
-import 'dart:async';
-import 'test_helper.dart';
-import 'package:expect/expect.dart';
-
-class ClassTableTest extends VmServiceRequestHelper {
-  ClassTableTest(port, id) :
-      super('http://127.0.0.1:$port/$id/classes');
-
-  onRequestCompleted(Map reply) {
-    ClassTableHelper helper = new ClassTableHelper(reply);
-  }
-}
-
-class VMTest extends VmServiceRequestHelper {
-  VMTest(port) : super('http://127.0.0.1:$port/vm');
-
-  String _isolateId;
-  onRequestCompleted(Map reply) {
-    VMTester tester = new VMTester(reply);
-    tester.checkIsolateCount(1);
-    _isolateId = tester.getIsolateId(0);
-  }
-}
-
-main() {
-  var process = new TestLauncher('field_script.dart');
-  process.launch().then((port) {
-    var test = new VMTest(port);
-    test.makeRequest().then((_) {
-      var classTableTest = new ClassTableTest(port, test._isolateId);
-      classTableTest.makeRequest().then((_) {
-        process.requestExit();
-      });
-    });
-  });
-}
diff --git a/tests/standalone/vmservice/websocket_client_test.dart b/tests/standalone/vmservice/websocket_client_test.dart
deleted file mode 100644
index 25b94ae..0000000
--- a/tests/standalone/vmservice/websocket_client_test.dart
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library unknown_command_test;
-
-import 'test_helper.dart';
-import 'package:expect/expect.dart';
-
-class ClientsRequestTest extends ServiceWebSocketRequestHelper {
-  ClientsRequestTest(port) : super('ws://127.0.0.1:$port/ws');
-  int _count = 0;
-
-  onResponse(var seq, Map response) {
-    if (seq == null) {
-      // Ignore push events.
-      return;
-    }
-    if (seq == 'cli') {
-      // Verify response is correct for 'cli' sequence id.
-      Expect.equals('ClientList', response['type']);
-      Expect.equals(1, response['members'].length);
-      _count++;
-    } else if (seq == 'vm') {
-      // Verify response is correct for 'vm' sequence id.
-      Expect.equals('VM', response['type']);
-      _count++;
-    } else {
-      Expect.fail('Unexpected response from $seq: $response');
-    }
-    if (_count == 2) {
-      // After receiving both responses, the test is complete.
-      complete();
-    }
-  }
-
-  runTest() {
-    // Send a request for clients with 'cli' sequence id.
-    sendMessage('cli', 'clients');
-    // Send a request for vm info with 'vm' sequence id.
-    sendMessage('vm', 'vm');
-  }
-}
-
-main() {
-  var process = new TestLauncher('unknown_command_script.dart');
-  process.launch().then((port) {
-    new ClientsRequestTest(port).connect().then((test) {
-      test.completed.then((_) {
-        process.requestExit();
-      });
-      test.runTest();
-    });
-  });
-}
diff --git a/tests/utils/dummy_compiler_test.dart b/tests/utils/dummy_compiler_test.dart
index cf57337..43a79c5 100644
--- a/tests/utils/dummy_compiler_test.dart
+++ b/tests/utils/dummy_compiler_test.dart
@@ -25,6 +25,8 @@
     return buildLibrarySource(DEFAULT_JS_HELPER_LIBRARY);
   } else if (uri.path.endsWith('isolate_helper.dart')) {
     return buildLibrarySource(DEFAULT_ISOLATE_HELPER_LIBRARY);
+  } else if (uri.path.endsWith('/async.dart')) {
+    return buildLibrarySource(DEFAULT_ASYNC_LIBRARY);
   } else {
     return "library lib${uri.path.replaceAll('/', '.')};";
   }
diff --git a/tools/VERSION b/tools/VERSION
index 0c4601a..b1ada01 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 1
 MINOR 9
 PATCH 0
-PRERELEASE 5
-PRERELEASE_PATCH 1
+PRERELEASE 6
+PRERELEASE_PATCH 0
diff --git a/tools/dartium/update_deps.py b/tools/dartium/update_deps.py
index 5dd1c84..742a114 100755
--- a/tools/dartium/update_deps.py
+++ b/tools/dartium/update_deps.py
@@ -40,7 +40,7 @@
 # Repositories to auto-update
 ########################################################################
 
-BRANCH_CURRENT="dart/dartium"
+BRANCH_CURRENT="dart/2125"
 BRANCH_NEXT="dart/dartium"
 BRANCH_MULTIVM="dart/multivm"
 
@@ -48,13 +48,15 @@
   'dartium': (
     'https://dart.googlecode.com/svn/branches/bleeding_edge/deps/dartium.deps',
     'dartium',
+    # TODO(vsm): 'chromium' will move to git
     ['webkit', 'chromium'],
     BRANCH_CURRENT,
     ),
   'integration': (
     'https://dart.googlecode.com/svn/branches/dartium_integration/deps/dartium.deps',
     'dartium',
-    ['webkit', 'chromium'],
+    # TODO(vsm): Reenable 'chromium'
+    ['webkit'],
     BRANCH_NEXT,
     ),
   'clank': (
diff --git a/tools/dom/scripts/htmlrenamer.py b/tools/dom/scripts/htmlrenamer.py
index f54b816..92aa17e 100644
--- a/tools/dom/scripts/htmlrenamer.py
+++ b/tools/dom/scripts/htmlrenamer.py
@@ -380,6 +380,13 @@
   'Window.getComputedStyle',
   'Window.clearInterval',
   'Window.clearTimeout',
+  # TODO(tll): These have been converted from int to double in Chrome 39 for
+  #            subpixel precision.  Special case for backward compatibility.
+  'Window.scrollX',
+  'Window.scrollY',
+  'Window.pageXOffset',
+  'Window.pageYOffset',
+
   'WindowTimers.clearInterval',
   'WindowTimers.clearTimeout',
   'WindowTimers.setInterval',
diff --git a/tools/dom/src/CssClassSet.dart b/tools/dom/src/CssClassSet.dart
index c948819..0b22ef7 100644
--- a/tools/dom/src/CssClassSet.dart
+++ b/tools/dom/src/CssClassSet.dart
@@ -96,12 +96,13 @@
 
   Set<String> readClasses() {
     var s = new LinkedHashSet<String>();
-    _elementCssClassSetIterable.forEach((e) => s.addAll(e.readClasses()));
+    _elementCssClassSetIterable.forEach(
+        (_ElementCssClassSet e) => s.addAll(e.readClasses()));
     return s;
   }
 
   void writeClasses(Set<String> s) {
-    var classes = new List.from(s).join(' ');
+    var classes = s.join(' ');
     for (Element e in _elementIterable) {
       e.className = classes;
     }
@@ -117,7 +118,7 @@
    *       className property of this element.
    */
   modify( f(Set<String> s)) {
-    _elementCssClassSetIterable.forEach((e) => e.modify(f));
+    _elementCssClassSetIterable.forEach((_ElementCssClassSet e) => e.modify(f));
   }
 
   /**
@@ -125,7 +126,9 @@
    * is.
    */
   bool toggle(String value, [bool shouldAdd]) =>
-      _modifyWithReturnValue((e) => e.toggle(value, shouldAdd));
+      _elementCssClassSetIterable.fold(false,
+          (bool changed, _ElementCssClassSet e) =>
+              e.toggle(value, shouldAdd) || changed);
 
   /**
    * Remove the class [value] from element, and return true on successful
@@ -134,10 +137,8 @@
    * This is the Dart equivalent of jQuery's
    * [removeClass](http://api.jquery.com/removeClass/).
    */
-  bool remove(Object value) => _modifyWithReturnValue((e) => e.remove(value));
-
-  bool _modifyWithReturnValue(f) => _elementCssClassSetIterable.fold(
-      false, (prevValue, element) => f(element) || prevValue);
+  bool remove(Object value) => _elementCssClassSetIterable.fold(false,
+      (bool changed, _ElementCssClassSet e) => e.remove(value) || changed);
 }
 
 class _ElementCssClassSet extends CssClassSetImpl {
@@ -160,7 +161,6 @@
   }
 
   void writeClasses(Set<String> s) {
-    List list = new List.from(s);
     _element.className = s.join(' ');
   }
 }
diff --git a/tools/dom/templates/html/impl/impl_Element.darttemplate b/tools/dom/templates/html/impl/impl_Element.darttemplate
index 0fe41b0..f263b29 100644
--- a/tools/dom/templates/html/impl/impl_Element.darttemplate
+++ b/tools/dom/templates/html/impl/impl_Element.darttemplate
@@ -297,6 +297,12 @@
       new _CssStyleDeclarationSet(this);
 
   void set classes(Iterable<String> value) {
+    // TODO(sra): This might be faster for Sets:
+    //
+    //     new _MultiElementCssClassSet(this).writeClasses(value)
+    //
+    // as the code below converts the Iterable[value] to a string multiple
+    // times.  Maybe compute the string and set className here.
     _nodeList.forEach((e) => e.classes = value);
   }
 
@@ -623,6 +629,8 @@
   CssClassSet get classes => new _ElementCssClassSet(this);
 
   void set classes(Iterable<String> value) {
+    // TODO(sra): Do this without reading the classes in clear() and addAll(),
+    // or writing the classes in clear().
     CssClassSet classSet = classes;
     classSet.clear();
     classSet.addAll(value);
diff --git a/tools/dom/templates/html/impl/impl_Window.darttemplate b/tools/dom/templates/html/impl/impl_Window.darttemplate
index 6b846f0..1c88777 100644
--- a/tools/dom/templates/html/impl/impl_Window.darttemplate
+++ b/tools/dom/templates/html/impl/impl_Window.darttemplate
@@ -254,6 +254,14 @@
   }
 
 $if DART2JS
+  @DomName('Window.pageXOffset')
+  @DocsEditable()
+  int get pageXOffset => JS('num', '#.pageXOffset', this).round();
+
+  @DomName('Window.pageYOffset')
+  @DocsEditable()
+  int get pageYOffset => JS('num', '#.pageYOffset', this).round();
+
   /**
    * The distance this window has been scrolled horizontally.
    *
@@ -264,8 +272,11 @@
    * * [scrollX]
    * (https://developer.mozilla.org/en-US/docs/Web/API/Window.scrollX) from MDN.
    */
-  int get scrollX => JS('bool', '("scrollX" in #)', this) ? JS('int',
-      '#.scrollX', this) : document.documentElement.scrollLeft;
+  @DomName('Window.scrollX')
+  @DocsEditable()
+  int get scrollX => JS('bool', '("scrollX" in #)', this) ?
+      JS('num', '#.scrollX', this).round() :
+      document.documentElement.scrollLeft;
 
   /**
    * The distance this window has been scrolled vertically.
@@ -277,8 +288,27 @@
    * * [scrollY]
    * (https://developer.mozilla.org/en-US/docs/Web/API/Window.scrollY) from MDN.
    */
-  int get scrollY => JS('bool', '("scrollY" in #)', this) ? JS('int',
-      '#.scrollY', this) : document.documentElement.scrollTop;
+  @DomName('Window.scrollY')
+  @DocsEditable()
+  int get scrollY => JS('bool', '("scrollY" in #)', this) ?
+      JS('num', '#.scrollY', this).round() :
+      document.documentElement.scrollTop;
+$else
+  @DomName('Window.pageXOffset')
+  @DocsEditable()
+  int get pageXOffset => _blink.BlinkWindow.instance.pageXOffset_Getter_(this).round();
+
+  @DomName('Window.pageYOffset')
+  @DocsEditable()
+  int get pageYOffset => _blink.BlinkWindow.instance.pageYOffset_Getter_(this).round();
+
+  @DomName('Window.scrollX')
+  @DocsEditable()
+  int get scrollX => _blink.BlinkWindow.instance.scrollX_Getter_(this).round();
+
+  @DomName('Window.scrollY')
+  @DocsEditable()
+  int get scrollY => _blink.BlinkWindow.instance.scrollY_Getter_(this).round();
 $endif
 }
 
diff --git a/tools/dom/templates/html/impl/impl_XMLHttpRequest.darttemplate b/tools/dom/templates/html/impl/impl_XMLHttpRequest.darttemplate
index 96cfca9..1994ff8 100644
--- a/tools/dom/templates/html/impl/impl_XMLHttpRequest.darttemplate
+++ b/tools/dom/templates/html/impl/impl_XMLHttpRequest.darttemplate
@@ -80,7 +80,7 @@
   static Future<String> getString(String url,
       {bool withCredentials, void onProgress(ProgressEvent e)}) {
     return request(url, withCredentials: withCredentials,
-        onProgress: onProgress).then((xhr) => xhr.responseText);
+        onProgress: onProgress).then((HttpRequest xhr) => xhr.responseText);
   }
 
   /**
diff --git a/tools/make_version.py b/tools/make_version.py
index 925e3a6..cf96fe2 100644
--- a/tools/make_version.py
+++ b/tools/make_version.py
@@ -35,8 +35,8 @@
   'symbols.cc',
 ]
 
-def makeVersionString(quiet):
-  version_string = utils.GetVersion()
+def makeVersionString(quiet, no_svn):
+  version_string = utils.GetSemanticSDKVersion(ignore_svn_revision=no_svn)
   if not quiet:
     debugLog("Returning version string: %s " % version_string)
   return version_string
@@ -51,9 +51,9 @@
   return vmhash.hexdigest()
 
 
-def makeFile(quiet, output_file, input_file):
+def makeFile(quiet, output_file, input_file, ignore_svn_revision):
   version_cc_text = open(input_file).read()
-  version_string = makeVersionString(quiet)
+  version_string = makeVersionString(quiet, ignore_svn_revision)
   version_cc_text = version_cc_text.replace("{{VERSION_STR}}",
                                             version_string)
   version_time = time.ctime(time.time())
@@ -73,6 +73,9 @@
     parser.add_option("-q", "--quiet",
                       action="store_true", default=False,
                       help="disable console output")
+    parser.add_option("--ignore_svn_revision",
+                      action="store_true", default=False,
+                      help="Don't try to determine svn revision")
     parser.add_option("--output",
                       action="store", type="string",
                       help="output file name")
@@ -92,7 +95,8 @@
     for arg in args:
       files.append(arg)
 
-    if not makeFile(options.quiet, options.output, options.input):
+    if not makeFile(options.quiet, options.output, options.input,
+                    options.ignore_svn_revision):
       return -1
 
     return 0
diff --git a/tools/testing/dart/browser_controller.dart b/tools/testing/dart/browser_controller.dart
index 9673071..2412d07 100644
--- a/tools/testing/dart/browser_controller.dart
+++ b/tools/testing/dart/browser_controller.dart
@@ -1154,7 +1154,9 @@
     // running for longer than RESTART_BROWSER_INTERVAL. The tests have
     // had flaky timeouts, and this may help.
     if ((browserName == 'ContentShellOnAndroid' ||
-         browserName == 'DartiumOnAndroid' ) &&
+         browserName == 'DartiumOnAndroid' ||
+         browserName == 'ie10' ||
+         browserName == 'ie11') &&
         status.timeSinceRestart.elapsed > RESTART_BROWSER_INTERVAL) {
       var id = status.browser.id;
       // Reset stopwatch so we don't trigger again before restarting.
diff --git a/tools/testing/dart/test_suite.dart b/tools/testing/dart/test_suite.dart
index bf79c8e..b29c3f0 100644
--- a/tools/testing/dart/test_suite.dart
+++ b/tools/testing/dart/test_suite.dart
@@ -131,9 +131,12 @@
   Map<String, String> _environmentOverrides;
 
   TestSuite(this.configuration, this.suiteName) {
-    _environmentOverrides = {
-        'DART_CONFIGURATION' : TestUtils.configurationDir(configuration)
-    };
+    TestUtils.buildDir(configuration);  // Sets configuration_directory.
+    if (configuration['configuration_directory'] != null) {
+      _environmentOverrides = {
+        'DART_CONFIGURATION' : configuration['configuration_directory']
+      };
+    }
   }
 
   Map<String, String> get environmentOverrides => _environmentOverrides;
@@ -2258,18 +2261,26 @@
     // is relative to the current working directory.
     // Thus, if we pass in an absolute path (e.g. '--build-directory=/tmp/out')
     // we get into trouble.
-    if (configuration['build_directory'] != '') {
-      return configuration['build_directory'];
+    if (configuration['build_directory'] == '') {
+      configuration['configuration_directory'] =
+          configurationDir(configuration);
+      configuration['build_directory'] =
+          outputDir(configuration) + configuration['configuration_directory'];
     }
-
-    return "${outputDir(configuration)}${configurationDir(configuration)}";
+    return configuration['build_directory'];
   }
 
-  static getValidOutputDir(Map configuration, String mode, String arch) {
+  static String configurationDir(Map configuration) {
+    // This returns the correct configuration directory (the last component
+    // of the output directory path) for regular dart checkouts.
+    // Dartium checkouts use the --build-directory option to pass in the
+    // correct build directory explicitly.
     // We allow our code to have been cross compiled, i.e., that there
     // is an X in front of the arch. We don't allow both a cross compiled
     // and a normal version to be present (except if you specifically pass
     // in the build_directory).
+    var mode = (configuration['mode'] == 'debug') ? 'Debug' : 'Release';
+    var arch = configuration['arch'].toUpperCase();
     var normal = '$mode$arch';
     var cross = '${mode}X$arch';
     var outDir = outputDir(configuration);
@@ -2285,20 +2296,6 @@
     return normal;
   }
 
-  static String configurationDir(Map configuration) {
-    // For regular dart checkouts, the configDir by default is mode+arch.
-    // For Dartium, the configDir by default is mode (as defined by the Chrome
-    // build setup). We can detect this because in the dartium checkout, the
-    // "output" directory is a sibling of the dart directory instead of a child.
-    var mode = (configuration['mode'] == 'debug') ? 'Debug' : 'Release';
-    var arch = configuration['arch'].toUpperCase();
-    if (currentWorkingDirectory != dartDir) {
-      return getValidOutputDir(configuration, mode, arch);
-    } else {
-      return mode;
-    }
-  }
-
   /**
    * Returns the path to the dart binary checked into the repo, used for
    * bootstrapping test.dart.
diff --git a/tools/utils.py b/tools/utils.py
index 2e92723..55a54bc 100644
--- a/tools/utils.py
+++ b/tools/utils.py
@@ -278,13 +278,13 @@
       version.major, version.minor, version.patch, version.prerelease,
       version.prerelease_patch))
 
-def GetSemanticSDKVersion():
+def GetSemanticSDKVersion(ignore_svn_revision=False):
   version = ReadVersionFile()
   if not version:
     return None
 
   if version.channel == 'be':
-    postfix = '-edge.%s' % GetSVNRevision()
+    postfix = '-edge' if ignore_svn_revision else '-edge.%s' % GetSVNRevision()
   elif version.channel == 'dev':
     postfix = '-dev.%s.%s' % (version.prerelease, version.prerelease_patch)
   else: