Version 1.12.0-dev.0.0

Merge commit '6c50e6d9412bb992416f61695945b6cdf32b024e' into dev
diff --git a/.gitignore b/.gitignore
index 65d9dea..effef47 100644
--- a/.gitignore
+++ b/.gitignore
@@ -38,6 +38,9 @@
 .children
 .project
 
+# IntelliJ project files
+*.iml
+
 # Built by chromebot and downloaded from Google Storage
 client/tests/drt
 
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9c36150..ddd1600 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,33 +1,71 @@
+## 1.12.0
+
+### Core library changes
+
+* `dart:html`
+  * `NodeTreeSanitizer` added the `const trusted` field. It can be used
+    instead of defining a `NullTreeSanitizer` class when calling
+    `setInnerHtml` or other methods that create DOM from text. It is
+    also more efficient, skipping the creation of a `DocumentFragment`.
+
 ## 1.11.0
 
 ### Core library changes
 
-* In `dart:html`, `appendHtml` and `insertAdjacentHtml` now take `nodeValidator`
-  and `treeSanitizer` parameters, and the inputs are consistently
-  sanitized. See [45818 announcement]
-  [45818 announcement](https://groups.google.com/a/dartlang.org/forum/#!topic/announce/GVO7EAcPi6A)
-* List iterators may not throw ConcurrentModificationError as eagerly in
-  release mode. In checked mode, the modification check is still as eager
-  as possible.
-  [r45198](https://code.google.com/p/dart/source/detail?r=45198)
 * `dart:core`
-  * Add `unmodifiable` constructor to `List` -
+  * `Iterable` added an `empty` constructor.
+    [dcf0286](https://github.com/dart-lang/sdk/commit/dcf0286f5385187a68ce9e66318d3bf19abf454b)
+  * `List` added an `unmodifiable` constructor.
     [r45334](https://code.google.com/p/dart/source/detail?r=45334)
-  * Add `unmodifiable` constructor to `Map` -
+  * `Map` added an `unmodifiable` constructor.
     [r45733](https://code.google.com/p/dart/source/detail?r=45733)
-  * Add `empty` constructor to `Iterable` -
-    [dcf0286f](https://github.com/dart-lang/sdk/commit/dcf0286f5385187a68ce9e66318d3bf19abf454b)
-* `dart:isolate`:
-  * Make the priority parameter of `Isolate.ping` and `Isolate.kill` methods
-    a named parameter named `priority`.
-  * Remove the `Isolate.AS_EVENT` priority.
-  * Add extra `response` parameter to `Isolate.ping` and
-    `Isolate.addOnExitListener` -
-    [r45092](https://code.google.com/p/dart/source/detail?r=45092)
+  * `int` added a `gcd` method.
+    [a192ef4](https://github.com/dart-lang/sdk/commit/a192ef4acb95fad1aad1887f59eed071eb5e8201)
+  * `int` added a `modInverse` method.
+    [f6f338c](https://github.com/dart-lang/sdk/commit/f6f338ce67eb8801b350417baacf6d3681b26002)
+  * `StackTrace` added a `fromString` constructor.
+    [68dd6f6](https://github.com/dart-lang/sdk/commit/68dd6f6338e63d0465041d662e778369c02c2ce6)
+  * `Uri` added a `directory` constructor.
+    [d8dbb4a](https://github.com/dart-lang/sdk/commit/d8dbb4a60f5e8a7f874c2a4fbf59eaf1a39f4776)
+  * List iterators may not throw `ConcurrentModificationError` as eagerly in
+    release mode. In checked mode, the modification check is still as eager
+    as possible.
+    [r45198](https://code.google.com/p/dart/source/detail?r=45198)
+
+* `dart:developer` - **NEW**
+  * Replaces the deprecated `dart:profiler` library.
+  * Adds new functions `debugger` and `inspect`.
+    [6e42aec](https://github.com/dart-lang/sdk/blob/6e42aec4f64cf356dde7bad9426e07e0ea5b58d5/sdk/lib/developer/developer.dart)
+
+* `dart:io`
+  * `FileSystemEntity` added a `uri` property.
+    [8cf32dc](https://github.com/dart-lang/sdk/commit/8cf32dc1a1664b516e57f804524e46e55fae88b2)
+  * `Platform` added a `static resolvedExecutable` property.
+    [c05c8c6](https://github.com/dart-lang/sdk/commit/c05c8c66069db91cc2fd48691dfc406c818d411d)
+
+* `dart:html`
+  * `Element` methods, `appendHtml` and `insertAdjacentHtml` now take `nodeValidator`
+    and `treeSanitizer` parameters, and the inputs are consistently
+    sanitized.
+    [r45818 announcement](https://groups.google.com/a/dartlang.org/forum/#!topic/announce/GVO7EAcPi6A)
+
+* `dart:isolate`
+  * **BREAKING** The positional `priority` parameter of `Isolate.ping` and `Isolate.kill` is
+    now a named parameter named `priority`.
+  * **BREAKING** Removed the `Isolate.AS_EVENT` priority.
+  * `Isolate` methods `ping` and `addOnExitListener` now have a named parameter
+    `response`.
+    [r45092](https://github.com/dart-lang/sdk/commit/1b208bd)
   * Remove the experimental state of the API.
 
+* `dart:profiler` - **DEPRECATED**
+  * This library will be removed in 1.12. Use `dart:developer` instead.
+
 ### Tool changes
 
+* This is the first release that does not include the Eclipse-based
+  **Dart Editor**.
+  See [dartlang.org/tools](https://www.dartlang.org/tools/]) for alternatives.
 * This is the last release that ships the (unsupported)
   dart2dart (aka `dart2js --output-type=dart`) utility as part
   of dart2js
diff --git a/DEPS b/DEPS
index 0a901f2..5fbe981 100644
--- a/DEPS
+++ b/DEPS
@@ -38,7 +38,7 @@
 
   # Revisions of /third_party/* dependencies.
   "7zip_rev" : "@19997",
-  "analyzer_cli_rev" : "@090c4859a2f88e62ae71a11583ba31e9999c74f6",
+  "analyzer_cli_rev" : "@8bf3516dd645ca289d7ebc641f7c228d5b3d37c4",
   "args_tag": "@0.13.0",
   "barback_rev" : "@29ee90dbcf77cfd64632fa2797a4c8a4f29a4b51",
   "charcode_tag": "@1.1.0",
@@ -48,10 +48,10 @@
   "collection_rev": "@1da9a07f32efa2ba0c391b289e2037391e31da0e",
   "crypto_rev" : "@2df57a1e26dd88e8d0614207d4b062c73209917d",
   "csslib_tag" : "@0.12.0",
-  "async_await_rev" : "@8b401a9f2e5e81dca5f70dbe7564112a0823dee6",
+  "dartdoc_rev" : "@9f677ec40f9beeb8933374885ef3af4c63d35d25",
   "dart_services_rev" : "@7aea2574e6f3924bf409a80afb8ad52aa2be4f97",
   "dart_style_tag": "@0.1.8",
-  "d8_rev" : "@39739",
+  "dev_compiler_rev": "@0.1.1",
   "fake_async_rev" : "@38614",
   "firefox_jsshell_rev" : "@45554",
   "glob_rev": "@704cf75e4f26b417505c5c611bdaacd8808467dd",
@@ -71,24 +71,28 @@
   "matcher_tag": "@0.12.0",
   "metatest_rev": "@e5aa8e4e19fc4188ac2f6d38368a47d8f07c3df1",
   "mime_rev": "@75890811d4af5af080351ba8a2853ad4c8df98dd",
+  "mustache4dart_rev" : "@5724cfd85151e5b6b53ddcd3380daf188fe47f92",
   "net_nss_rev": "@f81948e9a402db94287a43bb34a07ee0daf56cb5",
   "nss_rev": "@87b96db4268293187d7cf741907a6d5d1d8080e0",
   "oauth2_rev": "@1bff41f4d54505c36f2d1a001b83b8b745c452f5",
   "observe_rev": "@eee2b8ec34236fa46982575fbccff84f61202ac6",
   "observatory_pub_packages_rev": "@45565",
-  "package_config_tag": "@0.0.3+1",
+  "package_config_tag": "@0.1.1",
   "path_rev": "@93b3e2aa1db0ac0c8bab9d341588d77acda60320",
   "petitparser_rev" : "@37878",
   "ply_rev": "@604b32590ffad5cbb82e4afef1d305512d06ae93",
   "plugin_tag": "@0.1.0",
   "pool_rev": "@22e12aeb16ad0b626900dbe79e4a25391ddfb28c",
-  "pub_rev": "@68308887177ef3b78fdd52f068e4eaefe1b17e07",
+  "pub_rev": "@9d707158fedc86fc2b02f62cdfe804902b098d9d",
+  "pub_cache_tag": "@v0.0.1+2",
   "pub_semver_tag": "@1.2.1",
+  "quiver_tag": "@0.21.4",
   "scheduled_test_tag": "@0.11.8+1",
   "shelf_rev": "@1e87b79b21ac5e6fa2f93576d6c06eaa65285ef4",
   "smoke_rev" : "@f3361191cc2a85ebc1e4d4c33aec672d7915aba9",
   "source_maps_rev": "@379b4f31c4e2987eb15934d1ad8b419c6cc897b3",
   "sqlite_rev": "@38811b79f42801662adc0458a25270ab690a6b81",
+  "shelf_static_rev": "@v0.2.1",
   "shelf_web_socket_rev": "@ff170cec2c0e4e5722cdf47c557be63b5035a602",
   "source_span_rev": "@42501132e43599a151ba6727d340e44442f86c05",
   "stack_trace_tag": "@1.2.1",
@@ -99,7 +103,7 @@
   "utf_rev": "@1f55027068759e2d52f2c12de6a57cce5f3c5ee6",
   "unittest_tag": "@0.11.6",
   "usage_rev": "@b5080dac0d26a5609b266f8fdb0d053bc4c1c638",
-  "watcher_tag": "@0.9.5",
+  "watcher_tag": "@0.9.6",
   "when_tag": "@0.2.0+2",
   "which_tag": "@0.1.3+1",
   "web_components_rev": "@0e636b534d9b12c9e96f841e6679398e91a986ec",
@@ -119,7 +123,7 @@
       (Var("googlecode_url") % "gyp") + "/trunk" + Var("gyp_rev"),
 
   Var("dart_root") + "/tests/co19/src":
-      "https://github.com/dart-lang/co19.git" + Var("co19_rev"),
+      (Var("github_mirror") % "co19") + Var("co19_rev"),
 
   Var("dart_root") + "/third_party/nss":
       Var("chromium_git") + "/chromium/deps/nss.git" + Var("nss_rev"),
@@ -162,8 +166,6 @@
       Var("third_party") + "/gsutil" + Var("gsutil_rev"),
   Var("dart_root") + "/third_party/pkg/petitparser":
       Var("third_party") + "/petitparser" + Var("petitparser_rev"),
-  Var("dart_root") + "/third_party/d8":
-      Var("third_party") + "/d8" + Var("d8_rev"),
   Var("dart_root") + "/third_party/WebCore":
       Var("third_party") + "/WebCore" + Var("WebCore_rev"),
   Var("dart_root") + "/third_party/observatory_pub_packages":
@@ -178,14 +180,12 @@
       (Var("github_mirror") % "analyzer_cli") + Var("analyzer_cli_rev"),
   Var("dart_root") + "/third_party/pkg/args":
       (Var("github_mirror") % "args") + Var("args_tag"),
-  Var("dart_root") + "/third_party/pkg/async_await":
-      (Var("github_mirror") % "async_await") + Var("async_await_rev"),
   Var("dart_root") + "/third_party/pkg/barback":
       (Var("github_mirror") % "barback") + Var("barback_rev"),
   Var("dart_root") + "/third_party/pkg/charcode":
-      "https://github.com/dart-lang/charcode.git" + Var("charcode_tag"),
+      (Var("github_mirror") % "charcode") + Var("charcode_tag"),
   Var("dart_root") + "/third_party/pkg/cli_util":
-      "https://github.com/dart-lang/cli_util.git" + Var("cli_util_tag"),
+      (Var("github_mirror") % "cli_util") + Var("cli_util_tag"),
   Var("dart_root") + "/third_party/pkg/collection":
       (Var("github_mirror") % "collection") + Var("collection_rev"),
   Var("dart_root") + "/third_party/pkg/crypto":
@@ -194,6 +194,10 @@
       (Var("github_mirror") % "csslib") + Var("csslib_tag"),
   Var("dart_root") + "/third_party/pkg_tested/dart_style":
       (Var("github_mirror") % "dart_style") + Var("dart_style_tag"),
+  Var("dart_root") + "/third_party/pkg/dartdoc":  
+      "https://github.com/dart-lang/dartdoc.git" + Var("dartdoc_rev"),
+  Var("dart_root") + "/third_party/pkg/dev_compiler":
+      "https://github.com/dart-lang/dev_compiler.git" + Var("dev_compiler_rev"),
   Var("dart_root") + "/third_party/pkg/glob":
       (Var("github_mirror") % "glob") + Var("glob_rev"),
   Var("dart_root") + "/third_party/pkg/html":
@@ -217,13 +221,18 @@
   Var("dart_root") + "/third_party/pkg/logging":
       (Var("github_mirror") % "logging") + Var("logging_rev"),
   Var("dart_root") + "/third_party/pkg/markdown":
-      "https://github.com/dpeek/dart-markdown.git" + Var("markdown_rev"),
+      "https://chromium.googlesource.com/external/github.com" +
+      "/dpeek/dart-markdown.git" + Var("markdown_rev"),
   Var("dart_root") + "/third_party/pkg/matcher":
       (Var("github_mirror") % "matcher") + Var("matcher_tag"),
   Var("dart_root") + "/third_party/pkg/metatest":
       (Var("github_mirror") % "metatest") + Var("metatest_rev"),
   Var("dart_root") + "/third_party/pkg/mime":
       (Var("github_mirror") % "mime") + Var("mime_rev"),
+  Var("dart_root") + "/third_party/pkg/mustache4dart":  
+      Var("chromium_git")  
+      + "/external/github.com/valotas/mustache4dart.git"   
+      + Var("mustache4dart_rev"),
   Var("dart_root") + "/third_party/pkg/oauth2":
       (Var("github_mirror") % "oauth2") + Var("oauth2_rev"),
   Var("dart_root") + "/third_party/pkg/observe":
@@ -239,13 +248,22 @@
       (Var("github_mirror") % "pool") + Var("pool_rev"),
   Var("dart_root") + "/third_party/pkg/pub_semver":
       (Var("github_mirror") % "pub_semver") + Var("pub_semver_tag"),
-  Var("dart_root") + "/third_party/pkg_tested/pub":
+  Var("dart_root") + "/third_party/pkg/pub":
       ("https://github.com/dart-lang/pub.git") + Var("pub_rev"),
+  Var("dart_root") + "/third_party/pkg/pub_cache":  
+      (Var("github_mirror") % "pub_cache") + Var("pub_cache_tag"),
+  Var("dart_root") + "/third_party/pkg/quiver": 
+      Var("chromium_git")  
+      + "/external/github.com/google/quiver-dart.git"  
+      + Var("quiver_tag"),
   Var("dart_root") + "/third_party/pkg/scheduled_test":
       (Var("github_mirror") % "scheduled_test") +
       Var("scheduled_test_tag"),
   Var("dart_root") + "/third_party/pkg/shelf":
       (Var("github_mirror") % "shelf") + Var("shelf_rev"),
+  Var("dart_root") + "/third_party/pkg/shelf_static":
+      "https://github.com/kevmoo/shelf_static.dart.git" +
+      Var("shelf_static_rev"),
   Var("dart_root") + "/third_party/pkg/shelf_web_socket":
       (Var("github_mirror") % "shelf_web_socket") +
       Var("shelf_web_socket_rev"),
@@ -280,9 +298,9 @@
       (Var("github_mirror") % "web-components") +
       Var("web_components_rev"),
   Var("dart_root") + "/third_party/pkg/when":
-      "https://github.com/dart-lang/when.git" + Var("when_tag"),
+      (Var("github_mirror") % "when") + Var("when_tag"),
   Var("dart_root") + "/third_party/pkg/which":
-      "https://github.com/dart-lang/which.git"+ Var("which_tag"),
+      (Var("github_mirror") % "which") + Var("which_tag"),
   Var("dart_root") + "/third_party/pkg/yaml":
       (Var("github_mirror") % "yaml") + Var("yaml_rev"),
 
@@ -340,4 +358,19 @@
       Var('dart_root') + '/tools/testing/bin',
     ],
   },
+  {
+    'name': 'd8_testing_binaries',
+    'pattern': '.',
+    'action': [
+      'download_from_google_storage',
+      '--no_auth',
+      '--no_resume',
+      '--bucket',
+      'dart-dependencies',
+      '-d',
+      '-r',
+      Var('dart_root') + '/third_party/d8',
+    ],
+  },
+
 ]
diff --git a/client/tools/buildbot_annotated_steps.py b/client/tools/buildbot_annotated_steps.py
index 1ca3933..bde2a63 100755
--- a/client/tools/buildbot_annotated_steps.py
+++ b/client/tools/buildbot_annotated_steps.py
@@ -79,7 +79,9 @@
       return status
 
   name = GetName()
-  if name.startswith('pub-'):
+  if name.startswith('pkg-'):
+    status = ProcessBot(name, 'pkg')
+  elif name.startswith('pub-'):
     status = ProcessBot(name, 'pub')
   elif name.startswith('vm-android'):
     status = ProcessBot(name, 'android')
diff --git a/docs/language/Makefile b/docs/language/Makefile
index 9c76ad4..4819c23 100644
--- a/docs/language/Makefile
+++ b/docs/language/Makefile
@@ -39,4 +39,4 @@
 
 clean: cleanish
 	rm -f *.dvi *.pdf $(HASH) $(LIST)
-
+ 
diff --git a/docs/language/dartLangSpec.tex b/docs/language/dartLangSpec.tex
index 9c1f568..10d6f2c 100644
--- a/docs/language/dartLangSpec.tex
+++ b/docs/language/dartLangSpec.tex
@@ -6,8 +6,8 @@
 \usepackage{hyperref}
 \usepackage{lmodern}
 \newcommand{\code}[1]{{\sf #1}}
-\title{Dart Programming Language  Specification \\
-{\large Version 1.9}}
+\title{Dart Programming Language  Specification\\
+{\large Version 1.10}}
 
 % For information about Location Markers (and in particular the
 % commands \LMHash and \LMLabel), see the long comment at the
@@ -2012,18 +2012,12 @@
 A mixin describes the difference between a class and its superclass. A mixin is always derived from an existing class declaration. 
 
 \LMHash{}
-It is a compile-time error if a declared or derived mixin refers to \SUPER{}. It is a compile-time error if a declared or derived mixin explicitly declares a constructor. It is a compile-time error if a mixin is derived from a class whose superclass is not \code{Object}.
+It is a compile-time error if a declared or derived mixin explicitly declares a constructor. 
 
 \rationale{
-These restrictions are temporary.  We expect to remove them in later versions of Dart.
-
-The restriction on the use of \SUPER{} avoids the problem of rebinding \SUPER{} when the mixin is bound to difference superclasses.
+This restriction is temporary.  We expect to remove it in later versions of Dart.
 
 The restriction on constructors simplifies the construction of mixin applications because the process of creating instances is simpler.
-
-The restriction on the superclass means that the type of a class  from which a mixin is derived is always implemented by any class that mixes it in. This allows us to defer the question of whether and how to express the type of the mixin independently of its superclass and super interface types.
-
-Reasonable answers exist for all these issues, but their implementation is non-trivial.
 }
 
 \subsection{Mixin Application}
@@ -2077,6 +2071,12 @@
 The effect of a class definition of the form \code{\CLASS{} $C$ = $M$; } or the form 
  \code{\CLASS{} $C<T_1, \ldots, T_n>$ = $M$; } in library $L$  is to introduce the name $C$ into the scope of $L$, bound to the class (\ref{classes}) defined by the mixin application $M$. The name of the class is also set to $C$. Iff the  class is prefixed by the built-in identifier \ABSTRACT{}, the class being defined is an abstract class.
  
+ Let $M_A$ be a mixin derived from a class $M$ with direct superclass $S_{static}$.
+
+Let $A$ be an application of $M_A$. It is a static warning if the superclass of $A$ is not a subtype of $S_{static}$.
+
+Let $C$ be a class declaration that includes $M_A$ in a with clause. It is a static warning if $C$ does not implement, directly or indirectly, all the direct superinterfaces of $M$.
+ 
 
 \subsection{Mixin Composition}
 \LMLabel{mixinComposition}
@@ -2344,7 +2344,7 @@
 
 \begin{grammar}
 {\bf primary:}thisExpression;
-      \SUPER{} assignableSelector;
+      \SUPER{} unconditionalAssignableSelector;
       functionExpression;
       literal;
       identifier;
@@ -2526,7 +2526,7 @@
 \end{grammar}
 
 \LMHash{}
-The null object is the sole instance of the built-in class \code{Null}. Attempting to instantiate \code{Null} causes a run-time error. It is a compile-time error for a class to attempt to extend or implement \code{Null}. 
+The null object is the sole instance of the built-in class \code{Null}. Attempting to instantiate \code{Null} causes a run-time error. It is a compile-time error for a class to attempt to extend, mix in or implement \code{Null}. 
 Invoking a method on \NULL{}  yields a \code{NoSuchMethodError} unless the method is explicitly implemented by class \code{Null}.
 
 \LMHash{}
@@ -2576,7 +2576,7 @@
 }
 
 \LMHash{}
-It is a compile-time error for a class to attempt to extend or implement \code{int}. It is a compile-time error for a class to attempt to extend or implement \code{double}. It is a compile-time error for any type other than the types \code{int} and \code{double} to attempt to extend or implement \code{num}.
+It is a compile-time error for a class to attempt to extend, mix in or implement \code{int}. It is a compile-time error for a class to attempt to extend, mix in or implement \code{double}. It is a compile-time error for any type other than the types \code{int} and \code{double} to attempt to extend, mix in or implement \code{num}.
 
 \LMHash{}
 An {\em integer literal} is either a hexadecimal integer literal or a  decimal integer literal. Invoking the getter \code{runtimeType} on an integer literal returns the \code{Type} object that is the value of the expression \code{int}. The static type of an integer literal is \code{int}. 
@@ -2598,7 +2598,7 @@
 \end{grammar}
 
 \LMHash{}
-Both  \TRUE{} and \FALSE{} implement the built-in class \code{bool}.  It is a compile-time error for a class to attempt to extend or implement\code{ bool}. 
+Both  \TRUE{} and \FALSE{} implement the built-in class \code{bool}.  It is a compile-time error for a class to attempt to extend, mix in or implement\code{ bool}. 
 
 \commentary{
 It follows that the two boolean literals are the only two instances of \code{bool}. 
@@ -2748,6 +2748,10 @@
  \rationale{
  The idea is to ignore whitespace, where whitespace is defined as tabs, spaces and newlines. These can be represented directly, but since for most characters prefixing by backslash is an identity, we allow those forms as well.
  }
+ 
+ % could be clearer. Is the first line in  """\t
+ %    """ ignored not. It depends if we mean whitespace before escapes are interpreted,
+ % or after, or both.  See https://code.google.com/p/dart/issues/detail?id=23020
 
 \LMHash{}
 Strings support escape sequences for special characters. The escapes are:
@@ -2802,7 +2806,7 @@
  \end{grammar}
  
 \LMHash{}
-All string literals implement the built-in class \code{String}. It is a compile-time error for a class to attempt to extend or implement \code{String}. Invoking the getter \code{runtimeType} on a string literal returns the \code{Type} object that is the value of the expression \code{String}. The static type of a string literal is \code{String}.
+All string literals implement the built-in class \code{String}. It is a compile-time error for a class to attempt to extend, mix in or implement \code{String}. Invoking the getter \code{runtimeType} on a string literal returns the \code{Type} object that is the value of the expression \code{String}. The static type of a string literal is \code{String}.
 
 \subsubsection{String Interpolation}
 \LMLabel{stringInterpolation}
@@ -3666,6 +3670,8 @@
 \LMHash{}
 If there exists a lexically visible declaration named $id$, let $f_{id}$ be the innermost such declaration. Then:
 \begin{itemize}
+\item 
+If $f_{id}$ is a prefix object, a compile-time error occurs.
 \item
  If $f_{id}$ is a local function, a library function, a library or static getter or a variable then $i$ is interpreted as a function expression invocation (\ref{functionExpressionInvocation}).
  \item
@@ -3673,18 +3679,13 @@
 \item Otherwise, $f_{id}$ is considered equivalent to the ordinary method invocation $\THIS{}.id(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$.
 \end{itemize}
 
-%Otherwise, if there is an accessible (\ref{privacy}) static method named $id$ declared in a superclass $S$ of the immediately enclosing class $C$ then i is equivalent to the static method invocation $S.id(a_1, \ldots, a_n, x_{n+1}: a_{n+1}, \ldots, x_{n+k}: a_{n+k})$.  
-
-%\rationale{
-%Unqualified access to static methods of superclasses is inconsistent with the idea that static methods are not inherited. It is not particularly necessary and  may be restricted in future versions.
-%}
-
 \LMHash{}
 Otherwise, if $i$ occurs inside a top level or static function (be it function, method, getter,  or setter) or variable initializer, evaluation of $i$ causes a \cd{NoSuchMethodError} to be thrown.
 
 \LMHash{}
 If $i$ does not occur inside a top level or static function, $i$ is equivalent to $\THIS{}.id(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$.
 
+
 % Should also say:
 % It is a static warning if $i$  occurs inside a top level or static function (be it function, method, getter,  or setter) or variable initializer and there is no lexically visible declaration named $id$ in scope.
 
@@ -3732,7 +3733,7 @@
 
 \LMHash{}
 The result of  a lookup of method $m$ in class $C$ with respect to library $L$ is:
-If $C$ declares a concrete instance method named $m$ that is accessible to $L$,  then that method is the result of the lookup. Otherwise, if $C$ has a superclass $S$, then the result of the lookup is the result of looking up $m$  in $S$ with respect to $L$. Otherwise, we say that the method lookup has failed.
+If $C$ declares a concrete instance method named $m$ that is accessible to $L$,  then that method is the result of the lookup, and we say that the method was {\em looked up in $C$}. Otherwise, if $C$ has a superclass $S$, then the result of the lookup is the result of looking up $m$  in $S$ with respect to $L$. Otherwise, we say that the method lookup has failed.
 
 \rationale {
 The motivation for skipping abstract members during lookup is largely to allow smoother mixin composition. 
@@ -3747,7 +3748,7 @@
 
 \LMHash{}
 The result of a lookup of a getter (respectively setter) $m$ in class $C$  with respect to library $L$ is:
-If $C$ declares a concrete instance getter (respectively setter) named $m$  that is accessible to $L$,  then that getter (respectively setter) is the result of the lookup. Otherwise, if $C$ has a superclass $S$, then the result of the lookup is the result of looking up getter (respectively setter) $m$ in $S$ with respect to $L$. Otherwise, we say that the lookup has failed.
+If $C$ declares a concrete instance getter (respectively setter) named $m$  that is accessible to $L$,  then that getter (respectively setter) is the result of the lookup, and we say that the getter (respectively setter) was {\em looked up in $C$}. Otherwise, if $C$ has a superclass $S$, then the result of the lookup is the result of looking up getter (respectively setter) $m$ in $S$ with respect to $L$. Otherwise, we say that the lookup has failed.
 
 \rationale {
 The motivation for skipping abstract members during lookup is largely to allow smoother mixin composition. 
@@ -3869,6 +3870,8 @@
 \item
 $T$ or a superinterface of $T$ is annotated with an annotation denoting a constant identical to the constant \code{@proxy} defined in \code{dart:core}.  Or
 \item  $T$ is \code{Type}, $e$ is a constant type literal and the class corresponding to $e$ has a static getter named $m$.
+\item $T$ is \code{Function} and $m$ is \CALL. \rationale {The type \code{Function} is treated as if it has a \code{call} method for any possible signature of \CALL. The expectation is that any concrete subclass of \code{Function} will implement \CALL. Note that a warning will be issue if this is not the case. Furthermore, any use of \CALL on a subclass of \code{Function} that fails to implement \CALL{} will also provoke a a warning, as this exemption is limited to type \code{Function}, and does not apply to its subtypes. 
+}
 \end{itemize}
 
 \LMHash{}
@@ -3916,7 +3919,7 @@
 Evaluation of $i$ proceeds as follows:
 
 \LMHash{}
-First, the argument list $(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$ is evaluated  yielding actual argument objects $o_1, \ldots , o_{n+k}$. Let $S$ be the superclass of the immediately enclosing class, and let $f$ be the result of looking up method (\ref{ordinaryInvocation})  $m$ in $S$  with respect to the current library $L$. 
+First, the argument list $(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$ is evaluated  yielding actual argument objects $o_1, \ldots , o_{n+k}$. Let $g$ be the method currently executing, and let $C$ be the class in which $g$ was looked up (\ref{methodLookup}). Let $S_{dynamic}$ be the superclass of $C$, and let $f$ be the result of looking up method (\ref{methodLookup})  $m$ in $S_{dynamic}$  with respect to the current library $L$. 
 Let $p_1 \ldots p_h$ be the required parameters of $f$,  let $p_1 \ldots p_m$ be the positional parameters of $f$ and let $p_{h+1}, \ldots, p_{h+l}$ be the optional parameters declared by $f$.
 
 \LMHash{}
@@ -3926,8 +3929,8 @@
 If the method lookup succeeded, the body of $f$ is executed with respect to the bindings that resulted from the evaluation of the argument list, and with \THIS{} bound to the current value of \THIS{}. The value of $i$ is the value returned after $f$ is executed.
 
 \LMHash{}
-If the method lookup has failed, then let $g$ be the result of looking up getter (\ref{getterAndSetterLookup}) $m$ in $S$ with respect to $L$. If the getter lookup succeeded, let $v_g$ be the value of the getter invocation $\SUPER{}.m$. Then the value of $i$ is the result of invoking 
-the static method \code{Function.apply()} with arguments $v.g, [o_1, \ldots , o_n], \{x_{n+1}: o_{n+1}, \ldots , x_{n+k}: o_{n+k}\}$.
+If the method lookup has failed, then let $g$ be the result of looking up getter (\ref{getterAndSetterLookup}) $m$ in $S_{dynamic}$ with respect to $L$. If the getter lookup succeeded, let $v_g$ be the value of the getter invocation $\SUPER{}.m$. Then the value of $i$ is the result of invoking 
+the static method \code{Function.apply()} with arguments $v_g, [o_1, \ldots , o_n], \{x_{n+1}: o_{n+1}, \ldots , x_{n+k}: o_{n+k}\}$.
  
 \LMHash{}
 If  getter lookup has also failed, then a new instance $im$  of the predefined class  \code{Invocation}  is created, such that :
@@ -3937,7 +3940,7 @@
 \item \code{im.positionalArguments} evaluates to an immutable list with the same  values as  \code{[$o_1, \ldots, o_n$]}.
 \item \code{im.namedArguments} evaluates to an immutable map with the same keys and values as \code{\{$x_{n+1}: o_{n+1}, \ldots, x_{n+k} : o_{n+k}$\}}.
 \end{itemize}
-Then the method \code{noSuchMethod()} is looked up in $S$ and invoked on \THIS{} with argument $im$, and the result of this invocation is the result of evaluating $i$. However, if the implementation found cannot be invoked with a single positional argument, the implementation  of \code{noSuchMethod()} in class \code{Object} is invoked on \THIS{} with argument $im'$, where $im'$ is an instance of \code{Invocation} such that :
+Then the method \code{noSuchMethod()} is looked up in $S_{dynamic}$ and invoked on \THIS{} with argument $im$, and the result of this invocation is the result of evaluating $i$. However, if the implementation found cannot be invoked with a single positional argument, the implementation  of \code{noSuchMethod()} in class \code{Object} is invoked on \THIS{} with argument $im'$, where $im'$ is an instance of \code{Invocation} such that :
 \begin{itemize}
 \item  \code{im'.isMethod} evaluates to \code{\TRUE{}}.
 \item  \code{im'.memberName} evaluates to \code{\#noSuchMethod}.
@@ -3952,7 +3955,7 @@
 It is a compile-time error if a super method invocation occurs in a top-level function or variable initializer, in an instance variable initializer or initializer list, in class \code{Object}, in a factory constructor or in a static method or variable initializer.
 
 \LMHash{}
-It is a static type warning if $S$ does not have an accessible (\ref{privacy}) instance member named $m$ unless $S$ or a superinterface of $S$ is annotated with an annotation denoting a constant identical to the constant \code{@proxy} defined in \code{dart:core}. If $S.m$ exists, it  is a static type warning if the type $F$ of $S.m$ may not be assigned to a function type. If $S.m$ does not exist, or if $F$ is not a function type, the static type of $i$ is \DYNAMIC{}; otherwise the static type of $i$ is the declared return type of  $F$.  
+Let $S_{static}$ be the superclass of the immediately enclosing class. It is a static type warning if $S_{static}$ does not have an accessible (\ref{privacy}) instance member named $m$ unless $S_{static}$ or a superinterface of $S_{static}$ is annotated with an annotation denoting a constant identical to the constant \code{@proxy} defined in \code{dart:core}. If $S_{static}.m$ exists, it  is a static type warning if the type $F$ of $S_{static}.m$ may not be assigned to a function type. If $S_{static}.m$ does not exist, or if $F$ is not a function type, the static type of $i$ is \DYNAMIC{}; otherwise the static type of $i$ is the declared return type of  $F$.  
 % The following is not needed because it is specified in 'Binding Actuals to Formals"
 %Let $T_i$ be the static type of $a_i, i \in 1 .. n+k$. It is a static warning if $F$ is not a supertype of  $(T_1, \ldots, t_n, \{T_{n+1}$ $x_{n+1}, \ldots, T_{n+k}$ $x_{n+k}\}) \to \bot$.
 
@@ -3990,7 +3993,7 @@
 Tear-offs using the \cd{ x\#id}  syntax cannot be conditional at this time; this is inconsistent, and is likely to be addressed in the near future, perhaps via  notation such as  \cd{ x?\#id} . As indicated in section \ref{ecmaConformance}, experimentation in this area is allowed.
 }
 
-Evaluation of a {\em conditional property extraction expression} $e$ of the form $e_1?.id$  is equivalent to the evaluation of the expression  $((x) => x == \NULL ? \NULL : x.id)(e_1)$. The static type of $e$ is the same as the static type of $e_1.id$. Let $T$ be the static type of $e_1$ and let $y$ be a fresh variable o type $T$. Exactly the same static warnings that would be caused by $y.id$ are also generated in the case of $e_1?.id$.
+Evaluation of a {\em conditional property extraction expression} $e$ of the form $e_1?.id$  is equivalent to the evaluation of the expression  $((x) => x == \NULL ? \NULL : x.id)(e_1)$. The static type of $e$ is the same as the static type of $e_1.id$. Let $T$ be the static type of $e_1$ and let $y$ be a fresh variable of type $T$. Exactly the same static warnings that would be caused by $y.id$ are also generated in the case of $e_1?.id$.
 
 \commentary{
 One might be tempted to conclude that for $e \ne \NULL{}$, $e?.v$ is always equivalent to $e.v$. However this is not the case. If $e$ is a type literal representing a type with static member $v$, then $e.v$ refers to that member, but $e?.v$ does not.
@@ -4067,10 +4070,10 @@
 Evaluation of a property extraction $i$ of the form $\SUPER.m$ proceeds as follows:
 
 \LMHash{}
- Let $S$ be the superclass of the immediately enclosing class. Let $f$ be the result of looking up method $m$ in $S$ with respect to the current library $L$.  If method lookup succeeds then $i$ evaluates to the closurization of method $f$ with respect to superclass $S$ (\ref{superClosurization}).  
+Let $g$ be the method currently executing, and let $C$ be the class in which $g$ was looked up.  Let $S_{dynamic}$ be the superclass of $C$. Let $f$ be the result of looking up method $m$ in $S_{dynamic}$ with respect to the current library $L$.  If method lookup succeeds then $i$ evaluates to the closurization of method $f$ with respect to superclass $S_{dynamic}$ (\ref{superClosurization}).  
  
 \LMHash{}
- Otherwise, $i$ is a getter invocation.  Let $f$ be the result of  looking up getter $m$ in $S$  with respect to $L$.  The body of $f$  is executed with \THIS{} bound to the current value of  \THIS{}.  The value of $i$ is the result returned by the call to the getter function. 
+ Otherwise, $i$ is a getter invocation.  Let $f$ be the result of  looking up getter $m$ in $S_{dynamic}$  with respect to $L$.  The body of $f$  is executed with \THIS{} bound to the current value of  \THIS{}.  The value of $i$ is the result returned by the call to the getter function. 
 
 \LMHash{}
 If the getter lookup has failed, then a new instance $im$  of the predefined class  \code{Invocation}  is created, such that :
@@ -4080,7 +4083,7 @@
 \item \code{im.positionalArguments} evaluates to the value of \code{\CONST{} []}.
 \item \code{im.namedArguments} evaluates to the value of \code{\CONST{} \{\}}.
 \end{itemize}
-Then the method \code{noSuchMethod()} is looked up in $S$ and invoked  with argument $im$, and the result of this invocation is the result of evaluating $i$. However, if the implementation found cannot be invoked with a single positional argument, the implementation  of \code{noSuchMethod()} in class \code{Object} is invoked on \THIS{} with argument $im'$, where $im'$ is an instance of \code{Invocation} such that :
+Then the method \code{noSuchMethod()} is looked up in $S_{dynamic}$ and invoked  with argument $im$, and the result of this invocation is the result of evaluating $i$. However, if the implementation found cannot be invoked with a single positional argument, the implementation  of \code{noSuchMethod()} in class \code{Object} is invoked on \THIS{} with argument $im'$, where $im'$ is an instance of \code{Invocation} such that :
 \begin{itemize}
 \item  \code{im'.isMethod} evaluates to \code{\TRUE{}}.
 \item  \code{im'.memberName} evaluates to \code{\#noSuchMethod}.
@@ -4090,12 +4093,12 @@
 and the result of this latter invocation is the result of evaluating $i$.
 
 \LMHash{}
-It is a static type warning if $S$ does not have an accessible instance method or getter named $m$.  
+Let $S_{static}$ be the superclass of the immediately enclosing class. It is a static type warning if $S_{static}$ does not have an accessible instance method or getter named $m$.  
 
 The static type of $i$ is:
 \begin{itemize}
-\item The declared return type of $S.m$, if $S$ has an accessible instance getter named $m$.
-\item The static type of function $S.m$ if $S$ has an accessible instance method named $m$.
+\item The declared return type of $S_{static}.m$, if $S_{static}$ has an accessible instance getter named $m$.
+\item The static type of function $S_{static}.m$ if $S_{static}$ has an accessible instance method named $m$.
 \item The type  \DYNAMIC{} otherwise. 
 \end{itemize}
 
@@ -4155,14 +4158,16 @@
 \LMHash{}
 Let $T$ be the static type of $e$. It is a static type warning if $T$ does not have an accessible instance method or getter named $m$ unless either:
 \begin{itemize}
-\item $T$ or a superinterface of $T$ is annotated with an annotation denoting a constant identical to the constant proxy defined in \cd{dart:core}. Or
+\item $T$ or a superinterface of $T$ is annotated with an annotation denoting a constant identical to the constant \code{@proxy} defined in \cd{dart:core}. Or
 \item $T$ is \cd{Type}, $e$ is a constant type literal and the class corresponding to $e$ declares an accessible static method or getter named $m$.
+\item $T$ is \code{Function} and $m$ is \CALL.
 \end{itemize}
 
 The static type of $i$ is:
 \begin{itemize}
 \item The static type of function $T.m$, if $T$ has an accessible instance member named $m$.
 \item The static type of function $T.m$, if $T$ is \cd{Type}, $e$ is a constant type literal and the class corresponding to $e$ declares an accessible static member or constructor named $m$.
+\item \code{Function} if $T$ is \code{Function} and $m$ is \CALL.
 \item The type  \DYNAMIC{} otherwise. 
 \end{itemize}
 
@@ -4202,21 +4207,21 @@
 Evaluation of a property extraction $i$ of the form \SUPER$\#m$ proceeds as follows:
 
  \LMHash{}
-Let $S$ be the superclass of the immediately enclosing class.
+Let $g$ be the method currently executing, and let $C$ be the class in which $g$ was looked up.  Let $S_{dynamic}$ be the superclass of $C$. 
 
  \LMHash{}
-If $m$ is a setter name, let $f$ be the result of looking up setter $m$ in $S$ with respect to the current library $L$. If setter lookup succeeds then $i$ evaluates to the closurization of setter $f$  with respect to superclass $S$  (\ref{superClosurization}).  If setter lookup failed, a \cd{NoSuchMethodError} is thrown.
+If $m$ is a setter name, let $f$ be the result of looking up setter $m$ in $S_{dynamic}$ with respect to the current library $L$. If setter lookup succeeds then $i$ evaluates to the closurization of setter $f$  with respect to superclass $S_{dynamic}$  (\ref{superClosurization}).  If setter lookup failed, a \cd{NoSuchMethodError} is thrown.
 
-If $m$ is not a setter name, let $f$ be the result of looking up method $m$ in $S$ with respect to the current library $L$. If method lookup succeeds then $i$ evaluates to the closurization of method $m$ with respect to superclass $S$ (\ref{superClosurization}).
+If $m$ is not a setter name, let $f$ be the result of looking up method $m$ in $S_{dynamic}$ with respect to the current library $L$. If method lookup succeeds then $i$ evaluates to the closurization of method $m$ with respect to superclass $S_{dynamic}$ (\ref{superClosurization}).
 
 \LMHash{}
- Otherwise, let $f$ be the result of looking up getter $m$ in $S$ with respect to the current library $L$.  If getter lookup succeeds then $i$ evaluates to the closurization of getter $f$ with respect to superclass $S$ (\ref{superClosurization}).   If getter lookup failed, a \cd{NoSuchMethodError} is thrown.
+ Otherwise, let $f$ be the result of looking up getter $m$ in $S_{dynamic}$ with respect to the current library $L$.  If getter lookup succeeds then $i$ evaluates to the closurization of getter $f$ with respect to superclass $S_{dynamic}$ (\ref{superClosurization}).   If getter lookup failed, a \cd{NoSuchMethodError} is thrown.
 
 \LMHash{}
-It is a static type warning if $S$ does not have an accessible instance member named $m$.
+Let $S_{static}$ be the superclass of the immediately enclosing class.It is a static type warning if $S_{static}$ does not have an accessible instance member named $m$.
 
 \LMHash{}
-The static type of $i$ is the static type of the function $S.m$,  if $S$ has an accessible instance member named $m$. Otherwise the static type of $i$ is \DYNAMIC{}.
+The static type of $i$ is the static type of the function $S_{static}.m$,  if $S_{static}$ has an accessible instance member named $m$. Otherwise the static type of $i$ is \DYNAMIC{}.
 
 
 
@@ -4398,15 +4403,18 @@
 % \item Otherwise, the assignment is equivalent to the assignment \code{ \THIS{}.$v$ = $e$}. 
 % \end{itemize}
  
-%Otherwise,  
+%Otherwise 
 
 \LMHash{}
 Let $d$ be the innermost declaration whose name is $v$ or $v=$, if it exists.
+It is a compile-time error if $d$ denotes a prefix object.
 
 \LMHash{}
 If $d$ is the declaration of a local variable, the expression $e$ is evaluated to an object $o$. Then, the variable $v$ is bound to $o$ unless $v$ is \FINAL{} or \CONST{}, in which case a dynamic error occurs.
 If no error occurs, the value of the assignment expression is $o$.  
 
+% add local functions per bug 23218
+
 \LMHash{}
 If $d$ is the declaration of a library variable, top level getter or top level setter, the expression $e$ is evaluated to an object $o$. Then the setter $v=$ is invoked with its formal parameter bound to $o$. The value of the assignment expression is $o$.  
 
@@ -4475,8 +4483,8 @@
 Evaluation of an assignment of the form $\SUPER.v$ \code{=} $e$ proceeds as follows:
 
 \LMHash{}
-Let $S$ be the superclass of the immediately enclosing class.
-The expression $e$ is evaluated to an object $o$.  Then, the setter $v=$ is looked up (\ref{getterAndSetterLookup}) in $S$ with respect to the current library.  The body  of $v=$ is executed with its formal parameter bound to $o$ and \THIS{} bound to \THIS{}. 
+Let $g$ be the method currently executing, and let $C$ be the class in which $g$ was looked up.  Let $S_{dynamic}$ be the superclass of $C$. 
+The expression $e$ is evaluated to an object $o$.  Then, the setter $v=$ is looked up (\ref{getterAndSetterLookup}) in $S_{dynamic}$ with respect to the current library.  The body  of $v=$ is executed with its formal parameter bound to $o$ and \THIS{} bound to \THIS{}. 
 
 \LMHash{}
 If the setter lookup has failed, then a new instance $im$  of the predefined class  \code{Invocation}  is created, such that :
@@ -4488,7 +4496,7 @@
 \end{itemize}
 
 \LMHash{}
-Then the method \code{noSuchMethod()} is looked up in $S$ and invoked  with argument $im$. 
+Then the method \code{noSuchMethod()} is looked up in $S_{dynamic}$ and invoked  with argument $im$. 
 However, if the implementation found cannot be invoked with a single positional argument, the implementation  of \code{noSuchMethod()} in class \code{Object} is invoked on \THIS{} with argument $im'$, where $im'$ is an instance of \code{Invocation} such that :
 \begin{itemize}
 \item  \code{im'.isMethod} evaluates to \code{\TRUE{}}.
@@ -4504,7 +4512,7 @@
 In checked mode, it is a dynamic type error if $o$ is not \NULL{} and the interface of the class of $o$ is not a subtype of the actual type of $S.v$.
 
 \LMHash{}
-It is a static type warning if $S$ does not have an accessible instance setter named $v=$ unless $S$ or a superinterface of $S$ is annotated with an annotation denoting a constant identical to the constant \code{@proxy} defined in \code{dart:core}. 
+Let $S_{static}$ be the superclass of the immediately enclosing class. It is a static type warning if $S_{static}$ does not have an accessible instance setter named $v=$ unless $S_{static}$ or a superinterface of $S_{static}$ is annotated with an annotation denoting a constant identical to the constant \code{@proxy} defined in \code{dart:core}. 
 
 \LMHash{}
 It is a static type warning if the static type of $e$ may not be assigned to the static type of the formal parameter of the setter $v=$.   The static type of the expression $\SUPER.v$ \code{=} $e$ is the static type of $e$.
@@ -4535,7 +4543,13 @@
 \LMLabel{compoundAssignment}
 
 \LMHash{}
-Evaluation of a compound assignment of the form $v$ {\em ??=} $e$ is equivalent to the evaluation of the expression  $((x) => x == \NULL{}$ ?  $v=e : x)(v)$ where $x$ is a fresh variable that is not used in $e$. Evaluation of a compound assignment of the form $C.v$ {\em ??=} $e$, where $C$ is a type literal, is equivalent to the evaluation of the expression  $((x) => x == \NULL{}$?  $C.v=e: x)(C.v)$ where $x$ is a fresh variable that is not used in $e$. Evaluation of a compound assignment of the form $e_1.v$ {\em ??=} $e_2$ is equivalent to the evaluation of the expression  $((x) =>((y) => y == \NULL{}$ ? $ x.v = e_2: y)(x.v))(e_1)$ where $x$ and $y$ are distinct fresh variables that are not used in $e_2$. Evaluation of a compound assignment of the form  $e_1[e_2]$  {\em ??=} $e_3$ is equivalent to the evaluation of the expression  
+Evaluation of a compound assignment of the form $v$ {\em ??=} $e$ is equivalent to the evaluation of the expression  $((x) => x == \NULL{}$ ?  $v=e : x)(v)$ where $x$ is a fresh variable that is not used in $e$. Evaluation of a compound assignment of the form $C.v$ {\em ??=} $e$, where $C$ is a type literal, is equivalent to the evaluation of the expression  $((x) => x == \NULL{}$?  $C.v=e: x)(C.v)$ where $x$ is a fresh variable that is not used in $e$. 
+
+\commentary {
+The two rules above also apply when the variable v or the type C is prefixed.
+}
+
+Evaluation of a compound assignment of the form $e_1.v$ {\em ??=} $e_2$ is equivalent to the evaluation of the expression  $((x) =>((y) => y == \NULL{}$ ? $ x.v = e_2: y)(x.v))(e_1)$ where $x$ and $y$ are distinct fresh variables that are not used in $e_2$. Evaluation of a compound assignment of the form  $e_1[e_2]$  {\em ??=} $e_3$ is equivalent to the evaluation of the expression  
 $((a, i) => ((x) => x == \NULL{}$ ?  $a[i] = e_3: x)(a[i]))(e_1, e_2)$ where $x$, $a$ and $i$ are distinct fresh variables that are not used in $e_3$. Evaluation of a compound assignment of the form $\SUPER.v$  {\em ??=} $e$ is equivalent to the evaluation of the expression  $((x) => x == \NULL{}$ ? $\SUPER.v = e: x)(\SUPER.v)$ where $x$ is a fresh variable that is not used in $e$.
 
 \LMHash{}
@@ -4550,7 +4564,7 @@
 The static type of a compound assignment of the form  $C.v$ {\em ??=} $e$  is the least upper bound of the static type of $C.v$ and the static type of $e$.  Exactly the same static warnings that would be caused by $C.v = e$ are also generated in the case of $C.v$ {\em ??=} $e$.
 
 \LMHash{}
-The static type of a compound assignment of the form $e_1.v$  {\em ??=} $e_2$ is the least upper bound of the static type of $e_1.v$ and the static type of $e_2$. Let $T$ be the static type of $e_1$ and let $z$ be a fresh variable of type $T$. Exactly the same static warnings that would be caused by $z.v = e$ are also generated in the case of $e_1.v$  {\em ??=} $e_2$.
+The static type of a compound assignment of the form $e_1.v$  {\em ??=} $e_2$ is the least upper bound of the static type of $e_1.v$ and the static type of $e_2$. Let $T$ be the static type of $e_1$ and let $z$ be a fresh variable of type $T$. Exactly the same static warnings that would be caused by $z.v = e_2$ are also generated in the case of $e_1.v$  {\em ??=} $e_2$.
 
 \LMHash{}
 The static type of a compound assignment of the form $e_1[e_2]$  {\em ??=} $e_3$  is the least upper bound of the static type of $e_1[e_2]$ and the static type of $e_3$. Exactly the same static warnings that would be caused by $e_1[e_2] = e_3$ are also generated in the case of $e_1[e_2]$  {\em ??=} $e_3$.
@@ -4565,6 +4579,8 @@
 \LMHash{}
 Evaluation of a compound assignment of the form $e_1?.v$ $op = e_2$ is equivalent to \code{((x) $=>$ x?.v = x.v $op$ $e_2$)($e_1$)} where $x$ is a variable that is not used in $e_2$. The static type of $e_1?.v$ $op = e_2$ is the static type of $e_1.v$ $op$ $e_2$. Exactly the same static warnings that would be caused by $e_1.v$ $op = e_2$ are also generated in the case of $e_1?.v$ $op = e_2$.
 
+% Buggy. Allows C?.v = e.
+
 \begin{grammar}
 {\bf compoundAssignmentOperator:}`*=';
       `/=';
@@ -4998,46 +5014,93 @@
  A {\em postfix expression} is either a primary expression, a function, method or getter invocation, or an invocation of a postfix operator on an expression $e$.
 
 \LMHash{}
-A postfix expression of the form \code{$v$++}, where $v$ is an identifier, is equivalent to \code{()\{var r = $v$; $v$ = r + 1; return r\}()}.
+Execution of a postfix expression of the form \code{$v$++}, where $v$ is an identifier, is equivalent to executing \code{()\{\VAR{} r = $v$; $v$ = r + 1; \RETURN{} r\}()}.
+
+\LMHash{}
+The static type of such an expression is the static type of $v$.
+
 
 \rationale{The above ensures that if $v$ is a field, the getter gets called exactly once. Likewise in the cases below. 
 }
 
 \LMHash{}
-A postfix expression of the form \code{$C.v$ ++} is equivalent to 
+Execution of a postfix expression of the form \code{$C.v$ ++} is equivalent to executing 
 
-\code{()\{var r = $C.v$; $C.v$ = r + 1; return r\}()}.
+\code{()\{\VAR{} r = $C.v$; $C.v$ = r + 1; \RETURN{} r\}()}.
 
 \LMHash{}
-A postfix expression of the form \code{$e_1.v$++} is equivalent to 
+The static type of such an expression is the static type of $C.v$.
 
-\code{(x)\{var r = x.v; x.v = r + 1; \RETURN{} r\}($e_1$)}.
 
 \LMHash{}
-A postfix expression of the form \code{$e_1[e_2]$++},  is equivalent to 
+Execution of a postfix expression of the form \code{$e_1.v$++} is equivalent to executing 
 
-\code{(a, i)\{var r = a[i]; a[i] = r + 1; return r\}($e_1$, $e_2$)}.
+\code{(x)\{\VAR{} r = x.v; x.v = r + 1; \RETURN{} r\}($e_1$)}.
 
 \LMHash{}
-A postfix expression of the form \code{$v$-{}-}, where $v$ is an identifier, is equivalent to 
+The static type of such an expression is the static type of $e_1.v$.
 
-\code{()\{var r = $v$; $v$ = r - 1; return r\}()}.
 
 \LMHash{}
-A postfix expression of the form \code{$C.v$-{}-} is equivalent to 
+Execution of a postfix expression of the form \code{$e_1[e_2]$++},  is equivalent to executing 
 
-\code{()\{var r = $C.v$; $C.v$ = r - 1; return r\}()}.
+\code{(a, i)\{\VAR{} r = a[i]; a[i] = r + 1; \RETURN{} r\}($e_1$, $e_2$)}.
 
 \LMHash{}
-A postfix expression of the form \code{$e_1.v$-{}-} is equivalent to 
+The static type of such an expression is the static type of $e_1[e_2]$.
 
-\code{(x)\{var r = x.v; x.v = r - 1; \RETURN{} r\}($e_1$)}.
 
 \LMHash{}
-A postfix expression of the form \code{$e_1[e_2]$-{}-},  is equivalent to 
+Execution of a postfix expression of the form \code{$v$-{}-}, where $v$ is an identifier, is equivalent to executing 
 
-\code{(a, i)\{var r = a[i]; a[i] = r - 1; return r\}($e_1$, $e_2$)}.
- 
+\code{()\{\VAR{} r = $v$; $v$ = r - 1; \RETURN{} r\}()}.
+
+\LMHash{}
+The static type of such an expression is the static type of $v$.
+
+
+\LMHash{}
+Execution of a postfix expression of the form \code{$C.v$-{}-} is equivalent to executing 
+
+\code{()\{\VAR{} r = $C.v$; $C.v$ = r - 1; \RETURN{} r\}()}.
+
+\LMHash{}
+The static type of such an expression is the static type of $C.v$.
+
+
+\LMHash{}
+Execution of a postfix expression of the form \code{$e_1.v$-{}-} is equivalent to executing 
+
+\code{(x)\{\VAR{} r = x.v; x.v = r - 1; \RETURN{} r\}($e_1$)}.
+
+\LMHash{}
+The static type of such an expression is the static type of $e_1.v$.
+
+
+\LMHash{}
+Execution of a postfix expression of the form \code{$e_1[e_2]$-{}-},  is equivalent to executing 
+
+\code{(a, i)\{\VAR{} r = a[i]; a[i] = r - 1; \RETURN{} r\}($e_1$, $e_2$)}.
+
+\LMHash{}
+The static type of such an expression is the static type of $e_1[e_2]$.
+
+\LMHash{}
+Execution of a postfix expression of the form \code{$e_1?.v$++} is equivalent to executing 
+
+\code{((x) =$>$ x == \NULL? \NULL : x.v++)($e_1$)}.
+
+\LMHash{}
+The static type of such an expression is the static type of $e_1.v$.
+
+\LMHash{}
+Execution of a postfix expression of the form \code{$e_1?.v$-{}-} is equivalent to executing 
+
+\code{((x) =$>$ x == \NULL? \NULL : x.v-{}-)($e_1$)}.
+
+\LMHash{}
+The static type of such an expression is the static type of $e_1.v$.
+
 
 \subsection{ Assignable Expressions}
 \LMLabel{assignableExpressions}
@@ -5620,11 +5683,9 @@
    $s$ 
 \}
 \end{dartCode}
-where \code{n0} is an identifier that does not occur anywhere in the program.
+where \code{n0} is an identifier that does not occur anywhere in the program, except that for purposes of static typechecking, it is checked under the assumption that $n0$ is declared to be of type $T$, where $T$ is the static type of $e.iterator$.
 
-\commentary{
-Note that in fact, using a  \CONST{} variable would give rise to a compile time error since \cd{n0.current} is not a constant expression.  
-}
+ 
  
 \subsubsection{Asynchronous For-in}
 \LMLabel{asynchronousFor-in}
@@ -5711,7 +5772,7 @@
 
 
 {\bf switchCase:}
-      label* (\CASE{} expression `{\escapegrammar :}') statements
+      label* \CASE{} expression `{\escapegrammar :}' statements
     .
 
 {\bf defaultCase:}
@@ -5723,21 +5784,21 @@
  Given a switch statement of the form 
  
 \begin{dartCode}
-\SWITCH{} ($e$) \{ 
-   \CASE{} $label_{11} \ldots label_{1j_1}$ $e_1: s_1$ 
-   $\ldots$  
-   \CASE{} $label_{n1} \ldots label_{nj_n}$ $e_n: s_n$ 
-   \DEFAULT{}: $s_{n+1}$ 
+\SWITCH{} ($e$) \{
+   $label_{11} \ldots label_{1j_1}$ \CASE{} $e_1: s_1$
+   $\ldots$
+   $label_{n1} \ldots label_{nj_n}$ \CASE{} $e_n: s_n$
+   $label_{(n+1)1} \ldots label_{(n+1)j_{n+1}}$ \DEFAULT{}: $s_{n+1}$
 \}
 \end{dartCode}
  
  or the form 
  
 \begin{dartCode}
-\SWITCH{} ($e$) \{ 
-   \CASE{} $label_{11} \ldots label_{1j_1}$ $e_1: s_1$
-   $\ldots$  
-   \CASE{} $label_{n1} \ldots label_{nj_n}$ $e_n: s_n$ 
+\SWITCH{} ($e$) \{
+   $label_{11} \ldots label_{1j_1}$ \CASE{} $e_1: s_1$
+   $\ldots$
+   $label_{n1} \ldots label_{nj_n}$ \CASE{} $e_n: s_n$
 \}
 \end{dartCode}
  
@@ -5767,21 +5828,21 @@
 Execution of a switch statement of the form
 
 \begin{dartCode}
-\SWITCH{} ($e$) \{ 
-   \CASE{} $label_{11} \ldots label_{1j_1}$ $e_1: s_1$ 
-   $\ldots$  
-   \CASE{} $label_{n1} \ldots label_{nj_n}$ $e_n: s_n$ 
-   \DEFAULT{}: $s_{n+1}$ 
+\SWITCH{} ($e$) \{
+   $label_{11} \ldots label_{1j_1}$ \CASE{} $e_1: s_1$
+   $\ldots$
+   $label_{n1} \ldots label_{nj_n}$ \CASE{} $e_n: s_n$
+   $label_{(n+1)1} \ldots label_{(n+1)j_{n+1}}$ \DEFAULT{}: $s_{n+1}$
 \}
 \end{dartCode}
  
 or the form 
  
 \begin{dartCode}
-\SWITCH{} ($e$) \{ 
-   \CASE{} $label_{11} \ldots label_{1j_1}$ $e_1: s_1$
-   $\ldots$  
-   \CASE{} $label_{n1} \ldots label_{nj_n}$ $e_n: s_n$ 
+\SWITCH{} ($e$) \{
+   $label_{11} \ldots label_{1j_1}$ \CASE{} $e_1: s_1$
+   $\ldots$
+   $label_{n1} \ldots label_{nj_n}$ \CASE{} $e_n: s_n$
 \}
 \end{dartCode}
 
@@ -5802,11 +5863,11 @@
 Execution of a \CASE{} clause \CASE{} $e_{k}: s_{k}$ of a  switch statement  
 
 \begin{dartCode}
-\SWITCH{} ($e$) \{ 
-   \CASE{} $label_{11} \ldots label_{1j_1}$ $e_1: s_1$ 
-   $\ldots$  
-   \CASE{} $label_{n1} \ldots label_{nj_n}$ $e_n: s_n$ 
-   \DEFAULT{}: $s_{n+1}$ 
+\SWITCH{} ($e$) \{
+   $label_{11} \ldots label_{1j_1}$ \CASE{} $e_1: s_1$
+   $\ldots$
+   $label_{n1} \ldots label_{nj_n}$ \CASE{} $e_n: s_n$
+   $label_{(n+1)1} \ldots label_{(n+1)j_{n+1}}$ \DEFAULT{}: $s_{n+1}$
 \}
 \end{dartCode}
 
@@ -5822,10 +5883,10 @@
 Execution of a \CASE{} clause \CASE{} $e_{k}: s_{k}$ of a  switch statement  
 
 \begin{dartCode}
-\SWITCH{} ($e$) \{ 
-   \CASE{} $label_{11} \ldots label_{1j_1}$ $e_1: s_1$
-   $\ldots$  
-   \CASE{} $label_{n1} \ldots label_{nj_n}$ $e_n: s_n$ 
+\SWITCH{} ($e$) \{
+   $label_{11} \ldots label_{1j_1}$ \CASE{} $e_1: s_1$
+   $\ldots$
+   $label_{n1} \ldots label_{nj_n}$ \CASE{} $e_n: s_n$
 \}
 \end{dartCode}
 
@@ -5839,7 +5900,7 @@
 
 
 \commentary{
-In other words, there is no implicit fall-through between cases. The last case in a switch (default or otherwise) can `fall-through' to the end of the statement.
+In other words, there is no implicit fall-through between non-empty cases. The last case in a switch (default or otherwise) can `fall-through' to the end of the statement.
 }
 
 \LMHash{}
@@ -6557,17 +6618,24 @@
 Let $I$ be an import directive that refers to a URI via the string $s_1$. Evaluation of $I$  proceeds as follows:
 
 \LMHash{}
-If $I$ is a deferred import, no evaluation takes place. Instead, a mapping of the name of the prefix, $p$ to a {\em deferred prefix object} is added to the scope of $L$.
+If $I$ is a deferred import, no evaluation takes place. Instead, a mapping of the name of the prefix, $p$ to a {\em deferred prefix object} is added to the scope of the current library $L$.
 The deferred prefix object has the following methods:
 
 \begin{itemize}
 \item \code{loadLibrary}. This method returns a future $f$. When called, the method causes an immediate import $I'$ to be executed at some future time, where $I'$ is is derived from $I$ by eliding the word \DEFERRED{} and adding a \HIDE{} \code{loadLibrary}  combinator clause. When $I'$ executes without error, $f$ completes successfully. If $I'$ executes without error, we say that the call to \code{loadLibrary} has succeeded, otherwise we say the call has failed.
-\item  For every top level function $f$ named $id$ in $L$, a corresponding method named $id$ with the same signature as $f$. Calling the method results in a runtime error.
-\item For every top level getter $g$ named $id$ in $L$, a corresponding getter named $id$ with the same signature as $g$.  Calling the method results in a runtime error.
-\item For every top level setter $s$ named $id$ in $L$, a corresponding setter named $id$ with the same signature as $s$.  Calling the method results in a runtime error.
-\item For every type $T$ named $id$ in $L$, a corresponding getter named $id$ with return type \code{Type}.  Calling the method results in a runtime error.
+\item  For every top level function $f$ named $id$ in the imported library $B$, a corresponding method named $id$ with the same signature as $f$. Calling the method results in a runtime error.
+\item For every top level getter $g$ named $id$ in $B$, a corresponding getter named $id$ with the same signature as $g$.  Calling the method results in a runtime error.
+\item For every top level setter $s$ named $id$ in $B$, a corresponding setter named $id$ with the same signature as $s$.  Calling the method results in a runtime error.
+\item For every type $T$ named $id$ in $B$, a corresponding getter named $id$ with return type \code{Type}.  Calling the method results in a runtime error.
 \end{itemize}
 
+\rationale {
+The purpose of adding members of $B$ to $p$ is to ensure that any warnings  issued when using $p$ are correct, and no spurious warnings are generated.  In fact, at runtime we cannot add these members until $B$ is loaded; but any such invocations will fail at runtime as specified by virtue of being completely absent.
+}
+%But this is still a lie detectable by reflection. Probably revise so the type of p has these members but p does not.
+
+The static type of the prefix object $p$ is a unique interface type that has those members whose names and signatures are listed above.
+
 \LMHash{}
 After a call succeeds, the name $p$ is mapped to a non-deferred prefix object as described below. In addition, the prefix object also supports the \code{loadLibrary} method, and so it is possible to call \code{loadLibrary} again. If a call fails, nothing happens, and one again has the option to call \code{loadLibrary} again. Whether a repeated call to \code{loadLibrary} succeeds will vary as described below.
 
@@ -6621,7 +6689,7 @@
 
 then let $NS_i = \HIDE{}([id_1, \ldots, id_k], NS_{i-1}$) 
 
-where $hide(l, n)$ takes a list of identfiers $l$ and a namespace $n$, and produces a namespace that is identical to $n$ except that for each name $k$ in $l$, $k$ and $k=$ are undefined. 
+where $hide(l, n)$ takes a list of identifiers $l$ and a namespace $n$, and produces a namespace that is identical to $n$ except that for each name $k$ in $l$, $k$ and $k=$ are undefined. 
 \end{itemize}
  
 \LMHash{}
@@ -6638,6 +6706,9 @@
 Otherwise, let $NS = NS_n$.
 It is a compile-time error if the current library declares a top-level member named $p$.
 
+The static type of the prefix object $p$ is a unique interface type that has those members whose names and signatures are listed above.
+% What is the static type of a prefix object. Need to state that is a(n anonymous) type that has members with the same names as signatures as above.
+
 % This is problematic, because it implies that p.T would be available even in a scope that declared p. We really need to think of p as a single object with properties p.T etc., except it isn't really that
 % either. After all, p isn't actually available as a stand alone name.
 
@@ -6877,14 +6948,10 @@
 A URI of the form \code{dart:$s$} is interpreted as a reference to a system library (\ref{imports}) $s$. 
  
 \LMHash{}
-A URI of the form \code{package:$s$} is interpreted as a URI of the form \code{packages/s} relative to an implementation specified location.
-
-\commentary{ 
-This location will often be the location of the root library presented to the Dart compiler. However, implementations may supply means to override or replace this choice.
-}
+A URI of the form \code{package:$s$} is interpreted in an implementation specific manner.
 
 \rationale{
-The intent is that, during development, Dart programmers can rely on a package manager to find elements of their program. Such package managers may provide a directory structure starting at a local directory \code{packages} where they place the required dart code (or links thereto).
+The intent is that, during development, Dart programmers can rely on a package manager to find elements of their program. 
 }
 
 \LMHash{}
@@ -7270,7 +7337,7 @@
 %\commentary{Need to specify how a function values dynamic type is derived from its static signature.}
 
 \LMHash{}
-A function type $(T_1, \ldots T_{k}, [T_{k+1}  \ldots, T_{n+m}]) \rightarrow T$ is a more specific than the
+A function type $(T_1, \ldots T_{k}, [T_{k+1}  \ldots, T_{n+m}]) \rightarrow T$ is more specific than the
 function type $(S_1, \ldots, S_{k+j}, [S_{k+j+1} \ldots, S_{n}]) \rightarrow S$, if all of the following conditions are met:
 \begin{enumerate}
 \item Either
@@ -7438,7 +7505,8 @@
 \LMHash{}
 The least upper bound of \DYNAMIC{} and any type $T$ is \DYNAMIC{}.
 The least upper bound of \VOID{} and any type $T \ne \DYNAMIC{}$ is \VOID{}.
-Let $U$ be a type variable with upper bound $B$. The least upper bound of $U$ and a type $T$ is the least upper bound of $B$ and $T$. 
+The least upper bound of $\bot$ and any type $T$ is $T$.
+Let $U$ be a type variable with upper bound $B$. The least upper bound of $U$ and a type $T \ne \bot$ is the least upper bound of $B$ and $T$. 
 
 \LMHash{}
 The least upper bound relation is symmetric and reflexive.
diff --git a/pkg/analysis_server/lib/src/analysis_server.dart b/pkg/analysis_server/lib/src/analysis_server.dart
index 9d8f6b3..d42eb49 100644
--- a/pkg/analysis_server/lib/src/analysis_server.dart
+++ b/pkg/analysis_server/lib/src/analysis_server.dart
@@ -23,8 +23,6 @@
 import 'package:analysis_server/src/source/optimizing_pub_package_map_provider.dart';
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/instrumentation/instrumentation.dart';
-import 'package:analyzer/src/context/cache.dart';
-import 'package:analyzer/src/context/context.dart' as newContext;
 import 'package:analyzer/src/generated/ast.dart';
 import 'package:analyzer/src/generated/element.dart';
 import 'package:analyzer/src/generated/engine.dart';
@@ -33,8 +31,6 @@
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/source_io.dart';
 import 'package:analyzer/src/generated/utilities_general.dart';
-import 'package:analyzer/src/task/dart.dart';
-import 'package:analyzer/task/dart.dart';
 import 'package:plugin/plugin.dart';
 
 typedef void OptionUpdater(AnalysisOptionsImpl options);
@@ -1026,24 +1022,12 @@
     });
   }
 
-  void test_flushResolvedUnit(String file) {
+  void test_flushAstStructures(String file) {
     if (AnalysisEngine.isDartFileName(file)) {
       ContextSourcePair contextSource = getContextSourcePair(file);
-      AnalysisContext context = contextSource.context;
+      InternalAnalysisContext context = contextSource.context;
       Source source = contextSource.source;
-      if (context is AnalysisContextImpl) {
-        DartEntry dartEntry = context.getReadableSourceEntryOrNull(source);
-        dartEntry.flushAstStructures();
-      } else if (context is newContext.AnalysisContextImpl) {
-        CacheEntry entry = context.getCacheEntry(source);
-        entry.setState(RESOLVED_UNIT1, CacheState.FLUSHED);
-        entry.setState(RESOLVED_UNIT2, CacheState.FLUSHED);
-        entry.setState(RESOLVED_UNIT3, CacheState.FLUSHED);
-        entry.setState(RESOLVED_UNIT4, CacheState.FLUSHED);
-        entry.setState(RESOLVED_UNIT5, CacheState.FLUSHED);
-        entry.setState(RESOLVED_UNIT6, CacheState.FLUSHED);
-        entry.setState(RESOLVED_UNIT, CacheState.FLUSHED);
-      }
+      context.test_flushAstStructures(source);
     }
   }
 
diff --git a/pkg/analysis_server/lib/src/computer/computer_navigation.dart b/pkg/analysis_server/lib/src/computer/computer_navigation.dart
index 2236ee4..504bf40 100644
--- a/pkg/analysis_server/lib/src/computer/computer_navigation.dart
+++ b/pkg/analysis_server/lib/src/computer/computer_navigation.dart
@@ -10,6 +10,7 @@
 import 'package:analyzer/src/generated/ast.dart';
 import 'package:analyzer/src/generated/element.dart';
 import 'package:analyzer/src/generated/scanner.dart';
+import 'package:analyzer/src/generated/source.dart';
 
 /**
  * A computer for navigation regions in a Dart [CompilationUnit].
@@ -161,8 +162,8 @@
   visitExportDirective(ExportDirective node) {
     ExportElement exportElement = node.element;
     if (exportElement != null) {
-      Element element = exportElement.exportedLibrary;
-      computer._addRegion_tokenStart_nodeEnd(node.keyword, node.uri, element);
+      Element libraryElement = exportElement.exportedLibrary;
+      _addUriDirectiveRegion(node, libraryElement);
     }
     super.visitExportDirective(node);
   }
@@ -171,8 +172,8 @@
   visitImportDirective(ImportDirective node) {
     ImportElement importElement = node.element;
     if (importElement != null) {
-      Element element = importElement.importedLibrary;
-      computer._addRegion_tokenStart_nodeEnd(node.keyword, node.uri, element);
+      Element libraryElement = importElement.importedLibrary;
+      _addUriDirectiveRegion(node, libraryElement);
     }
     super.visitImportDirective(node);
   }
@@ -185,8 +186,7 @@
 
   @override
   visitPartDirective(PartDirective node) {
-    computer._addRegion_tokenStart_nodeEnd(
-        node.keyword, node.uri, node.element);
+    _addUriDirectiveRegion(node, node.element);
     super.visitPartDirective(node);
   }
 
@@ -260,6 +260,19 @@
     }
   }
 
+  /**
+   * If the source of the given [element] (referenced by the [node]) exists,
+   * then add the navigation region from the [node] to the [element].
+   */
+  void _addUriDirectiveRegion(UriBasedDirective node, Element element) {
+    if (element != null) {
+      Source source = element.source;
+      if (element.context.exists(source)) {
+        computer._addRegion_tokenStart_nodeEnd(node.keyword, node.uri, element);
+      }
+    }
+  }
+
   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 bfa8cb6..c397a80 100644
--- a/pkg/analysis_server/lib/src/context_manager.dart
+++ b/pkg/analysis_server/lib/src/context_manager.dart
@@ -387,11 +387,22 @@
   }
 
   /**
+   * Cancel all dependency subscriptions for the given context.
+   */
+  void _cancelDependencySubscriptions(_ContextInfo info) {
+    for (StreamSubscription<WatchEvent> s in info.dependencySubscriptions) {
+      s.cancel();
+    }
+    info.dependencySubscriptions.clear();
+  }
+
+  /**
    * Compute the appropriate package URI resolver for [folder], and store
    * dependency information in [info]. Return `null` if no package map can
    * be computed.
    */
   UriResolver _computePackageUriResolver(Folder folder, _ContextInfo info) {
+    _cancelDependencySubscriptions(info);
     if (info.packageRoot != null) {
       info.packageMapInfo = null;
       JavaFile packagesDir = new JavaFile(info.packageRoot);
@@ -425,6 +436,25 @@
             _packageMapProvider.computePackageMap(folder, info.packageMapInfo);
       });
       endComputePackageMap();
+      for (String dependencyPath in packageMapInfo.dependencies) {
+        Resource resource = resourceProvider.getResource(dependencyPath);
+        if (resource is File) {
+          StreamSubscription<WatchEvent> subscription;
+          subscription = resource.changes.listen((WatchEvent event) {
+            if (info.packageMapInfo != null &&
+                info.packageMapInfo.isChangedDependency(
+                    dependencyPath, resourceProvider)) {
+              _recomputePackageUriResolver(info);
+            }
+          }, onError: (error, StackTrace stackTrace) {
+            // Gracefully degrade if file is or becomes unwatchable
+            _instrumentationService.logException(error, stackTrace);
+            subscription.cancel();
+            info.dependencySubscriptions.remove(subscription);
+          });
+          info.dependencySubscriptions.add(subscription);
+        }
+      }
       info.packageMapInfo = packageMapInfo;
       if (packageMapInfo.packageMap == null) {
         return null;
@@ -513,7 +543,9 @@
    * Clean up and destroy the context associated with the given folder.
    */
   void _destroyContext(Folder folder) {
-    _contexts[folder].changeSubscription.cancel();
+    _ContextInfo info = _contexts[folder];
+    info.changeSubscription.cancel();
+    _cancelDependencySubscriptions(info);
     removeContext(folder);
     _contexts.remove(folder);
   }
@@ -749,6 +781,13 @@
   StreamSubscription<WatchEvent> changeSubscription;
 
   /**
+   * Stream subscriptions we are using to watch the files
+   * used to determine the package map.
+   */
+  final List<StreamSubscription<WatchEvent>> dependencySubscriptions =
+      <StreamSubscription<WatchEvent>>[];
+
+  /**
    * The analysis context that was created for the [folder].
    */
   AnalysisContext context;
diff --git a/pkg/analysis_server/lib/src/operation/operation_analysis.dart b/pkg/analysis_server/lib/src/operation/operation_analysis.dart
index 918deb8..1e71683 100644
--- a/pkg/analysis_server/lib/src/operation/operation_analysis.dart
+++ b/pkg/analysis_server/lib/src/operation/operation_analysis.dart
@@ -240,7 +240,14 @@
     // prepare results
     AnalysisResult result = context.performAnalysisTask();
     List<ChangeNotice> notices = result.changeNotices;
+    // nothing to analyze
     if (notices == null) {
+      bool cacheInconsistencyFixed = context.validateCacheConsistency();
+      if (cacheInconsistencyFixed) {
+        server.addOperation(new PerformAnalysisOperation(context, true));
+        return;
+      }
+      // analysis is done
       setCacheSize(context, IDLE_CACHE_SIZE);
       server.sendContextAnalysisDoneNotifications(
           context, AnalysisDoneReason.COMPLETE);
diff --git a/pkg/analysis_server/lib/src/protocol.dart b/pkg/analysis_server/lib/src/protocol.dart
index 8cee0f6..8a15ebe 100644
--- a/pkg/analysis_server/lib/src/protocol.dart
+++ b/pkg/analysis_server/lib/src/protocol.dart
@@ -518,12 +518,12 @@
    * have the following format:
    *
    *   {
+   *     'clientRequestTime': millisecondsSinceEpoch
    *     'id': String,
    *     'method': methodName,
    *     'params': {
    *       paramter_name: value
    *     }
-   *     'clientRequestTime': millisecondsSinceEpoch
    *   }
    *
    * where both the parameters and clientRequestTime are optional.
@@ -534,30 +534,53 @@
   factory Request.fromString(String data) {
     try {
       var result = JSON.decode(data);
-      if (result is! Map) {
-        return null;
+      if (result is Map) {
+        return new Request.fromJson(result);
       }
-      var id = result[Request.ID];
-      var method = result[Request.METHOD];
-      if (id is! String || method is! String) {
-        return null;
-      }
-      var time = result[Request.CLIENT_REQUEST_TIME];
-      if (time != null && time is! int) {
-        return null;
-      }
-      var params = result[Request.PARAMS];
-      if (params is Map || params == null) {
-        return new Request(id, method, params, time);
-      } else {
-        return null;
-      }
+      return null;
     } catch (exception) {
       return null;
     }
   }
 
   /**
+   * Return a request parsed from the given json, or `null` if the [data] is
+   * not a valid json representation of a request. The [data] is expected to
+   * have the following format:
+   *
+   *   {
+   *     'clientRequestTime': millisecondsSinceEpoch
+   *     'id': String,
+   *     'method': methodName,
+   *     'params': {
+   *       paramter_name: value
+   *     }
+   *   }
+   *
+   * where both the parameters and clientRequestTime are optional.
+   * The parameters can contain any number of name/value pairs.
+   * The clientRequestTime must be an int representing the time at which
+   * the client issued the request (milliseconds since epoch).
+   */
+  factory Request.fromJson(Map<String, dynamic> result) {
+    var id = result[Request.ID];
+    var method = result[Request.METHOD];
+    if (id is! String || method is! String) {
+      return null;
+    }
+    var time = result[Request.CLIENT_REQUEST_TIME];
+    if (time != null && time is! int) {
+      return null;
+    }
+    var params = result[Request.PARAMS];
+    if (params is Map || params == null) {
+      return new Request(id, method, params, time);
+    } else {
+      return null;
+    }
+  }
+
+  /**
    * Return a table representing the structure of the Json object that will be
    * sent to the client to represent this response.
    */
diff --git a/pkg/analysis_server/lib/src/services/completion/keyword_contributor.dart b/pkg/analysis_server/lib/src/services/completion/keyword_contributor.dart
index ce253e9..33dfa58 100644
--- a/pkg/analysis_server/lib/src/services/completion/keyword_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/keyword_contributor.dart
@@ -145,29 +145,19 @@
   }
 
   @override
+  visitPropertyAccess(PropertyAccess node) {
+    // suggestions before '.' but not after
+    if (entity != node.propertyName) {
+      super.visitPropertyAccess(node);
+    }
+  }
+
+  @override
   visitExpression(Expression node) {
     _addExpressionKeywords(node);
   }
 
   @override
-  visitInstanceCreationExpression(InstanceCreationExpression node) {
-    if (entity == node.constructorName) {
-      // no keywords in 'new ^' expression
-    } else {
-      super.visitInstanceCreationExpression(node);
-    }
-  }
-
-  @override
-  visitMethodInvocation(MethodInvocation node) {
-    if (entity == node.methodName) {
-      // no keywords in '.' expression
-    } else {
-      super.visitMethodInvocation(node);
-    }
-  }
-
-  @override
   visitExpressionFunctionBody(ExpressionFunctionBody node) {
     if (entity == node.expression) {
       _addExpressionKeywords(node);
@@ -201,6 +191,8 @@
   visitIfStatement(IfStatement node) {
     if (entity == node.thenStatement) {
       _addStatementKeywords(node);
+    } else if (entity == node.condition) {
+      _addExpressionKeywords(node);
     }
   }
 
@@ -217,6 +209,20 @@
   }
 
   @override
+  visitInstanceCreationExpression(InstanceCreationExpression node) {
+    if (entity == node.constructorName) {
+      // no keywords in 'new ^' expression
+    } else {
+      super.visitInstanceCreationExpression(node);
+    }
+  }
+
+  @override
+  visitLibraryIdentifier(LibraryIdentifier node) {
+    // no suggestions
+  }
+
+  @override
   visitMethodDeclaration(MethodDeclaration node) {
     if (entity == node.body) {
       if (node.body is EmptyFunctionBody) {
@@ -229,6 +235,15 @@
   }
 
   @override
+  visitMethodInvocation(MethodInvocation node) {
+    if (entity == node.methodName) {
+      // no keywords in '.' expression
+    } else {
+      super.visitMethodInvocation(node);
+    }
+  }
+
+  @override
   visitNamedExpression(NamedExpression node) {
     if (entity is SimpleIdentifier && entity == node.expression) {
       _addExpressionKeywords(node);
@@ -360,7 +375,7 @@
       Keyword.CONTINUE,
       Keyword.DO,
       Keyword.FINAL,
-      Keyword.FOR,
+      //Keyword.FOR,
       Keyword.IF,
       Keyword.NEW,
       Keyword.RETURN,
@@ -371,6 +386,7 @@
       Keyword.VOID,
       Keyword.WHILE
     ]);
+    _addSuggestion2('for ()', offset: 5);
     _addSuggestion(Keyword.RETHROW, DART_RELEVANCE_KEYWORD - 1);
   }
 
diff --git a/pkg/analysis_server/pubspec.yaml b/pkg/analysis_server/pubspec.yaml
index 49f6084..6f5124c 100644
--- a/pkg/analysis_server/pubspec.yaml
+++ b/pkg/analysis_server/pubspec.yaml
@@ -6,7 +6,7 @@
 environment:
   sdk: '>=1.9.0 <2.0.0'
 dependencies:
-  analyzer: '>=0.25.1-alpha.1 <0.26.0'
+  analyzer: '>=0.25.1-alpha.4 <0.26.0'
   args: '>=0.13.0 <0.14.0'
   dart_style: '>=0.1.7 <0.2.0'
   logging: any
diff --git a/pkg/analysis_server/test/analysis/update_content_test.dart b/pkg/analysis_server/test/analysis/update_content_test.dart
index e137ab9..b8c313d 100644
--- a/pkg/analysis_server/test/analysis/update_content_test.dart
+++ b/pkg/analysis_server/test/analysis/update_content_test.dart
@@ -205,7 +205,7 @@
     await server.onAnalysisComplete;
     // clear errors and make a no-op change
     filesErrors.clear();
-    server.test_flushResolvedUnit(testFile);
+    server.test_flushAstStructures(testFile);
     server.updateContent('2', {
       testFile: new ChangeContentOverlay([new SourceEdit(0, 4, 'main')])
     });
diff --git a/pkg/analysis_server/test/analysis_server_test.dart b/pkg/analysis_server/test/analysis_server_test.dart
index 5a03f56..d05602f 100644
--- a/pkg/analysis_server/test/analysis_server_test.dart
+++ b/pkg/analysis_server/test/analysis_server_test.dart
@@ -320,12 +320,12 @@
       subscriptions[service] = <String>[bar.path].toSet();
     }
     server.setAnalysisSubscriptions(subscriptions);
-    await pumpEventQueue(200);
+    await pumpEventQueue(500);
     expect(server.statusAnalyzing, isFalse);
     channel.notificationsReceived.clear();
     server.updateContent(
         '0', {bar.path: new AddContentOverlay('library bar; void f() {}')});
-    await pumpEventQueue(200);
+    await pumpEventQueue(500);
     expect(server.statusAnalyzing, isFalse);
     expect(channel.notificationsReceived, isNotEmpty);
     Set<String> notificationTypesReceived = new Set<String>();
@@ -428,6 +428,7 @@
     AnalysisResult firstResult = new AnalysisResult([notice], 0, '', 0);
     AnalysisResult lastResult = new AnalysisResult(null, 1, '', 1);
     when(context.analysisOptions).thenReturn(new AnalysisOptionsImpl());
+    when(context.validateCacheConsistency()).thenReturn(false);
     when(context.performAnalysisTask)
         .thenReturnList([firstResult, firstResult, firstResult, lastResult]);
     server.serverServices.add(ServerService.STATUS);
diff --git a/pkg/analysis_server/test/completion_test.dart b/pkg/analysis_server/test/completion_test.dart
index 883170b..bd78eda 100644
--- a/pkg/analysis_server/test/completion_test.dart
+++ b/pkg/analysis_server/test/completion_test.dart
@@ -1951,9 +1951,9 @@
       "1+while",
       "2+do",
       "3+while",
-      "4+for",
+      "4+for (!)",
       "5+in",
-      "6+for",
+      "6+for (!)",
       "7+switch",
       "8+case",
       "9+default",
diff --git a/pkg/analysis_server/test/context_manager_test.dart b/pkg/analysis_server/test/context_manager_test.dart
index ba4210d..2908cde 100644
--- a/pkg/analysis_server/test/context_manager_test.dart
+++ b/pkg/analysis_server/test/context_manager_test.dart
@@ -858,6 +858,34 @@
     });
   }
 
+  test_watch_modifyPackageMapDependency_outsideProject() {
+    // create a dependency file
+    String dependencyPath = '/my/other/dep';
+    resourceProvider.newFile(dependencyPath, 'contents');
+    packageMapProvider.dependencies.add(dependencyPath);
+    // create a Dart file
+    String dartFilePath = posix.join(projPath, 'main.dart');
+    resourceProvider.newFile(dartFilePath, 'contents');
+    // the created context has the expected empty package map
+    manager.setRoots(<String>[projPath], <String>[], <String, String>{});
+    _checkPackageMap(projPath, isEmpty);
+    // configure package map
+    String packagePath = '/package/foo';
+    resourceProvider.newFolder(packagePath);
+    packageMapProvider.packageMap = {'foo': projPath};
+    // Changing a .dart file in the project shouldn't cause a new
+    // package map to be picked up.
+    resourceProvider.modifyFile(dartFilePath, 'new contents');
+    return pumpEventQueue().then((_) {
+      _checkPackageMap(projPath, isEmpty);
+      // However, changing the package map dependency should.
+      resourceProvider.modifyFile(dependencyPath, 'new contents');
+      return pumpEventQueue().then((_) {
+        _checkPackageMap(projPath, equals(packageMapProvider.packageMap));
+      });
+    });
+  }
+
   test_watch_modifyPackageMapDependency_redundantly() async {
     // Create two dependency files
     String dependencyPath1 = posix.join(projPath, 'dep1');
diff --git a/pkg/analysis_server/test/integration/integration_tests.dart b/pkg/analysis_server/test/integration/integration_tests.dart
index 98e9860..3b7e13a 100644
--- a/pkg/analysis_server/test/integration/integration_tests.dart
+++ b/pkg/analysis_server/test/integration/integration_tests.dart
@@ -152,7 +152,7 @@
     });
     onServerError.listen((ServerErrorParams params) {
       // A server error should never happen during an integration test.
-      fail(params.message);
+      fail('${params.message}\n${params.stackTrace}');
     });
     return server.start().then((_) {
       server.listenToOutput(dispatchNotification);
diff --git a/pkg/analysis_server/test/performance/driver.dart b/pkg/analysis_server/test/performance/driver.dart
index ca34e27..b84aa8c 100644
--- a/pkg/analysis_server/test/performance/driver.dart
+++ b/pkg/analysis_server/test/performance/driver.dart
@@ -1,6 +1,11 @@
+// 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 server.driver;
 
 import 'dart:async';
+import 'dart:math' show max;
 
 import 'package:logging/logging.dart';
 
@@ -8,6 +13,24 @@
 import '../integration/integration_tests.dart';
 import 'operation.dart';
 
+final SPACE = ' '.codeUnitAt(0);
+
+void _printColumn(StringBuffer sb, String text, int keyLen,
+    {bool rightJustified: false}) {
+  if (!rightJustified) {
+    sb.write(text);
+    sb.write(',');
+  }
+  for (int i = text.length; i < keyLen; ++i) {
+    sb.writeCharCode(SPACE);
+  }
+  if (rightJustified) {
+    sb.write(text);
+    sb.write(',');
+  }
+  sb.writeCharCode(SPACE);
+}
+
 /**
  * [Driver] launches and manages an instance of analysis server,
  * reads a stream of operations, sends requests to analysis server
@@ -19,7 +42,7 @@
    * before forcibly terminating it.
    */
   static const Duration SHUTDOWN_TIMEOUT = const Duration(seconds: 5);
-  
+
   final Logger logger;
 
   /**
@@ -97,13 +120,13 @@
   /**
    * Shutdown the analysis server if it is running.
    */
-  Future stopServer() async {
+  Future stopServer([Duration timeout = SHUTDOWN_TIMEOUT]) async {
     if (running) {
       logger.log(Level.FINE, 'requesting server shutdown');
       // Give the server a short time to comply with the shutdown request; if it
       // doesn't exit, then forcibly terminate it.
       sendServerShutdown();
-      await server.exitCode.timeout(SHUTDOWN_TIMEOUT, onTimeout: () {
+      await server.exitCode.timeout(timeout, onTimeout: () {
         return server.kill();
       });
     }
@@ -121,6 +144,43 @@
 }
 
 /**
+ * [Measurement] tracks elapsed time for a given operation.
+ */
+class Measurement {
+  final String tag;
+  final List<Duration> elapsedTimes = new List<Duration>();
+  int errorCount = 0;
+
+  Measurement(this.tag);
+
+  void printSummary(int keyLen) {
+    int count = 0;
+    int totalTimeMicros = 0;
+    for (Duration elapsed in elapsedTimes) {
+      ++count;
+      totalTimeMicros += elapsed.inMicroseconds;
+    }
+    int averageTimeMicros = (totalTimeMicros / count).round();
+    StringBuffer sb = new StringBuffer();
+    _printColumn(sb, tag, keyLen);
+    _printColumn(sb, count.toString(), 5, rightJustified: true);
+    _printColumn(sb, errorCount.toString(), 5, rightJustified: true);
+    sb.write('  ');
+    sb.write(new Duration(microseconds: averageTimeMicros));
+    sb.write(',   ');
+    sb.write(new Duration(microseconds: totalTimeMicros));
+    print(sb.toString());
+  }
+
+  void record(bool success, Duration elapsed) {
+    if (!success) {
+      ++errorCount;
+    }
+    elapsedTimes.add(elapsed);
+  }
+}
+
+/**
  * [Results] contains information gathered by [Driver]
  * while running the analysis server
  */
@@ -132,45 +192,38 @@
    */
   void printResults() {
     print('==================================================================');
-    print('Results:');
-    for (String tag in measurements.keys.toList()..sort()) {
-      measurements[tag].printResults();
+    List<String> keys = measurements.keys.toList()..sort();
+    int keyLen = keys.fold(0, (int len, String key) => max(len, key.length));
+    StringBuffer sb = new StringBuffer();
+    _printColumn(sb, 'Results', keyLen);
+    _printColumn(sb, 'count', 5);
+    _printColumn(sb, 'errors', 5);
+    sb.write('   average,          total,');
+    print(sb.toString());
+    int totalCount = 0;
+    int totalErrorCount = 0;
+    for (String tag in keys) {
+      Measurement m = measurements[tag];
+      m.printSummary(keyLen);
+      totalCount += m.elapsedTimes.length;
+      totalErrorCount += m.errorCount;
     }
+    sb.clear();
+    _printColumn(sb, 'Totals', keyLen);
+    _printColumn(sb, totalCount.toString(), 5);
+    _printColumn(sb, totalErrorCount.toString(), 5);
+    print(sb.toString());
   }
 
   /**
    * Record the elapsed time for the given operation.
    */
-  void record(String tag, Duration elapsed) {
+  void record(String tag, Duration elapsed, {bool success: true}) {
     Measurement measurement = measurements[tag];
     if (measurement == null) {
       measurement = new Measurement(tag);
       measurements[tag] = measurement;
     }
-    measurement.record(elapsed);
-  }
-}
-
-/**
- * [Measurement] tracks elapsed time for a given operation.
- */
-class Measurement {
-  final String tag;
-  final List<Duration> elapsedTimes = new List<Duration>();
-  
-  Measurement(this.tag);
-
-  void record(Duration elapsed) {
-    elapsedTimes.add(elapsed);
-  }
-
-  void printResults() {
-    if (elapsedTimes.length == 0) {
-      return;
-    }
-    print('=== $tag');
-    for (Duration elapsed in elapsedTimes) {
-      print(elapsed);
-    }
+    measurement.record(success, elapsed);
   }
 }
diff --git a/pkg/analysis_server/test/performance/input_converter.dart b/pkg/analysis_server/test/performance/input_converter.dart
index d2167fb..9acf61a 100644
--- a/pkg/analysis_server/test/performance/input_converter.dart
+++ b/pkg/analysis_server/test/performance/input_converter.dart
@@ -1,12 +1,259 @@
+// 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 input.transformer;
 
 import 'dart:convert';
+import 'dart:io';
+
+import 'package:analysis_server/src/constants.dart';
+import 'package:analysis_server/src/protocol.dart';
+import 'package:analyzer/src/generated/java_engine.dart';
+import 'package:logging/logging.dart';
+import 'package:path/path.dart' as path;
 
 import 'instrumentation_input_converter.dart';
+import 'log_file_input_converter.dart';
 import 'operation.dart';
 
-final int NINE = '9'.codeUnitAt(0);
-final int ZERO = '0'.codeUnitAt(0);
+/**
+ * Common input converter superclass for sharing implementation.
+ */
+abstract class CommonInputConverter extends Converter<String, Operation> {
+  static final ERROR_PREFIX = 'Server responded with an error: ';
+  final Logger logger = new Logger('InstrumentationInputConverter');
+  final Set<String> eventsSeen = new Set<String>();
+
+  /**
+   * A mapping from request/response id to expected error message.
+   */
+  final Map<String, dynamic> expectedErrors = new Map<String, dynamic>();
+
+  /**
+   * A mapping of current overlay content
+   * parallel to what is in the analysis server
+   * so that we can update the file system.
+   */
+  final Map<String, String> overlays = new Map<String, String>();
+
+  /**
+   * The prefix used to determine if a request parameter is a file path.
+   */
+  final String rootPrefix = path.rootPrefix(path.current);
+
+  /**
+   * A mapping of source path prefixes
+   * from location where instrumentation or log file was generated
+   * to the target location of the source using during performance measurement.
+   */
+  final Map<String, String> srcPathMap;
+
+  /**
+   * The root directory for all source being modified
+   * during performance measurement.
+   */
+  final String tmpSrcDirPath;
+
+  CommonInputConverter(this.tmpSrcDirPath, this.srcPathMap);
+
+  /**
+   * Return an operation for the notification or `null` if none.
+   */
+  Operation convertNotification(Map<String, dynamic> json) {
+    String event = json['event'];
+    if (event == SERVER_STATUS) {
+      // {"event":"server.status","params":{"analysis":{"isAnalyzing":false}}}
+      Map<String, dynamic> params = json['params'];
+      if (params != null) {
+        Map<String, dynamic> analysis = params['analysis'];
+        if (analysis != null && analysis['isAnalyzing'] == false) {
+          return new WaitForAnalysisCompleteOperation();
+        }
+      }
+    }
+    if (event == SERVER_CONNECTED) {
+      // {"event":"server.connected","params":{"version":"1.7.0"}}
+      return new StartServerOperation();
+    }
+    if (eventsSeen.add(event)) {
+      logger.log(Level.INFO, 'Ignored notification: $event\n  $json');
+    }
+    return null;
+  }
+
+  /**
+   * Return an operation for the request or `null` if none.
+   */
+  Operation convertRequest(Map<String, dynamic> origJson) {
+    Map<String, dynamic> json = translateSrcPaths(origJson);
+    String method = json['method'];
+    // Sanity check operations that modify source
+    // to ensure that the operation is on source in temp space
+    if (method == ANALYSIS_UPDATE_CONTENT) {
+      try {
+        validateSrcPaths(json);
+      } catch (e, s) {
+        throw new AnalysisException('invalid src path in update request\n$json',
+            new CaughtException(e, s));
+      }
+      // Track overlays in parallel with the analysis server
+      // so that when an overlay is removed, the file can be updated on disk
+      Request request = new Request.fromJson(json);
+      var params = new AnalysisUpdateContentParams.fromRequest(request);
+      params.files.forEach((String path, change) {
+        if (change is AddContentOverlay) {
+          String content = change.content;
+          if (content == null) {
+            throw 'expected new overlay content\n$json';
+          }
+          overlays[path] = content;
+        } else if (change is ChangeContentOverlay) {
+          String content = overlays[path];
+          if (content == null) {
+            throw 'expected cached overlay content\n$json';
+          }
+          overlays[path] = SourceEdit.applySequence(content, change.edits);
+        } else if (change is RemoveContentOverlay) {
+          String content = overlays.remove(path);
+          if (content == null) {
+            throw 'expected cached overlay content\n$json';
+          }
+          validateSrcPaths(path);
+          new File(path).writeAsStringSync(content);
+        } else {
+          throw 'unknown overlay change $change\n$json';
+        }
+      });
+      return new RequestOperation(this, json);
+    }
+    // TODO(danrubel) replace this with code 
+    // that just forwards the translated request
+    if (method == ANALYSIS_GET_HOVER ||
+        method == ANALYSIS_SET_ANALYSIS_ROOTS ||
+        method == ANALYSIS_SET_PRIORITY_FILES ||
+        method == ANALYSIS_SET_SUBSCRIPTIONS ||
+        method == ANALYSIS_UPDATE_OPTIONS ||
+        method == COMPLETION_GET_SUGGESTIONS ||
+        method == EDIT_GET_ASSISTS ||
+        method == EDIT_GET_AVAILABLE_REFACTORINGS ||
+        method == EDIT_GET_FIXES ||
+        method == EDIT_GET_REFACTORING ||
+        method == EDIT_SORT_MEMBERS ||
+        method == EXECUTION_CREATE_CONTEXT ||
+        method == EXECUTION_DELETE_CONTEXT ||
+        method == EXECUTION_MAP_URI ||
+        method == EXECUTION_SET_SUBSCRIPTIONS ||
+        method == SEARCH_FIND_ELEMENT_REFERENCES ||
+        method == SERVER_GET_VERSION ||
+        method == SERVER_SET_SUBSCRIPTIONS) {
+      return new RequestOperation(this, json);
+    }
+    throw 'unknown request: $method\n  $json';
+  }
+
+  /**
+   * Determine if the given request is expected to fail
+   * and log an exception if not.
+   */
+  void recordErrorResponse(Map<String, dynamic> jsonRequest, exception) {
+    var actualErr;
+    if (exception is UnimplementedError) {
+      if (exception.message.startsWith(ERROR_PREFIX)) {
+        Map<String, dynamic> jsonResponse =
+            JSON.decode(exception.message.substring(ERROR_PREFIX.length));
+        actualErr = jsonResponse['error'];
+      }
+    }
+    String id = jsonRequest['id'];
+    if (id != null && actualErr != null) {
+      var expectedErr = expectedErrors[id];
+      if (expectedErr != null && actualErr == expectedErr) {
+        return;
+      }
+//      if (jsonRequest['method'] == EDIT_SORT_MEMBERS) {
+//        var params = jsonRequest['params'];
+//        if (params is Map) {
+//          var filePath = params['file'];
+//          if (filePath is String) {
+//            var content = overlays[filePath];
+//            if (content is String) {
+//              logger.log(Level.WARNING, 'sort failed: $filePath\n$content');
+//            }
+//          }
+//        }
+//      }
+    }
+    logger.log(
+        Level.SEVERE, 'Send request failed for $id\n$exception\n$jsonRequest');
+  }
+
+  /**
+   * Examine recorded responses and record any expected errors.
+   */
+  void recordResponse(Map<String, dynamic> json) {
+    var error = json['error'];
+    if (error != null) {
+      String id = json['id'];
+      print('expected error for $id is $error');
+    }
+  }
+
+  /**
+   * Recursively translate source paths in the specified JSON to reference
+   * the temporary source used during performance measurement rather than
+   * the original source when the instrumentation or log file was generated.
+   */
+  translateSrcPaths(json) {
+    if (json is String) {
+      String result = json;
+      srcPathMap.forEach((String oldPrefix, String newPrefix) {
+        if (json.startsWith(oldPrefix)) {
+          result = '$newPrefix${json.substring(oldPrefix.length)}';
+        }
+      });
+      return result;
+    }
+    if (json is List) {
+      List result = [];
+      for (int i = 0; i < json.length; ++i) {
+        result.add(translateSrcPaths(json[i]));
+      }
+      return result;
+    }
+    if (json is Map) {
+      Map<String, dynamic> result = new Map<String, dynamic>();
+      json.forEach((String origKey, value) {
+        result[translateSrcPaths(origKey)] = translateSrcPaths(value);
+      });
+      return result;
+    }
+    return json;
+  }
+
+  /**
+   * Recursively verify that the source paths in the specified JSON
+   * only reference the temporary source used during performance measurement.
+   */
+  void validateSrcPaths(json) {
+    if (json is String) {
+      if (json != null &&
+          path.isWithin(rootPrefix, json) &&
+          !path.isWithin(tmpSrcDirPath, json)) {
+        throw 'found path referencing source outside temp space\n$json';
+      }
+    } else if (json is List) {
+      for (int i = json.length - 1; i >= 0; --i) {
+        validateSrcPaths(json[i]);
+      }
+    } else if (json is Map) {
+      json.forEach((String key, value) {
+        validateSrcPaths(key);
+        validateSrcPaths(value);
+      });
+    }
+  }
+}
 
 /**
  * [InputConverter] converts an input stream
@@ -14,6 +261,20 @@
  * The input stream can be either an instrumenation or log file.
  */
 class InputConverter extends Converter<String, Operation> {
+  final Logger logger = new Logger('InputConverter');
+
+  /**
+   * A mapping of source path prefixes
+   * from location where instrumentation or log file was generated
+   * to the target location of the source using during performance measurement.
+   */
+  final Map<String, String> srcPathMap;
+
+  /**
+   * The root directory for all source being modified
+   * during performance measurement.
+   */
+  final String tmpSrcDirPath;
 
   /**
    * The number of lines read before the underlying converter was determined
@@ -27,23 +288,39 @@
    */
   Converter<String, Operation> converter;
 
+  /**
+   * [active] is `true` if converting lines to operations
+   * or `false` if an exception has occurred.
+   */
+  bool active = true;
+
+  InputConverter(this.tmpSrcDirPath, this.srcPathMap);
+
   @override
   Operation convert(String line) {
+    if (!active) {
+      return null;
+    }
     if (converter != null) {
-      return converter.convert(line);
+      try {
+        return converter.convert(line);
+      } catch (e) {
+        active = false;
+        rethrow;
+      }
     }
     if (headerLineCount == 20) {
       throw 'Failed to determine input file format';
     }
     if (InstrumentationInputConverter.isFormat(line)) {
-      converter = new InstrumentationInputConverter();
+      converter = new InstrumentationInputConverter(tmpSrcDirPath, srcPathMap);
     } else if (LogFileInputConverter.isFormat(line)) {
-      converter = new LogFileInputConverter();
+      converter = new LogFileInputConverter(tmpSrcDirPath, srcPathMap);
     }
     if (converter != null) {
       return converter.convert(line);
     }
-    print(line);
+    logger.log(Level.INFO, 'skipped input line: $line');
     return null;
   }
 
@@ -53,47 +330,6 @@
   }
 }
 
-/**
- * [LogFileInputConverter] converts a log file stream
- * into a series of operations to be sent to the analysis server.
- */
-class LogFileInputConverter extends Converter<String, Operation> {
-  @override
-  Operation convert(String line) {
-    throw 'not implemented yet';
-  }
-
-  /**
-   * Determine if the given line is from an instrumentation file.
-   * For example:
-   * `1428347977499 <= {"event":"server.connected","params":{"version":"1.6.0"}}`
-   */
-  static bool isFormat(String line) {
-    String timeStampString = _parseTimeStamp(line);
-    int start = timeStampString.length;
-    int end = start + 5;
-    return start > 10 &&
-        line.length > end &&
-        line.substring(start, end) == ' <= {"event":"server.connected"';
-  }
-
-  /**
-   * Parse the given line and return the millisecond timestamp or `null`
-   * if it cannot be determined.
-   */
-  static String _parseTimeStamp(String line) {
-    int index = 0;
-    while (index < line.length) {
-      int code = line.codeUnitAt(index);
-      if (code < ZERO || NINE < code) {
-        return line.substring(0, index);
-      }
-      ++index;
-    }
-    return line;
-  }
-}
-
 class _InputSink extends ChunkedConversionSink<String> {
   final Converter<String, Operation> converter;
   final outSink;
diff --git a/pkg/analysis_server/test/performance/instrumentation_input_converter.dart b/pkg/analysis_server/test/performance/instrumentation_input_converter.dart
index 4e027cf..b0f9c61 100644
--- a/pkg/analysis_server/test/performance/instrumentation_input_converter.dart
+++ b/pkg/analysis_server/test/performance/instrumentation_input_converter.dart
@@ -1,9 +1,16 @@
+// 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 input.transformer.instrumentation;
 
 import 'dart:convert';
 
+import 'package:analyzer/src/generated/java_engine.dart';
+import 'package:analyzer/instrumentation/instrumentation.dart';
 import 'package:logging/logging.dart';
 
+import 'input_converter.dart';
 import 'operation.dart';
 
 final int COLON = ':'.codeUnitAt(0);
@@ -12,87 +19,90 @@
  * [InstrumentationInputConverter] converts an instrumentation stream
  * into a series of operations to be sent to the analysis server.
  */
-class InstrumentationInputConverter extends Converter<String, Operation> {
-  final Logger logger = new Logger('InstrumentationInputConverter');
-  final Set<String> _codesSeen = new Set<String>();
-  final Set<String> _methodsSeen = new Set<String>();
-  final Set<String> _eventsSeen = new Set<String>();
+class InstrumentationInputConverter extends CommonInputConverter {
+  final Set<String> codesSeen = new Set<String>();
+
+  /**
+   * [readBuffer] holds the contents of the file being read from disk
+   * as recorded in the instrumentation log
+   * or `null` if not converting a "Read" entry.
+   */
+  StringBuffer readBuffer = null;
+
+  InstrumentationInputConverter(
+      String tmpSrcDirPath, Map<String, String> srcPathMap)
+      : super(tmpSrcDirPath, srcPathMap);
 
   @override
   Operation convert(String line) {
+    List<String> fields;
     try {
-      List<String> fields = _parseFields(line);
+      fields = _parseFields(line);
       if (fields.length < 2) {
-        //return new InfoOperation('Ignored line:\n  $line');
-        return null;
-      }
-      // int timeStamp = int.parse(fields[0], onError: (_) => -1);
-      String opCode = fields[1];
-      if (opCode == 'Req') {
-        return convertRequest(line, fields);
-      }
-      if (opCode == 'Noti') {
-        return convertNotification(fields);
-      }
-      if (opCode == 'Ver') {
-        // 1433195174666:Ver:1421765742287333878467:org.dartlang.dartplugin:0.0.0:1.7.0:1.11.0-edge.131698
-        return new StartServerOperation();
-      }
-      if (_codesSeen.add(opCode)) {
-        logger.log(Level.INFO, 'Ignored op code: $opCode\n  $line');
-      }
-      return null;
-    } catch (e, s) {
-      throw 'Failed to parse line\n  $line\n$e\n$s';
-    }
-  }
-
-  /**
-   * Return an operation for the notification defined by [line] and [fields]
-   * or `null` if none.
-   */
-  Operation convertNotification(List<String> fields) {
-    //1433344448533:Noti:{"event"::"server.status","params"::{"analysis"::{"isAnalyzing"::false}}}
-    Map<String, dynamic> json = JSON.decode(fields[2]);
-    String event = json['event'];
-    if (event == 'server.status') {
-      Map<String, dynamic> params = json['params'];
-      if (params != null) {
-        Map<String, dynamic> analysis = params['analysis'];
-        if (analysis != null && analysis['isAnalyzing'] == false) {
-          return new WaitForAnalysisCompleteOperation();
+        if (readBuffer != null) {
+          readBuffer.writeln(fields.length == 1 ? fields[0] : '');
+          return null;
         }
+        throw 'Failed to process line:\n$line';
       }
+      if (readBuffer != null) {
+        readBuffer = null;
+      }
+    } catch (e, s) {
+      throw new AnalysisException(
+          'Failed to parse line\n$line', new CaughtException(e, s));
     }
-    if (event == 'server.connected') {
-      // Handled by the driver
+    // int timeStamp = int.parse(fields[0], onError: (_) => -1);
+    String opCode = fields[1];
+    if (opCode == InstrumentationService.TAG_NOTIFICATION) {
+      return convertNotification(decodeJson(line, fields[2]));
+    } else if (opCode == 'Read') {
+      // 1434096943209:Read:/some/file/path:1434095535000:<file content>
+      //String filePath = fields[2];
+      readBuffer = new StringBuffer(fields.length > 4 ? fields[4] : '');
+      return null;
+    } else if (opCode == InstrumentationService.TAG_REQUEST) {
+      return convertRequest(decodeJson(line, fields[2]));
+    } else if (opCode == InstrumentationService.TAG_RESPONSE) {
+      // 1434096937454:Res:{"id"::"0","result"::{"version"::"1.7.0"}}
+      recordResponse(decodeJson(line, fields[2]));
+      return null;
+    } else if (opCode == InstrumentationService.TAG_ANALYSIS_TASK) {
+      // 1434096943208:Task:/Users/
+      return null;
+    } else if (opCode == InstrumentationService.TAG_LOG_ENTRY) {
+      // 1434096937454:Res:{"id"::"0","result"::{"version"::"1.7.0"}}
+      return null;
+    } else if (opCode == InstrumentationService.TAG_PERFORMANCE) {
+      //1434096960092:Perf:analysis_full:16884:context_id=0
+      return null;
+    } else if (opCode == InstrumentationService.TAG_SUBPROCESS_START) {
+      // 1434096938634:SPStart:0:/Users/da
+      return null;
+    } else if (opCode == InstrumentationService.TAG_SUBPROCESS_RESULT) {
+      // 1434096939068:SPResult:0:0:"{\"packages\"::{\"rpi_lidar\"::\"/Users
+      return null;
+    } else if (opCode == InstrumentationService.TAG_VERSION) {
+      // 1434096937358:Ver:1421765742287333878467:org.dartlang.dartplugin
+      return null;
+    } else if (opCode == InstrumentationService.TAG_WATCH_EVENT) {
+      // 1434097460414:Watch:/some/file/path
       return null;
     }
-    if (_eventsSeen.add(event)) {
-      logger.log(Level.INFO, 'Ignored notification: $event');
+    if (codesSeen.add(opCode)) {
+      logger.log(
+          Level.WARNING, 'Ignored instrumentation op code: $opCode\n  $line');
     }
     return null;
   }
 
-  /**
-   * Return an operation for the request defined by [line] and [fields]
-   * or `null` if none.
-   */
-  Operation convertRequest(String line, List<String> fields) {
-    Map<String, dynamic> json = JSON.decode(fields[2]);
-    String method = json['method'];
-    if (method == 'analysis.setAnalysisRoots') {
-      // 1433343174749:Req:{"id"::"3","method"::"analysis.setAnalysisRoots","params"::{"included"::["/usr/local/google/home/danrubel/work/git/dart_sdk/sdk/pkg/analysis_server","/usr/local/google/home/danrubel/work/git/dart_sdk/sdk/pkg/analyzer"],"excluded"::[],"packageRoots"::{}},"clientRequestTime"::1433343174702}
-      return new RequestOperation(json);
+  Map<String, dynamic> decodeJson(String line, String text) {
+    try {
+      return JSON.decode(text);
+    } catch (e, s) {
+      throw new AnalysisException(
+          'Failed to decode JSON: $text\n$line', new CaughtException(e, s));
     }
-    if (method == 'server.setSubscriptions') {
-      // 1433343174741:Req:{"id"::"1","method"::"server.setSubscriptions","params"::{"subscriptions"::["STATUS"]},"clientRequestTime"::1433343172679}
-      return new RequestOperation(json);
-    }
-    if (_methodsSeen.add(method)) {
-      logger.log(Level.INFO, 'Ignored request: $method\n  $line');
-    }
-    return null;
   }
 
   /**
@@ -102,6 +112,7 @@
    */
   static bool isFormat(String line) {
     List<String> fields = _parseFields(line);
+    if (fields.length < 2) return false;
     int timeStamp = int.parse(fields[0], onError: (_) => -1);
     String opCode = fields[1];
     return timeStamp > 0 && opCode == 'Ver';
diff --git a/pkg/analysis_server/test/performance/local_runner.dart b/pkg/analysis_server/test/performance/local_runner.dart
new file mode 100644
index 0000000..0cbe6e1
--- /dev/null
+++ b/pkg/analysis_server/test/performance/local_runner.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 'dart:io';
+import 'package:path/path.dart';
+import 'main.dart' as performance;
+
+// Local driver for performance measurement
+
+main(List<String> args) {
+  /*
+   * Parse arguments
+   */
+  if (args.length != 3) printHelp('Expected 3 arguments');
+  var gitDir = new Directory(args[0]);
+  if (!gitDir.existsSync()) printHelp('${gitDir.path} does not exist');
+  if (!new Directory(join(gitDir.path, '.git')).existsSync()) printHelp(
+      '${gitDir.path} does not appear to be a local git repository');
+  var branch = args[1];
+  var inputFile = new File(args[2]);
+  if (!inputFile.existsSync()) printHelp('${inputFile.path} does not exist');
+  /*
+   * Create a new temp directory
+   */
+  var tmpDir = new Directory(
+      join(Directory.systemTemp.path, 'analysis_server_perf_target'));
+  if (!tmpDir.path.contains('tmp')) throw 'invalid tmp directory\n  $tmpDir';
+  print('Extracting target analysis environment into\n  ${tmpDir.path}');
+  if (tmpDir.existsSync()) tmpDir.deleteSync(recursive: true);
+  tmpDir.createSync(recursive: true);
+  /*
+   * Setup the initial target source in the temp directory
+   */
+  var tarFilePath = join(tmpDir.path, 'targetSrc.tar');
+  var result = Process.runSync('git', ['archive', branch, '-o', tarFilePath],
+      workingDirectory: gitDir.path);
+  if (result.exitCode != 0) throw 'failed to obtain target source: $result';
+  var tmpSrcDirPath = join(tmpDir.path, 'targetSrc');
+  new Directory(tmpSrcDirPath).createSync();
+  result = Process.runSync('tar', ['-xf', tarFilePath],
+      workingDirectory: tmpSrcDirPath);
+  if (result.exitCode != 0) throw 'failed to extract target source: $result';
+  /*
+   * Symlink the out or xcodebuild directory
+   */
+  var outDirName = 'out';
+  if (!new Directory(join(gitDir.path, outDirName)).existsSync()) {
+    outDirName = 'xcodebuild';
+  }
+  if (!new Directory(join(gitDir.path, outDirName)).existsSync()) {
+    throw 'failed to find out or xcodebuild directory';
+  }
+  result = Process.runSync('ln', [
+    '-s',
+    join(gitDir.path, outDirName),
+    join(tmpSrcDirPath, outDirName)
+  ]);
+  if (result.exitCode != 0) throw 'failed to link out or xcodebuild: $result';
+  /*
+   * Launch the performance analysis tool
+   */
+  performance.main([
+    //'-vv', // very verbose
+    '-i',
+    inputFile.path,
+    '-t',
+    tmpSrcDirPath,
+    '-m',
+    '${gitDir.path},$tmpSrcDirPath',
+  ]);
+}
+
+/// Print help and exit
+void printHelp([String errMsg]) {
+  if (errMsg != null) {
+    print('');
+    print('Error: $errMsg');
+    print('');
+  }
+  print('Arguments: <gitDir> <branch> <inputFile>');
+  print('gitDir = git repository containing the initial target source');
+  print('branch = the branch containing the initial target source');
+  print('inputFile = the instrumentation or log file');
+  exit(1);
+}
diff --git a/pkg/analysis_server/test/performance/log_file_input_converter.dart b/pkg/analysis_server/test/performance/log_file_input_converter.dart
new file mode 100644
index 0000000..c15c450
--- /dev/null
+++ b/pkg/analysis_server/test/performance/log_file_input_converter.dart
@@ -0,0 +1,83 @@
+// 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 input.transformer.log_file;
+
+import 'dart:convert';
+
+import 'package:analyzer/src/generated/java_engine.dart';
+import 'package:logging/logging.dart';
+
+import 'input_converter.dart';
+import 'operation.dart';
+
+const CONNECTED_MSG_FRAGMENT = ' <= {"event":"server.connected"';
+final int NINE = '9'.codeUnitAt(0);
+const RECEIVED_FRAGMENT = ' <= {';
+const SENT_FRAGMENT = ' => {';
+final int ZERO = '0'.codeUnitAt(0);
+
+/**
+ * [LogFileInputConverter] converts a log file stream
+ * into a series of operations to be sent to the analysis server.
+ */
+class LogFileInputConverter extends CommonInputConverter {
+  LogFileInputConverter(String tmpSrcDirPath, Map<String, String> srcPathMap)
+      : super(tmpSrcDirPath, srcPathMap);
+
+  @override
+  Operation convert(String line) {
+    try {
+      String timeStampString = _parseTimeStamp(line);
+      String data = line.substring(timeStampString.length);
+      if (data.startsWith(RECEIVED_FRAGMENT)) {
+        Map<String, dynamic> json = JSON.decode(data.substring(4));
+        if (json.containsKey('event')) {
+          return convertNotification(json);
+        }
+        return null;
+      } else if (data.startsWith(SENT_FRAGMENT)) {
+        Map<String, dynamic> json = JSON.decode(data.substring(4));
+        if (json.containsKey('method')) {
+          return convertRequest(json);
+        }
+        return null;
+      }
+      logger.log(Level.INFO, 'unknown input line: $line');
+      return null;
+    } catch (e, s) {
+      throw new AnalysisException(
+          'Failed to parse line\n  $line', new CaughtException(e, s));
+    }
+  }
+
+  /**
+   * Determine if the given line is from an instrumentation file.
+   * For example:
+   * `1428347977499 <= {"event":"server.connected","params":{"version":"1.6.0"}}`
+   */
+  static bool isFormat(String line) {
+    String timeStampString = _parseTimeStamp(line);
+    int start = timeStampString.length;
+    int end = start + CONNECTED_MSG_FRAGMENT.length;
+    return (10 < start && end < line.length) &&
+        line.substring(start, end) == CONNECTED_MSG_FRAGMENT;
+  }
+
+  /**
+   * Parse the given line and return the millisecond timestamp or `null`
+   * if it cannot be determined.
+   */
+  static String _parseTimeStamp(String line) {
+    int index = 0;
+    while (index < line.length) {
+      int code = line.codeUnitAt(index);
+      if (code < ZERO || NINE < code) {
+        return line.substring(0, index);
+      }
+      ++index;
+    }
+    return line;
+  }
+}
diff --git a/pkg/analysis_server/test/performance/main.dart b/pkg/analysis_server/test/performance/main.dart
index 8604876..d7ec220 100644
--- a/pkg/analysis_server/test/performance/main.dart
+++ b/pkg/analysis_server/test/performance/main.dart
@@ -1,3 +1,7 @@
+// 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 server.performance;
 
 import 'dart:async';
@@ -12,6 +16,12 @@
 import 'operation.dart';
 
 /**
+ * The amount of time to give the server to respond to a shutdown request
+ * before forcibly terminating it.
+ */
+const Duration SHUTDOWN_TIMEOUT = const Duration(seconds: 25);
+
+/**
  * Launch and interact with the analysis server.
  */
 main(List<String> rawArgs) {
@@ -19,9 +29,9 @@
   logger.onRecord.listen((LogRecord rec) {
     print(rec.message);
   });
-  Driver driver = new Driver(logger);
+  PerfArgs args = parseArgs(rawArgs);
 
-  ArgResults args = parseArgs(rawArgs);
+  Driver driver = new Driver(logger);
   Stream<Operation> stream = openInput(args);
   StreamSubscription<Operation> subscription;
   subscription = stream.listen((Operation op) {
@@ -34,12 +44,11 @@
     }
   }, onDone: () {
     subscription.cancel();
-    driver.stopServer();
+    driver.stopServer(SHUTDOWN_TIMEOUT);
   }, onError: (e, s) {
     subscription.cancel();
-    logger.log(Level.WARNING, '$e\n$s');
-    driver.stopServer();
-    throw e;
+    logger.log(Level.SEVERE, '$e\n$s');
+    driver.stopServer(SHUTDOWN_TIMEOUT);
   });
   driver.runComplete.then((Results results) {
     results.printResults();
@@ -50,6 +59,8 @@
 
 const HELP_CMDLINE_OPTION = 'help';
 const INPUT_CMDLINE_OPTION = 'input';
+const MAP_OPTION = 'map';
+const TMP_SRC_DIR_OPTION = 'tmpSrcDir';
 const VERBOSE_CMDLINE_OPTION = 'verbose';
 const VERY_VERBOSE_CMDLINE_OPTION = 'vv';
 
@@ -57,34 +68,47 @@
  * Open and return the input stream specifying how this client
  * should interact with the analysis server.
  */
-Stream<Operation> openInput(ArgResults args) {
+Stream<Operation> openInput(PerfArgs args) {
+  var logger = new Logger('openInput');
   Stream<List<int>> inputRaw;
-  String inputPath = args[INPUT_CMDLINE_OPTION];
-  if (inputPath == null) {
-    return null;
-  }
-  if (inputPath == 'stdin') {
+  if (args.inputPath == 'stdin') {
     inputRaw = stdin;
   } else {
-    inputRaw = new File(inputPath).openRead();
+    inputRaw = new File(args.inputPath).openRead();
   }
+  args.srcPathMap.forEach((oldPath, newPath) {
+    logger.log(
+        Level.INFO, 'mapping source path\n  from $oldPath\n  to   $newPath');
+  });
+  logger.log(Level.INFO, 'tmpSrcDir: ${args.tmpSrcDirPath}');
   return inputRaw
       .transform(SYSTEM_ENCODING.decoder)
       .transform(new LineSplitter())
-      .transform(new InputConverter());
+      .transform(new InputConverter(args.tmpSrcDirPath, args.srcPathMap));
 }
 
 /**
  * Parse the command line arguments.
  */
-ArgResults parseArgs(List<String> rawArgs) {
+PerfArgs parseArgs(List<String> rawArgs) {
   ArgParser parser = new ArgParser();
 
-  parser.addOption(INPUT_CMDLINE_OPTION,
-      abbr: 'i',
-      help: 'The input file specifying how this client should interact '
-      'with the server. If the input file name is "stdin", '
-      'then the instructions are read from standard input.');
+  parser.addOption(INPUT_CMDLINE_OPTION, abbr: 'i', help: '<filePath>\n'
+      'The input file specifying how this client should interact with the server.\n'
+      'If the input file name is "stdin", then the instructions are read from standard input.');
+  parser.addOption(MAP_OPTION,
+      abbr: 'm',
+      allowMultiple: true,
+      splitCommas: false,
+      help: '<oldSrcPath>,<newSrcPath>\n'
+      'This option defines a mapping from the original source directory <oldSrcPath>\n'
+      'when the instrumentation or log file was generated\n'
+      'to the target source directory <newSrcPath> used during performance testing.\n'
+      'Multiple mappings can be specified.\n'
+      'WARNING: The contents of the target directory will be modified');
+  parser.addOption(TMP_SRC_DIR_OPTION, abbr: 't', help: '<dirPath>\n'
+      'The temporary directory containing source used during performance measurement.\n'
+      'WARNING: The contents of the target directory will be modified');
   parser.addFlag(VERBOSE_CMDLINE_OPTION,
       abbr: 'v', help: 'Verbose logging', negatable: false);
   parser.addFlag(VERY_VERBOSE_CMDLINE_OPTION,
@@ -92,15 +116,50 @@
   parser.addFlag(HELP_CMDLINE_OPTION,
       abbr: 'h', help: 'Print this help information', negatable: false);
 
-  ArgResults args = parser.parse(rawArgs);
+  ArgResults args;
+  PerfArgs perfArgs = new PerfArgs();
+  try {
+    args = parser.parse(rawArgs);
+  } on Exception catch (e) {
+    print(e);
+    printHelp(parser);
+    exit(1);
+  }
+
   bool showHelp = args[HELP_CMDLINE_OPTION] || args.rest.isNotEmpty;
 
-  if (args[INPUT_CMDLINE_OPTION] == null ||
-      args[INPUT_CMDLINE_OPTION].isEmpty) {
-    print('missing "input" argument');
+  bool isMissing(key) => args[key] == null || args[key].isEmpty;
+
+  perfArgs.inputPath = args[INPUT_CMDLINE_OPTION];
+  if (isMissing(INPUT_CMDLINE_OPTION)) {
+    print('missing $INPUT_CMDLINE_OPTION argument');
     showHelp = true;
   }
-  
+
+  perfArgs.srcPathMap = <String, String>{};
+  for (String pair in args[MAP_OPTION]) {
+    if (pair is String) {
+      int index = pair.indexOf(',');
+      if (index != -1 && pair.indexOf(',', index + 1) == -1) {
+        String oldSrcPath = pair.substring(0, index);
+        String newSrcPath = pair.substring(index + 1);
+        if (new Directory(oldSrcPath).existsSync() &&
+            new Directory(newSrcPath).existsSync()) {
+          perfArgs.srcPathMap[oldSrcPath] = newSrcPath;
+          continue;
+        }
+      }
+    }
+    print('must specifiy $MAP_OPTION <oldSrcPath>,<newSrcPath>');
+    showHelp = true;
+  }
+
+  perfArgs.tmpSrcDirPath = args[TMP_SRC_DIR_OPTION];
+  if (isMissing(TMP_SRC_DIR_OPTION)) {
+    print('missing $TMP_SRC_DIR_OPTION argument');
+    showHelp = true;
+  }
+
   if (args[VERY_VERBOSE_CMDLINE_OPTION] || rawArgs.contains('-vv')) {
     Logger.root.level = Level.FINE;
   } else if (args[VERBOSE_CMDLINE_OPTION]) {
@@ -110,11 +169,41 @@
   }
 
   if (showHelp) {
-    print('');
-    print('Launch and interact with the AnalysisServer');
-    print(parser.usage);
+    printHelp(parser);
     exit(1);
   }
 
-  return args;
+  return perfArgs;
+}
+
+void printHelp(ArgParser parser) {
+  print('');
+  print('Launch and interact with the AnalysisServer');
+  print('');
+  print(parser.usage);
+}
+
+/**
+ * The performance measurement arguments specified on the command line.
+ */
+class PerfArgs {
+
+  /**
+   * The file path of the instrumentation or log file 
+   * used to drive performance measurement,
+   * or 'stdin' if this information should be read from standard input.
+   */
+  String inputPath;
+
+  /**
+   * A mapping from the original source directory
+   * when the instrumentation or log file was generated
+   * to the target source directory used during performance testing.
+   */
+  Map<String, String> srcPathMap;
+
+  /**
+   * The temporary directory containing source used during performance measurement.
+   */
+  String tmpSrcDirPath;
 }
diff --git a/pkg/analysis_server/test/performance/operation.dart b/pkg/analysis_server/test/performance/operation.dart
index 0e30aea..5952252 100644
--- a/pkg/analysis_server/test/performance/operation.dart
+++ b/pkg/analysis_server/test/performance/operation.dart
@@ -1,3 +1,7 @@
+// 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 server.operation;
 
 import 'dart:async';
@@ -6,18 +10,7 @@
 import 'package:logging/logging.dart';
 
 import 'driver.dart';
-
-class InfoOperation extends Operation {
-  final String message;
-
-  InfoOperation(this.message);
-
-  @override
-  Future perform(Driver driver) {
-    driver.logger.log(Level.INFO, message);
-    return null;
-  }
-}
+import 'input_converter.dart';
 
 /**
  * An [Operation] represents an action such as sending a request to the server.
@@ -30,19 +23,29 @@
  * A [RequestOperation] sends a [JSON] request to the server.
  */
 class RequestOperation extends Operation {
+  final CommonInputConverter converter;
   final Map<String, dynamic> json;
 
-  RequestOperation(this.json);
+  RequestOperation(this.converter, this.json);
 
   @override
   Future perform(Driver driver) {
+    Stopwatch stopwatch = new Stopwatch();
     String method = json['method'];
     driver.logger.log(Level.FINE, 'Sending request: $method\n  $json');
+    stopwatch.start();
+    void recordResponse(bool success, response) {
+      stopwatch.stop();
+      Duration elapsed = stopwatch.elapsed;
+      driver.results.record(method, elapsed, success: success);
+      driver.logger.log(
+          Level.FINE, 'Response received: $method : $elapsed\n  $response');
+    }
     driver.send(method, json['params']).then((response) {
-      driver.logger.log(Level.FINE, 'Response received: $method : $response');
+      recordResponse(true, response);
     }).catchError((e, s) {
-      driver.logger.log(Level.WARNING, 'Request failed: $method\n  $e\n$s');
-      throw 'Send request failed: $e';
+      recordResponse(false, e);
+      converter.recordErrorResponse(json, e);
     });
     return null;
   }
diff --git a/pkg/analysis_server/test/protocol_server_test.dart b/pkg/analysis_server/test/protocol_server_test.dart
index fca8b53..6c9fedb 100644
--- a/pkg/analysis_server/test/protocol_server_test.dart
+++ b/pkg/analysis_server/test/protocol_server_test.dart
@@ -275,8 +275,7 @@
     engine.CompilationUnit unit = resolveLibraryUnit(source);
     {
       engine.ClassElement engineElement = findElementInUnit(unit, '_E1');
-      // TODO (danrubel) determine why enum is not deprecated
-      expect(engineElement.isDeprecated, isFalse);
+      expect(engineElement.isDeprecated, isTrue);
       // create notification Element
       Element element = newElement_fromEngine(engineElement);
       expect(element.kind, ElementKind.ENUM);
@@ -329,11 +328,11 @@
       expect(element.parameters, isNull);
       expect(element.returnType, '_E1');
       // TODO(danrubel) determine why enum constant is not marked as deprecated
-      engine.ClassElement classElement = engineElement.enclosingElement;
+      //engine.ClassElement classElement = engineElement.enclosingElement;
+      //expect(classElement.isDeprecated, isTrue);
       expect(element.flags,
-          (classElement.isDeprecated ? Element.FLAG_DEPRECATED : 0) |
-              Element.FLAG_CONST |
-              Element.FLAG_STATIC);
+          // Element.FLAG_DEPRECATED |
+          Element.FLAG_CONST | Element.FLAG_STATIC);
     }
     {
       engine.FieldElement engineElement = findElementInUnit(unit, 'three');
diff --git a/pkg/analysis_server/test/services/completion/keyword_contributor_test.dart b/pkg/analysis_server/test/services/completion/keyword_contributor_test.dart
index cbf3794..c9666b1 100644
--- a/pkg/analysis_server/test/services/completion/keyword_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/keyword_contributor_test.dart
@@ -172,20 +172,37 @@
     Keyword.TRUE,
   ];
 
+  static final Map<String, List<String>> keywordTemplates =
+      <String, List<String>>{
+    Keyword.IMPORT.syntax: [
+      "import '^';",
+      "import '^' as ;",
+      "import '^' hide ;",
+      "import '^' show ;"
+    ],
+    Keyword.FOR.syntax: ['for (^)']
+  };
+
   void assertSuggestKeywords(Iterable<Keyword> expectedKeywords,
       {List<String> pseudoKeywords: NO_PSEUDO_KEYWORDS,
       int relevance: DART_RELEVANCE_KEYWORD}) {
     Set<String> expectedCompletions = new Set<String>();
+    Map<String, int> expectedOffsets = <String, int>{};
     Set<String> actualCompletions = new Set<String>();
     expectedCompletions.addAll(expectedKeywords.map((k) => k.syntax));
     expectedCompletions.addAll(pseudoKeywords);
-    if (expectedCompletions.contains(Keyword.IMPORT.syntax)) {
-      expectedCompletions.remove(Keyword.IMPORT.syntax);
-      expectedCompletions.add("import '';");
-      expectedCompletions.add("import '' as ;");
-      expectedCompletions.add("import '' hide ;");
-      expectedCompletions.add("import '' show ;");
-    }
+    keywordTemplates.forEach((String key, List<String> templates) {
+      if (expectedCompletions.remove(key)) {
+        for (String t in templates) {
+          int offset = t.indexOf('^');
+          if (offset != -1) {
+            t = '${t.substring(0, offset)}${t.substring(offset + 1)}';
+            expectedOffsets[t] = offset;
+          }
+          expectedCompletions.add(t);
+        }
+      }
+    });
     for (CompletionSuggestion s in request.suggestions) {
       if (s.kind == CompletionSuggestionKind.KEYWORD) {
         Keyword k = Keyword.keywords[s.completion];
@@ -215,15 +232,18 @@
             ++importRelevance;
           }
           expect(s.relevance, equals(importRelevance), reason: s.completion);
-          expect(s.selectionOffset, equals(Keyword.IMPORT.syntax.length + 2));
         } else {
           if (s.completion == Keyword.RETHROW.syntax) {
             expect(s.relevance, equals(relevance - 1), reason: s.completion);
           } else {
             expect(s.relevance, equals(relevance), reason: s.completion);
           }
-          expect(s.selectionOffset, equals(s.completion.length));
         }
+        int expectedOffset = expectedOffsets[s.completion];
+        if (expectedOffset == null) {
+          expectedOffset = s.completion.length;
+        }
+        expect(s.selectionOffset, equals(expectedOffset));
         expect(s.selectionLength, equals(0));
         expect(s.isDeprecated, equals(false));
         expect(s.isPotential, equals(false));
@@ -646,6 +666,30 @@
     assertSuggestKeywords(STMT_START_OUTSIDE_CLASS, pseudoKeywords: ['await']);
   }
 
+  test_if_expression_in_class() {
+    addTestSource('class A {foo() {if (^) }}');
+    expect(computeFast(), isTrue);
+    assertSuggestKeywords(EXPRESSION_START_INSTANCE);
+  }
+
+  test_if_expression_in_class2() {
+    addTestSource('class A {foo() {if (n^) }}');
+    expect(computeFast(), isTrue);
+    assertSuggestKeywords(EXPRESSION_START_INSTANCE);
+  }
+
+  test_if_expression_in_function() {
+    addTestSource('foo() {if (^) }');
+    expect(computeFast(), isTrue);
+    assertSuggestKeywords(EXPRESSION_START_NO_INSTANCE);
+  }
+
+  test_if_expression_in_function2() {
+    addTestSource('foo() {if (n^) }');
+    expect(computeFast(), isTrue);
+    assertSuggestKeywords(EXPRESSION_START_NO_INSTANCE);
+  }
+
   test_if_in_class() {
     addTestSource('class A {foo() {if (true) ^}}');
     expect(computeFast(), isTrue);
@@ -799,6 +843,24 @@
         relevance: DART_RELEVANCE_HIGH);
   }
 
+  test_library_declaration() {
+    addTestSource('library ^');
+    expect(computeFast(), isTrue);
+    assertSuggestKeywords([]);
+  }
+
+  test_library_declaration2() {
+    addTestSource('library a^');
+    expect(computeFast(), isTrue);
+    assertSuggestKeywords([]);
+  }
+
+  test_library_declaration3() {
+    addTestSource('library a.^');
+    expect(computeFast(), isTrue);
+    assertSuggestKeywords([]);
+  }
+
   test_library_name() {
     addTestSource('library ^');
     expect(computeFast(), isTrue);
@@ -996,6 +1058,12 @@
     assertSuggestKeywords([]);
   }
 
+  test_prefixed_library() {
+    addTestSource('import "b" as b; class A { foo() {b.^}}');
+    expect(computeFast(), isTrue);
+    assertSuggestKeywords([]);
+  }
+
   test_prefixed_local() {
     addTestSource('class A { foo() {int x; x.^}}');
     expect(computeFast(), isTrue);
@@ -1008,6 +1076,12 @@
     assertSuggestKeywords([]);
   }
 
+  test_property_access() {
+    addTestSource('class A { get x => 7; foo() {new A().^}}');
+    expect(computeFast(), isTrue);
+    assertSuggestKeywords([]);
+  }
+
   test_switch_expression() {
     addTestSource('main() {switch(^) {}}');
     expect(computeFast(), isTrue);
diff --git a/pkg/analysis_server/test/services/index/dart_index_contributor_test.dart b/pkg/analysis_server/test/services/index/dart_index_contributor_test.dart
index d3fe203..a93591e 100644
--- a/pkg/analysis_server/test/services/index/dart_index_contributor_test.dart
+++ b/pkg/analysis_server/test/services/index/dart_index_contributor_test.dart
@@ -1502,7 +1502,7 @@
   LocationImpl _assertRecordedRelationForName(String expectedName,
       RelationshipImpl expectedRelationship,
       ExpectedLocation expectedLocation) {
-    _assertRecordedRelationForElement(
+    return _assertRecordedRelationForElement(
         new NameElement(expectedName), expectedRelationship, expectedLocation);
   }
 
diff --git a/pkg/analyzer/README.md b/pkg/analyzer/README.md
index 2423774..9dc9ce6 100644
--- a/pkg/analyzer/README.md
+++ b/pkg/analyzer/README.md
@@ -22,6 +22,6 @@
 
 Questions and requests for additional functionality are welcome, and can be made
 by either opening an issue at
-[https://code.google.com/p/dart/issues](https://code.google.com/p/dart/issues)
+[http://dartbug.com](http://dartbug.com)
 or by emailing
-[analyzer-discuss@dartlang.org](https://groups.google.com/a/dartlang.org/forum/#!forum/analyzer-discuss).
\ No newline at end of file
+[analyzer-discuss@dartlang.org](https://groups.google.com/a/dartlang.org/forum/#!forum/analyzer-discuss).
diff --git a/pkg/analyzer/lib/file_system/file_system.dart b/pkg/analyzer/lib/file_system/file_system.dart
index 6fb9885..9a41f81 100644
--- a/pkg/analyzer/lib/file_system/file_system.dart
+++ b/pkg/analyzer/lib/file_system/file_system.dart
@@ -15,6 +15,11 @@
  */
 abstract class File extends Resource {
   /**
+   * Watch for changes to this file
+   */
+  Stream<WatchEvent> get changes;
+  
+  /**
    * Return the last-modified stamp of the file.
    * Throws [FileSystemException] if the file does not exist.
    */
diff --git a/pkg/analyzer/lib/file_system/memory_file_system.dart b/pkg/analyzer/lib/file_system/memory_file_system.dart
index 8d1f114..a68a225 100644
--- a/pkg/analyzer/lib/file_system/memory_file_system.dart
+++ b/pkg/analyzer/lib/file_system/memory_file_system.dart
@@ -164,7 +164,7 @@
   void _notifyWatchers(String path, ChangeType changeType) {
     _pathToWatchers.forEach((String watcherPath,
         List<StreamController<WatchEvent>> streamControllers) {
-      if (posix.isWithin(watcherPath, path)) {
+      if (watcherPath == path || posix.isWithin(watcherPath, path)) {
         for (StreamController<WatchEvent> streamController
             in streamControllers) {
           streamController.add(new WatchEvent(changeType, path));
@@ -183,6 +183,11 @@
       : super(provider, path);
 
   @override
+  Stream<WatchEvent> get changes {
+    throw new FileSystemException(path, "File does not exist");
+  }
+
+  @override
   bool get exists => false;
 
   int get modificationStamp {
@@ -358,23 +363,6 @@
       : super(provider, path);
 
   @override
-  Stream<WatchEvent> get changes {
-    StreamController<WatchEvent> streamController =
-        new StreamController<WatchEvent>();
-    if (!_provider._pathToWatchers.containsKey(path)) {
-      _provider._pathToWatchers[path] = <StreamController<WatchEvent>>[];
-    }
-    _provider._pathToWatchers[path].add(streamController);
-    streamController.done.then((_) {
-      _provider._pathToWatchers[path].remove(streamController);
-      if (_provider._pathToWatchers[path].isEmpty) {
-        _provider._pathToWatchers.remove(path);
-      }
-    });
-    return streamController.stream;
-  }
-
-  @override
   bool get exists => _provider._pathToResource[path] is _MemoryFolder;
 
   @override
@@ -442,6 +430,22 @@
 
   _MemoryResource(this._provider, this.path);
 
+  Stream<WatchEvent> get changes {
+    StreamController<WatchEvent> streamController =
+        new StreamController<WatchEvent>();
+    if (!_provider._pathToWatchers.containsKey(path)) {
+      _provider._pathToWatchers[path] = <StreamController<WatchEvent>>[];
+    }
+    _provider._pathToWatchers[path].add(streamController);
+    streamController.done.then((_) {
+      _provider._pathToWatchers[path].remove(streamController);
+      if (_provider._pathToWatchers[path].isEmpty) {
+        _provider._pathToWatchers.remove(path);
+      }
+    });
+    return streamController.stream;
+  }
+
   @override
   get hashCode => path.hashCode;
 
diff --git a/pkg/analyzer/lib/file_system/physical_file_system.dart b/pkg/analyzer/lib/file_system/physical_file_system.dart
index 139d67d..9c9d5a6 100644
--- a/pkg/analyzer/lib/file_system/physical_file_system.dart
+++ b/pkg/analyzer/lib/file_system/physical_file_system.dart
@@ -73,6 +73,9 @@
  */
 class _PhysicalFile extends _PhysicalResource implements File {
   _PhysicalFile(io.File file) : super(file);
+ 
+  @override
+  Stream<WatchEvent> get changes => new FileWatcher(_entry.path).events;
 
   @override
   int get modificationStamp {
diff --git a/pkg/analyzer/lib/plugin/options.dart b/pkg/analyzer/lib/plugin/options.dart
new file mode 100644
index 0000000..cc0b88d
--- /dev/null
+++ b/pkg/analyzer/lib/plugin/options.dart
@@ -0,0 +1,61 @@
+// 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.
+
+/// Support for client code that wants to consume options contributed to the
+/// analysis options file.
+library analyzer.plugin.options;
+
+import 'package:analyzer/src/plugin/options_plugin.dart';
+import 'package:plugin/plugin.dart';
+import 'package:yaml/yaml.dart';
+
+/// The identifier of the extension point that allows plugins to access
+/// options defined in the analysis options file. The object used as an
+/// extension must be an [OptionsProcessor].
+final String OPTIONS_PROCESSOR_EXTENSION_POINT_ID = Plugin.join(
+    OptionsPlugin.UNIQUE_IDENTIFIER,
+    OptionsPlugin.OPTIONS_PROCESSOR_EXTENSION_POINT);
+
+/// Processes options defined in the analysis options file.
+/// 
+/// The options file format is intentionally very open-ended, giving clients
+/// utmost flexibility in defining their own options.  The only hardfast
+/// expectation is that options files will contain a mapping from Strings
+/// (identifying 'scopes') to associated options.  For example, the given
+/// content
+///
+///     linter:
+///       rules:
+///         camel_case_types: true
+///     compiler:
+///       resolver:
+///         useMultiPackage: true
+///       packagePaths:
+///         - /foo/bar/pkg
+///         - /bar/baz/pkg
+///
+/// defines two scopes, `linter` and `compiler`.  Parsing would result in a
+/// map, mapping the `linter` and `compiler` scope identifiers to their
+/// respective parsed option node contents. Extracting values is a simple
+/// matter of inspecting the parsed nodes.  For example, testing whether the
+/// compiler's resolver is set to use the `useMultiPackage` option might look
+/// something like this (eliding error-checking):
+///
+///     bool useMultiPackage =
+///         options['compiler']['resolver']['useMultiPackage'];
+abstract class OptionsProcessor {
+
+  /// Called when an error occurs in processing options.
+  void onError(Exception exception);
+
+  /// Called when the options file is processed.
+  ///
+  /// The options file is processed on analyzer initialization and
+  /// subsequently when the file is changed on disk.  In the event of a
+  /// change notification, note that the notification simply indicates
+  /// a change on disk. Content in specific option scopes may or may not
+  /// be different. It is up to the implementer to check whether specific
+  /// options have changed and to handle those changes appropriately.
+  void optionsProcessed(Map<String, YamlNode> options);
+}
diff --git a/pkg/analyzer/lib/src/context/cache.dart b/pkg/analyzer/lib/src/context/cache.dart
index c8aa54d..0b93d03 100644
--- a/pkg/analyzer/lib/src/context/cache.dart
+++ b/pkg/analyzer/lib/src/context/cache.dart
@@ -4,6 +4,7 @@
 
 library analyzer.src.context.cache;
 
+import 'dart:async';
 import 'dart:collection';
 
 import 'package:analyzer/src/generated/engine.dart'
@@ -36,12 +37,30 @@
   final List<CachePartition> _partitions;
 
   /**
+   * The [StreamController] reporting [InvalidatedResult]s.
+   */
+  final StreamController<InvalidatedResult> _onResultInvalidated =
+      new StreamController<InvalidatedResult>.broadcast(sync: true);
+
+  /**
    * Initialize a newly created cache to have the given [partitions]. The
    * partitions will be searched in the order in which they appear in the array,
    * so the most specific partition (usually an [SdkCachePartition]) should be
    * first and the most general (usually a [UniversalCachePartition]) last.
    */
-  AnalysisCache(this._partitions);
+  AnalysisCache(this._partitions) {
+    for (CachePartition partition in _partitions) {
+      partition.onResultInvalidated.listen((InvalidatedResult event) {
+        _onResultInvalidated.add(event);
+      });
+    }
+  }
+
+  /**
+   * Return the stream that is notified when a value is invalidated.
+   */
+  Stream<InvalidatedResult> get onResultInvalidated =>
+      _onResultInvalidated.stream;
 
   // TODO(brianwilkerson) Implement or delete this.
 //  /**
@@ -500,6 +519,9 @@
       _partition._targetMap.remove(target);
       _partition._removeIfSource(target);
     }
+    // Notify controller.
+    _partition._onResultInvalidated
+        .add(new InvalidatedResult(this, descriptor));
   }
 
   /**
@@ -744,6 +766,12 @@
       new HashMap<ResultCachingPolicy, CacheFlushManager>();
 
   /**
+   * The [StreamController] reporting [InvalidatedResult]s.
+   */
+  final StreamController<InvalidatedResult> _onResultInvalidated =
+      new StreamController<InvalidatedResult>.broadcast(sync: true);
+
+  /**
    * A table mapping the targets belonging to this partition to the information
    * known about those targets.
    */
@@ -776,6 +804,12 @@
   Map<AnalysisTarget, CacheEntry> get map => _targetMap;
 
   /**
+   * Return the stream that is notified when a value is invalidated.
+   */
+  Stream<InvalidatedResult> get onResultInvalidated =>
+      _onResultInvalidated.stream;
+
+  /**
    * Return the entry associated with the given [target].
    */
   CacheEntry get(AnalysisTarget target) => _targetMap[target];
@@ -926,6 +960,26 @@
 }
 
 /**
+ * [InvalidatedResult] describes an invalidated result.
+ */
+class InvalidatedResult {
+  /**
+   * The target in which the result was invalidated.
+   */
+  final CacheEntry entry;
+
+  /**
+   * The descriptor of the result which was invalidated.
+   */
+  final ResultDescriptor descriptor;
+
+  InvalidatedResult(this.entry, this.descriptor);
+
+  @override
+  String toString() => '$descriptor of ${entry.target}';
+}
+
+/**
  * The data about a single analysis result that is stored in a [CacheEntry].
  */
 // TODO(brianwilkerson) Consider making this a generic class so that the value
diff --git a/pkg/analyzer/lib/src/context/context.dart b/pkg/analyzer/lib/src/context/context.dart
index 4dcc143..c7a5c8d 100644
--- a/pkg/analyzer/lib/src/context/context.dart
+++ b/pkg/analyzer/lib/src/context/context.dart
@@ -21,7 +21,7 @@
         UniversalCachePartition,
         WorkManager;
 import 'package:analyzer/src/generated/error.dart';
-import 'package:analyzer/src/generated/html.dart' as ht;
+import 'package:analyzer/src/generated/html.dart' as ht show HtmlUnit;
 import 'package:analyzer/src/generated/incremental_resolver.dart';
 import 'package:analyzer/src/generated/java_core.dart';
 import 'package:analyzer/src/generated/java_engine.dart';
@@ -33,10 +33,14 @@
 import 'package:analyzer/src/task/dart.dart';
 import 'package:analyzer/src/task/dart_work_manager.dart';
 import 'package:analyzer/src/task/driver.dart';
+import 'package:analyzer/src/task/html.dart';
+import 'package:analyzer/src/task/html_work_manager.dart';
 import 'package:analyzer/src/task/manager.dart';
 import 'package:analyzer/task/dart.dart';
 import 'package:analyzer/task/general.dart';
+import 'package:analyzer/task/html.dart';
 import 'package:analyzer/task/model.dart';
+import 'package:html/dom.dart' show Document;
 
 /**
  * Type of callback functions used by PendingFuture. Functions of this type
@@ -122,6 +126,11 @@
   DartWorkManager dartWorkManager;
 
   /**
+   * The work manager that performs HTML specific scheduling.
+   */
+  HtmlWorkManager htmlWorkManager;
+
+  /**
    * The analysis driver used to perform analysis.
    */
   AnalysisDriver driver;
@@ -210,8 +219,9 @@
     _taskManager = AnalysisEngine.instance.taskManager;
     // TODO(scheglov) Get WorkManager(Factory)(s) from plugins.
     dartWorkManager = new DartWorkManager(this);
-    driver =
-        new AnalysisDriver(_taskManager, <WorkManager>[dartWorkManager], this);
+    htmlWorkManager = new HtmlWorkManager(this);
+    driver = new AnalysisDriver(
+        _taskManager, <WorkManager>[dartWorkManager, htmlWorkManager], this);
     _onSourcesChangedController =
         new StreamController<SourcesChangedEvent>.broadcast();
   }
@@ -255,6 +265,7 @@
     this._options.preserveComments = options.preserveComments;
     if (needsRecompute) {
       dartWorkManager.onAnalysisOptionsChanged();
+      htmlWorkManager.onAnalysisOptionsChanged();
     }
   }
 
@@ -273,6 +284,7 @@
       }
     }
     dartWorkManager.applyPriorityTargets(_priorityOrder);
+    htmlWorkManager.applyPriorityTargets(_priorityOrder);
   }
 
   @override
@@ -370,6 +382,7 @@
     _sourceFactory = factory;
     _cache = createCacheFromSourceFactory(factory);
     dartWorkManager.onSourceFactoryChanged();
+    htmlWorkManager.onSourceFactoryChanged();
   }
 
   @override
@@ -520,6 +533,8 @@
     }
     dartWorkManager.applyChange(
         changeSet.addedSources, changeSet.changedSources, removedSources);
+    htmlWorkManager.applyChange(
+        changeSet.addedSources, changeSet.changedSources, removedSources);
     _onSourcesChangedController.add(new SourcesChangedEvent(changeSet));
   }
 
@@ -560,16 +575,27 @@
   }
 
   @override
-  List<AnalysisError> computeErrors(Source source) =>
-      _computeResult(source, DART_ERRORS);
+  List<AnalysisError> computeErrors(Source source) {
+    String name = source.shortName;
+    if (AnalysisEngine.isDartFileName(name)) {
+      return _computeResult(source, DART_ERRORS);
+    } else if (AnalysisEngine.isHtmlFileName(name)) {
+      return _computeResult(source, HTML_ERRORS);
+    }
+    return AnalysisError.NO_ERRORS;
+  }
 
   @override
   List<Source> computeExportedLibraries(Source source) =>
       _computeResult(source, EXPORTED_LIBRARIES);
 
   @override
-  // TODO(brianwilkerson) Implement this.
-  HtmlElement computeHtmlElement(Source source) => null;
+  @deprecated
+  HtmlElement computeHtmlElement(Source source) {
+    // TODO(brianwilkerson) Remove this method after switching to the new task
+    // model.
+    throw new UnimplementedError('Not supported in the new task model');
+  }
 
   @override
   List<Source> computeImportedLibraries(Source source) =>
@@ -608,8 +634,9 @@
         !AnalysisEngine.isDartFileName(librarySource.shortName)) {
       return new CancelableFuture.error(new AnalysisNotScheduledError());
     }
+    var unitTarget = new LibrarySpecificUnit(librarySource, unitSource);
     return new _AnalysisFutureHelper<CompilationUnit>(this).computeAsync(
-        new LibrarySpecificUnit(librarySource, unitSource), (CacheEntry entry) {
+        unitTarget, (CacheEntry entry) {
       CacheState state = entry.getState(RESOLVED_UNIT);
       if (state == CacheState.ERROR) {
         throw entry.exception;
@@ -617,6 +644,8 @@
         return null;
       }
       return entry.getValue(RESOLVED_UNIT);
+    }, () {
+      dartWorkManager.addPriorityResult(unitTarget, RESOLVED_UNIT);
     });
   }
 
@@ -742,9 +771,6 @@
         }
         return element;
       }
-      if (AnalysisEngine.isHtmlFileName(sourceName)) {
-        return computeHtmlElement(source);
-      }
     } catch (exception) {
       // If the location cannot be decoded for some reason then the underlying
       // cause should have been logged already and we can fall though to return
@@ -755,54 +781,39 @@
 
   @override
   AnalysisErrorInfo getErrors(Source source) {
-    return dartWorkManager.getErrors(source);
+    String name = source.shortName;
+    if (AnalysisEngine.isDartFileName(name) || source is DartScript) {
+      return dartWorkManager.getErrors(source);
+    } else if (AnalysisEngine.isHtmlFileName(name)) {
+      return htmlWorkManager.getErrors(source);
+    }
+    return new AnalysisErrorInfoImpl(AnalysisError.NO_ERRORS, null);
   }
 
   @override
+  @deprecated
   HtmlElement getHtmlElement(Source source) {
-    // TODO(brianwilkerson) Implement this.
-//    SourceEntry sourceEntry = getReadableSourceEntryOrNull(source);
-//    if (sourceEntry is HtmlEntry) {
-//      return sourceEntry.getValue(HtmlEntry.ELEMENT);
-//    }
-    return null;
+    // TODO(brianwilkerson) Remove this method after switching to the new task
+    // model.
+    throw new UnimplementedError('Not supported in the new task model');
   }
 
   @override
   List<Source> getHtmlFilesReferencing(Source source) {
-    // TODO(brianwilkerson) Implement this.
-    SourceKind sourceKind = getKindOf(source);
-    if (sourceKind == null) {
+    if (!AnalysisEngine.isDartFileName(source.shortName)) {
       return Source.EMPTY_LIST;
     }
     List<Source> htmlSources = <Source>[];
-//    while (true) {
-//      if (sourceKind == SourceKind.PART) {
-//        List<Source> librarySources = getLibrariesContaining(source);
-//        for (Source source in _cache.sources) {
-//          CacheEntry entry = _cache.get(source);
-//          if (entry.getValue(SOURCE_KIND) == SourceKind.HTML) {
-//            List<Source> referencedLibraries =
-//                (entry as HtmlEntry).getValue(HtmlEntry.REFERENCED_LIBRARIES);
-//            if (_containsAny(referencedLibraries, librarySources)) {
-//              htmlSources.add(source);
-//            }
-//          }
-//        }
-//      } else {
-//        for (Source source in _cache.sources) {
-//          CacheEntry entry = _cache.get(source);
-//          if (entry.getValue(SOURCE_KIND) == SourceKind.HTML) {
-//            List<Source> referencedLibraries =
-//                (entry as HtmlEntry).getValue(HtmlEntry.REFERENCED_LIBRARIES);
-//            if (_contains(referencedLibraries, source)) {
-//              htmlSources.add(source);
-//            }
-//          }
-//        }
-//      }
-//      break;
-//    }
+    List<Source> librarySources = getLibrariesContaining(source);
+    for (Source source in _cache.sources) {
+      if (AnalysisEngine.isHtmlFileName(source.shortName)) {
+        List<Source> referencedLibraries =
+            analysisCache.getValue(source, REFERENCED_LIBRARIES);
+        if (_containsAny(referencedLibraries, librarySources)) {
+          htmlSources.add(source);
+        }
+      }
+    }
     if (htmlSources.isEmpty) {
       return Source.EMPTY_LIST;
     }
@@ -851,12 +862,10 @@
 
   @override
   List<Source> getLibrariesReferencedFromHtml(Source htmlSource) {
-    // TODO(brianwilkerson) Implement this.
-//    cache.CacheEntry entry = getReadableSourceEntryOrNull(htmlSource);
-//    if (entry is HtmlEntry) {
-//      HtmlEntry htmlEntry = entry;
-//      return htmlEntry.getValue(HtmlEntry.REFERENCED_LIBRARIES);
-//    }
+    CacheEntry entry = _cache.get(htmlSource);
+    if (entry != null) {
+      return entry.getValue(REFERENCED_LIBRARIES);
+    }
     return Source.EMPTY_LIST;
   }
 
@@ -899,13 +908,6 @@
     return builder.createPublicNamespaceForLibrary(library);
   }
 
-  /**
-   * Return the cache entry associated with the given [target], or `null` if
-   * there is no entry associated with the target.
-   */
-  CacheEntry getReadableSourceEntryOrNull(AnalysisTarget target) =>
-      _cache.get(target);
-
   @override
   CompilationUnit getResolvedCompilationUnit(
       Source unitSource, LibraryElement library) {
@@ -928,14 +930,11 @@
   }
 
   @override
+  @deprecated
   ht.HtmlUnit getResolvedHtmlUnit(Source htmlSource) {
-    // TODO(brianwilkerson) Implement this.
-//    SourceEntry sourceEntry = getReadableSourceEntryOrNull(htmlSource);
-//    if (sourceEntry is HtmlEntry) {
-//      HtmlEntry htmlEntry = sourceEntry;
-//      return htmlEntry.getValue(HtmlEntry.RESOLVED_UNIT);
-//    }
-    return null;
+    // TODO(brianwilkerson) Remove this method after switching to the new task
+    // model.
+    throw new UnimplementedError('Not supported in the new task model');
   }
 
   @override
@@ -1015,6 +1014,11 @@
   }
 
   @override
+  Stream<ComputedResult> onResultComputed(ResultDescriptor descriptor) {
+    return driver.onResultComputed(descriptor);
+  }
+
+  @override
   CompilationUnit parseCompilationUnit(Source source) {
     if (!AnalysisEngine.isDartFileName(source.shortName)) {
       return null;
@@ -1029,21 +1033,26 @@
   }
 
   @override
-  ht.HtmlUnit parseHtmlUnit(Source source) {
+  Document parseHtmlDocument(Source source) {
     if (!AnalysisEngine.isHtmlFileName(source.shortName)) {
       return null;
     }
-    // TODO(brianwilkerson) Implement HTML analysis.
-    return null; //_computeResult(source, null);
+    return _computeResult(source, HTML_DOCUMENT);
+  }
+
+  @override
+  @deprecated // use parseHtmlDocument(source)
+  ht.HtmlUnit parseHtmlUnit(Source source) {
+    // TODO(brianwilkerson) Remove this method after switching to the new task
+    // model.
+    throw new UnimplementedError('Not supported in the new task model');
   }
 
   @override
   AnalysisResult performAnalysisTask() {
     return PerformanceStatistics.performAnaysis.makeCurrentWhile(() {
+      _evaluatePendingFutures();
       bool done = !driver.performAnalysisTask();
-      if (done) {
-        done = !_validateCacheConsistency();
-      }
       List<ChangeNotice> notices = _getChangeNotices(done);
       if (notices != null) {
         int noticeCount = notices.length;
@@ -1067,7 +1076,6 @@
         entry.setValue(result, value, TargetedResult.EMPTY_LIST);
       }
       setValue(BUILD_DIRECTIVES_ERRORS, AnalysisError.NO_ERRORS);
-      setValue(BUILD_FUNCTION_TYPE_ALIASES_ERRORS, AnalysisError.NO_ERRORS);
       setValue(BUILD_LIBRARY_ERRORS, AnalysisError.NO_ERRORS);
       // CLASS_ELEMENTS
       setValue(COMPILATION_UNIT_ELEMENT, library.definingCompilationUnit);
@@ -1087,6 +1095,7 @@
       setValue(LIBRARY_ELEMENT3, library);
       setValue(LIBRARY_ELEMENT4, library);
       setValue(LIBRARY_ELEMENT5, library);
+      setValue(LIBRARY_ELEMENT6, library);
       setValue(LINE_INFO, new LineInfo(<int>[0]));
       setValue(PARSE_ERRORS, AnalysisError.NO_ERRORS);
       entry.setState(PARSED_UNIT, CacheState.FLUSHED);
@@ -1108,7 +1117,6 @@
       entry.setState(RESOLVED_UNIT3, CacheState.FLUSHED);
       entry.setState(RESOLVED_UNIT4, CacheState.FLUSHED);
       entry.setState(RESOLVED_UNIT5, CacheState.FLUSHED);
-      entry.setState(RESOLVED_UNIT6, CacheState.FLUSHED);
       // USED_IMPORTED_ELEMENTS
       // USED_LOCAL_ELEMENTS
       setValue(VERIFY_ERRORS, AnalysisError.NO_ERRORS);
@@ -1144,9 +1152,11 @@
   }
 
   @override
+  @deprecated
   ht.HtmlUnit resolveHtmlUnit(Source htmlSource) {
-    computeHtmlElement(htmlSource);
-    return parseHtmlUnit(htmlSource);
+    // TODO(brianwilkerson) Remove this method after switching to the new task
+    // model.
+    throw new UnimplementedError('Not supported in the new task model');
   }
 
   @override
@@ -1176,6 +1186,69 @@
   }
 
   @override
+  void test_flushAstStructures(Source source) {
+    CacheEntry entry = getCacheEntry(source);
+    entry.setState(PARSED_UNIT, CacheState.FLUSHED);
+    entry.setState(RESOLVED_UNIT1, CacheState.FLUSHED);
+    entry.setState(RESOLVED_UNIT2, CacheState.FLUSHED);
+    entry.setState(RESOLVED_UNIT3, CacheState.FLUSHED);
+    entry.setState(RESOLVED_UNIT4, CacheState.FLUSHED);
+    entry.setState(RESOLVED_UNIT5, CacheState.FLUSHED);
+    entry.setState(RESOLVED_UNIT, CacheState.FLUSHED);
+  }
+
+  @override
+  bool validateCacheConsistency() {
+    int consistencyCheckStart = JavaSystem.nanoTime();
+    HashSet<Source> changedSources = new HashSet<Source>();
+    HashSet<Source> missingSources = new HashSet<Source>();
+    for (Source source in _cache.sources) {
+      CacheEntry entry = _cache.get(source);
+      int sourceTime = getModificationStamp(source);
+      if (sourceTime != entry.modificationTime) {
+        changedSources.add(source);
+      }
+      if (entry.exception != null) {
+        if (!exists(source)) {
+          missingSources.add(source);
+        }
+      }
+    }
+    for (Source source in changedSources) {
+      _sourceChanged(source);
+    }
+    int removalCount = 0;
+    for (Source source in missingSources) {
+      if (getLibrariesContaining(source).isEmpty &&
+          getLibrariesDependingOn(source).isEmpty) {
+        _cache.remove(source);
+        removalCount++;
+      }
+    }
+    int consistencyCheckEnd = JavaSystem.nanoTime();
+    if (changedSources.length > 0 || missingSources.length > 0) {
+      StringBuffer buffer = new StringBuffer();
+      buffer.write("Consistency check took ");
+      buffer.write((consistencyCheckEnd - consistencyCheckStart) / 1000000.0);
+      buffer.writeln(" ms and found");
+      buffer.write("  ");
+      buffer.write(changedSources.length);
+      buffer.writeln(" inconsistent entries");
+      buffer.write("  ");
+      buffer.write(missingSources.length);
+      buffer.write(" missing sources (");
+      buffer.write(removalCount);
+      buffer.writeln(" removed");
+      for (Source source in missingSources) {
+        buffer.write("    ");
+        buffer.writeln(source.fullName);
+      }
+      _logInformation(buffer.toString());
+    }
+    return changedSources.length > 0;
+  }
+
+  @override
   void visitCacheItems(void callback(Source source, SourceEntry dartEntry,
       DataDescriptor rowDesc, CacheState state)) {
     // TODO(brianwilkerson) Figure out where this is used and either remove it
@@ -1398,6 +1471,20 @@
     return entries;
   }
 
+  void _evaluatePendingFutures() {
+    for (AnalysisTarget target in _pendingFutureTargets.keys) {
+      CacheEntry cacheEntry = _cache.get(target);
+      List<PendingFuture> pendingFutures = _pendingFutureTargets[target];
+      for (int i = 0; i < pendingFutures.length;) {
+        if (pendingFutures[i].evaluate(cacheEntry)) {
+          pendingFutures.removeAt(i);
+        } else {
+          i++;
+        }
+      }
+    }
+  }
+
   /**
    * Return a list containing all of the change notices that are waiting to be
    * returned. If there are no notices, then return either `null` or an empty
@@ -1421,11 +1508,22 @@
    */
   List<Source> _getSources(SourceKind kind) {
     List<Source> sources = <Source>[];
-    for (Source source in _cache.sources) {
-      CacheEntry entry = _cache.get(source);
-      if (entry.getValue(SOURCE_KIND) == kind) {
-        sources.add(source);
+    if (kind == SourceKind.LIBRARY || kind == SourceKind.PART) {
+      for (Source source in _cache.sources) {
+        CacheEntry entry = _cache.get(source);
+        if (entry.getValue(SOURCE_KIND) == kind) {
+          sources.add(source);
+        }
       }
+    } else if (kind == SourceKind.HTML) {
+      for (Source source in _cache.sources) {
+        if (AnalysisEngine.isHtmlFileName(source.shortName)) {
+          sources.add(source);
+        }
+      }
+    }
+    if (sources.isEmpty) {
+      return Source.EMPTY_LIST;
     }
     return sources;
   }
@@ -1625,6 +1723,8 @@
     entry.setState(CONTENT, CacheState.INVALID);
     dartWorkManager.applyChange(
         Source.EMPTY_LIST, <Source>[source], Source.EMPTY_LIST);
+    htmlWorkManager.applyChange(
+        Source.EMPTY_LIST, <Source>[source], Source.EMPTY_LIST);
   }
 
   /**
@@ -1734,62 +1834,6 @@
       return true;
     });
   }
-
-  /**
-   * Check the cache for any invalid entries (entries whose modification time
-   * does not match the modification time of the source associated with the
-   * entry). Invalid entries will be marked as invalid so that the source will
-   * be re-analyzed. Return `true` if at least one entry was invalid.
-   */
-  bool _validateCacheConsistency() {
-    int consistencyCheckStart = JavaSystem.nanoTime();
-    HashSet<Source> changedSources = new HashSet<Source>();
-    HashSet<Source> missingSources = new HashSet<Source>();
-    for (Source source in _cache.sources) {
-      CacheEntry entry = _cache.get(source);
-      int sourceTime = getModificationStamp(source);
-      if (sourceTime != entry.modificationTime) {
-        changedSources.add(source);
-      }
-      if (entry.exception != null) {
-        if (!exists(source)) {
-          missingSources.add(source);
-        }
-      }
-    }
-    for (Source source in changedSources) {
-      _sourceChanged(source);
-    }
-    int removalCount = 0;
-    for (Source source in missingSources) {
-      if (getLibrariesContaining(source).isEmpty &&
-          getLibrariesDependingOn(source).isEmpty) {
-        _cache.remove(source);
-        removalCount++;
-      }
-    }
-    int consistencyCheckEnd = JavaSystem.nanoTime();
-    if (changedSources.length > 0 || missingSources.length > 0) {
-      StringBuffer buffer = new StringBuffer();
-      buffer.write("Consistency check took ");
-      buffer.write((consistencyCheckEnd - consistencyCheckStart) / 1000000.0);
-      buffer.writeln(" ms and found");
-      buffer.write("  ");
-      buffer.write(changedSources.length);
-      buffer.writeln(" inconsistent entries");
-      buffer.write("  ");
-      buffer.write(missingSources.length);
-      buffer.write(" missing sources (");
-      buffer.write(removalCount);
-      buffer.writeln(" removed");
-      for (Source source in missingSources) {
-        buffer.write("    ");
-        buffer.writeln(source.fullName);
-      }
-      _logInformation(buffer.toString());
-    }
-    return changedSources.length > 0;
-  }
 }
 
 /**
@@ -1933,8 +1977,8 @@
 }
 
 /**
- * A helper class used to create futures for AnalysisContextImpl. Using a helper
- * class allows us to preserve the generic parameter T.
+ * A helper class used to create futures for [AnalysisContextImpl].
+ * Using a helper class allows us to preserve the generic parameter T.
  */
 class _AnalysisFutureHelper<T> {
   final AnalysisContextImpl _context;
@@ -1943,11 +1987,13 @@
 
   /**
    * Return a future that will be completed with the result of calling
-   * [computeValue].  If [computeValue] returns non-`null`, the future will be
-   * completed immediately with the resulting value.  If it returns `null`, then
-   * it will be re-executed in the future, after the next time the cached
-   * information for [target] has changed.  If [computeValue] throws an
-   * exception, the future will fail with that exception.
+   * [computeValue]. If [computeValue] returns non-`null`, the future will be
+   * completed immediately with the resulting value. If it returns `null`, then
+   * [scheduleComputation] is invoked to schedule analysis that will produce
+   * the required result, and [computeValue] will be re-executed in the future,
+   * after the next time the cached information for [target] has changed. If
+   * [computeValue] throws an exception, the future will fail with that
+   * exception.
    *
    * If the [computeValue] still returns `null` after there is no further
    * analysis to be done for [target], then the future will be completed with
@@ -1957,23 +2003,21 @@
    * updated, it should be free of side effects so that it doesn't cause
    * reentrant changes to the analysis state.
    */
-  CancelableFuture<T> computeAsync(
-      AnalysisTarget target, T computeValue(CacheEntry entry)) {
+  CancelableFuture<T> computeAsync(AnalysisTarget target,
+      T computeValue(CacheEntry entry), void scheduleComputation()) {
     if (_context.isDisposed) {
       // No further analysis is expected, so return a future that completes
       // immediately with AnalysisNotScheduledError.
       return new CancelableFuture.error(new AnalysisNotScheduledError());
     }
-    CacheEntry entry = _context.getReadableSourceEntryOrNull(target);
-    if (entry == null) {
-      return new CancelableFuture.error(new AnalysisNotScheduledError());
-    }
+    CacheEntry entry = _context.getCacheEntry(target);
     PendingFuture pendingFuture =
         new PendingFuture<T>(_context, target, computeValue);
     if (!pendingFuture.evaluate(entry)) {
       _context._pendingFutureTargets
           .putIfAbsent(target, () => <PendingFuture>[])
           .add(pendingFuture);
+      scheduleComputation();
     }
     return pendingFuture.future;
   }
diff --git a/pkg/analyzer/lib/src/generated/constant.dart b/pkg/analyzer/lib/src/generated/constant.dart
index 499ce50..572caab 100644
--- a/pkg/analyzer/lib/src/generated/constant.dart
+++ b/pkg/analyzer/lib/src/generated/constant.dart
@@ -18,7 +18,7 @@
 import 'engine.dart' show AnalysisEngine, RecordingErrorListener;
 import 'error.dart';
 import 'java_core.dart';
-import 'resolver.dart' show TypeProvider;
+import 'resolver.dart' show TypeProvider, TypeSystem, TypeSystemImpl;
 import 'scanner.dart' show Token, TokenType;
 import 'source.dart' show Source;
 import 'utilities_collection.dart';
@@ -217,9 +217,10 @@
       "^(?:${ConstantValueComputer._OPERATOR_RE}\$|$_PUBLIC_IDENTIFIER_RE(?:=?\$|[.](?!\$)))+?\$");
 
   /**
-   * The type provider used to access the known types.
+   * The type system.  This is used to gues the types of constants when their
+   * exact value is unknown.
    */
-  final TypeProvider typeProvider;
+  final TypeSystem typeSystem;
 
   /**
    * The set of variables declared on the command line using '-D'.
@@ -239,11 +240,17 @@
    * given, is used to verify correct dependency analysis when running unit
    * tests.
    */
-  ConstantEvaluationEngine(this.typeProvider, this._declaredVariables,
+  ConstantEvaluationEngine(TypeProvider typeProvider, this._declaredVariables,
       {ConstantEvaluationValidator validator})
       : validator = validator != null
           ? validator
-          : new ConstantEvaluationValidator_ForProduction();
+          : new ConstantEvaluationValidator_ForProduction(),
+        typeSystem = new TypeSystemImpl(typeProvider);
+
+  /**
+   * The type provider used to access the known types.
+   */
+  TypeProvider get typeProvider => typeSystem.typeProvider;
 
   /**
    * Check that the arguments to a call to fromEnvironment() are correct. The
@@ -329,33 +336,38 @@
         }
       }
     } else if (constant is VariableElement) {
-      RecordingErrorListener errorListener = new RecordingErrorListener();
-      ErrorReporter errorReporter =
-          new ErrorReporter(errorListener, constant.source);
-      DartObjectImpl dartObject =
-          (constant as PotentiallyConstVariableElement).constantInitializer
-              .accept(new ConstantVisitor(this, errorReporter));
-      // Only check the type for truly const declarations (don't check final
-      // fields with initializers, since their types may be generic.  The type
-      // of the final field will be checked later, when the constructor is
-      // invoked).
-      if (dartObject != null && constant.isConst) {
-        if (!runtimeTypeMatch(dartObject, constant.type)) {
-          errorReporter.reportErrorForElement(
-              CheckedModeCompileTimeErrorCode.VARIABLE_TYPE_MISMATCH, constant,
-              [dartObject.type, constant.type]);
+      Expression constantInitializer =
+          (constant as PotentiallyConstVariableElement).constantInitializer;
+      if (constantInitializer != null) {
+        RecordingErrorListener errorListener = new RecordingErrorListener();
+        ErrorReporter errorReporter =
+            new ErrorReporter(errorListener, constant.source);
+        DartObjectImpl dartObject = constantInitializer
+            .accept(new ConstantVisitor(this, errorReporter));
+        // Only check the type for truly const declarations (don't check final
+        // fields with initializers, since their types may be generic.  The type
+        // of the final field will be checked later, when the constructor is
+        // invoked).
+        if (dartObject != null && constant.isConst) {
+          if (!runtimeTypeMatch(dartObject, constant.type)) {
+            errorReporter.reportErrorForElement(
+                CheckedModeCompileTimeErrorCode.VARIABLE_TYPE_MISMATCH,
+                constant, [dartObject.type, constant.type]);
+          }
         }
+        (constant as VariableElementImpl).evaluationResult =
+            new EvaluationResultImpl(dartObject, errorListener.errors);
       }
-      (constant as VariableElementImpl).evaluationResult =
-          new EvaluationResultImpl(dartObject, errorListener.errors);
     } else if (constant is ConstructorElement) {
-      // No evaluation needs to be done; constructor declarations are only in
-      // the dependency graph to ensure that any constants referred to in
-      // initializer lists and parameter defaults are evaluated before
-      // invocations of the constructor.  However we do need to annotate the
-      // element as being free of constant evaluation cycles so that later code
-      // will know that it is safe to evaluate.
-      (constant as ConstructorElementImpl).isCycleFree = true;
+      if (constant.isConst) {
+        // No evaluation needs to be done; constructor declarations are only in
+        // the dependency graph to ensure that any constants referred to in
+        // initializer lists and parameter defaults are evaluated before
+        // invocations of the constructor.  However we do need to annotate the
+        // element as being free of constant evaluation cycles so that later
+        // code will know that it is safe to evaluate.
+        (constant as ConstructorElementImpl).isCycleFree = true;
+      }
     } else if (constant is ConstantEvaluationTarget_Annotation) {
       Annotation constNode = constant.annotation;
       ElementAnnotationImpl elementAnnotation = constNode.elementAnnotation;
@@ -369,7 +381,15 @@
           // Just copy the evaluation result.
           VariableElementImpl variableElement =
               element.variable as VariableElementImpl;
-          elementAnnotation.evaluationResult = variableElement.evaluationResult;
+          if (variableElement.evaluationResult != null) {
+            elementAnnotation.evaluationResult =
+                variableElement.evaluationResult;
+          } else {
+            // This could happen in the event that the annotation refers to a
+            // non-constant.  The error is detected elsewhere, so just silently
+            // ignore it here.
+            elementAnnotation.evaluationResult = new EvaluationResultImpl(null);
+          }
         } else if (element is ConstructorElementImpl &&
             element.isConst &&
             constNode.arguments != null) {
@@ -405,6 +425,13 @@
    * Determine which constant elements need to have their values computed
    * prior to computing the value of [constant], and report them using
    * [callback].
+   *
+   * Note that it's possible (in erroneous code) for a constant to depend on a
+   * non-constant.  When this happens, we report the dependency anyhow so that
+   * if the non-constant changes to a constant, we will know to recompute the
+   * thing that depends on it.  [computeDependencies] and
+   * [computeConstantValue] are responsible for ignoring the request if they
+   * are asked to act on a non-constant target.
    */
   void computeDependencies(
       ConstantEvaluationTarget constant, ReferenceFinderCallback callback) {
@@ -423,56 +450,60 @@
         initializer.accept(referenceFinder);
       }
     } else if (constant is ConstructorElementImpl) {
-      constant.isCycleFree = false;
-      ConstructorElement redirectedConstructor =
-          getConstRedirectedConstructor(constant);
-      if (redirectedConstructor != null) {
-        ConstructorElement redirectedConstructorBase =
-            ConstantEvaluationEngine._getConstructorBase(redirectedConstructor);
-        callback(redirectedConstructorBase);
-        return;
-      } else if (constant.isFactory) {
-        // Factory constructor, but getConstRedirectedConstructor returned
-        // null.  This can happen if we're visiting one of the special external
-        // const factory constructors in the SDK, or if the code contains
-        // errors (such as delegating to a non-const constructor, or delegating
-        // to a constructor that can't be resolved).  In any of these cases,
-        // we'll evaluate calls to this constructor without having to refer to
-        // any other constants.  So we don't need to report any dependencies.
-        return;
-      }
-      bool superInvocationFound = false;
-      List<ConstructorInitializer> initializers = constant.constantInitializers;
-      for (ConstructorInitializer initializer in initializers) {
-        if (initializer is SuperConstructorInvocation) {
-          superInvocationFound = true;
+      if (constant.isConst) {
+        constant.isCycleFree = false;
+        ConstructorElement redirectedConstructor =
+            getConstRedirectedConstructor(constant);
+        if (redirectedConstructor != null) {
+          ConstructorElement redirectedConstructorBase =
+              ConstantEvaluationEngine
+                  ._getConstructorBase(redirectedConstructor);
+          callback(redirectedConstructorBase);
+          return;
+        } else if (constant.isFactory) {
+          // Factory constructor, but getConstRedirectedConstructor returned
+          // null.  This can happen if we're visiting one of the special external
+          // const factory constructors in the SDK, or if the code contains
+          // errors (such as delegating to a non-const constructor, or delegating
+          // to a constructor that can't be resolved).  In any of these cases,
+          // we'll evaluate calls to this constructor without having to refer to
+          // any other constants.  So we don't need to report any dependencies.
+          return;
         }
-        initializer.accept(referenceFinder);
-      }
-      if (!superInvocationFound) {
-        // No explicit superconstructor invocation found, so we need to
-        // manually insert a reference to the implicit superconstructor.
-        InterfaceType superclass =
-            (constant.returnType as InterfaceType).superclass;
-        if (superclass != null && !superclass.isObject) {
-          ConstructorElement unnamedConstructor = ConstantEvaluationEngine
-              ._getConstructorBase(superclass.element.unnamedConstructor);
-          if (unnamedConstructor != null) {
-            callback(unnamedConstructor);
+        bool superInvocationFound = false;
+        List<ConstructorInitializer> initializers =
+            constant.constantInitializers;
+        for (ConstructorInitializer initializer in initializers) {
+          if (initializer is SuperConstructorInvocation) {
+            superInvocationFound = true;
+          }
+          initializer.accept(referenceFinder);
+        }
+        if (!superInvocationFound) {
+          // No explicit superconstructor invocation found, so we need to
+          // manually insert a reference to the implicit superconstructor.
+          InterfaceType superclass =
+              (constant.returnType as InterfaceType).superclass;
+          if (superclass != null && !superclass.isObject) {
+            ConstructorElement unnamedConstructor = ConstantEvaluationEngine
+                ._getConstructorBase(superclass.element.unnamedConstructor);
+            if (unnamedConstructor != null) {
+              callback(unnamedConstructor);
+            }
           }
         }
-      }
-      for (FieldElement field in constant.enclosingElement.fields) {
-        // Note: non-static const isn't allowed but we handle it anyway so that
-        // we won't be confused by incorrect code.
-        if ((field.isFinal || field.isConst) &&
-            !field.isStatic &&
-            field.initializer != null) {
-          callback(field);
+        for (FieldElement field in constant.enclosingElement.fields) {
+          // Note: non-static const isn't allowed but we handle it anyway so
+          // that we won't be confused by incorrect code.
+          if ((field.isFinal || field.isConst) &&
+              !field.isStatic &&
+              field.initializer != null) {
+            callback(field);
+          }
         }
-      }
-      for (ParameterElement parameterElement in constant.parameters) {
-        callback(parameterElement);
+        for (ParameterElement parameterElement in constant.parameters) {
+          callback(parameterElement);
+        }
       }
     } else if (constant is ConstantEvaluationTarget_Annotation) {
       Annotation constNode = constant.annotation;
@@ -486,7 +517,7 @@
           // The annotation is a reference to a compile-time constant variable,
           // so it depends on the variable.
           callback(element.variable);
-        } else if (element is ConstructorElementImpl && element.isConst) {
+        } else if (element is ConstructorElementImpl) {
           // The annotation is a constructor invocation, so it depends on the
           // constructor.
           callback(element);
@@ -723,6 +754,10 @@
               }
             }
             String fieldName = field.name;
+            if (fieldMap.containsKey(fieldName)) {
+              errorReporter.reportErrorForNode(
+                  CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, node);
+            }
             fieldMap[fieldName] = argumentValue;
           }
         } else {
@@ -744,6 +779,10 @@
             initializerExpression.accept(initializerVisitor);
         if (evaluationResult != null) {
           String fieldName = constructorFieldInitializer.fieldName.name;
+          if (fieldMap.containsKey(fieldName)) {
+            errorReporter.reportErrorForNode(
+                CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, node);
+          }
           fieldMap[fieldName] = evaluationResult;
           PropertyAccessorElement getter = definingClass.getGetter(fieldName);
           if (getter != null) {
@@ -1399,6 +1438,11 @@
    */
   TypeProvider get _typeProvider => evaluationEngine.typeProvider;
 
+  /**
+   * Convenience getter to gain access to the [evaluationEngine]'s type system.
+   */
+  TypeSystem get _typeSystem => evaluationEngine.typeSystem;
+
   @override
   DartObjectImpl visitAdjacentStrings(AdjacentStrings node) {
     DartObjectImpl result = null;
@@ -1511,7 +1555,7 @@
     ParameterizedType thenType = thenResult.type;
     ParameterizedType elseType = elseResult.type;
     return new DartObjectImpl.validWithUnknownValue(
-        thenType.getLeastUpperBound(elseType) as InterfaceType);
+        _typeSystem.getLeastUpperBound(thenType, elseType) as InterfaceType);
   }
 
   @override
@@ -4974,12 +5018,22 @@
   }
 
   @override
+  Object visitLabel(Label node) {
+    // We are visiting the "label" part of a named expression in a function
+    // call (presumably a constructor call), e.g. "const C(label: ...)".  We
+    // don't want to visit the SimpleIdentifier for the label because that's a
+    // reference to a function parameter that needs to be filled in; it's not a
+    // constant whose value we depend on.
+    return null;
+  }
+
+  @override
   Object visitRedirectingConstructorInvocation(
       RedirectingConstructorInvocation node) {
     super.visitRedirectingConstructorInvocation(node);
     ConstructorElement target =
         ConstantEvaluationEngine._getConstructorBase(node.staticElement);
-    if (target != null && target.isConst) {
+    if (target != null) {
       _callback(target);
     }
     return null;
@@ -4992,9 +5046,7 @@
       element = (element as PropertyAccessorElement).variable;
     }
     if (element is VariableElement) {
-      if (element.isConst) {
-        _callback(element);
-      }
+      _callback(element);
     }
     return null;
   }
@@ -5004,7 +5056,7 @@
     super.visitSuperConstructorInvocation(node);
     ConstructorElement constructor =
         ConstantEvaluationEngine._getConstructorBase(node.staticElement);
-    if (constructor != null && constructor.isConst) {
+    if (constructor != null) {
       _callback(constructor);
     }
     return null;
diff --git a/pkg/analyzer/lib/src/generated/element.dart b/pkg/analyzer/lib/src/generated/element.dart
index 9e7eeff..52ef4f5 100644
--- a/pkg/analyzer/lib/src/generated/element.dart
+++ b/pkg/analyzer/lib/src/generated/element.dart
@@ -128,7 +128,7 @@
 /**
  * An element that represents a class.
  */
-abstract class ClassElement implements Element {
+abstract class ClassElement implements TypeDefiningElement {
   /**
    * An empty list of class elements.
    */
@@ -265,9 +265,7 @@
    */
   InterfaceType get supertype;
 
-  /**
-   * Return the type defined by the class.
-   */
+  @override
   InterfaceType get type;
 
   /**
@@ -2051,7 +2049,12 @@
   /**
    * Return the least upper bound of this type and the given [type], or `null`
    * if there is no least upper bound.
+   *
+   * Deprecated, since it is impossible to implement the correct algorithm
+   * without access to a [TypeProvider].  Please use
+   * [TypeSystem.getLeastUpperBound] instead.
    */
+  @deprecated
   DartType getLeastUpperBound(DartType type);
 
   /**
@@ -2154,16 +2157,14 @@
 /**
  * The synthetic element representing the declaration of the type `dynamic`.
  */
-class DynamicElementImpl extends ElementImpl {
+class DynamicElementImpl extends ElementImpl implements TypeDefiningElement {
   /**
    * Return the unique instance of this class.
    */
   static DynamicElementImpl get instance =>
       DynamicTypeImpl.instance.element as DynamicElementImpl;
 
-  /**
-   * The type defined by this element.
-   */
+  @override
   DynamicTypeImpl type;
 
   /**
@@ -3261,10 +3262,12 @@
 
   R visitConstructorElement(ConstructorElement element);
 
+  @deprecated
   R visitEmbeddedHtmlScriptElement(EmbeddedHtmlScriptElement element);
 
   R visitExportElement(ExportElement element);
 
+  @deprecated
   R visitExternalHtmlScriptElement(ExternalHtmlScriptElement element);
 
   R visitFieldElement(FieldElement element);
@@ -3275,6 +3278,7 @@
 
   R visitFunctionTypeAliasElement(FunctionTypeAliasElement element);
 
+  @deprecated
   R visitHtmlElement(HtmlElement element);
 
   R visitImportElement(ImportElement element);
@@ -3303,6 +3307,7 @@
 /**
  * A script tag in an HTML file having content that defines a Dart library.
  */
+@deprecated
 abstract class EmbeddedHtmlScriptElement implements HtmlScriptElement {
   /**
    * Return the library element defined by the content of the script tag.
@@ -3313,6 +3318,7 @@
 /**
  * A concrete implementation of an [EmbeddedHtmlScriptElement].
  */
+@deprecated
 class EmbeddedHtmlScriptElementImpl extends HtmlScriptElementImpl
     implements EmbeddedHtmlScriptElement {
   /**
@@ -3828,6 +3834,7 @@
  * A script tag in an HTML file having a `source` attribute that references a
  * Dart library source file.
  */
+@deprecated
 abstract class ExternalHtmlScriptElement implements HtmlScriptElement {
   /**
    * Return the source referenced by this element, or `null` if this element
@@ -3839,6 +3846,7 @@
 /**
  * A concrete implementation of an [ExternalHtmlScriptElement].
  */
+@deprecated
 class ExternalHtmlScriptElementImpl extends HtmlScriptElementImpl
     implements ExternalHtmlScriptElement {
   /**
@@ -4371,7 +4379,7 @@
 /**
  * A function type alias (`typedef`).
  */
-abstract class FunctionTypeAliasElement implements Element {
+abstract class FunctionTypeAliasElement implements TypeDefiningElement {
   /**
    * An empty array of type alias elements.
    */
@@ -4394,9 +4402,7 @@
    */
   DartType get returnType;
 
-  /**
-   * Return the type of function defined by this type alias.
-   */
+  @override
   FunctionType get type;
 
   /**
@@ -4903,12 +4909,12 @@
       return false;
     }
     FunctionTypeImpl otherType = object as FunctionTypeImpl;
-    return TypeImpl.equalArrays(
+    return returnType == otherType.returnType &&
+        TypeImpl.equalArrays(
             normalParameterTypes, otherType.normalParameterTypes) &&
         TypeImpl.equalArrays(
             optionalParameterTypes, otherType.optionalParameterTypes) &&
-        _equals(namedParameterTypes, otherType.namedParameterTypes) &&
-        returnType == otherType.returnType;
+        _equals(namedParameterTypes, otherType.namedParameterTypes);
   }
 
   @override
@@ -5261,6 +5267,19 @@
       substitute2(argumentTypes, typeArguments);
 
   /**
+   * Compute the least upper bound of types [f] and [g], both of which are
+   * known to be function types.
+   *
+   * In the event that f and g have different numbers of required parameters,
+   * `null` is returned, in which case the least upper bound is the interface
+   * type `Function`.
+   */
+  static FunctionType computeLeastUpperBound(FunctionType f, FunctionType g) {
+    // TODO(paulberry): implement this.
+    return null;
+  }
+
+  /**
    * Return `true` if all of the name/type pairs in the first map ([firstTypes])
    * are equal to the corresponding name/type pairs in the second map
    * ([secondTypes]). The maps are expected to iterate over their entries in the
@@ -5360,6 +5379,7 @@
   }
 
   @override
+  @deprecated
   R visitEmbeddedHtmlScriptElement(EmbeddedHtmlScriptElement element) =>
       visitHtmlScriptElement(element);
 
@@ -5369,6 +5389,7 @@
   R visitExportElement(ExportElement element) => visitElement(element);
 
   @override
+  @deprecated
   R visitExternalHtmlScriptElement(ExternalHtmlScriptElement element) =>
       visitHtmlScriptElement(element);
 
@@ -5388,8 +5409,10 @@
       visitElement(element);
 
   @override
+  @deprecated
   R visitHtmlElement(HtmlElement element) => visitElement(element);
 
+  @deprecated
   R visitHtmlScriptElement(HtmlScriptElement element) => visitElement(element);
 
   @override
@@ -5489,6 +5512,7 @@
 /**
  * An HTML file.
  */
+@deprecated
 abstract class HtmlElement implements Element {
   /**
    * An empty list of HTML file elements.
@@ -5507,6 +5531,7 @@
 /**
  * A concrete implementation of an [HtmlElement].
  */
+@deprecated
 class HtmlElementImpl extends ElementImpl implements HtmlElement {
   /**
    * An empty list of HTML file elements.
@@ -5593,6 +5618,7 @@
  *
  * See [EmbeddedHtmlScriptElement], and [ExternalHtmlScriptElement].
  */
+@deprecated
 abstract class HtmlScriptElement implements Element {
   /**
    * An empty list of HTML script elements.
@@ -5603,6 +5629,7 @@
 /**
  * A concrete implementation of an [HtmlScriptElement].
  */
+@deprecated
 abstract class HtmlScriptElementImpl extends ElementImpl
     implements HtmlScriptElement {
   /**
@@ -5816,6 +5843,7 @@
    * and <i>J</i> is the sole element of <i>S<sub>q</sub></i>.
    */
   @override
+  @deprecated
   DartType getLeastUpperBound(DartType type);
 
   /**
@@ -6020,6 +6048,9 @@
    */
   static InterfaceType getSmartLeastUpperBound(
       InterfaceType first, InterfaceType second) {
+    // TODO(paulberry): this needs to be deprecated and replaced with a method
+    // in [TypeSystem], since it relies on the deprecated functionality of
+    // [DartType.getLeastUpperBound].
     if (first.element == second.element) {
       return _leastUpperBound(first, second);
     }
@@ -6296,6 +6327,7 @@
       .from((element as ClassElementImpl).getGetter(getterName), this);
 
   @override
+  @deprecated
   DartType getLeastUpperBound(DartType type) {
     // quick check for self
     if (identical(type, this)) {
@@ -6311,45 +6343,7 @@
     if (type is! InterfaceType) {
       return null;
     }
-    // new names to match up with the spec
-    InterfaceType i = this;
-    InterfaceType j = type as InterfaceType;
-    // compute set of supertypes
-    Set<InterfaceType> si = computeSuperinterfaceSet(i);
-    Set<InterfaceType> sj = computeSuperinterfaceSet(j);
-    // union si with i and sj with j
-    si.add(i);
-    sj.add(j);
-    // compute intersection, reference as set 's'
-    List<InterfaceType> s = _intersection(si, sj);
-    // for each element in Set s, compute the largest inheritance path to Object
-    List<int> depths = new List<int>.filled(s.length, 0);
-    int maxDepth = 0;
-    for (int n = 0; n < s.length; n++) {
-      depths[n] = computeLongestInheritancePathToObject(s[n]);
-      if (depths[n] > maxDepth) {
-        maxDepth = depths[n];
-      }
-    }
-    // ensure that the currently computed maxDepth is unique,
-    // otherwise, decrement and test for uniqueness again
-    for (; maxDepth >= 0; maxDepth--) {
-      int indexOfLeastUpperBound = -1;
-      int numberOfTypesAtMaxDepth = 0;
-      for (int m = 0; m < depths.length; m++) {
-        if (depths[m] == maxDepth) {
-          numberOfTypesAtMaxDepth++;
-          indexOfLeastUpperBound = m;
-        }
-      }
-      if (numberOfTypesAtMaxDepth == 1) {
-        return s[indexOfLeastUpperBound];
-      }
-    }
-    // illegal state, log and return null- Object at maxDepth == 0 should always
-    // return itself as the least upper bound.
-    // TODO (jwren) log the error state
-    return null;
+    return computeLeastUpperBound(this, type);
   }
 
   @override
@@ -6696,10 +6690,57 @@
       substitute2(argumentTypes, typeArguments);
 
   /**
+   * Compute the least upper bound of types [i] and [j], both of which are
+   * known to be interface types.
+   *
+   * In the event that the algorithm fails (which might occur due to a bug in
+   * the analyzer), `null` is returned.
+   */
+  static InterfaceType computeLeastUpperBound(
+      InterfaceType i, InterfaceType j) {
+    // compute set of supertypes
+    Set<InterfaceType> si = computeSuperinterfaceSet(i);
+    Set<InterfaceType> sj = computeSuperinterfaceSet(j);
+    // union si with i and sj with j
+    si.add(i);
+    sj.add(j);
+    // compute intersection, reference as set 's'
+    List<InterfaceType> s = _intersection(si, sj);
+    // for each element in Set s, compute the largest inheritance path to Object
+    List<int> depths = new List<int>.filled(s.length, 0);
+    int maxDepth = 0;
+    for (int n = 0; n < s.length; n++) {
+      depths[n] = computeLongestInheritancePathToObject(s[n]);
+      if (depths[n] > maxDepth) {
+        maxDepth = depths[n];
+      }
+    }
+    // ensure that the currently computed maxDepth is unique,
+    // otherwise, decrement and test for uniqueness again
+    for (; maxDepth >= 0; maxDepth--) {
+      int indexOfLeastUpperBound = -1;
+      int numberOfTypesAtMaxDepth = 0;
+      for (int m = 0; m < depths.length; m++) {
+        if (depths[m] == maxDepth) {
+          numberOfTypesAtMaxDepth++;
+          indexOfLeastUpperBound = m;
+        }
+      }
+      if (numberOfTypesAtMaxDepth == 1) {
+        return s[indexOfLeastUpperBound];
+      }
+    }
+    // Should be impossible--there should always be exactly one type with the
+    // maximum depth.
+    assert(false);
+    return null;
+  }
+
+  /**
    * Return the length of the longest inheritance path from the given [type] to
    * Object.
    *
-   * See [InterfaceType.getLeastUpperBound].
+   * See [computeLeastUpperBound].
    */
   static int computeLongestInheritancePathToObject(InterfaceType type) =>
       _computeLongestInheritancePathToObject(
@@ -6708,7 +6749,7 @@
   /**
    * Returns the set of all superinterfaces of the given [type].
    *
-   * See [getLeastUpperBound].
+   * See [computeLeastUpperBound].
    */
   static Set<InterfaceType> computeSuperinterfaceSet(InterfaceType type) =>
       _computeSuperinterfaceSet(type, new HashSet<InterfaceType>());
@@ -6719,7 +6760,7 @@
    * longest path from the subtype to this type. The set of [visitedTypes] is
    * used to prevent infinite recursion in the case of a cyclic type structure.
    *
-   * See [computeLongestInheritancePathToObject], and [getLeastUpperBound].
+   * See [computeLongestInheritancePathToObject], and [computeLeastUpperBound].
    */
   static int _computeLongestInheritancePathToObject(
       InterfaceType type, int depth, HashSet<ClassElement> visitedTypes) {
@@ -6763,7 +6804,7 @@
    * Add all of the superinterfaces of the given [type] to the given [set].
    * Return the [set] as a convenience.
    *
-   * See [computeSuperinterfaceSet], and [getLeastUpperBound].
+   * See [computeSuperinterfaceSet], and [computeLeastUpperBound].
    */
   static Set<InterfaceType> _computeSuperinterfaceSet(
       InterfaceType type, HashSet<InterfaceType> set) {
@@ -9323,6 +9364,7 @@
   }
 
   @override
+  @deprecated
   R visitEmbeddedHtmlScriptElement(EmbeddedHtmlScriptElement element) {
     element.visitChildren(this);
     return null;
@@ -9335,6 +9377,7 @@
   }
 
   @override
+  @deprecated
   R visitExternalHtmlScriptElement(ExternalHtmlScriptElement element) {
     element.visitChildren(this);
     return null;
@@ -9365,6 +9408,7 @@
   }
 
   @override
+  @deprecated
   R visitHtmlElement(HtmlElement element) {
     element.visitChildren(this);
     return null;
@@ -9513,12 +9557,14 @@
   R visitConstructorElement(ConstructorElement element) => null;
 
   @override
+  @deprecated
   R visitEmbeddedHtmlScriptElement(EmbeddedHtmlScriptElement element) => null;
 
   @override
   R visitExportElement(ExportElement element) => null;
 
   @override
+  @deprecated
   R visitExternalHtmlScriptElement(ExternalHtmlScriptElement element) => null;
 
   @override
@@ -9535,6 +9581,7 @@
   R visitFunctionTypeAliasElement(FunctionTypeAliasElement element) => null;
 
   @override
+  @deprecated
   R visitHtmlElement(HtmlElement element) => null;
 
   @override
@@ -9624,6 +9671,16 @@
 }
 
 /**
+ * An element that defines a type.
+ */
+abstract class TypeDefiningElement implements Element {
+  /**
+   * Return the type defined by this element.
+   */
+  DartType get type;
+}
+
+/**
  * The abstract class `TypeImpl` implements the behavior common to objects
  * representing the declared type of elements in the element model.
  */
diff --git a/pkg/analyzer/lib/src/generated/element_resolver.dart b/pkg/analyzer/lib/src/generated/element_resolver.dart
index 291ac5b..c047654 100644
--- a/pkg/analyzer/lib/src/generated/element_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/element_resolver.dart
@@ -200,13 +200,12 @@
 
   @override
   Object visitClassDeclaration(ClassDeclaration node) {
-    _setMetadata(node.element, node);
+    setMetadata(node.element, node);
     return null;
   }
-
   @override
   Object visitClassTypeAlias(ClassTypeAlias node) {
-    _setMetadata(node.element, node);
+    setMetadata(node.element, node);
     return null;
   }
 
@@ -332,7 +331,7 @@
           }
         }
       }
-      _setMetadata(constructorElement, node);
+      setMetadata(constructorElement, node);
     }
     return null;
   }
@@ -388,13 +387,13 @@
 
   @override
   Object visitDeclaredIdentifier(DeclaredIdentifier node) {
-    _setMetadata(node.element, node);
+    setMetadata(node.element, node);
     return null;
   }
 
   @override
   Object visitEnumDeclaration(EnumDeclaration node) {
-    _setMetadata(node.element, node);
+    setMetadata(node.element, node);
     return null;
   }
 
@@ -406,7 +405,7 @@
       // TODO(brianwilkerson) Figure out whether the element can ever be
       // something other than an ExportElement
       _resolveCombinators(exportElement.exportedLibrary, node.combinators);
-      _setMetadata(exportElement, node);
+      setMetadata(exportElement, node);
     }
     return null;
   }
@@ -419,7 +418,7 @@
 
   @override
   Object visitFunctionDeclaration(FunctionDeclaration node) {
-    _setMetadata(node.element, node);
+    setMetadata(node.element, node);
     return null;
   }
 
@@ -442,7 +441,7 @@
 
   @override
   Object visitFunctionTypeAlias(FunctionTypeAlias node) {
-    _setMetadata(node.element, node);
+    setMetadata(node.element, node);
     return null;
   }
 
@@ -471,7 +470,7 @@
       if (library != null) {
         _resolveCombinators(library, node.combinators);
       }
-      _setMetadata(importElement, node);
+      setMetadata(importElement, node);
     }
     return null;
   }
@@ -554,13 +553,13 @@
 
   @override
   Object visitLibraryDirective(LibraryDirective node) {
-    _setMetadata(node.element, node);
+    setMetadata(node.element, node);
     return null;
   }
 
   @override
   Object visitMethodDeclaration(MethodDeclaration node) {
-    _setMetadata(node.element, node);
+    setMetadata(node.element, node);
     return null;
   }
 
@@ -591,6 +590,11 @@
       propagatedElement = null;
     } else if (methodName.name == FunctionElement.LOAD_LIBRARY_NAME &&
         _isDeferredPrefix(target)) {
+      if (node.operator.type == sc.TokenType.QUESTION_PERIOD) {
+        _resolver.reportErrorForNode(
+            CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT, target,
+            [(target as SimpleIdentifier).name]);
+      }
       LibraryElement importedLibrary = _getImportedLibrary(target);
       methodName.staticElement = importedLibrary.loadLibraryFunction;
       return null;
@@ -609,10 +613,10 @@
         staticElement =
             propagatedElement = _resolveElement(typeReference, methodName);
       } else {
-        staticElement =
-            _resolveInvokedElementWithTarget(target, staticType, methodName);
+        staticElement = _resolveInvokedElementWithTarget(
+            target, staticType, methodName, isConditional);
         propagatedElement = _resolveInvokedElementWithTarget(
-            target, propagatedType, methodName);
+            target, propagatedType, methodName, isConditional);
       }
     }
     staticElement = _convertSetterToGetter(staticElement);
@@ -675,13 +679,11 @@
       return null;
     }
     if (identical(
-        errorCode, StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION)) {
-      _resolver.reportErrorForNode(
-          StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION, methodName,
-          [methodName.name]);
-    } else if (identical(errorCode, StaticTypeWarningCode.UNDEFINED_FUNCTION)) {
-      _resolver.reportErrorForNode(StaticTypeWarningCode.UNDEFINED_FUNCTION,
-          methodName, [methodName.name]);
+            errorCode, StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION) ||
+        identical(errorCode,
+            CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT) ||
+        identical(errorCode, StaticTypeWarningCode.UNDEFINED_FUNCTION)) {
+      _resolver.reportErrorForNode(errorCode, methodName, [methodName.name]);
     } else if (identical(errorCode, StaticTypeWarningCode.UNDEFINED_METHOD)) {
       String targetTypeName;
       if (target == null) {
@@ -741,13 +743,13 @@
 
   @override
   Object visitPartDirective(PartDirective node) {
-    _setMetadata(node.element, node);
+    setMetadata(node.element, node);
     return null;
   }
 
   @override
   Object visitPartOfDirective(PartOfDirective node) {
-    _setMetadata(node.element, node);
+    setMetadata(node.element, node);
     return null;
   }
 
@@ -1002,6 +1004,10 @@
         Annotation annotation = node.parent as Annotation;
         _resolver.reportErrorForNode(
             CompileTimeErrorCode.INVALID_ANNOTATION, annotation);
+      } else if (element is PrefixElement) {
+        _resolver.reportErrorForNode(
+            CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT, node,
+            [element.name]);
       } else {
         _recordUndefinedNode(_resolver.enclosingClass,
             StaticWarningCode.UNDEFINED_IDENTIFIER, node, [node.name]);
@@ -1087,36 +1093,17 @@
 
   @override
   Object visitTypeParameter(TypeParameter node) {
-    _setMetadata(node.element, node);
+    setMetadata(node.element, node);
     return null;
   }
 
   @override
   Object visitVariableDeclaration(VariableDeclaration node) {
-    _setMetadata(node.element, node);
+    setMetadata(node.element, node);
     return null;
   }
 
   /**
-   * Generate annotation elements for each of the annotations in the
-   * [annotationList] and add them to the given list of [annotations].
-   */
-  void _addAnnotations(List<ElementAnnotationImpl> annotationList,
-      NodeList<Annotation> annotations) {
-    int annotationCount = annotations.length;
-    for (int i = 0; i < annotationCount; i++) {
-      Annotation annotation = annotations[i];
-      Element resolvedElement = annotation.element;
-      if (resolvedElement != null) {
-        ElementAnnotationImpl elementAnnotation =
-            new ElementAnnotationImpl(resolvedElement);
-        annotation.elementAnnotation = elementAnnotation;
-        annotationList.add(elementAnnotation);
-      }
-    }
-  }
-
-  /**
    * Given that we have found code to invoke the given [element], return the
    * error code that should be reported, or `null` if no error should be
    * reported. The [target] is the target of the invocation, or `null` if there
@@ -1127,7 +1114,7 @@
       Expression target, bool useStaticContext, Element element) {
     // Prefix is not declared, instead "prefix.id" are declared.
     if (element is PrefixElement) {
-      element = null;
+      return CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT;
     }
     if (element is PropertyAccessorElement) {
       //
@@ -1355,6 +1342,22 @@
   }
 
   /**
+   * Return the best type of the given [expression] that is to be used for
+   * type analysis.
+   */
+  DartType _getBestType(Expression expression) {
+    DartType bestType = _resolveTypeParameter(expression.bestType);
+    if (bestType is FunctionType) {
+      //
+      // All function types are subtypes of 'Function', which is itself a
+      // subclass of 'Object'.
+      //
+      bestType = _resolver.typeProvider.functionType;
+    }
+    return bestType;
+  }
+
+  /**
    * Assuming that the given [expression] is a prefix for a deferred import,
    * return the library that is being imported.
    */
@@ -1392,22 +1395,6 @@
   }
 
   /**
-   * Return the best type of the given [expression] that is to be used for
-   * type analysis.
-   */
-  DartType _getBestType(Expression expression) {
-    DartType bestType = _resolveTypeParameter(expression.bestType);
-    if (bestType is FunctionType) {
-      //
-      // All function types are subtypes of 'Function', which is itself a
-      // subclass of 'Object'.
-      //
-      bestType = _resolver.typeProvider.functionType;
-    }
-    return bestType;
-  }
-
-  /**
    * Return the propagated type of the given [expression] that is to be used for
    * type analysis.
    */
@@ -2362,10 +2349,11 @@
    * invoked without arguments and the result of that invocation will then be
    * invoked with the arguments. The [target] is the target of the invocation
    * ('e'). The [targetType] is the type of the target. The [methodName] is th
-   *  name of the method being invoked ('m').
+   * name of the method being invoked ('m').  [isConditional] indicates
+   * whether the invocatoin uses a '?.' operator.
    */
-  Element _resolveInvokedElementWithTarget(
-      Expression target, DartType targetType, SimpleIdentifier methodName) {
+  Element _resolveInvokedElementWithTarget(Expression target,
+      DartType targetType, SimpleIdentifier methodName, bool isConditional) {
     if (targetType is InterfaceType) {
       Element element = _lookUpMethod(target, targetType, methodName.name);
       if (element == null) {
@@ -2381,6 +2369,11 @@
     } else if (target is SimpleIdentifier) {
       Element targetElement = target.staticElement;
       if (targetElement is PrefixElement) {
+        if (isConditional) {
+          _resolver.reportErrorForNode(
+              CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT,
+              target, [target.name]);
+        }
         //
         // Look to see whether the name of the method is really part of a
         // prefixed identifier for an imported top-level function or top-level
@@ -2621,35 +2614,6 @@
    * [element] to which that node has been resolved, create the annotations in
    * the element model representing the annotations on the node.
    */
-  void _setMetadata(Element element, AnnotatedNode node) {
-    if (element is! ElementImpl) {
-      return;
-    }
-    List<ElementAnnotationImpl> annotationList =
-        new List<ElementAnnotationImpl>();
-    _addAnnotations(annotationList, node.metadata);
-    if (node is VariableDeclaration && node.parent is VariableDeclarationList) {
-      VariableDeclarationList list = node.parent as VariableDeclarationList;
-      _addAnnotations(annotationList, list.metadata);
-      if (list.parent is FieldDeclaration) {
-        FieldDeclaration fieldDeclaration = list.parent as FieldDeclaration;
-        _addAnnotations(annotationList, fieldDeclaration.metadata);
-      } else if (list.parent is TopLevelVariableDeclaration) {
-        TopLevelVariableDeclaration variableDeclaration =
-            list.parent as TopLevelVariableDeclaration;
-        _addAnnotations(annotationList, variableDeclaration.metadata);
-      }
-    }
-    if (!annotationList.isEmpty) {
-      (element as ElementImpl).metadata = annotationList;
-    }
-  }
-
-  /**
-   * Given a [node] that can have annotations associated with it and the
-   * [element] to which that node has been resolved, create the annotations in
-   * the element model representing the annotations on the node.
-   */
   void _setMetadataForParameter(Element element, NormalFormalParameter node) {
     if (element is! ElementImpl) {
       return;
@@ -2691,6 +2655,53 @@
   }
 
   /**
+   * Given a [node] that can have annotations associated with it and the
+   * [element] to which that node has been resolved, create the annotations in
+   * the element model representing the annotations on the node.
+   */
+  static void setMetadata(Element element, AnnotatedNode node) {
+    if (element is! ElementImpl) {
+      return;
+    }
+    List<ElementAnnotationImpl> annotationList = <ElementAnnotationImpl>[];
+    _addAnnotations(annotationList, node.metadata);
+    if (node is VariableDeclaration && node.parent is VariableDeclarationList) {
+      VariableDeclarationList list = node.parent as VariableDeclarationList;
+      _addAnnotations(annotationList, list.metadata);
+      if (list.parent is FieldDeclaration) {
+        FieldDeclaration fieldDeclaration = list.parent as FieldDeclaration;
+        _addAnnotations(annotationList, fieldDeclaration.metadata);
+      } else if (list.parent is TopLevelVariableDeclaration) {
+        TopLevelVariableDeclaration variableDeclaration =
+            list.parent as TopLevelVariableDeclaration;
+        _addAnnotations(annotationList, variableDeclaration.metadata);
+      }
+    }
+    if (!annotationList.isEmpty) {
+      (element as ElementImpl).metadata = annotationList;
+    }
+  }
+
+  /**
+   * Generate annotation elements for each of the annotations in the
+   * [annotationList] and add them to the given list of [annotations].
+   */
+  static void _addAnnotations(List<ElementAnnotationImpl> annotationList,
+      NodeList<Annotation> annotations) {
+    int annotationCount = annotations.length;
+    for (int i = 0; i < annotationCount; i++) {
+      Annotation annotation = annotations[i];
+      Element resolvedElement = annotation.element;
+      if (resolvedElement != null) {
+        ElementAnnotationImpl elementAnnotation =
+            new ElementAnnotationImpl(resolvedElement);
+        annotation.elementAnnotation = elementAnnotation;
+        annotationList.add(elementAnnotation);
+      }
+    }
+  }
+
+  /**
    * Return `true` if the given [identifier] is the return type of a constructor
    * declaration.
    */
diff --git a/pkg/analyzer/lib/src/generated/engine.dart b/pkg/analyzer/lib/src/generated/engine.dart
index ac74c02..88bae32 100644
--- a/pkg/analyzer/lib/src/generated/engine.dart
+++ b/pkg/analyzer/lib/src/generated/engine.dart
@@ -15,13 +15,17 @@
 import 'package:analyzer/src/context/cache.dart' as cache;
 import 'package:analyzer/src/context/context.dart' as newContext;
 import 'package:analyzer/src/generated/incremental_resolution_validator.dart';
+import 'package:analyzer/src/plugin/command_line_plugin.dart';
 import 'package:analyzer/src/plugin/engine_plugin.dart';
+import 'package:analyzer/src/plugin/options_plugin.dart';
 import 'package:analyzer/src/services/lint.dart';
 import 'package:analyzer/src/task/manager.dart';
 import 'package:analyzer/src/task/task_dart.dart';
 import 'package:analyzer/task/dart.dart';
 import 'package:analyzer/task/model.dart';
+import 'package:html/dom.dart' show Document;
 import 'package:plugin/manager.dart';
+import 'package:plugin/plugin.dart';
 
 import '../../instrumentation/instrumentation.dart';
 import 'ast.dart';
@@ -484,6 +488,7 @@
    *
    * See [getHtmlElement].
    */
+  @deprecated
   HtmlElement computeHtmlElement(Source source);
 
   /**
@@ -604,6 +609,7 @@
    *
    * See [computeHtmlElement].
    */
+  @deprecated
   HtmlElement getHtmlElement(Source source);
 
   /**
@@ -704,6 +710,7 @@
    *
    * See [resolveHtmlUnit].
    */
+  @deprecated
   ht.HtmlUnit getResolvedHtmlUnit(Source htmlSource);
 
   /**
@@ -742,6 +749,12 @@
   bool isServerLibrary(Source librarySource);
 
   /**
+   * Return the stream that is notified when a new value for the given
+   * [descriptor] is computed.
+   */
+  Stream<ComputedResult> onResultComputed(ResultDescriptor descriptor);
+
+  /**
    * Parse the content of the given [source] to produce an AST structure. The
    * resulting AST structure may or may not be resolved, and may have a slightly
    * different structure depending upon whether it is resolved.
@@ -753,6 +766,15 @@
   CompilationUnit parseCompilationUnit(Source source);
 
   /**
+   * Parse a single HTML [source] to produce a document model.
+   *
+   * Throws an [AnalysisException] if the analysis could not be performed
+   *
+   * <b>Note:</b> This method cannot be used in an async environment.
+   */
+  Document parseHtmlDocument(Source source);
+
+  /**
    * Parse a single HTML [source] to produce an AST structure. The resulting
    * HTML AST structure may or may not be resolved, and may have a slightly
    * different structure depending upon whether it is resolved.
@@ -761,12 +783,28 @@
    *
    * <b>Note:</b> This method cannot be used in an async environment.
    */
+  @deprecated // use parseHtmlDocument(source)
   ht.HtmlUnit parseHtmlUnit(Source source);
 
   /**
    * Perform the next unit of work required to keep the analysis results
    * up-to-date and return information about the consequent changes to the
    * analysis results. This method can be long running.
+   *
+   * The implementation that uses the task model notifies subscribers of
+   * [onResultComputed] about computed results.
+   *
+   * The following results are computed for Dart sources.
+   *
+   * 1. For explicit and implicit sources:
+   *    [PARSED_UNIT]
+   *    [RESOLVED_UNIT]
+   *
+   * 2. For explicit sources:
+   *    [DART_ERRORS].
+   *
+   * 3. For explicit and implicit library sources:
+   *    [LIBRARY_ELEMENT].
    */
   AnalysisResult performAnalysisTask();
 
@@ -810,6 +848,7 @@
    *
    * <b>Note:</b> This method cannot be used in an async environment.
    */
+  @deprecated
   ht.HtmlUnit resolveHtmlUnit(Source htmlSource);
 
   /**
@@ -827,6 +866,14 @@
    * so that the default contents will be returned.
    */
   void setContents(Source source, String contents);
+
+  /**
+   * Check the cache for any invalid entries (entries whose modification time
+   * does not match the modification time of the source associated with the
+   * entry). Invalid entries will be marked as invalid so that the source will
+   * be re-analyzed. Return `true` if at least one entry was invalid.
+   */
+  bool validateCacheConsistency();
 }
 
 /**
@@ -1648,6 +1695,7 @@
       source, DartEntry.EXPORTED_LIBRARIES, Source.EMPTY_LIST);
 
   @override
+  @deprecated
   HtmlElement computeHtmlElement(Source source) =>
       _getHtmlResolutionData(source, HtmlEntry.ELEMENT, null);
 
@@ -1893,6 +1941,7 @@
   }
 
   @override
+  @deprecated
   HtmlElement getHtmlElement(Source source) {
     SourceEntry sourceEntry = getReadableSourceEntryOrNull(source);
     if (sourceEntry is HtmlEntry) {
@@ -2091,6 +2140,7 @@
   }
 
   @override
+  @deprecated
   ht.HtmlUnit getResolvedHtmlUnit(Source htmlSource) {
     SourceEntry sourceEntry = getReadableSourceEntryOrNull(htmlSource);
     if (sourceEntry is HtmlEntry) {
@@ -2207,10 +2257,21 @@
   }
 
   @override
+  Stream<ComputedResult> onResultComputed(ResultDescriptor descriptor) {
+    throw new NotImplementedException('In not task-based AnalysisContext.');
+  }
+
+  @override
   CompilationUnit parseCompilationUnit(Source source) =>
       _getDartParseData2(source, DartEntry.PARSED_UNIT, null);
 
   @override
+  Document parseHtmlDocument(Source source) {
+    return null;
+  }
+
+  @override
+  @deprecated
   ht.HtmlUnit parseHtmlUnit(Source source) =>
       _getHtmlParseData(source, HtmlEntry.PARSED_UNIT, null);
 
@@ -2224,9 +2285,6 @@
       AnalysisTask task = PerformanceStatistics.nextTask
           .makeCurrentWhile(() => nextAnalysisTask);
       int getEnd = JavaSystem.currentTimeMillis();
-      if (task == null && _validateCacheConsistency()) {
-        task = nextAnalysisTask;
-      }
       if (task == null) {
         _validateLastIncrementalResolutionResult();
         if (_performAnalysisTaskStopwatch != null) {
@@ -2489,6 +2547,7 @@
           unitSource, librarySource, DartEntry.RESOLVED_UNIT, null);
 
   @override
+  @deprecated
   ht.HtmlUnit resolveHtmlUnit(Source htmlSource) {
     computeHtmlElement(htmlSource);
     return parseHtmlUnit(htmlSource);
@@ -2521,6 +2580,66 @@
   }
 
   @override
+  void test_flushAstStructures(Source source) {
+    DartEntry dartEntry = getReadableSourceEntryOrNull(source);
+    dartEntry.flushAstStructures();
+  }
+
+  @override
+  bool validateCacheConsistency() {
+    int consistencyCheckStart = JavaSystem.nanoTime();
+    List<Source> changedSources = new List<Source>();
+    List<Source> missingSources = new List<Source>();
+    MapIterator<Source, SourceEntry> iterator = _cache.iterator();
+    while (iterator.moveNext()) {
+      Source source = iterator.key;
+      SourceEntry sourceEntry = iterator.value;
+      int sourceTime = getModificationStamp(source);
+      if (sourceTime != sourceEntry.modificationTime) {
+        changedSources.add(source);
+      }
+      if (sourceEntry.exception != null) {
+        if (!exists(source)) {
+          missingSources.add(source);
+        }
+      }
+    }
+    int count = changedSources.length;
+    for (int i = 0; i < count; i++) {
+      _sourceChanged(changedSources[i]);
+    }
+    int removalCount = 0;
+    for (Source source in missingSources) {
+      if (getLibrariesContaining(source).isEmpty &&
+          getLibrariesDependingOn(source).isEmpty) {
+        _cache.remove(source);
+        removalCount++;
+      }
+    }
+    int consistencyCheckEnd = JavaSystem.nanoTime();
+    if (changedSources.length > 0 || missingSources.length > 0) {
+      StringBuffer buffer = new StringBuffer();
+      buffer.write("Consistency check took ");
+      buffer.write((consistencyCheckEnd - consistencyCheckStart) / 1000000.0);
+      buffer.writeln(" ms and found");
+      buffer.write("  ");
+      buffer.write(changedSources.length);
+      buffer.writeln(" inconsistent entries");
+      buffer.write("  ");
+      buffer.write(missingSources.length);
+      buffer.write(" missing sources (");
+      buffer.write(removalCount);
+      buffer.writeln(" removed");
+      for (Source source in missingSources) {
+        buffer.write("    ");
+        buffer.writeln(source.fullName);
+      }
+      _logInformation(buffer.toString());
+    }
+    return changedSources.length > 0;
+  }
+
+  @override
   void visitCacheItems(void callback(Source source, SourceEntry dartEntry,
       DataDescriptor rowDesc, CacheState state)) {
     bool hintsEnabled = _options.hint;
@@ -3987,28 +4106,6 @@
     AnalysisEngine.instance.logger.logInformation(message);
   }
 
-  /**
-   * Notify all of the analysis listeners that a task is about to be performed.
-   */
-  void _notifyAboutToPerformTask(String taskDescription) {
-    int count = _listeners.length;
-    for (int i = 0; i < count; i++) {
-      _listeners[i].aboutToPerformTask(this, taskDescription);
-    }
-  }
-
-  /**
-   * Notify all of the analysis listeners that the errors associated with the
-   * given [source] has been updated to the given [errors].
-   */
-  void _notifyErrors(
-      Source source, List<AnalysisError> errors, LineInfo lineInfo) {
-    int count = _listeners.length;
-    for (int i = 0; i < count; i++) {
-      _listeners[i].computedErrors(this, source, errors, lineInfo);
-    }
-  }
-
 //  /**
 //   * Notify all of the analysis listeners that the given source is no longer included in the set of
 //   * sources that are being analyzed.
@@ -4088,6 +4185,28 @@
 //  }
 
   /**
+   * Notify all of the analysis listeners that a task is about to be performed.
+   */
+  void _notifyAboutToPerformTask(String taskDescription) {
+    int count = _listeners.length;
+    for (int i = 0; i < count; i++) {
+      _listeners[i].aboutToPerformTask(this, taskDescription);
+    }
+  }
+
+  /**
+   * Notify all of the analysis listeners that the errors associated with the
+   * given [source] has been updated to the given [errors].
+   */
+  void _notifyErrors(
+      Source source, List<AnalysisError> errors, LineInfo lineInfo) {
+    int count = _listeners.length;
+    for (int i = 0; i < count; i++) {
+      _listeners[i].computedErrors(this, source, errors, lineInfo);
+    }
+  }
+
+  /**
    * Given that the given [source] (with the corresponding [sourceEntry]) has
    * been invalidated, invalidate all of the libraries that depend on it.
    */
@@ -4686,65 +4805,6 @@
     });
   }
 
-  /**
-   * Check the cache for any invalid entries (entries whose modification time
-   * does not match the modification time of the source associated with the
-   * entry). Invalid entries will be marked as invalid so that the source will
-   * be re-analyzed. Return `true` if at least one entry was invalid.
-   */
-  bool _validateCacheConsistency() {
-    int consistencyCheckStart = JavaSystem.nanoTime();
-    List<Source> changedSources = new List<Source>();
-    List<Source> missingSources = new List<Source>();
-    MapIterator<Source, SourceEntry> iterator = _cache.iterator();
-    while (iterator.moveNext()) {
-      Source source = iterator.key;
-      SourceEntry sourceEntry = iterator.value;
-      int sourceTime = getModificationStamp(source);
-      if (sourceTime != sourceEntry.modificationTime) {
-        changedSources.add(source);
-      }
-      if (sourceEntry.exception != null) {
-        if (!exists(source)) {
-          missingSources.add(source);
-        }
-      }
-    }
-    int count = changedSources.length;
-    for (int i = 0; i < count; i++) {
-      _sourceChanged(changedSources[i]);
-    }
-    int removalCount = 0;
-    for (Source source in missingSources) {
-      if (getLibrariesContaining(source).isEmpty &&
-          getLibrariesDependingOn(source).isEmpty) {
-        _cache.remove(source);
-        removalCount++;
-      }
-    }
-    int consistencyCheckEnd = JavaSystem.nanoTime();
-    if (changedSources.length > 0 || missingSources.length > 0) {
-      StringBuffer buffer = new StringBuffer();
-      buffer.write("Consistency check took ");
-      buffer.write((consistencyCheckEnd - consistencyCheckStart) / 1000000.0);
-      buffer.writeln(" ms and found");
-      buffer.write("  ");
-      buffer.write(changedSources.length);
-      buffer.writeln(" inconsistent entries");
-      buffer.write("  ");
-      buffer.write(missingSources.length);
-      buffer.write(" missing sources (");
-      buffer.write(removalCount);
-      buffer.writeln(" removed");
-      for (Source source in missingSources) {
-        buffer.write("    ");
-        buffer.writeln(source.fullName);
-      }
-      _logInformation(buffer.toString());
-    }
-    return changedSources.length > 0;
-  }
-
   void _validateLastIncrementalResolutionResult() {
     if (incrementalResolutionValidation_lastUnitSource == null ||
         incrementalResolutionValidation_lastLibrarySource == null ||
@@ -5703,11 +5763,24 @@
   Logger _logger = Logger.NULL;
 
   /**
+   * The plugin that defines the extension points and extensions that are defined by
+   * command-line applications using the analysis engine.
+   */
+  final CommandLinePlugin commandLinePlugin = new CommandLinePlugin();
+
+  /**
    * The plugin that defines the extension points and extensions that are
    * inherently defined by the analysis engine.
    */
   final EnginePlugin enginePlugin = new EnginePlugin();
 
+  /***
+   * The plugin that defines the extension points and extensions that are defined
+   * by applications that want to consume options defined in the analysis
+   * options file.
+   */
+  final OptionsPlugin optionsPlugin = new OptionsPlugin();
+
   /**
    * The instrumentation service that is to be used by this analysis engine.
    */
@@ -5715,6 +5788,11 @@
       InstrumentationService.NULL_SERVICE;
 
   /**
+   * The list of supported plugins for processing by clients.
+   */
+  List<Plugin> _supportedPlugins;
+
+  /**
    * The partition manager being used to manage the shared partitions.
    */
   final PartitionManager partitionManager = new PartitionManager();
@@ -5771,6 +5849,20 @@
   }
 
   /**
+   * Return the list of supported plugins for processing by clients.
+   */
+  List<Plugin> get supportedPlugins {
+    if (_supportedPlugins == null) {
+      _supportedPlugins = <Plugin>[
+        enginePlugin,
+        commandLinePlugin,
+        optionsPlugin
+      ];
+    }
+    return _supportedPlugins;
+  }
+
+  /**
    * Return the task manager used to manage the tasks used to analyze code.
    */
   TaskManager get taskManager {
@@ -5940,6 +6032,7 @@
   /**
    * Reports that the given HTML [source] was parsed in the given [context].
    */
+  @deprecated
   void parsedHtml(AnalysisContext context, Source source, ht.HtmlUnit unit);
 
   /**
@@ -5951,6 +6044,7 @@
   /**
    * Reports that the given HTML [source] was resolved in the given [context].
    */
+  @deprecated
   void resolvedHtml(AnalysisContext context, Source source, ht.HtmlUnit unit);
 }
 
@@ -6853,6 +6947,7 @@
    * The fully resolved HTML AST that changed as a result of the analysis, or
    * `null` if the AST was not changed.
    */
+  @deprecated
   ht.HtmlUnit get resolvedHtmlUnit;
 
   /**
@@ -6891,6 +6986,7 @@
    * The fully resolved HTML AST that changed as a result of the analysis, or
    * `null` if the AST was not changed.
    */
+  @deprecated
   ht.HtmlUnit resolvedHtmlUnit;
 
   /**
@@ -7183,6 +7279,36 @@
 }
 
 /**
+ * [ComputedResult] describes a value computed for a [ResultDescriptor].
+ */
+class ComputedResult<V> {
+  /**
+   * The context in which the value was computed.
+   */
+  final AnalysisContext context;
+
+  /**
+   * The descriptor of the result which was computed.
+   */
+  final ResultDescriptor<V> descriptor;
+
+  /**
+   * The target for which the result was computed.
+   */
+  final AnalysisTarget target;
+
+  /**
+   * The computed value.
+   */
+  final V value;
+
+  ComputedResult(this.context, this.descriptor, this.target, this.value);
+
+  @override
+  String toString() => '$descriptor of $target in $context';
+}
+
+/**
  * A pair containing a library and a list of the (source, entry) pairs for
  * compilation units in the library.
  */
@@ -9187,6 +9313,12 @@
   bool shouldErrorsBeAnalyzed(Source source, Object entry);
 
   /**
+   * For testing only: flush all representations of the AST (both resolved and
+   * unresolved) for the given [source] out of the cache.
+   */
+  void test_flushAstStructures(Source source);
+
+  /**
    * Call the given callback function for eache cache item in the context.
    */
   void visitCacheItems(void callback(Source source, SourceEntry dartEntry,
diff --git a/pkg/analyzer/lib/src/generated/error.dart b/pkg/analyzer/lib/src/generated/error.dart
index 03befb3..c667af7 100644
--- a/pkg/analyzer/lib/src/generated/error.dart
+++ b/pkg/analyzer/lib/src/generated/error.dart
@@ -209,11 +209,11 @@
    * a single list of errors.
    */
   static List<AnalysisError> mergeLists(List<List<AnalysisError>> errorLists) {
-    List<AnalysisError> errors = <AnalysisError>[];
+    Set<AnalysisError> errors = new HashSet<AnalysisError>();
     for (List<AnalysisError> errorList in errorLists) {
       errors.addAll(errorList);
     }
-    return errors;
+    return errors.toList();
   }
 }
 
@@ -1949,6 +1949,14 @@
           "The name '{0}' is already used as an import prefix and cannot be used to name a top-level element");
 
   /**
+   * 16.32 Identifier Reference: If d is a prefix p, a compile-time error
+   * occurs unless the token immediately following d is '.'.
+   */
+  static const CompileTimeErrorCode PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT =
+      const CompileTimeErrorCode('PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT',
+          "The name '{0}' refers to an import prefix, so it must be followed by '.'");
+
+  /**
    * 6.2.2 Optional Formals: It is a compile-time error if the name of a named
    * optional parameter begins with an '_' character.
    */
@@ -3103,6 +3111,38 @@
 }
 
 /**
+ * The error codes used for errors in HTML files. The convention for this
+ * class is for the name of the error code to indicate the problem that caused
+ * the error to be generated and for the error message to explain what is wrong
+ * and, when appropriate, how the problem can be corrected.
+ */
+class HtmlErrorCode extends ErrorCode {
+  /**
+   * An error code indicating that there is a syntactic error in the file.
+   *
+   * Parameters:
+   * 0: the error message from the parse error
+   */
+  static const HtmlErrorCode PARSE_ERROR =
+      const HtmlErrorCode('PARSE_ERROR', '{0}');
+
+  /**
+   * 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
+   * given [correction] template.
+   */
+  const HtmlErrorCode(String name, String message, [String correction])
+      : super(name, message, correction);
+
+  @override
+  ErrorSeverity get errorSeverity => ErrorSeverity.ERROR;
+
+  @override
+  ErrorType get type => ErrorType.COMPILE_TIME_ERROR;
+}
+
+/**
  * The error codes used for warnings in HTML files. The convention for this
  * class is for the name of the error code to indicate the problem that caused
  * the error to be generated and for the error message to explain what is wrong
diff --git a/pkg/analyzer/lib/src/generated/html.dart b/pkg/analyzer/lib/src/generated/html.dart
index c6ad0e0..222fdf8 100644
--- a/pkg/analyzer/lib/src/generated/html.dart
+++ b/pkg/analyzer/lib/src/generated/html.dart
@@ -508,6 +508,7 @@
  * Instances of the class `HtmlScriptTagNode` represent a script tag within an HTML file that
  * references a Dart script.
  */
+@deprecated
 class HtmlScriptTagNode extends XmlTagNode {
   /**
    * The AST structure representing the Dart code within this tag.
@@ -563,6 +564,7 @@
 /**
  * Instances of the class `HtmlUnit` represent the contents of an HTML file.
  */
+@deprecated
 class HtmlUnit extends XmlNode {
   /**
    * The first token in the token stream that was parsed to form this HTML unit.
diff --git a/pkg/analyzer/lib/src/generated/incremental_resolver.dart b/pkg/analyzer/lib/src/generated/incremental_resolver.dart
index 82165c0..3a3374a 100644
--- a/pkg/analyzer/lib/src/generated/incremental_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/incremental_resolver.dart
@@ -20,6 +20,7 @@
         SCAN_ERRORS,
         USED_IMPORTED_ELEMENTS,
         USED_LOCAL_ELEMENTS,
+        VARIABLE_REFERENCE_ERRORS,
         VERIFY_ERRORS;
 import 'package:analyzer/task/dart.dart'
     show DART_ERRORS, LibrarySpecificUnit, PARSED_UNIT, TOKEN_STREAM;
@@ -836,7 +837,7 @@
   /**
    * The context the compilation unit being resolved in.
    */
-  AnalysisContextImpl _context;
+  AnalysisContext _context;
 
   /**
    * The object used to access the types from the core library.
@@ -1133,10 +1134,11 @@
   }
 
   void _shiftEntryErrors_NEW() {
-    _shiftErrors_NEW(RESOLVE_TYPE_NAMES_ERRORS);
-    _shiftErrors_NEW(RESOLVE_REFERENCES_ERRORS);
-    _shiftErrors_NEW(VERIFY_ERRORS);
     _shiftErrors_NEW(HINTS);
+    _shiftErrors_NEW(RESOLVE_REFERENCES_ERRORS);
+    _shiftErrors_NEW(RESOLVE_TYPE_NAMES_ERRORS);
+    _shiftErrors_NEW(VARIABLE_REFERENCE_ERRORS);
+    _shiftErrors_NEW(VERIFY_ERRORS);
   }
 
   void _shiftEntryErrors_OLD() {
@@ -1185,8 +1187,9 @@
   }
 
   void _updateEntry_NEW() {
-    _updateErrors_NEW(RESOLVE_TYPE_NAMES_ERRORS, []);
     _updateErrors_NEW(RESOLVE_REFERENCES_ERRORS, _resolveErrors);
+    _updateErrors_NEW(RESOLVE_TYPE_NAMES_ERRORS, []);
+    _updateErrors_NEW(VARIABLE_REFERENCE_ERRORS, []);
     _updateErrors_NEW(VERIFY_ERRORS, _verifyErrors);
     // invalidate results we don't update incrementally
     newUnitEntry.setState(USED_IMPORTED_ELEMENTS, CacheState.INVALID);
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index d4eee82..422a8e2 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -7837,7 +7837,6 @@
     }
     _buildDirectiveModels();
     _typeProvider = new TypeProviderImpl(coreElement, asyncElement);
-    _buildTypeAliases();
     _buildTypeHierarchies();
     //
     // Perform resolution and type analysis.
@@ -7917,7 +7916,6 @@
     _buildDirectiveModels();
     _typeProvider = new TypeProviderImpl(coreElement, asyncElement);
     _buildEnumMembers();
-    _buildTypeAliases();
     _buildTypeHierarchies();
     _buildImplicitConstructors();
     //
@@ -8216,37 +8214,6 @@
   }
 
   /**
-   * Resolve the types referenced by function type aliases across all of the function type aliases
-   * defined in the current cycle.
-   *
-   * @throws AnalysisException if any of the function type aliases could not be resolved
-   */
-  void _buildTypeAliases() {
-    PerformanceStatistics.resolve.makeCurrentWhile(() {
-      List<LibraryResolver_TypeAliasInfo> typeAliases =
-          new List<LibraryResolver_TypeAliasInfo>();
-      for (Library library in _librariesInCycles) {
-        for (Source source in library.compilationUnitSources) {
-          CompilationUnit ast = library.getAST(source);
-          for (CompilationUnitMember member in ast.declarations) {
-            if (member is FunctionTypeAlias) {
-              typeAliases.add(
-                  new LibraryResolver_TypeAliasInfo(library, source, member));
-            }
-          }
-        }
-      }
-      // TODO(brianwilkerson) We need to sort the type aliases such that all
-      // aliases referenced by an alias T are resolved before we resolve T.
-      for (LibraryResolver_TypeAliasInfo info in typeAliases) {
-        TypeResolverVisitor visitor = new TypeResolverVisitor.con1(
-            info._library, info._source, _typeProvider);
-        info._typeAlias.accept(visitor);
-      }
-    });
-  }
-
-  /**
    * Resolve the type hierarchy across all of the types declared in the libraries in the current
    * cycle.
    *
@@ -8685,7 +8652,6 @@
     _buildDirectiveModels();
     _typeProvider = new TypeProviderImpl(coreElement, asyncElement);
     _buildEnumMembers();
-    _buildTypeAliases();
     _buildTypeHierarchies();
     _buildImplicitConstructors();
     //
@@ -8925,38 +8891,6 @@
   }
 
   /**
-   * Resolve the types referenced by function type aliases across all of the function type aliases
-   * defined in the current cycle.
-   *
-   * @throws AnalysisException if any of the function type aliases could not be resolved
-   */
-  void _buildTypeAliases() {
-    PerformanceStatistics.resolve.makeCurrentWhile(() {
-      List<LibraryResolver2_TypeAliasInfo> typeAliases =
-          new List<LibraryResolver2_TypeAliasInfo>();
-      for (ResolvableLibrary library in _librariesInCycle) {
-        for (ResolvableCompilationUnit unit
-            in library.resolvableCompilationUnits) {
-          for (CompilationUnitMember member
-              in unit.compilationUnit.declarations) {
-            if (member is FunctionTypeAlias) {
-              typeAliases.add(new LibraryResolver2_TypeAliasInfo(
-                  library, unit.source, member));
-            }
-          }
-        }
-      }
-      // TODO(brianwilkerson) We need to sort the type aliases such that all
-      // aliases referenced by an alias T are resolved before we resolve T.
-      for (LibraryResolver2_TypeAliasInfo info in typeAliases) {
-        TypeResolverVisitor visitor = new TypeResolverVisitor.con4(
-            info._library, info._source, _typeProvider);
-        info._typeAlias.accept(visitor);
-      }
-    });
-  }
-
-  /**
    * Resolve the type hierarchy across all of the types declared in the libraries in the current
    * cycle.
    *
@@ -10994,10 +10928,12 @@
   @override
   Object visitEnumDeclaration(EnumDeclaration node) {
     //
-    // Resolve the metadata in the library scope.
+    // Resolve the metadata in the library scope
+    // and associate the annotations with the element.
     //
     if (node.metadata != null) {
       node.metadata.accept(this);
+      ElementResolver.setMetadata(node.element, node);
     }
     //
     // There is nothing else to do because everything else was resolved by the
@@ -14040,11 +13976,8 @@
   Object visitFunctionTypeAlias(FunctionTypeAlias node) {
     FunctionTypeAliasElementImpl element =
         node.element as FunctionTypeAliasElementImpl;
-    if (element.returnType == null) {
-      // Only visit function type aliases once.
-      super.visitFunctionTypeAlias(node);
-      element.returnType = _computeReturnType(node.returnType);
-    }
+    super.visitFunctionTypeAlias(node);
+    element.returnType = _computeReturnType(node.returnType);
     return null;
   }
 
@@ -14925,6 +14858,114 @@
 }
 
 /**
+ * The interface `TypeSystem` defines the behavior of an object representing
+ * the type system.  This provides a common location to put methods that act on
+ * types but may need access to more global data structures, and it paves the
+ * way for a possible future where we may wish to make the type system
+ * pluggable.
+ */
+abstract class TypeSystem {
+  /**
+   * Return the [TypeProvider] associated with this [TypeSystem].
+   */
+  TypeProvider get typeProvider;
+
+  /**
+   * Compute the least upper bound of two types.
+   */
+  DartType getLeastUpperBound(DartType type1, DartType type2);
+}
+
+/**
+ * Implementation of [TypeSystem] using the rules in the Dart specification.
+ */
+class TypeSystemImpl implements TypeSystem {
+  @override
+  final TypeProvider typeProvider;
+
+  TypeSystemImpl(this.typeProvider);
+
+  @override
+  DartType getLeastUpperBound(DartType type1, DartType type2) {
+    // The least upper bound relation is reflexive.
+    if (identical(type1, type2)) {
+      return type1;
+    }
+    // The least upper bound of dynamic and any type T is dynamic.
+    if (type1.isDynamic) {
+      return type1;
+    }
+    if (type2.isDynamic) {
+      return type2;
+    }
+    // The least upper bound of void and any type T != dynamic is void.
+    if (type1.isVoid) {
+      return type1;
+    }
+    if (type2.isVoid) {
+      return type2;
+    }
+    // The least upper bound of bottom and any type T is T.
+    if (type1.isBottom) {
+      return type2;
+    }
+    if (type2.isBottom) {
+      return type1;
+    }
+    // Let U be a type variable with upper bound B.  The least upper bound of U
+    // and a type T is the least upper bound of B and T.
+    while (type1 is TypeParameterType) {
+      // TODO(paulberry): is this correct in the complex of F-bounded
+      // polymorphism?
+      DartType bound = (type1 as TypeParameterType).element.bound;
+      if (bound == null) {
+        bound = typeProvider.objectType;
+      }
+      type1 = bound;
+    }
+    while (type2 is TypeParameterType) {
+      // TODO(paulberry): is this correct in the context of F-bounded
+      // polymorphism?
+      DartType bound = (type2 as TypeParameterType).element.bound;
+      if (bound == null) {
+        bound = typeProvider.objectType;
+      }
+      type2 = bound;
+    }
+    // The least upper bound of a function type and an interface type T is the
+    // least upper bound of Function and T.
+    if (type1 is FunctionType && type2 is InterfaceType) {
+      type1 = typeProvider.functionType;
+    }
+    if (type2 is FunctionType && type1 is InterfaceType) {
+      type2 = typeProvider.functionType;
+    }
+
+    // At this point type1 and type2 should both either be interface types or
+    // function types.
+    if (type1 is InterfaceType && type2 is InterfaceType) {
+      InterfaceType result =
+          InterfaceTypeImpl.computeLeastUpperBound(type1, type2);
+      if (result == null) {
+        return typeProvider.dynamicType;
+      }
+      return result;
+    } else if (type1 is FunctionType && type2 is FunctionType) {
+      FunctionType result =
+          FunctionTypeImpl.computeLeastUpperBound(type1, type2);
+      if (result == null) {
+        return typeProvider.functionType;
+      }
+      return result;
+    } else {
+      // Should never happen.  As a defensive measure, return the dynamic type.
+      assert(false);
+      return typeProvider.dynamicType;
+    }
+  }
+}
+
+/**
  * Instances of the class [UnusedLocalElementsVerifier] traverse an element
  * structure looking for cases of [HintCode.UNUSED_ELEMENT],
  * [HintCode.UNUSED_FIELD], [HintCode.UNUSED_LOCAL_VARIABLE], etc.
diff --git a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
index d091b2a..20f3957 100644
--- a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
+++ b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
@@ -42,6 +42,11 @@
   TypeProvider _typeProvider;
 
   /**
+   * The type system in use for static type analysis.
+   */
+  TypeSystem _typeSystem;
+
+  /**
    * The type representing the type 'dynamic'.
    */
   DartType _dynamicType;
@@ -78,6 +83,7 @@
     _dynamicType = _typeProvider.dynamicType;
     _overrideManager = _resolver.overrideManager;
     _promoteManager = _resolver.promoteManager;
+    _typeSystem = new TypeSystemImpl(_typeProvider);
   }
 
   /**
@@ -1202,7 +1208,8 @@
       // TODO(brianwilkerson) Determine whether this can still happen.
       staticType2 = _dynamicType;
     }
-    DartType staticType = staticType1.getLeastUpperBound(staticType2);
+    DartType staticType =
+        _typeSystem.getLeastUpperBound(staticType1, staticType2);
     if (staticType == null) {
       staticType = _dynamicType;
     }
@@ -1217,7 +1224,7 @@
         propagatedType2 = staticType2;
       }
       DartType propagatedType =
-          propagatedType1.getLeastUpperBound(propagatedType2);
+          _typeSystem.getLeastUpperBound(propagatedType1, propagatedType2);
       _resolver.recordPropagatedTypeIfBetter(node, propagatedType);
     }
   }
@@ -1266,7 +1273,8 @@
     }
     if (body is BlockFunctionBody) {
       _StaticTypeAnalyzer_computePropagatedReturnTypeOfFunction visitor =
-          new _StaticTypeAnalyzer_computePropagatedReturnTypeOfFunction();
+          new _StaticTypeAnalyzer_computePropagatedReturnTypeOfFunction(
+              _typeSystem);
       body.accept(visitor);
       return visitor.result;
     }
@@ -1927,9 +1935,10 @@
 
 class _StaticTypeAnalyzer_computePropagatedReturnTypeOfFunction
     extends GeneralizingAstVisitor<Object> {
+  final TypeSystem typeSystem;
   DartType result = null;
 
-  _StaticTypeAnalyzer_computePropagatedReturnTypeOfFunction();
+  _StaticTypeAnalyzer_computePropagatedReturnTypeOfFunction(this.typeSystem);
 
   @override
   Object visitExpression(Expression node) => null;
@@ -1948,7 +1957,7 @@
     if (result == null) {
       result = type;
     } else {
-      result = result.getLeastUpperBound(type);
+      result = typeSystem.getLeastUpperBound(result, type);
     }
     return null;
   }
diff --git a/pkg/analyzer/lib/src/generated/testing/element_factory.dart b/pkg/analyzer/lib/src/generated/testing/element_factory.dart
index c648e03..4c2a537 100644
--- a/pkg/analyzer/lib/src/generated/testing/element_factory.dart
+++ b/pkg/analyzer/lib/src/generated/testing/element_factory.dart
@@ -373,6 +373,7 @@
     return getter;
   }
 
+  @deprecated
   static HtmlElementImpl htmlUnit(AnalysisContext context, String fileName) {
     Source source =
         new NonExistingSource(fileName, toUri(fileName), UriKind.FILE_URI);
@@ -556,6 +557,9 @@
     return variable;
   }
 
-  static TypeParameterElementImpl typeParameterElement(String name) =>
-      new TypeParameterElementImpl(name, 0);
+  static TypeParameterElementImpl typeParameterElement(String name) {
+    TypeParameterElementImpl element = new TypeParameterElementImpl(name, 0);
+    element.type = new TypeParameterTypeImpl(element);
+    return element;
+  }
 }
diff --git a/pkg/analyzer/lib/src/generated/testing/html_factory.dart b/pkg/analyzer/lib/src/generated/testing/html_factory.dart
index a8fcb53..5006c02 100644
--- a/pkg/analyzer/lib/src/generated/testing/html_factory.dart
+++ b/pkg/analyzer/lib/src/generated/testing/html_factory.dart
@@ -12,6 +12,7 @@
 /**
  * Utility methods to create HTML nodes.
  */
+@deprecated
 class HtmlFactory {
   static XmlAttributeNode attribute(String name, String value) {
     Token nameToken = stringToken(name);
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 f24b96b..cc90ec6 100644
--- a/pkg/analyzer/lib/src/generated/testing/test_type_provider.dart
+++ b/pkg/analyzer/lib/src/generated/testing/test_type_provider.dart
@@ -11,10 +11,8 @@
 import 'package:analyzer/src/generated/constant.dart';
 import 'package:analyzer/src/generated/element.dart';
 import 'package:analyzer/src/generated/resolver.dart';
-import 'package:analyzer/src/generated/scanner.dart';
 import 'package:analyzer/src/generated/testing/ast_factory.dart';
 import 'package:analyzer/src/generated/testing/element_factory.dart';
-import 'package:analyzer/src/generated/testing/token_factory.dart';
 
 /**
  * A type provider that can be used by tests without creating the element model
diff --git a/pkg/analyzer/lib/src/plugin/command_line_plugin.dart b/pkg/analyzer/lib/src/plugin/command_line_plugin.dart
index 493bced..ffd43be 100644
--- a/pkg/analyzer/lib/src/plugin/command_line_plugin.dart
+++ b/pkg/analyzer/lib/src/plugin/command_line_plugin.dart
@@ -56,7 +56,7 @@
    * Return a list containing all of the result processors that were
    * contributed.
    */
-  List<ArgParserContributor> get resultProcessors =>
+  List<ArgResultsProcessor> get resultProcessors =>
       resultProcessorExtensionPoint.extensions;
 
   @override
diff --git a/pkg/analyzer/lib/src/plugin/engine_plugin.dart b/pkg/analyzer/lib/src/plugin/engine_plugin.dart
index bed1191..d95454d 100644
--- a/pkg/analyzer/lib/src/plugin/engine_plugin.dart
+++ b/pkg/analyzer/lib/src/plugin/engine_plugin.dart
@@ -7,6 +7,7 @@
 import 'package:analyzer/plugin/task.dart';
 import 'package:analyzer/src/task/dart.dart';
 import 'package:analyzer/src/task/general.dart';
+import 'package:analyzer/src/task/html.dart';
 import 'package:analyzer/task/model.dart';
 import 'package:plugin/plugin.dart';
 
@@ -66,7 +67,6 @@
     registerExtension(taskId, BuildDirectiveElementsTask.DESCRIPTOR);
     registerExtension(taskId, BuildEnumMemberElementsTask.DESCRIPTOR);
     registerExtension(taskId, BuildExportNamespaceTask.DESCRIPTOR);
-    registerExtension(taskId, BuildFunctionTypeAliasesTask.DESCRIPTOR);
     registerExtension(taskId, BuildLibraryConstructorsTask.DESCRIPTOR);
     registerExtension(taskId, BuildLibraryElementTask.DESCRIPTOR);
     registerExtension(taskId, BuildPublicNamespaceTask.DESCRIPTOR);
@@ -83,8 +83,9 @@
     registerExtension(taskId, LibraryErrorsReadyTask.DESCRIPTOR);
     registerExtension(taskId, LibraryUnitErrorsTask.DESCRIPTOR);
     registerExtension(taskId, ParseDartTask.DESCRIPTOR);
+    registerExtension(taskId, ResolveLibraryReferencesTask.DESCRIPTOR);
     registerExtension(taskId, ResolveLibraryTypeNamesTask.DESCRIPTOR);
-    registerExtension(taskId, ResolveReferencesTask.DESCRIPTOR);
+    registerExtension(taskId, ResolveUnitReferencesTask.DESCRIPTOR);
     registerExtension(taskId, ResolveUnitTypeNamesTask.DESCRIPTOR);
     registerExtension(taskId, ResolveVariableReferencesTask.DESCRIPTOR);
     registerExtension(taskId, ScanDartTask.DESCRIPTOR);
@@ -92,6 +93,9 @@
     //
     // Register HTML tasks.
     //
+    registerExtension(taskId, DartScriptsTask.DESCRIPTOR);
+    registerExtension(taskId, HtmlErrorsTask.DESCRIPTOR);
+    registerExtension(taskId, ParseHtmlTask.DESCRIPTOR);
   }
 
   /**
diff --git a/pkg/analyzer/lib/src/plugin/options_plugin.dart b/pkg/analyzer/lib/src/plugin/options_plugin.dart
new file mode 100644
index 0000000..1dea284
--- /dev/null
+++ b/pkg/analyzer/lib/src/plugin/options_plugin.dart
@@ -0,0 +1,51 @@
+// 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.plugin.options;
+
+import 'package:analyzer/plugin/options.dart';
+import 'package:plugin/plugin.dart';
+
+/// A plugin that defines the extension points and extensions that are defined
+/// by applications that want to consume options defined in the analysis
+/// options file.
+class OptionsPlugin implements Plugin {
+
+  /// The simple identifier of the extension point that allows plugins to
+  /// register new options processors.
+  static const String OPTIONS_PROCESSOR_EXTENSION_POINT = 'optionsProcessor';
+
+  /// The unique identifier of this plugin.
+  static const String UNIQUE_IDENTIFIER = 'options.core';
+
+  /// The extension point that allows plugins to register new options processors.
+  ExtensionPoint optionsProcessorExtensionPoint;
+
+  /// All contributed options processors.
+  List<OptionsProcessor> get optionsProcessors =>
+      optionsProcessorExtensionPoint.extensions;
+
+  @override
+  String get uniqueIdentifier => UNIQUE_IDENTIFIER;
+
+  @override
+  void registerExtensionPoints(RegisterExtensionPoint registerExtensionPoint) {
+    optionsProcessorExtensionPoint = registerExtensionPoint(
+        OPTIONS_PROCESSOR_EXTENSION_POINT, _validateOptionsProcessorExtension);
+  }
+
+  @override
+  void registerExtensions(RegisterExtension registerExtension) {
+    // There are no default extensions.
+  }
+
+  /// Validate the given extension by throwing an [ExtensionError] if it is not a
+  /// valid options processor.
+  void _validateOptionsProcessorExtension(Object extension) {
+    if (extension is! OptionsProcessor) {
+      String id = optionsProcessorExtensionPoint.uniqueIdentifier;
+      throw new ExtensionError('Extensions to $id must be an OptionsProcessor');
+    }
+  }
+}
diff --git a/pkg/analyzer/lib/src/task/dart.dart b/pkg/analyzer/lib/src/task/dart.dart
index f27614d..bf53bb2 100644
--- a/pkg/analyzer/lib/src/task/dart.dart
+++ b/pkg/analyzer/lib/src/task/dart.dart
@@ -23,6 +23,8 @@
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/task/driver.dart';
 import 'package:analyzer/src/task/general.dart';
+import 'package:analyzer/src/task/html.dart';
+import 'package:analyzer/src/task/inputs.dart';
 import 'package:analyzer/src/task/model.dart';
 import 'package:analyzer/task/dart.dart';
 import 'package:analyzer/task/general.dart';
@@ -46,17 +48,6 @@
         'BUILD_DIRECTIVES_ERRORS', AnalysisError.NO_ERRORS);
 
 /**
- * The errors produced while building function type aliases.
- *
- * The list will be empty if there were no errors, but will not be `null`.
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ListResultDescriptor<AnalysisError> BUILD_FUNCTION_TYPE_ALIASES_ERRORS =
-    new ListResultDescriptor<AnalysisError>(
-        'BUILD_FUNCTION_TYPE_ALIASES_ERRORS', AnalysisError.NO_ERRORS);
-
-/**
  * The errors produced while building a library element.
  *
  * The list will be empty if there were no errors, but will not be `null`.
@@ -242,7 +233,7 @@
 /**
  * The partial [LibraryElement] associated with a library.
  *
- * [LIBRARY_ELEMENT4] plus [RESOLVED_UNIT4] for every unit.
+ * [LIBRARY_ELEMENT4] plus resolved types for every element.
  *
  * The result is only available for [Source]s representing a library.
  */
@@ -251,6 +242,17 @@
         cachingPolicy: ELEMENT_CACHING_POLICY);
 
 /**
+ * The partial [LibraryElement] associated with a library.
+ *
+ * [LIBRARY_ELEMENT5] plus resolved elements and types for all expressions.
+ *
+ * The result is only available for [Source]s representing a library.
+ */
+final ResultDescriptor<LibraryElement> LIBRARY_ELEMENT6 =
+    new ResultDescriptor<LibraryElement>('LIBRARY_ELEMENT6', null,
+        cachingPolicy: ELEMENT_CACHING_POLICY);
+
+/**
  * The flag specifying whether all analysis errors are computed in a specific
  * library.
  *
@@ -326,7 +328,7 @@
 /**
  * The partially resolved [CompilationUnit] associated with a unit.
  *
- * All the function type aliases are resolved.
+ * [RESOLVED_UNIT2] with resolved type names.
  *
  * The result is only available for [LibrarySpecificUnit]s.
  */
@@ -337,7 +339,7 @@
 /**
  * The partially resolved [CompilationUnit] associated with a unit.
  *
- * [RESOLVED_UNIT3] with resolved type names.
+ * [RESOLVED_UNIT3] plus resolved local variables and formal parameters.
  *
  * The result is only available for [LibrarySpecificUnit]s.
  */
@@ -346,24 +348,13 @@
         cachingPolicy: AST_CACHING_POLICY);
 
 /**
- * The partially resolved [CompilationUnit] associated with a unit.
- *
- * [RESOLVED_UNIT4] plus resolved local variables and formal parameters.
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ResultDescriptor<CompilationUnit> RESOLVED_UNIT5 =
-    new ResultDescriptor<CompilationUnit>('RESOLVED_UNIT5', null,
-        cachingPolicy: AST_CACHING_POLICY);
-
-/**
  * The resolved [CompilationUnit] associated with a compilation unit, with
  * constants not yet resolved.
  *
  * The result is only available for [LibrarySpecificUnit]s.
  */
-final ResultDescriptor<CompilationUnit> RESOLVED_UNIT6 =
-    new ResultDescriptor<CompilationUnit>('RESOLVED_UNIT6', null,
+final ResultDescriptor<CompilationUnit> RESOLVED_UNIT5 =
+    new ResultDescriptor<CompilationUnit>('RESOLVED_UNIT5', null,
         cachingPolicy: AST_CACHING_POLICY);
 
 /**
@@ -404,6 +395,17 @@
         cachingPolicy: ELEMENT_CACHING_POLICY);
 
 /**
+ * The errors produced while resolving variable references in a compilation unit.
+ *
+ * The list will be empty if there were no errors, but will not be `null`.
+ *
+ * The result is only available for [LibrarySpecificUnit]s.
+ */
+final ListResultDescriptor<AnalysisError> VARIABLE_REFERENCE_ERRORS =
+    new ListResultDescriptor<AnalysisError>(
+        'VARIABLE_REFERENCE_ERRORS', AnalysisError.NO_ERRORS);
+
+/**
  * The errors produced while verifying a compilation unit.
  *
  * The list will be empty if there were no errors, but will not be `null`.
@@ -415,6 +417,17 @@
         'VERIFY_ERRORS', AnalysisError.NO_ERRORS);
 
 /**
+ * Return a list of errors containing the errors from the given [errors] list
+ * but with duplications removed.
+ */
+List<AnalysisError> removeDuplicateErrors(List<AnalysisError> errors) {
+  if (errors.isEmpty) {
+    return errors;
+  }
+  return errors.toSet().toList();
+}
+
+/**
  * A task that builds implicit constructors for a [ClassElement], or keeps
  * the existing explicit constructors if the class has them.
  */
@@ -509,11 +522,12 @@
    * input descriptors describing those inputs for a task with the
    * given [classElement].
    */
-  static Map<String, TaskInput> buildInputs(ClassElement classElement) {
-    Source librarySource = classElement.library.source;
-    DartType superType = classElement.supertype;
+  static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
+    ClassElement element = target;
+    Source librarySource = element.library.source;
+    DartType superType = element.supertype;
     if (superType is InterfaceType) {
-      if (classElement.isMixinApplication || classElement.mixins.isNotEmpty) {
+      if (element.isMixinApplication || element.mixins.isNotEmpty) {
         ClassElement superElement = superType.element;
         return <String, TaskInput>{
           'libraryDep': LIBRARY_ELEMENT5.of(librarySource),
@@ -717,9 +731,10 @@
    * input descriptors describing those inputs for a task with the given
    * [target].
    */
-  static Map<String, TaskInput> buildInputs(LibrarySpecificUnit target) {
+  static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
+    LibrarySpecificUnit unit = target;
     return <String, TaskInput>{
-      PARSED_UNIT_INPUT_NAME: PARSED_UNIT.of(target.unit)
+      PARSED_UNIT_INPUT_NAME: PARSED_UNIT.of(unit.unit)
     };
   }
 
@@ -825,6 +840,9 @@
           // directive was invalid.
           LibraryElement importedLibrary = importLibraryMap[importedSource];
           if (importedLibrary != null) {
+            if (importedLibrary.isDartCore) {
+              explicitlyImportsCore = true;
+            }
             ImportElementImpl importElement =
                 new ImportElementImpl(directive.offset);
             StringLiteral uriLiteral = importDirective.uri;
@@ -915,19 +933,20 @@
    * input descriptors describing those inputs for a task with the
    * given library [libSource].
    */
-  static Map<String, TaskInput> buildInputs(Source libSource) {
+  static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
+    Source source = target;
     return <String, TaskInput>{
-      LIBRARY_INPUT: LIBRARY_ELEMENT1.of(libSource),
+      LIBRARY_INPUT: LIBRARY_ELEMENT1.of(source),
       UNIT_INPUT_NAME:
-          RESOLVED_UNIT1.of(new LibrarySpecificUnit(libSource, libSource)),
+          RESOLVED_UNIT1.of(new LibrarySpecificUnit(source, source)),
       IMPORTS_LIBRARY_ELEMENT_INPUT_NAME:
-          IMPORTED_LIBRARIES.of(libSource).toMapOf(LIBRARY_ELEMENT1),
+          IMPORTED_LIBRARIES.of(source).toMapOf(LIBRARY_ELEMENT1),
       EXPORTS_LIBRARY_ELEMENT_INPUT_NAME:
-          EXPORTED_LIBRARIES.of(libSource).toMapOf(LIBRARY_ELEMENT1),
+          EXPORTED_LIBRARIES.of(source).toMapOf(LIBRARY_ELEMENT1),
       IMPORTS_SOURCE_KIND_INPUT_NAME:
-          IMPORTED_LIBRARIES.of(libSource).toMapOf(SOURCE_KIND),
+          IMPORTED_LIBRARIES.of(source).toMapOf(SOURCE_KIND),
       EXPORTS_SOURCE_KIND_INPUT_NAME:
-          EXPORTED_LIBRARIES.of(libSource).toMapOf(SOURCE_KIND)
+          EXPORTED_LIBRARIES.of(source).toMapOf(SOURCE_KIND)
     };
   }
 
@@ -1020,10 +1039,11 @@
    * input descriptors describing those inputs for a task with the
    * given [target].
    */
-  static Map<String, TaskInput> buildInputs(LibrarySpecificUnit target) {
+  static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
+    LibrarySpecificUnit unit = target;
     return <String, TaskInput>{
       TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request),
-      UNIT_INPUT: RESOLVED_UNIT1.of(target)
+      UNIT_INPUT: RESOLVED_UNIT1.of(unit)
     };
   }
 
@@ -1089,11 +1109,12 @@
    * input descriptors describing those inputs for a task with the
    * given library [libSource].
    */
-  static Map<String, TaskInput> buildInputs(Source libSource) {
+  static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
+    Source source = target;
     return <String, TaskInput>{
-      LIBRARY_INPUT: LIBRARY_ELEMENT3.of(libSource),
+      LIBRARY_INPUT: LIBRARY_ELEMENT3.of(source),
       'exportsLibraryPublicNamespace':
-          EXPORT_SOURCE_CLOSURE.of(libSource).toMapOf(LIBRARY_ELEMENT3)
+          EXPORT_SOURCE_CLOSURE.of(source).toMapOf(LIBRARY_ELEMENT3)
     };
   }
 
@@ -1108,93 +1129,8 @@
 }
 
 /**
- * A task that builds [RESOLVED_UNIT3] for a unit.
- */
-class BuildFunctionTypeAliasesTask extends SourceBasedAnalysisTask {
-  /**
-   * The name of the [TYPE_PROVIDER] input.
-   */
-  static const String TYPE_PROVIDER_INPUT = 'TYPE_PROVIDER_INPUT';
-
-  /**
-   * The name of the [LIBRARY_ELEMENT4] input.
-   */
-  static const String LIBRARY_INPUT = 'LIBRARY_INPUT';
-
-  /**
-   * The name of the [RESOLVED_UNIT2] input.
-   */
-  static const String UNIT_INPUT = 'UNIT_INPUT';
-
-  /**
-   * The task descriptor describing this kind of task.
-   */
-  static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
-      'BuildFunctionTypeAliasesTask', createTask, buildInputs,
-      <ResultDescriptor>[BUILD_FUNCTION_TYPE_ALIASES_ERRORS, RESOLVED_UNIT3]);
-
-  BuildFunctionTypeAliasesTask(
-      InternalAnalysisContext context, AnalysisTarget target)
-      : super(context, target);
-
-  @override
-  TaskDescriptor get descriptor => DESCRIPTOR;
-
-  @override
-  void internalPerform() {
-    RecordingErrorListener errorListener = new RecordingErrorListener();
-    //
-    // Prepare inputs.
-    //
-    Source source = getRequiredSource();
-    TypeProvider typeProvider = getRequiredInput(TYPE_PROVIDER_INPUT);
-    CompilationUnit unit = getRequiredInput(UNIT_INPUT);
-    LibraryElement libraryElement = getRequiredInput(LIBRARY_INPUT);
-    //
-    // Resolve FunctionTypeAlias declarations.
-    //
-    TypeResolverVisitor visitor = new TypeResolverVisitor.con2(
-        libraryElement, source, typeProvider, errorListener);
-    for (CompilationUnitMember member in unit.declarations) {
-      if (member is FunctionTypeAlias) {
-        member.accept(visitor);
-      }
-    }
-    //
-    // Record outputs.
-    //
-    outputs[BUILD_FUNCTION_TYPE_ALIASES_ERRORS] = errorListener.errors;
-    outputs[RESOLVED_UNIT3] = 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(LibrarySpecificUnit target) {
-    return <String, TaskInput>{
-      TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request),
-      'importsExportNamespace':
-          IMPORTED_LIBRARIES.of(target.library).toMapOf(LIBRARY_ELEMENT4),
-      LIBRARY_INPUT: LIBRARY_ELEMENT4.of(target.library),
-      UNIT_INPUT: RESOLVED_UNIT2.of(target)
-    };
-  }
-
-  /**
-   * Create a [BuildFunctionTypeAliasesTask] based on the given [target] in
-   * the given [context].
-   */
-  static BuildFunctionTypeAliasesTask createTask(
-      AnalysisContext context, AnalysisTarget target) {
-    return new BuildFunctionTypeAliasesTask(context, target);
-  }
-}
-
-/**
- * This task finishes building [LIBRARY_ELEMENT] by forcing building
- * constructors for classes in the defining and part units of a library.
+ * This task builds [LIBRARY_ELEMENT6] by forcing building constructors for
+ * all the classes of the defining and part units of a library.
  */
 class BuildLibraryConstructorsTask extends SourceBasedAnalysisTask {
   /**
@@ -1207,7 +1143,7 @@
    */
   static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
       'BuildLibraryConstructorsTask', createTask, buildInputs,
-      <ResultDescriptor>[LIBRARY_ELEMENT]);
+      <ResultDescriptor>[LIBRARY_ELEMENT6]);
 
   BuildLibraryConstructorsTask(
       InternalAnalysisContext context, AnalysisTarget target)
@@ -1219,7 +1155,7 @@
   @override
   void internalPerform() {
     LibraryElement library = getRequiredInput(LIBRARY_INPUT);
-    outputs[LIBRARY_ELEMENT] = library;
+    outputs[LIBRARY_ELEMENT6] = library;
   }
 
   /**
@@ -1227,11 +1163,11 @@
    * input descriptors describing those inputs for a task with the
    * given [target].
    */
-  static Map<String, TaskInput> buildInputs(Source libSource) {
+  static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
+    Source source = target;
     return <String, TaskInput>{
-      LIBRARY_INPUT: LIBRARY_ELEMENT5.of(libSource),
-      'resolvedConstructors':
-          CLASS_ELEMENTS.of(libSource).toListOf(CONSTRUCTORS),
+      LIBRARY_INPUT: LIBRARY_ELEMENT5.of(source),
+      'resolvedConstructors': CLASS_ELEMENTS.of(source).toListOf(CONSTRUCTORS),
     };
   }
 
@@ -1385,8 +1321,13 @@
     //
     // Create and populate the library element.
     //
+    AnalysisContext owningContext = context;
+    if (context is InternalAnalysisContext) {
+      InternalAnalysisContext internalContext = context;
+      owningContext = internalContext.getContextFor(librarySource);
+    }
     LibraryElementImpl libraryElement =
-        new LibraryElementImpl.forNode(context, libraryNameNode);
+        new LibraryElementImpl.forNode(owningContext, libraryNameNode);
     libraryElement.definingCompilationUnit = definingCompilationUnitElement;
     libraryElement.entryPoint = entryPoint;
     libraryElement.parts = sourcedCompilationUnits;
@@ -1494,12 +1435,13 @@
    * input descriptors describing those inputs for a task with the given
    * [libSource].
    */
-  static Map<String, TaskInput> buildInputs(Source libSource) {
+  static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
+    Source source = target;
     return <String, TaskInput>{
       DEFINING_UNIT_INPUT:
-          RESOLVED_UNIT1.of(new LibrarySpecificUnit(libSource, libSource)),
-      PARTS_UNIT_INPUT: INCLUDED_PARTS.of(libSource).toList((Source unit) {
-        return RESOLVED_UNIT1.of(new LibrarySpecificUnit(libSource, unit));
+          RESOLVED_UNIT1.of(new LibrarySpecificUnit(source, source)),
+      PARTS_UNIT_INPUT: INCLUDED_PARTS.of(source).toList((Source unit) {
+        return RESOLVED_UNIT1.of(new LibrarySpecificUnit(source, unit));
       })
     };
   }
@@ -1549,8 +1491,9 @@
    * input descriptors describing those inputs for a task with the
    * given library [libSource].
    */
-  static Map<String, TaskInput> buildInputs(Source libSource) {
-    return <String, TaskInput>{LIBRARY_INPUT: LIBRARY_ELEMENT2.of(libSource)};
+  static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
+    Source source = target;
+    return <String, TaskInput>{LIBRARY_INPUT: LIBRARY_ELEMENT2.of(source)};
   }
 
   /**
@@ -1621,11 +1564,12 @@
    * input descriptors describing those inputs for a task with the
    * given library [libSource].
    */
-  static Map<String, TaskInput> buildInputs(Source libSource) {
+  static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
+    Source source = target;
     return <String, TaskInput>{
-      IMPORT_INPUT: new _ImportSourceClosureTaskInput(libSource),
-      EXPORT_INPUT: new _ExportSourceClosureTaskInput(libSource),
-      IMPORT_EXPORT_INPUT: new _ImportExportSourceClosureTaskInput(libSource)
+      IMPORT_INPUT: new _ImportSourceClosureTaskInput(source),
+      EXPORT_INPUT: new _ExportSourceClosureTaskInput(source),
+      IMPORT_EXPORT_INPUT: new _ImportExportSourceClosureTaskInput(source)
     };
   }
 
@@ -1682,8 +1626,9 @@
     outputs[TYPE_PROVIDER] = typeProvider;
   }
 
-  static Map<String, TaskInput> buildInputs(AnalysisContextTarget target) {
-    SourceFactory sourceFactory = target.context.sourceFactory;
+  static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
+    AnalysisContextTarget contextTarget = target;
+    SourceFactory sourceFactory = contextTarget.context.sourceFactory;
     Source coreSource = sourceFactory.forUri(DartSdk.DART_CORE);
     Source asyncSource = sourceFactory.forUri(DartSdk.DART_ASYNC);
     return <String, TaskInput>{
@@ -1696,7 +1641,7 @@
    * Create a [BuildTypeProviderTask] based on the given [context].
    */
   static BuildTypeProviderTask createTask(
-      AnalysisContext context, AnalysisContextTarget target) {
+      AnalysisContext context, AnalysisTarget target) {
     return new BuildTypeProviderTask(context, target);
   }
 }
@@ -1706,7 +1651,7 @@
  */
 class ComputeConstantDependenciesTask extends ConstantEvaluationAnalysisTask {
   /**
-   * The name of the [RESOLVED_UNIT6] input.
+   * The name of the [RESOLVED_UNIT5] input.
    */
   static const String UNIT_INPUT = 'UNIT_INPUT';
 
@@ -1755,30 +1700,28 @@
    * input descriptors describing those inputs for a task with the
    * given [target].
    */
-  static Map<String, TaskInput> buildInputs(ConstantEvaluationTarget target) {
+  static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
     if (target is Element) {
-      CompilationUnitElementImpl unit = (target as Element)
+      CompilationUnitElementImpl unit = target
           .getAncestor((Element element) => element is CompilationUnitElement);
       return <String, TaskInput>{
-        UNIT_INPUT: RESOLVED_UNIT6
+        UNIT_INPUT: RESOLVED_UNIT5
             .of(new LibrarySpecificUnit(unit.librarySource, target.source)),
         TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request)
       };
     } else if (target is ConstantEvaluationTarget_Annotation) {
       return <String, TaskInput>{
-        UNIT_INPUT: RESOLVED_UNIT6
+        UNIT_INPUT: RESOLVED_UNIT5
             .of(new LibrarySpecificUnit(target.librarySource, target.source)),
         TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request)
       };
-    } else {
-      // Should never happen.
-      assert(false);
-      return <String, TaskInput>{};
     }
+    throw new AnalysisException(
+        'Cannot build inputs for a ${target.runtimeType}');
   }
 
   /**
-   * Create a [ResolveReferencesTask] based on the given [target] in
+   * Create a [ResolveUnitReferencesTask] based on the given [target] in
    * the given [context].
    */
   static ComputeConstantDependenciesTask createTask(
@@ -1858,10 +1801,11 @@
    * input descriptors describing those inputs for a task with the given
    * [target].
    */
-  static Map<String, TaskInput> buildInputs(ConstantEvaluationTarget target) {
+  static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
+    ConstantEvaluationTarget evaluationTarget = target;
     return <String, TaskInput>{
       DEPENDENCIES_INPUT:
-          CONSTANT_DEPENDENCIES.of(target).toListOf(CONSTANT_VALUE),
+          CONSTANT_DEPENDENCIES.of(evaluationTarget).toListOf(CONSTANT_VALUE),
       TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request)
     };
   }
@@ -1941,7 +1885,7 @@
    * input descriptors describing those inputs for a task with the
    * given [target].
    */
-  static Map<String, TaskInput> buildInputs(Source target) {
+  static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
     return <String, TaskInput>{};
   }
 
@@ -2023,16 +1967,17 @@
    * input descriptors describing those inputs for a task with the
    * given [target].
    */
-  static Map<String, TaskInput> buildInputs(Source target) {
+  static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
+    Source source = target;
     return <String, TaskInput>{
-      BUILD_DIRECTIVES_ERRORS_INPUT: BUILD_DIRECTIVES_ERRORS.of(target),
-      BUILD_LIBRARY_ERRORS_INPUT: BUILD_LIBRARY_ERRORS.of(target),
-      PARSE_ERRORS_INPUT: PARSE_ERRORS.of(target),
-      SCAN_ERRORS_INPUT: SCAN_ERRORS.of(target),
+      BUILD_DIRECTIVES_ERRORS_INPUT: BUILD_DIRECTIVES_ERRORS.of(source),
+      BUILD_LIBRARY_ERRORS_INPUT: BUILD_LIBRARY_ERRORS.of(source),
+      PARSE_ERRORS_INPUT: PARSE_ERRORS.of(source),
+      SCAN_ERRORS_INPUT: SCAN_ERRORS.of(source),
       LIBRARY_UNIT_ERRORS_INPUT: CONTAINING_LIBRARIES
-          .of(target)
+          .of(source)
           .toMap((Source library) {
-        LibrarySpecificUnit unit = new LibrarySpecificUnit(library, target);
+        LibrarySpecificUnit unit = new LibrarySpecificUnit(library, source);
         return LIBRARY_UNIT_ERRORS.of(unit);
       })
     };
@@ -2053,7 +1998,7 @@
  */
 class EvaluateUnitConstantsTask extends SourceBasedAnalysisTask {
   /**
-   * The name of the [RESOLVED_UNIT6] input.
+   * The name of the [RESOLVED_UNIT5] input.
    */
   static const String UNIT_INPUT = 'UNIT_INPUT';
 
@@ -2088,11 +2033,13 @@
    * input descriptors describing those inputs for a task with the
    * given [target].
    */
-  static Map<String, TaskInput> buildInputs(LibrarySpecificUnit target) {
+  static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
+    LibrarySpecificUnit unit = target;
     return <String, TaskInput>{
-      UNIT_INPUT: RESOLVED_UNIT6.of(target),
+      'libraryElement': LIBRARY_ELEMENT.of(unit.library),
+      UNIT_INPUT: RESOLVED_UNIT5.of(unit),
       CONSTANT_VALUES:
-          COMPILATION_UNIT_CONSTANTS.of(target).toListOf(CONSTANT_VALUE)
+          COMPILATION_UNIT_CONSTANTS.of(unit).toListOf(CONSTANT_VALUE)
     };
   }
 
@@ -2101,7 +2048,7 @@
    * the given [context].
    */
   static EvaluateUnitConstantsTask createTask(
-      AnalysisContext context, LibrarySpecificUnit target) {
+      AnalysisContext context, AnalysisTarget target) {
     return new EvaluateUnitConstantsTask(context, target);
   }
 }
@@ -2214,7 +2161,7 @@
  */
 class GatherUsedImportedElementsTask extends SourceBasedAnalysisTask {
   /**
-   * The name of the [RESOLVED_UNIT6] input.
+   * The name of the [RESOLVED_UNIT5] input.
    */
   static const String UNIT_INPUT = 'UNIT_INPUT';
 
@@ -2254,8 +2201,9 @@
    * input descriptors describing those inputs for a task with the
    * given [target].
    */
-  static Map<String, TaskInput> buildInputs(LibrarySpecificUnit target) {
-    return <String, TaskInput>{UNIT_INPUT: RESOLVED_UNIT6.of(target)};
+  static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
+    LibrarySpecificUnit unit = target;
+    return <String, TaskInput>{UNIT_INPUT: RESOLVED_UNIT5.of(unit)};
   }
 
   /**
@@ -2263,7 +2211,7 @@
    * the given [context].
    */
   static GatherUsedImportedElementsTask createTask(
-      AnalysisContext context, LibrarySpecificUnit target) {
+      AnalysisContext context, AnalysisTarget target) {
     return new GatherUsedImportedElementsTask(context, target);
   }
 }
@@ -2273,7 +2221,7 @@
  */
 class GatherUsedLocalElementsTask extends SourceBasedAnalysisTask {
   /**
-   * The name of the [RESOLVED_UNIT6] input.
+   * The name of the [RESOLVED_UNIT5] input.
    */
   static const String UNIT_INPUT = 'UNIT_INPUT';
 
@@ -2313,8 +2261,9 @@
    * input descriptors describing those inputs for a task with the
    * given [target].
    */
-  static Map<String, TaskInput> buildInputs(LibrarySpecificUnit target) {
-    return <String, TaskInput>{UNIT_INPUT: RESOLVED_UNIT6.of(target)};
+  static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
+    LibrarySpecificUnit unit = target;
+    return <String, TaskInput>{UNIT_INPUT: RESOLVED_UNIT5.of(unit)};
   }
 
   /**
@@ -2322,7 +2271,7 @@
    * the given [context].
    */
   static GatherUsedLocalElementsTask createTask(
-      AnalysisContext context, LibrarySpecificUnit target) {
+      AnalysisContext context, AnalysisTarget target) {
     return new GatherUsedLocalElementsTask(context, target);
   }
 }
@@ -2332,7 +2281,7 @@
  */
 class GenerateHintsTask extends SourceBasedAnalysisTask {
   /**
-   * The name of the [RESOLVED_UNIT6] input.
+   * The name of the [RESOLVED_UNIT5] input.
    */
   static const String RESOLVED_UNIT_INPUT = 'RESOLVED_UNIT';
 
@@ -2365,6 +2314,14 @@
 
   @override
   void internalPerform() {
+    AnalysisOptions analysisOptions = context.analysisOptions;
+    if (!analysisOptions.hint) {
+      outputs[HINTS] = AnalysisError.NO_ERRORS;
+      return;
+    }
+    //
+    // Prepare collectors.
+    //
     RecordingErrorListener errorListener = new RecordingErrorListener();
     Source source = getRequiredSource();
     ErrorReporter errorReporter = new ErrorReporter(errorListener, source);
@@ -2399,7 +2356,7 @@
       unitElement.accept(visitor);
     }
     // Dart2js analysis.
-    if (context.analysisOptions.dart2jsHint) {
+    if (analysisOptions.dart2jsHint) {
       unit.accept(new Dart2JSVerifier(errorReporter));
     }
     // Dart best practices.
@@ -2421,10 +2378,11 @@
    * input descriptors describing those inputs for a task with the
    * given [target].
    */
-  static Map<String, TaskInput> buildInputs(LibrarySpecificUnit target) {
-    Source libSource = target.library;
+  static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
+    LibrarySpecificUnit unit = target;
+    Source libSource = unit.library;
     return <String, TaskInput>{
-      RESOLVED_UNIT_INPUT: RESOLVED_UNIT.of(target),
+      RESOLVED_UNIT_INPUT: RESOLVED_UNIT.of(unit),
       USED_LOCAL_ELEMENTS_INPUT: UNITS.of(libSource).toList((unit) {
         LibrarySpecificUnit target = new LibrarySpecificUnit(libSource, unit);
         return USED_LOCAL_ELEMENTS.of(target);
@@ -2475,9 +2433,10 @@
    * input descriptors describing those inputs for a task with the
    * given [library].
    */
-  static Map<String, TaskInput> buildInputs(Source library) {
+  static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
+    Source source = target;
     return <String, TaskInput>{
-      'allErrors': UNITS.of(library).toListOf(DART_ERRORS)
+      'allErrors': UNITS.of(source).toListOf(DART_ERRORS)
     };
   }
 
@@ -2497,12 +2456,6 @@
  */
 class LibraryUnitErrorsTask extends SourceBasedAnalysisTask {
   /**
-   * The name of the [BUILD_FUNCTION_TYPE_ALIASES_ERRORS] input.
-   */
-  static const String BUILD_FUNCTION_TYPE_ALIASES_ERRORS_INPUT =
-      'BUILD_FUNCTION_TYPE_ALIASES_ERRORS';
-
-  /**
    * The name of the [HINTS] input.
    */
   static const String HINTS_INPUT = 'HINTS';
@@ -2520,11 +2473,22 @@
       'RESOLVE_TYPE_NAMES_ERRORS';
 
   /**
+   * The name of the [VARIABLE_REFERENCE_ERRORS] input.
+   */
+  static const String VARIABLE_REFERENCE_ERRORS_INPUT =
+      'VARIABLE_REFERENCE_ERRORS';
+
+  /**
    * The name of the [VERIFY_ERRORS] input.
    */
   static const String VERIFY_ERRORS_INPUT = 'VERIFY_ERRORS';
 
   /**
+   * The name of the [CONSTRUCTORS_ERRORS] input.
+   */
+  static const String CONSTRUCTORS_ERRORS_INPUT = 'CONSTRUCTORS_ERRORS';
+
+  /**
    * The task descriptor describing this kind of task.
    */
   static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
@@ -2543,10 +2507,11 @@
     // Prepare inputs.
     //
     List<List<AnalysisError>> errorLists = <List<AnalysisError>>[];
-    errorLists.add(getRequiredInput(BUILD_FUNCTION_TYPE_ALIASES_ERRORS_INPUT));
+    errorLists.addAll(getRequiredInput(CONSTRUCTORS_ERRORS_INPUT));
     errorLists.add(getRequiredInput(HINTS_INPUT));
     errorLists.add(getRequiredInput(RESOLVE_REFERENCES_ERRORS_INPUT));
     errorLists.add(getRequiredInput(RESOLVE_TYPE_NAMES_ERRORS_INPUT));
+    errorLists.add(getRequiredInput(VARIABLE_REFERENCE_ERRORS_INPUT));
     errorLists.add(getRequiredInput(VERIFY_ERRORS_INPUT));
     //
     // Record outputs.
@@ -2559,13 +2524,17 @@
    * input descriptors describing those inputs for a task with the
    * given [unit].
    */
-  static Map<String, TaskInput> buildInputs(LibrarySpecificUnit unit) {
+  static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
+    LibrarySpecificUnit unit = target;
     return <String, TaskInput>{
-      BUILD_FUNCTION_TYPE_ALIASES_ERRORS_INPUT:
-          BUILD_FUNCTION_TYPE_ALIASES_ERRORS.of(unit),
+      CONSTRUCTORS_ERRORS_INPUT: COMPILATION_UNIT_ELEMENT
+          .of(unit)
+          .mappedToList((CompilationUnitElement element) => element.types)
+          .toListOf(CONSTRUCTORS_ERRORS),
       HINTS_INPUT: HINTS.of(unit),
       RESOLVE_REFERENCES_ERRORS_INPUT: RESOLVE_REFERENCES_ERRORS.of(unit),
       RESOLVE_TYPE_NAMES_ERRORS_INPUT: RESOLVE_TYPE_NAMES_ERRORS.of(unit),
+      VARIABLE_REFERENCE_ERRORS_INPUT: VARIABLE_REFERENCE_ERRORS.of(unit),
       VERIFY_ERRORS_INPUT: VERIFY_ERRORS.of(unit)
     };
   }
@@ -2659,9 +2628,7 @@
             } else if (directive is ImportDirective) {
               explicitlyImportedSourceSet.add(referencedSource);
             } else if (directive is PartDirective) {
-              if (referencedSource != source) {
-                includedSourceSet.add(referencedSource);
-              }
+              includedSourceSet.add(referencedSource);
             } else {
               throw new AnalysisException(
                   '$runtimeType failed to handle a ${directive.runtimeType}');
@@ -2694,7 +2661,8 @@
     List<Source> exportedSources = exportedSourceSet.toList();
     List<Source> importedSources = importedSourceSet.toList();
     List<Source> includedSources = includedSourceSet.toList();
-    List<AnalysisError> parseErrors = errorListener.errors;
+    List<AnalysisError> parseErrors =
+        removeDuplicateErrors(errorListener.errors);
     List<Source> unitSources = <Source>[source]..addAll(includedSourceSet);
     outputs[EXPLICITLY_IMPORTED_LIBRARIES] = explicitlyImportedSources;
     outputs[EXPORTED_LIBRARIES] = exportedSources;
@@ -2711,11 +2679,11 @@
    * input descriptors describing those inputs for a task with the given
    * [source].
    */
-  static Map<String, TaskInput> buildInputs(Source source) {
+  static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
     return <String, TaskInput>{
-      LINE_INFO_INPUT_NAME: LINE_INFO.of(source),
-      MODIFICATION_TIME_INPUT_NAME: MODIFICATION_TIME.of(source),
-      TOKEN_STREAM_INPUT_NAME: TOKEN_STREAM.of(source)
+      LINE_INFO_INPUT_NAME: LINE_INFO.of(target),
+      MODIFICATION_TIME_INPUT_NAME: MODIFICATION_TIME.of(target),
+      TOKEN_STREAM_INPUT_NAME: TOKEN_STREAM.of(target)
     };
   }
 
@@ -2808,6 +2776,63 @@
 }
 
 /**
+ * A task that finishes resolution by requesting [RESOLVED_UNIT_NO_CONSTANTS] for every
+ * unit in the libraries closure and produces [LIBRARY_ELEMENT].
+ */
+class ResolveLibraryReferencesTask extends SourceBasedAnalysisTask {
+  /**
+   * The name of the [LIBRARY_ELEMENT6] input.
+   */
+  static const String LIBRARY_INPUT = 'LIBRARY_INPUT';
+
+  /**
+   * The task descriptor describing this kind of task.
+   */
+  static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
+      'ResolveLibraryReferencesTask', createTask, buildInputs,
+      <ResultDescriptor>[LIBRARY_ELEMENT]);
+
+  ResolveLibraryReferencesTask(
+      InternalAnalysisContext context, AnalysisTarget target)
+      : super(context, target);
+
+  @override
+  TaskDescriptor get descriptor => DESCRIPTOR;
+
+  @override
+  void internalPerform() {
+    LibraryElement library = getRequiredInput(LIBRARY_INPUT);
+    outputs[LIBRARY_ELEMENT] = library;
+  }
+
+  /**
+   * 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) {
+    Source source = target;
+    return <String, TaskInput>{
+      LIBRARY_INPUT: LIBRARY_ELEMENT6.of(source),
+      'resolvedUnits': IMPORT_EXPORT_SOURCE_CLOSURE
+          .of(source)
+          .toMapOf(UNITS)
+          .toFlattenList((Source library, Source unit) =>
+              RESOLVED_UNIT5.of(new LibrarySpecificUnit(library, unit))),
+    };
+  }
+
+  /**
+   * Create a [ResolveLibraryReferencesTask] based on the given [target] in
+   * the given [context].
+   */
+  static ResolveLibraryReferencesTask createTask(
+      AnalysisContext context, AnalysisTarget target) {
+    return new ResolveLibraryReferencesTask(context, target);
+  }
+}
+
+/**
  * An artifitial task that does nothing except to force type names resolution
  * for the defining and part units of a library.
  */
@@ -2842,14 +2867,15 @@
    * input descriptors describing those inputs for a task with the
    * given [target].
    */
-  static Map<String, TaskInput> buildInputs(Source libSource) {
+  static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
+    Source source = target;
     return <String, TaskInput>{
-      LIBRARY_INPUT: LIBRARY_ELEMENT4.of(libSource),
+      LIBRARY_INPUT: LIBRARY_ELEMENT4.of(source),
       'resolvedUnits': IMPORT_EXPORT_SOURCE_CLOSURE
-          .of(libSource)
+          .of(source)
           .toMapOf(UNITS)
           .toFlattenList((Source library, Source unit) =>
-              RESOLVED_UNIT4.of(new LibrarySpecificUnit(library, unit))),
+              RESOLVED_UNIT3.of(new LibrarySpecificUnit(library, unit))),
     };
   }
 
@@ -2864,16 +2890,16 @@
 }
 
 /**
- * A task that builds [RESOLVED_UNIT6] for a unit.
+ * A task that builds [RESOLVED_UNIT5] for a unit.
  */
-class ResolveReferencesTask extends SourceBasedAnalysisTask {
+class ResolveUnitReferencesTask extends SourceBasedAnalysisTask {
   /**
-   * The name of the [LIBRARY_ELEMENT] input.
+   * The name of the [LIBRARY_ELEMENT6] input.
    */
   static const String LIBRARY_INPUT = 'LIBRARY_INPUT';
 
   /**
-   * The name of the [RESOLVED_UNIT5] input.
+   * The name of the [RESOLVED_UNIT4] input.
    */
   static const String UNIT_INPUT = 'UNIT_INPUT';
 
@@ -2886,12 +2912,13 @@
    * The task descriptor describing this kind of task.
    */
   static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
-      'ResolveReferencesTask', createTask, buildInputs, <ResultDescriptor>[
+      'ResolveUnitReferencesTask', createTask, buildInputs, <ResultDescriptor>[
     RESOLVE_REFERENCES_ERRORS,
-    RESOLVED_UNIT6
+    RESOLVED_UNIT5
   ]);
 
-  ResolveReferencesTask(InternalAnalysisContext context, AnalysisTarget target)
+  ResolveUnitReferencesTask(
+      InternalAnalysisContext context, AnalysisTarget target)
       : super(context, target);
 
   @override
@@ -2918,8 +2945,9 @@
     //
     // Record outputs.
     //
-    outputs[RESOLVE_REFERENCES_ERRORS] = errorListener.errors;
-    outputs[RESOLVED_UNIT6] = unit;
+    outputs[RESOLVE_REFERENCES_ERRORS] =
+        removeDuplicateErrors(errorListener.errors);
+    outputs[RESOLVED_UNIT5] = unit;
   }
 
   /**
@@ -2927,26 +2955,27 @@
    * input descriptors describing those inputs for a task with the
    * given [target].
    */
-  static Map<String, TaskInput> buildInputs(LibrarySpecificUnit target) {
+  static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
+    LibrarySpecificUnit unit = target;
     return <String, TaskInput>{
-      LIBRARY_INPUT: LIBRARY_ELEMENT.of(target.library),
-      UNIT_INPUT: RESOLVED_UNIT5.of(target),
+      LIBRARY_INPUT: LIBRARY_ELEMENT6.of(unit.library),
+      UNIT_INPUT: RESOLVED_UNIT4.of(unit),
       TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request)
     };
   }
 
   /**
-   * Create a [ResolveReferencesTask] based on the given [target] in
+   * Create a [ResolveUnitReferencesTask] based on the given [target] in
    * the given [context].
    */
-  static ResolveReferencesTask createTask(
+  static ResolveUnitReferencesTask createTask(
       AnalysisContext context, AnalysisTarget target) {
-    return new ResolveReferencesTask(context, target);
+    return new ResolveUnitReferencesTask(context, target);
   }
 }
 
 /**
- * A task that builds [RESOLVED_UNIT4] for a unit.
+ * A task that builds [RESOLVED_UNIT3] for a unit.
  */
 class ResolveUnitTypeNamesTask extends SourceBasedAnalysisTask {
   /**
@@ -2955,7 +2984,7 @@
   static const String LIBRARY_INPUT = 'LIBRARY_INPUT';
 
   /**
-   * The name of the [RESOLVED_UNIT3] input.
+   * The name of the [RESOLVED_UNIT2] input.
    */
   static const String UNIT_INPUT = 'UNIT_INPUT';
 
@@ -2970,7 +2999,7 @@
   static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
       'ResolveUnitTypeNamesTask', createTask, buildInputs, <ResultDescriptor>[
     RESOLVE_TYPE_NAMES_ERRORS,
-    RESOLVED_UNIT4
+    RESOLVED_UNIT3
   ]);
 
   ResolveUnitTypeNamesTask(
@@ -2999,8 +3028,9 @@
     //
     // Record outputs.
     //
-    outputs[RESOLVE_TYPE_NAMES_ERRORS] = errorListener.errors;
-    outputs[RESOLVED_UNIT4] = unit;
+    outputs[RESOLVE_TYPE_NAMES_ERRORS] =
+        removeDuplicateErrors(errorListener.errors);
+    outputs[RESOLVED_UNIT3] = unit;
   }
 
   /**
@@ -3008,10 +3038,13 @@
    * input descriptors describing those inputs for a task with the
    * given [target].
    */
-  static Map<String, TaskInput> buildInputs(LibrarySpecificUnit target) {
+  static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
+    LibrarySpecificUnit unit = target;
     return <String, TaskInput>{
-      LIBRARY_INPUT: LIBRARY_ELEMENT4.of(target.library),
-      UNIT_INPUT: RESOLVED_UNIT3.of(target),
+      'importsExportNamespace':
+                IMPORTED_LIBRARIES.of(unit.library).toMapOf(LIBRARY_ELEMENT4),
+      LIBRARY_INPUT: LIBRARY_ELEMENT4.of(unit.library),
+      UNIT_INPUT: RESOLVED_UNIT2.of(unit),
       TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request)
     };
   }
@@ -3027,16 +3060,16 @@
 }
 
 /**
- * A task that builds [RESOLVED_UNIT5] for a unit.
+ * A task that builds [RESOLVED_UNIT4] for a unit.
  */
 class ResolveVariableReferencesTask extends SourceBasedAnalysisTask {
   /**
-   * The name of the [LIBRARY_ELEMENT] input.
+   * The name of the [LIBRARY_ELEMENT6] input.
    */
   static const String LIBRARY_INPUT = 'LIBRARY_INPUT';
 
   /**
-   * The name of the [RESOLVED_UNIT4] input.
+   * The name of the [RESOLVED_UNIT3] input.
    */
   static const String UNIT_INPUT = 'UNIT_INPUT';
 
@@ -3050,7 +3083,7 @@
    */
   static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
       'ResolveVariableReferencesTask', createTask, buildInputs,
-      <ResultDescriptor>[RESOLVED_UNIT5]);
+      <ResultDescriptor>[RESOLVED_UNIT4, VARIABLE_REFERENCE_ERRORS]);
 
   ResolveVariableReferencesTask(
       InternalAnalysisContext context, AnalysisTarget target)
@@ -3079,7 +3112,9 @@
     //
     // Record outputs.
     //
-    outputs[RESOLVED_UNIT5] = unit;
+    outputs[RESOLVED_UNIT4] = unit;
+    outputs[VARIABLE_REFERENCE_ERRORS] =
+        removeDuplicateErrors(errorListener.errors);
   }
 
   /**
@@ -3087,10 +3122,14 @@
    * input descriptors describing those inputs for a task with the
    * given [target].
    */
-  static Map<String, TaskInput> buildInputs(LibrarySpecificUnit target) {
+  static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
+    LibrarySpecificUnit unit = target;
     return <String, TaskInput>{
-      LIBRARY_INPUT: LIBRARY_ELEMENT.of(target.library),
-      UNIT_INPUT: RESOLVED_UNIT4.of(target),
+      'fullyBuiltLibraryElements': IMPORT_EXPORT_SOURCE_CLOSURE
+          .of(unit.library)
+          .toListOf(LIBRARY_ELEMENT6),
+      LIBRARY_INPUT: LIBRARY_ELEMENT6.of(unit.library),
+      UNIT_INPUT: RESOLVED_UNIT3.of(unit),
       TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request)
     };
   }
@@ -3137,21 +3176,46 @@
   @override
   void internalPerform() {
     Source source = getRequiredSource();
-    String content = getRequiredInput(CONTENT_INPUT_NAME);
+    if (target is DartScript) {
+      DartScript script = target;
+      List<ScriptFragment> fragments = script.fragments;
+      if (fragments.length < 1) {
+        throw new AnalysisException('Cannot scan scripts with no fragments');
+      } else if (fragments.length > 1) {
+        throw new AnalysisException(
+            'Cannot scan scripts with multiple fragments');
+      }
+      ScriptFragment fragment = fragments[0];
 
-    RecordingErrorListener errorListener = new RecordingErrorListener();
-    Scanner scanner =
-        new Scanner(source, new CharSequenceReader(content), errorListener);
-    scanner.preserveComments = context.analysisOptions.preserveComments;
-    scanner.enableNullAwareOperators =
-        context.analysisOptions.enableNullAwareOperators;
+      RecordingErrorListener errorListener = new RecordingErrorListener();
+      Scanner scanner = new Scanner(source,
+          new SubSequenceReader(fragment.content, fragment.offset),
+          errorListener);
+      scanner.setSourceStart(fragment.line, fragment.column);
+      scanner.preserveComments = context.analysisOptions.preserveComments;
+      scanner.enableNullAwareOperators =
+          context.analysisOptions.enableNullAwareOperators;
 
-    Token tokenStream = scanner.tokenize();
-    LineInfo lineInfo = new LineInfo(scanner.lineStarts);
-    List<AnalysisError> errors = errorListener.errors;
-    outputs[TOKEN_STREAM] = tokenStream;
-    outputs[LINE_INFO] = lineInfo;
-    outputs[SCAN_ERRORS] = errors;
+      outputs[TOKEN_STREAM] = scanner.tokenize();
+      outputs[LINE_INFO] = new LineInfo(scanner.lineStarts);
+      outputs[SCAN_ERRORS] = removeDuplicateErrors(errorListener.errors);
+    } else if (target is Source) {
+      String content = getRequiredInput(CONTENT_INPUT_NAME);
+
+      RecordingErrorListener errorListener = new RecordingErrorListener();
+      Scanner scanner =
+          new Scanner(source, new CharSequenceReader(content), errorListener);
+      scanner.preserveComments = context.analysisOptions.preserveComments;
+      scanner.enableNullAwareOperators =
+          context.analysisOptions.enableNullAwareOperators;
+
+      outputs[TOKEN_STREAM] = scanner.tokenize();
+      outputs[LINE_INFO] = new LineInfo(scanner.lineStarts);
+      outputs[SCAN_ERRORS] = removeDuplicateErrors(errorListener.errors);
+    } else {
+      throw new AnalysisException(
+          'Cannot scan Dart code from a ${target.runtimeType}');
+    }
   }
 
   /**
@@ -3159,8 +3223,17 @@
    * input descriptors describing those inputs for a task with the given
    * [source].
    */
-  static Map<String, TaskInput> buildInputs(Source source) {
-    return <String, TaskInput>{CONTENT_INPUT_NAME: CONTENT.of(source)};
+  static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
+    if (target is Source) {
+      return <String, TaskInput>{CONTENT_INPUT_NAME: CONTENT.of(target)};
+    } else if (target is DartScript) {
+      // This task does not use the following input; it is included only to add
+      // a dependency between this value and the containing source so that when
+      // the containing source is modified these results will be invalidated.
+      return <String, TaskInput>{'-': DART_SCRIPTS.of(target.source)};
+    }
+    throw new AnalysisException(
+        'Cannot build inputs for a ${target.runtimeType}');
   }
 
   /**
@@ -3208,10 +3281,10 @@
     RecordingErrorListener errorListener = new RecordingErrorListener();
     Source source = getRequiredSource();
     errorReporter = new ErrorReporter(errorListener, source);
-    TypeProvider typeProvider = getRequiredInput(TYPE_PROVIDER_INPUT);
     //
     // Prepare inputs.
     //
+    TypeProvider typeProvider = getRequiredInput(TYPE_PROVIDER_INPUT);
     CompilationUnit unit = getRequiredInput(UNIT_INPUT);
     CompilationUnitElement unitElement = unit.element;
     LibraryElement libraryElement = unitElement.library;
@@ -3220,6 +3293,12 @@
     //
     validateDirectives(unit);
     //
+    // Use the ConstantVerifier to compute errors.
+    //
+    ConstantVerifier constantVerifier = new ConstantVerifier(
+        errorReporter, libraryElement, typeProvider, context.declaredVariables);
+    unit.accept(constantVerifier);
+    //
     // Use the ErrorVerifier to compute errors.
     //
     ErrorVerifier errorVerifier = new ErrorVerifier(errorReporter,
@@ -3228,7 +3307,7 @@
     //
     // Record outputs.
     //
-    outputs[VERIFY_ERRORS] = errorListener.errors;
+    outputs[VERIFY_ERRORS] = removeDuplicateErrors(errorListener.errors);
   }
 
   /**
@@ -3269,9 +3348,15 @@
    * input descriptors describing those inputs for a task with the
    * given [target].
    */
-  static Map<String, TaskInput> buildInputs(LibrarySpecificUnit target) {
+  static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
+    LibrarySpecificUnit unit = target;
     return <String, TaskInput>{
-      UNIT_INPUT: RESOLVED_UNIT.of(target),
+      'resolvedUnits': IMPORT_EXPORT_SOURCE_CLOSURE
+          .of(unit.library)
+          .toMapOf(UNITS)
+          .toFlattenList((Source library, Source unit) =>
+              RESOLVED_UNIT.of(new LibrarySpecificUnit(library, unit))),
+      UNIT_INPUT: RESOLVED_UNIT.of(unit),
       TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request)
     };
   }
@@ -3290,7 +3375,7 @@
  * A [TaskInput] whose value is a list of library sources exported directly
  * or indirectly by the target [Source].
  */
-class _ExportSourceClosureTaskInput implements TaskInput<List<Source>> {
+class _ExportSourceClosureTaskInput extends TaskInputImpl<List<Source>> {
   final Source target;
 
   _ExportSourceClosureTaskInput(this.target);
@@ -3304,7 +3389,7 @@
  * A [TaskInput] whose value is a list of library sources imported or exported,
  * directly or indirectly by the target [Source].
  */
-class _ImportExportSourceClosureTaskInput implements TaskInput<List<Source>> {
+class _ImportExportSourceClosureTaskInput extends TaskInputImpl<List<Source>> {
   final Source target;
 
   _ImportExportSourceClosureTaskInput(this.target);
@@ -3319,7 +3404,7 @@
  * A [TaskInput] whose value is a list of library sources imported directly
  * or indirectly by the target [Source].
  */
-class _ImportSourceClosureTaskInput implements TaskInput<List<Source>> {
+class _ImportSourceClosureTaskInput extends TaskInputImpl<List<Source>> {
   final Source target;
 
   _ImportSourceClosureTaskInput(this.target);
@@ -3340,7 +3425,7 @@
 class _SourceClosureTaskInputBuilder implements TaskInputBuilder<List<Source>> {
   final _SourceClosureKind kind;
   final Set<LibraryElement> _libraries = new HashSet<LibraryElement>();
-  final Set<Source> _newSources = new HashSet<Source>();
+  final List<Source> _newSources = <Source>[];
 
   Source currentTarget;
 
@@ -3388,8 +3473,7 @@
     if (_newSources.isEmpty) {
       return false;
     }
-    currentTarget = _newSources.first;
-    _newSources.remove(currentTarget);
+    currentTarget = _newSources.removeLast();
     return true;
   }
 }
diff --git a/pkg/analyzer/lib/src/task/dart_work_manager.dart b/pkg/analyzer/lib/src/task/dart_work_manager.dart
index 6700e1f..c02d594 100644
--- a/pkg/analyzer/lib/src/task/dart_work_manager.dart
+++ b/pkg/analyzer/lib/src/task/dart_work_manager.dart
@@ -42,10 +42,10 @@
    * The list of errors that are reported for raw Dart [LibrarySpecificUnit]s.
    */
   static final List<ResultDescriptor> _UNIT_ERRORS = <ResultDescriptor>[
-    BUILD_FUNCTION_TYPE_ALIASES_ERRORS,
     HINTS,
     RESOLVE_REFERENCES_ERRORS,
     RESOLVE_TYPE_NAMES_ERRORS,
+    VARIABLE_REFERENCE_ERRORS,
     VERIFY_ERRORS
   ];
 
@@ -82,7 +82,16 @@
   /**
    * Initialize a newly created manager.
    */
-  DartWorkManager(this.context);
+  DartWorkManager(this.context) {
+    analysisCache.onResultInvalidated.listen((InvalidatedResult event) {
+      if (event.descriptor == LIBRARY_ERRORS_READY) {
+        CacheEntry entry = event.entry;
+        if (entry.getValue(SOURCE_KIND) == SourceKind.LIBRARY) {
+          librarySourceQueue.add(entry.target);
+        }
+      }
+    });
+  }
 
   /**
    * Returns the correctly typed result of `context.analysisCache`.
@@ -127,21 +136,6 @@
       partLibrariesMap.remove(removedSource);
       _onLibrarySourceChangedOrRemoved(removedSource);
     }
-    // Some of the libraries might have been invalidated, reschedule them.
-    {
-      MapIterator<AnalysisTarget, CacheEntry> iterator =
-          analysisCache.iterator();
-      while (iterator.moveNext()) {
-        AnalysisTarget target = iterator.key;
-        if (_isDartSource(target)) {
-          CacheEntry entry = iterator.value;
-          if (entry.getValue(SOURCE_KIND) == SourceKind.LIBRARY &&
-              entry.getValue(LIBRARY_ERRORS_READY) != true) {
-            librarySourceQueue.add(target);
-          }
-        }
-      }
-    }
   }
 
   @override
@@ -158,8 +152,10 @@
     for (AnalysisTarget target in targets) {
       if (_isDartSource(target)) {
         SourceKind sourceKind = analysisCache.getValue(target, SOURCE_KIND);
-        if (sourceKind == SourceKind.LIBRARY) {
-          addPriorityResult(target, LIBRARY_ERRORS_READY);
+        if (sourceKind == SourceKind.UNKNOWN) {
+          addPriorityResult(target, SOURCE_KIND);
+        } else if (sourceKind == SourceKind.LIBRARY) {
+          _schedulePriorityLibrarySourceAnalysis(target);
         } else if (sourceKind == SourceKind.PART) {
           List<Source> libraries = context.getLibrariesContaining(target);
           for (Source library in libraries) {
@@ -177,6 +173,11 @@
    * errors in the source. The errors contained in the list can be incomplete.
    */
   AnalysisErrorInfo getErrors(Source source) {
+    if (analysisCache.getState(source, DART_ERRORS) == CacheState.VALID) {
+      List<AnalysisError> errors = analysisCache.getValue(source, DART_ERRORS);
+      LineInfo lineInfo = analysisCache.getValue(source, LINE_INFO);
+      return new AnalysisErrorInfoImpl(errors, lineInfo);
+    }
     List<AnalysisError> errors = <AnalysisError>[];
     for (ResultDescriptor descriptor in _SOURCE_ERRORS) {
       errors.addAll(analysisCache.getValue(source, descriptor));
@@ -269,12 +270,19 @@
       AnalysisTarget target, Map<ResultDescriptor, dynamic> outputs) {
     // Organize sources.
     if (_isDartSource(target)) {
+      Source source = target;
       SourceKind kind = outputs[SOURCE_KIND];
       if (kind != null) {
-        unknownSourceQueue.remove(target);
-        if (kind == SourceKind.LIBRARY &&
-            context.shouldErrorsBeAnalyzed(target, null)) {
-          librarySourceQueue.add(target);
+        unknownSourceQueue.remove(source);
+        if (kind == SourceKind.LIBRARY) {
+          if (context.prioritySources.contains(source)) {
+            _schedulePriorityLibrarySourceAnalysis(source);
+          } else {
+            bool needErrors = _shouldErrorsBeComputed(source);
+            if (needErrors) {
+              librarySourceQueue.add(target);
+            }
+          }
         }
       }
     }
@@ -414,6 +422,24 @@
     _invalidateContainingLibraries(library);
   }
 
+  /**
+   * Schedule computing [RESOLVED_UNIT] for the given [librarySource].
+   * If errors should be computed, then schedule [LIBRARY_ERRORS_READY] instead,
+   * it also computes [RESOLVED_UNIT] in process.
+   */
+  void _schedulePriorityLibrarySourceAnalysis(Source librarySource) {
+    bool needErrors = _shouldErrorsBeComputed(librarySource);
+    if (needErrors) {
+      addPriorityResult(librarySource, LIBRARY_ERRORS_READY);
+    } else {
+      var target = new LibrarySpecificUnit(librarySource, librarySource);
+      addPriorityResult(target, RESOLVED_UNIT);
+    }
+  }
+
+  bool _shouldErrorsBeComputed(Source source) =>
+      context.shouldErrorsBeAnalyzed(source, null);
+
   static bool _isDartSource(AnalysisTarget target) {
     return target is Source && AnalysisEngine.isDartFileName(target.fullName);
   }
diff --git a/pkg/analyzer/lib/src/task/driver.dart b/pkg/analyzer/lib/src/task/driver.dart
index 36781f5..ff5767d 100644
--- a/pkg/analyzer/lib/src/task/driver.dart
+++ b/pkg/analyzer/lib/src/task/driver.dart
@@ -42,6 +42,12 @@
   final InternalAnalysisContext context;
 
   /**
+   * The map of [ComputedResult] controllers.
+   */
+  final Map<ResultDescriptor, StreamController<ComputedResult>> resultComputedControllers =
+      <ResultDescriptor, StreamController<ComputedResult>>{};
+
+  /**
    * The work order that was previously computed but that has not yet been
    * completed.
    */
@@ -151,13 +157,13 @@
         state == CacheState.IN_PROCESS) {
       return null;
     }
+    TaskDescriptor taskDescriptor = taskManager.findTask(target, result);
     try {
-      TaskDescriptor taskDescriptor = taskManager.findTask(target, result);
       WorkItem workItem = new WorkItem(context, target, taskDescriptor, result);
       return new WorkOrder(taskManager, workItem);
     } catch (exception, stackTrace) {
       throw new AnalysisException(
-          'Could not create work order (target = $target; result = $result)',
+          'Could not create work order (target = $target; taskDescriptor = $taskDescriptor; result = $result)',
           new CaughtException(exception, stackTrace));
     }
   }
@@ -187,6 +193,15 @@
   }
 
   /**
+   * Return the stream that is notified when a new value for the given
+   * [descriptor] is computed.
+   */
+  Stream<ComputedResult> onResultComputed(ResultDescriptor descriptor) {
+    return resultComputedControllers.putIfAbsent(descriptor, () =>
+        new StreamController<ComputedResult>.broadcast(sync: true)).stream;
+  }
+
+  /**
    * Perform the next analysis task, and return `true` if there is more work to
    * be done in order to compute all of the required analysis information.
    */
@@ -243,7 +258,8 @@
     AnalysisTask task = item.buildTask();
     _onTaskStartedController.add(task);
     task.perform();
-    CacheEntry entry = context.getCacheEntry(task.target);
+    AnalysisTarget target = task.target;
+    CacheEntry entry = context.getCacheEntry(target);
     if (task.caughtException == null) {
       List<TargetedResult> dependedOn = item.inputTargetedResults.toList();
       Map<ResultDescriptor, dynamic> outputs = task.outputs;
@@ -252,8 +268,17 @@
         // and throw an exception if not (unless we want to allow null values).
         entry.setValue(result, outputs[result], dependedOn);
       }
+      outputs.forEach((ResultDescriptor descriptor, value) {
+        StreamController<ComputedResult> controller =
+            resultComputedControllers[descriptor];
+        if (controller != null) {
+          ComputedResult event =
+              new ComputedResult(context, descriptor, target, value);
+          controller.add(event);
+        }
+      });
       for (WorkManager manager in workManagers) {
-        manager.resultsComputed(task.target, outputs);
+        manager.resultsComputed(target, outputs);
       }
     } else {
       entry.setErrorState(task.caughtException, item.descriptor.results);
diff --git a/pkg/analyzer/lib/src/task/html.dart b/pkg/analyzer/lib/src/task/html.dart
new file mode 100644
index 0000000..b75bad4
--- /dev/null
+++ b/pkg/analyzer/lib/src/task/html.dart
@@ -0,0 +1,352 @@
+// 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.html;
+
+import 'dart:collection';
+
+import 'package:analyzer/src/generated/engine.dart' hide AnalysisTask;
+import 'package:analyzer/src/generated/error.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/task/dart.dart';
+import 'package:analyzer/src/task/general.dart';
+import 'package:analyzer/task/dart.dart';
+import 'package:analyzer/task/general.dart';
+import 'package:analyzer/task/html.dart';
+import 'package:analyzer/task/model.dart';
+import 'package:html/dom.dart';
+import 'package:html/parser.dart';
+import 'package:source_span/source_span.dart';
+
+/**
+ * The Dart scripts that are embedded in an HTML file.
+ */
+final ListResultDescriptor<DartScript> DART_SCRIPTS =
+    new ListResultDescriptor<DartScript>('DART_SCRIPTS', DartScript.EMPTY_LIST);
+
+/**
+ * The errors found while parsing an HTML file.
+ */
+final ListResultDescriptor<AnalysisError> HTML_DOCUMENT_ERRORS =
+    new ListResultDescriptor<AnalysisError>(
+        'HTML_DOCUMENT_ERRORS', AnalysisError.NO_ERRORS);
+
+/**
+ * A Dart script that is embedded in an HTML file.
+ */
+class DartScript implements Source {
+  /**
+   * An empty list of scripts.
+   */
+  static final List<DartScript> EMPTY_LIST = <DartScript>[];
+
+  /**
+   * The source containing this script.
+   */
+  final Source source;
+
+  /**
+   * The fragments that comprise this content of the script.
+   */
+  final List<ScriptFragment> fragments;
+
+  /**
+   * Initialize a newly created script in the given [source] that is composed of
+   * given [fragments].
+   */
+  DartScript(this.source, this.fragments);
+
+  @override
+  TimestampedData<String> get contents =>
+      new TimestampedData(modificationStamp, fragments[0].content);
+
+  @override
+  String get encoding => source.encoding;
+
+  @override
+  String get fullName => source.fullName;
+
+  @override
+  bool get isInSystemLibrary => source.isInSystemLibrary;
+
+  @override
+  int get modificationStamp => source.modificationStamp;
+
+  @override
+  String get shortName => source.shortName;
+
+  @override
+  Uri get uri => throw new StateError('uri not supported for scripts');
+
+  @override
+  UriKind get uriKind =>
+      throw new StateError('uriKind not supported for scripts');
+
+  @override
+  bool exists() => source.exists();
+
+  @override
+  Uri resolveRelativeUri(Uri relativeUri) =>
+      throw new StateError('resolveRelativeUri not supported for scripts');
+}
+
+/**
+ * A task that looks for Dart scripts in an HTML file and computes both the Dart
+ * libraries that are referenced by those scripts and the embedded Dart scripts.
+ */
+class DartScriptsTask extends SourceBasedAnalysisTask {
+  /**
+   * The name of the [HTML_DOCUMENT] input.
+   */
+  static const String DOCUMENT_INPUT = 'DOCUMENT';
+
+  /**
+   * The task descriptor describing this kind of task.
+   */
+  static final TaskDescriptor DESCRIPTOR = new TaskDescriptor('DartScriptsTask',
+      createTask, buildInputs, <ResultDescriptor>[
+    DART_SCRIPTS,
+    REFERENCED_LIBRARIES
+  ]);
+
+  DartScriptsTask(InternalAnalysisContext context, AnalysisTarget target)
+      : super(context, target);
+
+  @override
+  TaskDescriptor get descriptor => DESCRIPTOR;
+
+  @override
+  void internalPerform() {
+    //
+    // Prepare inputs.
+    //
+    Source source = target.source;
+    Document document = getRequiredInput(DOCUMENT_INPUT);
+    //
+    // Process the script tags.
+    //
+    List<Source> libraries = <Source>[];
+    List<DartScript> inlineScripts = <DartScript>[];
+    List<Element> scripts = document.getElementsByTagName('script');
+    for (Element script in scripts) {
+      LinkedHashMap<dynamic, String> attributes = script.attributes;
+      if (attributes['type'] == 'application/dart') {
+        String src = attributes['src'];
+        if (src == null) {
+          if (script.hasContent()) {
+            List<ScriptFragment> fragments = <ScriptFragment>[];
+            for (Node node in script.nodes) {
+              if (node.nodeType == Node.TEXT_NODE) {
+                FileLocation start = node.sourceSpan.start;
+                fragments.add(new ScriptFragment(start.offset, start.line,
+                    start.column, (node as Text).data));
+              }
+            }
+            inlineScripts.add(new DartScript(source, fragments));
+          }
+        } else if (AnalysisEngine.isDartFileName(src)) {
+          Source source = context.sourceFactory.resolveUri(target.source, src);
+          if (source != null) {
+            libraries.add(source);
+          }
+        }
+      }
+    }
+    //
+    // Record outputs.
+    //
+    outputs[REFERENCED_LIBRARIES] =
+        libraries.isEmpty ? Source.EMPTY_LIST : libraries;
+    outputs[DART_SCRIPTS] =
+        inlineScripts.isEmpty ? DartScript.EMPTY_LIST : inlineScripts;
+  }
+
+  /**
+   * 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(Source target) {
+    return <String, TaskInput>{DOCUMENT_INPUT: HTML_DOCUMENT.of(target)};
+  }
+
+  /**
+   * Create a [DartScriptsTask] based on the given [target] in the given
+   * [context].
+   */
+  static DartScriptsTask createTask(
+      AnalysisContext context, AnalysisTarget target) {
+    return new DartScriptsTask(context, target);
+  }
+}
+
+/**
+ * A task that merges all of the errors for a single source into a single list
+ * of errors.
+ */
+class HtmlErrorsTask extends SourceBasedAnalysisTask {
+  /**
+   * The name of the input that is a list of errors from each of the embedded
+   * Dart scripts.
+   */
+  static const String DART_ERRORS_INPUT = 'DART_ERRORS';
+
+  /**
+   * The name of the [HTML_DOCUMENT_ERRORS] input.
+   */
+  static const String DOCUMENT_ERRORS_INPUT = 'DOCUMENT_ERRORS';
+
+  /**
+   * The task descriptor describing this kind of task.
+   */
+  static final TaskDescriptor DESCRIPTOR = new TaskDescriptor('HtmlErrorsTask',
+      createTask, buildInputs, <ResultDescriptor>[HTML_ERRORS]);
+
+  HtmlErrorsTask(InternalAnalysisContext context, AnalysisTarget target)
+      : super(context, target);
+
+  @override
+  TaskDescriptor get descriptor => DESCRIPTOR;
+
+  @override
+  void internalPerform() {
+    //
+    // Prepare inputs.
+    //
+    List<List<AnalysisError>> dartErrors = getRequiredInput(DART_ERRORS_INPUT);
+    List<AnalysisError> documentErrors =
+        getRequiredInput(DOCUMENT_ERRORS_INPUT);
+    //
+    // Compute the error list.
+    //
+    List<AnalysisError> errors = <AnalysisError>[];
+    errors.addAll(documentErrors);
+    for (List<AnalysisError> scriptErrors in dartErrors) {
+      errors.addAll(scriptErrors);
+    }
+    //
+    // Record outputs.
+    //
+    outputs[HTML_ERRORS] = removeDuplicateErrors(errors);
+  }
+
+  /**
+   * 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(Source target) {
+    return <String, TaskInput>{
+      DOCUMENT_ERRORS_INPUT: HTML_DOCUMENT_ERRORS.of(target),
+      DART_ERRORS_INPUT: DART_SCRIPTS.of(target).toListOf(DART_ERRORS)
+    };
+  }
+
+  /**
+   * Create an [HtmlErrorsTask] based on the given [target] in the given
+   * [context].
+   */
+  static HtmlErrorsTask createTask(
+      AnalysisContext context, AnalysisTarget target) {
+    return new HtmlErrorsTask(context, target);
+  }
+}
+
+/**
+ * A task that scans the content of a file, producing a set of Dart tokens.
+ */
+class ParseHtmlTask extends SourceBasedAnalysisTask {
+  /**
+   * The name of the input whose value is the content of the file.
+   */
+  static const String CONTENT_INPUT_NAME = 'CONTENT_INPUT_NAME';
+
+  /**
+   * The task descriptor describing this kind of task.
+   */
+  static final TaskDescriptor DESCRIPTOR = new TaskDescriptor('ParseHtmlTask',
+      createTask, buildInputs, <ResultDescriptor>[
+    HTML_DOCUMENT,
+    HTML_DOCUMENT_ERRORS
+  ]);
+
+  /**
+   * Initialize a newly created task to access the content of the source
+   * associated with the given [target] in the given [context].
+   */
+  ParseHtmlTask(InternalAnalysisContext context, AnalysisTarget target)
+      : super(context, target);
+
+  @override
+  TaskDescriptor get descriptor => DESCRIPTOR;
+
+  @override
+  void internalPerform() {
+    String content = getRequiredInput(CONTENT_INPUT_NAME);
+
+    HtmlParser parser = new HtmlParser(content, generateSpans: true);
+    parser.compatMode = 'quirks';
+    Document document = parser.parse();
+    List<ParseError> parseErrors = parser.errors;
+    List<AnalysisError> errors = <AnalysisError>[];
+    for (ParseError parseError in parseErrors) {
+      SourceSpan span = parseError.span;
+      errors.add(new AnalysisError(target.source, span.start.offset,
+          span.length, HtmlErrorCode.PARSE_ERROR, [parseError.message]));
+    }
+
+    outputs[HTML_DOCUMENT] = document;
+    outputs[HTML_DOCUMENT_ERRORS] = errors;
+  }
+
+  /**
+   * 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
+   * [source].
+   */
+  static Map<String, TaskInput> buildInputs(Source source) {
+    return <String, TaskInput>{CONTENT_INPUT_NAME: CONTENT.of(source)};
+  }
+
+  /**
+   * Create a [ParseHtmlTask] based on the given [target] in the given [context].
+   */
+  static ParseHtmlTask createTask(
+      AnalysisContext context, AnalysisTarget target) {
+    return new ParseHtmlTask(context, target);
+  }
+}
+
+/**
+ * A fragment of a [DartScript].
+ */
+class ScriptFragment {
+  /**
+   * The offset of the first character of the fragment, relative to the start of
+   * the containing source.
+   */
+  final int offset;
+
+  /**
+   * The line number of the line containing the first character of the fragment.
+   */
+  final int line;
+
+  /**
+   * The column number of the line containing the first character of the
+   * fragment.
+   */
+  final int column;
+
+  /**
+   * The content of the fragment.
+   */
+  final String content;
+
+  /**
+   * Initialize a newly created script fragment to have the given [offset] and
+   * [content].
+   */
+  ScriptFragment(this.offset, this.line, this.column, this.content);
+}
diff --git a/pkg/analyzer/lib/src/task/html_work_manager.dart b/pkg/analyzer/lib/src/task/html_work_manager.dart
new file mode 100644
index 0000000..d438d51
--- /dev/null
+++ b/pkg/analyzer/lib/src/task/html_work_manager.dart
@@ -0,0 +1,267 @@
+// 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.html_work_manager;
+
+import 'dart:collection';
+
+import 'package:analyzer/src/context/cache.dart';
+import 'package:analyzer/src/generated/engine.dart'
+    show
+        AnalysisEngine,
+        AnalysisErrorInfo,
+        AnalysisErrorInfoImpl,
+        AnalysisOptions,
+        CacheState,
+        InternalAnalysisContext;
+import 'package:analyzer/src/generated/error.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/generated/utilities_collection.dart';
+import 'package:analyzer/src/task/driver.dart';
+import 'package:analyzer/src/task/html.dart';
+import 'package:analyzer/task/general.dart';
+import 'package:analyzer/task/html.dart';
+import 'package:analyzer/task/model.dart';
+
+/**
+ * The manager for HTML specific analysis.
+ */
+class HtmlWorkManager implements WorkManager {
+  /**
+   * The context for which work is being managed.
+   */
+  final InternalAnalysisContext context;
+
+  /**
+   * The [TargetedResult]s that should be computed with priority.
+   */
+  final LinkedHashSet<TargetedResult> priorityResultQueue =
+      new LinkedHashSet<TargetedResult>();
+
+  /**
+   * The HTML sources.
+   */
+  final LinkedHashSet<Source> sourceQueue = new LinkedHashSet<Source>();
+
+  /**
+   * Initialize a newly created manager.
+   */
+  HtmlWorkManager(this.context) {
+    analysisCache.onResultInvalidated.listen(onResultInvalidated);
+  }
+
+  /**
+   * Returns the correctly typed result of `context.analysisCache`.
+   */
+  AnalysisCache get analysisCache => context.analysisCache;
+
+  /**
+   * The partition that contains analysis results that are not shared with other
+   * contexts.
+   */
+  CachePartition get privateAnalysisCachePartition =>
+      context.privateAnalysisCachePartition;
+
+  /**
+   * Specifies that the client want the given [result] of the given [target]
+   * to be computed with priority.
+   */
+  void addPriorityResult(AnalysisTarget target, ResultDescriptor result) {
+    priorityResultQueue.add(new TargetedResult(target, result));
+  }
+
+  /**
+   * Notifies the manager about changes in the explicit source list.
+   */
+  void applyChange(List<Source> addedSources, List<Source> changedSources,
+      List<Source> removedSources) {
+    addedSources = addedSources.where(_isHtmlSource).toList();
+    changedSources = changedSources.where(_isHtmlSource).toList();
+    removedSources = removedSources.where(_isHtmlSource).toList();
+    // source queue
+    sourceQueue.addAll(addedSources);
+    sourceQueue.addAll(changedSources);
+    sourceQueue.removeAll(removedSources);
+  }
+
+  @override
+  void applyPriorityTargets(List<AnalysisTarget> targets) {
+    // Unschedule the old targets.
+    List<TargetedResult> resultsToUnschedule = <TargetedResult>[];
+    for (TargetedResult result in priorityResultQueue) {
+      if (result.result == HTML_ERRORS) {
+        resultsToUnschedule.add(result);
+      }
+    }
+    priorityResultQueue.removeAll(resultsToUnschedule);
+    // Schedule new targets.
+    for (AnalysisTarget target in targets) {
+      if (_isHtmlSource(target)) {
+        addPriorityResult(target, HTML_ERRORS);
+      }
+    }
+  }
+
+  /**
+   * Return an [AnalysisErrorInfo] containing the list of all of the errors and
+   * the line info associated with the given [source]. The list of errors will
+   * be empty if the source is not known to the context or if there are no
+   * errors in the source. The errors contained in the list can be incomplete.
+   */
+  AnalysisErrorInfo getErrors(Source source) {
+    if (analysisCache.getState(source, HTML_ERRORS) == CacheState.VALID) {
+      List<AnalysisError> errors = analysisCache.getValue(source, HTML_ERRORS);
+      LineInfo lineInfo = analysisCache.getValue(source, LINE_INFO);
+      return new AnalysisErrorInfoImpl(errors, lineInfo);
+    }
+    List<AnalysisError> errors = <AnalysisError>[];
+    errors.addAll(analysisCache.getValue(source, HTML_DOCUMENT_ERRORS));
+    List<DartScript> scripts = analysisCache.getValue(source, DART_SCRIPTS);
+    for (DartScript script in scripts) {
+      errors.addAll(context.getErrors(script).errors);
+    }
+    LineInfo lineInfo = analysisCache.getValue(source, LINE_INFO);
+    return new AnalysisErrorInfoImpl(errors, lineInfo);
+  }
+
+  @override
+  TargetedResult getNextResult() {
+    // Try to find a priority result to compute.
+    while (priorityResultQueue.isNotEmpty) {
+      TargetedResult result = priorityResultQueue.first;
+      if (!_needsComputing(result.target, result.result)) {
+        priorityResultQueue.remove(result);
+        continue;
+      }
+      return result;
+    }
+    // Try to find a new HTML file to analyze.
+    while (sourceQueue.isNotEmpty) {
+      Source htmlSource = sourceQueue.first;
+      // Maybe done with this library.
+      if (!_needsComputing(htmlSource, HTML_ERRORS)) {
+        sourceQueue.remove(htmlSource);
+        continue;
+      }
+      // Analyze this library.
+      return new TargetedResult(htmlSource, HTML_ERRORS);
+    }
+    // No results to compute.
+    return null;
+  }
+
+  @override
+  WorkOrderPriority getNextResultPriority() {
+    if (priorityResultQueue.isNotEmpty) {
+      return WorkOrderPriority.PRIORITY;
+    }
+    if (sourceQueue.isNotEmpty) {
+      return WorkOrderPriority.NORMAL;
+    }
+    return WorkOrderPriority.NONE;
+  }
+
+  /**
+   * Notifies the manager about analysis options changes.
+   */
+  void onAnalysisOptionsChanged() {
+    _invalidateAllLocalResolutionInformation(false);
+  }
+
+  /**
+   * Notifies the manager that a result has been invalidated.
+   */
+  onResultInvalidated(InvalidatedResult event) {
+    ResultDescriptor descriptor = event.descriptor;
+    if (descriptor == HTML_ERRORS) {
+      sourceQueue.add(event.entry.target);
+    } else if (descriptor == DART_SCRIPTS) {
+      // TODO(brianwilkerson) Remove the scripts from the DartWorkManager's
+      // queues.
+    }
+  }
+
+  /**
+   * Notifies the manager about [SourceFactory] changes.
+   */
+  void onSourceFactoryChanged() {
+    _invalidateAllLocalResolutionInformation(true);
+  }
+
+  @override
+  void resultsComputed(
+      AnalysisTarget target, Map<ResultDescriptor, dynamic> outputs) {
+    // Update notice.
+    if (_isHtmlSource(target)) {
+      bool shouldSetErrors = false;
+      outputs.forEach((ResultDescriptor descriptor, value) {
+        if (descriptor == HTML_ERRORS) {
+          shouldSetErrors = true;
+        } else if (descriptor == DART_SCRIPTS) {
+          // List<DartScript> scripts = value;
+          if (priorityResultQueue.contains(target)) {
+            // TODO(brianwilkerson) Add the scripts to the DartWorkManager's
+            // priority queue.
+          } else {
+            // TODO(brianwilkerson) Add the scripts to the DartWorkManager's
+            // library queue.
+          }
+        }
+      });
+      if (shouldSetErrors) {
+        AnalysisErrorInfo info = getErrors(target);
+        context.getNotice(target).setErrors(info.errors, info.lineInfo);
+      }
+    }
+  }
+
+  /**
+   * Invalidate all of the resolution results computed by this context. The flag
+   * [invalidateUris] should be `true` if the cached results of converting URIs
+   * to source files should also be invalidated.
+   */
+  void _invalidateAllLocalResolutionInformation(bool invalidateUris) {
+    CachePartition partition = privateAnalysisCachePartition;
+    // Prepare targets and values to invalidate.
+    List<Source> htmlSources = <Source>[];
+    List<DartScript> scriptTargets = <DartScript>[];
+    MapIterator<AnalysisTarget, CacheEntry> iterator = partition.iterator();
+    while (iterator.moveNext()) {
+      AnalysisTarget target = iterator.key;
+      if (_isHtmlSource(target)) {
+        htmlSources.add(target);
+      }
+      if (target is DartScript) {
+        scriptTargets.add(target);
+      }
+    }
+    // Invalidate targets and values.
+    scriptTargets.forEach(partition.remove);
+    for (Source htmlSource in htmlSources) {
+      CacheEntry entry = partition.get(htmlSource);
+      if (htmlSource != null) {
+        entry.setState(HTML_ERRORS, CacheState.INVALID);
+        if (invalidateUris) {
+          entry.setState(REFERENCED_LIBRARIES, CacheState.INVALID);
+        }
+      }
+    }
+  }
+
+  /**
+   * Returns `true` if the given [result] of the given [target] needs
+   * computing, i.e. it is not in the valid and not in the error state.
+   */
+  bool _needsComputing(AnalysisTarget target, ResultDescriptor result) {
+    CacheState state = analysisCache.getState(target, result);
+    return state != CacheState.VALID && state != CacheState.ERROR;
+  }
+
+  /**
+   * Return `true` if the given target is an HTML source.
+   */
+  static bool _isHtmlSource(AnalysisTarget target) {
+    return target is Source && AnalysisEngine.isHtmlFileName(target.fullName);
+  }
+}
diff --git a/pkg/analyzer/lib/src/task/inputs.dart b/pkg/analyzer/lib/src/task/inputs.dart
index 5efac2c..308b06a 100644
--- a/pkg/analyzer/lib/src/task/inputs.dart
+++ b/pkg/analyzer/lib/src/task/inputs.dart
@@ -16,6 +16,11 @@
 typedef TaskInput<E> GenerateTaskInputs<B, E>(B object);
 
 /**
+ * A function that maps one [value] to another value.
+ */
+typedef R Mapper<P, R>(P value);
+
+/**
  * An input to an [AnalysisTask] that is computed by accessing a single result
  * defined on a single target.
  */
@@ -180,7 +185,7 @@
  * Finally, each of the task inputs are used to access analysis results,
  * and the list of the results is used as the input.
  */
-class MapToFlattenListTaskInput<K, V, E> implements TaskInput<List<E>> {
+class MapToFlattenListTaskInput<K, V, E> extends TaskInputImpl<List<E>> {
   final MapTaskInput<K, List<V>> base;
   final BinaryFunction<K, V, E> mapper;
 
@@ -293,10 +298,139 @@
 }
 
 /**
+ * An input to an [AnalysisTask] that is computed by mapping the value of
+ * another task input to a list of values.
+ */
+class ObjectToListTaskInput<E> extends TaskInputImpl<List<E>> with ListTaskInputMixin<E>
+    implements ListTaskInput<E> {
+  /**
+   * The input used to compute the value to be mapped.
+   */
+  final TaskInput baseInput;
+
+  /**
+   * The function used to map the value of the base input to the list of values.
+   */
+  final Mapper<Object, List<E>> mapper;
+
+  /**
+   * Initialize a newly created task input that computes the input by accessing
+   * the given [result] associated with the given [target].
+   */
+  ObjectToListTaskInput(this.baseInput, this.mapper);
+
+  @override
+  TaskInputBuilder<List<E>> createBuilder() =>
+      new ObjectToListTaskInputBuilder<E>(this);
+
+  @override
+  ListTaskInput /*<V>*/ toListOf(ResultDescriptor /*<V>*/ valueResult) {
+    return new ListToListTaskInput<E, dynamic /*V*/ >(
+        this, valueResult.of as dynamic);
+  }
+
+  @override
+  MapTaskInput<AnalysisTarget, dynamic /*V*/ > toMapOf(
+      ResultDescriptor /*<V>*/ valueResult) {
+    return new ListToMapTaskInput<AnalysisTarget, dynamic /*V*/ >(
+        this as dynamic, valueResult.of);
+  }
+}
+
+/**
+ * A [TaskInputBuilder] used to build an input based on a [SimpleTaskInput].
+ */
+class ObjectToListTaskInputBuilder<E> implements TaskInputBuilder<List<E>> {
+  /**
+   * The input being built.
+   */
+  final ObjectToListTaskInput<E> input;
+
+  /**
+   * The builder created by the input.
+   */
+  TaskInputBuilder builder;
+
+  /**
+   * The value of the input being built, or `null` if the value hasn't been set
+   * yet or if no result is available ([currentValueNotAvailable] was called).
+   */
+  List<E> _inputValue = null;
+
+  /**
+   * Initialize a newly created task input builder that computes the result
+   * specified by the given [input].
+   */
+  ObjectToListTaskInputBuilder(this.input) {
+    builder = input.baseInput.createBuilder();
+  }
+
+  @override
+  ResultDescriptor get currentResult {
+    if (builder == null) {
+      return null;
+    }
+    return builder.currentResult;
+  }
+
+  @override
+  AnalysisTarget get currentTarget {
+    if (builder == null) {
+      return null;
+    }
+    return builder.currentTarget;
+  }
+
+  @override
+  void set currentValue(Object value) {
+    if (builder == null) {
+      throw new StateError(
+          'Cannot set the result value when there is no current result');
+    }
+    builder.currentValue = value;
+  }
+
+  @override
+  List<E> get inputValue {
+    if (builder != null) {
+      throw new StateError('Result value has not been created');
+    }
+    return _inputValue;
+  }
+
+  @override
+  void currentValueNotAvailable() {
+    if (builder == null) {
+      throw new StateError(
+          'Cannot set the result value when there is no current result');
+    }
+    builder.currentValueNotAvailable();
+  }
+
+  @override
+  bool moveNext() {
+    if (builder == null) {
+      return false;
+    } else if (builder.moveNext()) {
+      return true;
+    } else {
+      // This might not be the right semantics. If the value could not be
+      // computed then we pass the resulting `null` in to the mapper function.
+      // Unfortunately, we cannot tell the difference between a `null` that's
+      // there because no value could be computed and a `null` that's there
+      // because that's what *was* computed.
+      _inputValue = input.mapper(builder.inputValue);
+      builder = null;
+      return false;
+    }
+  }
+}
+
+/**
  * An input to an [AnalysisTask] that is computed by accessing a single result
  * defined on a single target.
  */
-class SimpleTaskInput<V> implements TaskInput<V> {
+class SimpleTaskInput<V> extends TaskInputImpl<V> {
   /**
    * The target on which the result is defined.
    */
@@ -416,6 +550,13 @@
   }
 }
 
+abstract class TaskInputImpl<V> implements TaskInput<V> {
+  @override
+  ListTaskInput /*<E>*/ mappedToList(List /*<E>*/ mapper(V value)) {
+    return new ObjectToListTaskInput(this, mapper);
+  }
+}
+
 /**
  * A [TaskInputBuilder] used to build an input based on one or more other task
  * inputs. The task inputs to be built are specified by a table mapping the name
@@ -546,7 +687,7 @@
  * input. Finally, each of the task inputs are used to access analysis results,
  * and a collection of the analysis results is used as the input to the task.
  */
-abstract class _ListToCollectionTaskInput<B, E, C> implements TaskInput<C> {
+abstract class _ListToCollectionTaskInput<B, E, C> extends TaskInputImpl<C> {
   /**
    * The accessor used to access the list of elements being mapped.
    */
diff --git a/pkg/analyzer/lib/task/html.dart b/pkg/analyzer/lib/task/html.dart
new file mode 100644
index 0000000..abfbdf7
--- /dev/null
+++ b/pkg/analyzer/lib/task/html.dart
@@ -0,0 +1,29 @@
+// 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.task.html;
+
+import 'package:analyzer/src/generated/error.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/task/model.dart';
+import 'package:html/dom.dart';
+
+/**
+ * The result of parsing an HTML file.
+ */
+final ResultDescriptor<Document> HTML_DOCUMENT =
+    new ResultDescriptor<Document>('HTML_DOCUMENT', null);
+
+/**
+ * The analysis errors associated with a [Source] representing an HTML file.
+ */
+final ListResultDescriptor<AnalysisError> HTML_ERRORS =
+    new ListResultDescriptor<AnalysisError>(
+        'HTML_ERRORS', AnalysisError.NO_ERRORS);
+
+/**
+ * The sources of the Dart libraries referenced by an HTML file.
+ */
+final ListResultDescriptor<Source> REFERENCED_LIBRARIES =
+    new ListResultDescriptor<Source>('REFERENCED_LIBRARIES', Source.EMPTY_LIST);
diff --git a/pkg/analyzer/lib/task/model.dart b/pkg/analyzer/lib/task/model.dart
index 15ff9fc..0a45766 100644
--- a/pkg/analyzer/lib/task/model.dart
+++ b/pkg/analyzer/lib/task/model.dart
@@ -437,6 +437,12 @@
    * Create and return a builder that can be used to build this task input.
    */
   TaskInputBuilder<V> createBuilder();
+
+  /**
+   * Return a task input that can be used to compute a list whose elements are
+   * the result of passing the result of this input to the [mapper] function.
+   */
+  ListTaskInput /*<E>*/ mappedToList(List /*<E>*/ mapper(V value));
 }
 
 /**
diff --git a/pkg/analyzer/pubspec.yaml b/pkg/analyzer/pubspec.yaml
index 3ef3494..4c79bb5 100644
--- a/pkg/analyzer/pubspec.yaml
+++ b/pkg/analyzer/pubspec.yaml
@@ -1,15 +1,17 @@
 name: analyzer
-version: 0.25.1-alpha.1
+version: 0.25.1-alpha.4
 author: Dart Team <misc@dartlang.org>
 description: Static analyzer for Dart.
 homepage: http://www.dartlang.org
 environment:
-  sdk: '>=0.8.10+6 <2.0.0'
+  sdk: '>=1.8.0 <2.0.0'
 dependencies:
-  args: <0.14.0
+  args: '>=0.12.1 <0.14.0'
+  html: ^0.12.0
   path: '>=0.9.0 <2.0.0'
-  plugin: <0.2.0
-  watcher: '>=0.9.0 <0.10.0'
+  plugin: ^0.1.0
+  watcher: '>=0.9.6 <0.10.0'
+  yaml: ^2.1.2
 dev_dependencies:
   typed_mock: '>=0.0.4 <1.0.0'
   unittest: '>=0.9.0 <0.12.0'
diff --git a/pkg/analyzer/test/file_system/physical_resource_provider_test.dart b/pkg/analyzer/test/file_system/physical_resource_provider_test.dart
index 33ef876..7d0c141 100644
--- a/pkg/analyzer/test/file_system/physical_resource_provider_test.dart
+++ b/pkg/analyzer/test/file_system/physical_resource_provider_test.dart
@@ -286,7 +286,37 @@
     expect(provider.getStateLocation(idOne), equals(folderOne));
   }
 
-  test_watch_createFile() {
+  test_watchFile_delete() {
+    var path = join(tempPath, 'foo');
+    var file = new io.File(path);
+    file.writeAsStringSync('contents 1');
+    return _watchingFile(path, (changesReceived) {
+      expect(changesReceived, hasLength(0));
+      file.deleteSync();
+      return _delayed(() {
+        expect(changesReceived, hasLength(1));
+        expect(changesReceived[0].type, equals(ChangeType.REMOVE));
+        expect(changesReceived[0].path, equals(path));
+      });
+    });
+  }
+
+  test_watchFile_modify() {
+    var path = join(tempPath, 'foo');
+    var file = new io.File(path);
+    file.writeAsStringSync('contents 1');
+    return _watchingFile(path, (changesReceived) {
+      expect(changesReceived, hasLength(0));
+      file.writeAsStringSync('contents 2');
+      return _delayed(() {
+        expect(changesReceived, hasLength(1));
+        expect(changesReceived[0].type, equals(ChangeType.MODIFY));
+        expect(changesReceived[0].path, equals(path));
+      });
+    });
+  }
+
+  test_watchFolder_createFile() {
     return _watchingFolder(tempPath, (changesReceived) {
       expect(changesReceived, hasLength(0));
       var path = join(tempPath, 'foo');
@@ -306,7 +336,7 @@
     });
   }
 
-  test_watch_deleteFile() {
+  test_watchFolder_deleteFile() {
     var path = join(tempPath, 'foo');
     var file = new io.File(path);
     file.writeAsStringSync('contents 1');
@@ -321,7 +351,7 @@
     });
   }
 
-  test_watch_modifyFile() {
+  test_watchFolder_modifyFile() {
     var path = join(tempPath, 'foo');
     var file = new io.File(path);
     file.writeAsStringSync('contents 1');
@@ -336,7 +366,7 @@
     });
   }
 
-  test_watch_modifyFile_inSubDir() {
+  test_watchFolder_modifyFile_inSubDir() {
     var subdirPath = join(tempPath, 'foo');
     new io.Directory(subdirPath).createSync();
     var path = join(tempPath, 'bar');
@@ -360,6 +390,22 @@
     return new Future.delayed(new Duration(seconds: 1), computation);
   }
 
+  _watchingFile(String path, test(List<WatchEvent> changesReceived)) {
+    // Delay before we start watching the file.  This is necessary
+    // because on MacOS, file modifications that occur just before we
+    // start watching are sometimes misclassified as happening just after
+    // we start watching.
+    return _delayed(() {
+      File file = PhysicalResourceProvider.INSTANCE.getResource(path);
+      var changesReceived = <WatchEvent>[];
+      var subscription = file.changes.listen(changesReceived.add);
+      // Delay running the rest of the test to allow file.changes propogate.
+      return _delayed(() => test(changesReceived)).whenComplete(() {
+        subscription.cancel();
+      });
+    });
+  }
+
   _watchingFolder(String path, test(List<WatchEvent> changesReceived)) {
     // Delay before we start watching the folder.  This is necessary
     // because on MacOS, file modifications that occur just before we
diff --git a/pkg/analyzer/test/generated/all_the_rest_test.dart b/pkg/analyzer/test/generated/all_the_rest_test.dart
index 248ea3d..9eafca6 100644
--- a/pkg/analyzer/test/generated/all_the_rest_test.dart
+++ b/pkg/analyzer/test/generated/all_the_rest_test.dart
@@ -66,13 +66,14 @@
   runReflectiveTests(ExitDetectorTest2);
   runReflectiveTests(FileBasedSourceTest);
   runReflectiveTests(FileUriResolverTest);
-  runReflectiveTests(HtmlParserTest);
-  runReflectiveTests(HtmlTagInfoBuilderTest);
-  runReflectiveTests(HtmlUnitBuilderTest);
-  runReflectiveTests(HtmlWarningCodeTest);
+  if (!AnalysisEngine.instance.useTaskModel) {
+    runReflectiveTests(HtmlParserTest);
+    runReflectiveTests(HtmlTagInfoBuilderTest);
+    runReflectiveTests(HtmlUnitBuilderTest);
+    runReflectiveTests(HtmlWarningCodeTest);
+  }
   runReflectiveTests(ReferenceFinderTest);
   runReflectiveTests(SDKLibrariesReaderTest);
-  runReflectiveTests(SourceFactoryTest);
   runReflectiveTests(ToSourceVisitorTest);
   runReflectiveTests(UriKindTest);
   runReflectiveTests(StringScannerTest);
@@ -876,7 +877,7 @@
 
   EvaluationResult _getExpressionValue(String contents) {
     Source source = addSource("var x = $contents;");
-    LibraryElement library = resolve(source);
+    LibraryElement library = resolve2(source);
     CompilationUnit unit =
         analysisContext.resolveCompilationUnit(source, library);
     expect(unit, isNotNull);
@@ -1264,7 +1265,7 @@
 const int a = c;
 const int b = a;
 const int c = b;''');
-    LibraryElement libraryElement = resolve(librarySource);
+    LibraryElement libraryElement = resolve2(librarySource);
     CompilationUnit unit =
         analysisContext.resolveCompilationUnit(librarySource, libraryElement);
     analysisContext.computeErrors(librarySource);
@@ -1283,7 +1284,7 @@
     Source librarySource = addSource(r'''
 const int b = a;
 const int a = 0;''');
-    LibraryElement libraryElement = resolve(librarySource);
+    LibraryElement libraryElement = resolve2(librarySource);
     CompilationUnit unit =
         analysisContext.resolveCompilationUnit(librarySource, libraryElement);
     expect(unit, isNotNull);
@@ -1311,7 +1312,7 @@
 part of lib;
 const int b = a;
 const int d = c;''');
-    LibraryElement libraryElement = resolve(librarySource);
+    LibraryElement libraryElement = resolve2(librarySource);
     CompilationUnit libraryUnit =
         analysisContext.resolveCompilationUnit(librarySource, libraryElement);
     expect(libraryUnit, isNotNull);
@@ -1336,7 +1337,7 @@
 
   void test_computeValues_singleVariable() {
     Source librarySource = addSource("const int a = 0;");
-    LibraryElement libraryElement = resolve(librarySource);
+    LibraryElement libraryElement = resolve2(librarySource);
     CompilationUnit unit =
         analysisContext.resolveCompilationUnit(librarySource, libraryElement);
     expect(unit, isNotNull);
@@ -1353,7 +1354,7 @@
 enum E { id0, id1 }
 const E e = E.id0;
 ''');
-    LibraryElement libraryElement = resolve(librarySource);
+    LibraryElement libraryElement = resolve2(librarySource);
     CompilationUnit unit =
         analysisContext.resolveCompilationUnit(librarySource, libraryElement);
     expect(unit, isNotNull);
@@ -2169,7 +2170,7 @@
   void _assertProperDependencies(String sourceText,
       [List<ErrorCode> expectedErrorCodes = ErrorCode.EMPTY_LIST]) {
     Source source = addSource(sourceText);
-    LibraryElement element = resolve(source);
+    LibraryElement element = resolve2(source);
     CompilationUnit unit =
         analysisContext.resolveCompilationUnit(source, element);
     expect(unit, isNotNull);
@@ -6591,7 +6592,7 @@
    */
   CompilationUnit _resolveContents(String code) {
     Source source = addSource(code);
-    LibraryElement library = resolve(source);
+    LibraryElement library = resolve2(source);
     assertNoErrors(source);
     verify([source]);
     return analysisContext.resolveCompilationUnit(source, library);
@@ -7330,7 +7331,7 @@
   return x;
 }
 ''');
-    LibraryElement element = resolve(source);
+    LibraryElement element = resolve2(source);
     CompilationUnit unit = resolveCompilationUnit(source, element);
     FunctionDeclaration function = unit.declarations.last;
     BlockFunctionBody body = function.functionExpression.body;
@@ -7352,7 +7353,7 @@
   return x;
 }
 ''');
-    LibraryElement element = resolve(source);
+    LibraryElement element = resolve2(source);
     CompilationUnit unit = resolveCompilationUnit(source, element);
     FunctionDeclaration function = unit.declarations.last;
     BlockFunctionBody body = function.functionExpression.body;
@@ -7372,7 +7373,7 @@
   }
 }
 ''');
-    LibraryElement element = resolve(source);
+    LibraryElement element = resolve2(source);
     CompilationUnit unit = resolveCompilationUnit(source, element);
     FunctionDeclaration function = unit.declarations.last;
     BlockFunctionBody body = function.functionExpression.body;
@@ -7392,7 +7393,7 @@
   }
 }
 ''');
-    LibraryElement element = resolve(source);
+    LibraryElement element = resolve2(source);
     CompilationUnit unit = resolveCompilationUnit(source, element);
     FunctionDeclaration function = unit.declarations.last;
     BlockFunctionBody body = function.functionExpression.body;
@@ -8121,7 +8122,7 @@
   }
   void test_visitSimpleIdentifier_nonConst() {
     _visitNode(_makeTailVariable("v2", false));
-    _assertNoArcs();
+    _assertOneArc(_tail);
   }
   void test_visitSuperConstructorInvocation_const() {
     _visitNode(_makeTailSuperConstructorInvocation("A", true));
@@ -8129,7 +8130,7 @@
   }
   void test_visitSuperConstructorInvocation_nonConst() {
     _visitNode(_makeTailSuperConstructorInvocation("A", false));
-    _assertNoArcs();
+    _assertOneArc(_tail);
   }
   void test_visitSuperConstructorInvocation_unresolved() {
     SuperConstructorInvocation superConstructorInvocation =
@@ -8258,97 +8259,6 @@
   }
 }
 
-@reflectiveTest
-class SourceFactoryTest {
-  void test_creation() {
-    expect(new SourceFactory([]), isNotNull);
-  }
-  void test_fromEncoding_invalidUri() {
-    SourceFactory factory = new SourceFactory([]);
-    try {
-      factory.fromEncoding("<:&%>");
-      fail("Expected IllegalArgumentException");
-    } on IllegalArgumentException {}
-  }
-  void test_fromEncoding_noResolver() {
-    SourceFactory factory = new SourceFactory([]);
-    try {
-      factory.fromEncoding("foo:/does/not/exist.dart");
-      fail("Expected IllegalArgumentException");
-    } on IllegalArgumentException {}
-  }
-  void test_fromEncoding_valid() {
-    String encoding = "file:///does/not/exist.dart";
-    SourceFactory factory = new SourceFactory(
-        [new UriResolver_SourceFactoryTest_test_fromEncoding_valid(encoding)]);
-    expect(factory.fromEncoding(encoding), isNotNull);
-  }
-  void test_resolveUri_absolute() {
-    UriResolver_absolute resolver = new UriResolver_absolute();
-    SourceFactory factory = new SourceFactory([resolver]);
-    factory.resolveUri(null, "dart:core");
-    expect(resolver.invoked, isTrue);
-  }
-  void test_resolveUri_nonAbsolute_absolute() {
-    SourceFactory factory =
-        new SourceFactory([new UriResolver_nonAbsolute_absolute()]);
-    String absolutePath = "/does/not/matter.dart";
-    Source containingSource =
-        new FileBasedSource(FileUtilities2.createFile("/does/not/exist.dart"));
-    Source result = factory.resolveUri(containingSource, absolutePath);
-    expect(result.fullName,
-        FileUtilities2.createFile(absolutePath).getAbsolutePath());
-  }
-  void test_resolveUri_nonAbsolute_relative() {
-    SourceFactory factory =
-        new SourceFactory([new UriResolver_nonAbsolute_relative()]);
-    Source containingSource =
-        new FileBasedSource(FileUtilities2.createFile("/does/not/have.dart"));
-    Source result = factory.resolveUri(containingSource, "exist.dart");
-    expect(result.fullName,
-        FileUtilities2.createFile("/does/not/exist.dart").getAbsolutePath());
-  }
-
-  void test_resolveUri_nonAbsolute_relative_package() {
-    MemoryResourceProvider provider = new MemoryResourceProvider();
-    Context context = provider.pathContext;
-    String packagePath =
-        context.joinAll([context.separator, 'path', 'to', 'package']);
-    String libPath = context.joinAll([packagePath, 'lib']);
-    String dirPath = context.joinAll([libPath, 'dir']);
-    String firstPath = context.joinAll([dirPath, 'first.dart']);
-    String secondPath = context.joinAll([dirPath, 'second.dart']);
-
-    provider.newFolder(packagePath);
-    Folder libFolder = provider.newFolder(libPath);
-    provider.newFolder(dirPath);
-    File firstFile = provider.newFile(firstPath, '');
-    provider.newFile(secondPath, '');
-
-    PackageMapUriResolver resolver =
-        new PackageMapUriResolver(provider, {'package': [libFolder]});
-    SourceFactory factory = new SourceFactory([resolver]);
-    Source librarySource =
-        firstFile.createSource(Uri.parse('package:package/dir/first.dart'));
-
-    Source result = factory.resolveUri(librarySource, 'second.dart');
-    expect(result, isNotNull);
-    expect(result.fullName, secondPath);
-    expect(result.uri.toString(), 'package:package/dir/second.dart');
-  }
-
-  void test_restoreUri() {
-    JavaFile file1 = FileUtilities2.createFile("/some/file1.dart");
-    JavaFile file2 = FileUtilities2.createFile("/some/file2.dart");
-    Source source1 = new FileBasedSource(file1);
-    Source source2 = new FileBasedSource(file2);
-    Uri expected1 = parseUriWithException("file:///my_file.dart");
-    SourceFactory factory =
-        new SourceFactory([new UriResolver_restoreUri(source1, expected1)]);
-    expect(factory.restoreUri(source1), same(expected1));
-    expect(factory.restoreUri(source2), same(null));
-  }
-}
 
 @reflectiveTest
 class StringScannerTest extends AbstractScannerTest {
@@ -8426,66 +8336,6 @@
   }
 }
 
-class UriResolver_absolute extends UriResolver {
-  bool invoked = false;
-
-  UriResolver_absolute();
-
-  @override
-  Source resolveAbsolute(Uri uri) {
-    invoked = true;
-    return null;
-  }
-}
-
-class UriResolver_nonAbsolute_absolute extends UriResolver {
-  @override
-  Source resolveAbsolute(Uri uri) {
-    return new FileBasedSource(new JavaFile.fromUri(uri), uri);
-  }
-}
-
-class UriResolver_nonAbsolute_relative extends UriResolver {
-  @override
-  Source resolveAbsolute(Uri uri) {
-    return new FileBasedSource(new JavaFile.fromUri(uri), uri);
-  }
-}
-
-class UriResolver_restoreUri extends UriResolver {
-  Source source1;
-
-  Uri expected1;
-
-  UriResolver_restoreUri(this.source1, this.expected1);
-
-  @override
-  Source resolveAbsolute(Uri uri) => null;
-
-  @override
-  Uri restoreAbsolute(Source source) {
-    if (identical(source, source1)) {
-      return expected1;
-    }
-    return null;
-  }
-}
-
-class UriResolver_SourceFactoryTest_test_fromEncoding_valid
-    extends UriResolver {
-  String encoding;
-
-  UriResolver_SourceFactoryTest_test_fromEncoding_valid(this.encoding);
-
-  @override
-  Source resolveAbsolute(Uri uri) {
-    if (uri.toString() == encoding) {
-      return new TestSource();
-    }
-    return null;
-  }
-}
-
 /**
  * Instances of `XmlValidator` traverse an [XmlNode] structure and validate the node
  * hierarchy.
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 abea165..cfc2f62 100644
--- a/pkg/analyzer/test/generated/compile_time_error_code_test.dart
+++ b/pkg/analyzer/test/generated/compile_time_error_code_test.dart
@@ -4,6 +4,7 @@
 
 library engine.compile_time_error_code_test;
 
+import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/error.dart';
 import 'package:analyzer/src/generated/parser.dart' show ParserErrorCode;
 import 'package:analyzer/src/generated/source_io.dart';
@@ -27,7 +28,7 @@
 f(x) {
   return await x;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.AWAIT_IN_WRONG_CONTEXT]);
     verify([source]);
   }
@@ -40,7 +41,7 @@
 f(x) sync* {
   yield await x;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.AWAIT_IN_WRONG_CONTEXT]);
     verify([source]);
   }
@@ -48,7 +49,7 @@
   void fail_compileTimeConstantRaisesException() {
     Source source = addSource(r'''
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.COMPILE_TIME_CONSTANT_RAISES_EXCEPTION]);
     verify([source]);
@@ -60,7 +61,7 @@
   const C();
 }
 f() { return const C(); }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.CONST_CONSTRUCTOR_THROWS_EXCEPTION]);
     verify([source]);
@@ -74,7 +75,7 @@
     int async;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.INVALID_IDENTIFIER_IN_ASYNC]);
     verify([source]);
   }
@@ -87,7 +88,7 @@
     int await;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.INVALID_IDENTIFIER_IN_ASYNC]);
     verify([source]);
   }
@@ -100,7 +101,7 @@
     int yield;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.INVALID_IDENTIFIER_IN_ASYNC]);
     verify([source]);
   }
@@ -111,7 +112,7 @@
   A() {}
 }
 class B extends Object mixin A {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.MIXIN_DECLARES_CONSTRUCTOR]);
     verify([source]);
   }
@@ -121,7 +122,7 @@
     Source source = addSource(r'''
 var A;
 class B extends Object mixin A {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.MIXIN_OF_NON_CLASS]);
     verify([source]);
   }
@@ -129,7 +130,7 @@
   void fail_objectCannotExtendAnotherClass() {
     Source source = addSource(r'''
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.OBJECT_CANNOT_EXTEND_ANOTHER_CLASS]);
     verify([source]);
@@ -138,7 +139,7 @@
   void fail_superInitializerInObject() {
     Source source = addSource(r'''
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.SUPER_INITIALIZER_IN_OBJECT]);
     verify([source]);
   }
@@ -150,7 +151,7 @@
 f() async {
   yield* 0;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.YIELD_EACH_IN_NON_GENERATOR]);
     verify([source]);
   }
@@ -162,7 +163,7 @@
 f() {
   yield* 0;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.YIELD_IN_NON_GENERATOR]);
     verify([source]);
   }
@@ -174,7 +175,7 @@
 f() async {
   yield 0;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.YIELD_IN_NON_GENERATOR]);
     verify([source]);
   }
@@ -186,7 +187,7 @@
 f() {
   yield 0;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.YIELD_EACH_IN_NON_GENERATOR]);
     verify([source]);
   }
@@ -197,7 +198,7 @@
 String name(E e) {
   return e._name;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.ACCESS_PRIVATE_ENUM_FIELD]);
     // Cannot verify because "_name" cannot be resolved.
   }
@@ -213,7 +214,7 @@
     addNamedSource("/lib2.dart", r'''
 library lib2;
 class N {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.AMBIGUOUS_EXPORT]);
     verify([source]);
   }
@@ -226,7 +227,7 @@
   g(0);
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER]);
     verify([source]);
   }
@@ -239,7 +240,7 @@
   new C().g(async: 0);
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER]);
     // Note: we don't call verify([source]) because verify() doesn't understand
     // about @proxy.
@@ -251,7 +252,7 @@
   var async = 1;
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER]);
     verify([source]);
   }
@@ -262,7 +263,7 @@
   var async = 1;
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER]);
     verify([source]);
   }
@@ -275,7 +276,7 @@
   }
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER,
       CompileTimeErrorCode.LABEL_UNDEFINED
@@ -293,7 +294,7 @@
   return new C()..async();
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER]);
     verify([source]);
   }
@@ -307,7 +308,7 @@
   return new C()..async = 1;
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER]);
     verify([source]);
   }
@@ -321,7 +322,7 @@
   } catch (async) { }
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER]);
     verify([source]);
   }
@@ -335,7 +336,7 @@
   } catch (e, async) { }
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER]);
     verify([source]);
   }
@@ -348,7 +349,7 @@
   }
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER,
       CompileTimeErrorCode.LABEL_UNDEFINED
@@ -364,7 +365,7 @@
   for (async in []) {}
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER]);
     verify([source]);
   }
@@ -376,7 +377,7 @@
   g(0);
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER]);
     verify([source]);
   }
@@ -390,7 +391,7 @@
   return new C().async;
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER]);
     verify([source]);
   }
@@ -404,7 +405,7 @@
   return new C().async();
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER]);
     verify([source]);
   }
@@ -415,7 +416,7 @@
   int async() => null;
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER]);
     verify([source]);
   }
@@ -427,7 +428,7 @@
   return new async.Future.value(0);
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER]);
     verify([source]);
   }
@@ -441,7 +442,7 @@
   new C().async = 1;
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER]);
     verify([source]);
   }
@@ -453,7 +454,7 @@
 }
 g() {}
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER]);
     verify([source]);
   }
@@ -465,7 +466,7 @@
   return "$async";
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER]);
     verify([source]);
   }
@@ -481,7 +482,7 @@
   return l.async;
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER]);
     verify([source]);
   }
@@ -494,7 +495,7 @@
   }
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER]);
     verify([source]);
   }
@@ -505,7 +506,7 @@
   var async = 1;
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER]);
     verify([source]);
   }
@@ -516,7 +517,7 @@
   await for (var e in list) {
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.ASYNC_FOR_IN_WRONG_CONTEXT]);
     verify([source]);
   }
@@ -527,7 +528,7 @@
   var await = 1;
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER]);
     verify([source]);
   }
@@ -538,7 +539,7 @@
   var await = 1;
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER]);
     verify([source]);
   }
@@ -549,7 +550,7 @@
   var await = 1;
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER]);
     verify([source]);
   }
@@ -563,7 +564,7 @@
   dynamic @A(const A()) x;
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       ParserErrorCode.EXPECTED_CLASS_MEMBER,
       ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE
@@ -576,7 +577,7 @@
 class A {}
 class B {}
 class as = A with B;''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPEDEF_NAME]);
     verify([source]);
@@ -588,7 +589,7 @@
   var x;
   A(static this.x);
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE]);
     verify([source]);
   }
@@ -597,7 +598,7 @@
     Source source = addSource(r'''
 f(static x) {
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE]);
     verify([source]);
   }
@@ -607,14 +608,14 @@
 f() {
   typedef x;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE]);
     verify([source]);
   }
 
   void test_builtInIdentifierAsTypedefName_functionTypeAlias() {
     Source source = addSource("typedef bool as();");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPEDEF_NAME]);
     verify([source]);
@@ -622,7 +623,7 @@
 
   void test_builtInIdentifierAsTypeName() {
     Source source = addSource("class as {}");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE_NAME]);
     verify([source]);
@@ -630,7 +631,7 @@
 
   void test_builtInIdentifierAsTypeParameterName() {
     Source source = addSource("class A<as> {}");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source,
         [CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE_PARAMETER_NAME]);
     verify([source]);
@@ -653,7 +654,7 @@
     default: return 0;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.CASE_EXPRESSION_TYPE_IMPLEMENTS_EQUALS]);
     verify([source]);
@@ -665,7 +666,7 @@
   int x;
   A.x() {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.CONFLICTING_CONSTRUCTOR_NAME_AND_FIELD]);
     verify([source]);
@@ -677,7 +678,7 @@
   const A.x();
   void x() {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.CONFLICTING_CONSTRUCTOR_NAME_AND_METHOD]);
     verify([source]);
@@ -691,7 +692,7 @@
 class B extends A {
   m() {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.CONFLICTING_GETTER_AND_METHOD]);
     verify([source]);
   }
@@ -704,7 +705,7 @@
 class B extends A {
   m() {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.CONFLICTING_GETTER_AND_METHOD]);
     verify([source]);
   }
@@ -717,7 +718,7 @@
 class B extends A {
   int m;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.CONFLICTING_METHOD_AND_GETTER]);
     verify([source]);
   }
@@ -730,7 +731,7 @@
 class B extends A {
   get m => 0;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.CONFLICTING_METHOD_AND_GETTER]);
     verify([source]);
   }
@@ -739,7 +740,7 @@
     Source source = addSource(r'''
 class T<T> {
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_CLASS]);
     verify([source]);
@@ -750,7 +751,7 @@
 class A<T> {
   var T;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER]);
     verify([source]);
@@ -761,7 +762,7 @@
 class A<T> {
   get T => null;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER]);
     verify([source]);
@@ -772,7 +773,7 @@
 class A<T> {
   T() {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER]);
     verify([source]);
@@ -783,7 +784,7 @@
 class A<T> {
   static T() {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER]);
     verify([source]);
@@ -794,7 +795,7 @@
 class A<T> {
   set T(x) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER]);
     verify([source]);
@@ -820,7 +821,7 @@
       break;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -834,7 +835,7 @@
 int f() {
   return 3;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     // TODO(paulberry): the error CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE is
     // redundant and ought to be suppressed.
     assertErrors(source, [
@@ -853,7 +854,7 @@
 int f() {
   return 3;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -865,7 +866,7 @@
 class A extends Object with M {
   const A();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_MIXIN]);
     verify([source]);
   }
@@ -878,7 +879,7 @@
 class B extends A {
   const B(): super();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_CONST_SUPER]);
     verify([source]);
@@ -892,7 +893,7 @@
 class B extends A {
   const B();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_CONST_SUPER]);
     verify([source]);
@@ -906,7 +907,7 @@
 class B extends Object with A {
   const B();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_MIXIN,
       CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD
@@ -922,7 +923,7 @@
 class B extends A {
   const B();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD,
       CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_CONST_SUPER
@@ -936,7 +937,7 @@
   int x;
   const A();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD]);
     verify([source]);
@@ -980,7 +981,7 @@
   const A();
 }
 const a = new A();''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source,
         [CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE]);
     verify([source]);
@@ -994,7 +995,7 @@
   external factory const A();
 }
 const x = const A();''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -1007,7 +1008,7 @@
 }
 final a = const A();
 const C = a.m;''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source,
         [CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE]);
     verify([source]);
@@ -1025,28 +1026,69 @@
 
   void test_constEvalThrowsException_divisionByZero() {
     Source source = addSource("const C = 1 ~/ 0;");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.CONST_EVAL_THROWS_IDBZE]);
     verify([source]);
   }
 
+  void test_constEvalThrowsException_finalAlreadySet_initializer() {
+    // If a final variable has an initializer at the site of its declaration,
+    // and at the site of the constructor, then invoking that constructor would
+    // produce a runtime error; hence invoking that constructor via the "const"
+    // keyword results in a compile-time error.
+    Source source = addSource('''
+class C {
+  final x = 1;
+  const C() : x = 2;
+}
+var x = const C();
+''');
+    computeLibrarySourceErrors(source);
+    assertErrors(source, [
+      CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION,
+      StaticWarningCode.FIELD_INITIALIZED_IN_INITIALIZER_AND_DECLARATION
+    ]);
+    verify([source]);
+  }
+
+  void test_constEvalThrowsException_finalAlreadySet_initializing_formal() {
+    // If a final variable has an initializer at the site of its declaration,
+    // and it is initialized using an initializing formal at the site of the
+    // constructor, then invoking that constructor would produce a runtime
+    // error; hence invoking that constructor via the "const" keyword results
+    // in a compile-time error.
+    Source source = addSource('''
+class C {
+  final x = 1;
+  const C(this.x);
+}
+var x = const C(2);
+''');
+    computeLibrarySourceErrors(source);
+    assertErrors(source, [
+      CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION,
+      StaticWarningCode.FINAL_INITIALIZED_IN_DECLARATION_AND_CONSTRUCTOR
+    ]);
+    verify([source]);
+  }
+
   void test_constEvalThrowsException_unaryBitNot_null() {
     Source source = addSource("const C = ~null;");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION]);
     // no verify(), '~null' is not resolved
   }
 
   void test_constEvalThrowsException_unaryNegated_null() {
     Source source = addSource("const C = -null;");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION]);
     // no verify(), '-null' is not resolved
   }
 
   void test_constEvalThrowsException_unaryNot_null() {
     Source source = addSource("const C = !null;");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION]);
     verify([source]);
   }
@@ -1058,7 +1100,7 @@
 
   void test_constEvalTypeBool_binary_leftTrue() {
     Source source = addSource("const C = (true || 0);");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL,
       StaticTypeWarningCode.NON_BOOL_OPERAND,
@@ -1076,7 +1118,7 @@
   final a;
   const B(num p) : a = p == const A();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_NUM_STRING]);
     verify([source]);
@@ -1091,7 +1133,7 @@
   final a;
   const B(String p) : a = p != const A();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_NUM_STRING]);
     verify([source]);
@@ -1124,14 +1166,14 @@
   var x;
   A(const this.x) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.CONST_FORMAL_PARAMETER]);
     verify([source]);
   }
 
   void test_constFormalParameter_simpleFormalParameter() {
     Source source = addSource("f(const x) {}");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.CONST_FORMAL_PARAMETER]);
     verify([source]);
   }
@@ -1141,7 +1183,7 @@
 f(p) {
   const C = p;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source,
         [CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE]);
     verify([source]);
@@ -1149,7 +1191,7 @@
 
   void test_constInitializedWithNonConstValue_missingConstInListLiteral() {
     Source source = addSource("const List L = [0];");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source,
         [CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE]);
     verify([source]);
@@ -1157,7 +1199,7 @@
 
   void test_constInitializedWithNonConstValue_missingConstInMapLiteral() {
     Source source = addSource("const Map M = {'a' : 0};");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source,
         [CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE]);
     verify([source]);
@@ -1196,7 +1238,7 @@
 class C {
   const int f = 0;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.CONST_INSTANCE_FIELD]);
     verify([source]);
   }
@@ -1210,7 +1252,7 @@
 main() {
   const {const A() : 0};
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source,
         [CompileTimeErrorCode.CONST_MAP_KEY_EXPRESSION_TYPE_IMPLEMENTS_EQUALS]);
     verify([source]);
@@ -1231,7 +1273,7 @@
 main() {
   const {B.a : 0};
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source,
         [CompileTimeErrorCode.CONST_MAP_KEY_EXPRESSION_TYPE_IMPLEMENTS_EQUALS]);
     verify([source]);
@@ -1250,7 +1292,7 @@
 main() {
   var m = const { const A(): 42 };
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source,
         [CompileTimeErrorCode.CONST_MAP_KEY_EXPRESSION_TYPE_IMPLEMENTS_EQUALS]);
     verify([source]);
@@ -1268,7 +1310,7 @@
 main() {
   const {const B() : 0};
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source,
         [CompileTimeErrorCode.CONST_MAP_KEY_EXPRESSION_TYPE_IMPLEMENTS_EQUALS]);
     verify([source]);
@@ -1280,7 +1322,7 @@
   const A();
 }
 f() { return const A<A>(); }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.CONST_WITH_INVALID_TYPE_PARAMETERS]);
     verify([source]);
@@ -1295,7 +1337,7 @@
 f(p) {
   return const C<A>();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.CONST_WITH_INVALID_TYPE_PARAMETERS]);
     verify([source]);
@@ -1310,7 +1352,7 @@
 f(p) {
   return const C<A, A>();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.CONST_WITH_INVALID_TYPE_PARAMETERS]);
     verify([source]);
@@ -1322,7 +1364,7 @@
   T(a, b, {c, d}) {}
 }
 f() { return const T(0, 1, c: 2, d: 3); }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.CONST_WITH_NON_CONST]);
     verify([source]);
   }
@@ -1336,7 +1378,7 @@
 @A(v)
 main() {
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.CONST_WITH_NON_CONSTANT_ARGUMENT]);
     verify([source]);
@@ -1348,7 +1390,7 @@
   const A(a);
 }
 f(p) { return const A(p); }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     // TODO(paulberry): the error INVALID_CONSTAT is redundant and ought to be
     // suppressed.
     assertErrors(source, [
@@ -1364,7 +1406,7 @@
 f() {
   return const A();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.CONST_WITH_NON_TYPE]);
     verify([source]);
   }
@@ -1376,8 +1418,8 @@
 void f() {
   const lib.A();
 }''');
-    resolve(source1);
-    resolve(source2);
+    computeLibrarySourceErrors(source1);
+    computeLibrarySourceErrors(source2);
     assertErrors(source2, [CompileTimeErrorCode.CONST_WITH_NON_TYPE]);
     verify([source1]);
   }
@@ -1388,7 +1430,7 @@
   static const V = const A<T>();
   const A();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       CompileTimeErrorCode.CONST_WITH_TYPE_PARAMETERS,
       StaticWarningCode.TYPE_PARAMETER_REFERENCED_BY_STATIC
@@ -1402,7 +1444,7 @@
   static const V = const A<List<T>>();
   const A();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       CompileTimeErrorCode.CONST_WITH_TYPE_PARAMETERS,
       StaticWarningCode.TYPE_PARAMETER_REFERENCED_BY_STATIC
@@ -1418,7 +1460,7 @@
 f() {
   return const A.noSuchConstructor();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.CONST_WITH_UNDEFINED_CONSTRUCTOR]);
     // no verify(), 'noSuchConstructor' is not resolved
@@ -1432,7 +1474,7 @@
 f() {
   return const A();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source,
         [CompileTimeErrorCode.CONST_WITH_UNDEFINED_CONSTRUCTOR_DEFAULT]);
     verify([source]);
@@ -1440,7 +1482,7 @@
 
   void test_defaultValueInFunctionTypeAlias() {
     Source source = addSource("typedef F([x = 0]);");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE_ALIAS]);
     verify([source]);
@@ -1448,7 +1490,7 @@
 
   void test_defaultValueInFunctionTypedParameter_named() {
     Source source = addSource("f(g({p: null})) {}");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source,
         [CompileTimeErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPED_PARAMETER]);
     verify([source]);
@@ -1456,7 +1498,7 @@
 
   void test_defaultValueInFunctionTypedParameter_optional() {
     Source source = addSource("f(g([p = null])) {}");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source,
         [CompileTimeErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPED_PARAMETER]);
     verify([source]);
@@ -1471,7 +1513,7 @@
 class B implements A {
   B([int x = 1]) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       CompileTimeErrorCode.DEFAULT_VALUE_IN_REDIRECTING_FACTORY_CONSTRUCTOR
     ]);
@@ -1484,7 +1526,7 @@
   A.a() {}
   A.a() {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       CompileTimeErrorCode.DUPLICATE_CONSTRUCTOR_NAME,
       CompileTimeErrorCode.DUPLICATE_CONSTRUCTOR_NAME
@@ -1498,7 +1540,7 @@
   A() {}
   A() {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       CompileTimeErrorCode.DUPLICATE_CONSTRUCTOR_DEFAULT,
       CompileTimeErrorCode.DUPLICATE_CONSTRUCTOR_DEFAULT
@@ -1506,17 +1548,6 @@
     verify([source]);
   }
 
-  void test_duplicateDefinition() {
-    Source source = addSource(r'''
-f() {
-  int m = 0;
-  m(a) {}
-}''');
-    resolve(source);
-    assertErrors(source, [CompileTimeErrorCode.DUPLICATE_DEFINITION]);
-    verify([source]);
-  }
-
   void test_duplicateDefinition_acrossLibraries() {
     Source librarySource = addNamedSource("/lib.dart", r'''
 library lib;
@@ -1531,18 +1562,28 @@
 part of lib;
 
 class A {}''');
-    resolve(librarySource);
+    computeLibrarySourceErrors(librarySource);
     assertErrors(sourceB, [CompileTimeErrorCode.DUPLICATE_DEFINITION]);
     verify([librarySource, sourceA, sourceB]);
   }
 
+  void test_duplicateDefinition_catch() {
+    Source source = addSource(r'''
+main() {
+  try {} catch (e, e) {}
+}''');
+    computeLibrarySourceErrors(source);
+    assertErrors(source, [CompileTimeErrorCode.DUPLICATE_DEFINITION]);
+    verify([source]);
+  }
+
   void test_duplicateDefinition_classMembers_fields() {
     Source source = addSource(r'''
 class A {
   int a;
   int a;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.DUPLICATE_DEFINITION]);
     verify([source]);
   }
@@ -1553,7 +1594,7 @@
   int x;
   static int x;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.DUPLICATE_DEFINITION]);
     verify([source]);
   }
@@ -1564,12 +1605,50 @@
   m() {}
   m() {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.DUPLICATE_DEFINITION]);
     verify([source]);
   }
 
-  void test_duplicateDefinition_localFields() {
+  void test_duplicateDefinition_locals_inCase() {
+    Source source = addSource(r'''
+main() {
+  switch(1) {
+    case 1:
+      var a;
+      var a;
+  }
+}''');
+    computeLibrarySourceErrors(source);
+    assertErrors(source, [CompileTimeErrorCode.DUPLICATE_DEFINITION]);
+    verify([source]);
+  }
+
+  void test_duplicateDefinition_locals_inFunctionBlock() {
+    Source source = addSource(r'''
+main() {
+  int m = 0;
+  m(a) {}
+}''');
+    computeLibrarySourceErrors(source);
+    assertErrors(source, [CompileTimeErrorCode.DUPLICATE_DEFINITION]);
+    verify([source]);
+  }
+
+  void test_duplicateDefinition_locals_inIf() {
+    Source source = addSource(r'''
+main(int p) {
+  if (p != 0) {
+    var a;
+    var a;
+  }
+}''');
+    computeLibrarySourceErrors(source);
+    assertErrors(source, [CompileTimeErrorCode.DUPLICATE_DEFINITION]);
+    verify([source]);
+  }
+
+  void test_duplicateDefinition_locals_inMethodBlock() {
     Source source = addSource(r'''
 class A {
   m() {
@@ -1577,7 +1656,56 @@
     int a;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
+    assertErrors(source, [CompileTimeErrorCode.DUPLICATE_DEFINITION]);
+    verify([source]);
+  }
+
+  void test_duplicateDefinition_parameters_inFunctionTypeAlias() {
+    Source source = addSource(r'''
+typedef F(int a, double a);
+''');
+    computeLibrarySourceErrors(source);
+    assertErrors(source, [CompileTimeErrorCode.DUPLICATE_DEFINITION]);
+    verify([source]);
+  }
+
+  void test_duplicateDefinition_parameters_inLocalFunction() {
+    Source source = addSource(r'''
+main() {
+  f(int a, double a) {
+  };
+}''');
+    computeLibrarySourceErrors(source);
+    assertErrors(source, [CompileTimeErrorCode.DUPLICATE_DEFINITION]);
+    verify([source]);
+  }
+
+  void test_duplicateDefinition_parameters_inMethod() {
+    Source source = addSource(r'''
+class A {
+  m(int a, double a) {
+  }
+}''');
+    computeLibrarySourceErrors(source);
+    assertErrors(source, [CompileTimeErrorCode.DUPLICATE_DEFINITION]);
+    verify([source]);
+  }
+
+  void test_duplicateDefinition_parameters_inTopLevelFunction() {
+    Source source = addSource(r'''
+f(int a, double a) {
+}''');
+    computeLibrarySourceErrors(source);
+    assertErrors(source, [CompileTimeErrorCode.DUPLICATE_DEFINITION]);
+    verify([source]);
+  }
+
+  void test_duplicateDefinition_typeParameters() {
+    Source source = addSource(r'''
+class A<T, T> {
+}''');
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.DUPLICATE_DEFINITION]);
     verify([source]);
   }
@@ -1590,7 +1718,7 @@
 class B extends A {
   static int get x => 0;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.DUPLICATE_DEFINITION_INHERITANCE]);
     verify([source]);
@@ -1604,7 +1732,7 @@
 class B extends A {
   static int get x => 0;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.DUPLICATE_DEFINITION_INHERITANCE]);
     verify([source]);
@@ -1618,7 +1746,7 @@
 class B extends A {
   static x() {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.DUPLICATE_DEFINITION_INHERITANCE]);
     verify([source]);
@@ -1632,7 +1760,7 @@
 abstract class B extends A {
   static x() {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.DUPLICATE_DEFINITION_INHERITANCE]);
     verify([source]);
@@ -1646,7 +1774,7 @@
 class B extends A {
   static set x(value) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.DUPLICATE_DEFINITION_INHERITANCE]);
     verify([source]);
@@ -1660,7 +1788,7 @@
 class B extends A {
   static set x(value) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.DUPLICATE_DEFINITION_INHERITANCE]);
     verify([source]);
@@ -1672,14 +1800,14 @@
 main() {
   f(a: 1, a: 2);
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.DUPLICATE_NAMED_ARGUMENT]);
     verify([source]);
   }
 
   void test_exportInternalLibrary() {
     Source source = addSource("export 'dart:_interceptors';");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.EXPORT_INTERNAL_LIBRARY]);
     verify([source]);
   }
@@ -1689,7 +1817,7 @@
 library L;
 export 'lib1.dart';''');
     addNamedSource("/lib1.dart", "part of lib;");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.EXPORT_OF_NON_LIBRARY]);
     verify([source]);
   }
@@ -1721,7 +1849,7 @@
 
   void test_extendsDisallowedClass_class_bool() {
     Source source = addSource("class A extends bool {}");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS,
       CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT
@@ -1731,7 +1859,7 @@
 
   void test_extendsDisallowedClass_class_double() {
     Source source = addSource("class A extends double {}");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS,
       CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT
@@ -1741,7 +1869,7 @@
 
   void test_extendsDisallowedClass_class_int() {
     Source source = addSource("class A extends int {}");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS,
       CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT
@@ -1751,7 +1879,7 @@
 
   void test_extendsDisallowedClass_class_Null() {
     Source source = addSource("class A extends Null {}");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS,
       CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT
@@ -1761,7 +1889,7 @@
 
   void test_extendsDisallowedClass_class_num() {
     Source source = addSource("class A extends num {}");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS,
       CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT
@@ -1771,7 +1899,7 @@
 
   void test_extendsDisallowedClass_class_String() {
     Source source = addSource("class A extends String {}");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS,
       CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT
@@ -1783,7 +1911,7 @@
     Source source = addSource(r'''
 class M {}
 class C = bool with M;''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS,
       CompileTimeErrorCode.MIXIN_HAS_NO_CONSTRUCTORS
@@ -1795,7 +1923,7 @@
     Source source = addSource(r'''
 class M {}
 class C = double with M;''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS]);
     verify([source]);
   }
@@ -1804,7 +1932,7 @@
     Source source = addSource(r'''
 class M {}
 class C = int with M;''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS,
       CompileTimeErrorCode.MIXIN_HAS_NO_CONSTRUCTORS
@@ -1816,7 +1944,7 @@
     Source source = addSource(r'''
 class M {}
 class C = Null with M;''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS]);
     verify([source]);
   }
@@ -1825,7 +1953,7 @@
     Source source = addSource(r'''
 class M {}
 class C = num with M;''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS]);
     verify([source]);
   }
@@ -1834,7 +1962,7 @@
     Source source = addSource(r'''
 class M {}
 class C = String with M;''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS,
       CompileTimeErrorCode.MIXIN_HAS_NO_CONSTRUCTORS
@@ -1846,7 +1974,7 @@
     Source source = addSource(r'''
 enum E { ONE }
 class A extends E {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.EXTENDS_ENUM]);
     verify([source]);
   }
@@ -1855,14 +1983,14 @@
     Source source = addSource(r'''
 int A;
 class B extends A {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.EXTENDS_NON_CLASS]);
     verify([source]);
   }
 
   void test_extendsNonClass_dynamic() {
     Source source = addSource("class B extends dynamic {}");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.EXTENDS_NON_CLASS]);
     verify([source]);
   }
@@ -1875,7 +2003,7 @@
 main() {
   const A(0);
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.EXTRA_POSITIONAL_ARGUMENTS]);
     verify([source]);
   }
@@ -1888,7 +2016,7 @@
 class B extends A {
   const B() : super(0);
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.EXTRA_POSITIONAL_ARGUMENTS]);
     verify([source]);
   }
@@ -1899,7 +2027,7 @@
   int x;
   A() : x = 0, x = 1 {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source,
         [CompileTimeErrorCode.FIELD_INITIALIZED_BY_MULTIPLE_INITIALIZERS]);
     verify([source]);
@@ -1911,7 +2039,7 @@
   int x;
   A() : x = 0, x = 1, x = 2 {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       CompileTimeErrorCode.FIELD_INITIALIZED_BY_MULTIPLE_INITIALIZERS,
       CompileTimeErrorCode.FIELD_INITIALIZED_BY_MULTIPLE_INITIALIZERS
@@ -1926,7 +2054,7 @@
   int y;
   A() : x = 0, x = 1, y = 0, y = 1 {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       CompileTimeErrorCode.FIELD_INITIALIZED_BY_MULTIPLE_INITIALIZERS,
       CompileTimeErrorCode.FIELD_INITIALIZED_BY_MULTIPLE_INITIALIZERS
@@ -1940,7 +2068,7 @@
   int x;
   A(this.x) : x = 1 {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source,
         [CompileTimeErrorCode.FIELD_INITIALIZED_IN_PARAMETER_AND_INITIALIZER]);
     verify([source]);
@@ -1952,7 +2080,7 @@
   int x;
   factory A(this.x) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.FIELD_INITIALIZER_FACTORY_CONSTRUCTOR]);
     verify([source]);
@@ -1965,7 +2093,7 @@
   int x;
   m(this.x) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       ParserErrorCode.FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR,
       CompileTimeErrorCode.FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR
@@ -1979,7 +2107,7 @@
   int x;
   m([this.x]) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR]);
     verify([source]);
@@ -1992,7 +2120,7 @@
   A.named() {}
   A() : this.named(), x = 42;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source,
         [CompileTimeErrorCode.FIELD_INITIALIZER_REDIRECTING_CONSTRUCTOR]);
     verify([source]);
@@ -2005,7 +2133,7 @@
   A.named() {}
   A() : x = 42, this.named();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source,
         [CompileTimeErrorCode.FIELD_INITIALIZER_REDIRECTING_CONSTRUCTOR]);
     verify([source]);
@@ -2018,7 +2146,7 @@
   A.named() {}
   A(this.x) : this.named();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source,
         [CompileTimeErrorCode.FIELD_INITIALIZER_REDIRECTING_CONSTRUCTOR]);
     verify([source]);
@@ -2030,7 +2158,7 @@
   final x;
   A() : x = 0, x = 0 {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source,
         [CompileTimeErrorCode.FIELD_INITIALIZED_BY_MULTIPLE_INITIALIZERS]);
     verify([source]);
@@ -2050,7 +2178,7 @@
   final x;
   A(this.x) : x = 0 {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source,
         [CompileTimeErrorCode.FIELD_INITIALIZED_IN_PARAMETER_AND_INITIALIZER]);
     verify([source]);
@@ -2062,7 +2190,7 @@
   final x;
   A(this.x, this.x) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.FINAL_INITIALIZED_MULTIPLE_TIMES]);
     verify([source]);
@@ -2073,14 +2201,14 @@
 class A {
   static const F;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.CONST_NOT_INITIALIZED]);
     verify([source]);
   }
 
   void test_finalNotInitialized_library_const() {
     Source source = addSource("const F;");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.CONST_NOT_INITIALIZED]);
     verify([source]);
   }
@@ -2090,7 +2218,7 @@
 f() {
   const int x;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.CONST_NOT_INITIALIZED]);
     verify([source]);
   }
@@ -2099,7 +2227,7 @@
     Source source = addSource(r'''
 var b1 = const bool.fromEnvironment(1);
 var b2 = const bool.fromEnvironment('x', defaultValue: 1);''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION,
       StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE,
@@ -2115,7 +2243,7 @@
     analysisContext2.declaredVariables.define("x", "true");
     Source source =
         addSource("var b = const bool.fromEnvironment('x', defaultValue: 1);");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION,
       StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE
@@ -2129,7 +2257,7 @@
   x(y) {}
   get x => 0;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.GETTER_AND_METHOD_WITH_SAME_NAME]);
     verify([source]);
@@ -2163,49 +2291,49 @@
 
   void test_implementsDisallowedClass_class_bool() {
     Source source = addSource("class A implements bool {}");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS]);
     verify([source]);
   }
 
   void test_implementsDisallowedClass_class_double() {
     Source source = addSource("class A implements double {}");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS]);
     verify([source]);
   }
 
   void test_implementsDisallowedClass_class_int() {
     Source source = addSource("class A implements int {}");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS]);
     verify([source]);
   }
 
   void test_implementsDisallowedClass_class_Null() {
     Source source = addSource("class A implements Null {}");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS]);
     verify([source]);
   }
 
   void test_implementsDisallowedClass_class_num() {
     Source source = addSource("class A implements num {}");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS]);
     verify([source]);
   }
 
   void test_implementsDisallowedClass_class_String() {
     Source source = addSource("class A implements String {}");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS]);
     verify([source]);
   }
 
   void test_implementsDisallowedClass_class_String_num() {
     Source source = addSource("class A implements String, num {}");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS,
       CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS
@@ -2218,7 +2346,7 @@
 class A {}
 class M {}
 class C = A with M implements bool;''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS]);
     verify([source]);
   }
@@ -2228,7 +2356,7 @@
 class A {}
 class M {}
 class C = A with M implements double;''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS]);
     verify([source]);
   }
@@ -2238,7 +2366,7 @@
 class A {}
 class M {}
 class C = A with M implements int;''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS]);
     verify([source]);
   }
@@ -2248,7 +2376,7 @@
 class A {}
 class M {}
 class C = A with M implements Null;''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS]);
     verify([source]);
   }
@@ -2258,7 +2386,7 @@
 class A {}
 class M {}
 class C = A with M implements num;''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS]);
     verify([source]);
   }
@@ -2268,7 +2396,7 @@
 class A {}
 class M {}
 class C = A with M implements String;''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS]);
     verify([source]);
   }
@@ -2278,7 +2406,7 @@
 class A {}
 class M {}
 class C = A with M implements String, num;''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS,
       CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS
@@ -2288,7 +2416,7 @@
 
   void test_implementsDynamic() {
     Source source = addSource("class A implements dynamic {}");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.IMPLEMENTS_DYNAMIC]);
     verify([source]);
   }
@@ -2297,7 +2425,7 @@
     Source source = addSource(r'''
 enum E { ONE }
 class A implements E {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.IMPLEMENTS_ENUM]);
     verify([source]);
   }
@@ -2306,7 +2434,7 @@
     Source source = addSource(r'''
 int A;
 class B implements A {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.IMPLEMENTS_NON_CLASS]);
     verify([source]);
   }
@@ -2317,7 +2445,7 @@
 class M {}
 int B;
 class C = A with M implements B;''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.IMPLEMENTS_NON_CLASS]);
     verify([source]);
   }
@@ -2326,7 +2454,7 @@
     Source source = addSource(r'''
 class A {}
 class B implements A, A {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.IMPLEMENTS_REPEATED]);
     verify([source]);
   }
@@ -2335,7 +2463,7 @@
     Source source = addSource(r'''
 class A {} class C{}
 class B implements A, A, A, A {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       CompileTimeErrorCode.IMPLEMENTS_REPEATED,
       CompileTimeErrorCode.IMPLEMENTS_REPEATED,
@@ -2348,14 +2476,14 @@
     Source source = addSource(r'''
 class A {}
 class B extends A implements A {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.IMPLEMENTS_SUPER_CLASS]);
     verify([source]);
   }
 
   void test_implementsSuperClass_Object() {
     Source source = addSource("class A implements Object {}");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.IMPLEMENTS_SUPER_CLASS]);
     verify([source]);
   }
@@ -2367,7 +2495,7 @@
   A() : v = f;
   var f;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.IMPLICIT_THIS_REFERENCE_IN_INITIALIZER]);
     verify([source]);
@@ -2379,7 +2507,7 @@
   final x = 0;
   final y = x;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.IMPLICIT_THIS_REFERENCE_IN_INITIALIZER]);
     verify([source]);
@@ -2392,7 +2520,7 @@
   A() : v = f();
   f() {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.IMPLICIT_THIS_REFERENCE_IN_INITIALIZER]);
     verify([source]);
@@ -2404,7 +2532,7 @@
   static var F = m();
   m() {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.IMPLICIT_THIS_REFERENCE_IN_INITIALIZER]);
     verify([source]);
@@ -2417,7 +2545,7 @@
   A.named() : this(f);
   var f;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.IMPLICIT_THIS_REFERENCE_IN_INITIALIZER]);
     verify([source]);
@@ -2432,7 +2560,7 @@
   B() : super(f);
   var f;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.IMPLICIT_THIS_REFERENCE_IN_INITIALIZER]);
     verify([source]);
@@ -2440,7 +2568,7 @@
 
   void test_importInternalLibrary() {
     Source source = addSource("import 'dart:_interceptors';");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     // Note, in these error cases we may generate an UNUSED_IMPORT hint, while
     // we could prevent the hint from being generated by testing the import
     // directive for the error, this is such a minor corner case that we don't
@@ -2455,7 +2583,7 @@
 
   void test_importInternalLibrary_js_helper() {
     Source source = addSource("import 'dart:_js_helper';");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     // Note, in these error cases we may generate an UNUSED_IMPORT hint, while
     // we could prevent the hint from being generated by testing the import
     // directive for the error, this is such a minor corner case that we don't
@@ -2476,7 +2604,7 @@
     addNamedSource("/part.dart", r'''
 part of lib;
 class A{}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.IMPORT_OF_NON_LIBRARY]);
     verify([source]);
   }
@@ -2491,7 +2619,7 @@
       break;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.INCONSISTENT_CASE_EXPRESSION_TYPES]);
     verify([source]);
@@ -2517,7 +2645,7 @@
       break;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       CompileTimeErrorCode.INCONSISTENT_CASE_EXPRESSION_TYPES,
       CompileTimeErrorCode.INCONSISTENT_CASE_EXPRESSION_TYPES
@@ -2537,7 +2665,7 @@
       break;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       CompileTimeErrorCode.INCONSISTENT_CASE_EXPRESSION_TYPES,
       CompileTimeErrorCode.INCONSISTENT_CASE_EXPRESSION_TYPES
@@ -2553,7 +2681,7 @@
   const A() : x = 'foo';
 }
 A a = const A();''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.INITIALIZER_FOR_NON_EXISTENT_FIELD]);
   }
@@ -2563,7 +2691,7 @@
 class A {
   A() : x = 0 {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.INITIALIZER_FOR_NON_EXISTENT_FIELD]);
   }
@@ -2574,7 +2702,7 @@
   static int x;
   A() : x = 0 {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.INITIALIZER_FOR_STATIC_FIELD]);
     verify([source]);
   }
@@ -2584,7 +2712,7 @@
 class A {
   A(this.x) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source,
         [CompileTimeErrorCode.INITIALIZING_FORMAL_FOR_NON_EXISTENT_FIELD]);
     verify([source]);
@@ -2598,7 +2726,7 @@
 class B extends A {
   B(this.x) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source,
         [CompileTimeErrorCode.INITIALIZING_FORMAL_FOR_NON_EXISTENT_FIELD]);
     verify([source]);
@@ -2609,7 +2737,7 @@
 class A {
   A([this.x]) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source,
         [CompileTimeErrorCode.INITIALIZING_FORMAL_FOR_NON_EXISTENT_FIELD]);
     verify([source]);
@@ -2621,7 +2749,7 @@
   int get x => 1;
   A(this.x) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source,
         [CompileTimeErrorCode.INITIALIZING_FORMAL_FOR_NON_EXISTENT_FIELD]);
     verify([source]);
@@ -2633,7 +2761,7 @@
   static int x;
   A([this.x]) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.INITIALIZING_FORMAL_FOR_STATIC_FIELD]);
     verify([source]);
@@ -2649,7 +2777,7 @@
     return new A();
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.INSTANCE_MEMBER_ACCESS_FROM_FACTORY]);
     verify([source]);
@@ -2665,7 +2793,7 @@
     return new A._();
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.INSTANCE_MEMBER_ACCESS_FROM_FACTORY]);
     verify([source]);
@@ -2679,7 +2807,7 @@
     f;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.INSTANCE_MEMBER_ACCESS_FROM_STATIC]);
     verify([source]);
@@ -2693,7 +2821,7 @@
     g;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.INSTANCE_MEMBER_ACCESS_FROM_STATIC]);
     verify([source]);
@@ -2707,7 +2835,7 @@
     m();
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.INSTANCE_MEMBER_ACCESS_FROM_STATIC]);
     verify([source]);
@@ -2719,7 +2847,7 @@
 E e(String name) {
   return const E();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.INSTANTIATE_ENUM]);
     verify([source]);
   }
@@ -2730,7 +2858,7 @@
 E e(String name) {
   return new E();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.INSTANTIATE_ENUM]);
     verify([source]);
   }
@@ -2741,7 +2869,7 @@
 @V
 main() {
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.INVALID_ANNOTATION]);
     verify([source]);
   }
@@ -2755,7 +2883,7 @@
 @p.V
 main() {
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.INVALID_ANNOTATION]);
     verify([source]);
   }
@@ -2769,7 +2897,7 @@
 @p.V
 main() {
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.INVALID_ANNOTATION]);
     verify([source]);
   }
@@ -2783,7 +2911,7 @@
 @p.V
 main() {
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.INVALID_ANNOTATION]);
     verify([source]);
   }
@@ -2794,7 +2922,7 @@
 @V
 main() {
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.INVALID_ANNOTATION]);
     verify([source]);
   }
@@ -2805,7 +2933,7 @@
 @V
 main() {
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.INVALID_ANNOTATION]);
     verify([source]);
   }
@@ -2818,7 +2946,7 @@
 @A.f
 main() {
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.INVALID_ANNOTATION]);
     verify([source]);
   }
@@ -2828,7 +2956,7 @@
 @unresolved
 main() {
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.INVALID_ANNOTATION]);
   }
 
@@ -2837,7 +2965,7 @@
 @Unresolved()
 main() {
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.INVALID_ANNOTATION]);
   }
 
@@ -2847,7 +2975,7 @@
 @p.unresolved
 main() {
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.INVALID_ANNOTATION]);
   }
 
@@ -2857,7 +2985,7 @@
 class A {
   static const foo = null;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.INVALID_ANNOTATION]);
   }
 
@@ -2913,7 +3041,7 @@
   B() : super();
 }
 class B {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.INVALID_CONSTRUCTOR_NAME]);
     // no verify() call, "B" is not resolved
   }
@@ -2923,7 +3051,7 @@
 class A {
   B() : super();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.INVALID_CONSTRUCTOR_NAME]);
     // no verify() call, "B" is not resolved
   }
@@ -2934,7 +3062,7 @@
 class A {
   factory B() {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.INVALID_FACTORY_NAME_NOT_A_CLASS]);
     verify([source]);
@@ -2945,7 +3073,7 @@
 class A {
   factory B() {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.INVALID_FACTORY_NAME_NOT_A_CLASS]);
     // no verify() call, "B" is not resolved
@@ -2956,7 +3084,7 @@
 class A {
   A() async {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.INVALID_MODIFIER_ON_CONSTRUCTOR]);
     verify([source]);
@@ -2967,7 +3095,7 @@
 class A {
   A() async* {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.INVALID_MODIFIER_ON_CONSTRUCTOR]);
     verify([source]);
@@ -2978,7 +3106,7 @@
 class A {
   A() sync* {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.INVALID_MODIFIER_ON_CONSTRUCTOR]);
     verify([source]);
@@ -2989,7 +3117,7 @@
 class A {
   set x(v) async {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER]);
     verify([source]);
   }
@@ -2999,7 +3127,7 @@
 class A {
   set x(v) async* {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER]);
     verify([source]);
   }
@@ -3009,28 +3137,28 @@
 class A {
   set x(v) sync* {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER]);
     verify([source]);
   }
 
   void test_invalidModifierOnSetter_topLevel_async() {
     Source source = addSource("set x(v) async {}");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER]);
     verify([source]);
   }
 
   void test_invalidModifierOnSetter_topLevel_asyncStar() {
     Source source = addSource("set x(v) async* {}");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER]);
     verify([source]);
   }
 
   void test_invalidModifierOnSetter_topLevel_syncStar() {
     Source source = addSource("set x(v) sync* {}");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER]);
     verify([source]);
   }
@@ -3040,7 +3168,7 @@
 class A {
   factory A() { return this; }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.INVALID_REFERENCE_TO_THIS]);
     verify([source]);
   }
@@ -3051,7 +3179,7 @@
   var f;
   A() : f = this;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.INVALID_REFERENCE_TO_THIS]);
     verify([source]);
   }
@@ -3061,7 +3189,7 @@
 class A {
   var f = this;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.INVALID_REFERENCE_TO_THIS]);
     verify([source]);
   }
@@ -3071,7 +3199,7 @@
 class A {
   static m() { return this; }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.INVALID_REFERENCE_TO_THIS]);
     verify([source]);
   }
@@ -3081,7 +3209,7 @@
 class A {
   static A f = this;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.INVALID_REFERENCE_TO_THIS]);
     verify([source]);
   }
@@ -3094,21 +3222,21 @@
 class B extends A {
   B() : super(this);
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.INVALID_REFERENCE_TO_THIS]);
     verify([source]);
   }
 
   void test_invalidReferenceToThis_topLevelFunction() {
     Source source = addSource("f() { return this; }");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.INVALID_REFERENCE_TO_THIS]);
     verify([source]);
   }
 
   void test_invalidReferenceToThis_variableInitializer() {
     Source source = addSource("int x = this;");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.INVALID_REFERENCE_TO_THIS]);
     verify([source]);
   }
@@ -3120,7 +3248,7 @@
     return const <E>[];
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_LIST]);
     verify([source]);
@@ -3133,7 +3261,7 @@
     return const <String, E>{};
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_MAP]);
     verify([source]);
@@ -3141,19 +3269,21 @@
 
   void test_invalidUri_export() {
     Source source = addSource("export 'ht:';");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.INVALID_URI]);
   }
 
   void test_invalidUri_import() {
     Source source = addSource("import 'ht:';");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.INVALID_URI]);
   }
 
   void test_invalidUri_part() {
-    Source source = addSource("part 'ht:';");
-    resolve(source);
+    Source source = addSource(r'''
+library lib;
+part 'ht:';''');
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.INVALID_URI]);
   }
 
@@ -3168,7 +3298,7 @@
 const x = const Foo<int>(const Foo<int>(0, 1),
     const <Foo<String>>[]); // (1)
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS]);
     verify([source]);
@@ -3190,7 +3320,7 @@
   _foo() {
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.IMPLICIT_THIS_REFERENCE_IN_INITIALIZER]);
     verify([source]);
@@ -3207,7 +3337,7 @@
     }
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.LABEL_IN_OUTER_SCOPE]);
     // We cannot verify resolution with unresolvable labels
   }
@@ -3219,7 +3349,7 @@
     break y;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.LABEL_UNDEFINED]);
     // We cannot verify resolution with undefined labels
   }
@@ -3231,7 +3361,7 @@
     continue y;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.LABEL_UNDEFINED]);
     // We cannot verify resolution with undefined labels
   }
@@ -3240,7 +3370,7 @@
     // Attempting to compute the length of constant that couldn't be evaluated
     // (due to an error) should not crash the analyzer (see dartbug.com/23383)
     Source source = addSource("const int i = (1 ? 'alpha' : 'beta').length;");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE,
       CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL,
@@ -3254,7 +3384,7 @@
 class A {
   int A = 0;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.MEMBER_WITH_CLASS_NAME]);
     verify([source]);
   }
@@ -3264,7 +3394,7 @@
 class A {
   int z, A, b = 0;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.MEMBER_WITH_CLASS_NAME]);
     verify([source]);
   }
@@ -3274,7 +3404,7 @@
 class A {
   get A => 0;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.MEMBER_WITH_CLASS_NAME]);
     verify([source]);
   }
@@ -3289,7 +3419,7 @@
   get x => 0;
   x(y) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.METHOD_AND_GETTER_WITH_SAME_NAME]);
     verify([source]);
@@ -3305,7 +3435,7 @@
   }
   return false;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       CompileTimeErrorCode.MISSING_ENUM_CONSTANT_IN_SWITCH,
       CompileTimeErrorCode.MISSING_ENUM_CONSTANT_IN_SWITCH
@@ -3319,7 +3449,7 @@
   A() {}
 }
 class B extends Object with A {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.MIXIN_DECLARES_CONSTRUCTOR]);
     verify([source]);
   }
@@ -3330,7 +3460,7 @@
   A() {}
 }
 class B = Object with A;''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.MIXIN_DECLARES_CONSTRUCTOR]);
     verify([source]);
   }
@@ -3368,7 +3498,7 @@
 class M {}
 class C = B with M;
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.MIXIN_HAS_NO_CONSTRUCTORS]);
     verify([source]);
   }
@@ -3385,7 +3515,7 @@
     // generate a further error (despite the fact that it's not forwarded),
     // since CompileTimeErrorCode.MIXIN_HAS_NO_CONSTRUCTORS does a better job
     // of explaining the probem to the user.
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.MIXIN_HAS_NO_CONSTRUCTORS]);
     verify([source]);
   }
@@ -3404,7 +3534,7 @@
     // error (despite the fact that it's not forwarded), since
     // CompileTimeErrorCode.MIXIN_HAS_NO_CONSTRUCTORS does a better job of
     // explaining the error to the user.
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.MIXIN_HAS_NO_CONSTRUCTORS]);
     verify([source]);
   }
@@ -3423,7 +3553,7 @@
     // error (despite the fact that it's not forwarded), since
     // CompileTimeErrorCode.MIXIN_HAS_NO_CONSTRUCTORS does a better job of
     // explaining the error to the user.
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.MIXIN_HAS_NO_CONSTRUCTORS]);
     verify([source]);
   }
@@ -3442,7 +3572,7 @@
     // further error (despite the fact that it's not forwarded), since
     // CompileTimeErrorCode.MIXIN_HAS_NO_CONSTRUCTORS does a better job of
     // explaining the error to the user.
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.MIXIN_HAS_NO_CONSTRUCTORS]);
     verify([source]);
   }
@@ -3452,7 +3582,7 @@
 class A {}
 class B extends A {}
 class C extends Object with B {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.MIXIN_INHERITS_FROM_NOT_OBJECT]);
     verify([source]);
   }
@@ -3462,7 +3592,7 @@
 class A {}
 class B extends Object with A {}
 class C extends Object with B {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.MIXIN_INHERITS_FROM_NOT_OBJECT]);
     verify([source]);
   }
@@ -3472,7 +3602,7 @@
 class A {}
 class B extends A {}
 class C = Object with B;''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.MIXIN_INHERITS_FROM_NOT_OBJECT]);
     verify([source]);
   }
@@ -3482,49 +3612,49 @@
 class A {}
 class B extends Object with A {}
 class C = Object with B;''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.MIXIN_INHERITS_FROM_NOT_OBJECT]);
     verify([source]);
   }
 
   void test_mixinOfDisallowedClass_class_bool() {
     Source source = addSource("class A extends Object with bool {}");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS]);
     verify([source]);
   }
 
   void test_mixinOfDisallowedClass_class_double() {
     Source source = addSource("class A extends Object with double {}");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS]);
     verify([source]);
   }
 
   void test_mixinOfDisallowedClass_class_int() {
     Source source = addSource("class A extends Object with int {}");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS]);
     verify([source]);
   }
 
   void test_mixinOfDisallowedClass_class_Null() {
     Source source = addSource("class A extends Object with Null {}");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS]);
     verify([source]);
   }
 
   void test_mixinOfDisallowedClass_class_num() {
     Source source = addSource("class A extends Object with num {}");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS]);
     verify([source]);
   }
 
   void test_mixinOfDisallowedClass_class_String() {
     Source source = addSource("class A extends Object with String {}");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS]);
     verify([source]);
   }
@@ -3533,7 +3663,7 @@
     Source source = addSource(r'''
 class A {}
 class C = A with bool;''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS]);
     verify([source]);
   }
@@ -3542,7 +3672,7 @@
     Source source = addSource(r'''
 class A {}
 class C = A with double;''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS]);
     verify([source]);
   }
@@ -3551,7 +3681,7 @@
     Source source = addSource(r'''
 class A {}
 class C = A with int;''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS]);
     verify([source]);
   }
@@ -3560,7 +3690,7 @@
     Source source = addSource(r'''
 class A {}
 class C = A with Null;''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS]);
     verify([source]);
   }
@@ -3569,7 +3699,7 @@
     Source source = addSource(r'''
 class A {}
 class C = A with num;''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS]);
     verify([source]);
   }
@@ -3578,7 +3708,7 @@
     Source source = addSource(r'''
 class A {}
 class C = A with String;''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS]);
     verify([source]);
   }
@@ -3587,7 +3717,7 @@
     Source source = addSource(r'''
 class A {}
 class C = A with String, num;''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS,
       CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS
@@ -3599,7 +3729,7 @@
     Source source = addSource(r'''
 enum E { ONE }
 class A extends Object with E {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.MIXIN_OF_ENUM]);
     verify([source]);
   }
@@ -3608,7 +3738,7 @@
     Source source = addSource(r'''
 int A;
 class B extends Object with A {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.MIXIN_OF_NON_CLASS]);
     verify([source]);
   }
@@ -3618,7 +3748,7 @@
 class A {}
 int B;
 class C = A with B;''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.MIXIN_OF_NON_CLASS]);
     verify([source]);
   }
@@ -3629,7 +3759,7 @@
   toString() => super.toString();
 }
 class B extends Object with A {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.MIXIN_REFERENCES_SUPER]);
     verify([source]);
   }
@@ -3639,7 +3769,7 @@
 int A;
 class B {}
 class C extends A with B {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.MIXIN_WITH_NON_CLASS_SUPERCLASS]);
     verify([source]);
@@ -3650,7 +3780,7 @@
 int A;
 class B {}
 class C = A with B;''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.MIXIN_WITH_NON_CLASS_SUPERCLASS]);
     verify([source]);
@@ -3663,7 +3793,7 @@
   A.a() {}
   A.b() {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source,
         [CompileTimeErrorCode.MULTIPLE_REDIRECTING_CONSTRUCTOR_INVOCATIONS]);
     verify([source]);
@@ -3675,7 +3805,7 @@
 class B extends A {
   B() : super(), super() {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.MULTIPLE_SUPER_INITIALIZERS]);
     verify([source]);
   }
@@ -3685,7 +3815,7 @@
     // error code is generated through the ErrorVerifier, it is not a
     // CompileTimeErrorCode.
     Source source = addSource("class A native 'string' {}");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [ParserErrorCode.NATIVE_CLAUSE_IN_NON_SDK_CODE]);
     verify([source]);
   }
@@ -3695,7 +3825,7 @@
     // error code is generated through the ErrorVerifier, it is not a
     // CompileTimeErrorCode.
     Source source = addSource("int m(a) native 'string';");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [ParserErrorCode.NATIVE_FUNCTION_BODY_IN_NON_SDK_CODE]);
     verify([source]);
@@ -3709,7 +3839,7 @@
 class A{
   static int m(a) native 'string';
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [ParserErrorCode.NATIVE_FUNCTION_BODY_IN_NON_SDK_CODE]);
     verify([source]);
@@ -3723,7 +3853,7 @@
 @A
 main() {
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.NO_ANNOTATION_CONSTRUCTOR_ARGUMENTS]);
     verify([source]);
@@ -3737,7 +3867,7 @@
 class B extends A {
   B() {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_EXPLICIT]);
     verify([source]);
@@ -3755,7 +3885,7 @@
   C(x) : super();
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source,
         [CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INITIALIZER_DEFAULT]);
     verify([source]);
@@ -3773,7 +3903,7 @@
   C();
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source,
         [CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INITIALIZER_DEFAULT]);
     verify([source]);
@@ -3791,7 +3921,7 @@
   C(x) : super.named();
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INITIALIZER]);
     // Don't verify since call to super.named() can't be resolved.
@@ -3809,7 +3939,7 @@
   C();
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source,
         [CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INITIALIZER_DEFAULT]);
     verify([source]);
@@ -3826,7 +3956,7 @@
   C(x) : super();
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source,
         [CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INITIALIZER_DEFAULT]);
     verify([source]);
@@ -3843,7 +3973,7 @@
   C();
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_EXPLICIT]);
     verify([source]);
@@ -3860,7 +3990,7 @@
   C(x) : super.named();
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INITIALIZER]);
     // Don't verify since call to super.named() can't be resolved.
@@ -3877,7 +4007,7 @@
   C();
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_EXPLICIT]);
     verify([source]);
@@ -3893,7 +4023,7 @@
 class Mixed = B with M;
 class C extends Mixed {}
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT]);
     verify([source]);
@@ -3909,7 +4039,7 @@
 class Mixed = B with M;
 class C extends Mixed {}
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT]);
     verify([source]);
@@ -3924,7 +4054,7 @@
 }
 class C extends B with M {}
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT]);
     verify([source]);
@@ -3939,7 +4069,7 @@
 }
 class C extends B with M {}
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT]);
     verify([source]);
@@ -3952,7 +4082,7 @@
 }
 class B extends A {
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT]);
     verify([source]);
@@ -3962,7 +4092,7 @@
     Source source = addSource(r'''
 class A { A.named() {} }
 class B extends A {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT]);
     verify([source]);
@@ -3976,7 +4106,7 @@
 @A.fromInt()
 main() {
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.NON_CONSTANT_ANNOTATION_CONSTRUCTOR]);
     verify([source]);
@@ -3990,7 +4120,7 @@
 @A()
 main() {
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.NON_CONSTANT_ANNOTATION_CONSTRUCTOR]);
     verify([source]);
@@ -4000,7 +4130,7 @@
     Source source = addSource(r'''
 int y;
 f({x : y}) {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE]);
     verify([source]);
   }
@@ -4009,7 +4139,7 @@
     Source source = addSource(r'''
 int y;
 f([x = y]) {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE]);
     verify([source]);
   }
@@ -4020,7 +4150,7 @@
   int y;
   A({x : y}) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE]);
     verify([source]);
   }
@@ -4031,7 +4161,7 @@
   int y;
   A([x = y]) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE]);
     verify([source]);
   }
@@ -4042,7 +4172,7 @@
   int y;
   m({x : y}) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE]);
     verify([source]);
   }
@@ -4053,7 +4183,7 @@
   int y;
   m([x = y]) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE]);
     verify([source]);
   }
@@ -4094,7 +4224,7 @@
       break;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.NON_CONSTANT_CASE_EXPRESSION]);
     verify([source]);
   }
@@ -4142,7 +4272,7 @@
 f(a) {
   return const [a];
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT]);
     verify([source]);
   }
@@ -4184,7 +4314,7 @@
 f() {
   {'a' : 0, 'b' : 1}.length;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.NON_CONST_MAP_AS_EXPRESSION_STATEMENT]);
     verify([source]);
@@ -4195,7 +4325,7 @@
 f() {
   {'a' : 0, 'b' : 1};
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.NON_CONST_MAP_AS_EXPRESSION_STATEMENT]);
     verify([source]);
@@ -4206,7 +4336,7 @@
 f(a) {
   return const {a : 0};
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.NON_CONSTANT_MAP_KEY]);
     verify([source]);
   }
@@ -4248,7 +4378,7 @@
 f(a) {
   return const {'a' : a};
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE]);
     verify([source]);
   }
@@ -4291,7 +4421,7 @@
   final bool a;
   const A(String p) : a = p && true;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL,
       StaticTypeWarningCode.NON_BOOL_OPERAND
@@ -4305,7 +4435,7 @@
   final bool a;
   const A(String p) : a = true && p;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL,
       StaticTypeWarningCode.NON_BOOL_OPERAND
@@ -4319,7 +4449,7 @@
   final int a;
   const A(String p) : a = 5 & p;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       CompileTimeErrorCode.CONST_EVAL_TYPE_INT,
       StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE
@@ -4333,7 +4463,7 @@
   final int a;
   const A(String p) : a = 5 + p;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       CompileTimeErrorCode.CONST_EVAL_TYPE_NUM,
       StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE
@@ -4348,7 +4478,7 @@
   final int a;
   const A() : a = C;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.NON_CONSTANT_VALUE_IN_INITIALIZER]);
     verify([source]);
@@ -4364,7 +4494,7 @@
   final a;
 }
 var b = const B();''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     // TODO(paulberry): the error INVALID_CONSTAT is redundant and ought to be
     // suppressed.
     assertErrors(source, [
@@ -4381,7 +4511,7 @@
   const A.named(p);
   const A() : this.named(C);
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.NON_CONSTANT_VALUE_IN_INITIALIZER]);
     verify([source]);
@@ -4396,7 +4526,7 @@
   static var C;
   const B() : super(C);
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.NON_CONSTANT_VALUE_IN_INITIALIZER]);
     verify([source]);
@@ -4480,7 +4610,7 @@
 class B extends A {
   B() : super.named();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.NON_GENERATIVE_CONSTRUCTOR]);
     verify([source]);
   }
@@ -4493,7 +4623,7 @@
 class B extends A {
   B();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.NON_GENERATIVE_CONSTRUCTOR]);
     verify([source]);
   }
@@ -4505,7 +4635,7 @@
 }
 class B extends A {
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.NON_GENERATIVE_CONSTRUCTOR]);
     verify([source]);
   }
@@ -4518,7 +4648,7 @@
 main() {
   const A();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.NOT_ENOUGH_REQUIRED_ARGUMENTS]);
     verify([source]);
   }
@@ -4531,7 +4661,7 @@
 class B extends A {
   const B() : super();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.NOT_ENOUGH_REQUIRED_ARGUMENTS]);
     verify([source]);
   }
@@ -4541,7 +4671,7 @@
 class A {
   operator +({p}) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.OPTIONAL_PARAMETER_IN_OPERATOR]);
     verify([source]);
   }
@@ -4551,7 +4681,7 @@
 class A {
   operator +([p]) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.OPTIONAL_PARAMETER_IN_OPERATOR]);
     verify([source]);
   }
@@ -4561,11 +4691,227 @@
 library l1;
 part 'l2.dart';''');
     addNamedSource("/l2.dart", "library l2;");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.PART_OF_NON_PART]);
     verify([source]);
   }
 
+  void test_partOfNonPart_self() {
+    Source source = addSource(r'''
+library lib;
+part 'test.dart';''');
+    computeLibrarySourceErrors(source);
+    assertErrors(source, [CompileTimeErrorCode.PART_OF_NON_PART]);
+    verify([source]);
+  }
+
+  void test_prefix_assignment_compound_in_method() {
+    addNamedSource('/lib.dart', 'library lib;');
+    Source source = addSource('''
+import 'lib.dart' as p;
+class C {
+  f() {
+    p += 1;
+  }
+}
+''');
+    computeLibrarySourceErrors(source);
+    assertErrors(
+        source, [CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT]);
+    verify([source]);
+  }
+
+  void test_prefix_assignment_compound_not_in_method() {
+    addNamedSource('/lib.dart', 'library lib;');
+    Source source = addSource('''
+import 'lib.dart' as p;
+f() {
+  p += 1;
+}
+''');
+    computeLibrarySourceErrors(source);
+    assertErrors(
+        source, [CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT]);
+    verify([source]);
+  }
+
+  void test_prefix_assignment_in_method() {
+    addNamedSource('/lib.dart', 'library lib;');
+    Source source = addSource('''
+import 'lib.dart' as p;
+class C {
+  f() {
+    p = 1;
+  }
+}
+''');
+    computeLibrarySourceErrors(source);
+    assertErrors(
+        source, [CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT]);
+    verify([source]);
+  }
+
+  void test_prefix_assignment_not_in_method() {
+    addNamedSource('/lib.dart', 'library lib;');
+    Source source = addSource('''
+import 'lib.dart' as p;
+f() {
+  p = 1;
+}
+''');
+    computeLibrarySourceErrors(source);
+    assertErrors(
+        source, [CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT]);
+    verify([source]);
+  }
+
+  void test_prefix_conditionalPropertyAccess_call() {
+    AnalysisOptionsImpl options = new AnalysisOptionsImpl();
+    options.enableNullAwareOperators = true;
+    resetWithOptions(options);
+    addNamedSource('/lib.dart', '''
+library lib;
+g() {}
+''');
+    Source source = addSource('''
+import 'lib.dart' as p;
+f() {
+  p?.g();
+}
+''');
+    computeLibrarySourceErrors(source);
+    assertErrors(
+        source, [CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT]);
+    verify([source]);
+  }
+
+  void test_prefix_conditionalPropertyAccess_call_loadLibrary() {
+    AnalysisOptionsImpl options = new AnalysisOptionsImpl();
+    options.enableNullAwareOperators = true;
+    resetWithOptions(options);
+    addNamedSource('/lib.dart', '''
+library lib;
+''');
+    Source source = addSource('''
+import 'lib.dart' deferred as p;
+f() {
+  p?.loadLibrary();
+}
+''');
+    computeLibrarySourceErrors(source);
+    assertErrors(
+        source, [CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT]);
+    verify([source]);
+  }
+
+  void test_prefix_conditionalPropertyAccess_get() {
+    AnalysisOptionsImpl options = new AnalysisOptionsImpl();
+    options.enableNullAwareOperators = true;
+    resetWithOptions(options);
+    addNamedSource('/lib.dart', '''
+library lib;
+var x;
+''');
+    Source source = addSource('''
+import 'lib.dart' as p;
+f() {
+  return p?.x;
+}
+''');
+    computeLibrarySourceErrors(source);
+    assertErrors(
+        source, [CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT]);
+    verify([source]);
+  }
+
+  void test_prefix_conditionalPropertyAccess_get_loadLibrary() {
+    AnalysisOptionsImpl options = new AnalysisOptionsImpl();
+    options.enableNullAwareOperators = true;
+    resetWithOptions(options);
+    addNamedSource('/lib.dart', '''
+library lib;
+''');
+    Source source = addSource('''
+import 'lib.dart' deferred as p;
+f() {
+  return p?.loadLibrary;
+}
+''');
+    computeLibrarySourceErrors(source);
+    assertErrors(
+        source, [CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT]);
+    verify([source]);
+  }
+
+  void test_prefix_conditionalPropertyAccess_set() {
+    AnalysisOptionsImpl options = new AnalysisOptionsImpl();
+    options.enableNullAwareOperators = true;
+    resetWithOptions(options);
+    addNamedSource('/lib.dart', '''
+library lib;
+var x;
+''');
+    Source source = addSource('''
+import 'lib.dart' as p;
+f() {
+  p?.x = null;
+}
+''');
+    computeLibrarySourceErrors(source);
+    assertErrors(
+        source, [CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT]);
+    verify([source]);
+  }
+
+  void test_prefix_conditionalPropertyAccess_set_loadLibrary() {
+    AnalysisOptionsImpl options = new AnalysisOptionsImpl();
+    options.enableNullAwareOperators = true;
+    resetWithOptions(options);
+    addNamedSource('/lib.dart', '''
+library lib;
+''');
+    Source source = addSource('''
+import 'lib.dart' deferred as p;
+f() {
+  p?.loadLibrary = null;
+}
+''');
+    computeLibrarySourceErrors(source);
+    assertErrors(
+        source, [CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT]);
+    verify([source]);
+  }
+
+  void test_prefix_unqualified_invocation_in_method() {
+    addNamedSource('/lib.dart', 'librarylib;');
+    Source source = addSource('''
+import 'lib.dart' as p;
+class C {
+  f() {
+    p();
+  }
+}
+''');
+    computeLibrarySourceErrors(source);
+    assertErrors(
+        source, [CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT]);
+    verify([source]);
+  }
+
+  void test_prefix_unqualified_invocation_not_in_method() {
+    addNamedSource('/lib.dart', 'librarylib;');
+    Source source = addSource('''
+import 'lib.dart' as p;
+f() {
+  p();
+}
+''');
+    computeLibrarySourceErrors(source);
+    assertErrors(
+        source, [CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT]);
+    verify([source]);
+  }
+
   void test_prefixCollidesWithTopLevelMembers_functionTypeAlias() {
     addNamedSource("/lib.dart", r'''
 library lib;
@@ -4574,7 +4920,7 @@
 import 'lib.dart' as p;
 typedef p();
 p.A a;''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.PREFIX_COLLIDES_WITH_TOP_LEVEL_MEMBER]);
     verify([source]);
@@ -4588,7 +4934,7 @@
 import 'lib.dart' as p;
 p() {}
 p.A a;''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.PREFIX_COLLIDES_WITH_TOP_LEVEL_MEMBER]);
     verify([source]);
@@ -4602,7 +4948,7 @@
 import 'lib.dart' as p;
 var p = null;
 p.A a;''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.PREFIX_COLLIDES_WITH_TOP_LEVEL_MEMBER]);
     verify([source]);
@@ -4616,15 +4962,63 @@
 import 'lib.dart' as p;
 class p {}
 p.A a;''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.PREFIX_COLLIDES_WITH_TOP_LEVEL_MEMBER]);
     verify([source]);
   }
 
+  void test_prefixNotFollowedByDot() {
+    addNamedSource('/lib.dart', 'library lib;');
+    Source source = addSource('''
+import 'lib.dart' as p;
+f() {
+  return p;
+}
+''');
+    computeLibrarySourceErrors(source);
+    assertErrors(
+        source, [CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT]);
+    verify([source]);
+  }
+
+  void test_prefixNotFollowedByDot_compoundAssignment() {
+    addNamedSource('/lib.dart', 'library lib;');
+    Source source = addSource('''
+import 'lib.dart' as p;
+f() {
+  p += 1;
+}
+''');
+    computeLibrarySourceErrors(source);
+    assertErrors(
+        source, [CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT]);
+    verify([source]);
+  }
+
+  void test_prefixNotFollowedByDot_conditionalMethodInvocation() {
+    AnalysisOptionsImpl options = new AnalysisOptionsImpl();
+    options.enableNullAwareOperators = true;
+    resetWithOptions(options);
+    addNamedSource('/lib.dart', '''
+library lib;
+g() {}
+''');
+    Source source = addSource('''
+import 'lib.dart' as p;
+f() {
+  p?.g();
+}
+''');
+    computeLibrarySourceErrors(source);
+    assertErrors(
+        source, [CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT]);
+    verify([source]);
+  }
+
   void test_privateOptionalParameter() {
     Source source = addSource("f({var _p}) {}");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.PRIVATE_OPTIONAL_PARAMETER]);
     verify([source]);
   }
@@ -4635,14 +5029,14 @@
   var _p;
   A({this._p: 0});
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.PRIVATE_OPTIONAL_PARAMETER]);
     verify([source]);
   }
 
   void test_privateOptionalParameter_withDefaultValue() {
     Source source = addSource("f({_p : 0}) {}");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.PRIVATE_OPTIONAL_PARAMETER]);
     verify([source]);
   }
@@ -4653,7 +5047,7 @@
   const A();
   final m = const A();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.RECURSIVE_COMPILE_TIME_CONSTANT]);
     verify([source]);
@@ -4663,7 +5057,7 @@
     Source source = addSource(r'''
 const x = y + 1;
 const y = x + 1;''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       CompileTimeErrorCode.RECURSIVE_COMPILE_TIME_CONSTANT,
       CompileTimeErrorCode.RECURSIVE_COMPILE_TIME_CONSTANT
@@ -4679,7 +5073,7 @@
   final x;
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.RECURSIVE_COMPILE_TIME_CONSTANT]);
     verify([source]);
@@ -4689,7 +5083,7 @@
     Source source = addSource(r'''
 const x = x;
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.RECURSIVE_COMPILE_TIME_CONSTANT]);
     verify([source]);
@@ -4701,7 +5095,7 @@
   A.a() : this.b();
   A.b() : this.a();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       CompileTimeErrorCode.RECURSIVE_CONSTRUCTOR_REDIRECT,
       CompileTimeErrorCode.RECURSIVE_CONSTRUCTOR_REDIRECT
@@ -4714,7 +5108,7 @@
 class A {
   A() : this();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.RECURSIVE_CONSTRUCTOR_REDIRECT]);
     verify([source]);
   }
@@ -4730,7 +5124,7 @@
 class C implements A {
   factory C() = B;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       CompileTimeErrorCode.RECURSIVE_FACTORY_REDIRECT,
       CompileTimeErrorCode.RECURSIVE_FACTORY_REDIRECT,
@@ -4747,7 +5141,7 @@
 class A {
   factory A() = A;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.RECURSIVE_FACTORY_REDIRECT]);
     verify([source]);
   }
@@ -4764,7 +5158,7 @@
   const C<int>();
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.RECURSIVE_FACTORY_REDIRECT]);
     verify([source]);
   }
@@ -4780,7 +5174,7 @@
 class C<T> implements A<T> {
   factory C() = B;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       CompileTimeErrorCode.RECURSIVE_FACTORY_REDIRECT,
       CompileTimeErrorCode.RECURSIVE_FACTORY_REDIRECT,
@@ -4803,7 +5197,7 @@
 class C implements A {
   factory C.nameC() = B.nameB;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       CompileTimeErrorCode.RECURSIVE_FACTORY_REDIRECT,
       CompileTimeErrorCode.RECURSIVE_FACTORY_REDIRECT,
@@ -4830,7 +5224,7 @@
 class C implements A, B {
   factory C() = B;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       CompileTimeErrorCode.RECURSIVE_FACTORY_REDIRECT,
       CompileTimeErrorCode.RECURSIVE_FACTORY_REDIRECT,
@@ -4844,7 +5238,7 @@
     Source source = addSource(r'''
 class A extends B {}
 class B extends A {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE,
       CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE
@@ -4856,7 +5250,7 @@
     Source source = addSource(r'''
 class A extends B {}
 class B implements A {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE,
       CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE
@@ -4868,7 +5262,7 @@
     Source source = addSource(r'''
 class A implements B {}
 class B implements A {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE,
       CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE
@@ -4880,7 +5274,7 @@
     Source source = addSource(r'''
 class M1 = Object with M2;
 class M2 = Object with M1;''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE,
       CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE
@@ -4892,7 +5286,7 @@
     Source source = addSource(r'''
 abstract class A implements A {}
 class B implements A {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_BASE_CASE_IMPLEMENTS
     ]);
@@ -4904,7 +5298,7 @@
 abstract class A implements B {}
 abstract class B implements A {}
 class C implements A {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE,
       CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE
@@ -4918,7 +5312,7 @@
 abstract class B implements C {}
 abstract class C implements A {}
 class D implements A {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE,
       CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE,
@@ -4929,7 +5323,7 @@
 
   void test_recursiveInterfaceInheritanceBaseCaseExtends() {
     Source source = addSource("class A extends A {}");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_BASE_CASE_EXTENDS
     ]);
@@ -4938,7 +5332,7 @@
 
   void test_recursiveInterfaceInheritanceBaseCaseImplements() {
     Source source = addSource("class A implements A {}");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_BASE_CASE_IMPLEMENTS
     ]);
@@ -4950,7 +5344,7 @@
 class A {}
 class M {}
 class B = A with M implements B;''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_BASE_CASE_IMPLEMENTS
     ]);
@@ -4959,7 +5353,7 @@
 
   void test_recursiveInterfaceInheritanceBaseCaseWith() {
     Source source = addSource("class M = Object with M;");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source,
         [CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_BASE_CASE_WITH]);
     verify([source]);
@@ -4970,7 +5364,7 @@
 class A {
   A() : this.noSuchConstructor();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source,
         [CompileTimeErrorCode.REDIRECT_GENERATIVE_TO_MISSING_CONSTRUCTOR]);
   }
@@ -4981,7 +5375,7 @@
   A() : this.x();
   factory A.x() => null;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       CompileTimeErrorCode.REDIRECT_GENERATIVE_TO_NON_GENERATIVE_CONSTRUCTOR
     ]);
@@ -4996,7 +5390,7 @@
 class B {
   const factory B() = A.name;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.REDIRECT_TO_MISSING_CONSTRUCTOR]);
   }
@@ -5009,7 +5403,7 @@
 class B {
   const factory B() = A;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.REDIRECT_TO_MISSING_CONSTRUCTOR]);
   }
@@ -5020,7 +5414,7 @@
 class B {
   const factory B() = A;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.REDIRECT_TO_NON_CLASS]);
     verify([source]);
   }
@@ -5030,7 +5424,7 @@
 class B {
   const factory B() = A;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.REDIRECT_TO_NON_CLASS]);
     verify([source]);
   }
@@ -5041,7 +5435,7 @@
   A.a() {}
   const factory A.b() = A.a;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.REDIRECT_TO_NON_CONST_CONSTRUCTOR]);
     verify([source]);
@@ -5055,7 +5449,7 @@
   v() {}
 }
 print(x) {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.REFERENCED_BEFORE_DECLARATION]);
   }
 
@@ -5067,7 +5461,7 @@
   var v = 2;
 }
 print(x) {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.REFERENCED_BEFORE_DECLARATION]);
   }
 
@@ -5081,7 +5475,7 @@
   var v = 2;
 }
 print(x) {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.REFERENCED_BEFORE_DECLARATION]);
   }
 
@@ -5090,7 +5484,7 @@
 main() {
   var v = () => v;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.REFERENCED_BEFORE_DECLARATION]);
   }
 
@@ -5099,7 +5493,7 @@
 main() {
   var v = v;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.REFERENCED_BEFORE_DECLARATION]);
   }
 
@@ -5108,7 +5502,7 @@
 f() {
   rethrow;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.RETHROW_OUTSIDE_CATCH]);
     verify([source]);
   }
@@ -5118,7 +5512,7 @@
 class A {
   A() { return 0; }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.RETURN_IN_GENERATIVE_CONSTRUCTOR]);
     verify([source]);
@@ -5129,7 +5523,7 @@
 class A {
   A() => null;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.RETURN_IN_GENERATIVE_CONSTRUCTOR]);
     verify([source]);
@@ -5140,7 +5534,7 @@
 f() async* {
   return 0;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.RETURN_IN_GENERATOR]);
     verify([source]);
   }
@@ -5150,7 +5544,7 @@
 f() sync* {
   return 0;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.RETURN_IN_GENERATOR]);
     verify([source]);
   }
@@ -5173,7 +5567,7 @@
 
   void test_superInInvalidContext_binaryExpression() {
     Source source = addSource("var v = super + 0;");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.SUPER_IN_INVALID_CONTEXT]);
     // no verify(), 'super.v' is not resolved
   }
@@ -5187,7 +5581,7 @@
   var f;
   B() : f = super.m();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.SUPER_IN_INVALID_CONTEXT]);
     // no verify(), 'super.m' is not resolved
   }
@@ -5202,7 +5596,7 @@
     super.m();
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.SUPER_IN_INVALID_CONTEXT]);
     // no verify(), 'super.m' is not resolved
   }
@@ -5215,7 +5609,7 @@
 class B extends A {
  var b = super.a;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.SUPER_IN_INVALID_CONTEXT]);
     // no verify(), 'super.a' is not resolved
   }
@@ -5228,7 +5622,7 @@
 class B extends A {
   static n() { return super.m(); }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.SUPER_IN_INVALID_CONTEXT]);
     // no verify(), 'super.m' is not resolved
   }
@@ -5241,7 +5635,7 @@
 class B extends A {
   static int b = super.a;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.SUPER_IN_INVALID_CONTEXT]);
     // no verify(), 'super.a' is not resolved
   }
@@ -5251,14 +5645,14 @@
 f() {
   super.f();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.SUPER_IN_INVALID_CONTEXT]);
     // no verify(), 'super.f' is not resolved
   }
 
   void test_superInInvalidContext_topLevelVariableInitializer() {
     Source source = addSource("var v = super.y;");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.SUPER_IN_INVALID_CONTEXT]);
     // no verify(), 'super.y' is not resolved
   }
@@ -5270,7 +5664,7 @@
   B() : this.name(), super();
   B.name() {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.SUPER_IN_REDIRECTING_CONSTRUCTOR]);
     verify([source]);
@@ -5283,7 +5677,7 @@
   B() : super(), this.name();
   B.name() {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.SUPER_IN_REDIRECTING_CONSTRUCTOR]);
     verify([source]);
@@ -5296,7 +5690,7 @@
 var s3 = const Symbol();
 var s4 = const Symbol('x', 'y');
 var s5 = const Symbol('x', foo: 'x');''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION,
       CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION,
@@ -5315,7 +5709,7 @@
 main() {
   F foo(G g) => g;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF,
       CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF
@@ -5334,14 +5728,14 @@
 abstract class E extends A<dynamic, F> {}
 typedef D F();
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
 
   void test_typeAliasCannotReferenceItself_parameterType_named() {
     Source source = addSource("typedef A({A a});");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF]);
     verify([source]);
@@ -5349,7 +5743,7 @@
 
   void test_typeAliasCannotReferenceItself_parameterType_positional() {
     Source source = addSource("typedef A([A a]);");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF]);
     verify([source]);
@@ -5357,7 +5751,7 @@
 
   void test_typeAliasCannotReferenceItself_parameterType_required() {
     Source source = addSource("typedef A(A a);");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF]);
     verify([source]);
@@ -5365,7 +5759,7 @@
 
   void test_typeAliasCannotReferenceItself_parameterType_typeArgument() {
     Source source = addSource("typedef A(List<A> a);");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF]);
     verify([source]);
@@ -5379,14 +5773,14 @@
 class C {
   B a;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
 
   void test_typeAliasCannotReferenceItself_returnType() {
     Source source = addSource("typedef A A();");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF]);
     verify([source]);
@@ -5396,7 +5790,7 @@
     Source source = addSource(r'''
 typedef B A();
 typedef A B();''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF,
       CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF
@@ -5406,7 +5800,7 @@
 
   void test_typeAliasCannotReferenceItself_typeVariableBounds() {
     Source source = addSource("typedef A<T extends A>();");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF]);
     verify([source]);
@@ -5420,7 +5814,7 @@
   const G();
 }
 f() { return const G<B>(); }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS]);
     verify([source]);
@@ -5431,7 +5825,7 @@
 f() {
   return const A();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.UNDEFINED_CLASS]);
     verify([source]);
   }
@@ -5442,7 +5836,7 @@
 class B extends A {
   B() : super.named();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INITIALIZER]);
     // no verify(), "super.named()" is not resolved
@@ -5456,7 +5850,7 @@
 class B extends A {
   B() : super();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source,
         [CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INITIALIZER_DEFAULT]);
     verify([source]);
@@ -5470,7 +5864,7 @@
 class B extends A {
   B();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source,
         [CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INITIALIZER_DEFAULT]);
     verify([source]);
@@ -5484,32 +5878,34 @@
 main() {
   const A(p: 0);
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.UNDEFINED_NAMED_PARAMETER]);
     // no verify(), 'p' is not resolved
   }
 
   void test_uriDoesNotExist_export() {
     Source source = addSource("export 'unknown.dart';");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.URI_DOES_NOT_EXIST]);
   }
 
   void test_uriDoesNotExist_import() {
     Source source = addSource("import 'unknown.dart';");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.URI_DOES_NOT_EXIST]);
   }
 
   void test_uriDoesNotExist_part() {
-    Source source = addSource("part 'unknown.dart';");
-    resolve(source);
+    Source source = addSource(r'''
+library lib;
+part 'unknown.dart';''');
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.URI_DOES_NOT_EXIST]);
   }
 
   void test_uriWithInterpolation_constant() {
     Source source = addSource("import 'stuff_\$platform.dart';");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       CompileTimeErrorCode.URI_WITH_INTERPOLATION,
       StaticWarningCode.UNDEFINED_IDENTIFIER
@@ -5522,7 +5918,7 @@
     Source source = addSource(r'''
 library lib;
 part '${'a'}.dart';''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.URI_WITH_INTERPOLATION]);
     // We cannot verify resolution with an unresolvable URI: '${'a'}.dart'
   }
@@ -5550,7 +5946,7 @@
 class A {
   operator -(a, b) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source,
         [CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR_MINUS]);
     verify([source]);
@@ -5564,7 +5960,7 @@
 
   void test_wrongNumberOfParametersForSetter_function_named() {
     Source source = addSource("set x({p}) {}");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_SETTER]);
     verify([source]);
@@ -5572,7 +5968,7 @@
 
   void test_wrongNumberOfParametersForSetter_function_optional() {
     Source source = addSource("set x([p]) {}");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_SETTER]);
     verify([source]);
@@ -5580,7 +5976,7 @@
 
   void test_wrongNumberOfParametersForSetter_function_tooFew() {
     Source source = addSource("set x() {}");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_SETTER]);
     verify([source]);
@@ -5588,7 +5984,7 @@
 
   void test_wrongNumberOfParametersForSetter_function_tooMany() {
     Source source = addSource("set x(a, b) {}");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_SETTER]);
     verify([source]);
@@ -5599,7 +5995,7 @@
 class A {
   set x({p}) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_SETTER]);
     verify([source]);
@@ -5610,7 +6006,7 @@
 class A {
   set x([p]) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_SETTER]);
     verify([source]);
@@ -5621,7 +6017,7 @@
 class A {
   set x() {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_SETTER]);
     verify([source]);
@@ -5632,7 +6028,7 @@
 class A {
   set x(a, b) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_SETTER]);
     verify([source]);
@@ -5644,7 +6040,7 @@
   var yield = 1;
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER]);
     verify([source]);
   }
@@ -5655,7 +6051,7 @@
   var yield = 1;
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER]);
     verify([source]);
   }
@@ -5666,14 +6062,14 @@
   var yield = 1;
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(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);
+    computeLibrarySourceErrors(source);
     if (resolved) {
       assertErrors(source, [CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION]);
       verify([source]);
@@ -5690,7 +6086,7 @@
   final a;
   const A(bool p) : a = $expr;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL,
       StaticTypeWarningCode.NON_BOOL_OPERAND
@@ -5705,7 +6101,7 @@
   final a;
   const A(int p) : a = $expr;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       CompileTimeErrorCode.CONST_EVAL_TYPE_INT,
       StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE
@@ -5720,7 +6116,7 @@
   final a;
   const A(num p) : a = $expr;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       CompileTimeErrorCode.CONST_EVAL_TYPE_NUM,
       StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE
@@ -5735,7 +6131,7 @@
 class A {
   operator $name($parameters) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR]);
     verify([source]);
diff --git a/pkg/analyzer/test/generated/element_test.dart b/pkg/analyzer/test/generated/element_test.dart
index eeee8c4..5bdceca 100644
--- a/pkg/analyzer/test/generated/element_test.dart
+++ b/pkg/analyzer/test/generated/element_test.dart
@@ -48,14 +48,17 @@
     AnalysisContext context = contextHelper.context;
     Source source = contextHelper.addSource("/test.dart", r'''
 class A {}
-class B {}
-enum C {C1, C2, C3}''');
+@deprecated class B {}
+enum C {C1, C2, C3}
+@deprecated enum D {D1, D2, D3}''');
     // prepare CompilationUnitElement
     LibraryElement libraryElement = context.computeLibraryElement(source);
     CompilationUnitElement unitElement = libraryElement.definingCompilationUnit;
     // A
     {
       ClassElement elementA = unitElement.getType("A");
+      expect(elementA.isDeprecated, isFalse);
+      expect(elementA.isEnum, isFalse);
       ClassDeclaration nodeA = elementA.computeNode();
       expect(nodeA, isNotNull);
       expect(nodeA.name.name, "A");
@@ -64,6 +67,8 @@
     // B
     {
       ClassElement elementB = unitElement.getType("B");
+      expect(elementB.isDeprecated, isTrue);
+      expect(elementB.isEnum, isFalse);
       ClassDeclaration nodeB = elementB.computeNode();
       expect(nodeB, isNotNull);
       expect(nodeB.name.name, "B");
@@ -72,11 +77,23 @@
     // C
     {
       ClassElement elementC = unitElement.getEnum("C");
+      expect(elementC.isDeprecated, isFalse);
+      expect(elementC.isEnum, isTrue);
       EnumDeclaration nodeC = elementC.computeNode();
       expect(nodeC, isNotNull);
       expect(nodeC.name.name, "C");
       expect(nodeC.element, same(elementC));
     }
+    // D
+    {
+      ClassElement elementD = unitElement.getEnum("D");
+      expect(elementD.isDeprecated, isTrue);
+      expect(elementD.isEnum, isTrue);
+      EnumDeclaration nodeC = elementD.computeNode();
+      expect(nodeC, isNotNull);
+      expect(nodeC.name.name, "D");
+      expect(nodeC.element, same(elementD));
+    }
   }
 
   void test_computeNode_ClassTypeAlias() {
diff --git a/pkg/analyzer/test/generated/engine_test.dart b/pkg/analyzer/test/generated/engine_test.dart
index 85ffcab..db8c17d 100644
--- a/pkg/analyzer/test/generated/engine_test.dart
+++ b/pkg/analyzer/test/generated/engine_test.dart
@@ -35,6 +35,7 @@
 import 'package:analyzer/src/string_source.dart';
 import 'package:analyzer/src/task/task_dart.dart';
 import 'package:analyzer/task/model.dart' hide AnalysisTask;
+import 'package:html/dom.dart' show Document;
 import 'package:path/path.dart' as pathos;
 import 'package:typed_mock/typed_mock.dart';
 import 'package:unittest/unittest.dart';
@@ -47,30 +48,34 @@
 
 main() {
   groupSep = ' | ';
-  runReflectiveTests(AnalysisCacheTest);
-  runReflectiveTests(AnalysisContextImplTest);
-  runReflectiveTests(AnalysisTaskTest);
-  runReflectiveTests(AnalysisOptionsImplTest);
-  runReflectiveTests(DartEntryTest);
-  runReflectiveTests(GenerateDartErrorsTaskTest);
-  runReflectiveTests(GenerateDartHintsTaskTest);
-  runReflectiveTests(GenerateDartLintsTaskTest);
-  runReflectiveTests(GetContentTaskTest);
-  runReflectiveTests(HtmlEntryTest);
-  runReflectiveTests(IncrementalAnalysisCacheTest);
-  runReflectiveTests(IncrementalAnalysisTaskTest);
-  runReflectiveTests(LintGeneratorTest);
-  runReflectiveTests(ParseDartTaskTest);
-  runReflectiveTests(ParseHtmlTaskTest);
-  runReflectiveTests(PartitionManagerTest);
-  runReflectiveTests(ResolveDartLibraryTaskTest);
-  runReflectiveTests(ResolveDartUnitTaskTest);
-  runReflectiveTests(ResolveHtmlTaskTest);
-  runReflectiveTests(ScanDartTaskTest);
-  runReflectiveTests(SdkCachePartitionTest);
+  // Tests for the classes used in both old and new analysis implementations.
   runReflectiveTests(SourcesChangedEventTest);
-  runReflectiveTests(UniversalCachePartitionTest);
-  runReflectiveTests(WorkManagerTest);
+  // Tests for the classes used in the old analysis implementation.
+  if (!AnalysisEngine.instance.useTaskModel) {
+    runReflectiveTests(AnalysisCacheTest);
+    runReflectiveTests(AnalysisContextImplTest);
+    runReflectiveTests(AnalysisTaskTest);
+    runReflectiveTests(AnalysisOptionsImplTest);
+    runReflectiveTests(DartEntryTest);
+    runReflectiveTests(GenerateDartErrorsTaskTest);
+    runReflectiveTests(GenerateDartHintsTaskTest);
+    runReflectiveTests(GenerateDartLintsTaskTest);
+    runReflectiveTests(GetContentTaskTest);
+    runReflectiveTests(HtmlEntryTest);
+    runReflectiveTests(IncrementalAnalysisCacheTest);
+    runReflectiveTests(IncrementalAnalysisTaskTest);
+    runReflectiveTests(LintGeneratorTest);
+    runReflectiveTests(ParseDartTaskTest);
+    runReflectiveTests(ParseHtmlTaskTest);
+    runReflectiveTests(PartitionManagerTest);
+    runReflectiveTests(ResolveDartLibraryTaskTest);
+    runReflectiveTests(ResolveDartUnitTaskTest);
+    runReflectiveTests(ResolveHtmlTaskTest);
+    runReflectiveTests(ScanDartTaskTest);
+    runReflectiveTests(SdkCachePartitionTest);
+    runReflectiveTests(UniversalCachePartitionTest);
+    runReflectiveTests(WorkManagerTest);
+  }
 }
 
 @reflectiveTest
@@ -5559,6 +5564,7 @@
     return null;
   }
   @override
+  @deprecated
   HtmlElement computeHtmlElement(Source source) {
     fail("Unexpected invocation of computeHtmlElement");
     return null;
@@ -5640,6 +5646,7 @@
     return null;
   }
   @override
+  @deprecated
   HtmlElement getHtmlElement(Source source) {
     fail("Unexpected invocation of getHtmlElement");
     return null;
@@ -5707,6 +5714,7 @@
     return null;
   }
   @override
+  @deprecated
   ht.HtmlUnit getResolvedHtmlUnit(Source htmlSource) {
     fail("Unexpected invocation of getResolvedHtmlUnit");
     return null;
@@ -5737,11 +5745,21 @@
     return false;
   }
   @override
+  Stream<ComputedResult> onResultComputed(ResultDescriptor descriptor) {
+    fail("Unexpected invocation of onResultComputed");
+    return null;
+  }
+  @override
   CompilationUnit parseCompilationUnit(Source source) {
     fail("Unexpected invocation of parseCompilationUnit");
     return null;
   }
   @override
+  Document parseHtmlDocument(Source source) {
+    fail("Unexpected invocation of parseHtmlDocument");
+    return null;
+  }
+  @override
   ht.HtmlUnit parseHtmlUnit(Source source) {
     fail("Unexpected invocation of parseHtmlUnit");
     return null;
@@ -5751,6 +5769,7 @@
     fail("Unexpected invocation of performAnalysisTask");
     return null;
   }
+
   @override
   void recordLibraryElements(Map<Source, LibraryElement> elementMap) {
     fail("Unexpected invocation of recordLibraryElements");
@@ -5776,6 +5795,7 @@
   }
 
   @override
+  @deprecated
   ht.HtmlUnit resolveHtmlUnit(Source htmlSource) {
     fail("Unexpected invocation of resolveHtmlUnit");
     return null;
@@ -5791,12 +5811,23 @@
   void setContents(Source source, String contents) {
     fail("Unexpected invocation of setContents");
   }
-
   @override
   bool shouldErrorsBeAnalyzed(Source source, Object entry) {
     fail("Unexpected invocation of shouldErrorsBeAnalyzed");
     return false;
   }
+
+  @override
+  void test_flushAstStructures(Source source) {
+    fail("Unexpected invocation of test_flushAstStructures");
+  }
+
+  @override
+  bool validateCacheConsistency() {
+    fail("Unexpected invocation of validateCacheConsistency");
+    return false;
+  }
+
   @override
   void visitCacheItems(void callback(Source source, SourceEntry dartEntry,
       DataDescriptor rowDesc, CacheState state)) {
@@ -5849,6 +5880,7 @@
   bool invoked = false;
   TestAnalysisContext_test_computeHtmlElement();
   @override
+  @deprecated
   HtmlElement computeHtmlElement(Source source) {
     invoked = true;
     return null;
@@ -5983,6 +6015,7 @@
   bool invoked = false;
   TestAnalysisContext_test_getHtmlElement();
   @override
+  @deprecated
   HtmlElement getHtmlElement(Source source) {
     invoked = true;
     return null;
@@ -6154,6 +6187,7 @@
   bool invoked = false;
   TestAnalysisContext_test_getResolvedHtmlUnit();
   @override
+  @deprecated
   ht.HtmlUnit getResolvedHtmlUnit(Source htmlSource) {
     invoked = true;
     return null;
@@ -6289,6 +6323,7 @@
   bool invoked = false;
   TestAnalysisContext_test_resolveHtmlUnit();
   @override
+  @deprecated
   ht.HtmlUnit resolveHtmlUnit(Source htmlSource) {
     invoked = true;
     return null;
diff --git a/pkg/analyzer/test/generated/incremental_resolver_test.dart b/pkg/analyzer/test/generated/incremental_resolver_test.dart
index 735a882..54bb524 100644
--- a/pkg/analyzer/test/generated/incremental_resolver_test.dart
+++ b/pkg/analyzer/test/generated/incremental_resolver_test.dart
@@ -2447,7 +2447,7 @@
   void _assertMatchKind(
       DeclarationMatchKind expectMatch, String oldContent, String newContent) {
     Source source = addSource(oldContent);
-    LibraryElement library = resolve(source);
+    LibraryElement library = resolve2(source);
     CompilationUnit oldUnit = resolveCompilationUnit(source, library);
     // parse
     CompilationUnit newUnit = ParserTestCase.parseCompilationUnit(newContent);
@@ -2824,7 +2824,7 @@
     {
       source = addSource(newCode);
       _runTasks();
-      LibraryElement library = resolve(source);
+      LibraryElement library = resolve2(source);
       fullNewUnit = resolveCompilationUnit(source, library);
     }
     try {
@@ -2843,7 +2843,7 @@
   void _resolveUnit(String code) {
     this.code = code;
     source = addSource(code);
-    library = resolve(source);
+    library = resolve2(source);
     unit = resolveCompilationUnit(source, library);
     _runTasks();
   }
@@ -3868,7 +3868,7 @@
   void _resolveUnit(String code) {
     this.code = code;
     source = addSource(code);
-    oldLibrary = resolve(source);
+    oldLibrary = resolve2(source);
     oldUnit = resolveCompilationUnit(source, oldLibrary);
     oldUnitElement = oldUnit.element;
   }
@@ -3908,7 +3908,7 @@
       source = addSource(newCode + ' ');
       source = addSource(newCode);
       _runTasks();
-      LibraryElement library = resolve(source);
+      LibraryElement library = resolve2(source);
       CompilationUnit fullNewUnit = resolveCompilationUnit(source, library);
       // Validate tokens.
       _assertEqualTokens(newUnit, fullNewUnit);
diff --git a/pkg/analyzer/test/generated/non_error_resolver_test.dart b/pkg/analyzer/test/generated/non_error_resolver_test.dart
index 9974fc6..e36ab22 100644
--- a/pkg/analyzer/test/generated/non_error_resolver_test.dart
+++ b/pkg/analyzer/test/generated/non_error_resolver_test.dart
@@ -29,7 +29,7 @@
 E e() {
   return E.TWO;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -45,7 +45,7 @@
     addNamedSource("/lib2.dart", r'''
 library lib2;
 class N {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -63,7 +63,7 @@
 library L2;
 class B {}
 class C {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -81,7 +81,7 @@
 library L2;
 class B {}
 class C {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -94,7 +94,7 @@
     addNamedSource("/lib.dart", r'''
 library lib;
 class N {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -121,7 +121,7 @@
 library lib3;
 class N {}
 class N3 {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
   }
 
@@ -141,7 +141,7 @@
 library lib2;
 class N {}
 class N2 {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
   }
 
@@ -158,7 +158,7 @@
   main() {
     caller(new CallMeBack());
   }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -174,7 +174,7 @@
   E object2;
   TimestampedObject(this.object2);
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -186,7 +186,7 @@
     f(v);
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -197,7 +197,7 @@
 f(A<int> a) {
   a(1);
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -208,7 +208,7 @@
   process(() {});
 }
 process(Object x) {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -221,7 +221,7 @@
   A a = getA();
   a(1, '2');
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -232,7 +232,7 @@
 f(A a) {
   a(1, '2');
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -249,7 +249,7 @@
   F f2 = (() => f());
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -266,7 +266,7 @@
   F f2 = (() => f());
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -277,7 +277,7 @@
   final x = 0;
   -x;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -292,7 +292,7 @@
   A a = new A();
   a.x = 0;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -309,7 +309,7 @@
 main() {
   B.a.x = 0;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -324,7 +324,7 @@
     addNamedSource("/lib1.dart", r'''
 library lib1;
 bool x = false;''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -335,7 +335,7 @@
   return;
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -346,7 +346,7 @@
   return 5;
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -355,7 +355,7 @@
     Source source = addSource('''
 dynamic f() async {}
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -368,7 +368,7 @@
   F f = (int i) async => i;
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -384,7 +384,7 @@
 }
 Future<int> f() => null;
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -396,7 +396,7 @@
   return;
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -408,7 +408,7 @@
   return 5;
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -418,7 +418,7 @@
 import 'dart:async';
 Future<dynamic> f() async {}
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -430,7 +430,7 @@
   return new Future<int>.value(5);
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -442,7 +442,7 @@
   return 5;
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -454,7 +454,7 @@
   return;
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -464,7 +464,7 @@
 import 'dart:async';
 Future<Null> f() async {}
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -476,7 +476,7 @@
   return;
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -488,7 +488,7 @@
   return 5;
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -498,7 +498,7 @@
 import 'dart:async';
 Future<Object> f() async {}
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -510,7 +510,7 @@
   return;
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -522,7 +522,7 @@
   return 5;
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -532,7 +532,7 @@
 import 'dart:async';
 Future f() async {}
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -545,7 +545,7 @@
 }
 Future<Future<int>> g() => null;
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -556,7 +556,7 @@
   return;
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -567,7 +567,7 @@
   return 5;
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -576,7 +576,7 @@
     Source source = addSource('''
 f() async {}
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -587,7 +587,7 @@
   await for (var e in list) {
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -598,7 +598,7 @@
   await for (var e in list) {
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -611,7 +611,7 @@
   int b = await ffi();
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -624,7 +624,7 @@
   int a = await fi();
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -634,7 +634,7 @@
 f(x, y) async {
   return await x + await y;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -644,7 +644,7 @@
 f(x, y) async* {
   yield await x + await y;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -659,7 +659,7 @@
     }
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -669,7 +669,7 @@
 f() {
   dynamic x;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -696,7 +696,7 @@
     }
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -709,7 +709,7 @@
       p = p + 1;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -736,7 +736,7 @@
   case const C(1): print('Switch: 1'); break;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -749,7 +749,7 @@
     default: return 0;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -767,7 +767,7 @@
     default: return 0;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -780,7 +780,7 @@
     default: return 0;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -792,10 +792,10 @@
   A(int p) {}
 }''';
     Source source = addSource(code);
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
-    CompilationUnit unit = analysisContext.parseCompilationUnit(source);
+    CompilationUnit unit = _getResolvedLibraryUnit(source);
     {
       SimpleIdentifier ref = EngineTestCase.findNode(
           unit, code, "p]", (node) => node is SimpleIdentifier);
@@ -810,10 +810,10 @@
 foo(int p) {
 }''';
     Source source = addSource(code);
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
-    CompilationUnit unit = analysisContext.parseCompilationUnit(source);
+    CompilationUnit unit = _getResolvedLibraryUnit(source);
     SimpleIdentifier ref = EngineTestCase.findNode(
         unit, code, "p]", (node) => node is SimpleIdentifier);
     EngineTestCase.assertInstanceOf(
@@ -825,10 +825,10 @@
 /// [p]
 foo(int p) => null;''';
     Source source = addSource(code);
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
-    CompilationUnit unit = analysisContext.parseCompilationUnit(source);
+    CompilationUnit unit = _getResolvedLibraryUnit(source);
     SimpleIdentifier ref = EngineTestCase.findNode(
         unit, code, "p]", (node) => node is SimpleIdentifier);
     EngineTestCase.assertInstanceOf(
@@ -844,10 +844,10 @@
   mb(int p2);
 }''';
     Source source = addSource(code);
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
-    CompilationUnit unit = analysisContext.parseCompilationUnit(source);
+    CompilationUnit unit = _getResolvedLibraryUnit(source);
     {
       SimpleIdentifier ref = EngineTestCase.findNode(
           unit, code, "p1]", (node) => node is SimpleIdentifier);
@@ -869,10 +869,10 @@
   foo() {}
 }''';
     Source source = addSource(code);
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
-    CompilationUnit unit = analysisContext.parseCompilationUnit(source);
+    CompilationUnit unit = _getResolvedLibraryUnit(source);
     SimpleIdentifier ref = EngineTestCase.findNode(
         unit, code, "foo]", (node) => node is SimpleIdentifier);
     EngineTestCase.assertInstanceOf(
@@ -892,10 +892,10 @@
 }
 ''';
     Source source = addSource(code);
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
-    CompilationUnit unit = analysisContext.parseCompilationUnit(source);
+    CompilationUnit unit = _getResolvedLibraryUnit(source);
     {
       SimpleIdentifier ref = EngineTestCase.findNode(
           unit, code, "x] in A", (node) => node is SimpleIdentifier);
@@ -915,7 +915,7 @@
 abstract class A {
   m();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -928,7 +928,7 @@
 class B extends A {
   m();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -941,7 +941,7 @@
 class B extends A {
   get v => 1;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -952,7 +952,7 @@
   static get x => 0;
   static set x(int p) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -963,7 +963,19 @@
   static x() {}
   static set x(int p) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
+  void test_const_constructor_with_named_generic_parameter() {
+    Source source = addSource('''
+class C<T> {
+  const C({T t});
+}
+const c = const C(t: 1);
+''');
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -972,7 +984,7 @@
     Source source = addSource('''
 const Type d = dynamic;
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -985,7 +997,7 @@
 class B extends A {
   const B(): super();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -1001,7 +1013,7 @@
 class C extends A {
   const factory C() = B;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -1014,7 +1026,7 @@
 class B extends A {
   const B(): super();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source,
         [CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INITIALIZER_DEFAULT]);
     verify([source]);
@@ -1026,7 +1038,7 @@
   final int x = 0;
   const A();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -1039,7 +1051,7 @@
 class B extends Object with A {
   const B();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_MIXIN]);
     verify([source]);
   }
@@ -1050,7 +1062,7 @@
   static int x;
   const A();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -1062,7 +1074,7 @@
   set x(value) {}
   get x {return 0;}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -1087,7 +1099,7 @@
     Source source = addSource(r'''
 typedef F();
 const C = F;''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -1099,7 +1111,7 @@
     Source source = addSource(r'''
 import 'math.dart' as math;
 const C = math.PI;''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -1111,7 +1123,7 @@
   static m() {}
 }
 const C = A.m;''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -1123,7 +1135,7 @@
     Source source = addSource(r'''
 const C = #foo;
 foo() {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -1153,7 +1165,7 @@
   const B.n1(num p) : v = p == null;
   const B.n2(num p) : v = null == p;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
   }
 
@@ -1182,7 +1194,7 @@
   const B.n1(num p) : v = p != null;
   const B.n2(num p) : v = null != p;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -1192,7 +1204,7 @@
 const String A = 'a';
 const String B = A + 'b';
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -1214,7 +1226,7 @@
 Map getMap() {
   return const { const C(0): 'Map: 0' };
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -1224,7 +1236,7 @@
 class A {
   static const int x = 0;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -1234,7 +1246,7 @@
 main() {
   const int x = 0;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -1245,7 +1257,7 @@
 class A {
   A(@app int app) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -1256,7 +1268,7 @@
   const A(a, b, c, d);
 }
 f() { return const A(true, 0, 1.0, '2'); }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -1267,7 +1279,7 @@
   static const V = const A<int>();
   const A();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -1280,7 +1292,7 @@
 f() {
   return const A.name();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -1293,28 +1305,28 @@
 f() {
   return const A();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
 
   void test_defaultValueInFunctionTypeAlias() {
     Source source = addSource("typedef F([x]);");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
 
   void test_defaultValueInFunctionTypedParameter_named() {
     Source source = addSource("f(g({p})) {}");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
 
   void test_defaultValueInFunctionTypedParameter_optional() {
     Source source = addSource("f(g([p])) {}");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -1329,7 +1341,7 @@
 class A {}
 @deprecated
 class B {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -1343,14 +1355,14 @@
   'a' : () {},
   'b' : () {}
 };''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
 
   void test_duplicateDefinition_getter() {
     Source source = addSource("bool get a => true;");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -1360,7 +1372,7 @@
 main() {
   var v = dynamic;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -1371,7 +1383,7 @@
 Stream<int> f() async* {
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -1381,7 +1393,7 @@
 Iterable<int> f() sync* {
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -1391,7 +1403,7 @@
 main() {
   <int> [];
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -1401,7 +1413,7 @@
 main() {
   <int, int> {};
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -1411,7 +1423,7 @@
 library L;
 export 'lib1.dart';''');
     addNamedSource("/lib1.dart", "library lib1;");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -1421,7 +1433,7 @@
 library L;
 export 'lib1.dart';''');
     addNamedSource("/lib1.dart", "");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -1432,7 +1444,7 @@
 main() {
   f(1, 2);
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -1442,7 +1454,7 @@
 f(Function a) {
   a(1, 2);
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -1457,7 +1469,7 @@
 void main() {
    B<int> x = new B<int>(0,0);
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -1470,7 +1482,7 @@
   A a = getA();
   a(1, 2);
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -1481,7 +1493,7 @@
 f(A a) {
   a(1, 2);
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -1493,7 +1505,7 @@
   int y;
   A() : x = 0, y = 0 {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -1504,7 +1516,7 @@
   int x = 0;
   A() : x = 1 {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -1515,7 +1527,7 @@
   final int x;
   A() : x = 1 {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -1526,7 +1538,7 @@
   int x;
   A(this.x) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -1537,7 +1549,7 @@
   int x;
   A([this.x]) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -1551,7 +1563,7 @@
   int x;
   B(this.x) : super();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -1562,7 +1574,7 @@
   final x;
   A() : x = 1 {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -1573,7 +1585,7 @@
   final x;
   A(this.x) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -1584,7 +1596,7 @@
   final int x = 0;
   A() {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -1595,7 +1607,7 @@
   final int x = 0;
   A() {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -1606,7 +1618,7 @@
   final Function x;
   A(int this.x(int p)) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -1617,7 +1629,7 @@
   final int x;
   A() {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [ParserErrorCode.NATIVE_CLAUSE_IN_NON_SDK_CODE]);
     verify([source]);
   }
@@ -1627,7 +1639,7 @@
 class A native 'something' {
   final int x;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [ParserErrorCode.NATIVE_CLAUSE_IN_NON_SDK_CODE]);
     verify([source]);
   }
@@ -1638,7 +1650,7 @@
   final int x;
   A() : x = 0 {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -1650,14 +1662,14 @@
   A(this.x);
   A.named() : this (42);
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
 
   void test_functionDeclaration_scope_returnType() {
     Source source = addSource("int f(int) { return 0; }");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -1666,14 +1678,14 @@
     Source source = addSource(r'''
 const app = 0;
 f(@app int app) {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
 
   void test_functionTypeAlias_scope_returnType() {
     Source source = addSource("typedef int f(int);");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -1682,7 +1694,7 @@
     Source source = addSource(r'''
 const app = 0;
 typedef int f(@app int app);''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -1699,14 +1711,14 @@
 }
 class D extends C {
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
 
   void test_functionWithoutCall_doesNotImplementFunction() {
     Source source = addSource("class A {}");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -1718,7 +1730,7 @@
   static call() { }
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -1731,7 +1743,7 @@
     return 42;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -1754,7 +1766,7 @@
   new C2(5);
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -1768,7 +1780,7 @@
   var v;
   B() : v = new A.named();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -1779,7 +1791,7 @@
 class A {
   var v = new abstract.Completer();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -1793,7 +1805,7 @@
   var v;
   B(A a) : v = a.f;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -1807,7 +1819,7 @@
   var v;
   B() : v = new A().f();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -1821,7 +1833,7 @@
   var v;
   B() : v = new A().f;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -1833,7 +1845,7 @@
   A() : v = f;
   static var f;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -1845,7 +1857,7 @@
   A() : v = f;
   static get f => 42;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -1857,7 +1869,7 @@
   A() : v = f();
   static f() => 42;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -1869,7 +1881,7 @@
   A() : v = f;
 }
 var f = 42;''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -1881,7 +1893,7 @@
   A() : v = f();
 }
 f() => 42;''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -1893,7 +1905,7 @@
   A() : v = f;
 }
 get f => 42;''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -1904,7 +1916,7 @@
   var v;
   A(p) : v = (p is T);
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -1915,7 +1927,7 @@
 import 'lib.dart';
 import 'lib.dart';''');
     addNamedSource("/lib.dart", "library lib;");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       HintCode.UNUSED_IMPORT,
       HintCode.UNUSED_IMPORT,
@@ -1932,7 +1944,7 @@
     addNamedSource("/part.dart", r'''
 library lib1;
 class A {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -1943,7 +1955,7 @@
 import 'part.dart';
 A a;''');
     addNamedSource("/part.dart", "class A {}");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -1963,7 +1975,7 @@
     addNamedSource("/lib2.dart", r'''
 library lib2;
 test2() {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -1978,7 +1990,7 @@
       break;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -1992,7 +2004,7 @@
   E get x {return null;}
 }
 class C<E> extends A<E> implements B<E> {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -2008,7 +2020,7 @@
 class C<E> implements A<E>, B<E> {
   E get x => null;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -2027,7 +2039,7 @@
 }
 class A<E> extends B<E> implements D<E> {
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -2043,7 +2055,7 @@
 class C<E> extends A<E> implements B<E> {
   x(E e) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -2059,7 +2071,7 @@
 class C<E> implements A<E>, B<E> {
   x(E e) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -2076,7 +2088,7 @@
 class C extends B<double> implements I<int> {
   num get g => null;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -2093,7 +2105,7 @@
 class C extends B<double> implements I<int> {
   m(num n) => null;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -2110,7 +2122,7 @@
 class C extends B<double> implements I<int> {
   set t(num n) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -2126,7 +2138,7 @@
 class C implements A, B {
   x() {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -2137,7 +2149,7 @@
   int x;
   A(this.x) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -2154,7 +2166,7 @@
 @D(const C())
 f() {}
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -2167,7 +2179,7 @@
 /// [A.m]
 main() {
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -2178,7 +2190,7 @@
 main() {
   m();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -2191,7 +2203,7 @@
   static foo() {
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -2207,7 +2219,7 @@
 class A {
   static var _m;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -2223,7 +2235,7 @@
 class A {
   static _m() {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -2234,7 +2246,7 @@
 class A {
   static const C = 0;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -2250,7 +2262,7 @@
 @p.A.C
 main() {
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -2261,7 +2273,7 @@
 @C
 main() {
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -2275,7 +2287,7 @@
 @p.C
 main() {
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -2291,7 +2303,7 @@
 @p.A(42)
 main() {
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -2307,7 +2319,7 @@
 @p.A.named(42)
 main() {
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -2319,7 +2331,7 @@
   var y;
   x = y;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -2336,7 +2348,7 @@
   byte b = new byte(52);
   b += 3;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -2345,7 +2357,7 @@
     Source source = addSource(r'''
 f({String x: '0'}) {
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -2354,7 +2366,7 @@
     Source source = addSource(r'''
 f([String x = '0']) {
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -2369,7 +2381,7 @@
   n ??= i;
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -2384,7 +2396,7 @@
   j ??= i;
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -2405,7 +2417,7 @@
 }
 typedef int IntToInt(int x);
 IntToInt f = new I();''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -2426,7 +2438,7 @@
 }
 typedef int IntToInt(int x);
 IntToInt f = new C();''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -2445,7 +2457,7 @@
 }
 typedef int IntToInt(int x);
 Function f = new C();''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -2471,7 +2483,7 @@
 }
 typedef int VoidToInt();
 VoidToInt f = new C();''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -2482,7 +2494,7 @@
   var g;
   g = () => 0;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -2492,7 +2504,7 @@
 class A {
   factory A() {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -2506,7 +2518,7 @@
     int yield;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -2519,7 +2531,7 @@
 class B implements A {
   m({int a, int b}) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -2532,7 +2544,7 @@
 class B extends A {
   m({int p : 0}) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -2546,7 +2558,7 @@
 class B extends A {
   thing(String a, {orElse : nothing}) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -2559,7 +2571,7 @@
 class B extends A {
   m([int p = 0]) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -2572,7 +2584,7 @@
 class B extends A {
   m([int b = 0, String a = '0']) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -2586,7 +2598,7 @@
 class B extends A {
   thing(String a, [orElse = nothing]) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -2599,7 +2611,7 @@
 class B extends A {
   m({b, a}) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -2612,7 +2624,7 @@
 class B extends A {
   m(a, [b]) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -2625,7 +2637,7 @@
 class B extends A {
   m(a) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -2638,7 +2650,7 @@
 class B implements A {
   int m() { return 1; }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -2653,7 +2665,7 @@
 class C implements B {
   int m() { return 1; }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -2666,7 +2678,7 @@
 class B extends Object with A {
   int m() { return 1; }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -2679,7 +2691,7 @@
 class B extends A<dynamic> {
   List<dynamic> m() { return new List<dynamic>(); }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -2692,7 +2704,7 @@
 class B extends A {
   int m() { return 1; }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -2705,7 +2717,7 @@
 class B extends A {
   int m() { return 1; }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -2720,7 +2732,7 @@
 class C extends B {
   int m() { return 1; }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -2733,7 +2745,7 @@
 class B extends A {
   int m() { return 0; }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -2745,7 +2757,7 @@
     var v = this;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -2757,7 +2769,7 @@
     var v = this;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -2769,7 +2781,7 @@
     return const <int, int>{};
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -2781,7 +2793,7 @@
     return <E>[];
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -2793,7 +2805,7 @@
     return <String, E>{};
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -2808,7 +2820,7 @@
     f();
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -2822,7 +2834,7 @@
   A a;
   a.g();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -2833,7 +2845,7 @@
   var g;
   g();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -2845,7 +2857,7 @@
   var v = f;
   v();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -2858,7 +2870,7 @@
   v = 1;
   v();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -2869,7 +2881,7 @@
   Object v = null;
   v();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -2887,7 +2899,7 @@
   Functor f = new Functor();
   f();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -2896,7 +2908,7 @@
     Source source = addSource(r'''
 var v1 = <int> [42];
 var v2 = const <int> [42];''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -2920,7 +2932,7 @@
   return () async* { yield 0; };
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -2931,14 +2943,14 @@
   return () sync* { yield 0; };
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
 
   void test_mapKeyTypeNotAssignable() {
     Source source = addSource("var v = <String, int > {'a' : 1};");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -2948,7 +2960,7 @@
 class A {
   set A(v) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -2959,7 +2971,7 @@
 class A {
   foo(@app int app) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -2970,7 +2982,7 @@
   int get x => 0;
   set x(int v) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -2981,7 +2993,7 @@
   get x => 0;
   set x(String v) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -2992,7 +3004,7 @@
   int get x => 0;
   set x(v) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3001,7 +3013,7 @@
     Source source = addSource(r'''
 int get x => 0;
 set x(int v) {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3010,7 +3022,7 @@
     Source source = addSource(r'''
 get x => 0;
 set x(String v) {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3019,7 +3031,7 @@
     Source source = addSource(r'''
 int get x => 0;
 set x(v) {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3035,7 +3047,7 @@
     case E.C: break;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3050,7 +3062,7 @@
     default: break;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3066,7 +3078,7 @@
     return 0;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3077,7 +3089,7 @@
   if (p) return 42;
   // implicit 'return;' is ignored
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3092,7 +3104,7 @@
   }
   // implicit 'return;' is ignored
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3107,7 +3119,7 @@
     return 0;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3118,7 +3130,7 @@
   m() {}
 }
 class B extends Object with A {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3129,7 +3141,7 @@
   factory A() {}
 }
 class B extends Object with A {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3139,7 +3151,7 @@
 class A {}
 class B = Object with A;
 class C extends Object with B {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3149,7 +3161,7 @@
 class A {}
 class B = Object with A;
 class C = Object with B;''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3160,7 +3172,7 @@
 class B extends A {
   B() {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3171,7 +3183,7 @@
 class B extends A {
   B() : super() {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3180,7 +3192,7 @@
     Source source = addSource(r'''
 import 'dart-ext:x';
 int m(a) native 'string';''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     // Cannot verify the AST because the import's URI cannot be resolved.
   }
@@ -3196,7 +3208,7 @@
 A f() {
   return new A();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3209,7 +3221,7 @@
 f() {
   new A.name();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3222,7 +3234,7 @@
 f() {
   new A();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3236,7 +3248,7 @@
   int get g;
 }
 class C extends B {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3250,7 +3262,7 @@
   m(p);
 }
 class C extends B {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3264,7 +3276,7 @@
   set s(v);
 }
 class C extends B {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3278,7 +3290,7 @@
   m();
 }
 abstract class B = A with M implements I;''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3291,7 +3303,7 @@
 }
 abstract class A {}
 abstract class B = A with M;''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3304,7 +3316,7 @@
   m();
 }
 abstract class B = A with M;''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3320,7 +3332,7 @@
 }
 class B extends A with M {}
 class C extends B {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3335,7 +3347,7 @@
 }
 class B extends A with M {}
 class C extends B {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3350,7 +3362,7 @@
 }
 class B extends A with M {}
 class C extends B {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3363,7 +3375,7 @@
 class B extends A {
   noSuchMethod(v) => '';
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3376,7 +3388,7 @@
 class B extends A {
   noSuchMethod(v) => '';
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3387,7 +3399,7 @@
 f() {
   assert(makeAssertion);
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3397,7 +3409,7 @@
 f() {
   assert(true);
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3410,7 +3422,7 @@
   !pb;
   !pd;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3420,7 +3432,7 @@
 bool f(bool left, bool right) {
   return left && right;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3430,7 +3442,7 @@
 bool f(left, dynamic right) {
   return left && right;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3440,7 +3452,7 @@
 bool f(bool left, bool right) {
   return left || right;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3450,21 +3462,21 @@
 bool f(dynamic left, right) {
   return left || right;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
 
   void test_nonConstantDefaultValue_function_named() {
     Source source = addSource("f({x : 2 + 3}) {}");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
 
   void test_nonConstantDefaultValue_function_positional() {
     Source source = addSource("f([x = 2 + 3]) {}");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3474,7 +3486,7 @@
 class A {
   A({x : 2 + 3}) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3484,7 +3496,7 @@
 class A {
   A([x = 2 + 3]) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3494,7 +3506,7 @@
 class A {
   m({x : 2 + 3}) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3504,7 +3516,7 @@
 class A {
   m([x = 2 + 3]) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3518,7 +3530,7 @@
 class B extends A {
   const B({b}) : super(a: b);
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3534,7 +3546,7 @@
       return false;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3544,7 +3556,7 @@
 f() {
   const {'a' : 0, 'b' : 1};
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3554,7 +3566,7 @@
 f() {
   var m = {'a' : 0, 'b' : 1};
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3564,7 +3576,7 @@
 f() {
   <String, int> {'a' : 0, 'b' : 1};
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3578,7 +3590,7 @@
   const A.b1(bool p) : v = p || true;
   const A.b2(bool p) : v = true || p;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.DEAD_CODE]);
     verify([source]);
   }
@@ -3608,7 +3620,7 @@
   const A.j1(p) : v = p % 5;
   const A.j2(p) : v = 5 % p;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     // operations on "p" are not resolved
   }
@@ -3628,7 +3640,7 @@
   const A.e1(int p) : v = p << 5;
   const A.e2(int p) : v = 5 << p;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3658,7 +3670,7 @@
   const A.j1(num p) : v = p % 5;
   const A.j2(num p) : v = 5 % p;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3669,7 +3681,7 @@
   final int a;
   const A() : a = 5;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3680,7 +3692,7 @@
   const A.named(p);
   const A() : this.named(42);
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3693,7 +3705,7 @@
 class B extends A {
   const B() : super(42);
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3706,7 +3718,7 @@
   const A.b(int p) : v = ~p;
   const A.c(num p) : v = -p;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3720,7 +3732,7 @@
 class B extends A {
   B() : super.named();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3732,7 +3744,7 @@
   } on String catch (e) {
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3745,7 +3757,7 @@
   } on F catch (e) {
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3759,7 +3771,7 @@
     }
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3771,7 +3783,7 @@
   } catch (e) {
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3781,7 +3793,7 @@
 class A {
   operator []=(a, b) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3791,21 +3803,21 @@
 class A {
   void operator []=(a, b) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
 
   void test_nonVoidReturnForSetter_function_no() {
     Source source = addSource("set x(v) {}");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
 
   void test_nonVoidReturnForSetter_function_void() {
     Source source = addSource("void set x(v) {}");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3815,7 +3827,7 @@
 class A {
   set x(v) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3825,7 +3837,7 @@
 class A {
   void set x(v) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3835,7 +3847,7 @@
 main() {
   null.m();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
   }
 
@@ -3846,7 +3858,7 @@
   null == 5;
   null[0];
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
   }
 
@@ -3855,7 +3867,7 @@
 class A {
   operator +(p) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3864,7 +3876,7 @@
     // The final "f" should refer to the toplevel function "f", not to the
     // parameter called "f".  See dartbug.com/13179.
     Source source = addSource('void f([void f([x]) = f]) {}');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3880,7 +3892,7 @@
 }
 h(x) {}
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3896,7 +3908,7 @@
 }
 h(x) {}
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3910,7 +3922,7 @@
 }
 h(x) {}
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3926,7 +3938,7 @@
 var p3;
 class p4 {}
 p.A a;''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3937,7 +3949,7 @@
 abstract class B<F> implements A<F>{}
 abstract class C<G, H extends A<G>> {}
 class D<I> extends C<I, B<I>> {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3952,7 +3964,7 @@
   B(S p) : super(p);
   B.named(S p) : super.named(p);
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3970,7 +3982,7 @@
   a++;
   ++a;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
   }
 
@@ -3989,7 +4001,7 @@
     ++a;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
   }
 
@@ -4008,7 +4020,7 @@
 }
 @proxy
 class A {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
   }
 
@@ -4021,7 +4033,7 @@
   new PrefixProxy().foo;
   new PrefixProxy().foo();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
   }
 
@@ -4037,7 +4049,7 @@
     var y = this + this;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
   }
 
@@ -4054,7 +4066,7 @@
 }
 @proxy
 class A {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
   }
 
@@ -4071,7 +4083,7 @@
 }
 @proxy
 class A {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
   }
 
@@ -4088,7 +4100,7 @@
 }
 @proxy
 class A {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
   }
 
@@ -4105,7 +4117,7 @@
 }
 class B implements A{}
 class A implements B{}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     // Test is that a stack overflow isn't reached in resolution
     // (previous line), no need to assert error set.
   }
@@ -4117,7 +4129,7 @@
   A.b() : this.c();
   A.c() {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -4133,7 +4145,7 @@
 class C implements B {
   factory C() {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -4146,7 +4158,7 @@
 class B {
   factory B(int p) = A;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -4159,7 +4171,7 @@
 class B extends A {
   factory B() = A;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -4170,7 +4182,7 @@
   const A.a();
   const factory A.b() = A.a;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -4186,7 +4198,7 @@
   var stream = 123;
   print(stream);
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -4199,7 +4211,7 @@
 f() {
   var x = new A.x();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -4212,7 +4224,7 @@
 f(A a) {
   var x = a.x();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -4225,7 +4237,7 @@
 f(A a) {
   var x = a.x;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -4237,7 +4249,7 @@
     try {} catch (e) {rethrow;}
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -4249,7 +4261,7 @@
   return;
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -4260,7 +4272,7 @@
   return;
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -4270,7 +4282,7 @@
 class A {
   A() { return; }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -4280,7 +4292,7 @@
 f() async {
   return 0;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -4290,7 +4302,7 @@
 f() {
   return 0;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -4303,7 +4315,7 @@
     return 0;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -4322,7 +4334,7 @@
     }
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -4334,7 +4346,7 @@
 }
 class A<T> implements I {
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -4344,7 +4356,7 @@
 class A {}
 class B extends A {}
 A f(B b) { return b; }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -4354,7 +4366,7 @@
 class A {}
 class B extends A {}
 B f(A a) { return a; }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -4374,7 +4386,7 @@
 class Foo<T> {
   Type get t => T;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source);
     verify([source]);
   }
@@ -4389,21 +4401,21 @@
 g1() {}
 void g2() {}
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
 
   void test_returnWithoutValue_noReturnType() {
     Source source = addSource("f() { return; }");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
 
   void test_returnWithoutValue_void() {
     Source source = addSource("void f() { return; }");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -4416,7 +4428,7 @@
 class _InvertedCodec<T2, S2> extends Codec<T2, S2> {
   _InvertedCodec(Codec<S2, T2> codec);
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -4449,7 +4461,7 @@
 @A.name()
 main() {
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -4463,7 +4475,7 @@
   A.m;
   A.m();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -4477,7 +4489,7 @@
   A.f;
   A.f = 1;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -4492,7 +4504,7 @@
   A.f;
   A.f = 1;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -4510,7 +4522,7 @@
     var v = super.m();
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -4521,7 +4533,7 @@
 class B {
   A a;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -4534,7 +4546,7 @@
   const G();
 }
 f() { return const G<B>(); }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -4545,21 +4557,21 @@
 class B extends A {}
 class G<E extends A> {}
 f() { return new G<B>(); }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
 
   void test_typeArgumentNotMatchingBounds_typeArgumentList_0() {
     Source source = addSource("abstract class A<T extends A>{}");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
 
   void test_typeArgumentNotMatchingBounds_typeArgumentList_1() {
     Source source = addSource("abstract class A<T extends A<A>>{}");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -4567,7 +4579,7 @@
   void test_typeArgumentNotMatchingBounds_typeArgumentList_20() {
     Source source = addSource(
         "abstract class A<T extends A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A>>>>>>>>>>>>>>>>>>>>>{}");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -4577,7 +4589,7 @@
 main(Object p) {
   p is String && p.length != 0;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -4588,7 +4600,7 @@
 main(Object p) {
   (p is String) && callMe(() { p.length; });
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -4604,7 +4616,7 @@
 main(A p) {
   (p is C) && (print(() => p) && (p is B)) ? p.mc() : p = null;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -4614,7 +4626,7 @@
 main(Object p) {
   p is String ? p.length : 0;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -4625,7 +4637,7 @@
 main(Object p) {
   p is String ? callMe(() { p.length; }) : 0;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -4641,7 +4653,7 @@
     f(new A());
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -4656,7 +4668,7 @@
     A a = f(new A());
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -4671,7 +4683,7 @@
     A a = f(null);
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -4686,7 +4698,7 @@
     });
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -4705,7 +4717,7 @@
     p.b;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -4718,7 +4730,7 @@
   }
   p = 0;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -4731,7 +4743,7 @@
     p.length;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -4750,7 +4762,7 @@
     p.b;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -4765,7 +4777,7 @@
     p = 0;
   };
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -4778,7 +4790,7 @@
     p.length;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -4791,7 +4803,7 @@
     p.length;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -4810,7 +4822,7 @@
     p.b;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -4822,7 +4834,7 @@
     p.length;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -4834,7 +4846,7 @@
     p.length;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -4847,7 +4859,7 @@
   ((p)) is String ? p.length : 0;
   ((p) is String) ? p.length : 0;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -4859,7 +4871,7 @@
 main() {
   f(C);
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -4874,7 +4886,7 @@
 main() {
   f(p.C);
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -4886,7 +4898,7 @@
 main() {
   f(F);
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -4901,7 +4913,7 @@
 main() {
   f(p.F);
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -4914,7 +4926,7 @@
 class B extends A {
   B() : super.named();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -4927,7 +4939,7 @@
 class B extends A {
   B() : super();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -4940,7 +4952,7 @@
 class B extends A {
   B();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -4953,7 +4965,7 @@
 class B extends A {
   B();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -4965,7 +4977,7 @@
 class B extends A {
   B();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -4979,7 +4991,7 @@
   Bar() : this.ctor();
   Bar.ctor() : super.ctor();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -4994,7 +5006,7 @@
 class A {}
 f() => A?.hashCode;
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -5009,7 +5021,7 @@
     element.last;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -5019,7 +5031,7 @@
 library L;
 export 'lib1.dart' hide a;''');
     addNamedSource("/lib1.dart", "library lib1;");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -5029,7 +5041,7 @@
 library L;
 export 'lib1.dart' show a;''');
     addNamedSource("/lib1.dart", "library lib1;");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -5040,7 +5052,7 @@
 main() {
   print(is String);
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [ParserErrorCode.MISSING_IDENTIFIER]);
   }
 
@@ -5050,7 +5062,7 @@
 main(int p) {
   p.();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [ParserErrorCode.MISSING_IDENTIFIER]);
   }
 
@@ -5059,7 +5071,7 @@
 main() {
   (() => null).call();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     // A call to verify(source) fails as '.call()' isn't resolved.
   }
@@ -5069,7 +5081,7 @@
 main() {
   (() => null)();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     // A call to verify(source) fails as '(() => null)()' isn't resolved.
   }
@@ -5084,7 +5096,7 @@
 class A {}
 f() => A?.toString();
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -5099,7 +5111,7 @@
   a[0];
   a[0] = 1;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -5108,7 +5120,7 @@
     Source source = addSource(r'''
 const A = 3;
 const B = ~((1 << A) - 1);''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -5122,7 +5134,7 @@
 main() {
   x.y = 0;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -5137,7 +5149,7 @@
     super.m();
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -5152,7 +5164,7 @@
     super.m();
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -5166,7 +5178,7 @@
 /// [new A] or [new A.named]
 main() {
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -5174,21 +5186,21 @@
   void test_uriDoesNotExist_dll() {
     addNamedSource("/lib.dll", "");
     Source source = addSource("import 'dart-ext:lib';");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
   }
 
   void test_uriDoesNotExist_dylib() {
     addNamedSource("/lib.dylib", "");
     Source source = addSource("import 'dart-ext:lib';");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
   }
 
   void test_uriDoesNotExist_so() {
     addNamedSource("/lib.so", "");
     Source source = addSource("import 'dart-ext:lib';");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
   }
 
@@ -5215,7 +5227,7 @@
 class A {
   operator []=(a, b) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -5230,7 +5242,7 @@
 class A {
   set x(a) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -5241,7 +5253,7 @@
   yield 3;
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -5253,7 +5265,7 @@
   yield 3;
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -5265,7 +5277,7 @@
   yield 3;
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -5276,7 +5288,7 @@
   yield 3;
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -5288,7 +5300,7 @@
 }
 g() => null;
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -5301,7 +5313,7 @@
 }
 g() => null;
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -5314,7 +5326,7 @@
 }
 g() => null;
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -5327,7 +5339,7 @@
 }
 Stream g() => null;
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -5340,7 +5352,7 @@
 }
 Stream<int> g() => null;
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -5353,7 +5365,7 @@
 }
 Stream<int> g() => null;
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -5365,7 +5377,7 @@
 }
 g() => null;
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -5377,7 +5389,7 @@
 }
 g() => null;
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -5389,7 +5401,7 @@
 }
 g() => null;
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -5401,7 +5413,7 @@
 }
 Iterable g() => null;
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -5413,7 +5425,7 @@
 }
 Iterable<int> g() => null;
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -5425,7 +5437,7 @@
 }
 Iterable<int> g() => null;
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -5436,7 +5448,7 @@
   yield 3;
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -5447,7 +5459,7 @@
   yield 3;
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -5458,7 +5470,7 @@
   yield 3;
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -5469,7 +5481,7 @@
   yield 3;
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -5479,7 +5491,7 @@
 f() async* {
   yield 0;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -5489,7 +5501,7 @@
 f() sync* {
   yield 0;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -5500,7 +5512,7 @@
 class A {
   operator $name($parameters) {}
 }""");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
     reset();
@@ -5509,4 +5521,7 @@
   void _check_wrongNumberOfParametersForOperator1(String name) {
     _check_wrongNumberOfParametersForOperator(name, "a");
   }
+
+  CompilationUnit _getResolvedLibraryUnit(Source source) =>
+      analysisContext.getResolvedCompilationUnit2(source, source);
 }
diff --git a/pkg/analyzer/test/generated/resolver_test.dart b/pkg/analyzer/test/generated/resolver_test.dart
index 5929e06..a796d5e 100644
--- a/pkg/analyzer/test/generated/resolver_test.dart
+++ b/pkg/analyzer/test/generated/resolver_test.dart
@@ -43,9 +43,15 @@
   runReflectiveTests(ScopeTest);
   runReflectiveTests(ElementResolverTest);
   runReflectiveTests(InheritanceManagerTest);
-  runReflectiveTests(LibraryElementBuilderTest);
-  runReflectiveTests(LibraryResolver2Test);
-  runReflectiveTests(LibraryResolverTest);
+  if (!AnalysisEngine.instance.useTaskModel) {
+    runReflectiveTests(LibraryElementBuilderTest);
+  }
+  if (!AnalysisEngine.instance.useTaskModel) {
+    runReflectiveTests(LibraryResolver2Test);
+  }
+  if (!AnalysisEngine.instance.useTaskModel) {
+    runReflectiveTests(LibraryResolverTest);
+  }
   runReflectiveTests(LibraryTest);
   runReflectiveTests(StaticTypeAnalyzerTest);
   runReflectiveTests(StaticTypeAnalyzer2Test);
@@ -589,7 +595,7 @@
   const C(this.a);
 }
 var v = const C(const B());''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -603,7 +609,7 @@
   const A(String this.x);
 }
 var v = const A(null);''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.UNDEFINED_CLASS]);
     verify([source]);
   }
@@ -622,7 +628,7 @@
   const C(this.a);
 }
 var v = const C(const B());''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -634,7 +640,7 @@
   const A(List<int> x);
 }
 var x = const A(const [1, 2, 3]);''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -646,7 +652,7 @@
   const A(List<num> x);
 }
 var x = const A(const <int>[1, 2, 3]);''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -659,7 +665,7 @@
   const A(Map<int, int> x);
 }
 var x = const A(const {1: 2});''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -672,7 +678,7 @@
   const A(Map<num, int> x);
 }
 var x = const A(const <int, int>{1: 2});''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -685,7 +691,7 @@
   const A(Map<int, num> x);
 }
 var x = const A(const <int, int>{1: 2});''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -699,7 +705,7 @@
   const A(this.x);
 }
 var v = const A(5);''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -712,7 +718,7 @@
   const A(this.x);
 }
 var v = const A(null);''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -728,7 +734,7 @@
 }
 foo(x) => 1;
 var v = const A(foo);''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -742,7 +748,7 @@
   const A(this.x);
 }
 var v = const A<int>(3);''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -754,7 +760,7 @@
   const A(this.x);
 }
 var v = const A('foo');''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
       StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE
@@ -778,7 +784,7 @@
   const C(this.b);
 }
 var v = const C(const A());''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH
     ]);
@@ -792,7 +798,7 @@
   const A(String this.x);
 }
 var v = const A('foo');''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
       StaticWarningCode.FIELD_INITIALIZING_FORMAL_NOT_ASSIGNABLE
@@ -807,7 +813,7 @@
   const A(String this.x);
 }
 var v = const A('foo');''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
       StaticWarningCode.UNDEFINED_CLASS
@@ -829,7 +835,7 @@
   const C(this.b);
 }
 var v = const C(const A());''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH
     ]);
@@ -843,7 +849,7 @@
   const A(List<int> x);
 }
 var x = const A(const <num>[1, 2, 3]);''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH
     ]);
@@ -858,7 +864,7 @@
   const A(Map<int, int> x);
 }
 var x = const A(const <num, int>{1: 2});''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH
     ]);
@@ -873,7 +879,7 @@
   const A(Map<int, int> x);
 }
 var x = const A(const <int, num>{1: 2});''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH
     ]);
@@ -887,7 +893,7 @@
   const A([this.x = 'foo']);
 }
 var v = const A();''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
       StaticTypeWarningCode.INVALID_ASSIGNMENT
@@ -906,7 +912,7 @@
 }
 int foo(String x) => 1;
 var v = const A(foo);''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
       StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE
@@ -920,7 +926,7 @@
   final int x;
   const A() : x = '';
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       CheckedModeCompileTimeErrorCode.CONST_FIELD_INITIALIZER_NOT_ASSIGNABLE,
       StaticWarningCode.FIELD_INITIALIZER_NOT_ASSIGNABLE
@@ -935,7 +941,7 @@
   final int y;
 }
 var v = const A('foo');''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_FIELD_TYPE_MISMATCH
     ]);
@@ -951,7 +957,7 @@
 const y = 1;
 var v = const C<String>();
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_FIELD_TYPE_MISMATCH,
       HintCode.INVALID_ASSIGNMENT
@@ -966,7 +972,7 @@
   final Unresolved y;
 }
 var v = const A('foo');''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_FIELD_TYPE_MISMATCH,
       StaticWarningCode.UNDEFINED_CLASS
@@ -983,7 +989,7 @@
 const y = 1;
 var v = const C<int>();
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.INVALID_ASSIGNMENT]);
     verify([source]);
   }
@@ -995,7 +1001,7 @@
   final int y;
 }
 var v = const A(null);''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -1009,14 +1015,14 @@
   final Unresolved y;
 }
 var v = const A(null);''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.UNDEFINED_CLASS]);
     verify([source]);
   }
 
   void test_listElementTypeNotAssignable() {
     Source source = addSource("var v = const <String> [42];");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       CheckedModeCompileTimeErrorCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE,
       StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE
@@ -1026,7 +1032,7 @@
 
   void test_mapKeyTypeNotAssignable() {
     Source source = addSource("var v = const <String, int > {1 : 2};");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       CheckedModeCompileTimeErrorCode.MAP_KEY_TYPE_NOT_ASSIGNABLE,
       StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE
@@ -1036,7 +1042,7 @@
 
   void test_mapValueTypeNotAssignable() {
     Source source = addSource("var v = const <String, String> {'a' : 2};");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       CheckedModeCompileTimeErrorCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE,
       StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE
@@ -1051,7 +1057,7 @@
   const A(int x);
 }
 var v = const A(null);''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -1062,7 +1068,7 @@
   const A(T x);
 }
 var v = const A<int>(3);''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -1075,7 +1081,7 @@
   const A(Unresolved x);
 }
 var v = const A(null);''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.UNDEFINED_CLASS]);
     verify([source]);
   }
@@ -1086,7 +1092,7 @@
   const A(int x);
 }
 var v = const A('foo');''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
       StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE
@@ -1100,7 +1106,7 @@
   const A(T x);
 }
 var v = const A<int>('foo');''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
       StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE
@@ -1114,7 +1120,7 @@
   const A(Unresolved x);
 }
 var v = const A('foo');''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
       StaticWarningCode.UNDEFINED_CLASS
@@ -1129,7 +1135,7 @@
   const A.a2(String x);
 }
 var v = const A.a1(0);''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH
     ]);
@@ -1138,7 +1144,7 @@
 
   void test_topLevelVarAssignable_null() {
     Source source = addSource("const int x = null;");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -1147,14 +1153,14 @@
     // Null always passes runtime type checks, even when the type is
     // unresolved.
     Source source = addSource("const Unresolved x = null;");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.UNDEFINED_CLASS]);
     verify([source]);
   }
 
   void test_topLevelVarNotAssignable() {
     Source source = addSource("const int x = 'foo';");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       CheckedModeCompileTimeErrorCode.VARIABLE_TYPE_MISMATCH,
       StaticTypeWarningCode.INVALID_ASSIGNMENT
@@ -1164,7 +1170,7 @@
 
   void test_topLevelVarNotAssignable_undefined() {
     Source source = addSource("const Unresolved x = 'foo';");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       CheckedModeCompileTimeErrorCode.VARIABLE_TYPE_MISMATCH,
       StaticWarningCode.UNDEFINED_CLASS
@@ -2125,7 +2131,7 @@
     }
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [ResolverErrorCode.BREAK_LABEL_ON_SWITCH_MEMBER]);
     verify([source]);
   }
@@ -2140,7 +2146,7 @@
     }
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [ResolverErrorCode.CONTINUE_LABEL_ON_SWITCH]);
     verify([source]);
   }
@@ -2152,7 +2158,7 @@
     int get x => 0;
   }
 }''');
-    LibraryElement library = resolve(source);
+    LibraryElement library = resolve2(source);
     expect(library, isNotNull);
     var unit = library.definingCompilationUnit;
     expect(unit, isNotNull);
@@ -2186,7 +2192,7 @@
     var two = 2;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.DEAD_CODE]);
     verify([source]);
   }
@@ -2198,21 +2204,21 @@
   throw 'Stop here';
   var two = 2;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.DEAD_CODE]);
     verify([source]);
   }
 
   void fail_isInt() {
     Source source = addSource("var v = 1 is int;");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.IS_INT]);
     verify([source]);
   }
 
   void fail_isNotInt() {
     Source source = addSource("var v = 1 is! int;");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.IS_NOT_INT]);
     verify([source]);
   }
@@ -2222,7 +2228,7 @@
 class A {
   bool operator ==(x) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.OVERRIDE_EQUALS_BUT_NOT_HASH_CODE]);
     verify([source]);
   }
@@ -2240,7 +2246,7 @@
     Source source3 = addNamedSource("/lib2.dart", r'''
 library lib2;
 class B {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.UNUSED_IMPORT]);
     assertNoErrors(source2);
     assertNoErrors(source3);
@@ -2256,7 +2262,7 @@
 class A {
   n(void f(int i)) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]);
     verify([source]);
   }
@@ -2275,7 +2281,7 @@
   n(i);
 }
 n(int i) {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]);
     verify([source]);
   }
@@ -2285,7 +2291,7 @@
 f() {
   true ? 1 : 2;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.DEAD_CODE]);
     verify([source]);
   }
@@ -2296,7 +2302,7 @@
 f() {
   true ? true : false && false;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.DEAD_CODE]);
     verify([source]);
   }
@@ -2306,7 +2312,7 @@
 f() {
   false ? 1 : 2;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.DEAD_CODE]);
     verify([source]);
   }
@@ -2317,7 +2323,7 @@
 f() {
   false ? false && false : true;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.DEAD_CODE]);
     verify([source]);
   }
@@ -2327,7 +2333,7 @@
 f() {
   if(true) {} else {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.DEAD_CODE]);
     verify([source]);
   }
@@ -2338,7 +2344,7 @@
 f() {
   if(true) {} else {if (false) {}}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.DEAD_CODE]);
     verify([source]);
   }
@@ -2348,7 +2354,7 @@
 f() {
   if(false) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.DEAD_CODE]);
     verify([source]);
   }
@@ -2359,7 +2365,7 @@
 f() {
   if(false) {if(false) {}}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.DEAD_CODE]);
     verify([source]);
   }
@@ -2369,7 +2375,7 @@
 f() {
   while(false) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.DEAD_CODE]);
     verify([source]);
   }
@@ -2380,7 +2386,7 @@
 f() {
   while(false) {if(false) {}}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.DEAD_CODE]);
     verify([source]);
   }
@@ -2391,7 +2397,7 @@
 f() {
   try {} catch (e) {} catch (e) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.DEAD_CODE_CATCH_FOLLOWING_CATCH]);
     verify([source]);
   }
@@ -2403,7 +2409,7 @@
 f() {
   try {} catch (e) {} catch (e) {if(false) {}}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.DEAD_CODE_CATCH_FOLLOWING_CATCH]);
     verify([source]);
   }
@@ -2413,7 +2419,7 @@
 f() {
   try {} on Object catch (e) {} catch (e) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.DEAD_CODE_CATCH_FOLLOWING_CATCH]);
     verify([source]);
   }
@@ -2424,7 +2430,7 @@
 f() {
   try {} on Object catch (e) {} catch (e) {if(false) {}}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.DEAD_CODE_CATCH_FOLLOWING_CATCH]);
     verify([source]);
   }
@@ -2436,7 +2442,7 @@
 f() {
   try {} on A catch (e) {} on B catch (e) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.DEAD_CODE_ON_CATCH_SUBTYPE]);
     verify([source]);
   }
@@ -2449,7 +2455,7 @@
 f() {
   try {} on A catch (e) {} on B catch (e) {if(false) {}}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.DEAD_CODE_ON_CATCH_SUBTYPE]);
     verify([source]);
   }
@@ -2459,7 +2465,7 @@
 f() {
   bool b = false && false;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.DEAD_CODE]);
     verify([source]);
   }
@@ -2469,7 +2475,7 @@
 f() {
   bool b = false && (false && false);
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.DEAD_CODE]);
     verify([source]);
   }
@@ -2479,7 +2485,7 @@
 f() {
   bool b = true || true;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.DEAD_CODE]);
     verify([source]);
   }
@@ -2489,7 +2495,7 @@
 f() {
   bool b = true || (false && false);
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.DEAD_CODE]);
     verify([source]);
   }
@@ -2504,7 +2510,7 @@
       var a;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.DEAD_CODE]);
     verify([source]);
   }
@@ -2518,7 +2524,7 @@
     var a;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.DEAD_CODE]);
     verify([source]);
   }
@@ -2531,7 +2537,7 @@
     var a;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.DEAD_CODE]);
     verify([source]);
   }
@@ -2545,7 +2551,7 @@
       var a;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.DEAD_CODE]);
     verify([source]);
   }
@@ -2558,7 +2564,7 @@
     var a;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.DEAD_CODE]);
     verify([source]);
   }
@@ -2572,7 +2578,7 @@
     var a;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.DEAD_CODE]);
     verify([source]);
   }
@@ -2585,7 +2591,7 @@
     var a;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.DEAD_CODE]);
     verify([source]);
   }
@@ -2598,7 +2604,7 @@
     var a;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.DEAD_CODE]);
     verify([source]);
   }
@@ -2610,7 +2616,7 @@
   return;
   var two = 2;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.DEAD_CODE]);
     verify([source]);
   }
@@ -2624,7 +2630,7 @@
     var two = 2;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.DEAD_CODE]);
     verify([source]);
   }
@@ -2638,7 +2644,7 @@
     var two = 2;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.DEAD_CODE]);
     verify([source]);
   }
@@ -2650,7 +2656,7 @@
   return;
   if(false) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.DEAD_CODE]);
     verify([source]);
   }
@@ -2664,7 +2670,7 @@
   return;
   var three = 3;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.DEAD_CODE]);
     verify([source]);
   }
@@ -2679,7 +2685,7 @@
   A b;
   a += b;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.DEPRECATED_MEMBER_USE]);
     verify([source]);
   }
@@ -2691,7 +2697,7 @@
   m() {}
   n() {m();}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.DEPRECATED_MEMBER_USE]);
     verify([source]);
   }
@@ -2703,7 +2709,7 @@
   m() {}
   n() {m();}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.DEPRECATED_MEMBER_USE]);
     verify([source]);
   }
@@ -2714,7 +2720,7 @@
 @deprecated
 library deprecated_library;
 class A {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.DEPRECATED_MEMBER_USE]);
     verify([source]);
   }
@@ -2728,7 +2734,7 @@
 f(A a) {
   return a.m;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.DEPRECATED_MEMBER_USE]);
     verify([source]);
   }
@@ -2741,7 +2747,7 @@
 @deprecated
 library deprecated_library;
 class A {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.DEPRECATED_MEMBER_USE]);
     verify([source]);
   }
@@ -2755,7 +2761,7 @@
 f(A a) {
   return a[1];
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.DEPRECATED_MEMBER_USE]);
     verify([source]);
   }
@@ -2769,7 +2775,7 @@
 f() {
   A a = new A(1);
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.DEPRECATED_MEMBER_USE]);
     verify([source]);
   }
@@ -2783,7 +2789,7 @@
 f() {
   A a = new A.named(1);
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.DEPRECATED_MEMBER_USE]);
     verify([source]);
   }
@@ -2798,7 +2804,7 @@
   A b;
   return a + b;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.DEPRECATED_MEMBER_USE]);
     verify([source]);
   }
@@ -2812,7 +2818,7 @@
 f(A a) {
   return a.s = 1;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.DEPRECATED_MEMBER_USE]);
     verify([source]);
   }
@@ -2826,7 +2832,7 @@
 class B extends A {
   B() : super() {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.DEPRECATED_MEMBER_USE]);
     verify([source]);
   }
@@ -2840,7 +2846,7 @@
 class B extends A {
   B() : super.named() {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.DEPRECATED_MEMBER_USE]);
     verify([source]);
   }
@@ -2850,7 +2856,7 @@
 f(double x, double y) {
   var v = (x / y).toInt();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.DIVISION_OPTIMIZATION]);
     verify([source]);
   }
@@ -2860,7 +2866,7 @@
 f(int x, int y) {
   var v = (x / y).toInt();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.DIVISION_OPTIMIZATION]);
     verify([source]);
   }
@@ -2873,7 +2879,7 @@
   y = 1;
   var v = (x / y).toInt();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.DIVISION_OPTIMIZATION]);
     verify([source]);
   }
@@ -2883,7 +2889,7 @@
 f(int x, int y) {
   var v = (((x / y))).toInt();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.DIVISION_OPTIMIZATION]);
     verify([source]);
   }
@@ -2897,7 +2903,7 @@
     addNamedSource("/lib1.dart", r'''
 library lib1;
 class A {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.DUPLICATE_IMPORT]);
     verify([source]);
   }
@@ -2912,7 +2918,7 @@
     addNamedSource("/lib1.dart", r'''
 library lib1;
 class A {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [HintCode.DUPLICATE_IMPORT, HintCode.DUPLICATE_IMPORT]);
     verify([source]);
@@ -2928,7 +2934,7 @@
 library lib1;
 class A {}
 class B {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.DUPLICATE_IMPORT]);
     verify([source]);
   }
@@ -2957,7 +2963,7 @@
     a.x = y;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.INVALID_ASSIGNMENT]);
     verify([source]);
   }
@@ -2969,7 +2975,7 @@
     int x = y;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.INVALID_ASSIGNMENT]);
     verify([source]);
   }
@@ -2991,7 +2997,7 @@
     A.x = y;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.INVALID_ASSIGNMENT]);
     verify([source]);
   }
@@ -3011,21 +3017,21 @@
   var p2 = new Point(10, 10);
   int n = p1 + p2;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.INVALID_ASSIGNMENT]);
     verify([source]);
   }
 
   void test_isDouble() {
     Source source = addSource("var v = 1 is double;");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.IS_DOUBLE]);
     verify([source]);
   }
 
   void test_isNotDouble() {
     Source source = addSource("var v = 1 is! double;");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.IS_NOT_DOUBLE]);
     verify([source]);
   }
@@ -3035,14 +3041,14 @@
 import 'dart:async';
 Future<int> f() async {}
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.MISSING_RETURN]);
     verify([source]);
   }
 
   void test_missingReturn_function() {
     Source source = addSource("int f() {}");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.MISSING_RETURN]);
     verify([source]);
   }
@@ -3052,7 +3058,7 @@
 class A {
   int m() {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.MISSING_RETURN]);
     verify([source]);
   }
@@ -3067,7 +3073,7 @@
   @override
   int get m => 1;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.OVERRIDE_ON_NON_OVERRIDING_GETTER]);
     verify([source]);
   }
@@ -3082,7 +3088,7 @@
   @override
   int m() => 1;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.OVERRIDE_ON_NON_OVERRIDING_METHOD]);
     verify([source]);
   }
@@ -3097,7 +3103,7 @@
   @override
   set m(int x) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.OVERRIDE_ON_NON_OVERRIDING_SETTER]);
     verify([source]);
   }
@@ -3107,7 +3113,7 @@
 m(i) {
   bool b = i is Null;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.TYPE_CHECK_IS_NULL]);
     verify([source]);
   }
@@ -3117,7 +3123,7 @@
 m(i) {
   bool b = i is! Null;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.TYPE_CHECK_IS_NOT_NULL]);
     verify([source]);
   }
@@ -3130,7 +3136,7 @@
     return a.m;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.UNDEFINED_GETTER]);
   }
 
@@ -3148,7 +3154,7 @@
   var a = 'str';
   a.notAMethodOnString();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.UNDEFINED_METHOD]);
   }
 
@@ -3162,7 +3168,7 @@
     a += a2;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.UNDEFINED_METHOD]);
   }
 
@@ -3174,7 +3180,7 @@
     a + 1;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.UNDEFINED_OPERATOR]);
   }
 
@@ -3186,7 +3192,7 @@
     a[0]++;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.UNDEFINED_OPERATOR]);
   }
 
@@ -3198,7 +3204,7 @@
     a[0];
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.UNDEFINED_OPERATOR]);
   }
 
@@ -3210,7 +3216,7 @@
     a[0] = 1;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.UNDEFINED_OPERATOR]);
   }
 
@@ -3222,7 +3228,7 @@
     a++;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.UNDEFINED_OPERATOR]);
   }
 
@@ -3234,7 +3240,7 @@
     ++a;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.UNDEFINED_OPERATOR]);
   }
 
@@ -3246,7 +3252,7 @@
     a.m = 0;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.UNDEFINED_SETTER]);
   }
 
@@ -3263,7 +3269,7 @@
 m(int i) {
   var b = i as Object;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.UNNECESSARY_CAST]);
     verify([source]);
   }
@@ -3273,21 +3279,21 @@
 m(num i) {
   var b = i as num;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.UNNECESSARY_CAST]);
     verify([source]);
   }
 
   void test_unnecessaryTypeCheck_null_is_Null() {
     Source source = addSource("bool b = null is Null;");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.UNNECESSARY_TYPE_CHECK_TRUE]);
     verify([source]);
   }
 
   void test_unnecessaryTypeCheck_null_not_Null() {
     Source source = addSource("bool b = null is! Null;");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.UNNECESSARY_TYPE_CHECK_FALSE]);
     verify([source]);
   }
@@ -3297,7 +3303,7 @@
 m(i) {
   bool b = i is dynamic;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.UNNECESSARY_TYPE_CHECK_TRUE]);
     verify([source]);
   }
@@ -3307,7 +3313,7 @@
 m(i) {
   bool b = i is Object;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.UNNECESSARY_TYPE_CHECK_TRUE]);
     verify([source]);
   }
@@ -3317,7 +3323,7 @@
 m(i) {
   bool b = i is! dynamic;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.UNNECESSARY_TYPE_CHECK_FALSE]);
     verify([source]);
   }
@@ -3327,7 +3333,7 @@
 m(i) {
   bool b = i is! Object;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.UNNECESSARY_TYPE_CHECK_FALSE]);
     verify([source]);
   }
@@ -3338,7 +3344,7 @@
 class _A {}
 class B extends _A {}
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3349,7 +3355,7 @@
 class _A {}
 class B implements _A {}
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3361,7 +3367,7 @@
 main() {
   new _A();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3375,7 +3381,7 @@
 main() {
   _A.F;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3389,7 +3395,7 @@
 main() {
   _A.m();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3402,7 +3408,7 @@
   var v = new List<_A>();
   print(v);
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3419,7 +3425,7 @@
   }
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.UNUSED_ELEMENT]);
     verify([source]);
   }
@@ -3432,7 +3438,7 @@
   _A.named() {}
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.UNUSED_ELEMENT]);
     verify([source]);
   }
@@ -3446,7 +3452,7 @@
   }
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.UNUSED_ELEMENT]);
     verify([source]);
   }
@@ -3457,7 +3463,7 @@
 class _A {}
 main() {
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.UNUSED_ELEMENT]);
     verify([source]);
   }
@@ -3472,7 +3478,7 @@
 }
 print(x) {}
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.UNUSED_ELEMENT]);
     verify([source]);
   }
@@ -3484,7 +3490,7 @@
 main() {
   print(_MyEnum.B);
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3495,7 +3501,7 @@
 enum _MyEnum {A, B, C}
 main() {
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.UNUSED_ELEMENT]);
     verify([source]);
   }
@@ -3508,7 +3514,7 @@
 }
 print(x) {}
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3520,7 +3526,7 @@
   f() {}
   f();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3534,7 +3540,7 @@
 }
 print(x) {}
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3545,7 +3551,7 @@
 main() {
   f() {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.UNUSED_ELEMENT]);
     verify([source]);
   }
@@ -3558,7 +3564,7 @@
     _f(p - 1);
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.UNUSED_ELEMENT]);
     verify([source]);
   }
@@ -3570,7 +3576,7 @@
 main() {
   _f();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3584,7 +3590,7 @@
 }
 print(x) {}
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3595,7 +3601,7 @@
 _f() {}
 main() {
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.UNUSED_ELEMENT]);
     verify([source]);
   }
@@ -3608,7 +3614,7 @@
 }
 main() {
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.UNUSED_ELEMENT]);
     verify([source]);
   }
@@ -3622,7 +3628,7 @@
     print('F');
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3633,7 +3639,7 @@
 typedef _F(a, b);
 main(_F f) {
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3646,7 +3652,7 @@
   var v = new List<_F>();
   print(v);
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3658,7 +3664,7 @@
 class A {
   _F f;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3669,7 +3675,7 @@
 typedef _F(a, b);
 main() {
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.UNUSED_ELEMENT]);
     verify([source]);
   }
@@ -3683,7 +3689,7 @@
     var v = _g;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3698,7 +3704,7 @@
   var v = a._g;
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3713,7 +3719,7 @@
   var v = new A()._g;
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3724,7 +3730,7 @@
 class A {
   get _g => null;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.UNUSED_ELEMENT]);
     verify([source]);
   }
@@ -3737,7 +3743,7 @@
     return _g;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.UNUSED_ELEMENT]);
     verify([source]);
   }
@@ -3753,7 +3759,7 @@
 }
 print(x) {}
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3772,7 +3778,7 @@
 }
 print(x) {}
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3786,7 +3792,7 @@
 main(A a) {
   a._m;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3800,7 +3806,7 @@
 main() {
   new A()._m;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3814,7 +3820,7 @@
     _m();
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3831,7 +3837,7 @@
 class B extends A {
   _m() {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3845,7 +3851,7 @@
 main(A<int> a) {
   a._m(0);
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3860,7 +3866,7 @@
   var a = new A();
   a._m();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3875,7 +3881,7 @@
   A a = new A();
   a._m();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3892,7 +3898,7 @@
 main(A a) {
   a._m();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3905,7 +3911,7 @@
 }
 main() {
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3919,7 +3925,7 @@
 main() {
   A._m();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3930,7 +3936,7 @@
 class A {
   static _m() {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.UNUSED_ELEMENT]);
     verify([source]);
   }
@@ -3943,7 +3949,7 @@
     _m(p - 1);
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.UNUSED_ELEMENT]);
     verify([source]);
   }
@@ -3957,7 +3963,7 @@
     _s = 42;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3972,7 +3978,7 @@
   a._s = 42;
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3987,7 +3993,7 @@
   new A()._s = 42;
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -3998,7 +4004,7 @@
 class A {
   set _s(x) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.UNUSED_ELEMENT]);
     verify([source]);
   }
@@ -4013,7 +4019,7 @@
     }
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.UNUSED_ELEMENT]);
     verify([source]);
   }
@@ -4028,7 +4034,7 @@
   }
 }
 print(x) {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source);
     verify([source]);
   }
@@ -4043,7 +4049,7 @@
   }
 }
 print(x) {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source);
     verify([source]);
   }
@@ -4055,7 +4061,7 @@
   int _f;
   m() => _f;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source);
     verify([source]);
   }
@@ -4073,7 +4079,7 @@
   int _f;
 }
 print(x) {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source);
     verify([source]);
   }
@@ -4089,7 +4095,7 @@
   print(a._f);
 }
 print(x) {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source);
     verify([source]);
   }
@@ -4105,7 +4111,7 @@
   print(a._f);
 }
 print(x) {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source);
     verify([source]);
   }
@@ -4120,7 +4126,7 @@
   print(a._f);
 }
 print(x) {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source);
     verify([source]);
   }
@@ -4134,7 +4140,7 @@
     _f += 2;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.UNUSED_FIELD]);
     verify([source]);
   }
@@ -4146,7 +4152,7 @@
   int _f;
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.UNUSED_FIELD]);
     verify([source]);
   }
@@ -4160,7 +4166,7 @@
     _f++;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.UNUSED_FIELD]);
     verify([source]);
   }
@@ -4174,7 +4180,7 @@
     ++_f;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.UNUSED_FIELD]);
     verify([source]);
   }
@@ -4192,7 +4198,7 @@
   a._f = 2;
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.UNUSED_FIELD]);
     verify([source]);
   }
@@ -4202,7 +4208,7 @@
 library L;
 import 'lib1.dart';''');
     Source source2 = addNamedSource("/lib1.dart", "library lib1;");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.UNUSED_IMPORT]);
     assertNoErrors(source2);
     verify([source, source2]);
@@ -4217,7 +4223,7 @@
     Source source2 = addNamedSource("/lib1.dart", r'''
 library lib1;
 class A {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.UNUSED_IMPORT]);
     assertNoErrors(source2);
     verify([source, source2]);
@@ -4232,7 +4238,7 @@
     Source source2 = addNamedSource("/lib1.dart", r'''
 library lib1;
 class A {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.UNUSED_IMPORT]);
     assertNoErrors(source2);
     verify([source, source2]);
@@ -4248,7 +4254,7 @@
 library lib1;
 class A {}
 class B {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.UNUSED_IMPORT]);
     assertNoErrors(source2);
     verify([source, source2]);
@@ -4262,7 +4268,7 @@
   } on String catch (exception) {
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.UNUSED_CATCH_CLAUSE]);
     verify([source]);
   }
@@ -4276,7 +4282,7 @@
     print(stack);
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -4289,7 +4295,7 @@
   } catch (exception) {
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -4302,7 +4308,7 @@
   } catch (exception, stackTrace) {
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.UNUSED_CATCH_STACK]);
     verify([source]);
   }
@@ -4317,7 +4323,7 @@
   }
 }
 print(x) {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source);
     verify([source]);
   }
@@ -4332,7 +4338,7 @@
     }
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source);
     verify([source]);
   }
@@ -4344,7 +4350,7 @@
   var v = 1;
   v = 2;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.UNUSED_LOCAL_VARIABLE]);
     verify([source]);
   }
@@ -4358,7 +4364,7 @@
     v = 2;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.UNUSED_LOCAL_VARIABLE]);
     verify([source]);
   }
@@ -4371,7 +4377,7 @@
   Foo foo;
   foo();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source);
     verify([source]);
   }
@@ -4383,7 +4389,7 @@
   var v = 1;
   v += 2;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.UNUSED_LOCAL_VARIABLE]);
     verify([source]);
   }
@@ -4395,7 +4401,7 @@
   var v = 1;
   v++;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.UNUSED_LOCAL_VARIABLE]);
     verify([source]);
   }
@@ -4407,7 +4413,7 @@
   var v = 1;
   ++v;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.UNUSED_LOCAL_VARIABLE]);
     verify([source]);
   }
@@ -4420,7 +4426,7 @@
   print(++v);
 }
 print(x) {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source);
     verify([source]);
   }
@@ -4436,7 +4442,7 @@
   a.foo();
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source);
     verify([source]);
   }
@@ -4450,7 +4456,7 @@
     a = f();
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.USE_OF_VOID_RESULT]);
     verify([source]);
   }
@@ -4464,7 +4470,7 @@
     a = m();
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.USE_OF_VOID_RESULT]);
     verify([source]);
   }
@@ -4477,7 +4483,7 @@
     for(var a = m();;) {}
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.USE_OF_VOID_RESULT]);
     verify([source]);
   }
@@ -4490,7 +4496,7 @@
     var a = f();
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.USE_OF_VOID_RESULT]);
     verify([source]);
   }
@@ -4503,7 +4509,7 @@
     var a = m();
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [HintCode.USE_OF_VOID_RESULT]);
     verify([source]);
   }
@@ -4516,7 +4522,7 @@
     var a = m(), b = m();
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [HintCode.USE_OF_VOID_RESULT, HintCode.USE_OF_VOID_RESULT]);
     verify([source]);
@@ -6454,7 +6460,7 @@
 f() {
   DEBUG ? 1 : 2;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -6465,7 +6471,7 @@
 f() {
   DEBUG ? 1 : 2;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -6476,7 +6482,7 @@
 f() {
   if(DEBUG) {} else {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -6489,7 +6495,7 @@
 f() {
   if(A.DEBUG) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -6506,7 +6512,7 @@
 class A {
   static const bool DEBUG = false;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -6523,7 +6529,7 @@
 class A {
   static const bool DEBUG = false;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -6534,7 +6540,7 @@
 f() {
   if(DEBUG) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -6545,7 +6551,7 @@
 f() {
   while(DEBUG) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -6557,7 +6563,7 @@
 f() {
   try {} on B catch (e) {} on A catch (e) {} catch (e) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -6568,7 +6574,7 @@
 f() {
   bool b = DEBUG && false;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -6579,7 +6585,7 @@
 f() {
   bool b = DEBUG || true;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -6589,7 +6595,7 @@
 f(int x, int y) {
   var v = x / y.toInt();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -6599,7 +6605,7 @@
 f(x, y) {
   var v = (x / y).toInt();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -6612,7 +6618,7 @@
 f(A x, A y) {
   var v = (x / y).toInt();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -6627,7 +6633,7 @@
     addNamedSource("/lib1.dart", r'''
 library lib1;
 class A {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -6643,7 +6649,7 @@
 library lib1;
 class A {}
 class B {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -6659,7 +6665,7 @@
 library lib1;
 class A {}
 class B {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -6685,7 +6691,7 @@
   }
   int s = message;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -6702,7 +6708,7 @@
   }
   int s = message;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -6718,7 +6724,7 @@
   }
   String s = message;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -6728,28 +6734,28 @@
 abstract class A {
   int m();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
 
   void test_missingReturn_expressionFunctionBody() {
     Source source = addSource("int f() => 0;");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
 
   void test_missingReturn_noReturnType() {
     Source source = addSource("f() {}");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
 
   void test_missingReturn_voidReturnType() {
     Source source = addSource("void f() {}");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -6760,7 +6766,7 @@
   bool operator ==(x) { return x; }
   get hashCode => 0;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -6776,7 +6782,7 @@
   @override
   int get m => 1;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -6792,7 +6798,7 @@
   @override
   int get m => 1;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -6808,7 +6814,7 @@
   @override
   int m() => 1;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -6824,7 +6830,7 @@
   @override
   int m() => 1;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -6840,7 +6846,7 @@
   @override
   set m(int x) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -6856,7 +6862,7 @@
   @override
   set m(int x) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -6873,7 +6879,7 @@
     y.x.add(new A());
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -6892,7 +6898,7 @@
   a++;
   ++a;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
   }
 
@@ -6912,7 +6918,7 @@
     ++a;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
   }
 
@@ -6932,7 +6938,7 @@
 }
 @proxy
 class A {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
   }
 
@@ -6947,7 +6953,7 @@
     return a.b;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
   }
 
@@ -6962,7 +6968,7 @@
   a2 = new A();
   a += a2;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
   }
 
@@ -6972,7 +6978,7 @@
   fieldAccess(T t) => t.abc;
   methodAccess(T t) => t.xyz(1, 2, 'three');
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
   }
 
@@ -6986,7 +6992,7 @@
   var a = new A();
   a.b();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
   }
 
@@ -7007,7 +7013,7 @@
   }
   ab.m();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
   }
 
@@ -7026,7 +7032,7 @@
   }
   ab.m(0);
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
   }
 
@@ -7041,7 +7047,7 @@
     a + 1;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
   }
 
@@ -7056,7 +7062,7 @@
     a[0]++;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
   }
 
@@ -7071,7 +7077,7 @@
     a[0];
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
   }
 
@@ -7086,7 +7092,7 @@
     a[0] = 1;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
   }
 
@@ -7101,7 +7107,7 @@
     a++;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
   }
 
@@ -7116,7 +7122,7 @@
     ++a;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
   }
 
@@ -7131,7 +7137,7 @@
     a.b = 0;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
   }
 
@@ -7147,7 +7153,7 @@
     (e as A).a();
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -7160,7 +7166,7 @@
 I m(A a, B b) {
   return a == null ? b as I : a as I;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -7170,7 +7176,7 @@
 m(v) {
   var b = v as Object;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -7183,7 +7189,7 @@
 void g(bool c) {
   (c ? f(): new Future.value(0) as Future<int>).then((int value) {});
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -7193,7 +7199,7 @@
 m(v) {
   var b = Object as dynamic;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -7208,7 +7214,7 @@
 class A {
   const A() {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source);
     verify([source, source2]);
   }
@@ -7227,7 +7233,7 @@
     Source source3 = addNamedSource("/lib2.dart", r'''
 library lib2;
 class B {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source);
     assertNoErrors(source2);
     assertNoErrors(source3);
@@ -7238,7 +7244,7 @@
     Source source = addSource(r'''
 library L;
 import 'dart:core';''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -7255,7 +7261,7 @@
     addNamedSource("/lib2.dart", r'''
 library lib2;
 class Two {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -7276,7 +7282,7 @@
     addNamedSource("/lib3.dart", r'''
 library lib3;
 class Three {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -7298,7 +7304,7 @@
 library lib3;
 export 'lib2.dart';
 class Three {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -7315,7 +7321,7 @@
     addNamedSource("/lib1.dart", r'''
 library lib1;
 const x = 0;''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -7335,7 +7341,7 @@
 library lib1;
 class One {}
 topLevelFunction() {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -7348,7 +7354,7 @@
     var a = f();
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -7359,7 +7365,7 @@
 g() {
   var a = f();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -7368,13 +7374,13 @@
 class PubSuggestionCodeTest extends ResolverTestCase {
   void test_import_package() {
     Source source = addSource("import 'package:somepackage/other.dart';");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [CompileTimeErrorCode.URI_DOES_NOT_EXIST]);
   }
 
   void test_import_packageWithDotDot() {
     Source source = addSource("import 'package:somepackage/../other.dart';");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       CompileTimeErrorCode.URI_DOES_NOT_EXIST,
       HintCode.PACKAGE_IMPORT_CONTAINS_DOT_DOT
@@ -7383,7 +7389,7 @@
 
   void test_import_packageWithLeadingDotDot() {
     Source source = addSource("import 'package:../other.dart';");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       CompileTimeErrorCode.URI_DOES_NOT_EXIST,
       HintCode.PACKAGE_IMPORT_CONTAINS_DOT_DOT
@@ -7395,7 +7401,7 @@
     cacheSource("/myproj/lib/other.dart", "");
     Source source =
         addNamedSource("/myproj/web/test.dart", "import '../lib/other.dart';");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [HintCode.FILE_IMPORT_OUTSIDE_LIB_REFERENCES_FILE_INSIDE]);
   }
@@ -7404,7 +7410,7 @@
     cacheSource("/myproj/lib/other.dart", "");
     Source source =
         addNamedSource("/myproj/web/test.dart", "import '../lib/other.dart';");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
   }
 
@@ -7413,7 +7419,7 @@
     cacheSource("/myproj/web/other.dart", "");
     Source source =
         addNamedSource("/myproj/lib/test.dart", "import '../web/other.dart';");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [HintCode.FILE_IMPORT_INSIDE_LIB_REFERENCES_FILE_OUTSIDE]);
   }
@@ -7422,7 +7428,7 @@
     cacheSource("/myproj/web/other.dart", "");
     Source source =
         addNamedSource("/myproj/lib/test.dart", "import '../web/other.dart';");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
   }
 
@@ -7431,7 +7437,7 @@
     cacheSource("/myproj/lib/other.dart", "");
     Source source =
         addNamedSource("/myproj/lib/test.dart", "import 'other.dart';");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
   }
 
@@ -7440,7 +7446,7 @@
     cacheSource("/myproj/lib/bar/other.dart", "");
     Source source = addNamedSource(
         "/myproj/lib/foo/test.dart", "import '../bar/other.dart';");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
   }
 
@@ -7449,7 +7455,7 @@
     cacheSource("/myproj/web/other.dart", "");
     Source source =
         addNamedSource("/myproj/lib2/test.dart", "import '../web/other.dart';");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
   }
 }
@@ -7830,6 +7836,15 @@
   }
 
   /**
+   * Computes errors for the given [librarySource].
+   * This assumes that the given [librarySource] and its parts have already
+   * been added to the content provider using the method [addNamedSource].
+   */
+  void computeLibrarySourceErrors(Source librarySource) {
+    analysisContext.computeErrors(librarySource);
+  }
+
+  /**
    * Create a library element that represents a library named `"test"` containing a single
    * empty compilation unit.
    *
@@ -7926,7 +7941,7 @@
    * @return the element representing the resolved library
    * @throws AnalysisException if the analysis could not be performed
    */
-  LibraryElement resolve(Source librarySource) =>
+  LibraryElement resolve2(Source librarySource) =>
       analysisContext2.computeLibraryElement(librarySource);
 
   /**
@@ -8133,7 +8148,7 @@
   new C().x += 1;
 }
 ''');
-    LibraryElement library = resolve(source);
+    LibraryElement library = resolve2(source);
     assertNoErrors(source);
     verify([source]);
     // Verify that both the getter and setter for "x" in "new C().x" refer to
@@ -8161,7 +8176,7 @@
     A.g(1,0);
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -8274,7 +8289,7 @@
 class A {
   set sss(x) {}
 }''');
-    LibraryElement library = resolve(source);
+    LibraryElement library = resolve2(source);
     CompilationUnitElement unit = library.definingCompilationUnit;
     // find "a.sss = 0"
     AssignmentExpression assignment;
@@ -8310,7 +8325,7 @@
 class B {
   set sss(x) {}
 }''');
-    LibraryElement library = resolve(source);
+    LibraryElement library = resolve2(source);
     CompilationUnitElement unit = library.definingCompilationUnit;
     // find "a.b.sss = 0"
     AssignmentExpression assignment;
@@ -8343,7 +8358,7 @@
 class A {
   set sss(x) {}
 }''');
-    LibraryElement library = resolve(source);
+    LibraryElement library = resolve2(source);
     CompilationUnitElement unit = library.definingCompilationUnit;
     // find "a.sss = 0"
     AssignmentExpression assignment;
@@ -8378,7 +8393,7 @@
 class B {
   set sss(x) {}
 }''');
-    LibraryElement library = resolve(source);
+    LibraryElement library = resolve2(source);
     CompilationUnitElement unit = library.definingCompilationUnit;
     // find "a.b.sss = 0"
     AssignmentExpression assignment;
@@ -8536,7 +8551,7 @@
 int f(A a) {
   return a(0);
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -8546,7 +8561,7 @@
 class A extends B implements C {}
 class B {}
 class C {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -8560,7 +8575,7 @@
   A.n() {}
   m() {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -8573,7 +8588,7 @@
   /** [e] [f] */
   m(e, f()) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -8582,7 +8597,7 @@
     Source source = addSource(r'''
 /// [A]
 class A {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -8716,7 +8731,7 @@
 
   void test_empty() {
     Source source = addSource("");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -8728,7 +8743,7 @@
     Source source = addNamedSource("/one.dart", r'''
 library one;
 export 'two.dart';''');
-    LibraryElement library = resolve(source);
+    LibraryElement library = resolve2(source);
     expect(library, isNotNull);
     FunctionElement main = library.entryPoint;
     expect(main, isNotNull);
@@ -8741,7 +8756,7 @@
     Source source = addNamedSource("/one.dart", r'''
 library one;
 main() {}''');
-    LibraryElement library = resolve(source);
+    LibraryElement library = resolve2(source);
     expect(library, isNotNull);
     FunctionElement main = library.entryPoint;
     expect(main, isNotNull);
@@ -8752,7 +8767,7 @@
 
   void test_entryPoint_none() {
     Source source = addNamedSource("/one.dart", "library one;");
-    LibraryElement library = resolve(source);
+    LibraryElement library = resolve2(source);
     expect(library, isNotNull);
     expect(library.entryPoint, isNull);
     assertNoErrors(source);
@@ -8768,7 +8783,7 @@
 main() {
   EEE e = null;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -8782,7 +8797,7 @@
 class A {
   void sort([compare = Comparable.compare]) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -8793,7 +8808,7 @@
   int x;
   A(this.x) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -8805,7 +8820,7 @@
   for (int x in list) {}
   for (int x in list) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -8818,7 +8833,7 @@
   for (int i = 0; i < 3; i++) {
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -8832,7 +8847,7 @@
     if (p(e)) {}
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -8854,7 +8869,7 @@
   }
 }
 ''');
-    LibraryElement library = resolve(source);
+    LibraryElement library = resolve2(source);
     assertNoErrors(source);
     verify([source]);
     // Verify that both the getter and setter for "x" in C.f() refer to the
@@ -8885,7 +8900,7 @@
   }
 }
 ''');
-    LibraryElement library = resolve(source);
+    LibraryElement library = resolve2(source);
     assertNoErrors(source);
     verify([source]);
     // Verify that the getter for "x" in C.f() refers to the getter defined in
@@ -8912,7 +8927,7 @@
   var y = new C().x;
 }
 ''');
-    LibraryElement library = resolve(source);
+    LibraryElement library = resolve2(source);
     assertNoErrors(source);
     verify([source]);
     // Verify that the getter for "x" in "new C().x" refers to the getter
@@ -8935,7 +8950,7 @@
 g (A a) {
   a.f = a.f.toString();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [StaticWarningCode.MISMATCHED_GETTER_AND_SETTER_TYPES]);
     verify([source]);
@@ -8945,7 +8960,7 @@
     Source source = addSource(r'''
 class A {}
 class B {toString() => super.toString();}''');
-    LibraryElement library = resolve(source);
+    LibraryElement library = resolve2(source);
     expect(library, isNotNull);
     CompilationUnitElement unit = library.definingCompilationUnit;
     expect(unit, isNotNull);
@@ -8973,7 +8988,7 @@
   foo = 0;
 }
 A a;''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -8990,7 +9005,7 @@
 main() {
   _two.f(0);
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -9005,7 +9020,7 @@
 main() {
   foo();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -9020,7 +9035,7 @@
   List<List<List<int>>> c;
   c[0][0][0];
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -9031,7 +9046,7 @@
   List<List<int>> b;
   b[0][0] = 'hi';
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.INVALID_ASSIGNMENT]);
     verify([source]);
   }
@@ -9053,7 +9068,7 @@
 main() {
   g(f()[0]);
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -9066,7 +9081,7 @@
     X.last;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -9075,7 +9090,7 @@
     Source source = addSource(r'''
 class A extends B {}
 class B {}''');
-    LibraryElement library = resolve(source);
+    LibraryElement library = resolve2(source);
     expect(library, isNotNull);
     CompilationUnitElement unit = library.definingCompilationUnit;
     expect(unit, isNotNull);
@@ -9091,7 +9106,7 @@
 class A {
   A() {}
 }''');
-    LibraryElement library = resolve(source);
+    LibraryElement library = resolve2(source);
     expect(library, isNotNull);
     CompilationUnitElement unit = library.definingCompilationUnit;
     expect(unit, isNotNull);
@@ -9109,7 +9124,7 @@
     return super.toString();
   }
 }''');
-    LibraryElement library = resolve(source);
+    LibraryElement library = resolve2(source);
     expect(library, isNotNull);
     CompilationUnitElement unit = library.definingCompilationUnit;
     expect(unit, isNotNull);
@@ -9122,7 +9137,7 @@
 
   void test_isValidMixin_valid() {
     Source source = addSource("class A {}");
-    LibraryElement library = resolve(source);
+    LibraryElement library = resolve2(source);
     expect(library, isNotNull);
     CompilationUnitElement unit = library.definingCompilationUnit;
     expect(unit, isNotNull);
@@ -9145,7 +9160,7 @@
       continue l1;
   }
 }''');
-    LibraryElement library = resolve(source);
+    LibraryElement library = resolve2(source);
     expect(library, isNotNull);
     assertNoErrors(source);
     verify([source]);
@@ -9158,10 +9173,10 @@
   var myVar = (int p) => 'foo';
   myVar(42);
 }''');
-    LibraryElement library = resolve(source);
+    LibraryElement library = resolve2(source);
     expect(library, isNotNull);
     CompilationUnit unit =
-        analysisContext.getResolvedCompilationUnit(source, library);
+        analysisContext.resolveCompilationUnit(source, library);
     expect(unit, isNotNull);
     List<bool> found = [false];
     List<CaughtException> thrownException = new List<CaughtException>(1);
@@ -9178,7 +9193,7 @@
     Source source = addSource(r'''
 const A = null;
 @A class C<A> {}''');
-    LibraryElement library = resolve(source);
+    LibraryElement library = resolve2(source);
     expect(library, isNotNull);
     CompilationUnitElement unitElement = library.definingCompilationUnit;
     expect(unitElement, isNotNull);
@@ -9208,7 +9223,7 @@
 class C {
   @A int f;
 }''');
-    LibraryElement library = resolve(source);
+    LibraryElement library = resolve2(source);
     expect(library, isNotNull);
     CompilationUnitElement unit = library.definingCompilationUnit;
     expect(unit, isNotNull);
@@ -9228,7 +9243,7 @@
   int f;
   C(@A this.f);
 }''');
-    LibraryElement library = resolve(source);
+    LibraryElement library = resolve2(source);
     expect(library, isNotNull);
     CompilationUnitElement unit = library.definingCompilationUnit;
     expect(unit, isNotNull);
@@ -9248,7 +9263,7 @@
     Source source = addSource(r'''
 const A = null;
 @A f() {}''');
-    LibraryElement library = resolve(source);
+    LibraryElement library = resolve2(source);
     expect(library, isNotNull);
     CompilationUnitElement unit = library.definingCompilationUnit;
     expect(unit, isNotNull);
@@ -9264,7 +9279,7 @@
     Source source = addSource(r'''
 const A = null;
 f(@A int p(int x)) {}''');
-    LibraryElement library = resolve(source);
+    LibraryElement library = resolve2(source);
     expect(library, isNotNull);
     CompilationUnitElement unit = library.definingCompilationUnit;
     expect(unit, isNotNull);
@@ -9282,7 +9297,7 @@
     Source source = addSource(r'''
 @A library lib;
 const A = null;''');
-    LibraryElement library = resolve(source);
+    LibraryElement library = resolve2(source);
     expect(library, isNotNull);
     List<ElementAnnotation> annotations = library.metadata;
     expect(annotations, hasLength(1));
@@ -9296,7 +9311,7 @@
 class C {
   @A void m() {}
 }''');
-    LibraryElement library = resolve(source);
+    LibraryElement library = resolve2(source);
     expect(library, isNotNull);
     CompilationUnitElement unit = library.definingCompilationUnit;
     expect(unit, isNotNull);
@@ -9313,7 +9328,7 @@
     Source source = addSource(r'''
 const A = null;
 f({@A int p : 0}) {}''');
-    LibraryElement library = resolve(source);
+    LibraryElement library = resolve2(source);
     expect(library, isNotNull);
     CompilationUnitElement unit = library.definingCompilationUnit;
     expect(unit, isNotNull);
@@ -9331,7 +9346,7 @@
     Source source = addSource(r'''
 const A = null;
 f([@A int p = 0]) {}''');
-    LibraryElement library = resolve(source);
+    LibraryElement library = resolve2(source);
     expect(library, isNotNull);
     CompilationUnitElement unit = library.definingCompilationUnit;
     expect(unit, isNotNull);
@@ -9349,7 +9364,7 @@
     Source source = addSource(r'''
 const A = null;
 f(@A p1, @A int p2) {}''');
-    LibraryElement library = resolve(source);
+    LibraryElement library = resolve2(source);
     expect(library, isNotNull);
     CompilationUnitElement unit = library.definingCompilationUnit;
     expect(unit, isNotNull);
@@ -9369,7 +9384,7 @@
     Source source = addSource(r'''
 const A = null;
 @A typedef F<A>();''');
-    LibraryElement library = resolve(source);
+    LibraryElement library = resolve2(source);
     expect(library, isNotNull);
     CompilationUnitElement unitElement = library.definingCompilationUnit;
     expect(unitElement, isNotNull);
@@ -9406,7 +9421,7 @@
   bar() => super.bar();
   foo() => super.foo();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -9425,7 +9440,7 @@
   new C().f();
 }
 ''');
-    LibraryElement library = resolve(source);
+    LibraryElement library = resolve2(source);
     assertNoErrors(source);
     verify([source]);
     // Verify that the "f" in "new C().f()" refers to the "f" defined in M2.
@@ -9452,7 +9467,7 @@
   }
 }
 ''');
-    LibraryElement library = resolve(source);
+    LibraryElement library = resolve2(source);
     assertNoErrors(source);
     verify([source]);
     // Verify that the call to f() in C.g() refers to the method defined in M2.
@@ -9479,7 +9494,7 @@
   new C().f();
 }
 ''');
-    LibraryElement library = resolve(source);
+    LibraryElement library = resolve2(source);
     assertNoErrors(source);
     verify([source]);
     // Verify that the call to f() in "new C().f()" refers to the method
@@ -9504,7 +9519,7 @@
 f(C c) {
   c.m1();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -9520,7 +9535,7 @@
      ..m2();
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -9538,7 +9553,7 @@
      ..m2();
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     // failing with error code: INVOCATION_OF_NON_FUNCTION
     assertNoErrors(source);
     verify([source]);
@@ -9549,7 +9564,7 @@
 f(var p) {
   return null == p;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
   }
 
@@ -9568,7 +9583,7 @@
   }
 }
 ''');
-    LibraryElement library = resolve(source);
+    LibraryElement library = resolve2(source);
     assertNoErrors(source);
     verify([source]);
     // Verify that the setter for "x" in C.f() refers to the setter defined in
@@ -9596,7 +9611,7 @@
   new C().x = 1;
 }
 ''');
-    LibraryElement library = resolve(source);
+    LibraryElement library = resolve2(source);
     assertNoErrors(source);
     verify([source]);
     // Verify that the setter for "x" in "new C().x" refers to the setter
@@ -9621,7 +9636,7 @@
   int get x => super.x == null ? 0 : super.x;
   int f() => x = 1;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -9634,7 +9649,7 @@
 main() {
   s = 123;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -9661,7 +9676,7 @@
    *           valid
    */
   void _validateArgumentResolution(Source source, List<int> indices) {
-    LibraryElement library = resolve(source);
+    LibraryElement library = resolve2(source);
     expect(library, isNotNull);
     ClassElement classElement = library.definingCompilationUnit.types[0];
     List<ParameterElement> parameters = classElement.methods[1].parameters;
@@ -9805,7 +9820,7 @@
   void _resolveTestUnit(String code) {
     testCode = code;
     testSource = addSource(testCode);
-    LibraryElement library = resolve(testSource);
+    LibraryElement library = resolve2(testSource);
     assertNoErrors(testSource);
     verify([testSource]);
     testUnit = resolveCompilationUnit(testSource, library);
@@ -11405,7 +11420,7 @@
     sum += list[i];
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.UNDEFINED_OPERATOR]);
   }
 
@@ -11422,7 +11437,7 @@
   assert (n is int);
   return n & 0x0F;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.UNDEFINED_OPERATOR]);
   }
 
@@ -11431,7 +11446,7 @@
 int f(num n) {
   return (n is int && n > 0) ? n & 0x0F : 0;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
   }
 
@@ -11440,7 +11455,7 @@
 int f(num n) {
   return (n is int) ? n & 0x0F : 0;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
   }
 
@@ -11449,7 +11464,7 @@
 int f(num n) {
   return (n is! int) ? 0 : n & 0x0F;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.UNDEFINED_OPERATOR]);
   }
 
@@ -11458,7 +11473,7 @@
 int f(num n) {
   return (n is! int || n < 0) ? 0 : n & 0x0F;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.UNDEFINED_OPERATOR]);
   }
 
@@ -11470,7 +11485,7 @@
     sum += n & 0x0F;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.UNDEFINED_OPERATOR]);
   }
 
@@ -11482,7 +11497,7 @@
   }
   return 0;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
   }
 
@@ -11494,7 +11509,7 @@
   }
   return 0;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
   }
 
@@ -11507,7 +11522,7 @@
     return n & 0x0F;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.UNDEFINED_OPERATOR]);
   }
 
@@ -11519,7 +11534,7 @@
   }
   return n & 0x0F;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.UNDEFINED_OPERATOR]);
   }
 
@@ -11532,7 +11547,7 @@
     return n & 0x0F;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.UNDEFINED_OPERATOR]);
   }
 
@@ -11542,7 +11557,7 @@
   num n = 1234;
   return n & 0x0F;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.UNDEFINED_OPERATOR]);
   }
 }
@@ -11950,7 +11965,7 @@
     return null;
   }
 }''');
-    LibraryElement library = resolve(source);
+    LibraryElement library = resolve2(source);
     assertNoErrors(source);
     verify([source]);
     CompilationUnit unit = resolveCompilationUnit(source, library);
@@ -11973,7 +11988,7 @@
   assert (p is A);
   return p;
 }''');
-    LibraryElement library = resolve(source);
+    LibraryElement library = resolve2(source);
     assertNoErrors(source);
     verify([source]);
     CompilationUnit unit = resolveCompilationUnit(source, library);
@@ -11994,7 +12009,7 @@
   v = 0;
   return v;
 }''');
-    LibraryElement library = resolve(source);
+    LibraryElement library = resolve2(source);
     assertNoErrors(source);
     verify([source]);
     CompilationUnit unit = resolveCompilationUnit(source, library);
@@ -12013,7 +12028,7 @@
   v = 1.0;
   return v;
 }''');
-    LibraryElement library = resolve(source);
+    LibraryElement library = resolve2(source);
     assertNoErrors(source);
     verify([source]);
     CompilationUnit unit = resolveCompilationUnit(source, library);
@@ -12035,7 +12050,7 @@
     CompilationUnit unit;
     {
       Source source = addSource(code);
-      LibraryElement library = resolve(source);
+      LibraryElement library = resolve2(source);
       assertNoErrors(source);
       verify([source]);
       unit = resolveCompilationUnit(source, library);
@@ -12067,7 +12082,7 @@
   var context = canvas.getContext('2d');
 }''';
     Source source = addSource(code);
-    LibraryElement library = resolve(source);
+    LibraryElement library = resolve2(source);
     assertNoErrors(source);
     verify([source]);
     CompilationUnit unit = resolveCompilationUnit(source, library);
@@ -12085,7 +12100,7 @@
   }
 }''';
     Source source = addSource(code);
-    LibraryElement library = resolve(source);
+    LibraryElement library = resolve2(source);
     assertNoErrors(source);
     verify([source]);
     CompilationUnit unit = resolveCompilationUnit(source, library);
@@ -12116,7 +12131,7 @@
   });
 }''';
     Source source = addSource(code);
-    LibraryElement library = resolve(source);
+    LibraryElement library = resolve2(source);
     assertNoErrors(source);
     verify([source]);
     CompilationUnit unit = resolveCompilationUnit(source, library);
@@ -12150,7 +12165,7 @@
   m2.forEach((k, v) {});
 }''';
     Source source = addSource(code);
-    LibraryElement library = resolve(source);
+    LibraryElement library = resolve2(source);
     assertNoErrors(source);
     verify([source]);
     CompilationUnit unit = resolveCompilationUnit(source, library);
@@ -12174,7 +12189,7 @@
   });
 }''';
     Source source = addSource(code);
-    LibraryElement library = resolve(source);
+    LibraryElement library = resolve2(source);
     assertNoErrors(source);
     verify([source]);
     CompilationUnit unit = resolveCompilationUnit(source, library);
@@ -12202,7 +12217,7 @@
   });
 }''';
     Source source = addSource(code);
-    LibraryElement library = resolve(source);
+    LibraryElement library = resolve2(source);
     assertNoErrors(source);
     verify([source]);
     CompilationUnit unit = resolveCompilationUnit(source, library);
@@ -12228,7 +12243,7 @@
   a.m(() => 0);
 }''';
     Source source = addSource(code);
-    LibraryElement library = resolve(source);
+    LibraryElement library = resolve2(source);
     assertErrors(source, [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]);
     verify([source]);
     CompilationUnit unit = resolveCompilationUnit(source, library);
@@ -12251,7 +12266,7 @@
   });
 }''';
     Source source = addSource(code);
-    LibraryElement library = resolve(source);
+    LibraryElement library = resolve2(source);
     assertNoErrors(source);
     verify([source]);
     CompilationUnit unit = resolveCompilationUnit(source, library);
@@ -12278,7 +12293,7 @@
   });
 }''';
     Source source = addSource(code);
-    LibraryElement library = resolve(source);
+    LibraryElement library = resolve2(source);
     assertNoErrors(source);
     verify([source]);
     CompilationUnit unit = resolveCompilationUnit(source, library);
@@ -12302,7 +12317,7 @@
   var v = 0;
   return v;
 }''');
-    LibraryElement library = resolve(source);
+    LibraryElement library = resolve2(source);
     assertNoErrors(source);
     verify([source]);
     CompilationUnit unit = resolveCompilationUnit(source, library);
@@ -12332,7 +12347,7 @@
   var v = 'String';
   v.
 }''');
-    LibraryElement library = resolve(source);
+    LibraryElement library = resolve2(source);
     CompilationUnit unit = resolveCompilationUnit(source, library);
     FunctionDeclaration function = unit.declarations[0] as FunctionDeclaration;
     BlockFunctionBody body =
@@ -12350,7 +12365,7 @@
   int v = 0;
   return v;
 }''');
-    LibraryElement library = resolve(source);
+    LibraryElement library = resolve2(source);
     assertNoErrors(source);
     verify([source]);
     CompilationUnit unit = resolveCompilationUnit(source, library);
@@ -12381,7 +12396,7 @@
   List<int> v = <int>[];
   return v;
 }''');
-    LibraryElement library = resolve(source);
+    LibraryElement library = resolve2(source);
     assertNoErrors(source);
     verify([source]);
     CompilationUnit unit = resolveCompilationUnit(source, library);
@@ -12415,7 +12430,7 @@
     CompilationUnit unit;
     {
       Source source = addSource(code);
-      LibraryElement library = resolve(source);
+      LibraryElement library = resolve2(source);
       assertNoErrors(source);
       verify([source]);
       unit = resolveCompilationUnit(source, library);
@@ -12440,7 +12455,7 @@
 A f(var p) {
   return (p is A) ? p : null;
 }''');
-    LibraryElement library = resolve(source);
+    LibraryElement library = resolve2(source);
     assertNoErrors(source);
     verify([source]);
     CompilationUnit unit = resolveCompilationUnit(source, library);
@@ -12467,7 +12482,7 @@
     return null;
   }
 }''');
-    LibraryElement library = resolve(source);
+    LibraryElement library = resolve2(source);
     assertNoErrors(source);
     verify([source]);
     CompilationUnit unit = resolveCompilationUnit(source, library);
@@ -12507,7 +12522,7 @@
     return null;
   }
 }''');
-    LibraryElement library = resolve(source);
+    LibraryElement library = resolve2(source);
     assertNoErrors(source);
     verify([source]);
     CompilationUnit unit = resolveCompilationUnit(source, library);
@@ -12533,7 +12548,7 @@
     return null;
   }
 }''');
-    LibraryElement library = resolve(source);
+    LibraryElement library = resolve2(source);
     assertNoErrors(source);
     verify([source]);
     CompilationUnit unit = resolveCompilationUnit(source, library);
@@ -12556,7 +12571,7 @@
   A a = (p is A) ? p : throw null;
   return p;
 }''');
-    LibraryElement library = resolve(source);
+    LibraryElement library = resolve2(source);
     assertNoErrors(source);
     verify([source]);
     CompilationUnit unit = resolveCompilationUnit(source, library);
@@ -12581,7 +12596,7 @@
   }
   return p;
 }''');
-    LibraryElement library = resolve(source);
+    LibraryElement library = resolve2(source);
     assertNoErrors(source);
     verify([source]);
     CompilationUnit unit = resolveCompilationUnit(source, library);
@@ -12607,7 +12622,7 @@
   }
   return p;
 }''');
-    LibraryElement library = resolve(source);
+    LibraryElement library = resolve2(source);
     assertNoErrors(source);
     CompilationUnit unit = resolveCompilationUnit(source, library);
     FunctionDeclaration function = unit.declarations[2] as FunctionDeclaration;
@@ -12630,7 +12645,7 @@
   }
   return p;
 }''');
-    LibraryElement library = resolve(source);
+    LibraryElement library = resolve2(source);
     assertNoErrors(source);
     verify([source]);
     CompilationUnit unit = resolveCompilationUnit(source, library);
@@ -12652,7 +12667,7 @@
 A f(var p) {
   return (p is! A) ? null : p;
 }''');
-    LibraryElement library = resolve(source);
+    LibraryElement library = resolve2(source);
     assertNoErrors(source);
     verify([source]);
     CompilationUnit unit = resolveCompilationUnit(source, library);
@@ -12679,7 +12694,7 @@
     return p;
   }
 }''');
-    LibraryElement library = resolve(source);
+    LibraryElement library = resolve2(source);
     assertNoErrors(source);
     verify([source]);
     CompilationUnit unit = resolveCompilationUnit(source, library);
@@ -12705,7 +12720,7 @@
     return p;
   }
 }''');
-    LibraryElement library = resolve(source);
+    LibraryElement library = resolve2(source);
     assertNoErrors(source);
     CompilationUnit unit = resolveCompilationUnit(source, library);
     ClassDeclaration classA = unit.declarations[0] as ClassDeclaration;
@@ -12727,7 +12742,7 @@
   A a = (p is! A) ? throw null : p;
   return p;
 }''');
-    LibraryElement library = resolve(source);
+    LibraryElement library = resolve2(source);
     assertNoErrors(source);
     verify([source]);
     CompilationUnit unit = resolveCompilationUnit(source, library);
@@ -12750,7 +12765,7 @@
   }
   return p;
 }''');
-    LibraryElement library = resolve(source);
+    LibraryElement library = resolve2(source);
     assertNoErrors(source);
     verify([source]);
     CompilationUnit unit = resolveCompilationUnit(source, library);
@@ -12824,7 +12839,7 @@
   var v = [0, '1', 2];
   return v[2];
 }''');
-    LibraryElement library = resolve(source);
+    LibraryElement library = resolve2(source);
     assertNoErrors(source);
     verify([source]);
     CompilationUnit unit = resolveCompilationUnit(source, library);
@@ -12842,7 +12857,7 @@
   var v = [0, 1, 2];
   return v[2];
 }''');
-    LibraryElement library = resolve(source);
+    LibraryElement library = resolve2(source);
     assertNoErrors(source);
     verify([source]);
     CompilationUnit unit = resolveCompilationUnit(source, library);
@@ -12866,7 +12881,7 @@
   var v = {'0' : 0, 1 : '1', '2' : 2};
   return v;
 }''');
-    LibraryElement library = resolve(source);
+    LibraryElement library = resolve2(source);
     assertNoErrors(source);
     verify([source]);
     CompilationUnit unit = resolveCompilationUnit(source, library);
@@ -12889,7 +12904,7 @@
   var v = {'a' : 0, 'b' : 1, 'c' : 2};
   return v;
 }''');
-    LibraryElement library = resolve(source);
+    LibraryElement library = resolve2(source);
     assertNoErrors(source);
     verify([source]);
     CompilationUnit unit = resolveCompilationUnit(source, library);
@@ -13004,7 +13019,7 @@
   }
   x = null;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
   }
 
@@ -13145,7 +13160,7 @@
   var b3 = query('body div');
   return [v1, v2, v3, v4, v5, v6, v7, m1, b1, b2, b3];
 }''');
-    LibraryElement library = resolve(source);
+    LibraryElement library = resolve2(source);
     assertNoErrors(source);
     verify([source]);
     CompilationUnit unit = resolveCompilationUnit(source, library);
@@ -13207,7 +13222,7 @@
   SimpleIdentifier _findMarkedIdentifier(String code, String marker) {
     try {
       Source source = addSource(code);
-      LibraryElement library = resolve(source);
+      LibraryElement library = resolve2(source);
       assertNoErrors(source);
       verify([source]);
       CompilationUnit unit = resolveCompilationUnit(source, library);
diff --git a/pkg/analyzer/test/generated/source_factory_test.dart b/pkg/analyzer/test/generated/source_factory_test.dart
new file mode 100644
index 0000000..67ec71e
--- /dev/null
+++ b/pkg/analyzer/test/generated/source_factory_test.dart
@@ -0,0 +1,179 @@
+// 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.
+
+// This code was auto-generated, is not intended to be edited, and is subject to
+// significant change. Please see the README file for more information.
+
+library analyzer.test.generated.source_factory;
+
+import 'package:analyzer/file_system/file_system.dart';
+import 'package:analyzer/file_system/memory_file_system.dart';
+import 'package:analyzer/source/package_map_resolver.dart';
+import 'package:analyzer/src/generated/java_core.dart';
+import 'package:analyzer/src/generated/java_engine_io.dart';
+import 'package:analyzer/src/generated/java_io.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/generated/source_io.dart';
+import 'package:path/path.dart';
+import 'package:unittest/unittest.dart';
+
+import '../reflective_tests.dart';
+import 'test_support.dart';
+
+main() {
+  groupSep = ' | ';
+  runReflectiveTests(SourceFactoryTest);
+}
+
+@reflectiveTest
+class SourceFactoryTest {
+  void test_creation() {
+    expect(new SourceFactory([]), isNotNull);
+  }
+  void test_fromEncoding_invalidUri() {
+    SourceFactory factory = new SourceFactory([]);
+    try {
+      factory.fromEncoding("<:&%>");
+      fail("Expected IllegalArgumentException");
+    } on IllegalArgumentException {}
+  }
+  void test_fromEncoding_noResolver() {
+    SourceFactory factory = new SourceFactory([]);
+    try {
+      factory.fromEncoding("foo:/does/not/exist.dart");
+      fail("Expected IllegalArgumentException");
+    } on IllegalArgumentException {}
+  }
+  void test_fromEncoding_valid() {
+    String encoding = "file:///does/not/exist.dart";
+    SourceFactory factory = new SourceFactory(
+        [new UriResolver_SourceFactoryTest_test_fromEncoding_valid(encoding)]);
+    expect(factory.fromEncoding(encoding), isNotNull);
+  }
+  void test_resolveUri_absolute() {
+    UriResolver_absolute resolver = new UriResolver_absolute();
+    SourceFactory factory = new SourceFactory([resolver]);
+    factory.resolveUri(null, "dart:core");
+    expect(resolver.invoked, isTrue);
+  }
+  void test_resolveUri_nonAbsolute_absolute() {
+    SourceFactory factory =
+        new SourceFactory([new UriResolver_nonAbsolute_absolute()]);
+    String absolutePath = "/does/not/matter.dart";
+    Source containingSource =
+        new FileBasedSource(FileUtilities2.createFile("/does/not/exist.dart"));
+    Source result = factory.resolveUri(containingSource, absolutePath);
+    expect(result.fullName,
+        FileUtilities2.createFile(absolutePath).getAbsolutePath());
+  }
+  void test_resolveUri_nonAbsolute_relative() {
+    SourceFactory factory =
+        new SourceFactory([new UriResolver_nonAbsolute_relative()]);
+    Source containingSource =
+        new FileBasedSource(FileUtilities2.createFile("/does/not/have.dart"));
+    Source result = factory.resolveUri(containingSource, "exist.dart");
+    expect(result.fullName,
+        FileUtilities2.createFile("/does/not/exist.dart").getAbsolutePath());
+  }
+
+  void test_resolveUri_nonAbsolute_relative_package() {
+    MemoryResourceProvider provider = new MemoryResourceProvider();
+    Context context = provider.pathContext;
+    String packagePath =
+        context.joinAll([context.separator, 'path', 'to', 'package']);
+    String libPath = context.joinAll([packagePath, 'lib']);
+    String dirPath = context.joinAll([libPath, 'dir']);
+    String firstPath = context.joinAll([dirPath, 'first.dart']);
+    String secondPath = context.joinAll([dirPath, 'second.dart']);
+
+    provider.newFolder(packagePath);
+    Folder libFolder = provider.newFolder(libPath);
+    provider.newFolder(dirPath);
+    File firstFile = provider.newFile(firstPath, '');
+    provider.newFile(secondPath, '');
+
+    PackageMapUriResolver resolver =
+        new PackageMapUriResolver(provider, {'package': [libFolder]});
+    SourceFactory factory = new SourceFactory([resolver]);
+    Source librarySource =
+        firstFile.createSource(Uri.parse('package:package/dir/first.dart'));
+
+    Source result = factory.resolveUri(librarySource, 'second.dart');
+    expect(result, isNotNull);
+    expect(result.fullName, secondPath);
+    expect(result.uri.toString(), 'package:package/dir/second.dart');
+  }
+
+  void test_restoreUri() {
+    JavaFile file1 = FileUtilities2.createFile("/some/file1.dart");
+    JavaFile file2 = FileUtilities2.createFile("/some/file2.dart");
+    Source source1 = new FileBasedSource(file1);
+    Source source2 = new FileBasedSource(file2);
+    Uri expected1 = parseUriWithException("file:///my_file.dart");
+    SourceFactory factory =
+        new SourceFactory([new UriResolver_restoreUri(source1, expected1)]);
+    expect(factory.restoreUri(source1), same(expected1));
+    expect(factory.restoreUri(source2), same(null));
+  }
+}
+
+class UriResolver_absolute extends UriResolver {
+  bool invoked = false;
+
+  UriResolver_absolute();
+
+  @override
+  Source resolveAbsolute(Uri uri) {
+    invoked = true;
+    return null;
+  }
+}
+
+class UriResolver_nonAbsolute_absolute extends UriResolver {
+  @override
+  Source resolveAbsolute(Uri uri) {
+    return new FileBasedSource(new JavaFile.fromUri(uri), uri);
+  }
+}
+
+class UriResolver_nonAbsolute_relative extends UriResolver {
+  @override
+  Source resolveAbsolute(Uri uri) {
+    return new FileBasedSource(new JavaFile.fromUri(uri), uri);
+  }
+}
+
+class UriResolver_restoreUri extends UriResolver {
+  Source source1;
+
+  Uri expected1;
+
+  UriResolver_restoreUri(this.source1, this.expected1);
+
+  @override
+  Source resolveAbsolute(Uri uri) => null;
+
+  @override
+  Uri restoreAbsolute(Source source) {
+    if (identical(source, source1)) {
+      return expected1;
+    }
+    return null;
+  }
+}
+
+class UriResolver_SourceFactoryTest_test_fromEncoding_valid
+    extends UriResolver {
+  String encoding;
+
+  UriResolver_SourceFactoryTest_test_fromEncoding_valid(this.encoding);
+
+  @override
+  Source resolveAbsolute(Uri uri) {
+    if (uri.toString() == encoding) {
+      return new TestSource();
+    }
+    return null;
+  }
+}
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 8e5a303..f35d057 100644
--- a/pkg/analyzer/test/generated/static_type_warning_code_test.dart
+++ b/pkg/analyzer/test/generated/static_type_warning_code_test.dart
@@ -22,7 +22,7 @@
   void fail_inaccessibleSetter() {
     Source source = addSource(r'''
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.INACCESSIBLE_SETTER]);
     verify([source]);
   }
@@ -34,7 +34,7 @@
 E e() {
   return E.TWO;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.UNDEFINED_ENUM_CONSTANT]);
     verify([source]);
   }
@@ -50,7 +50,7 @@
     addNamedSource("/lib2.dart", r'''
 library lib2;
 f() {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.AMBIGUOUS_IMPORT]);
   }
 
@@ -62,7 +62,7 @@
   Future<int> b = await ffi(); // Warning: int not assignable to Future<int>
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.INVALID_ASSIGNMENT]);
     verify([source]);
   }
@@ -75,7 +75,7 @@
   String a = await fi(); // Warning: int not assignable to String
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.INVALID_ASSIGNMENT]);
     verify([source]);
   }
@@ -101,7 +101,7 @@
   }
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       StaticTypeWarningCode.INVALID_ASSIGNMENT,
       StaticTypeWarningCode.INVALID_ASSIGNMENT
@@ -114,7 +114,7 @@
 main() {
   <int, int> [];
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [StaticTypeWarningCode.EXPECTED_ONE_LIST_TYPE_ARGUMENTS]);
     verify([source]);
@@ -125,7 +125,7 @@
 main() {
   <int> {};
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [StaticTypeWarningCode.EXPECTED_TWO_MAP_TYPE_ARGUMENTS]);
     verify([source]);
@@ -136,7 +136,7 @@
 main() {
   <int, int, int> {};
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [StaticTypeWarningCode.EXPECTED_TWO_MAP_TYPE_ARGUMENTS]);
     verify([source]);
@@ -146,7 +146,7 @@
     Source source = addSource('''
 int f() async {}
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       StaticTypeWarningCode.ILLEGAL_ASYNC_RETURN_TYPE,
       HintCode.MISSING_RETURN
@@ -158,7 +158,7 @@
     Source source = addSource('''
 int f() async* {}
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [StaticTypeWarningCode.ILLEGAL_ASYNC_GENERATOR_RETURN_TYPE]);
     verify([source]);
@@ -170,7 +170,7 @@
   int f() async* {}
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [StaticTypeWarningCode.ILLEGAL_ASYNC_GENERATOR_RETURN_TYPE]);
     verify([source]);
@@ -182,7 +182,7 @@
   int f() async {}
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       StaticTypeWarningCode.ILLEGAL_ASYNC_RETURN_TYPE,
       HintCode.MISSING_RETURN
@@ -194,7 +194,7 @@
     Source source = addSource('''
 int f() sync* {}
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [StaticTypeWarningCode.ILLEGAL_SYNC_GENERATOR_RETURN_TYPE]);
     verify([source]);
@@ -206,7 +206,7 @@
   int f() sync* {}
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [StaticTypeWarningCode.ILLEGAL_SYNC_GENERATOR_RETURN_TYPE]);
     verify([source]);
@@ -222,7 +222,7 @@
 }
 class C implements A, B {
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [StaticTypeWarningCode.INCONSISTENT_METHOD_INHERITANCE]);
     verify([source]);
@@ -237,7 +237,7 @@
   x(String s);
 }
 abstract class C implements A, B {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [StaticTypeWarningCode.INCONSISTENT_METHOD_INHERITANCE]);
     verify([source]);
@@ -252,7 +252,7 @@
   String x();
 }
 abstract class C implements A, B {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [StaticTypeWarningCode.INCONSISTENT_METHOD_INHERITANCE]);
     verify([source]);
@@ -266,7 +266,7 @@
 main(A a) {
   a.m();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [StaticTypeWarningCode.INSTANCE_ACCESS_TO_STATIC_MEMBER]);
     verify([source]);
@@ -280,7 +280,7 @@
 main(A a) {
   a.m;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [StaticTypeWarningCode.INSTANCE_ACCESS_TO_STATIC_MEMBER]);
     verify([source]);
@@ -294,7 +294,7 @@
 main(A a) {
   a.f;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [StaticTypeWarningCode.INSTANCE_ACCESS_TO_STATIC_MEMBER]);
     verify([source]);
@@ -308,7 +308,7 @@
 main(A a) {
   a.f;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [StaticTypeWarningCode.INSTANCE_ACCESS_TO_STATIC_MEMBER]);
     verify([source]);
@@ -322,7 +322,7 @@
 main(A a) {
   a.f = 42;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [StaticTypeWarningCode.INSTANCE_ACCESS_TO_STATIC_MEMBER]);
     verify([source]);
@@ -340,7 +340,7 @@
   byte b = new byte(52);
   b += 3;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.INVALID_ASSIGNMENT]);
     verify([source]);
   }
@@ -349,7 +349,7 @@
     Source source = addSource(r'''
 f({String x: 0}) {
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.INVALID_ASSIGNMENT]);
     verify([source]);
   }
@@ -358,7 +358,7 @@
     Source source = addSource(r'''
 f([String x = 0]) {
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.INVALID_ASSIGNMENT]);
     verify([source]);
   }
@@ -369,7 +369,7 @@
   dynamic = 1;
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.INVALID_ASSIGNMENT]);
     verify([source]);
   }
@@ -379,7 +379,7 @@
 main() {
   String x = (() => 5)();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.INVALID_ASSIGNMENT]);
     verify([source]);
   }
@@ -394,7 +394,7 @@
   d ??= i;
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.INVALID_ASSIGNMENT]);
     verify([source]);
   }
@@ -408,7 +408,7 @@
   A a;
   a.x = '0';
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.INVALID_ASSIGNMENT]);
     verify([source]);
   }
@@ -419,7 +419,7 @@
   int x;
   x = '0';
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.INVALID_ASSIGNMENT]);
     verify([source]);
   }
@@ -430,7 +430,7 @@
 class C<T> {
   T t = int;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.INVALID_ASSIGNMENT]);
     verify([source]);
   }
@@ -443,14 +443,14 @@
 f() {
   A.x = '0';
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.INVALID_ASSIGNMENT]);
     verify([source]);
   }
 
   void test_invalidAssignment_topLevelVariableDeclaration() {
     Source source = addSource("int x = 'string';");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.INVALID_ASSIGNMENT]);
     verify([source]);
   }
@@ -464,7 +464,7 @@
     value = n;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.INVALID_ASSIGNMENT]);
     verify([source]);
   }
@@ -474,7 +474,7 @@
 class A {
   int x = 'string';
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.INVALID_ASSIGNMENT]);
     verify([source]);
   }
@@ -486,7 +486,7 @@
     A();
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION]);
   }
 
@@ -502,7 +502,7 @@
 f(Function f) {
   return f();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION]);
     verify([source]);
   }
@@ -515,7 +515,7 @@
 f(Object o) {
   return o();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION]);
     verify([source]);
   }
@@ -526,7 +526,7 @@
   int x;
   return x();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION]);
     verify([source]);
   }
@@ -541,7 +541,7 @@
     A.x();
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION]);
     // A call to verify(source) fails as A.x() cannot be resolved.
   }
@@ -554,7 +554,7 @@
     A.g();
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION]);
     // A call to verify(source) fails as g() cannot be resolved.
   }
@@ -569,7 +569,7 @@
     var v = super.g();
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION]);
     verify([source]);
   }
@@ -579,7 +579,7 @@
 f() {
   3(5);
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION_EXPRESSION]);
     verify([source]);
@@ -587,7 +587,7 @@
 
   void test_nonBoolCondition_conditional() {
     Source source = addSource("f() { return 3 ? 2 : 1; }");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.NON_BOOL_CONDITION]);
     verify([source]);
   }
@@ -597,7 +597,7 @@
 f() {
   do {} while (3);
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.NON_BOOL_CONDITION]);
     verify([source]);
   }
@@ -607,7 +607,7 @@
 f() {
   if (3) return 2; else return 1;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.NON_BOOL_CONDITION]);
     verify([source]);
   }
@@ -617,7 +617,7 @@
 f() {
   while (3) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.NON_BOOL_CONDITION]);
     verify([source]);
   }
@@ -628,7 +628,7 @@
 f() {
   assert(makeAssertion);
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.NON_BOOL_EXPRESSION]);
     verify([source]);
   }
@@ -638,7 +638,7 @@
 f() {
   assert(0);
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.NON_BOOL_EXPRESSION]);
     verify([source]);
   }
@@ -648,7 +648,7 @@
 f() {
   !42;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.NON_BOOL_NEGATION_EXPRESSION]);
     verify([source]);
   }
@@ -658,7 +658,7 @@
 bool f(int left, bool right) {
   return left && right;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.NON_BOOL_OPERAND]);
     verify([source]);
   }
@@ -668,7 +668,7 @@
 bool f(bool left, String right) {
   return left && right;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.NON_BOOL_OPERAND]);
     verify([source]);
   }
@@ -678,7 +678,7 @@
 bool f(List<int> left, bool right) {
   return left || right;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.NON_BOOL_OPERAND]);
     verify([source]);
   }
@@ -688,7 +688,7 @@
 bool f(bool left, double right) {
   return left || right;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.NON_BOOL_OPERAND]);
     verify([source]);
   }
@@ -698,7 +698,7 @@
 int A;
 class B<E> {}
 f(B<A> b) {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.NON_TYPE_AS_TYPE_ARGUMENT]);
     verify([source]);
   }
@@ -707,7 +707,7 @@
     Source source = addSource(r'''
 class B<E> {}
 f(B<A> b) {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.NON_TYPE_AS_TYPE_ARGUMENT]);
     verify([source]);
   }
@@ -719,7 +719,7 @@
   return 5;
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.RETURN_OF_INVALID_TYPE]);
     verify([source]);
   }
@@ -731,7 +731,7 @@
   return 5;
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.RETURN_OF_INVALID_TYPE]);
     verify([source]);
   }
@@ -742,7 +742,7 @@
   return 5;
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       StaticTypeWarningCode.RETURN_OF_INVALID_TYPE,
       StaticTypeWarningCode.ILLEGAL_ASYNC_RETURN_TYPE
@@ -752,14 +752,14 @@
 
   void test_returnOfInvalidType_expressionFunctionBody_function() {
     Source source = addSource("int f() => '0';");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.RETURN_OF_INVALID_TYPE]);
     verify([source]);
   }
 
   void test_returnOfInvalidType_expressionFunctionBody_getter() {
     Source source = addSource("int get g => '0';");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.RETURN_OF_INVALID_TYPE]);
     verify([source]);
   }
@@ -772,7 +772,7 @@
     return '0';
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.RETURN_OF_INVALID_TYPE]);
     verify([source]);
   }
@@ -782,28 +782,28 @@
 class A {
   int f() => '0';
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.RETURN_OF_INVALID_TYPE]);
     verify([source]);
   }
 
   void test_returnOfInvalidType_expressionFunctionBody_void() {
     Source source = addSource("void f() => 42;");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.RETURN_OF_INVALID_TYPE]);
     verify([source]);
   }
 
   void test_returnOfInvalidType_function() {
     Source source = addSource("int f() { return '0'; }");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.RETURN_OF_INVALID_TYPE]);
     verify([source]);
   }
 
   void test_returnOfInvalidType_getter() {
     Source source = addSource("int get g { return '0'; }");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.RETURN_OF_INVALID_TYPE]);
     verify([source]);
   }
@@ -816,7 +816,7 @@
     return '0';
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.RETURN_OF_INVALID_TYPE]);
     verify([source]);
   }
@@ -826,14 +826,14 @@
 class A {
   int f() { return '0'; }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.RETURN_OF_INVALID_TYPE]);
     verify([source]);
   }
 
   void test_returnOfInvalidType_void() {
     Source source = addSource("void f() { return 42; }");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.RETURN_OF_INVALID_TYPE]);
     verify([source]);
   }
@@ -845,7 +845,7 @@
 class C {}
 class G<E extends A> {}
 class D = G<B> with C;''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS]);
     verify([source]);
@@ -857,7 +857,7 @@
 class B {}
 class G<E extends A> {}
 class C extends G<B>{}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS]);
     verify([source]);
@@ -868,7 +868,7 @@
     Source source = addSource(r'''
 class X<T extends Type> {}
 class Y<U> extends X<U> {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS]);
     verify([source]);
@@ -883,7 +883,7 @@
   var f;
   C(G<B> this.f) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS]);
     verify([source]);
@@ -895,7 +895,7 @@
 class B {}
 class G<E extends A> {}
 G<B> f() { return null; }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS]);
     verify([source]);
@@ -907,7 +907,7 @@
 class B {}
 class G<E extends A> {}
 typedef G<B> f();''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS]);
     verify([source]);
@@ -919,7 +919,7 @@
 class B {}
 class G<E extends A> {}
 f(G<B> h()) {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS]);
     verify([source]);
@@ -931,7 +931,7 @@
 class B {}
 class G<E extends A> {}
 class C implements G<B>{}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS]);
     verify([source]);
@@ -943,7 +943,7 @@
 class B {}
 class G<E extends A> {}
 var b = 1 is G<B>;''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS]);
     verify([source]);
@@ -957,7 +957,7 @@
 class C {
   G<B> m() { return null; }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS]);
     verify([source]);
@@ -969,7 +969,7 @@
 class B {}
 class G<E extends A> {}
 f() { return new G<B>(); }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS]);
     verify([source]);
@@ -982,7 +982,7 @@
 class C extends B {}
 class G<E extends B> {}
 f() { return new G<A>(); }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS]);
     verify([source]);
@@ -994,7 +994,7 @@
 class B {}
 class G<E extends A> {}
 f(G<B> g) {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS]);
     verify([source]);
@@ -1008,7 +1008,7 @@
   X(int x, int y) {}
   factory X.name(int x, int y) = X<B>;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS,
       StaticWarningCode.REDIRECT_TO_INVALID_RETURN_TYPE
@@ -1023,7 +1023,7 @@
 class C<E> {}
 class D<E extends A> {}
 C<D<B>> Var;''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS]);
     verify([source]);
@@ -1036,7 +1036,7 @@
 class C {}
 class G<E extends A> {}
 class D<F extends G<B>> {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS]);
     verify([source]);
@@ -1048,7 +1048,7 @@
 class B {}
 class G<E extends A> {}
 G<B> g;''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS]);
     verify([source]);
@@ -1060,7 +1060,7 @@
 class B {}
 class G<E extends A> {}
 class C extends Object with G<B>{}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS]);
     verify([source]);
@@ -1070,7 +1070,7 @@
     Source source = addSource(r'''
 class A<T extends T> {
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [StaticTypeWarningCode.TYPE_PARAMETER_SUPERTYPE_OF_ITS_BOUND]);
     verify([source]);
@@ -1083,7 +1083,7 @@
   (p is String) && callMe(() { p.length; });
   p = 0;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.UNDEFINED_GETTER]);
   }
 
@@ -1092,7 +1092,7 @@
 main(Object p) {
   ((p is String) && ((p = 42) == 42)) && p.length != 0;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.UNDEFINED_GETTER]);
   }
 
@@ -1101,7 +1101,7 @@
 main(Object p) {
   (p is String) && (((p = 42) == 42) && p.length != 0);
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.UNDEFINED_GETTER]);
   }
 
@@ -1112,7 +1112,7 @@
   p is String ? callMe(() { p.length; }) : 0;
   p = 42;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.UNDEFINED_GETTER]);
   }
 
@@ -1123,7 +1123,7 @@
   p = 42;
   p is String ? callMe(() { p.length; }) : 0;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.UNDEFINED_GETTER]);
   }
 
@@ -1132,7 +1132,7 @@
 main(Object p) {
   p is String ? (p.length + (p = 42)) : 0;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.UNDEFINED_GETTER]);
   }
 
@@ -1147,7 +1147,7 @@
   }
   p = 0;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.UNDEFINED_GETTER]);
   }
 
@@ -1158,7 +1158,7 @@
     p.length;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.UNDEFINED_GETTER]);
   }
 
@@ -1175,7 +1175,7 @@
     p.b;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.UNDEFINED_GETTER]);
   }
 
@@ -1192,7 +1192,7 @@
     p.b;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.UNDEFINED_GETTER]);
   }
 
@@ -1204,7 +1204,7 @@
     p = 0;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.UNDEFINED_GETTER]);
   }
 
@@ -1216,7 +1216,7 @@
     p.length;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.UNDEFINED_GETTER]);
   }
 
@@ -1228,7 +1228,7 @@
   }
   () {p = 0;};
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.UNDEFINED_GETTER]);
   }
 
@@ -1240,7 +1240,7 @@
     p.length;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.UNDEFINED_GETTER]);
   }
 
@@ -1252,7 +1252,7 @@
   }
   f() {p = 0;};
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.UNDEFINED_GETTER]);
   }
 
@@ -1264,7 +1264,7 @@
     p.length;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.UNDEFINED_GETTER]);
   }
 
@@ -1281,7 +1281,7 @@
     p.b;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.UNDEFINED_GETTER]);
   }
 
@@ -1298,7 +1298,7 @@
     p.b;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.UNDEFINED_GETTER]);
   }
 
@@ -1307,16 +1307,7 @@
 void f() {
   g();
 }''');
-    resolve(source);
-    assertErrors(source, [StaticTypeWarningCode.UNDEFINED_FUNCTION]);
-  }
-
-  void test_undefinedFunction_hasImportPrefix() {
-    Source source = addSource(r'''
-import 'lib.dart' as f;
-main() { return f(); }''');
-    addNamedSource("/lib.dart", "library lib;");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.UNDEFINED_FUNCTION]);
   }
 
@@ -1328,7 +1319,7 @@
     g();
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.UNDEFINED_FUNCTION]);
   }
 
@@ -1339,7 +1330,7 @@
     addNamedSource("/lib.dart", r'''
 library lib;
 h() {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.UNDEFINED_FUNCTION]);
   }
 
@@ -1347,7 +1338,7 @@
     Source source = addSource(r'''
 class T {}
 f(T e) { return e.m; }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.UNDEFINED_GETTER]);
   }
 
@@ -1363,7 +1354,7 @@
   return f.call;
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.UNDEFINED_GETTER]);
   }
 
@@ -1376,7 +1367,7 @@
   return o.call;
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.UNDEFINED_GETTER]);
   }
 
@@ -1391,7 +1382,7 @@
 main() {
   new PrefixProxy().foo;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.UNDEFINED_GETTER]);
   }
 
@@ -1399,7 +1390,7 @@
     Source source = addSource(r'''
 class A {}
 var a = A.B;''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.UNDEFINED_GETTER]);
   }
 
@@ -1415,7 +1406,7 @@
 }
 var a = A?.x;
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.UNDEFINED_GETTER]);
   }
 
@@ -1425,7 +1416,7 @@
   void m() {}
 }
 f(T e) { return e.m().f; }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.UNDEFINED_GETTER]);
   }
 
@@ -1437,7 +1428,7 @@
 main(A<int> a) {
   a.element.anyGetterExistsInDynamic;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [StaticTypeWarningCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS]);
     verify([source]);
@@ -1451,7 +1442,7 @@
 main(A<int,int> a) {
   a.element.anyGetterExistsInDynamic;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [StaticTypeWarningCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS]);
     verify([source]);
@@ -1465,7 +1456,7 @@
 main(A<NoSuchType> a) {
   a.element.anyGetterExistsInDynamic;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.NON_TYPE_AS_TYPE_ARGUMENT]);
     verify([source]);
   }
@@ -1477,7 +1468,7 @@
     n();
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.UNDEFINED_METHOD]);
   }
 
@@ -1490,7 +1481,7 @@
     a += a2;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.UNDEFINED_METHOD]);
   }
 
@@ -1506,7 +1497,7 @@
   f.call();
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.UNDEFINED_METHOD]);
   }
 
@@ -1522,7 +1513,13 @@
     a.m();
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
+    assertErrors(source, [StaticTypeWarningCode.UNDEFINED_METHOD]);
+  }
+
+  void test_undefinedMethod_leastUpperBoundWithNull() {
+    Source source = addSource('f(bool b, int i) => (b ? null : i).foo();');
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.UNDEFINED_METHOD]);
   }
 
@@ -1535,7 +1532,7 @@
   o.call();
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.UNDEFINED_METHOD]);
   }
 
@@ -1552,7 +1549,7 @@
     _foo();
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.UNDEFINED_METHOD]);
   }
 
@@ -1567,7 +1564,7 @@
 main() {
   new PrefixProxy().foo();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.UNDEFINED_METHOD]);
   }
 
@@ -1583,7 +1580,7 @@
 }
 f() { A?.m(); }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.UNDEFINED_METHOD]);
   }
 
@@ -1593,7 +1590,7 @@
 f(A a) {
   a[0]++;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.UNDEFINED_OPERATOR]);
   }
 
@@ -1603,7 +1600,7 @@
 f(A a) {
   a[0];
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.UNDEFINED_OPERATOR]);
   }
 
@@ -1613,7 +1610,7 @@
 f(A a) {
   a[0] = 1;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.UNDEFINED_OPERATOR]);
   }
 
@@ -1623,7 +1620,7 @@
 f(A a) {
   a + 1;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.UNDEFINED_OPERATOR]);
   }
 
@@ -1633,7 +1630,7 @@
 f(A a) {
   a++;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.UNDEFINED_OPERATOR]);
   }
 
@@ -1643,7 +1640,7 @@
 f(A a) {
   ++a;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.UNDEFINED_OPERATOR]);
   }
 
@@ -1651,7 +1648,7 @@
     Source source = addSource(r'''
 class T {}
 f(T e1) { e1.m = 0; }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.UNDEFINED_SETTER]);
   }
 
@@ -1659,7 +1656,7 @@
     Source source = addSource(r'''
 class A {}
 f() { A.B = 0;}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.UNDEFINED_SETTER]);
   }
 
@@ -1675,7 +1672,7 @@
 }
 f() { A?.x = 1; }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.UNDEFINED_SETTER]);
   }
 
@@ -1685,7 +1682,7 @@
   void m() {}
 }
 f(T e) { e.m().f = 0; }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.UNDEFINED_SETTER]);
   }
 
@@ -1697,7 +1694,7 @@
     return super.g;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.UNDEFINED_SUPER_GETTER]);
   }
 
@@ -1707,7 +1704,7 @@
 class B extends A {
   m() { return super.m(); }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.UNDEFINED_SUPER_METHOD]);
   }
 
@@ -1719,7 +1716,7 @@
     return super + value;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.UNDEFINED_SUPER_OPERATOR]);
   }
 
@@ -1731,7 +1728,7 @@
     return super[index]++;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.UNDEFINED_SUPER_OPERATOR]);
   }
 
@@ -1743,7 +1740,7 @@
     return super[index + 1];
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.UNDEFINED_SUPER_OPERATOR]);
   }
 
@@ -1755,7 +1752,7 @@
     return super[index] = 0;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.UNDEFINED_SUPER_OPERATOR]);
   }
 
@@ -1767,7 +1764,7 @@
     super.m = 0;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.UNDEFINED_SUPER_SETTER]);
   }
 
@@ -1781,7 +1778,7 @@
     return a;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       StaticTypeWarningCode.UNQUALIFIED_REFERENCE_TO_NON_LOCAL_STATIC_MEMBER
     ]);
@@ -1798,7 +1795,7 @@
     a();
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       StaticTypeWarningCode.UNQUALIFIED_REFERENCE_TO_NON_LOCAL_STATIC_MEMBER
     ]);
@@ -1815,7 +1812,7 @@
     a = y;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       StaticTypeWarningCode.UNQUALIFIED_REFERENCE_TO_NON_LOCAL_STATIC_MEMBER
     ]);
@@ -1827,7 +1824,7 @@
 class A {}
 class M {}
 class B<F extends num> = A<F> with M;''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [StaticTypeWarningCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS]);
     verify([source]);
@@ -1837,7 +1834,7 @@
     Source source = addSource(r'''
 class A<E, F> {}
 A<A> a = null;''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [StaticTypeWarningCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS]);
     verify([source]);
@@ -1847,7 +1844,7 @@
     Source source = addSource(r'''
 class A<E> {}
 A<A, A> a = null;''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [StaticTypeWarningCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS]);
     verify([source]);
@@ -1860,7 +1857,7 @@
 f(p) {
   return p is C<A>;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [StaticTypeWarningCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS]);
     verify([source]);
@@ -1873,7 +1870,7 @@
 f(p) {
   return p is C<A, A>;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [StaticTypeWarningCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS]);
     verify([source]);
@@ -1885,7 +1882,7 @@
   yield 3;
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       StaticTypeWarningCode.YIELD_OF_INVALID_TYPE,
       StaticTypeWarningCode.ILLEGAL_ASYNC_GENERATOR_RETURN_TYPE
@@ -1899,7 +1896,7 @@
   yield 3;
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       StaticTypeWarningCode.YIELD_OF_INVALID_TYPE,
       StaticTypeWarningCode.ILLEGAL_ASYNC_GENERATOR_RETURN_TYPE
@@ -1914,7 +1911,7 @@
   yield "foo";
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.YIELD_OF_INVALID_TYPE]);
     verify([source]);
   }
@@ -1925,7 +1922,7 @@
   yield* 0;
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.YIELD_OF_INVALID_TYPE]);
     verify([source]);
   }
@@ -1938,7 +1935,7 @@
 }
 Stream<String> g() => null;
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.YIELD_OF_INVALID_TYPE]);
     verify([source]);
   }
@@ -1949,7 +1946,7 @@
   yield* 0;
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.YIELD_OF_INVALID_TYPE]);
     verify([source]);
   }
@@ -1961,7 +1958,7 @@
 }
 Iterable<String> g() => null;
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.YIELD_OF_INVALID_TYPE]);
     verify([source]);
   }
@@ -1972,7 +1969,7 @@
   yield 3;
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       StaticTypeWarningCode.YIELD_OF_INVALID_TYPE,
       StaticTypeWarningCode.ILLEGAL_SYNC_GENERATOR_RETURN_TYPE
@@ -1986,7 +1983,7 @@
   yield "foo";
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.YIELD_OF_INVALID_TYPE]);
     verify([source]);
   }
@@ -1998,7 +1995,7 @@
   yield 3;
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       StaticTypeWarningCode.YIELD_OF_INVALID_TYPE,
       StaticTypeWarningCode.ILLEGAL_SYNC_GENERATOR_RETURN_TYPE
diff --git a/pkg/analyzer/test/generated/static_warning_code_test.dart b/pkg/analyzer/test/generated/static_warning_code_test.dart
index 6df4785..c5bede5 100644
--- a/pkg/analyzer/test/generated/static_warning_code_test.dart
+++ b/pkg/analyzer/test/generated/static_warning_code_test.dart
@@ -21,7 +21,7 @@
   void fail_undefinedGetter() {
     Source source = addSource(r'''
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.UNDEFINED_GETTER]);
     verify([source]);
   }
@@ -31,7 +31,7 @@
 /** [m] xxx [new B.c] */
 class A {
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       StaticWarningCode.UNDEFINED_IDENTIFIER,
       StaticWarningCode.UNDEFINED_IDENTIFIER
@@ -44,7 +44,7 @@
 f(var p) {
   C.m = 0;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.UNDEFINED_SETTER]);
     verify([source]);
   }
@@ -60,7 +60,7 @@
     addNamedSource("/lib2.dart", r'''
 library lib2;
 class N {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.AMBIGUOUS_IMPORT]);
   }
 
@@ -75,7 +75,7 @@
     addNamedSource("/lib2.dart", r'''
 library lib2;
 class N {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       StaticWarningCode.AMBIGUOUS_IMPORT,
       CompileTimeErrorCode.EXTENDS_NON_CLASS
@@ -93,7 +93,7 @@
     addNamedSource("/lib2.dart", r'''
 library lib2;
 class N {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       StaticWarningCode.AMBIGUOUS_IMPORT,
       CompileTimeErrorCode.IMPLEMENTS_NON_CLASS
@@ -115,7 +115,7 @@
     Source partSource = addNamedSource("/part.dart", r'''
 part of lib;
 class A extends N {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(partSource, [
       StaticWarningCode.AMBIGUOUS_IMPORT,
       CompileTimeErrorCode.EXTENDS_NON_CLASS
@@ -134,7 +134,7 @@
     addNamedSource("/lib2.dart", r'''
 library lib2;
 class N {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.AMBIGUOUS_IMPORT]);
   }
 
@@ -149,7 +149,7 @@
     addNamedSource("/lib2.dart", r'''
 library lib2;
 class N {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.AMBIGUOUS_IMPORT]);
   }
 
@@ -164,7 +164,7 @@
     addNamedSource("/lib2.dart", r'''
 library lib2;
 class N {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.AMBIGUOUS_IMPORT]);
   }
 
@@ -187,7 +187,7 @@
     addNamedSource("/lib2.dart", r'''
 library lib2;
 class N {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       StaticWarningCode.AMBIGUOUS_IMPORT,
       StaticWarningCode.AMBIGUOUS_IMPORT,
@@ -211,7 +211,7 @@
     addNamedSource("/lib2.dart", r'''
 library lib2;
 class N {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.AMBIGUOUS_IMPORT]);
   }
 
@@ -227,7 +227,7 @@
     addNamedSource("/lib2.dart", r'''
 library lib2;
 class N {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.AMBIGUOUS_IMPORT]);
   }
 
@@ -243,7 +243,7 @@
     addNamedSource("/lib2.dart", r'''
 library lib2;
 var v;''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.AMBIGUOUS_IMPORT]);
   }
 
@@ -258,7 +258,7 @@
     addNamedSource("/lib2.dart", r'''
 library lib2;
 var v;''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.AMBIGUOUS_IMPORT]);
   }
 
@@ -276,7 +276,7 @@
     addNamedSource("/lib2.dart", r'''
 library lib2;
 f() {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.AMBIGUOUS_IMPORT]);
   }
 
@@ -293,7 +293,7 @@
 library lib2;
 class _A {}
 g(h(_A a)) {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     // The name _A is private to the library it's defined in, so this is a type
     // mismatch. Furthermore, the error message should mention both _A and the
     // filenames so the user can figure out what's going on.
@@ -315,7 +315,7 @@
 @A.fromInt('0')
 main() {
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]);
     verify([source]);
   }
@@ -328,7 +328,7 @@
 @A('0')
 main() {
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]);
     verify([source]);
   }
@@ -341,7 +341,7 @@
 f(A a) {
   a + '0';
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]);
     verify([source]);
   }
@@ -360,7 +360,7 @@
   A a = new A();
   a..  ma().mb(0);
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]);
     verify([source]);
   }
@@ -373,7 +373,7 @@
 main() {
   const A(42);
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE,
       CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH
@@ -389,7 +389,7 @@
 class B extends A {
   const B() : super(42);
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]);
     verify([source]);
   }
@@ -399,7 +399,7 @@
 main() {
   (int x) {} ('');
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]);
     verify([source]);
   }
@@ -412,7 +412,7 @@
 f(A a) {
   a['0'];
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]);
     verify([source]);
   }
@@ -425,7 +425,7 @@
 f(A a) {
   a('0');
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]);
     verify([source]);
   }
@@ -439,7 +439,7 @@
   A a = new A();
   a('0');
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]);
     verify([source]);
   }
@@ -449,7 +449,7 @@
 a(b(int p)) {
   b('0');
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]);
     verify([source]);
   }
@@ -461,7 +461,7 @@
     f(v);
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]);
     verify([source]);
   }
@@ -473,7 +473,7 @@
 main() {
   acceptFunNumOptBool(funNumBool);
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]);
     verify([source]);
   }
@@ -486,7 +486,7 @@
 f(A<String> a) {
   a.m(1);
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]);
     verify([source]);
   }
@@ -497,7 +497,7 @@
 main() {
   f(p: 42);
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]);
     verify([source]);
   }
@@ -508,7 +508,7 @@
 main() {
   f(42);
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]);
     verify([source]);
   }
@@ -519,7 +519,7 @@
 main() {
   f(42);
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]);
     verify([source]);
   }
@@ -530,7 +530,7 @@
 f(A<int> a) {
   a('1');
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]);
     verify([source]);
   }
@@ -543,7 +543,7 @@
   A a = getA();
   a('1');
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]);
     verify([source]);
   }
@@ -554,7 +554,7 @@
 f(A a) {
   a('1');
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]);
     verify([source]);
   }
@@ -567,7 +567,7 @@
 main() {
   new A<String>(42);
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]);
     verify([source]);
   }
@@ -580,7 +580,7 @@
 main() {
   new A(42);
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]);
     verify([source]);
   }
@@ -593,7 +593,7 @@
 main() {
   new A(42);
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]);
     verify([source]);
   }
@@ -605,7 +605,7 @@
   C = null;
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.ASSIGNMENT_TO_TYPE]);
   }
 
@@ -617,7 +617,7 @@
 f() {
   A.v = 1;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.ASSIGNMENT_TO_CONST]);
     verify([source]);
   }
@@ -630,7 +630,7 @@
 f() {
   A.v += 1;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.ASSIGNMENT_TO_CONST]);
     verify([source]);
   }
@@ -641,7 +641,7 @@
   const x = 0;
   x = 1;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.ASSIGNMENT_TO_CONST]);
     verify([source]);
   }
@@ -652,7 +652,7 @@
   const x = 0;
   x += 1;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.ASSIGNMENT_TO_CONST]);
     verify([source]);
   }
@@ -664,7 +664,7 @@
   E = null;
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.ASSIGNMENT_TO_TYPE]);
   }
 
@@ -677,7 +677,7 @@
   A a = new A();
   a.v = 1;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.ASSIGNMENT_TO_FINAL]);
     verify([source]);
   }
@@ -691,7 +691,7 @@
   A a = new A();
   a.v += 1;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.ASSIGNMENT_TO_FINAL]);
     verify([source]);
   }
@@ -702,7 +702,7 @@
   final x = 0;
   x = 1;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.ASSIGNMENT_TO_FINAL]);
     verify([source]);
   }
@@ -713,7 +713,7 @@
   final x = 0;
   x += 1;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.ASSIGNMENT_TO_FINAL]);
     verify([source]);
   }
@@ -724,7 +724,7 @@
   final x = 0;
   x--;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.ASSIGNMENT_TO_FINAL]);
     verify([source]);
   }
@@ -735,7 +735,7 @@
   final x = 0;
   x++;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.ASSIGNMENT_TO_FINAL]);
     verify([source]);
   }
@@ -746,7 +746,7 @@
   final x = 0;
   --x;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.ASSIGNMENT_TO_FINAL]);
     verify([source]);
   }
@@ -757,7 +757,7 @@
   final x = 0;
   ++x;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.ASSIGNMENT_TO_FINAL]);
     verify([source]);
   }
@@ -768,7 +768,7 @@
   final x = 0;
   x--;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.ASSIGNMENT_TO_FINAL]);
     verify([source]);
   }
@@ -779,7 +779,7 @@
   final x = 0;
   x++;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.ASSIGNMENT_TO_FINAL]);
     verify([source]);
   }
@@ -788,7 +788,7 @@
     Source source = addSource(r'''
 final x = 0;
 f() { x = 1; }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.ASSIGNMENT_TO_FINAL]);
     verify([source]);
   }
@@ -802,7 +802,7 @@
   A a = new A();
   a.x = 0;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.ASSIGNMENT_TO_FINAL_NO_SETTER]);
     verify([source]);
   }
@@ -818,7 +818,7 @@
 main() {
   B.a.x = 0;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.ASSIGNMENT_TO_FINAL_NO_SETTER]);
     verify([source]);
   }
@@ -829,7 +829,7 @@
 main() {
   f = null;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.ASSIGNMENT_TO_FUNCTION]);
     verify([source]);
   }
@@ -842,7 +842,7 @@
 f(A a) {
   a.m = () {};
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.ASSIGNMENT_TO_METHOD]);
     verify([source]);
   }
@@ -854,7 +854,7 @@
   F = null;
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.ASSIGNMENT_TO_TYPE]);
   }
 
@@ -866,7 +866,7 @@
   }
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.ASSIGNMENT_TO_TYPE]);
   }
 
@@ -880,7 +880,7 @@
       break;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.CASE_BLOCK_NOT_TERMINATED]);
     verify([source]);
   }
@@ -889,7 +889,7 @@
     Source source = addSource(r'''
 var A = 0;
 f(String s) { var x = s as A; }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.CAST_TO_NON_TYPE]);
     verify([source]);
   }
@@ -899,7 +899,7 @@
 class A {
   m();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [StaticWarningCode.CONCRETE_CLASS_WITH_ABSTRACT_MEMBER]);
     verify([source]);
@@ -914,7 +914,7 @@
     addNamedSource("/lib.dart", r'''
 library lib;
 class Future {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.CONFLICTING_DART_IMPORT]);
   }
 
@@ -926,7 +926,7 @@
 class B extends A {
   var v;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source,
         [StaticWarningCode.CONFLICTING_INSTANCE_GETTER_AND_SUPERCLASS_MEMBER]);
     verify([source]);
@@ -940,7 +940,7 @@
 class B extends A {
   get v => 0;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source,
         [StaticWarningCode.CONFLICTING_INSTANCE_GETTER_AND_SUPERCLASS_MEMBER]);
     verify([source]);
@@ -954,7 +954,7 @@
 class B extends A {
   get v => 0;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source,
         [StaticWarningCode.CONFLICTING_INSTANCE_GETTER_AND_SUPERCLASS_MEMBER]);
     verify([source]);
@@ -968,7 +968,7 @@
 class B extends A {
   get v => 0;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source,
         [StaticWarningCode.CONFLICTING_INSTANCE_GETTER_AND_SUPERCLASS_MEMBER]);
     verify([source]);
@@ -983,7 +983,7 @@
 class C extends B {
   get v => 0;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source,
         [StaticWarningCode.CONFLICTING_INSTANCE_GETTER_AND_SUPERCLASS_MEMBER]);
     verify([source]);
@@ -997,7 +997,7 @@
 class B extends Object with M {
   get v => 0;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source,
         [StaticWarningCode.CONFLICTING_INSTANCE_GETTER_AND_SUPERCLASS_MEMBER]);
     verify([source]);
@@ -1011,7 +1011,7 @@
 class B extends A {
   get v => 0;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source,
         [StaticWarningCode.CONFLICTING_INSTANCE_GETTER_AND_SUPERCLASS_MEMBER]);
     verify([source]);
@@ -1023,7 +1023,7 @@
   foo() {}
   set foo(a) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [StaticWarningCode.CONFLICTING_INSTANCE_METHOD_SETTER2]);
     verify([source]);
@@ -1035,7 +1035,7 @@
   set foo(a) {}
   foo() {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [StaticWarningCode.CONFLICTING_INSTANCE_METHOD_SETTER]);
     verify([source]);
@@ -1049,7 +1049,7 @@
 abstract class B implements A {
   foo() {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [StaticWarningCode.CONFLICTING_INSTANCE_METHOD_SETTER]);
     verify([source]);
@@ -1063,7 +1063,7 @@
 class B extends A {
   foo() {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [StaticWarningCode.CONFLICTING_INSTANCE_METHOD_SETTER]);
     verify([source]);
@@ -1077,7 +1077,7 @@
 class B extends A {
   set v(x) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source,
         [StaticWarningCode.CONFLICTING_INSTANCE_SETTER_AND_SUPERCLASS_MEMBER]);
     verify([source]);
@@ -1091,7 +1091,7 @@
 class B extends Object with A {
   static get x => 0;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source,
         [StaticWarningCode.CONFLICTING_STATIC_GETTER_AND_INSTANCE_SETTER]);
     verify([source]);
@@ -1105,7 +1105,7 @@
 class B extends A {
   static get x => 0;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source,
         [StaticWarningCode.CONFLICTING_STATIC_GETTER_AND_INSTANCE_SETTER]);
     verify([source]);
@@ -1117,7 +1117,7 @@
   static get x => 0;
   set x(int p) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source,
         [StaticWarningCode.CONFLICTING_STATIC_GETTER_AND_INSTANCE_SETTER]);
     verify([source]);
@@ -1129,7 +1129,7 @@
   get x => 0;
   static set x(int p) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source,
         [StaticWarningCode.CONFLICTING_STATIC_SETTER_AND_INSTANCE_MEMBER]);
     verify([source]);
@@ -1141,7 +1141,7 @@
   x() {}
   static set x(int p) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source,
         [StaticWarningCode.CONFLICTING_STATIC_SETTER_AND_INSTANCE_MEMBER]);
     verify([source]);
@@ -1155,14 +1155,14 @@
 void f() {
   A a = const A();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.CONST_WITH_ABSTRACT_CLASS]);
     verify([source]);
   }
 
   void test_equalKeysInMap() {
     Source source = addSource("var m = {'a' : 0, 'b' : 1, 'a' : 2};");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.EQUAL_KEYS_IN_MAP]);
     verify([source]);
   }
@@ -1173,7 +1173,7 @@
   const A();
 }
 var m = {const A<int>(): 0, const A<int>(): 1};''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.EQUAL_KEYS_IN_MAP]);
     verify([source]);
   }
@@ -1186,7 +1186,7 @@
   const A();
 }
 var m = {const A<int>(): 0, const A<num>(): 1};''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -1198,7 +1198,7 @@
 export 'lib2.dart';''');
     addNamedSource("/lib1.dart", "library lib;");
     addNamedSource("/lib2.dart", "library lib;");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.EXPORT_DUPLICATED_LIBRARY_NAMED]);
     verify([source]);
   }
@@ -1210,7 +1210,7 @@
 export 'lib2.dart';''');
     addNamedSource("/lib1.dart", "");
     addNamedSource("/lib2.dart", "");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.EXPORT_DUPLICATED_LIBRARY_UNNAMED]);
     verify([source]);
   }
@@ -1221,7 +1221,7 @@
 main() {
   f(0, 1, '2');
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.EXTRA_POSITIONAL_ARGUMENTS]);
     verify([source]);
   }
@@ -1231,7 +1231,7 @@
 main() {
   (int x) {} (0, 1);
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.EXTRA_POSITIONAL_ARGUMENTS]);
     verify([source]);
   }
@@ -1242,7 +1242,7 @@
   final int x = 0;
   A() : x = 1 {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source,
         [StaticWarningCode.FIELD_INITIALIZED_IN_INITIALIZER_AND_DECLARATION]);
     verify([source]);
@@ -1254,7 +1254,7 @@
   int x;
   A() : x = '';
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.FIELD_INITIALIZER_NOT_ASSIGNABLE]);
     verify([source]);
   }
@@ -1265,7 +1265,7 @@
   int x;
   A(String this.x) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [StaticWarningCode.FIELD_INITIALIZING_FORMAL_NOT_ASSIGNABLE]);
     verify([source]);
@@ -1286,7 +1286,7 @@
   final x = 0;
   A() : x = 0 {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source,
         [StaticWarningCode.FIELD_INITIALIZED_IN_INITIALIZER_AND_DECLARATION]);
     verify([source]);
@@ -1298,7 +1298,7 @@
   final x = 0;
   A(this.x) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source,
         [StaticWarningCode.FINAL_INITIALIZED_IN_DECLARATION_AND_CONSTRUCTOR]);
     verify([source]);
@@ -1310,7 +1310,7 @@
   final int x;
   A() {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [StaticWarningCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_1]);
     verify([source]);
@@ -1323,7 +1323,7 @@
   final int b;
   A() {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [StaticWarningCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_2]);
     verify([source]);
@@ -1337,7 +1337,7 @@
   final int c;
   A() {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [StaticWarningCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_3_PLUS]);
     verify([source]);
@@ -1348,7 +1348,7 @@
 class A {
   final F;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.FINAL_NOT_INITIALIZED]);
     verify([source]);
   }
@@ -1358,14 +1358,14 @@
 class A {
   static final F;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.FINAL_NOT_INITIALIZED]);
     verify([source]);
   }
 
   void test_finalNotInitialized_library_final() {
     Source source = addSource("final F;");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.FINAL_NOT_INITIALIZED]);
     verify([source]);
   }
@@ -1375,7 +1375,7 @@
 f() {
   final int x;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.FINAL_NOT_INITIALIZED]);
     verify([source]);
   }
@@ -1384,7 +1384,7 @@
     Source source = addSource(r'''
 class A implements Function {
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.FUNCTION_WITHOUT_CALL]);
     verify([source]);
   }
@@ -1395,7 +1395,7 @@
 }
 class B extends A {
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.FUNCTION_WITHOUT_CALL]);
     verify([source]);
   }
@@ -1406,7 +1406,7 @@
 }
 class B implements A {
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.FUNCTION_WITHOUT_CALL]);
     verify([source]);
   }
@@ -1418,7 +1418,7 @@
 import 'lib2.dart';''');
     addNamedSource("/lib1.dart", "library lib;");
     addNamedSource("/lib2.dart", "library lib;");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       StaticWarningCode.IMPORT_DUPLICATED_LIBRARY_NAMED,
       HintCode.UNUSED_IMPORT,
@@ -1434,7 +1434,7 @@
 import 'lib2.dart';''');
     addNamedSource("/lib1.dart", "");
     addNamedSource("/lib2.dart", "");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       StaticWarningCode.IMPORT_DUPLICATED_LIBRARY_UNNAMED,
       HintCode.UNUSED_IMPORT,
@@ -1465,7 +1465,7 @@
 }
 class C implements A, B {
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source,
         [StaticWarningCode.INCONSISTENT_METHOD_INHERITANCE_GETTER_AND_METHOD]);
     verify([source]);
@@ -1479,7 +1479,7 @@
 class B extends A {
   void n() {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       StaticWarningCode.INSTANCE_METHOD_NAME_COLLIDES_WITH_SUPERCLASS_STATIC
     ]);
@@ -1496,7 +1496,7 @@
 class C extends B {
   void n() {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       StaticWarningCode.INSTANCE_METHOD_NAME_COLLIDES_WITH_SUPERCLASS_STATIC
     ]);
@@ -1511,7 +1511,7 @@
 class B extends A {
   void n() {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       StaticWarningCode.INSTANCE_METHOD_NAME_COLLIDES_WITH_SUPERCLASS_STATIC
     ]);
@@ -1528,7 +1528,7 @@
 class C extends B {
   void n() {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       StaticWarningCode.INSTANCE_METHOD_NAME_COLLIDES_WITH_SUPERCLASS_STATIC
     ]);
@@ -1547,7 +1547,7 @@
   foo() {}
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       StaticWarningCode.INSTANCE_METHOD_NAME_COLLIDES_WITH_SUPERCLASS_STATIC
     ]);
@@ -1562,7 +1562,7 @@
 class B extends A {
   void n() {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       StaticWarningCode.INSTANCE_METHOD_NAME_COLLIDES_WITH_SUPERCLASS_STATIC
     ]);
@@ -1579,7 +1579,7 @@
 class C extends B {
   void n() {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       StaticWarningCode.INSTANCE_METHOD_NAME_COLLIDES_WITH_SUPERCLASS_STATIC
     ]);
@@ -1594,7 +1594,7 @@
 class B extends A {
   void n() {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       StaticWarningCode.INSTANCE_METHOD_NAME_COLLIDES_WITH_SUPERCLASS_STATIC
     ]);
@@ -1611,7 +1611,7 @@
 class C extends B {
   void n() {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       StaticWarningCode.INSTANCE_METHOD_NAME_COLLIDES_WITH_SUPERCLASS_STATIC
     ]);
@@ -1626,7 +1626,7 @@
 class B extends A {
   String get g { return 'a'; }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [StaticWarningCode.INVALID_GETTER_OVERRIDE_RETURN_TYPE]);
     verify([source]);
@@ -1640,7 +1640,7 @@
 class B extends A {
   int f;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       StaticWarningCode.INVALID_GETTER_OVERRIDE_RETURN_TYPE,
       StaticWarningCode.INVALID_SETTER_OVERRIDE_NORMAL_PARAM_TYPE
@@ -1661,7 +1661,7 @@
 class B extends A {
   String get getter => null;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [StaticWarningCode.INVALID_GETTER_OVERRIDE_RETURN_TYPE]);
     verify([source]);
@@ -1678,7 +1678,7 @@
 class B implements I<int>, J<String> {
   double get g => null;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [StaticWarningCode.INVALID_GETTER_OVERRIDE_RETURN_TYPE]);
     verify([source]);
@@ -1692,7 +1692,7 @@
 class B implements A {
   m({String a}) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [StaticWarningCode.INVALID_METHOD_OVERRIDE_NAMED_PARAM_TYPE]);
     verify([source]);
@@ -1706,7 +1706,7 @@
 class B implements A {
   m(String a) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [StaticWarningCode.INVALID_METHOD_OVERRIDE_NORMAL_PARAM_TYPE]);
     verify([source]);
@@ -1720,7 +1720,7 @@
 class B extends A {
   m(String a) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [StaticWarningCode.INVALID_METHOD_OVERRIDE_NORMAL_PARAM_TYPE]);
     verify([source]);
@@ -1737,7 +1737,7 @@
 class B extends I<int> implements J<String> {
   m(double d) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [StaticWarningCode.INVALID_METHOD_OVERRIDE_NORMAL_PARAM_TYPE]);
     verify([source]);
@@ -1755,7 +1755,7 @@
 class B extends A {
   m(String n) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [StaticWarningCode.INVALID_METHOD_OVERRIDE_NORMAL_PARAM_TYPE]);
     verify([source]);
@@ -1773,7 +1773,7 @@
 class B implements I<int>, J<String> {
   m(double d) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [StaticWarningCode.INVALID_METHOD_OVERRIDE_NORMAL_PARAM_TYPE]);
     verify([source]);
@@ -1787,7 +1787,7 @@
 class B implements A {
   m([String a]) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source,
         [StaticWarningCode.INVALID_METHOD_OVERRIDE_OPTIONAL_PARAM_TYPE]);
     verify([source]);
@@ -1805,7 +1805,7 @@
 class B extends A {
   m([String n]) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source,
         [StaticWarningCode.INVALID_METHOD_OVERRIDE_OPTIONAL_PARAM_TYPE]);
     verify([source]);
@@ -1819,7 +1819,7 @@
 class B implements A {
   String m() { return 'a'; }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [StaticWarningCode.INVALID_METHOD_OVERRIDE_RETURN_TYPE]);
     verify([source]);
@@ -1835,7 +1835,7 @@
 class C implements B {
   String m() { return 'a'; }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [StaticWarningCode.INVALID_METHOD_OVERRIDE_RETURN_TYPE]);
     verify([source]);
@@ -1849,7 +1849,7 @@
 class B extends Object with A {
   String m() { return 'a'; }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [StaticWarningCode.INVALID_METHOD_OVERRIDE_RETURN_TYPE]);
     verify([source]);
@@ -1863,7 +1863,7 @@
 class B extends A {
   String m() { return 'a'; }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [StaticWarningCode.INVALID_METHOD_OVERRIDE_RETURN_TYPE]);
     verify([source]);
@@ -1879,7 +1879,7 @@
 class C extends B {
   String m() { return 'a'; }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [StaticWarningCode.INVALID_METHOD_OVERRIDE_RETURN_TYPE]);
     verify([source]);
@@ -1897,7 +1897,7 @@
 class B extends A {
   String m() => '';
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [StaticWarningCode.INVALID_METHOD_OVERRIDE_RETURN_TYPE]);
     verify([source]);
@@ -1911,7 +1911,7 @@
 class B extends A {
   void m() {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [StaticWarningCode.INVALID_METHOD_OVERRIDE_RETURN_TYPE]);
     verify([source]);
@@ -1929,7 +1929,7 @@
   foo([x]) {}
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       StaticWarningCode.INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_POSITIONAL
     ]);
@@ -1948,7 +1948,7 @@
   foo({x}) {}
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source,
         [StaticWarningCode.INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_NAMED]);
     verify([source]);
@@ -1967,7 +1967,7 @@
   foo([x]) {}
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -1985,7 +1985,7 @@
   foo({x}) {}
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -2002,7 +2002,7 @@
   foo([x = 1]) {}
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -2019,7 +2019,7 @@
   foo({x: 1}) {}
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertNoErrors(source);
     verify([source]);
   }
@@ -2032,7 +2032,7 @@
 class B extends A {
   m({int p : 1}) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source,
         [StaticWarningCode.INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_NAMED]);
     verify([source]);
@@ -2046,7 +2046,7 @@
 class B extends A {
   m([int p = 1]) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       StaticWarningCode.INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_POSITIONAL
     ]);
@@ -2061,7 +2061,7 @@
 class B extends A {
   m({a}) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.INVALID_OVERRIDE_NAMED]);
     verify([source]);
   }
@@ -2074,7 +2074,7 @@
 class B extends A {
   m({a, c}) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.INVALID_OVERRIDE_NAMED]);
     verify([source]);
   }
@@ -2087,7 +2087,7 @@
 class B extends A {
   m([a]) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.INVALID_OVERRIDE_POSITIONAL]);
     verify([source]);
   }
@@ -2100,7 +2100,7 @@
 class B extends A {
   m(a, b, [c]) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.INVALID_OVERRIDE_POSITIONAL]);
     verify([source]);
   }
@@ -2113,7 +2113,7 @@
 class B extends A {
   m(a, [c, d]) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.INVALID_OVERRIDE_POSITIONAL]);
     verify([source]);
   }
@@ -2126,7 +2126,7 @@
 class B extends A {
   m(a, b) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.INVALID_OVERRIDE_REQUIRED]);
     verify([source]);
   }
@@ -2139,7 +2139,7 @@
 class B extends A {
   void set s(String v) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [StaticWarningCode.INVALID_SETTER_OVERRIDE_NORMAL_PARAM_TYPE]);
     verify([source]);
@@ -2157,7 +2157,7 @@
 class B extends A {
   set setter14(String _) => null;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [StaticWarningCode.INVALID_SETTER_OVERRIDE_NORMAL_PARAM_TYPE]);
     verify([source]);
@@ -2176,7 +2176,7 @@
 class B extends A {
   set setter14(String _) => null;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [StaticWarningCode.INVALID_SETTER_OVERRIDE_NORMAL_PARAM_TYPE]);
     verify([source]);
@@ -2193,7 +2193,7 @@
 class B implements I<int>, J<String> {
   set s(double d) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [StaticWarningCode.INVALID_SETTER_OVERRIDE_NORMAL_PARAM_TYPE]);
     verify([source]);
@@ -2201,21 +2201,21 @@
 
   void test_listElementTypeNotAssignable() {
     Source source = addSource("var v = <String> [42];");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE]);
     verify([source]);
   }
 
   void test_mapKeyTypeNotAssignable() {
     Source source = addSource("var v = <String, int > {1 : 2};");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE]);
     verify([source]);
   }
 
   void test_mapValueTypeNotAssignable() {
     Source source = addSource("var v = <String, String> {'a' : 2};");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE]);
     verify([source]);
   }
@@ -2226,7 +2226,7 @@
   int get g { return 0; }
   set g(String v) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [StaticWarningCode.MISMATCHED_GETTER_AND_SETTER_TYPES]);
     verify([source]);
@@ -2240,7 +2240,7 @@
 class B extends A {
   set g(String v) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source,
         [StaticWarningCode.MISMATCHED_GETTER_AND_SETTER_TYPES_FROM_SUPERTYPE]);
     verify([source]);
@@ -2254,7 +2254,7 @@
 class B extends A {
   String get g { return ''; }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source,
         [StaticWarningCode.MISMATCHED_GETTER_AND_SETTER_TYPES_FROM_SUPERTYPE]);
     verify([source]);
@@ -2264,7 +2264,7 @@
     Source source = addSource(r'''
 int get g { return 0; }
 set g(String v) {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [StaticWarningCode.MISMATCHED_GETTER_AND_SETTER_TYPES]);
     verify([source]);
@@ -2282,7 +2282,7 @@
     };
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       StaticWarningCode.MIXED_RETURN_TYPES,
       StaticWarningCode.MIXED_RETURN_TYPES
@@ -2300,7 +2300,7 @@
     return 0;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       StaticWarningCode.MIXED_RETURN_TYPES,
       StaticWarningCode.MIXED_RETURN_TYPES
@@ -2316,7 +2316,7 @@
   }
   return 0;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       StaticWarningCode.MIXED_RETURN_TYPES,
       StaticWarningCode.MIXED_RETURN_TYPES
@@ -2330,7 +2330,7 @@
 void f() {
   A a = new A();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.NEW_WITH_ABSTRACT_CLASS]);
     verify([source]);
   }
@@ -2339,7 +2339,7 @@
     Source source = addSource(r'''
 class A {}
 f() { return new A<A>(); }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.NEW_WITH_INVALID_TYPE_PARAMETERS]);
     verify([source]);
   }
@@ -2351,7 +2351,7 @@
 f(p) {
   return new C<A>();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.NEW_WITH_INVALID_TYPE_PARAMETERS]);
     verify([source]);
   }
@@ -2363,7 +2363,7 @@
 f(p) {
   return new C<A, A>();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.NEW_WITH_INVALID_TYPE_PARAMETERS]);
     verify([source]);
   }
@@ -2374,7 +2374,7 @@
 void f() {
   var a = new A();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.NEW_WITH_NON_TYPE]);
     verify([source]);
   }
@@ -2387,8 +2387,8 @@
   var a = new lib.A();
 }
 lib.B b;''');
-    resolve(source1);
-    resolve(source2);
+    computeLibrarySourceErrors(source1);
+    computeLibrarySourceErrors(source2);
     assertErrors(source2, [StaticWarningCode.NEW_WITH_NON_TYPE]);
     verify([source1]);
   }
@@ -2401,7 +2401,7 @@
 f() {
   new A.name();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.NEW_WITH_UNDEFINED_CONSTRUCTOR]);
     // no verify(), 'name' is not resolved
   }
@@ -2414,7 +2414,7 @@
 f() {
   new A();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [StaticWarningCode.NEW_WITH_UNDEFINED_CONSTRUCTOR_DEFAULT]);
     verify([source]);
@@ -2431,7 +2431,7 @@
 }
 class C extends A {
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [
       StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_FIVE_PLUS
     ]);
@@ -2448,7 +2448,7 @@
 }
 class C extends A {
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source,
         [StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_FOUR]);
     verify([source]);
@@ -2463,7 +2463,7 @@
   m();
 }
 class B = A with M implements I;''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source,
         [StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE]);
     verify([source]);
@@ -2477,7 +2477,7 @@
 }
 abstract class A {}
 class B = A with M;''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source,
         [StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE]);
     verify([source]);
@@ -2491,7 +2491,7 @@
   m();
 }
 class B = A with M;''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source,
         [StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE]);
     verify([source]);
@@ -2507,7 +2507,7 @@
   foo(x, [y]);
 }
 class E extends C implements D {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source,
         [StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE]);
     verify([source]);
@@ -2520,7 +2520,7 @@
 }
 class C implements I {
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source,
         [StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE]);
     verify([source]);
@@ -2533,7 +2533,7 @@
 }
 class C extends A {
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source,
         [StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE]);
     verify([source]);
@@ -2546,7 +2546,7 @@
 }
 class C implements I {
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source,
         [StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE]);
     verify([source]);
@@ -2559,7 +2559,7 @@
 }
 class C extends A {
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source,
         [StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE]);
     verify([source]);
@@ -2576,7 +2576,7 @@
 }
 class C implements A, B {
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source,
         [StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE]);
     verify([source]);
@@ -2588,7 +2588,7 @@
 abstract class A { get g1; get g2; }
 abstract class B implements A { get g1 => 1; }
 class C extends Object with B {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source,
         [StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE]);
   }
@@ -2599,7 +2599,7 @@
 abstract class A { m1(); m2(); }
 abstract class B implements A { m1() => 1; }
 class C extends Object with B {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source,
         [StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE]);
   }
@@ -2610,7 +2610,7 @@
 abstract class A { set s1(v); set s2(v); }
 abstract class B implements A { set s1(v) {} }
 class C extends Object with B {}''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source,
         [StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE]);
   }
@@ -2627,7 +2627,7 @@
 class B extends A implements I {
   get field => 0;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source,
         [StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE]);
     verify([source]);
@@ -2640,7 +2640,7 @@
 }
 class C implements I {
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source,
         [StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE]);
     verify([source]);
@@ -2653,7 +2653,7 @@
 }
 class C extends A {
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source,
         [StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE]);
     verify([source]);
@@ -2670,7 +2670,7 @@
 }
 class C extends B {
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source,
         [StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE]);
     verify([source]);
@@ -2685,7 +2685,7 @@
 class C implements I {
   set v(_) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source,
         [StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE]);
     verify([source]);
@@ -2700,7 +2700,7 @@
 class C implements I {
   get v => 1;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source,
         [StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE]);
     verify([source]);
@@ -2715,7 +2715,7 @@
 }
 class C extends A {
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source,
         [StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_THREE]);
     verify([source]);
@@ -2729,7 +2729,7 @@
 }
 class C extends A {
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source,
         [StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_TWO]);
     verify([source]);
@@ -2743,7 +2743,7 @@
 }
 class C implements I {
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source,
         [StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_TWO]);
     verify([source]);
@@ -2756,7 +2756,7 @@
   } on T catch (e) {
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.NON_TYPE_IN_CATCH_CLAUSE]);
     verify([source]);
   }
@@ -2769,7 +2769,7 @@
   } on T catch (e) {
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.NON_TYPE_IN_CATCH_CLAUSE]);
     verify([source]);
   }
@@ -2779,7 +2779,7 @@
 class A {
   int operator []=(a, b) { return a; }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.NON_VOID_RETURN_FOR_OPERATOR]);
     verify([source]);
   }
@@ -2789,7 +2789,7 @@
 int set x(int v) {
   return 42;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.NON_VOID_RETURN_FOR_SETTER]);
     verify([source]);
   }
@@ -2801,7 +2801,7 @@
     return 42;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.NON_VOID_RETURN_FOR_SETTER]);
     verify([source]);
   }
@@ -2812,7 +2812,7 @@
 main() {
   f v = null;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.NOT_A_TYPE]);
     verify([source]);
   }
@@ -2823,7 +2823,7 @@
 main() {
   f();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.NOT_ENOUGH_REQUIRED_ARGUMENTS]);
     verify([source]);
   }
@@ -2833,7 +2833,7 @@
 main() {
   (int x) {} ();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.NOT_ENOUGH_REQUIRED_ARGUMENTS]);
     verify([source]);
   }
@@ -2845,7 +2845,7 @@
 main() {
   getter();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.NOT_ENOUGH_REQUIRED_ARGUMENTS]);
     verify([source]);
   }
@@ -2855,7 +2855,7 @@
 library lib;
 part 'part.dart';''');
     addNamedSource("/part.dart", "part of lub;");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.PART_OF_DIFFERENT_LIBRARY]);
     verify([source]);
   }
@@ -2868,7 +2868,7 @@
 class B {
   factory B() = A;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.REDIRECT_TO_INVALID_FUNCTION_TYPE]);
     verify([source]);
   }
@@ -2881,7 +2881,7 @@
 class B {
   factory B() = A;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.REDIRECT_TO_INVALID_RETURN_TYPE]);
     verify([source]);
   }
@@ -2894,7 +2894,7 @@
 class B {
   factory B() = A.name;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.REDIRECT_TO_MISSING_CONSTRUCTOR]);
   }
 
@@ -2906,7 +2906,7 @@
 class B {
   factory B() = A;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.REDIRECT_TO_MISSING_CONSTRUCTOR]);
   }
 
@@ -2916,7 +2916,7 @@
   int A;
   factory B() = A;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.REDIRECT_TO_NON_CLASS]);
     verify([source]);
   }
@@ -2926,7 +2926,7 @@
 class B {
   factory B() = A;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.REDIRECT_TO_NON_CLASS]);
     verify([source]);
   }
@@ -2938,28 +2938,28 @@
   return;
 }
 ''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.RETURN_WITHOUT_VALUE]);
     verify([source]);
   }
 
   void test_returnWithoutValue_factoryConstructor() {
     Source source = addSource("class A { factory A() { return; } }");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.RETURN_WITHOUT_VALUE]);
     verify([source]);
   }
 
   void test_returnWithoutValue_function() {
     Source source = addSource("int f() { return; }");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.RETURN_WITHOUT_VALUE]);
     verify([source]);
   }
 
   void test_returnWithoutValue_method() {
     Source source = addSource("class A { int m() { return; } }");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.RETURN_WITHOUT_VALUE]);
     verify([source]);
   }
@@ -2974,7 +2974,7 @@
   }
   return;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.RETURN_WITHOUT_VALUE]);
     verify([source]);
   }
@@ -2987,7 +2987,7 @@
 main() {
   A.m();
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.STATIC_ACCESS_TO_INSTANCE_MEMBER]);
     verify([source]);
   }
@@ -3000,7 +3000,7 @@
 main() {
   A.m;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.STATIC_ACCESS_TO_INSTANCE_MEMBER]);
     verify([source]);
   }
@@ -3013,7 +3013,7 @@
 main() {
   A.f;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.STATIC_ACCESS_TO_INSTANCE_MEMBER]);
     verify([source]);
   }
@@ -3026,7 +3026,7 @@
 main() {
   A.f;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.STATIC_ACCESS_TO_INSTANCE_MEMBER]);
     verify([source]);
   }
@@ -3039,7 +3039,7 @@
 main() {
   A.f = 42;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.STATIC_ACCESS_TO_INSTANCE_MEMBER]);
     verify([source]);
   }
@@ -3051,7 +3051,7 @@
     case 'a': break;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.SWITCH_EXPRESSION_NOT_ASSIGNABLE]);
     verify([source]);
   }
@@ -3223,7 +3223,7 @@
 class A<K> {
   static K k;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [StaticWarningCode.TYPE_PARAMETER_REFERENCED_BY_STATIC]);
     verify([source]);
@@ -3234,7 +3234,7 @@
 class A<K> {
   static K get k => null;
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [StaticWarningCode.TYPE_PARAMETER_REFERENCED_BY_STATIC]);
     verify([source]);
@@ -3247,7 +3247,7 @@
     K k;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [StaticWarningCode.TYPE_PARAMETER_REFERENCED_BY_STATIC]);
     verify([source]);
@@ -3258,7 +3258,7 @@
 class A<K> {
   static m(K k) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [StaticWarningCode.TYPE_PARAMETER_REFERENCED_BY_STATIC]);
     verify([source]);
@@ -3269,7 +3269,7 @@
 class A<K> {
   static K m() { return null; }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [StaticWarningCode.TYPE_PARAMETER_REFERENCED_BY_STATIC]);
     verify([source]);
@@ -3280,7 +3280,7 @@
 class A<K> {
   static set s(K k) {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(
         source, [StaticWarningCode.TYPE_PARAMETER_REFERENCED_BY_STATIC]);
     verify([source]);
@@ -3297,7 +3297,7 @@
     f(new B());
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]);
   }
 
@@ -3308,7 +3308,7 @@
   if (p is A) {
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.TYPE_TEST_WITH_NON_TYPE]);
     verify([source]);
   }
@@ -3319,26 +3319,26 @@
   if (p is A) {
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.TYPE_TEST_WITH_UNDEFINED_NAME]);
     verify([source]);
   }
 
   void test_undefinedClass_instanceCreation() {
     Source source = addSource("f() { new C(); }");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.UNDEFINED_CLASS]);
   }
 
   void test_undefinedClass_variableDeclaration() {
     Source source = addSource("f() { C c; }");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.UNDEFINED_CLASS]);
   }
 
   void test_undefinedClassBoolean_variableDeclaration() {
     Source source = addSource("f() { boolean v; }");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.UNDEFINED_CLASS_BOOLEAN]);
   }
 
@@ -3349,8 +3349,8 @@
 void f() {
   var g = lib.gg;
 }''');
-    resolve(source1);
-    resolve(source2);
+    computeLibrarySourceErrors(source1);
+    computeLibrarySourceErrors(source2);
     assertErrors(source2, [StaticWarningCode.UNDEFINED_GETTER]);
     verify([source1]);
   }
@@ -3361,52 +3361,36 @@
   for (e in l) {
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.UNDEFINED_IDENTIFIER]);
   }
 
   void test_undefinedIdentifier_function() {
     Source source = addSource("int a() => b;");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.UNDEFINED_IDENTIFIER]);
   }
 
-  void test_undefinedIdentifier_function_prefix() {
-    addNamedSource("/lib.dart", r'''
-library lib;
-class C {}''');
+  void test_undefinedIdentifier_importCore_withShow() {
     Source source = addSource(r'''
-import 'lib.dart' as b;
-
-int a() => b;
-b.C c;''');
-    resolve(source);
+import 'dart:core' show List;
+main() {
+  List;
+  String;
+}''');
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.UNDEFINED_IDENTIFIER]);
-    verify([source]);
   }
 
   void test_undefinedIdentifier_initializer() {
     Source source = addSource("var a = b;");
-    resolve(source);
-    assertErrors(source, [StaticWarningCode.UNDEFINED_IDENTIFIER]);
-  }
-
-  void test_undefinedIdentifier_initializer_prefix() {
-    addNamedSource("/lib.dart", r'''
-library lib;
-class C {}''');
-    Source source = addSource(r'''
-import 'lib.dart' as b;
-
-var a = b;
-b.C c;''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.UNDEFINED_IDENTIFIER]);
   }
 
   void test_undefinedIdentifier_methodInvocation() {
     Source source = addSource("f() { C.m(); }");
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.UNDEFINED_IDENTIFIER]);
   }
 
@@ -3423,7 +3407,7 @@
     var v = _foo;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.UNDEFINED_IDENTIFIER]);
   }
 
@@ -3440,7 +3424,7 @@
     _foo = 42;
   }
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.UNDEFINED_IDENTIFIER]);
   }
 
@@ -3450,7 +3434,7 @@
 main() {
   f(c: 1);
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.UNDEFINED_NAMED_PARAMETER]);
     // no verify(), 'c' is not resolved
   }
@@ -3462,8 +3446,8 @@
 void f() {
   lib.gg = null;
 }''');
-    resolve(source1);
-    resolve(source2);
+    computeLibrarySourceErrors(source1);
+    computeLibrarySourceErrors(source2);
     assertErrors(source2, [StaticWarningCode.UNDEFINED_SETTER]);
   }
 
@@ -3473,7 +3457,7 @@
 f(var p) {
   f(C.m);
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.UNDEFINED_GETTER]);
   }
 
@@ -3486,7 +3470,7 @@
 f(var p) {
   f(C.g);
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.UNDEFINED_GETTER]);
   }
 
@@ -3496,7 +3480,7 @@
 f(var p) {
   f(C.m());
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.UNDEFINED_METHOD]);
   }
 
@@ -3509,7 +3493,7 @@
 f(var p) {
   f(C.m());
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.UNDEFINED_METHOD]);
   }
 
@@ -3522,7 +3506,7 @@
 f(var p) {
   f(C.s = 1);
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticTypeWarningCode.UNDEFINED_SETTER]);
   }
 
@@ -3531,7 +3515,7 @@
 class S {
   void get value {}
 }''');
-    resolve(source);
+    computeLibrarySourceErrors(source);
     assertErrors(source, [StaticWarningCode.VOID_RETURN_FOR_GETTER]);
   }
 }
diff --git a/pkg/analyzer/test/generated/test_all.dart b/pkg/analyzer/test/generated/test_all.dart
index b632b51..33435d4 100644
--- a/pkg/analyzer/test/generated/test_all.dart
+++ b/pkg/analyzer/test/generated/test_all.dart
@@ -19,8 +19,10 @@
 import 'parser_test.dart' as parser_test;
 import 'resolver_test.dart' as resolver_test;
 import 'scanner_test.dart' as scanner_test;
+import 'source_factory_test.dart' as source_factory_test;
 import 'static_type_warning_code_test.dart' as static_type_warning_code_test;
 import 'static_warning_code_test.dart' as static_warning_code_test;
+import 'type_system_test.dart' as type_system_test;
 import 'utilities_test.dart' as utilities_test;
 
 /// Utility for manually running all tests.
@@ -40,8 +42,10 @@
     parser_test.main();
     resolver_test.main();
     scanner_test.main();
+    source_factory_test.main();
     static_type_warning_code_test.main();
     static_warning_code_test.main();
+    type_system_test.main();
     utilities_test.main();
   });
 }
diff --git a/pkg/analyzer/test/generated/type_system_test.dart b/pkg/analyzer/test/generated/type_system_test.dart
new file mode 100644
index 0000000..5077871
--- /dev/null
+++ b/pkg/analyzer/test/generated/type_system_test.dart
@@ -0,0 +1,357 @@
+// 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.
+
+// Tests related to the [TypeSystem] class.
+
+library engine.type_system_test;
+
+import 'package:analyzer/src/generated/element.dart';
+import 'package:analyzer/src/generated/resolver.dart';
+import 'package:analyzer/src/generated/testing/element_factory.dart';
+import 'package:analyzer/src/generated/testing/test_type_provider.dart';
+import 'package:unittest/unittest.dart';
+
+import '../reflective_tests.dart';
+
+main() {
+  groupSep = ' | ';
+  runReflectiveTests(TypeSystemTest);
+}
+
+@reflectiveTest
+class TypeSystemTest {
+  TypeProvider typeProvider;
+  TypeSystem typeSystem;
+  FunctionType simpleFunctionType;
+
+  DartType get bottomType => typeProvider.bottomType;
+  InterfaceType get doubleType => typeProvider.doubleType;
+  DartType get dynamicType => typeProvider.dynamicType;
+  InterfaceType get functionType => typeProvider.functionType;
+  InterfaceType get intType => typeProvider.intType;
+  InterfaceType get listType => typeProvider.listType;
+  InterfaceType get numType => typeProvider.numType;
+  InterfaceType get objectType => typeProvider.objectType;
+  InterfaceType get stringType => typeProvider.stringType;
+  DartType get voidType => VoidTypeImpl.instance;
+
+  void setUp() {
+    typeProvider = new TestTypeProvider();
+    typeSystem = new TypeSystemImpl(typeProvider);
+    FunctionTypeAliasElementImpl typeAlias =
+        ElementFactory.functionTypeAliasElement('A');
+    typeAlias.parameters = [];
+    typeAlias.returnType = voidType;
+    simpleFunctionType = typeAlias.type;
+  }
+
+  void test_getLeastUpperBound_bottom_function() {
+    _checkLeastUpperBound(bottomType, simpleFunctionType, simpleFunctionType);
+  }
+
+  void test_getLeastUpperBound_bottom_interface() {
+    DartType interfaceType = ElementFactory.classElement2('A', []).type;
+    _checkLeastUpperBound(bottomType, interfaceType, interfaceType);
+  }
+
+  void test_getLeastUpperBound_bottom_typeParam() {
+    DartType typeParam = ElementFactory.typeParameterElement('T').type;
+    _checkLeastUpperBound(bottomType, typeParam, typeParam);
+  }
+
+  void test_getLeastUpperBound_directInterfaceCase() {
+    //
+    // class A
+    // class B implements A
+    // class C implements B
+    //
+    ClassElementImpl classA = ElementFactory.classElement2("A");
+    ClassElementImpl classB = ElementFactory.classElement2("B");
+    ClassElementImpl classC = ElementFactory.classElement2("C");
+    InterfaceType typeA = classA.type;
+    InterfaceType typeB = classB.type;
+    InterfaceType typeC = classC.type;
+    classB.interfaces = <InterfaceType>[typeA];
+    classC.interfaces = <InterfaceType>[typeB];
+    _checkLeastUpperBound(typeB, typeC, typeB);
+  }
+
+  void test_getLeastUpperBound_directSubclassCase() {
+    //
+    // class A
+    // class B extends A
+    // class C extends B
+    //
+    ClassElementImpl classA = ElementFactory.classElement2("A");
+    ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
+    ClassElementImpl classC = ElementFactory.classElement("C", classB.type);
+    InterfaceType typeB = classB.type;
+    InterfaceType typeC = classC.type;
+    _checkLeastUpperBound(typeB, typeC, typeB);
+  }
+
+  void test_getLeastUpperBound_dynamic_bottom() {
+    _checkLeastUpperBound(dynamicType, bottomType, dynamicType);
+  }
+
+  void test_getLeastUpperBound_dynamic_function() {
+    _checkLeastUpperBound(dynamicType, simpleFunctionType, dynamicType);
+  }
+
+  void test_getLeastUpperBound_dynamic_interface() {
+    DartType interfaceType = ElementFactory.classElement2('A', []).type;
+    _checkLeastUpperBound(dynamicType, interfaceType, dynamicType);
+  }
+
+  void test_getLeastUpperBound_dynamic_typeParam() {
+    DartType typeParam = ElementFactory.typeParameterElement('T').type;
+    _checkLeastUpperBound(dynamicType, typeParam, dynamicType);
+  }
+
+  void test_getLeastUpperBound_dynamic_void() {
+    _checkLeastUpperBound(dynamicType, voidType, dynamicType);
+  }
+
+  void test_getLeastUpperBound_interface_function() {
+    DartType interfaceType = ElementFactory.classElement2('A', []).type;
+    _checkLeastUpperBound(interfaceType, simpleFunctionType, objectType);
+  }
+
+  void test_getLeastUpperBound_mixinCase() {
+    //
+    // class A
+    // class B extends A
+    // class C extends A
+    // class D extends B with M, N, O, P
+    //
+    ClassElement classA = ElementFactory.classElement2("A");
+    ClassElement classB = ElementFactory.classElement("B", classA.type);
+    ClassElement classC = ElementFactory.classElement("C", classA.type);
+    ClassElementImpl classD = ElementFactory.classElement("D", classB.type);
+    InterfaceType typeA = classA.type;
+    InterfaceType typeC = classC.type;
+    InterfaceType typeD = classD.type;
+    classD.mixins = <InterfaceType>[
+      ElementFactory.classElement2("M").type,
+      ElementFactory.classElement2("N").type,
+      ElementFactory.classElement2("O").type,
+      ElementFactory.classElement2("P").type
+    ];
+    _checkLeastUpperBound(typeD, typeC, typeA);
+  }
+
+  void test_getLeastUpperBound_object() {
+    ClassElementImpl classA = ElementFactory.classElement2("A");
+    ClassElementImpl classB = ElementFactory.classElement2("B");
+    InterfaceType typeA = classA.type;
+    InterfaceType typeB = classB.type;
+    DartType typeObject = typeA.element.supertype;
+    // assert that object does not have a super type
+    expect((typeObject.element as ClassElement).supertype, isNull);
+    // assert that both A and B have the same super type of Object
+    expect(typeB.element.supertype, typeObject);
+    // finally, assert that the only least upper bound of A and B is Object
+    _checkLeastUpperBound(typeA, typeB, typeObject);
+  }
+
+  void test_getLeastUpperBound_self() {
+    DartType typeParam = ElementFactory.typeParameterElement('T').type;
+    DartType interfaceType = ElementFactory.classElement2('A', []).type;
+    expect(
+        typeSystem.getLeastUpperBound(dynamicType, dynamicType), dynamicType);
+    expect(typeSystem.getLeastUpperBound(voidType, voidType), voidType);
+    expect(typeSystem.getLeastUpperBound(bottomType, bottomType), bottomType);
+    expect(typeSystem.getLeastUpperBound(typeParam, typeParam), typeParam);
+    expect(typeSystem.getLeastUpperBound(interfaceType, interfaceType),
+        interfaceType);
+    expect(
+        typeSystem.getLeastUpperBound(simpleFunctionType, simpleFunctionType),
+        simpleFunctionType);
+  }
+
+  void test_getLeastUpperBound_sharedSuperclass1() {
+    ClassElementImpl classA = ElementFactory.classElement2("A");
+    ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
+    ClassElementImpl classC = ElementFactory.classElement("C", classA.type);
+    InterfaceType typeA = classA.type;
+    InterfaceType typeB = classB.type;
+    InterfaceType typeC = classC.type;
+    _checkLeastUpperBound(typeB, typeC, typeA);
+  }
+
+  void test_getLeastUpperBound_sharedSuperclass2() {
+    ClassElementImpl classA = ElementFactory.classElement2("A");
+    ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
+    ClassElementImpl classC = ElementFactory.classElement("C", classA.type);
+    ClassElementImpl classD = ElementFactory.classElement("D", classC.type);
+    InterfaceType typeA = classA.type;
+    InterfaceType typeB = classB.type;
+    InterfaceType typeD = classD.type;
+    _checkLeastUpperBound(typeB, typeD, typeA);
+  }
+
+  void test_getLeastUpperBound_sharedSuperclass3() {
+    ClassElementImpl classA = ElementFactory.classElement2("A");
+    ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
+    ClassElementImpl classC = ElementFactory.classElement("C", classB.type);
+    ClassElementImpl classD = ElementFactory.classElement("D", classB.type);
+    InterfaceType typeB = classB.type;
+    InterfaceType typeC = classC.type;
+    InterfaceType typeD = classD.type;
+    _checkLeastUpperBound(typeC, typeD, typeB);
+  }
+
+  void test_getLeastUpperBound_sharedSuperclass4() {
+    ClassElement classA = ElementFactory.classElement2("A");
+    ClassElement classA2 = ElementFactory.classElement2("A2");
+    ClassElement classA3 = ElementFactory.classElement2("A3");
+    ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
+    ClassElementImpl classC = ElementFactory.classElement("C", classA.type);
+    InterfaceType typeA = classA.type;
+    InterfaceType typeA2 = classA2.type;
+    InterfaceType typeA3 = classA3.type;
+    InterfaceType typeB = classB.type;
+    InterfaceType typeC = classC.type;
+    classB.interfaces = <InterfaceType>[typeA2];
+    classC.interfaces = <InterfaceType>[typeA3];
+    _checkLeastUpperBound(typeB, typeC, typeA);
+  }
+
+  void test_getLeastUpperBound_sharedSuperinterface1() {
+    ClassElementImpl classA = ElementFactory.classElement2("A");
+    ClassElementImpl classB = ElementFactory.classElement2("B");
+    ClassElementImpl classC = ElementFactory.classElement2("C");
+    InterfaceType typeA = classA.type;
+    InterfaceType typeB = classB.type;
+    InterfaceType typeC = classC.type;
+    classB.interfaces = <InterfaceType>[typeA];
+    classC.interfaces = <InterfaceType>[typeA];
+    _checkLeastUpperBound(typeB, typeC, typeA);
+  }
+
+  void test_getLeastUpperBound_sharedSuperinterface2() {
+    ClassElementImpl classA = ElementFactory.classElement2("A");
+    ClassElementImpl classB = ElementFactory.classElement2("B");
+    ClassElementImpl classC = ElementFactory.classElement2("C");
+    ClassElementImpl classD = ElementFactory.classElement2("D");
+    InterfaceType typeA = classA.type;
+    InterfaceType typeB = classB.type;
+    InterfaceType typeC = classC.type;
+    InterfaceType typeD = classD.type;
+    classB.interfaces = <InterfaceType>[typeA];
+    classC.interfaces = <InterfaceType>[typeA];
+    classD.interfaces = <InterfaceType>[typeC];
+    _checkLeastUpperBound(typeB, typeD, typeA);
+  }
+
+  void test_getLeastUpperBound_sharedSuperinterface3() {
+    ClassElementImpl classA = ElementFactory.classElement2("A");
+    ClassElementImpl classB = ElementFactory.classElement2("B");
+    ClassElementImpl classC = ElementFactory.classElement2("C");
+    ClassElementImpl classD = ElementFactory.classElement2("D");
+    InterfaceType typeA = classA.type;
+    InterfaceType typeB = classB.type;
+    InterfaceType typeC = classC.type;
+    InterfaceType typeD = classD.type;
+    classB.interfaces = <InterfaceType>[typeA];
+    classC.interfaces = <InterfaceType>[typeB];
+    classD.interfaces = <InterfaceType>[typeB];
+    _checkLeastUpperBound(typeC, typeD, typeB);
+  }
+
+  void test_getLeastUpperBound_sharedSuperinterface4() {
+    ClassElement classA = ElementFactory.classElement2("A");
+    ClassElement classA2 = ElementFactory.classElement2("A2");
+    ClassElement classA3 = ElementFactory.classElement2("A3");
+    ClassElementImpl classB = ElementFactory.classElement2("B");
+    ClassElementImpl classC = ElementFactory.classElement2("C");
+    InterfaceType typeA = classA.type;
+    InterfaceType typeA2 = classA2.type;
+    InterfaceType typeA3 = classA3.type;
+    InterfaceType typeB = classB.type;
+    InterfaceType typeC = classC.type;
+    classB.interfaces = <InterfaceType>[typeA, typeA2];
+    classC.interfaces = <InterfaceType>[typeA, typeA3];
+    _checkLeastUpperBound(typeB, typeC, typeA);
+  }
+
+  void test_getLeastUpperBound_twoComparables() {
+    _checkLeastUpperBound(stringType, numType, objectType);
+  }
+
+  void test_getLeastUpperBound_typeParam_function_bounded() {
+    DartType typeA = ElementFactory.classElement('A', functionType).type;
+    TypeParameterElementImpl typeParamElement =
+        ElementFactory.typeParameterElement('T');
+    typeParamElement.bound = typeA;
+    DartType typeParam = typeParamElement.type;
+    _checkLeastUpperBound(typeParam, simpleFunctionType, functionType);
+  }
+
+  void test_getLeastUpperBound_typeParam_function_noBound() {
+    DartType typeParam = ElementFactory.typeParameterElement('T').type;
+    _checkLeastUpperBound(typeParam, simpleFunctionType, objectType);
+  }
+
+  void test_getLeastUpperBound_typeParam_interface_bounded() {
+    DartType typeA = ElementFactory.classElement2('A', []).type;
+    DartType typeB = ElementFactory.classElement('B', typeA).type;
+    DartType typeC = ElementFactory.classElement('C', typeA).type;
+    TypeParameterElementImpl typeParamElement =
+        ElementFactory.typeParameterElement('T');
+    typeParamElement.bound = typeB;
+    DartType typeParam = typeParamElement.type;
+    _checkLeastUpperBound(typeParam, typeC, typeA);
+  }
+
+  void test_getLeastUpperBound_typeParam_interface_noBound() {
+    DartType typeParam = ElementFactory.typeParameterElement('T').type;
+    DartType interfaceType = ElementFactory.classElement2('A', []).type;
+    _checkLeastUpperBound(typeParam, interfaceType, objectType);
+  }
+
+  void test_getLeastUpperBound_typeParameters_different() {
+    //
+    // class List<int>
+    // class List<double>
+    //
+    InterfaceType listOfIntType = listType.substitute4(<DartType>[intType]);
+    InterfaceType listOfDoubleType =
+        listType.substitute4(<DartType>[doubleType]);
+    _checkLeastUpperBound(listOfIntType, listOfDoubleType, objectType);
+  }
+
+  void test_getLeastUpperBound_typeParameters_same() {
+    //
+    // List<int>
+    // List<int>
+    //
+    InterfaceType listOfIntType = listType.substitute4(<DartType>[intType]);
+    expect(typeSystem.getLeastUpperBound(listOfIntType, listOfIntType),
+        listOfIntType);
+  }
+
+  void test_getLeastUpperBound_void_bottom() {
+    _checkLeastUpperBound(voidType, bottomType, voidType);
+  }
+
+  void test_getLeastUpperBound_void_function() {
+    _checkLeastUpperBound(voidType, simpleFunctionType, voidType);
+  }
+
+  void test_getLeastUpperBound_void_interface() {
+    DartType interfaceType = ElementFactory.classElement2('A', []).type;
+    _checkLeastUpperBound(voidType, interfaceType, voidType);
+  }
+
+  void test_getLeastUpperBound_void_typeParam() {
+    DartType typeParam = ElementFactory.typeParameterElement('T').type;
+    _checkLeastUpperBound(voidType, typeParam, voidType);
+  }
+
+  void _checkLeastUpperBound(
+      DartType type1, DartType type2, DartType expectedResult) {
+    expect(typeSystem.getLeastUpperBound(type1, type2), expectedResult);
+  }
+}
diff --git a/pkg/analyzer/test/src/context/abstract_context.dart b/pkg/analyzer/test/src/context/abstract_context.dart
index a4a374f..4c8f4a2 100644
--- a/pkg/analyzer/test/src/context/abstract_context.dart
+++ b/pkg/analyzer/test/src/context/abstract_context.dart
@@ -14,6 +14,7 @@
 import 'package:analyzer/src/generated/sdk.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/task/driver.dart';
+import 'package:analyzer/task/model.dart';
 import 'package:unittest/unittest.dart';
 
 import 'mock_sdk.dart';
@@ -27,6 +28,10 @@
   AnalysisCache analysisCache;
   AnalysisDriver analysisDriver;
 
+  AnalysisTask task;
+  Map<ResultDescriptor<dynamic>, dynamic> oldOutputs;
+  Map<ResultDescriptor<dynamic>, dynamic> outputs;
+
   Source addSource(String path, String contents) {
     Source source = newSource(path, contents);
     ChangeSet changeSet = new ChangeSet();
@@ -64,6 +69,17 @@
     expect(elements, hasLength(names.length));
   }
 
+  /**
+   * Compute the given [result] for the given [target].
+   */
+  void computeResult(AnalysisTarget target, ResultDescriptor result) {
+    oldOutputs = outputs;
+    task = analysisDriver.computeResult(target, result);
+    expect(task, isNotNull);
+    expect(task.caughtException, isNull);
+    outputs = task.outputs;
+  }
+
   AnalysisContextImpl createAnalysisContext() {
     return new AnalysisContextImpl();
   }
diff --git a/pkg/analyzer/test/src/context/cache_test.dart b/pkg/analyzer/test/src/context/cache_test.dart
index cd28a42..2a3952a 100644
--- a/pkg/analyzer/test/src/context/cache_test.dart
+++ b/pkg/analyzer/test/src/context/cache_test.dart
@@ -491,10 +491,18 @@
     entry.setValue(result, 10, TargetedResult.EMPTY_LIST);
     expect(entry.getState(result), CacheState.VALID);
     expect(entry.getValue(result), 10);
+    // listen, expect "result" invalidation event
+    int numberOfEvents = 0;
+    cache.onResultInvalidated.listen((event) {
+      numberOfEvents++;
+      expect(event.entry, same(entry));
+      expect(event.descriptor, same(result));
+    });
     // set INVALID
     entry.setState(result, CacheState.INVALID);
     expect(entry.getState(result), CacheState.INVALID);
     expect(entry.getValue(result), 1);
+    expect(numberOfEvents, 1);
   }
 
   test_setState_invalid_dependencyCycle() {
@@ -510,11 +518,24 @@
     entry2.setValue(result, 200, [new TargetedResult(target1, result)]);
     expect(entry1.getState(result), CacheState.VALID);
     expect(entry2.getState(result), CacheState.VALID);
+    // Listen, expect entry1.result and entry2.result invalidation events.
+    int numberOfEvents = 0;
+    bool wasEntry1 = false;
+    bool wasEntry2 = false;
+    cache.onResultInvalidated.listen((event) {
+      numberOfEvents++;
+      if (event.entry == entry1) wasEntry1 = true;
+      if (event.entry == entry2) wasEntry2 = true;
+      expect(event.descriptor, same(result));
+    });
     // Invalidate entry1.result; this should cause entry2 to be also
     // cleared without going into an infinite regress.
     entry1.setState(result, CacheState.INVALID);
     expect(cache.get(target1), isNull);
     expect(cache.get(target2), isNull);
+    expect(numberOfEvents, 2);
+    expect(wasEntry1, isTrue);
+    expect(wasEntry2, isTrue);
   }
 
   test_setState_invalid_invalidateDependent() {
diff --git a/pkg/analyzer/test/src/context/context_test.dart b/pkg/analyzer/test/src/context/context_test.dart
index ddca982..60e430c 100644
--- a/pkg/analyzer/test/src/context/context_test.dart
+++ b/pkg/analyzer/test/src/context/context_test.dart
@@ -35,6 +35,7 @@
 import 'package:analyzer/src/generated/scanner.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/task/dart.dart';
+import 'package:html/dom.dart' show Document;
 import 'package:path/path.dart' as pathos;
 import 'package:unittest/unittest.dart';
 import 'package:watcher/src/utils.dart';
@@ -60,6 +61,365 @@
     fail('Should have failed');
   }
 
+  void fail_extractContext() {
+    fail("Implement this");
+  }
+
+  void fail_mergeContext() {
+    fail("Implement this");
+  }
+
+  void fail_parseHtmlUnit_resolveDirectives() {
+    Source libSource = addSource("/lib.dart", r'''
+library lib;
+class ClassA {}''');
+    Source source = addSource("/lib.html", r'''
+<!DOCTYPE html>
+<html>
+<head>
+  <script type='application/dart'>
+    import 'lib.dart';
+    ClassA v = null;
+  </script>
+</head>
+<body>
+</body>
+</html>''');
+    // TODO(brianwilkerson) Rewrite this. We need a way to get the AST for the
+    // script.
+    ht.HtmlUnit unit = context.parseHtmlUnit(source);
+    expect(unit, isNotNull);
+    // import directive should be resolved
+    ht.XmlTagNode htmlNode = unit.tagNodes[0];
+    ht.XmlTagNode headNode = htmlNode.tagNodes[0];
+    ht.HtmlScriptTagNode scriptNode = headNode.tagNodes[0];
+    CompilationUnit script = scriptNode.script;
+    ImportDirective importNode = script.directives[0] as ImportDirective;
+    expect(importNode.uriContent, isNotNull);
+    expect(importNode.source, libSource);
+  }
+
+  void fail_performAnalysisTask_getContentException_dart() {
+    Source source = _addSourceWithException('test.dart');
+    // prepare errors
+    _analyzeAll_assertFinished();
+    List<AnalysisError> errors = context.getErrors(source).errors;
+    // validate errors
+    expect(errors, hasLength(1));
+    AnalysisError error = errors[0];
+    expect(error.source, same(source));
+    expect(error.errorCode, ScannerErrorCode.UNABLE_GET_CONTENT);
+  }
+
+  void fail_performAnalysisTask_getContentException_html() {
+    Source source = _addSourceWithException('test.html');
+    // prepare errors
+    _analyzeAll_assertFinished();
+    List<AnalysisError> errors = context.getErrors(source).errors;
+    // validate errors
+    expect(errors, hasLength(1));
+    AnalysisError error = errors[0];
+    expect(error.source, same(source));
+    expect(error.errorCode, ScannerErrorCode.UNABLE_GET_CONTENT);
+  }
+
+  void test_performAnalysisTask_importedLibraryAdd_html() {
+    Source htmlSource = addSource("/page.html", r'''
+<html><body><script type="application/dart">
+  import '/libB.dart';
+  main() {print('hello dart');}
+</script></body></html>''');
+    _analyzeAll_assertFinished();
+    context.computeErrors(htmlSource);
+    expect(_hasAnalysisErrorWithErrorSeverity(context.getErrors(htmlSource)),
+        isTrue, reason: "htmlSource has an error");
+    // add libB.dart and analyze
+    Source libBSource = addSource("/libB.dart", "library libB;");
+    _analyzeAll_assertFinished();
+    expect(
+        context.getResolvedCompilationUnit2(libBSource, libBSource), isNotNull,
+        reason: "libB resolved 2");
+    // TODO (danrubel) commented out to fix red bots
+//    context.computeErrors(htmlSource);
+//    AnalysisErrorInfo errors = _context.getErrors(htmlSource);
+//    expect(
+//        !_hasAnalysisErrorWithErrorSeverity(errors),
+//        isTrue,
+//        reason: "htmlSource doesn't have errors");
+  }
+
+  void fail_performAnalysisTask_importedLibraryDelete_html() {
+    // NOTE: This was failing before converting to the new task model.
+    Source htmlSource = addSource("/page.html", r'''
+<html><body><script type="application/dart">
+  import 'libB.dart';
+  main() {print('hello dart');}
+</script></body></html>''');
+    Source libBSource = addSource("/libB.dart", "library libB;");
+    _analyzeAll_assertFinished();
+    context.computeErrors(htmlSource);
+    expect(
+        context.getResolvedCompilationUnit2(libBSource, libBSource), isNotNull,
+        reason: "libB resolved 1");
+    expect(!_hasAnalysisErrorWithErrorSeverity(context.getErrors(htmlSource)),
+        isTrue, reason: "htmlSource doesn't have errors");
+    // remove libB.dart content and analyze
+    context.setContents(libBSource, null);
+    _analyzeAll_assertFinished();
+    context.computeErrors(htmlSource);
+    AnalysisErrorInfo errors = context.getErrors(htmlSource);
+    expect(_hasAnalysisErrorWithErrorSeverity(errors), isTrue,
+        reason: "htmlSource has an error");
+  }
+
+  void fail_performAnalysisTask_IOException() {
+    TestSource source = _addSourceWithException2("/test.dart", "library test;");
+    int oldTimestamp = context.getModificationStamp(source);
+    source.generateExceptionOnRead = false;
+    _analyzeAll_assertFinished();
+    expect(source.readCount, 1);
+    source.generateExceptionOnRead = true;
+    do {
+      _changeSource(source, "");
+      // Ensure that the timestamp differs,
+      // so that analysis engine notices the change
+    } while (oldTimestamp == context.getModificationStamp(source));
+    _analyzeAll_assertFinished();
+    expect(source.readCount, 2);
+  }
+
+  void fail_recordLibraryElements() {
+    fail("Implement this");
+  }
+
+  void fail_setAnalysisOptions_reduceAnalysisPriorityOrder() {
+    AnalysisOptionsImpl options =
+        new AnalysisOptionsImpl.from(context.analysisOptions);
+    List<Source> sources = new List<Source>();
+    for (int index = 0; index < options.cacheSize; index++) {
+      sources.add(addSource("/lib.dart$index", ""));
+    }
+    context.analysisPriorityOrder = sources;
+    int oldPriorityOrderSize = _getPriorityOrder(context).length;
+    options.cacheSize = options.cacheSize - 10;
+    context.analysisOptions = options;
+    expect(oldPriorityOrderSize > _getPriorityOrder(context).length, isTrue);
+  }
+
+  void fail_setAnalysisPriorityOrder_lessThanCacheSize() {
+    AnalysisOptions options = context.analysisOptions;
+    List<Source> sources = new List<Source>();
+    for (int index = 0; index < options.cacheSize; index++) {
+      sources.add(addSource("/lib.dart$index", ""));
+    }
+    context.analysisPriorityOrder = sources;
+    expect(options.cacheSize > _getPriorityOrder(context).length, isTrue);
+  }
+
+  Future fail_setChangedContents_libraryWithPart() {
+    AnalysisOptionsImpl options = new AnalysisOptionsImpl();
+    options.incremental = true;
+    context.analysisOptions = options;
+    SourcesChangedListener listener = new SourcesChangedListener();
+    context.onSourcesChanged.listen(listener.onData);
+    String oldCode = r'''
+library lib;
+part 'part.dart';
+int a = 0;''';
+    Source librarySource = addSource("/lib.dart", oldCode);
+    String partContents = r'''
+part of lib;
+int b = a;''';
+    Source partSource = addSource("/part.dart", partContents);
+    LibraryElement element = context.computeLibraryElement(librarySource);
+    CompilationUnit unit =
+        context.getResolvedCompilationUnit(librarySource, element);
+    expect(unit, isNotNull);
+    int offset = oldCode.indexOf("int a") + 4;
+    String newCode = r'''
+library lib;
+part 'part.dart';
+int ya = 0;''';
+    expect(_getIncrementalAnalysisCache(context), isNull);
+    context.setChangedContents(librarySource, newCode, offset, 0, 1);
+    expect(context.getContents(librarySource).data, newCode);
+    IncrementalAnalysisCache incrementalCache =
+        _getIncrementalAnalysisCache(context);
+    expect(incrementalCache.librarySource, librarySource);
+    expect(incrementalCache.resolvedUnit, same(unit));
+    expect(
+        context.getResolvedCompilationUnit2(partSource, librarySource), isNull);
+    expect(incrementalCache.newContents, newCode);
+    return pumpEventQueue().then((_) {
+      listener.assertEvent(wereSourcesAdded: true);
+      listener.assertEvent(changedSources: [librarySource]);
+      listener.assertEvent(wereSourcesAdded: true);
+      listener.assertEvent(changedSources: [partSource]);
+      listener.assertEvent(changedSources: [librarySource]);
+      listener.assertNoMoreEvents();
+    });
+  }
+
+  void fail_unreadableSource() {
+    Source test1 = addSource("/test1.dart", r'''
+import 'test2.dart';
+library test1;''');
+    Source test2 = addSource("/test2.dart", r'''
+import 'test1.dart';
+import 'test3.dart';
+library test2;''');
+    Source test3 = _addSourceWithException("/test3.dart");
+    _analyzeAll_assertFinished();
+    // test1 and test2 should have been successfully analyzed
+    // despite the fact that test3 couldn't be read.
+    expect(context.computeLibraryElement(test1), isNotNull);
+    expect(context.computeLibraryElement(test2), isNotNull);
+    expect(context.computeLibraryElement(test3), isNull);
+  }
+
+  @override
+  void tearDown() {
+    context = null;
+    sourceFactory = null;
+    super.tearDown();
+  }
+
+  Future test_applyChanges_add() {
+    SourcesChangedListener listener = new SourcesChangedListener();
+    context.onSourcesChanged.listen(listener.onData);
+    expect(context.sourcesNeedingProcessing, isEmpty);
+    Source source = newSource('/test.dart');
+    ChangeSet changeSet = new ChangeSet();
+    changeSet.addedSource(source);
+    context.applyChanges(changeSet);
+    expect(context.sourcesNeedingProcessing, contains(source));
+    return pumpEventQueue().then((_) {
+      listener.assertEvent(wereSourcesAdded: true);
+      listener.assertNoMoreEvents();
+    });
+  }
+
+  Future test_applyChanges_change() {
+    SourcesChangedListener listener = new SourcesChangedListener();
+    context.onSourcesChanged.listen(listener.onData);
+    expect(context.sourcesNeedingProcessing, isEmpty);
+    Source source = newSource('/test.dart');
+    ChangeSet changeSet1 = new ChangeSet();
+    changeSet1.addedSource(source);
+    context.applyChanges(changeSet1);
+    expect(context.sourcesNeedingProcessing, contains(source));
+    Source source2 = newSource('/test2.dart');
+    ChangeSet changeSet2 = new ChangeSet();
+    changeSet2.addedSource(source2);
+    changeSet2.changedSource(source);
+    context.applyChanges(changeSet2);
+    return pumpEventQueue().then((_) {
+      listener.assertEvent(wereSourcesAdded: true);
+      listener.assertEvent(wereSourcesAdded: true, changedSources: [source]);
+      listener.assertNoMoreEvents();
+    });
+  }
+
+  Future test_applyChanges_change_content() {
+    SourcesChangedListener listener = new SourcesChangedListener();
+    context.onSourcesChanged.listen(listener.onData);
+    expect(context.sourcesNeedingProcessing, isEmpty);
+    Source source = newSource('/test.dart');
+    ChangeSet changeSet1 = new ChangeSet();
+    changeSet1.addedSource(source);
+    context.applyChanges(changeSet1);
+    expect(context.sourcesNeedingProcessing, contains(source));
+    Source source2 = newSource('/test2.dart');
+    ChangeSet changeSet2 = new ChangeSet();
+    changeSet2.addedSource(source2);
+    changeSet2.changedContent(source, 'library test;');
+    context.applyChanges(changeSet2);
+    return pumpEventQueue().then((_) {
+      listener.assertEvent(wereSourcesAdded: true);
+      listener.assertEvent(wereSourcesAdded: true, changedSources: [source]);
+      listener.assertNoMoreEvents();
+    });
+  }
+
+  void test_applyChanges_change_flush_element() {
+    Source librarySource = addSource("/lib.dart", r'''
+library lib;
+int a = 0;''');
+    expect(context.computeLibraryElement(librarySource), isNotNull);
+    context.setContents(librarySource, r'''
+library lib;
+int aa = 0;''');
+    expect(context.getLibraryElement(librarySource), isNull);
+  }
+
+  Future test_applyChanges_change_multiple() {
+    SourcesChangedListener listener = new SourcesChangedListener();
+    context.onSourcesChanged.listen(listener.onData);
+    String libraryContents1 = r'''
+library lib;
+part 'part.dart';
+int a = 0;''';
+    Source librarySource = addSource("/lib.dart", libraryContents1);
+    String partContents1 = r'''
+part of lib;
+int b = a;''';
+    Source partSource = addSource("/part.dart", partContents1);
+    context.computeLibraryElement(librarySource);
+    String libraryContents2 = r'''
+library lib;
+part 'part.dart';
+int aa = 0;''';
+    context.setContents(librarySource, libraryContents2);
+    String partContents2 = r'''
+part of lib;
+int b = aa;''';
+    context.setContents(partSource, partContents2);
+    context.computeLibraryElement(librarySource);
+    CompilationUnit libraryUnit =
+        context.resolveCompilationUnit2(librarySource, librarySource);
+    expect(libraryUnit, isNotNull);
+    CompilationUnit partUnit =
+        context.resolveCompilationUnit2(partSource, librarySource);
+    expect(partUnit, isNotNull);
+    TopLevelVariableDeclaration declaration =
+        libraryUnit.declarations[0] as TopLevelVariableDeclaration;
+    Element declarationElement = declaration.variables.variables[0].element;
+    TopLevelVariableDeclaration use =
+        partUnit.declarations[0] as TopLevelVariableDeclaration;
+    Element useElement = (use.variables.variables[
+        0].initializer as SimpleIdentifier).staticElement;
+    expect((useElement as PropertyAccessorElement).variable,
+        same(declarationElement));
+    return pumpEventQueue().then((_) {
+      listener.assertEvent(wereSourcesAdded: true);
+      listener.assertEvent(wereSourcesAdded: true);
+      listener.assertEvent(changedSources: [librarySource]);
+      listener.assertEvent(changedSources: [partSource]);
+      listener.assertNoMoreEvents();
+    });
+  }
+
+  Future test_applyChanges_change_range() {
+    SourcesChangedListener listener = new SourcesChangedListener();
+    context.onSourcesChanged.listen(listener.onData);
+    expect(context.sourcesNeedingProcessing, isEmpty);
+    Source source = newSource('/test.dart');
+    ChangeSet changeSet1 = new ChangeSet();
+    changeSet1.addedSource(source);
+    context.applyChanges(changeSet1);
+    expect(context.sourcesNeedingProcessing, contains(source));
+    Source source2 = newSource('/test2.dart');
+    ChangeSet changeSet2 = new ChangeSet();
+    changeSet2.addedSource(source2);
+    changeSet2.changedRange(source, 'library test;', 0, 0, 13);
+    context.applyChanges(changeSet2);
+    return pumpEventQueue().then((_) {
+      listener.assertEvent(wereSourcesAdded: true);
+      listener.assertEvent(wereSourcesAdded: true, changedSources: [source]);
+      listener.assertNoMoreEvents();
+    });
+  }
+
   void test_applyChanges_overriddenSource() {
     // Note: addSource adds the source to the contentCache.
     Source source = addSource("/test.dart", "library test;");
@@ -136,6 +496,53 @@
     });
   }
 
+  void test_computeDocumentationComment_block() {
+    String comment = "/** Comment */";
+    Source source = addSource("/test.dart", """
+$comment
+class A {}""");
+    LibraryElement libraryElement = context.computeLibraryElement(source);
+    expect(libraryElement, isNotNull);
+    ClassElement classElement = libraryElement.definingCompilationUnit.types[0];
+    expect(libraryElement, isNotNull);
+    expect(context.computeDocumentationComment(classElement), comment);
+  }
+
+  void test_computeDocumentationComment_none() {
+    Source source = addSource("/test.dart", "class A {}");
+    LibraryElement libraryElement = context.computeLibraryElement(source);
+    expect(libraryElement, isNotNull);
+    ClassElement classElement = libraryElement.definingCompilationUnit.types[0];
+    expect(libraryElement, isNotNull);
+    expect(context.computeDocumentationComment(classElement), isNull);
+  }
+
+  void test_computeDocumentationComment_null() {
+    expect(context.computeDocumentationComment(null), isNull);
+  }
+
+  void test_computeDocumentationComment_singleLine_multiple_EOL_n() {
+    String comment = "/// line 1\n/// line 2\n/// line 3\n";
+    Source source = addSource("/test.dart", "${comment}class A {}");
+    LibraryElement libraryElement = context.computeLibraryElement(source);
+    expect(libraryElement, isNotNull);
+    ClassElement classElement = libraryElement.definingCompilationUnit.types[0];
+    expect(libraryElement, isNotNull);
+    String actual = context.computeDocumentationComment(classElement);
+    expect(actual, "/// line 1\n/// line 2\n/// line 3");
+  }
+
+  void test_computeDocumentationComment_singleLine_multiple_EOL_rn() {
+    String comment = "/// line 1\r\n/// line 2\r\n/// line 3\r\n";
+    Source source = addSource("/test.dart", "${comment}class A {}");
+    LibraryElement libraryElement = context.computeLibraryElement(source);
+    expect(libraryElement, isNotNull);
+    ClassElement classElement = libraryElement.definingCompilationUnit.types[0];
+    expect(libraryElement, isNotNull);
+    String actual = context.computeDocumentationComment(classElement);
+    expect(actual, "/// line 1\n/// line 2\n/// line 3");
+  }
+
   void test_computeErrors_dart_none() {
     Source source = addSource("/lib.dart", "library lib;");
     List<AnalysisError> errors = context.computeErrors(source);
@@ -159,17 +566,23 @@
     expect(errors.length > 0, isTrue);
   }
 
-  void fail_computeErrors_html_none() {
-    Source source = addSource("/test.html", "<html></html>");
+  void test_computeErrors_html_none() {
+    Source source = addSource("/test.html", "<!DOCTYPE html><html></html>");
     List<AnalysisError> errors = context.computeErrors(source);
     expect(errors, hasLength(0));
   }
 
-  void fail_computeHtmlElement_valid() {
-    Source source = addSource("/test.html", "<html></html>");
-    HtmlElement element = context.computeHtmlElement(source);
-    expect(element, isNotNull);
-    expect(context.computeHtmlElement(source), same(element));
+  void test_computeExportedLibraries_none() {
+    Source source = addSource("/test.dart", "library test;");
+    expect(context.computeExportedLibraries(source), hasLength(0));
+  }
+
+  void test_computeExportedLibraries_some() {
+    //    addSource("/lib1.dart", "library lib1;");
+    //    addSource("/lib2.dart", "library lib2;");
+    Source source = addSource(
+        "/test.dart", "library test; export 'lib1.dart'; export 'lib2.dart';");
+    expect(context.computeExportedLibraries(source), hasLength(2));
   }
 
   void test_computeImportedLibraries_none() {
@@ -183,34 +596,120 @@
     expect(context.computeImportedLibraries(source), hasLength(2));
   }
 
-  void fail_computeResolvableCompilationUnit_dart_exception() {
-    TestSource source = _addSourceWithException("/test.dart");
-    try {
-      context.computeResolvableCompilationUnit(source);
-      fail("Expected AnalysisException");
-    } on AnalysisException {
-      // Expected
-    }
+  void test_computeKindOf_html() {
+    Source source = addSource("/test.html", "");
+    expect(context.computeKindOf(source), same(SourceKind.HTML));
   }
 
-  void fail_computeResolvableCompilationUnit_html_exception() {
-    Source source = addSource("/lib.html", "<html></html>");
-    try {
-      context.computeResolvableCompilationUnit(source);
-      fail("Expected AnalysisException");
-    } on AnalysisException {
-      // Expected
-    }
+  void test_computeKindOf_library() {
+    Source source = addSource("/test.dart", "library lib;");
+    expect(context.computeKindOf(source), same(SourceKind.LIBRARY));
   }
 
-  void fail_computeResolvableCompilationUnit_valid() {
+  void test_computeKindOf_libraryAndPart() {
+    Source source = addSource("/test.dart", "library lib; part of lib;");
+    expect(context.computeKindOf(source), same(SourceKind.LIBRARY));
+  }
+
+  void test_computeKindOf_part() {
+    Source source = addSource("/test.dart", "part of lib;");
+    expect(context.computeKindOf(source), same(SourceKind.PART));
+  }
+
+  void test_computeLibraryElement() {
+    Source source = addSource("/test.dart", "library lib;");
+    LibraryElement element = context.computeLibraryElement(source);
+    expect(element, isNotNull);
+  }
+
+  void test_computeLineInfo_dart() {
+    Source source = addSource("/test.dart", r'''
+library lib;
+
+main() {}''');
+    LineInfo info = context.computeLineInfo(source);
+    expect(info, isNotNull);
+  }
+
+  void test_computeLineInfo_html() {
+    Source source = addSource("/test.html", r'''
+<html>
+  <body>
+    <h1>A</h1>
+  </body>
+</html>''');
+    LineInfo info = context.computeLineInfo(source);
+    expect(info, isNotNull);
+  }
+
+  Future test_computeResolvedCompilationUnitAsync() {
     Source source = addSource("/lib.dart", "library lib;");
-    CompilationUnit parsedUnit = context.parseCompilationUnit(source);
-    expect(parsedUnit, isNotNull);
-    CompilationUnit resolvedUnit =
-        context.computeResolvableCompilationUnit(source);
-    expect(resolvedUnit, isNotNull);
-    expect(resolvedUnit, same(parsedUnit));
+    // Complete all pending analysis tasks and flush the AST so that it won't
+    // be available immediately.
+    _performPendingAnalysisTasks();
+    _flushAst(source);
+    bool completed = false;
+    context
+        .computeResolvedCompilationUnitAsync(source, source)
+        .then((CompilationUnit unit) {
+      expect(unit, isNotNull);
+      completed = true;
+    });
+    return pumpEventQueue().then((_) {
+      expect(completed, isFalse);
+      _performPendingAnalysisTasks();
+    }).then((_) => pumpEventQueue()).then((_) {
+      expect(completed, isTrue);
+    });
+  }
+
+  Future test_computeResolvedCompilationUnitAsync_afterDispose() {
+    Source source = addSource("/lib.dart", "library lib;");
+    // Complete all pending analysis tasks and flush the AST so that it won't
+    // be available immediately.
+    _performPendingAnalysisTasks();
+    _flushAst(source);
+    // Dispose of the context.
+    context.dispose();
+    // Any attempt to start an asynchronous computation should return a future
+    // which completes with error.
+    CancelableFuture<CompilationUnit> future =
+        context.computeResolvedCompilationUnitAsync(source, source);
+    bool completed = false;
+    future.then((CompilationUnit unit) {
+      fail('Future should have completed with error');
+    }, onError: (error) {
+      expect(error, new isInstanceOf<AnalysisNotScheduledError>());
+      completed = true;
+    });
+    return pumpEventQueue().then((_) {
+      expect(completed, isTrue);
+    });
+  }
+
+  Future test_computeResolvedCompilationUnitAsync_cancel() {
+    Source source = addSource("/lib.dart", "library lib;");
+    // Complete all pending analysis tasks and flush the AST so that it won't
+    // be available immediately.
+    _performPendingAnalysisTasks();
+    _flushAst(source);
+    CancelableFuture<CompilationUnit> future =
+        context.computeResolvedCompilationUnitAsync(source, source);
+    bool completed = false;
+    future.then((CompilationUnit unit) {
+      fail('Future should have been canceled');
+    }, onError: (error) {
+      expect(error, new isInstanceOf<FutureCanceledError>());
+      completed = true;
+    });
+    expect(completed, isFalse);
+    expect(context.pendingFutureSources_forTesting, isNotEmpty);
+    future.cancel();
+    expect(context.pendingFutureSources_forTesting, isEmpty);
+    return pumpEventQueue().then((_) {
+      expect(completed, isTrue);
+      expect(context.pendingFutureSources_forTesting, isEmpty);
+    });
   }
 
   Future test_computeResolvedCompilationUnitAsync_dispose() {
@@ -240,16 +739,14 @@
     });
   }
 
-  Future fail_computeResolvedCompilationUnitAsync_unrelatedLibrary() {
+  Future test_computeResolvedCompilationUnitAsync_noCacheEntry() {
     Source librarySource = addSource("/lib.dart", "library lib;");
     Source partSource = addSource("/part.dart", "part of foo;");
     bool completed = false;
     context
         .computeResolvedCompilationUnitAsync(partSource, librarySource)
-        .then((_) {
-      fail('Expected resolution to fail');
-    }, onError: (e) {
-      expect(e, new isInstanceOf<AnalysisNotScheduledError>());
+        .then((CompilationUnit unit) {
+      expect(unit, isNotNull);
       completed = true;
     });
     return pumpEventQueue().then((_) {
@@ -260,8 +757,159 @@
     });
   }
 
-  void fail_extractContext() {
-    fail("Implement this");
+  void test_dispose() {
+    expect(context.isDisposed, isFalse);
+    context.dispose();
+    expect(context.isDisposed, isTrue);
+  }
+
+  void test_ensureResolvedDartUnits_definingUnit_hasResolved() {
+    Source source = addSource('/test.dart', '');
+    LibrarySpecificUnit libTarget = new LibrarySpecificUnit(source, source);
+    analysisDriver.computeResult(libTarget, RESOLVED_UNIT);
+    CompilationUnit unit =
+        context.getCacheEntry(libTarget).getValue(RESOLVED_UNIT);
+    List<CompilationUnit> units = context.ensureResolvedDartUnits(source);
+    expect(units, unorderedEquals([unit]));
+  }
+
+  void test_ensureResolvedDartUnits_definingUnit_notResolved() {
+    Source source = addSource('/test.dart', '');
+    LibrarySpecificUnit libTarget = new LibrarySpecificUnit(source, source);
+    analysisDriver.computeResult(libTarget, RESOLVED_UNIT);
+    // flush
+    context.getCacheEntry(libTarget).setState(
+        RESOLVED_UNIT, CacheState.FLUSHED);
+    // schedule recomputing
+    List<CompilationUnit> units = context.ensureResolvedDartUnits(source);
+    expect(units, isNull);
+    // should be the next result to compute
+    TargetedResult nextResult = context.dartWorkManager.getNextResult();
+    expect(nextResult.target, libTarget);
+    expect(nextResult.result, RESOLVED_UNIT);
+  }
+
+  void test_ensureResolvedDartUnits_partUnit_hasResolved() {
+    Source libSource1 = addSource('/lib1.dart', r'''
+library lib;
+part 'part.dart';
+''');
+    Source libSource2 = addSource('/lib2.dart', r'''
+library lib;
+part 'part.dart';
+''');
+    Source partSource = addSource('/part.dart', r'''
+part of lib;
+''');
+    LibrarySpecificUnit partTarget1 =
+        new LibrarySpecificUnit(libSource1, partSource);
+    LibrarySpecificUnit partTarget2 =
+        new LibrarySpecificUnit(libSource2, partSource);
+    analysisDriver.computeResult(partTarget1, RESOLVED_UNIT);
+    analysisDriver.computeResult(partTarget2, RESOLVED_UNIT);
+    CompilationUnit unit1 =
+        context.getCacheEntry(partTarget1).getValue(RESOLVED_UNIT);
+    CompilationUnit unit2 =
+        context.getCacheEntry(partTarget2).getValue(RESOLVED_UNIT);
+    List<CompilationUnit> units = context.ensureResolvedDartUnits(partSource);
+    expect(units, unorderedEquals([unit1, unit2]));
+  }
+
+  void test_ensureResolvedDartUnits_partUnit_notResolved() {
+    Source libSource1 = addSource('/lib1.dart', r'''
+library lib;
+part 'part.dart';
+''');
+    Source libSource2 = addSource('/lib2.dart', r'''
+library lib;
+part 'part.dart';
+''');
+    Source partSource = addSource('/part.dart', r'''
+part of lib;
+''');
+    LibrarySpecificUnit partTarget1 =
+        new LibrarySpecificUnit(libSource1, partSource);
+    LibrarySpecificUnit partTarget2 =
+        new LibrarySpecificUnit(libSource2, partSource);
+    analysisDriver.computeResult(partTarget1, RESOLVED_UNIT);
+    analysisDriver.computeResult(partTarget2, RESOLVED_UNIT);
+    // flush
+    context.getCacheEntry(partTarget1).setState(
+        RESOLVED_UNIT, CacheState.FLUSHED);
+    context.getCacheEntry(partTarget2).setState(
+        RESOLVED_UNIT, CacheState.FLUSHED);
+    // schedule recomputing
+    List<CompilationUnit> units = context.ensureResolvedDartUnits(partSource);
+    expect(units, isNull);
+    // should be the next result to compute
+    TargetedResult nextResult = context.dartWorkManager.getNextResult();
+    expect(nextResult.target, anyOf(partTarget1, partTarget2));
+    expect(nextResult.result, RESOLVED_UNIT);
+  }
+
+  void test_exists_false() {
+    TestSource source = new TestSource();
+    source.exists2 = false;
+    expect(context.exists(source), isFalse);
+  }
+
+  void test_exists_null() {
+    expect(context.exists(null), isFalse);
+  }
+
+  void test_exists_overridden() {
+    Source source = new TestSource();
+    context.setContents(source, "");
+    expect(context.exists(source), isTrue);
+  }
+
+  void test_exists_true() {
+    expect(context.exists(new AnalysisContextImplTest_Source_exists_true()),
+        isTrue);
+  }
+
+  void test_getAnalysisOptions() {
+    expect(context.analysisOptions, isNotNull);
+  }
+
+  void test_getContents_fromSource() {
+    String content = "library lib;";
+    TimestampedData<String> contents =
+        context.getContents(new TestSource('/test.dart', content));
+    expect(contents.data.toString(), content);
+  }
+
+  void test_getContents_overridden() {
+    String content = "library lib;";
+    Source source = new TestSource();
+    context.setContents(source, content);
+    TimestampedData<String> contents = context.getContents(source);
+    expect(contents.data.toString(), content);
+  }
+
+  void test_getContents_unoverridden() {
+    String content = "library lib;";
+    Source source = new TestSource('/test.dart', content);
+    context.setContents(source, "part of lib;");
+    context.setContents(source, null);
+    TimestampedData<String> contents = context.getContents(source);
+    expect(contents.data.toString(), content);
+  }
+
+  void test_getDeclaredVariables() {
+    expect(context.declaredVariables, isNotNull);
+  }
+
+  void test_getElement() {
+    LibraryElement core =
+        context.computeLibraryElement(sourceFactory.forUri("dart:core"));
+    expect(core, isNotNull);
+    ClassElement classObject =
+        _findClass(core.definingCompilationUnit, "Object");
+    expect(classObject, isNotNull);
+    ElementLocation location = classObject.location;
+    Element element = context.getElement(location);
+    expect(element, same(classObject));
   }
 
   void test_getElement_constructor_named() {
@@ -334,7 +982,7 @@
     expect(errors, hasLength(0));
   }
 
-  void fail_getErrors_html_some() {
+  void test_getErrors_html_some() {
     Source source = addSource("/test.html", r'''
 <html><head>
 <script type='application/dart' src='test.dart'/>
@@ -343,37 +991,47 @@
     expect(errorInfo, isNotNull);
     List<AnalysisError> errors = errorInfo.errors;
     expect(errors, hasLength(0));
-    context.computeErrors(source);
-    errors = errorInfo.errors;
-    expect(errors, hasLength(1));
+    errors = context.computeErrors(source);
+    expect(errors, hasLength(3));
   }
 
-  void fail_getHtmlElement_html() {
-    Source source = addSource("/test.html", "<html></html>");
-    HtmlElement element = context.getHtmlElement(source);
-    expect(element, isNull);
-    context.computeHtmlElement(source);
-    element = context.getHtmlElement(source);
-    expect(element, isNotNull);
-  }
-
-  void fail_getHtmlFilesReferencing_library() {
+  void test_getHtmlFilesReferencing_html() {
     Source htmlSource = addSource("/test.html", r'''
 <html><head>
 <script type='application/dart' src='test.dart'/>
 <script type='application/dart' src='test.js'/>
 </head></html>''');
     Source librarySource = addSource("/test.dart", "library lib;");
+    Source secondHtmlSource = addSource("/test.html", "<html></html>");
+    context.computeLibraryElement(librarySource);
+    List<Source> result = context.getHtmlFilesReferencing(secondHtmlSource);
+    expect(result, hasLength(0));
+    context.parseHtmlDocument(htmlSource);
+    result = context.getHtmlFilesReferencing(secondHtmlSource);
+    expect(result, hasLength(0));
+  }
+
+  void test_getHtmlFilesReferencing_library() {
+    Source htmlSource = addSource("/test.html", r'''
+<!DOCTYPE html>
+<html><head>
+<script type='application/dart' src='test.dart'/>
+<script type='application/dart' src='test.js'/>
+</head></html>''');
+    Source librarySource = addSource("/test.dart", "library lib;");
+    context.computeLibraryElement(librarySource);
     List<Source> result = context.getHtmlFilesReferencing(librarySource);
     expect(result, hasLength(0));
-    context.parseHtmlUnit(htmlSource);
+    // Indirectly force the data to be computed.
+    context.computeErrors(htmlSource);
     result = context.getHtmlFilesReferencing(librarySource);
     expect(result, hasLength(1));
     expect(result[0], htmlSource);
   }
 
-  void fail_getHtmlFilesReferencing_part() {
+  void test_getHtmlFilesReferencing_part() {
     Source htmlSource = addSource("/test.html", r'''
+<!DOCTYPE html>
 <html><head>
 <script type='application/dart' src='test.dart'/>
 <script type='application/dart' src='test.js'/>
@@ -384,36 +1042,246 @@
     context.computeLibraryElement(librarySource);
     List<Source> result = context.getHtmlFilesReferencing(partSource);
     expect(result, hasLength(0));
-    context.parseHtmlUnit(htmlSource);
+    // Indirectly force the data to be computed.
+    context.computeErrors(htmlSource);
     result = context.getHtmlFilesReferencing(partSource);
     expect(result, hasLength(1));
     expect(result[0], htmlSource);
   }
 
-  void fail_getHtmlSources() {
+  void test_getHtmlSources() {
     List<Source> sources = context.htmlSources;
     expect(sources, hasLength(0));
     Source source = addSource("/test.html", "");
-    context.computeKindOf(source);
     sources = context.htmlSources;
     expect(sources, hasLength(1));
     expect(sources[0], source);
   }
 
-  void fail_getLibrariesReferencedFromHtml() {
+  void test_getKindOf_html() {
+    Source source = addSource("/test.html", "");
+    expect(context.getKindOf(source), same(SourceKind.HTML));
+  }
+
+  void test_getKindOf_library() {
+    Source source = addSource("/test.dart", "library lib;");
+    expect(context.getKindOf(source), same(SourceKind.UNKNOWN));
+    context.computeKindOf(source);
+    expect(context.getKindOf(source), same(SourceKind.LIBRARY));
+  }
+
+  void test_getKindOf_part() {
+    Source source = addSource("/test.dart", "part of lib;");
+    expect(context.getKindOf(source), same(SourceKind.UNKNOWN));
+    context.computeKindOf(source);
+    expect(context.getKindOf(source), same(SourceKind.PART));
+  }
+
+  void test_getKindOf_unknown() {
+    Source source = addSource("/test.css", "");
+    expect(context.getKindOf(source), same(SourceKind.UNKNOWN));
+  }
+
+  void test_getLaunchableClientLibrarySources_doesNotImportHtml() {
+    Source source = addSource("/test.dart", r'''
+main() {}''');
+    context.computeLibraryElement(source);
+    List<Source> sources = context.launchableClientLibrarySources;
+    expect(sources, isEmpty);
+  }
+
+  void test_getLaunchableClientLibrarySources_importsHtml_explicitly() {
+    List<Source> sources = context.launchableClientLibrarySources;
+    expect(sources, isEmpty);
+    Source source = addSource("/test.dart", r'''
+import 'dart:html';
+main() {}''');
+    context.computeLibraryElement(source);
+    sources = context.launchableClientLibrarySources;
+    expect(sources, unorderedEquals([source]));
+  }
+
+  void test_getLaunchableClientLibrarySources_importsHtml_implicitly() {
+    List<Source> sources = context.launchableClientLibrarySources;
+    expect(sources, isEmpty);
+    addSource("/a.dart", r'''
+import 'dart:html';
+''');
+    Source source = addSource("/test.dart", r'''
+import 'a.dart';
+main() {}''');
+    context.computeLibraryElement(source);
+    sources = context.launchableClientLibrarySources;
+    expect(sources, unorderedEquals([source]));
+  }
+
+  void test_getLaunchableClientLibrarySources_importsHtml_implicitly2() {
+    List<Source> sources = context.launchableClientLibrarySources;
+    expect(sources, isEmpty);
+    addSource("/a.dart", r'''
+export 'dart:html';
+''');
+    Source source = addSource("/test.dart", r'''
+import 'a.dart';
+main() {}''');
+    context.computeLibraryElement(source);
+    sources = context.launchableClientLibrarySources;
+    expect(sources, unorderedEquals([source]));
+  }
+
+  void test_getLaunchableServerLibrarySources() {
+    expect(context.launchableServerLibrarySources, isEmpty);
+    Source source = addSource("/test.dart", "main() {}");
+    context.computeLibraryElement(source);
+    expect(context.launchableServerLibrarySources, unorderedEquals([source]));
+  }
+
+  void test_getLaunchableServerLibrarySources_importsHtml_explicitly() {
+    Source source = addSource("/test.dart", r'''
+import 'dart:html';
+main() {}
+''');
+    context.computeLibraryElement(source);
+    expect(context.launchableServerLibrarySources, isEmpty);
+  }
+
+  void test_getLaunchableServerLibrarySources_importsHtml_implicitly() {
+    addSource("/imports_html.dart", r'''
+import 'dart:html';
+''');
+    Source source = addSource("/test.dart", r'''
+import 'imports_html.dart';
+main() {}''');
+    context.computeLibraryElement(source);
+    expect(context.launchableServerLibrarySources, isEmpty);
+  }
+
+  void test_getLaunchableServerLibrarySources_noMain() {
+    Source source = addSource("/test.dart", '');
+    context.computeLibraryElement(source);
+    expect(context.launchableServerLibrarySources, isEmpty);
+  }
+
+  void test_getLibrariesContaining() {
+    Source librarySource = addSource("/lib.dart", r'''
+library lib;
+part 'part.dart';''');
+    Source partSource = addSource("/part.dart", "part of lib;");
+    context.computeLibraryElement(librarySource);
+    List<Source> result = context.getLibrariesContaining(librarySource);
+    expect(result, hasLength(1));
+    expect(result[0], librarySource);
+    result = context.getLibrariesContaining(partSource);
+    expect(result, hasLength(1));
+    expect(result[0], librarySource);
+  }
+
+  void test_getLibrariesDependingOn() {
+    Source libASource = addSource("/libA.dart", "library libA;");
+    addSource("/libB.dart", "library libB;");
+    Source lib1Source = addSource("/lib1.dart", r'''
+library lib1;
+import 'libA.dart';
+export 'libB.dart';''');
+    Source lib2Source = addSource("/lib2.dart", r'''
+library lib2;
+import 'libB.dart';
+export 'libA.dart';''');
+    context.computeLibraryElement(lib1Source);
+    context.computeLibraryElement(lib2Source);
+    List<Source> result = context.getLibrariesDependingOn(libASource);
+    expect(result, unorderedEquals([lib1Source, lib2Source]));
+  }
+
+  void test_getLibrariesReferencedFromHtml() {
     Source htmlSource = addSource("/test.html", r'''
+<!DOCTYPE html>
 <html><head>
 <script type='application/dart' src='test.dart'/>
 <script type='application/dart' src='test.js'/>
 </head></html>''');
     Source librarySource = addSource("/test.dart", "library lib;");
     context.computeLibraryElement(librarySource);
-    context.parseHtmlUnit(htmlSource);
+    // Indirectly force the data to be computed.
+    context.computeErrors(htmlSource);
     List<Source> result = context.getLibrariesReferencedFromHtml(htmlSource);
     expect(result, hasLength(1));
     expect(result[0], librarySource);
   }
 
+  void test_getLibrariesReferencedFromHtml_none() {
+    Source htmlSource = addSource("/test.html", r'''
+<html><head>
+<script type='application/dart' src='test.js'/>
+</head></html>''');
+    addSource("/test.dart", "library lib;");
+    context.parseHtmlDocument(htmlSource);
+    List<Source> result = context.getLibrariesReferencedFromHtml(htmlSource);
+    expect(result, hasLength(0));
+  }
+
+  void test_getLibraryElement() {
+    Source source = addSource("/test.dart", "library lib;");
+    LibraryElement element = context.getLibraryElement(source);
+    expect(element, isNull);
+    context.computeLibraryElement(source);
+    element = context.getLibraryElement(source);
+    expect(element, isNotNull);
+  }
+
+  void test_getLibrarySources() {
+    List<Source> sources = context.librarySources;
+    int originalLength = sources.length;
+    Source source = addSource("/test.dart", "library lib;");
+    context.computeKindOf(source);
+    sources = context.librarySources;
+    expect(sources, hasLength(originalLength + 1));
+    for (Source returnedSource in sources) {
+      if (returnedSource == source) {
+        return;
+      }
+    }
+    fail("The added source was not in the list of library sources");
+  }
+
+  void test_getLineInfo() {
+    Source source = addSource("/test.dart", r'''
+library lib;
+
+main() {}''');
+    LineInfo info = context.getLineInfo(source);
+    expect(info, isNull);
+    context.parseCompilationUnit(source);
+    info = context.getLineInfo(source);
+    expect(info, isNotNull);
+  }
+
+  void test_getModificationStamp_fromSource() {
+    int stamp = 42;
+    expect(context.getModificationStamp(
+        new AnalysisContextImplTest_Source_getModificationStamp_fromSource(
+            stamp)), stamp);
+  }
+
+  void test_getModificationStamp_overridden() {
+    int stamp = 42;
+    Source source =
+        new AnalysisContextImplTest_Source_getModificationStamp_overridden(
+            stamp);
+    context.setContents(source, "");
+    expect(stamp != context.getModificationStamp(source), isTrue);
+  }
+
+  void test_getPublicNamespace_element() {
+    Source source = addSource("/test.dart", "class A {}");
+    LibraryElement library = context.computeLibraryElement(source);
+    expect(library, isNotNull);
+    Namespace namespace = context.getPublicNamespace(library);
+    expect(namespace, isNotNull);
+    EngineTestCase.assertInstanceOf(
+        (obj) => obj is ClassElement, ClassElement, namespace.get("A"));
+  }
+
   void test_getResolvedCompilationUnit_library() {
     Source source = addSource("/lib.dart", "library libb;");
     LibraryElement library = context.computeLibraryElement(source);
@@ -423,48 +1291,159 @@
     expect(context.getResolvedCompilationUnit(source, library), isNull);
   }
 
-  void fail_getResolvedHtmlUnit() {
+  void test_getResolvedCompilationUnit_library_null() {
+    Source source = addSource("/lib.dart", "library lib;");
+    expect(context.getResolvedCompilationUnit(source, null), isNull);
+  }
+
+  void test_getResolvedCompilationUnit_source_dart() {
+    Source source = addSource("/lib.dart", "library lib;");
+    expect(context.getResolvedCompilationUnit2(source, source), isNull);
+    context.resolveCompilationUnit2(source, source);
+    expect(context.getResolvedCompilationUnit2(source, source), isNotNull);
+  }
+
+  void test_getResolvedCompilationUnit_source_html() {
     Source source = addSource("/test.html", "<html></html>");
-    expect(context.getResolvedHtmlUnit(source), isNull);
-    context.resolveHtmlUnit(source);
-    expect(context.getResolvedHtmlUnit(source), isNotNull);
+    expect(context.getResolvedCompilationUnit2(source, source), isNull);
+    expect(context.resolveCompilationUnit2(source, source), isNull);
+    expect(context.getResolvedCompilationUnit2(source, source), isNull);
   }
 
-  void fail_mergeContext() {
-    fail("Implement this");
+  void test_getSourceFactory() {
+    expect(context.sourceFactory, same(sourceFactory));
   }
 
-  void fail_parseHtmlUnit_noErrors() {
-    Source source = addSource("/lib.html", "<html></html>");
-    ht.HtmlUnit unit = context.parseHtmlUnit(source);
-    expect(unit, isNotNull);
+  void test_getSourcesWithFullName() {
+    String filePath = '/foo/lib/file.dart';
+    List<Source> expected = <Source>[];
+    ChangeSet changeSet = new ChangeSet();
+
+    TestSourceWithUri source1 =
+        new TestSourceWithUri(filePath, Uri.parse('file://$filePath'));
+    expected.add(source1);
+    changeSet.addedSource(source1);
+
+    TestSourceWithUri source2 =
+        new TestSourceWithUri(filePath, Uri.parse('package:foo/file.dart'));
+    expected.add(source2);
+    changeSet.addedSource(source2);
+
+    context.applyChanges(changeSet);
+    expect(context.getSourcesWithFullName(filePath), unorderedEquals(expected));
   }
 
-  void fail_parseHtmlUnit_resolveDirectives() {
-    Source libSource = addSource("/lib.dart", r'''
+  void test_getStatistics() {
+    AnalysisContextStatistics statistics = context.statistics;
+    expect(statistics, isNotNull);
+    // The following lines are fragile.
+    // The values depend on the number of libraries in the SDK.
+//    assertLength(0, statistics.getCacheRows());
+//    assertLength(0, statistics.getExceptions());
+//    assertLength(0, statistics.getSources());
+  }
+
+  void test_handleContentsChanged() {
+    ContentCache contentCache = new ContentCache();
+    context.contentCache = contentCache;
+    String oldContents = 'foo() {}';
+    String newContents = 'bar() {}';
+    // old contents
+    Source source = addSource("/test.dart", oldContents);
+    _analyzeAll_assertFinished();
+    expect(context.getResolvedCompilationUnit2(source, source), isNotNull);
+    // new contents
+    contentCache.setContents(source, newContents);
+    context.handleContentsChanged(source, oldContents, newContents, true);
+    // there is some work to do
+    AnalysisResult analysisResult = context.performAnalysisTask();
+    expect(analysisResult.changeNotices, isNotNull);
+  }
+
+  void test_isClientLibrary_dart() {
+    Source source = addSource("/test.dart", r'''
+import 'dart:html';
+
+main() {}''');
+    expect(context.isClientLibrary(source), isFalse);
+    expect(context.isServerLibrary(source), isFalse);
+    context.computeLibraryElement(source);
+    expect(context.isClientLibrary(source), isTrue);
+    expect(context.isServerLibrary(source), isFalse);
+  }
+
+  void test_isClientLibrary_html() {
+    Source source = addSource("/test.html", "<html></html>");
+    expect(context.isClientLibrary(source), isFalse);
+  }
+
+  void test_isServerLibrary_dart() {
+    Source source = addSource("/test.dart", r'''
 library lib;
-class ClassA {}''');
-    Source source = addSource("/lib.html", r'''
-<html>
-<head>
-  <script type='application/dart'>
-    import 'lib.dart';
-    ClassA v = null;
-  </script>
-</head>
-<body>
-</body>
-</html>''');
-    ht.HtmlUnit unit = context.parseHtmlUnit(source);
-    expect(unit, isNotNull);
-    // import directive should be resolved
-    ht.XmlTagNode htmlNode = unit.tagNodes[0];
-    ht.XmlTagNode headNode = htmlNode.tagNodes[0];
-    ht.HtmlScriptTagNode scriptNode = headNode.tagNodes[0];
-    CompilationUnit script = scriptNode.script;
-    ImportDirective importNode = script.directives[0] as ImportDirective;
-    expect(importNode.uriContent, isNotNull);
-    expect(importNode.source, libSource);
+
+main() {}''');
+    expect(context.isClientLibrary(source), isFalse);
+    expect(context.isServerLibrary(source), isFalse);
+    context.computeLibraryElement(source);
+    expect(context.isClientLibrary(source), isFalse);
+    expect(context.isServerLibrary(source), isTrue);
+  }
+
+  void test_isServerLibrary_html() {
+    Source source = addSource("/test.html", "<html></html>");
+    expect(context.isServerLibrary(source), isFalse);
+  }
+
+  void test_parseCompilationUnit_errors() {
+    Source source = addSource("/lib.dart", "library {");
+    CompilationUnit compilationUnit = context.parseCompilationUnit(source);
+    expect(compilationUnit, isNotNull);
+    var errorInfo = context.getErrors(source);
+    expect(errorInfo, isNotNull);
+    List<AnalysisError> errors = errorInfo.errors;
+    expect(errors, isNotNull);
+    expect(errors.length > 0, isTrue);
+  }
+
+  void test_parseCompilationUnit_exception() {
+    Source source = _addSourceWithException("/test.dart");
+    try {
+      context.parseCompilationUnit(source);
+      fail("Expected AnalysisException");
+    } on AnalysisException {
+      // Expected
+    }
+  }
+
+  void test_parseCompilationUnit_html() {
+    Source source = addSource("/test.html", "<html></html>");
+    expect(context.parseCompilationUnit(source), isNull);
+  }
+
+  void test_parseCompilationUnit_noErrors() {
+    Source source = addSource("/lib.dart", "library lib;");
+    CompilationUnit compilationUnit = context.parseCompilationUnit(source);
+    expect(compilationUnit, isNotNull);
+    AnalysisErrorInfo errorInfo = context.getErrors(source);
+    expect(errorInfo, isNotNull);
+    expect(errorInfo.errors, hasLength(0));
+  }
+
+  void test_parseCompilationUnit_nonExistentSource() {
+    Source source = newSource('/test.dart');
+    resourceProvider.deleteFile('/test.dart');
+    try {
+      context.parseCompilationUnit(source);
+      fail("Expected AnalysisException because file does not exist");
+    } on AnalysisException {
+      // Expected result
+    }
+  }
+
+  void test_parseHtmlDocument() {
+    Source source = addSource("/lib.html", "<!DOCTYPE html><html></html>");
+    Document document = context.parseHtmlDocument(source);
+    expect(document, isNotNull);
   }
 
   void test_performAnalysisTask_addPart() {
@@ -649,42 +1628,6 @@
         reason: "part resolved 3");
   }
 
-  void fail_performAnalysisTask_getContentException_dart() {
-    // add source that throw an exception on "get content"
-    Source source = new _Source_getContent_throwException('test.dart');
-    {
-      ChangeSet changeSet = new ChangeSet();
-      changeSet.addedSource(source);
-      context.applyChanges(changeSet);
-    }
-    // prepare errors
-    _analyzeAll_assertFinished();
-    List<AnalysisError> errors = context.getErrors(source).errors;
-    // validate errors
-    expect(errors, hasLength(1));
-    AnalysisError error = errors[0];
-    expect(error.source, same(source));
-    expect(error.errorCode, ScannerErrorCode.UNABLE_GET_CONTENT);
-  }
-
-  void fail_performAnalysisTask_getContentException_html() {
-    // add source that throw an exception on "get content"
-    Source source = new _Source_getContent_throwException('test.html');
-    {
-      ChangeSet changeSet = new ChangeSet();
-      changeSet.addedSource(source);
-      context.applyChanges(changeSet);
-    }
-    // prepare errors
-    _analyzeAll_assertFinished();
-    List<AnalysisError> errors = context.getErrors(source).errors;
-    // validate errors
-    expect(errors, hasLength(1));
-    AnalysisError error = errors[0];
-    expect(error.source, same(source));
-    expect(error.errorCode, ScannerErrorCode.UNABLE_GET_CONTENT);
-  }
-
   void test_performAnalysisTask_importedLibraryAdd() {
     Source libASource =
         addSource("/libA.dart", "library libA; import 'libB.dart';");
@@ -707,33 +1650,6 @@
         isFalse, reason: "libA doesn't have errors");
   }
 
-  void fail_performAnalysisTask_importedLibraryAdd_html() {
-    Source htmlSource = addSource("/page.html", r'''
-<html><body><script type="application/dart">
-  import '/libB.dart';
-  main() {print('hello dart');}
-</script></body></html>''');
-    _analyzeAll_assertFinished();
-    expect(context.getResolvedHtmlUnit(htmlSource), isNotNull,
-        reason: "htmlUnit resolved 1");
-    expect(_hasAnalysisErrorWithErrorSeverity(context.getErrors(htmlSource)),
-        isTrue, reason: "htmlSource has an error");
-    // add libB.dart and analyze
-    Source libBSource = addSource("/libB.dart", "library libB;");
-    _analyzeAll_assertFinished();
-    expect(context.getResolvedHtmlUnit(htmlSource), isNotNull,
-        reason: "htmlUnit resolved 1");
-    expect(
-        context.getResolvedCompilationUnit2(libBSource, libBSource), isNotNull,
-        reason: "libB resolved 2");
-    // TODO (danrubel) commented out to fix red bots
-//    AnalysisErrorInfo errors = _context.getErrors(htmlSource);
-//    expect(
-//        !_hasAnalysisErrorWithErrorSeverity(errors),
-//        isTrue,
-//        reason: "htmlSource doesn't have errors");
-  }
-
   void test_performAnalysisTask_importedLibraryDelete() {
     Source libASource =
         addSource("/libA.dart", "library libA; import 'libB.dart';");
@@ -757,48 +1673,6 @@
         isTrue, reason: "libA has an error");
   }
 
-  void fail_performAnalysisTask_importedLibraryDelete_html() {
-    // NOTE: This was failing before converting to the new task model.
-    Source htmlSource = addSource("/page.html", r'''
-<html><body><script type="application/dart">
-  import 'libB.dart';
-  main() {print('hello dart');}
-</script></body></html>''');
-    Source libBSource = addSource("/libB.dart", "library libB;");
-    _analyzeAll_assertFinished();
-    expect(context.getResolvedHtmlUnit(htmlSource), isNotNull,
-        reason: "htmlUnit resolved 1");
-    expect(
-        context.getResolvedCompilationUnit2(libBSource, libBSource), isNotNull,
-        reason: "libB resolved 1");
-    expect(!_hasAnalysisErrorWithErrorSeverity(context.getErrors(htmlSource)),
-        isTrue, reason: "htmlSource doesn't have errors");
-    // remove libB.dart content and analyze
-    context.setContents(libBSource, null);
-    _analyzeAll_assertFinished();
-    expect(context.getResolvedHtmlUnit(htmlSource), isNotNull,
-        reason: "htmlUnit resolved 1");
-    AnalysisErrorInfo errors = context.getErrors(htmlSource);
-    expect(_hasAnalysisErrorWithErrorSeverity(errors), isTrue,
-        reason: "htmlSource has an error");
-  }
-
-  void fail_performAnalysisTask_IOException() {
-    TestSource source = _addSourceWithException2("/test.dart", "library test;");
-    int oldTimestamp = context.getModificationStamp(source);
-    source.generateExceptionOnRead = false;
-    _analyzeAll_assertFinished();
-    expect(source.readCount, 1);
-    source.generateExceptionOnRead = true;
-    do {
-      _changeSource(source, "");
-      // Ensure that the timestamp differs,
-      // so that analysis engine notices the change
-    } while (oldTimestamp == context.getModificationStamp(source));
-    _analyzeAll_assertFinished();
-    expect(source.readCount, 2);
-  }
-
   void test_performAnalysisTask_missingPart() {
     Source source =
         addSource("/test.dart", "library lib; part 'no-such-file.dart';");
@@ -807,10 +1681,65 @@
         reason: "performAnalysisTask failed to compute an element model");
   }
 
-  void fail_recordLibraryElements() {
-    fail("Implement this");
+  void test_performAnalysisTask_modifiedAfterParse() {
+    // TODO(scheglov) no threads in Dart
+//    Source source = _addSource("/test.dart", "library lib;");
+//    int initialTime = _context.getModificationStamp(source);
+//    List<Source> sources = new List<Source>();
+//    sources.add(source);
+//    _context.analysisPriorityOrder = sources;
+//    _context.parseCompilationUnit(source);
+//    while (initialTime == JavaSystem.currentTimeMillis()) {
+//      Thread.sleep(1);
+//      // Force the modification time to be different.
+//    }
+//    _context.setContents(source, "library test;");
+//    JUnitTestCase.assertTrue(initialTime != _context.getModificationStamp(source));
+//    _analyzeAll_assertFinished();
+//    JUnitTestCase.assertNotNullMsg("performAnalysisTask failed to compute an element model", _context.getLibraryElement(source));
   }
 
+  void test_performAnalysisTask_onResultComputed() {
+    Set<String> libraryElementUris = new Set<String>();
+    Set<String> parsedUnitUris = new Set<String>();
+    Set<String> resolvedUnitUris = new Set<String>();
+    // listen
+    context.onResultComputed(LIBRARY_ELEMENT).listen((event) {
+      Source librarySource = event.target;
+      libraryElementUris.add(librarySource.uri.toString());
+    });
+    context.onResultComputed(PARSED_UNIT).listen((event) {
+      Source source = event.target;
+      parsedUnitUris.add(source.uri.toString());
+    });
+    context.onResultComputed(RESOLVED_UNIT).listen((event) {
+      LibrarySpecificUnit target = event.target;
+      Source librarySource = target.library;
+      resolvedUnitUris.add(librarySource.uri.toString());
+    });
+    // analyze
+    addSource('/test.dart', 'main() {}');
+    _analyzeAll_assertFinished();
+    // verify
+    expect(libraryElementUris, contains('dart:core'));
+    expect(libraryElementUris, contains('file:///test.dart'));
+    expect(parsedUnitUris, contains('dart:core'));
+    expect(parsedUnitUris, contains('file:///test.dart'));
+    expect(resolvedUnitUris, contains('dart:core'));
+    expect(resolvedUnitUris, contains('file:///test.dart'));
+  }
+
+//  void test_resolveCompilationUnit_sourceChangeDuringResolution() {
+//    _context = new _AnalysisContext_sourceChangeDuringResolution();
+//    AnalysisContextFactory.initContextWithCore(_context);
+//    _sourceFactory = _context.sourceFactory;
+//    Source source = _addSource("/lib.dart", "library lib;");
+//    CompilationUnit compilationUnit =
+//        _context.resolveCompilationUnit2(source, source);
+//    expect(compilationUnit, isNotNull);
+//    expect(_context.getLineInfo(source), isNotNull);
+//  }
+
   void test_resolveCompilationUnit_import_relative() {
     Source sourceA =
         addSource("/libA.dart", "library libA; import 'libB.dart'; class A{}");
@@ -851,957 +1780,6 @@
     ]);
   }
 
-  void fail_resolveHtmlUnit() {
-    Source source = addSource("/lib.html", "<html></html>");
-    ht.HtmlUnit unit = context.resolveHtmlUnit(source);
-    expect(unit, isNotNull);
-  }
-
-  void fail_setAnalysisOptions_reduceAnalysisPriorityOrder() {
-    AnalysisOptionsImpl options =
-        new AnalysisOptionsImpl.from(context.analysisOptions);
-    List<Source> sources = new List<Source>();
-    for (int index = 0; index < options.cacheSize; index++) {
-      sources.add(addSource("/lib.dart$index", ""));
-    }
-    context.analysisPriorityOrder = sources;
-    int oldPriorityOrderSize = _getPriorityOrder(context).length;
-    options.cacheSize = options.cacheSize - 10;
-    context.analysisOptions = options;
-    expect(oldPriorityOrderSize > _getPriorityOrder(context).length, isTrue);
-  }
-
-  void fail_setAnalysisPriorityOrder_lessThanCacheSize() {
-    AnalysisOptions options = context.analysisOptions;
-    List<Source> sources = new List<Source>();
-    for (int index = 0; index < options.cacheSize; index++) {
-      sources.add(addSource("/lib.dart$index", ""));
-    }
-    context.analysisPriorityOrder = sources;
-    expect(options.cacheSize > _getPriorityOrder(context).length, isTrue);
-  }
-
-  Future fail_setChangedContents_libraryWithPart() {
-    AnalysisOptionsImpl options = new AnalysisOptionsImpl();
-    options.incremental = true;
-    context.analysisOptions = options;
-    SourcesChangedListener listener = new SourcesChangedListener();
-    context.onSourcesChanged.listen(listener.onData);
-    String oldCode = r'''
-library lib;
-part 'part.dart';
-int a = 0;''';
-    Source librarySource = addSource("/lib.dart", oldCode);
-    String partContents = r'''
-part of lib;
-int b = a;''';
-    Source partSource = addSource("/part.dart", partContents);
-    LibraryElement element = context.computeLibraryElement(librarySource);
-    CompilationUnit unit =
-        context.getResolvedCompilationUnit(librarySource, element);
-    expect(unit, isNotNull);
-    int offset = oldCode.indexOf("int a") + 4;
-    String newCode = r'''
-library lib;
-part 'part.dart';
-int ya = 0;''';
-    expect(_getIncrementalAnalysisCache(context), isNull);
-    context.setChangedContents(librarySource, newCode, offset, 0, 1);
-    expect(context.getContents(librarySource).data, newCode);
-    IncrementalAnalysisCache incrementalCache =
-        _getIncrementalAnalysisCache(context);
-    expect(incrementalCache.librarySource, librarySource);
-    expect(incrementalCache.resolvedUnit, same(unit));
-    expect(
-        context.getResolvedCompilationUnit2(partSource, librarySource), isNull);
-    expect(incrementalCache.newContents, newCode);
-    return pumpEventQueue().then((_) {
-      listener.assertEvent(wereSourcesAdded: true);
-      listener.assertEvent(changedSources: [librarySource]);
-      listener.assertEvent(wereSourcesAdded: true);
-      listener.assertEvent(changedSources: [partSource]);
-      listener.assertEvent(changedSources: [librarySource]);
-      listener.assertNoMoreEvents();
-    });
-  }
-
-  void test_setContents_unchanged_consistentModificationTime() {
-    String contents = "// foo";
-    Source source = addSource("/test.dart", contents);
-    context.setContents(source, contents);
-    // do all, no tasks
-    _analyzeAll_assertFinished();
-    {
-      AnalysisResult result = context.performAnalysisTask();
-      expect(result.changeNotices, isNull);
-    }
-    // set the same contents, still no tasks
-    context.setContents(source, contents);
-    {
-      AnalysisResult result = context.performAnalysisTask();
-      expect(result.changeNotices, isNull);
-    }
-  }
-
-  void fail_unreadableSource() {
-    Source test1 = addSource("/test1.dart", r'''
-import 'test2.dart';
-library test1;''');
-    Source test2 = addSource("/test2.dart", r'''
-import 'test1.dart';
-import 'test3.dart';
-library test2;''');
-    Source test3 = _addSourceWithException("/test3.dart");
-    _analyzeAll_assertFinished();
-    // test1 and test2 should have been successfully analyzed
-    // despite the fact that test3 couldn't be read.
-    expect(context.computeLibraryElement(test1), isNotNull);
-    expect(context.computeLibraryElement(test2), isNotNull);
-    expect(context.computeLibraryElement(test3), isNull);
-  }
-
-  @override
-  void tearDown() {
-    context = null;
-    sourceFactory = null;
-    super.tearDown();
-  }
-
-  Future test_applyChanges_add() {
-    SourcesChangedListener listener = new SourcesChangedListener();
-    context.onSourcesChanged.listen(listener.onData);
-    expect(context.sourcesNeedingProcessing, isEmpty);
-    Source source = newSource('/test.dart');
-    ChangeSet changeSet = new ChangeSet();
-    changeSet.addedSource(source);
-    context.applyChanges(changeSet);
-    expect(context.sourcesNeedingProcessing, contains(source));
-    return pumpEventQueue().then((_) {
-      listener.assertEvent(wereSourcesAdded: true);
-      listener.assertNoMoreEvents();
-    });
-  }
-
-  Future test_applyChanges_change() {
-    SourcesChangedListener listener = new SourcesChangedListener();
-    context.onSourcesChanged.listen(listener.onData);
-    expect(context.sourcesNeedingProcessing, isEmpty);
-    Source source = newSource('/test.dart');
-    ChangeSet changeSet1 = new ChangeSet();
-    changeSet1.addedSource(source);
-    context.applyChanges(changeSet1);
-    expect(context.sourcesNeedingProcessing, contains(source));
-    Source source2 = newSource('/test2.dart');
-    ChangeSet changeSet2 = new ChangeSet();
-    changeSet2.addedSource(source2);
-    changeSet2.changedSource(source);
-    context.applyChanges(changeSet2);
-    return pumpEventQueue().then((_) {
-      listener.assertEvent(wereSourcesAdded: true);
-      listener.assertEvent(wereSourcesAdded: true, changedSources: [source]);
-      listener.assertNoMoreEvents();
-    });
-  }
-
-  Future test_applyChanges_change_content() {
-    SourcesChangedListener listener = new SourcesChangedListener();
-    context.onSourcesChanged.listen(listener.onData);
-    expect(context.sourcesNeedingProcessing, isEmpty);
-    Source source = newSource('/test.dart');
-    ChangeSet changeSet1 = new ChangeSet();
-    changeSet1.addedSource(source);
-    context.applyChanges(changeSet1);
-    expect(context.sourcesNeedingProcessing, contains(source));
-    Source source2 = newSource('/test2.dart');
-    ChangeSet changeSet2 = new ChangeSet();
-    changeSet2.addedSource(source2);
-    changeSet2.changedContent(source, 'library test;');
-    context.applyChanges(changeSet2);
-    return pumpEventQueue().then((_) {
-      listener.assertEvent(wereSourcesAdded: true);
-      listener.assertEvent(wereSourcesAdded: true, changedSources: [source]);
-      listener.assertNoMoreEvents();
-    });
-  }
-
-  void test_applyChanges_change_flush_element() {
-    Source librarySource = addSource("/lib.dart", r'''
-library lib;
-int a = 0;''');
-    expect(context.computeLibraryElement(librarySource), isNotNull);
-    context.setContents(librarySource, r'''
-library lib;
-int aa = 0;''');
-    expect(context.getLibraryElement(librarySource), isNull);
-  }
-
-  Future test_applyChanges_change_multiple() {
-    SourcesChangedListener listener = new SourcesChangedListener();
-    context.onSourcesChanged.listen(listener.onData);
-    String libraryContents1 = r'''
-library lib;
-part 'part.dart';
-int a = 0;''';
-    Source librarySource = addSource("/lib.dart", libraryContents1);
-    String partContents1 = r'''
-part of lib;
-int b = a;''';
-    Source partSource = addSource("/part.dart", partContents1);
-    context.computeLibraryElement(librarySource);
-    String libraryContents2 = r'''
-library lib;
-part 'part.dart';
-int aa = 0;''';
-    context.setContents(librarySource, libraryContents2);
-    String partContents2 = r'''
-part of lib;
-int b = aa;''';
-    context.setContents(partSource, partContents2);
-    context.computeLibraryElement(librarySource);
-    CompilationUnit libraryUnit =
-        context.resolveCompilationUnit2(librarySource, librarySource);
-    expect(libraryUnit, isNotNull);
-    CompilationUnit partUnit =
-        context.resolveCompilationUnit2(partSource, librarySource);
-    expect(partUnit, isNotNull);
-    TopLevelVariableDeclaration declaration =
-        libraryUnit.declarations[0] as TopLevelVariableDeclaration;
-    Element declarationElement = declaration.variables.variables[0].element;
-    TopLevelVariableDeclaration use =
-        partUnit.declarations[0] as TopLevelVariableDeclaration;
-    Element useElement = (use.variables.variables[
-        0].initializer as SimpleIdentifier).staticElement;
-    expect((useElement as PropertyAccessorElement).variable,
-        same(declarationElement));
-    return pumpEventQueue().then((_) {
-      listener.assertEvent(wereSourcesAdded: true);
-      listener.assertEvent(wereSourcesAdded: true);
-      listener.assertEvent(changedSources: [librarySource]);
-      listener.assertEvent(changedSources: [partSource]);
-      listener.assertNoMoreEvents();
-    });
-  }
-
-  Future test_applyChanges_change_range() {
-    SourcesChangedListener listener = new SourcesChangedListener();
-    context.onSourcesChanged.listen(listener.onData);
-    expect(context.sourcesNeedingProcessing, isEmpty);
-    Source source = newSource('/test.dart');
-    ChangeSet changeSet1 = new ChangeSet();
-    changeSet1.addedSource(source);
-    context.applyChanges(changeSet1);
-    expect(context.sourcesNeedingProcessing, contains(source));
-    Source source2 = newSource('/test2.dart');
-    ChangeSet changeSet2 = new ChangeSet();
-    changeSet2.addedSource(source2);
-    changeSet2.changedRange(source, 'library test;', 0, 0, 13);
-    context.applyChanges(changeSet2);
-    return pumpEventQueue().then((_) {
-      listener.assertEvent(wereSourcesAdded: true);
-      listener.assertEvent(wereSourcesAdded: true, changedSources: [source]);
-      listener.assertNoMoreEvents();
-    });
-  }
-
-  void test_computeDocumentationComment_block() {
-    String comment = "/** Comment */";
-    Source source = addSource("/test.dart", """
-$comment
-class A {}""");
-    LibraryElement libraryElement = context.computeLibraryElement(source);
-    expect(libraryElement, isNotNull);
-    ClassElement classElement = libraryElement.definingCompilationUnit.types[0];
-    expect(libraryElement, isNotNull);
-    expect(context.computeDocumentationComment(classElement), comment);
-  }
-
-  void test_computeDocumentationComment_none() {
-    Source source = addSource("/test.dart", "class A {}");
-    LibraryElement libraryElement = context.computeLibraryElement(source);
-    expect(libraryElement, isNotNull);
-    ClassElement classElement = libraryElement.definingCompilationUnit.types[0];
-    expect(libraryElement, isNotNull);
-    expect(context.computeDocumentationComment(classElement), isNull);
-  }
-
-  void test_computeDocumentationComment_null() {
-    expect(context.computeDocumentationComment(null), isNull);
-  }
-
-  void test_computeDocumentationComment_singleLine_multiple_EOL_n() {
-    String comment = "/// line 1\n/// line 2\n/// line 3\n";
-    Source source = addSource("/test.dart", "${comment}class A {}");
-    LibraryElement libraryElement = context.computeLibraryElement(source);
-    expect(libraryElement, isNotNull);
-    ClassElement classElement = libraryElement.definingCompilationUnit.types[0];
-    expect(libraryElement, isNotNull);
-    String actual = context.computeDocumentationComment(classElement);
-    expect(actual, "/// line 1\n/// line 2\n/// line 3");
-  }
-
-  void test_computeDocumentationComment_singleLine_multiple_EOL_rn() {
-    String comment = "/// line 1\r\n/// line 2\r\n/// line 3\r\n";
-    Source source = addSource("/test.dart", "${comment}class A {}");
-    LibraryElement libraryElement = context.computeLibraryElement(source);
-    expect(libraryElement, isNotNull);
-    ClassElement classElement = libraryElement.definingCompilationUnit.types[0];
-    expect(libraryElement, isNotNull);
-    String actual = context.computeDocumentationComment(classElement);
-    expect(actual, "/// line 1\n/// line 2\n/// line 3");
-  }
-
-  void test_computeExportedLibraries_none() {
-    Source source = addSource("/test.dart", "library test;");
-    expect(context.computeExportedLibraries(source), hasLength(0));
-  }
-
-  void test_computeExportedLibraries_some() {
-    //    addSource("/lib1.dart", "library lib1;");
-    //    addSource("/lib2.dart", "library lib2;");
-    Source source = addSource(
-        "/test.dart", "library test; export 'lib1.dart'; export 'lib2.dart';");
-    expect(context.computeExportedLibraries(source), hasLength(2));
-  }
-
-  void test_computeHtmlElement_nonHtml() {
-    Source source = addSource("/test.dart", "library test;");
-    expect(context.computeHtmlElement(source), isNull);
-  }
-
-  void test_computeKindOf_html() {
-    Source source = addSource("/test.html", "");
-    expect(context.computeKindOf(source), same(SourceKind.HTML));
-  }
-
-  void test_computeKindOf_library() {
-    Source source = addSource("/test.dart", "library lib;");
-    expect(context.computeKindOf(source), same(SourceKind.LIBRARY));
-  }
-
-  void test_computeKindOf_libraryAndPart() {
-    Source source = addSource("/test.dart", "library lib; part of lib;");
-    expect(context.computeKindOf(source), same(SourceKind.LIBRARY));
-  }
-
-  void test_computeKindOf_part() {
-    Source source = addSource("/test.dart", "part of lib;");
-    expect(context.computeKindOf(source), same(SourceKind.PART));
-  }
-
-  void test_computeLibraryElement() {
-    Source source = addSource("/test.dart", "library lib;");
-    LibraryElement element = context.computeLibraryElement(source);
-    expect(element, isNotNull);
-  }
-
-  void test_computeLineInfo_dart() {
-    Source source = addSource("/test.dart", r'''
-library lib;
-
-main() {}''');
-    LineInfo info = context.computeLineInfo(source);
-    expect(info, isNotNull);
-  }
-
-  void test_computeLineInfo_html() {
-    Source source = addSource("/test.html", r'''
-<html>
-  <body>
-    <h1>A</h1>
-  </body>
-</html>''');
-    LineInfo info = context.computeLineInfo(source);
-    expect(info, isNotNull);
-  }
-
-  Future test_computeResolvedCompilationUnitAsync_afterDispose() {
-    Source source = addSource("/lib.dart", "library lib;");
-    // Complete all pending analysis tasks and flush the AST so that it won't
-    // be available immediately.
-    _performPendingAnalysisTasks();
-    _flushAst(source);
-    // Dispose of the context.
-    context.dispose();
-    // Any attempt to start an asynchronous computation should return a future
-    // which completes with error.
-    CancelableFuture<CompilationUnit> future =
-        context.computeResolvedCompilationUnitAsync(source, source);
-    bool completed = false;
-    future.then((CompilationUnit unit) {
-      fail('Future should have completed with error');
-    }, onError: (error) {
-      expect(error, new isInstanceOf<AnalysisNotScheduledError>());
-      completed = true;
-    });
-    return pumpEventQueue().then((_) {
-      expect(completed, isTrue);
-    });
-  }
-
-  void test_dispose() {
-    expect(context.isDisposed, isFalse);
-    context.dispose();
-    expect(context.isDisposed, isTrue);
-  }
-
-  void test_ensureResolvedDartUnits_definingUnit_hasResolved() {
-    Source source = addSource('/test.dart', '');
-    LibrarySpecificUnit libTarget = new LibrarySpecificUnit(source, source);
-    analysisDriver.computeResult(libTarget, RESOLVED_UNIT);
-    CompilationUnit unit =
-        context.getCacheEntry(libTarget).getValue(RESOLVED_UNIT);
-    List<CompilationUnit> units = context.ensureResolvedDartUnits(source);
-    expect(units, unorderedEquals([unit]));
-  }
-
-  void test_ensureResolvedDartUnits_definingUnit_notResolved() {
-    Source source = addSource('/test.dart', '');
-    LibrarySpecificUnit libTarget = new LibrarySpecificUnit(source, source);
-    analysisDriver.computeResult(libTarget, RESOLVED_UNIT);
-    // flush
-    context.getCacheEntry(libTarget).setState(
-        RESOLVED_UNIT, CacheState.FLUSHED);
-    // schedule recomputing
-    List<CompilationUnit> units = context.ensureResolvedDartUnits(source);
-    expect(units, isNull);
-    // should be the next result to compute
-    TargetedResult nextResult = context.dartWorkManager.getNextResult();
-    expect(nextResult.target, libTarget);
-    expect(nextResult.result, RESOLVED_UNIT);
-  }
-
-  void test_ensureResolvedDartUnits_partUnit_notResolved() {
-    Source libSource1 = addSource('/lib1.dart', r'''
-library lib;
-part 'part.dart';
-''');
-    Source libSource2 = addSource('/lib2.dart', r'''
-library lib;
-part 'part.dart';
-''');
-    Source partSource = addSource('/part.dart', r'''
-part of lib;
-''');
-    LibrarySpecificUnit partTarget1 =
-        new LibrarySpecificUnit(libSource1, partSource);
-    LibrarySpecificUnit partTarget2 =
-        new LibrarySpecificUnit(libSource2, partSource);
-    analysisDriver.computeResult(partTarget1, RESOLVED_UNIT);
-    analysisDriver.computeResult(partTarget2, RESOLVED_UNIT);
-    // flush
-    context.getCacheEntry(partTarget1).setState(
-        RESOLVED_UNIT, CacheState.FLUSHED);
-    context.getCacheEntry(partTarget2).setState(
-        RESOLVED_UNIT, CacheState.FLUSHED);
-    // schedule recomputing
-    List<CompilationUnit> units = context.ensureResolvedDartUnits(partSource);
-    expect(units, isNull);
-    // should be the next result to compute
-    TargetedResult nextResult = context.dartWorkManager.getNextResult();
-    expect(nextResult.target, anyOf(partTarget1, partTarget2));
-    expect(nextResult.result, RESOLVED_UNIT);
-  }
-
-  void test_ensureResolvedDartUnits_partUnit_hasResolved() {
-    Source libSource1 = addSource('/lib1.dart', r'''
-library lib;
-part 'part.dart';
-''');
-    Source libSource2 = addSource('/lib2.dart', r'''
-library lib;
-part 'part.dart';
-''');
-    Source partSource = addSource('/part.dart', r'''
-part of lib;
-''');
-    LibrarySpecificUnit partTarget1 =
-        new LibrarySpecificUnit(libSource1, partSource);
-    LibrarySpecificUnit partTarget2 =
-        new LibrarySpecificUnit(libSource2, partSource);
-    analysisDriver.computeResult(partTarget1, RESOLVED_UNIT);
-    analysisDriver.computeResult(partTarget2, RESOLVED_UNIT);
-    CompilationUnit unit1 =
-        context.getCacheEntry(partTarget1).getValue(RESOLVED_UNIT);
-    CompilationUnit unit2 =
-        context.getCacheEntry(partTarget2).getValue(RESOLVED_UNIT);
-    List<CompilationUnit> units = context.ensureResolvedDartUnits(partSource);
-    expect(units, unorderedEquals([unit1, unit2]));
-  }
-
-  void test_exists_false() {
-    TestSource source = new TestSource();
-    source.exists2 = false;
-    expect(context.exists(source), isFalse);
-  }
-
-  void test_exists_null() {
-    expect(context.exists(null), isFalse);
-  }
-
-  void test_exists_overridden() {
-    Source source = new TestSource();
-    context.setContents(source, "");
-    expect(context.exists(source), isTrue);
-  }
-
-  void test_exists_true() {
-    expect(context.exists(new AnalysisContextImplTest_Source_exists_true()),
-        isTrue);
-  }
-
-  void test_getAnalysisOptions() {
-    expect(context.analysisOptions, isNotNull);
-  }
-
-  void test_getContents_fromSource() {
-    String content = "library lib;";
-    TimestampedData<String> contents =
-        context.getContents(new TestSource('/test.dart', content));
-    expect(contents.data.toString(), content);
-  }
-
-  void test_getContents_overridden() {
-    String content = "library lib;";
-    Source source = new TestSource();
-    context.setContents(source, content);
-    TimestampedData<String> contents = context.getContents(source);
-    expect(contents.data.toString(), content);
-  }
-
-  void test_getContents_unoverridden() {
-    String content = "library lib;";
-    Source source = new TestSource('/test.dart', content);
-    context.setContents(source, "part of lib;");
-    context.setContents(source, null);
-    TimestampedData<String> contents = context.getContents(source);
-    expect(contents.data.toString(), content);
-  }
-
-  void test_getDeclaredVariables() {
-    expect(context.declaredVariables, isNotNull);
-  }
-
-  void test_getElement() {
-    LibraryElement core =
-        context.computeLibraryElement(sourceFactory.forUri("dart:core"));
-    expect(core, isNotNull);
-    ClassElement classObject =
-        _findClass(core.definingCompilationUnit, "Object");
-    expect(classObject, isNotNull);
-    ElementLocation location = classObject.location;
-    Element element = context.getElement(location);
-    expect(element, same(classObject));
-  }
-
-  void test_getHtmlElement_dart() {
-    Source source = addSource("/test.dart", "");
-    expect(context.getHtmlElement(source), isNull);
-    expect(context.computeHtmlElement(source), isNull);
-    expect(context.getHtmlElement(source), isNull);
-  }
-
-  void test_getHtmlFilesReferencing_html() {
-    Source htmlSource = addSource("/test.html", r'''
-<html><head>
-<script type='application/dart' src='test.dart'/>
-<script type='application/dart' src='test.js'/>
-</head></html>''');
-    Source librarySource = addSource("/test.dart", "library lib;");
-    Source secondHtmlSource = addSource("/test.html", "<html></html>");
-    context.computeLibraryElement(librarySource);
-    List<Source> result = context.getHtmlFilesReferencing(secondHtmlSource);
-    expect(result, hasLength(0));
-    context.parseHtmlUnit(htmlSource);
-    result = context.getHtmlFilesReferencing(secondHtmlSource);
-    expect(result, hasLength(0));
-  }
-
-  void test_getKindOf_html() {
-    Source source = addSource("/test.html", "");
-    expect(context.getKindOf(source), same(SourceKind.HTML));
-  }
-
-  void test_getKindOf_library() {
-    Source source = addSource("/test.dart", "library lib;");
-    expect(context.getKindOf(source), same(SourceKind.UNKNOWN));
-    context.computeKindOf(source);
-    expect(context.getKindOf(source), same(SourceKind.LIBRARY));
-  }
-
-  void test_getKindOf_part() {
-    Source source = addSource("/test.dart", "part of lib;");
-    expect(context.getKindOf(source), same(SourceKind.UNKNOWN));
-    context.computeKindOf(source);
-    expect(context.getKindOf(source), same(SourceKind.PART));
-  }
-
-  void test_getKindOf_unknown() {
-    Source source = addSource("/test.css", "");
-    expect(context.getKindOf(source), same(SourceKind.UNKNOWN));
-  }
-
-  void test_getLaunchableClientLibrarySources_doesNotImportHtml() {
-    Source source = addSource("/test.dart", r'''
-main() {}''');
-    context.computeLibraryElement(source);
-    List<Source> sources = context.launchableClientLibrarySources;
-    expect(sources, isEmpty);
-  }
-
-  void test_getLaunchableClientLibrarySources_importsHtml_explicitly() {
-    List<Source> sources = context.launchableClientLibrarySources;
-    expect(sources, isEmpty);
-    Source source = addSource("/test.dart", r'''
-import 'dart:html';
-main() {}''');
-    context.computeLibraryElement(source);
-    sources = context.launchableClientLibrarySources;
-    expect(sources, unorderedEquals([source]));
-  }
-
-  void test_getLaunchableClientLibrarySources_importsHtml_implicitly() {
-    List<Source> sources = context.launchableClientLibrarySources;
-    expect(sources, isEmpty);
-    addSource("/a.dart", r'''
-import 'dart:html';
-''');
-    Source source = addSource("/test.dart", r'''
-import 'a.dart';
-main() {}''');
-    context.computeLibraryElement(source);
-    sources = context.launchableClientLibrarySources;
-    expect(sources, unorderedEquals([source]));
-  }
-
-  void test_getLaunchableClientLibrarySources_importsHtml_implicitly2() {
-    List<Source> sources = context.launchableClientLibrarySources;
-    expect(sources, isEmpty);
-    addSource("/a.dart", r'''
-export 'dart:html';
-''');
-    Source source = addSource("/test.dart", r'''
-import 'a.dart';
-main() {}''');
-    context.computeLibraryElement(source);
-    sources = context.launchableClientLibrarySources;
-    expect(sources, unorderedEquals([source]));
-  }
-
-  void test_getLaunchableServerLibrarySources() {
-    expect(context.launchableServerLibrarySources, isEmpty);
-    Source source = addSource("/test.dart", "main() {}");
-    context.computeLibraryElement(source);
-    expect(context.launchableServerLibrarySources, unorderedEquals([source]));
-  }
-
-  void test_getLaunchableServerLibrarySources_importsHtml_explicitly() {
-    Source source = addSource("/test.dart", r'''
-import 'dart:html';
-main() {}
-''');
-    context.computeLibraryElement(source);
-    expect(context.launchableServerLibrarySources, isEmpty);
-  }
-
-  void test_getLaunchableServerLibrarySources_importsHtml_implicitly() {
-    addSource("/imports_html.dart", r'''
-import 'dart:html';
-''');
-    Source source = addSource("/test.dart", r'''
-import 'imports_html.dart';
-main() {}''');
-    context.computeLibraryElement(source);
-    expect(context.launchableServerLibrarySources, isEmpty);
-  }
-
-  void test_getLaunchableServerLibrarySources_noMain() {
-    Source source = addSource("/test.dart", '');
-    context.computeLibraryElement(source);
-    expect(context.launchableServerLibrarySources, isEmpty);
-  }
-
-  void test_getLibrariesContaining() {
-    Source librarySource = addSource("/lib.dart", r'''
-library lib;
-part 'part.dart';''');
-    Source partSource = addSource("/part.dart", "part of lib;");
-    context.computeLibraryElement(librarySource);
-    List<Source> result = context.getLibrariesContaining(librarySource);
-    expect(result, hasLength(1));
-    expect(result[0], librarySource);
-    result = context.getLibrariesContaining(partSource);
-    expect(result, hasLength(1));
-    expect(result[0], librarySource);
-  }
-
-  void test_getLibrariesDependingOn() {
-    Source libASource = addSource("/libA.dart", "library libA;");
-    addSource("/libB.dart", "library libB;");
-    Source lib1Source = addSource("/lib1.dart", r'''
-library lib1;
-import 'libA.dart';
-export 'libB.dart';''');
-    Source lib2Source = addSource("/lib2.dart", r'''
-library lib2;
-import 'libB.dart';
-export 'libA.dart';''');
-    context.computeLibraryElement(lib1Source);
-    context.computeLibraryElement(lib2Source);
-    List<Source> result = context.getLibrariesDependingOn(libASource);
-    expect(result, unorderedEquals([lib1Source, lib2Source]));
-  }
-
-  void test_getLibrariesReferencedFromHtml_no() {
-    Source htmlSource = addSource("/test.html", r'''
-<html><head>
-<script type='application/dart' src='test.js'/>
-</head></html>''');
-    addSource("/test.dart", "library lib;");
-    context.parseHtmlUnit(htmlSource);
-    List<Source> result = context.getLibrariesReferencedFromHtml(htmlSource);
-    expect(result, hasLength(0));
-  }
-
-  void test_getLibraryElement() {
-    Source source = addSource("/test.dart", "library lib;");
-    LibraryElement element = context.getLibraryElement(source);
-    expect(element, isNull);
-    context.computeLibraryElement(source);
-    element = context.getLibraryElement(source);
-    expect(element, isNotNull);
-  }
-
-  void test_getLibrarySources() {
-    List<Source> sources = context.librarySources;
-    int originalLength = sources.length;
-    Source source = addSource("/test.dart", "library lib;");
-    context.computeKindOf(source);
-    sources = context.librarySources;
-    expect(sources, hasLength(originalLength + 1));
-    for (Source returnedSource in sources) {
-      if (returnedSource == source) {
-        return;
-      }
-    }
-    fail("The added source was not in the list of library sources");
-  }
-
-  void test_getLineInfo() {
-    Source source = addSource("/test.dart", r'''
-library lib;
-
-main() {}''');
-    LineInfo info = context.getLineInfo(source);
-    expect(info, isNull);
-    context.parseCompilationUnit(source);
-    info = context.getLineInfo(source);
-    expect(info, isNotNull);
-  }
-
-  void test_getModificationStamp_fromSource() {
-    int stamp = 42;
-    expect(context.getModificationStamp(
-        new AnalysisContextImplTest_Source_getModificationStamp_fromSource(
-            stamp)), stamp);
-  }
-
-  void test_getModificationStamp_overridden() {
-    int stamp = 42;
-    Source source =
-        new AnalysisContextImplTest_Source_getModificationStamp_overridden(
-            stamp);
-    context.setContents(source, "");
-    expect(stamp != context.getModificationStamp(source), isTrue);
-  }
-
-  void test_getPublicNamespace_element() {
-    Source source = addSource("/test.dart", "class A {}");
-    LibraryElement library = context.computeLibraryElement(source);
-    expect(library, isNotNull);
-    Namespace namespace = context.getPublicNamespace(library);
-    expect(namespace, isNotNull);
-    EngineTestCase.assertInstanceOf(
-        (obj) => obj is ClassElement, ClassElement, namespace.get("A"));
-  }
-
-  void test_getResolvedCompilationUnit_library_null() {
-    Source source = addSource("/lib.dart", "library lib;");
-    expect(context.getResolvedCompilationUnit(source, null), isNull);
-  }
-
-  void test_getResolvedCompilationUnit_source_dart() {
-    Source source = addSource("/lib.dart", "library lib;");
-    expect(context.getResolvedCompilationUnit2(source, source), isNull);
-    context.resolveCompilationUnit2(source, source);
-    expect(context.getResolvedCompilationUnit2(source, source), isNotNull);
-  }
-
-  void test_getResolvedCompilationUnit_source_html() {
-    Source source = addSource("/test.html", "<html></html>");
-    expect(context.getResolvedCompilationUnit2(source, source), isNull);
-    expect(context.resolveCompilationUnit2(source, source), isNull);
-    expect(context.getResolvedCompilationUnit2(source, source), isNull);
-  }
-
-  void test_getSourceFactory() {
-    expect(context.sourceFactory, same(sourceFactory));
-  }
-
-  void test_getSourcesWithFullName() {
-    String filePath = '/foo/lib/file.dart';
-    List<Source> expected = <Source>[];
-    ChangeSet changeSet = new ChangeSet();
-
-    TestSourceWithUri source1 =
-        new TestSourceWithUri(filePath, Uri.parse('file://$filePath'));
-    expected.add(source1);
-    changeSet.addedSource(source1);
-
-    TestSourceWithUri source2 =
-        new TestSourceWithUri(filePath, Uri.parse('package:foo/file.dart'));
-    expected.add(source2);
-    changeSet.addedSource(source2);
-
-    context.applyChanges(changeSet);
-    expect(context.getSourcesWithFullName(filePath), unorderedEquals(expected));
-  }
-
-  void test_getStatistics() {
-    AnalysisContextStatistics statistics = context.statistics;
-    expect(statistics, isNotNull);
-    // The following lines are fragile.
-    // The values depend on the number of libraries in the SDK.
-//    assertLength(0, statistics.getCacheRows());
-//    assertLength(0, statistics.getExceptions());
-//    assertLength(0, statistics.getSources());
-  }
-
-  void test_handleContentsChanged() {
-    ContentCache contentCache = new ContentCache();
-    context.contentCache = contentCache;
-    String oldContents = 'foo() {}';
-    String newContents = 'bar() {}';
-    // old contents
-    Source source = addSource("/test.dart", oldContents);
-    _analyzeAll_assertFinished();
-    expect(context.getResolvedCompilationUnit2(source, source), isNotNull);
-    // new contents
-    contentCache.setContents(source, newContents);
-    context.handleContentsChanged(source, oldContents, newContents, true);
-    // there is some work to do
-    AnalysisResult analysisResult = context.performAnalysisTask();
-    expect(analysisResult.changeNotices, isNotNull);
-  }
-
-  void test_isClientLibrary_dart() {
-    Source source = addSource("/test.dart", r'''
-import 'dart:html';
-
-main() {}''');
-    expect(context.isClientLibrary(source), isFalse);
-    expect(context.isServerLibrary(source), isFalse);
-    context.computeLibraryElement(source);
-    expect(context.isClientLibrary(source), isTrue);
-    expect(context.isServerLibrary(source), isFalse);
-  }
-
-  void test_isClientLibrary_html() {
-    Source source = addSource("/test.html", "<html></html>");
-    expect(context.isClientLibrary(source), isFalse);
-  }
-
-  void test_isServerLibrary_dart() {
-    Source source = addSource("/test.dart", r'''
-library lib;
-
-main() {}''');
-    expect(context.isClientLibrary(source), isFalse);
-    expect(context.isServerLibrary(source), isFalse);
-    context.computeLibraryElement(source);
-    expect(context.isClientLibrary(source), isFalse);
-    expect(context.isServerLibrary(source), isTrue);
-  }
-
-  void test_isServerLibrary_html() {
-    Source source = addSource("/test.html", "<html></html>");
-    expect(context.isServerLibrary(source), isFalse);
-  }
-
-  void test_parseCompilationUnit_errors() {
-    Source source = addSource("/lib.dart", "library {");
-    CompilationUnit compilationUnit = context.parseCompilationUnit(source);
-    expect(compilationUnit, isNotNull);
-    var errorInfo = context.getErrors(source);
-    expect(errorInfo, isNotNull);
-    List<AnalysisError> errors = errorInfo.errors;
-    expect(errors, isNotNull);
-    expect(errors.length > 0, isTrue);
-  }
-
-  void test_parseCompilationUnit_exception() {
-    Source source = _addSourceWithException("/test.dart");
-    try {
-      context.parseCompilationUnit(source);
-      fail("Expected AnalysisException");
-    } on AnalysisException {
-      // Expected
-    }
-  }
-
-  void test_parseCompilationUnit_html() {
-    Source source = addSource("/test.html", "<html></html>");
-    expect(context.parseCompilationUnit(source), isNull);
-  }
-
-  void test_parseCompilationUnit_noErrors() {
-    Source source = addSource("/lib.dart", "library lib;");
-    CompilationUnit compilationUnit = context.parseCompilationUnit(source);
-    expect(compilationUnit, isNotNull);
-    AnalysisErrorInfo errorInfo = context.getErrors(source);
-    expect(errorInfo, isNotNull);
-    expect(errorInfo.errors, hasLength(0));
-  }
-
-  void test_parseCompilationUnit_nonExistentSource() {
-    Source source = newSource('/test.dart');
-    resourceProvider.deleteFile('/test.dart');
-    try {
-      context.parseCompilationUnit(source);
-      fail("Expected AnalysisException because file does not exist");
-    } on AnalysisException {
-      // Expected result
-    }
-  }
-
-//  void test_resolveCompilationUnit_sourceChangeDuringResolution() {
-//    _context = new _AnalysisContext_sourceChangeDuringResolution();
-//    AnalysisContextFactory.initContextWithCore(_context);
-//    _sourceFactory = _context.sourceFactory;
-//    Source source = _addSource("/lib.dart", "library lib;");
-//    CompilationUnit compilationUnit =
-//        _context.resolveCompilationUnit2(source, source);
-//    expect(compilationUnit, isNotNull);
-//    expect(_context.getLineInfo(source), isNotNull);
-//  }
-
-  void test_performAnalysisTask_modifiedAfterParse() {
-    // TODO(scheglov) no threads in Dart
-//    Source source = _addSource("/test.dart", "library lib;");
-//    int initialTime = _context.getModificationStamp(source);
-//    List<Source> sources = new List<Source>();
-//    sources.add(source);
-//    _context.analysisPriorityOrder = sources;
-//    _context.parseCompilationUnit(source);
-//    while (initialTime == JavaSystem.currentTimeMillis()) {
-//      Thread.sleep(1);
-//      // Force the modification time to be different.
-//    }
-//    _context.setContents(source, "library test;");
-//    JUnitTestCase.assertTrue(initialTime != _context.getModificationStamp(source));
-//    _analyzeAll_assertFinished();
-//    JUnitTestCase.assertNotNullMsg("performAnalysisTask failed to compute an element model", _context.getLibraryElement(source));
-  }
-
   void test_resolveCompilationUnit_library() {
     Source source = addSource("/lib.dart", "library lib;");
     LibraryElement library = context.computeLibraryElement(source);
@@ -1907,6 +1885,24 @@
     expect(_getIncrementalAnalysisCache(context), isNull);
   }
 
+  void test_setContents_unchanged_consistentModificationTime() {
+    String contents = "// foo";
+    Source source = addSource("/test.dart", contents);
+    context.setContents(source, contents);
+    // do all, no tasks
+    _analyzeAll_assertFinished();
+    {
+      AnalysisResult result = context.performAnalysisTask();
+      expect(result.changeNotices, isNull);
+    }
+    // set the same contents, still no tasks
+    context.setContents(source, contents);
+    {
+      AnalysisResult result = context.performAnalysisTask();
+      expect(result.changeNotices, isNull);
+    }
+  }
+
   void test_setSourceFactory() {
     expect(context.sourceFactory, sourceFactory);
     SourceFactory factory = new SourceFactory([]);
@@ -1927,52 +1923,6 @@
     expect(context.sourcesNeedingProcessing.contains(source), isFalse);
   }
 
-  Future xtest_computeResolvedCompilationUnitAsync() {
-    Source source = addSource("/lib.dart", "library lib;");
-    // Complete all pending analysis tasks and flush the AST so that it won't
-    // be available immediately.
-    _performPendingAnalysisTasks();
-    _flushAst(source);
-    bool completed = false;
-    context
-        .computeResolvedCompilationUnitAsync(source, source)
-        .then((CompilationUnit unit) {
-      expect(unit, isNotNull);
-      completed = true;
-    });
-    return pumpEventQueue().then((_) {
-      expect(completed, isFalse);
-      _performPendingAnalysisTasks();
-    }).then((_) => pumpEventQueue()).then((_) {
-      expect(completed, isTrue);
-    });
-  }
-
-  Future xtest_computeResolvedCompilationUnitAsync_cancel() {
-    Source source = addSource("/lib.dart", "library lib;");
-    // Complete all pending analysis tasks and flush the AST so that it won't
-    // be available immediately.
-    _performPendingAnalysisTasks();
-    _flushAst(source);
-    CancelableFuture<CompilationUnit> future =
-        context.computeResolvedCompilationUnitAsync(source, source);
-    bool completed = false;
-    future.then((CompilationUnit unit) {
-      fail('Future should have been canceled');
-    }, onError: (error) {
-      expect(error, new isInstanceOf<FutureCanceledError>());
-      completed = true;
-    });
-    expect(completed, isFalse);
-    expect(context.pendingFutureSources_forTesting, isNotEmpty);
-    future.cancel();
-    expect(context.pendingFutureSources_forTesting, isEmpty);
-    return pumpEventQueue().then((_) {
-      expect(completed, isTrue);
-      expect(context.pendingFutureSources_forTesting, isEmpty);
-    });
-  }
-
   void xtest_performAnalysisTask_stress() {
     int maxCacheSize = 4;
     AnalysisOptionsImpl options =
@@ -2054,8 +2004,8 @@
   }
 
   void _flushAst(Source source) {
-    CacheEntry entry = context
-        .getReadableSourceEntryOrNull(new LibrarySpecificUnit(source, source));
+    CacheEntry entry =
+        context.getCacheEntry(new LibrarySpecificUnit(source, source));
     entry.setState(RESOLVED_UNIT, CacheState.FLUSHED);
   }
 
@@ -2103,31 +2053,6 @@
   }
 }
 
-//class FakeSdk extends DirectoryBasedDartSdk {
-//  FakeSdk(JavaFile arg0) : super(arg0);
-//
-//  @override
-//  LibraryMap initialLibraryMap(bool useDart2jsPaths) {
-//    LibraryMap map = new LibraryMap();
-//    _addLibrary(map, DartSdk.DART_ASYNC, false, "async.dart");
-//    _addLibrary(map, DartSdk.DART_CORE, false, "core.dart");
-//    _addLibrary(map, DartSdk.DART_HTML, false, "html_dartium.dart");
-//    _addLibrary(map, "dart:math", false, "math.dart");
-//    _addLibrary(map, "dart:_interceptors", true, "_interceptors.dart");
-//    _addLibrary(map, "dart:_js_helper", true, "_js_helper.dart");
-//    return map;
-//  }
-//
-//  void _addLibrary(LibraryMap map, String uri, bool isInternal, String path) {
-//    SdkLibraryImpl library = new SdkLibraryImpl(uri);
-//    if (isInternal) {
-//      library.category = "Internal";
-//    }
-//    library.path = path;
-//    map.setLibrary(uri, library);
-//  }
-//}
-
 class _AnalysisContextImplTest_test_applyChanges_removeContainer
     implements SourceContainer {
   Source libB;
@@ -2135,16 +2060,3 @@
   @override
   bool contains(Source source) => source == libB;
 }
-
-class _Source_getContent_throwException extends NonExistingSource {
-  _Source_getContent_throwException(String name)
-      : super(name, pathos.toUri(name), UriKind.FILE_URI);
-
-  @override
-  TimestampedData<String> get contents {
-    throw 'Read error';
-  }
-
-  @override
-  bool exists() => true;
-}
diff --git a/pkg/analyzer/test/src/context/test_all.dart b/pkg/analyzer/test/src/context/test_all.dart
index fe1b98c..d3e5f76 100644
--- a/pkg/analyzer/test/src/context/test_all.dart
+++ b/pkg/analyzer/test/src/context/test_all.dart
@@ -12,7 +12,7 @@
 /// Utility for manually running all tests.
 main() {
   groupSep = ' | ';
-  group('task tests', () {
+  group('context tests', () {
     cache_test.main();
     context_test.main();
   });
diff --git a/pkg/analyzer/test/src/task/dart_test.dart b/pkg/analyzer/test/src/task/dart_test.dart
index 4036ee2..e8b5813 100644
--- a/pkg/analyzer/test/src/task/dart_test.dart
+++ b/pkg/analyzer/test/src/task/dart_test.dart
@@ -8,11 +8,15 @@
 import 'package:analyzer/src/generated/ast.dart';
 import 'package:analyzer/src/generated/constant.dart';
 import 'package:analyzer/src/generated/element.dart';
-import 'package:analyzer/src/generated/engine.dart' show CacheState;
+import 'package:analyzer/src/generated/engine.dart'
+    show AnalysisOptionsImpl, CacheState;
 import 'package:analyzer/src/generated/error.dart';
 import 'package:analyzer/src/generated/resolver.dart';
+import 'package:analyzer/src/generated/scanner.dart';
+import 'package:analyzer/src/generated/sdk.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/task/dart.dart';
+import 'package:analyzer/src/task/html.dart';
 import 'package:analyzer/task/dart.dart';
 import 'package:analyzer/task/general.dart';
 import 'package:analyzer/task/model.dart';
@@ -30,7 +34,6 @@
   runReflectiveTests(BuildEnumMemberElementsTaskTest);
   runReflectiveTests(BuildSourceClosuresTaskTest);
   runReflectiveTests(BuildExportNamespaceTaskTest);
-  runReflectiveTests(BuildFunctionTypeAliasesTaskTest);
   runReflectiveTests(BuildLibraryConstructorsTaskTest);
   runReflectiveTests(BuildLibraryElementTaskTest);
   runReflectiveTests(BuildPublicNamespaceTaskTest);
@@ -66,14 +69,14 @@
 ''');
     LibraryElement libraryElement;
     {
-      _computeResult(source, LIBRARY_ELEMENT5);
+      computeResult(source, LIBRARY_ELEMENT5);
       libraryElement = outputs[LIBRARY_ELEMENT5];
     }
     // prepare C
     ClassElement c = libraryElement.getType('C');
     expect(c, isNotNull);
     // build constructors
-    _computeResult(c, CONSTRUCTORS);
+    computeResult(c, CONSTRUCTORS);
     expect(task, new isInstanceOf<BuildClassConstructorsTask>());
     _fillErrorListener(CONSTRUCTORS_ERRORS);
     errorListener.assertErrorsWithCodes(
@@ -91,14 +94,14 @@
 ''');
     LibraryElement libraryElement;
     {
-      _computeResult(source, LIBRARY_ELEMENT5);
+      computeResult(source, LIBRARY_ELEMENT5);
       libraryElement = outputs[LIBRARY_ELEMENT5];
     }
     // prepare C
     ClassElement c = libraryElement.getType('C');
     expect(c, isNotNull);
     // build constructors
-    _computeResult(c, CONSTRUCTORS);
+    computeResult(c, CONSTRUCTORS);
     expect(task, new isInstanceOf<BuildClassConstructorsTask>());
     // no errors
     expect(outputs[CONSTRUCTORS_ERRORS], isEmpty);
@@ -121,14 +124,14 @@
 ''');
     LibraryElement libraryElement;
     {
-      _computeResult(source, LIBRARY_ELEMENT5);
+      computeResult(source, LIBRARY_ELEMENT5);
       libraryElement = outputs[LIBRARY_ELEMENT5];
     }
     // prepare C2
     ClassElement class2 = libraryElement.getType('C2');
     expect(class2, isNotNull);
     // build constructors
-    _computeResult(class2, CONSTRUCTORS);
+    computeResult(class2, CONSTRUCTORS);
     expect(task, new isInstanceOf<BuildClassConstructorsTask>());
     List<ConstructorElement> constructors = outputs[CONSTRUCTORS];
     expect(constructors, hasLength(1));
@@ -145,14 +148,14 @@
 ''');
     LibraryElement libraryElement;
     {
-      _computeResult(source, LIBRARY_ELEMENT5);
+      computeResult(source, LIBRARY_ELEMENT5);
       libraryElement = outputs[LIBRARY_ELEMENT5];
     }
     // prepare C
     ClassElement c = libraryElement.getType('C');
     expect(c, isNotNull);
     // build constructors
-    _computeResult(c, CONSTRUCTORS);
+    computeResult(c, CONSTRUCTORS);
     expect(task, new isInstanceOf<BuildClassConstructorsTask>());
     _fillErrorListener(CONSTRUCTORS_ERRORS);
     errorListener.assertErrorsWithCodes(
@@ -260,7 +263,7 @@
     CacheEntry cacheEntry = analysisCache.get(target);
     cacheEntry.setState(RESOLVED_UNIT1, CacheState.INVALID);
     // compute again
-    _computeResult(target, RESOLVED_UNIT1);
+    computeResult(target, RESOLVED_UNIT1);
     expect(outputs[COMPILATION_UNIT_ELEMENT], same(unitElement));
     expect(outputs[RESOLVED_UNIT1], isNot(same(unit)));
   }
@@ -268,7 +271,7 @@
   void _performBuildTask(String content) {
     source = newSource('/test.dart', content);
     target = new LibrarySpecificUnit(source, source);
-    _computeResult(target, RESOLVED_UNIT1);
+    computeResult(target, RESOLVED_UNIT1);
     expect(task, new isInstanceOf<BuildCompilationUnitElementTask>());
   }
 }
@@ -320,7 +323,7 @@
     Source sourceB = sources[1];
     Source sourceC = sources[2];
     // perform task
-    _computeResult(sourceA, LIBRARY_ELEMENT2);
+    computeResult(sourceA, LIBRARY_ELEMENT2);
     expect(task, new isInstanceOf<BuildDirectiveElementsTask>());
     // prepare outputs
     LibraryElement libraryElementA = outputs[LIBRARY_ELEMENT2];
@@ -358,6 +361,7 @@
       List<ImportElement> imports = libraryElementA.imports;
       expect(imports, hasLength(2));
       expect(imports[1].importedLibrary.isDartCore, isTrue);
+      expect(imports[1].isSynthetic, isTrue);
     }
   }
 
@@ -373,7 +377,7 @@
     });
     Source sourceA = sources[0];
     // perform task
-    _computeResult(sourceA, LIBRARY_ELEMENT2);
+    computeResult(sourceA, LIBRARY_ELEMENT2);
     expect(task, new isInstanceOf<BuildDirectiveElementsTask>());
     // prepare outputs
     CompilationUnit libraryUnitA = context
@@ -398,6 +402,22 @@
     }
   }
 
+  test_perform_dartCoreContext() {
+    List<Source> sources = newSources({'/libA.dart': ''});
+    Source source = sources[0];
+    // perform task
+    computeResult(source, LIBRARY_ELEMENT2);
+    expect(task, new isInstanceOf<BuildDirectiveElementsTask>());
+    // prepare outputs
+    LibraryElement libraryElement = outputs[LIBRARY_ELEMENT2];
+    // verify that dart:core has SDK context
+    {
+      LibraryElement coreLibrary = libraryElement.importedLibraries[0];
+      DartSdk dartSdk = context.sourceFactory.dartSdk;
+      expect(coreLibrary.context, same(dartSdk.context));
+    }
+  }
+
   test_perform_error_exportOfNonLibrary() {
     List<Source> sources = newSources({
       '/libA.dart': '''
@@ -410,7 +430,7 @@
     });
     Source sourceA = sources[0];
     // perform task
-    _computeResult(sourceA, LIBRARY_ELEMENT2);
+    computeResult(sourceA, LIBRARY_ELEMENT2);
     expect(task, new isInstanceOf<BuildDirectiveElementsTask>());
     // validate errors
     _assertErrorsWithCodes([CompileTimeErrorCode.EXPORT_OF_NON_LIBRARY]);
@@ -428,12 +448,34 @@
     });
     Source sourceA = sources[0];
     // perform task
-    _computeResult(sourceA, LIBRARY_ELEMENT2);
+    computeResult(sourceA, LIBRARY_ELEMENT2);
     expect(task, new isInstanceOf<BuildDirectiveElementsTask>());
     // validate errors
     _assertErrorsWithCodes([CompileTimeErrorCode.IMPORT_OF_NON_LIBRARY]);
   }
 
+  test_perform_explicitDartCoreImport() {
+    List<Source> sources = newSources({
+      '/lib.dart': '''
+library lib;
+import 'dart:core' show List;
+'''
+    });
+    Source source = sources[0];
+    // perform task
+    computeResult(source, LIBRARY_ELEMENT2);
+    expect(task, new isInstanceOf<BuildDirectiveElementsTask>());
+    // prepare outputs
+    LibraryElement libraryElement = outputs[LIBRARY_ELEMENT2];
+    // has an explicit "dart:core" import
+    {
+      List<ImportElement> imports = libraryElement.imports;
+      expect(imports, hasLength(1));
+      expect(imports[0].importedLibrary.isDartCore, isTrue);
+      expect(imports[0].isSynthetic, isFalse);
+    }
+  }
+
   test_perform_hasExtUri() {
     List<Source> sources = newSources({
       '/lib.dart': '''
@@ -442,7 +484,7 @@
     });
     Source source = sources[0];
     // perform task
-    _computeResult(source, LIBRARY_ELEMENT2);
+    computeResult(source, LIBRARY_ELEMENT2);
     expect(task, new isInstanceOf<BuildDirectiveElementsTask>());
     // prepare outputs
     LibraryElement libraryElement = outputs[LIBRARY_ELEMENT2];
@@ -466,7 +508,7 @@
     Source sourceA = sources[0];
     Source sourceB = sources[1];
     // perform task
-    _computeResult(sourceA, LIBRARY_ELEMENT2);
+    computeResult(sourceA, LIBRARY_ELEMENT2);
     expect(task, new isInstanceOf<BuildDirectiveElementsTask>());
     // prepare outputs
     CompilationUnit libraryUnitA = context
@@ -516,7 +558,7 @@
   A, B
 }
 ''');
-    _computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT2);
+    computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT2);
     expect(task, new isInstanceOf<BuildEnumMemberElementsTask>());
     CompilationUnit unit = outputs[RESOLVED_UNIT2];
     // validate Element
@@ -581,7 +623,7 @@
 library lib_b;
 main() {}
 ''');
-    _computeResult(sourceA, LIBRARY_ELEMENT4);
+    computeResult(sourceA, LIBRARY_ELEMENT4);
     expect(task, new isInstanceOf<BuildExportNamespaceTask>());
     // validate
     {
@@ -613,7 +655,7 @@
 class C2 {}
 class C3 {}
 ''');
-    _computeResult(sourceA, LIBRARY_ELEMENT4);
+    computeResult(sourceA, LIBRARY_ELEMENT4);
     expect(task, new isInstanceOf<BuildExportNamespaceTask>());
     // validate
     {
@@ -638,7 +680,7 @@
 class B2 {}
 class _B3 {}
 ''');
-    _computeResult(sourceA, LIBRARY_ELEMENT4);
+    computeResult(sourceA, LIBRARY_ELEMENT4);
     expect(task, new isInstanceOf<BuildExportNamespaceTask>());
     // validate
     {
@@ -659,7 +701,7 @@
 library lib_b;
 int topLevelB;
 ''');
-    _computeResult(sourceA, LIBRARY_ELEMENT4);
+    computeResult(sourceA, LIBRARY_ELEMENT4);
     expect(task, new isInstanceOf<BuildExportNamespaceTask>());
     // validate
     {
@@ -672,49 +714,6 @@
 }
 
 @reflectiveTest
-class BuildFunctionTypeAliasesTaskTest extends _AbstractDartTaskTest {
-  test_perform() {
-    Source source = newSource('/test.dart', '''
-typedef int F(G g);
-typedef String G(int p);
-''');
-    LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
-    _computeResult(target, RESOLVED_UNIT3);
-    expect(task, new isInstanceOf<BuildFunctionTypeAliasesTask>());
-    // validate
-    CompilationUnit unit = outputs[RESOLVED_UNIT3];
-    FunctionTypeAlias nodeF = unit.declarations[0];
-    FunctionTypeAlias nodeG = unit.declarations[1];
-    {
-      FormalParameter parameter = nodeF.parameters.parameters[0];
-      DartType parameterType = parameter.element.type;
-      Element returnTypeElement = nodeF.returnType.type.element;
-      expect(returnTypeElement.displayName, 'int');
-      expect(parameterType.element, nodeG.element);
-    }
-    {
-      FormalParameter parameter = nodeG.parameters.parameters[0];
-      DartType parameterType = parameter.element.type;
-      expect(nodeG.returnType.type.element.displayName, 'String');
-      expect(parameterType.element.displayName, 'int');
-    }
-  }
-
-  test_perform_errors() {
-    Source source = newSource('/test.dart', '''
-typedef int F(NoSuchType p);
-''');
-    LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
-    _computeResult(target, BUILD_FUNCTION_TYPE_ALIASES_ERRORS);
-    expect(task, new isInstanceOf<BuildFunctionTypeAliasesTask>());
-    // validate
-    _fillErrorListener(BUILD_FUNCTION_TYPE_ALIASES_ERRORS);
-    errorListener
-        .assertErrorsWithCodes(<ErrorCode>[StaticWarningCode.UNDEFINED_CLASS]);
-  }
-}
-
-@reflectiveTest
 class BuildLibraryConstructorsTaskTest extends _AbstractDartTaskTest {
   test_perform() {
     Source source = newSource('/test.dart', '''
@@ -728,9 +727,9 @@
 class C1 = B with M1;
 class C3 = B with M2;
 ''');
-    _computeResult(source, LIBRARY_ELEMENT);
+    computeResult(source, LIBRARY_ELEMENT6);
     expect(task, new isInstanceOf<BuildLibraryConstructorsTask>());
-    LibraryElement libraryElement = outputs[LIBRARY_ELEMENT];
+    LibraryElement libraryElement = outputs[LIBRARY_ELEMENT6];
     // C1
     {
       ClassElement classElement = libraryElement.getType('C2');
@@ -1026,7 +1025,7 @@
   void _performBuildTask(Map<String, String> sourceMap) {
     List<Source> sources = newSources(sourceMap);
     Source libSource = sources.first;
-    _computeResult(libSource, LIBRARY_ELEMENT1);
+    computeResult(libSource, LIBRARY_ELEMENT1);
     expect(task, new isInstanceOf<BuildLibraryElementTask>());
     libraryUnit = context
         .getCacheEntry(new LibrarySpecificUnit(libSource, libSource))
@@ -1089,7 +1088,7 @@
 d() {}
 '''
     });
-    _computeResult(sources.first, LIBRARY_ELEMENT3);
+    computeResult(sources.first, LIBRARY_ELEMENT3);
     expect(task, new isInstanceOf<BuildPublicNamespaceTask>());
     // validate
     LibraryElement library = outputs[LIBRARY_ELEMENT3];
@@ -1118,21 +1117,21 @@
 ''');
     // a.dart
     {
-      _computeResult(sourceA, EXPORT_SOURCE_CLOSURE);
+      computeResult(sourceA, EXPORT_SOURCE_CLOSURE);
       expect(task, new isInstanceOf<BuildSourceClosuresTask>());
       List<Source> closure = outputs[EXPORT_SOURCE_CLOSURE];
       expect(closure, unorderedEquals([sourceA, sourceB, sourceC]));
     }
     // c.dart
     {
-      _computeResult(sourceC, EXPORT_SOURCE_CLOSURE);
+      computeResult(sourceC, EXPORT_SOURCE_CLOSURE);
       expect(task, new isInstanceOf<BuildSourceClosuresTask>());
       List<Source> closure = outputs[EXPORT_SOURCE_CLOSURE];
       expect(closure, unorderedEquals([sourceA, sourceB, sourceC]));
     }
     // d.dart
     {
-      _computeResult(sourceD, EXPORT_SOURCE_CLOSURE);
+      computeResult(sourceD, EXPORT_SOURCE_CLOSURE);
       expect(task, new isInstanceOf<BuildSourceClosuresTask>());
       List<Source> closure = outputs[EXPORT_SOURCE_CLOSURE];
       expect(closure, unorderedEquals([sourceD]));
@@ -1158,7 +1157,7 @@
     Source coreSource = context.sourceFactory.resolveUri(null, 'dart:core');
     // a.dart
     {
-      _computeResult(sourceA, IMPORT_SOURCE_CLOSURE);
+      computeResult(sourceA, IMPORT_SOURCE_CLOSURE);
       expect(task, new isInstanceOf<BuildSourceClosuresTask>());
       List<Source> closure = outputs[IMPORT_SOURCE_CLOSURE];
       expect(closure, contains(sourceA));
@@ -1168,7 +1167,7 @@
     }
     // c.dart
     {
-      _computeResult(sourceC, IMPORT_SOURCE_CLOSURE);
+      computeResult(sourceC, IMPORT_SOURCE_CLOSURE);
       expect(task, new isInstanceOf<BuildSourceClosuresTask>());
       List<Source> closure = outputs[IMPORT_SOURCE_CLOSURE];
       expect(closure, contains(sourceA));
@@ -1178,7 +1177,7 @@
     }
     // d.dart
     {
-      _computeResult(sourceD, IMPORT_SOURCE_CLOSURE);
+      computeResult(sourceD, IMPORT_SOURCE_CLOSURE);
       expect(task, new isInstanceOf<BuildSourceClosuresTask>());
       List<Source> closure = outputs[IMPORT_SOURCE_CLOSURE];
       expect(closure, contains(sourceD));
@@ -1201,7 +1200,7 @@
     Source coreSource = context.sourceFactory.resolveUri(null, 'dart:core');
     // c.dart
     {
-      _computeResult(sourceC, IMPORT_EXPORT_SOURCE_CLOSURE);
+      computeResult(sourceC, IMPORT_EXPORT_SOURCE_CLOSURE);
       expect(task, new isInstanceOf<BuildSourceClosuresTask>());
       List<Source> closure = outputs[IMPORT_EXPORT_SOURCE_CLOSURE];
       expect(closure, contains(sourceA));
@@ -1211,7 +1210,7 @@
     }
     // b.dart
     {
-      _computeResult(sourceB, IMPORT_EXPORT_SOURCE_CLOSURE);
+      computeResult(sourceB, IMPORT_EXPORT_SOURCE_CLOSURE);
       expect(task, new isInstanceOf<BuildSourceClosuresTask>());
       List<Source> closure = outputs[IMPORT_EXPORT_SOURCE_CLOSURE];
       expect(closure, contains(sourceA));
@@ -1228,7 +1227,7 @@
     newSource('/b.dart', '''
 library lib_b;
 ''');
-    _computeResult(sourceA, IS_CLIENT);
+    computeResult(sourceA, IS_CLIENT);
     expect(task, new isInstanceOf<BuildSourceClosuresTask>());
     expect(outputs[IS_CLIENT], isFalse);
   }
@@ -1241,7 +1240,7 @@
     Source source = newSource('/test.dart', '''
 import 'exports_html.dart';
 ''');
-    _computeResult(source, IS_CLIENT);
+    computeResult(source, IS_CLIENT);
     expect(task, new isInstanceOf<BuildSourceClosuresTask>());
     expect(outputs[IS_CLIENT], isTrue);
   }
@@ -1251,7 +1250,7 @@
 library lib_a;
 import 'dart:html';
 ''');
-    _computeResult(sourceA, IS_CLIENT);
+    computeResult(sourceA, IS_CLIENT);
     expect(task, new isInstanceOf<BuildSourceClosuresTask>());
     expect(outputs[IS_CLIENT], isTrue);
   }
@@ -1265,7 +1264,7 @@
 library lib_b;
 import 'dart:html';
 ''');
-    _computeResult(sourceA, IS_CLIENT);
+    computeResult(sourceA, IS_CLIENT);
     expect(task, new isInstanceOf<BuildSourceClosuresTask>());
     expect(outputs[IS_CLIENT], isTrue);
   }
@@ -1274,7 +1273,7 @@
 @reflectiveTest
 class BuildTypeProviderTaskTest extends _AbstractDartTaskTest {
   test_perform() {
-    _computeResult(AnalysisContextTarget.request, TYPE_PROVIDER);
+    computeResult(AnalysisContextTarget.request, TYPE_PROVIDER);
     expect(task, new isInstanceOf<BuildTypeProviderTask>());
     // validate
     TypeProvider typeProvider = outputs[TYPE_PROVIDER];
@@ -1307,7 +1306,7 @@
     // First compute the resolved unit for the source.
     LibrarySpecificUnit librarySpecificUnit =
         new LibrarySpecificUnit(source, source);
-    _computeResult(librarySpecificUnit, RESOLVED_UNIT1);
+    computeResult(librarySpecificUnit, RESOLVED_UNIT1);
     CompilationUnit unit = outputs[RESOLVED_UNIT1];
     // Find the elements for x and D's constructor, and the annotation on C.
     List<PropertyAccessorElement> accessors = unit.element.accessors;
@@ -1320,7 +1319,7 @@
     // Now compute the dependencies for the annotation, and check that it is
     // the set [x, constructorForD].
     // TODO(paulberry): test librarySource != source
-    _computeResult(new ConstantEvaluationTarget_Annotation(
+    computeResult(new ConstantEvaluationTarget_Annotation(
         context, source, source, annotation), CONSTANT_DEPENDENCIES);
     expect(
         outputs[CONSTANT_DEPENDENCIES].toSet(), [x, constructorForD].toSet());
@@ -1334,7 +1333,7 @@
     // First compute the resolved unit for the source.
     LibrarySpecificUnit librarySpecificUnit =
         new LibrarySpecificUnit(source, source);
-    _computeResult(librarySpecificUnit, RESOLVED_UNIT1);
+    computeResult(librarySpecificUnit, RESOLVED_UNIT1);
     CompilationUnit unit = outputs[RESOLVED_UNIT1];
     // Find the element for x and the annotation on C.
     List<PropertyAccessorElement> accessors = unit.element.accessors;
@@ -1343,7 +1342,7 @@
     Annotation annotation = findClassAnnotation(unit, 'C');
     // Now compute the dependencies for the annotation, and check that it is
     // the list [x].
-    _computeResult(new ConstantEvaluationTarget_Annotation(
+    computeResult(new ConstantEvaluationTarget_Annotation(
         context, source, source, annotation), CONSTANT_DEPENDENCIES);
     expect(outputs[CONSTANT_DEPENDENCIES], [x]);
   }
@@ -1355,7 +1354,7 @@
     // First compute the resolved unit for the source.
     LibrarySpecificUnit librarySpecificUnit =
         new LibrarySpecificUnit(source, source);
-    _computeResult(librarySpecificUnit, RESOLVED_UNIT2);
+    computeResult(librarySpecificUnit, RESOLVED_UNIT2);
     CompilationUnit unit = outputs[RESOLVED_UNIT2];
     // Find the element for 'A'
     EnumDeclaration enumDeclaration = unit.declarations[0];
@@ -1363,7 +1362,7 @@
     FieldElement constantElement = constantDeclaration.element;
     // Now compute the dependencies for the constant and check that there are
     // none.
-    _computeResult(constantElement, CONSTANT_DEPENDENCIES);
+    computeResult(constantElement, CONSTANT_DEPENDENCIES);
     expect(outputs[CONSTANT_DEPENDENCIES], isEmpty);
   }
 
@@ -1375,7 +1374,7 @@
     // First compute the resolved unit for the source.
     LibrarySpecificUnit librarySpecificUnit =
         new LibrarySpecificUnit(source, source);
-    _computeResult(librarySpecificUnit, RESOLVED_UNIT1);
+    computeResult(librarySpecificUnit, RESOLVED_UNIT1);
     CompilationUnit unit = outputs[RESOLVED_UNIT1];
     // Find the elements for the constants x and y.
     List<PropertyAccessorElement> accessors = unit.element.accessors;
@@ -1384,7 +1383,7 @@
     Element y = accessors.firstWhere((PropertyAccessorElement accessor) =>
         accessor.isGetter && accessor.name == 'y').variable;
     // Now compute the dependencies for x, and check that it is the list [y].
-    _computeResult(x, CONSTANT_DEPENDENCIES);
+    computeResult(x, CONSTANT_DEPENDENCIES);
     expect(outputs[CONSTANT_DEPENDENCIES], [y]);
   }
 }
@@ -1400,7 +1399,7 @@
         ConstantEvaluationTarget_Annotation target =
             new ConstantEvaluationTarget_Annotation(
                 context, source, source, annotation);
-        _computeResult(target, CONSTANT_VALUE);
+        computeResult(target, CONSTANT_VALUE);
         expect(outputs[CONSTANT_VALUE], same(target));
         EvaluationResultImpl evaluationResult =
             (annotation.elementAnnotation as ElementAnnotationImpl).evaluationResult;
@@ -1495,6 +1494,21 @@
 ''');
   }
 
+  test_const_constructor_calls_implicit_super_constructor_implicitly() {
+    // Note: the situation below is a compile-time error (since the synthetic
+    // constructor for Base is non-const), but we need to handle it without
+    // throwing an exception.
+    EvaluationResultImpl evaluationResult = _computeTopLevelVariableConstValue(
+        'x', '''
+class Base {}
+class Derived extends Base {
+  const Derived();
+}
+const x = const Derived();
+''');
+    expect(evaluationResult, isNotNull);
+  }
+
   test_dependency() {
     EvaluationResultImpl evaluationResult = _computeTopLevelVariableConstValue(
         'x', '''
@@ -1555,7 +1569,7 @@
     // Find the element for the given constant.
     PropertyInducingElement variableElement = _findVariable(unit, variableName);
     // Now compute the value of the constant.
-    _computeResult(variableElement, CONSTANT_VALUE);
+    computeResult(variableElement, CONSTANT_VALUE);
     expect(outputs[CONSTANT_VALUE], same(variableElement));
     EvaluationResultImpl evaluationResult =
         (variableElement as TopLevelVariableElementImpl).evaluationResult;
@@ -1580,7 +1594,7 @@
   CompilationUnit _resolveSource(Source source) {
     LibrarySpecificUnit librarySpecificUnit =
         new LibrarySpecificUnit(source, source);
-    _computeResult(librarySpecificUnit, RESOLVED_UNIT1);
+    computeResult(librarySpecificUnit, RESOLVED_UNIT1);
     CompilationUnit unit = outputs[RESOLVED_UNIT1];
     return unit;
   }
@@ -1627,8 +1641,8 @@
 
   test_perform_definingCompilationUnit() {
     AnalysisTarget library = newSource('/test.dart', 'library test;');
-    _computeResult(library, INCLUDED_PARTS);
-    _computeResult(library, CONTAINING_LIBRARIES);
+    computeResult(library, INCLUDED_PARTS);
+    computeResult(library, CONTAINING_LIBRARIES);
     expect(task, new isInstanceOf<ContainingLibrariesTask>());
     expect(outputs, hasLength(1));
     List<Source> containingLibraries = outputs[CONTAINING_LIBRARIES];
@@ -1641,10 +1655,10 @@
     AnalysisTarget library2 =
         newSource('/lib2.dart', 'library test; part "part.dart";');
     AnalysisTarget part = newSource('/part.dart', 'part of test;');
-    _computeResult(library1, INCLUDED_PARTS);
-    _computeResult(library2, INCLUDED_PARTS);
-    _computeResult(part, SOURCE_KIND);
-    _computeResult(part, CONTAINING_LIBRARIES);
+    computeResult(library1, INCLUDED_PARTS);
+    computeResult(library2, INCLUDED_PARTS);
+    computeResult(part, SOURCE_KIND);
+    computeResult(part, CONTAINING_LIBRARIES);
     expect(task, new isInstanceOf<ContainingLibrariesTask>());
     expect(outputs, hasLength(1));
     List<Source> containingLibraries = outputs[CONTAINING_LIBRARIES];
@@ -1655,9 +1669,9 @@
     AnalysisTarget library =
         newSource('/lib.dart', 'library test; part "part.dart";');
     AnalysisTarget part = newSource('/part.dart', 'part of test;');
-    _computeResult(library, INCLUDED_PARTS);
-    _computeResult(part, SOURCE_KIND);
-    _computeResult(part, CONTAINING_LIBRARIES);
+    computeResult(library, INCLUDED_PARTS);
+    computeResult(part, SOURCE_KIND);
+    computeResult(part, CONTAINING_LIBRARIES);
     expect(task, new isInstanceOf<ContainingLibrariesTask>());
     expect(outputs, hasLength(1));
     List<Source> containingLibraries = outputs[CONTAINING_LIBRARIES];
@@ -1706,8 +1720,8 @@
   test_perform_definingCompilationUnit() {
     AnalysisTarget library =
         newSource('/test.dart', 'library test; import "dart:math";');
-    _computeResult(library, INCLUDED_PARTS);
-    _computeResult(library, DART_ERRORS);
+    computeResult(library, INCLUDED_PARTS);
+    computeResult(library, DART_ERRORS);
     expect(task, new isInstanceOf<DartErrorsTask>());
     expect(outputs, hasLength(1));
     List<AnalysisError> errors = outputs[DART_ERRORS];
@@ -1719,9 +1733,9 @@
         '/lib.dart', 'library test; import "dart:math"; part "part.dart";');
     AnalysisTarget part =
         newSource('/part.dart', 'part of test; class A extends A {}');
-    _computeResult(library, INCLUDED_PARTS);
-    _computeResult(library, DART_ERRORS);
-    _computeResult(part, DART_ERRORS);
+    computeResult(library, INCLUDED_PARTS);
+    computeResult(library, DART_ERRORS);
+    computeResult(part, DART_ERRORS);
     expect(task, new isInstanceOf<DartErrorsTask>());
     expect(outputs, hasLength(1));
     List<AnalysisError> errors = outputs[DART_ERRORS];
@@ -1745,7 +1759,7 @@
 const x = const C();
 ''');
     LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
-    _computeResult(target, RESOLVED_UNIT);
+    computeResult(target, RESOLVED_UNIT);
     expect(task, new isInstanceOf<EvaluateUnitConstantsTask>());
     CompilationUnit unit = outputs[RESOLVED_UNIT];
     CompilationUnitElement unitElement = unit.element;
@@ -1785,7 +1799,7 @@
 
   void _computeUsedElements(Source source) {
     LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
-    _computeResult(target, USED_IMPORTED_ELEMENTS);
+    computeResult(target, USED_IMPORTED_ELEMENTS);
     expect(task, new isInstanceOf<GatherUsedImportedElementsTask>());
     usedElements = outputs[USED_IMPORTED_ELEMENTS];
     usedElementNames = usedElements.elements.map((e) => e.name).toSet();
@@ -1829,7 +1843,7 @@
 
   void _computeUsedElements(Source source) {
     LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
-    _computeResult(target, USED_LOCAL_ELEMENTS);
+    computeResult(target, USED_LOCAL_ELEMENTS);
     expect(task, new isInstanceOf<GatherUsedLocalElementsTask>());
     usedElements = outputs[USED_LOCAL_ELEMENTS];
     usedElementNames = usedElements.elements.map((e) => e.name).toSet();
@@ -1844,7 +1858,7 @@
 }
 ''');
     LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
-    _computeResult(target, HINTS);
+    computeResult(target, HINTS);
     expect(task, new isInstanceOf<GenerateHintsTask>());
     // validate
     _fillErrorListener(HINTS);
@@ -1860,7 +1874,7 @@
 }
 ''');
     LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
-    _computeResult(target, HINTS);
+    computeResult(target, HINTS);
     expect(task, new isInstanceOf<GenerateHintsTask>());
     // validate
     _fillErrorListener(HINTS);
@@ -1876,13 +1890,28 @@
 }
 ''');
     LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
-    _computeResult(target, HINTS);
+    computeResult(target, HINTS);
     expect(task, new isInstanceOf<GenerateHintsTask>());
     // validate
     _fillErrorListener(HINTS);
     errorListener.assertErrorsWithCodes(<ErrorCode>[HintCode.DEAD_CODE]);
   }
 
+  test_perform_disabled() {
+    context.analysisOptions =
+        new AnalysisOptionsImpl.from(context.analysisOptions)..hint = false;
+    Source source = newSource('/test.dart', '''
+int main() {
+}
+''');
+    LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
+    computeResult(target, HINTS);
+    expect(task, new isInstanceOf<GenerateHintsTask>());
+    // validate
+    _fillErrorListener(HINTS);
+    errorListener.assertNoErrors();
+  }
+
   test_perform_imports_duplicateImport() {
     newSource('/a.dart', r'''
 library lib_a;
@@ -1896,7 +1925,7 @@
 }
 ''');
     LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
-    _computeResult(target, HINTS);
+    computeResult(target, HINTS);
     expect(task, new isInstanceOf<GenerateHintsTask>());
     // validate
     _fillErrorListener(HINTS);
@@ -1919,7 +1948,7 @@
   new A();
 }''');
     LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
-    _computeResult(target, HINTS);
+    computeResult(target, HINTS);
     expect(task, new isInstanceOf<GenerateHintsTask>());
     // validate
     _fillErrorListener(HINTS);
@@ -1937,7 +1966,7 @@
   new A();
 }''');
     LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
-    _computeResult(target, HINTS);
+    computeResult(target, HINTS);
     expect(task, new isInstanceOf<GenerateHintsTask>());
     // validate
     _fillErrorListener(HINTS);
@@ -1953,7 +1982,7 @@
 }
 ''');
     LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
-    _computeResult(target, HINTS);
+    computeResult(target, HINTS);
     expect(task, new isInstanceOf<GenerateHintsTask>());
     // validate
     _fillErrorListener(HINTS);
@@ -1968,7 +1997,7 @@
 }
 ''');
     LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
-    _computeResult(target, HINTS);
+    computeResult(target, HINTS);
     expect(task, new isInstanceOf<GenerateHintsTask>());
     // validate
     _fillErrorListener(HINTS);
@@ -1984,7 +2013,7 @@
 }
 ''');
     LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
-    _computeResult(target, HINTS);
+    computeResult(target, HINTS);
     expect(task, new isInstanceOf<GenerateHintsTask>());
     // validate
     _fillErrorListener(HINTS);
@@ -1998,7 +2027,7 @@
 }
 ''');
     LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
-    _computeResult(target, HINTS);
+    computeResult(target, HINTS);
     expect(task, new isInstanceOf<GenerateHintsTask>());
     // validate
     _fillErrorListener(HINTS);
@@ -2024,7 +2053,7 @@
 }
 ''');
     LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
-    _computeResult(target, HINTS);
+    computeResult(target, HINTS);
     expect(task, new isInstanceOf<GenerateHintsTask>());
     // validate
     _fillErrorListener(HINTS);
@@ -2050,7 +2079,7 @@
 part of lib;
 X v3;
 ''');
-    _computeResult(library, LIBRARY_ERRORS_READY);
+    computeResult(library, LIBRARY_ERRORS_READY);
     expect(task, new isInstanceOf<LibraryErrorsReadyTask>());
     expect(outputs, hasLength(1));
     bool ready = outputs[LIBRARY_ERRORS_READY];
@@ -2068,10 +2097,11 @@
         .buildInputs(new LibrarySpecificUnit(emptySource, emptySource));
     expect(inputs, isNotNull);
     expect(inputs.keys, unorderedEquals([
-      LibraryUnitErrorsTask.BUILD_FUNCTION_TYPE_ALIASES_ERRORS_INPUT,
+      LibraryUnitErrorsTask.CONSTRUCTORS_ERRORS_INPUT,
       LibraryUnitErrorsTask.HINTS_INPUT,
       LibraryUnitErrorsTask.RESOLVE_REFERENCES_ERRORS_INPUT,
       LibraryUnitErrorsTask.RESOLVE_TYPE_NAMES_ERRORS_INPUT,
+      LibraryUnitErrorsTask.VARIABLE_REFERENCE_ERRORS_INPUT,
       LibraryUnitErrorsTask.VERIFY_ERRORS_INPUT
     ]));
   }
@@ -2105,7 +2135,7 @@
   test_perform_definingCompilationUnit() {
     AnalysisTarget library =
         newSource('/test.dart', 'library test; import "dart:math";');
-    _computeResult(
+    computeResult(
         new LibrarySpecificUnit(library, library), LIBRARY_UNIT_ERRORS);
     expect(task, new isInstanceOf<LibraryUnitErrorsTask>());
     expect(outputs, hasLength(1));
@@ -2117,7 +2147,7 @@
     AnalysisTarget library =
         newSource('/lib.dart', 'library test; part "part.dart";');
     AnalysisTarget part = newSource('/part.dart', 'part of test;');
-    _computeResult(new LibrarySpecificUnit(library, part), LIBRARY_UNIT_ERRORS);
+    computeResult(new LibrarySpecificUnit(library, part), LIBRARY_UNIT_ERRORS);
     expect(task, new isInstanceOf<LibraryUnitErrorsTask>());
     expect(outputs, hasLength(1));
     List<AnalysisError> errors = outputs[LIBRARY_UNIT_ERRORS];
@@ -2127,6 +2157,8 @@
 
 @reflectiveTest
 class ParseDartTaskTest extends _AbstractDartTaskTest {
+  Source source;
+
   test_buildInputs() {
     Map<String, TaskInput> inputs = ParseDartTask.buildInputs(emptySource);
     expect(inputs, isNotNull);
@@ -2178,7 +2210,7 @@
 
   test_perform_computeSourceKind_noDirectives_hasContainingLibrary() {
     // Parse "lib.dart" to let the context know that "test.dart" is included.
-    _computeResult(newSource('/lib.dart', r'''
+    computeResult(newSource('/lib.dart', r'''
 library lib;
 part 'test.dart';
 '''), PARSED_UNIT);
@@ -2242,6 +2274,14 @@
     expect(outputs[UNITS], hasLength(2));
   }
 
+  test_perform_library_selfReferenceAsPart() {
+    _performParseTask(r'''
+library lib;
+part 'test.dart';
+''');
+    expect(outputs[INCLUDED_PARTS], unorderedEquals(<Source>[source]));
+  }
+
   test_perform_part() {
     _performParseTask(r'''
 part of lib;
@@ -2258,8 +2298,8 @@
   }
 
   void _performParseTask(String content) {
-    AnalysisTarget target = newSource('/test.dart', content);
-    _computeResult(target, PARSED_UNIT);
+    source = newSource('/test.dart', content);
+    computeResult(source, PARSED_UNIT);
     expect(task, new isInstanceOf<ParseDartTask>());
   }
 
@@ -2284,7 +2324,7 @@
 part of my_lib;
 class C extends A {}
 ''');
-    _computeResult(sourceLib, LIBRARY_ELEMENT5);
+    computeResult(sourceLib, LIBRARY_ELEMENT5);
     expect(task, new isInstanceOf<ResolveLibraryTypeNamesTask>());
     // validate
     LibraryElement library = outputs[LIBRARY_ELEMENT5];
@@ -2318,7 +2358,7 @@
 library c;
 class C {}
 ''');
-    _computeResult(sourceA, LIBRARY_ELEMENT5);
+    computeResult(sourceA, LIBRARY_ELEMENT5);
     expect(task, new isInstanceOf<ResolveLibraryTypeNamesTask>());
     // validate
     LibraryElement library = outputs[LIBRARY_ELEMENT5];
@@ -2351,15 +2391,15 @@
 ''');
     LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
     // prepare unit and "a.m()" invocation
-    _computeResult(target, RESOLVED_UNIT6);
-    CompilationUnit unit = outputs[RESOLVED_UNIT6];
+    computeResult(target, RESOLVED_UNIT5);
+    CompilationUnit unit = outputs[RESOLVED_UNIT5];
     // walk the AST
     FunctionDeclaration function = unit.declarations[1];
     BlockFunctionBody body = function.functionExpression.body;
     ExpressionStatement statement = body.block.statements[0];
     MethodInvocation invocation = statement.expression;
-    expect(task, new isInstanceOf<ResolveReferencesTask>());
-    expect(unit, same(outputs[RESOLVED_UNIT6]));
+    expect(task, new isInstanceOf<ResolveUnitReferencesTask>());
+    expect(unit, same(outputs[RESOLVED_UNIT5]));
     // a.m() is resolved now
     expect(invocation.methodName.staticElement, isNotNull);
   }
@@ -2373,8 +2413,8 @@
 }
 ''');
     LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
-    _computeResult(target, RESOLVED_UNIT6);
-    expect(task, new isInstanceOf<ResolveReferencesTask>());
+    computeResult(target, RESOLVED_UNIT5);
+    expect(task, new isInstanceOf<ResolveUnitReferencesTask>());
     // validate
     _fillErrorListener(RESOLVE_REFERENCES_ERRORS);
     errorListener.assertErrorsWithCodes(
@@ -2399,10 +2439,10 @@
   new A<int>().m();
 }
 ''');
-    _computeResult(new LibrarySpecificUnit(sourceC, sourceC), RESOLVED_UNIT6);
-    expect(task, new isInstanceOf<ResolveReferencesTask>());
+    computeResult(new LibrarySpecificUnit(sourceC, sourceC), RESOLVED_UNIT5);
+    expect(task, new isInstanceOf<ResolveUnitReferencesTask>());
     // validate
-    CompilationUnit unit = outputs[RESOLVED_UNIT6];
+    CompilationUnit unit = outputs[RESOLVED_UNIT5];
     expect(unit, isNotNull);
     {
       FunctionDeclaration functionDeclaration = unit.declarations[0];
@@ -2427,10 +2467,10 @@
 int f(String p) => p.length;
 ''');
     LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
-    _computeResult(target, RESOLVED_UNIT4);
+    computeResult(target, RESOLVED_UNIT3);
     expect(task, new isInstanceOf<ResolveUnitTypeNamesTask>());
     // validate
-    CompilationUnit unit = outputs[RESOLVED_UNIT4];
+    CompilationUnit unit = outputs[RESOLVED_UNIT3];
     {
       ClassDeclaration nodeA = unit.declarations[0];
       ClassDeclaration nodeB = unit.declarations[1];
@@ -2452,7 +2492,47 @@
 NoSuchClass f() => null;
 ''');
     LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
-    _computeResult(target, RESOLVE_TYPE_NAMES_ERRORS);
+    computeResult(target, RESOLVE_TYPE_NAMES_ERRORS);
+    expect(task, new isInstanceOf<ResolveUnitTypeNamesTask>());
+    // validate
+    _fillErrorListener(RESOLVE_TYPE_NAMES_ERRORS);
+    errorListener
+        .assertErrorsWithCodes(<ErrorCode>[StaticWarningCode.UNDEFINED_CLASS]);
+  }
+
+  test_perform_typedef() {
+    Source source = newSource('/test.dart', '''
+typedef int F(G g);
+typedef String G(int p);
+''');
+    LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
+    computeResult(target, RESOLVED_UNIT3);
+    expect(task, new isInstanceOf<ResolveUnitTypeNamesTask>());
+    // validate
+    CompilationUnit unit = outputs[RESOLVED_UNIT3];
+    FunctionTypeAlias nodeF = unit.declarations[0];
+    FunctionTypeAlias nodeG = unit.declarations[1];
+    {
+      FormalParameter parameter = nodeF.parameters.parameters[0];
+      DartType parameterType = parameter.element.type;
+      Element returnTypeElement = nodeF.returnType.type.element;
+      expect(returnTypeElement.displayName, 'int');
+      expect(parameterType.element, nodeG.element);
+    }
+    {
+      FormalParameter parameter = nodeG.parameters.parameters[0];
+      DartType parameterType = parameter.element.type;
+      expect(nodeG.returnType.type.element.displayName, 'String');
+      expect(parameterType.element.displayName, 'int');
+    }
+  }
+
+  test_perform_typedef_errors() {
+    Source source = newSource('/test.dart', '''
+typedef int F(NoSuchType p);
+''');
+    LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
+    computeResult(target, RESOLVE_TYPE_NAMES_ERRORS);
     expect(task, new isInstanceOf<ResolveUnitTypeNamesTask>());
     // validate
     _fillErrorListener(RESOLVE_TYPE_NAMES_ERRORS);
@@ -2473,6 +2553,16 @@
     expect(variable.isPotentiallyMutatedInScope, mutatedInScope);
   }
 
+  test_perform_buildClosureLibraryElements() {
+    Source source = newSource('/test.dart', '''
+main() {
+}
+''');
+    LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
+    computeResult(target, RESOLVED_UNIT4);
+    expect(task, new isInstanceOf<ResolveVariableReferencesTask>());
+  }
+
   test_perform_local() {
     Source source = newSource('/test.dart', '''
 main() {
@@ -2489,10 +2579,10 @@
 }
 ''');
     LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
-    _computeResult(target, RESOLVED_UNIT5);
+    computeResult(target, RESOLVED_UNIT4);
     expect(task, new isInstanceOf<ResolveVariableReferencesTask>());
     // validate
-    CompilationUnit unit = outputs[RESOLVED_UNIT5];
+    CompilationUnit unit = outputs[RESOLVED_UNIT4];
     FunctionElement main = unit.element.functions[0];
     expectMutated(main.localVariables[0], isFalse, isFalse);
     expectMutated(main.localVariables[1], isFalse, isTrue);
@@ -2512,10 +2602,10 @@
 }
 ''');
     LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
-    _computeResult(target, RESOLVED_UNIT5);
+    computeResult(target, RESOLVED_UNIT4);
     expect(task, new isInstanceOf<ResolveVariableReferencesTask>());
     // validate
-    CompilationUnit unit = outputs[RESOLVED_UNIT5];
+    CompilationUnit unit = outputs[RESOLVED_UNIT4];
     FunctionElement main = unit.element.functions[0];
     expectMutated(main.parameters[0], isFalse, isFalse);
     expectMutated(main.parameters[1], isFalse, isTrue);
@@ -2572,21 +2662,64 @@
     expect(outputs[TOKEN_STREAM], isNotNull);
   }
 
+  test_perform_script() {
+    String scriptContent = '''
+      void buttonPressed() {
+    ''';
+    String htmlContent = '''
+<!DOCTYPE html>
+<html>
+  <head>
+    <title>test page</title>
+    <script type='application/dart'>$scriptContent</script>
+  </head>
+  <body>Test</body>
+</html>
+''';
+    Source source = newSource('/test.html', htmlContent);
+    DartScript script =
+        new DartScript(source, [new ScriptFragment(97, 5, 36, scriptContent)]);
+
+    computeResult(script, TOKEN_STREAM);
+    expect(task, new isInstanceOf<ScanDartTask>());
+    expect(outputs[LINE_INFO], isNotNull);
+    expect(outputs[SCAN_ERRORS], isEmpty);
+    Token tokenStream = outputs[TOKEN_STREAM];
+    expect(tokenStream, isNotNull);
+    expect(tokenStream.lexeme, 'void');
+  }
+
   void _performScanTask(String content) {
     AnalysisTarget target = newSource('/test.dart', content);
-    _computeResult(target, TOKEN_STREAM);
+    computeResult(target, TOKEN_STREAM);
     expect(task, new isInstanceOf<ScanDartTask>());
   }
 }
 
 @reflectiveTest
 class VerifyUnitTaskTest extends _AbstractDartTaskTest {
+  test_perform_constantError() {
+    Source source = newSource('/test.dart', '''
+main(int p) {
+  const v = p;
+}
+''');
+    LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
+    computeResult(target, VERIFY_ERRORS);
+    expect(task, new isInstanceOf<VerifyUnitTask>());
+    // validate
+    _fillErrorListener(VERIFY_ERRORS);
+    errorListener.assertErrorsWithCodes(<ErrorCode>[
+      CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+    ]);
+  }
+
   test_perform_directiveError() {
     Source source = newSource('/test.dart', '''
 import 'no-such-file.dart';
 ''');
     LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
-    _computeResult(target, VERIFY_ERRORS);
+    computeResult(target, VERIFY_ERRORS);
     expect(task, new isInstanceOf<VerifyUnitTask>());
     // validate
     _fillErrorListener(VERIFY_ERRORS);
@@ -2603,7 +2736,7 @@
 }
 ''');
     LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
-    _computeResult(target, VERIFY_ERRORS);
+    computeResult(target, VERIFY_ERRORS);
     expect(task, new isInstanceOf<VerifyUnitTask>());
     // validate
     _fillErrorListener(VERIFY_ERRORS);
@@ -2615,9 +2748,6 @@
 class _AbstractDartTaskTest extends AbstractContextTest {
   Source emptySource;
 
-  AnalysisTask task;
-  Map<ResultDescriptor<dynamic>, dynamic> oldOutputs;
-  Map<ResultDescriptor<dynamic>, dynamic> outputs;
   GatheringErrorListener errorListener = new GatheringErrorListener();
 
   void assertIsInvalid(AnalysisTarget target, ResultDescriptor descriptor) {
@@ -2638,19 +2768,31 @@
     });
   }
 
+  /**
+   * Create a script object with a single fragment containing the given
+   * [scriptContent].
+   */
+  DartScript createScript(String scriptContent) {
+    String htmlContent = '''
+<!DOCTYPE html>
+<html>
+  <head>
+    <title>test page</title>
+    <script type='application/dart'>$scriptContent</script>
+  </head>
+  <body>Test</body>
+</html>
+''';
+    Source source = newSource('/test.html', htmlContent);
+    return new DartScript(
+        source, [new ScriptFragment(97, 5, 36, scriptContent)]);
+  }
+
   void setUp() {
     super.setUp();
     emptySource = newSource('/test.dart');
   }
 
-  void _computeResult(AnalysisTarget target, ResultDescriptor result) {
-    oldOutputs = outputs;
-    task = analysisDriver.computeResult(target, result);
-    expect(task, isNotNull);
-    expect(task.caughtException, isNull);
-    outputs = task.outputs;
-  }
-
   /**
    * Fill [errorListener] with [result] errors in the current [task].
    */
diff --git a/pkg/analyzer/test/src/task/dart_work_manager_test.dart b/pkg/analyzer/test/src/task/dart_work_manager_test.dart
index 2281be8..9119cee 100644
--- a/pkg/analyzer/test/src/task/dart_work_manager_test.dart
+++ b/pkg/analyzer/test/src/task/dart_work_manager_test.dart
@@ -122,18 +122,6 @@
     expect_unknownSourceQueue([]);
   }
 
-  void test_applyChange_scheduleInvalidatedLibraries() {
-    // libraries source1 and source3 are invalid
-    entry1.setValue(SOURCE_KIND, SourceKind.LIBRARY, []);
-    entry2.setValue(SOURCE_KIND, SourceKind.PART, []);
-    entry3.setValue(SOURCE_KIND, SourceKind.LIBRARY, []);
-    entry1.setValue(LIBRARY_ERRORS_READY, false, []);
-    entry3.setValue(LIBRARY_ERRORS_READY, false, []);
-    // change source2, schedule source1 and source3
-    manager.applyChange([], [source2], []);
-    expect_librarySourceQueue([source1, source3]);
-  }
-
   void test_applyChange_updatePartsLibraries_changeLibrary() {
     Source part1 = new TestSource('part1.dart');
     Source part2 = new TestSource('part2.dart');
@@ -219,7 +207,9 @@
     expect(manager.libraryPartsMap[library2], [part1, part2]);
   }
 
-  void test_applyPriorityTargets_library() {
+  void test_applyPriorityTargets_isLibrary_computeErrors() {
+    when(context.shouldErrorsBeAnalyzed(source2, null)).thenReturn(true);
+    when(context.shouldErrorsBeAnalyzed(source3, null)).thenReturn(true);
     entry1.setValue(SOURCE_KIND, SourceKind.LIBRARY, []);
     entry2.setValue(SOURCE_KIND, SourceKind.LIBRARY, []);
     entry3.setValue(SOURCE_KIND, SourceKind.LIBRARY, []);
@@ -239,7 +229,27 @@
     expect(request.result, LIBRARY_ERRORS_READY);
   }
 
-  void test_applyPriorityTargets_part() {
+  void test_applyPriorityTargets_isLibrary_computeUnit() {
+    when(context.shouldErrorsBeAnalyzed(source2, null)).thenReturn(false);
+    when(context.shouldErrorsBeAnalyzed(source3, null)).thenReturn(false);
+    entry1.setValue(SOURCE_KIND, SourceKind.LIBRARY, []);
+    entry2.setValue(SOURCE_KIND, SourceKind.LIBRARY, []);
+    entry3.setValue(SOURCE_KIND, SourceKind.LIBRARY, []);
+    manager.priorityResultQueue
+        .add(new TargetedResult(source1, LIBRARY_ERRORS_READY));
+    manager.priorityResultQueue
+        .add(new TargetedResult(source2, LIBRARY_ERRORS_READY));
+    // -source1 +source3
+    manager.applyPriorityTargets([source2, source3]);
+    expect(manager.priorityResultQueue, unorderedEquals([
+      new TargetedResult(
+          new LibrarySpecificUnit(source2, source2), RESOLVED_UNIT),
+      new TargetedResult(
+          new LibrarySpecificUnit(source3, source3), RESOLVED_UNIT),
+    ]));
+  }
+
+  void test_applyPriorityTargets_isPart() {
     entry1.setValue(SOURCE_KIND, SourceKind.PART, []);
     entry2.setValue(SOURCE_KIND, SourceKind.LIBRARY, []);
     entry3.setValue(SOURCE_KIND, SourceKind.LIBRARY, []);
@@ -257,6 +267,18 @@
     expect(request.result, LIBRARY_ERRORS_READY);
   }
 
+  void test_applyPriorityTargets_isUnknown() {
+    manager.applyPriorityTargets([source2, source3]);
+    expect(manager.priorityResultQueue, unorderedEquals([
+      new TargetedResult(source2, SOURCE_KIND),
+      new TargetedResult(source3, SOURCE_KIND)
+    ]));
+    // get next request
+    TargetedResult request = manager.getNextResult();
+    expect(request.target, source2);
+    expect(request.result, SOURCE_KIND);
+  }
+
   void test_getErrors() {
     AnalysisError error1 =
         new AnalysisError(source1, 1, 0, ScannerErrorCode.MISSING_DIGIT);
@@ -273,6 +295,20 @@
     expect(errorInfo.lineInfo, lineInfo);
   }
 
+  void test_getErrors_hasFullList() {
+    AnalysisError error1 =
+        new AnalysisError(source1, 1, 0, ScannerErrorCode.MISSING_DIGIT);
+    AnalysisError error2 =
+        new AnalysisError(source1, 2, 0, ScannerErrorCode.MISSING_DIGIT);
+    when(context.getLibrariesContaining(source1)).thenReturn([source2]);
+    LineInfo lineInfo = new LineInfo([0]);
+    entry1.setValue(LINE_INFO, lineInfo, []);
+    entry1.setValue(DART_ERRORS, <AnalysisError>[error1, error2], []);
+    AnalysisErrorInfo errorInfo = manager.getErrors(source1);
+    expect(errorInfo.errors, unorderedEquals([error1, error2]));
+    expect(errorInfo.lineInfo, lineInfo);
+  }
+
   void test_getLibrariesContainingPart() {
     Source part1 = new TestSource('part1.dart');
     Source part2 = new TestSource('part2.dart');
@@ -437,6 +473,22 @@
     expect(entry1.getState(INCLUDED_PARTS), CacheState.VALID);
   }
 
+  void test_onResultInvalidated_scheduleInvalidatedLibraries() {
+    // set SOURCE_KIND
+    entry1.setValue(SOURCE_KIND, SourceKind.LIBRARY, []);
+    entry2.setValue(SOURCE_KIND, SourceKind.PART, []);
+    entry3.setValue(SOURCE_KIND, SourceKind.LIBRARY, []);
+    // set LIBRARY_ERRORS_READY for source1 and source3
+    entry1.setValue(LIBRARY_ERRORS_READY, true, []);
+    entry3.setValue(LIBRARY_ERRORS_READY, true, []);
+    // invalidate LIBRARY_ERRORS_READY for source1, schedule it
+    entry1.setState(LIBRARY_ERRORS_READY, CacheState.INVALID);
+    expect_librarySourceQueue([source1]);
+    // invalidate LIBRARY_ERRORS_READY for source3, schedule it
+    entry3.setState(LIBRARY_ERRORS_READY, CacheState.INVALID);
+    expect_librarySourceQueue([source1, source3]);
+  }
+
   void test_onSourceFactoryChanged() {
     when(context.exists(anyObject)).thenReturn(true);
     // set cache values
@@ -570,12 +622,35 @@
 
   void test_resultsComputed_sourceKind_isLibrary() {
     manager.unknownSourceQueue.addAll([source1, source2, source3]);
+    when(context.prioritySources).thenReturn(<Source>[]);
     when(context.shouldErrorsBeAnalyzed(source2, null)).thenReturn(true);
     manager.resultsComputed(source2, {SOURCE_KIND: SourceKind.LIBRARY});
     expect_librarySourceQueue([source2]);
     expect_unknownSourceQueue([source1, source3]);
   }
 
+  void test_resultsComputed_sourceKind_isLibrary_isPriority_computeErrors() {
+    manager.unknownSourceQueue.addAll([source1, source2, source3]);
+    when(context.prioritySources).thenReturn(<Source>[source2]);
+    when(context.shouldErrorsBeAnalyzed(source2, null)).thenReturn(true);
+    manager.resultsComputed(source2, {SOURCE_KIND: SourceKind.LIBRARY});
+    expect_unknownSourceQueue([source1, source3]);
+    expect(manager.priorityResultQueue,
+        unorderedEquals([new TargetedResult(source2, LIBRARY_ERRORS_READY)]));
+  }
+
+  void test_resultsComputed_sourceKind_isLibrary_isPriority_computeUnit() {
+    manager.unknownSourceQueue.addAll([source1, source2, source3]);
+    when(context.prioritySources).thenReturn(<Source>[source2]);
+    when(context.shouldErrorsBeAnalyzed(source2, null)).thenReturn(false);
+    manager.resultsComputed(source2, {SOURCE_KIND: SourceKind.LIBRARY});
+    expect_unknownSourceQueue([source1, source3]);
+    expect(manager.priorityResultQueue, unorderedEquals([
+      new TargetedResult(
+          new LibrarySpecificUnit(source2, source2), RESOLVED_UNIT)
+    ]));
+  }
+
   void test_resultsComputed_sourceKind_isPart() {
     manager.unknownSourceQueue.addAll([source1, source2, source3]);
     manager.resultsComputed(source2, {SOURCE_KIND: SourceKind.PART});
diff --git a/pkg/analyzer/test/src/task/driver_test.dart b/pkg/analyzer/test/src/task/driver_test.dart
index cfbbe81..1053691 100644
--- a/pkg/analyzer/test/src/task/driver_test.dart
+++ b/pkg/analyzer/test/src/task/driver_test.dart
@@ -28,8 +28,8 @@
   groupSep = ' | ';
   runReflectiveTests(AnalysisDriverTest);
   runReflectiveTests(CycleAwareDependencyWalkerTest);
-  runReflectiveTests(WorkOrderTest);
   runReflectiveTests(WorkItemTest);
+  runReflectiveTests(WorkOrderTest);
 }
 
 class AbstractDriverTest {
@@ -332,6 +332,28 @@
     expect(analysisDriver.performAnalysisTask(), false);
   }
 
+  test_performAnalysisTask_onResultComputed() {
+    AnalysisTarget target = new TestSource();
+    ResultDescriptor result = new ResultDescriptor('result', null);
+    TestAnalysisTask task;
+    TaskDescriptor descriptor = new TaskDescriptor(
+        'task', (context, target) => task, (target) => {}, [result]);
+    task = new TestAnalysisTask(context, target,
+        descriptor: descriptor, value: 42);
+    WorkItem item = new WorkItem(context, target, descriptor, null);
+
+    bool streamNotified = false;
+    analysisDriver.onResultComputed(result).listen((event) {
+      streamNotified = true;
+      expect(event.context, same(context));
+      expect(event.target, same(target));
+      expect(event.descriptor, same(result));
+      expect(event.value, 42);
+    });
+    analysisDriver.performWorkItem(item);
+    expect(streamNotified, isTrue);
+  }
+
   test_performWorkItem_exceptionInTask() {
     AnalysisTarget target = new TestSource();
     ResultDescriptor result = new ResultDescriptor('result', null);
diff --git a/pkg/analyzer/test/src/task/html_test.dart b/pkg/analyzer/test/src/task/html_test.dart
new file mode 100644
index 0000000..e3413b7
--- /dev/null
+++ b/pkg/analyzer/test/src/task/html_test.dart
@@ -0,0 +1,309 @@
+// 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.html_test;
+
+import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/task/html.dart';
+import 'package:analyzer/task/html.dart';
+import 'package:analyzer/task/model.dart';
+import 'package:unittest/unittest.dart';
+
+import '../../reflective_tests.dart';
+import '../context/abstract_context.dart';
+
+main() {
+  groupSep = ' | ';
+  runReflectiveTests(DartScriptsTaskTest);
+  runReflectiveTests(HtmlErrorsTaskTest);
+  runReflectiveTests(ParseHtmlTaskTest);
+}
+
+@reflectiveTest
+class DartScriptsTaskTest extends AbstractContextTest {
+  test_buildInputs() {
+    Source source = newSource('/test.html');
+    Map<String, TaskInput> inputs = DartScriptsTask.buildInputs(source);
+    expect(inputs, isNotNull);
+    expect(inputs.keys, unorderedEquals([DartScriptsTask.DOCUMENT_INPUT]));
+  }
+
+  test_constructor() {
+    Source source = newSource('/test.html');
+    DartScriptsTask task = new DartScriptsTask(context, source);
+    expect(task, isNotNull);
+    expect(task.context, context);
+    expect(task.target, source);
+  }
+
+  test_createTask() {
+    Source source = newSource('/test.html');
+    DartScriptsTask task = DartScriptsTask.createTask(context, source);
+    expect(task, isNotNull);
+    expect(task.context, context);
+    expect(task.target, source);
+  }
+
+  test_description() {
+    Source source = newSource('/test.html');
+    DartScriptsTask task = new DartScriptsTask(null, source);
+    expect(task.description, isNotNull);
+  }
+
+  test_descriptor() {
+    TaskDescriptor descriptor = DartScriptsTask.DESCRIPTOR;
+    expect(descriptor, isNotNull);
+  }
+
+  void test_perform_embedded_source() {
+    String content = r'''
+    void buttonPressed() {}
+  ''';
+    AnalysisTarget target = newSource('/test.html', '''
+<!DOCTYPE html>
+<html>
+<head>
+  <script type='application/dart'>$content</script>
+</head>
+<body>
+</body>
+</html>''');
+    computeResult(target, REFERENCED_LIBRARIES);
+    expect(task, new isInstanceOf<DartScriptsTask>());
+    expect(outputs[REFERENCED_LIBRARIES], hasLength(0));
+    expect(outputs[DART_SCRIPTS], hasLength(1));
+    DartScript script = outputs[DART_SCRIPTS][0];
+    expect(script.fragments, hasLength(1));
+    ScriptFragment fragment = script.fragments[0];
+    expect(fragment.content, content);
+  }
+
+  void test_perform_empty_source_reference() {
+    AnalysisTarget target = newSource('/test.html', r'''
+<!DOCTYPE html>
+<html>
+<head>
+  <script type='application/dart' src=''/>
+</head>
+<body>
+</body>
+</html>''');
+    computeResult(target, REFERENCED_LIBRARIES);
+    expect(task, new isInstanceOf<DartScriptsTask>());
+    expect(outputs[REFERENCED_LIBRARIES], hasLength(0));
+    expect(outputs[DART_SCRIPTS], hasLength(0));
+  }
+
+  void test_perform_invalid_source_reference() {
+    AnalysisTarget target = newSource('/test.html', r'''
+<!DOCTYPE html>
+<html>
+<head>
+  <script type='application/dart' src='an;invalid:[]uri'/>
+</head>
+<body>
+</body>
+</html>''');
+    computeResult(target, REFERENCED_LIBRARIES);
+    expect(task, new isInstanceOf<DartScriptsTask>());
+    expect(outputs[REFERENCED_LIBRARIES], hasLength(0));
+    expect(outputs[DART_SCRIPTS], hasLength(0));
+  }
+
+  void test_perform_non_existing_source_reference() {
+    AnalysisTarget target = newSource('/test.html', r'''
+<!DOCTYPE html>
+<html>
+<head>
+  <script type='application/dart' src='does/not/exist.dart'/>
+</head>
+<body>
+</body>
+</html>''');
+    computeResult(target, REFERENCED_LIBRARIES);
+    expect(task, new isInstanceOf<DartScriptsTask>());
+    expect(outputs[REFERENCED_LIBRARIES], hasLength(1));
+    expect(outputs[DART_SCRIPTS], hasLength(0));
+  }
+
+  test_perform_none() {
+    AnalysisTarget target = newSource('/test.html', r'''
+<!DOCTYPE html>
+<html>
+  <head>
+    <title>test page</title>
+  </head>
+  <body>
+    Test
+  </body>
+</html>
+''');
+    computeResult(target, REFERENCED_LIBRARIES);
+    expect(task, new isInstanceOf<DartScriptsTask>());
+    expect(outputs[REFERENCED_LIBRARIES], hasLength(0));
+    expect(outputs[DART_SCRIPTS], hasLength(0));
+  }
+
+  void test_perform_referenced_source() {
+    AnalysisTarget target = newSource('/test.html', r'''
+<!DOCTYPE html>
+<html>
+<head>
+  <script type='application/dart' src='test.dart'/>
+</head>
+<body>
+</body>
+</html>''');
+    computeResult(target, REFERENCED_LIBRARIES);
+    expect(task, new isInstanceOf<DartScriptsTask>());
+    expect(outputs[REFERENCED_LIBRARIES], hasLength(1));
+    expect(outputs[DART_SCRIPTS], hasLength(0));
+  }
+}
+
+@reflectiveTest
+class HtmlErrorsTaskTest extends AbstractContextTest {
+  test_buildInputs() {
+    Source source = newSource('/test.html');
+    Map<String, TaskInput> inputs = HtmlErrorsTask.buildInputs(source);
+    expect(inputs, isNotNull);
+    expect(inputs.keys, unorderedEquals([
+      HtmlErrorsTask.DART_ERRORS_INPUT,
+      HtmlErrorsTask.DOCUMENT_ERRORS_INPUT
+    ]));
+  }
+
+  test_constructor() {
+    Source source = newSource('/test.html');
+    HtmlErrorsTask task = new HtmlErrorsTask(context, source);
+    expect(task, isNotNull);
+    expect(task.context, context);
+    expect(task.target, source);
+  }
+
+  test_createTask() {
+    Source source = newSource('/test.html');
+    HtmlErrorsTask task = HtmlErrorsTask.createTask(context, source);
+    expect(task, isNotNull);
+    expect(task.context, context);
+    expect(task.target, source);
+  }
+
+  test_description() {
+    Source source = newSource('/test.html');
+    HtmlErrorsTask task = new HtmlErrorsTask(null, source);
+    expect(task.description, isNotNull);
+  }
+
+  test_descriptor() {
+    TaskDescriptor descriptor = HtmlErrorsTask.DESCRIPTOR;
+    expect(descriptor, isNotNull);
+  }
+
+  test_perform_dartErrors() {
+    AnalysisTarget target = newSource('/test.html', r'''
+<!DOCTYPE html>
+<html>
+  <head>
+    <title>test page</title>
+    <script type='application/dart'>
+      void buttonPressed() {
+    </script>
+  </head>
+  <body>Test</body>
+</html>
+''');
+    computeResult(target, HTML_ERRORS);
+    expect(task, new isInstanceOf<HtmlErrorsTask>());
+    expect(outputs[HTML_ERRORS], hasLength(1));
+  }
+
+  test_perform_htmlErrors() {
+    AnalysisTarget target = newSource('/test.html', r'''
+<html>
+  <head>
+    <title>test page</title>
+  </head>
+  <body>
+    Test
+  </body>
+</html>
+''');
+    computeResult(target, HTML_ERRORS);
+    expect(task, new isInstanceOf<HtmlErrorsTask>());
+    expect(outputs[HTML_ERRORS], hasLength(1));
+  }
+
+  test_perform_noErrors() {
+    AnalysisTarget target = newSource('/test.html', r'''
+<!DOCTYPE html>
+<html>
+  <head>
+    <title>test page</title>
+  </head>
+  <body>
+    Test
+  </body>
+</html>
+''');
+    computeResult(target, HTML_ERRORS);
+    expect(task, new isInstanceOf<HtmlErrorsTask>());
+    expect(outputs[HTML_ERRORS], isEmpty);
+  }
+}
+
+@reflectiveTest
+class ParseHtmlTaskTest extends AbstractContextTest {
+  test_buildInputs() {
+    Source source = newSource('/test.html');
+    Map<String, TaskInput> inputs = ParseHtmlTask.buildInputs(source);
+    expect(inputs, isNotNull);
+    expect(inputs.keys, unorderedEquals([ParseHtmlTask.CONTENT_INPUT_NAME]));
+  }
+
+  test_constructor() {
+    Source source = newSource('/test.html');
+    ParseHtmlTask task = new ParseHtmlTask(context, source);
+    expect(task, isNotNull);
+    expect(task.context, context);
+    expect(task.target, source);
+  }
+
+  test_createTask() {
+    Source source = newSource('/test.html');
+    ParseHtmlTask task = ParseHtmlTask.createTask(context, source);
+    expect(task, isNotNull);
+    expect(task.context, context);
+    expect(task.target, source);
+  }
+
+  test_description() {
+    Source source = newSource('/test.html');
+    ParseHtmlTask task = new ParseHtmlTask(null, source);
+    expect(task.description, isNotNull);
+  }
+
+  test_descriptor() {
+    TaskDescriptor descriptor = ParseHtmlTask.DESCRIPTOR;
+    expect(descriptor, isNotNull);
+  }
+
+  test_perform() {
+    AnalysisTarget target = newSource('/test.html', r'''
+<!DOCTYPE html>
+<html>
+  <head>
+    <title>test page</title>
+  </head>
+  <body>
+    <h1 Test>
+  </body>
+</html>
+''');
+    computeResult(target, HTML_DOCUMENT);
+    expect(task, new isInstanceOf<ParseHtmlTask>());
+    expect(outputs[HTML_DOCUMENT], isNotNull);
+    expect(outputs[HTML_DOCUMENT_ERRORS], isNotEmpty);
+  }
+}
diff --git a/pkg/analyzer/test/src/task/html_work_manager_test.dart b/pkg/analyzer/test/src/task/html_work_manager_test.dart
new file mode 100644
index 0000000..94015ae
--- /dev/null
+++ b/pkg/analyzer/test/src/task/html_work_manager_test.dart
@@ -0,0 +1,352 @@
+// 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.html_work_manager_test;
+
+import 'package:analyzer/src/context/cache.dart';
+import 'package:analyzer/src/generated/engine.dart'
+    show
+        AnalysisEngine,
+        AnalysisErrorInfo,
+        AnalysisErrorInfoImpl,
+        CacheState,
+        ChangeNoticeImpl,
+        InternalAnalysisContext;
+import 'package:analyzer/src/generated/error.dart'
+    show AnalysisError, HtmlErrorCode;
+import 'package:analyzer/src/generated/java_engine.dart' show CaughtException;
+import 'package:analyzer/src/generated/scanner.dart' show ScannerErrorCode;
+import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/task/driver.dart';
+import 'package:analyzer/src/task/html.dart';
+import 'package:analyzer/src/task/html_work_manager.dart';
+import 'package:analyzer/task/dart.dart';
+import 'package:analyzer/task/general.dart';
+import 'package:analyzer/task/html.dart';
+import 'package:analyzer/task/model.dart';
+import 'package:typed_mock/typed_mock.dart';
+import 'package:unittest/unittest.dart';
+
+import '../../generated/test_support.dart';
+import '../../reflective_tests.dart';
+
+main() {
+  groupSep = ' | ';
+  runReflectiveTests(HtmlWorkManagerTest);
+}
+
+@reflectiveTest
+class HtmlWorkManagerTest {
+  InternalAnalysisContext context = new _InternalAnalysisContextMock();
+  AnalysisCache cache;
+  HtmlWorkManager manager;
+
+  CaughtException caughtException = new CaughtException(null, null);
+
+  Source source1 = new TestSource('1.html');
+  Source source2 = new TestSource('2.html');
+  Source source3 = new TestSource('3.html');
+  Source source4 = new TestSource('4.html');
+  CacheEntry entry1;
+  CacheEntry entry2;
+  CacheEntry entry3;
+  CacheEntry entry4;
+
+  void expect_sourceQueue(List<Source> sources) {
+    expect(manager.sourceQueue, unorderedEquals(sources));
+  }
+
+  void setUp() {
+    cache = context.analysisCache;
+    manager = new HtmlWorkManager(context);
+    entry1 = context.getCacheEntry(source1);
+    entry2 = context.getCacheEntry(source2);
+    entry3 = context.getCacheEntry(source3);
+    entry4 = context.getCacheEntry(source4);
+  }
+
+  void test_applyChange_add() {
+    // add source1
+    manager.applyChange([source1], [], []);
+    expect_sourceQueue([source1]);
+    // add source2
+    manager.applyChange([source2], [], []);
+    expect_sourceQueue([source1, source2]);
+  }
+
+  void test_applyChange_add_duplicate() {
+    // add source1
+    manager.applyChange([source1], [], []);
+    expect_sourceQueue([source1]);
+    // add source1 again
+    manager.applyChange([source1], [], []);
+    expect_sourceQueue([source1]);
+  }
+
+  void test_applyChange_change() {
+    // change source1
+    manager.applyChange([], [source1], []);
+    expect_sourceQueue([source1]);
+  }
+
+  void test_applyChange_change_afterAdd() {
+    manager.applyChange([source1, source2], [], []);
+    // change source1
+    manager.applyChange([], [source1], []);
+    expect_sourceQueue([source1, source2]);
+  }
+
+  void test_applyChange_remove() {
+    manager.applyChange([source1, source2], [], []);
+    // remove source1
+    manager.applyChange([], [], [source1]);
+    expect_sourceQueue([source2]);
+    // remove source2
+    manager.applyChange([], [], [source2]);
+    expect_sourceQueue([]);
+    // remove source3
+    manager.applyChange([], [], [source3]);
+    expect_sourceQueue([]);
+  }
+
+  void test_applyPriorityTargets() {
+    when(context.shouldErrorsBeAnalyzed(source2, null)).thenReturn(true);
+    when(context.shouldErrorsBeAnalyzed(source3, null)).thenReturn(true);
+    manager.priorityResultQueue.add(new TargetedResult(source1, HTML_ERRORS));
+    manager.priorityResultQueue.add(new TargetedResult(source2, HTML_ERRORS));
+    // -source1 +source3
+    manager.applyPriorityTargets([source2, source3]);
+    expect(manager.priorityResultQueue, unorderedEquals([
+      new TargetedResult(source2, HTML_ERRORS),
+      new TargetedResult(source3, HTML_ERRORS)
+    ]));
+    // get next request
+    TargetedResult request = manager.getNextResult();
+    expect(request.target, source2);
+    expect(request.result, HTML_ERRORS);
+  }
+
+  void test_getErrors_fullList() {
+    AnalysisError error1 =
+        new AnalysisError(source1, 1, 0, HtmlErrorCode.PARSE_ERROR, ['']);
+    AnalysisError error2 =
+        new AnalysisError(source1, 2, 0, HtmlErrorCode.PARSE_ERROR, ['']);
+    LineInfo lineInfo = new LineInfo([0]);
+    entry1.setValue(HTML_DOCUMENT_ERRORS, <AnalysisError>[error1], []);
+    entry1.setValue(LINE_INFO, lineInfo, []);
+
+    DartScript script = new DartScript(source1, []);
+    entry1.setValue(DART_SCRIPTS, [script], []);
+    CacheEntry scriptEntry = context.getCacheEntry(script);
+    scriptEntry.setValue(DART_ERRORS, [error2], []);
+
+    AnalysisErrorInfo errorInfo = manager.getErrors(source1);
+    expect(errorInfo.errors, unorderedEquals([error1, error2]));
+    expect(errorInfo.lineInfo, lineInfo);
+  }
+
+  void test_getErrors_partialList() {
+    AnalysisError error1 =
+        new AnalysisError(source1, 1, 0, HtmlErrorCode.PARSE_ERROR, ['']);
+    AnalysisError error2 =
+        new AnalysisError(source1, 2, 0, HtmlErrorCode.PARSE_ERROR, ['']);
+    LineInfo lineInfo = new LineInfo([0]);
+    entry1.setValue(HTML_DOCUMENT_ERRORS, <AnalysisError>[error1, error2], []);
+    entry1.setValue(LINE_INFO, lineInfo, []);
+
+    AnalysisErrorInfo errorInfo = manager.getErrors(source1);
+    expect(errorInfo.errors, unorderedEquals([error1, error2]));
+    expect(errorInfo.lineInfo, lineInfo);
+  }
+
+  void test_getNextResult_hasNormal_firstIsError() {
+    entry1.setErrorState(caughtException, [HTML_ERRORS]);
+    manager.sourceQueue.addAll([source1, source2]);
+    TargetedResult request = manager.getNextResult();
+    expect(request.target, source2);
+    expect(request.result, HTML_ERRORS);
+    // source1 is out, source2 is waiting
+    expect_sourceQueue([source2]);
+  }
+
+  void test_getNextResult_hasNormal_firstIsInvalid() {
+    entry1.setState(HTML_ERRORS, CacheState.INVALID);
+    manager.sourceQueue.addAll([source1, source2]);
+    TargetedResult request = manager.getNextResult();
+    expect(request.target, source1);
+    expect(request.result, HTML_ERRORS);
+    // no changes until computed
+    expect_sourceQueue([source1, source2]);
+  }
+
+  void test_getNextResult_hasNormal_firstIsValid() {
+    entry1.setValue(HTML_ERRORS, [], []);
+    manager.sourceQueue.addAll([source1, source2]);
+    TargetedResult request = manager.getNextResult();
+    expect(request.target, source2);
+    expect(request.result, HTML_ERRORS);
+    // source1 is out, source2 is waiting
+    expect_sourceQueue([source2]);
+  }
+
+  void test_getNextResult_hasNormalAndPriority() {
+    entry1.setState(HTML_ERRORS, CacheState.INVALID);
+    manager.sourceQueue.addAll([source1, source2]);
+    manager.addPriorityResult(source3, HTML_ERRORS);
+
+    TargetedResult request = manager.getNextResult();
+    expect(request.target, source3);
+    expect(request.result, HTML_ERRORS);
+    // no changes until computed
+    expect_sourceQueue([source1, source2]);
+  }
+
+  void test_getNextResult_hasPriority() {
+    manager.addPriorityResult(source1, HTML_ERRORS);
+    manager.addPriorityResult(source2, HTML_ERRORS);
+    expect(manager.priorityResultQueue, unorderedEquals([
+      new TargetedResult(source1, HTML_ERRORS),
+      new TargetedResult(source2, HTML_ERRORS)
+    ]));
+
+    TargetedResult request = manager.getNextResult();
+    expect(request.target, source1);
+    expect(request.result, HTML_ERRORS);
+    // no changes until computed
+    expect(manager.priorityResultQueue, unorderedEquals([
+      new TargetedResult(source1, HTML_ERRORS),
+      new TargetedResult(source2, HTML_ERRORS)
+    ]));
+  }
+
+  void test_getNextResult_nothingToDo() {
+    TargetedResult request = manager.getNextResult();
+    expect(request, isNull);
+  }
+
+  void test_getNextResultPriority_hasPriority() {
+    manager.addPriorityResult(source1, SOURCE_KIND);
+    expect(manager.getNextResultPriority(), WorkOrderPriority.PRIORITY);
+  }
+
+  void test_getNextResultPriority_hasSource() {
+    manager.sourceQueue.addAll([source1]);
+    expect(manager.getNextResultPriority(), WorkOrderPriority.NORMAL);
+  }
+
+  void test_getNextResultPriority_nothingToDo() {
+    expect(manager.getNextResultPriority(), WorkOrderPriority.NONE);
+  }
+
+  void test_onAnalysisOptionsChanged() {
+    when(context.exists(anyObject)).thenReturn(true);
+    // set cache values
+    entry1.setValue(DART_SCRIPTS, [], []);
+    entry1.setValue(HTML_DOCUMENT, null, []);
+    entry1.setValue(HTML_DOCUMENT_ERRORS, [], []);
+    entry1.setValue(HTML_ERRORS, [], []);
+    entry1.setValue(REFERENCED_LIBRARIES, [], []);
+    // notify
+    manager.onAnalysisOptionsChanged();
+    // Only resolution-based values are invalidated.
+    expect(entry1.getState(DART_SCRIPTS), CacheState.VALID);
+    expect(entry1.getState(HTML_DOCUMENT), CacheState.VALID);
+    expect(entry1.getState(HTML_DOCUMENT_ERRORS), CacheState.VALID);
+    expect(entry1.getState(HTML_ERRORS), CacheState.INVALID);
+    expect(entry1.getState(REFERENCED_LIBRARIES), CacheState.VALID);
+  }
+
+  void test_onResultInvalidated_scheduleInvalidatedLibraries() {
+    // set HTML_ERRORS for source1 and source3
+    entry1.setValue(HTML_ERRORS, [], []);
+    entry3.setValue(HTML_ERRORS, [], []);
+    // invalidate HTML_ERRORS for source1, schedule it
+    entry1.setState(HTML_ERRORS, CacheState.INVALID);
+    expect_sourceQueue([source1]);
+    // invalidate HTML_ERRORS for source3, schedule it
+    entry3.setState(HTML_ERRORS, CacheState.INVALID);
+    expect_sourceQueue([source1, source3]);
+  }
+
+  void test_onSourceFactoryChanged() {
+    when(context.exists(anyObject)).thenReturn(true);
+    // set cache values
+    entry1.setValue(DART_SCRIPTS, [], []);
+    entry1.setValue(HTML_DOCUMENT, null, []);
+    entry1.setValue(HTML_DOCUMENT_ERRORS, [], []);
+    entry1.setValue(HTML_ERRORS, [], []);
+    entry1.setValue(REFERENCED_LIBRARIES, [], []);
+    // notify
+    manager.onSourceFactoryChanged();
+    // Only resolution-based values are invalidated.
+    expect(entry1.getState(DART_SCRIPTS), CacheState.VALID);
+    expect(entry1.getState(HTML_DOCUMENT), CacheState.VALID);
+    expect(entry1.getState(HTML_DOCUMENT_ERRORS), CacheState.VALID);
+    expect(entry1.getState(HTML_ERRORS), CacheState.INVALID);
+    expect(entry1.getState(REFERENCED_LIBRARIES), CacheState.INVALID);
+  }
+
+  void test_resultsComputed_errors() {
+    AnalysisError error1 =
+        new AnalysisError(source1, 1, 0, HtmlErrorCode.PARSE_ERROR, ['']);
+    AnalysisError error2 =
+        new AnalysisError(source1, 2, 0, HtmlErrorCode.PARSE_ERROR, ['']);
+    LineInfo lineInfo = new LineInfo([0]);
+    entry1.setValue(LINE_INFO, lineInfo, []);
+    entry1.setValue(HTML_ERRORS, <AnalysisError>[error1, error2], []);
+    // RESOLVED_UNIT is ready, set errors
+    manager.resultsComputed(source1, {HTML_ERRORS: null});
+    // all of the errors are included
+    ChangeNoticeImpl notice = context.getNotice(source1);
+    expect(notice.errors, unorderedEquals([error1, error2]));
+    expect(notice.lineInfo, lineInfo);
+  }
+}
+
+class _InternalAnalysisContextMock extends TypedMock
+    implements InternalAnalysisContext {
+  @override
+  CachePartition privateAnalysisCachePartition;
+
+  @override
+  AnalysisCache analysisCache;
+
+  Map<Source, ChangeNoticeImpl> _pendingNotices = <Source, ChangeNoticeImpl>{};
+
+  _InternalAnalysisContextMock() {
+    privateAnalysisCachePartition = new UniversalCachePartition(this);
+    analysisCache = new AnalysisCache([privateAnalysisCachePartition]);
+  }
+
+  @override
+  CacheEntry getCacheEntry(AnalysisTarget target) {
+    CacheEntry entry = analysisCache.get(target);
+    if (entry == null) {
+      entry = new CacheEntry(target);
+      analysisCache.put(entry);
+    }
+    return entry;
+  }
+
+  @override
+  AnalysisErrorInfo getErrors(Source source) {
+    String name = source.shortName;
+    List<AnalysisError> errors = AnalysisError.NO_ERRORS;
+    if (AnalysisEngine.isDartFileName(name) || source is DartScript) {
+      errors = getCacheEntry(source).getValue(DART_ERRORS);
+    } else if (AnalysisEngine.isHtmlFileName(name)) {
+      errors = getCacheEntry(source).getValue(HTML_ERRORS);
+    }
+    return new AnalysisErrorInfoImpl(
+        errors, getCacheEntry(source).getValue(LINE_INFO));
+  }
+
+  @override
+  ChangeNoticeImpl getNotice(Source source) {
+    return _pendingNotices.putIfAbsent(
+        source, () => new ChangeNoticeImpl(source));
+  }
+
+  noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
+}
diff --git a/pkg/analyzer/test/src/task/inputs_test.dart b/pkg/analyzer/test/src/task/inputs_test.dart
index cbd5890..625f916 100644
--- a/pkg/analyzer/test/src/task/inputs_test.dart
+++ b/pkg/analyzer/test/src/task/inputs_test.dart
@@ -19,6 +19,8 @@
   runReflectiveTests(ListToListTaskInputBuilderTest);
   runReflectiveTests(ListToMapTaskInputBuilderTest);
   runReflectiveTests(ListToMapTaskInputTest);
+  runReflectiveTests(ObjectToListTaskInputBuilderTest);
+  runReflectiveTests(ObjectToListTaskInputTest);
   runReflectiveTests(SimpleTaskInputTest);
   runReflectiveTests(SimpleTaskInputBuilderTest);
   runReflectiveTests(TopLevelTaskInputBuilderTest);
@@ -460,20 +462,27 @@
 }
 
 @reflectiveTest
-class SimpleTaskInputBuilderTest extends EngineTestCase {
+class ObjectToListTaskInputBuilderTest extends EngineTestCase {
   static final AnalysisTarget target = new TestSource();
   static final ResultDescriptorImpl result =
       new ResultDescriptorImpl('result', null);
-  static final SimpleTaskInput input = new SimpleTaskInput(target, result);
+  static final SimpleTaskInput baseInput = new SimpleTaskInput(target, result);
+  static final Function mapper = (x) => [x];
+  static final ObjectToListTaskInput input =
+      new ObjectToListTaskInput(baseInput, mapper);
+
+  ObjectToListTaskInputBuilder builder;
+
+  void setUp() {
+    builder = new ObjectToListTaskInputBuilder(input);
+  }
 
   test_create() {
-    SimpleTaskInputBuilder builder = new SimpleTaskInputBuilder(input);
     expect(builder, isNotNull);
     expect(builder.input, input);
   }
 
   test_currentResult_afterComplete() {
-    SimpleTaskInputBuilder builder = new SimpleTaskInputBuilder(input);
     builder.moveNext();
     builder.currentValue = 'value';
     builder.moveNext();
@@ -481,7 +490,6 @@
   }
 
   test_currentResult_afterCurrentValueNotAvailable() {
-    SimpleTaskInputBuilder builder = new SimpleTaskInputBuilder(input);
     builder.moveNext();
     builder.currentValueNotAvailable();
     builder.moveNext();
@@ -489,18 +497,15 @@
   }
 
   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_afterComplete() {
-    SimpleTaskInputBuilder builder = new SimpleTaskInputBuilder(input);
     builder.moveNext();
     builder.currentValue = 'value';
     builder.moveNext();
@@ -508,7 +513,6 @@
   }
 
   test_currentTarget_afterCurrentValueNotAvailable() {
-    SimpleTaskInputBuilder builder = new SimpleTaskInputBuilder(input);
     builder.moveNext();
     builder.currentValueNotAvailable();
     builder.moveNext();
@@ -516,44 +520,184 @@
   }
 
   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);
   }
 
   test_currentValue_afterOneMoveNext() {
-    SimpleTaskInputBuilder builder = new SimpleTaskInputBuilder(input);
     builder.moveNext();
     builder.currentValue = 'value';
   }
 
   test_currentValue_beforeMoveNext() {
-    SimpleTaskInputBuilder builder = new SimpleTaskInputBuilder(input);
     expect(() {
       builder.currentValue = 'value';
     }, throwsStateError);
   }
 
   test_currentValueNotAvailable_afterOneMoveNext() {
-    SimpleTaskInputBuilder builder = new SimpleTaskInputBuilder(input);
     builder.moveNext();
     builder.currentValueNotAvailable();
   }
 
   test_currentValueNotAvailable_beforeMoveNext() {
-    SimpleTaskInputBuilder builder = new SimpleTaskInputBuilder(input);
     expect(() {
       builder.currentValueNotAvailable();
     }, throwsStateError);
   }
 
   test_inputValue_afterComplete() {
-    SimpleTaskInputBuilder builder = new SimpleTaskInputBuilder(input);
+    builder.moveNext();
+    String value = 'value';
+    builder.currentValue = value;
+    builder.moveNext();
+    expect(builder.inputValue, [value]);
+  }
+
+  test_inputValue_afterCurrentValueNotAvailable() {
+    builder.moveNext();
+    builder.currentValueNotAvailable();
+    builder.moveNext();
+    expect(builder.inputValue, [null]);
+  }
+
+  test_inputValue_afterOneMoveNext() {
+    builder.moveNext();
+    expect(() => builder.inputValue, throwsStateError);
+  }
+
+  test_inputValue_beforeMoveNext() {
+    expect(() => builder.inputValue, throwsStateError);
+  }
+
+  test_moveNext_withoutSet() {
+    expect(builder.moveNext(), true);
+    expect(() => builder.moveNext(), throwsStateError);
+  }
+
+  test_moveNext_withSet() {
+    expect(builder.moveNext(), true);
+    builder.currentValue = 'value';
+    expect(builder.moveNext(), false);
+    expect(builder.moveNext(), false);
+  }
+}
+
+@reflectiveTest
+class ObjectToListTaskInputTest extends EngineTestCase {
+  static final AnalysisTarget target = new TestSource();
+  static final ResultDescriptorImpl result =
+      new ResultDescriptorImpl('result', null);
+
+  test_create() {
+    SimpleTaskInput baseInput = new SimpleTaskInput(target, result);
+    Function mapper = (x) => [x];
+    ObjectToListTaskInput input = new ObjectToListTaskInput(baseInput, mapper);
+    expect(input, isNotNull);
+    expect(input.baseInput, baseInput);
+    expect(input.mapper, equals(mapper));
+  }
+
+  test_createBuilder() {
+    SimpleTaskInput baseInput = new SimpleTaskInput(target, result);
+    Function mapper = (x) => [x];
+    ObjectToListTaskInput input = new ObjectToListTaskInput(baseInput, mapper);
+    expect(input.createBuilder(),
+        new isInstanceOf<ObjectToListTaskInputBuilder>());
+  }
+}
+
+@reflectiveTest
+class SimpleTaskInputBuilderTest extends EngineTestCase {
+  static final AnalysisTarget target = new TestSource();
+  static final ResultDescriptorImpl result =
+      new ResultDescriptorImpl('result', null);
+  static final SimpleTaskInput input = new SimpleTaskInput(target, result);
+
+  SimpleTaskInputBuilder builder;
+
+  void setUp() {
+    builder = new SimpleTaskInputBuilder(input);
+  }
+
+  test_create() {
+    expect(builder, isNotNull);
+    expect(builder.input, input);
+  }
+
+  test_currentResult_afterComplete() {
+    builder.moveNext();
+    builder.currentValue = 'value';
+    builder.moveNext();
+    expect(builder.currentResult, null);
+  }
+
+  test_currentResult_afterCurrentValueNotAvailable() {
+    builder.moveNext();
+    builder.currentValueNotAvailable();
+    builder.moveNext();
+    expect(builder.currentResult, null);
+  }
+
+  test_currentResult_afterOneMoveNext() {
+    builder.moveNext();
+    expect(builder.currentResult, result);
+  }
+
+  test_currentResult_beforeMoveNext() {
+    expect(builder.currentResult, null);
+  }
+
+  test_currentTarget_afterComplete() {
+    builder.moveNext();
+    builder.currentValue = 'value';
+    builder.moveNext();
+    expect(builder.currentTarget, null);
+  }
+
+  test_currentTarget_afterCurrentValueNotAvailable() {
+    builder.moveNext();
+    builder.currentValueNotAvailable();
+    builder.moveNext();
+    expect(builder.currentTarget, null);
+  }
+
+  test_currentTarget_afterOneMoveNext() {
+    builder.moveNext();
+    expect(builder.currentTarget, target);
+  }
+
+  test_currentTarget_beforeMoveNext() {
+    expect(builder.currentTarget, null);
+  }
+
+  test_currentValue_afterOneMoveNext() {
+    builder.moveNext();
+    builder.currentValue = 'value';
+  }
+
+  test_currentValue_beforeMoveNext() {
+    expect(() {
+      builder.currentValue = 'value';
+    }, throwsStateError);
+  }
+
+  test_currentValueNotAvailable_afterOneMoveNext() {
+    builder.moveNext();
+    builder.currentValueNotAvailable();
+  }
+
+  test_currentValueNotAvailable_beforeMoveNext() {
+    expect(() {
+      builder.currentValueNotAvailable();
+    }, throwsStateError);
+  }
+
+  test_inputValue_afterComplete() {
     builder.moveNext();
     String value = 'value';
     builder.currentValue = value;
@@ -562,7 +706,6 @@
   }
 
   test_inputValue_afterCurrentValueNotAvailable() {
-    SimpleTaskInputBuilder builder = new SimpleTaskInputBuilder(input);
     builder.moveNext();
     builder.currentValueNotAvailable();
     builder.moveNext();
@@ -570,24 +713,20 @@
   }
 
   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);
   }
 
   test_moveNext_withoutSet() {
-    SimpleTaskInputBuilder builder = new SimpleTaskInputBuilder(input);
     expect(builder.moveNext(), true);
     expect(() => builder.moveNext(), throwsStateError);
   }
 
   test_moveNext_withSet() {
-    SimpleTaskInputBuilder builder = new SimpleTaskInputBuilder(input);
     expect(builder.moveNext(), true);
     builder.currentValue = 'value';
     expect(builder.moveNext(), false);
diff --git a/pkg/analyzer/test/src/task/test_all.dart b/pkg/analyzer/test/src/task/test_all.dart
index 2b6de23..44d4eef 100644
--- a/pkg/analyzer/test/src/task/test_all.dart
+++ b/pkg/analyzer/test/src/task/test_all.dart
@@ -10,6 +10,8 @@
 import 'dart_work_manager_test.dart' as dart_work_manager_test;
 import 'driver_test.dart' as driver_test;
 import 'general_test.dart' as general_test;
+import 'html_test.dart' as html_test;
+import 'html_work_manager_test.dart' as html_work_manager_test;
 import 'incremental_element_builder_test.dart'
     as incremental_element_builder_test;
 import 'inputs_test.dart' as inputs_test;
@@ -24,6 +26,8 @@
     dart_work_manager_test.main();
     driver_test.main();
     general_test.main();
+    html_test.main();
+    html_work_manager_test.main();
     incremental_element_builder_test.main();
     inputs_test.main();
     manager_test.main();
diff --git a/pkg/compiler/lib/src/apiimpl.dart b/pkg/compiler/lib/src/apiimpl.dart
index c2e9446..a36ee9a 100644
--- a/pkg/compiler/lib/src/apiimpl.dart
+++ b/pkg/compiler/lib/src/apiimpl.dart
@@ -100,6 +100,7 @@
                 hasOption(options, '--enable-experimental-mirrors'),
             generateCodeWithCompileTimeErrors:
                 hasOption(options, '--generate-code-with-compile-time-errors'),
+            testMode: hasOption(options, '--test-mode'),
             allowNativeExtensions:
                 hasOption(options, '--allow-native-extensions'),
             enableNullAwareOperators:
diff --git a/pkg/compiler/lib/src/closure.dart b/pkg/compiler/lib/src/closure.dart
index 1b59ee3..3beedab 100644
--- a/pkg/compiler/lib/src/closure.dart
+++ b/pkg/compiler/lib/src/closure.dart
@@ -88,7 +88,7 @@
 
 /// Common interface for [BoxFieldElement] and [ClosureFieldElement] as
 /// non-elements.
-abstract class CapturedVariable {}
+abstract class CapturedVariable implements Element {}
 
 // TODO(ahe): These classes continuously cause problems.  We need to
 // find a more general solution.
@@ -651,7 +651,8 @@
       // things in the builder.
       // Note that nested (named) functions are immutable.
       if (variable != closureData.thisLocal &&
-          variable != closureData.closureElement) {
+          variable != closureData.closureElement &&
+          variable is! TypeVariableLocal) {
         closureData.variablesUsedInTryOrGenerator.add(variable);
       }
     } else if (variable is LocalParameterElement &&
diff --git a/pkg/compiler/lib/src/compile_time_constants.dart b/pkg/compiler/lib/src/compile_time_constants.dart
index a1c3768..b0c7502 100644
--- a/pkg/compiler/lib/src/compile_time_constants.dart
+++ b/pkg/compiler/lib/src/compile_time_constants.dart
@@ -12,7 +12,6 @@
 import 'dart2jslib.dart' show Compiler, CompilerTask, MessageKind, WorldImpact, invariant;
 import 'elements/elements.dart';
 import 'elements/modelx.dart' show FunctionElementX;
-import 'helpers/helpers.dart';
 import 'resolution/resolution.dart';
 import 'resolution/operators.dart';
 import 'tree/tree.dart';
@@ -248,6 +247,10 @@
     return expression;
   }
 
+  void cacheConstantValue(ConstantExpression expression, ConstantValue value) {
+    constantValueMap[expression] = value;
+  }
+
   ConstantExpression compileNodeWithDefinitions(Node node,
                                                 TreeElements definitions,
                                                 {bool isConst: true}) {
@@ -256,7 +259,7 @@
         this, definitions, compiler, isConst: isConst);
     AstConstant constant = evaluator.evaluate(node);
     if (constant != null) {
-      constantValueMap[constant.expression] = constant.value;
+      cacheConstantValue(constant.expression, constant.value);
       return constant.expression;
     }
     return null;
@@ -302,7 +305,7 @@
                                                 TreeElements definitions,
                                                 {bool isConst: true}) {
     ConstantExpression constant = definitions.getConstant(node);
-    if (constant != null) {
+    if (constant != null && getConstantValue(constant) != null) {
       return constant;
     }
     constant =
@@ -785,7 +788,7 @@
       return new AstConstant.fromDefaultValue(
           element, constant, handler.getConstantValue(constant));
     }
-    target.computeSignature(compiler);
+    target.computeType(compiler);
 
     if (!callStructure.signatureApplies(target)) {
       String name = Elements.constructorNameForDiagnostics(
diff --git a/pkg/compiler/lib/src/compiler.dart b/pkg/compiler/lib/src/compiler.dart
index 2ba863e..7e42649 100644
--- a/pkg/compiler/lib/src/compiler.dart
+++ b/pkg/compiler/lib/src/compiler.dart
@@ -93,17 +93,17 @@
     world.registerStaticUse(element);
   }
 
-  void registerDynamicInvocation(Selector selector) {
+  void registerDynamicInvocation(UniverseSelector selector) {
     world.registerDynamicInvocation(selector);
     compiler.dumpInfoTask.elementUsesSelector(currentElement, selector);
   }
 
-  void registerDynamicSetter(Selector selector) {
+  void registerDynamicSetter(UniverseSelector selector) {
     world.registerDynamicSetter(selector);
     compiler.dumpInfoTask.elementUsesSelector(currentElement, selector);
   }
 
-  void registerDynamicGetter(Selector selector) {
+  void registerDynamicGetter(UniverseSelector selector) {
     world.registerDynamicGetter(selector);
     compiler.dumpInfoTask.elementUsesSelector(currentElement, selector);
   }
@@ -135,8 +135,8 @@
     backend.registerTypeVariableBoundsSubtypeCheck(subtype, supertype);
   }
 
-  void registerClosureWithFreeTypeVariables(FunctionElement element) {
-    backend.registerClosureWithFreeTypeVariables(element, world, this);
+  void registerInstantiatedClosure(LocalFunctionElement element) {
+    backend.registerInstantiatedClosure(element, this);
   }
 
   void registerGetOfStaticFunction(FunctionElement element) {
@@ -144,7 +144,7 @@
   }
 
   void registerSelectorUse(Selector selector) {
-    world.registerSelectorUse(selector);
+    world.registerSelectorUse(new UniverseSelector(selector, null));
   }
 
   void registerConstSymbol(String name) {
@@ -239,11 +239,11 @@
 
   bool get isForResolution;
 
-  void registerDynamicInvocation(Selector selector);
+  void registerDynamicInvocation(UniverseSelector selector);
 
-  void registerDynamicGetter(Selector selector);
+  void registerDynamicGetter(UniverseSelector selector);
 
-  void registerDynamicSetter(Selector selector);
+  void registerDynamicSetter(UniverseSelector selector);
 
   void registerStaticInvocation(Element element);
 
@@ -302,8 +302,6 @@
 
   List<CompilerTask> get tasks;
 
-  bool get canHandleCompilationFailed;
-
   void onResolutionComplete() {}
   void onTypeInferenceComplete() {}
 
@@ -314,6 +312,14 @@
   bool classNeedsRti(ClassElement cls);
   bool methodNeedsRti(FunctionElement function);
 
+  /// Enable compilation of code with compile time errors. Returns `true` if
+  /// supported by the backend.
+  bool enableCodegenWithErrorsIfSupported(Spannable node);
+
+  /// Enable deferred loading. Returns `true` if the backend supports deferred
+  /// loading.
+  bool enableDeferredLoadingIfSupported(Spannable node, Registry registry);
+
   /// Called during codegen when [constant] has been used.
   void registerCompileTimeConstant(ConstantValue constant, Registry registry) {}
 
@@ -790,6 +796,9 @@
   /// Generate output even when there are compile-time errors.
   final bool generateCodeWithCompileTimeErrors;
 
+  /// The compiler is run from the build bot.
+  final bool testMode;
+
   bool disableInlining = false;
 
   List<Uri> librariesToAnalyzeWhenRun;
@@ -1049,6 +1058,7 @@
             this.allowNativeExtensions: false,
             this.enableNullAwareOperators: false,
             this.generateCodeWithCompileTimeErrors: false,
+            this.testMode: false,
             api.CompilerOutputProvider outputProvider,
             List<String> strips: const []})
       : this.disableTypeInferenceFlag =
@@ -1324,7 +1334,6 @@
         // The maximum number of imports chains to show.
         final int compactChainLimit = verbose ? 20 : 10;
         int chainCount = 0;
-        bool limitExceeded = false;
         loadedLibraries.forEachImportChain(DART_MIRRORS,
             callback: (Link<Uri> importChainReversed) {
           Link<CodeLocation> compactImportChain = const Link<CodeLocation>();
@@ -1485,7 +1494,6 @@
     // suitably maintained static reference to the current compiler.
     StringToken.canonicalizedSubstrings.clear();
     Selector.canonicalizedValues.clear();
-    world.canonicalizedValues.clear();
 
     assert(uri != null || analyzeOnly || hasIncrementalSupport);
     return new Future.sync(() {
@@ -1541,7 +1549,8 @@
       mainFunction = backend.helperForBadMain();
     } else {
       mainFunction = main;
-      FunctionSignature parameters = mainFunction.computeSignature(this);
+      mainFunction.computeType(this);
+      FunctionSignature parameters = mainFunction.functionSignature;
       if (parameters.requiredParameterCount > 2) {
         int index = 0;
         parameters.orderedForEachParameter((Element parameter) {
@@ -1617,9 +1626,11 @@
       });
     }
 
-    // TODO(sigurdm): The dart backend should handle failed compilations.
-    if (compilationFailed && !backend.canHandleCompilationFailed) {
-      return;
+    if (compilationFailed){
+      if (!generateCodeWithCompileTimeErrors) return;
+      if (!backend.enableCodegenWithErrorsIfSupported(NO_LOCATION_SPANNABLE)) {
+        return;
+      }
     }
 
     if (analyzeOnly) {
@@ -1708,7 +1719,8 @@
     world.nativeEnqueuer.processNativeClasses(libraryLoader.libraries);
     if (main != null && !main.isErroneous) {
       FunctionElement mainMethod = main;
-      if (mainMethod.computeSignature(this).parameterCount != 0) {
+      mainMethod.computeType(this);
+      if (mainMethod.functionSignature.parameterCount != 0) {
         // The first argument could be a list of strings.
         backend.listImplementation.ensureResolved(this);
         world.registerInstantiatedType(
@@ -1793,8 +1805,7 @@
     Node tree = parser.parse(element);
     assert(invariant(element, !element.isSynthesized || tree == null));
     WorldImpact worldImpact = resolver.resolve(element);
-    if (tree != null && !analyzeSignaturesOnly &&
-        !suppressWarnings) {
+    if (tree != null && !analyzeSignaturesOnly && !suppressWarnings) {
       // Only analyze nodes with a corresponding [TreeElements].
       checker.check(element);
     }
@@ -1943,6 +1954,10 @@
     if (element == null) {
       element = currentElement;
     }
+    if (element == null) {
+      return null;
+    }
+
     if (element.sourcePosition != null) {
       return element.sourcePosition;
     }
@@ -2151,7 +2166,14 @@
   }
 
   EventSink<String> outputProvider(String name, String extension) {
-    if (compilationFailed) return new NullSink('$name.$extension');
+    if (compilationFailed) {
+      if (!generateCodeWithCompileTimeErrors || testMode) {
+        // Disable output in test mode: The build bot currently uses the time
+        // stamp of the generated file to determine whether the output is
+        // up-to-date.
+        return new NullSink('$name.$extension');
+      }
+    }
     return userOutputProvider(name, extension);
   }
 }
@@ -2420,21 +2442,32 @@
   InterfaceType get doubleType => doubleClass.computeType(compiler);
 
   @override
-  InterfaceType get functionType =>  functionClass.computeType(compiler);
+  InterfaceType get functionType => functionClass.computeType(compiler);
 
   @override
   InterfaceType get intType => intClass.computeType(compiler);
 
   @override
-  InterfaceType listType([DartType elementType = const DynamicType()]) {
-    return listClass.computeType(compiler).createInstantiation([elementType]);
+  InterfaceType listType([DartType elementType]) {
+    InterfaceType type = listClass.computeType(compiler);
+    if (elementType == null) {
+      return listClass.rawType;
+    }
+    return type.createInstantiation([elementType]);
   }
 
   @override
-  InterfaceType mapType([DartType keyType = const DynamicType(),
-                         DartType valueType = const DynamicType()]) {
-    return mapClass.computeType(compiler)
-        .createInstantiation([keyType, valueType]);
+  InterfaceType mapType([DartType keyType,
+                         DartType valueType]) {
+    InterfaceType type = mapClass.computeType(compiler);
+    if (keyType == null && valueType == null) {
+      return mapClass.rawType;
+    } else if (keyType == null) {
+      keyType = const DynamicType();
+    } else if (valueType == null) {
+      valueType = const DynamicType();
+    }
+    return type.createInstantiation([keyType, valueType]);
   }
 
   @override
@@ -2447,22 +2480,36 @@
   InterfaceType get stringType => stringClass.computeType(compiler);
 
   @override
+  InterfaceType get symbolType => symbolClass.computeType(compiler);
+
+  @override
   InterfaceType get typeType => typeClass.computeType(compiler);
 
   @override
-  InterfaceType iterableType([DartType elementType = const DynamicType()]) {
-    return iterableClass.computeType(compiler)
-        .createInstantiation([elementType]);
+  InterfaceType iterableType([DartType elementType]) {
+    InterfaceType type = iterableClass.computeType(compiler);
+    if (elementType == null) {
+      return iterableClass.rawType;
+    }
+    return type.createInstantiation([elementType]);
   }
 
   @override
-  InterfaceType futureType([DartType elementType = const DynamicType()]) {
-    return futureClass.computeType(compiler).createInstantiation([elementType]);
+  InterfaceType futureType([DartType elementType]) {
+    InterfaceType type = futureClass.computeType(compiler);
+    if (elementType == null) {
+      return futureClass.rawType;
+    }
+    return type.createInstantiation([elementType]);
   }
 
   @override
-  InterfaceType streamType([DartType elementType = const DynamicType()]) {
-    return streamClass.computeType(compiler).createInstantiation([elementType]);
+  InterfaceType streamType([DartType elementType]) {
+    InterfaceType type = streamClass.computeType(compiler);
+    if (elementType == null) {
+      return streamClass.rawType;
+    }
+    return type.createInstantiation([elementType]);
   }
 }
 
diff --git a/pkg/compiler/lib/src/constants/constructors.dart b/pkg/compiler/lib/src/constants/constructors.dart
index ab0e45a..a92edcc 100644
--- a/pkg/compiler/lib/src/constants/constructors.dart
+++ b/pkg/compiler/lib/src/constants/constructors.dart
@@ -14,7 +14,6 @@
 import '../tree/tree.dart';
 import '../universe/universe.dart' show CallStructure;
 import 'expressions.dart';
-import 'values.dart';
 
 ConstantConstructor computeConstantConstructor(ResolvedAst resolvedAst) {
   ConstantConstructorComputer visitor =
diff --git a/pkg/compiler/lib/src/constants/expressions.dart b/pkg/compiler/lib/src/constants/expressions.dart
index 23d65f2..5644b0f 100644
--- a/pkg/compiler/lib/src/constants/expressions.dart
+++ b/pkg/compiler/lib/src/constants/expressions.dart
@@ -5,6 +5,7 @@
 library dart2js.constants.expressions;
 
 import '../constants/constant_system.dart';
+import '../core_types.dart';
 import '../dart2jslib.dart' show assertDebugMode, Compiler;
 import '../dart_types.dart';
 import '../elements/elements.dart' show
@@ -40,6 +41,7 @@
   STRING_FROM_ENVIRONMENT,
   STRING_LENGTH,
   SYMBOL,
+  SYNTHETIC,
   TYPE,
   UNARY,
   VARIABLE,
@@ -275,6 +277,10 @@
   ConstantValue evaluate(Environment environment,
                          ConstantSystem constantSystem);
 
+  /// Returns the type of this constant expression, if it is independent of the
+  /// environment values.
+  DartType getKnownType(CoreTypes coreTypes) => null;
+
   String getText() {
     ConstExpPrinter printer = new ConstExpPrinter();
     accept(printer);
@@ -329,6 +335,35 @@
   bool _equals(ErroneousConstantExpression other) => true;
 }
 
+// TODO(johnniwinther): Avoid the need for this class.
+class SyntheticConstantExpression extends ConstantExpression {
+  final SyntheticConstantValue value;
+
+  SyntheticConstantExpression(this.value);
+
+  @override
+  ConstantValue evaluate(Environment environment,
+                         ConstantSystem constantSystem) {
+    return value;
+  }
+
+  @override
+  int _computeHashCode() => 13 * value.hashCode;
+
+  accept(ConstantExpressionVisitor visitor, [context]) {
+    throw "unsupported";
+  }
+
+  @override
+  bool _equals(SyntheticConstantExpression other) {
+    return value == other.value;
+  }
+
+  ConstantExpressionKind get kind => ConstantExpressionKind.SYNTHETIC;
+}
+
+
+
 /// A boolean, int, double, string, or null constant.
 abstract class PrimitiveConstantExpression extends ConstantExpression {
   /// The primitive value of this contant expression.
@@ -360,6 +395,9 @@
   bool _equals(BoolConstantExpression other) {
     return primitiveValue == other.primitiveValue;
   }
+
+  @override
+  DartType getKnownType(CoreTypes coreTypes) => coreTypes.boolType;
 }
 
 /// Integer literal constant.
@@ -387,6 +425,9 @@
   bool _equals(IntConstantExpression other) {
     return primitiveValue == other.primitiveValue;
   }
+
+  @override
+  DartType getKnownType(CoreTypes coreTypes) => coreTypes.intType;
 }
 
 /// Double literal constant.
@@ -414,6 +455,9 @@
   bool _equals(DoubleConstantExpression other) {
     return primitiveValue == other.primitiveValue;
   }
+
+  @override
+  DartType getKnownType(CoreTypes coreTypes) => coreTypes.doubleType;
 }
 
 /// String literal constant.
@@ -441,6 +485,9 @@
   bool _equals(StringConstantExpression other) {
     return primitiveValue == other.primitiveValue;
   }
+
+  @override
+  DartType getKnownType(CoreTypes coreTypes) => coreTypes.stringType;
 }
 
 /// Null literal constant.
@@ -466,6 +513,9 @@
 
   @override
   bool _equals(NullConstantExpression other) => true;
+
+  @override
+  DartType getKnownType(CoreTypes coreTypes) => coreTypes.nullType;
 }
 
 /// Literal list constant.
@@ -511,6 +561,9 @@
     }
     return true;
   }
+
+  @override
+  DartType getKnownType(CoreTypes coreTypes) => type;
 }
 
 /// Literal map constant.
@@ -562,6 +615,9 @@
     }
     return true;
   }
+
+  @override
+  DartType getKnownType(CoreTypes coreTypes) => type;
 }
 
 /// Invocation of a const constructor.
@@ -699,6 +755,9 @@
     }
     return true;
   }
+
+  @override
+  DartType getKnownType(CoreTypes coreTypes) => coreTypes.stringType;
 }
 
 /// Symbol literal.
@@ -727,6 +786,9 @@
     // TODO(johnniwinther): Implement this.
     throw new UnsupportedError('SymbolConstantExpression.evaluate');
   }
+
+  @override
+  DartType getKnownType(CoreTypes coreTypes) => coreTypes.symbolType;
 }
 
 /// Type literal.
@@ -757,6 +819,9 @@
   bool _equals(TypeConstantExpression other) {
     return type == other.type;
   }
+
+  @override
+  DartType getKnownType(CoreTypes coreTypes) => coreTypes.typeType;
 }
 
 /// Reference to a constant local, top-level, or static variable.
@@ -811,6 +876,9 @@
   bool _equals(FunctionConstantExpression other) {
     return element == other.element;
   }
+
+  @override
+  DartType getKnownType(CoreTypes coreTypes) => coreTypes.functionType;
 }
 
 /// A constant binary expression like `a * b`.
@@ -844,6 +912,58 @@
         right.apply(arguments));
   }
 
+  DartType getKnownType(CoreTypes coreTypes) {
+    DartType knownLeftType = left.getKnownType(coreTypes);
+    DartType knownRightType = right.getKnownType(coreTypes);
+    switch (operator.kind) {
+      case BinaryOperatorKind.EQ:
+      case BinaryOperatorKind.NOT_EQ:
+      case BinaryOperatorKind.LOGICAL_AND:
+      case BinaryOperatorKind.LOGICAL_OR:
+      case BinaryOperatorKind.GT:
+      case BinaryOperatorKind.LT:
+      case BinaryOperatorKind.GTEQ:
+      case BinaryOperatorKind.LTEQ:
+        return coreTypes.boolType;
+      case BinaryOperatorKind.ADD:
+        if (knownLeftType == coreTypes.stringType) {
+          assert(knownRightType == coreTypes.stringType);
+          return coreTypes.stringType;
+        } else if (knownLeftType == coreTypes.intType &&
+                   knownRightType == coreTypes.intType) {
+          return coreTypes.intType;
+        }
+        assert(knownLeftType == coreTypes.doubleType ||
+               knownRightType == coreTypes.doubleType);
+        return coreTypes.doubleType;
+      case BinaryOperatorKind.SUB:
+      case BinaryOperatorKind.MUL:
+      case BinaryOperatorKind.MOD:
+        if (knownLeftType == coreTypes.intType &&
+            knownRightType == coreTypes.intType) {
+          return coreTypes.intType;
+        }
+        assert(knownLeftType == coreTypes.doubleType ||
+               knownRightType == coreTypes.doubleType);
+        return coreTypes.doubleType;
+      case BinaryOperatorKind.DIV:
+        return coreTypes.doubleType;
+      case BinaryOperatorKind.IDIV:
+        return coreTypes.intType;
+      case BinaryOperatorKind.AND:
+      case BinaryOperatorKind.OR:
+      case BinaryOperatorKind.XOR:
+      case BinaryOperatorKind.SHR:
+      case BinaryOperatorKind.SHL:
+        return coreTypes.intType;
+      case BinaryOperatorKind.IF_NULL:
+      case BinaryOperatorKind.INDEX:
+        throw new UnsupportedError(
+            'Unexpected constant binary operator: $operator');
+    }
+  }
+
+
   int get precedence => PRECEDENCE_MAP[operator.kind];
 
   @override
@@ -923,6 +1043,9 @@
     return left == other.left &&
            right == other.right;
   }
+
+  @override
+  DartType getKnownType(CoreTypes coreTypes) => coreTypes.boolType;
 }
 
 /// A unary constant expression like `-a`.
@@ -967,6 +1090,11 @@
            expression == other.expression;
   }
 
+  @override
+  DartType getKnownType(CoreTypes coreTypes) {
+    return expression.getKnownType(coreTypes);
+  }
+
   static const Map<UnaryOperatorKind, int> PRECEDENCE_MAP = const {
     UnaryOperatorKind.NOT: 14,
     UnaryOperatorKind.COMPLEMENT: 14,
@@ -1013,6 +1141,9 @@
   bool _equals(StringLengthConstantExpression other) {
     return expression == other.expression;
   }
+
+  @override
+  DartType getKnownType(CoreTypes coreTypes) => coreTypes.intType;
 }
 
 /// A constant conditional expression like `a ? b : c`.
@@ -1071,6 +1202,16 @@
       return new NonConstantValue();
     }
   }
+
+  @override
+  DartType getKnownType(CoreTypes coreTypes) {
+    DartType trueType = trueExp.getKnownType(coreTypes);
+    DartType falseType = falseExp.getKnownType(coreTypes);
+    if (trueType == falseType) {
+      return trueType;
+    }
+    return null;
+  }
 }
 
 /// A reference to a position parameter.
@@ -1203,6 +1344,9 @@
         name.apply(arguments),
         defaultValue != null ? defaultValue.apply(arguments) : null);
   }
+
+  @override
+  DartType getKnownType(CoreTypes coreTypes) => coreTypes.boolType;
 }
 
 /// A `const int.fromEnvironment` constant.
@@ -1256,6 +1400,9 @@
         name.apply(arguments),
         defaultValue != null ? defaultValue.apply(arguments) : null);
   }
+
+  @override
+  DartType getKnownType(CoreTypes coreTypes) => coreTypes.intType;
 }
 
 /// A `const String.fromEnvironment` constant.
@@ -1305,6 +1452,9 @@
         name.apply(arguments),
         defaultValue != null ? defaultValue.apply(arguments) : null);
   }
+
+  @override
+  DartType getKnownType(CoreTypes coreTypes) => coreTypes.stringType;
 }
 
 /// A constant expression referenced with a deferred prefix.
@@ -1381,15 +1531,6 @@
   R visitNamed(NamedArgumentReference exp, A context);
 }
 
-/// Represents the declaration of a constant [element] with value [expression].
-// TODO(johnniwinther): Where does this class belong?
-class ConstDeclaration {
-  final VariableElement element;
-  final ConstantExpression expression;
-
-  ConstDeclaration(this.element, this.expression);
-}
-
 class ConstExpPrinter extends ConstantExpressionVisitor {
   final StringBuffer sb = new StringBuffer();
 
diff --git a/pkg/compiler/lib/src/constants/values.dart b/pkg/compiler/lib/src/constants/values.dart
index e40a6b8..068a096 100644
--- a/pkg/compiler/lib/src/constants/values.dart
+++ b/pkg/compiler/lib/src/constants/values.dart
@@ -15,7 +15,6 @@
          FunctionElement,
          PrefixElement;
 import '../tree/tree.dart' hide unparse;
-import '../types/types.dart' as ti show TypeMask;
 import '../util/util.dart' show Hashing;
 
 abstract class ConstantValueVisitor<R, A> {
@@ -32,7 +31,7 @@
   R visitConstructed(ConstructedConstantValue constant, A arg);
   R visitType(TypeConstantValue constant, A arg);
   R visitInterceptor(InterceptorConstantValue constant, A arg);
-  R visitDummy(DummyConstantValue constant, A arg);
+  R visitSynthetic(SyntheticConstantValue constant, A arg);
   R visitDeferred(DeferredConstantValue constant, A arg);
 }
 
@@ -80,7 +79,7 @@
   /// expression from the value so the unparse of these is best effort.
   ///
   /// For the synthetic constants, [DeferredConstantValue],
-  /// [DummyConstantValue], [InterceptorConstantValue] the unparse is
+  /// [SyntheticConstantValue], [InterceptorConstantValue] the unparse is
   /// descriptive only.
   String unparse();
 
@@ -603,30 +602,32 @@
   }
 }
 
-// TODO(johnniwinther): Remove this class.
-class DummyConstantValue extends ConstantValue {
-  final ti.TypeMask typeMask;
+class SyntheticConstantValue extends ConstantValue {
+  final payload;
+  final kind;
 
-  DummyConstantValue(this.typeMask);
+  SyntheticConstantValue(this.kind, this.payload);
 
   bool get isDummy => true;
 
   bool operator ==(other) {
-    return other is DummyConstantValue
-        && typeMask == other.typeMask;
+    return other is SyntheticConstantValue
+        && payload == other.payload;
   }
 
-  get hashCode => typeMask.hashCode;
+  get hashCode => payload.hashCode * 17 + kind.hashCode;
 
   List<ConstantValue> getDependencies() => const <ConstantValue>[];
 
-  accept(ConstantValueVisitor visitor, arg) => visitor.visitDummy(this, arg);
+  accept(ConstantValueVisitor visitor, arg) {
+    return visitor.visitSynthetic(this, arg);
+  }
 
   DartType getType(CoreTypes types) => const DynamicType();
 
-  String unparse() => 'dummy($typeMask)';
+  String unparse() => 'synthetic($kind, $payload)';
 
-  String toStructuredString() => 'DummyConstant($typeMask)';
+  String toStructuredString() => 'SyntheticConstant($kind, $payload)';
 }
 
 class ConstructedConstantValue extends ObjectConstantValue {
@@ -639,6 +640,7 @@
       hashCode = Hashing.mapHash(fields, Hashing.objectHash(type)),
       super(type) {
     assert(type != null);
+    assert(!fields.containsValue(null));
   }
 
   bool get isConstructedObject => true;
diff --git a/pkg/compiler/lib/src/core_types.dart b/pkg/compiler/lib/src/core_types.dart
index c2e66c6..d8302be 100644
--- a/pkg/compiler/lib/src/core_types.dart
+++ b/pkg/compiler/lib/src/core_types.dart
@@ -27,6 +27,9 @@
   /// The `String` type defined in 'dart:core'.
   InterfaceType get stringType;
 
+  /// The `Symbol` type defined in 'dart:core'.
+  InterfaceType get symbolType;
+
   /// The `Function` type defined in 'dart:core'.
   InterfaceType get functionType;
 
@@ -38,25 +41,34 @@
 
   /// Returns an instance of the `List` type defined in 'dart:core' with
   /// [elementType] as its type argument.
-  InterfaceType listType([DartType elementType = const DynamicType()]);
+  ///
+  /// If no type argument is provided, the canonical raw type is returned.
+  InterfaceType listType([DartType elementType]);
 
   /// Returns an instance of the `Map` type defined in 'dart:core' with
   /// [keyType] and [valueType] as its type arguments.
-  InterfaceType mapType([DartType keyType = const DynamicType(),
-                         DartType valueType = const DynamicType()]);
+  ///
+  /// If no type arguments are provided, the canonical raw type is returned.
+  InterfaceType mapType([DartType keyType, DartType valueType]);
 
   /// Returns an instance of the `Iterable` type defined in 'dart:core' with
   /// [elementType] as its type argument.
-  InterfaceType iterableType([DartType elementType = const DynamicType()]);
+  ///
+  /// If no type argument is provided, the canonical raw type is returned.
+  InterfaceType iterableType([DartType elementType]);
 
   /// The `Future` class declaration.
   ClassElement get futureClass;
 
   /// Returns an instance of the `Future` type defined in 'dart:async' with
   /// [elementType] as its type argument.
-  InterfaceType futureType([DartType elementType = const DynamicType()]);
+  ///
+  /// If no type argument is provided, the canonical raw type is returned.
+  InterfaceType futureType([DartType elementType]);
 
   /// Returns an instance of the `Stream` type defined in 'dart:async' with
   /// [elementType] as its type argument.
-  InterfaceType streamType([DartType elementType = const DynamicType()]);
+  ///
+  /// If no type argument is provided, the canonical raw type is returned.
+  InterfaceType streamType([DartType elementType]);
 }
diff --git a/pkg/compiler/lib/src/cps_ir/builtin_operator.dart b/pkg/compiler/lib/src/cps_ir/builtin_operator.dart
new file mode 100644
index 0000000..9010bc2
--- /dev/null
+++ b/pkg/compiler/lib/src/cps_ir/builtin_operator.dart
@@ -0,0 +1,105 @@
+// 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 builtin_operator;
+// This is shared by the CPS and Tree IRs.
+// Both cps_ir_nodes and tree_ir_nodes import and re-export this file.
+
+/// An operator supported natively in the CPS and Tree IRs using the
+/// `ApplyBuiltinOperator` instructions.
+///
+/// These operators are pure in the sense that they cannot throw, diverge,
+/// have observable side-effects, return new objects, nor depend on any
+/// mutable state.
+///
+/// Most operators place restrictions on the values that may be given as
+/// argument; their behaviour is unspecified if those requirements are violated.
+///
+/// In all cases, the word "null" refers to the Dart null object, corresponding
+/// to both JS null and JS undefined.
+///
+/// Some operators, notably [IsFloor] and [IsNumberAndFloor], take "repeated"
+/// arguments to reflect the number of times the given value is referenced
+/// by the generated code. The tree IR needs to know the number of references
+/// to safely propagate assignments.
+enum BuiltinOperator {
+  /// The numeric binary operators must take two numbers as argument.
+  /// The bitwise operators coerce the result to an unsigned integer, but
+  /// otherwise these all behave like the corresponding JS operator.
+  NumAdd,
+  NumSubtract,
+  NumMultiply,
+  NumAnd,
+  NumOr,
+  NumXor,
+  NumLt,
+  NumLe,
+  NumGt,
+  NumGe,
+
+  /// Concatenates any number of strings.
+  ///
+  /// Takes any number of arguments, and each argument must be a string.
+  ///
+  /// Returns the empty string if no arguments are given.
+  StringConcatenate,
+
+  /// Returns true if the two arguments are the same value, and that value is
+  /// not NaN, or if one argument is +0 and the other is -0.
+  ///
+  /// Compiled as a static method call.
+  Identical,
+
+  /// Like [Identical], except at most one argument may be null.
+  ///
+  /// Compiles to `===`.
+  StrictEq,
+
+  /// Negated version of [StrictEq]. Introduced by [LogicalRewriter] in Tree IR.
+  StrictNeq,
+
+  /// Returns true if the two arguments are both null or are the same string,
+  /// boolean, or number, and that number is not NaN, or one argument is +0
+  /// and the other is -0.
+  ///
+  /// One of the following must hold:
+  /// - At least one argument is null.
+  /// - Arguments are both strings, or both booleans, or both numbers.
+  ///
+  /// Compiles to `==`.
+  LooseEq,
+
+  /// Negated version of [LooseEq]. Introduced by [LogicalRewriter] in Tree IR.
+  LooseNeq,
+
+  /// Returns true if the argument is false, +0. -0, NaN, the empty string,
+  /// or null.
+  ///
+  /// Compiles to `!`.
+  IsFalsy,
+
+  /// Returns true if the argument is a number.
+  ///
+  /// Compiles to `typeof x === 'number'`
+  IsNumber,
+
+  /// Returns true if the argument is not a number.
+  ///
+  /// Compiles to `typeof x !== 'number'`.
+  IsNotNumber,
+
+  /// Returns true if the argument is an integer, false if it is a double or
+  /// null, and unspecified if it is anything else.
+  ///
+  /// The argument must be repeated 2 times.
+  ///
+  /// Compiles to `Math.floor(x) === x`
+  IsFloor,
+
+  /// Returns true if the argument is an integer.
+  ///
+  /// The argument must be repeated 3 times.
+  ///
+  /// Compiles to `typeof x === 'number' && Math.floor(x) === x`
+  IsNumberAndFloor,
+}
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 0ea0217..df98350 100644
--- a/pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart
+++ b/pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart
@@ -6,19 +6,23 @@
 
 import '../compile_time_constants.dart' show BackendConstantEnvironment;
 import '../constants/constant_system.dart';
-import '../constants/expressions.dart';
 import '../constants/values.dart' show ConstantValue, PrimitiveConstantValue;
 import '../dart_types.dart';
 import '../dart2jslib.dart';
 import '../elements/elements.dart';
 import '../io/source_information.dart';
 import '../tree/tree.dart' as ast;
+import '../types/types.dart' show TypeMask;
 import '../closure.dart' hide ClosureScope;
 import '../universe/universe.dart' show SelectorKind;
 import 'cps_ir_nodes.dart' as ir;
 import 'cps_ir_builder_task.dart' show DartCapturedVariables,
     GlobalProgramInformation;
 
+import '../common.dart' as types show TypeMask;
+import '../js/js.dart' as js show Template;
+import '../native/native.dart' show NativeBehavior;
+
 /// A mapping from variable elements to their compile-time values.
 ///
 /// Map elements denoted by parameters and local variables to the
@@ -64,24 +68,25 @@
 
   void extend(Local element, ir.Primitive value) {
     // Assert that the name is not already in the environment.  `null` is used
-    // as the name of anonymous variables.  Because the variable2index map is
-    // shared, `null` can already occur.  This is safe because such variables
-    // are not looked up by name.
-    //
-    // TODO(kmillikin): This is still kind of fishy.  Refactor to not share
-    // name maps or else garbage collect unneeded names.
-    assert(element == null || !variable2index.containsKey(element));
-    variable2index[element] = index2variable.length;
+    // as the name of anonymous variables.
+    assert(!variable2index.containsKey(element));
+    if (element != null) variable2index[element] = index2variable.length;
     index2variable.add(element);
     index2value.add(value);
   }
 
-  void discard(int count) {
+  /// Drop [count] values from the environment.
+  ///
+  /// Return the previous last value in the environment for convenience.
+  ir.Primitive discard(int count) {
+    assert(count > 0);
     assert(count <= index2variable.length);
+    ir.Primitive value = index2value.last;
     // The map from variables to their index are shared, so we cannot remove
     // the mapping in `variable2index`.
     index2variable.length -= count;
     index2value.length -= count;
+    return value;
   }
 
   ir.Primitive lookup(Local element) {
@@ -104,10 +109,12 @@
       Local variable = index2variable[i];
       if (variable != other.index2variable[i]) return false;
 
-      // The variable maps to the same index in both environments.
-      int index = variable2index[variable];
-      if (index == null || index != other.variable2index[variable]) {
-        return false;
+      // A named variable maps to the same index in both environments.
+      if (variable != null) {
+        int index = variable2index[variable];
+        if (index == null || index != other.variable2index[variable]) {
+          return false;
+        }
       }
     }
     return true;
@@ -127,7 +134,15 @@
   final List<Iterable<LocalVariableElement>> _boxedTryVariables =
       <Iterable<LocalVariableElement>>[];
 
-  JumpCollector(this._continuationEnvironment, this.target);
+  /// Construct a collector for a given environment and optionally a target.
+  ///
+  /// The environment is the one in effect at the point where the jump's
+  /// continuation will be bound.  Continuations can take an extra argument
+  /// (see [addJump]).
+  JumpCollector(this._continuationEnvironment, this.target,
+      bool hasExtraArgument) {
+    if (hasExtraArgument) _continuationEnvironment.extend(null, null);
+  }
 
   /// True if the collector has not recorded any jumps to its continuation.
   bool get isEmpty;
@@ -140,7 +155,12 @@
   Environment get environment;
 
   /// Emit a jump to the continuation for a given [IrBuilder].
-  void addJump(IrBuilder builder);
+  ///
+  /// Jumps can take a single extra argument.  This is used to pass return
+  /// values to finally blocks for returns inside try/finally and to pass
+  /// values of expressions that have internal control flow to their join-point
+  /// continuations.
+  void addJump(IrBuilder builder, [ir.Primitive value]);
 
   /// Add a set of variables that were boxed on entry to a try block.
   ///
@@ -202,8 +222,9 @@
   /// continuation represented by this collector will be bound.  The
   /// environment is copied by the collector.  Subsequent mutation of the
   /// original environment will not affect the collector.
-  ForwardJumpCollector(Environment environment, {JumpTarget target: null})
-      : super(new Environment.from(environment), target);
+  ForwardJumpCollector(Environment environment,
+      {JumpTarget target, bool hasExtraArgument: false})
+      : super(new Environment.from(environment), target, hasExtraArgument);
 
   bool get isEmpty => _invocations.isEmpty;
 
@@ -217,12 +238,20 @@
     return _continuationEnvironment;
   }
 
-  void addJump(IrBuilder builder) {
+  void addJump(IrBuilder builder, [ir.Primitive value]) {
     assert(_continuation == null);
     _buildTryExit(builder);
     ir.InvokeContinuation invoke = new ir.InvokeContinuation.uninitialized();
     builder.add(invoke);
     _invocations.add(invoke);
+    // Truncate the environment at the invocation site so it only includes
+    // values that will be continuation arguments.  If an extra value is passed
+    // it will already be included in the continuation environment, but it is
+    // not present in the invocation environment.
+    int delta = builder.environment.length - _continuationEnvironment.length;
+    if (value != null) ++delta;
+    if (delta > 0) builder.environment.discard(delta);
+    if (value != null) builder.environment.extend(null, value);
     _invocationEnvironments.add(builder.environment);
     builder._current = null;
     // TODO(kmillikin): Can we set builder.environment to null to make it
@@ -304,8 +333,9 @@
   /// continuation represented by this collector will be bound.  The
   /// translation of the continuation body will use an environment with the
   /// same shape, but with fresh continuation parameters for each variable.
-  BackwardJumpCollector(Environment environment, {JumpTarget target: null})
-      : super(new Environment.fresh(environment), target) {
+  BackwardJumpCollector(Environment environment,
+      {JumpTarget target, bool hasExtraArgument: false})
+      : super(new Environment.fresh(environment), target, hasExtraArgument) {
     List<ir.Parameter> parameters =
         new List<ir.Parameter>.from(_continuationEnvironment.index2value);
     _continuation = new ir.Continuation(parameters, isRecursive: true);
@@ -316,13 +346,20 @@
   ir.Continuation get continuation => _continuation;
   Environment get environment => _continuationEnvironment;
 
-  void addJump(IrBuilder builder) {
+  void addJump(IrBuilder builder, [ir.Primitive value]) {
     assert(_continuation.parameters.length <= builder.environment.length);
     isEmpty = false;
     _buildTryExit(builder);
+    // Truncate the environment at the invocation site so it only includes
+    // values that will be continuation arguments.  If an extra value is passed
+    // it will already be included in the continuation environment, but it is
+    // not present in the invocation environment.
+    int delta = builder.environment.length - _continuationEnvironment.length;
+    if (value != null) ++delta;
+    if (delta > 0) builder.environment.discard(delta);
+    if (value != null) builder.environment.extend(null, value);
     builder.add(new ir.InvokeContinuation(_continuation,
-        builder.environment.index2value.take(_continuation.parameters.length)
-            .toList(),
+        builder.environment.index2value,
         isRecursive: true));
     builder._current = null;
   }
@@ -385,33 +422,45 @@
 
 /// Shared state between delimited IrBuilders within the same function.
 class IrBuilderSharedState {
+  final GlobalProgramInformation program;
+
   final BackendConstantEnvironment constants;
 
   ConstantSystem get constantSystem => constants.constantSystem;
 
   /// A stack of collectors for breaks.
-  final List<JumpCollector> breakCollectors = <JumpCollector>[];
+  List<JumpCollector> breakCollectors = <JumpCollector>[];
 
   /// A stack of collectors for continues.
-  final List<JumpCollector> continueCollectors = <JumpCollector>[];
-
-  final List<ConstDeclaration> localConstants = <ConstDeclaration>[];
+  List<JumpCollector> continueCollectors = <JumpCollector>[];
 
   final ExecutableElement currentElement;
 
   final ir.Continuation returnContinuation = new ir.Continuation.retrn();
-  ir.Parameter _thisParameter;
-  ir.Parameter enclosingMethodThisParameter;
+
+  /// The target of a return from the function.
+  ///
+  /// A null value indicates that the target is the function's return
+  /// continuation.  Otherwise, when inside the try block of try/finally
+  /// a return is intercepted to give a place to generate the finally code.
+  JumpCollector returnCollector = null;
+
+  /// Parameter holding the internal value of 'this' passed to the function.
+  ///
+  /// For nested functions, this is *not* captured receiver, but the function
+  /// object itself.
+  ir.Parameter thisParameter;
+
+  /// If non-null, this refers to the receiver (`this`) in the enclosing method.
+  ir.Primitive enclosingThis;
 
   final List<ir.Parameter> functionParameters = <ir.Parameter>[];
 
-  IrBuilderSharedState(this.constants, this.currentElement);
+  /// Maps boxed locals to their location. These locals are not part of
+  /// the environment.
+  final Map<Local, ClosureLocation> boxedVariables = {};
 
-  ir.Parameter get thisParameter => _thisParameter;
-  void set thisParameter(ir.Parameter value) {
-    assert(_thisParameter == null);
-    _thisParameter = value;
-  }
+  IrBuilderSharedState(this.program, this.constants, this.currentElement);
 }
 
 class ThisParameterLocal implements Local {
@@ -421,72 +470,24 @@
   toString() => 'ThisParameterLocal($executableContext)';
 }
 
-/// A factory for building the cps IR.
+/// The IR builder maintains an environment and an IR fragment.
 ///
-/// [DartIrBuilder] and [JsIrBuilder] implement nested functions and captured
-/// variables in different ways.
-abstract class IrBuilder {
-  IrBuilder _makeInstance();
-
-  void declareLocalVariable(LocalVariableElement element,
-                            {ir.Primitive initialValue});
-
-  /// Called when entering a nested function with free variables.
-  ///
-  /// The free variables must subsequently be accessible using [buildLocalGet]
-  /// and [buildLocalSet].
-  void _enterClosureEnvironment(ClosureEnvironment env);
-
-  /// Called when entering a function body or loop body.
-  ///
-  /// This is not called for for-loops, which instead use the methods
-  /// [_enterForLoopInitializer], [_enterForLoopBody], and [_enterForLoopUpdate]
-  /// due to their special scoping rules.
-  ///
-  /// The boxed variables declared in this scope must subsequently be available
-  /// using [buildLocalGet], [buildLocalSet], etc.
-  void _enterScope(ClosureScope scope);
-
-  /// Called before building the initializer of a for-loop.
-  ///
-  /// The loop variables will subsequently be declared using
-  /// [declareLocalVariable].
-  void _enterForLoopInitializer(ClosureScope scope,
-                                List<LocalElement> loopVariables);
-
-  /// Called before building the body of a for-loop.
-  void _enterForLoopBody(ClosureScope scope,
-                         List<LocalElement> loopVariables);
-
-  /// Called before building the update of a for-loop.
-  void _enterForLoopUpdate(ClosureScope scope,
-                           List<LocalElement> loopVariables);
-
-  /// Add the given function parameter to the IR, and bind it in the environment
-  /// or put it in its box, if necessary.
-  void _createFunctionParameter(Local parameterElement);
-  void _createThisParameter();
-
-  /// Reifies the value of [variable] on the current receiver object.
-  ir.Primitive buildReifyTypeVariable(TypeVariableType variable);
-
-  /// Creates an access to the receiver from the current (or enclosing) method.
-  ///
-  /// If inside a closure class, [buildThis] will redirect access through
-  /// closure fields in order to access the receiver from the enclosing method.
-  ir.Primitive buildThis();
-
-  /// Creates a type test or type cast of [value] against [type].
-  ir.Primitive buildTypeOperator(ir.Primitive value,
-                                 DartType type,
-                                 {bool isTypeTest});
-
-  // TODO(johnniwinther): Make these field final and remove the default values
-  // when [IrBuilder] is a property of [IrBuilderVisitor] instead of a mixin.
-
+/// The IR fragment is an expression with a hole in it. The hole represents
+/// the focus where new expressions can be added. The fragment is implemented
+/// by [_root] which is the root of the expression and [_current] which is the
+/// expression that immediately contains the hole. Not all expressions have a
+/// hole (e.g., invocations, which always occur in tail position, do not have a
+/// hole). Expressions with a hole have a plug method.
+///
+/// The environment maintains the reaching definition of each local variable,
+/// including some synthetic locals such as [TypeVariableLocal].
+///
+/// Internally, IR builders also maintains a [JumpCollector] stack and tracks
+/// which variables are currently boxed or held in a mutable local variable.
+class IrBuilder {
   final List<ir.Parameter> _parameters = <ir.Parameter>[];
 
-  IrBuilderSharedState state;
+  final IrBuilderSharedState state;
 
   /// A map from variable indexes to their values.
   ///
@@ -500,6 +501,36 @@
   /// side effects.
   Map<Local, ir.MutableVariable> mutableVariables;
 
+  ir.Expression _root = null;
+  ir.Expression _current = null;
+
+  GlobalProgramInformation get program => state.program;
+
+  IrBuilder(GlobalProgramInformation program,
+            BackendConstantEnvironment constants,
+            ExecutableElement currentElement)
+    : state = new IrBuilderSharedState(program, constants, currentElement),
+      environment = new Environment.empty(),
+      mutableVariables = <Local, ir.MutableVariable>{};
+
+  IrBuilder._internal(this.state, this.environment, this.mutableVariables);
+
+  /// Construct a delimited visitor for visiting a subtree.
+  ///
+  /// Build a subterm that is not (yet) connected to the CPS term.  The
+  /// delimited visitor has its own has its own context for building an IR
+  /// expression, so the built expression is not plugged into the parent's
+  /// context.  It has its own compile-time environment mapping local
+  /// variables to their values.  If an optional environment argument is
+  /// supplied, it is used as the builder's initial environment.  Otherwise
+  /// the environment is initially a copy of the parent builder's environment.
+  IrBuilder makeDelimitedBuilder([Environment env = null]) {
+    return new IrBuilder._internal(
+        state,
+        env != null ? env : new Environment.from(environment),
+        mutableVariables);
+  }
+
   /// True if [local] should currently be accessed from a [ir.MutableVariable].
   bool isInMutableVariable(Local local) {
     return mutableVariables.containsKey(local);
@@ -523,57 +554,6 @@
     return mutableVariables[local];
   }
 
-  // The IR builder maintains a context, which is an expression with a hole in
-  // it.  The hole represents the focus where new expressions can be added.
-  // The context is implemented by 'root' which is the root of the expression
-  // and 'current' which is the expression that immediately contains the hole.
-  // Not all expressions have a hole (e.g., invocations, which always occur in
-  // tail position, do not have a hole).  Expressions with a hole have a plug
-  // method.
-  //
-  // Conceptually, visiting a statement takes a context as input and returns
-  // either a new context or else an expression without a hole if all
-  // control-flow paths through the statement have exited.  An expression
-  // without a hole is represented by a (root, current) pair where root is the
-  // expression and current is null.
-  //
-  // Conceptually again, visiting an expression takes a context as input and
-  // returns either a pair of a new context and a definition denoting
-  // the expression's value, or else an expression without a hole if all
-  // control-flow paths through the expression have exited.
-  //
-  // We do not pass contexts as arguments or return them.  Rather we use the
-  // current context (root, current) as the visitor state and mutate current.
-  // Visiting a statement returns null; visiting an expression returns the
-  // primitive denoting its value.
-
-  ir.Expression _root = null;
-  ir.Expression _current = null;
-
-  /// Initialize a new top-level IR builder.
-  void _init(BackendConstantEnvironment constants,
-             ExecutableElement currentElement) {
-    state = new IrBuilderSharedState(constants, currentElement);
-    environment = new Environment.empty();
-    mutableVariables = <Local, ir.MutableVariable>{};
-  }
-
-  /// Construct a delimited visitor for visiting a subtree.
-  ///
-  /// Build a subterm that is not (yet) connected to the CPS term.  The
-  /// delimited visitor has its own has its own context for building an IR
-  /// expression, so the built expression is not plugged into the parent's
-  /// context.  It has its own compile-time environment mapping local
-  /// variables to their values.  If an optional environment argument is
-  /// supplied, it is used as the builder's initial environment.  Otherwise
-  /// the environment is initially a copy of the parent builder's environment.
-  IrBuilder makeDelimitedBuilder([Environment env = null]) {
-    return _makeInstance()
-        ..state = state
-        ..environment = env != null ? env : new Environment.from(environment)
-        ..mutableVariables = mutableVariables;
-  }
-
   bool get isOpen => _root == null || _current != null;
 
   List<ir.Primitive> buildFunctionHeader(Iterable<Local> parameters,
@@ -587,20 +567,13 @@
   }
 
   /// Creates a parameter for [local] and adds it to the current environment.
-  ir.Parameter createLocalParameter(Local local) {
+  ir.Parameter _createLocalParameter(Local local) {
     ir.Parameter parameter = new ir.Parameter(local);
     _parameters.add(parameter);
     environment.extend(local, parameter);
     return parameter;
   }
 
-  /// Adds the constant [variableElement] to the environment with [value] as its
-  /// constant value.
-  void declareLocalConstant(LocalVariableElement variableElement,
-                            ConstantExpression value) {
-    state.localConstants.add(new ConstDeclaration(variableElement, value));
-  }
-
   /// Plug an expression into the 'hole' in the context being accumulated.  The
   /// empty context (just a hole) is represented by root (and current) being
   /// null.  Since the hole in the current context is filled by this function,
@@ -653,72 +626,61 @@
 
   ir.Primitive _buildInvokeDynamic(ir.Primitive receiver,
                                    Selector selector,
+                                   TypeMask mask,
                                    List<ir.Primitive> arguments,
                                    {SourceInformation sourceInformation}) {
     assert(isOpen);
     return _continueWithExpression(
-        (k) => new ir.InvokeMethod(receiver, selector, arguments, k,
+        (k) => new ir.InvokeMethod(receiver, selector, mask, arguments, k,
             sourceInformation: sourceInformation));
   }
 
   ir.Primitive _buildInvokeCall(ir.Primitive target,
                                 CallStructure callStructure,
+                                TypeMask mask,
                                 List<ir.Definition> arguments,
                                 {SourceInformation sourceInformation}) {
     Selector selector = callStructure.callSelector;
-    return _buildInvokeDynamic(target, selector, arguments,
+    return _buildInvokeDynamic(target, selector, mask, arguments,
         sourceInformation: sourceInformation);
   }
 
 
-  /// Create a [ir.Constant] from [constant] and add it to the CPS term.
-  // TODO(johnniwinther): Remove [value] when [ConstantValue] can be computed
-  // directly from [constant].
-  ir.Constant buildConstant(ConstantExpression constant, ConstantValue value) {
+  /// Create a [ir.Constant] from [value] and add it to the CPS term.
+  ir.Constant buildConstant(ConstantValue value) {
     assert(isOpen);
-    return addPrimitive(new ir.Constant(constant, value));
+    return addPrimitive(new ir.Constant(value));
   }
 
   /// Create an integer constant and add it to the CPS term.
   ir.Constant buildIntegerConstant(int value) {
-    return buildConstant(
-        new IntConstantExpression(value),
-        state.constantSystem.createInt(value));
+    return buildConstant(state.constantSystem.createInt(value));
   }
 
   /// Create a double constant and add it to the CPS term.
   ir.Constant buildDoubleConstant(double value) {
-    return buildConstant(
-        new DoubleConstantExpression(value),
-        state.constantSystem.createDouble(value));
+    return buildConstant(state.constantSystem.createDouble(value));
   }
 
   /// Create a Boolean constant and add it to the CPS term.
   ir.Constant buildBooleanConstant(bool value) {
-    return buildConstant(
-        new BoolConstantExpression(value),
-        state.constantSystem.createBool(value));
+    return buildConstant(state.constantSystem.createBool(value));
   }
 
   /// Create a null constant and add it to the CPS term.
   ir.Constant buildNullConstant() {
-    return buildConstant(
-        new NullConstantExpression(),
-        state.constantSystem.createNull());
+    return buildConstant(state.constantSystem.createNull());
   }
 
   /// Create a string constant and add it to the CPS term.
   ir.Constant buildStringConstant(String value) {
     return buildConstant(
-        new StringConstantExpression(value),
         state.constantSystem.createString(new ast.DartString.literal(value)));
   }
 
   /// Create a string constant and add it to the CPS term.
   ir.Constant buildDartStringConstant(ast.DartString value) {
-    return buildConstant(
-        new StringConstantExpression(value.slowToString()),
-        state.constantSystem.createString(value));
+    return buildConstant(state.constantSystem.createString(value));
   }
 
   /// Creates a non-constant list literal of the provided [type] and with the
@@ -768,20 +730,10 @@
     // expressions cannot introduce variable bindings.
     assert(environment.length == thenBuilder.environment.length);
     assert(environment.length == elseBuilder.environment.length);
-    // Extend the join-point environment with a placeholder for the value of
-    // the expression.  Optimistically assume that the value is the value of
-    // the first subexpression.  This value might noe even be in scope at the
-    // join-point because it's bound in the first subexpression.  However, if
-    // that is the case, it will necessarily differ from the value of the
-    // other subexpression and cause the introduction of a join-point
-    // continuation parameter.  If the two values do happen to be the same,
-    // this will avoid inserting a useless continuation parameter.
-    environment.extend(null, thenValue);
-    thenBuilder.environment.extend(null, thenValue);
-    elseBuilder.environment.extend(null, elseValue);
-    JumpCollector join = new ForwardJumpCollector(environment);
-    thenBuilder.jumpTo(join);
-    elseBuilder.jumpTo(join);
+    JumpCollector join =
+        new ForwardJumpCollector(environment, hasExtraArgument: true);
+    thenBuilder.jumpTo(join, thenValue);
+    elseBuilder.jumpTo(join, elseValue);
 
     // Build the term
     //   let cont join(x, ..., result) = [] in
@@ -800,10 +752,7 @@
                               thenContinuation,
                               elseContinuation))));
     environment = join.environment;
-    environment.discard(1);
-    return (thenValue == elseValue)
-        ? thenValue
-        : join.continuation.parameters.last;
+    return environment.discard(1);
   }
 
   /**
@@ -848,15 +797,6 @@
     return _buildInvokeSuper(method, selector, arguments);
   }
 
-  /// Create a read access of the [field] on the super class.
-  ir.Primitive buildSuperFieldGet(FieldElement field) {
-    // TODO(johnniwinther): This should have its own ir node.
-    return _buildInvokeSuper(
-        field,
-        new Selector.getter(field.name, field.library),
-        const <ir.Primitive>[]);
-  }
-
   /// Create a read access of the [method] on the super class, i.e. a
   /// closurization of [method].
   ir.Primitive buildSuperMethodGet(MethodElement method) {
@@ -876,16 +816,6 @@
         const <ir.Primitive>[]);
   }
 
-  /// Create a write access to the [field] on the super class of with [value].
-  ir.Primitive buildSuperFieldSet(Element field, ir.Primitive value) {
-    // TODO(johnniwinther): This should have its own ir node.
-    _buildInvokeSuper(
-        field,
-        new Selector.setter(field.name, field.library),
-        <ir.Primitive>[value]);
-    return value;
-  }
-
   /// Create an setter invocation of the [setter] on the super class with
   /// [value].
   ir.Primitive buildSuperSetterSet(MethodElement setter,
@@ -921,52 +851,43 @@
   /// defined by [arguments].
   ir.Primitive buildDynamicInvocation(ir.Primitive receiver,
                                       Selector selector,
+                                      TypeMask mask,
                                       List<ir.Primitive> arguments) {
-    return _buildInvokeDynamic(receiver, selector, arguments);
+    return _buildInvokeDynamic(receiver, selector, mask, arguments);
   }
 
-  /// Create an if-null expression. This is equivalent to a conditional
-  /// expression whose result is either [value] if [value] is not null, or
-  /// `right` if [value] is null. Only when [value] is null, [buildRight] is
-  /// evaluated to produce the `right` value.
-  ir.Primitive buildIfNull(ir.Primitive value,
-                           ir.Primitive buildRight(IrBuilder builder));
-
-  /// Create a conditional send. This is equivalent to a conditional expression
-  /// that checks if [receiver] is null, if so, it returns null, otherwise it
-  /// evaluates the [buildSend] expression.
-  ir.Primitive buildIfNotNullSend(ir.Primitive receiver,
-                                  ir.Primitive buildSend(IrBuilder builder));
-
   /// Create a dynamic getter invocation on [receiver] where the getter name is
   /// defined by [selector].
-  ir.Primitive buildDynamicGet(ir.Primitive receiver, Selector selector) {
+  ir.Primitive buildDynamicGet(ir.Primitive receiver,
+                               Selector selector,
+                               TypeMask mask) {
     assert(selector.isGetter);
-    return _buildInvokeDynamic(receiver, selector, const <ir.Primitive>[]);
+    return _buildInvokeDynamic(
+        receiver, selector, mask, const <ir.Primitive>[]);
   }
 
   /// Create a dynamic setter invocation on [receiver] where the setter name and
   /// argument are defined by [selector] and [value], respectively.
   ir.Primitive buildDynamicSet(ir.Primitive receiver,
                                Selector selector,
+                               TypeMask mask,
                                ir.Primitive value) {
     assert(selector.isSetter);
-    _buildInvokeDynamic(receiver, selector, <ir.Primitive>[value]);
+    _buildInvokeDynamic(receiver, selector, mask, <ir.Primitive>[value]);
     return value;
   }
 
   /// Create a dynamic index set invocation on [receiver] with the provided
   /// [index] and [value].
   ir.Primitive  buildDynamicIndexSet(ir.Primitive receiver,
+                                     TypeMask mask,
                                      ir.Primitive index,
                                      ir.Primitive value) {
     _buildInvokeDynamic(
-        receiver, new Selector.indexSet(), <ir.Primitive>[index, value]);
+        receiver, new Selector.indexSet(), mask, <ir.Primitive>[index, value]);
     return value;
   }
 
-  ir.Primitive _buildLocalGet(LocalElement element);
-
   /// Create a read access of the [local] variable or parameter.
   ir.Primitive buildLocalVariableGet(LocalElement local) {
     // TODO(johnniwinther): Separate function access from variable access.
@@ -980,10 +901,6 @@
     return _buildLocalGet(function);
   }
 
-  /// Create a write access to the [local] variable or parameter with the
-  /// provided [value].
-  ir.Primitive buildLocalVariableSet(LocalElement local, ir.Primitive value);
-
   /// Create an invocation of the the [local] variable or parameter where
   /// argument structure is defined by [callStructure] and the argument values
   /// are defined by [arguments].
@@ -1078,29 +995,26 @@
     return _buildInvokeStatic(element, selector, arguments, null);
   }
 
-  /// Create a constructor invocation of [element] on [type] where the
-  /// constructor name and argument structure are defined by [callStructure] and
-  /// the argument values are defined by [arguments].
-  ir.Primitive buildConstructorInvocation(FunctionElement element,
-                                          CallStructure callStructure,
-                                          DartType type,
-                                          List<ir.Primitive> arguments);
-
-  /// Create a string concatenation of the [arguments].
+  /// Concatenate string values.
+  ///
+  /// The arguments must be strings; usually a call to [buildStringify] is
+  /// needed to ensure the proper conversion takes places.
   ir.Primitive buildStringConcatenation(List<ir.Primitive> arguments) {
     assert(isOpen);
-    return _continueWithExpression(
-        (k) => new ir.ConcatenateStrings(arguments, k));
+    return addPrimitive(new ir.ApplyBuiltinOperator(
+        ir.BuiltinOperator.StringConcatenate,
+        arguments));
   }
 
   /// Create an invocation of the `call` method of [functionExpression], where
   /// the structure of arguments are given by [callStructure].
+  // TODO(johnniwinther): This should take a [TypeMask].
   ir.Primitive buildCallInvocation(
       ir.Primitive functionExpression,
       CallStructure callStructure,
       List<ir.Definition> arguments,
       {SourceInformation sourceInformation}) {
-    return _buildInvokeCall(functionExpression, callStructure, arguments,
+    return _buildInvokeCall(functionExpression, callStructure, null, arguments,
         sourceInformation: sourceInformation);
   }
 
@@ -1181,8 +1095,8 @@
     }
   }
 
-  void jumpTo(JumpCollector collector) {
-    collector.addJump(this);
+  void jumpTo(JumpCollector collector, [ir.Primitive value]) {
+    collector.addJump(this, value);
   }
 
   void addRecursiveContinuation(BackwardJumpCollector collector) {
@@ -1351,6 +1265,10 @@
                    SubbuildFunction buildVariableDeclaration,
                    Element variableElement,
                    Selector variableSelector,
+                   TypeMask variableMask,
+                   TypeMask currentMask,
+                   TypeMask iteratorMask,
+                   TypeMask moveNextMask,
                    SubbuildFunction buildBody,
                    JumpTarget target,
                    ClosureScope closureScope}) {
@@ -1378,6 +1296,7 @@
     add(new ir.LetCont(iteratorInvoked,
         new ir.InvokeMethod(expressionReceiver,
             new Selector.getter("iterator", null),
+            iteratorMask,
             emptyArguments,
             iteratorInvoked)));
 
@@ -1394,6 +1313,7 @@
     add(new ir.LetCont(moveNextInvoked,
         new ir.InvokeMethod(iterator,
             new Selector.call("moveNext", null, 0),
+            moveNextMask,
             emptyArguments,
             moveNextInvoked)));
 
@@ -1413,7 +1333,10 @@
     ir.Parameter currentValue = new ir.Parameter(null);
     ir.Continuation currentInvoked = new ir.Continuation([currentValue]);
     bodyBuilder.add(new ir.LetCont(currentInvoked,
-        new ir.InvokeMethod(iterator, new Selector.getter("current", null),
+        new ir.InvokeMethod(
+            iterator,
+            new Selector.getter("current", null),
+            currentMask,
             emptyArguments, currentInvoked)));
     // TODO(sra): Does this cover all cases? The general setter case include
     // super.
@@ -1433,7 +1356,8 @@
     } else {
       ir.Primitive receiver = bodyBuilder.buildThis();
       assert(receiver != null);
-      bodyBuilder.buildDynamicSet(receiver, variableSelector, currentValue);
+      bodyBuilder.buildDynamicSet(
+          receiver, variableSelector, variableMask, currentValue);
     }
 
     // Translate the body in the hole in the delimited term above, and add
@@ -1644,28 +1568,158 @@
     environment = breakCollector.environment;
   }
 
-  /// Creates a try-statement.
+  void buildSimpleSwitch(JumpTarget target,
+                         ir.Primitive value,
+                         List<SwitchCaseInfo> cases,
+                         SwitchCaseInfo defaultCase,
+                         Element error,
+                         SourceInformation sourceInformation) {
+    assert(isOpen);
+    JumpCollector join = new ForwardJumpCollector(environment, target: target);
+
+    IrBuilder casesBuilder = makeDelimitedBuilder();
+    casesBuilder.state.breakCollectors.add(join);
+    for (SwitchCaseInfo caseInfo in cases) {
+      buildConditionsFrom(int index) => (IrBuilder builder) {
+        ir.Primitive comparison = builder.buildIdentical(
+            value, caseInfo.constants[index]);
+        return (index == caseInfo.constants.length - 1)
+            ? comparison
+            : builder.buildLogicalOperator(
+                comparison, buildConditionsFrom(index + 1), isLazyOr: true);
+      };
+
+      ir.Primitive condition = buildConditionsFrom(0)(casesBuilder);
+      IrBuilder thenBuilder = makeDelimitedBuilder();
+      caseInfo.buildBody(thenBuilder);
+      if (thenBuilder.isOpen) {
+        // It is a runtime error to reach the end of a switch case, unless
+        // it is the last case.
+        if (caseInfo == cases.last && defaultCase == null) {
+          thenBuilder.jumpTo(join);
+        } else {
+          ir.Primitive exception = thenBuilder._buildInvokeStatic(
+              error,
+              new Selector.fromElement(error),
+              <ir.Primitive>[],
+              sourceInformation);
+          thenBuilder.buildThrow(exception);
+        }
+      }
+
+      ir.Continuation thenContinuation = new ir.Continuation([]);
+      thenContinuation.body = thenBuilder._root;
+      ir.Continuation elseContinuation = new ir.Continuation([]);
+      // A LetCont.many term has a hole as the body of the first listed
+      // continuation, to be plugged by the translation.  Therefore put the
+      // else continuation first.
+      casesBuilder.add(
+          new ir.LetCont.many(<ir.Continuation>[elseContinuation,
+                                                thenContinuation],
+              new ir.Branch(new ir.IsTrue(condition),
+                            thenContinuation,
+                            elseContinuation)));
+    }
+
+    if (defaultCase != null) {
+      defaultCase.buildBody(casesBuilder);
+    }
+    if (casesBuilder.isOpen) casesBuilder.jumpTo(join);
+
+    casesBuilder.state.breakCollectors.removeLast();
+
+    if (!join.isEmpty) {
+      add(new ir.LetCont(join.continuation, casesBuilder._root));
+      environment = join.environment;
+    } else if (casesBuilder._root != null) {
+      add(casesBuilder._root);
+      _current = casesBuilder._current;
+      environment = casesBuilder.environment;
+    } else {
+      // The translation of the cases did not emit any code.
+    }
+  }
+
+  /// Utility function to translate try/catch into the IR.
   ///
-  /// [tryInfo] provides information on local variables declared and boxed
-  /// within this try statement.
+  /// The translation treats try/finally and try/catch/finally as if they
+  /// were macro-expanded into try/catch.  This utility function generates
+  /// that try/catch.  The function is parameterized over a list of variables
+  /// that should be boxed on entry to the try, and over functions to emit
+  /// code for entering the try, building the try body, leaving the try body,
+  /// building the catch body, and leaving the entire try/catch.
+  ///
+  /// Please see the function's implementation for where these functions are
+  /// called.
+  void _helpBuildTryCatch(TryStatementInfo variables,
+      void enterTry(IrBuilder builder),
+      SubbuildFunction buildTryBlock,
+      void leaveTry(IrBuilder builder),
+      List<ir.Parameter> buildCatch(IrBuilder builder, JumpCollector join),
+      void leaveTryCatch(IrBuilder builder, JumpCollector join,
+          ir.Expression body)) {
+    JumpCollector join = new ForwardJumpCollector(environment);
+    IrBuilder tryCatchBuilder = makeDelimitedBuilder();
+
+    // Variables treated as mutable in a try are not mutable outside of it.
+    // Work with a copy of the outer builder's mutable variables.
+    tryCatchBuilder.mutableVariables =
+        new Map<Local, ir.MutableVariable>.from(mutableVariables);
+    for (LocalVariableElement variable in variables.boxedOnEntry) {
+      assert(!tryCatchBuilder.isInMutableVariable(variable));
+      ir.Primitive value = tryCatchBuilder.buildLocalVariableGet(variable);
+      tryCatchBuilder.makeMutableVariable(variable);
+      tryCatchBuilder.declareLocalVariable(variable, initialValue: value);
+    }
+
+    IrBuilder tryBuilder = tryCatchBuilder.makeDelimitedBuilder();
+    enterTry(tryBuilder);
+    buildTryBlock(tryBuilder);
+    if (tryBuilder.isOpen) {
+      join.enterTry(variables.boxedOnEntry);
+      tryBuilder.jumpTo(join);
+      join.leaveTry();
+    }
+    leaveTry(tryBuilder);
+
+    IrBuilder catchBuilder = tryCatchBuilder.makeDelimitedBuilder();
+    for (LocalVariableElement variable in variables.boxedOnEntry) {
+      assert(catchBuilder.isInMutableVariable(variable));
+      ir.Primitive value = catchBuilder.buildLocalVariableGet(variable);
+      // After this point, the variables that were boxed on entry to the try
+      // are no longer treated as mutable.
+      catchBuilder.removeMutableVariable(variable);
+      catchBuilder.environment.update(variable, value);
+    }
+
+    List<ir.Parameter> catchParameters = buildCatch(catchBuilder, join);
+    ir.Continuation catchContinuation = new ir.Continuation(catchParameters);
+    catchContinuation.body = catchBuilder._root;
+    tryCatchBuilder.add(
+        new ir.LetHandler(catchContinuation, tryBuilder._root));
+
+    leaveTryCatch(this, join, tryCatchBuilder._root);
+  }
+
+  /// Translates a try/catch.
+  ///
+  /// [variables] provides information on local variables declared and boxed
+  /// within the try body.
   /// [buildTryBlock] builds the try block.
   /// [catchClauseInfos] provides access to the catch type, exception variable,
   /// and stack trace variable, and a function for building the catch block.
-  void buildTry(
-      {TryStatementInfo tryStatementInfo,
-       SubbuildFunction buildTryBlock,
-       List<CatchClauseInfo> catchClauseInfos: const <CatchClauseInfo>[],
-       ClosureClassMap closureClassMap}) {
+  void buildTryCatch(TryStatementInfo variables,
+                     SubbuildFunction buildTryBlock,
+                     List<CatchClauseInfo> catchClauseInfos) {
     assert(isOpen);
-
     // Catch handlers are in scope for their body.  The CPS translation of
-    // [[try tryBlock catch (e) catchBlock; successor]] is:
+    // [[try tryBlock catch (ex, st) catchBlock; successor]] is:
     //
     // let cont join(v0, v1, ...) = [[successor]] in
     //   let mutable m0 = x0 in
     //     let mutable m1 = x1 in
     //       ...
-    //       let handler catch_(e) =
+    //       let handler catch_(ex, st) =
     //         let prim p0 = GetMutable(m0) in
     //           let prim p1 = GetMutable(m1) in
     //             ...
@@ -1687,125 +1741,219 @@
     // scope of the handler.  The mutable bindings are dereferenced at the end
     // of the try block and at the beginning of the catch block, so the
     // variables are unboxed in the catch block and at the join point.
-    JumpCollector join = new ForwardJumpCollector(environment);
-    IrBuilder tryCatchBuilder = makeDelimitedBuilder();
 
-    // Variables treated as mutable in a try are not mutable outside of it.
-    // Work with a copy of the outer builder's mutable variables.
-    tryCatchBuilder.mutableVariables =
-        new Map<Local, ir.MutableVariable>.from(mutableVariables);
-    for (LocalVariableElement variable in tryStatementInfo.boxedOnEntry) {
-      assert(!tryCatchBuilder.isInMutableVariable(variable));
-      ir.Primitive value = tryCatchBuilder.buildLocalVariableGet(variable);
-      tryCatchBuilder.makeMutableVariable(variable);
-      tryCatchBuilder.declareLocalVariable(variable, initialValue: value);
-    }
-
-    IrBuilder tryBuilder = tryCatchBuilder.makeDelimitedBuilder();
-
-    void interceptJumps(JumpCollector collector) {
-      collector.enterTry(tryStatementInfo.boxedOnEntry);
-    }
-    void restoreJumps(JumpCollector collector) {
-      collector.leaveTry();
-    }
-    tryBuilder.state.breakCollectors.forEach(interceptJumps);
-    tryBuilder.state.continueCollectors.forEach(interceptJumps);
-    buildTryBlock(tryBuilder);
-    if (tryBuilder.isOpen) {
-      interceptJumps(join);
-      tryBuilder.jumpTo(join);
-      restoreJumps(join);
-    }
-    tryBuilder.state.breakCollectors.forEach(restoreJumps);
-    tryBuilder.state.continueCollectors.forEach(restoreJumps);
-
-    IrBuilder catchBuilder = tryCatchBuilder.makeDelimitedBuilder();
-    for (LocalVariableElement variable in tryStatementInfo.boxedOnEntry) {
-      assert(catchBuilder.isInMutableVariable(variable));
-      ir.Primitive value = catchBuilder.buildLocalVariableGet(variable);
-      // After this point, the variables that were boxed on entry to the try
-      // are no longer treated as mutable.
-      catchBuilder.removeMutableVariable(variable);
-      catchBuilder.environment.update(variable, value);
-    }
-
-    // Handlers are always translated as having both exception and stack trace
-    // parameters.  Multiple clauses do not have to use the same names for
-    // them.  Choose the first of each as the name hint for the respective
-    // handler parameter.
-    ir.Parameter exceptionParameter =
-        new ir.Parameter(catchClauseInfos.first.exceptionVariable);
-    LocalVariableElement traceVariable;
-    CatchClauseInfo catchAll;
-    for (int i = 0; i < catchClauseInfos.length; ++i) {
-      CatchClauseInfo info = catchClauseInfos[i];
-      if (info.type == null) {
-        catchAll = info;
-        catchClauseInfos.length = i;
-        break;
+    void enterTry(IrBuilder builder) {
+      // On entry to try of try/catch, update the builder's state to reflect the
+      // variables that have been boxed.
+      void interceptJump(JumpCollector collector) {
+        collector.enterTry(variables.boxedOnEntry);
       }
-      if (traceVariable == null) {
-        traceVariable = info.stackTraceVariable;
-      }
-    }
-    ir.Parameter traceParameter = new ir.Parameter(traceVariable);
-    // Expand multiple catch clauses into an explicit if/then/else.  Iterate
-    // them in reverse so the current block becomes the next else block.
-    ir.Expression catchBody;
-    if (catchAll == null) {
-      catchBody = new ir.Rethrow();
-    } else {
-      IrBuilder clauseBuilder = catchBuilder.makeDelimitedBuilder();
-      clauseBuilder.declareLocalVariable(catchAll.exceptionVariable,
-                                         initialValue: exceptionParameter);
-      if (catchAll.stackTraceVariable != null) {
-        clauseBuilder.declareLocalVariable(catchAll.stackTraceVariable,
-                                           initialValue: traceParameter);
-      }
-      catchAll.buildCatchBlock(clauseBuilder);
-      if (clauseBuilder.isOpen) clauseBuilder.jumpTo(join);
-      catchBody = clauseBuilder._root;
-    }
-    for (CatchClauseInfo clause in catchClauseInfos.reversed) {
-      IrBuilder clauseBuilder = catchBuilder.makeDelimitedBuilder();
-      clauseBuilder.declareLocalVariable(clause.exceptionVariable,
-                                         initialValue: exceptionParameter);
-      if (clause.stackTraceVariable != null) {
-        clauseBuilder.declareLocalVariable(clause.stackTraceVariable,
-                                           initialValue: traceParameter);
-      }
-      clause.buildCatchBlock(clauseBuilder);
-      if (clauseBuilder.isOpen) clauseBuilder.jumpTo(join);
-      ir.Continuation thenContinuation = new ir.Continuation([]);
-      thenContinuation.body = clauseBuilder._root;
-      ir.Continuation elseContinuation = new ir.Continuation([]);
-      elseContinuation.body = catchBody;
-
-      // Build the type test guarding this clause. We can share the environment
-      // with the nested builder because this part cannot mutate it.
-      IrBuilder checkBuilder = catchBuilder.makeDelimitedBuilder(environment);
-      ir.Primitive typeMatches =
-          checkBuilder.buildTypeOperator(exceptionParameter,
-                                         clause.type,
-                                         isTypeTest: true);
-      checkBuilder.add(new ir.LetCont.many([thenContinuation, elseContinuation],
-                           new ir.Branch(new ir.IsTrue(typeMatches),
-                                         thenContinuation,
-                                         elseContinuation)));
-      catchBody = checkBuilder._root;
+      builder.state.breakCollectors.forEach(interceptJump);
+      builder.state.continueCollectors.forEach(interceptJump);
     }
 
-    List<ir.Parameter> catchParameters =
-        <ir.Parameter>[exceptionParameter, traceParameter];
-    ir.Continuation catchContinuation = new ir.Continuation(catchParameters);
-    catchBuilder.add(catchBody);
-    catchContinuation.body = catchBuilder._root;
+    void leaveTry(IrBuilder builder) {
+      // On exit from try of try/catch, update the builder's state to reflect
+      // the variables that are no longer boxed.
+      void restoreJump(JumpCollector collector) {
+        collector.leaveTry();
+      }
+      builder.state.breakCollectors.forEach(restoreJump);
+      builder.state.continueCollectors.forEach(restoreJump);
+    }
 
-    tryCatchBuilder.add(
-        new ir.LetHandler(catchContinuation, tryBuilder._root));
-    add(new ir.LetCont(join.continuation, tryCatchBuilder._root));
-    environment = join.environment;
+    List<ir.Parameter> buildCatch(IrBuilder builder,
+                                  JumpCollector join) {
+      // Translate the catch clauses.  Multiple clauses are translated as if
+      // they were explicitly cascaded if/else type tests.
+
+      // Handlers are always translated as having both exception and stack trace
+      // parameters.  Multiple clauses do not have to use the same names for
+      // them.  Choose the first of each as the name hint for the respective
+      // handler parameter.
+      ir.Parameter exceptionParameter =
+          new ir.Parameter(catchClauseInfos.first.exceptionVariable);
+      LocalVariableElement traceVariable;
+      CatchClauseInfo catchAll;
+      for (int i = 0; i < catchClauseInfos.length; ++i) {
+        CatchClauseInfo info = catchClauseInfos[i];
+        if (info.type == null) {
+          catchAll = info;
+          catchClauseInfos.length = i;
+          break;
+        }
+        if (traceVariable == null) {
+          traceVariable = info.stackTraceVariable;
+        }
+      }
+      ir.Parameter traceParameter = new ir.Parameter(traceVariable);
+
+      ir.Expression buildCatchClause(CatchClauseInfo clause) {
+        IrBuilder clauseBuilder = builder.makeDelimitedBuilder();
+        clauseBuilder.declareLocalVariable(clause.exceptionVariable,
+            initialValue: exceptionParameter);
+        if (clause.stackTraceVariable != null) {
+          clauseBuilder.declareLocalVariable(clause.stackTraceVariable,
+              initialValue: traceParameter);
+        }
+        clause.buildCatchBlock(clauseBuilder);
+        if (clauseBuilder.isOpen) clauseBuilder.jumpTo(join);
+        return clauseBuilder._root;
+      }
+
+      // Expand multiple catch clauses into an explicit if/then/else.  Iterate
+      // them in reverse so the current block becomes the next else block.
+      ir.Expression catchBody = (catchAll == null)
+          ? new ir.Rethrow()
+          : buildCatchClause(catchAll);
+      for (CatchClauseInfo clause in catchClauseInfos.reversed) {
+        ir.Continuation thenContinuation = new ir.Continuation([]);
+        ir.Continuation elseContinuation = new ir.Continuation([]);
+        thenContinuation.body = buildCatchClause(clause);
+        elseContinuation.body = catchBody;
+
+        // Build the type test guarding this clause. We can share the
+        // environment with the nested builder because this part cannot mutate
+        // it.
+        IrBuilder checkBuilder = builder.makeDelimitedBuilder(environment);
+        ir.Primitive typeMatches =
+            checkBuilder.buildTypeOperator(exceptionParameter,
+                clause.type,
+                isTypeTest: true);
+        checkBuilder.add(new ir.LetCont.many([thenContinuation,
+                                              elseContinuation],
+                new ir.Branch(new ir.IsTrue(typeMatches),
+                    thenContinuation,
+                    elseContinuation)));
+        catchBody = checkBuilder._root;
+      }
+      builder.add(catchBody);
+
+      return <ir.Parameter>[exceptionParameter, traceParameter];
+    }
+
+    void leaveTryCatch(IrBuilder builder, JumpCollector join,
+                       ir.Expression body) {
+      // Add the binding for the join-point continuation and continue the
+      // translation in its body.
+      builder.add(new ir.LetCont(join.continuation, body));
+      builder.environment = join.environment;
+    }
+
+    _helpBuildTryCatch(variables, enterTry, buildTryBlock, leaveTry,
+        buildCatch, leaveTryCatch);
+  }
+
+  /// Translates a try/finally.
+  ///
+  /// [variables] provides information on local variables declared and boxed
+  /// within the try body.
+  /// [buildTryBlock] builds the try block.
+  /// [buildFinallyBlock] builds the finally block.
+  void buildTryFinally(TryStatementInfo variables,
+                       SubbuildFunction buildTryBlock,
+                       SubbuildFunction buildFinallyBlock) {
+    assert(isOpen);
+    // Try/finally is implemented in terms of try/catch and by duplicating the
+    // code for finally at all exits.  The encoding is:
+    //
+    // try tryBlock finally finallyBlock
+    // ==>
+    // try tryBlock catch (ex, st) { finallyBlock; rethrow } finallyBlock
+    //
+    // Where in tryBlock, all of the break, continue, and return exits are
+    // translated as jumps to continuations (bound outside the catch handler)
+    // that include the finally code followed by a break, continue, or
+    // return respectively.
+
+    List<JumpCollector> savedBreaks, newBreaks, savedContinues, newContinues;
+    JumpCollector savedReturn, newReturn;
+    void enterTry(IrBuilder builder) {
+      // On entry to the try of try/finally, update the builder's state to
+      // relfect the variables that have been boxed.  Then intercept all break,
+      // continue, and return jumps out of the try so that they can go to
+      // continuations that include the finally code.
+      JumpCollector interceptJump(JumpCollector collector) {
+        JumpCollector result =
+            new ForwardJumpCollector(environment, target: collector.target);
+        result.enterTry(variables.boxedOnEntry);
+        return result;
+      }
+      savedBreaks = builder.state.breakCollectors;
+      savedContinues = builder.state.continueCollectors;
+      savedReturn = builder.state.returnCollector;
+
+      builder.state.breakCollectors = newBreaks =
+          savedBreaks.map(interceptJump).toList();
+      builder.state.continueCollectors = newContinues =
+          savedContinues.map(interceptJump).toList();
+      builder.state.returnCollector = newReturn =
+          new ForwardJumpCollector(environment, hasExtraArgument: true)
+              ..enterTry(variables.boxedOnEntry);
+    }
+
+    void leaveTry(IrBuilder builder) {
+      // On exit from the try of try/finally, update the builder's state to
+      // reflect the variables that are no longer boxed and restore the
+      // original, unintercepted break, continue, and return targets.
+      void restoreJump(JumpCollector collector) {
+        collector.leaveTry();
+      }
+      newBreaks.forEach(restoreJump);
+      newContinues.forEach(restoreJump);
+      newReturn.leaveTry();
+      builder.state.breakCollectors = savedBreaks;
+      builder.state.continueCollectors = savedContinues;
+      builder.state.returnCollector = savedReturn;
+    }
+
+    List<ir.Parameter> buildCatch(IrBuilder builder,
+                                  JumpCollector join) {
+      // The catch block of the try/catch used for try/finally is the finally
+      // code followed by a rethrow.
+      buildFinallyBlock(builder);
+      if (builder.isOpen) {
+        builder.add(new ir.Rethrow());
+        builder._current = null;
+      }
+      return <ir.Parameter>[new ir.Parameter(null), new ir.Parameter(null)];
+    }
+
+    void leaveTryCatch(IrBuilder builder, JumpCollector join,
+                       ir.Expression body) {
+      // Build a list of continuations for jumps from the try block and
+      // duplicate the finally code before jumping to the actual target.
+      List<ir.Continuation> exits = <ir.Continuation>[join.continuation];
+      void addJump(JumpCollector newCollector,
+                   JumpCollector originalCollector) {
+        if (newCollector.isEmpty) return;
+        IrBuilder builder = makeDelimitedBuilder(newCollector.environment);
+        buildFinallyBlock(builder);
+        if (builder.isOpen) builder.jumpTo(originalCollector);
+        newCollector.continuation.body = builder._root;
+        exits.add(newCollector.continuation);
+      }
+      for (int i = 0; i < newBreaks.length; ++i) {
+        addJump(newBreaks[i], savedBreaks[i]);
+      }
+      for (int i = 0; i < newContinues.length; ++i) {
+        addJump(newContinues[i], savedContinues[i]);
+      }
+      if (!newReturn.isEmpty) {
+        IrBuilder builder = makeDelimitedBuilder(newReturn.environment);
+        ir.Primitive value = builder.environment.discard(1);
+        buildFinallyBlock(builder);
+        if (builder.isOpen) builder.buildReturn(value);
+        newReturn.continuation.body = builder._root;
+        exits.add(newReturn.continuation);
+      }
+      builder.add(new ir.LetCont.many(exits, body));
+      builder.environment = join.environment;
+      buildFinallyBlock(builder);
+    }
+
+    _helpBuildTryCatch(variables, enterTry, buildTryBlock, leaveTry,
+        buildCatch, leaveTryCatch);
   }
 
   /// Create a return statement `return value;` or `return;` if [value] is
@@ -1819,8 +1967,15 @@
     if (value == null) {
       value = buildNullConstant();
     }
-    add(new ir.InvokeContinuation(state.returnContinuation, [value]));
-    _current = null;
+    if (state.returnCollector == null) {
+      add(new ir.InvokeContinuation(state.returnContinuation, [value]));
+      _current = null;
+    } else {
+      // Inside the try block of try/finally, all returns go to a join-point
+      // continuation that contains the finally code.  The return value is
+      // passed as an extra argument.
+      jumpTo(state.returnCollector, value);
+    }
   }
 
   /// Create a blocks of [statements] by applying [build] to all reachable
@@ -1925,9 +2080,7 @@
     ir.Continuation elseContinuation = new ir.Continuation([]);
 
     ir.Constant makeBoolConstant(bool value) {
-      return new ir.Constant(
-          new BoolConstantExpression(value),
-          state.constantSystem.createBool(value));
+      return new ir.Constant(state.constantSystem.createBool(value));
     }
 
     ir.Constant trueConstant = makeBoolConstant(true);
@@ -1979,24 +2132,19 @@
     ir.Constant rightTrue = rightTrueBuilder.buildBooleanConstant(true);
     ir.Constant rightFalse = rightFalseBuilder.buildBooleanConstant(false);
 
-    // Treat the result values as named values in the environment, so they
-    // will be treated as arguments to the join-point continuation.
+    // Result values are passed as continuation arguments, which are
+    // constructed based on environments.  These assertions are a sanity check.
     assert(environment.length == emptyBuilder.environment.length);
     assert(environment.length == rightTrueBuilder.environment.length);
     assert(environment.length == rightFalseBuilder.environment.length);
-    // Treat the value of the expression as a local variable so it will get
-    // a continuation parameter.
-    environment.extend(null, null);
-    emptyBuilder.environment.extend(null, leftBool);
-    rightTrueBuilder.environment.extend(null, rightTrue);
-    rightFalseBuilder.environment.extend(null, rightFalse);
 
     // Wire up two continuations for the left subexpression, two continuations
     // for the right subexpression, and a three-way join continuation.
-    JumpCollector join = new ForwardJumpCollector(environment);
-    emptyBuilder.jumpTo(join);
-    rightTrueBuilder.jumpTo(join);
-    rightFalseBuilder.jumpTo(join);
+    JumpCollector join =
+        new ForwardJumpCollector(environment, hasExtraArgument: true);
+    emptyBuilder.jumpTo(join, leftBool);
+    rightTrueBuilder.jumpTo(join, rightTrue);
+    rightFalseBuilder.jumpTo(join, rightFalse);
     ir.Continuation leftTrueContinuation = new ir.Continuation([]);
     ir.Continuation leftFalseContinuation = new ir.Continuation([]);
     ir.Continuation rightTrueContinuation = new ir.Continuation([]);
@@ -2028,56 +2176,18 @@
                               leftTrueContinuation,
                               leftFalseContinuation))));
     environment = join.environment;
-    environment.discard(1);
-    // There is always a join parameter for the result value, because it
-    // is different on at least two paths.
-    return join.continuation.parameters.last;
-  }
-}
-
-/// State shared between JsIrBuilders within the same function.
-///
-/// Note that this is not shared between builders of nested functions.
-class JsIrBuilderSharedState {
-  /// Maps boxed locals to their location. These locals are not part of
-  /// the environment.
-  final Map<Local, ClosureLocation> boxedVariables = {};
-
-  /// If non-null, this refers to the receiver (`this`) in the enclosing method.
-  ir.Primitive receiver;
-
-  /// `true` when we are currently building expressions inside the initializer
-  /// list of a constructor.
-  bool inInitializers = false;
-}
-
-/// JS-specific subclass of [IrBuilder].
-///
-/// Inner functions are represented by a [ClosureClassElement], and captured
-/// variables are boxed as necessary using [CreateBox], [GetField], [SetField].
-class JsIrBuilder extends IrBuilder {
-  final JsIrBuilderSharedState jsState;
-  final GlobalProgramInformation program;
-
-  IrBuilder _makeInstance() => new JsIrBuilder._blank(program, jsState);
-  JsIrBuilder._blank(this.program, this.jsState);
-
-  JsIrBuilder(this.program, BackendConstantEnvironment constants,
-      ExecutableElement currentElement)
-      : jsState = new JsIrBuilderSharedState() {
-    _init(constants, currentElement);
+    return environment.discard(1);
   }
 
-  void enterInitializers() {
-    assert(jsState.inInitializers == false);
-    jsState.inInitializers = true;
+  ir.Primitive buildIdentical(ir.Primitive x, ir.Primitive y) {
+    return addPrimitive(new ir.ApplyBuiltinOperator(
+        ir.BuiltinOperator.Identical, <ir.Primitive>[x, y]));
   }
 
-  void leaveInitializers() {
-    assert(jsState.inInitializers == true);
-    jsState.inInitializers = false;
-  }
-
+  /// Called when entering a nested function with free variables.
+  ///
+  /// The free variables must subsequently be accessible using [buildLocalGet]
+  /// and [buildLocalSet].
   void _enterClosureEnvironment(ClosureEnvironment env) {
     if (env == null) return;
 
@@ -2088,7 +2198,7 @@
     env.freeVariables.forEach((Local local, ClosureLocation location) {
       if (location.isBox) {
         // Boxed variables are loaded from their box on-demand.
-        jsState.boxedVariables[local] = location;
+        state.boxedVariables[local] = location;
       } else {
         // Unboxed variables are loaded from the function object immediately.
         // This includes BoxLocals which are themselves unboxed variables.
@@ -2100,7 +2210,7 @@
     // If the function captures a reference to the receiver from the
     // enclosing method, remember which primitive refers to the receiver object.
     if (env.thisLocal != null && env.freeVariables.containsKey(env.thisLocal)) {
-      jsState.receiver = environment.lookup(env.thisLocal);
+      state.enclosingThis = environment.lookup(env.thisLocal);
     }
 
     // If the function has a self-reference, use the value of `this`.
@@ -2116,24 +2226,34 @@
   /// [declareLocalVariable], [buildLocalGet], and [buildLocalSet].
   void enterScope(ClosureScope scope) => _enterScope(scope);
 
+  /// Called when entering a function body or loop body.
+  ///
+  /// This is not called for for-loops, which instead use the methods
+  /// [_enterForLoopInitializer], [_enterForLoopBody], and [_enterForLoopUpdate]
+  /// due to their special scoping rules.
+  ///
+  /// The boxed variables declared in this scope must subsequently be available
+  /// using [buildLocalGet], [buildLocalSet], etc.
   void _enterScope(ClosureScope scope) {
     if (scope == null) return;
     ir.CreateBox boxPrim = addPrimitive(new ir.CreateBox());
     environment.extend(scope.box, boxPrim);
     boxPrim.useElementAsHint(scope.box);
     scope.capturedVariables.forEach((Local local, ClosureLocation location) {
-      assert(!jsState.boxedVariables.containsKey(local));
+      assert(!state.boxedVariables.containsKey(local));
       if (location.isBox) {
-        jsState.boxedVariables[local] = location;
+        state.boxedVariables[local] = location;
       }
     });
   }
 
+  /// Add the given function parameter to the IR, and bind it in the environment
+  /// or put it in its box, if necessary.
   void _createFunctionParameter(Local parameterElement) {
     ir.Parameter parameter = new ir.Parameter(parameterElement);
     _parameters.add(parameter);
     state.functionParameters.add(parameter);
-    ClosureLocation location = jsState.boxedVariables[parameterElement];
+    ClosureLocation location = state.boxedVariables[parameterElement];
     if (location != null) {
       add(new ir.SetField(environment.lookup(location.box),
                           location.field,
@@ -2144,6 +2264,7 @@
   }
 
   void _createThisParameter() {
+    assert(state.thisParameter == null);
     if (Elements.isStaticOrTopLevel(state.currentElement)) return;
     if (state.currentElement.isLocal) return;
     state.thisParameter =
@@ -2156,7 +2277,7 @@
     if (initialValue == null) {
       initialValue = buildNullConstant();
     }
-    ClosureLocation location = jsState.boxedVariables[variableElement];
+    ClosureLocation location = state.boxedVariables[variableElement];
     if (location != null) {
       add(new ir.SetField(environment.lookup(location.box),
                           location.field,
@@ -2192,10 +2313,9 @@
   }
 
   /// Create a read access of [local] variable or parameter.
-  @override
   ir.Primitive _buildLocalGet(LocalElement local) {
     assert(isOpen);
-    ClosureLocation location = jsState.boxedVariables[local];
+    ClosureLocation location = state.boxedVariables[local];
     if (location != null) {
       ir.Primitive result = new ir.GetField(environment.lookup(location.box),
                                             location.field);
@@ -2210,10 +2330,9 @@
 
   /// Create a write access to [local] variable or parameter with the provided
   /// [value].
-  @override
   ir.Primitive buildLocalVariableSet(LocalElement local, ir.Primitive value) {
     assert(isOpen);
-    ClosureLocation location = jsState.boxedVariables[local];
+    ClosureLocation location = state.boxedVariables[local];
     if (location != null) {
       add(new ir.SetField(environment.lookup(location.box),
                           location.field,
@@ -2227,6 +2346,10 @@
     return value;
   }
 
+  /// Called before building the initializer of a for-loop.
+  ///
+  /// The loop variables will subsequently be declared using
+  /// [declareLocalVariable].
   void _enterForLoopInitializer(ClosureScope scope,
                                 List<LocalElement> loopVariables) {
     if (scope == null) return;
@@ -2236,6 +2359,7 @@
     _enterScope(scope);
   }
 
+  /// Called before building the body of a for-loop.
   void _enterForLoopBody(ClosureScope scope,
                          List<LocalElement> loopVariables) {
     if (scope == null) return;
@@ -2245,6 +2369,7 @@
     _enterScope(scope);
   }
 
+  /// Called before building the update of a for-loop.
   void _enterForLoopUpdate(ClosureScope scope,
                            List<LocalElement> loopVariables) {
     if (scope == null) return;
@@ -2262,18 +2387,20 @@
     environment.update(scope.box, newBox);
   }
 
+  /// Creates an access to the receiver from the current (or enclosing) method.
+  ///
+  /// If inside a closure class, [buildThis] will redirect access through
+  /// closure fields in order to access the receiver from the enclosing method.
   ir.Primitive buildThis() {
-    if (jsState.receiver != null) return jsState.receiver;
+    if (state.enclosingThis != null) return state.enclosingThis;
     assert(state.thisParameter != null);
     return state.thisParameter;
   }
 
-  @override
   ir.Primitive buildSuperFieldGet(FieldElement target) {
     return addPrimitive(new ir.GetField(buildThis(), target));
   }
 
-  @override
   ir.Primitive buildSuperFieldSet(FieldElement target, ir.Primitive value) {
     add(new ir.SetField(buildThis(), target, value));
     return value;
@@ -2299,15 +2426,17 @@
                                   ClosureScope closureScope) {
     _createThisParameter();
     for (Local param in parameters) {
-      ir.Parameter parameter = createLocalParameter(param);
+      ir.Parameter parameter = _createLocalParameter(param);
       state.functionParameters.add(parameter);
     }
     if (closureScope != null) {
-      jsState.boxedVariables.addAll(closureScope.capturedVariables);
+      state.boxedVariables.addAll(closureScope.capturedVariables);
     }
   }
 
-  @override
+  /// Create a constructor invocation of [element] on [type] where the
+  /// constructor name and argument structure are defined by [callStructure] and
+  /// the argument values are defined by [arguments].
   ir.Primitive buildConstructorInvocation(ConstructorElement element,
                                           CallStructure callStructure,
                                           DartType type,
@@ -2333,9 +2462,10 @@
   }
 
   ir.Primitive buildTypeExpression(DartType type) {
+    type = program.unaliasType(type);
     if (type is TypeVariableType) {
       return buildTypeVariableAccess(type);
-    } else if (type is InterfaceType) {
+    } else if (type is InterfaceType || type is FunctionType) {
       List<ir.Primitive> arguments = <ir.Primitive>[];
       type.forEachTypeVariable((TypeVariableType variable) {
         ir.Primitive value = buildTypeVariableAccess(variable);
@@ -2379,7 +2509,7 @@
         buildTypeExpression(binding));
   }
 
-  @override
+  /// Reifies the value of [variable] on the current receiver object.
   ir.Primitive buildReifyTypeVariable(TypeVariableType variable) {
     ir.Primitive typeArgument = buildTypeVariableAccess(variable);
     return addPrimitive(new ir.ReifyRuntimeType(typeArgument));
@@ -2390,13 +2520,37 @@
     return addPrimitive(new ir.CreateInvocationMirror(selector, arguments));
   }
 
-  @override
+  ir.Primitive buildForeignCode(js.Template codeTemplate,
+                                List<ir.Primitive> arguments,
+                                NativeBehavior behavior,
+                                {Element dependency}) {
+    types.TypeMask type = program.getTypeMaskForForeign(behavior);
+    if (codeTemplate.isExpression) {
+      return _continueWithExpression((k) => new ir.ForeignCode(
+        codeTemplate,
+        type,
+        arguments,
+        behavior,
+        continuation: k,
+        dependency: dependency));
+    } else {
+      assert(isOpen);
+      add(new ir.ForeignCode(codeTemplate, type, arguments, behavior,
+          dependency: dependency));
+      _current = null;
+      return null;
+    }
+  }
+
+  /// Creates a type test or type cast of [value] against [type].
   ir.Primitive buildTypeOperator(ir.Primitive value,
                                  DartType type,
                                  {bool isTypeTest}) {
     assert(isOpen);
     assert(isTypeTest != null);
 
+    type = program.unaliasType(type);
+
     if (type.isMalformed) {
       FunctionElement helper = program.throwTypeErrorHelper;
       ErroneousElement element = type.element;
@@ -2407,40 +2561,48 @@
           <ir.Primitive>[message]);
     }
 
+    List<ir.Primitive> typeArguments = const <ir.Primitive>[];
+    if (type is GenericType && type.typeArguments.isNotEmpty) {
+      typeArguments = type.typeArguments.map(buildTypeExpression).toList();
+    } else if (type is TypeVariableType) {
+      typeArguments = <ir.Primitive>[buildTypeVariableAccess(type)];
+    } else if (type is FunctionType) {
+      typeArguments = <ir.Primitive>[buildTypeExpression(type)];
+    }
+
     if (isTypeTest) {
       // For type tests, we must treat specially the rare cases where `null`
       // satisfies the test (which otherwise never satisfies a type test).
       // This is not an optimization: the TypeOperator assumes that `null`
-      // cannot satisfy the type test.
+      // cannot satisfy the type test unless the type is a type variable.
       if (type.isObject || type.isDynamic) {
         // `x is Object` and `x is dynamic` are always true, even if x is null.
         return buildBooleanConstant(true);
       }
       if (type is InterfaceType && type.element == program.nullClass) {
         // `x is Null` is true if and only if x is null.
-        return addPrimitive(new ir.Identical(value, buildNullConstant()));
+        return _buildCheckNull(value);
       }
+      return addPrimitive(new ir.TypeTest(value, type, typeArguments));
+    } else {
+      return _continueWithExpression(
+              (k) => new ir.TypeCast(value, type, typeArguments, k));
     }
-    List<ir.Primitive> typeArguments = const <ir.Primitive>[];
-    if (type is GenericType && type.typeArguments.isNotEmpty) {
-      typeArguments = type.typeArguments.map(buildTypeExpression).toList();
-    } else if (type is TypeVariableType) {
-      typeArguments = <ir.Primitive>[buildTypeVariableAccess(type)];
-    }
-    ir.Primitive check = _continueWithExpression(
-            (k) => new ir.TypeOperator(value,
-                       type, typeArguments, k, isTypeTest: isTypeTest));
-    return check;
   }
 
-  @override
+  /// Create an if-null expression. This is equivalent to a conditional
+  /// expression whose result is either [value] if [value] is not null, or
+  /// `right` if [value] is null. Only when [value] is null, [buildRight] is
+  /// evaluated to produce the `right` value.
   ir.Primitive buildIfNull(ir.Primitive value,
                            ir.Primitive buildRight(IrBuilder builder)) {
     ir.Primitive condition = _buildCheckNull(value);
     return buildConditional(condition, buildRight, (_) => value);
   }
 
-  @override
+  /// Create a conditional send. This is equivalent to a conditional expression
+  /// that checks if [receiver] is null, if so, it returns null, otherwise it
+  /// evaluates the [buildSend] expression.
   ir.Primitive buildIfNotNullSend(ir.Primitive receiver,
                                   ir.Primitive buildSend(IrBuilder builder)) {
     ir.Primitive condition = _buildCheckNull(receiver);
@@ -2450,8 +2612,15 @@
   /// Creates a type test checking whether [value] is null.
   ir.Primitive _buildCheckNull(ir.Primitive value) {
     assert(isOpen);
-    ir.Primitive right = buildNullConstant();
-    return addPrimitive(new ir.Identical(value, right));
+    return buildIdentical(value, buildNullConstant());
+  }
+
+  /// Convert the given value to a string.
+  ir.Primitive buildStringify(ir.Primitive value) {
+    return buildStaticFunctionInvocation(
+        program.stringifyFunction,
+        new CallStructure.unnamed(1),
+        <ir.Primitive>[value]);
   }
 }
 
@@ -2525,3 +2694,12 @@
                    this.stackTraceVariable,
                    this.buildCatchBlock});
 }
+
+class SwitchCaseInfo {
+  final List<ir.Primitive> constants = <ir.Primitive>[];
+  final SubbuildFunction buildBody;
+
+  SwitchCaseInfo(this.buildBody);
+
+  void addConstant(ir.Primitive constant) => constants.add(constant);
+}
diff --git a/pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart b/pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart
index c075b77..f5e5cc9 100644
--- a/pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart
+++ b/pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart
@@ -13,14 +13,27 @@
 import '../elements/modelx.dart' show SynthesizedConstructorElementX,
     ConstructorBodyElementX, FunctionSignatureX;
 import '../io/source_information.dart';
-import '../js_backend/js_backend.dart' show JavaScriptBackend;
+import '../js_backend/js_backend.dart' show JavaScriptBackend,
+    SyntheticConstantKind;
 import '../resolution/semantic_visitor.dart';
 import '../resolution/operators.dart' as op;
-import '../scanner/scannerlib.dart' show Token, isUserDefinableOperator;
 import '../tree/tree.dart' as ast;
+import '../types/types.dart' show TypeMask;
 import '../universe/universe.dart' show SelectorKind, CallStructure;
+import '../constants/values.dart' show ConstantValue;
 import 'cps_ir_nodes.dart' as ir;
 import 'cps_ir_builder.dart';
+import '../native/native.dart' show NativeBehavior;
+
+// TODO(karlklose): remove.
+import '../js/js.dart' as js show js, Template, Expression, Name;
+import '../ssa/ssa.dart' show TypeMaskFactory;
+import '../types/types.dart' show TypeMask;
+import '../util/util.dart';
+
+import 'package:_internal/compiler/js_lib/shared/embedded_names.dart'
+    show JsBuiltin, JsGetName;
+import '../constants/values.dart';
 
 typedef void IrBuilderCallback(Element element, ir.FunctionDefinition irNode);
 
@@ -69,12 +82,14 @@
   }
 }
 
-
-/// A tree visitor that builds [ir.Node]s.
+/// Translates the frontend AST of a method to its CPS IR.
 ///
-/// The visit methods add statements using the [irBuilder] and return the last
-/// added statement for trees that represent expressions.
+/// The visitor has an [IrBuilder] which contains an IR fragment to build upon
+/// and the current reaching definition of local variables.
 ///
+/// Visiting a statement or expression extends the IR builder's fragment.
+/// For expressions, the primitive holding the resulting value is returned.
+/// For statements, `null` is returned.
 // TODO(johnniwinther): Implement [SemanticDeclVisitor].
 abstract class IrBuilderVisitor extends ast.Visitor<ir.Primitive>
     with IrBuilderMixin<ast.Node>,
@@ -98,7 +113,7 @@
   /// The analysis information includes the set of variables that must be
   /// copied into [ir.MutableVariable]s on entry to the try and copied out on
   /// exit.
-  Map<ast.TryStatement, TryStatementInfo> tryStatements = null;
+  Map<ast.Node, TryStatementInfo> tryStatements = null;
 
   // In SSA terms, join-point continuation parameters are the phis and the
   // continuation invocation arguments are the corresponding phi inputs.  To
@@ -167,33 +182,19 @@
   /// Read the value of [field].
   ir.Primitive buildStaticFieldGet(FieldElement field, SourceInformation src);
 
-  /// Creates a [TypedSelector] variant of [newSelector] using the type of
-  /// [oldSelector], if available.
-  ///
-  /// This is needed to preserve inferred receiver types when creating new
-  /// selectors.
-  Selector useSelectorType(Selector newSelector, Selector oldSelector) {
-    // TODO(asgerf,johnniwinther): This works but it is brittle.
-    //     We should decouple selectors from inferred receiver type masks.
-    // TODO(asgerf): Use this whenever we create a selector for a dynamic call.
-    if (oldSelector is TypedSelector) {
-      return new TypedSelector(oldSelector.mask, newSelector, compiler.world);
-    } else {
-      return newSelector;
-    }
-  }
-
-  /// Like [useSelectorType], except the original typed selector is obtained
-  /// from the [node].
-  Selector useSelectorTypeOfNode(Selector newSelector, ast.Send node) {
-    return useSelectorType(newSelector, elements.getSelector(node));
-  }
-
   ir.FunctionDefinition _makeFunctionBody(FunctionElement element,
                                           ast.FunctionExpression node) {
     FunctionSignature signature = element.functionSignature;
-    List<ParameterElement> parameters = [];
-    signature.orderedForEachParameter(parameters.add);
+    List<Local> parameters = <Local>[];
+    signature.orderedForEachParameter(
+        (LocalParameterElement e) => parameters.add(e));
+
+    if (element.isFactoryConstructor) {
+      // Type arguments are passed in as extra parameters.
+      for (DartType typeVariable in element.enclosingClass.typeVariables) {
+        parameters.add(new TypeVariableLocal(typeVariable, element));
+      }
+    }
 
     irBuilder.buildFunctionHeader(parameters,
                                   closureScope: getClosureScopeForNode(node),
@@ -327,6 +328,10 @@
         buildVariableDeclaration: subbuild(variableDeclaration),
         variableElement: variableElement,
         variableSelector: selector,
+        variableMask: elements.getTypeMask(identifier),
+        currentMask: elements.getCurrentTypeMask(node),
+        moveNextMask: elements.getMoveNextTypeMask(node),
+        iteratorMask: elements.getIteratorTypeMask(node),
         buildBody: subbuild(node.body),
         target: elements.getTargetDefinition(node),
         closureScope: getClosureScopeForNode(node));
@@ -335,13 +340,8 @@
   ir.Primitive visitVariableDefinitions(ast.VariableDefinitions node) {
     assert(irBuilder.isOpen);
     if (node.modifiers.isConst) {
-      for (ast.SendSet definition in node.definitions.nodes) {
-        assert(!definition.arguments.isEmpty);
-        assert(definition.arguments.tail.isEmpty);
-        VariableElement element = elements[definition];
-        ConstantExpression value = getConstantForVariable(element);
-        irBuilder.declareLocalConstant(element, value);
-      }
+      // Do nothing.
+      // handleLocalConstantGet inlines the constant at use-site.
     } else {
       for (ast.Node definition in node.definitions.nodes) {
         Element element = elements[definition];
@@ -372,12 +372,49 @@
     return null;
   }
 
-  visitTryStatement(ast.TryStatement node) {
-    // Finally blocks are not yet implemented.
-    if (node.finallyBlock != null) {
-      return giveup(node, 'try/finally');
+  visitSwitchStatement(ast.SwitchStatement node) {
+    assert(irBuilder.isOpen);
+    // We do not handle switch statements with continue to labeled cases.
+    for (ast.SwitchCase switchCase in node.cases) {
+      for (ast.Node labelOrCase in switchCase.labelsAndCases) {
+        if (labelOrCase is ast.Label) {
+          LabelDefinition definition = elements.getLabelDefinition(labelOrCase);
+          if (definition != null && definition.isContinueTarget) {
+            return giveup(node, "continue to a labeled switch case");
+          }
+        }
+      }
     }
 
+    // Each switch case contains a list of interleaved labels and expressions
+    // and a non-empty body.  We can ignore the labels because they are not
+    // jump targets.
+    List<SwitchCaseInfo> cases = <SwitchCaseInfo>[];
+    SwitchCaseInfo defaultCase;
+    for (ast.SwitchCase switchCase in node.cases) {
+      SwitchCaseInfo caseInfo =
+          new SwitchCaseInfo(subbuildSequence(switchCase.statements));
+      if (switchCase.isDefaultCase) {
+        defaultCase = caseInfo;
+      } else {
+        cases.add(caseInfo);
+        for (ast.Node labelOrCase in switchCase.labelsAndCases) {
+          if (labelOrCase is ast.CaseMatch) {
+            ir.Primitive constant = translateConstant(labelOrCase.expression);
+            caseInfo.addConstant(constant);
+          }
+        }
+      }
+    }
+    ir.Primitive value = visit(node.expression);
+    JumpTarget target = elements.getTargetDefinition(node);
+    Element error =
+        (compiler.backend as JavaScriptBackend).getFallThroughError();
+    irBuilder.buildSimpleSwitch(target, value, cases, defaultCase, error,
+        sourceInformationBuilder.buildGeneric(node));
+  }
+
+  visitTryStatement(ast.TryStatement node) {
     List<CatchClauseInfo> catchClauseInfos = <CatchClauseInfo>[];
     for (ast.CatchBlock catchClause in node.catchBlocks.nodes) {
       assert(catchClause.exception != null);
@@ -397,11 +434,29 @@
           buildCatchBlock: subbuild(catchClause.block)));
     }
 
-    irBuilder.buildTry(
-        tryStatementInfo: tryStatements[node],
-        buildTryBlock: subbuild(node.tryBlock),
-        catchClauseInfos: catchClauseInfos,
-        closureClassMap: closureClassMap);
+    assert(!node.catchBlocks.isEmpty || node.finallyBlock != null);
+    if (!node.catchBlocks.isEmpty && node.finallyBlock != null) {
+      // Try/catch/finally is encoded in terms of try/catch and try/finally:
+      //
+      // try tryBlock catch (ex, st) catchBlock finally finallyBlock
+      // ==>
+      // try { try tryBlock catch (ex, st) catchBlock } finally finallyBlock
+      irBuilder.buildTryFinally(tryStatements[node.finallyBlock],
+          (IrBuilder inner) {
+            inner.buildTryCatch(tryStatements[node.catchBlocks],
+                subbuild(node.tryBlock),
+                catchClauseInfos);
+          },
+          subbuild(node.finallyBlock));
+    } else if (!node.catchBlocks.isEmpty) {
+      irBuilder.buildTryCatch(tryStatements[node.catchBlocks],
+          subbuild(node.tryBlock),
+          catchClauseInfos);
+    } else {
+      irBuilder.buildTryFinally(tryStatements[node.finallyBlock],
+          subbuild(node.tryBlock),
+          subbuild(node.finallyBlock));
+    }
   }
 
   // ## Expressions ##
@@ -439,27 +494,16 @@
     return irBuilder.buildDartStringConstant(node.dartString);
   }
 
-  ConstantExpression getConstantForNode(ast.Node node) {
-    ConstantExpression constant =
-        irBuilder.state.constants.getConstantForNode(node, elements);
-    assert(invariant(node, constant != null,
-        message: 'No constant computed for $node'));
-    return constant;
+  ConstantValue getConstantForNode(ast.Node node) {
+    return irBuilder.state.constants.getConstantValueForNode(node, elements);
   }
 
-  ConstantExpression getConstantForVariable(VariableElement element) {
-    ConstantExpression constant =
-        irBuilder.state.constants.getConstantForVariable(element);
-    assert(invariant(element, constant != null,
-            message: 'No constant computed for $element'));
-    return constant;
+  ConstantValue getConstantForVariable(VariableElement element) {
+    return irBuilder.state.constants.getConstantValueForVariable(element);
   }
 
-  /// Builds a constant pulling the value from the constant environment.
-  // TODO(johnniwinther): Remove this when [IrBuilder.buildConstant] only takes
-  // a [ConstantExpression].
-  ir.Primitive buildConstant(ConstantExpression expression) {
-    return irBuilder.buildConstant(expression,
+  ir.Primitive buildConstantExpression(ConstantExpression expression) {
+    return irBuilder.buildConstant(
         irBuilder.state.constants.getConstantValue(expression));
   }
 
@@ -557,7 +601,7 @@
   ir.Primitive handleConstantGet(
       ast.Node node,
       ConstantExpression constant, _) {
-    return buildConstant(constant);
+    return buildConstantExpression(constant);
   }
 
   /// If [node] is null, returns this.
@@ -574,7 +618,8 @@
       _) {
     return irBuilder.buildDynamicGet(
         translateReceiver(receiver),
-        selector);
+        selector,
+        elements.getTypeMask(node));
   }
 
   @override
@@ -586,7 +631,8 @@
     ir.Primitive target = visit(receiver);
     return irBuilder.buildIfNotNullSend(
         target,
-        nested(() => irBuilder.buildDynamicGet(target, selector)));
+        nested(() => irBuilder.buildDynamicGet(
+            target, selector, elements.getTypeMask(node))));
   }
 
   @override
@@ -594,7 +640,7 @@
       ast.Send node,
       ConstantExpression constant,
       _) {
-    return buildConstant(constant);
+    return buildConstantExpression(constant);
   }
 
   @override
@@ -603,7 +649,7 @@
       LocalVariableElement element,
       _) {
     return element.isConst
-        ? buildConstant(getConstantForVariable(element))
+        ? irBuilder.buildConstant(getConstantForVariable(element))
         : irBuilder.buildLocalVariableGet(element);
   }
 
@@ -671,7 +717,8 @@
   ir.Primitive visitUnresolvedSuperGet(
       ast.Send node,
       Element element, _) {
-    return buildInstanceNoSuchMethod(elements.getSelector(node), []);
+    return buildInstanceNoSuchMethod(
+        elements.getSelector(node), elements.getTypeMask(node), []);
   }
 
   @override
@@ -755,14 +802,16 @@
     return irBuilder.buildNegation(check);
   }
 
-  ir.Primitive translateBinary(ast.Node left,
+  ir.Primitive translateBinary(ast.Send node,
+                               ast.Node left,
                                op.BinaryOperator operator,
                                ast.Node right) {
     Selector selector = new Selector.binaryOperator(operator.selectorName);
     ir.Primitive receiver = visit(left);
     List<ir.Primitive> arguments = <ir.Primitive>[visit(right)];
     arguments = normalizeDynamicArguments(selector.callStructure, arguments);
-    return irBuilder.buildDynamicInvocation(receiver, selector, arguments);
+    return irBuilder.buildDynamicInvocation(
+        receiver, selector, elements.getTypeMask(node), arguments);
   }
 
   @override
@@ -770,7 +819,7 @@
                            ast.Node left,
                            op.BinaryOperator operator,
                            ast.Node right, _) {
-    return translateBinary(left, operator, right);
+    return translateBinary(node, left, operator, right);
   }
 
   @override
@@ -781,7 +830,8 @@
     ir.Primitive target = visit(receiver);
     List<ir.Primitive> arguments = <ir.Primitive>[visit(index)];
     arguments = normalizeDynamicArguments(selector.callStructure, arguments);
-    return irBuilder.buildDynamicInvocation(target, selector, arguments);
+    return irBuilder.buildDynamicInvocation(
+        target, selector, elements.getTypeMask(node), arguments);
   }
 
   ir.Primitive translateSuperBinary(FunctionElement function,
@@ -819,7 +869,7 @@
       ast.Node left,
       ast.Node right,
       _) {
-    return translateBinary(left, op.BinaryOperator.EQ, right);
+    return translateBinary(node, left, op.BinaryOperator.EQ, right);
   }
 
   @override
@@ -846,7 +896,7 @@
       ast.Node right,
       _) {
     return irBuilder.buildNegation(
-        translateBinary(left, op.BinaryOperator.NOT_EQ, right));
+        translateBinary(node, left, op.BinaryOperator.NOT_EQ, right));
   }
 
   @override
@@ -865,7 +915,8 @@
     // TODO(johnniwinther): Clean up the creation of selectors.
     Selector selector = operator.selector;
     ir.Primitive receiver = translateReceiver(expression);
-    return irBuilder.buildDynamicInvocation(receiver, selector, const []);
+    return irBuilder.buildDynamicInvocation(
+        receiver, selector, elements.getTypeMask(node), const []);
   }
 
   @override
@@ -910,7 +961,7 @@
       ast.NodeList arguments,
       CallStructure callStructure,
       _) {
-    ir.Primitive target = buildConstant(constant);
+    ir.Primitive target = buildConstantExpression(constant);
     return translateCallInvoke(target, arguments, callStructure);
   }
 
@@ -922,7 +973,7 @@
       Selector selector,
       _) {
     return irBuilder.buildDynamicInvocation(
-        translateReceiver(receiver), selector,
+        translateReceiver(receiver), selector, elements.getTypeMask(node),
         translateDynamicArguments(arguments, selector.callStructure));
   }
 
@@ -937,7 +988,7 @@
     return irBuilder.buildIfNotNullSend(
         target,
         nested(() => irBuilder.buildDynamicInvocation(
-            target, selector,
+            target, selector, elements.getTypeMask(node),
             translateDynamicArguments(arguments, selector.callStructure))));
   }
 
@@ -987,15 +1038,7 @@
       MethodElement function,
       ast.NodeList arguments,
       CallStructure callStructure,
-      _) {
-    // TODO(karlklose): support foreign functions.
-    if (compiler.backend.isForeign(function)) {
-      return giveup(node, 'handleStaticFunctionInvoke: foreign: $function');
-    }
-    return irBuilder.buildStaticFunctionInvocation(function, callStructure,
-        translateStaticArguments(arguments, function, callStructure),
-        sourceInformation: sourceInformationBuilder.buildCall(node));
-  }
+      _);
 
   @override
   ir.Primitive handleStaticFunctionIncompatibleInvoke(
@@ -1069,6 +1112,7 @@
       CallStructure callStructure, _) {
     return buildInstanceNoSuchMethod(
         elements.getSelector(node),
+        elements.getTypeMask(node),
         translateDynamicArguments(arguments, callStructure));
   }
 
@@ -1080,6 +1124,7 @@
       Selector selector, _) {
     return buildInstanceNoSuchMethod(
         elements.getSelector(node),
+        elements.getTypeMask(node),
         translateDynamicArguments(arguments, selector.callStructure));
   }
 
@@ -1113,7 +1158,7 @@
        ast.Node rhs,
        _) {
     return irBuilder.buildDynamicIndexSet(
-        visit(receiver), visit(index), visit(rhs));
+        visit(receiver), elements.getTypeMask(node), visit(index), visit(rhs));
   }
 
   @override
@@ -1129,7 +1174,8 @@
   ir.Primitive translateCompounds(
       {ir.Primitive getValue(),
        CompoundRhs rhs,
-       void setValue(ir.Primitive value)}) {
+       void setValue(ir.Primitive value),
+       TypeMask operatorTypeMask}) {
     ir.Primitive value = getValue();
     op.BinaryOperator operator = rhs.operator;
     if (operator.kind == op.BinaryOperatorKind.IF_NULL) {
@@ -1154,7 +1200,8 @@
     arguments = normalizeDynamicArguments(
         operatorSelector.callStructure, arguments);
     ir.Primitive result =
-        irBuilder.buildDynamicInvocation(value, operatorSelector, arguments);
+        irBuilder.buildDynamicInvocation(
+            value, operatorSelector, operatorTypeMask, arguments);
     setValue(result);
     return rhs.kind == CompoundKind.POSTFIX ? value : result;
   }
@@ -1169,6 +1216,7 @@
     return irBuilder.buildDynamicSet(
         translateReceiver(receiver),
         selector,
+        elements.getTypeMask(node),
         visit(rhs));
   }
 
@@ -1182,7 +1230,8 @@
     ir.Primitive target = visit(receiver);
     return irBuilder.buildIfNotNullSend(
         target,
-        nested(() => irBuilder.buildDynamicSet(target, selector, visit(rhs))));
+        nested(() => irBuilder.buildDynamicSet(
+            target, selector, elements.getTypeMask(node), visit(rhs))));
   }
 
   @override
@@ -1247,14 +1296,15 @@
       CompoundRhs rhs,
       arg) {
     return translateCompounds(
-        getValue: () => buildConstant(constant),
+        getValue: () => buildConstantExpression(constant),
         rhs: rhs,
-        setValue: (value) {}); // The binary operator will throw before this.
+        setValue: (value) {}, // The binary operator will throw before this.
+        operatorTypeMask: elements.getOperatorTypeMaskInComplexSendSet(node));
   }
 
   @override
   ir.Primitive handleDynamicCompounds(
-      ast.Send node,
+      ast.SendSet node,
       ast.Node receiver,
       CompoundRhs rhs,
       Selector getterSelector,
@@ -1263,11 +1313,16 @@
     ir.Primitive target = translateReceiver(receiver);
     ir.Primitive helper() {
       return translateCompounds(
-          getValue: () => irBuilder.buildDynamicGet(target, getterSelector),
+          getValue: () => irBuilder.buildDynamicGet(
+              target,
+              getterSelector,
+              elements.getGetterTypeMaskInComplexSendSet(node)),
           rhs: rhs,
           setValue: (ir.Primitive result) {
-            irBuilder.buildDynamicSet(target, setterSelector, result);
-          });
+            irBuilder.buildDynamicSet(
+                target, setterSelector, elements.getTypeMask(node), result);
+          },
+          operatorTypeMask: elements.getOperatorTypeMaskInComplexSendSet(node));
     }
     return node.isConditional
         ? irBuilder.buildIfNotNullSend(target, nested(helper))
@@ -1301,7 +1356,8 @@
           } else {
             return buildLocalNoSuchSetter(local, result);
           }
-        });
+        },
+        operatorTypeMask: elements.getOperatorTypeMaskInComplexSendSet(node));
   }
 
   ir.Primitive buildStaticNoSuchGetter(Element element) {
@@ -1351,18 +1407,23 @@
               return buildStaticNoSuchSetter(
                   setter != null ? setter : getter, result);
           }
-        });
+        },
+        operatorTypeMask: elements.getOperatorTypeMaskInComplexSendSet(node));
   }
 
-  ir.Primitive buildSuperNoSuchGetter(Element element) {
+  ir.Primitive buildSuperNoSuchGetter(Element element, TypeMask mask) {
     return buildInstanceNoSuchMethod(
         new Selector.getter(element.name, element.library),
+        mask,
         const <ir.Primitive>[]);
   }
 
-  ir.Primitive buildSuperNoSuchSetter(Element element, ir.Primitive value) {
+  ir.Primitive buildSuperNoSuchSetter(Element element,
+                                      TypeMask mask,
+                                      ir.Primitive value) {
     return buildInstanceNoSuchMethod(
         new Selector.setter(element.name, element.library),
+        mask,
         <ir.Primitive>[value]);
   }
 
@@ -1386,7 +1447,9 @@
               return irBuilder.buildSuperMethodGet(getter);
             case CompoundGetter.UNRESOLVED:
               // TODO(johnniwinther): Ensure [getter] is not null.
-              return buildSuperNoSuchGetter(getter != null ? getter : setter);
+              return buildSuperNoSuchGetter(
+                  getter != null ? getter : setter,
+                  elements.getGetterTypeMaskInComplexSendSet(node));
           }
         },
         rhs: rhs,
@@ -1397,9 +1460,11 @@
             case CompoundSetter.SETTER:
               return irBuilder.buildSuperSetterSet(setter, result);
             case CompoundSetter.INVALID:
-              return buildSuperNoSuchSetter(setter, result);
+              return buildSuperNoSuchSetter(
+                  setter, elements.getTypeMask(node), result);
           }
-        });
+        },
+        operatorTypeMask: elements.getOperatorTypeMaskInComplexSendSet(node));
   }
 
   @override
@@ -1411,7 +1476,8 @@
     return translateCompounds(
         getValue: () => irBuilder.buildReifyTypeVariable(typeVariable.type),
         rhs: rhs,
-        setValue: (value) {}); // The binary operator will throw before this.
+        setValue: (value) {}, // The binary operator will throw before this.
+        operatorTypeMask: elements.getOperatorTypeMaskInComplexSendSet(node));
   }
 
   @override
@@ -1429,12 +1495,21 @@
           List<ir.Primitive> arguments = <ir.Primitive>[indexValue];
           arguments =
               normalizeDynamicArguments(selector.callStructure, arguments);
-          return irBuilder.buildDynamicInvocation(target, selector, arguments);
+          return irBuilder.buildDynamicInvocation(
+              target,
+              selector,
+              elements.getGetterTypeMaskInComplexSendSet(node),
+              arguments);
         },
         rhs: rhs,
         setValue: (ir.Primitive result) {
-          irBuilder.buildDynamicIndexSet(target, indexValue, result);
-        });
+          irBuilder.buildDynamicIndexSet(
+              target,
+              elements.getTypeMask(node),
+              indexValue,
+              result);
+        },
+        operatorTypeMask: elements.getOperatorTypeMaskInComplexSendSet(node));
   }
 
   @override
@@ -1454,7 +1529,9 @@
             return irBuilder.buildSuperIndex(indexFunction, indexValue);
           } else {
             return buildInstanceNoSuchMethod(
-                new Selector.index(), <ir.Primitive>[indexValue]);
+                new Selector.index(),
+                elements.getGetterTypeMaskInComplexSendSet(node),
+                <ir.Primitive>[indexValue]);
           }
         },
         rhs: rhs,
@@ -1463,34 +1540,57 @@
             irBuilder.buildSuperIndexSet(indexSetFunction, indexValue, result);
           } else {
             buildInstanceNoSuchMethod(
-                new Selector.indexSet(), <ir.Primitive>[indexValue, result]);
+                new Selector.indexSet(),
+                elements.getTypeMask(node),
+                <ir.Primitive>[indexValue, result]);
           }
-        });
+        },
+        operatorTypeMask: elements.getOperatorTypeMaskInComplexSendSet(node));
+  }
+
+  /// Evaluates a string interpolation and appends each part to [accumulator]
+  /// (after stringify conversion).
+  void buildStringParts(ast.Node node, List<ir.Primitive> accumulator) {
+    if (node is ast.StringJuxtaposition) {
+      buildStringParts(node.first, accumulator);
+      buildStringParts(node.second, accumulator);
+    } else if (node is ast.StringInterpolation) {
+      buildStringParts(node.string, accumulator);
+      for (ast.StringInterpolationPart part in node.parts) {
+        buildStringParts(part.expression, accumulator);
+        buildStringParts(part.string, accumulator);
+      }
+    } else if (node is ast.LiteralString) {
+      // Empty strings often occur at the end of a string interpolation,
+      // do not bother to include them.
+      if (!node.dartString.isEmpty) {
+        accumulator.add(irBuilder.buildDartStringConstant(node.dartString));
+      }
+    } else if (node is ast.ParenthesizedExpression) {
+      buildStringParts(node.expression, accumulator);
+    } else {
+      ir.Primitive value = visit(node);
+      accumulator.add(irBuilder.buildStringify(value));
+    }
   }
 
   ir.Primitive visitStringJuxtaposition(ast.StringJuxtaposition node) {
     assert(irBuilder.isOpen);
-    ir.Primitive first = visit(node.first);
-    ir.Primitive second = visit(node.second);
-    return irBuilder.buildStringConcatenation([first, second]);
+    List<ir.Primitive> parts = <ir.Primitive>[];
+    buildStringParts(node, parts);
+    return irBuilder.buildStringConcatenation(parts);
   }
 
   ir.Primitive visitStringInterpolation(ast.StringInterpolation node) {
     assert(irBuilder.isOpen);
-    List<ir.Primitive> arguments = [];
-    arguments.add(visitLiteralString(node.string));
-    var it = node.parts.iterator;
-    while (it.moveNext()) {
-      ast.StringInterpolationPart part = it.current;
-      arguments.add(visit(part.expression));
-      arguments.add(visitLiteralString(part.string));
-    }
-    return irBuilder.buildStringConcatenation(arguments);
+    List<ir.Primitive> parts = <ir.Primitive>[];
+    buildStringParts(node, parts);
+    return irBuilder.buildStringConcatenation(parts);
   }
 
   ir.Primitive translateConstant(ast.Node node) {
     assert(irBuilder.isOpen);
-    return buildConstant(getConstantForNode(node));
+    return irBuilder.buildConstant(getConstantForNode(node));
   }
 
   ir.Primitive visitThrow(ast.Throw node) {
@@ -1506,6 +1606,7 @@
 
   ir.Primitive buildInstanceNoSuchMethod(
       Selector selector,
+      TypeMask mask,
       List<ir.Primitive> arguments);
 
   ir.Primitive buildRuntimeError(String message);
@@ -1624,8 +1725,8 @@
       Element function,
       ast.Node index, _) {
     // Assume the index getter is missing.
-    Selector selector = useSelectorTypeOfNode(new Selector.index(), node);
-    return buildInstanceNoSuchMethod(selector, [visit(index)]);
+    return buildInstanceNoSuchMethod(
+        new Selector.index(), elements.getTypeMask(node), [visit(index)]);
   }
 
   @override
@@ -1636,6 +1737,7 @@
       ast.Node argument, _) {
     return buildInstanceNoSuchMethod(
         elements.getSelector(node),
+        elements.getTypeMask(node),
         [visit(argument)]);
   }
 
@@ -1644,7 +1746,8 @@
       ast.Send node,
       op.UnaryOperator operator,
       Element element, _) {
-    return buildInstanceNoSuchMethod(elements.getSelector(node), []);
+    return buildInstanceNoSuchMethod(
+        elements.getSelector(node), elements.getTypeMask(node), []);
   }
 
   @override
@@ -1732,10 +1835,10 @@
       ast.SendSet node,
       FieldElement field,
       ast.Node rhs, _) {
-    Selector selector = useSelectorTypeOfNode(
+    return buildInstanceNoSuchMethod(
         new Selector.setter(field.name, field.library),
-        node);
-    return buildInstanceNoSuchMethod(selector, [visit(rhs)]);
+        elements.getTypeMask(node),
+        [visit(rhs)]);
   }
 
   @override
@@ -1800,10 +1903,10 @@
       FunctionElement getter,
       ast.Node rhs,
       _) {
-    Selector selector = useSelectorTypeOfNode(
+    return buildInstanceNoSuchMethod(
         new Selector.setter(getter.name, getter.library),
-        node);
-    return buildInstanceNoSuchMethod(selector, [visit(rhs)]);
+        elements.getTypeMask(node),
+        [visit(rhs)]);
   }
 
   @override
@@ -1812,20 +1915,20 @@
       MethodElement method,
       ast.Node rhs,
       _) {
-    Selector selector = useSelectorTypeOfNode(
+    return buildInstanceNoSuchMethod(
         new Selector.setter(method.name, method.library),
-        node);
-    return buildInstanceNoSuchMethod(selector, [visit(rhs)]);
+        elements.getTypeMask(node),
+        [visit(rhs)]);
   }
 
   @override
   ir.Primitive visitSuperSetterGet(
       ast.Send node,
       FunctionElement setter, _) {
-    Selector selector = useSelectorTypeOfNode(
+    return buildInstanceNoSuchMethod(
         new Selector.setter(setter.name, setter.library),
-        node);
-    return buildInstanceNoSuchMethod(selector, []);
+        elements.getTypeMask(node),
+        []);
   }
 
   @override
@@ -1837,10 +1940,10 @@
     List<ir.Primitive> args =
         translateDynamicArguments(arguments, callStructure);
     Name name = new Name(setter.name, setter.library);
-    Selector selector = useSelectorTypeOfNode(
+    return buildInstanceNoSuchMethod(
         new Selector(SelectorKind.CALL, name, callStructure),
-        node);
-    return buildInstanceNoSuchMethod(selector, args);
+        elements.getTypeMask(node),
+        args);
   }
 
   ir.FunctionDefinition nullIfGiveup(ir.FunctionDefinition action()) {
@@ -1854,7 +1957,7 @@
     }
   }
 
-  void internalError(ast.Node node, String message) {
+  internalError(ast.Node node, String message) {
     giveup(node, message);
   }
 
@@ -1886,8 +1989,13 @@
   bool insideInitializer = false;
   Set<Local> capturedVariables = new Set<Local>();
 
-  Map<ast.TryStatement, TryStatementInfo> tryStatements =
-      <ast.TryStatement, TryStatementInfo>{};
+  /// A map containing variables boxed inside try blocks.
+  ///
+  /// The map is keyed by the [NodeList] of catch clauses for try/catch and
+  /// by the finally block for try/finally.  try/catch/finally is treated
+  /// as a try/catch nested in the try block of a try/finally.
+  Map<ast.Node, TryStatementInfo> tryStatements =
+      <ast.Node, TryStatementInfo>{};
 
   List<TryStatementInfo> tryNestingStack = <TryStatementInfo>[];
   bool get inTryStatement => tryNestingStack.isNotEmpty;
@@ -2004,15 +2112,42 @@
   }
 
   visitTryStatement(ast.TryStatement node) {
-    TryStatementInfo info = new TryStatementInfo();
-    tryStatements[node] = info;
-    tryNestingStack.add(info);
+    // Try/catch/finally is treated as two simpler constructs: try/catch and
+    // try/finally.  The encoding is:
+    //
+    // try S0 catch (ex, st) S1 finally S2
+    // ==>
+    // try { try S0 catch (ex, st) S1 } finally S2
+    //
+    // The analysis associates variables assigned in S0 with the catch clauses
+    // and variables assigned in S0 and S1 with the finally block.
+    TryStatementInfo enterTryFor(ast.Node node) {
+      TryStatementInfo info = new TryStatementInfo();
+      tryStatements[node] = info;
+      tryNestingStack.add(info);
+      return info;
+    }
+    void leaveTryFor(TryStatementInfo info) {
+      assert(tryNestingStack.last == info);
+      tryNestingStack.removeLast();
+    }
+    bool hasCatch = !node.catchBlocks.isEmpty;
+    bool hasFinally = node.finallyBlock != null;
+    TryStatementInfo catchInfo, finallyInfo;
+    // There is a nesting stack of try blocks, so the outer try/finally block
+    // is added first.
+    if (hasFinally) finallyInfo = enterTryFor(node.finallyBlock);
+    if (hasCatch) catchInfo = enterTryFor(node.catchBlocks);
     visit(node.tryBlock);
-    assert(tryNestingStack.last == info);
-    tryNestingStack.removeLast();
 
-    visit(node.catchBlocks);
-    if (node.finallyBlock != null) visit(node.finallyBlock);
+    if (hasCatch) {
+      leaveTryFor(catchInfo);
+      visit(node.catchBlocks);
+    }
+    if (hasFinally) {
+      leaveTryFor(finallyInfo);
+      visit(node.finallyBlock);
+    }
   }
 
   visitVariableDefinitions(ast.VariableDefinitions node) {
@@ -2044,16 +2179,23 @@
     return cls.typeVariables.isNotEmpty && _backend.classNeedsRti(cls);
   }
 
+  FunctionElement get stringifyFunction {
+    return _backend.getStringInterpolationHelper();
+  }
+
   FunctionElement get throwTypeErrorHelper => _backend.getThrowTypeError();
 
   ClassElement get nullClass => _compiler.nullClass;
+
+  DartType unaliasType(DartType type) => type.unalias(_compiler);
+
+  TypeMask getTypeMaskForForeign(NativeBehavior behavior) {
+    return TypeMaskFactory.fromNativeBehavior(behavior, _compiler);
+  }
 }
 
 /// IR builder specific to the JavaScript backend, coupled to the [JsIrBuilder].
 class JsIrBuilderVisitor extends IrBuilderVisitor {
-  /// Promote the type of [irBuilder] to [JsIrBuilder].
-  JsIrBuilder get irBuilder => super.irBuilder;
-
   JavaScriptBackend get backend => compiler.backend;
 
   /// Result of closure conversion for the current body of code.
@@ -2062,10 +2204,6 @@
   /// It is computed by the [ClosureTranslator].
   ClosureClassMap closureClassMap;
 
-  /// During construction of a constructor factory, [fieldValues] maps fields
-  /// to the primitive containing their initial value.
-  Map<FieldElement, ir.Primitive> fieldValues = <FieldElement, ir.Primitive>{};
-
   JsIrBuilderVisitor(TreeElements elements,
                      Compiler compiler,
                      SourceInformationBuilder sourceInformationBuilder)
@@ -2208,15 +2346,23 @@
     });
   }
 
+  /// Make a visitor suitable for translating ASTs taken from [context].
+  ///
+  /// Every visitor can only be applied to nodes in one context, because
+  /// the [elements] field is specific to that context.
+  JsIrBuilderVisitor makeVisitorForContext(AstElement context) {
+    return new JsIrBuilderVisitor(
+        context.resolvedAst.elements,
+        compiler,
+        sourceInformationBuilder.forContext(context));
+  }
+
   /// Builds the IR for an [expression] taken from a different [context].
   ///
   /// Such expressions need to be compiled with a different [sourceFile] and
   /// [elements] mapping.
   ir.Primitive inlineExpression(AstElement context, ast.Expression expression) {
-    JsIrBuilderVisitor visitor = new JsIrBuilderVisitor(
-        context.resolvedAst.elements,
-        compiler,
-        sourceInformationBuilder.forContext(context));
+    JsIrBuilderVisitor visitor = makeVisitorForContext(context);
     return visitor.withBuilder(irBuilder, () => visitor.visit(expression));
   }
 
@@ -2225,15 +2371,12 @@
   /// Such constants need to be compiled with a different [sourceFile] and
   /// [elements] mapping.
   ir.Primitive inlineConstant(AstElement context, ast.Expression exp) {
-    JsIrBuilderVisitor visitor = new JsIrBuilderVisitor(
-        context.resolvedAst.elements,
-        compiler,
-        sourceInformationBuilder.forContext(context));
+    JsIrBuilderVisitor visitor = makeVisitorForContext(context);
     return visitor.withBuilder(irBuilder, () => visitor.translateConstant(exp));
   }
 
-  JsIrBuilder getBuilderFor(Element element) {
-    return new JsIrBuilder(
+  IrBuilder getBuilderFor(Element element) {
+    return new IrBuilder(
         new GlobalProgramInformation(compiler),
         compiler.backend.constants,
         element);
@@ -2252,7 +2395,7 @@
     constructor = constructor.implementation;
     ClassElement classElement = constructor.enclosingClass.implementation;
 
-    JsIrBuilder builder = getBuilderFor(constructor);
+    IrBuilder builder = getBuilderFor(constructor);
 
     final bool requiresTypeInformation =
         builder.program.requiresRuntimeTypesFor(classElement);
@@ -2297,12 +2440,15 @@
       // get it out of the way here to avoid complications with mixins.
       loadTypeVariablesForSuperClasses(classElement);
 
+      /// Maps each field from this class or a superclass to its initial value.
+      Map<FieldElement, ir.Primitive> fieldValues =
+          <FieldElement, ir.Primitive>{};
+
       // -- Evaluate field initializers ---
       // Evaluate field initializers in constructor and super constructors.
-      irBuilder.enterInitializers();
       List<ConstructorElement> constructorList = <ConstructorElement>[];
-      evaluateConstructorFieldInitializers(constructor, constructorList);
-      irBuilder.leaveInitializers();
+      evaluateConstructorFieldInitializers(
+          constructor, constructorList, fieldValues);
 
       // All parameters in all constructors are now bound in the environment.
       // BoxLocals for captured parameters are also in the environment.
@@ -2357,8 +2503,12 @@
   /// the environment, but will be put there by this procedure.
   ///
   /// All constructors will be added to [supers], with superconstructors first.
-  void evaluateConstructorFieldInitializers(ConstructorElement constructor,
-                                            List<ConstructorElement> supers) {
+  void evaluateConstructorFieldInitializers(
+      ConstructorElement constructor,
+      List<ConstructorElement> supers,
+      Map<FieldElement, ir.Primitive> fieldValues) {
+    assert(constructor.isImplementation);
+    assert(constructor == elements.analyzedElement);
     ClassElement enclosingClass = constructor.enclosingClass.implementation;
     // Evaluate declaration-site field initializers, unless this constructor
     // redirects to another using a `this()` initializer. In that case, these
@@ -2395,19 +2545,18 @@
         if (initializer is ast.SendSet) {
           // Field initializer.
           FieldElement field = elements[initializer];
-          fieldValues[field] =
-              inlineExpression(constructor, initializer.arguments.head);
+          fieldValues[field] = visit(initializer.arguments.head);
         } else if (initializer is ast.Send) {
           // Super or this initializer.
           ConstructorElement target = elements[initializer].implementation;
           Selector selector = elements.getSelector(initializer);
-          ir.Primitive evaluateArgument(ast.Node arg) {
-            return inlineExpression(constructor, arg);
-          }
-          List<ir.Primitive> arguments =
-              initializer.arguments.mapToList(evaluateArgument);
-          loadArguments(target, selector, arguments);
-          evaluateConstructorFieldInitializers(target, supers);
+          List<ir.Primitive> arguments = initializer.arguments.mapToList(visit);
+          evaluateConstructorCallFromInitializer(
+              target,
+              selector.callStructure,
+              arguments,
+              supers,
+              fieldValues);
           hasConstructorCall = true;
         } else {
           compiler.internalError(initializer,
@@ -2422,12 +2571,35 @@
       if (target == null) {
         compiler.internalError(superClass, "No default constructor available.");
       }
-      evaluateConstructorFieldInitializers(target, supers);
+      target = target.implementation;
+      evaluateConstructorCallFromInitializer(
+          target,
+          CallStructure.NO_ARGS,
+          const [],
+          supers,
+          fieldValues);
     }
     // Add this constructor after the superconstructors.
     supers.add(constructor);
   }
 
+  /// Evaluates a call to the given constructor from an initializer list.
+  ///
+  /// Calls [loadArguments] and [evaluateConstructorFieldInitializers] in a
+  /// visitor that has the proper [TreeElements] mapping.
+  void evaluateConstructorCallFromInitializer(
+      ConstructorElement target,
+      CallStructure call,
+      List<ir.Primitive> arguments,
+      List<ConstructorElement> supers,
+      Map<FieldElement, ir.Primitive> fieldValues) {
+    JsIrBuilderVisitor visitor = makeVisitorForContext(target);
+    return visitor.withBuilder(irBuilder, () {
+      visitor.loadArguments(target, call, arguments);
+      visitor.evaluateConstructorFieldInitializers(target, supers, fieldValues);
+    });
+  }
+
   /// Loads the type variables for all super classes of [superClass] into the
   /// IR builder's environment with their corresponding values.
   ///
@@ -2466,9 +2638,10 @@
   /// Defaults for optional arguments are evaluated in order to ensure
   /// all parameters are available in the environment.
   void loadArguments(ConstructorElement target,
-                     Selector selector,
+                     CallStructure call,
                      List<ir.Primitive> arguments) {
-    target = target.implementation;
+    assert(target.isImplementation);
+    assert(target == elements.analyzedElement);
     FunctionSignature signature = target.functionSignature;
 
     // Establish a scope in case parameters are captured.
@@ -2487,9 +2660,9 @@
       ir.Primitive value;
       // Load argument if provided.
       if (signature.optionalParametersAreNamed) {
-        int nameIndex = selector.namedArguments.indexOf(param.name);
+        int nameIndex = call.namedArguments.indexOf(param.name);
         if (nameIndex != -1) {
-          int translatedIndex = selector.positionalArgumentCount + nameIndex;
+          int translatedIndex = call.positionalArgumentCount + nameIndex;
           value = arguments[translatedIndex];
         }
       } else if (index < arguments.length) {
@@ -2498,7 +2671,7 @@
       // Load default if argument was not provided.
       if (value == null) {
         if (param.initializer != null) {
-          value = inlineExpression(target, param.initializer);
+          value = visit(param.initializer);
         } else {
           value = irBuilder.buildNullConstant();
         }
@@ -2520,9 +2693,8 @@
     // cannot add a BoxLocal as parameter, because BoxLocal is not an element.
     // Instead of forging ParameterElements to forge a FunctionSignature, we
     // need a way to create backend methods without creating more fake elements.
-
     assert(constructor.isGenerativeConstructor);
-    assert(invariant(constructor, constructor.isImplementation));
+    assert(constructor.isImplementation);
     if (constructor.isSynthesized) return null;
     ast.FunctionExpression node = constructor.node;
     // If we know the body doesn't have any code, we don't generate it.
@@ -2618,7 +2790,7 @@
     // variable analysis in some way.
     DartCapturedVariables variables = _analyzeCapturedVariables(node);
     tryStatements = variables.tryStatements;
-    JsIrBuilder builder = getBuilderFor(body);
+    IrBuilder builder = getBuilderFor(body);
 
     return withBuilder(builder, () {
       irBuilder.buildConstructorBodyHeader(getConstructorBodyParameters(body),
@@ -2758,10 +2930,12 @@
 
   @override
   ir.Primitive buildInstanceNoSuchMethod(Selector selector,
+                                         TypeMask mask,
                                          List<ir.Primitive> arguments) {
     return irBuilder.buildDynamicInvocation(
         irBuilder.buildThis(),
-        useSelectorType(compiler.noSuchMethodSelector, selector),
+        compiler.noSuchMethodSelector,
+        mask,
         [irBuilder.buildInvocationMirror(selector, arguments)]);
   }
 
@@ -2788,16 +2962,244 @@
   }
 
   ir.Primitive buildStaticFieldGet(FieldElement field, SourceInformation src) {
-    ConstantExpression constant =
-        backend.constants.getConstantForVariable(field);
+    ConstantValue constant = getConstantForVariable(field);
     if (constant != null && !field.isAssignable) {
-      return buildConstant(constant);
+      return irBuilder.buildConstant(constant);
     } else if (backend.constants.lazyStatics.contains(field)) {
       return irBuilder.buildStaticFieldLazyGet(field, src);
     } else {
       return irBuilder.buildStaticFieldGet(field, src);
     }
   }
+
+  /// Build code to handle foreign code, that is, native JavaScript code, or
+  /// builtin values and operations of the backend.
+  ir.Primitive handleForeignCode(ast.Send node,
+                                 MethodElement function,
+                                 ast.NodeList argumentList,
+                                 CallStructure callStructure) {
+
+    void validateArgumentCount({int minimum, int exactly}) {
+      assert((minimum == null) != (exactly == null));
+      int count = 0;
+      int maximum;
+      if (exactly != null) {
+        minimum = exactly;
+        maximum = exactly;
+      }
+      for (ast.Node argument in argumentList) {
+        count++;
+        if (maximum != null && count > maximum) {
+          internalError(argument, 'Additional argument.');
+        }
+      }
+      if (count < minimum) {
+        internalError(node, 'Expected at least $minimum arguments.');
+      }
+    }
+
+    /// Call a helper method from the isolate library. The isolate library uses
+    /// its own isolate structure, that encapsulates dart2js's isolate.
+    ir.Primitive buildIsolateHelperInvocation(String helperName,
+                                              CallStructure callStructure) {
+      Element element = backend.isolateHelperLibrary.find(helperName);
+      if (element == null) {
+        compiler.internalError(node,
+            'Isolate library and compiler mismatch.');
+      }
+      List<ir.Primitive> arguments = translateStaticArguments(argumentList,
+          element, CallStructure.TWO_ARGS);
+      return irBuilder.buildStaticFunctionInvocation(element,
+          CallStructure.TWO_ARGS, arguments,
+          sourceInformation: sourceInformationBuilder.buildCall(node));
+    }
+
+    /// Lookup the value of the enum described by [node].
+    getEnumValue(ast.Node node, EnumClassElement enumClass, List values) {
+      Element element = elements[node];
+      if (element is! FieldElement || element.enclosingClass != enumClass) {
+        internalError(node, 'expected a JsBuiltin enum value');
+      }
+
+      int index = enumClass.enumValues.indexOf(element);
+      return values[index];
+    }
+
+    /// Returns the String the node evaluates to, or throws an error if the
+    /// result is not a string constant.
+    String expectStringConstant(ast.Node node) {
+      ir.Primitive nameValue = visit(node);
+      if (nameValue is ir.Constant && nameValue.value.isString) {
+        StringConstantValue constantValue = nameValue.value;
+        return constantValue.primitiveValue.slowToString();
+      } else {
+        return internalError(node, 'expected a literal string');
+      }
+    }
+
+    Link<ast.Node> argumentNodes  = argumentList.nodes;
+    NativeBehavior behavior =
+        compiler.enqueuer.resolution.nativeEnqueuer.getNativeBehaviorOf(node);
+    switch (function.name) {
+      case 'JS':
+        validateArgumentCount(minimum: 2);
+        // The first two arguments are the type and the foreign code template,
+        // which already have been analyzed by the resolver and can be retrieved
+        // using [NativeBehavior]. We can ignore these arguments in the backend.
+        List<ir.Primitive> arguments =
+            argumentNodes.skip(2).mapToList(visit, growable: false);
+        return irBuilder.buildForeignCode(behavior.codeTemplate, arguments,
+            behavior);
+
+      case 'DART_CLOSURE_TO_JS':
+        // TODO(ahe): This should probably take care to wrap the closure in
+        // another closure that saves the current isolate.
+      case 'RAW_DART_FUNCTION_REF':
+        validateArgumentCount(exactly: 1);
+
+        ast.Node argument = node.arguments.single;
+        FunctionElement closure = elements[argument].implementation;
+        if (!Elements.isStaticOrTopLevelFunction(closure)) {
+          internalError(argument,
+              'only static or toplevel function supported');
+        }
+        if (closure.functionSignature.hasOptionalParameters) {
+          internalError(argument,
+              'closures with optional parameters not supported');
+        }
+        return irBuilder.buildForeignCode(
+            js.js.expressionTemplateYielding(
+                        backend.emitter.staticFunctionAccess(function)),
+            <ir.Primitive>[],
+            NativeBehavior.PURE,
+            dependency: closure);
+
+      case 'JS_BUILTIN':
+        // The first argument is a description of the type and effect of the
+        // builtin, which has already been analyzed in the frontend.  The second
+        // argument must be a [JsBuiltin] value.  All other arguments are
+        // values used by the JavaScript template that is associated with the
+        // builtin.
+        validateArgumentCount(minimum: 2);
+
+        ast.Node builtin = argumentNodes.tail.head;
+        JsBuiltin value = getEnumValue(builtin, backend.jsBuiltinEnum,
+                                       JsBuiltin.values);
+        js.Template template = backend.emitter.builtinTemplateFor(value);
+        List<ir.Primitive> arguments =
+            argumentNodes.skip(2).mapToList(visit, growable: false);
+        return irBuilder.buildForeignCode(template, arguments, behavior);
+
+      case 'JS_EMBEDDED_GLOBAL':
+        validateArgumentCount(exactly: 2);
+
+        String name = expectStringConstant(argumentNodes.tail.head);
+        js.Expression access =
+            backend.emitter.generateEmbeddedGlobalAccess(name);
+        js.Template template = js.js.expressionTemplateYielding(access);
+        return irBuilder.buildForeignCode(template, <ir.Primitive>[], behavior);
+
+      case 'JS_INTERCEPTOR_CONSTANT':
+        validateArgumentCount(exactly: 1);
+
+        ast.Node argument = argumentNodes.head;
+        ir.Primitive argumentValue = visit(argument);
+        if (argumentValue is ir.Constant && argumentValue.value.isType) {
+          TypeConstantValue constant = argumentValue.value;
+          ConstantValue interceptorValue =
+              new InterceptorConstantValue(constant.representedType);
+          return irBuilder.buildConstant(interceptorValue);
+        } else {
+          internalError(argument, 'expected Type as argument');
+        }
+        break;
+
+      case 'JS_EFFECT':
+        return irBuilder.buildNullConstant();
+
+      case 'JS_GET_NAME':
+        validateArgumentCount(exactly: 1);
+
+        ast.Node argument = argumentNodes.head;
+        JsGetName id = getEnumValue(argument, backend.jsGetNameEnum,
+            JsGetName.values);
+        js.Name name = backend.namer.getNameForJsGetName(argument, id);
+        ConstantValue nameConstant =
+            new SyntheticConstantValue(SyntheticConstantKind.NAME,
+                                       js.js.quoteName(name));
+
+        return irBuilder.buildConstant(nameConstant);
+
+      case 'JS_GET_FLAG':
+        validateArgumentCount(exactly: 1);
+
+        String name = expectStringConstant(argumentNodes.first);
+        bool value = false;
+        switch (name) {
+          case 'MUST_RETAIN_METADATA':
+            value = backend.mustRetainMetadata;
+            break;
+          case 'USE_CONTENT_SECURITY_POLICY':
+            value = compiler.useContentSecurityPolicy;
+            break;
+          default:
+            internalError(node, 'Unknown internal flag "$name".');
+        }
+        return irBuilder.buildBooleanConstant(value);
+
+      case 'JS_STRING_CONCAT':
+        validateArgumentCount(exactly: 2);
+        List<ir.Primitive> arguments = argumentNodes.mapToList(visit);
+        return irBuilder.buildStringConcatenation(arguments);
+
+      case 'JS_CURRENT_ISOLATE_CONTEXT':
+        validateArgumentCount(exactly: 0);
+
+        if (!compiler.hasIsolateSupport) {
+          // If the isolate library is not used, we just generate code
+          // to fetch the current isolate.
+          String name = backend.namer.currentIsolate;
+          return irBuilder.buildForeignCode(js.js.parseForeignJS(name),
+              const <ir.Primitive>[], NativeBehavior.PURE);
+        } else {
+          return buildIsolateHelperInvocation('_currentIsolate',
+              CallStructure.NO_ARGS);
+        }
+        break;
+
+      case 'JS_CALL_IN_ISOLATE':
+        validateArgumentCount(exactly: 2);
+
+        if (!compiler.hasIsolateSupport) {
+          ir.Primitive closure = visit(argumentNodes.tail.head);
+          return irBuilder.buildCallInvocation(closure, CallStructure.NO_ARGS,
+              const <ir.Primitive>[]);
+        } else {
+          return buildIsolateHelperInvocation('_callInIsolate',
+              CallStructure.TWO_ARGS);
+        }
+        break;
+
+      default:
+        giveup(node, 'unplemented native construct: ${function.name}');
+        break;
+    }
+  }
+
+  @override
+  ir.Primitive handleStaticFunctionInvoke(ast.Send node,
+                                          MethodElement function,
+                                          ast.NodeList argumentList,
+                                          CallStructure callStructure,
+                                          _) {
+    if (compiler.backend.isForeign(function)) {
+      return handleForeignCode(node, function, argumentList, callStructure);
+    } else {
+      return irBuilder.buildStaticFunctionInvocation(function, callStructure,
+          translateStaticArguments(argumentList, function, callStructure),
+          sourceInformation: sourceInformationBuilder.buildCall(node));
+    }
+  }
 }
 
 /// Perform simple post-processing on the initial CPS-translated root term.
@@ -2810,13 +3212,11 @@
 ///   - Replace [ir.LetPrim] binding a [ir.NonTailThrow] with a [ir.Throw]
 ///     expression.
 class CleanupPass extends ir.RecursiveVisitor {
-  RemovalVisitor _remover = new RemovalVisitor();
-
   ir.Expression replacementFor(ir.Expression expression) {
     if (expression != null && expression is ir.LetPrim) {
       ir.Primitive primitive = expression.primitive;
       if (primitive is ir.NonTailThrow) {
-        _remover.visit(expression);
+        ir.RemovalVisitor.remove(expression);
         return new ir.Throw(primitive.value.definition);
       }
     }
@@ -2859,10 +3259,3 @@
     node.body = replacementFor(node.body);
   }
 }
-
-/// Visit a just-deleted subterm and unlink all [Reference]s in it.
-class RemovalVisitor extends ir.RecursiveVisitor {
-  processReference(ir.Reference reference) {
-    reference.unlink();
-  }
-}
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 0bb7ecc..fa33169 100644
--- a/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart
+++ b/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart
@@ -8,8 +8,19 @@
 import '../dart_types.dart' show DartType, InterfaceType, TypeVariableType;
 import '../elements/elements.dart';
 import '../io/source_information.dart' show SourceInformation;
+import '../types/types.dart' show TypeMask;
 import '../universe/universe.dart' show Selector, SelectorKind;
 
+import 'builtin_operator.dart';
+export 'builtin_operator.dart';
+
+// These imports are only used for the JavaScript specific nodes.  If we want to
+// support more than one native backend, we should probably create better
+// abstractions for native code and its type and effect system.
+import '../js/js.dart' as js show Template;
+import '../native/native.dart' as native show NativeBehavior;
+import '../types/types.dart' as types show TypeMask;
+
 abstract class Node {
   /// A pointer to the parent node. Is null until set by optimization passes.
   Node parent;
@@ -28,6 +39,8 @@
 /// that can be obtained without side-effects, divergence, or throwing
 /// exceptions can be built using a [LetPrim].
 abstract class Expression extends Node {
+  InteriorNode get parent; // Only InteriorNodes may contain expressions.
+
   Expression plug(Expression expr) => throw 'impossible';
 }
 
@@ -59,12 +72,10 @@
   }
 }
 
-/// An expression that cannot throw or diverge and has no side-effects.
-/// All primitives are named using the identity of the [Primitive] object.
+/// A named value.
 ///
-/// Primitives may allocate objects; this is not considered side-effect here.
-///
-/// Although primitives may not mutate state, they may depend on state.
+/// The identity of the [Primitive] object is the name of the value.
+/// The subclass describes how to compute the value.
 ///
 /// All primitives except [Parameter] must be bound by a [LetPrim].
 abstract class Primitive extends Definition<Primitive> {
@@ -80,6 +91,13 @@
       this.hint = hint;
     }
   }
+
+  /// True if the primitive can be removed, assuming it has no uses
+  /// (this getter does not check if there are any uses).
+  ///
+  /// False must be returned for primitives that may throw, diverge, or have
+  /// observable side-effects.
+  bool get isSafeForElimination => true;
 }
 
 /// Operands to invocations and primitives are always variables.  They point to
@@ -117,7 +135,7 @@
 /// During one-pass construction a LetPrim with an empty body is used to
 /// represent the one-hole context `let val x = V in []`.
 class LetPrim extends Expression implements InteriorNode {
-  final Primitive primitive;
+  Primitive primitive;
   Expression body;
 
   LetPrim(this.primitive, [this.body = null]);
@@ -265,6 +283,7 @@
 class InvokeMethod extends Expression implements Invoke {
   Reference<Primitive> receiver;
   Selector selector;
+  TypeMask mask;
   final List<Reference<Primitive>> arguments;
   final Reference<Continuation> continuation;
   final SourceInformation sourceInformation;
@@ -276,6 +295,7 @@
 
   InvokeMethod(Primitive receiver,
                this.selector,
+               this.mask,
                List<Primitive> arguments,
                Continuation continuation,
                {this.sourceInformation})
@@ -357,10 +377,14 @@
   accept(Visitor visitor) => visitor.visitInvokeConstructor(this);
 }
 
-// TODO(asgerf): Make a Primitive for "is" and an Expression for "as".
-
-/// An "as" cast or an "is" check.
-class TypeOperator extends Expression {
+/// An "is" type test.
+///
+/// Returns `true` if [value] is an instance of [type].
+///
+/// [type] must not be the [Object], `dynamic` or [Null] types (though it might
+/// be a type variable containing one of these types). This design is chosen
+/// to simplify code generation for type tests.
+class TypeTest extends Primitive {
   Reference<Primitive> value;
   final DartType type;
 
@@ -371,37 +395,61 @@
   /// If [type] is a [TypeVariableType], this is a singleton list with
   /// the internal representation of the type held in that type variable.
   ///
+  /// If [type] is a [FunctionType], this is a singleton list with the
+  /// internal representation of that type,
+  ///
   /// Otherwise the list is empty.
   final List<Reference<Primitive>> typeArguments;
-  final Reference<Continuation> continuation;
-  final bool isTypeTest;
 
-  TypeOperator(Primitive value,
-               this.type,
-               List<Primitive> typeArguments,
-               Continuation cont,
-               {bool this.isTypeTest})
-      : this.value = new Reference<Primitive>(value),
-        this.typeArguments = _referenceList(typeArguments),
-        this.continuation = new Reference<Continuation>(cont) {
-    assert(isTypeTest != null);
-  }
+  TypeTest(Primitive value,
+           this.type,
+           List<Primitive> typeArguments)
+  : this.value = new Reference<Primitive>(value),
+    this.typeArguments = _referenceList(typeArguments);
 
-  bool get isTypeCast => !isTypeTest;
-
-  accept(Visitor visitor) => visitor.visitTypeOperator(this);
+  accept(Visitor visitor) => visitor.visitTypeTest(this);
 }
 
-/// Invoke [toString] on each argument and concatenate the results.
-class ConcatenateStrings extends Expression {
-  final List<Reference<Primitive>> arguments;
+/// An "as" type cast.
+///
+/// If [value] is `null` or is an instance of [type], [continuation] is invoked
+/// with [value] as argument. Otherwise, a [CastError] is thrown.
+///
+/// Discussion:
+/// The parameter to [continuation] is redundant since it will always equal
+/// [value], which is typically in scope in the continuation. However, it might
+/// simplify type propagation, since a better type can be computed for the
+/// continuation parameter without needing flow-sensitive analysis.
+class TypeCast extends Expression {
+  Reference<Primitive> value;
+  final DartType type;
+
+  /// See the corresponding field on [TypeTest].
+  final List<Reference<Primitive>> typeArguments;
   final Reference<Continuation> continuation;
 
-  ConcatenateStrings(List<Primitive> args, Continuation cont)
-      : arguments = _referenceList(args),
-        continuation = new Reference<Continuation>(cont);
+  TypeCast(Primitive value,
+           this.type,
+           List<Primitive> typeArguments,
+           Continuation cont)
+      : this.value = new Reference<Primitive>(value),
+        this.typeArguments = _referenceList(typeArguments),
+        this.continuation = new Reference<Continuation>(cont);
 
-  accept(Visitor visitor) => visitor.visitConcatenateStrings(this);
+  accept(Visitor visitor) => visitor.visitTypeCast(this);
+}
+
+/// Apply a built-in operator.
+///
+/// It must be known that the arguments have the proper types.
+class ApplyBuiltinOperator extends Primitive {
+  BuiltinOperator operator;
+  List<Reference<Primitive>> arguments;
+
+  ApplyBuiltinOperator(this.operator, List<Primitive> arguments)
+      : this.arguments = _referenceList(arguments);
+
+  accept(Visitor visitor) => visitor.visitApplyBuiltinOperator(this);
 }
 
 /// Throw a value.
@@ -439,6 +487,14 @@
   accept(Visitor visitor) => visitor.visitNonTailThrow(this);
 }
 
+/// An expression that is known to be unreachable.
+///
+/// This can be placed as the body of a call continuation, when the caller is
+/// known never to invoke it, e.g. because the calling expression always throws.
+class Unreachable extends Expression {
+  accept(Visitor visitor) => visitor.visitUnreachable(this);
+}
+
 /// Gets the value from a [MutableVariable].
 ///
 /// [MutableVariable]s can be seen as ref cells that are not first-class
@@ -554,14 +610,24 @@
 }
 
 /// Directly reads from a field on a given object.
+///
+/// The [object] must either be `null` or an object that has [field].
 class GetField extends Primitive {
   final Reference<Primitive> object;
   FieldElement field;
 
+  /// True if the receiver is known not to be null.
+  // TODO(asgerf): This is a placeholder until we agree on how to track
+  //               side effects.
+  bool objectIsNotNull = false;
+
   GetField(Primitive object, this.field)
       : this.object = new Reference<Primitive>(object);
 
   accept(Visitor visitor) => visitor.visitGetField(this);
+
+  @override
+  bool get isSafeForElimination => objectIsNotNull;
 }
 
 /// Reads the value of a static field or tears off a static method.
@@ -641,19 +707,6 @@
   accept(Visitor visitor) => visitor.visitCreateInstance(this);
 }
 
-/// Compare objects for identity.
-///
-/// It is an error pass in a value that does not correspond to a Dart value,
-/// such as an interceptor or a box.
-class Identical extends Primitive {
-  final Reference<Primitive> left;
-  final Reference<Primitive> right;
-  Identical(Primitive left, Primitive right)
-      : left = new Reference<Primitive>(left),
-        right = new Reference<Primitive>(right);
-  accept(Visitor visitor) => visitor.visitIdentical(this);
-}
-
 class Interceptor extends Primitive {
   final Reference<Primitive> input;
   final Set<ClassElement> interceptedClasses;
@@ -673,11 +726,30 @@
   accept(Visitor visitor) => visitor.visitCreateInvocationMirror(this);
 }
 
+class ForeignCode extends Expression {
+  final js.Template codeTemplate;
+  final types.TypeMask type;
+  final List<Reference<Primitive>> arguments;
+  final native.NativeBehavior nativeBehavior;
+  final FunctionElement dependency;
+
+  /// The continuation, if the foreign code is not a JavaScript 'throw',
+  /// otherwise null.
+  final Reference<Continuation> continuation;
+
+  ForeignCode(this.codeTemplate, this.type, List<Primitive> arguments,
+      this.nativeBehavior, {Continuation continuation, this.dependency})
+      : arguments = _referenceList(arguments),
+        continuation = continuation == null ? null
+            : new Reference<Continuation>(continuation);
+
+  accept(Visitor visitor) => visitor.visitForeignCode(this);
+}
+
 class Constant extends Primitive {
-  final ConstantExpression expression;
   final values.ConstantValue value;
 
-  Constant(this.expression, this.value);
+  Constant(this.value);
 
   accept(Visitor visitor) => visitor.visitConstant(this);
 }
@@ -871,15 +943,15 @@
   T visitInvokeMethod(InvokeMethod node);
   T visitInvokeMethodDirectly(InvokeMethodDirectly node);
   T visitInvokeConstructor(InvokeConstructor node);
-  T visitConcatenateStrings(ConcatenateStrings node);
   T visitThrow(Throw node);
   T visitRethrow(Rethrow node);
   T visitBranch(Branch node);
-  T visitTypeOperator(TypeOperator node);
+  T visitTypeCast(TypeCast node);
   T visitSetMutableVariable(SetMutableVariable node);
   T visitSetStatic(SetStatic node);
   T visitGetLazyStatic(GetLazyStatic node);
   T visitSetField(SetField node);
+  T visitUnreachable(Unreachable node);
 
   // Definitions.
   T visitLiteralList(LiteralList node);
@@ -892,7 +964,6 @@
   T visitMutableVariable(MutableVariable node);
   T visitNonTailThrow(NonTailThrow node);
   T visitGetStatic(GetStatic node);
-  T visitIdentical(Identical node);
   T visitInterceptor(Interceptor node);
   T visitCreateInstance(CreateInstance node);
   T visitGetField(GetField node);
@@ -901,9 +972,14 @@
   T visitReadTypeVariable(ReadTypeVariable node);
   T visitTypeExpression(TypeExpression node);
   T visitCreateInvocationMirror(CreateInvocationMirror node);
+  T visitTypeTest(TypeTest node);
+  T visitApplyBuiltinOperator(ApplyBuiltinOperator node);
 
   // Conditions.
   T visitIsTrue(IsTrue node);
+
+  // Support for literal foreign code.
+  T visitForeignCode(ForeignCode node);
 }
 
 /// Recursively visits the entire CPS term, and calls abstract `process*`
@@ -992,13 +1068,6 @@
     node.arguments.forEach(processReference);
   }
 
-  processConcatenateStrings(ConcatenateStrings node) {}
-  visitConcatenateStrings(ConcatenateStrings node) {
-    processConcatenateStrings(node);
-    processReference(node.continuation);
-    node.arguments.forEach(processReference);
-  }
-
   processThrow(Throw node) {}
   visitThrow(Throw node) {
     processThrow(node);
@@ -1018,14 +1087,21 @@
     visit(node.condition);
   }
 
-  processTypeOperator(TypeOperator node) {}
-  visitTypeOperator(TypeOperator node) {
-    processTypeOperator(node);
+  processTypeCast(TypeCast node) {}
+  visitTypeCast(TypeCast node) {
+    processTypeCast(node);
     processReference(node.continuation);
     processReference(node.value);
     node.typeArguments.forEach(processReference);
   }
 
+  processTypeTest(TypeTest node) {}
+  visitTypeTest(TypeTest node) {
+    processTypeTest(node);
+    processReference(node.value);
+    node.typeArguments.forEach(processReference);
+  }
+
   processSetMutableVariable(SetMutableVariable node) {}
   visitSetMutableVariable(SetMutableVariable node) {
     processSetMutableVariable(node);
@@ -1095,13 +1171,6 @@
     processReference(node.value);
   }
 
-  processIdentical(Identical node) {}
-  visitIdentical(Identical node) {
-    processIdentical(node);
-    processReference(node.left);
-    processReference(node.right);
-  }
-
   processInterceptor(Interceptor node) {}
   visitInterceptor(Interceptor node) {
     processInterceptor(node);
@@ -1175,4 +1244,37 @@
     processCreateInvocationMirror(node);
     node.arguments.forEach(processReference);
   }
+
+  processApplyBuiltinOperator(ApplyBuiltinOperator node) {}
+  visitApplyBuiltinOperator(ApplyBuiltinOperator node) {
+    processApplyBuiltinOperator(node);
+    node.arguments.forEach(processReference);
+  }
+
+  processForeignCode(ForeignCode node) {}
+  visitForeignCode(ForeignCode node) {
+    processForeignCode(node);
+    if (node.continuation != null) {
+      processReference(node.continuation);
+    }
+    node.arguments.forEach(processReference);
+  }
+
+  processUnreachable(Unreachable node) {}
+  visitUnreachable(Unreachable node) {
+    processUnreachable(node);
+  }
+}
+
+/// Visit a just-deleted subterm and unlink all [Reference]s in it.
+class RemovalVisitor extends RecursiveVisitor {
+  const RemovalVisitor();
+
+  processReference(Reference reference) {
+    reference.unlink();
+  }
+
+  static void remove(Node node) {
+    (const RemovalVisitor()).visit(node);
+  }
 }
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 ed8d685..528edc2 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
@@ -173,12 +173,6 @@
     return '$indentation(InvokeConstructor $callName $args $cont)';
   }
 
-  String visitConcatenateStrings(ConcatenateStrings node) {
-    String cont = access(node.continuation);
-    String args = node.arguments.map(access).join(' ');
-    return '$indentation(ConcatenateStrings ($args) $cont)';
-  }
-
   String visitInvokeContinuation(InvokeContinuation node) {
     String name = access(node.continuation);
     if (node.isRecursive) name = 'rec $name';
@@ -202,6 +196,10 @@
     return '$indentation(Branch $condition $trueCont $falseCont)';
   }
 
+  String visitUnreachable(Unreachable node) {
+    return '$indentation(Unreachable)';
+  }
+
   String visitConstant(Constant node) {
     String value = node.value.accept(new ConstantStringifier(), null);
     return '(Constant $value)';
@@ -229,13 +227,17 @@
            '$value\n$body)';
   }
 
-  String visitTypeOperator(TypeOperator node) {
+  String visitTypeCast(TypeCast node) {
     String value = access(node.value);
     String cont = access(node.continuation);
-    String operator = node.isTypeTest ? 'is' : 'as';
     String typeArguments = node.typeArguments.map(access).join(' ');
-    return '$indentation(TypeOperator $operator $value ${node.type} '
-           '($typeArguments) $cont)';
+    return '$indentation(TypeCast $value ${node.type} ($typeArguments) $cont)';
+  }
+
+  String visitTypeTest(TypeTest node) {
+    String value = access(node.value);
+    String typeArguments = node.typeArguments.map(access).join(' ');
+    return '(TypeTest $value ${node.type} ($typeArguments))';
   }
 
   String visitLiteralList(LiteralList node) {
@@ -297,12 +299,6 @@
     return '(CreateInstance $className ($arguments)$typeInformation)';
   }
 
-  String visitIdentical(Identical node) {
-    String left = access(node.left);
-    String right = access(node.right);
-    return '(Identical $left $right)';
-  }
-
   String visitInterceptor(Interceptor node) {
     return '(Interceptor ${access(node.input)})';
   }
@@ -316,8 +312,8 @@
   }
 
   String visitTypeExpression(TypeExpression node) {
-    String args = node.arguments.map(access).join(', ');
-    return '(TypeExpression ${node.dartType.toString()} $args)';
+    String args = node.arguments.map(access).join(' ');
+    return '(TypeExpression ${node.dartType} ($args))';
   }
 
   String visitNonTailThrow(NonTailThrow node) {
@@ -327,8 +323,22 @@
 
   String visitCreateInvocationMirror(CreateInvocationMirror node) {
     String selector = node.selector.name;
-    String args = node.arguments.map(access).join(', ');
-    return '(CreateInvocationMirror $selector $args)';
+    String args = node.arguments.map(access).join(' ');
+    return '(CreateInvocationMirror $selector ($args))';
+  }
+
+  String visitApplyBuiltinOperator(ApplyBuiltinOperator node) {
+    String operator = node.operator.toString();
+    String args = node.arguments.map(access).join(' ');
+    return '(ApplyBuiltinOperator $operator ($args))';
+  }
+
+  @override
+  String visitForeignCode(ForeignCode node) {
+    String arguments = node.arguments.map(access).join(' ');
+    String continuation = node.continuation == null ? ''
+        : ' ${access(node.continuation)}';
+    return '(JS ${node.type} ${node.codeTemplate} ($arguments)$continuation)';
   }
 }
 
@@ -395,7 +405,7 @@
     return _failWith(constant);
   }
 
-  String visitDummy(DummyConstantValue constant, _) {
+  String visitSynthetic(SyntheticConstantValue constant, _) {
     return _failWith(constant);
   }
 
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 c0097e9..56d5896 100644
--- a/pkg/compiler/lib/src/cps_ir/cps_ir_tracer.dart
+++ b/pkg/compiler/lib/src/cps_ir/cps_ir_tracer.dart
@@ -175,13 +175,6 @@
     printStmt(dummy, "InvokeConstructor $callName ($args) $kont");
   }
 
-  visitConcatenateStrings(cps_ir.ConcatenateStrings node) {
-    String dummy = names.name(node);
-    String args = node.arguments.map(formatReference).join(', ');
-    String kont = formatReference(node.continuation);
-    printStmt(dummy, "ConcatenateStrings ($args) $kont");
-  }
-
   visitThrow(cps_ir.Throw node) {
     String dummy = names.name(node);
     String value = formatReference(node.value);
@@ -193,6 +186,11 @@
     printStmt(dummy, "Rethrow");
   }
 
+  visitUnreachable(cps_ir.Unreachable node) {
+    String dummy = names.name(node);
+    printStmt(dummy, 'Unreachable');
+  }
+
   visitLiteralList(cps_ir.LiteralList node) {
     String dummy = names.name(node);
     String values = node.values.map(formatReference).join(', ');
@@ -210,13 +208,12 @@
     printStmt(dummy, "LiteralMap (${entries.join(', ')})");
   }
 
-  visitTypeOperator(cps_ir.TypeOperator node) {
+  visitTypeCast(cps_ir.TypeCast node) {
     String dummy = names.name(node);
-    String operator = node.isTypeTest ? 'is' : 'as';
-    List<String> entries = new List<String>();
     String value = formatReference(node.value);
+    String args = node.typeArguments.map(formatReference).join(', ');
     String kont = formatReference(node.continuation);
-    printStmt(dummy, "TypeOperator ($operator $value ${node.type}) $kont");
+    printStmt(dummy, "TypeCast ($value ${node.type} ($args)) $kont");
   }
 
   visitInvokeContinuation(cps_ir.InvokeContinuation node) {
@@ -319,12 +316,6 @@
     return 'CreateInstance $className ($arguments) <$typeInformation>';
   }
 
-  visitIdentical(cps_ir.Identical node) {
-    String left = formatReference(node.left);
-    String right = formatReference(node.right);
-    return "Identical($left, $right)";
-  }
-
   visitInterceptor(cps_ir.Interceptor node) {
     return "Interceptor(${formatReference(node.input)})";
   }
@@ -361,6 +352,28 @@
     String args = node.arguments.map(formatReference).join(', ');
     return "CreateInvocationMirror(${node.selector.name}, $args)";
   }
+
+  visitTypeTest(cps_ir.TypeTest node) {
+    String value = formatReference(node.value);
+    String args = node.typeArguments.map(formatReference).join(', ');
+    return "TypeTest ($value ${node.type} ($args))";
+  }
+
+  visitApplyBuiltinOperator(cps_ir.ApplyBuiltinOperator node) {
+    String operator = node.operator.toString();
+    String args = node.arguments.map(formatReference).join(', ');
+    return 'ApplyBuiltinOperator $operator ($args)';
+  }
+
+  @override
+  visitForeignCode(cps_ir.ForeignCode node) {
+    String id = names.name(node);
+    String arguments = node.arguments.map(formatReference).join(', ');
+    String continuation = node.continuation == null ? ''
+        : ' ${formatReference(node.continuation)}';
+    printStmt(id, "ForeignCode ${node.type} ${node.codeTemplate} $arguments"
+        "$continuation");
+  }
 }
 
 /**
@@ -487,16 +500,15 @@
     addEdgeToContinuation(exp.continuation);
   }
 
-  visitConcatenateStrings(cps_ir.ConcatenateStrings exp) {
-    addEdgeToContinuation(exp.continuation);
-  }
-
   visitThrow(cps_ir.Throw exp) {
   }
 
   visitRethrow(cps_ir.Rethrow exp) {
   }
 
+  visitUnreachable(cps_ir.Unreachable node) {
+  }
+
   visitSetMutableVariable(cps_ir.SetMutableVariable exp) {
     visit(exp.body);
   }
@@ -524,7 +536,7 @@
     }
   }
 
-  visitTypeOperator(cps_ir.TypeOperator exp) {
+  visitTypeCast(cps_ir.TypeCast exp) {
     addEdgeToContinuation(exp.continuation);
   }
 
@@ -544,42 +556,51 @@
   visitLiteralList(cps_ir.LiteralList node) {
     unexpectedNode(node);
   }
+
   visitLiteralMap(cps_ir.LiteralMap node) {
     unexpectedNode(node);
   }
+
   visitConstant(cps_ir.Constant node) {
     unexpectedNode(node);
   }
+
   visitCreateFunction(cps_ir.CreateFunction node) {
     unexpectedNode(node);
   }
+
   visitGetMutableVariable(cps_ir.GetMutableVariable node) {
     unexpectedNode(node);
   }
+
   visitParameter(cps_ir.Parameter node) {
     unexpectedNode(node);
   }
+
   visitMutableVariable(cps_ir.MutableVariable node) {
     unexpectedNode(node);
   }
+
   visitGetField(cps_ir.GetField node) {
     unexpectedNode(node);
   }
+
   visitGetStatic(cps_ir.GetStatic node) {
     unexpectedNode(node);
   }
+
   visitCreateBox(cps_ir.CreateBox node) {
     unexpectedNode(node);
   }
+
   visitCreateInstance(cps_ir.CreateInstance node) {
     unexpectedNode(node);
   }
+
   visitIsTrue(cps_ir.IsTrue node) {
     unexpectedNode(node);
   }
-  visitIdentical(cps_ir.Identical node) {
-    unexpectedNode(node);
-  }
+
   visitInterceptor(cps_ir.Interceptor node) {
     unexpectedNode(node);
   }
@@ -603,4 +624,19 @@
   visitCreateInvocationMirror(cps_ir.CreateInvocationMirror node) {
     unexpectedNode(node);
   }
+
+  visitTypeTest(cps_ir.TypeTest node) {
+    unexpectedNode(node);
+  }
+
+  visitApplyBuiltinOperator(cps_ir.ApplyBuiltinOperator node) {
+    unexpectedNode(node);
+  }
+
+  @override
+  visitForeignCode(cps_ir.ForeignCode node) {
+    if (node.continuation != null) {
+      addEdgeToContinuation(node.continuation);
+    }
+  }
 }
diff --git a/pkg/compiler/lib/src/cps_ir/optimizers.dart b/pkg/compiler/lib/src/cps_ir/optimizers.dart
index f1007c6..c80dfb0 100644
--- a/pkg/compiler/lib/src/cps_ir/optimizers.dart
+++ b/pkg/compiler/lib/src/cps_ir/optimizers.dart
@@ -6,8 +6,7 @@
 
 import 'cps_ir_nodes.dart';
 
-export 'type_propagation.dart' show TypePropagator, TypeSystem,
-                                    UnitTypeSystem, TypeMaskSystem;
+export 'type_propagation.dart' show TypePropagator;
 export 'redundant_phi.dart' show RedundantPhiEliminator;
 export 'shrinking_reductions.dart' show ShrinkingReducer, ParentVisitor;
 
diff --git a/pkg/compiler/lib/src/cps_ir/shrinking_reductions.dart b/pkg/compiler/lib/src/cps_ir/shrinking_reductions.dart
index ea14f3c..fb62a72 100644
--- a/pkg/compiler/lib/src/cps_ir/shrinking_reductions.dart
+++ b/pkg/compiler/lib/src/cps_ir/shrinking_reductions.dart
@@ -246,8 +246,11 @@
   }
 }
 
-/// Returns true iff the bound primitive is unused.
-bool _isDeadVal(LetPrim node) => !node.primitive.hasAtLeastOneUse;
+/// Returns true iff the bound primitive is unused, and has no effects
+/// preventing it from being eliminated.
+bool _isDeadVal(LetPrim node) {
+  return node.primitive.hasNoUses && node.primitive.isSafeForElimination;
+}
 
 /// Returns true iff the continuation is unused.
 bool _isDeadCont(Continuation cont) {
@@ -275,9 +278,12 @@
 
   // Beta-reduction will move the continuation's body to its unique invocation
   // site.  This is not safe if the body is moved into an exception handler
-  // binding.
+  // binding.  Search from the invocation to the continuation binding to
+  // make sure that there is no binding for a handler.
   Node current = invoke.parent;
   while (current != cont.parent) {
+    // There is no need to reduce a beta-redex inside a deleted subterm.
+    if (current == ShrinkingReducer._DELETED) return false;
     if (current is LetHandler) return false;
     current = current.parent;
   }
@@ -551,23 +557,23 @@
     node.arguments.forEach((Reference ref) => ref.parent = node);
   }
 
-  processConcatenateStrings(ConcatenateStrings node) {
-    node.continuation.parent = node;
-    node.arguments.forEach((Reference ref) => ref.parent = node);
-  }
-
   processBranch(Branch node) {
     node.condition.parent = node;
     node.trueContinuation.parent = node;
     node.falseContinuation.parent = node;
   }
 
-  processTypeOperator(TypeOperator node) {
+  processTypeCast(TypeCast node) {
     node.typeArguments.forEach((Reference ref) => ref.parent = node);
     node.continuation.parent = node;
     node.value.parent = node;
   }
 
+  processTypeTest(TypeTest node) {
+    node.typeArguments.forEach((Reference ref) => ref.parent = node);
+    node.value.parent = node;
+  }
+
   processSetMutableVariable(SetMutableVariable node) {
     node.variable.parent = node;
     node.body.parent = node;
@@ -610,11 +616,6 @@
     node.value.parent = node;
   }
 
-  processIdentical(Identical node) {
-    node.left.parent = node;
-    node.right.parent = node;
-  }
-
   processInterceptor(Interceptor node) {
     node.input.parent = node;
   }
@@ -664,6 +665,17 @@
   processCreateInvocationMirror(CreateInvocationMirror node) {
     node.arguments.forEach((Reference ref) => ref.parent = node);
   }
+
+  processApplyBuiltinOperator(ApplyBuiltinOperator node) {
+    node.arguments.forEach((Reference ref) => ref.parent = node);
+  }
+
+  processForeignCode(ForeignCode node) {
+    if (node.continuation != null) {
+      node.continuation.parent = node;
+    }
+    node.arguments.forEach((Reference ref) => ref.parent = node);
+  }
 }
 
 class _ReductionKind {
diff --git a/pkg/compiler/lib/src/cps_ir/type_propagation.dart b/pkg/compiler/lib/src/cps_ir/type_propagation.dart
index b9db352..a8a7ee2 100644
--- a/pkg/compiler/lib/src/cps_ir/type_propagation.dart
+++ b/pkg/compiler/lib/src/cps_ir/type_propagation.dart
@@ -5,95 +5,53 @@
 import 'optimizers.dart' show Pass, ParentVisitor;
 
 import '../constants/constant_system.dart';
-import '../constants/expressions.dart';
 import '../resolution/operators.dart';
 import '../constants/values.dart';
 import '../dart_types.dart' as types;
 import '../dart2jslib.dart' as dart2js;
-import '../tree/tree.dart' show LiteralDartString;
+import '../tree/tree.dart' show DartString, ConsDartString, LiteralDartString;
 import 'cps_ir_nodes.dart';
-import '../types/types.dart' show TypeMask, TypesTask;
+import '../types/types.dart';
 import '../types/constants.dart' show computeTypeMask;
-import '../elements/elements.dart' show ClassElement, Element, Entity,
-    FieldElement, FunctionElement, ParameterElement;
-import '../dart2jslib.dart' show ClassWorld;
+import '../elements/elements.dart';
+import '../dart2jslib.dart' show ClassWorld, World;
 import '../universe/universe.dart';
+import '../js_backend/js_backend.dart' show JavaScriptBackend;
 
-abstract class TypeSystem<T> {
-  T get dynamicType;
-  T get typeType;
-  T get functionType;
-  T get boolType;
-  T get intType;
-  T get stringType;
-  T get listType;
-  T get mapType;
-  T get nonNullType;
-
-  T getReturnType(FunctionElement element);
-  T getSelectorReturnType(Selector selector);
-  T getParameterType(ParameterElement element);
-  T getFieldType(FieldElement element);
-  T join(T a, T b);
-  T exact(ClassElement element);
-  T getTypeOf(ConstantValue constant);
-
-  bool areDisjoint(T leftType, T rightType);
-
-  /// True if all values satisfying [type] are booleans (null is not a boolean).
-  bool isDefinitelyBool(T type);
-
-  bool isDefinitelyNotNull(T type);
+enum AbstractBool {
+  True, False, Maybe, Nothing
 }
 
-class UnitTypeSystem implements TypeSystem<String> {
-  static const String UNIT = 'unit';
-
-  get boolType => UNIT;
-  get dynamicType => UNIT;
-  get functionType => UNIT;
-  get intType => UNIT;
-  get listType => UNIT;
-  get mapType => UNIT;
-  get stringType => UNIT;
-  get typeType => UNIT;
-  get nonNullType => UNIT;
-
-  getParameterType(_) => UNIT;
-  getReturnType(_) => UNIT;
-  getSelectorReturnType(_) => UNIT;
-  getFieldType(_) => UNIT;
-  join(a, b) => UNIT;
-  exact(_) => UNIT;
-  getTypeOf(_) => UNIT;
-
-  bool isDefinitelyBool(_) => false;
-
-  bool isDefinitelyNotNull(_) => false;
-
-  bool areDisjoint(String leftType, String rightType) {
-    return false;
-  }
-}
-
-class TypeMaskSystem implements TypeSystem<TypeMask> {
+class TypeMaskSystem {
   final TypesTask inferrer;
-  final ClassWorld classWorld;
+  final World classWorld;
 
   TypeMask get dynamicType => inferrer.dynamicType;
   TypeMask get typeType => inferrer.typeType;
   TypeMask get functionType => inferrer.functionType;
   TypeMask get boolType => inferrer.boolType;
   TypeMask get intType => inferrer.intType;
+  TypeMask get doubleType => inferrer.doubleType;
+  TypeMask get numType => inferrer.numType;
   TypeMask get stringType => inferrer.stringType;
   TypeMask get listType => inferrer.listType;
   TypeMask get mapType => inferrer.mapType;
   TypeMask get nonNullType => inferrer.nonNullType;
 
+  TypeMask numStringBoolType;
+
   // TODO(karlklose): remove compiler here.
   TypeMaskSystem(dart2js.Compiler compiler)
     : inferrer = compiler.typesTask,
-      classWorld = compiler.world;
+      classWorld = compiler.world {
+    numStringBoolType =
+      new TypeMask.unionOf(<TypeMask>[numType, stringType, boolType],
+                           classWorld);
+  }
+
+  Element locateSingleElement(TypeMask mask, Selector selector) {
+    return mask.locateSingleElement(selector, mask, classWorld.compiler);
+  }
 
   TypeMask getParameterType(ParameterElement parameter) {
     return inferrer.getGuaranteedTypeOfElement(parameter);
@@ -103,43 +61,308 @@
     return inferrer.getGuaranteedReturnTypeOfElement(function);
   }
 
-  TypeMask getSelectorReturnType(Selector selector) {
-    return inferrer.getGuaranteedTypeOfSelector(selector);
+  TypeMask getInvokeReturnType(Selector selector, TypeMask mask) {
+    return inferrer.getGuaranteedTypeOfSelector(selector, mask);
   }
 
   TypeMask getFieldType(FieldElement field) {
     return inferrer.getGuaranteedTypeOfElement(field);
   }
 
-  @override
   TypeMask join(TypeMask a, TypeMask b) {
     return a.union(b, classWorld);
   }
 
-  @override
   TypeMask getTypeOf(ConstantValue constant) {
     return computeTypeMask(inferrer.compiler, constant);
   }
 
-  TypeMask exact(ClassElement element) {
+  TypeMask nonNullExact(ClassElement element) {
     // The class world does not know about classes created by
     // closure conversion, so just treat those as a subtypes of Function.
     // TODO(asgerf): Maybe closure conversion should create a new ClassWorld?
     if (element.isClosure) return functionType;
-    return new TypeMask.exact(element, classWorld);
+    return new TypeMask.nonNullExact(element, classWorld);
   }
 
-  bool isDefinitelyBool(TypeMask t) {
-    return t.containsOnlyBool(classWorld) && !t.isNullable;
+  bool isDefinitelyBool(TypeMask t, {bool allowNull: false}) {
+    if (!allowNull && t.isNullable) return false;
+    return t.containsOnlyBool(classWorld);
   }
 
-  bool isDefinitelyNotNull(TypeMask t) => !t.isNullable;
+  bool isDefinitelyNum(TypeMask t, {bool allowNull: false}) {
+    if (!allowNull && t.isNullable) return false;
+    return t.containsOnlyNum(classWorld);
+  }
 
-  @override
+  bool isDefinitelyString(TypeMask t, {bool allowNull: false}) {
+    if (!allowNull && t.isNullable) return false;
+    return t.containsOnlyString(classWorld);
+  }
+
+  bool isDefinitelyNumStringBool(TypeMask t, {bool allowNull: false}) {
+    if (!allowNull && t.isNullable) return false;
+    return numStringBoolType.containsMask(t, classWorld);
+  }
+
+  bool isDefinitelyNotNumStringBool(TypeMask t) {
+    return areDisjoint(t, numStringBoolType);
+  }
+
+  /// True if all values of [t] are either integers or not numbers at all.
+  ///
+  /// This does not imply that the value is an integer, since most other values
+  /// such as null are also not a non-integer double.
+  bool isDefinitelyNotNonIntegerDouble(TypeMask t) {
+    // Even though int is a subclass of double in the JS type system, we can
+    // still check this with disjointness, because [doubleType] is the *exact*
+    // double class, so this excludes things that are known to be instances of a
+    // more specific class.
+    // We currently exploit that there are no subclasses of double that are
+    // not integers (e.g. there is no UnsignedDouble class or whatever).
+    return areDisjoint(t, doubleType);
+  }
+
   bool areDisjoint(TypeMask leftType, TypeMask rightType) {
     TypeMask intersection = leftType.intersection(rightType, classWorld);
     return intersection.isEmpty && !intersection.isNullable;
   }
+
+  AbstractBool isSubtypeOf(TypeMask value,
+                           types.DartType type,
+                           {bool allowNull}) {
+    assert(allowNull != null);
+    if (type is types.DynamicType) {
+      return AbstractBool.True;
+    }
+    if (type is types.InterfaceType) {
+      TypeMask typeAsMask = allowNull
+          ? new TypeMask.subtype(type.element, classWorld)
+          : new TypeMask.nonNullSubtype(type.element, classWorld);
+      if (areDisjoint(value, typeAsMask)) {
+        // Disprove the subtype relation based on the class alone.
+        return AbstractBool.False;
+      }
+      if (!type.treatAsRaw) {
+        // If there are type arguments, we cannot prove the subtype relation,
+        // because the type arguments are unknown on both the value and type.
+        return AbstractBool.Maybe;
+      }
+      if (typeAsMask.containsMask(value, classWorld)) {
+        // All possible values are contained in the set of allowed values.
+        // Note that we exploit the fact that [typeAsMask] is an exact
+        // representation of [type], not an approximation.
+        return AbstractBool.True;
+      }
+      // The value is neither contained in the type, nor disjoint from the type.
+      return AbstractBool.Maybe;
+    }
+    // TODO(asgerf): Support function types, and what else might be missing.
+    return AbstractBool.Maybe;
+  }
+}
+
+class ConstantPropagationLattice {
+  final TypeMaskSystem typeSystem;
+  final ConstantSystem constantSystem;
+  final types.DartTypes dartTypes;
+  final AbstractValue anything;
+
+  ConstantPropagationLattice(TypeMaskSystem typeSystem,
+                             this.constantSystem,
+                             this.dartTypes)
+    : this.typeSystem = typeSystem,
+      anything = new AbstractValue.nonConstant(typeSystem.dynamicType);
+
+  final AbstractValue nothing = new AbstractValue.nothing();
+
+  AbstractValue constant(ConstantValue value, [TypeMask type]) {
+    if (type == null) type = typeSystem.getTypeOf(value);
+    return new AbstractValue.constantValue(value, type);
+  }
+
+  AbstractValue nonConstant([TypeMask type]) {
+    if (type == null) type = typeSystem.dynamicType;
+    return new AbstractValue.nonConstant(type);
+  }
+
+  /// Compute the join of two values in the lattice.
+  AbstractValue join(AbstractValue x, AbstractValue y) {
+    assert(x != null);
+    assert(y != null);
+
+    if (x.isNothing) {
+      return y;
+    } else if (y.isNothing) {
+      return x;
+    } else if (x.isConstant && y.isConstant && x.constant == y.constant) {
+      return x;
+    } else {
+      return new AbstractValue.nonConstant(typeSystem.join(x.type, y.type));
+    }
+  }
+
+  /// True if all members of this value are booleans.
+  bool isDefinitelyBool(AbstractValue value, {bool allowNull: false}) {
+    return value.isNothing ||
+      typeSystem.isDefinitelyBool(value.type, allowNull: allowNull);
+  }
+
+  /// True if all members of this value are numbers.
+  bool isDefinitelyNum(AbstractValue value, {bool allowNull: false}) {
+    return value.isNothing ||
+      typeSystem.isDefinitelyNum(value.type, allowNull: allowNull);
+  }
+
+  /// True if all members of this value are strings.
+  bool isDefinitelyString(AbstractValue value, {bool allowNull: false}) {
+    return value.isNothing ||
+      typeSystem.isDefinitelyString(value.type, allowNull: allowNull);
+  }
+
+  /// True if all members of this value are numbers, strings, or booleans.
+  bool isDefinitelyNumStringBool(AbstractValue value, {bool allowNull: false}) {
+    return value.isNothing ||
+      typeSystem.isDefinitelyNumStringBool(value.type, allowNull: allowNull);
+  }
+
+  /// True if this value cannot be a string, number, or boolean.
+  bool isDefinitelyNotNumStringBool(AbstractValue value) {
+    return value.isNothing ||
+      typeSystem.isDefinitelyNotNumStringBool(value.type);
+  }
+
+  /// True if this value cannot be a non-integer double.
+  ///
+  /// In other words, if true is returned, and the value is a number, then
+  /// it is a whole number and is not NaN, Infinity, or minus Infinity.
+  bool isDefinitelyNotNonIntegerDouble(AbstractValue value) {
+    return value.isNothing ||
+      value.isConstant && !value.constant.isDouble ||
+      typeSystem.isDefinitelyNotNonIntegerDouble(value.type);
+  }
+
+  /// Returns whether the given [value] is an instance of [type].
+  ///
+  /// Since [value] and [type] are not always known, [AbstractBool.Maybe] is
+  /// returned if the answer is not known.
+  ///
+  /// [AbstractBool.Nothing] is returned if [value] is nothing.
+  ///
+  /// If [allowNull] is true, `null` is considered an instance of anything,
+  /// otherwise it is only considered an instance of [Object], [dynamic], and
+  /// [Null].
+  AbstractBool isSubtypeOf(AbstractValue value,
+                           types.DartType type,
+                           {bool allowNull}) {
+    assert(allowNull != null);
+    if (value.isNothing) {
+      return AbstractBool.Nothing;
+    }
+    if (value.isConstant) {
+      if (value.constant.isNull) {
+        if (allowNull ||
+            type.isObject ||
+            type.isDynamic ||
+            type == dartTypes.coreTypes.nullType) {
+          return AbstractBool.True;
+        }
+        if (type is types.TypeVariableType) {
+          return AbstractBool.Maybe;
+        }
+        return AbstractBool.False;
+      }
+      if (type == dartTypes.coreTypes.intType) {
+        return constantSystem.isInt(value.constant)
+          ? AbstractBool.True
+          : AbstractBool.False;
+      }
+      types.DartType valueType = value.constant.getType(dartTypes.coreTypes);
+      if (constantSystem.isSubtype(dartTypes, valueType, type)) {
+        return AbstractBool.True;
+      }
+      if (!dartTypes.isPotentialSubtype(valueType, type)) {
+        return AbstractBool.False;
+      }
+      return AbstractBool.Maybe;
+    }
+    return typeSystem.isSubtypeOf(value.type, type, allowNull: allowNull);
+  }
+
+  /// Returns the possible results of applying [operator] to [value],
+  /// assuming the operation does not throw.
+  ///
+  /// Because we do not explicitly track thrown values, we currently use the
+  /// convention that constant values are returned from this method only
+  /// if the operation is known not to throw.
+  ///
+  /// This method returns `null` if a good result could not be found. In that
+  /// case, it is best to fall back on interprocedural type information.
+  AbstractValue unaryOp(UnaryOperator operator,
+                        AbstractValue value) {
+    // TODO(asgerf): Also return information about whether this can throw?
+    if (value.isNothing) {
+      return nothing;
+    }
+    if (value.isConstant) {
+      UnaryOperation operation = constantSystem.lookupUnary(operator);
+      ConstantValue result = operation.fold(value.constant);
+      if (result == null) return anything;
+      return constant(result);
+    }
+    return null; // TODO(asgerf): Look up type?
+  }
+
+  /// Returns the possible results of applying [operator] to [left], [right],
+  /// assuming the operation does not throw.
+  ///
+  /// Because we do not explicitly track thrown values, we currently use the
+  /// convention that constant values are returned from this method only
+  /// if the operation is known not to throw.
+  ///
+  /// This method returns `null` if a good result could not be found. In that
+  /// case, it is best to fall back on interprocedural type information.
+  AbstractValue binaryOp(BinaryOperator operator,
+                         AbstractValue left,
+                         AbstractValue right) {
+    if (left.isNothing || right.isNothing) {
+      return nothing;
+    }
+    if (left.isConstant && right.isConstant) {
+      BinaryOperation operation = constantSystem.lookupBinary(operator);
+      ConstantValue result = operation.fold(left.constant, right.constant);
+      if (result == null) return anything;
+      return constant(result);
+    }
+    return null; // TODO(asgerf): Look up type?
+  }
+
+  AbstractValue stringConstant(String value) {
+    return constant(new StringConstantValue(new DartString.literal(value)));
+  }
+
+  AbstractValue stringify(AbstractValue value) {
+    if (value.isNothing) return nothing;
+    if (value.isNonConst) return nonConstant(typeSystem.stringType);
+    ConstantValue constantValue = value.constant;
+    if (constantValue is StringConstantValue) {
+      return value;
+    } else if (constantValue is PrimitiveConstantValue) {
+      // Note: The primitiveValue for a StringConstantValue is not suitable
+      // for toString() use since it is a DartString. But the other subclasses
+      // returns an unwrapped Dart value we can safely convert to a string.
+      return stringConstant(constantValue.primitiveValue.toString());
+    } else {
+      return nonConstant(typeSystem.stringType);
+    }
+  }
+
+  /// The possible return types of a method that may be targeted by
+  /// [typedSelector]. If the given selector is not a [TypedSelector], any
+  /// reachable method matching the selector may be targeted.
+  AbstractValue getInvokeReturnType(Selector selector, TypeMask mask) {
+    return nonConstant(typeSystem.getInvokeReturnType(selector, mask));
+  }
 }
 
 /**
@@ -152,107 +375,155 @@
  * Implemented according to 'Constant Propagation with Conditional Branches'
  * by Wegman, Zadeck.
  */
-class TypePropagator<T> extends Pass {
+class TypePropagator extends Pass {
   String get passName => 'Sparse constant propagation';
 
-  final types.DartTypes _dartTypes;
-
+  final dart2js.Compiler _compiler;
   // The constant system is used for evaluation of expressions with constant
   // arguments.
-  final ConstantSystem _constantSystem;
-  final TypeSystem _typeSystem;
+  final ConstantPropagationLattice _lattice;
   final dart2js.InternalErrorFunction _internalError;
-  final Map<Node, _AbstractValue> _types;
+  final Map<Definition, AbstractValue> _values = <Definition, AbstractValue>{};
 
-  TypePropagator(this._dartTypes,
-                 this._constantSystem,
-                 this._typeSystem,
-                 this._internalError)
-      : _types = <Node, _AbstractValue>{};
+  TypePropagator(dart2js.Compiler compiler)
+      : _compiler = compiler,
+        _internalError = compiler.internalError,
+        _lattice = new ConstantPropagationLattice(
+            new TypeMaskSystem(compiler),
+            compiler.backend.constantSystem,
+            compiler.types);
 
   @override
   void rewrite(FunctionDefinition root) {
     // Set all parent pointers.
     new ParentVisitor().visit(root);
 
+    Map<Expression, ConstantValue> replacements = <Expression, ConstantValue>{};
+
     // Analyze. In this phase, the entire term is analyzed for reachability
     // and the abstract value of each expression.
-    _TypePropagationVisitor<T> analyzer = new _TypePropagationVisitor<T>(
-        _constantSystem,
-        _typeSystem,
-        _types,
-        _internalError,
-        _dartTypes);
+    TypePropagationVisitor analyzer = new TypePropagationVisitor(
+        _lattice,
+        _values,
+        replacements,
+        _internalError);
 
     analyzer.analyze(root);
 
     // Transform. Uses the data acquired in the previous analysis phase to
     // replace branches with fixed targets and side-effect-free expressions
-    // with constant results.
-    _TransformingVisitor<T> transformer = new _TransformingVisitor<T>(
-        analyzer.reachableNodes, analyzer.values, _internalError, _typeSystem);
+    // with constant results or existing values that are in scope.
+    TransformingVisitor transformer = new TransformingVisitor(
+        _compiler,
+        _lattice,
+        analyzer.reachableNodes,
+        analyzer.values,
+        replacements,
+        _internalError);
     transformer.transform(root);
   }
 
-  getType(Node node) => _types[node];
+  getType(Node node) => _values[node];
 }
 
+final Map<String, BuiltinOperator> NumBinaryBuiltins =
+  const <String, BuiltinOperator>{
+    '+':  BuiltinOperator.NumAdd,
+    '-':  BuiltinOperator.NumSubtract,
+    '*':  BuiltinOperator.NumMultiply,
+    '&':  BuiltinOperator.NumAnd,
+    '|':  BuiltinOperator.NumOr,
+    '^':  BuiltinOperator.NumXor,
+    '<':  BuiltinOperator.NumLt,
+    '<=': BuiltinOperator.NumLe,
+    '>':  BuiltinOperator.NumGt,
+    '>=': BuiltinOperator.NumGe
+};
+
 /**
  * Uses the information from a preceding analysis pass in order to perform the
  * actual transformations on the CPS graph.
  */
-class _TransformingVisitor<T> extends RecursiveVisitor {
+class TransformingVisitor extends RecursiveVisitor {
   final Set<Node> reachable;
-  final Map<Node, _AbstractValue> values;
-  final TypeSystem<T> typeSystem;
+  final Map<Node, AbstractValue> values;
+  final Map<Expression, ConstantValue> replacements;
+  final ConstantPropagationLattice lattice;
+  final dart2js.Compiler compiler;
+
+  JavaScriptBackend get backend => compiler.backend;
+  TypeMaskSystem get typeSystem => lattice.typeSystem;
+  types.DartTypes get dartTypes => lattice.dartTypes;
 
   final dart2js.InternalErrorFunction internalError;
 
-  _TransformingVisitor(this.reachable,
-                       this.values,
-                       this.internalError,
-                       this.typeSystem);
+  TransformingVisitor(this.compiler,
+                      this.lattice,
+                      this.reachable,
+                      this.values,
+                      this.replacements,
+                      this.internalError);
 
   void transform(FunctionDefinition root) {
     visit(root);
   }
 
-  /// Given an expression with a known constant result and a continuation,
-  /// replaces the expression by a new LetPrim / InvokeContinuation construct.
-  /// `unlink` is a closure responsible for unlinking all removed references.
-  LetPrim constifyExpression(Expression node,
-                             Continuation continuation,
-                             void unlink()) {
-    _AbstractValue value = values[node];
-    if (value == null || !value.isConstant) {
-      return null;
-    }
+  /// Removes the entire subtree of [node] and inserts [replacement].
+  /// All references in the [node] subtree are unlinked, and parent pointers
+  /// in [replacement] are initialized.
+  ///
+  /// [replacement] must be "fresh", i.e. it must not contain significant parts
+  /// of the original IR inside of it since the [ParentVisitor] will
+  /// redundantly reprocess it.
+  void replaceSubtree(Expression node, Expression replacement) {
+    InteriorNode parent = node.parent;
+    parent.body = replacement;
+    replacement.parent = parent;
+    node.parent = null;
+    RemovalVisitor.remove(node);
+    new ParentVisitor().visit(replacement);
+  }
 
+  /// Make a constant primitive for [constant] and set its entry in [values].
+  Constant makeConstantPrimitive(ConstantValue constant) {
+    Constant primitive = new Constant(constant);
+    values[primitive] = new AbstractValue.constantValue(constant,
+        typeSystem.getTypeOf(constant));
+    return primitive;
+  }
+
+  /// Builds `(LetPrim p (InvokeContinuation k p))`.
+  ///
+  /// No parent pointers are set.
+  LetPrim makeLetPrimInvoke(Primitive primitive, Continuation continuation) {
     assert(continuation.parameters.length == 1);
 
-    // Set up the replacement structure.
-    PrimitiveConstantValue primitiveConstant = value.constant;
-    ConstantExpression constExp =
-        const ConstantExpressionCreator().convert(primitiveConstant);
-    Constant constant = new Constant(constExp, primitiveConstant);
-    LetPrim letPrim = new LetPrim(constant);
+    LetPrim letPrim = new LetPrim(primitive);
     InvokeContinuation invoke =
-        new InvokeContinuation(continuation, <Primitive>[constant]);
-
-    invoke.parent = constant.parent = letPrim;
+        new InvokeContinuation(continuation, <Primitive>[primitive]);
     letPrim.body = invoke;
-
-    // Replace the method invocation.
-
-    InteriorNode parent = node.parent;
-    letPrim.parent = parent;
-    parent.body = letPrim;
-
-    unlink();
+    primitive.hint = continuation.parameters.single.hint;
 
     return letPrim;
   }
 
+  /// Side-effect free expressions with constant results are be replaced by:
+  ///
+  ///    (LetPrim p = constant (InvokeContinuation k p)).
+  ///
+  /// The new expression will be visited.
+  ///
+  /// Returns true if the node was replaced.
+  bool constifyExpression(Expression node, Continuation continuation) {
+    ConstantValue constant = replacements[node];
+    if (constant == null) return false;
+    Constant primitive = makeConstantPrimitive(constant);
+    LetPrim letPrim = makeLetPrimInvoke(primitive, continuation);
+    replaceSubtree(node, letPrim);
+    visitLetPrim(letPrim);
+    return true;
+  }
+
   // A branch can be eliminated and replaced by an invocation if only one of
   // the possible continuations is reachable. Removal often leads to both dead
   // primitives (the condition variable) and dead continuations (the unreachable
@@ -280,92 +551,378 @@
     InvokeContinuation invoke =
         new InvokeContinuation(successor, <Primitive>[]);
 
-    InteriorNode parent = node.parent;
-    invoke.parent = parent;
-    parent.body = invoke;
-
-    // Unlink all removed references.
-
-    node.trueContinuation.unlink();
-    node.falseContinuation.unlink();
-    IsTrue isTrue = node.condition;
-    isTrue.value.unlink();
-
+    replaceSubtree(node, invoke);
     visitInvokeContinuation(invoke);
   }
 
-  // Side-effect free method calls with constant results can be replaced by
-  // a LetPrim / InvokeContinuation pair. May lead to dead primitives which
-  // are removed by the shrinking reductions pass.
-  //
-  // (InvokeMethod v0 == v1 k0)
-  // -> (assuming the result is a constant `true`)
-  // (LetPrim v2 (Constant true))
-  // (InvokeContinuation k0 v2)
+  /// True if the given reference is a use that converts its value to a boolean
+  /// and only uses the coerced value.
+  bool isBoolifyingUse(Reference<Primitive> ref) {
+    Node use = ref.parent;
+    return use is IsTrue ||
+      use is ApplyBuiltinOperator && use.operator == BuiltinOperator.IsFalsy;
+  }
+
+  /// True if all uses of [prim] only use its value after boolean conversion.
+  bool isAlwaysBoolified(Primitive prim) {
+    for (Reference ref = prim.firstRef; ref != null; ref = ref.next) {
+      Node use = ref.parent;
+      if (!isBoolifyingUse(ref)) return false;
+    }
+    return true;
+  }
+
+  /// Replaces [node] with a more specialized instruction, if possible.
+  ///
+  /// Returns `true` if the node was replaced.
+  bool specializeInvoke(InvokeMethod node) {
+    Continuation cont = node.continuation.definition;
+    bool replaceWithBinary(BuiltinOperator operator,
+                           Primitive left,
+                           Primitive right) {
+      Primitive prim =
+          new ApplyBuiltinOperator(operator, <Primitive>[left, right]);
+      LetPrim let = makeLetPrimInvoke(prim, cont);
+      replaceSubtree(node, let);
+      visitLetPrim(let);
+      return true; // So returning early is more convenient.
+    }
+    bool replaceWithUnary(BuiltinOperator operator,
+                          Primitive argument) {
+      Primitive prim =
+          new ApplyBuiltinOperator(operator, <Primitive>[argument]);
+      LetPrim let = makeLetPrimInvoke(prim, cont);
+      replaceSubtree(node, let);
+      visitLetPrim(let);
+      return true;
+    }
+
+    if (node.selector.isOperator && node.arguments.length == 2) {
+      // The operators we specialize are are intercepted calls, so the operands
+      // are in the argument list.
+      Primitive leftArg = node.arguments[0].definition;
+      Primitive rightArg = node.arguments[1].definition;
+      AbstractValue left = getValue(leftArg);
+      AbstractValue right = getValue(rightArg);
+
+      if (node.selector.name == '==') {
+        // Equality is special due to its treatment of null values and the
+        // fact that Dart-null corresponds to both JS-null and JS-undefined.
+        // Please see documentation for IsFalsy, StrictEq, and LooseEq.
+        bool isBoolified = isAlwaysBoolified(cont.parameters.single);
+        // Comparison with null constants.
+        if (isBoolified &&
+            right.isNullConstant &&
+            lattice.isDefinitelyNotNumStringBool(left)) {
+          // TODO(asgerf): This is shorter but might confuse te VM? Evaluate.
+          return replaceWithUnary(BuiltinOperator.IsFalsy, leftArg);
+        }
+        if (isBoolified &&
+            left.isNullConstant &&
+            lattice.isDefinitelyNotNumStringBool(right)) {
+          return replaceWithUnary(BuiltinOperator.IsFalsy, rightArg);
+        }
+        if (left.isNullConstant || right.isNullConstant) {
+          return replaceWithBinary(BuiltinOperator.LooseEq, leftArg, rightArg);
+        }
+        // Comparison of numbers, strings, and booleans.
+        if (lattice.isDefinitelyNumStringBool(left, allowNull: true) &&
+            lattice.isDefinitelyNumStringBool(right, allowNull: true) &&
+            !(left.isNullable && right.isNullable)) {
+          return replaceWithBinary(BuiltinOperator.StrictEq, leftArg, rightArg);
+        }
+        if (lattice.isDefinitelyNum(left, allowNull: true) &&
+            lattice.isDefinitelyNum(right, allowNull: true)) {
+          return replaceWithBinary(BuiltinOperator.LooseEq, leftArg, rightArg);
+        }
+        if (lattice.isDefinitelyString(left, allowNull: true) &&
+            lattice.isDefinitelyString(right, allowNull: true)) {
+          return replaceWithBinary(BuiltinOperator.LooseEq, leftArg, rightArg);
+        }
+        if (lattice.isDefinitelyBool(left, allowNull: true) &&
+            lattice.isDefinitelyBool(right, allowNull: true)) {
+          return replaceWithBinary(BuiltinOperator.LooseEq, leftArg, rightArg);
+        }
+      } else {
+        // Try to insert a numeric operator.
+        if (lattice.isDefinitelyNum(left, allowNull: false) &&
+            lattice.isDefinitelyNum(right, allowNull: false)) {
+          BuiltinOperator operator = NumBinaryBuiltins[node.selector.name];
+          if (operator != null) {
+            return replaceWithBinary(operator, leftArg, rightArg);
+          }
+        }
+        else if (lattice.isDefinitelyString(left, allowNull: false) &&
+                 lattice.isDefinitelyString(right, allowNull: false)) {
+          return replaceWithBinary(BuiltinOperator.StringConcatenate,
+                                   leftArg, rightArg);
+        }
+      }
+    }
+    // We should only get here if the node was not specialized.
+    assert(node.parent != null);
+    return false;
+  }
+
+  bool isInterceptedSelector(Selector selector) {
+    return backend.isInterceptedSelector(selector);
+  }
+
+  Primitive getDartReceiver(InvokeMethod node) {
+    if (isInterceptedSelector(node.selector)) {
+      return node.arguments[0].definition;
+    } else {
+      return node.receiver.definition;
+    }
+  }
+
+  Primitive getDartArgument(InvokeMethod node, int n) {
+    if (isInterceptedSelector(node.selector)) {
+      return node.arguments[n+1].definition;
+    } else {
+      return node.arguments[n].definition;
+    }
+  }
+
+  /// If [node] is a getter or setter invocation, tries to replace the
+  /// invocation with a direct access to a field.
+  ///
+  /// Returns `true` if the node was replaced.
+  bool inlineFieldAccess(InvokeMethod node) {
+    if (!node.selector.isGetter && !node.selector.isSetter) return false;
+    AbstractValue receiver = getValue(getDartReceiver(node));
+    if (receiver.isNothing) return false;
+    Element target =
+        typeSystem.locateSingleElement(receiver.type, node.selector);
+    if (target is! FieldElement) return false;
+    // TODO(asgerf): Inlining native fields will make some tests pass for the
+    // wrong reason, so for testing reasons avoid inlining them.
+    if (target.isNative) return false;
+    Continuation cont = node.continuation.definition;
+    if (node.selector.isGetter) {
+      GetField get = new GetField(getDartReceiver(node), target);
+      get.objectIsNotNull = receiver.isDefinitelyNotNull;
+      LetPrim let = makeLetPrimInvoke(get, cont);
+      replaceSubtree(node, let);
+      visitLetPrim(let);
+      return true;
+    } else {
+      if (target.isFinal) return false;
+      assert(cont.parameters.single.hasNoUses);
+      cont.parameters.clear();
+      SetField set = new SetField(getDartReceiver(node),
+                                  target,
+                                  getDartArgument(node, 0));
+      set.body = new InvokeContinuation(cont, <Primitive>[]);
+      replaceSubtree(node, set);
+      visitSetField(set);
+      return true;
+    }
+  }
+
   void visitInvokeMethod(InvokeMethod node) {
     Continuation cont = node.continuation.definition;
-    LetPrim letPrim = constifyExpression(node, cont, () {
-      node.receiver.unlink();
-      node.continuation.unlink();
-      node.arguments.forEach((Reference ref) => ref.unlink());
-    });
+    if (constifyExpression(node, cont)) return;
+    if (specializeInvoke(node)) return;
+    if (inlineFieldAccess(node)) return;
 
-    if (letPrim == null) {
-      _AbstractValue<T> receiver = getValue(node.receiver.definition);
-      node.receiverIsNotNull = receiver.isDefinitelyNotNull(typeSystem);
-      super.visitInvokeMethod(node);
-    } else {
-      visitLetPrim(letPrim);
-    }
+    AbstractValue receiver = getValue(node.receiver.definition);
+    node.receiverIsNotNull = receiver.isDefinitelyNotNull;
+    super.visitInvokeMethod(node);
   }
 
-  // See [visitInvokeMethod].
-  void visitConcatenateStrings(ConcatenateStrings node) {
+  void visitTypeCast(TypeCast node) {
     Continuation cont = node.continuation.definition;
-    LetPrim letPrim = constifyExpression(node, cont, () {
-      node.continuation.unlink();
-      node.arguments.forEach((Reference ref) => ref.unlink());
-    });
 
-    if (letPrim == null) {
-      super.visitConcatenateStrings(node);
-    } else {
-      visitLetPrim(letPrim);
+    AbstractValue value = getValue(node.value.definition);
+    switch (lattice.isSubtypeOf(value, node.type, allowNull: true)) {
+      case AbstractBool.Maybe:
+      case AbstractBool.Nothing:
+        break;
+
+      case AbstractBool.True:
+        // Cast always succeeds, replace it with InvokeContinuation.
+        InvokeContinuation invoke =
+            new InvokeContinuation(cont, <Primitive>[node.value.definition]);
+        replaceSubtree(node, invoke);
+        visitInvokeContinuation(invoke);
+        return;
+
+      case AbstractBool.False:
+        // Cast always fails, remove unreachable continuation body.
+        assert(!reachable.contains(cont));
+        replaceSubtree(cont.body, new Unreachable());
+        break;
     }
+
+    super.visitTypeCast(node);
   }
 
-  // See [visitInvokeMethod].
-  void visitTypeOperator(TypeOperator node) {
+  /// Specialize calls to static methods.
+  ///
+  /// Returns true if the call was replaced.
+  bool specializeInvokeStatic(InvokeStatic node) {
+    // TODO(asgerf): This is written to easily scale to more cases,
+    //               either add more cases or clean up.
     Continuation cont = node.continuation.definition;
-    LetPrim letPrim = constifyExpression(node, cont, () {
-      node.value.unlink();
-      node.typeArguments.forEach((Reference ref) => ref.unlink());
-      node.continuation.unlink();
-    });
+    Primitive arg(int n) => node.arguments[n].definition;
+    AbstractValue argType(int n) => getValue(arg(n));
+    if (node.target.library.isInternalLibrary) {
+      switch(node.target.name) {
+        case InternalMethod.Stringify:
+          if (lattice.isDefinitelyString(argType(0))) {
+            InvokeContinuation invoke =
+                new InvokeContinuation(cont, <Primitive>[arg(0)]);
+            replaceSubtree(node, invoke);
+            visitInvokeContinuation(invoke);
+            return true;
+          }
+          break;
+      }
+    }
+    return false;
+  }
 
-    if (letPrim == null) {
-      super.visitTypeOperator(node);
+  void visitInvokeStatic(InvokeStatic node) {
+    if (constifyExpression(node, node.continuation.definition)) return;
+    if (specializeInvokeStatic(node)) return;
+  }
+
+  AbstractValue getValue(Primitive primitive) {
+    AbstractValue value = values[primitive];
+    return value == null ? new AbstractValue.nothing() : value;
+  }
+
+  void insertLetPrim(Expression node, Primitive prim) {
+    InteriorNode parent = node.parent;
+    LetPrim let = new LetPrim(prim);
+    parent.body = let;
+    let.body = node;
+    node.parent = let;
+    let.parent = parent;
+  }
+
+  void visitApplyBuiltinOperator(ApplyBuiltinOperator node) {
+    DartString getString(AbstractValue value) {
+      StringConstantValue constant = value.constant;
+      return constant.primitiveValue;
+    }
+    switch (node.operator) {
+      case BuiltinOperator.StringConcatenate:
+        // Concatenate consecutive constants.
+        bool argumentsWereRemoved = false;
+        int i = 0;
+        while (i < node.arguments.length - 1) {
+          int startOfSequence = i;
+          AbstractValue firstValue = getValue(node.arguments[i++].definition);
+          if (!firstValue.isConstant) continue;
+          AbstractValue secondValue = getValue(node.arguments[i++].definition);
+          if (!secondValue.isConstant) continue;
+
+          DartString string =
+              new ConsDartString(getString(firstValue), getString(secondValue));
+
+          // We found a sequence of at least two constants.
+          // Look for the end of the sequence.
+          while (i < node.arguments.length) {
+            AbstractValue value = getValue(node.arguments[i].definition);
+            if (!value.isConstant) break;
+            string = new ConsDartString(string, getString(value));
+            ++i;
+          }
+          Constant prim =
+              makeConstantPrimitive(new StringConstantValue(string));
+          insertLetPrim(node.parent, prim);
+          for (int k = startOfSequence; k < i; ++k) {
+            node.arguments[k].unlink();
+            node.arguments[k] = null; // Remove the argument after the loop.
+          }
+          node.arguments[startOfSequence] = new Reference<Primitive>(prim);
+          argumentsWereRemoved = true;
+        }
+        if (argumentsWereRemoved) {
+          node.arguments.removeWhere((ref) => ref == null);
+        }
+        // TODO(asgerf): Rebalance nested StringConcats that arise from
+        //               rewriting the + operator to StringConcat.
+        break;
+
+      case BuiltinOperator.Identical:
+        Primitive left = node.arguments[0].definition;
+        Primitive right = node.arguments[1].definition;
+        AbstractValue leftValue = getValue(left);
+        AbstractValue rightValue = getValue(right);
+        // Replace identical(x, true) by x when x is known to be a boolean.
+        if (lattice.isDefinitelyBool(leftValue) &&
+            rightValue.isConstant &&
+            rightValue.constant.isTrue) {
+          left.substituteFor(node);
+        }
+        break;
+
+      default:
+    }
+  }
+
+  Primitive visitTypeTest(TypeTest node) {
+    Primitive prim = node.value.definition;
+    AbstractValue value = getValue(prim);
+    if (node.type == dartTypes.coreTypes.intType) {
+      // Compile as typeof x === 'number' && Math.floor(x) === x
+      if (lattice.isDefinitelyNum(value, allowNull: true)) {
+        // If value is null or a number, we can skip the typeof test.
+        return new ApplyBuiltinOperator(
+            BuiltinOperator.IsFloor,
+            <Primitive>[prim, prim]);
+      }
+      if (lattice.isDefinitelyNotNonIntegerDouble(value)) {
+        // If the value cannot be a non-integer double, but might not be a
+        // number at all, we can skip the Math.floor test.
+        return new ApplyBuiltinOperator(
+            BuiltinOperator.IsNumber,
+            <Primitive>[prim]);
+      }
+      return new ApplyBuiltinOperator(
+          BuiltinOperator.IsNumberAndFloor,
+          <Primitive>[prim, prim, prim]);
+    }
+    return null;
+  }
+
+  void visitGetField(GetField node) {
+    node.objectIsNotNull = getValue(node.object.definition).isDefinitelyNotNull;
+  }
+
+  void visitLetPrim(LetPrim node) {
+    AbstractValue value = getValue(node.primitive);
+    if (node.primitive is! Constant && value.isConstant) {
+      // If the value is a known constant, compile it as a constant.
+      Constant newPrim = makeConstantPrimitive(value.constant);
+      newPrim.substituteFor(node.primitive);
+      RemovalVisitor.remove(node.primitive);
+      node.primitive = newPrim;
     } else {
-      visitLetPrim(letPrim);
+      Primitive newPrim = visit(node.primitive);
+      if (newPrim != null) {
+        if (!values.containsKey(newPrim)) {
+          // If the type was not set, default to the same type as before.
+          values[newPrim] = values[node.primitive];
+        }
+        newPrim.substituteFor(node.primitive);
+        RemovalVisitor.remove(node.primitive);
+        node.primitive = newPrim;
+      }
+      if (node.primitive.hasNoUses && node.primitive.isSafeForElimination) {
+        // Remove unused primitives before entering the body.
+        // This would also be done by shrinking reductions, but usage analyses
+        // such as isAlwaysBoolified are more precise without the dead uses, so
+        // we prefer to remove them early.
+        RemovalVisitor.remove(node.primitive);
+        node.parent.body = node.body;
+        node.body.parent = node.parent;
+      }
     }
-  }
-
-  _AbstractValue<T> getValue(Primitive primitive) {
-    _AbstractValue<T> value = values[primitive];
-    return value == null ? new _AbstractValue.nothing() : value;
-  }
-
-  void visitIdentical(Identical node) {
-    Primitive left = node.left.definition;
-    Primitive right = node.right.definition;
-    _AbstractValue<T> leftValue = getValue(left);
-    _AbstractValue<T> rightValue = getValue(right);
-    // Replace identical(x, true) by x when x is known to be a boolean.
-    if (leftValue.isDefinitelyBool(typeSystem) &&
-        rightValue.isConstant &&
-        rightValue.constant.isTrue) {
-      left.substituteFor(node);
-    }
+    visit(node.body);
   }
 }
 
@@ -374,7 +931,7 @@
  * const-ness as well as reachability, both of which are used in the subsequent
  * transformation pass.
  */
-class _TypePropagationVisitor<T> implements Visitor {
+class TypePropagationVisitor implements Visitor {
   // The node worklist stores nodes that are both reachable and need to be
   // processed, but have not been processed yet. Using a worklist avoids deep
   // recursion.
@@ -391,35 +948,31 @@
   // since their lattice value has changed.
   final Set<Definition> defWorkset = new Set<Definition>();
 
-  final ConstantSystem constantSystem;
-  final TypeSystem<T> typeSystem;
+  final ConstantPropagationLattice lattice;
   final dart2js.InternalErrorFunction internalError;
-  final types.DartTypes _dartTypes;
 
-  _AbstractValue<T> nothing = new _AbstractValue.nothing();
+  TypeMaskSystem get typeSystem => lattice.typeSystem;
 
-  _AbstractValue<T> nonConstant([T type]) {
-    if (type == null) {
-      type = typeSystem.dynamicType;
-    }
-    return new _AbstractValue<T>.nonConstant(type);
+  AbstractValue get nothing => lattice.nothing;
+
+  AbstractValue nonConstant([TypeMask type]) => lattice.nonConstant(type);
+
+  AbstractValue constantValue(ConstantValue constant, [TypeMask type]) {
+    return lattice.constant(constant, type);
   }
 
-  _AbstractValue<T> constantValue(ConstantValue constant, T type) {
-    return new _AbstractValue<T>.constantValue(constant, type);
-  }
-
-  // Stores the current lattice value for nodes. Note that it contains not only
-  // definitions as keys, but also expressions such as method invokes.
+  // Stores the current lattice value for primitives and mutable variables.
   // Access through [getValue] and [setValue].
-  final Map<Node, _AbstractValue<T>> values;
+  final Map<Definition, AbstractValue> values;
 
-  _TypePropagationVisitor(this.constantSystem,
-                          TypeSystem typeSystem,
-                          this.values,
-                          this.internalError,
-                          this._dartTypes)
-      : this.typeSystem = typeSystem;
+  /// Expressions that invoke their call continuation with a constant value
+  /// and without any side effects. These can be replaced by the constant.
+  final Map<Expression, ConstantValue> replacements;
+
+  TypePropagationVisitor(this.lattice,
+                         this.values,
+                         this.replacements,
+                         this.internalError);
 
   void analyze(FunctionDefinition root) {
     reachableNodes.clear();
@@ -463,17 +1016,17 @@
   /// Returns the lattice value corresponding to [node], defaulting to nothing.
   ///
   /// Never returns null.
-  _AbstractValue<T> getValue(Node node) {
-    _AbstractValue<T> value = values[node];
+  AbstractValue getValue(Node node) {
+    AbstractValue value = values[node];
     return (value == null) ? nothing : value;
   }
 
   /// Joins the passed lattice [updateValue] to the current value of [node],
   /// and adds it to the definition work set if it has changed and [node] is
   /// a definition.
-  void setValue(Node node, _AbstractValue<T> updateValue) {
-    _AbstractValue<T> oldValue = getValue(node);
-    _AbstractValue<T> newValue = updateValue.join(oldValue, typeSystem);
+  void setValue(Node node, AbstractValue updateValue) {
+    AbstractValue oldValue = getValue(node);
+    AbstractValue newValue = lattice.join(oldValue, updateValue);
     if (oldValue == newValue) {
       return;
     }
@@ -536,11 +1089,30 @@
 
     assert(cont.parameters.length == 1);
     Parameter returnValue = cont.parameters[0];
-    Entity target = node.target;
-    T returnType = target is FieldElement
-        ? typeSystem.dynamicType
-        : typeSystem.getReturnType(node.target);
-    setValue(returnValue, nonConstant(returnType));
+
+    /// Sets the value of the target continuation parameter, and possibly
+    /// try to replace the whole invocation with a constant.
+    void setResult(AbstractValue updateValue, {bool canReplace: false}) {
+      setValue(returnValue, updateValue);
+      if (canReplace && updateValue.isConstant) {
+        replacements[node] = updateValue.constant;
+      } else {
+        // A previous iteration might have tried to replace this.
+        replacements.remove(node);
+      }
+    }
+
+    if (node.target.library.isInternalLibrary) {
+      switch (node.target.name) {
+        case InternalMethod.Stringify:
+          AbstractValue argValue = getValue(node.arguments[0].definition);
+          setResult(lattice.stringify(argValue), canReplace: true);
+          return;
+      }
+    }
+
+    TypeMask returnType = typeSystem.getReturnType(node.target);
+    setResult(nonConstant(returnType));
   }
 
   void visitInvokeContinuation(InvokeContinuation node) {
@@ -551,7 +1123,7 @@
     // continuation. Note that this is effectively a phi node in SSA terms.
     for (int i = 0; i < node.arguments.length; i++) {
       Definition def = node.arguments[i].definition;
-      _AbstractValue<T> cell = getValue(def);
+      AbstractValue cell = getValue(def);
       setValue(cont.parameters[i], cell);
     }
   }
@@ -560,65 +1132,120 @@
     Continuation cont = node.continuation.definition;
     setReachable(cont);
 
-    /// Sets the value of both the current node and the target continuation
-    /// parameter.
-    void setValues(_AbstractValue<T> updateValue) {
-      setValue(node, updateValue);
+    /// Sets the value of the target continuation parameter, and possibly
+    /// try to replace the whole invocation with a constant.
+    void setResult(AbstractValue updateValue, {bool canReplace: false}) {
       Parameter returnValue = cont.parameters[0];
       setValue(returnValue, updateValue);
+      if (canReplace && updateValue.isConstant) {
+        replacements[node] = updateValue.constant;
+      } else {
+        // A previous iteration might have tried to replace this.
+        replacements.remove(node);
+      }
     }
 
-    _AbstractValue<T> lhs = getValue(node.receiver.definition);
-    if (lhs.isNothing) {
+    AbstractValue receiver = getValue(node.receiver.definition);
+    if (receiver.isNothing) {
       return;  // And come back later.
-    } else if (lhs.isNonConst) {
-      setValues(nonConstant(typeSystem.getSelectorReturnType(node.selector)));
-      return;
-    } else if (!node.selector.isOperator) {
+    }
+    if (!node.selector.isOperator) {
       // TODO(jgruber): Handle known methods on constants such as String.length.
-      setValues(nonConstant());
+      setResult(lattice.getInvokeReturnType(node.selector, node.mask));
       return;
     }
 
     // Calculate the resulting constant if possible.
-    ConstantValue result;
+    // Operators are intercepted, so the operands are in the argument list.
+    AbstractValue result;
     String opname = node.selector.name;
-    if (node.selector.argumentCount == 0) {
+    if (node.arguments.length == 1) {
+      AbstractValue argument = getValue(node.arguments[0].definition);
       // Unary operator.
-
       if (opname == "unary-") {
         opname = "-";
       }
-      UnaryOperation operation = constantSystem.lookupUnary(
-          UnaryOperator.parse(opname));
-      if (operation != null) {
-        result = operation.fold(lhs.constant);
-      }
-    } else if (node.selector.argumentCount == 1) {
+      UnaryOperator operator = UnaryOperator.parse(opname);
+      result = lattice.unaryOp(operator, argument);
+    } else if (node.arguments.length == 2) {
       // Binary operator.
-
-      _AbstractValue<T> rhs = getValue(node.arguments[0].definition);
-      if (!rhs.isConstant) {
-        setValues(nonConstant());
-        return;
-      }
-
-      BinaryOperation operation = constantSystem.lookupBinary(
-          BinaryOperator.parse(opname));
-      if (operation != null) {
-        result = operation.fold(lhs.constant, rhs.constant);
-      }
+      AbstractValue left = getValue(node.arguments[0].definition);
+      AbstractValue right = getValue(node.arguments[1].definition);
+      BinaryOperator operator = BinaryOperator.parse(opname);
+      result = lattice.binaryOp(operator, left, right);
     }
 
     // Update value of the continuation parameter. Again, this is effectively
     // a phi.
     if (result == null) {
-      setValues(nonConstant());
+      setResult(lattice.getInvokeReturnType(node.selector, node.mask));
     } else {
-      T type = typeSystem.getTypeOf(result);
-      setValues(constantValue(result, type));
+      setResult(result, canReplace: true);
     }
-   }
+  }
+
+  void visitApplyBuiltinOperator(ApplyBuiltinOperator node) {
+    // Note that most built-in operators do not exist before the transformation
+    // pass after this analysis has finished.
+    switch (node.operator) {
+      case BuiltinOperator.StringConcatenate:
+        DartString stringValue = const LiteralDartString('');
+        for (Reference<Primitive> arg in node.arguments) {
+          AbstractValue value = getValue(arg.definition);
+          if (value.isNothing) {
+            return; // And come back later
+          } else if (value.isConstant &&
+                     value.constant.isString &&
+                     stringValue != null) {
+            StringConstantValue constant = value.constant;
+            stringValue =
+                new ConsDartString(stringValue, constant.primitiveValue);
+          } else {
+            stringValue = null;
+            break;
+          }
+        }
+        if (stringValue == null) {
+          setValue(node, nonConstant(typeSystem.stringType));
+        } else {
+          setValue(node, constantValue(new StringConstantValue(stringValue)));
+        }
+        break;
+
+      case BuiltinOperator.Identical:
+        AbstractValue leftConst = getValue(node.arguments[0].definition);
+        AbstractValue rightConst = getValue(node.arguments[1].definition);
+        ConstantValue leftValue = leftConst.constant;
+        ConstantValue rightValue = rightConst.constant;
+        if (leftConst.isNothing || rightConst.isNothing) {
+          // Come back later.
+          return;
+        } else if (!leftConst.isConstant || !rightConst.isConstant) {
+          TypeMask leftType = leftConst.type;
+          TypeMask rightType = rightConst.type;
+          if (typeSystem.areDisjoint(leftType, rightType)) {
+            setValue(node,
+                constantValue(new FalseConstantValue(), typeSystem.boolType));
+          } else {
+            setValue(node, nonConstant(typeSystem.boolType));
+          }
+          return;
+        } else if (leftValue.isPrimitive && rightValue.isPrimitive) {
+          assert(leftConst.isConstant && rightConst.isConstant);
+          PrimitiveConstantValue left = leftValue;
+          PrimitiveConstantValue right = rightValue;
+          ConstantValue result =
+            new BoolConstantValue(left.primitiveValue == right.primitiveValue);
+          setValue(node, constantValue(result, typeSystem.boolType));
+        } else {
+          setValue(node, nonConstant(typeSystem.boolType));
+        }
+        break;
+
+      default:
+        setValue(node, nonConstant());
+    }
+  }
 
   void visitInvokeMethodDirectly(InvokeMethodDirectly node) {
     Continuation cont = node.continuation.definition;
@@ -639,56 +1266,22 @@
     setValue(returnValue, nonConstant(typeSystem.getReturnType(node.target)));
   }
 
-  void visitConcatenateStrings(ConcatenateStrings node) {
-    Continuation cont = node.continuation.definition;
-    setReachable(cont);
-
-    void setValues(_AbstractValue<T> updateValue) {
-      setValue(node, updateValue);
-      Parameter returnValue = cont.parameters[0];
-      setValue(returnValue, updateValue);
-    }
-
-    // TODO(jgruber): Currently we only optimize if all arguments are string
-    // constants, but we could also handle cases such as "foo${42}".
-    bool allStringConstants = node.arguments.every((Reference ref) {
-      if (!(ref.definition is Constant)) {
-        return false;
-      }
-      Constant constant = ref.definition;
-      return constant != null && constant.value.isString;
-    });
-
-    T type = typeSystem.stringType;
-    assert(cont.parameters.length == 1);
-    if (allStringConstants) {
-      // All constant, we can concatenate ourselves.
-      Iterable<String> allStrings = node.arguments.map((Reference ref) {
-        Constant constant = ref.definition;
-        StringConstantValue stringConstant = constant.value;
-        return stringConstant.primitiveValue.slowToString();
-      });
-      LiteralDartString dartString = new LiteralDartString(allStrings.join());
-      ConstantValue constant = new StringConstantValue(dartString);
-      setValues(constantValue(constant, type));
-    } else {
-      setValues(nonConstant(type));
-    }
-  }
-
   void visitThrow(Throw node) {
   }
 
   void visitRethrow(Rethrow node) {
   }
 
+  void visitUnreachable(Unreachable node) {
+  }
+
   void visitNonTailThrow(NonTailThrow node) {
     internalError(null, 'found non-tail throw after they were eliminated');
   }
 
   void visitBranch(Branch node) {
     IsTrue isTrue = node.condition;
-    _AbstractValue<T> conditionCell = getValue(isTrue.value.definition);
+    AbstractValue conditionCell = getValue(isTrue.value.definition);
 
     if (conditionCell.isNothing) {
       return;  // And come back later.
@@ -709,50 +1302,47 @@
     }
   }
 
-  void visitTypeOperator(TypeOperator node) {
+  void visitTypeTest(TypeTest node) {
+    AbstractValue input = getValue(node.value.definition);
+    TypeMask boolType = typeSystem.boolType;
+    switch(lattice.isSubtypeOf(input, node.type, allowNull: false)) {
+      case AbstractBool.Nothing:
+        break; // And come back later.
+
+      case AbstractBool.True:
+        setValue(node, constantValue(new TrueConstantValue(), boolType));
+        break;
+
+      case AbstractBool.False:
+        setValue(node, constantValue(new FalseConstantValue(), boolType));
+        break;
+
+      case AbstractBool.Maybe:
+        setValue(node, nonConstant(boolType));
+        break;
+    }
+  }
+
+  void visitTypeCast(TypeCast node) {
     Continuation cont = node.continuation.definition;
-    setReachable(cont);
+    AbstractValue input = getValue(node.value.definition);
+    switch (lattice.isSubtypeOf(input, node.type, allowNull: true)) {
+      case AbstractBool.Nothing:
+        break; // And come back later.
 
-    void setValues(_AbstractValue<T> updateValue) {
-      setValue(node, updateValue);
-      Parameter returnValue = cont.parameters[0];
-      setValue(returnValue, updateValue);
-    }
+      case AbstractBool.True:
+        setReachable(cont);
+        setValue(cont.parameters.single, input);
+        break;
 
-    if (node.isTypeCast) {
-      // TODO(jgruber): Add support for `as` casts.
-      setValues(nonConstant());
-      return;
-    }
+      case AbstractBool.False:
+        break; // Cast fails. Continuation should remain unreachable.
 
-    _AbstractValue<T> cell = getValue(node.value.definition);
-    if (cell.isNothing) {
-      return;  // And come back later.
-    } else if (cell.isConstant && node.type.kind == types.TypeKind.INTERFACE) {
-      // Receiver is a constant, perform is-checks at compile-time.
-
-      types.InterfaceType checkedType = node.type;
-      ConstantValue constant = cell.constant;
-      types.DartType constantType = constant.getType(_dartTypes.coreTypes);
-
-      T type = typeSystem.boolType;
-      _AbstractValue<T> result;
-      if (constant.isNull &&
-          checkedType != _dartTypes.coreTypes.nullType &&
-          checkedType != _dartTypes.coreTypes.objectType) {
-        // `(null is Type)` is true iff Type is in { Null, Object }.
-        result = constantValue(new FalseConstantValue(), type);
-      } else {
-        // Otherwise, perform a standard subtype check.
-        result = constantValue(
-            constantSystem.isSubtype(_dartTypes, constantType, checkedType)
-            ? new TrueConstantValue()
-            : new FalseConstantValue(),
-            type);
-      }
-      setValues(result);
-    } else {
-      setValues(nonConstant(typeSystem.boolType));
+      case AbstractBool.Maybe:
+        // TODO(asgerf): Narrow type of output to those that survive the cast.
+        setReachable(cont);
+        setValue(cont.parameters.single, input);
+        break;
     }
   }
 
@@ -797,7 +1387,7 @@
       // never constant.
       // TODO(karlklose): remove reference to the element model.
       Entity source = node.hint;
-      T type = (source is ParameterElement)
+      TypeMask type = (source is ParameterElement)
           ? typeSystem.getParameterType(source)
           : typeSystem.dynamicType;
       setValue(node, nonConstant(type));
@@ -811,7 +1401,7 @@
   void visitParameter(Parameter node) {
     Entity source = node.hint;
     // TODO(karlklose): remove reference to the element model.
-    T type = (source is ParameterElement)
+    TypeMask type = (source is ParameterElement)
         ? typeSystem.getParameterType(source)
         : typeSystem.dynamicType;
     if (node.parent is FunctionDefinition) {
@@ -859,36 +1449,9 @@
     visitBranch(branch);
   }
 
-  void visitIdentical(Identical node) {
-    _AbstractValue<T> leftConst = getValue(node.left.definition);
-    _AbstractValue<T> rightConst = getValue(node.right.definition);
-    ConstantValue leftValue = leftConst.constant;
-    ConstantValue rightValue = rightConst.constant;
-    if (leftConst.isNothing || rightConst.isNothing) {
-      // Come back later.
-      return;
-    } else if (!leftConst.isConstant || !rightConst.isConstant) {
-      T leftType = leftConst.type;
-      T rightType = rightConst.type;
-      if (typeSystem.areDisjoint(leftType, rightType)) {
-        setValue(node,
-            constantValue(new FalseConstantValue(), typeSystem.boolType));
-      } else {
-        setValue(node, nonConstant(typeSystem.boolType));
-      }
-    } else if (leftValue.isPrimitive && rightValue.isPrimitive) {
-      assert(leftConst.isConstant && rightConst.isConstant);
-      PrimitiveConstantValue left = leftValue;
-      PrimitiveConstantValue right = rightValue;
-      ConstantValue result =
-          new BoolConstantValue(left.primitiveValue == right.primitiveValue);
-      setValue(node, constantValue(result, typeSystem.boolType));
-    }
-  }
-
   void visitInterceptor(Interceptor node) {
     setReachable(node.input.definition);
-    _AbstractValue<T> value = getValue(node.input.definition);
+    AbstractValue value = getValue(node.input.definition);
     if (!value.isNothing) {
       setValue(node, nonConstant(typeSystem.nonNullType));
     }
@@ -907,7 +1470,7 @@
   }
 
   void visitCreateInstance(CreateInstance node) {
-    setValue(node, nonConstant(typeSystem.exact(node.classElement)));
+    setValue(node, nonConstant(typeSystem.nonNullExact(node.classElement.declaration)));
   }
 
   void visitReifyRuntimeType(ReifyRuntimeType node) {
@@ -931,6 +1494,18 @@
     // TODO(asgerf): Expose [Invocation] type.
     setValue(node, nonConstant(typeSystem.nonNullType));
   }
+
+  @override
+  visitForeignCode(ForeignCode node) {
+    if (node.continuation != null) {
+      Continuation continuation = node.continuation.definition;
+      setReachable(continuation);
+
+      assert(continuation.parameters.length == 1);
+      Parameter returnValue = continuation.parameters.first;
+      setValue(returnValue, nonConstant(node.type));
+    }
+  }
 }
 
 /// Represents the abstract value of a primitive value at some point in the
@@ -942,38 +1517,42 @@
 ///   CONSTANT: is a constant. The value is stored in the [constant] field,
 ///             and the type of the constant is in the [type] field.
 ///   NONCONST: not a constant, but [type] may hold some information.
-class _AbstractValue<T> {
+class AbstractValue {
   static const int NOTHING  = 0;
   static const int CONSTANT = 1;
   static const int NONCONST = 2;
 
   final int kind;
   final ConstantValue constant;
-  final T type;
+  final TypeMask type;
 
-  _AbstractValue._internal(this.kind, this.constant, this.type) {
+  AbstractValue._internal(this.kind, this.constant, this.type) {
     assert(kind != CONSTANT || constant != null);
   }
 
-  _AbstractValue.nothing()
+  AbstractValue.nothing()
       : this._internal(NOTHING, null, null);
 
-  _AbstractValue.constantValue(ConstantValue constant, T type)
+  AbstractValue.constantValue(ConstantValue constant, TypeMask type)
       : this._internal(CONSTANT, constant, type);
 
-  _AbstractValue.nonConstant(T type)
+  AbstractValue.nonConstant(TypeMask type)
       : this._internal(NONCONST, null, type);
 
   bool get isNothing  => (kind == NOTHING);
   bool get isConstant => (kind == CONSTANT);
   bool get isNonConst => (kind == NONCONST);
+  bool get isNullConstant => kind == CONSTANT && constant.isNull;
+
+  bool get isNullable => kind != NOTHING && type.isNullable;
+  bool get isDefinitelyNotNull => kind == NOTHING || !type.isNullable;
 
   int get hashCode {
     int hash = kind * 31 + constant.hashCode * 59 + type.hashCode * 67;
     return hash & 0x3fffffff;
   }
 
-  bool operator ==(_AbstractValue that) {
+  bool operator ==(AbstractValue that) {
     return that.kind == this.kind &&
            that.constant == this.constant &&
            that.type == this.type;
@@ -982,113 +1561,15 @@
   String toString() {
     switch (kind) {
       case NOTHING: return "Nothing";
-      case CONSTANT: return "Constant: $constant: $type";
+      case CONSTANT: return "Constant: ${constant.unparse()}: $type";
       case NONCONST: return "Non-constant: $type";
       default: assert(false);
     }
     return null;
   }
-
-  /// Compute the join of two values in the lattice.
-  _AbstractValue join(_AbstractValue that, TypeSystem typeSystem) {
-    assert(that != null);
-
-    if (isNothing) {
-      return that;
-    } else if (that.isNothing) {
-      return this;
-    } else if (isConstant && that.isConstant && constant == that.constant) {
-      return this;
-    } else {
-      return new _AbstractValue.nonConstant(
-          typeSystem.join(this.type, that.type));
-    }
-  }
-
-  /// True if all members of this value are booleans.
-  bool isDefinitelyBool(TypeSystem<T> typeSystem) {
-    if (kind == NOTHING) return true;
-    return typeSystem.isDefinitelyBool(type);
-  }
-
-  /// True if null is not a member of this value.
-  bool isDefinitelyNotNull(TypeSystem<T> typeSystem) {
-    if (kind == NOTHING) return true;
-    if (kind == CONSTANT) return !constant.isNull;
-    return typeSystem.isDefinitelyNotNull(type);
-  }
 }
 
-class ConstantExpressionCreator
-    implements ConstantValueVisitor<ConstantExpression, dynamic> {
-
-  const ConstantExpressionCreator();
-
-  ConstantExpression convert(ConstantValue value) => value.accept(this, null);
-
-  @override
-  ConstantExpression visitBool(BoolConstantValue constant, _) {
-    return new BoolConstantExpression(constant.primitiveValue);
-  }
-
-  @override
-  ConstantExpression visitConstructed(ConstructedConstantValue constant, arg) {
-    throw new UnsupportedError("ConstantExpressionCreator.visitConstructed");
-  }
-
-  @override
-  ConstantExpression visitDeferred(DeferredConstantValue constant, arg) {
-    throw new UnsupportedError("ConstantExpressionCreator.visitDeferred");
-  }
-
-  @override
-  ConstantExpression visitDouble(DoubleConstantValue constant, arg) {
-    return new DoubleConstantExpression(constant.primitiveValue);
-  }
-
-  @override
-  ConstantExpression visitDummy(DummyConstantValue constant, arg) {
-    throw new UnsupportedError("ConstantExpressionCreator.visitDummy");
-  }
-
-  @override
-  ConstantExpression visitFunction(FunctionConstantValue constant, arg) {
-    throw new UnsupportedError("ConstantExpressionCreator.visitFunction");
-  }
-
-  @override
-  ConstantExpression visitInt(IntConstantValue constant, arg) {
-    return new IntConstantExpression(constant.primitiveValue);
-  }
-
-  @override
-  ConstantExpression visitInterceptor(InterceptorConstantValue constant, arg) {
-    throw new UnsupportedError("ConstantExpressionCreator.visitInterceptor");
-  }
-
-  @override
-  ConstantExpression visitList(ListConstantValue constant, arg) {
-    throw new UnsupportedError("ConstantExpressionCreator.visitList");
-  }
-
-  @override
-  ConstantExpression visitMap(MapConstantValue constant, arg) {
-    throw new UnsupportedError("ConstantExpressionCreator.visitMap");
-  }
-
-  @override
-  ConstantExpression visitNull(NullConstantValue constant, arg) {
-    return new NullConstantExpression();
-  }
-
-  @override
-  ConstantExpression visitString(StringConstantValue constant, arg) {
-    return new StringConstantExpression(
-        constant.primitiveValue.slowToString());
-  }
-
-  @override
-  ConstantExpression visitType(TypeConstantValue constant, arg) {
-    throw new UnsupportedError("ConstantExpressionCreator.visitType");
-  }
-}
\ No newline at end of file
+/// Enum-like class with the names of internal methods we care about.
+abstract class InternalMethod {
+  static const String Stringify = 'S';
+}
diff --git a/pkg/compiler/lib/src/dart2js.dart b/pkg/compiler/lib/src/dart2js.dart
index 098e09c..9db2af5 100644
--- a/pkg/compiler/lib/src/dart2js.dart
+++ b/pkg/compiler/lib/src/dart2js.dart
@@ -367,6 +367,7 @@
     }),
     new OptionHandler('--allow-native-extensions', setAllowNativeExtensions),
     new OptionHandler('--generate-code-with-compile-time-errors', passThrough),
+    new OptionHandler('--test-mode', passThrough),
 
     // The following three options must come last.
     new OptionHandler('-D.+=.*', addInEnvironment),
diff --git a/pkg/compiler/lib/src/dart2jslib.dart b/pkg/compiler/lib/src/dart2jslib.dart
index 0221ca9..a203791 100644
--- a/pkg/compiler/lib/src/dart2jslib.dart
+++ b/pkg/compiler/lib/src/dart2jslib.dart
@@ -13,7 +13,6 @@
 import 'cache_strategy.dart';
 import 'closure.dart' as closureMapping;
 import 'compile_time_constants.dart';
-import 'constant_system_dart.dart';
 import 'constants/constant_system.dart';
 import 'constants/expressions.dart';
 import 'constants/values.dart';
@@ -62,7 +61,6 @@
 import 'util/characters.dart' show $_;
 import 'util/uri_extras.dart' as uri_extras show relativize;
 import 'util/util.dart';
-import 'dart_backend/dart_backend.dart';
 
 export 'helpers/helpers.dart';
 export 'resolution/resolution.dart' show TreeElements, TreeElementMapping;
diff --git a/pkg/compiler/lib/src/dart_backend/backend.dart b/pkg/compiler/lib/src/dart_backend/backend.dart
index 7ac9d67..2e9bad4 100644
--- a/pkg/compiler/lib/src/dart_backend/backend.dart
+++ b/pkg/compiler/lib/src/dart_backend/backend.dart
@@ -49,7 +49,13 @@
   final Set<ClassElement> _userImplementedPlatformClasses =
       new Set<ClassElement>();
 
-  bool get canHandleCompilationFailed => false;
+  bool enableCodegenWithErrorsIfSupported(Spannable node) {
+    compiler.reportHint(node,
+        MessageKind.GENERIC,
+        {'text': "Generation of code with compile time errors is not "
+                 "supported for dart2dart."});
+    return false;
+  }
 
   /**
    * Tells whether it is safe to remove type declarations from variables,
@@ -123,10 +129,14 @@
     }
     // Enqueue the methods that the VM might invoke on user objects because
     // we don't trust the resolution to always get these included.
-    world.registerInvocation(new Selector.call("toString", null, 0));
-    world.registerInvokedGetter(new Selector.getter("hashCode", null));
-    world.registerInvocation(new Selector.binaryOperator("=="));
-    world.registerInvocation(new Selector.call("compareTo", null, 1));
+    world.registerInvocation(
+        new UniverseSelector(new Selector.call("toString", null, 0), null));
+    world.registerInvokedGetter(
+        new UniverseSelector(new Selector.getter("hashCode", null), null));
+    world.registerInvocation(
+        new UniverseSelector(new Selector.binaryOperator("=="), null));
+    world.registerInvocation(
+        new UniverseSelector(new Selector.call("compareTo", null, 1), null));
   }
 
   WorldImpact codegen(CodegenWorkItem work) => const WorldImpact();
@@ -144,9 +154,6 @@
   }
 
   int assembleProgram() {
-    ElementAstCreationContext context =
-        new _ElementAstCreationContext(compiler, constantSystem);
-
     ElementAst computeElementAst(AstElement element) {
       return new ElementAst(element.resolvedAst.node,
                             element.resolvedAst.elements);
@@ -290,20 +297,21 @@
             // Register selectors for all instance methods since these might
             // be called on user classes from within the platform
             // implementation.
-            superclass.forEachLocalMember((Element element) {
+            superclass.forEachLocalMember((MemberElement element) {
               if (element.isConstructor || element.isStatic) return;
 
               FunctionElement function = element.asFunctionElement();
-              if (function != null) {
-                function.computeSignature(compiler);
-              }
+              element.computeType(compiler);
               Selector selector = new Selector.fromElement(element);
               if (selector.isGetter) {
-                registry.registerDynamicGetter(selector);
+                registry.registerDynamicGetter(
+                    new UniverseSelector(selector, null));
               } else if (selector.isSetter) {
-                registry.registerDynamicSetter(selector);
+                registry.registerDynamicSetter(
+                    new UniverseSelector(selector, null));
               } else {
-                registry.registerDynamicInvocation(selector);
+                registry.registerDynamicInvocation(
+                    new UniverseSelector(selector, null));
               }
             });
           }
@@ -312,6 +320,13 @@
     }
 
   }
+
+  @override
+  bool enableDeferredLoadingIfSupported(Spannable node, Registry registry) {
+    // TODO(sigurdm): Implement deferred loading for dart2dart.
+    compiler.reportWarning(node, MessageKind.DEFERRED_LIBRARY_DART_2_DART);
+    return false;
+  }
 }
 
 class DartResolutionCallbacks extends ResolutionCallbacks {
@@ -500,20 +515,3 @@
         task.constantCompiler.constantValueMap);
   }
 }
-
-abstract class ElementAstCreationContext {
-  DartTypes get dartTypes;
-  ConstantSystem get constantSystem;
-  InternalErrorFunction get internalError;
-}
-
-class _ElementAstCreationContext implements ElementAstCreationContext {
-  final Compiler compiler;
-  final ConstantSystem constantSystem;
-
-  _ElementAstCreationContext(this.compiler, this.constantSystem);
-
-  DartTypes get dartTypes => compiler.types;
-
-  InternalErrorFunction get internalError => compiler.internalError;
-}
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 454ee91..0375bc3 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
@@ -1213,7 +1213,6 @@
     }
 
     if (supertype != null) {
-      tree.Node superclass;
       if (supertype.element.isUnnamedMixinApplication) {
         while (supertype.element.isUnnamedMixinApplication) {
           elements.MixinApplicationElement mixinApplication = supertype.element;
diff --git a/pkg/compiler/lib/src/dart_backend/dart_backend.dart b/pkg/compiler/lib/src/dart_backend/dart_backend.dart
index 2dbc036..ab6f388 100644
--- a/pkg/compiler/lib/src/dart_backend/dart_backend.dart
+++ b/pkg/compiler/lib/src/dart_backend/dart_backend.dart
@@ -15,6 +15,7 @@
 import '../constants/constant_system.dart';
 import '../constants/expressions.dart';
 import '../constants/values.dart';
+import '../universe/universe.dart' show UniverseSelector;
 import '../util/util.dart';
 import '../mirror_renamer/mirror_renamer.dart';
 import 'backend_ast_to_frontend_ast.dart' as backend2frontend;
diff --git a/pkg/compiler/lib/src/dart_backend/placeholder_collector.dart b/pkg/compiler/lib/src/dart_backend/placeholder_collector.dart
index e32f4a5..12c70b3 100644
--- a/pkg/compiler/lib/src/dart_backend/placeholder_collector.dart
+++ b/pkg/compiler/lib/src/dart_backend/placeholder_collector.dart
@@ -337,7 +337,6 @@
     // collector logic in visitVariableDefinitions when resolver becomes better
     // and/or catch syntax changes.
     if (node.type == null) return;
-    Element definitionElement = treeElements[node.definitions.nodes.head];
     bool requiresVar = !node.modifiers.isFinalOrConst;
     declarationTypePlaceholders.add(
         new DeclarationTypePlaceholder(node.type, requiresVar));
diff --git a/pkg/compiler/lib/src/dart_types.dart b/pkg/compiler/lib/src/dart_types.dart
index 18f9fa4..21fbc78 100644
--- a/pkg/compiler/lib/src/dart_types.dart
+++ b/pkg/compiler/lib/src/dart_types.dart
@@ -15,7 +15,6 @@
          TypeDeclarationElementX,
          TypedefElementX;
 import 'elements/elements.dart';
-import 'helpers/helpers.dart';  // Included for debug helpers.
 import 'ordered_typeset.dart' show OrderedTypeSet;
 import 'util/util.dart' show CURRENT_ELEMENT_SPANNABLE, equalElements;
 
@@ -1232,6 +1231,10 @@
 
   /// Returns `true` if [t] is a subtype of [s].
   bool isSubtype(DartType t, DartType s);
+
+  /// Returns `true` if [t] might be a subtype of [s] for some values of
+  /// type variables in [s] and [t].
+  bool isPotentialSubtype(DartType t, DartType s);
 }
 
 class Types implements DartTypes {
@@ -1590,8 +1593,6 @@
     List<DartType> bNamedParameterTypes = b.namedParameterTypes;
     int aIndex = 0;
     int bIndex = 0;
-    int prefixLength =
-        min(aNamedParameterTypes.length, bNamedParameterTypes.length);
     while (aIndex < aNamedParameters.length &&
            bIndex < bNamedParameters.length) {
       String aNamedParameter = aNamedParameters[aIndex];
diff --git a/pkg/compiler/lib/src/deferred_load.dart b/pkg/compiler/lib/src/deferred_load.dart
index 92116b8..3213f9f 100644
--- a/pkg/compiler/lib/src/deferred_load.dart
+++ b/pkg/compiler/lib/src/deferred_load.dart
@@ -4,7 +4,6 @@
 
 library deferred_load;
 
-import 'constants/expressions.dart';
 import 'constants/values.dart' show
     ConstantValue,
     ConstructedConstantValue,
@@ -18,9 +17,6 @@
     invariant,
     MessageKind;
 
-import 'dart_backend/dart_backend.dart' show
-    DartBackend;
-
 import 'js_backend/js_backend.dart' show
     JavaScriptBackend;
 
@@ -286,8 +282,13 @@
       }
       treeElements.forEachConstantNode((Node node, _) {
         // Explicitly depend on the backend constants.
-        constants.add(
-            backend.constants.getConstantValueForNode(node, treeElements));
+        ConstantValue value =
+            backend.constants.getConstantValueForNode(node, treeElements);
+        if (value != null) {
+          // TODO(johnniwinther): Assert that all constants have values when
+          // these are directly evaluated.
+          constants.add(value);
+        }
       });
       elements.addAll(treeElements.otherDependencies);
     }
@@ -770,16 +771,9 @@
         }
       });
     }
-    Backend backend = compiler.backend;
-    if (isProgramSplit && backend is JavaScriptBackend) {
-      backend.registerCheckDeferredIsLoaded(compiler.globalDependencies);
-    }
-    if (isProgramSplit && backend is DartBackend) {
-      // TODO(sigurdm): Implement deferred loading for dart2dart.
-      compiler.reportWarning(
-          lastDeferred,
-          MessageKind.DEFERRED_LIBRARY_DART_2_DART);
-      isProgramSplit = false;
+    if (isProgramSplit) {
+      isProgramSplit = compiler.backend.enableDeferredLoadingIfSupported(
+            lastDeferred, compiler.globalDependencies);
     }
   }
 
diff --git a/pkg/compiler/lib/src/dump_info.dart b/pkg/compiler/lib/src/dump_info.dart
index fb26f0c..3e4cda2 100644
--- a/pkg/compiler/lib/src/dump_info.dart
+++ b/pkg/compiler/lib/src/dump_info.dart
@@ -22,7 +22,7 @@
 import 'deferred_load.dart' show OutputUnit;
 import 'js_backend/js_backend.dart' show JavaScriptBackend;
 import 'js/js.dart' as jsAst;
-import 'universe/universe.dart' show Selector;
+import 'universe/universe.dart' show Selector, UniverseSelector;
 import 'util/util.dart' show NO_LOCATION_SPANNABLE;
 
 /// Maps objects to an id.  Supports lookups in
@@ -389,8 +389,8 @@
 
 class Selection {
   final Element selectedElement;
-  final Selector selector;
-  Selection(this.selectedElement, this.selector);
+  final TypeMask mask;
+  Selection(this.selectedElement, this.mask);
 }
 
 class DumpInfoTask extends CompilerTask {
@@ -414,9 +414,8 @@
   // A mapping from Javascript AST Nodes to the size of their
   // pretty-printed contents.
   final Map<jsAst.Node, int> _nodeToSize = <jsAst.Node, int>{};
-  final Map<Element, int> _fieldNameToSize = <Element, int>{};
 
-  final Map<Element, Set<Selector>> selectorsFromElement = {};
+  final Map<Element, Set<UniverseSelector>> selectorsFromElement = {};
   final Map<Element, int> inlineCount = <Element, int>{};
   // A mapping from an element to a list of elements that are
   // inlined inside of it.
@@ -438,10 +437,10 @@
    * Registers that a function uses a selector in the
    * function body
    */
-  void elementUsesSelector(Element element, Selector selector) {
+  void elementUsesSelector(Element element, UniverseSelector selector) {
     if (compiler.dumpInfo) {
       selectorsFromElement
-          .putIfAbsent(element, () => new Set<Selector>())
+          .putIfAbsent(element, () => new Set<UniverseSelector>())
           .add(selector);
     }
   }
@@ -456,9 +455,11 @@
       return const <Selection>[];
     } else {
       return selectorsFromElement[element].expand(
-        (selector) {
-          return compiler.world.allFunctions.filter(selector).map((element) {
-            return new Selection(element, selector);
+        (UniverseSelector selector) {
+          return compiler.world.allFunctions.filter(
+              selector.selector, selector.mask)
+              .map((element) {
+            return new Selection(element, selector.mask);
           });
         });
     }
@@ -494,19 +495,10 @@
     }
   }
 
-  // Field names are treated differently by the dart compiler
-  // so they must be recorded seperately.
-  void recordFieldNameSize(Element element, int size) {
-    _fieldNameToSize[element] = size;
-  }
-
   // Returns the size of the source code that
   // was generated for an element.  If no source
   // code was produced, return 0.
   int sizeOf(Element element) {
-    if (_fieldNameToSize.containsKey(element)) {
-      return _fieldNameToSize[element];
-    }
     if (_elementToNodes.containsKey(element)) {
       return _elementToNodes[element]
         .map(sizeOfNode)
@@ -573,7 +565,7 @@
             .map((selection) {
               return <String, String>{
                 "id": infoCollector.idOf(selection.selectedElement),
-                "mask": selection.selector.mask.toString()
+                "mask": selection.mask.toString()
               };
             })
             // Filter non-null ids for the same reason as above.
diff --git a/pkg/compiler/lib/src/elements/common.dart b/pkg/compiler/lib/src/elements/common.dart
index 7c3f944..13ea3b6 100644
--- a/pkg/compiler/lib/src/elements/common.dart
+++ b/pkg/compiler/lib/src/elements/common.dart
@@ -8,7 +8,6 @@
 

 import '../dart2jslib.dart' show Compiler, isPrivateName;

 import '../dart_types.dart' show DartType, InterfaceType, FunctionType;

-import '../universe/universe.dart' show Selector;

 import '../util/util.dart' show Link;

 

 import 'elements.dart';

diff --git a/pkg/compiler/lib/src/elements/elements.dart b/pkg/compiler/lib/src/elements/elements.dart
index c2e809f..22a0933 100644
--- a/pkg/compiler/lib/src/elements/elements.dart
+++ b/pkg/compiler/lib/src/elements/elements.dart
@@ -27,7 +27,6 @@
                                  isPrivateName;
 
 import '../dart_types.dart';
-import '../helpers/helpers.dart';
 
 import '../scanner/scannerlib.dart' show Token,
                                          isUserDefinableOperator,
@@ -189,16 +188,6 @@
   Element get enclosingElement;
   Link<MetadataAnnotation> get metadata;
 
-  /// Do not use [computeType] outside of the resolver; instead retrieve the
-  /// type from the corresponding field:
-  /// - `type` for fields, variables, type variable, and function elements.
-  /// - `thisType` or `rawType` for [TypeDeclarationElement]s (classes and
-  ///    typedefs), depending on the use case.
-  /// Trying to access a type that has not been computed in resolution is an
-  /// error and calling [computeType] covers that error.
-  /// This method will go away!
-  @deprecated DartType computeType(Compiler compiler);
-
   /// `true` if this element is a library.
   bool get isLibrary;
 
@@ -1090,8 +1079,8 @@
  * field named "x", a getter named "x", and a setter named "x=".
  */
 abstract class AbstractFieldElement extends Element {
-  FunctionElement get getter;
-  FunctionElement get setter;
+  GetterElement get getter;
+  SetterElement get setter;
 }
 
 abstract class FunctionSignature {
@@ -1129,14 +1118,6 @@
   FunctionElement get patch;
   FunctionElement get origin;
 
-  /// Do not use [computeSignature] outside of the resolver; instead retrieve
-  /// the signature through the [functionSignature] field.
-  /// Trying to access a function signature that has not been computed in
-  /// resolution is an error and calling [computeSignature] covers that error.
-  /// This method will go away!
-  // TODO(johnniwinther): Rename to `ensureFunctionSignature`.
-  @deprecated FunctionSignature computeSignature(Compiler compiler);
-
   bool get hasFunctionSignature;
 
   /// The parameters of this functions.
@@ -1292,6 +1273,15 @@
 /// [TypeDeclarationElement] defines the common interface for class/interface
 /// declarations and typedefs.
 abstract class TypeDeclarationElement extends Element implements AstElement {
+  /// Do not use [computeType] outside of the resolver; instead retrieve the
+  /// type from the [thisType] or [rawType], depending on the use case.
+  ///
+  /// Trying to access a type that has not been computed in resolution is an
+  /// error and calling [computeType] covers that error.
+  /// This method will go away!
+  @deprecated
+  GenericType computeType(Compiler compiler);
+
   /**
    * The `this type` for this type declaration.
    *
@@ -1524,6 +1514,15 @@
 
 /// An [Element] that has a type.
 abstract class TypedElement extends Element {
+  /// Do not use [computeType] outside of the resolver; instead retrieve the
+  /// type from  [type] property.
+  ///
+  /// Trying to access a type that has not been computed in resolution is an
+  /// error and calling [computeType] covers that error.
+  /// This method will go away!
+  @deprecated
+  DartType computeType(Compiler compiler);
+
   DartType get type;
 }
 
diff --git a/pkg/compiler/lib/src/elements/modelx.dart b/pkg/compiler/lib/src/elements/modelx.dart
index 964cb74..cf96f4e 100644
--- a/pkg/compiler/lib/src/elements/modelx.dart
+++ b/pkg/compiler/lib/src/elements/modelx.dart
@@ -8,7 +8,6 @@
 import 'elements.dart';
 import '../constants/expressions.dart';
 import '../constants/constructors.dart';
-import '../helpers/helpers.dart';  // Included for debug helpers.
 import '../tree/tree.dart';
 import '../util/util.dart';
 import '../resolution/resolution.dart';
@@ -67,12 +66,6 @@
     return null;
   }
 
-  DartType computeType(Compiler compiler) {
-    compiler.internalError(this,
-        "computeType not implemented on $this.");
-    return null;
-  }
-
   void addMetadata(MetadataAnnotationX annotation) {
     assert(annotation.annotatedElement == null);
     annotation.annotatedElement = this;
@@ -302,6 +295,7 @@
   bool get isRedirectingFactory => unsupported();
 
   computeSignature(compiler) => unsupported();
+  computeType(compiler) => unsupported();
 
   bool get hasFunctionSignature => false;
 
@@ -2142,6 +2136,7 @@
               Modifiers.EMPTY,
               enclosing) {
     typeCache = new FunctionType.synthesized(enclosingClass.thisType);
+    functionSignatureCache = new FunctionSignatureX(type: type);
   }
 
   FunctionExpression parseNode(DiagnosticListener listener) => null;
@@ -2166,18 +2161,16 @@
 
   FunctionSignature computeSignature(compiler) {
     if (functionSignatureCache != null) return functionSignatureCache;
-    if (isDefaultConstructor) {
-      return functionSignatureCache = new FunctionSignatureX(
-          type: type);
-    }
     if (definingConstructor.isErroneous) {
       return functionSignatureCache =
           compiler.objectClass.localLookup('').computeSignature(compiler);
     }
     // TODO(johnniwinther): Ensure that the function signature (and with it the
     // function type) substitutes type variables correctly.
-    return functionSignatureCache =
-        definingConstructor.computeSignature(compiler);
+    definingConstructor.computeType(compiler);
+    functionSignatureCache = definingConstructor.functionSignature;
+    typeCache = definingConstructor.type;
+    return functionSignatureCache;
   }
 
   accept(ElementVisitor visitor, arg) {
diff --git a/pkg/compiler/lib/src/enqueue.dart b/pkg/compiler/lib/src/enqueue.dart
index 186025c..39f08dc 100644
--- a/pkg/compiler/lib/src/enqueue.dart
+++ b/pkg/compiler/lib/src/enqueue.dart
@@ -35,9 +35,10 @@
 class WorldImpact {
   const WorldImpact();
 
-  Iterable<Selector> get dynamicInvocations => const <Selector>[];
-  Iterable<Selector> get dynamicGetters => const <Selector>[];
-  Iterable<Selector> get dynamicSetters => const <Selector>[];
+  Iterable<UniverseSelector> get dynamicInvocations =>
+      const <UniverseSelector>[];
+  Iterable<UniverseSelector> get dynamicGetters => const <UniverseSelector>[];
+  Iterable<UniverseSelector> get dynamicSetters => const <UniverseSelector>[];
 
   // TODO(johnniwinther): Split this into more precise subsets.
   Iterable<Element> get staticUses => const <Element>[];
@@ -143,7 +144,6 @@
     assert(invariant(member, member.isDeclaration));
     if (isProcessed(member)) return;
     if (!member.isInstanceMember) return;
-
     String memberName = member.name;
 
     if (member.kind == ElementKind.FIELD) {
@@ -189,7 +189,7 @@
       }
     } else if (member.kind == ElementKind.FUNCTION) {
       FunctionElement function = member;
-      function.computeSignature(compiler);
+      function.computeType(compiler);
       if (function.name == Compiler.NO_SUCH_METHOD) {
         registerNoSuchMethod(function);
       }
@@ -215,7 +215,7 @@
       }
     } else if (member.kind == ElementKind.GETTER) {
       FunctionElement getter = member;
-      getter.computeSignature(compiler);
+      getter.computeType(compiler);
       if (universe.hasInvokedGetter(getter, compiler.world)) {
         addToWorkList(getter);
         return;
@@ -228,7 +228,7 @@
       }
     } else if (member.kind == ElementKind.SETTER) {
       FunctionElement setter = member;
-      setter.computeSignature(compiler);
+      setter.computeType(compiler);
       if (universe.hasInvokedSetter(setter, compiler.world)) {
         addToWorkList(setter);
         return;
@@ -276,32 +276,27 @@
     });
   }
 
-  void registerNewSelector(Selector selector,
-                           Map<String, Set<Selector>> selectorsMap) {
-    String name = selector.name;
-    Set<Selector> selectors =
-        selectorsMap.putIfAbsent(name, () => new Setlet<Selector>());
-    if (!selectors.contains(selector)) {
-      selectors.add(selector);
-      handleUnseenSelector(name, selector);
-    }
-  }
-
-  void registerInvocation(Selector selector) {
+  void registerInvocation(UniverseSelector selector) {
     task.measure(() {
-      registerNewSelector(selector, universe.invokedNames);
+      if (universe.registerInvocation(selector)) {
+        handleUnseenSelector(selector);
+      }
     });
   }
 
-  void registerInvokedGetter(Selector selector) {
+  void registerInvokedGetter(UniverseSelector selector) {
     task.measure(() {
-      registerNewSelector(selector, universe.invokedGetters);
+      if (universe.registerInvokedGetter(selector)) {
+        handleUnseenSelector(selector);
+      }
     });
   }
 
-  void registerInvokedSetter(Selector selector) {
+  void registerInvokedSetter(UniverseSelector selector) {
     task.measure(() {
-      registerNewSelector(selector, universe.invokedSetters);
+      if (universe.registerInvokedSetter(selector)) {
+        handleUnseenSelector(selector);
+      }
     });
   }
 
@@ -355,11 +350,12 @@
         // We need to enqueue all members matching this one in subclasses, as
         // well.
         // TODO(herhut): Use TypedSelector.subtype for enqueueing
-        Selector selector = new Selector.fromElement(element);
+        UniverseSelector selector = new UniverseSelector(
+            new Selector.fromElement(element), null);
         registerSelectorUse(selector);
         if (element.isField) {
-          Selector selector =
-              new Selector.setter(element.name, element.library);
+          UniverseSelector selector = new UniverseSelector(
+              new Selector.setter(element.name, element.library), null);
           registerInvokedSetter(selector);
         }
       }
@@ -499,9 +495,11 @@
     processSet(instanceFunctionsByName, n, f);
   }
 
-  void handleUnseenSelector(String methodName, Selector selector) {
+  void handleUnseenSelector(UniverseSelector universeSelector) {
+    Selector selector = universeSelector.selector;
+    String methodName = selector.name;
     processInstanceMembers(methodName, (Element member) {
-      if (selector.appliesUnnamed(member, compiler.world)) {
+      if (universeSelector.appliesUnnamed(member, compiler.world)) {
         if (member.isFunction && selector.isGetter) {
           registerClosurizedMember(member, compiler.globalDependencies);
         }
@@ -530,7 +528,7 @@
     });
     if (selector.isGetter) {
       processInstanceFunctions(methodName, (Element member) {
-        if (selector.appliesUnnamed(member, compiler.world)) {
+        if (universeSelector.appliesUnnamed(member, compiler.world)) {
           registerClosurizedMember(member, compiler.globalDependencies);
           return true;
         }
@@ -546,7 +544,8 @@
    */
   void registerStaticUse(Element element) {
     if (element == null) return;
-    assert(invariant(element, element.isDeclaration));
+    assert(invariant(element, element.isDeclaration,
+        message: "Element ${element} is not the declaration."));
     if (Elements.isStaticOrTopLevel(element) && element.isField) {
       universe.registerStaticFieldUse(element);
     }
@@ -560,26 +559,26 @@
     universe.staticFunctionsNeedingGetter.add(element);
   }
 
-  void registerDynamicInvocation(Selector selector) {
+  void registerDynamicInvocation(UniverseSelector selector) {
     assert(selector != null);
     registerInvocation(selector);
   }
 
-  void registerSelectorUse(Selector selector) {
-    if (selector.isGetter) {
-      registerInvokedGetter(selector);
-    } else if (selector.isSetter) {
-      registerInvokedSetter(selector);
+  void registerSelectorUse(UniverseSelector universeSelector) {
+    if (universeSelector.selector.isGetter) {
+      registerInvokedGetter(universeSelector);
+    } else if (universeSelector.selector.isSetter) {
+      registerInvokedSetter(universeSelector);
     } else {
-      registerInvocation(selector);
+      registerInvocation(universeSelector);
     }
   }
 
-  void registerDynamicGetter(Selector selector) {
+  void registerDynamicGetter(UniverseSelector selector) {
     registerInvokedGetter(selector);
   }
 
-  void registerDynamicSetter(Selector selector) {
+  void registerDynamicSetter(UniverseSelector selector) {
     registerInvokedSetter(selector);
   }
 
@@ -612,14 +611,15 @@
     universe.callMethodsWithFreeTypeVariables.add(element);
   }
 
-  void registerClosurizedMember(Element element, Registry registry) {
+  void registerClosurizedMember(TypedElement element, Registry registry) {
     assert(element.isInstanceMember);
     registerClosureIfFreeTypeVariables(element, registry);
     compiler.backend.registerBoundClosure(this);
     universe.closurizedMembers.add(element);
   }
 
-  void registerClosureIfFreeTypeVariables(Element element, Registry registry) {
+  void registerClosureIfFreeTypeVariables(TypedElement element,
+                                          Registry registry) {
     if (element.computeType(compiler).containsTypeVariables) {
       compiler.backend.registerClosureWithFreeTypeVariables(
           element, this, registry);
@@ -839,7 +839,7 @@
 
   final Set<Element> newlyEnqueuedElements;
 
-  final Set<Selector> newlySeenSelectors;
+  final Set<UniverseSelector> newlySeenSelectors;
 
   bool enabledNoSuchMethod = false;
 
@@ -915,11 +915,11 @@
     }
   }
 
-  void handleUnseenSelector(String methodName, Selector selector) {
+  void handleUnseenSelector(UniverseSelector selector) {
     if (compiler.hasIncrementalSupport) {
       newlySeenSelectors.add(selector);
     }
-    super.handleUnseenSelector(methodName, selector);
+    super.handleUnseenSelector(selector);
   }
 }
 
diff --git a/pkg/compiler/lib/src/helpers/trace.dart b/pkg/compiler/lib/src/helpers/trace.dart
index a6bdcf6..f19b0d0 100644
--- a/pkg/compiler/lib/src/helpers/trace.dart
+++ b/pkg/compiler/lib/src/helpers/trace.dart
@@ -53,6 +53,12 @@
   }
 }
 
+/// Creates a function to use as an `condition` argument in [trace] that filters
+/// stack traces that contains any of the [exceptions].
+traceExceptions(List<String> exceptions) {
+  return (String stackTrace) => !exceptions.any(stackTrace.contains);
+}
+
 /// Function signature of [traceAndReport].
 typedef void TraceAndReport(Compiler compiler, Spannable node, String message,
                             {bool condition(String stackTrace), int limit,
@@ -149,7 +155,7 @@
           columnNo = line.substring(lastColon+1, rightParenPos);
           try {
             int.parse(lineNo);
-          } on FormatException catch (e) {
+          } on FormatException {
             lineNo = columnNo;
             columnNo = '';
             nextToLastColon = lastColon;
diff --git a/pkg/compiler/lib/src/inferrer/closure_tracer.dart b/pkg/compiler/lib/src/inferrer/closure_tracer.dart
index 844c76a..262f652 100644
--- a/pkg/compiler/lib/src/inferrer/closure_tracer.dart
+++ b/pkg/compiler/lib/src/inferrer/closure_tracer.dart
@@ -38,10 +38,11 @@
 
   void analyzeCall(CallSiteTypeInformation info) {
     Selector selector = info.selector;
+    TypeMask mask = info.mask;
     tracedElements.forEach((FunctionElement functionElement) {
       if (!selector.signatureApplies(functionElement)) return;
       inferrer.updateParameterAssignments(info, functionElement, info.arguments,
-          selector, remove: false, addToQueue: false);
+          selector, mask, remove: false, addToQueue: false);
     });
   }
 
diff --git a/pkg/compiler/lib/src/inferrer/concrete_types_inferrer.dart b/pkg/compiler/lib/src/inferrer/concrete_types_inferrer.dart
index ed8c156..9369d1d 100644
--- a/pkg/compiler/lib/src/inferrer/concrete_types_inferrer.dart
+++ b/pkg/compiler/lib/src/inferrer/concrete_types_inferrer.dart
@@ -517,9 +517,8 @@
   }
 
   @override
-  Selector newTypedSelector(ConcreteType receiver, Selector selector) {
-    return new TypedSelector(concreteTypeToTypeMask(receiver), selector,
-        compiler.world);
+  TypeMask newTypedSelector(ConcreteType receiver, TypeMask mask) {
+    return concreteTypeToTypeMask(receiver);
   }
 
   @override
@@ -574,12 +573,14 @@
   }
 
   @override
-  bool selectorNeedsUpdate(ConcreteType type, Selector selector) {
-    return concreteTypeToTypeMask(type) != selector.mask;
+  bool selectorNeedsUpdate(ConcreteType type, TypeMask mask) {
+    return concreteTypeToTypeMask(type) != mask;
   }
 
   @override
-  ConcreteType refineReceiver(Selector selector, ConcreteType receiverType,
+  ConcreteType refineReceiver(Selector selector,
+                              TypeMask mask,
+                              ConcreteType receiverType,
       bool isConditional) {
     if (isConditional) {
       throw new UnimplementedError("isConditional in concrete type inferrer");
@@ -707,7 +708,6 @@
       _current = null;
       return false;
     }
-    Element keyToIncrement = null;
     for (final key in concreteTypes.keys) {
       final iterator = state[key];
       if (iterator != null && iterator.moveNext()) {
@@ -993,7 +993,9 @@
     throw new UnsupportedError("");
   }
 
-  Element locateSingleElement(Selector selector, Compiler compiler) {
+  Element locateSingleElement(Selector selector,
+                              TypeMask mask,
+                              Compiler compiler) {
     throw new UnsupportedError("");
   }
 
@@ -1279,12 +1281,12 @@
    *
    * Precondition: [:(typeOfThis != null) && (returnType != null):]
    */
-  void augmentInferredSelectorType(Selector selector, TypeMask typeOfThis,
+  void augmentInferredSelectorType(Selector selector,
+                                   TypeMask typeOfThis,
                                    TypeMask returnType) {
     assert(returnType != null);
     assert(typeOfThis != null);
 
-    selector = selector.asUntyped;
     Map<TypeMask, TypeMask> currentMap = inferredSelectorTypes.putIfAbsent(
         selector, () => new Map<TypeMask, TypeMask>());
     TypeMask currentReturnType = currentMap[typeOfThis];
@@ -1493,21 +1495,19 @@
    * "I don't know".
    */
   @override
-  TypeMask getTypeOfSelector(Selector selector) {
-    Map<TypeMask, TypeMask> candidates =
-        inferredSelectorTypes[selector.asUntyped];
+  TypeMask getTypeOfSelector(Selector selector, TypeMask mask) {
+    Map<TypeMask, TypeMask> candidates = inferredSelectorTypes[selector];
     if (candidates == null) {
       return null;
     }
     TypeMask result = new TypeMask.nonNullEmpty();
-    if (selector.mask == null) {
+    if (mask == null) {
       candidates.forEach((TypeMask receiverType, TypeMask returnType) {
         result = typeMaskUnion(result, returnType);
       });
     } else {
       candidates.forEach((TypeMask receiverType, TypeMask returnType) {
-        TypeMask intersection =
-            receiverType.intersection(selector.mask, compiler.world);
+        TypeMask intersection = receiverType.intersection(mask, compiler.world);
         if (!intersection.isEmpty || intersection.isNullable) {
           result = typeMaskUnion(result, returnType);
         }
@@ -1919,7 +1919,9 @@
   }
 
   @override
-  void forEachElementMatching(Selector selector, bool f(Element element)) {
+  void forEachElementMatching(Selector selector,
+                              TypeMask mask,
+                              bool f(Element element)) {
     getMembersBySelector(selector).forEach(f);
   }
 
@@ -1989,6 +1991,7 @@
   @override
   ConcreteType registerCalledElement(Spannable node,
                                      Selector selector,
+                                     TypeMask mask,
                                      Element caller,
                                      Element callee,
                                      ArgumentsTypes<ConcreteType> arguments,
@@ -2068,6 +2071,7 @@
   @override
   ConcreteType registerCalledSelector(Node node,
                                       Selector selector,
+                                      TypeMask mask,
                                       ConcreteType receiverType,
                                       Element caller,
                                       ArgumentsTypes<ConcreteType> arguments,
@@ -2255,6 +2259,7 @@
   @override
   ConcreteType registerCalledClosure(Node node,
                                      Selector selector,
+                                     TypeMask mask,
                                      ConcreteType closure,
                                      Element caller,
                                      ArgumentsTypes<ConcreteType> arguments,
diff --git a/pkg/compiler/lib/src/inferrer/inferrer_visitor.dart b/pkg/compiler/lib/src/inferrer/inferrer_visitor.dart
index 3314fcd..e8af978 100644
--- a/pkg/compiler/lib/src/inferrer/inferrer_visitor.dart
+++ b/pkg/compiler/lib/src/inferrer/inferrer_visitor.dart
@@ -47,7 +47,7 @@
   T nonNullExact(ClassElement type);
   T nonNullEmpty();
   bool isNull(T type);
-  Selector newTypedSelector(T receiver, Selector selector);
+  TypeMask newTypedSelector(T receiver, TypeMask mask);
 
   T allocateList(T type,
                  Node node,
@@ -110,7 +110,7 @@
    * Returns `true` if `selector` should be updated to reflect the new
    * `receiverType`.
    */
-  bool selectorNeedsUpdate(T receiverType, Selector selector);
+  bool selectorNeedsUpdate(T receiverType, TypeMask mask);
 
   /**
    * Returns a new receiver type for this [selector] applied to
@@ -120,7 +120,10 @@
    * conditional send (e.g.  `a?.selector`), in which case the returned type may
    * be null.
    */
-  T refineReceiver(Selector selector, T receiverType, bool isConditional);
+  T refineReceiver(Selector selector,
+                   TypeMask mask,
+                   T receiverType,
+                   bool isConditional);
 
   /**
    * Returns the internal inferrer representation for [mask].
diff --git a/pkg/compiler/lib/src/inferrer/map_tracer.dart b/pkg/compiler/lib/src/inferrer/map_tracer.dart
index eecd7d8..94caa57 100644
--- a/pkg/compiler/lib/src/inferrer/map_tracer.dart
+++ b/pkg/compiler/lib/src/inferrer/map_tracer.dart
@@ -73,7 +73,6 @@
     if (currentUser == info.receiver) {
       if (!okMapSelectorsSet.contains(selectorName)) {
         if (selector.isCall) {
-          int positionalLength = info.arguments.positional.length;
           if (selectorName == 'addAll') {
             // All keys and values from the argument flow into
             // the map.
diff --git a/pkg/compiler/lib/src/inferrer/simple_types_inferrer.dart b/pkg/compiler/lib/src/inferrer/simple_types_inferrer.dart
index 59372ca..e9ceabb 100644
--- a/pkg/compiler/lib/src/inferrer/simple_types_inferrer.dart
+++ b/pkg/compiler/lib/src/inferrer/simple_types_inferrer.dart
@@ -124,8 +124,8 @@
     return functionType;
   }
 
-  Selector newTypedSelector(TypeMask receiver, Selector selector) {
-    return new TypedSelector(receiver, selector, compiler.world);
+  TypeMask newTypedSelector(TypeMask receiver, TypeMask mask) {
+    return receiver;
   }
 
   TypeMask addPhiInput(Local variable,
@@ -152,13 +152,16 @@
     return phiType;
   }
 
-  bool selectorNeedsUpdate(TypeMask type, Selector selector) {
-    return type != selector.mask;
+  bool selectorNeedsUpdate(TypeMask type, TypeMask mask) {
+    return type != mask;
   }
 
-  TypeMask refineReceiver(Selector selector, TypeMask receiverType,
-      bool isConditional) {
-    TypeMask newType = compiler.world.allFunctions.receiverType(selector);
+  TypeMask refineReceiver(Selector selector,
+                          TypeMask mask,
+                          TypeMask receiverType,
+                          bool isConditional) {
+    TypeMask newType =
+        compiler.world.allFunctions.receiverType(selector, mask);
     return receiverType.intersection(newType, classWorld);
   }
 
@@ -245,6 +248,7 @@
    */
   T registerCalledElement(Spannable node,
                           Selector selector,
+                          TypeMask mask,
                           Element caller,
                           Element callee,
                           ArgumentsTypes<T> arguments,
@@ -262,6 +266,7 @@
    */
   T registerCalledSelector(ast.Node node,
                            Selector selector,
+                           TypeMask mask,
                            T receiverType,
                            Element caller,
                            ArgumentsTypes<T> arguments,
@@ -278,6 +283,7 @@
    */
   T registerCalledClosure(ast.Node node,
                           Selector selector,
+                          TypeMask mask,
                           T closure,
                           Element caller,
                           ArgumentsTypes<T> arguments,
@@ -301,10 +307,13 @@
 
   /**
    * Applies [f] to all elements in the universe that match
-   * [selector]. If [f] returns false, aborts the iteration.
+   * [selector] and [mask]. If [f] returns false, aborts the iteration.
    */
-  void forEachElementMatching(Selector selector, bool f(Element element)) {
-    Iterable<Element> elements = compiler.world.allFunctions.filter(selector);
+  void forEachElementMatching(Selector selector,
+                              TypeMask mask,
+                              bool f(Element element)) {
+    Iterable<Element> elements =
+        compiler.world.allFunctions.filter(selector, mask);
     for (Element e in elements) {
       if (!f(e.implementation)) return;
     }
@@ -386,7 +395,7 @@
   }
 
   void updateSelectorInTree(
-      AstElement owner, Spannable node, Selector selector) {
+      AstElement owner, Spannable node, Selector selector, TypeMask mask) {
     if (node is cps_ir.Node) {
       // TODO(lry): update selector for IrInvokeDynamic.
       throw "updateSelector for IR node $node";
@@ -395,24 +404,24 @@
     TreeElements elements = owner.resolvedAst.elements;
     if (astNode.asSendSet() != null) {
       if (selector.isSetter || selector.isIndexSet) {
-        elements.setSelector(node, selector);
+        elements.setTypeMask(node, mask);
       } else if (selector.isGetter || selector.isIndex) {
-        elements.setGetterSelectorInComplexSendSet(node, selector);
+        elements.setGetterTypeMaskInComplexSendSet(node, mask);
       } else {
         assert(selector.isOperator);
-        elements.setOperatorSelectorInComplexSendSet(node, selector);
+        elements.setOperatorTypeMaskInComplexSendSet(node, mask);
       }
     } else if (astNode.asSend() != null) {
-      elements.setSelector(node, selector);
+      elements.setTypeMask(node, mask);
     } else {
       assert(astNode.asForIn() != null);
-      if (selector.asUntyped == compiler.iteratorSelector) {
-        elements.setIteratorSelector(node, selector);
-      } else if (selector.asUntyped == compiler.currentSelector) {
-        elements.setCurrentSelector(node, selector);
+      if (selector == compiler.iteratorSelector) {
+        elements.setIteratorTypeMask(node, mask);
+      } else if (selector == compiler.currentSelector) {
+        elements.setCurrentTypeMask(node, mask);
       } else {
-        assert(selector.asUntyped == compiler.moveNextSelector);
-        elements.setMoveNextSelector(node, selector);
+        assert(selector == compiler.moveNextSelector);
+        elements.setMoveNextTypeMask(node, mask);
       }
     }
   }
@@ -448,7 +457,7 @@
   SideEffects sideEffects = new SideEffects.empty();
   final Element outermostElement;
   final InferrerEngine<T, TypeSystem<T>> inferrer;
-  final Setlet<Element> capturedVariables = new Setlet<Element>();
+  final Setlet<Entity> capturedVariables = new Setlet<Entity>();
 
   SimpleTypeInferrerVisitor.internal(analyzedElement,
                                      this.outermostElement,
@@ -572,6 +581,7 @@
           analyzeSuperConstructorCall(target, arguments);
           inferrer.registerCalledElement(node,
                                          null,
+                                         null,
                                          outermostElement,
                                          target.implementation,
                                          arguments,
@@ -595,7 +605,7 @@
       }
       returnType = types.nonNullExact(cls);
     } else {
-      signature.forEachParameter((element) {
+      signature.forEachParameter((LocalParameterElement element) {
         locals.update(element, inferrer.typeOfElement(element), node);
       });
       visit(node.body);
@@ -741,9 +751,9 @@
     return compiler.world.isSubclassOf(enclosing, cls);
   }
 
-  void checkIfExposesThis(Selector selector) {
+  void checkIfExposesThis(Selector selector, TypeMask mask) {
     if (isThisExposed) return;
-    inferrer.forEachElementMatching(selector, (element) {
+    inferrer.forEachElementMatching(selector, mask, (element) {
       if (element.isField) {
         if (!selector.isSetter
             && isInClassOrSubclass(element)
@@ -787,9 +797,14 @@
 
     Selector getterSelector =
         elements.getGetterSelectorInComplexSendSet(node);
+    TypeMask getterMask =
+        elements.getGetterTypeMaskInComplexSendSet(node);
     Selector operatorSelector =
         elements.getOperatorSelectorInComplexSendSet(node);
+    TypeMask operatorMask =
+        elements.getOperatorTypeMaskInComplexSendSet(node);
     Selector setterSelector = elements.getSelector(node);
+    TypeMask setterMask = elements.getTypeMask(node);
 
     String op = node.assignmentOperator.source;
     bool isIncrementOrDecrement = op == '++' || op == '--';
@@ -807,13 +822,12 @@
     }
 
     T rhsType;
-    T indexType;
 
     if (isIncrementOrDecrement) {
       rhsType = types.uint31Type;
-      if (node.isIndex) indexType = visit(node.arguments.head);
+      if (node.isIndex) visit(node.arguments.head);
     } else if (node.isIndex) {
-      indexType = visit(node.arguments.head);
+      visit(node.arguments.head);
       rhsType = visit(node.arguments.tail.head);
     } else {
       rhsType = visit(node.arguments.head);
@@ -828,10 +842,12 @@
       }
       if (!isThisExposed && isCallOnThis) {
         checkIfExposesThis(
-            types.newTypedSelector(receiverType, setterSelector));
+            setterSelector,
+            types.newTypedSelector(receiverType, setterMask));
         if (getterSelector != null) {
           checkIfExposesThis(
-              types.newTypedSelector(receiverType, getterSelector));
+              getterSelector,
+              types.newTypedSelector(receiverType, getterMask));
         }
       }
     }
@@ -840,7 +856,7 @@
       return internalError(node, "Unexpected index operation");
     } else if (op == '=') {
       return handlePlainAssignment(
-          node, element, setterSelector, receiverType, rhsType,
+          node, element, setterSelector, setterMask, receiverType, rhsType,
           node.arguments.head);
     } else {
       // [: foo++ :] or [: foo += 1 :].
@@ -852,33 +868,37 @@
         newType = types.dynamicType;
       } else if (Elements.isStaticOrTopLevelField(element)) {
         Element getterElement = elements[node.selector];
-        getterType =
-            handleStaticSend(node, getterSelector, getterElement, null);
+        getterType = handleStaticSend(
+            node, getterSelector, getterMask, getterElement, null);
         newType = handleDynamicSend(
-            node, operatorSelector, getterType, operatorArguments);
+            node, operatorSelector, operatorMask,
+            getterType, operatorArguments);
         handleStaticSend(
-            node, setterSelector, element,
+            node, setterSelector, setterMask, element,
             new ArgumentsTypes<T>([newType], null));
       } else if (Elements.isUnresolved(element)
                  || element.isSetter
                  || element.isField) {
         getterType = handleDynamicSend(
-            node, getterSelector, receiverType, null);
+            node, getterSelector, getterMask, receiverType, null);
         newType = handleDynamicSend(
-            node, operatorSelector, getterType, operatorArguments);
-        handleDynamicSend(node, setterSelector, receiverType,
+            node, operatorSelector, operatorMask,
+            getterType, operatorArguments);
+        handleDynamicSend(node, setterSelector, setterMask, receiverType,
                           new ArgumentsTypes<T>([newType], null));
       } else if (element.isLocal) {
         LocalElement local = element;
         getterType = locals.use(local);
         newType = handleDynamicSend(
-            node, operatorSelector, getterType, operatorArguments);
+            node, operatorSelector, operatorMask,
+            getterType, operatorArguments);
         locals.update(element, newType, node);
       } else {
         // Bogus SendSet, for example [: myMethod += 42 :].
         getterType = types.dynamicType;
         newType = handleDynamicSend(
-            node, operatorSelector, getterType, operatorArguments);
+            node, operatorSelector, operatorMask,
+            getterType, operatorArguments);
       }
 
       if (node.isPostfix) {
@@ -896,24 +916,32 @@
       T indexType,
       T rhsType) {
     Selector getterSelector =
-         elements.getGetterSelectorInComplexSendSet(node);
-     Selector operatorSelector =
-         elements.getOperatorSelectorInComplexSendSet(node);
-     Selector setterSelector = elements.getSelector(node);
+        elements.getGetterSelectorInComplexSendSet(node);
+    TypeMask getterMask =
+        elements.getGetterTypeMaskInComplexSendSet(node);
+    Selector operatorSelector =
+        elements.getOperatorSelectorInComplexSendSet(node);
+    TypeMask operatorMask =
+        elements.getOperatorTypeMaskInComplexSendSet(node);
+    Selector setterSelector = elements.getSelector(node);
+    TypeMask setterMask = elements.getTypeMask(node);
 
     T getterType = handleDynamicSend(
         node,
         getterSelector,
+        getterMask,
         receiverType,
         new ArgumentsTypes<T>([indexType], null));
     T returnType = handleDynamicSend(
         node,
         operatorSelector,
+        operatorMask,
         getterType,
         new ArgumentsTypes<T>([rhsType], null));
     handleDynamicSend(
         node,
         setterSelector,
+        setterMask,
         receiverType,
         new ArgumentsTypes<T>([indexType, returnType], null));
 
@@ -1126,9 +1154,11 @@
   /// Handle index set, like `foo[0] = 42`.
   T handleIndexSet(ast.SendSet node, T receiverType, T indexType, T rhsType) {
     Selector setterSelector = elements.getSelector(node);
+    TypeMask setterMask = elements.getTypeMask(node);
     handleDynamicSend(
         node,
         setterSelector,
+        setterMask,
         receiverType,
         new ArgumentsTypes<T>([indexType, rhsType], null));
     return rhsType;
@@ -1181,6 +1211,7 @@
   T handlePlainAssignment(ast.Node node,
                           Element element,
                           Selector setterSelector,
+                          TypeMask setterMask,
                           T receiverType,
                           T rhsType,
                           ast.Node rhs) {
@@ -1188,14 +1219,15 @@
     if (Elements.isErroneous(element)) {
       // Code will always throw.
     } else if (Elements.isStaticOrTopLevelField(element)) {
-      handleStaticSend(node, setterSelector, element, arguments);
+      handleStaticSend(node, setterSelector, setterMask, element, arguments);
     } else if (Elements.isUnresolved(element) || element.isSetter) {
       if (analyzedElement.isGenerativeConstructor
           && (node.asSendSet() != null)
           && (node.asSendSet().receiver != null)
           && node.asSendSet().receiver.isThis()) {
         Iterable<Element> targets = compiler.world.allFunctions.filter(
-            types.newTypedSelector(thisType, setterSelector));
+            setterSelector,
+            types.newTypedSelector(thisType, setterMask));
         // We just recognized a field initialization of the form:
         // `this.foo = 42`. If there is only one target, we can update
         // its type.
@@ -1207,7 +1239,7 @@
         }
       }
       handleDynamicSend(
-          node, setterSelector, receiverType, arguments);
+          node, setterSelector, setterMask, receiverType, arguments);
     } else if (element.isField) {
       if (element.isFinal) {
         inferrer.recordTypeOfFinalField(
@@ -1220,7 +1252,7 @@
           inferrer.recordTypeOfNonFinalField(node, element, rhsType);
         } else {
           handleDynamicSend(
-              node, setterSelector, receiverType, arguments);
+              node, setterSelector, setterMask, receiverType, arguments);
         }
       }
     } else if (element.isLocal) {
@@ -1235,12 +1267,13 @@
         ? null
         : analyzeArguments(node.arguments);
     Selector selector = elements.getSelector(node);
+    TypeMask mask = elements.getTypeMask(node);
     // TODO(herhut): We could do better here if we knew what we
     // are calling does not expose this.
     isThisExposed = true;
     // Ensure we create a node, to make explicit the call to the
     // `noSuchMethod` handler.
-    return handleDynamicSend(node, selector, superType, arguments);
+    return handleDynamicSend(node, selector, mask, superType, arguments);
   }
 
   /// Handle a .call invocation on the values retrieved from the super
@@ -1251,11 +1284,12 @@
       ast.NodeList arguments) {
     ArgumentsTypes argumentTypes = analyzeArguments(arguments.nodes);
     Selector selector = elements.getSelector(node);
+    TypeMask mask = elements.getTypeMask(node);
     // TODO(herhut): We could do better here if we knew what we
     // are calling does not expose this.
     isThisExposed = true;
     return inferrer.registerCalledClosure(
-        node, selector, inferrer.typeOfElement(element),
+        node, selector, mask, inferrer.typeOfElement(element),
         outermostElement, argumentTypes, sideEffects, inLoop);
   }
 
@@ -1266,8 +1300,10 @@
     // TODO(herhut): We could do better here if we knew what we
     // are calling does not expose this.
     isThisExposed = true;
+    Selector selector = elements.getSelector(node);
+    TypeMask mask = elements.getTypeMask(node);
     return handleStaticSend(
-        node, elements.getSelector(node), method, arguments);
+        node, selector, mask, method, arguments);
   }
 
   /// Handle access to a super field or getter [element].
@@ -1276,8 +1312,10 @@
     // TODO(herhut): We could do better here if we knew what we
     // are calling does not expose this.
     isThisExposed = true;
+    Selector selector = elements.getSelector(node);
+    TypeMask mask = elements.getTypeMask(node);
     return handleStaticSend(
-        node, elements.getSelector(node), element, null);
+        node, selector, mask, element, null);
   }
 
   /// Handle super constructor invocation.
@@ -1288,8 +1326,10 @@
     assert(visitingInitializers);
     seenSuperConstructorCall = true;
     analyzeSuperConstructorCall(element, arguments);
+    Selector selector = elements.getSelector(node);
+    TypeMask mask = elements.getTypeMask(node);
     return handleStaticSend(
-        node, elements.getSelector(node), element, arguments);
+        node, selector, mask, element, arguments);
   }
 
   @override
@@ -1497,7 +1537,11 @@
     ArgumentsTypes<T> arguments =
         new ArgumentsTypes<T>(<T>[expression.accept(this)], null);
     return handleStaticSend(
-        node, new Selector.fromElement(element), element, arguments);
+        node,
+        new Selector.fromElement(element),
+        null,
+        element,
+        arguments);
   }
 
   @override
@@ -1543,14 +1587,16 @@
       return handleForeignSend(node, element);
     }
     Selector selector = elements.getSelector(node);
+    TypeMask mask = elements.getTypeMask(node);
     // In erroneous code the number of arguments in the selector might not
     // match the function element.
     // TODO(polux): return nonNullEmpty and check it doesn't break anything
-    if (!selector.applies(element, compiler.world)) {
+    if (!selector.applies(element, compiler.world) ||
+        (mask != null && !mask.canHit(element, selector, compiler.world))) {
       return types.dynamicType;
     }
 
-    T returnType = handleStaticSend(node, selector, element, arguments);
+    T returnType = handleStaticSend(node, selector, mask, element, arguments);
     if (Elements.isGrowableListConstructorCall(element, node, compiler)) {
       return inferrer.concreteTypes.putIfAbsent(
           node, () => types.allocateList(
@@ -1592,9 +1638,10 @@
   T handleStaticFieldOrGetterInvoke(ast.Send node, Element element) {
     ArgumentsTypes arguments = analyzeArguments(node.arguments);
     Selector selector = elements.getSelector(node);
-    handleStaticSend(node, selector, element, arguments);
+    TypeMask mask = elements.getTypeMask(node);
+    handleStaticSend(node, selector, mask, element, arguments);
     return inferrer.registerCalledClosure(
-              node, selector, inferrer.typeOfElement(element),
+              node, selector, mask, inferrer.typeOfElement(element),
               outermostElement, arguments, sideEffects, inLoop);
   }
 
@@ -1605,7 +1652,8 @@
     }
     ArgumentsTypes arguments = analyzeArguments(node.arguments);
     Selector selector = elements.getSelector(node);
-    return handleStaticSend(node, selector, function, arguments);
+    TypeMask mask = elements.getTypeMask(node);
+    return handleStaticSend(node, selector, mask, function, arguments);
   }
 
   /// Handle an static invocation of an unresolved target or with incompatible
@@ -1696,6 +1744,26 @@
   }
 
   @override
+  T visitStaticSetterInvoke(
+      ast.Send node,
+      MethodElement setter,
+      ast.NodeList arguments,
+      CallStructure callStructure,
+      _) {
+    return handleInvalidStaticInvoke(node);
+  }
+
+  @override
+  T visitTopLevelSetterInvoke(
+      ast.Send node,
+      MethodElement setter,
+      ast.NodeList arguments,
+      CallStructure callStructure,
+      _) {
+    return handleInvalidStaticInvoke(node);
+  }
+
+  @override
   T visitUnresolvedInvoke(
       ast.Send node,
       Element element,
@@ -1708,8 +1776,9 @@
   T handleForeignSend(ast.Send node, Element element) {
     ArgumentsTypes arguments = analyzeArguments(node.arguments);
     Selector selector = elements.getSelector(node);
+    TypeMask mask = elements.getTypeMask(node);
     String name = element.name;
-    handleStaticSend(node, selector, element, arguments);
+    handleStaticSend(node, selector, mask, element, arguments);
     if (name == 'JS' || name == 'JS_EMBEDDED_GLOBAL' || name == 'JS_BUILTIN') {
       native.NativeBehavior nativeBehavior =
           compiler.enqueuer.resolution.nativeEnqueuer.getNativeBehaviorOf(node);
@@ -1759,17 +1828,23 @@
 
   /// Read a static or top level field.
   T handleStaticFieldGet(ast.Send node, FieldElement field) {
-    return handleStaticSend(node, elements.getSelector(node), field, null);
+    Selector selector = elements.getSelector(node);
+    TypeMask mask = elements.getTypeMask(node);
+    return handleStaticSend(node, selector, mask, field, null);
   }
 
   /// Invoke a static or top level getter.
   T handleStaticGetterGet(ast.Send node, MethodElement getter) {
-    return handleStaticSend(node, elements.getSelector(node), getter, null);
+    Selector selector = elements.getSelector(node);
+    TypeMask mask = elements.getTypeMask(node);
+    return handleStaticSend(node, selector, mask, getter, null);
   }
 
   /// Closurize a static or top level function.
   T handleStaticFunctionGet(ast.Send node, MethodElement function) {
-    return handleStaticSend(node, elements.getSelector(node), function, null);
+    Selector selector = elements.getSelector(node);
+    TypeMask mask = elements.getTypeMask(node);
+    return handleStaticSend(node, selector, mask, function, null);
   }
 
   @override
@@ -1871,6 +1946,22 @@
   }
 
   @override
+  T visitStaticSetterGet(
+      ast.Send node,
+      MethodElement setter,
+      _) {
+    return types.dynamicType;
+  }
+
+  @override
+  T visitTopLevelSetterGet(
+      ast.Send node,
+      MethodElement setter,
+      _) {
+    return types.dynamicType;
+  }
+
+  @override
   T visitUnresolvedGet(
       ast.Send node,
       Element element,
@@ -1882,8 +1973,9 @@
   T handleCallInvoke(ast.Send node, T closure) {
     ArgumentsTypes arguments = analyzeArguments(node.arguments);
     Selector selector = elements.getSelector(node);
+    TypeMask mask = elements.getTypeMask(node);
     return inferrer.registerCalledClosure(
-        node, selector, closure, outermostElement, arguments,
+        node, selector, mask, closure, outermostElement, arguments,
         sideEffects, inLoop);
   }
 
@@ -1935,17 +2027,29 @@
       _) {
     ArgumentsTypes argumentTypes = analyzeArguments(node.arguments);
     Selector selector = elements.getSelector(node);
-    if (!selector.applies(function, compiler.world)) return types.dynamicType;
+    TypeMask mask = elements.getTypeMask(node);
     // This only works for function statements. We need a
     // more sophisticated type system with function types to support
     // more.
     return inferrer.registerCalledElement(
-        node, selector, outermostElement, function, argumentTypes,
+        node, selector, mask, outermostElement, function, argumentTypes,
         sideEffects, inLoop);
   }
 
+  @override
+  T visitLocalFunctionIncompatibleInvoke(
+      ast.Send node,
+      LocalFunctionElement function,
+      ast.NodeList arguments,
+      CallStructure callStructure,
+      _) {
+    analyzeArguments(node.arguments);
+    return types.dynamicType;
+  }
+
   T handleStaticSend(ast.Node node,
                      Selector selector,
+                     TypeMask mask,
                      Element element,
                      ArgumentsTypes arguments) {
     assert(!element.isFactoryConstructor ||
@@ -1956,20 +2060,21 @@
     // need to pay attention if the constructor is pointing to an erroneous
     // element.
     return inferrer.registerCalledElement(
-        node, selector, outermostElement, element, arguments,
+        node, selector, mask, outermostElement, element, arguments,
         sideEffects, inLoop);
   }
 
   T handleDynamicSend(ast.Node node,
                       Selector selector,
+                      TypeMask mask,
                       T receiverType,
                       ArgumentsTypes arguments) {
     assert(receiverType != null);
-    if (types.selectorNeedsUpdate(receiverType, selector)) {
-      selector = (receiverType == types.dynamicType)
-          ? selector.asUntyped
-          : types.newTypedSelector(receiverType, selector);
-      inferrer.updateSelectorInTree(analyzedElement, node, selector);
+    if (types.selectorNeedsUpdate(receiverType, mask)) {
+      mask = receiverType == types.dynamicType
+          ? null
+          : types.newTypedSelector(receiverType, mask);
+      inferrer.updateSelectorInTree(analyzedElement, node, selector, mask);
     }
 
     // If the receiver of the call is a local, we may know more about
@@ -1981,15 +2086,15 @@
       if (receiver != null) {
         Element element = elements[receiver];
         if (Elements.isLocal(element) && !capturedVariables.contains(element)) {
-          T refinedType = types.refineReceiver(selector, receiverType,
-              send.isConditional);
+          T refinedType = types.refineReceiver(
+              selector, mask, receiverType, send.isConditional);
           locals.update(element, refinedType, node);
         }
       }
     }
 
     return inferrer.registerCalledSelector(
-        node, selector, receiverType, outermostElement, arguments,
+        node, selector, mask, receiverType, outermostElement, arguments,
         sideEffects, inLoop);
   }
 
@@ -2017,15 +2122,16 @@
     }
 
     Selector selector = elements.getSelector(node);
+    TypeMask mask = elements.getTypeMask(node);
     if (!isThisExposed && isCallOnThis) {
-      checkIfExposesThis(types.newTypedSelector(receiverType, selector));
+      checkIfExposesThis(selector, types.newTypedSelector(receiverType, mask));
     }
 
     ArgumentsTypes arguments = node.isPropertyAccess
         ? null
         : analyzeArguments(node.arguments);
-    if (selector.name == '=='
-        || selector.name == '!=') {
+    if (selector.name == '==' ||
+        selector.name == '!=') {
       if (types.isNull(receiverType)) {
         potentiallyAddNullCheck(node, node.arguments.head);
         return types.boolType;
@@ -2034,7 +2140,7 @@
         return types.boolType;
       }
     }
-    return handleDynamicSend(node, selector, receiverType, arguments);
+    return handleDynamicSend(node, selector, mask, receiverType, arguments);
   }
 
   void recordReturnType(T type) {
@@ -2071,6 +2177,7 @@
     ArgumentsTypes arguments = new ArgumentsTypes<T>(unnamed, named);
     return inferrer.registerCalledElement(node,
                                           null,
+                                          null,
                                           outermostElement,
                                           element,
                                           arguments,
@@ -2103,12 +2210,18 @@
     return null;
   }
 
-  T handleForInLoop(ast.ForIn node, T iteratorType, Selector currentSelector,
-                    Selector moveNextSelector) {
-    handleDynamicSend(node, moveNextSelector, iteratorType,
-                      new ArgumentsTypes<T>.empty());
-    T currentType = handleDynamicSend(node, currentSelector, iteratorType,
-                                      new ArgumentsTypes<T>.empty());
+  T handleForInLoop(ast.ForIn node,
+                    T iteratorType,
+                    Selector currentSelector,
+                    TypeMask currentMask,
+                    Selector moveNextSelector,
+                    TypeMask moveNextMask) {
+    handleDynamicSend(
+        node, moveNextSelector, moveNextMask, iteratorType,
+        new ArgumentsTypes<T>.empty());
+    T currentType = handleDynamicSend(
+        node, currentSelector, currentMask, iteratorType,
+        new ArgumentsTypes<T>.empty());
 
     if (node.expression.isThis()) {
       // Any reasonable implementation of an iterator would expose
@@ -2119,6 +2232,7 @@
     ast.Node identifier = node.declaredIdentifier;
     Element element = elements.getForInVariable(node);
     Selector selector = elements.getSelector(identifier);
+    TypeMask mask = elements.getTypeMask(identifier);
 
     T receiverType;
     if (element != null && element.isInstanceMember) {
@@ -2127,7 +2241,7 @@
       receiverType = types.dynamicType;
     }
 
-    handlePlainAssignment(identifier, element, selector,
+    handlePlainAssignment(identifier, element, selector, mask,
                           receiverType, currentType,
                           node.expression);
     return handleLoop(node, () {
@@ -2139,30 +2253,36 @@
     T expressionType = visit(node.expression);
 
     Selector currentSelector = elements.getCurrentSelector(node);
+    TypeMask currentMask = elements.getCurrentTypeMask(node);
     Selector moveNextSelector = elements.getMoveNextSelector(node);
+    TypeMask moveNextMask = elements.getMoveNextTypeMask(node);
 
     js.JavaScriptBackend backend = compiler.backend;
     Element ctor = backend.getStreamIteratorConstructor();
 
     /// Synthesize a call to the [StreamIterator] constructor.
-    T iteratorType = handleStaticSend(node, null, ctor,
+    T iteratorType = handleStaticSend(node, null, null, ctor,
                                       new ArgumentsTypes<T>([expressionType],
                                                             null));
 
-    return handleForInLoop(node, iteratorType, currentSelector,
-                           moveNextSelector);
+    return handleForInLoop(node, iteratorType, currentSelector, currentMask,
+                           moveNextSelector, moveNextMask);
   }
 
   T visitSyncForIn(ast.SyncForIn node) {
     T expressionType = visit(node.expression);
     Selector iteratorSelector = elements.getIteratorSelector(node);
+    TypeMask iteratorMask = elements.getIteratorTypeMask(node);
     Selector currentSelector = elements.getCurrentSelector(node);
+    TypeMask currentMask = elements.getCurrentTypeMask(node);
     Selector moveNextSelector = elements.getMoveNextSelector(node);
+    TypeMask moveNextMask = elements.getMoveNextTypeMask(node);
 
-    T iteratorType = handleDynamicSend(node, iteratorSelector, expressionType,
-                                       new ArgumentsTypes<T>.empty());
+    T iteratorType = handleDynamicSend(
+        node, iteratorSelector, iteratorMask, expressionType,
+        new ArgumentsTypes<T>.empty());
 
-    return handleForInLoop(node, iteratorType, currentSelector,
-                           moveNextSelector);
+    return handleForInLoop(node, iteratorType, currentSelector, currentMask,
+                           moveNextSelector, moveNextMask);
   }
 }
diff --git a/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart b/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart
index 7d760e5..506985e 100644
--- a/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart
+++ b/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart
@@ -6,7 +6,6 @@
 
 import 'dart:collection' show Queue, IterableBase;
 
-import '../constants/expressions.dart';
 import '../constants/values.dart';
 import '../cps_ir/cps_ir_nodes.dart' as cps_ir
     show Node;
@@ -245,15 +244,18 @@
         firstType.type.union(secondType.type, classWorld));
   }
 
-  bool selectorNeedsUpdate(TypeInformation info, Selector selector)
-  {
-    return info.type != selector.mask;
+  bool selectorNeedsUpdate(TypeInformation info, TypeMask mask) {
+    return info.type != mask;
   }
 
-  TypeInformation refineReceiver(Selector selector, TypeInformation receiver,
+  TypeInformation refineReceiver(
+      Selector selector,
+      TypeMask mask,
+      TypeInformation receiver,
       bool isConditional) {
     if (receiver.type.isExact) return receiver;
-    TypeMask otherType = compiler.world.allFunctions.receiverType(selector);
+    TypeMask otherType =
+        compiler.world.allFunctions.receiverType(selector, mask);
     // Conditional sends (a?.b) can still narrow the possible types of `a`,
     // however, we still need to consider that `a` may be null.
     if (isConditional) {
@@ -434,13 +436,11 @@
     return map;
   }
 
-  Selector newTypedSelector(TypeInformation info, Selector selector) {
+  TypeMask newTypedSelector(TypeInformation info, TypeMask mask) {
     // Only type the selector if [info] is concrete, because the other
     // kinds of [TypeInformation] have the empty type at this point of
     // analysis.
-    return info.isConcrete
-        ? new TypedSelector(info.type, selector, classWorld)
-        : selector;
+    return info.isConcrete ? info.type : mask;
   }
 
   TypeInformation allocateDiamondPhi(TypeInformation firstInput,
@@ -589,15 +589,15 @@
       new Selector.call('removeLast', null, 0)
     ]);
 
-  bool returnsListElementType(Selector selector) {
-    return (selector.mask != null) &&
-           selector.mask.isContainer &&
-           _returnsListElementTypeSet.contains(selector.asUntyped);
+  bool returnsListElementType(Selector selector, TypeMask mask) {
+    return mask != null &&
+           mask.isContainer &&
+           _returnsListElementTypeSet.contains(selector);
   }
 
-  bool returnsMapValueType(Selector selector) {
-    return (selector.mask != null) &&
-           selector.mask.isMap &&
+  bool returnsMapValueType(Selector selector, TypeMask mask) {
+    return mask != null &&
+           mask.isMap &&
            selector.isIndex;
   }
 
@@ -863,8 +863,8 @@
       if (!info.inLoop) return;
       if (info is StaticCallSiteTypeInformation) {
         compiler.world.addFunctionCalledInLoop(info.calledElement);
-      } else if (info.selector.mask != null &&
-                 !info.selector.mask.containsAll(compiler.world)) {
+      } else if (info.mask != null &&
+                 !info.mask.containsAll(compiler.world)) {
         // For instance methods, we only register a selector called in a
         // loop if it is a typed selector, to avoid marking too many
         // methods as being called from within a loop. This cuts down
@@ -921,6 +921,7 @@
                                   Element callee,
                                   ArgumentsTypes arguments,
                                   Selector selector,
+                                  TypeMask mask,
                                   {bool remove, bool addToQueue: true}) {
     if (callee.name == Compiler.NO_SUCH_METHOD) return;
     if (callee.isField) {
@@ -1098,13 +1099,14 @@
 
   TypeInformation registerCalledElement(Spannable node,
                                         Selector selector,
+                                        TypeMask mask,
                                         Element caller,
                                         Element callee,
                                         ArgumentsTypes arguments,
                                         SideEffects sideEffects,
                                         bool inLoop) {
     CallSiteTypeInformation info = new StaticCallSiteTypeInformation(
-          types.currentMember, node, caller, callee, selector, arguments,
+          types.currentMember, node, caller, callee, selector, mask, arguments,
           inLoop);
     info.addToGraph(this);
     allocatedCalls.add(info);
@@ -1114,6 +1116,7 @@
 
   TypeInformation registerCalledSelector(ast.Node node,
                                          Selector selector,
+                                         TypeMask mask,
                                          TypeInformation receiverType,
                                          Element caller,
                                          ArgumentsTypes arguments,
@@ -1121,16 +1124,17 @@
                                          bool inLoop) {
     if (selector.isClosureCall) {
       return registerCalledClosure(
-          node, selector, receiverType, caller, arguments, sideEffects, inLoop);
+          node, selector, mask, receiverType,
+          caller, arguments, sideEffects, inLoop);
     }
 
-    compiler.world.allFunctions.filter(selector).forEach((callee) {
+    compiler.world.allFunctions.filter(selector, mask).forEach((callee) {
       updateSideEffects(sideEffects, selector, callee);
     });
 
     CallSiteTypeInformation info = new DynamicCallSiteTypeInformation(
-          types.currentMember, node, caller, selector, receiverType, arguments,
-          inLoop);
+          types.currentMember, node, caller, selector, mask,
+          receiverType, arguments, inLoop);
 
     info.addToGraph(this);
     allocatedCalls.add(info);
@@ -1147,6 +1151,7 @@
 
   TypeInformation registerCalledClosure(ast.Node node,
                                         Selector selector,
+                                        TypeMask mask,
                                         TypeInformation closure,
                                         Element caller,
                                         ArgumentsTypes arguments,
@@ -1155,7 +1160,7 @@
     sideEffects.setDependsOnSomething();
     sideEffects.setAllSideEffects();
     CallSiteTypeInformation info = new ClosureCallSiteTypeInformation(
-          types.currentMember, node, caller, selector, closure, arguments,
+          types.currentMember, node, caller, selector, mask, closure, arguments,
           inLoop);
     info.addToGraph(this);
     allocatedCalls.add(info);
@@ -1295,7 +1300,7 @@
     return info.checksGrowable;
   }
 
-  TypeMask getTypeOfSelector(Selector selector) {
+  TypeMask getTypeOfSelector(Selector selector, TypeMask mask) {
     if (compiler.disableTypeInference) return compiler.typesTask.dynamicType;
     // Bailout for closure calls. We're not tracking types of
     // closures.
@@ -1303,20 +1308,21 @@
     if (selector.isSetter || selector.isIndexSet) {
       return compiler.typesTask.dynamicType;
     }
-    if (inferrer.returnsListElementType(selector)) {
-      ContainerTypeMask mask = selector.mask;
-      TypeMask elementType = mask.elementType;
+    if (inferrer.returnsListElementType(selector, mask)) {
+      ContainerTypeMask containerTypeMask = mask;
+      TypeMask elementType = containerTypeMask.elementType;
       return elementType == null ? compiler.typesTask.dynamicType : elementType;
     }
-    if (inferrer.returnsMapValueType(selector)) {
-      MapTypeMask mask = selector.mask;
-      TypeMask valueType = mask.valueType;
+    if (inferrer.returnsMapValueType(selector, mask)) {
+      MapTypeMask mapTypeMask = mask;
+      TypeMask valueType = mapTypeMask.valueType;
       return valueType == null ? compiler.typesTask.dynamicType
                                : valueType;
     }
 
     TypeMask result = const TypeMask.nonNullEmpty();
-    Iterable<Element> elements = compiler.world.allFunctions.filter(selector);
+    Iterable<Element> elements =
+        compiler.world.allFunctions.filter(selector, mask);
     for (Element element in elements) {
       TypeMask type =
           inferrer.typeOfElementWithSelector(element, selector).type;
diff --git a/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart b/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
index 7df1cbb..51c39f5 100644
--- a/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
+++ b/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
@@ -627,6 +627,7 @@
   final Spannable call;
   final Element caller;
   final Selector selector;
+  final TypeMask mask;
   final ArgumentsTypes arguments;
   final bool inLoop;
 
@@ -635,6 +636,7 @@
       this.call,
       this.caller,
       this.selector,
+      this.mask,
       this.arguments,
       this.inLoop) : super.noAssignments(context);
 
@@ -656,9 +658,10 @@
       Element enclosing,
       this.calledElement,
       Selector selector,
+      TypeMask mask,
       ArgumentsTypes arguments,
       bool inLoop)
-      : super(context, call, enclosing, selector, arguments, inLoop);
+      : super(context, call, enclosing, selector, mask, arguments, inLoop);
 
   void addToGraph(TypeGraphInferrerEngine inferrer) {
     MemberTypeInformation callee =
@@ -669,7 +672,7 @@
       arguments.forEach((info) => info.addUser(this));
     }
     inferrer.updateParameterAssignments(
-        this, calledElement, arguments, selector, remove: false,
+        this, calledElement, arguments, selector, mask, remove: false,
         addToQueue: false);
   }
 
@@ -723,15 +726,16 @@
       Spannable call,
       Element enclosing,
       Selector selector,
+      TypeMask mask,
       this.receiver,
       ArgumentsTypes arguments,
       bool inLoop)
-      : super(context, call, enclosing, selector, arguments, inLoop);
+      : super(context, call, enclosing, selector, mask, arguments, inLoop);
 
   void addToGraph(TypeGraphInferrerEngine inferrer) {
     assert(receiver != null);
-    Selector typedSelector = computeTypedSelector(inferrer);
-    targets = inferrer.compiler.world.allFunctions.filter(typedSelector);
+    TypeMask typeMask = computeTypedSelector(inferrer);
+    targets = inferrer.compiler.world.allFunctions.filter(selector, typeMask);
     receiver.addUser(this);
     if (arguments != null) {
       arguments.forEach((info) => info.addUser(this));
@@ -741,22 +745,21 @@
       callee.addCall(caller, call);
       callee.addUser(this);
       inferrer.updateParameterAssignments(
-          this, element, arguments, typedSelector, remove: false,
+          this, element, arguments, selector, typeMask, remove: false,
           addToQueue: false);
     }
   }
 
   Iterable<Element> get callees => targets.map((e) => e.implementation);
 
-  Selector computeTypedSelector(TypeGraphInferrerEngine inferrer) {
+  TypeMask computeTypedSelector(TypeGraphInferrerEngine inferrer) {
     TypeMask receiverType = receiver.type;
 
-    if (selector.mask != receiverType) {
+    if (mask != receiverType) {
       return receiverType == inferrer.compiler.typesTask.dynamicType
-          ? selector.asUntyped
-          : new TypedSelector(receiverType, selector, inferrer.classWorld);
+          ? null : receiverType;
     } else {
-      return selector;
+      return mask;
     }
   }
 
@@ -776,12 +779,13 @@
    * [int.operator+] only says it returns a [num].
    */
   TypeInformation handleIntrisifiedSelector(Selector selector,
+                                            TypeMask mask,
                                             TypeGraphInferrerEngine inferrer) {
     ClassWorld classWorld = inferrer.classWorld;
     if (!classWorld.backend.intImplementation.isResolved) return null;
     TypeMask emptyType = const TypeMask.nonNullEmpty();
-    if (selector.mask == null) return null;
-    if (!selector.mask.containsOnlyInt(classWorld)) {
+    if (mask == null) return null;
+    if (!mask.containsOnlyInt(classWorld)) {
       return null;
     }
     if (!selector.isCall && !selector.isOperator) return null;
@@ -855,21 +859,22 @@
 
   TypeMask computeType(TypeGraphInferrerEngine inferrer) {
     Iterable<Element> oldTargets = targets;
-    Selector typedSelector = computeTypedSelector(inferrer);
-    inferrer.updateSelectorInTree(caller, call, typedSelector);
+    TypeMask typeMask = computeTypedSelector(inferrer);
+    inferrer.updateSelectorInTree(caller, call, selector, typeMask);
 
     Compiler compiler = inferrer.compiler;
-    Selector selectorToUse = typedSelector.extendIfReachesAll(compiler);
+    TypeMask maskToUse =
+        compiler.world.extendMaskIfReachesAll(selector, typeMask);
     bool canReachAll = compiler.enabledInvokeOn &&
-        (selectorToUse != typedSelector);
+        (maskToUse != typeMask);
 
     // If this call could potentially reach all methods that satisfy
     // the untyped selector (through noSuchMethod's `Invocation`
     // and a call to `delegate`), we iterate over all these methods to
     // update their parameter types.
-    targets = compiler.world.allFunctions.filter(selectorToUse);
+    targets = compiler.world.allFunctions.filter(selector, maskToUse);
     Iterable<Element> typedTargets = canReachAll
-        ? compiler.world.allFunctions.filter(typedSelector)
+        ? compiler.world.allFunctions.filter(selector, typeMask)
         : targets;
 
     // Add calls to new targets to the graph.
@@ -879,7 +884,7 @@
       callee.addCall(caller, call);
       callee.addUser(this);
       inferrer.updateParameterAssignments(
-          this, element, arguments, typedSelector, remove: false,
+          this, element, arguments, selector, typeMask, remove: false,
           addToQueue: true);
     });
 
@@ -891,7 +896,7 @@
       callee.removeCall(caller, call);
       callee.removeUser(this);
       inferrer.updateParameterAssignments(
-          this, element, arguments, typedSelector, remove: true,
+          this, element, arguments, selector, typeMask, remove: true,
           addToQueue: true);
     });
 
@@ -907,20 +912,21 @@
         return const TypeMask.nonNullEmpty();
       }
 
-      if (inferrer.returnsListElementType(typedSelector)) {
-        ContainerTypeMask mask = receiver.type;
-        return mask.elementType;
-      } else if (inferrer.returnsMapValueType(typedSelector)) {
-        if (typedSelector.mask.isDictionary &&
+      if (inferrer.returnsListElementType(selector, typeMask)) {
+        ContainerTypeMask containerTypeMask = receiver.type;
+        return containerTypeMask.elementType;
+      } else if (inferrer.returnsMapValueType(selector, typeMask)) {
+        if (typeMask.isDictionary &&
             arguments.positional[0].type.isValue) {
-          DictionaryTypeMask mask = typedSelector.mask;
+          DictionaryTypeMask dictionaryTypeMask = typeMask;
           ValueTypeMask arg = arguments.positional[0].type;
           String key = arg.value;
-          if (mask.typeMap.containsKey(key)) {
+          if (dictionaryTypeMask.typeMap.containsKey(key)) {
             if (_VERBOSE) {
-              print("Dictionary lookup for $key yields ${mask.typeMap[key]}.");
+              print("Dictionary lookup for $key yields "
+                    "${dictionaryTypeMask.typeMap[key]}.");
             }
-            return mask.typeMap[key];
+            return dictionaryTypeMask.typeMap[key];
           } else {
             // The typeMap is precise, so if we do not find the key, the lookup
             // will be [null] at runtime.
@@ -930,16 +936,17 @@
             return inferrer.types.nullType.type;
           }
         }
-        MapTypeMask mask = typedSelector.mask;
+        MapTypeMask mapTypeMask = typeMask;
         if (_VERBOSE) {
-          print("Map lookup for $typedSelector yields ${mask.valueType}.");
+          print(
+              "Map lookup for $selector yields ${mapTypeMask.valueType}.");
         }
-        return mask.valueType;
+        return mapTypeMask.valueType;
       } else {
         TypeInformation info =
-            handleIntrisifiedSelector(typedSelector, inferrer);
+            handleIntrisifiedSelector(selector, typeMask, inferrer);
         if (info != null) return info.type;
-        return inferrer.typeOfElementWithSelector(element, typedSelector).type;
+        return inferrer.typeOfElementWithSelector(element, selector).type;
       }
     }));
 
@@ -955,16 +962,16 @@
 
   void giveUp(TypeGraphInferrerEngine inferrer, {bool clearAssignments: true}) {
     if (!abandonInferencing) {
-      inferrer.updateSelectorInTree(caller, call, selector);
+      inferrer.updateSelectorInTree(caller, call, selector, mask);
       Iterable<Element> oldTargets = targets;
-      targets = inferrer.compiler.world.allFunctions.filter(selector);
+      targets = inferrer.compiler.world.allFunctions.filter(selector, mask);
       for (Element element in targets) {
         if (!oldTargets.contains(element)) {
           MemberTypeInformation callee =
               inferrer.types.getInferredTypeOf(element);
           callee.addCall(caller, call);
           inferrer.updateParameterAssignments(
-              this, element, arguments, selector, remove: false,
+              this, element, arguments, selector, mask, remove: false,
               addToQueue: true);
         }
       }
@@ -1006,10 +1013,11 @@
       Spannable call,
       Element enclosing,
       Selector selector,
+      TypeMask mask,
       this.closure,
       ArgumentsTypes arguments,
       bool inLoop)
-      : super(context, call, enclosing, selector, arguments, inLoop);
+      : super(context, call, enclosing, selector, mask, arguments, inLoop);
 
   void addToGraph(TypeGraphInferrerEngine inferrer) {
     arguments.forEach((info) => info.addUser(this));
diff --git a/pkg/compiler/lib/src/js/js.dart b/pkg/compiler/lib/src/js/js.dart
index bfbe96a..2d208a6 100644
--- a/pkg/compiler/lib/src/js/js.dart
+++ b/pkg/compiler/lib/src/js/js.dart
@@ -7,7 +7,6 @@
 import 'package:js_ast/js_ast.dart';
 export 'package:js_ast/js_ast.dart';
 
-import '../helpers/helpers.dart';
 import '../io/code_output.dart' show CodeBuffer;
 import '../io/source_information.dart' show SourceInformation;
 import '../js_emitter/js_emitter.dart' show USE_NEW_EMITTER;
diff --git a/pkg/compiler/lib/src/js/rewrite_async.dart b/pkg/compiler/lib/src/js/rewrite_async.dart
index 9ea66a2..e29c104 100644
--- a/pkg/compiler/lib/src/js/rewrite_async.dart
+++ b/pkg/compiler/lib/src/js/rewrite_async.dart
@@ -15,8 +15,6 @@
 import '../util/util.dart';
 import '../dart2jslib.dart' show DiagnosticListener;
 
-import "../helpers/helpers.dart";
-
 /// Rewrites a [js.Fun] with async/sync*/async* functions and await and yield
 /// (with dart-like semantics) to an equivalent function without these.
 /// await-for is not handled and must be rewritten before. (Currently handled
@@ -117,11 +115,9 @@
   /// or error case.
   String errorCodeName;
 
-  final String suggestedBodyName;
   /// The inner function that is scheduled to do each await/yield,
   /// and called to do a new iteration for sync*.
-  js.VariableUse get body => new js.VariableUse(bodyName);
-  String bodyName;
+  js.Name bodyName;
 
   /// Used to simulate a goto.
   ///
@@ -181,7 +177,7 @@
   AsyncRewriterBase(this.diagnosticListener,
                     spannable,
                     this.safeVariableName,
-                    this.suggestedBodyName)
+                    this.bodyName)
       : _spannable = spannable;
 
   /// Initialize names used by the subClass.
@@ -201,7 +197,6 @@
     // generated after the analysis.
     resultName = freshName("result");
     errorCodeName = freshName("errorCode");
-    bodyName = freshName(suggestedBodyName);
     gotoName = freshName("goto");
     handlerName = freshName("handler");
     nextName = freshName("next");
@@ -1183,11 +1178,26 @@
   js.Expression visitLiteralString(js.LiteralString node) => node;
 
   @override
+  js.Expression visitStringConcatenation(js.StringConcatenation node) => node;
+
+  @override
+  js.Name visitName(js.Name node) => node;
+
+  @override
   visitNamedFunction(js.NamedFunction node) {
     unsupported(node);
   }
 
   @override
+  js.Expression visitDeferredExpression(js.DeferredExpression node) => node;
+
+  @override
+  js.Expression visitDeferredNumber(js.DeferredNumber node) => node;
+
+  @override
+  js.Expression visitDeferredString(js.DeferredString node) => node;
+
+  @override
   js.Expression visitNew(js.New node) {
     bool storeTarget = node.arguments.any(shouldTransform);
     return withCallTargetExpression(node.target, (target) {
@@ -1677,7 +1687,7 @@
                 {this.asyncHelper,
                  this.newCompleter,
                  String safeVariableName(String proposedName),
-                 String bodyName})
+                 js.Name bodyName})
         : super(diagnosticListener,
                 spannable,
                 safeVariableName,
@@ -1740,12 +1750,12 @@
   js.Statement awaitStatement(js.Expression value) {
     return js.js.statement("""
           return #asyncHelper(#value,
-                              #body,
+                              #bodyName,
                               #completer);
           """, {
             "asyncHelper": asyncHelper,
             "value": value,
-            "body": body,
+            "bodyName": bodyName,
             "completer": completer});
   }
 
@@ -1809,7 +1819,7 @@
                  this.yieldStarExpression,
                  this.uncaughtErrorExpression,
                  String safeVariableName(String proposedName),
-                 String bodyName})
+                 js.Name bodyName})
         : super(diagnosticListener,
                 spannable,
                 safeVariableName,
@@ -1979,7 +1989,7 @@
                  this.yieldExpression,
                  this.yieldStarExpression,
                  String safeVariableName(String proposedName),
-                 String bodyName})
+                 js.Name bodyName})
         : super(diagnosticListener,
                 spannable,
                 safeVariableName,
@@ -2007,12 +2017,12 @@
         [nextWhenCanceled, new js.ArrayInitializer(
             enclosingFinallyLabels.map(js.number).toList())]));
     addStatement(js.js.statement("""
-        return #asyncStarHelper(#yieldExpression(#expression), #body,
+        return #asyncStarHelper(#yieldExpression(#expression), #bodyName,
             #controller);""", {
       "asyncStarHelper": asyncStarHelper,
       "yieldExpression": node.hasStar ? yieldStarExpression : yieldExpression,
       "expression": expression,
-      "body": body,
+      "bodyName": bodyName,
       "controller": controllerName,
     }));
   }
@@ -2110,12 +2120,12 @@
   js.Statement awaitStatement(js.Expression value) {
     return js.js.statement("""
           return #asyncHelper(#value,
-                              #body,
+                              #bodyName,
                               #controller);
           """, {
             "asyncHelper": asyncStarHelper,
             "value": value,
-            "body": body,
+            "bodyName": bodyName,
             "controller": controllerName});
   }
 }
@@ -2385,6 +2395,21 @@
   }
 
   @override
+  bool visitDeferredExpression(js.DeferredExpression node) {
+    return false;
+  }
+
+  @override
+  bool visitDeferredNumber(js.DeferredNumber node) {
+    return false;
+  }
+
+  @override
+  bool visitDeferredString(js.DeferredString node) {
+    return false;
+  }
+
+  @override
   bool visitLiteralBool(js.LiteralBool node) {
     return false;
   }
@@ -2415,6 +2440,16 @@
   }
 
   @override
+  bool visitStringConcatenation(js.StringConcatenation node) {
+    return true;
+  }
+
+  @override
+  bool visitName(js.Name node) {
+    return true;
+  }
+
+  @override
   bool visitNamedFunction(js.NamedFunction node) {
     return false;
   }
diff --git a/pkg/compiler/lib/src/js_backend/backend.dart b/pkg/compiler/lib/src/js_backend/backend.dart
index b99336b..ddeacb4 100644
--- a/pkg/compiler/lib/src/js_backend/backend.dart
+++ b/pkg/compiler/lib/src/js_backend/backend.dart
@@ -212,6 +212,13 @@
   }
 }
 
+enum SyntheticConstantKind {
+  DUMMY_INTERCEPTOR,
+  EMPTY_VALUE,
+  TYPEVARIABLE_REFERENCE,
+  NAME
+}
+
 class JavaScriptBackend extends Backend {
   static final Uri DART_JS_HELPER = new Uri(scheme: 'dart', path: '_js_helper');
   static final Uri DART_INTERCEPTORS =
@@ -429,7 +436,7 @@
    * A collection of selectors that must have a one shot interceptor
    * generated.
    */
-  final Map<String, Selector> oneShotInterceptors;
+  final Map<jsAst.Name, Selector> oneShotInterceptors;
 
   /**
    * The members of instantiated interceptor classes: maps a member name to the
@@ -460,7 +467,7 @@
    * the generic version that contains all possible type checks is
    * also stored in this map.
    */
-  final Map<String, Set<ClassElement>> specializedGetInterceptors;
+  final Map<jsAst.Name, Set<ClassElement>> specializedGetInterceptors;
 
   /**
    * Set of classes whose methods are intercepted.
@@ -608,18 +615,16 @@
 
   PatchResolverTask patchResolverTask;
 
-  bool get canHandleCompilationFailed => true;
-
   bool enabledNoSuchMethod = false;
 
   JavaScriptBackend(Compiler compiler,
                     SourceInformationFactory sourceInformationFactory,
                     {bool generateSourceMap: true})
       : namer = determineNamer(compiler),
-        oneShotInterceptors = new Map<String, Selector>(),
+        oneShotInterceptors = new Map<jsAst.Name, Selector>(),
         interceptedElements = new Map<String, Set<Element>>(),
         rti = new RuntimeTypes(compiler),
-        specializedGetInterceptors = new Map<String, Set<ClassElement>>(),
+        specializedGetInterceptors = new Map<jsAst.Name, Set<ClassElement>>(),
         annotations = new Annotations(compiler),
         super(compiler) {
     emitter = new CodeEmitterTask(compiler, namer, generateSourceMap);
@@ -644,6 +649,7 @@
   }
 
   FunctionElement resolveExternalFunction(FunctionElement element) {
+    if (isForeign(element)) return element;
     return patchResolverTask.measure(() {
       return patchResolverTask.resolveExternalFunction(element);
     });
@@ -711,9 +717,9 @@
     return false;
   }
 
-  String registerOneShotInterceptor(Selector selector) {
+  jsAst.Name registerOneShotInterceptor(Selector selector) {
     Set<ClassElement> classes = getInterceptedClassesOn(selector.name);
-    String name = namer.nameForGetOneShotInterceptor(selector, classes);
+    jsAst.Name name = namer.nameForGetOneShotInterceptor(selector, classes);
     if (!oneShotInterceptors.containsKey(name)) {
       registerSpecializedGetInterceptor(classes);
       oneShotInterceptors[name] = selector;
@@ -779,7 +785,7 @@
    * into an intercepted class.  These selectors are not eligible for the 'dummy
    * explicit receiver' optimization.
    */
-  bool isInterceptedMixinSelector(Selector selector) {
+  bool isInterceptedMixinSelector(Selector selector, TypeMask mask) {
     Set<Element> elements = interceptedMixinElements.putIfAbsent(
         selector.name,
         () {
@@ -794,7 +800,10 @@
 
     if (elements == null) return false;
     if (elements.isEmpty) return false;
-    return elements.any((element) => selector.applies(element, compiler.world));
+    return elements.any((element) {
+      return selector.applies(element, compiler.world) &&
+             (mask == null || mask.canHit(element, selector, compiler.world));
+    });
   }
 
   final Map<String, Set<ClassElement>> interceptedClassesCache =
@@ -916,7 +925,7 @@
   }
 
   void registerSpecializedGetInterceptor(Set<ClassElement> classes) {
-    String name = namer.nameForGetInterceptor(classes);
+    jsAst.Name name = namer.nameForGetInterceptor(classes);
     if (classes.contains(jsInterceptorClass)) {
       // We can't use a specialized [getInterceptorMethod], so we make
       // sure we emit the one with all checks.
@@ -1060,7 +1069,6 @@
     if (cls == closureClass) {
       enqueue(enqueuer, findHelper('closureFromTearOff'), registry);
     }
-    ClassElement result = null;
     if (cls == compiler.stringClass || cls == jsStringClass) {
       addInterceptors(jsStringClass, enqueuer, registry);
     } else if (cls == compiler.listClass ||
@@ -1181,6 +1189,14 @@
     }
   }
 
+  /// Call during codegen if an instance of [closure] is being created.
+  void registerInstantiatedClosure(LocalFunctionElement closure,
+                                   CodegenRegistry registry) {
+    if (methodNeedsRti(closure)) {
+      registerComputeSignature(compiler.enqueuer.codegen, registry);
+    }
+  }
+
   void registerBoundClosure(Enqueuer enqueuer) {
     boundClosureClass.ensureResolved(compiler);
     enqueuer.registerInstantiatedType(
@@ -1266,7 +1282,8 @@
 
   void enableNoSuchMethod(Enqueuer world) {
     enqueue(world, getCreateInvocationMirror(), compiler.globalDependencies);
-    world.registerInvocation(compiler.noSuchMethodSelector);
+    world.registerInvocation(
+        new UniverseSelector(compiler.noSuchMethodSelector, null));
   }
 
   void enableIsolateSupport(Enqueuer enqueuer) {
@@ -1420,6 +1437,7 @@
         compiler.enqueuer.codegen.registerStaticUse(getCyclicThrowHelper());
       }
     }
+
     generatedCode[element] = functionCompiler.compile(work);
     return const WorldImpact();
   }
@@ -1766,18 +1784,26 @@
     return findHelper('assertSubtype');
   }
 
+  Element getSubtypeCast() {
+    return findHelper('subtypeCast');
+  }
+
   Element getCheckSubtypeOfRuntimeType() {
     return findHelper('checkSubtypeOfRuntimeType');
   }
 
-  Element getCheckDeferredIsLoaded() {
-    return findHelper('checkDeferredIsLoaded');
-  }
-
   Element getAssertSubtypeOfRuntimeType() {
     return findHelper('assertSubtypeOfRuntimeType');
   }
 
+  Element getSubtypeOfRuntimeTypeCast() {
+    return findHelper('subtypeOfRuntimeTypeCast');
+  }
+
+  Element getCheckDeferredIsLoaded() {
+    return findHelper('checkDeferredIsLoaded');
+  }
+
   Element getThrowNoSuchMethod() {
     return findHelper('throwNoSuchMethod');
   }
@@ -2009,10 +2035,6 @@
     }).then((_) {
       Uri uri = library.canonicalUri;
 
-      VariableElement findVariable(String name) {
-        return find(library, name);
-      }
-
       FunctionElement findMethod(String name) {
         return find(library, name);
       }
@@ -2024,29 +2046,25 @@
       if (uri == DART_INTERCEPTORS) {
         getInterceptorMethod = findMethod('getInterceptor');
         getNativeInterceptorMethod = findMethod('getNativeInterceptor');
-
-        List<ClassElement> classes = [
-          jsInterceptorClass = findClass('Interceptor'),
-          jsStringClass = findClass('JSString'),
-          jsArrayClass = findClass('JSArray'),
-          // The int class must be before the double class, because the
-          // emitter relies on this list for the order of type checks.
-          jsIntClass = findClass('JSInt'),
-          jsPositiveIntClass = findClass('JSPositiveInt'),
-          jsUInt32Class = findClass('JSUInt32'),
-          jsUInt31Class = findClass('JSUInt31'),
-          jsDoubleClass = findClass('JSDouble'),
-          jsNumberClass = findClass('JSNumber'),
-          jsNullClass = findClass('JSNull'),
-          jsBoolClass = findClass('JSBool'),
-          jsMutableArrayClass = findClass('JSMutableArray'),
-          jsFixedArrayClass = findClass('JSFixedArray'),
-          jsExtendableArrayClass = findClass('JSExtendableArray'),
-          jsUnmodifiableArrayClass = findClass('JSUnmodifiableArray'),
-          jsPlainJavaScriptObjectClass = findClass('PlainJavaScriptObject'),
-          jsUnknownJavaScriptObjectClass = findClass('UnknownJavaScriptObject'),
-        ];
-
+        jsInterceptorClass = findClass('Interceptor');
+        jsStringClass = findClass('JSString');
+        jsArrayClass = findClass('JSArray');
+        // The int class must be before the double class, because the
+        // emitter relies on this list for the order of type checks.
+        jsIntClass = findClass('JSInt');
+        jsPositiveIntClass = findClass('JSPositiveInt');
+        jsUInt32Class = findClass('JSUInt32');
+        jsUInt31Class = findClass('JSUInt31');
+        jsDoubleClass = findClass('JSDouble');
+        jsNumberClass = findClass('JSNumber');
+        jsNullClass = findClass('JSNull');
+        jsBoolClass = findClass('JSBool');
+        jsMutableArrayClass = findClass('JSMutableArray');
+        jsFixedArrayClass = findClass('JSFixedArray');
+        jsExtendableArrayClass = findClass('JSExtendableArray');
+        jsUnmodifiableArrayClass = findClass('JSUnmodifiableArray');
+        jsPlainJavaScriptObjectClass = findClass('PlainJavaScriptObject');
+        jsUnknownJavaScriptObjectClass = findClass('UnknownJavaScriptObject');
         jsIndexableClass = findClass('JSIndexable');
         jsMutableIndexableClass = findClass('JSMutableIndexable');
       } else if (uri == DART_JS_HELPER) {
@@ -2669,6 +2687,25 @@
       enqueue(enqueuer, getStreamIteratorConstructor(), registry);
     }
   }
+
+  @override
+  bool enableDeferredLoadingIfSupported(Spannable node, Registry registry) {
+    registerCheckDeferredIsLoaded(registry);
+    return true;
+  }
+
+  @override
+  bool enableCodegenWithErrorsIfSupported(Spannable node) {
+    if (compiler.useCpsIr) {
+      compiler.reportHint(
+          node,
+          MessageKind.GENERIC,
+          {'text': "Generation of code with compile time errors is currently "
+                   "not supported with the CPS IR."});
+      return false;
+    }
+    return true;
+  }
 }
 
 /// Handling of special annotations for tests.
diff --git a/pkg/compiler/lib/src/js_backend/checked_mode_helpers.dart b/pkg/compiler/lib/src/js_backend/checked_mode_helpers.dart
index a781ceb..003ab69 100644
--- a/pkg/compiler/lib/src/js_backend/checked_mode_helpers.dart
+++ b/pkg/compiler/lib/src/js_backend/checked_mode_helpers.dart
@@ -88,8 +88,8 @@
                                    HTypeConversion node,
                                    List<jsAst.Expression> arguments) {
     DartType type = node.typeExpression;
-    String additionalArgument = codegen.backend.namer.operatorIsType(type);
-    arguments.add(js.string(additionalArgument));
+    jsAst.Name additionalArgument = codegen.backend.namer.operatorIsType(type);
+    arguments.add(js.quoteName(additionalArgument));
   }
 }
 
@@ -113,11 +113,11 @@
                                    List<jsAst.Expression> arguments) {
     DartType type = node.typeExpression;
     Element element = type.element;
-    String isField = codegen.backend.namer.operatorIs(element);
-    arguments.add(js.string(isField));
+    jsAst.Name isField = codegen.backend.namer.operatorIs(element);
+    arguments.add(js.quoteName(isField));
     codegen.use(node.typeRepresentation);
     arguments.add(codegen.pop());
-    String asField = codegen.backend.namer.substitutionName(element);
-    arguments.add(js.string(asField));
+    jsAst.Name asField = codegen.backend.namer.substitutionName(element);
+    arguments.add(js.quoteName(asField));
   }
 }
diff --git a/pkg/compiler/lib/src/js_backend/codegen/codegen.dart b/pkg/compiler/lib/src/js_backend/codegen/codegen.dart
index b852418..bd40919 100644
--- a/pkg/compiler/lib/src/js_backend/codegen/codegen.dart
+++ b/pkg/compiler/lib/src/js_backend/codegen/codegen.dart
@@ -7,6 +7,7 @@
 import 'glue.dart';
 
 import '../../tree_ir/tree_ir_nodes.dart' as tree_ir;
+import '../../tree_ir/tree_ir_nodes.dart' show BuiltinOperator;
 import '../../js/js.dart' as js;
 import '../../elements/elements.dart';
 import '../../io/source_information.dart' show SourceInformation;
@@ -14,6 +15,9 @@
 import '../../constants/values.dart';
 import '../../dart2jslib.dart';
 import '../../dart_types.dart';
+import '../../types/types.dart' show TypeMask;
+import '../../universe/universe.dart' show UniverseSelector;
+import '../../closure.dart' show ClosureClassElement;
 
 class CodegenBailout {
   final tree_ir.Node node;
@@ -169,31 +173,6 @@
   }
 
   @override
-  js.Expression visitConcatenateStrings(tree_ir.ConcatenateStrings node) {
-    js.Expression addStrings(js.Expression left, js.Expression right) {
-      return new js.Binary('+', left, right);
-    }
-
-    js.Expression toString(tree_ir.Expression input) {
-      bool useDirectly = input is tree_ir.Constant &&
-          (input.value.isString ||
-           input.value.isInt ||
-           input.value.isBool);
-      js.Expression value = visitExpression(input);
-      if (useDirectly) {
-        return value;
-      } else {
-        Element convertToString = glue.getStringConversion();
-        registry.registerStaticUse(convertToString);
-        js.Expression access = glue.staticFunctionAccess(convertToString);
-        return (new js.Call(access, <js.Expression>[value]));
-      }
-    }
-
-    return node.arguments.map(toString).reduce(addStrings);
-  }
-
-  @override
   js.Expression visitConditional(tree_ir.Conditional node) {
     return new js.Conditional(
         visitExpression(node.condition),
@@ -230,7 +209,8 @@
       //   [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);
+      return js.propertyCall(interceptorLibrary, js.string(selector.name),
+                             arguments);
     } else {
       js.Expression elementAccess = glue.staticFunctionAccess(target);
       return new js.Call(elementAccess, arguments,
@@ -251,10 +231,11 @@
 
   void registerMethodInvoke(tree_ir.InvokeMethod node) {
     Selector selector = node.selector;
+    TypeMask mask = node.mask;
     if (selector.isGetter) {
-      registry.registerDynamicGetter(selector);
+      registry.registerDynamicGetter(new UniverseSelector(selector, mask));
     } else if (selector.isSetter) {
-      registry.registerDynamicSetter(selector);
+      registry.registerDynamicSetter(new UniverseSelector(selector, mask));
     } else {
       assert(invariant(CURRENT_ELEMENT_SPANNABLE,
           selector.isCall || selector.isOperator ||
@@ -262,8 +243,8 @@
           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);
+      registry.registerDynamicInvocation(new UniverseSelector(call, null));
+      registry.registerDynamicInvocation(new UniverseSelector(selector, mask));
     }
   }
 
@@ -355,43 +336,47 @@
   js.Expression visitTypeOperator(tree_ir.TypeOperator node) {
     js.Expression value = visitExpression(node.value);
     List<js.Expression> typeArguments = visitExpressionList(node.typeArguments);
-    if (!node.isTypeTest) {
-      giveup(node, 'type casts not implemented.');
-    }
     DartType type = node.type;
-    // Note that the trivial (but special) cases of Object, dynamic, and Null
-    // are handled at build-time and must not occur in a TypeOperator.
-    assert(!type.isObject && !type.isDynamic);
     if (type is InterfaceType) {
       glue.registerIsCheck(type, registry);
       ClassElement clazz = type.element;
 
-      // We use the helper:
+      // We use one of the two helpers:
       //
       //     checkSubtype(value, $isT, typeArgs, $asT)
+      //     subtypeCast(value, $isT, typeArgs, $asT)
       //
       // Any of the last two arguments may be null if there are no type
       // arguments, and/or if no substitution is required.
+      Element function = node.isTypeTest
+          ? glue.getCheckSubtype()
+          : glue.getSubtypeCast();
 
-      js.Expression isT = js.string(glue.getTypeTestTag(type));
+      js.Expression isT = js.quoteName(glue.getTypeTestTag(type));
 
       js.Expression typeArgumentArray = typeArguments.isNotEmpty
           ? new js.ArrayInitializer(typeArguments)
           : new js.LiteralNull();
 
       js.Expression asT = glue.hasStrictSubtype(clazz)
-          ? js.string(glue.getTypeSubstitutionTag(clazz))
+          ? js.quoteName(glue.getTypeSubstitutionTag(clazz))
           : new js.LiteralNull();
 
       return buildStaticHelperInvocation(
-          glue.getCheckSubtype(),
+          function,
           <js.Expression>[value, isT, typeArgumentArray, asT]);
-    } else if (type is TypeVariableType) {
+    } else if (type is TypeVariableType || type is FunctionType) {
       glue.registerIsCheck(type, registry);
+
+      Element function = node.isTypeTest
+          ? glue.getCheckSubtypeOfRuntimeType()
+          : glue.getSubtypeOfRuntimeTypeCast();
+
       // The only type argument is the type held in the type variable.
       js.Expression typeValue = typeArguments.single;
+
       return buildStaticHelperInvocation(
-          glue.getCheckSubtypeOfRuntime(),
+          function,
           <js.Expression>[value, typeValue]);
     }
     return giveup(node, 'type check unimplemented for $type.');
@@ -547,6 +532,12 @@
   }
 
   @override
+  void visitUnreachable(tree_ir.Unreachable node) {
+    // Output nothing.
+    // TODO(asgerf): Emit a throw/return to assist local analysis in the VM?
+  }
+
+  @override
   void visitTry(tree_ir.Try node) {
     js.Block tryBlock = buildBodyBlock(node.tryBody);
     tree_ir.Variable exceptionVariable = node.catchParameters.first;
@@ -564,19 +555,22 @@
 
   @override
   js.Expression visitCreateInstance(tree_ir.CreateInstance node) {
-    ClassElement cls = node.classElement;
+    ClassElement classElement = node.classElement;
     // TODO(asgerf): To allow inlining of InvokeConstructor, CreateInstance must
     //               carry a DartType so we can register the instantiated type
     //               with its type arguments. Otherwise dataflow analysis is
     //               needed to reconstruct the instantiated type.
-    registry.registerInstantiatedClass(cls);
+    registry.registerInstantiatedClass(classElement);
+    if (classElement is ClosureClassElement) {
+      registry.registerInstantiatedClosure(classElement.methodElement);
+    }
     js.Expression instance = new js.New(
-        glue.constructorAccess(cls),
+        glue.constructorAccess(classElement),
         visitExpressionList(node.arguments));
 
     List<tree_ir.Expression> typeInformation = node.typeInformation;
     assert(typeInformation.isEmpty ||
-        typeInformation.length == cls.typeVariables.length);
+        typeInformation.length == classElement.typeVariables.length);
     if (typeInformation.isNotEmpty) {
       FunctionElement helper = glue.getAddRuntimeTypeInformation();
       js.Expression typeArguments = new js.ArrayInitializer(
@@ -592,19 +586,30 @@
   js.Expression visitCreateInvocationMirror(
       tree_ir.CreateInvocationMirror node) {
     js.Expression name = js.string(node.selector.name);
-    js.Expression internalName = js.string(glue.invocationName(node.selector));
+    js.Expression internalName =
+        js.quoteName(glue.invocationName(node.selector));
     js.Expression kind = js.number(node.selector.invocationMirrorKind);
     js.Expression arguments = new js.ArrayInitializer(
         visitExpressionList(node.arguments));
     js.Expression argumentNames = new js.ArrayInitializer(
         node.selector.namedArguments.map(js.string).toList(growable: false));
     return buildStaticHelperInvocation(glue.createInvocationMirrorMethod,
-        [name, internalName, kind, arguments, argumentNames]);
+        <js.Expression>[name, internalName, kind, arguments, argumentNames]);
+  }
+
+  @override
+  js.Expression visitInterceptor(tree_ir.Interceptor node) {
+    glue.registerUseInterceptorInCodegen();
+    registry.registerSpecializedGetInterceptor(node.interceptedClasses);
+    js.Name helperName = glue.getInterceptorName(node.interceptedClasses);
+    js.Expression globalHolder = glue.getInterceptorLibrary();
+    return js.js('#.#(#)',
+        [globalHolder, helperName, visitExpression(node.input)]);
   }
 
   @override
   js.Expression visitGetField(tree_ir.GetField node) {
-    return new js.PropertyAccess.field(
+    return new js.PropertyAccess(
         visitExpression(node.object),
         glue.instanceFieldPropertyName(node.field));
   }
@@ -612,7 +617,7 @@
   @override
   js.Assignment visitSetField(tree_ir.SetField node) {
     js.PropertyAccess field =
-        new js.PropertyAccess.field(
+        new js.PropertyAccess(
             visitExpression(node.object),
             glue.instanceFieldPropertyName(node.field));
     return new js.Assignment(field, visitExpression(node.value));
@@ -685,6 +690,72 @@
     return glue.generateTypeRepresentation(node.dartType, arguments);
   }
 
+  js.Node handleForeignCode(tree_ir.ForeignCode node) {
+    registry.registerStaticUse(node.dependency);
+    return node.codeTemplate.instantiate(visitExpressionList(node.arguments));
+  }
+
+  @override
+  js.Expression visitForeignExpression(tree_ir.ForeignExpression node) {
+    return handleForeignCode(node);
+  }
+
+  @override
+  visitForeignStatement(tree_ir.ForeignStatement node) {
+    return handleForeignCode(node);
+  }
+
+  @override
+  js.Expression visitApplyBuiltinOperator(tree_ir.ApplyBuiltinOperator node) {
+    List<js.Expression> args = visitExpressionList(node.arguments);
+    switch (node.operator) {
+      case BuiltinOperator.NumAdd:
+        return new js.Binary('+', args[0], args[1]);
+      case BuiltinOperator.NumSubtract:
+        return new js.Binary('-', args[0], args[1]);
+      case BuiltinOperator.NumMultiply:
+        return new js.Binary('*', args[0], args[1]);
+      case BuiltinOperator.NumAnd:
+        return js.js('(# & #) >>> 0', args);
+      case BuiltinOperator.NumOr:
+        return js.js('(# | #) >>> 0', args);
+      case BuiltinOperator.NumXor:
+        return js.js('(# ^ #) >>> 0', args);
+      case BuiltinOperator.NumLt:
+        return new js.Binary('<', args[0], args[1]);
+      case BuiltinOperator.NumLe:
+        return new js.Binary('<=', args[0], args[1]);
+      case BuiltinOperator.NumGt:
+        return new js.Binary('>', args[0], args[1]);
+      case BuiltinOperator.NumGe:
+        return new js.Binary('>=', args[0], args[1]);
+      case BuiltinOperator.StringConcatenate:
+        if (args.isEmpty) return js.string('');
+        return args.reduce((e1,e2) => new js.Binary('+', e1, e2));
+      case BuiltinOperator.Identical:
+        registry.registerStaticInvocation(glue.identicalFunction);
+        return buildStaticHelperInvocation(glue.identicalFunction, args);
+      case BuiltinOperator.StrictEq:
+        return new js.Binary('===', args[0], args[1]);
+      case BuiltinOperator.StrictNeq:
+        return new js.Binary('!==', args[0], args[1]);
+      case BuiltinOperator.LooseEq:
+        return new js.Binary('==', args[0], args[1]);
+      case BuiltinOperator.LooseNeq:
+        return new js.Binary('!=', args[0], args[1]);
+      case BuiltinOperator.IsFalsy:
+        return new js.Prefix('!', args[0]);
+      case BuiltinOperator.IsNumber:
+        return js.js("typeof # === 'number'", args);
+      case BuiltinOperator.IsNotNumber:
+        return js.js("typeof # !== 'number'", args);
+      case BuiltinOperator.IsFloor:
+        return js.js("Math.floor(#) === #", args);
+      case BuiltinOperator.IsNumberAndFloor:
+        return js.js("typeof # === 'number' && Math.floor(#) === #", args);
+    }
+  }
+
   visitFunctionExpression(tree_ir.FunctionExpression node) {
     // FunctionExpressions are currently unused.
     // We might need them if we want to emit raw JS nested functions.
diff --git a/pkg/compiler/lib/src/js_backend/codegen/glue.dart b/pkg/compiler/lib/src/js_backend/codegen/glue.dart
index 4cdc447..bb7ce13 100644
--- a/pkg/compiler/lib/src/js_backend/codegen/glue.dart
+++ b/pkg/compiler/lib/src/js_backend/codegen/glue.dart
@@ -10,7 +10,6 @@
 import '../../js/js.dart' as js;
 import '../../constants/values.dart';
 import '../../elements/elements.dart';
-import '../../constants/expressions.dart';
 import '../../dart_types.dart' show DartType, TypeVariableType, InterfaceType;
 
 /// Encapsulates the dependencies of the function-compiler to the compiler,
@@ -36,10 +35,6 @@
     return _emitter.constantReference(value);
   }
 
-  Element getStringConversion() {
-    return _backend.getStringInterpolationHelper();
-  }
-
   reportInternalError(String message) {
     _compiler.internalError(_compiler.currentElement, message);
   }
@@ -84,7 +79,7 @@
 
   FunctionElement get identicalFunction => _compiler.identicalFunction;
 
-  String invocationName(Selector selector) {
+  js.Name invocationName(Selector selector) {
     return _namer.invocationName(selector);
   }
 
@@ -116,11 +111,11 @@
     return _backend.emitter.constructorAccess(element);
   }
 
-  String instanceFieldPropertyName(Element field) {
+  js.Name instanceFieldPropertyName(Element field) {
     return _namer.instanceFieldPropertyName(field);
   }
 
-  String instanceMethodName(FunctionElement element) {
+  js.Name instanceMethodName(FunctionElement element) {
     return _namer.instanceMethodName(element);
   }
 
@@ -130,7 +125,7 @@
         hasBeenInstantiated: hasBeenInstantiated);
   }
 
-  String getInterceptorName(Set<ClassElement> interceptedClasses) {
+  js.Name getInterceptorName(Set<ClassElement> interceptedClasses) {
     return _backend.namer.nameForGetInterceptor(interceptedClasses);
   }
 
@@ -176,13 +171,23 @@
     return _backend.getCheckSubtype();
   }
 
+  /// subtypeCast(value, $isT, typeArgs, $asT)
+  FunctionElement getSubtypeCast() {
+    return _backend.getSubtypeCast();
+  }
+
   /// checkSubtypeOfRuntime(value, runtimeType)
-  FunctionElement getCheckSubtypeOfRuntime() {
+  FunctionElement getCheckSubtypeOfRuntimeType() {
     return _backend.getCheckSubtypeOfRuntimeType();
   }
 
+  /// subtypeOfRuntimeTypeCast(value, runtimeType)
+  FunctionElement getSubtypeOfRuntimeTypeCast() {
+    return _backend.getSubtypeOfRuntimeTypeCast();
+  }
+
   js.Expression getRuntimeTypeName(ClassElement cls) {
-    return js.string(_namer.runtimeTypeName(cls));
+    return js.quoteName(_namer.runtimeTypeName(cls));
   }
 
   int getTypeVariableIndex(TypeVariableType variable) {
@@ -214,11 +219,11 @@
     _backend.registerIsCheckForCodegen(type, _enqueuer, registry);
   }
 
-  String getTypeTestTag(DartType type) {
+  js.Name getTypeTestTag(DartType type) {
     return _backend.namer.operatorIsType(type);
   }
 
-  String getTypeSubstitutionTag(ClassElement element) {
+  js.Name getTypeSubstitutionTag(ClassElement element) {
     return _backend.namer.substitutionName(element);
   }
 
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
deleted file mode 100644
index 98893f8..0000000
--- a/pkg/compiler/lib/src/js_backend/codegen/js_tree_builder.dart
+++ /dev/null
@@ -1,81 +0,0 @@
-// 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 js_tree_ir_builder;
-
-import '../../tree_ir/tree_ir_builder.dart' show Builder;
-import 'glue.dart' show Glue;
-import '../../dart2jslib.dart' show Selector, InternalErrorFunction;
-import '../../elements/elements.dart';
-import '../../cps_ir/cps_ir_nodes.dart' as cps_ir;
-import '../../tree_ir/tree_ir_nodes.dart';
-
-/// Subclass of [Builder] that can translate nodes which are specific to the
-/// JavaScript backend.
-class JsTreeBuilder extends Builder {
-  final Glue _glue;
-  final Element identicalFunction;
-
-  JsTreeBuilder(
-      InternalErrorFunction internalError,
-      this.identicalFunction,
-      this._glue,
-      [Builder parent])
-    : super(internalError, parent);
-
-  JsTreeBuilder createInnerBuilder() {
-    return new JsTreeBuilder(internalError, identicalFunction, _glue, this);
-  }
-
-  Selector get identicalSelector {
-    return new Selector.call('identical', null, 2);
-  }
-
-  Expression visitIdentical(cps_ir.Identical node) {
-    return new InvokeStatic(
-        identicalFunction,
-        identicalSelector,
-        <Expression>[getVariableUse(node.left),
-                     getVariableUse(node.right)])..isEffectivelyConstant = true;
-  }
-
-  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,
-        selector,
-        <Expression>[getVariableUse(node.input)])..isEffectivelyConstant = true;
-  }
-
-  Expression visitGetField(cps_ir.GetField node) {
-    return new GetField(getVariableUse(node.object), node.field);
-  }
-
-  Statement visitSetField(cps_ir.SetField node) {
-    SetField setField =
-        new SetField(getVariableUse(node.object),
-                     node.field,
-                     getVariableUse(node.value));
-    return new ExpressionStatement(setField, visit(node.body));
-  }
-
-  Expression visitCreateBox(cps_ir.CreateBox node) {
-    return new CreateBox();
-  }
-
-  Expression visitCreateInstance(cps_ir.CreateInstance node) {
-    return new CreateInstance(
-        node.classElement,
-        node.arguments.map(getVariableUse).toList(growable: false),
-        node.typeInformation.map(getVariableUse).toList(growable: false));
-  }
-
-  Expression visitCreateInvocationMirror(cps_ir.CreateInvocationMirror node) {
-    return new CreateInvocationMirror(node.selector,
-        node.arguments.map(getVariableUse).toList(growable: false));
-  }
-}
diff --git a/pkg/compiler/lib/src/js_backend/codegen/task.dart b/pkg/compiler/lib/src/js_backend/codegen/task.dart
index 0540d4c..25492d6 100644
--- a/pkg/compiler/lib/src/js_backend/codegen/task.dart
+++ b/pkg/compiler/lib/src/js_backend/codegen/task.dart
@@ -31,7 +31,6 @@
 import '../../tree_ir/optimization/optimization.dart' as tree_opt;
 import '../../tree_ir/tree_ir_integrity.dart';
 import '../../cps_ir/cps_ir_nodes_sexpr.dart';
-import 'js_tree_builder.dart';
 
 class CpsFunctionCompiler implements FunctionCompiler {
   final ConstantSystem constantSystem;
@@ -39,8 +38,6 @@
   final Glue glue;
   final SourceInformationFactory sourceInformationFactory;
 
-  TypeSystem types;
-
   // TODO(karlklose,sigurm): remove and update dart-doc of [compile].
   final FunctionCompiler fallbackCompiler;
 
@@ -59,21 +56,39 @@
 
   String get name => 'CPS Ir pipeline';
 
-  /// Generates JavaScript code for `work.element`. First tries to use the
-  /// Cps Ir -> tree ir -> js pipeline, and if that fails due to language
-  /// features not implemented it will fall back to the ssa pipeline (for
-  /// platform code) or will cancel compilation (for user code).
+  /// Generates JavaScript code for `work.element`.
   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 ||
-          element.library == backend.interceptorsLibrary) {
-        compiler.log('Using SSA compiler for platform element $element');
-        return fallbackCompiler.compile(work);
-      }
       try {
+        ClassElement cls = element.enclosingClass;
+        String name = element.name;
+        String className = cls == null ? null : cls.name;
+        LibraryElement library = element.library;
+        String libraryName = library == null ? null : library.toString();
+        // TODO(karlklose): remove this fallback.
+        // Fallback for a few functions that we know require try-finally and
+        // switch.
+        if (element.isNative ||
+            element.isPatched ||
+            libraryName == 'origin library(dart:typed_data)' ||
+            // Using switch or try-finally.
+            library.isInternalLibrary && name == 'unwrapException' ||
+            library.isPlatformLibrary && className == 'IterableBase' ||
+            library.isInternalLibrary && className == 'Closure' ||
+            libraryName == 'origin library(dart:collection)' &&
+               name == 'mapToString' ||
+            libraryName == 'library(dart:html)' && name == 'sanitizeNode' ||
+            className == '_IsolateContext' ||
+            className == 'IsolateNatives' ||
+            className == '_Deserializer' ||
+            name == '_rootRun' ||
+            name == '_microtaskLoopEntry') {
+          compiler.log('Using SSA compiler for platform element $element');
+          return fallbackCompiler.compile(work);
+        }
+
         if (tracer != null) {
           tracer.traceCompilation(element.name, null);
         }
@@ -138,7 +153,7 @@
   }
 
   void dumpTypedIR(cps.FunctionDefinition cpsNode,
-                   TypePropagator<TypeMask> typePropagator) {
+                   TypePropagator typePropagator) {
     if (PRINT_TYPED_IR_FILTER != null &&
         PRINT_TYPED_IR_FILTER.matchAsPrefix(cpsNode.element.name) != null) {
       String printType(nodeOrRef, String s) {
@@ -166,11 +181,7 @@
       assert(checkCpsIntegrity(cpsNode));
     }
 
-    TypePropagator typePropagator = new TypePropagator<TypeMask>(
-        compiler.types,
-        constantSystem,
-        new TypeMaskSystem(compiler),
-        compiler.internalError);
+    TypePropagator typePropagator = new TypePropagator(compiler);
     applyCpsPass(typePropagator);
     dumpTypedIR(cpsNode, typePropagator);
     applyCpsPass(new RedundantPhiEliminator());
@@ -180,8 +191,8 @@
   }
 
   tree_ir.FunctionDefinition compileToTreeIR(cps.FunctionDefinition cpsNode) {
-    tree_builder.Builder builder = new JsTreeBuilder(
-        compiler.internalError, compiler.identicalFunction, glue);
+    tree_builder.Builder builder = new tree_builder.Builder(
+        compiler.internalError);
     tree_ir.FunctionDefinition treeNode = builder.buildFunction(cpsNode);
     assert(treeNode != null);
     traceGraph('Tree builder', treeNode);
@@ -201,7 +212,7 @@
       assert(checkTreeIntegrity(node));
     }
 
-    applyTreePass(new StatementRewriter(isDartMode: false));
+    applyTreePass(new StatementRewriter());
     applyTreePass(new VariableMerger());
     applyTreePass(new LoopRewriter());
     applyTreePass(new LogicalRewriter());
diff --git a/pkg/compiler/lib/src/js_backend/codegen/unsugar.dart b/pkg/compiler/lib/src/js_backend/codegen/unsugar.dart
index 045e766..bbe998f 100644
--- a/pkg/compiler/lib/src/js_backend/codegen/unsugar.dart
+++ b/pkg/compiler/lib/src/js_backend/codegen/unsugar.dart
@@ -82,21 +82,15 @@
   }
 
   Constant get trueConstant {
-    return new Constant(
-        new BoolConstantExpression(true),
-        new TrueConstantValue());
+    return new Constant(new TrueConstantValue());
   }
 
   Constant get falseConstant {
-    return new Constant(
-        new BoolConstantExpression(false),
-        new FalseConstantValue());
+    return new Constant(new FalseConstantValue());
   }
 
   Constant get nullConstant {
-    return new Constant(
-        new NullConstantExpression(),
-        new NullConstantValue());
+    return new Constant(new NullConstantValue());
   }
 
   void insertLetPrim(Primitive primitive, Expression node) {
@@ -131,7 +125,9 @@
                 function.returnContinuation, <Primitive>[falsePrimitive]));
 
     Primitive nullPrimitive = nullConstant;
-    Primitive test = new Identical(function.parameters.single, nullPrimitive);
+    Primitive test = new ApplyBuiltinOperator(
+        BuiltinOperator.Identical,
+          <Primitive>[function.parameters.single, nullPrimitive]);
 
     Expression newBody =
         new LetCont.many(<Continuation>[returnFalse, originalBody],
@@ -276,7 +272,9 @@
     InteriorNode parent = node.parent;
     IsTrue condition = node.condition;
     Primitive t = trueConstant;
-    Primitive i = new Identical(condition.value.definition, t);
+    Primitive i = new ApplyBuiltinOperator(
+        BuiltinOperator.Identical,
+        <Primitive>[condition.value.definition, t]);
     LetPrim newNode = new LetPrim(t,
         new LetPrim(i,
             new Branch(new IsTrue(i),
diff --git a/pkg/compiler/lib/src/js_backend/constant_emitter.dart b/pkg/compiler/lib/src/js_backend/constant_emitter.dart
index b113d24..3f38a28 100644
--- a/pkg/compiler/lib/src/js_backend/constant_emitter.dart
+++ b/pkg/compiler/lib/src/js_backend/constant_emitter.dart
@@ -6,6 +6,8 @@
 
 typedef jsAst.Expression _ConstantReferenceGenerator(ConstantValue constant);
 
+typedef jsAst.Expression _ConstantListGenerator(jsAst.Expression array);
+
 /**
  * Generates the JavaScript expressions for constants.
  *
@@ -24,7 +26,7 @@
   final Compiler compiler;
   final Namer namer;
   final _ConstantReferenceGenerator constantReferenceGenerator;
-  final jsAst.Template makeConstantListTemplate;
+  final _ConstantListGenerator makeConstantList;
 
   /**
    * The given [constantReferenceGenerator] function must, when invoked with a
@@ -35,7 +37,7 @@
       this.compiler,
       this.namer,
       jsAst.Expression this.constantReferenceGenerator(ConstantValue constant),
-      this.makeConstantListTemplate);
+      this.makeConstantList);
 
   /**
    * Constructs a literal expression that evaluates to the constant. Uses a
@@ -160,7 +162,7 @@
         .map(constantReferenceGenerator)
         .toList(growable: false);
     jsAst.ArrayInitializer array = new jsAst.ArrayInitializer(elements);
-    jsAst.Expression value = makeConstantListTemplate.instantiate([array]);
+    jsAst.Expression value = makeConstantList(array);
     return maybeAddTypeArguments(constant.type, value);
   }
 
@@ -250,10 +252,9 @@
   @override
   jsAst.Expression visitType(TypeConstantValue constant, [_]) {
     DartType type = constant.representedType;
-    String name = namer.runtimeTypeName(type.element);
-    jsAst.Expression typeName = new jsAst.LiteralString("'$name'");
+    jsAst.Name typeName = namer.runtimeTypeName(type.element);
     return new jsAst.Call(getHelperProperty(backend.getCreateRuntimeType()),
-                          [typeName]);
+                          [js.quoteName(typeName)]);
   }
 
   @override
@@ -263,8 +264,19 @@
   }
 
   @override
-  jsAst.Expression visitDummy(DummyConstantValue constant, [_]) {
-    return new jsAst.LiteralNumber('0');
+  jsAst.Expression visitSynthetic(SyntheticConstantValue constant, [_]) {
+    switch (constant.kind) {
+      case SyntheticConstantKind.DUMMY_INTERCEPTOR:
+      case SyntheticConstantKind.EMPTY_VALUE:
+        return new jsAst.LiteralNumber('0');
+      case SyntheticConstantKind.TYPEVARIABLE_REFERENCE:
+      case SyntheticConstantKind.NAME:
+        return constant.payload;
+      default:
+        compiler.internalError(NO_LOCATION_SPANNABLE,
+                               "Unexpected DummyConstantKind ${constant.kind}");
+        return null;
+    }
   }
 
   @override
diff --git a/pkg/compiler/lib/src/js_backend/constant_handler_javascript.dart b/pkg/compiler/lib/src/js_backend/constant_handler_javascript.dart
index d6fdc1b..57ae567 100644
--- a/pkg/compiler/lib/src/js_backend/constant_handler_javascript.dart
+++ b/pkg/compiler/lib/src/js_backend/constant_handler_javascript.dart
@@ -200,7 +200,7 @@
                                       TreeElements definitions,
                                       {bool isConst: true}) {
     ConstantExpression constant = nodeConstantMap[node];
-    if (constant != null) {
+    if (constant != null && getConstantValue(constant) != null) {
       return constant;
     }
     constant =
diff --git a/pkg/compiler/lib/src/js_backend/constant_system_javascript.dart b/pkg/compiler/lib/src/js_backend/constant_system_javascript.dart
index 214c480..c79c5b6 100644
--- a/pkg/compiler/lib/src/js_backend/constant_system_javascript.dart
+++ b/pkg/compiler/lib/src/js_backend/constant_system_javascript.dart
@@ -254,7 +254,6 @@
   BoolConstantValue createBool(bool value) => new BoolConstantValue(value);
   NullConstantValue createNull() => new NullConstantValue();
 
-
   @override
   ListConstantValue createList(InterfaceType type,
                                List<ConstantValue> values) {
diff --git a/pkg/compiler/lib/src/js_backend/custom_elements_analysis.dart b/pkg/compiler/lib/src/js_backend/custom_elements_analysis.dart
index 6afef1b..a13db64 100644
--- a/pkg/compiler/lib/src/js_backend/custom_elements_analysis.dart
+++ b/pkg/compiler/lib/src/js_backend/custom_elements_analysis.dart
@@ -192,7 +192,7 @@
       if (member.isGenerativeConstructor) {
         // Ignore constructors that cannot be called with zero arguments.
         FunctionElement constructor = member;
-        constructor.computeSignature(compiler);
+        constructor.computeType(compiler);
         FunctionSignature parameters = constructor.functionSignature;
         if (parameters.requiredParameterCount == 0) {
           result.add(member);
diff --git a/pkg/compiler/lib/src/js_backend/js_backend.dart b/pkg/compiler/lib/src/js_backend/js_backend.dart
index ad59c4a..d44688a 100644
--- a/pkg/compiler/lib/src/js_backend/js_backend.dart
+++ b/pkg/compiler/lib/src/js_backend/js_backend.dart
@@ -5,6 +5,7 @@
 library js_backend;
 
 import 'dart:async' show EventSink, Future;
+import 'dart:collection' show HashMap;
 
 import 'package:_internal/compiler/js_lib/shared/embedded_names.dart'
     as embeddedNames;
@@ -28,6 +29,7 @@
          CodeEmitterTask,
          ClassBuilder,
          MetadataCollector,
+         Placeholder,
          USE_NEW_EMITTER;
 
 import '../library_loader.dart' show LibraryLoader, LoadedLibraries;
diff --git a/pkg/compiler/lib/src/js_backend/minify_namer.dart b/pkg/compiler/lib/src/js_backend/minify_namer.dart
index 45a10eb..2f0b37c 100644
--- a/pkg/compiler/lib/src/js_backend/minify_namer.dart
+++ b/pkg/compiler/lib/src/js_backend/minify_namer.dart
@@ -31,11 +31,11 @@
   ///
   /// [sanitizeForNatives] and [sanitizeForAnnotations] are ignored because the
   /// minified names will always avoid clashing with annotated names or natives.
-  String getFreshName(String proposedName,
-                      Set<String> usedNames,
-                      Map<String, String> suggestedNames,
-                      {bool sanitizeForNatives: false,
-                       bool sanitizeForAnnotations: false}) {
+  jsAst.Name getFreshName(String proposedName,
+                             Set<String> usedNames,
+                             Map<String, String> suggestedNames,
+                             {bool sanitizeForNatives: false,
+                              bool sanitizeForAnnotations: false}) {
     String freshName;
     String suggestion = suggestedNames[proposedName];
     if (suggestion != null && !usedNames.contains(suggestion)) {
@@ -45,7 +45,7 @@
           suggestedNames.values);
     }
     usedNames.add(freshName);
-    return freshName;
+    return new StringBackedName(freshName);
   }
 
   // From issue 7554.  These should not be used on objects (as instance
@@ -143,7 +143,7 @@
         assert(c != $Z);
         c = (c == $z) ? $A : c + 1;
         letter = new String.fromCharCodes([c]);
-      } while (used.contains(letter));
+      } while (_hasBannedPrefix(letter) || used.contains(letter));
       assert(suggestionMap[name] == null);
       suggestionMap[name] = letter;
     }
@@ -209,10 +209,17 @@
     return h;
   }
 
+  /// Remember bad hashes to avoid using a the same character with long numbers
+  /// for frequent hashes. For example, `closure` is a very common name.
+  Map<int, int> _badNames = new Map<int, int>();
+
   /// If we can't find a hash based name in the three-letter space, then base
   /// the name on a letter and a counter.
   String _badName(int hash, Set<String> usedNames) {
-    String startLetter = new String.fromCharCodes([_letterNumber(hash)]);
+    int count = _badNames.putIfAbsent(hash, () => 0);
+    String startLetter =
+        new String.fromCharCodes([_letterNumber(hash + count)]);
+    _badNames[hash] = count + 1;
     String name;
     int i = 0;
     do {
@@ -237,9 +244,9 @@
     return $0 + x - 52;
   }
 
-  String instanceFieldPropertyName(Element element) {
+  jsAst.Name instanceFieldPropertyName(Element element) {
     if (element.hasFixedBackendName) {
-      return element.fixedBackendName;
+      return new StringBackedName(element.fixedBackendName);
     }
 
     _FieldNamingScope names;
@@ -271,15 +278,15 @@
   final Map<Entity, _FieldNamingScope> scopes =
       new Map<Entity, _FieldNamingScope>();
 
-  final Map<Entity, String> globalNames = new Map<Entity, String>();
+  final Map<Entity, jsAst.Name> globalNames = new Map<Entity, jsAst.Name>();
 
   int globalCount = 0;
 
-  final List<String> nameStore = new List<String>();
+  final List<jsAst.Name> nameStore = new List<jsAst.Name>();
 
   _FieldNamingRegistry(this.namer);
 
-  String getName(int count) {
+  jsAst.Name getName(int count) {
     if (count >= nameStore.length) {
       // The namer usually does not use certain names as they clash with
       // existing properties on JS objects (see [_reservedNativeProperties]).
@@ -287,7 +294,8 @@
       // Thus, we shortcut the namer to use those first.
       if (count < MinifyNamer._reservedNativeProperties.length &&
           MinifyNamer._reservedNativeProperties[count].length <= 2) {
-        nameStore.add(MinifyNamer._reservedNativeProperties[count]);
+        nameStore.add(new StringBackedName(
+            MinifyNamer._reservedNativeProperties[count]));
       } else {
         nameStore.add(namer.getFreshName("field$count",
             namer.usedInstanceNames, namer.suggestedInstanceNames));
@@ -303,9 +311,9 @@
  * class hierarchy. The root node typically is the node corresponding to the
  * `Object` class. It is used to assign a unique name to each field of a class.
  * Unique here means unique wrt. all fields along the path back to the root.
- * This is achieved at construction time via the [_fieldNameCounter] field that counts the
- * number of fields on the path to the root node that have been encountered so
- * far.
+ * This is achieved at construction time via the [_fieldNameCounter] field that
+ * counts the number of fields on the path to the root node that have been
+ * encountered so far.
  *
  * Obviously, this only works if no fields are added to a parent node after its
  * children have added their first field.
@@ -313,7 +321,7 @@
 class _FieldNamingScope {
   final _FieldNamingScope superScope;
   final Entity container;
-  final Map<Element, String> names = new Maplet<Element, String>();
+  final Map<Element, jsAst.Name> names = new Maplet<Element, jsAst.Name>();
   final _FieldNamingRegistry registry;
 
   /// Naming counter used for fields of ordinary classes.
@@ -373,15 +381,15 @@
   /**
    * Checks whether [name] is already used in the current scope chain.
    */
-  _isNameUnused(String name) {
+  _isNameUnused(jsAst.Name name) {
     return !names.values.contains(name) &&
         ((superScope == null) || superScope._isNameUnused(name));
   }
 
-  String _nextName() => registry.getName(_localFieldNameCounter++);
+  jsAst.Name _nextName() => registry.getName(_localFieldNameCounter++);
 
-  String operator[](Element field) {
-    String name = names[field];
+  jsAst.Name operator[](Element field) {
+    jsAst.Name name = names[field];
     if (name == null && superScope != null) return superScope[field];
     return name;
   }
@@ -389,7 +397,7 @@
   void add(Element field) {
     if (names.containsKey(field)) return;
 
-    String value = _nextName();
+    jsAst.Name value = _nextName();
     assert(invariant(field, _isNameUnused(value)));
     names[field] = value;
   }
@@ -410,7 +418,7 @@
   int get _localFieldNameCounter => registry.globalCount;
   void set _localFieldNameCounter(int val) { registry.globalCount = val; }
 
-  Map<Entity, String> get names => registry.globalNames;
+  Map<Entity, jsAst.Name> get names => registry.globalNames;
 
   _MixinFieldNamingScope.mixin(ClassElement cls, _FieldNamingRegistry registry)
     : super.rootScope(cls, registry);
@@ -419,9 +427,9 @@
       _FieldNamingScope superScope, _FieldNamingRegistry registry)
     : super.inherit(container, superScope, registry);
 
-  String _nextName() {
-    String proposed = super._nextName();
-    return proposed + r'$';
+  jsAst.Name _nextName() {
+    jsAst.Name proposed = super._nextName();
+    return new CompoundName([proposed, Namer._literalDollar]);
   }
 }
 
@@ -437,7 +445,7 @@
 
   bool containsField(_) => true;
 
-  String operator[](Element field) {
+  jsAst.Name operator[](Element field) {
     if (!names.containsKey(field)) add(field);
     return names[field];
   }
diff --git a/pkg/compiler/lib/src/js_backend/namer.dart b/pkg/compiler/lib/src/js_backend/namer.dart
index 06267f8..1dac9f9 100644
--- a/pkg/compiler/lib/src/js_backend/namer.dart
+++ b/pkg/compiler/lib/src/js_backend/namer.dart
@@ -320,8 +320,10 @@
     return _jsVariableReserved;
   }
 
+  final String asyncPrefix = r"$async$";
   final String currentIsolate = r'$';
   final String getterPrefix = r'get$';
+  final String lazyGetterPrefix = r'$get$';
   final String setterPrefix = r'set$';
   final String superPrefix = r'super$';
   final String metadataField = '@';
@@ -343,6 +345,17 @@
   /// The non-minifying namer's [callPrefix] with a dollar after it.
   static const String _callPrefixDollar = r'call$';
 
+  static final jsAst.Name _literalSuper = new StringBackedName("super");
+  static final jsAst.Name _literalDollar = new StringBackedName(r'$');
+  static final jsAst.Name _literalUnderscore = new StringBackedName('_');
+  static final jsAst.Name literalPlus = new StringBackedName('+');
+  static final jsAst.Name _literalDynamic = new StringBackedName("dynamic");
+
+  jsAst.Name _literalAsyncPrefix;
+  jsAst.Name _literalGetterPrefix;
+  jsAst.Name _literalSetterPrefix;
+  jsAst.Name _literalLazyGetterPrefix;
+
   // Name of property in a class description for the native dispatch metadata.
   final String nativeSpecProperty = '%';
 
@@ -358,20 +371,29 @@
   /// (see [globalObjectFor]), we currently use a single namespace for all these
   /// names.
   final Set<String> usedGlobalNames = new Set<String>();
-  final Map<Element, String> userGlobals = <Element, String>{};
-  final Map<String, String> internalGlobals = <String, String>{};
+  final Map<Element, jsAst.Name> userGlobals =
+      new HashMap<Element, jsAst.Name>();
+  final Map<String, jsAst.Name> internalGlobals =
+      new HashMap<String, jsAst.Name>();
 
   /// Used disambiguated names in the instance namespace, issued by
   /// [_disambiguateMember], [_disambiguateInternalMember],
   /// [_disambiguateOperator], and [reservePublicMemberName].
   final Set<String> usedInstanceNames = new Set<String>();
-  final Map<String, String> userInstanceMembers = <String, String>{};
-  final Map<Element, String> internalInstanceMembers = <Element, String>{};
-  final Map<String, String> userInstanceOperators = <String, String>{};
+  final Map<String, jsAst.Name> userInstanceMembers =
+      new HashMap<String, jsAst.Name>();
+  final Map<Element, jsAst.Name> internalInstanceMembers =
+      new HashMap<Element, jsAst.Name>();
+  final Map<String, jsAst.Name> userInstanceOperators =
+      new HashMap<String, jsAst.Name>();
 
   final Map<String, int> popularNameCounters = <String, int>{};
 
-  final Map<ConstantValue, String> constantNames = <ConstantValue, String>{};
+  final Map<LibraryElement, String> libraryLongNames =
+      new HashMap<LibraryElement, String>();
+
+  final Map<ConstantValue, jsAst.Name> constantNames =
+      new HashMap<ConstantValue, jsAst.Name>();
   final Map<ConstantValue, String> constantLongNames =
       <ConstantValue, String>{};
   ConstantCanonicalHasher constantHasher;
@@ -391,21 +413,28 @@
   final Map<String, String> suggestedGlobalNames = <String, String>{};
   final Map<String, String> suggestedInstanceNames = <String, String>{};
 
-  // All alphanumeric characters.
-  static const String _alphaNumeric =
-      'abcdefghijklmnopqrstuvwxyzABZDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
+  /// Used to store unique keys for library names. Keys are not used as names,
+  /// nor are they visible in the output. The only serve as an internal
+  /// key into maps.
+  final Map<LibraryElement, String> _libraryKeys =
+      new HashMap<LibraryElement, String>();
 
   Namer(Compiler compiler)
       : compiler = compiler,
         constantHasher = new ConstantCanonicalHasher(compiler),
-        functionTypeNamer = new FunctionTypeNamer(compiler);
+        functionTypeNamer = new FunctionTypeNamer(compiler) {
+    _literalAsyncPrefix = new StringBackedName(asyncPrefix);
+    _literalGetterPrefix = new StringBackedName(getterPrefix);
+    _literalSetterPrefix = new StringBackedName(setterPrefix);
+    _literalLazyGetterPrefix = new StringBackedName(lazyGetterPrefix);
+  }
 
   JavaScriptBackend get backend => compiler.backend;
 
   String get deferredTypesName => 'deferredTypes';
   String get isolateName => 'Isolate';
   String get isolatePropertiesName => r'$isolateProperties';
-  String get noSuchMethodName => publicInstanceMethodNameByArity(
+  jsAst.Name get noSuchMethodName => publicInstanceMethodNameByArity(
       Compiler.NO_SUCH_METHOD, Compiler.NO_SUCH_METHOD_ARG_COUNT);
   /**
    * Some closures must contain their name. The name is stored in
@@ -417,54 +446,63 @@
 
   /// Returns the string that is to be used as the result of a call to
   /// [JS_GET_NAME] at [node] with argument [name].
-  String getNameForJsGetName(Node node, JsGetName name) {
+  jsAst.Name getNameForJsGetName(Node node, JsGetName name) {
     switch (name) {
-      case JsGetName.GETTER_PREFIX: return getterPrefix;
-      case JsGetName.SETTER_PREFIX: return setterPrefix;
-      case JsGetName.CALL_PREFIX: return callPrefix;
-      case JsGetName.CALL_PREFIX0: return '${callPrefix}\$0';
-      case JsGetName.CALL_PREFIX1: return '${callPrefix}\$1';
-      case JsGetName.CALL_PREFIX2: return '${callPrefix}\$2';
-      case JsGetName.CALL_PREFIX3: return '${callPrefix}\$3';
-      case JsGetName.CALL_CATCH_ALL: return callCatchAllName;
-      case JsGetName.REFLECTABLE: return reflectableField;
+      case JsGetName.GETTER_PREFIX: return asName(getterPrefix);
+      case JsGetName.SETTER_PREFIX: return asName(setterPrefix);
+      case JsGetName.CALL_PREFIX: return asName(callPrefix);
+      case JsGetName.CALL_PREFIX0: return asName('${callPrefix}\$0');
+      case JsGetName.CALL_PREFIX1: return asName('${callPrefix}\$1');
+      case JsGetName.CALL_PREFIX2: return asName('${callPrefix}\$2');
+      case JsGetName.CALL_PREFIX3: return asName('${callPrefix}\$3');
+      case JsGetName.CALL_CATCH_ALL: return asName(callCatchAllName);
+      case JsGetName.REFLECTABLE: return asName(reflectableField);
       case JsGetName.CLASS_DESCRIPTOR_PROPERTY:
-        return classDescriptorProperty;
+        return asName(classDescriptorProperty);
       case JsGetName.REQUIRED_PARAMETER_PROPERTY:
-        return requiredParameterField;
-      case JsGetName.DEFAULT_VALUES_PROPERTY: return defaultValuesField;
-      case JsGetName.CALL_NAME_PROPERTY: return callNameField;
-      case JsGetName.DEFERRED_ACTION_PROPERTY: return deferredAction;
-      case JsGetName.OPERATOR_AS_PREFIX: return operatorAsPrefix;
-      case JsGetName.SIGNATURE_NAME: return operatorSignature;
-      case JsGetName.TYPEDEF_TAG: return typedefTag;
+        return asName(requiredParameterField);
+      case JsGetName.DEFAULT_VALUES_PROPERTY: return asName(defaultValuesField);
+      case JsGetName.CALL_NAME_PROPERTY: return asName(callNameField);
+      case JsGetName.DEFERRED_ACTION_PROPERTY: return asName(deferredAction);
+      case JsGetName.OPERATOR_AS_PREFIX: return asName(operatorAsPrefix);
+      case JsGetName.SIGNATURE_NAME: return asName(operatorSignature);
+      case JsGetName.TYPEDEF_TAG: return asName(typedefTag);
       case JsGetName.FUNCTION_TYPE_VOID_RETURN_TAG:
-        return functionTypeVoidReturnTag;
+        return asName(functionTypeVoidReturnTag);
       case JsGetName.FUNCTION_TYPE_RETURN_TYPE_TAG:
-        return functionTypeReturnTypeTag;
+        return asName(functionTypeReturnTypeTag);
       case JsGetName.FUNCTION_TYPE_REQUIRED_PARAMETERS_TAG:
-        return functionTypeRequiredParametersTag;
+        return asName(functionTypeRequiredParametersTag);
       case JsGetName.FUNCTION_TYPE_OPTIONAL_PARAMETERS_TAG:
-        return functionTypeOptionalParametersTag;
+        return asName(functionTypeOptionalParametersTag);
       case JsGetName.FUNCTION_TYPE_NAMED_PARAMETERS_TAG:
-        return functionTypeNamedParametersTag;
+        return asName(functionTypeNamedParametersTag);
+      case JsGetName.IS_INDEXABLE_FIELD_NAME:
+        Element cls = backend.findHelper('JavaScriptIndexingBehavior');
+        return operatorIs(cls);
+      case JsGetName.NULL_CLASS_TYPE_NAME:
+        return runtimeTypeName(compiler.nullClass);
+      case JsGetName.OBJECT_CLASS_TYPE_NAME:
+        return runtimeTypeName(compiler.objectClass);
+      case JsGetName.FUNCTION_CLASS_TYPE_NAME:
+        return runtimeTypeName(compiler.functionClass);
       default:
         compiler.reportError(
           node, MessageKind.GENERIC,
           {'text': 'Error: Namer has no name for "$name".'});
-        return 'BROKEN';
+        return asName('BROKEN');
     }
   }
 
   /// Disambiguated name for [constant].
   ///
   /// Unique within the global-member namespace.
-  String constantName(ConstantValue constant) {
+  jsAst.Name constantName(ConstantValue constant) {
     // In the current implementation it doesn't make sense to give names to
     // function constants since the function-implementation itself serves as
     // constant and can be accessed directly.
     assert(!constant.isFunction);
-    String result = constantNames[constant];
+    jsAst.Name result = constantNames[constant];
     if (result == null) {
       String longName = constantLongName(constant);
       result = getFreshName(longName, usedGlobalNames, suggestedGlobalNames);
@@ -531,9 +569,10 @@
       // Make sure to return a private name that starts with _ so it
       // cannot clash with any public names.
       // The name is still not guaranteed to be unique, since both the library
-      // name and originalName could contain $ symbols.
-      String libraryName = _disambiguateGlobal(library);
-      return '_$libraryName\$${text}';
+      // name and originalName could contain $ symbols and as the library
+      // name itself might clash.
+      String libraryName = _proposeNameForGlobal(library);
+      return "_$libraryName\$$text";
     }
   }
 
@@ -547,7 +586,7 @@
   }
 
   /// Annotated name for [method] encoding arity and named parameters.
-  String instanceMethodName(FunctionElement method) {
+  jsAst.Name instanceMethodName(FunctionElement method) {
     if (method.isGenerativeConstructorBody) {
       return _disambiguateInternalMember(method,
           () => _proposeNameForConstructorBody(method));
@@ -557,7 +596,8 @@
 
   /// Annotated name for a public method with the given [originalName]
   /// and [arity] and no named parameters.
-  String publicInstanceMethodNameByArity(String originalName, int arity) {
+  jsAst.Name publicInstanceMethodNameByArity(String originalName,
+                                             int arity) {
     return invocationName(new Selector.call(originalName, null, arity));
   }
 
@@ -568,9 +608,9 @@
   ///
   /// This name cannot be minified because it is generated by string
   /// concatenation at runtime, by applyFunction in js_helper.dart.
-  String deriveCallMethodName(List<String> suffix) {
+  jsAst.Name deriveCallMethodName(List<String> suffix) {
     // TODO(asgerf): Avoid clashes when named parameters contain $ symbols.
-    return '$callPrefix\$${suffix.join(r'$')}';
+    return new StringBackedName('$callPrefix\$${suffix.join(r'$')}');
   }
 
   /// The suffix list for the pattern:
@@ -602,20 +642,23 @@
   }
 
   /// Annotated name for the member being invoked by [selector].
-  String invocationName(Selector selector) {
+  jsAst.Name invocationName(Selector selector) {
     switch (selector.kind) {
       case SelectorKind.GETTER:
-        String disambiguatedName = _disambiguateMember(selector.memberName);
+        jsAst.Name disambiguatedName =
+            _disambiguateMember(selector.memberName);
         return deriveGetterName(disambiguatedName);
 
       case SelectorKind.SETTER:
-        String disambiguatedName = _disambiguateMember(selector.memberName);
+        jsAst.Name disambiguatedName =
+            _disambiguateMember(selector.memberName);
         return deriveSetterName(disambiguatedName);
 
       case SelectorKind.OPERATOR:
       case SelectorKind.INDEX:
         String operatorIdentifier = operatorNameToIdentifier(selector.name);
-        String disambiguatedName = _disambiguateOperator(operatorIdentifier);
+        jsAst.Name disambiguatedName =
+            _disambiguateOperator(operatorIdentifier);
         return disambiguatedName; // Operators are not annotated.
 
       case SelectorKind.CALL:
@@ -624,7 +667,7 @@
           // Derive the annotated name for this variant of 'call'.
           return deriveCallMethodName(suffix);
         }
-        String disambiguatedName =
+        jsAst.Name disambiguatedName =
             _disambiguateMember(selector.memberName, suffix);
         return disambiguatedName; // Methods other than call are not annotated.
 
@@ -638,14 +681,14 @@
   /**
    * Returns the internal name used for an invocation mirror of this selector.
    */
-  String invocationMirrorInternalName(Selector selector)
+  jsAst.Name invocationMirrorInternalName(Selector selector)
       => invocationName(selector);
 
   /**
    * Returns the disambiguated name for the given field, used for constructing
    * the getter and setter names.
    */
-  String fieldAccessorName(FieldElement element) {
+  jsAst.Name fieldAccessorName(FieldElement element) {
     return element.isInstanceMember
         ? _disambiguateMember(element.memberName)
         : _disambiguateGlobal(element);
@@ -655,7 +698,7 @@
    * Returns name of the JavaScript property used to store a static or instance
    * field.
    */
-  String fieldPropertyName(FieldElement element) {
+  jsAst.Name fieldPropertyName(FieldElement element) {
     return element.isInstanceMember
         ? instanceFieldPropertyName(element)
         : _disambiguateGlobal(element);
@@ -665,7 +708,7 @@
    * Returns name of the JavaScript property used to store the
    * `readTypeVariable` function for the given type variable.
    */
-  String nameForReadTypeVariable(TypeVariableElement element) {
+  jsAst.Name nameForReadTypeVariable(TypeVariableElement element) {
     return _disambiguateInternalMember(element, () => element.name);
   }
 
@@ -676,14 +719,14 @@
    * Should be used together with [globalObjectFor], which denotes the object
    * on which the returned property name should be used.
    */
-  String globalPropertyName(Element element) {
+  jsAst.Name globalPropertyName(Element element) {
     return _disambiguateGlobal(element);
   }
 
   /**
    * Returns the JavaScript property name used to store an instance field.
    */
-  String instanceFieldPropertyName(FieldElement element) {
+  jsAst.Name instanceFieldPropertyName(FieldElement element) {
     ClassElement enclosingClass = element.enclosingClass;
 
     if (element.hasFixedBackendName) {
@@ -692,7 +735,7 @@
       assert(enclosingClass.isNative &&
              !element.fixedBackendName.contains(r'$'));
 
-      return element.fixedBackendName;
+      return new StringBackedName(element.fixedBackendName);
     }
 
     // Instances of BoxFieldElement are special. They are already created with
@@ -702,7 +745,7 @@
     // fixedBackendName, as we want to allow other namers to do something more
     // clever with them.
     if (element is BoxFieldElement) {
-      return element.name;
+      return new StringBackedName(element.name);
     }
 
     // If the name of the field might clash with another field,
@@ -737,46 +780,46 @@
   }
 
   /// Annotated name for the setter of [element].
-  String setterForElement(MemberElement element) {
+  jsAst.Name setterForElement(MemberElement element) {
     // We dynamically create setters from the field-name. The setter name must
     // therefore be derived from the instance field-name.
-    String name = _disambiguateMember(element.memberName);
+    jsAst.Name name = _disambiguateMember(element.memberName);
     return deriveSetterName(name);
   }
 
   /// Annotated name for the setter of any member with [disambiguatedName].
-  String deriveSetterName(String disambiguatedName) {
+  jsAst.Name deriveSetterName(jsAst.Name disambiguatedName) {
     // We dynamically create setters from the field-name. The setter name must
     // therefore be derived from the instance field-name.
-    return '$setterPrefix$disambiguatedName';
+    return new SetterName(_literalSetterPrefix, disambiguatedName);
   }
 
   /// Annotated name for the setter of any member with [disambiguatedName].
-  String deriveGetterName(String disambiguatedName) {
+  jsAst.Name deriveGetterName(jsAst.Name disambiguatedName) {
     // We dynamically create getters from the field-name. The getter name must
     // therefore be derived from the instance field-name.
-    return '$getterPrefix$disambiguatedName';
+    return new GetterName(_literalGetterPrefix, disambiguatedName);
   }
 
   /// Annotated name for the getter of [element].
-  String getterForElement(MemberElement element) {
+  jsAst.Name getterForElement(MemberElement element) {
     // We dynamically create getters from the field-name. The getter name must
     // therefore be derived from the instance field-name.
-    String name = _disambiguateMember(element.memberName);
+    jsAst.Name name = _disambiguateMember(element.memberName);
     return deriveGetterName(name);
   }
 
   /// Property name for the getter of an instance member with [originalName].
-  String getterForMember(Name originalName) {
-    String disambiguatedName = _disambiguateMember(originalName);
+  jsAst.Name getterForMember(Name originalName) {
+    jsAst.Name disambiguatedName = _disambiguateMember(originalName);
     return deriveGetterName(disambiguatedName);
   }
 
   /// Disambiguated name for a compiler-owned global variable.
   ///
   /// The resulting name is unique within the global-member namespace.
-  String _disambiguateInternalGlobal(String name) {
-    String newName = internalGlobals[name];
+  jsAst.Name _disambiguateInternalGlobal(String name) {
+    jsAst.Name newName = internalGlobals[name];
     if (newName == null) {
       newName = getFreshName(name, usedGlobalNames, suggestedGlobalNames);
       internalGlobals[name] = newName;
@@ -795,19 +838,34 @@
   /// This provides an easy mechanism of avoiding a name-clash with user-space
   /// globals, although the callers of must still take care not to accidentally
   /// pass in the same [name] for two different internal globals.
-  String internalGlobal(String name) {
+  jsAst.Name internalGlobal(String name) {
     assert(!name.contains(r'$'));
     return _disambiguateInternalGlobal(name);
   }
 
+  /// Generates a unique key for [library].
+  ///
+  /// Keys are meant to be used in maps and should not be visible in the output.
+  String _generateLibraryKey(LibraryElement library) {
+    return _libraryKeys.putIfAbsent(library, () {
+      String keyBase = library.name;
+      int counter = 0;
+      String key = keyBase;
+      while (_libraryKeys.values.contains(key)) {
+        key ="$keyBase${counter++}";
+      }
+      return key;
+    });
+  }
+
   /// Returns the disambiguated name for a top-level or static element.
   ///
   /// The resulting name is unique within the global-member namespace.
-  String _disambiguateGlobal(Element element) {
+  jsAst.Name _disambiguateGlobal(Element element) {
     // TODO(asgerf): We can reuse more short names if we disambiguate with
     // a separate namespace for each of the global holder objects.
     element = element.declaration;
-    String newName = userGlobals[element];
+    jsAst.Name newName = userGlobals[element];
     if (newName == null) {
       String proposedName = _proposeNameForGlobal(element);
       newName = getFreshName(proposedName, usedGlobalNames,
@@ -833,17 +891,17 @@
   /// The resulting name, and its associated annotated names, are unique
   /// to the ([originalName], [suffixes]) pair within the instance-member
   /// namespace.
-  String _disambiguateMember(Name originalName,
-                             [List<String> suffixes = const []]) {
+  jsAst.Name _disambiguateMember(Name originalName,
+                                 [List<String> suffixes = const []]) {
     // Build a string encoding the library name, if the name is private.
     String libraryKey = originalName.isPrivate
-            ? _disambiguateGlobal(originalName.library)
+            ? _generateLibraryKey(originalName.library)
             : '';
 
     // In the unique key, separate the name parts by '@'.
     // This avoids clashes since the original names cannot contain that symbol.
     String key = '$libraryKey@${originalName.text}@${suffixes.join('@')}';
-    String newName = userInstanceMembers[key];
+    jsAst.Name newName = userInstanceMembers[key];
     if (newName == null) {
       String proposedName = privateName(originalName);
       if (!suffixes.isEmpty) {
@@ -875,7 +933,7 @@
     String key = '$libraryPrefix@$originalName@$suffix';
     assert(!userInstanceMembers.containsKey(key));
     assert(!usedInstanceNames.contains(disambiguatedName));
-    userInstanceMembers[key] = disambiguatedName;
+    userInstanceMembers[key] = new StringBackedName(disambiguatedName);
     usedInstanceNames.add(disambiguatedName);
   }
 
@@ -885,8 +943,9 @@
   /// constructor bodies, and super-accessors.
   ///
   /// The resulting name is unique within the instance-member namespace.
-  String _disambiguateInternalMember(Element element, String proposeName()) {
-    String newName = internalInstanceMembers[element];
+  jsAst.Name _disambiguateInternalMember(Element element,
+                                         String proposeName()) {
+    jsAst.Name newName = internalInstanceMembers[element];
     if (newName == null) {
       String name = proposeName();
       bool mayClashNative = _isUserClassExtendingNative(element.enclosingClass);
@@ -905,8 +964,8 @@
   /// `$add` and not `+`.
   ///
   /// The resulting name is unique within the instance-member namespace.
-  String _disambiguateOperator(String operatorIdentifier) {
-    String newName = userInstanceOperators[operatorIdentifier];
+  jsAst.Name _disambiguateOperator(String operatorIdentifier) {
+    jsAst.Name newName = userInstanceOperators[operatorIdentifier];
     if (newName == null) {
       newName = getFreshName(operatorIdentifier, usedInstanceNames,
                              suggestedInstanceNames);
@@ -927,11 +986,11 @@
   ///
   /// Note that [MinifyNamer] overrides this method with one that produces
   /// minified names.
-  String getFreshName(String proposedName,
-                      Set<String> usedNames,
-                      Map<String, String> suggestedNames,
-                      {bool sanitizeForAnnotations: false,
-                       bool sanitizeForNatives: false}) {
+  jsAst.Name getFreshName(String proposedName,
+                          Set<String> usedNames,
+                          Map<String, String> suggestedNames,
+                          {bool sanitizeForAnnotations: false,
+                           bool sanitizeForNatives: false}) {
     if (sanitizeForAnnotations) {
       proposedName = _sanitizeForAnnotations(proposedName);
     }
@@ -952,7 +1011,7 @@
       candidate = "$proposedName$i";
     }
     usedNames.add(candidate);
-    return candidate;
+    return new StringBackedName(candidate);
   }
 
   /// Returns a variant of [name] that cannot clash with the annotated
@@ -1018,6 +1077,8 @@
       }
     } else if (element.isLibrary) {
       LibraryElement library = element;
+      name = libraryLongNames[library];
+      if (name != null) return name;
       name = library.getLibraryOrScriptName();
       if (name.contains('.')) {
         // For libraries that have a library tag, we use the last part
@@ -1036,6 +1097,15 @@
           name = 'lib_$name';
         }
       }
+      // Names constructed based on a libary name will be further disambiguated.
+      // However, as names from the same libary should have the same libary
+      // name part, we disambiguate the library name here.
+      String disambiguated  = name;
+      for (int c = 0; libraryLongNames.containsValue(disambiguated); c++) {
+        disambiguated = "$name$c";
+      }
+      libraryLongNames[library] = disambiguated;
+      name = disambiguated;
     } else {
       name = element.name;
     }
@@ -1070,7 +1140,7 @@
   }
 
   /// Property name used for `getInterceptor` or one of its specializations.
-  String nameForGetInterceptor(Iterable<ClassElement> classes) {
+  jsAst.Name nameForGetInterceptor(Iterable<ClassElement> classes) {
     FunctionElement getInterceptor = backend.getInterceptorMethod;
     if (classes.contains(backend.jsInterceptorClass)) {
       // If the base Interceptor class is in the set of intercepted classes, we
@@ -1087,27 +1157,24 @@
 
   /// Property name used for the one-shot interceptor method for the given
   /// [selector] and return-type specialization.
-  String nameForGetOneShotInterceptor(Selector selector,
-                                      Iterable<ClassElement> classes) {
+  jsAst.Name nameForGetOneShotInterceptor(Selector selector,
+                                          Iterable<ClassElement> classes) {
     // The one-shot name is a global name derived from the invocation name.  To
     // avoid instability we would like the names to be unique and not clash with
     // other global names.
-
-    String root = invocationName(selector);
+    jsAst.Name root = invocationName(selector);
 
     if (classes.contains(backend.jsInterceptorClass)) {
       // If the base Interceptor class is in the set of intercepted classes,
       // this is the most general specialization which uses the generic
-      // getInterceptor method.  To keep the name short, we add '$' only to
-      // distinguish from internal globals requested from outside the Namer
-      // with internalGlobal().
+      // getInterceptor method.
       // TODO(sra): Find a way to get the simple name when Object is not in the
       // set of classes for most general variant, e.g. "$lt$n" could be "$lt".
-      if (selector.isGetter || selector.isSetter) root = '$root\$';
-      return _disambiguateInternalGlobal(root);
+      return new CompoundName([root, _literalDollar]);
     } else {
       String suffix = suffixForGetInterceptor(classes);
-      return _disambiguateInternalGlobal("$root\$$suffix");
+      return new CompoundName([root, _literalDollar,
+                               new StringBackedName(suffix)]);
     }
   }
 
@@ -1120,8 +1187,8 @@
   /// [operatorIsPrefix] or [operatorAsPrefix]. If this is a function type,
   /// then by convention, an underscore must also separate [operatorIsPrefix]
   /// from the type name.
-  String runtimeTypeName(TypeDeclarationElement element) {
-    if (element == null) return 'dynamic';
+  jsAst.Name runtimeTypeName(TypeDeclarationElement element) {
+    if (element == null) return _literalDynamic;
     // The returned name affects both the global and instance member namespaces:
     //
     // - If given a class, this must coincide with the class name, which
@@ -1140,7 +1207,7 @@
   ///
   /// This is both the *runtime type* of the class (see [runtimeTypeName])
   /// and a global property name in which to store its JS constructor.
-  String className(ClassElement class_) => _disambiguateGlobal(class_);
+  jsAst.Name className(ClassElement class_) => _disambiguateGlobal(class_);
 
   /// Property name on which [member] can be accessed directly,
   /// without clashing with another JS property name.
@@ -1162,11 +1229,12 @@
   ///         this.super$A$foo(); // super.foo()
   ///     }
   ///
-  String aliasedSuperMemberPropertyName(Element member) {
+  jsAst.Name aliasedSuperMemberPropertyName(Element member) {
     assert(!member.isField); // Fields do not need super aliases.
-    String methodName = instanceMethodName(member);
-    return _disambiguateInternalMember(member,
-        () => 'super\$${member.enclosingClass.name}\$$methodName');
+    return _disambiguateInternalMember(member, () {
+      String invocationName = operatorNameToIdentifier(member.name);
+      return "super\$${member.enclosingClass.name}\$$invocationName";
+    });
   }
 
   /// Property name in which to store the given static or instance [method].
@@ -1175,7 +1243,7 @@
   ///
   /// The name is not necessarily unique to [method], since a static method
   /// may share its name with an instance method.
-  String methodPropertyName(Element method) {
+  jsAst.Name methodPropertyName(Element method) {
     return method.isInstanceMember
         ? instanceMethodName(method)
         : globalPropertyName(method);
@@ -1214,23 +1282,33 @@
         library.getLibraryOrScriptName().hashCode % userGlobalObjects.length];
   }
 
-  String lazyInitializerName(Element element) {
-    assert(Elements.isStaticOrTopLevelField(element));
-    String name = _disambiguateGlobal(element);
-    return _disambiguateInternalGlobal("$getterPrefix$name");
+  jsAst.Name deriveLazyInitializerName(jsAst.Name name) {
+    // These are not real dart getters, so do not use GetterName;
+    return new CompoundName([_literalLazyGetterPrefix, name]);
   }
 
-  String staticClosureName(Element element) {
+  jsAst.Name lazyInitializerName(Element element) {
+    assert(Elements.isStaticOrTopLevelField(element));
+    jsAst.Name name = _disambiguateGlobal(element);
+    // These are not real dart getters, so do not use GetterName;
+    return deriveLazyInitializerName(name);
+  }
+
+  jsAst.Name staticClosureName(Element element) {
     assert(Elements.isStaticOrTopLevelFunction(element));
-    String name = _disambiguateGlobal(element);
-    return _disambiguateInternalGlobal("$name\$closure");
+    String enclosing = element.enclosingClass == null
+        ? "" : element.enclosingClass.name;
+    String library = _proposeNameForGlobal(element.library);
+    return _disambiguateInternalGlobal(
+        "${library}_${enclosing}_${element.name}\$closure");
   }
 
   // This name is used as part of the name of a TypeConstant
   String uniqueNameForTypeConstantElement(Element element) {
     // TODO(sra): If we replace the period with an identifier character,
     // TypeConstants will have better names in unminified code.
-    return "${globalObjectFor(element)}.${globalPropertyName(element)}";
+    String library = _proposeNameForGlobal(element.library);
+    return "${library}.${element.name}";
   }
 
   String globalObjectForConstant(ConstantValue constant) => 'C';
@@ -1255,30 +1333,32 @@
 
   String get functionTypeNamedParametersTag => r'named';
 
-  Map<FunctionType,String> functionTypeNameMap =
-      new Map<FunctionType,String>();
+  Map<FunctionType, jsAst.Name> functionTypeNameMap =
+      new HashMap<FunctionType, jsAst.Name>();
   final FunctionTypeNamer functionTypeNamer;
 
-  String getFunctionTypeName(FunctionType functionType) {
+  jsAst.Name getFunctionTypeName(FunctionType functionType) {
     return functionTypeNameMap.putIfAbsent(functionType, () {
       String proposedName = functionTypeNamer.computeName(functionType);
-      String freshName = getFreshName(proposedName, usedInstanceNames,
-                                      suggestedInstanceNames);
-      return freshName;
+      return getFreshName(proposedName, usedInstanceNames,
+                          suggestedInstanceNames);
     });
   }
 
-  String operatorIsType(DartType type) {
+  jsAst.Name operatorIsType(DartType type) {
     if (type.isFunctionType) {
       // TODO(erikcorry): Reduce from $isx to ix when we are minifying.
-      return '${operatorIsPrefix}_${getFunctionTypeName(type)}';
+      return new CompoundName([new StringBackedName(operatorIsPrefix),
+                               _literalUnderscore,
+                               getFunctionTypeName(type)]);
     }
     return operatorIs(type.element);
   }
 
-  String operatorIs(ClassElement element) {
+  jsAst.Name operatorIs(ClassElement element) {
     // TODO(erikcorry): Reduce from $isx to ix when we are minifying.
-    return '${operatorIsPrefix}${runtimeTypeName(element)}';
+    return new CompoundName([new StringBackedName(operatorIsPrefix),
+                             runtimeTypeName(element)]);
   }
 
   /// Returns a name that does not clash with reserved JS keywords.
@@ -1290,8 +1370,29 @@
     return name;
   }
 
-  String substitutionName(Element element) {
-    return '${operatorAsPrefix}${runtimeTypeName(element)}';
+  jsAst.Name substitutionName(Element element) {
+    return new CompoundName([new StringBackedName(operatorAsPrefix),
+                             runtimeTypeName(element)]);
+  }
+
+  /// Translates a [String] into the corresponding [Name] data structure as
+  /// used by the namer.
+  ///
+  /// If [name] is a setter or getter name, the corresponding [GetterName] or
+  /// [SetterName] data structure is used.
+  jsAst.Name asName(String name) {
+    if (name.startsWith(getterPrefix) && name.length > getterPrefix.length) {
+      return new GetterName(_literalGetterPrefix,
+                           new StringBackedName(
+                               name.substring(getterPrefix.length)));
+    }
+    if (name.startsWith(setterPrefix) && name.length > setterPrefix.length) {
+      return new GetterName(_literalSetterPrefix,
+                            new StringBackedName(
+                                name.substring(setterPrefix.length)));
+    }
+
+    return new StringBackedName(name);
   }
 
   /// Returns a variable name that cannot clash with a keyword, a global
@@ -1306,6 +1407,20 @@
     return name;
   }
 
+  /// Returns a safe variable name for use in async rewriting.
+  ///
+  /// Has the same property as [safeVariableName] but does not clash with
+  /// names returned from there.
+  /// Additionally, when used as a prefix to a variable name, the result
+  /// will be safe to use, as well.
+  String safeVariablePrefixForAsyncRewrite(String name) {
+    return "$asyncPrefix$name";
+  }
+
+  jsAst.Name deriveAsyncBodyName(jsAst.Name original) {
+    return new _AsyncName(_literalAsyncPrefix, original);
+  }
+
   String operatorNameToIdentifier(String name) {
     if (name == null) return null;
     if (name == '==') {
@@ -1360,13 +1475,140 @@
   }
 
   void forgetElement(Element element) {
-    String globalName = userGlobals[element];
+    jsAst.Name globalName = userGlobals[element];
     invariant(element, globalName != null, message: 'No global name.');
     usedGlobalNames.remove(globalName);
     userGlobals.remove(element);
   }
 }
 
+abstract class _NamerName extends jsAst.Name {
+  int get _kind;
+}
+
+class StringBackedName extends _NamerName {
+  final String name;
+  int get _kind => 1;
+  
+  StringBackedName(this.name);
+
+  toString() => throw new UnsupportedError("Cannot convert a name to a string");
+
+  operator==(other) {
+    if (identical(this, other)) return true;
+    return (other is StringBackedName) && other.name == name;
+  }
+
+  int get hashCode => name.hashCode;
+
+  int compareTo(_NamerName other) {
+    if (other._kind != _kind) return other._kind - _kind;
+    return name.compareTo(other.name);
+  }
+}
+
+abstract class _PrefixedName extends _NamerName {
+  final jsAst.Name prefix;
+  final jsAst.Name base;
+  int get _kind;
+
+  _PrefixedName(this.prefix, this.base);
+  
+  String get name => prefix.name + base.name;
+
+  toString() => throw new UnsupportedError("Cannot convert a name to a string");
+
+  bool operator==(other) {
+    if (identical(this, other)) return true;
+    if (other is! _PrefixedName) return false;
+    return other.base == base && other.prefix == prefix;
+  }
+
+  int get hashCode => base.hashCode * 13 + prefix.hashCode;
+
+  int compareTo(_NamerName other) {
+    if (other._kind != _kind) return other._kind - _kind;
+    _PrefixedName otherSameKind = other;
+    int result = prefix.compareTo(otherSameKind.prefix);
+    if (result == 0) {
+      result = name.compareTo(otherSameKind.name);
+    }
+    return result;
+  }
+}
+
+class GetterName extends _PrefixedName {
+  int get _kind => 2;
+
+  GetterName(jsAst.Name prefix, jsAst.Name base) : super(prefix, base);
+}
+
+class SetterName extends _PrefixedName {
+  int get _kind => 3;
+
+  SetterName(jsAst.Name prefix, jsAst.Name base) : super(prefix, base);
+}
+
+class _AsyncName extends _PrefixedName {
+  int get _kind => 4;
+
+  _AsyncName(jsAst.Name prefix, jsAst.Name base) : super(prefix, base);
+
+  @override
+  bool get allowRename => true;
+}
+
+class CompoundName extends _NamerName {
+  final List<_NamerName> _parts;
+  int get _kind => 4;
+  String _cachedName;
+  int _cachedHashCode = -1;
+
+  CompoundName(this._parts);
+
+  String get name {
+    if (_cachedName == null) {
+      _cachedName = _parts.map((jsAst.Name name) => name.name).join();
+    }
+    return _cachedName;
+  }
+
+  toString() => throw new UnsupportedError("Cannot convert a name to a string");
+
+  bool operator==(other) {
+    if (identical(this, other)) return true;
+    if (other is! CompoundName) return false;
+    if (other._parts.length != _parts.length) return false;
+    for (int i = 0; i < _parts.length; ++i) {
+      if (other._parts[i] != _parts[i]) return false;
+    }
+    return true;
+  }
+
+  int get hashCode {
+    if (_cachedHashCode < 0) {
+      _cachedHashCode = 0;
+      for (jsAst.Name name in _parts) {
+        _cachedHashCode = (_cachedHashCode * 17 + name.hashCode) & 0x7fffffff;
+      }
+    }
+    return _cachedHashCode;
+  }
+
+  int compareTo(_NamerName other) {
+    if (other._kind != _kind) return other._kind - _kind;
+    CompoundName otherSameKind = other;
+    if (otherSameKind._parts.length != _parts.length) {
+      return otherSameKind._parts.length - _parts.length;
+    }
+    int result = 0;
+    for (int pos = 0; result == 0 && pos < _parts.length; pos++) {
+      result = _parts[pos].compareTo(otherSameKind._parts[pos]);
+    }
+    return result;
+  }
+}
+
 /**
  * Generator of names for [ConstantValue] values.
  *
@@ -1543,8 +1785,21 @@
   }
 
   @override
-  void visitDummy(DummyConstantValue constant, [_]) {
-    add('dummy_receiver');
+  void visitSynthetic(SyntheticConstantValue constant, [_]) {
+    switch (constant.kind) {
+      case SyntheticConstantKind.DUMMY_INTERCEPTOR:
+        add('dummy_receiver');
+        break;
+      case SyntheticConstantKind.TYPEVARIABLE_REFERENCE:
+        add('type_variable_reference');
+        break;
+      case SyntheticConstantKind.NAME:
+        add('name');
+        break;
+      default:
+        compiler.internalError(compiler.currentElement,
+                               "Unexpected SyntheticConstantValue");
+    }
   }
 
   @override
@@ -1646,9 +1901,16 @@
   }
 
   @override
-  visitDummy(DummyConstantValue constant, [_]) {
-    compiler.internalError(NO_LOCATION_SPANNABLE,
-        'DummyReceiverConstant should never be named and never be subconstant');
+  visitSynthetic(SyntheticConstantValue constant, [_]) {
+    switch (constant.kind) {
+      case SyntheticConstantKind.TYPEVARIABLE_REFERENCE:
+        return constant.payload.hashCode;
+      default:
+        compiler.internalError(NO_LOCATION_SPANNABLE,
+                               'SyntheticConstantValue should never be named and '
+                               'never be subconstant');
+        return null;
+    }
   }
 
   @override
diff --git a/pkg/compiler/lib/src/js_backend/patch_resolver.dart b/pkg/compiler/lib/src/js_backend/patch_resolver.dart
index 34a5014..166490f 100644
--- a/pkg/compiler/lib/src/js_backend/patch_resolver.dart
+++ b/pkg/compiler/lib/src/js_backend/patch_resolver.dart
@@ -8,9 +8,7 @@
 import '../dart_types.dart';
 import '../elements/elements.dart';
 import '../elements/modelx.dart';
-import '../resolution/resolution.dart';
 import '../tree/tree.dart';
-import '../util/util.dart';
 
 class PatchResolverTask extends CompilerTask {
   PatchResolverTask(Compiler compiler) : super(compiler);
diff --git a/pkg/compiler/lib/src/js_backend/runtime_types.dart b/pkg/compiler/lib/src/js_backend/runtime_types.dart
index 2b13f03..66be56a 100644
--- a/pkg/compiler/lib/src/js_backend/runtime_types.dart
+++ b/pkg/compiler/lib/src/js_backend/runtime_types.dart
@@ -32,7 +32,7 @@
 
   JavaScriptBackend get backend => compiler.backend;
 
-  String get getFunctionThatReturnsNullName
+  jsAst.Name get getFunctionThatReturnsNullName
       => backend.namer.internalGlobal('functionThatReturnsNull');
 
   RuntimeTypes(Compiler compiler)
@@ -401,7 +401,7 @@
   String getTypeRepresentationForTypeConstant(DartType type) {
     JavaScriptBackend backend = compiler.backend;
     Namer namer = backend.namer;
-    if (type.isDynamic) return namer.runtimeTypeName(null);
+    if (type.isDynamic) return "dynamic";
     String name = namer.uniqueNameForTypeConstantElement(type.element);
     if (!type.element.isClass) return name;
     InterfaceType interface = type;
@@ -541,10 +541,10 @@
         getTypeEncoding(type, alwaysGenerateFunction: true);
     if (contextClass != null) {
       JavaScriptBackend backend = compiler.backend;
-      String contextName = backend.namer.className(contextClass);
+      jsAst.Name contextName = backend.namer.className(contextClass);
       return js('function () { return #(#, #, #); }',
           [ backend.emitter.staticFunctionAccess(backend.getComputeSignature()),
-              encoding, this_, js.string(contextName) ]);
+              encoding, this_, js.quoteName(contextName) ]);
     } else {
       return encoding;
     }
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 6b04672..5d779a0 100644
--- a/pkg/compiler/lib/src/js_backend/type_variable_handler.dart
+++ b/pkg/compiler/lib/src/js_backend/type_variable_handler.dart
@@ -20,15 +20,15 @@
    *  Maps a class element to a list with indices that point to type variables
    *  constants for each of the class' type variables.
    */
-  Map<ClassElement, List<int>> _typeVariables =
-      new Map<ClassElement, List<int>>();
+  Map<ClassElement, List<jsAst.Expression>> _typeVariables =
+      new Map<ClassElement, List<jsAst.Expression>>();
 
   /**
    *  Maps a TypeVariableType to the index pointing to the constant representing
    *  the corresponding type variable at runtime.
    */
-  Map<TypeVariableElement, int> _typeVariableConstants =
-      new Map<TypeVariableElement, int>();
+  Map<TypeVariableElement, jsAst.Expression> _typeVariableConstants =
+      new Map<TypeVariableElement, jsAst.Expression>();
 
   TypeVariableHandler(this._compiler);
 
@@ -60,14 +60,17 @@
       }
     } else {
       if (_backend.isAccessibleByReflection(cls)) {
-        _processTypeVariablesOf(cls);
+        processTypeVariablesOf(cls);
       }
     }
   }
 
-  void _processTypeVariablesOf(ClassElement cls) {
+  void processTypeVariablesOf(ClassElement cls) {
+    // Do not process classes twice.
+    if (_typeVariables.containsKey(cls)) return;
+
     InterfaceType typeVariableType = _typeVariableClass.thisType;
-    List<int> constants = <int>[];
+    List<jsAst.Expression> constants = <jsAst.Expression>[];
 
     for (TypeVariableType currentTypeVariable in cls.typeVariables) {
       TypeVariableElement typeVariableElement = currentTypeVariable.element;
@@ -78,12 +81,19 @@
           new StringConstantExpression(currentTypeVariable.name),
           _backend.constantSystem.createString(
               new DartString.literal(currentTypeVariable.name)));
-      int boundIndex = _metadataCollector.reifyType(typeVariableElement.bound);
+      jsAst.Expression boundIndex =
+          _metadataCollector.reifyType(typeVariableElement.bound);
+      ConstantValue boundValue =
+          new SyntheticConstantValue(
+              SyntheticConstantKind.TYPEVARIABLE_REFERENCE,
+              boundIndex);
+      ConstantExpression boundExpression =
+          new SyntheticConstantExpression(boundValue);
       AstConstant bound = new AstConstant(
           typeVariableElement,
           typeVariableElement.node,
-          new IntConstantExpression(boundIndex),
-          _backend.constantSystem.createInt(boundIndex));
+          boundExpression,
+          boundValue);
       AstConstant type = new AstConstant(
           typeVariableElement,
           typeVariableElement.node,
@@ -123,17 +133,16 @@
    * entry in the list has already been reserved and the constant is added
    * there, otherwise a new entry for [c] is created.
    */
-  int _reifyTypeVariableConstant(ConstantValue c, TypeVariableElement variable) {
+  jsAst.Expression _reifyTypeVariableConstant(ConstantValue c,
+                                              TypeVariableElement variable) {
     jsAst.Expression name = _task.constantReference(c);
-    int index;
+    jsAst.Expression result = _metadataCollector.reifyExpression(name);
     if (_typeVariableConstants.containsKey(variable)) {
-      index = _typeVariableConstants[variable];
-      _metadataCollector.globalMetadata[index] = name;
-    } else {
-      index = _metadataCollector.addGlobalMetadata(name);
-      _typeVariableConstants[variable] = index;
+      Placeholder placeholder = _typeVariableConstants[variable];
+      placeholder.bind(result);
     }
-    return index;
+    _typeVariableConstants[variable] = result;
+    return result;
   }
 
   /**
@@ -146,21 +155,20 @@
    * [reifyTypeVariableConstant] will be called and the constant will be added
    * on the allocated entry.
    */
-  int reifyTypeVariable(TypeVariableElement variable) {
+  jsAst.Expression reifyTypeVariable(TypeVariableElement variable) {
     if (_typeVariableConstants.containsKey(variable)) {
       return _typeVariableConstants[variable];
     }
 
-    // TODO(15613): Remove quotes.
-    _metadataCollector.globalMetadata.add(js('"Placeholder for ${variable}"'));
-    return _typeVariableConstants[variable] =
-        _metadataCollector.globalMetadata.length - 1;
+    Placeholder placeholder =
+        _metadataCollector.getMetadataPlaceholder(variable);
+    return _typeVariableConstants[variable] = placeholder;
   }
 
-  List<int> typeVariablesOf(ClassElement classElement) {
-    List<int> result = _typeVariables[classElement];
+  List<jsAst.Expression> typeVariablesOf(ClassElement classElement) {
+    List<jsAst.Expression> result = _typeVariables[classElement];
     if (result == null) {
-      result = const <int>[];
+      result = const <jsAst.Expression>[];
     }
     return result;
   }
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 e21ba1d..45604fde1 100644
--- a/pkg/compiler/lib/src/js_emitter/class_stub_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/class_stub_generator.dart
@@ -26,14 +26,14 @@
          namer.deferredAction]);
   }
 
-  jsAst.Expression generateGetter(Element member, String fieldName) {
+  jsAst.Expression generateGetter(Element member, jsAst.Name fieldName) {
     ClassElement cls = member.enclosingClass;
     String receiver = backend.isInterceptorClass(cls) ? 'receiver' : 'this';
     List<String> args = backend.isInterceptedMethod(member) ? ['receiver'] : [];
     return js('function(#) { return #.# }', [args, receiver, fieldName]);
   }
 
-  jsAst.Expression generateSetter(Element member, String fieldName) {
+  jsAst.Expression generateSetter(Element member, jsAst.Name fieldName) {
     ClassElement cls = member.enclosingClass;
     String receiver = backend.isInterceptorClass(cls) ? 'receiver' : 'this';
     List<String> args = backend.isInterceptedMethod(member) ? ['receiver'] : [];
@@ -47,8 +47,8 @@
    *
    * Invariant: [member] must be a declaration element.
    */
-  Map<String, jsAst.Expression> generateCallStubsForGetter(
-      Element member, Set<Selector> selectors) {
+  Map<jsAst.Name, jsAst.Expression> generateCallStubsForGetter(
+      Element member, Map<Selector, TypeMaskSet> selectors) {
     assert(invariant(member, member.isDeclaration));
 
     // If the method is intercepted, the stub gets the
@@ -63,32 +63,38 @@
       jsAst.Expression receiver =
           js(isInterceptorClass ? receiverArgumentName : 'this');
       if (member.isGetter) {
-        String getterName = namer.getterForElement(member);
+        jsAst.Name getterName = namer.getterForElement(member);
         if (isInterceptedMethod) {
           return js('this.#(#)', [getterName, receiver]);
         }
         return js('#.#()', [receiver, getterName]);
       } else {
-        String fieldName = namer.instanceFieldPropertyName(member);
+        jsAst.Name fieldName = namer.instanceFieldPropertyName(member);
         return js('#.#', [receiver, fieldName]);
       }
     }
 
-    Map<String, jsAst.Expression> generatedStubs = <String, jsAst.Expression>{};
+    Map<jsAst.Name, jsAst.Expression> generatedStubs =
+      <jsAst.Name, jsAst.Expression>{};
 
     // Two selectors may match but differ only in type.  To avoid generating
     // identical stubs for each we track untyped selectors which already have
     // stubs.
     Set<Selector> generatedSelectors = new Set<Selector>();
-    for (Selector selector in selectors) {
-      if (selector.applies(member, compiler.world)) {
-        selector = selector.asUntyped;
-        if (generatedSelectors.contains(selector)) continue;
+    for (Selector selector in selectors.keys) {
+      if (generatedSelectors.contains(selector)) continue;
+      if (!selector.appliesUnnamed(member, compiler.world)) continue;
+      for (TypeMask mask in selectors[selector].masks) {
+        if (mask != null &&
+            !mask.canHit(member, selector, compiler.world)) {
+          continue;
+        }
+
         generatedSelectors.add(selector);
 
-        String invocationName = namer.invocationName(selector);
+        jsAst.Name invocationName = namer.invocationName(selector);
         Selector callSelector = new Selector.callClosureFrom(selector);
-        String closureCallName = namer.invocationName(callSelector);
+        jsAst.Name closureCallName = namer.invocationName(callSelector);
 
         List<jsAst.Parameter> parameters = <jsAst.Parameter>[];
         List<jsAst.Expression> arguments = <jsAst.Expression>[];
@@ -113,38 +119,42 @@
     return generatedStubs;
   }
 
-  Map<String, Selector> computeSelectorsForNsmHandlers() {
+  Map<jsAst.Name, Selector> computeSelectorsForNsmHandlers() {
 
-    Map<String, Selector> jsNames = <String, Selector>{};
+    Map<jsAst.Name, Selector> jsNames = <jsAst.Name, 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) {
+    void addNoSuchMethodHandlers(String ignore,
+                                 Map<Selector, TypeMaskSet> selectors) {
       TypeMask objectSubclassTypeMask =
           new TypeMask.subclass(compiler.objectClass, compiler.world);
 
-      for (Selector selector in selectors) {
-        TypeMask mask = selector.mask;
-        if (mask == null) mask = objectSubclassTypeMask;
+      for (Selector selector in selectors.keys) {
+        TypeMaskSet maskSet = selectors[selector];
+        for (TypeMask mask in maskSet.masks) {
+          if (mask == null) mask = objectSubclassTypeMask;
 
-        if (!mask.needsNoSuchMethodHandling(selector, compiler.world)) {
-          continue;
+          if (mask.needsNoSuchMethodHandling(selector, compiler.world)) {
+            jsAst.Name jsName = namer.invocationMirrorInternalName(selector);
+            jsNames[jsName] = selector;
+            break;
+          }
         }
-        String jsName = namer.invocationMirrorInternalName(selector);
-        jsNames[jsName] = selector;
       }
     }
 
-    compiler.codegenWorld.invokedNames.forEach(addNoSuchMethodHandlers);
-    compiler.codegenWorld.invokedGetters.forEach(addNoSuchMethodHandlers);
-    compiler.codegenWorld.invokedSetters.forEach(addNoSuchMethodHandlers);
+    compiler.codegenWorld.forEachInvokedName(addNoSuchMethodHandlers);
+    compiler.codegenWorld.forEachInvokedGetter(addNoSuchMethodHandlers);
+    compiler.codegenWorld.forEachInvokedSetter(addNoSuchMethodHandlers);
     return jsNames;
   }
 
-  StubMethod generateStubForNoSuchMethod(String name, Selector selector) {
+  StubMethod generateStubForNoSuchMethod(jsAst.Name name,
+                                         Selector selector) {
     // Values match JSInvocationMirror in js-helper library.
     int type = selector.invocationMirrorKind;
     List<String> parameterNames =
@@ -154,32 +164,34 @@
         selector.callStructure.getOrderedNamedArguments().map((String name) =>
             js.string(name)).toList();
 
-    String methodName = selector.invocationMirrorMemberName;
-    String internalName = namer.invocationMirrorInternalName(selector);
+    jsAst.Name methodName = namer.asName(selector.invocationMirrorMemberName);
+    jsAst.Name internalName = namer.invocationMirrorInternalName(selector);
 
     assert(backend.isInterceptedName(Compiler.NO_SUCH_METHOD));
+    bool isIntercepted = backend.isInterceptedName(selector.name);
     jsAst.Expression expression =
-        js('''this.#noSuchMethodName(this,
+        js('''this.#noSuchMethodName(#receiver,
                     #createInvocationMirror(#methodName,
                                             #internalName,
                                             #type,
                                             #arguments,
                                             #namedArguments))''',
-           {'noSuchMethodName': namer.noSuchMethodName,
+           {'receiver': isIntercepted ? r'$receiver' : 'this',
+            'noSuchMethodName': namer.noSuchMethodName,
             'createInvocationMirror':
                 backend.emitter.staticFunctionAccess(
                     backend.getCreateInvocationMirror()),
             'methodName':
-                js.string(compiler.enableMinification
+                js.quoteName(compiler.enableMinification
                     ? internalName : methodName),
-            'internalName': js.string(internalName),
+            'internalName': js.quoteName(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)) {
+    if (isIntercepted) {
       function = js(r'function($receiver, #) { return # }',
                               [parameterNames, expression]);
     } else {
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 59fe76a..6f3f30e 100644
--- a/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart
+++ b/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart
@@ -216,8 +216,8 @@
           backend.retainMetadataOf(cls);
           oldEmitter.classEmitter.visitFields(cls, false,
               (Element member,
-               String name,
-               String accessorName,
+               jsAst.Name name,
+               jsAst.Name accessorName,
                bool needsGetter,
                bool needsSetter,
                bool needsCheckedSetter) {
diff --git a/pkg/compiler/lib/src/js_emitter/helpers.dart b/pkg/compiler/lib/src/js_emitter/helpers.dart
index 017094b..a5591ac 100644
--- a/pkg/compiler/lib/src/js_emitter/helpers.dart
+++ b/pkg/compiler/lib/src/js_emitter/helpers.dart
@@ -12,3 +12,22 @@
   }
   return mixin;
 }
+
+class _DeferredOutputUnitHash extends jsAst.DeferredString {
+  String _hash;
+  final OutputUnit _outputUnit;
+
+  _DeferredOutputUnitHash(this._outputUnit);
+
+  void setHash(String hash) {
+    assert(_hash == null);
+    _hash = hash;
+  }
+
+  String get value {
+    assert(_hash != null);
+    return '"$_hash"';
+  }
+
+  String toString() => "HashCode for ${_outputUnit} [$_hash]";
+}
\ No newline at end of file
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 26d9a13..1da1a03 100644
--- a/pkg/compiler/lib/src/js_emitter/interceptor_stub_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/interceptor_stub_generator.dart
@@ -287,11 +287,11 @@
     return null;
   }
 
-  jsAst.Expression generateOneShotInterceptor(String name) {
+  jsAst.Expression generateOneShotInterceptor(jsAst.Name name) {
     Selector selector = backend.oneShotInterceptors[name];
     Set<ClassElement> classes =
         backend.getInterceptedClassesOn(selector.name);
-    String getInterceptorName = namer.nameForGetInterceptor(classes);
+    jsAst.Name getInterceptorName = namer.nameForGetInterceptor(classes);
 
     List<String> parameterNames = <String>[];
     parameterNames.add('receiver');
@@ -304,7 +304,7 @@
       }
     }
 
-    String invocationName = backend.namer.invocationName(selector);
+    jsAst.Name invocationName = backend.namer.invocationName(selector);
     String globalObject = namer.globalObjectFor(backend.interceptorsLibrary);
 
     jsAst.Statement optimizedPath =
diff --git a/pkg/compiler/lib/src/js_emitter/js_emitter.dart b/pkg/compiler/lib/src/js_emitter/js_emitter.dart
index 3b4bfa0..89b615d 100644
--- a/pkg/compiler/lib/src/js_emitter/js_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/js_emitter.dart
@@ -5,10 +5,10 @@
 library dart2js.js_emitter;
 
 import 'dart:convert';
+import 'dart:collection' show HashMap;
 
 import '../common.dart';
 
-import '../constants/expressions.dart';
 import '../constants/values.dart';
 
 import '../closure.dart' show
@@ -28,24 +28,28 @@
     FieldElement,
     ParameterElement,
     TypeVariableElement,
-    MethodElement;
+    MethodElement,
+    MemberElement;
 
 import '../hash/sha1.dart' show Hasher;
 
-import '../helpers/helpers.dart';  // Included for debug helpers.
-
 import '../js/js.dart' as jsAst;
 import '../js/js.dart' show
     js;
 
+import 'package:js_ast/src/precedence.dart' as js_precedence;
+
 import '../js_backend/js_backend.dart' show
     CheckedModeHelper,
+    CompoundName,
     ConstantEmitter,
     CustomElementsAnalysis,
+    GetterName,
     JavaScriptBackend,
     JavaScriptConstantCompiler,
     Namer,
     RuntimeTypes,
+    SetterName,
     Substitution,
     TypeCheck,
     TypeChecks,
@@ -63,6 +67,10 @@
 import '../io/source_map_builder.dart' show
     SourceMapBuilder;
 
+import '../universe/universe.dart' show
+    TypeMaskSet,
+    TypedSelector;
+
 import '../util/characters.dart' show
     $$,
     $A,
diff --git a/pkg/compiler/lib/src/js_emitter/metadata_collector.dart b/pkg/compiler/lib/src/js_emitter/metadata_collector.dart
index b2f1351..68ec03d 100644
--- a/pkg/compiler/lib/src/js_emitter/metadata_collector.dart
+++ b/pkg/compiler/lib/src/js_emitter/metadata_collector.dart
@@ -4,27 +4,144 @@
 
 part of dart2js.js_emitter;
 
-class MetadataCollector {
+/// Represents an entry's position in one of the global metadata arrays.
+///
+/// [_rc] is used to count the number of references of the token in the
+/// ast for a program.
+/// [value] is the actual position, once they have been finalized.
+abstract class _MetadataEntry extends jsAst.DeferredNumber
+    implements Comparable {
+  jsAst.Expression get entry;
+  int get value;
+  int get _rc;
+
+  // Mark this entry as seen. On the first time this is seen, the visitor
+  // will be applied to the [entry] to also mark potential [_MetadataEntry]
+  // instances in the [entry] as seen.
+  markSeen(jsAst.BaseVisitor visitor);
+}
+
+class _BoundMetadataEntry extends _MetadataEntry {
+  int _value = -1;
+  int _rc = 0;
+  final jsAst.Expression entry;
+
+  _BoundMetadataEntry(this.entry);
+
+  bool get isFinalized => _value != -1;
+
+  finalize(int value) {
+    assert(!isFinalized);
+    _value = value;
+  }
+
+  int get value {
+    assert(isFinalized);
+    return _value;
+  }
+
+  bool get isUsed => _rc > 0;
+
+  markSeen(jsAst.BaseVisitor visitor) {
+    _rc++;
+    if (_rc == 1) entry.accept(visitor);
+  }
+
+  int compareTo(_MetadataEntry other) => other._rc - this._rc;
+}
+
+abstract class Placeholder implements jsAst.DeferredNumber {
+  bind(_MetadataEntry entry);
+}
+
+class _ForwardingMetadataEntry extends _MetadataEntry implements Placeholder {
+  _MetadataEntry _forwardTo;
+  var debug;
+
+  bool get isBound => _forwardTo != null;
+
+  _ForwardingMetadataEntry([this.debug]);
+
+  _MetadataEntry get forwardTo {
+     assert(isBound);
+     return _forwardTo;
+   }
+
+  jsAst.Expression get entry {
+    assert(isBound);
+    return forwardTo.entry;
+  }
+
+  int get value {
+    assert(isBound);
+    return forwardTo.value;
+  }
+
+  int get _rc => forwardTo._rc;
+
+  markSeen(jsAst.BaseVisitor visitor) => forwardTo.markSeen(visitor);
+
+  int compareTo(other) => forwardTo.compareTo(other);
+
+  bind(_MetadataEntry entry) {
+    assert(!isBound);
+    _forwardTo = entry;
+  }
+}
+
+class _MetadataList extends jsAst.DeferredExpression {
+  jsAst.Expression _value;
+
+  void setExpression(jsAst.Expression value) {
+    // TODO(herhut): Enable the below assertion once incremental mode is gone.
+    // assert(_value == null);
+    assert(value.precedenceLevel == this.precedenceLevel);
+    _value = value;
+  }
+
+  jsAst.Expression get value {
+    assert(_value != null);
+    return _value;
+  }
+
+  int get precedenceLevel => js_precedence.PRIMARY;
+}
+
+class MetadataCollector implements TokenFinalizer {
   final Compiler _compiler;
   final Emitter _emitter;
 
-  /// A list of JS expressions that represent metadata, parameter names and
-  /// type variable types.
-  final List<jsAst.Expression> globalMetadata = <jsAst.Expression>[];
+  /// A token for a list of expressions that represent metadata, parameter names
+  /// and type variable types.
+  final _MetadataList _globalMetadata = new _MetadataList();
+  jsAst.Expression get globalMetadata => _globalMetadata;
 
   /// A map used to canonicalize the entries of globalMetadata.
-  final Map<String, int> _globalMetadataMap = <String, int>{};
+  Map<String, _BoundMetadataEntry> _globalMetadataMap;
 
-  /// A map with lists of JS expressions, one list for each output unit. The
-  /// entries represent types including function types and typedefs.
-  final Map<OutputUnit, List<jsAst.Expression>> types =
-      <OutputUnit, List<jsAst.Expression>>{};
+  /// A map with a token for a lists of JS expressions, one token for each
+  /// output unit. Once finalized, the entries represent types including
+  /// function types and typedefs.
+  Map<OutputUnit, _MetadataList> _typesTokens =
+      new Map<OutputUnit, _MetadataList>();
+
+  jsAst.Expression getTypesForOutputUnit(OutputUnit outputUnit) {
+    return _typesTokens.putIfAbsent(outputUnit, () => new _MetadataList());
+  }
 
   /// A map used to canonicalize the entries of types.
-  final Map<OutputUnit, Map<String, int>> _typesMap =
-      <OutputUnit, Map<String, int>>{};
+  Map<OutputUnit, Map<DartType, _BoundMetadataEntry>> _typesMap =
+      <OutputUnit, Map<DartType, _BoundMetadataEntry>>{};
 
-  MetadataCollector(this._compiler, this._emitter);
+  // To support incremental compilation, we have to be able to eagerly emit
+  // metadata and add metadata later on. We use the below two counters for
+  // this.
+  int _globalMetadataCounter = 0;
+  int _globalTypesCounter = 0;
+
+  MetadataCollector(this._compiler, this._emitter) {
+    _globalMetadataMap = new Map<String, _BoundMetadataEntry>();
+  }
 
   JavaScriptBackend get _backend => _compiler.backend;
   TypeVariableHandler get _typeVariableHandler => _backend.typeVariableHandler;
@@ -64,51 +181,78 @@
     });
   }
 
-  List<int> reifyDefaultArguments(FunctionElement function) {
+  List<jsAst.DeferredNumber> reifyDefaultArguments(FunctionElement function) {
     FunctionSignature signature = function.functionSignature;
     if (signature.optionalParameterCount == 0) return const [];
-    List<int> defaultValues = <int>[];
+    List<jsAst.DeferredNumber> defaultValues = <jsAst.DeferredNumber>[];
     for (ParameterElement element in signature.optionalParameters) {
       ConstantValue constant =
           _backend.constants.getConstantValueForVariable(element);
       jsAst.Expression expression = (constant == null)
-          ? null
+          ? new jsAst.LiteralNull()
           : _emitter.constantReference(constant);
-      defaultValues.add(addGlobalMetadata(expression));
+      defaultValues.add(_addGlobalMetadata(expression));
     }
     return defaultValues;
   }
 
-  int reifyMetadata(MetadataAnnotation annotation) {
+  jsAst.Expression reifyMetadata(MetadataAnnotation annotation) {
     ConstantValue constant =
         _backend.constants.getConstantValueForMetadata(annotation);
     if (constant == null) {
       _compiler.internalError(annotation, 'Annotation value is null.');
-      return -1;
+      return null;
     }
-    return addGlobalMetadata(_emitter.constantReference(constant));
+    return _addGlobalMetadata(_emitter.constantReference(constant));
   }
 
-  int reifyType(DartType type, {bool ignoreTypeVariables: false}) {
+  jsAst.Expression reifyType(DartType type, {ignoreTypeVariables: false}) {
     return reifyTypeForOutputUnit(type,
                                   _compiler.deferredLoadTask.mainOutputUnit,
                                   ignoreTypeVariables: ignoreTypeVariables);
   }
 
-  int reifyTypeForOutputUnit(DartType type, OutputUnit outputUnit,
-                             {bool ignoreTypeVariables: false}) {
-    jsAst.Expression representation =
-        _backend.rti.getTypeRepresentation(
-            type,
-            (variable) {
-              if (ignoreTypeVariables) return new jsAst.LiteralNull();
-              return js.number(
-                  _typeVariableHandler.reifyTypeVariable(
-                      variable.element));
-            },
-            (TypedefType typedef) {
-              return _backend.isAccessibleByReflection(typedef.element);
-            });
+  jsAst.Expression reifyTypeForOutputUnit(DartType type,
+                                          OutputUnit outputUnit,
+                                          {ignoreTypeVariables: false}) {
+    return addTypeInOutputUnit(type, outputUnit,
+                               ignoreTypeVariables: ignoreTypeVariables);
+  }
+
+  jsAst.Expression reifyName(String name) {
+    return _addGlobalMetadata(js.string(name));
+  }
+
+  jsAst.Expression reifyExpression(jsAst.Expression expression) {
+    return _addGlobalMetadata(expression);
+  }
+
+  Placeholder getMetadataPlaceholder([debug]) {
+    return new _ForwardingMetadataEntry(debug);
+  }
+
+  _MetadataEntry _addGlobalMetadata(jsAst.Node node) {
+    String printed = jsAst.prettyPrint(node, _compiler).getText();
+    return _globalMetadataMap.putIfAbsent(printed, () {
+      _BoundMetadataEntry result = new _BoundMetadataEntry(node);
+      if (_compiler.hasIncrementalSupport) {
+        result.finalize(_globalMetadataCounter++);
+      }
+      return result;
+    });
+  }
+
+  jsAst.Expression _computeTypeRepresentation(DartType type,
+                                              {ignoreTypeVariables: false}) {
+    jsAst.Expression representation = _backend.rti.getTypeRepresentation(
+        type,
+        (variable) {
+          if (ignoreTypeVariables) return new jsAst.LiteralNull();
+          return _typeVariableHandler.reifyTypeVariable(variable.element);
+        },
+        (TypedefType typedef) {
+          return _backend.isAccessibleByReflection(typedef.element);
+        });
 
     if (representation is jsAst.LiteralString) {
       // We don't want the representation to be a string, since we use
@@ -117,42 +261,31 @@
           NO_LOCATION_SPANNABLE, 'reified types should not be strings.');
     }
 
-    return addTypeInOutputUnit(representation, outputUnit);
+    return representation;
+
   }
 
-  int reifyName(String name) {
-    return addGlobalMetadata(js('"$name"'));
-  }
-
-  int addGlobalMetadata(jsAst.Expression expression) {
-    // TODO(sigmund): consider adding an effient way to compare expressions
-    String string = jsAst.prettyPrint(expression, _compiler).getText();
-    return _globalMetadataMap.putIfAbsent(string, () {
-      globalMetadata.add(expression);
-      return globalMetadata.length - 1;
-    });
-  }
-
-  int addTypeInOutputUnit(jsAst.Expression type, OutputUnit outputUnit) {
-    String string = jsAst.prettyPrint(type, _compiler).getText();
+  jsAst.Expression addTypeInOutputUnit(DartType type,
+                                       OutputUnit outputUnit,
+                                       {ignoreTypeVariables: false}) {
     if (_typesMap[outputUnit] == null) {
-      _typesMap[outputUnit] = <String, int>{};
+      _typesMap[outputUnit] = new Map<DartType, _BoundMetadataEntry>();
     }
-    return _typesMap[outputUnit].putIfAbsent(string, () {
-
-      if (types[outputUnit] == null) {
-        types[outputUnit] = <jsAst.Expression>[];
+    return _typesMap[outputUnit].putIfAbsent(type, () {
+      _BoundMetadataEntry result = new _BoundMetadataEntry(
+          _computeTypeRepresentation(type,
+                                     ignoreTypeVariables: ignoreTypeVariables));
+      if (_compiler.hasIncrementalSupport) {
+        result.finalize(_globalTypesCounter++);
       }
-
-      types[outputUnit].add(type);
-      return types[outputUnit].length - 1;
+      return result;
     });
   }
 
-  List<int> computeMetadata(FunctionElement element) {
+  List<jsAst.DeferredNumber> computeMetadata(FunctionElement element) {
     return _compiler.withCurrentElement(element, () {
-      if (!_mustEmitMetadataFor(element)) return const <int>[];
-      List<int> metadata = <int>[];
+      if (!_mustEmitMetadataFor(element)) return const <jsAst.DeferredNumber>[];
+      List<jsAst.DeferredNumber> metadata = <jsAst.DeferredNumber>[];
       Link link = element.metadata;
       // TODO(ahe): Why is metadata sometimes null?
       if (link != null) {
@@ -163,4 +296,118 @@
       return metadata;
     });
   }
+
+  @override
+  void countTokensInAst(jsAst.Node ast) {
+    TokenCounter visitor = new TokenCounter();
+    visitor.countTokens(ast);
+  }
+
+  @override
+  void finalizeTokens() {
+    bool checkTokensInTypes(OutputUnit outputUnit, entries) {
+      UnBoundDebugger debugger = new UnBoundDebugger(outputUnit);
+      for (_BoundMetadataEntry entry in entries) {
+        if (!entry.isUsed) continue;
+        if (debugger.findUnboundPlaceholders(entry.entry)) {
+          return false;
+        }
+      }
+      return true;
+    }
+    void countTokensInTypes(Iterable<_BoundMetadataEntry> entries) {
+      TokenCounter counter = new TokenCounter();
+      entries.where((_BoundMetadataEntry e) => e._rc > 0)
+             .map((_BoundMetadataEntry e) => e.entry)
+             .forEach(counter.countTokens);
+    }
+
+    jsAst.ArrayInitializer finalizeMap(Map<dynamic, _BoundMetadataEntry> map) {
+      // When in incremental mode, we allocate entries eagerly.
+      if (_compiler.hasIncrementalSupport) {
+        return new jsAst.ArrayInitializer(map.values.toList());
+      }
+
+      bool isUsed(_BoundMetadataEntry entry) => entry.isUsed;
+      List<_BoundMetadataEntry> entries = map.values.where(isUsed).toList();
+      entries.sort();
+
+      // TODO(herhut): Bucket entries by index length and use a stable
+      //               distribution within buckets.
+      int count = 0;
+      for (_BoundMetadataEntry entry in entries) {
+        entry.finalize(count++);
+      }
+
+      List<jsAst.Node> values =
+          entries.map((_BoundMetadataEntry e) => e.entry).toList();
+
+       return new jsAst.ArrayInitializer(values);
+    }
+
+    _globalMetadata.setExpression(finalizeMap(_globalMetadataMap));
+
+    _typesTokens.forEach((OutputUnit outputUnit, _MetadataList token) {
+      Map typesMap = _typesMap[outputUnit];
+      if (typesMap != null) {
+        assert(checkTokensInTypes(outputUnit, typesMap.values));
+        countTokensInTypes(typesMap.values);
+        token.setExpression(finalizeMap(typesMap));
+      } else {
+        token.setExpression(new jsAst.ArrayInitializer([]));
+      }
+    });
+  }
 }
+
+/// Interface for ast nodes that encapsulate an ast that needs to be
+/// traversed when counting tokens.
+///
+/// TODO(herhut): Find a shared place once namer also uses tokens.
+abstract class AstContainer implements jsAst.Node {
+  jsAst.Node get ast;
+}
+
+abstract class TokenFinalizer {
+  void countTokensInAst(jsAst.Node ast);
+  void finalizeTokens();
+}
+
+class TokenCounter extends jsAst.BaseVisitor {
+  @override
+  visitNode(jsAst.Node node) {
+    if (node is AstContainer) {
+      node.ast.accept(this);
+    } else {
+      super.visitNode(node);
+    }
+  }
+
+  @override
+  visitDeferredNumber(jsAst.DeferredNumber token) {
+    if (token is _MetadataEntry) {
+      token.markSeen(this);
+    }
+  }
+
+  void countTokens(jsAst.Node node) => node.accept(this);
+}
+
+class UnBoundDebugger extends jsAst.BaseVisitor {
+  OutputUnit outputUnit;
+  bool _foundUnboundToken = false;
+
+  UnBoundDebugger(this.outputUnit);
+
+  @override
+  visitDeferredNumber(jsAst.DeferredNumber token) {
+    if (token is _ForwardingMetadataEntry && !token.isBound) {
+      _foundUnboundToken = true;
+    }
+  }
+
+  bool findUnboundPlaceholders(jsAst.Node node) {
+    node.accept(this);
+    return _foundUnboundToken;
+  }
+}
\ No newline at end of file
diff --git a/pkg/compiler/lib/src/js_emitter/model.dart b/pkg/compiler/lib/src/js_emitter/model.dart
index 69eb6ae..8dec194 100644
--- a/pkg/compiler/lib/src/js_emitter/model.dart
+++ b/pkg/compiler/lib/src/js_emitter/model.dart
@@ -4,12 +4,12 @@
 
 library dart2js.new_js_emitter.model;
 
-import '../js/js.dart' as js show Expression, Statement;
+import '../js/js.dart' as js show Expression, Statement, Name, Literal;
 import '../constants/values.dart' show ConstantValue;
 
 import '../deferred_load.dart' show OutputUnit;
 
-import 'js_emitter.dart' show MetadataCollector;
+import 'js_emitter.dart' show MetadataCollector, TokenFinalizer;
 
 import '../common.dart';
 
@@ -29,6 +29,7 @@
   // TODO(floitsch): we should store the metadata directly instead of storing
   // the collector. However, the old emitter still updates the data.
   final MetadataCollector _metadataCollector;
+  TokenFinalizer get metadataFinalizer => _metadataCollector;
 
   Program(this.fragments,
           this.holders,
@@ -53,21 +54,20 @@
   /// list must not be emitted before all operations on it are done. For
   /// example, the old emitter generates metadata when emitting reflection
   /// data.
-  List<js.Expression> get metadata => _metadataCollector.globalMetadata;
+  js.Expression get metadata => _metadataCollector.globalMetadata;
 
-  /// A map with lists of type expressions.
+  /// Accessor for the list of metadata entries for a given [OutputUnit].
   ///
   /// There is one list for each output unit. The list belonging to the main
   /// unit must be emitted in the `TYPES` 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.
-  Map<OutputUnit, List<js.Expression>> get metadataTypes
-      => _metadataCollector.types;
-
+  /// list is only a placeholder and will be filled in once metadata collection
+  /// is finalized.
+  js.Expression metadataTypesForOutputUnit(OutputUnit unit) {
+    return _metadataCollector.getTypesForOutputUnit(unit);
+  }
 
   bool get isSplit => fragments.length > 1;
   Iterable<Fragment> get deferredFragments => fragments.skip(1);
@@ -165,7 +165,7 @@
 }
 
 class Constant {
-  final String name;
+  final js.Name name;
   final Holder holder;
   final ConstantValue value;
 
@@ -196,7 +196,7 @@
   /// Uses indicate missing information in the model.
   final Element element;
 
-  final String name;
+  js.Name name;
   // TODO(floitsch): the holder for static fields is the isolate object. We
   // could remove this field and use the isolate object directly.
   final Holder holder;
@@ -214,7 +214,7 @@
   /// Uses indicate missing information in the model.
   final Element element;
 
-  final String name;
+  final js.Name name;
   final Holder holder;
   Class _superclass;
   final List<Method> methods;
@@ -236,13 +236,13 @@
 
   // If the class implements a function type, and the type is encoded in the
   // metatada table, then this field contains the index into that field.
-  final int functionTypeIndex;
+  final js.Expression functionTypeIndex;
 
   /// Whether the class must be evaluated eagerly.
   bool isEager = false;
 
   /// Data that must be emitted with the class for native interop.
-  String nativeInfo;
+  js.Literal nativeInfo;
 
   Class(this.element, this.name, this.holder,
         this.methods,
@@ -268,8 +268,9 @@
     _superclass = superclass;
   }
 
-  String get superclassName
-      => (superclass == null) ? "" : superclass.name;
+  js.Name get superclassName
+      => superclass == null ? null : superclass.name;
+
   int get superclassHolderIndex
       => (superclass == null) ? 0 : superclass.holder.index;
 }
@@ -277,13 +278,13 @@
 class MixinApplication extends Class {
   Class _mixinClass;
 
-  MixinApplication(Element element, String name, Holder holder,
+  MixinApplication(Element element, js.Name name, Holder holder,
                    List<Field> instanceFields,
                    List<Field> staticFieldsForReflection,
                    List<StubMethod> callStubs,
                    List<StubMethod> typeVariableReaderStubs,
                    List<StubMethod> isChecks,
-                   int functionTypeIndex,
+                   js.Expression functionTypeIndex,
                    {bool onlyForRti,
                     bool isDirectlyInstantiated})
       : super(element,
@@ -316,8 +317,8 @@
   /// Uses indicate missing information in the model.
   final Element element;
 
-  final String name;
-  final String accessorName;
+  final js.Name name;
+  final js.Name accessorName;
 
   /// 00: Does not need any getter.
   /// 01:  function() { return this.field; }
@@ -349,7 +350,7 @@
   /// 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.Name name;
   final js.Expression code;
 
   Method(this.element, this.name, this.code);
@@ -358,7 +359,7 @@
 /// A method that corresponds to a method in the original Dart program.
 class DartMethod extends Method {
   final bool needsTearOff;
-  final String tearOffName;
+  final js.Name tearOffName;
   final List<ParameterStubMethod> parameterStubs;
   final bool canBeApplied;
   final bool canBeReflected;
@@ -378,9 +379,9 @@
   // 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;
+  final js.Name callName;
 
-  DartMethod(Element element, String name, js.Expression code,
+  DartMethod(Element element, js.Name name, js.Expression code,
              this.parameterStubs, this.callName,
              {this.needsTearOff, this.tearOffName, this.canBeApplied,
               this.canBeReflected, this.requiredParameterCount,
@@ -401,15 +402,15 @@
   /// 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 js.Name aliasName;
   final bool isClosure;
 
 
-  InstanceMethod(Element element, String name, js.Expression code,
+  InstanceMethod(Element element, js.Name name, js.Expression code,
                  List<ParameterStubMethod> parameterStubs,
-                 String callName,
+                 js.Name callName,
                  {bool needsTearOff,
-                  String tearOffName,
+                  js.Name tearOffName,
                   this.aliasName,
                   bool canBeApplied,
                   bool canBeReflected,
@@ -433,7 +434,7 @@
 /// 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,
+  StubMethod(js.Name name, js.Expression code,
              {Element element})
       : super(element, name, code);
 }
@@ -453,9 +454,9 @@
   /// name when it is used this way.
   ///
   /// If a stub's member can not be torn off, the [callName] is `null`.
-  String callName;
+  js.Name callName;
 
-  ParameterStubMethod(String name, this.callName, js.Expression code)
+  ParameterStubMethod(js.Name name, this.callName, js.Expression code)
       : super(name, code);
 }
 
@@ -466,11 +467,12 @@
 class StaticDartMethod extends DartMethod implements StaticMethod {
   final Holder holder;
 
-  StaticDartMethod(Element element, String name, this.holder,
+  StaticDartMethod(Element element, js.Name name, this.holder,
                    js.Expression code, List<ParameterStubMethod> parameterStubs,
-                   String callName,
-                   {bool needsTearOff, String tearOffName, bool canBeApplied,
-                    bool canBeReflected, int requiredParameterCount,
+                   js.Name callName,
+                   {bool needsTearOff, js.Name tearOffName,
+                    bool canBeApplied, bool canBeReflected,
+                    int requiredParameterCount,
                     /* List | Map */ optionalParameterDefaultValues,
                     js.Expression functionType})
       : super(element, name, code, parameterStubs, callName,
@@ -485,6 +487,6 @@
 
 class StaticStubMethod extends StubMethod implements StaticMethod {
   Holder holder;
-  StaticStubMethod(String name, this.holder, js.Expression code)
+  StaticStubMethod(js.Name 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 d6d39be..3e7b649 100644
--- a/pkg/compiler/lib/src/js_emitter/native_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/native_emitter.dart
@@ -194,15 +194,19 @@
         if (nonleafStr != '') {
           sb..write(';')..write(nonleafStr);
         }
-        if (extensions != null) {
-          sb..write(';')
-            ..writeAll(extensions.map((Class cls) => cls.name), '|');
-        }
+
         String encoding = sb.toString();
 
-        if (cls.isNative || encoding != '') {
+        if (cls.isNative || encoding != '' || extensions != null) {
+          List<jsAst.Literal> parts = <jsAst.Literal>[js.stringPart(encoding)];
+          if (extensions != null) {
+            parts..add(js.stringPart(';'))
+                 ..addAll(
+                     js.joinLiterals(extensions.map((Class cls) => cls.name),
+                                     js.stringPart('|')));
+          }
           assert(cls.nativeInfo == null);
-          cls.nativeInfo = encoding;
+          cls.nativeInfo = js.concatenateStrings(parts, addQuotes: true);
         }
       }
       generateClassInfo(jsInterceptorClass);
@@ -301,7 +305,7 @@
   List<jsAst.Statement> generateParameterStubStatements(
       FunctionElement member,
       bool isInterceptedMethod,
-      String invocationName,
+      jsAst.Name invocationName,
       List<jsAst.Parameter> stubParameters,
       List<jsAst.Expression> argumentsBuffer,
       int indexOfLastOptionalArgumentInParameters) {
@@ -343,22 +347,7 @@
     return statements;
   }
 
-  bool isSupertypeOfNativeClass(Element element) {
-    if (element.isTypeVariable) {
-      compiler.internalError(element, "Is check for type variable.");
-      return false;
-    }
-    if (element.computeType(compiler).unalias(compiler) is FunctionType) {
-      // The element type is a function type either directly or through
-      // typedef(s).
-      return false;
-    }
-
-    if (!element.isClass) {
-      compiler.internalError(element, "Is check does not handle element.");
-      return false;
-    }
-
+  bool isSupertypeOfNativeClass(ClassElement element) {
     if (backend.classesMixedIntoInterceptedClasses.contains(element)) {
       return 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 1cea1f3..d3425bf 100644
--- a/pkg/compiler/lib/src/js_emitter/new_emitter/emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/new_emitter/emitter.dart
@@ -76,10 +76,9 @@
   }
 
   js.PropertyAccess _globalPropertyAccess(Element element) {
-    String name = namer.globalPropertyName(element);
-    js.PropertyAccess pa = new js.PropertyAccess.field(
-        new js.VariableUse(namer.globalObjectFor(element)),
-        name);
+    js.Name name = namer.globalPropertyName(element);
+    js.PropertyAccess pa = new js.PropertyAccess(
+        new js.VariableUse(namer.globalObjectFor(element)), name);
     return pa;
   }
 
@@ -163,23 +162,8 @@
         String isPrefix = namer.operatorIsPrefix;
         return js.js.expressionTemplateFor("('$isPrefix' + #) in #.prototype");
 
-      case JsBuiltin.isFunctionTypeRti:
-        String functionClassName =
-            _backend.namer.runtimeTypeName(_compiler.functionClass);
-        return js.js.expressionTemplateFor(
-            '#.$typeNameProperty === "$functionClassName"');
-
-      case JsBuiltin.isNullTypeRti:
-        String nullClassName =
-            _backend.namer.runtimeTypeName(_compiler.nullClass);
-        return js.js.expressionTemplateFor(
-            '#.$typeNameProperty === "$nullClassName"');
-
-      case JsBuiltin.isDartObjectTypeRti:
-        String dartObjectClassName =
-            _backend.namer.runtimeTypeName(_compiler.objectClass);
-        return js.js.expressionTemplateFor(
-            '#.$typeNameProperty === "$dartObjectClassName"');
+      case JsBuiltin.isGivenTypeRti:
+        return js.js.expressionTemplateFor('#.$typeNameProperty === #');
 
       case JsBuiltin.getMetadata:
         return _emitter.templateForReadMetadata;
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 912fa4b..8ccd680 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
@@ -6,7 +6,6 @@
 
 import '../../constants/values.dart' show ConstantValue, FunctionConstantValue;
 import '../../dart2jslib.dart' show Compiler;
-import '../../dart_types.dart' show DartType;
 import '../../elements/elements.dart' show ClassElement, FunctionElement;
 import '../../js/js.dart' as js;
 import '../../js_backend/js_backend.dart' show
@@ -14,8 +13,7 @@
     Namer,
     ConstantEmitter;
 
-import '../js_emitter.dart' show
-    NativeEmitter;
+import '../js_emitter.dart' show AstContainer, NativeEmitter;
 
 import 'package:_internal/compiler/js_lib/shared/embedded_names.dart' show
     CREATE_NEW_ISOLATE,
@@ -35,6 +33,46 @@
 import '../js_emitter.dart' show NativeGenerator, buildTearOffCode;
 import '../model.dart';
 
+/// Represents the LiteralString resulting from unparsing [expression]. The
+/// actual unparsing is done on demand when requesting the [value] of this
+/// node.
+class _UnparsedNode extends js.DeferredString
+                    implements AstContainer {
+  @override
+  final js.Node ast;
+  final Compiler _compiler;
+  final bool _protectForEval;
+  js.LiteralString _cachedLiteral;
+
+  /// A [js.Literal] that represents the string result of unparsing [ast].
+  ///
+  /// When its string [value] is requested, the node pretty-prints the given
+  /// [ast] and, if [protectForEval] is true, wraps the resulting
+  /// string in parenthesis. The result is also escaped.
+  _UnparsedNode(this.ast, this._compiler, this._protectForEval);
+
+  js.LiteralString get _literal {
+    if (_cachedLiteral == null) {
+      String text = js.prettyPrint(ast, _compiler).getText();
+      if (_protectForEval) {
+        if (ast is js.Fun) text = '($text)';
+        if (ast is js.LiteralExpression) {
+          js.LiteralExpression literalExpression = ast;
+          String template = literalExpression.template;
+          if (template.startsWith("function ") ||
+              template.startsWith("{")) {
+            text = '($text)';
+          }
+        }
+      }
+      _cachedLiteral = js.js.escapedString(text);
+    }
+    return _cachedLiteral;
+  }
+
+  @override
+  String get value => _literal.value;
+}
 
 class ModelEmitter {
   final Compiler compiler;
@@ -55,14 +93,15 @@
   ModelEmitter(Compiler compiler, Namer namer, this.nativeEmitter)
       : this.compiler = compiler,
         this.namer = namer {
-    // TODO(floitsch): remove hard-coded name.
-    // TODO(floitsch): there is no harm in caching the template.
-    js.Template makeConstantListTemplate =
-        js.js.uncachedExpressionTemplate('makeConstList(#)');
 
     this.constantEmitter = new ConstantEmitter(
         compiler, namer, this.generateConstantReference,
-        makeConstantListTemplate);
+        constantListGenerator);
+  }
+
+  js.Expression constantListGenerator(js.Expression array) {
+    // TODO(floitsch): remove hard-coded name.
+    return js.js('makeConstList(#)', [array]);
   }
 
   js.Expression generateEmbeddedGlobalAccess(String global) {
@@ -137,19 +176,27 @@
     // We have to emit the deferred fragments first, since we need their
     // deferred hash (which depends on the output) when emitting the main
     // fragment.
-    fragments.skip(1).forEach((DeferredFragment deferredUnit) {
-      List<js.Expression> types =
-          program.metadataTypes[deferredUnit.outputUnit];
-      js.Expression ast = emitDeferredFragment(types, deferredUnit,
-                                               program.holders);
-      String code = js.prettyPrint(ast, compiler).getText();
-      totalSize += code.length;
-      compiler.outputProvider(deferredUnit.outputFileName, deferredExtension)
-          ..add(code)
-          ..close();
-    });
+    List<js.Expression> fragmentsCode = fragments.skip(1).map(
+            (DeferredFragment deferredUnit) {
+      js.Expression types =
+          program.metadataTypesForOutputUnit(deferredUnit.outputUnit);
+      return emitDeferredFragment(types, deferredUnit, program.holders);
+    }).toList();
 
     js.Statement mainAst = emitMainFragment(program);
+
+    fragmentsCode.forEach(program.metadataFinalizer.countTokensInAst);
+    program.metadataFinalizer.countTokensInAst(mainAst);
+    program.metadataFinalizer.finalizeTokens();
+
+    for (int i = 0; i < fragmentsCode.length; ++i) {
+      String code = js.prettyPrint(fragmentsCode[i], compiler).getText();
+      totalSize += code.length;
+      compiler.outputProvider(fragments[i+1].outputFileName, deferredExtension)
+        ..add(code)
+        ..close();
+    }
+
     String mainCode = js.prettyPrint(mainAst, compiler).getText();
     compiler.outputProvider(mainFragment.outputFileName, 'js')
         ..add(buildGeneratedBy(compiler))
@@ -160,23 +207,17 @@
     return totalSize;
   }
 
-  /// Unparses the given [value].
+  /// Returns a [js.Literal] that represents the string result of unparsing
+  /// [value].
   ///
-  /// Pretty-prints the given [value] and, if [protectForEval] is
-  /// true, wraps the resulting string in parenthesis. The result is escaped
-  /// and returned.
-  js.LiteralString unparse(Compiler compiler, js.Node value,
-                           {bool protectForEval: true}) {
-    String text = js.prettyPrint(value, compiler).getText();
-    if (protectForEval) {
-      if (value is js.Fun) text = '($text)';
-      if (value is js.LiteralExpression &&
-      (value.template.startsWith("function ") ||
-      value.template.startsWith("{"))) {
-        text = '($text)';
-      }
-    }
-    return js.js.escapedString(text);
+  /// The returned node will, when its string value is requested, pretty-print
+  /// the given [value] and, if [protectForEval] is true, wrap the resulting
+  /// string in parenthesis. The result is also escaped.
+  ///
+  /// See [_UnparsedNode] for details.
+  js.Literal unparse(Compiler compiler, js.Node value,
+                     {bool protectForEval: true}) {
+    return new _UnparsedNode(value, compiler, protectForEval);
   }
 
   String buildGeneratedBy(compiler) {
@@ -192,7 +233,6 @@
         emitLazilyInitializedStatics(fragment.staticLazilyInitializedFields));
     elements.add(emitConstants(fragment.constants));
 
-
     js.Expression code = new js.ArrayInitializer(elements);
 
     Map<String, dynamic> holes =
@@ -345,7 +385,7 @@
          compiler.stringClass, compiler.boolClass, compiler.nullClass,
          compiler.listClass];
     nativeClassesNeedingUnmangledName.forEach((element) {
-        names.add(new js.Property(js.string(namer.className(element)),
+        names.add(new js.Property(js.quoteName(namer.className(element)),
                                   js.string(element.name)));
     });
 
@@ -479,34 +519,21 @@
   }
 
   List<js.Property> emitMetadata(Program program) {
-    // Unparses all given js-expressions (suitable for `expressionCompile`) and
-    // returns the result in a js-array.
-    // If the given [expressions] is null returns the empty js-array.
-    js.ArrayInitializer unparseExpressions(List<js.Expression> expressions) {
-      if (expressions == null) expressions = <js.Expression>[];
-      List<js.LiteralString> unparsedExpressions = expressions
-          .map((expr) => unparse(compiler, expr, protectForEval: false))
-          .toList();
-      return new js.ArrayInitializer(unparsedExpressions);
-    }
-
     List<js.Property> metadataGlobals = <js.Property>[];
 
-    js.ArrayInitializer unparsedMetadata = unparseExpressions(program.metadata);
-    metadataGlobals.add(new js.Property(js.string(lazyMetadataName),
-                                        unparsedMetadata));
-    metadataGlobals.add(new js.Property(js.string(METADATA),
-                                        new js.ArrayInitializer([])));
+    js.Property createGlobal(js.Expression metadata, String global) {
+      return new js.Property(js.string(global), metadata);
+    }
 
-    List<js.Expression> types =
-        program.metadataTypes[program.fragments.first.outputUnit];
-    metadataGlobals.add(new js.Property(js.string(TYPES),
-                                        unparseExpressions(types)));
+    metadataGlobals.add(createGlobal(program.metadata, METADATA));
+    js.Expression types =
+        program.metadataTypesForOutputUnit(program.mainFragment.outputUnit);
+    metadataGlobals.add(createGlobal(types, TYPES));
 
     return metadataGlobals;
   }
 
-  js.Expression emitDeferredFragment(List<js.Expression> types,
+  js.Expression emitDeferredFragment(js.Expression deferredTypes,
                                      DeferredFragment fragment,
                                      List<Holder> holders) {
     // TODO(floitsch): initialize eager classes.
@@ -529,11 +556,7 @@
         emitEagerClassInitializations(fragment.libraries)]);
 
 
-    js.LiteralString immediateString = unparse(compiler, immediateCode);
-
-    js.Expression deferredTypes = (types == null)
-        ? js.string("[]")
-        : unparse(compiler, new js.ArrayInitializer(types));
+    js.Literal immediateString = unparse(compiler, immediateCode);
 
     js.ArrayInitializer hunk =
         new js.ArrayInitializer([deferredArray, immediateString,
@@ -557,7 +580,7 @@
       data.addAll(constants.expand((Constant constant) {
         assert(constant.holder.index == holderIndex);
         js.Expression code = constantEmitter.generate(constant.value);
-        return [js.string(constant.name), unparse(compiler, code)];
+        return [js.quoteName(constant.name), unparse(compiler, code)];
       }));
     }
     return new js.ArrayInitializer(data);
@@ -573,8 +596,8 @@
 
   js.Expression emitLazilyInitializedStatics(List<StaticField> fields) {
     Iterable fieldDescriptors = fields.expand((field) =>
-        [ js.string(field.name),
-          js.string("${namer.getterPrefix}${field.name}"),
+        [ js.quoteName(field.name),
+          js.quoteName(namer.deriveLazyInitializerName(field.name)),
           js.number(field.holder.index),
           emitLazyInitializer(field) ]);
     return new js.ArrayInitializer(fieldDescriptors.toList(growable: false));
@@ -604,13 +627,13 @@
     Iterable staticDescriptors = library.statics.expand(emitStaticMethod);
 
     Iterable classDescriptors = library.classes.expand((Class cls) {
-      js.LiteralString name = js.string(cls.name);
+      js.Literal name = js.quoteName(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];
+        return [name, emittedClass, cls.nativeInfo, holderIndex];
       }
     });
 
@@ -623,21 +646,20 @@
   }
 
   js.Expression _generateConstructor(Class cls) {
-    List<String> fieldNames = <String>[];
+    List<js.Name> fieldNames = const <js.Name>[];
 
     // If the class is not directly instantiated we only need it for inheritance
     // or RTI. In either case we don't need its fields.
     if (cls.isDirectlyInstantiated && !cls.isNative) {
       fieldNames = cls.fields.map((Field field) => field.name).toList();
     }
-    String name = cls.name;
-    String parameters = fieldNames.join(', ');
-    String assignments = fieldNames
-        .map((String field) => "this.$field = $field;\n")
-        .join();
-    String code = 'function $name($parameters) { $assignments }';
-    js.Template template = js.js.uncachedExpressionTemplate(code);
-    return template.instantiate(const []);
+    js.Name name = cls.name;
+
+    Iterable<js.Name> assignments = fieldNames.map((js.Name field) {
+        return js.js("this.#field = #field", {"field": field});
+      });
+
+    return js.js('function #(#) { # }', [name, fieldNames, assignments]);
   }
 
   Method _generateGetter(Field field) {
@@ -650,9 +672,9 @@
       return null;
     }
 
-    js.Expression fieldName = js.string(field.name);
+    js.Expression fieldName = js.quoteName(field.name);
     js.Expression code = js.js(getterTemplateFor(field.getterFlags), fieldName);
-    String getterName = "${namer.getterPrefix}${field.accessorName}";
+    js.Name getterName = namer.deriveGetterName(field.accessorName);
     return new StubMethod(getterName, code);
   }
 
@@ -665,9 +687,9 @@
       }
       return null;
     }
-    js.Expression fieldName = js.string(field.name);
+    js.Expression fieldName = js.quoteName(field.name);
     js.Expression code = js.js(setterTemplateFor(field.setterFlags), fieldName);
-    String setterName = "${namer.setterPrefix}${field.accessorName}";
+    js.Name setterName = namer.deriveSetterName(field.accessorName);
     return new StubMethod(setterName, code);
   }
 
@@ -691,12 +713,12 @@
       "reference.";
 
   js.Expression emitClass(Class cls) {
-    List elements = [js.string(cls.superclassName),
+    List elements = [js.quoteName(cls.superclassName, allowNull: true),
                      js.number(cls.superclassHolderIndex)];
 
     if (cls.isMixinApplication) {
       MixinApplication mixin = cls;
-      elements.add(js.string(mixin.mixinClass.name));
+      elements.add(js.quoteName(mixin.mixinClass.name));
       elements.add(js.number(mixin.mixinClass.holder.index));
       if (cls.isDirectlyInstantiated) {
         elements.add(_generateConstructor(cls));
@@ -825,14 +847,14 @@
   Iterable<js.Expression> emitInstanceMethod(Method method) {
 
     List<js.Expression> makeNameCodePair(Method method) {
-      return [js.string(method.name), method.code];
+      return [js.quoteName(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];
+          : js.quoteName(stub.callName);
+      return [js.quoteName(stub.name), callName, stub.code];
     }
 
     if (method is InstanceMethod) {
@@ -843,15 +865,15 @@
         // functionType, stub1_name, stub1_callName, stub1_code, ...]
         var data = [];
         if (method.aliasName != null) {
-          data.add(js.string(method.aliasName));
+          data.add(js.quoteName(method.aliasName));
         }
         data.add(method.code);
-        data.add(js.string(method.callName));
+        data.add(js.quoteName(method.callName, allowNull: true));
 
         if (method.needsTearOff) {
           bool isIntercepted = backend.isInterceptedMethod(method.element);
           data.add(new js.LiteralBool(isIntercepted));
-          data.add(js.string(method.tearOffName));
+          data.add(js.quoteName(method.tearOffName));
           data.add((method.functionType));
         }
 
@@ -860,7 +882,7 @@
           data.add(js.number(method.requiredParameterCount));
           data.add(_encodeOptionalParameterDefaultValues(method));
         }
-        return [js.string(method.name), new js.ArrayInitializer(data)];
+        return [js.quoteName(method.name), new js.ArrayInitializer(data)];
       } else {
         // TODO(floitsch): not the most efficient way...
         return ([method]..addAll(method.parameterStubs))
@@ -877,7 +899,7 @@
 
     void _addMethod(Method method) {
       js.Expression unparsed = unparse(compiler, method.code);
-      output.add(js.string(method.name));
+      output.add(js.quoteName(method.name));
       output.add(holderIndex);
       output.add(unparsed);
     }
@@ -885,8 +907,8 @@
     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)];
+          : js.quoteName(stub.callName);
+      return [js.quoteName(stub.name), callName, unparse(compiler, stub.code)];
     }
 
     _addMethod(method);
@@ -899,15 +921,15 @@
         // [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(js.quoteName(method.callName));
+        data.add(js.quoteName(method.tearOffName));
         data.add(method.functionType);
         data.addAll(method.parameterStubs.expand(makeNameCallNameCodeTriplet));
         if (method.canBeApplied) {
           data.add(js.number(method.requiredParameterCount));
           data.add(_encodeOptionalParameterDefaultValues(method));
         }
-        return [js.string(method.name), holderIndex,
+        return [js.quoteName(method.name), holderIndex,
                 new js.ArrayInitializer(data)];
       } else {
         method.parameterStubs.forEach(_addMethod);
@@ -923,7 +945,7 @@
 // Declare deferred-initializer global.
 #deferredInitializer;
 
-!function(start, program) {
+(function(start, program) {
   // Initialize holder objects.
   #holders;
   var nativeInfos = Object.create(null);
@@ -1257,7 +1279,7 @@
 
   #invokeMain;  // Start main.
 
-}(Date.now(), #code)
+})(Date.now(), #code)
 }""";
 
 }
diff --git a/pkg/compiler/lib/src/js_emitter/old_emitter/class_builder.dart b/pkg/compiler/lib/src/js_emitter/old_emitter/class_builder.dart
index 3be27cf..4d69d92 100644
--- a/pkg/compiler/lib/src/js_emitter/old_emitter/class_builder.dart
+++ b/pkg/compiler/lib/src/js_emitter/old_emitter/class_builder.dart
@@ -9,24 +9,37 @@
  */
 class ClassBuilder {
   final List<jsAst.Property> properties = <jsAst.Property>[];
-  final List<String> fields = <String>[];
+  final List<jsAst.Literal> fields = <jsAst.Literal>[];
 
-  String superName;
-  String functionType;
+  jsAst.Name superName;
+  jsAst.Node functionType;
   List<jsAst.Node> fieldMetadata;
 
   final Element element;
   final Namer namer;
+  final bool isForActualClass;
 
-  ClassBuilder(this.element, this.namer);
+  ClassBuilder(this.element, this.namer, this.isForActualClass);
 
-  jsAst.Property addProperty(String name, jsAst.Expression value) {
+  ClassBuilder.forClass(ClassElement cls, this.namer)
+      : isForActualClass = true,
+        element = cls;
+
+  ClassBuilder.forStatics(this.element, this.namer) : isForActualClass = false;
+
+  jsAst.Property addProperty(jsAst.Literal name, jsAst.Expression value) {
+    jsAst.Property property = new jsAst.Property(js.quoteName(name), value);
+    properties.add(property);
+    return property;
+  }
+
+  jsAst.Property addPropertyByName(String name, jsAst.Expression value) {
     jsAst.Property property = new jsAst.Property(js.string(name), value);
     properties.add(property);
     return property;
   }
 
-  void addField(String field) {
+  void addField(jsAst.Literal field) {
     fields.add(field);
   }
 
@@ -41,18 +54,21 @@
 
   jsAst.ObjectInitializer toObjectInitializer(
       {bool emitClassDescriptor: true}) {
-    StringBuffer buffer = new StringBuffer();
-    if (superName != null) {
-      buffer.write(superName);
-      if (functionType != null) {
-        // See [functionTypeEncodingDescription] above.
-        buffer.write(':$functionType');
+    List<jsAst.Literal> parts = <jsAst.Literal>[];
+    if (isForActualClass) {
+      if (superName != null) {
+        parts.add(superName);
+        if (functionType != null) {
+          // See [functionTypeEncodingDescription] above.
+          parts.add(js.stringPart(':'));
+          parts.add(functionType);
+        }
       }
-      buffer.write(';');
+      parts.add(js.stringPart(';'));
     }
     // See [fieldEncodingDescription] above.
-    buffer.writeAll(fields, ',');
-    var classData = js.string('$buffer');
+    parts.addAll(js.joinLiterals(fields, js.stringPart(',')));
+    var classData = js.concatenateStrings(parts, addQuotes: true);
     if (fieldMetadata != null) {
       // If we need to store fieldMetadata, classData is turned into an array,
       // and the field metadata is appended. So if classData is just a string,
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 dc1f7da..a4417c1 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
@@ -20,19 +20,20 @@
     emitter.needsClassSupport = true;
 
     ClassElement superclass = classElement.superclass;
-    String superName = "";
+    jsAst.Name superName;
     if (superclass != null) {
       superName = namer.className(superclass);
     }
 
     if (cls.isMixinApplication) {
       MixinApplication mixinApplication = cls;
-      String mixinName = mixinApplication.mixinClass.name;
-      superName = '$superName+$mixinName';
+      jsAst.Name mixinName = mixinApplication.mixinClass.name;
+      superName =
+          new CompoundName([superName, Namer.literalPlus, mixinName]);
       emitter.needsMixinSupport = true;
     }
 
-    ClassBuilder builder = new ClassBuilder(classElement, namer);
+    ClassBuilder builder = new ClassBuilder.forClass(classElement, namer);
     builder.superName = superName;
     emitConstructorsForCSP(cls);
     emitFields(cls, builder);
@@ -48,7 +49,7 @@
       // We add a special getter here to allow for tearing off a closure from
       // itself.
       jsAst.Fun function = js('function() { return this; }');
-      String name = namer.getterForMember(Selector.CALL_NAME);
+      jsAst.Name name = namer.getterForMember(Selector.CALL_NAME);
       builder.addProperty(name, function);
     }
 
@@ -72,7 +73,7 @@
     jsAst.Expression constructorAst =
         _stubGenerator.generateClassConstructor(classElement, fieldNames);
 
-    String constructorName = namer.className(classElement);
+    jsAst.Name constructorName = namer.className(classElement);
     OutputUnit outputUnit =
         compiler.deferredLoadTask.outputUnitForElement(classElement);
     emitter.assemblePrecompiledConstructor(
@@ -105,8 +106,8 @@
 
     for (Field field in fields) {
       FieldElement fieldElement = field.element;
-      String name = field.name;
-      String accessorName = field.accessorName;
+      jsAst.Name name = field.name;
+      jsAst.Name accessorName = field.accessorName;
       bool needsGetter = field.needsGetter;
       bool needsSetter = field.needsUncheckedSetter;
 
@@ -128,19 +129,19 @@
         fieldMetadata.add(metadata);
         recordMangledField(fieldElement, accessorName,
             namer.privateName(fieldElement.memberName));
-        String fieldName = name;
-        String fieldCode = '';
-        String reflectionMarker = '';
+        List<jsAst.Literal> fieldNameParts = <jsAst.Literal>[];
         if (!needsAccessor) {
           // Emit field for constructor generation.
           assert(!classIsNative);
+          fieldNameParts.add(name);
         } else {
           // Emit (possibly renaming) field name so we can add accessors at
           // runtime.
           if (name != accessorName) {
-            fieldName = '$accessorName:$name';
+            fieldNameParts.add(accessorName);
+            fieldNameParts.add(js.stringPart(':'));
           }
-
+          fieldNameParts.add(name);
           if (field.needsInterceptedGetter) {
             emitter.interceptorEmitter.interceptorInvocationNames.add(
                 namer.getterForElement(fieldElement));
@@ -157,19 +158,27 @@
           if (code == 0) {
             compiler.internalError(fieldElement,
                 'Field code is 0 ($fieldElement).');
-          } else {
-            fieldCode = FIELD_CODE_CHARACTERS[code - FIRST_FIELD_CODE];
+          }
+          fieldNameParts.add(
+              js.stringPart(FIELD_CODE_CHARACTERS[code - FIRST_FIELD_CODE]));
+        }
+        // Fields can only be reflected if their declaring class is reflectable
+        // (as they are only accessible via [ClassMirror.declarations]).
+        // However, set/get operations can be performed on them, so they are
+        // reflectable in some sense, which leads to [isAccessibleByReflection]
+        // reporting `true`.
+        if (backend.isAccessibleByReflection(fieldElement)) {
+          fieldNameParts.add(new jsAst.LiteralString('-'));
+          if (fieldElement.isTopLevel ||
+              backend.isAccessibleByReflection(fieldElement.enclosingClass)) {
+            DartType type = fieldElement.type;
+            fieldNameParts.add(task.metadataCollector.reifyType(type));
           }
         }
-        if (backend.isAccessibleByReflection(fieldElement)) {
-          DartType type = fieldElement.type;
-          reflectionMarker = '-${task.metadataCollector.reifyType(type)}';
-        }
-        String builtFieldname = '$fieldName$fieldCode$reflectionMarker';
-        builder.addField(builtFieldname);
+        jsAst.Literal fieldNameAst = js.concatenateStrings(fieldNameParts);
+        builder.addField(fieldNameAst);
         // Add 1 because adding a field to the class also requires a comma
-        compiler.dumpInfoTask.recordFieldNameSize(fieldElement,
-            builtFieldname.length + 1);
+        compiler.dumpInfoTask.registerElementAst(fieldElement, fieldNameAst);
         fieldsAdded = true;
       }
     }
@@ -257,7 +266,7 @@
   void emitRuntimeTypeInformation(Class cls, ClassBuilder builder) {
     assert(builder.functionType == null);
     if (cls.functionTypeIndex != null) {
-      builder.functionType = '${cls.functionTypeIndex}';
+      builder.functionType = cls.functionTypeIndex;
     }
 
     for (Method method in cls.isChecks) {
@@ -267,7 +276,7 @@
 
   void emitNativeInfo(Class cls, ClassBuilder builder) {
     if (cls.nativeInfo != null) {
-      builder.addProperty(namer.nativeSpecProperty, js.string(cls.nativeInfo));
+      builder.addPropertyByName(namer.nativeSpecProperty, cls.nativeInfo);
     }
   }
 
@@ -276,29 +285,30 @@
                                           ClassBuilder enclosingBuilder,
                                           Fragment fragment) {
     ClassElement classElement = cls.element;
-    String className = cls.name;
+    jsAst.Name className = cls.name;
 
     var metadata = task.metadataCollector.buildMetadataFunction(classElement);
     if (metadata != null) {
-      classBuilder.addProperty("@", metadata);
+      classBuilder.addPropertyByName("@", metadata);
     }
 
     if (backend.isAccessibleByReflection(classElement)) {
       List<DartType> typeVars = classElement.typeVariables;
       Iterable typeVariableProperties = emitter.typeVariableHandler
-          .typeVariablesOf(classElement).map(js.number);
+          .typeVariablesOf(classElement);
 
       ClassElement superclass = classElement.superclass;
       bool hasSuper = superclass != null;
       if ((!typeVariableProperties.isEmpty && !hasSuper) ||
           (hasSuper && !equalElements(superclass.typeVariables, typeVars))) {
-        classBuilder.addProperty('<>',
+        classBuilder.addPropertyByName('<>',
             new jsAst.ArrayInitializer(typeVariableProperties.toList()));
       }
     }
 
     List<jsAst.Property> statics = new List<jsAst.Property>();
-    ClassBuilder staticsBuilder = new ClassBuilder(classElement, namer);
+    ClassBuilder staticsBuilder =
+        new ClassBuilder.forStatics(classElement, namer);
     if (emitFields(cls, staticsBuilder, emitStatics: true)) {
       jsAst.ObjectInitializer initializer =
         staticsBuilder.toObjectInitializer();
@@ -317,27 +327,32 @@
     }
 
     if (!statics.isEmpty) {
-      classBuilder.addProperty('static', new jsAst.ObjectInitializer(statics));
+      classBuilder.addPropertyByName('static',
+                                     new jsAst.ObjectInitializer(statics));
     }
 
     // TODO(ahe): This method (generateClass) should return a jsAst.Expression.
-    jsAst.ObjectInitializer propertyValue = classBuilder.toObjectInitializer();
+    jsAst.ObjectInitializer propertyValue =
+        classBuilder.toObjectInitializer();
     compiler.dumpInfoTask.registerElementAst(classBuilder.element, propertyValue);
     enclosingBuilder.addProperty(className, propertyValue);
 
     String reflectionName = emitter.getReflectionName(classElement, className);
     if (reflectionName != null) {
       if (!backend.isAccessibleByReflection(classElement)) {
-        enclosingBuilder.addProperty("+$reflectionName", js.number(0));
+        // TODO(herhut): Fix use of reflection name here.
+        enclosingBuilder.addPropertyByName("+$reflectionName", js.number(0));
       } else {
-        List<int> types = <int>[];
+        List<jsAst.Expression> types = <jsAst.Expression>[];
         if (classElement.supertype != null) {
           types.add(task.metadataCollector.reifyType(classElement.supertype));
         }
         for (DartType interface in classElement.interfaces) {
           types.add(task.metadataCollector.reifyType(interface));
         }
-        enclosingBuilder.addProperty("+$reflectionName", js.numArray(types));
+        // TODO(herhut): Fix use of reflection name here.
+        enclosingBuilder.addPropertyByName("+$reflectionName",
+            new jsAst.ArrayInitializer(types));
       }
     }
   }
@@ -380,7 +395,6 @@
 
     void visitField(Element holder, FieldElement field) {
       assert(invariant(element, field.isDeclaration));
-      String name = field.name;
 
       // Keep track of whether or not we're dealing with a field mixin
       // into a native class.
@@ -401,8 +415,8 @@
       if ((isInstantiated && !holder.isNative)
           || needsGetter
           || needsSetter) {
-        String accessorName = namer.fieldAccessorName(field);
-        String fieldName = namer.fieldPropertyName(field);
+        jsAst.Name accessorName = namer.fieldAccessorName(field);
+        jsAst.Name fieldName = namer.fieldPropertyName(field);
         bool needsCheckedSetter = false;
         if (compiler.enableTypeAssertions
             && needsSetter
@@ -441,13 +455,13 @@
   }
 
   void recordMangledField(Element member,
-                          String accessorName,
+                          jsAst.Name accessorName,
                           String memberName) {
     if (!backend.shouldRetainGetter(member)) return;
     String previousName;
     if (member.isInstanceMember) {
       previousName = emitter.mangledFieldNames.putIfAbsent(
-          '${namer.getterPrefix}$accessorName',
+          namer.deriveGetterName(accessorName),
           () => memberName);
     } else {
       previousName = emitter.mangledGlobalFieldNames.putIfAbsent(
@@ -461,23 +475,27 @@
   bool fieldNeedsGetter(VariableElement field) {
     assert(field.isField);
     if (fieldAccessNeverThrows(field)) return false;
-    return backend.shouldRetainGetter(field)
-        || compiler.codegenWorld.hasInvokedGetter(field, compiler.world);
+    if (backend.shouldRetainGetter(field)) return true;
+    return field.isClassMember &&
+           compiler.codegenWorld.hasInvokedGetter(field, compiler.world);
   }
 
   bool fieldNeedsSetter(VariableElement field) {
     assert(field.isField);
     if (fieldAccessNeverThrows(field)) return false;
-    return (!field.isFinal && !field.isConst)
-        && (backend.shouldRetainSetter(field)
-            || compiler.codegenWorld.hasInvokedSetter(field, compiler.world));
+    if (field.isFinal || field.isConst) return false;
+    if (backend.shouldRetainSetter(field)) return true;
+    return field.isClassMember &&
+           compiler.codegenWorld.hasInvokedSetter(field, compiler.world);
   }
 
-  // We never access a field in a closure (a captured variable) without knowing
-  // that it is there.  Therefore we don't need to use a getter (that will throw
-  // if the getter method is missing), but can always access the field directly.
   static bool fieldAccessNeverThrows(VariableElement field) {
-    return field is ClosureFieldElement;
+    return
+        // We never access a field in a closure (a captured variable) without
+        // knowing that it is there.  Therefore we don't need to use a getter
+        // (that will throw if the getter method is missing), but can always
+        // access the field directly.
+        field is ClosureFieldElement;
   }
 
   bool canAvoidGeneratedCheckedSetter(VariableElement member) {
@@ -488,26 +506,27 @@
   }
 
   void generateCheckedSetter(Element member,
-                             String fieldName,
-                             String accessorName,
+                             jsAst.Name fieldName,
+                             jsAst.Name accessorName,
                              ClassBuilder builder) {
     jsAst.Expression code = backend.generatedCode[member];
     assert(code != null);
-    String setterName = namer.deriveSetterName(accessorName);
+    jsAst.Name setterName = namer.deriveSetterName(accessorName);
     compiler.dumpInfoTask.registerElementAst(member,
         builder.addProperty(setterName, code));
     generateReflectionDataForFieldGetterOrSetter(
         member, setterName, builder, isGetter: false);
   }
 
-  void emitGetterForCSP(Element member, String fieldName, String accessorName,
+  void emitGetterForCSP(Element member, jsAst.Name fieldName,
+                        jsAst.Name accessorName,
                         ClassBuilder builder) {
     jsAst.Expression function =
         _stubGenerator.generateGetter(member, fieldName);
 
-    String getterName = namer.deriveGetterName(accessorName);
+    jsAst.Name getterName = namer.deriveGetterName(accessorName);
     ClassElement cls = member.enclosingClass;
-    String className = namer.className(cls);
+    jsAst.Name className = namer.className(cls);
     OutputUnit outputUnit =
         compiler.deferredLoadTask.outputUnitForElement(member);
     emitter.cspPrecompiledFunctionFor(outputUnit).add(
@@ -519,14 +538,15 @@
     }
   }
 
-  void emitSetterForCSP(Element member, String fieldName, String accessorName,
+  void emitSetterForCSP(Element member, jsAst.Name fieldName,
+                        jsAst.Name accessorName,
                         ClassBuilder builder) {
     jsAst.Expression function =
         _stubGenerator.generateSetter(member, fieldName);
 
-    String setterName = namer.deriveSetterName(accessorName);
+    jsAst.Name setterName = namer.deriveSetterName(accessorName);
     ClassElement cls = member.enclosingClass;
-    String className = namer.className(cls);
+    jsAst.Name className = namer.className(cls);
     OutputUnit outputUnit =
         compiler.deferredLoadTask.outputUnitForElement(member);
     emitter.cspPrecompiledFunctionFor(outputUnit).add(
@@ -539,7 +559,7 @@
   }
 
   void generateReflectionDataForFieldGetterOrSetter(Element member,
-                                                    String name,
+                                                    jsAst.Name name,
                                                     ClassBuilder builder,
                                                     {bool isGetter}) {
     Selector selector = isGetter
@@ -549,7 +569,7 @@
     if (reflectionName != null) {
       var reflectable =
           js(backend.isAccessibleByReflection(member) ? '1' : '0');
-      builder.addProperty('+$reflectionName', reflectable);
+      builder.addPropertyByName('+$reflectionName', reflectable);
     }
   }
 }
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 bccbce8..eeff7d5 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
@@ -12,16 +12,16 @@
 
   void addMemberMethod(DartMethod method, ClassBuilder builder) {
     MethodElement member = method.element;
-    String name = method.name;
+    jsAst.Name name = method.name;
     FunctionSignature parameters = member.functionSignature;
     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;
+    jsAst.Name tearOffName = method.tearOffName;
     bool isClosure = method is InstanceMethod && method.isClosure;
-    String superAlias = method is InstanceMethod ? method.aliasName : null;
+    jsAst.Name superAlias = method is InstanceMethod ? method.aliasName : null;
     bool hasSuperAlias = superAlias != null;
     jsAst.Expression memberTypeExpression = method.functionType;
 
@@ -77,7 +77,7 @@
 
     // Create the optional aliasing entry if this method is called via super.
     if (hasSuperAlias) {
-      expressions.add(new jsAst.LiteralString('"${superAlias}"'));
+      expressions.add(js.quoteName(superAlias));
     }
 
     expressions.add(code);
@@ -93,9 +93,11 @@
       return;
     }
 
-    String callSelectorString = 'null';
-    if (method.callName != null) {
-      callSelectorString = '"${method.callName}"';
+    jsAst.Literal callSelectorString;
+    if (method.callName == null) {
+      callSelectorString = new jsAst.LiteralNull();
+    } else {
+      callSelectorString = js.quoteName(method.callName);
     }
 
     // On [requiredParameterCount], the lower bit is set if this method can be
@@ -106,54 +108,53 @@
     int optionalParameterCount = parameters.optionalParameterCount << 1;
     if (parameters.optionalParametersAreNamed) optionalParameterCount++;
 
-    // TODO(sra): Don't use LiteralString for non-strings.
-    List tearOffInfo = [new jsAst.LiteralString(callSelectorString)];
+    List tearOffInfo = [callSelectorString];
 
     for (ParameterStubMethod stub in method.parameterStubs) {
-      String invocationName = stub.name;
+      jsAst.Name invocationName = stub.name;
       emitter.interceptorEmitter
           .recordMangledNameOfMemberMethod(member, invocationName);
 
       expressions.add(stub.code);
       if (member.isInstanceMember) {
-        expressions.add(js.string(invocationName));
+        expressions.add(js.quoteName(invocationName));
       }
-      String callName = stub.callName;
-      String callSelectorString = (callName == null) ? 'null' : '"$callName"';
-      tearOffInfo.add(new jsAst.LiteralString(callSelectorString));
+      jsAst.Name callName = stub.callName;
+      jsAst.Literal callSelectorString =
+          (callName == null) ? new jsAst.LiteralNull() : js.quoteName(callName);
+      tearOffInfo.add(callSelectorString);
     }
 
     expressions
         ..addAll(tearOffInfo)
         ..add((tearOffName == null || member.isAccessor)
-              ? js("null") : js.string(tearOffName))
+              ? js("null") : js.quoteName(tearOffName))
         ..add(js.number(requiredParameterCount))
         ..add(js.number(optionalParameterCount))
         ..add(memberTypeExpression == null ? js("null") : memberTypeExpression)
-        ..addAll(task.metadataCollector
-            .reifyDefaultArguments(member).map(js.number));
+        ..addAll(task.metadataCollector.reifyDefaultArguments(member));
 
     if (canBeReflected || canBeApplied) {
       parameters.forEachParameter((Element parameter) {
-        expressions.add(
-            js.number(task.metadataCollector.reifyName(parameter.name)));
+        expressions.add(task.metadataCollector.reifyName(parameter.name));
         if (backend.mustRetainMetadata) {
-          Iterable<int> metadataIndices =
+          Iterable<jsAst.Expression> metadataIndices =
               parameter.metadata.map((MetadataAnnotation annotation) {
             ConstantValue constant =
                 backend.constants.getConstantValueForMetadata(annotation);
             backend.constants.addCompileTimeConstantForEmission(constant);
             return task.metadataCollector.reifyMetadata(annotation);
           });
-          expressions.add(new jsAst.ArrayInitializer(
-              metadataIndices.map(js.number).toList()));
+          expressions.add(new jsAst.ArrayInitializer(metadataIndices.toList()));
         }
       });
     }
     if (canBeReflected) {
       jsAst.LiteralString reflectionName;
       if (member.isConstructor) {
-        String reflectionNameString = emitter.getReflectionName(member, name);
+        // TODO(herhut): This registers name as a mangled name. Do we need this
+        //               given that we use a different name below?
+        emitter.getReflectionName(member, name);
         reflectionName =
             new jsAst.LiteralString(
                 '"new ${Elements.reconstructConstructorName(member)}"');
@@ -163,8 +164,7 @@
       }
       expressions
           ..add(reflectionName)
-          ..addAll(task.metadataCollector
-              .computeMetadata(member).map(js.number));
+          ..addAll(task.metadataCollector.computeMetadata(member));
     } else if (isClosure && canBeApplied) {
       expressions.add(js.string(namer.privateName(member.memberName)));
     }
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 9edfdce..833abeb 100644
--- a/pkg/compiler/lib/src/js_emitter/old_emitter/declarations.dart
+++ b/pkg/compiler/lib/src/js_emitter/old_emitter/declarations.dart
@@ -10,7 +10,8 @@
 /**
  * Call-back for adding property with [name] and [value].
  */
-typedef jsAst.Property AddPropertyFunction(String name, jsAst.Expression value);
+typedef jsAst.Property AddPropertyFunction(jsAst.Name name,
+                                           jsAst.Expression value);
 
 /**
  * [member] is a field (instance, static, or top level).
@@ -31,8 +32,8 @@
  * type assertions are enabled (checked mode).
  */
 typedef void AcceptField(VariableElement member,
-                         String name,
-                         String accessorName,
+                         jsAst.Name name,
+                         jsAst.Name accessorName,
                          bool needsGetter,
                          bool needsSetter,
                          bool needsCheckedSetter);
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 203db5d..2749850 100644
--- a/pkg/compiler/lib/src/js_emitter/old_emitter/emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/old_emitter/emitter.dart
@@ -43,9 +43,11 @@
       => task.outputClassLists;
   Map<OutputUnit, List<ConstantValue>> get outputConstantLists
       => task.outputConstantLists;
-  final Map<String, String> mangledFieldNames = <String, String>{};
-  final Map<String, String> mangledGlobalFieldNames = <String, String>{};
-  final Set<String> recordedMangledNames = new Set<String>();
+  final Map<jsAst.Name, String> mangledFieldNames =
+      new HashMap<jsAst.Name, String>();
+  final Map<jsAst.Name, String> mangledGlobalFieldNames =
+      new HashMap<jsAst.Name, String>();
+  final Set<jsAst.Name> recordedMangledNames = new Set<jsAst.Name>();
 
   List<TypedefElement> get typedefsNeededForReflection =>
       task.typedefsNeededForReflection;
@@ -93,7 +95,7 @@
         cachedClassBuilders = compiler.cacheStrategy.newMap(),
         cachedElements = compiler.cacheStrategy.newSet() {
     constantEmitter = new ConstantEmitter(
-        compiler, namer, this.constantReference, makeConstantListTemplate);
+        compiler, namer, this.constantReference, constantListGenerator);
     containerBuilder.emitter = this;
     classEmitter.emitter = this;
     nsmEmitter.emitter = this;
@@ -152,7 +154,9 @@
     if (r != 0) return r;
     // Resolve collisions in the long name by using the constant name (i.e. JS
     // name) which is unique.
-    return namer.constantName(a).compareTo(namer.constantName(b));
+    // TODO(herhut): Find a better way to resolve collisions.
+    return namer.constantName(a).hashCode.compareTo(
+        namer.constantName(b).hashCode);
   }
 
   @override
@@ -187,7 +191,8 @@
       => '${namer.isolateName}.${lazyInitializerProperty}';
   String get initName => 'init';
 
-  String get makeConstListProperty => namer.internalGlobal('makeConstantList');
+  jsAst.Name get makeConstListProperty
+      => namer.internalGlobal('makeConstantList');
 
   /// The name of the property that contains all field names.
   ///
@@ -199,7 +204,7 @@
 
   /// Contains the global state that is needed to initialize and load a
   /// deferred library.
-  String get globalsHolder => namer.internalGlobal("globalsHolder");
+  jsAst.Name get globalsHolder => namer.internalGlobal("globalsHolder");
 
   @override
   jsAst.Expression generateEmbeddedGlobalAccess(String global) {
@@ -212,8 +217,8 @@
   }
 
   jsAst.PropertyAccess globalPropertyAccess(Element element) {
-    String name = namer.globalPropertyName(element);
-    jsAst.PropertyAccess pa = new jsAst.PropertyAccess.field(
+    jsAst.Name name = namer.globalPropertyName(element);
+    jsAst.PropertyAccess pa = new jsAst.PropertyAccess(
         new jsAst.VariableUse(namer.globalObjectFor(element)),
         name);
     return pa;
@@ -293,23 +298,8 @@
         return jsAst.js.expressionTemplateFor(
             "('$isPrefix' + #) in #.prototype");
 
-      case JsBuiltin.isFunctionTypeRti:
-        String functionClassName =
-            backend.namer.runtimeTypeName(compiler.functionClass);
-        return jsAst.js.expressionTemplateFor(
-            '#.$typeNameProperty === "$functionClassName"');
-
-      case JsBuiltin.isDartObjectTypeRti:
-        String objectClassName =
-            backend.namer.runtimeTypeName(compiler.objectClass);
-        return jsAst.js.expressionTemplateFor(
-            '#.$typeNameProperty === "$objectClassName"');
-
-      case JsBuiltin.isNullTypeRti:
-        String nullClassName =
-            backend.namer.runtimeTypeName(compiler.nullClass);
-        return jsAst.js.expressionTemplateFor(
-            '#.$typeNameProperty === "$nullClassName"');
+      case JsBuiltin.isGivenTypeRti:
+        return jsAst.js.expressionTemplateFor('#.$typeNameProperty === #');
 
       case JsBuiltin.getMetadata:
         String metadataAccess =
@@ -371,7 +361,7 @@
   /// The reflection name of class 'C' is 'C'.
   /// An anonymous mixin application has no reflection name.
   /// This is used by js_mirrors.dart.
-  String getReflectionName(elementOrSelector, String mangledName) {
+  String getReflectionName(elementOrSelector, jsAst.Name mangledName) {
     String name = elementOrSelector.name;
     if (backend.shouldRetainName(name) ||
         elementOrSelector is Element &&
@@ -390,13 +380,15 @@
     return null;
   }
 
-  String getReflectionNameInternal(elementOrSelector, String mangledName) {
+  String getReflectionNameInternal(elementOrSelector,
+                                   jsAst.Name mangledName) {
     String name = namer.privateName(elementOrSelector.memberName);
     if (elementOrSelector.isGetter) return name;
     if (elementOrSelector.isSetter) {
-      if (!mangledName.startsWith(namer.setterPrefix)) return '$name=';
-      String base = mangledName.substring(namer.setterPrefix.length);
-      String getter = '${namer.getterPrefix}$base';
+      if (mangledName is! SetterName) return '$name=';
+      SetterName setterName = mangledName;
+      jsAst.Name base = setterName.base;
+      jsAst.Name getter = namer.deriveGetterName(base);
       mangledFieldNames.putIfAbsent(getter, () => name);
       assert(mangledFieldNames[getter] == name);
       recordedMangledNames.add(getter);
@@ -409,7 +401,7 @@
       // Closures are synthesized and their name might conflict with existing
       // globals. Assign an illegal name, and make sure they don't clash
       // with each other.
-      return " $mangledName";
+      return " $name";
     }
     if (elementOrSelector is Selector
         || elementOrSelector.isFunction
@@ -501,7 +493,8 @@
       if (compiler.hasIncrementalSupport) {
         ClassBuilder cachedBuilder =
             cachedClassBuilders.putIfAbsent(classElement, () {
-              ClassBuilder builder = new ClassBuilder(classElement, namer);
+              ClassBuilder builder =
+                  new ClassBuilder.forClass(classElement, namer);
               classEmitter.emitClass(cls, builder, fragment);
               return builder;
             });
@@ -525,7 +518,7 @@
       // 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);
+      ClassBuilder builder = new ClassBuilder.forStatics(element, namer);
       containerBuilder.addMemberMethod(method, builder);
       getElementDescriptor(element, fragment).properties
           .addAll(builder.properties);
@@ -625,12 +618,12 @@
       // before code generation.
       if (code == null) continue;
       if (compiler.enableMinification) {
-        laziesInfo.addAll([js.string(namer.globalPropertyName(element)),
-                           js.string(namer.lazyInitializerName(element)),
+        laziesInfo.addAll([js.quoteName(namer.globalPropertyName(element)),
+                           js.quoteName(namer.lazyInitializerName(element)),
                            code]);
       } else {
-        laziesInfo.addAll([js.string(namer.globalPropertyName(element)),
-                           js.string(namer.lazyInitializerName(element)),
+        laziesInfo.addAll([js.quoteName(namer.globalPropertyName(element)),
+                           js.quoteName(namer.lazyInitializerName(element)),
                            code,
                            js.string(element.name)]);
       }
@@ -655,8 +648,8 @@
       // in new lazy values.
       return js('#(#,#,#,#,#)',
           [js(lazyInitializerName),
-           js.string(namer.globalPropertyName(element)),
-           js.string(namer.lazyInitializerName(element)),
+           js.quoteName(namer.globalPropertyName(element)),
+           js.quoteName(namer.lazyInitializerName(element)),
            code,
            js.string(element.name),
            isolateProperties]);
@@ -665,14 +658,14 @@
     if (compiler.enableMinification) {
       return js('#(#,#,#)',
           [js(lazyInitializerName),
-           js.string(namer.globalPropertyName(element)),
-           js.string(namer.lazyInitializerName(element)),
+           js.quoteName(namer.globalPropertyName(element)),
+           js.quoteName(namer.lazyInitializerName(element)),
            code]);
     } else {
       return js('#(#,#,#,#)',
           [js(lazyInitializerName),
-           js.string(namer.globalPropertyName(element)),
-           js.string(namer.lazyInitializerName(element)),
+           js.quoteName(namer.globalPropertyName(element)),
+           js.quoteName(namer.lazyInitializerName(element)),
            code,
            js.string(element.name)]);
     }
@@ -681,11 +674,7 @@
   jsAst.Statement buildMetadata(Program program, OutputUnit outputUnit) {
     List<jsAst.Statement> parts = <jsAst.Statement>[];
 
-    jsAst.Expression constructList(List<jsAst.Expression> list) {
-      return new jsAst.ArrayInitializer(list == null ? [] : list);
-    }
-
-    List<jsAst.Expression> types = program.metadataTypes[outputUnit];
+    jsAst.Expression types = program.metadataTypesForOutputUnit(outputUnit);
 
     if (outputUnit == compiler.deferredLoadTask.mainOutputUnit) {
       jsAst.Expression metadataAccess =
@@ -693,12 +682,11 @@
       jsAst.Expression typesAccess =
           generateEmbeddedGlobalAccess(embeddedNames.TYPES);
 
-      parts..add(js.statement('# = #;', [metadataAccess,
-                                         constructList(program.metadata)]))
-           ..add(js.statement('# = #;', [typesAccess, constructList(types)]));
+      parts..add(js.statement('# = #;', [metadataAccess, program.metadata]))
+           ..add(js.statement('# = #;', [typesAccess, types]));
     } else if (types != null) {
       parts.add(js.statement('var ${namer.deferredTypesName} = #;',
-                             constructList(types)));
+                             types));
     }
     return new jsAst.Block(parts);
   }
@@ -725,16 +713,15 @@
   }
 
   jsAst.Statement buildConstantInitializer(ConstantValue constant) {
-    String name = namer.constantName(constant);
+    jsAst.Name name = namer.constantName(constant);
     return js.statement('#.# = #',
                         [namer.globalObjectForConstant(constant), name,
                          constantInitializerExpression(constant)]);
   }
 
-  jsAst.Template get makeConstantListTemplate {
+  jsAst.Expression constantListGenerator(jsAst.Expression array) {
     // TODO(floitsch): there is no harm in caching the template.
-    return jsAst.js.uncachedExpressionTemplate(
-        '${namer.isolateName}.$makeConstListProperty(#)');
+    return js('${namer.isolateName}.#(#)', [makeConstListProperty, array]);
   }
 
   jsAst.Statement buildMakeConstantList() {
@@ -802,11 +789,11 @@
     return js.statement('''
       function init() {
         $isolatePropertiesName = Object.create(null);
-        #allClasses = Object.create(null);
+        #allClasses = map();
         #getTypeFromName = function(name) {return #allClasses[name];};
-        #interceptorsByTag = Object.create(null);
-        #leafTags = Object.create(null);
-        #finishedClasses = Object.create(null);
+        #interceptorsByTag = map();
+        #leafTags = map();
+        #finishedClasses = map();
 
         if (#needsLazyInitializer) {
           // [staticName] is only provided in non-minified mode. If missing, we 
@@ -1029,12 +1016,11 @@
   }
 
   void assemblePrecompiledConstructor(OutputUnit outputUnit,
-                                      String constructorName,
+                                      jsAst.Name constructorName,
                                       jsAst.Expression constructorAst,
                                       List<String> fields) {
     cspPrecompiledFunctionFor(outputUnit).add(
-        new jsAst.FunctionDeclaration(
-            new jsAst.VariableDeclaration(constructorName), constructorAst));
+        new jsAst.FunctionDeclaration(constructorName, constructorAst));
 
     String fieldNamesProperty = FIELD_NAMES_PROPERTY_NAME;
     bool hasIsolateSupport = compiler.hasIsolateSupport;
@@ -1056,7 +1042,7 @@
         }''',
         {"constructorName": constructorName,
          "typeNameProperty": typeNameProperty,
-         "constructorNameString": js.string(constructorName),
+         "constructorNameString": js.quoteName(constructorName),
          "hasIsolateSupport": hasIsolateSupport,
          "fieldNamesArray": fieldNamesArray}));
 
@@ -1076,13 +1062,13 @@
       DartType type = typedef.alias;
       // TODO(zarah): reify type variables once reflection on type arguments of
       // typedefs is supported.
-      int typeIndex =
+      jsAst.Expression typeIndex =
           task.metadataCollector.reifyType(type, ignoreTypeVariables: true);
-      ClassBuilder builder = new ClassBuilder(typedef, namer);
-      builder.addProperty(embeddedNames.TYPEDEF_TYPE_PROPERTY_NAME,
-                          js.number(typeIndex));
-      builder.addProperty(embeddedNames.TYPEDEF_PREDICATE_PROPERTY_NAME,
-                          js.boolean(true));
+      ClassBuilder builder = new ClassBuilder.forStatics(typedef, namer);
+      builder.addPropertyByName(embeddedNames.TYPEDEF_TYPE_PROPERTY_NAME,
+                                typeIndex);
+      builder.addPropertyByName(embeddedNames.TYPEDEF_PREDICATE_PROPERTY_NAME,
+                                js.boolean(true));
 
       // We can be pretty sure that the objectClass is initialized, since
       // typedefs are only emitted with reflection, which requires lots of
@@ -1090,13 +1076,13 @@
       assert(compiler.objectClass != null);
       builder.superName = namer.className(compiler.objectClass);
       jsAst.Node declaration = builder.toObjectInitializer();
-      String mangledName = namer.globalPropertyName(typedef);
+      jsAst.Name mangledName = namer.globalPropertyName(typedef);
       String reflectionName = getReflectionName(typedef, mangledName);
       getElementDescriptor(library, mainFragment)
           ..addProperty(mangledName, declaration)
-          ..addProperty("+$reflectionName", js.string(''));
+          ..addPropertyByName("+$reflectionName", js.string(''));
       // Also emit a trivial constructor for CSP mode.
-      String constructorName = mangledName;
+      jsAst.Name constructorName = mangledName;
       jsAst.Expression constructorAst = js('function() {}');
       List<String> fieldNames = [];
       assemblePrecompiledConstructor(mainOutputUnit,
@@ -1196,12 +1182,11 @@
     List<jsAst.Statement> parts = <jsAst.Statement>[];
 
     if (!mangledFieldNames.isEmpty) {
-      var keys = mangledFieldNames.keys.toList();
-      keys.sort();
+      List<jsAst.Name> keys = mangledFieldNames.keys.toList()..sort();
       var properties = [];
-      for (String key in keys) {
-        var value = js.string('${mangledFieldNames[key]}');
-        properties.add(new jsAst.Property(js.string(key), value));
+      for (jsAst.Name key in keys) {
+        var value = js.string(mangledFieldNames[key]);
+        properties.add(new jsAst.Property(key, value));
       }
 
       jsAst.Expression mangledNamesAccess =
@@ -1211,16 +1196,16 @@
     }
 
     if (!mangledGlobalFieldNames.isEmpty) {
-      var keys = mangledGlobalFieldNames.keys.toList();
-      keys.sort();
-      var properties = [];
-      for (String key in keys) {
-        var value = js.string('${mangledGlobalFieldNames[key]}');
-        properties.add(new jsAst.Property(js.string(key), value));
+      List<jsAst.Name> keys = mangledGlobalFieldNames.keys.toList()
+          ..sort();
+      List<jsAst.Property> properties = <jsAst.Property>[];
+      for (jsAst.Name key in keys) {
+        jsAst.Literal value = js.string(mangledGlobalFieldNames[key]);
+        properties.add(new jsAst.Property(js.quoteName(key), value));
       }
       jsAst.Expression mangledGlobalNamesAccess =
           generateEmbeddedGlobalAccess(embeddedNames.MANGLED_GLOBAL_NAMES);
-      var map = new jsAst.ObjectInitializer(properties);
+      jsAst.ObjectInitializer map = new jsAst.ObjectInitializer(properties);
       parts.add(js.statement('# = #', [mangledGlobalNamesAccess, map]));
     }
 
@@ -1267,23 +1252,10 @@
     assembleTypedefs(program);
   }
 
-  void emitMainOutputUnit(Program program,
-                          Map<OutputUnit, String> deferredLoadHashes) {
-    MainFragment mainFragment = program.fragments.first;
+  jsAst.Program buildOutputAstForMain(Program program,
+      Map<OutputUnit, _DeferredOutputUnitHash> deferredLoadHashes) {
+    MainFragment mainFragment = program.mainFragment;
     OutputUnit mainOutputUnit = mainFragment.outputUnit;
-
-    LineColumnCollector lineColumnCollector;
-    List<CodeOutputListener> codeOutputListeners;
-    if (generateSourceMap) {
-      lineColumnCollector = new LineColumnCollector();
-      codeOutputListeners = <CodeOutputListener>[lineColumnCollector];
-    }
-
-    CodeOutput mainOutput =
-        new StreamCodeOutput(compiler.outputProvider('', 'js'),
-                             codeOutputListeners);
-    outputBuffers[mainOutputUnit] = mainOutput;
-
     bool isProgramSplit = program.isSplit;
 
     List<jsAst.Statement> statements = <jsAst.Statement>[];
@@ -1488,7 +1460,24 @@
       "main": buildMain(mainFragment.invokeMain)
     }));
 
-    mainOutput.addBuffer(jsAst.prettyPrint(new jsAst.Program(statements),
+    return new jsAst.Program(statements);
+  }
+
+  void emitMainOutputUnit(OutputUnit mainOutputUnit, jsAst.Program program) {
+    LineColumnCollector lineColumnCollector;
+    List<CodeOutputListener> codeOutputListeners;
+    if (generateSourceMap) {
+      lineColumnCollector = new LineColumnCollector();
+      codeOutputListeners = <CodeOutputListener>[lineColumnCollector];
+    }
+
+    CodeOutput mainOutput =
+        new StreamCodeOutput(compiler.outputProvider('', 'js'),
+                             codeOutputListeners);
+    outputBuffers[mainOutputUnit] = mainOutput;
+
+
+    mainOutput.addBuffer(jsAst.prettyPrint(program,
                                            compiler,
                                            monitor: compiler.dumpInfoTask));
 
@@ -1655,6 +1644,13 @@
     return outputs;
   }
 
+  void finalizeTokensInAst(jsAst.Program main,
+                           Iterable<jsAst.Program> deferredParts) {
+    task.metadataCollector.countTokensInAst(main);
+    deferredParts.forEach(task.metadataCollector.countTokensInAst);
+    task.metadataCollector.finalizeTokens();
+  }
+
   int emitProgram(ProgramBuilder programBuilder) {
     Program program = programBuilder.buildProgram(
         storeFunctionTypesInMetadata: true);
@@ -1665,6 +1661,19 @@
     Map<OutputUnit, jsAst.Program> deferredParts =
         buildOutputAstForDeferredCode(program);
 
+    Map<OutputUnit, _DeferredOutputUnitHash> deferredHashTokens =
+        new Map<OutputUnit, _DeferredOutputUnitHash>.fromIterables(
+          deferredParts.keys,
+          deferredParts.keys.map((OutputUnit unit) {
+            return new _DeferredOutputUnitHash(unit);
+          })
+        );
+
+    jsAst.Program mainOutput =
+        buildOutputAstForMain(program, deferredHashTokens);
+
+    finalizeTokensInAst(mainOutput, deferredParts.values);
+
     // Emit deferred units first, so we have their hashes.
     // Map from OutputUnit to a hash of its content. The hash uniquely
     // identifies the code of the output-unit. It does not include
@@ -1672,7 +1681,11 @@
     // itself.
     Map<OutputUnit, String> deferredLoadHashes =
         emitDeferredOutputUnits(deferredParts);
-    emitMainOutputUnit(program, deferredLoadHashes);
+
+    deferredHashTokens.forEach((OutputUnit key, _DeferredOutputUnitHash token) {
+      token.setHash(deferredLoadHashes[key]);
+    });
+    emitMainOutputUnit(program.mainFragment.outputUnit, mainOutput);
 
     if (backend.requiresPreamble &&
         !backend.htmlLibraryIsLoaded) {
@@ -1695,6 +1708,7 @@
 
   ClassBuilder getElementDescriptor(Element element, Fragment fragment) {
     Element owner = element.library;
+    bool isClass = false;
     if (!element.isLibrary && !element.isTopLevel && !element.isNative) {
       // For static (not top level) elements, record their code in a buffer
       // specific to the class. For now, not supported for native classes and
@@ -1713,12 +1727,14 @@
     }
     return elementDescriptors
         .putIfAbsent(fragment, () => new Map<Element, ClassBuilder>())
-        .putIfAbsent(owner, () => new ClassBuilder(owner, namer));
+        .putIfAbsent(owner, () {
+          return new ClassBuilder(owner, namer, owner.isClass);
+        });
   }
 
   /// Emits support-code for deferred loading into [output].
   jsAst.Statement buildDeferredBoilerPlate(
-      Map<OutputUnit, String> deferredLoadHashes) {
+      Map<OutputUnit, _DeferredOutputUnitHash> deferredLoadHashes) {
     List<jsAst.Statement> parts = <jsAst.Statement>[];
 
     parts.add(js.statement('''
@@ -1735,11 +1751,12 @@
           // Function for initializing a loaded hunk, given its hash.
           #initializeLoadedHunk = function(hunkHash) {
             $deferredInitializers[hunkHash](
-            $globalsHolder, ${namer.currentIsolate});
+            #globalsHolder, ${namer.currentIsolate});
             #deferredInitialized[hunkHash] = true;
           };
         }
-        ''', {"isHunkLoaded": generateEmbeddedGlobalAccess(
+        ''', {"globalsHolder": globalsHolder,
+              "isHunkLoaded": generateEmbeddedGlobalAccess(
                   embeddedNames.IS_HUNK_LOADED),
               "isHunkInitialized": generateEmbeddedGlobalAccess(
                   embeddedNames.IS_HUNK_INITIALIZED),
@@ -1752,17 +1769,19 @@
     // from the import prefix.) to a list of lists of uris of hunks to load,
     // and a corresponding mapping to a list of hashes used by
     // INITIALIZE_LOADED_HUNK and IS_HUNK_LOADED.
-    Map<String, List<String>> deferredLibraryUris =
-        new Map<String, List<String>>();
-    Map<String, List<String>> deferredLibraryHashes =
-        new Map<String, List<String>>();
+    Map<String, List<jsAst.LiteralString>> deferredLibraryUris =
+        new Map<String, List<jsAst.LiteralString>>();
+    Map<String, List<_DeferredOutputUnitHash>> deferredLibraryHashes =
+        new Map<String, List<_DeferredOutputUnitHash>>();
     compiler.deferredLoadTask.hunksToLoad.forEach(
                   (String loadId, List<OutputUnit>outputUnits) {
-      List<String> uris = new List<String>();
-      List<String> hashes = new List<String>();
-      deferredLibraryHashes[loadId] = new List<String>();
+      List<jsAst.LiteralString> uris = new List<jsAst.LiteralString>();
+      List<_DeferredOutputUnitHash> hashes =
+          new List<_DeferredOutputUnitHash>();
+      deferredLibraryHashes[loadId] = new List<_DeferredOutputUnitHash>();
       for (OutputUnit outputUnit in outputUnits) {
-        uris.add(backend.deferredPartFileName(outputUnit.name));
+        uris.add(js.escapedString(
+            backend.deferredPartFileName(outputUnit.name)));
         hashes.add(deferredLoadHashes[outputUnit]);
       }
 
@@ -1770,12 +1789,11 @@
       deferredLibraryHashes[loadId] = hashes;
     });
 
-    void emitMapping(String name, Map<String, List<String>> mapping) {
+    void emitMapping(String name, Map<String, List<jsAst.Expression>> mapping) {
       List<jsAst.Property> properties = new List<jsAst.Property>();
-      mapping.forEach((String key, List<String> values) {
+      mapping.forEach((String key, List<jsAst.Expression> values) {
         properties.add(new jsAst.Property(js.escapedString(key),
-            new jsAst.ArrayInitializer(
-                values.map(js.escapedString).toList())));
+            new jsAst.ArrayInitializer(values)));
       });
       jsAst.Node initializer =
           new jsAst.ObjectInitializer(properties, isOneLiner: true);
@@ -1811,14 +1829,18 @@
       body.add(js.comment("/* ::norenaming:: "));
 
       for (String globalObject in Namer.reservedGlobalObjectNames) {
-        body.add(js.statement('var #object = ${globalsHolder}.#object;',
-                              {'object': globalObject}));
+        body.add(js.statement('var #object = #globalsHolder.#object;',
+                              {'globalsHolder': globalsHolder,
+                               'object': globalObject}));
       }
-      body..add(js.statement('var init = ${globalsHolder}.init;'))
+      body..add(js.statement('var init = #globalsHolder.init;',
+                             {'globalsHolder': globalsHolder}))
           ..add(js.statement('var $setupProgramName = '
-                             '$globalsHolder.$setupProgramName;'))
+                             '#globalsHolder.$setupProgramName;',
+                             {'globalsHolder': globalsHolder}))
           ..add(js.statement('var ${namer.isolateName} = '
-                             '${globalsHolder}.${namer.isolateName};'));
+                             '#globalsHolder.${namer.isolateName};',
+                             {'globalsHolder': globalsHolder}));
       String typesAccess =
           generateEmbeddedGlobalAccessString(embeddedNames.TYPES);
       if (libraryDescriptor != null) {
@@ -1834,11 +1856,9 @@
             js.statement('$setupProgramName(dart, ${typesAccess}.length);'));
       }
 
-      if (task.metadataCollector.types[outputUnit] != null) {
-        body..add(buildMetadata(program, outputUnit))
-            ..add(js.statement('${typesAccess}.push.apply(${typesAccess}, '
-                               '${namer.deferredTypesName});'));
-      }
+      body..add(buildMetadata(program, outputUnit))
+          ..add(js.statement('${typesAccess}.push.apply(${typesAccess}, '
+                             '${namer.deferredTypesName});'));
 
       // Set the currentIsolate variable to the current isolate (which is
       // provided as second argument).
@@ -1853,10 +1873,10 @@
       statements
           ..add(buildGeneratedBy())
           ..add(js.statement('${deferredInitializers}.current = '
-                             """function (${globalsHolder}) {
+                             """function (#) {
                                   #
                                 }
-                             """, [body]));
+                             """, [globalsHolder, body]));
 
       result[outputUnit] = new jsAst.Program(statements);
     }
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 aa43580..5605aa5 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
@@ -5,15 +5,17 @@
 part of dart2js.js_emitter;
 
 class InterceptorEmitter extends CodeEmitterHelper {
-  final Set<String> interceptorInvocationNames = new Set<String>();
+  final Set<jsAst.Name> interceptorInvocationNames =
+      new Set<jsAst.Name>();
 
-  void recordMangledNameOfMemberMethod(FunctionElement member, String name) {
+  void recordMangledNameOfMemberMethod(FunctionElement member,
+                                       jsAst.Name name) {
     if (backend.isInterceptedMethod(member)) {
       interceptorInvocationNames.add(name);
     }
   }
 
-  jsAst.Expression buildGetInterceptorMethod(String key,
+  jsAst.Expression buildGetInterceptorMethod(jsAst.Name key,
                                              Set<ClassElement> classes) {
     InterceptorStubGenerator stubGenerator =
         new InterceptorStubGenerator(compiler, namer, backend);
@@ -31,9 +33,11 @@
 
     parts.add(js.comment('getInterceptor methods'));
 
-    Map<String, Set<ClassElement>> specializedGetInterceptors =
+    Map<jsAst.Name, Set<ClassElement>> specializedGetInterceptors =
         backend.specializedGetInterceptors;
-    for (String name in specializedGetInterceptors.keys.toList()..sort()) {
+    List<jsAst.Name> names = specializedGetInterceptors.keys.toList()
+        ..sort();
+    for (jsAst.Name name in names) {
       Set<ClassElement> classes = specializedGetInterceptors[name];
       parts.add(
           js.statement('#.# = #',
@@ -47,13 +51,13 @@
 
   jsAst.Statement buildOneShotInterceptors() {
     List<jsAst.Statement> parts = <jsAst.Statement>[];
-    List<String> names = backend.oneShotInterceptors.keys.toList();
-    names.sort();
+    Iterable<jsAst.Name> names = backend.oneShotInterceptors.keys.toList()
+        ..sort();
 
     InterceptorStubGenerator stubGenerator =
         new InterceptorStubGenerator(compiler, namer, backend);
     String globalObject = namer.globalObjectFor(backend.interceptorsLibrary);
-    for (String name in names) {
+    for (jsAst.Name name in names) {
       jsAst.Expression function =
           stubGenerator.generateOneShotInterceptor(name);
       parts.add(js.statement('${globalObject}.# = #', [name, function]));
@@ -75,13 +79,11 @@
     // (which can easily be identified).
     if (!compiler.enabledInvokeOn) return null;
 
-    List<String> invocationNames = interceptorInvocationNames.toList()..sort();
-    List<jsAst.Property> properties =
-        new List<jsAst.Property>(invocationNames.length);
-    for (int i = 0; i < invocationNames.length; i++) {
-      String name = invocationNames[i];
-      properties[i] = new jsAst.Property(js.string(name), js.number(1));
-    }
+    Iterable<jsAst.Name> invocationNames = interceptorInvocationNames.toList()
+        ..sort();;
+    List<jsAst.Property> properties = invocationNames.map((jsAst.Name name) {
+      return new jsAst.Property(js.quoteName(name), js.number(1));
+    }).toList();
     return new jsAst.ObjectInitializer(properties, isOneLiner: true);
   }
 
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 86ff20a..134e6cf 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
@@ -25,7 +25,7 @@
 
     // Keep track of the JavaScript names we've already added so we
     // do not introduce duplicates (bad for code size).
-    Map<String, Selector> addedJsNames
+    Map<jsAst.Name, Selector> addedJsNames
         = generator.computeSelectorsForNsmHandlers();
 
     // Set flag used by generateMethod helper below.  If we have very few
@@ -33,7 +33,9 @@
     // them at runtime.
     bool haveVeryFewNoSuchMemberHandlers =
         (addedJsNames.length < VERY_FEW_NO_SUCH_METHOD_HANDLERS);
-    for (String jsName in addedJsNames.keys.toList()..sort()) {
+    List<jsAst.Name> names = addedJsNames.keys.toList()
+        ..sort();
+    for (jsAst.Name jsName in names) {
       Selector selector = addedJsNames[jsName];
       String reflectionName = emitter.getReflectionName(selector, jsName);
 
@@ -54,9 +56,11 @@
             generator.generateStubForNoSuchMethod(jsName, selector);
         addProperty(method.name, method.code);
         if (reflectionName != null) {
-          bool accessible = compiler.world.allFunctions.filter(selector).any(
+          bool accessible =
+              compiler.world.allFunctions.filter(selector, null).any(
               (Element e) => backend.isAccessibleByReflection(e));
-          addProperty('+$reflectionName', js(accessible ? '2' : '0'));
+          addProperty(namer.asName('+$reflectionName'),
+                      js(accessible ? '2' : '0'));
         }
       }
     }
@@ -65,23 +69,13 @@
   // Identify the noSuchMethod handlers that are so simple that we can
   // generate them programatically.
   bool isTrivialNsmHandler(
-      int type, List argNames, Selector selector, String internalName) {
+      int type, List argNames, Selector selector, jsAst.Name internalName) {
     if (!generateTrivialNsmHandlers) return false;
-    // Check for interceptor calling convention.
-    if (backend.isInterceptedName(selector.name)) {
-      // We can handle the calling convention used by intercepted names in the
-      // diff encoding, but we don't use that for non-minified code.
-      if (!compiler.enableMinification) return false;
-      String shortName = namer.invocationMirrorInternalName(selector);
-      if (shortName.length > MAX_MINIFIED_LENGTH_FOR_DIFF_ENCODING) {
-        return false;
-      }
-    }
     // Check for named arguments.
     if (argNames.length != 0) return false;
     // Check for unexpected name (this doesn't really happen).
-    if (internalName.startsWith(namer.getterPrefix[0])) return type == 1;
-    if (internalName.startsWith(namer.setterPrefix[0])) return type == 2;
+    if (internalName is GetterName) return type == 1;
+    if (internalName is SetterName) return type == 2;
     return type == 0;
   }
 
@@ -127,33 +121,190 @@
   List<jsAst.Statement> buildTrivialNsmHandlers() {
     List<jsAst.Statement> statements = <jsAst.Statement>[];
     if (trivialNsmHandlers.length == 0) return statements;
-    // Sort by calling convention, JS name length and by JS name.
-    trivialNsmHandlers.sort((a, b) {
-      bool aIsIntercepted = backend.isInterceptedName(a.name);
-      bool bIsIntercepted = backend.isInterceptedName(b.name);
-      if (aIsIntercepted != bIsIntercepted) return aIsIntercepted ? -1 : 1;
-      String aName = namer.invocationMirrorInternalName(a);
-      String bName = namer.invocationMirrorInternalName(b);
-      if (aName.length != bName.length) return aName.length - bName.length;
-      return aName.compareTo(bName);
-    });
+
+    bool minify = compiler.enableMinification;
+    bool useDiffEncoding = minify && trivialNsmHandlers.length > 30;
 
     // Find out how many selectors there are with the special calling
     // convention.
-    int firstNormalSelector = trivialNsmHandlers.length;
-    for (int i = 0; i < trivialNsmHandlers.length; i++) {
-      if (!backend.isInterceptedName(trivialNsmHandlers[i].name)) {
-        firstNormalSelector = i;
-        break;
-      }
-    }
+    Iterable<Selector> interceptedSelectors = trivialNsmHandlers.where(
+            (Selector s) => backend.isInterceptedName(s.name));
+    Iterable<Selector> ordinarySelectors = trivialNsmHandlers.where(
+            (Selector s) => !backend.isInterceptedName(s.name));
 
     // Get the short names (JS names, perhaps minified).
-    Iterable<String> shorts = trivialNsmHandlers.map((selector) =>
-         namer.invocationMirrorInternalName(selector));
-    final diffShorts = <String>[];
-    var diffEncoding = new StringBuffer();
+    Iterable<jsAst.Name> interceptedShorts =
+        interceptedSelectors.map(namer.invocationMirrorInternalName);
+    Iterable<jsAst.Name> ordinaryShorts =
+        ordinarySelectors.map(namer.invocationMirrorInternalName);
 
+    jsAst.Expression sortedShorts;
+    Iterable<String> sortedLongs;
+    if (useDiffEncoding) {
+      assert(minify);
+      sortedShorts = new _DiffEncodedListOfNames(
+          [interceptedShorts, ordinaryShorts]);
+    } else {
+      Iterable<Selector> sorted =
+          [interceptedSelectors, ordinarySelectors].expand((e) => (e));
+      sortedShorts = js.concatenateStrings(
+          js.joinLiterals(
+              sorted.map(namer.invocationMirrorInternalName),
+              js.stringPart(",")),
+          addQuotes: true);
+
+      if (!minify) {
+        sortedLongs = sorted.map((selector) =>
+            selector.invocationMirrorMemberName);
+      }
+    }
+    // Startup code that loops over the method names and puts handlers on the
+    // Object class to catch noSuchMethod invocations.
+    ClassElement objectClass = compiler.objectClass;
+    jsAst.Expression createInvocationMirror = backend.emitter
+        .staticFunctionAccess(backend.getCreateInvocationMirror());
+    if (useDiffEncoding) {
+      statements.add(js.statement('''{
+          var objectClassObject = processedClasses.collected[#objectClass],
+              nameSequences = #diffEncoding.split("."),
+              shortNames = [];
+          if (objectClassObject instanceof Array)
+              objectClassObject = objectClassObject[1];
+          for (var j = 0; j < nameSequences.length; ++j) {
+              var sequence = nameSequences[j].split(","),
+                nameNumber = 0;
+            // If we are loading a deferred library the object class will not be
+            // in the collectedClasses so objectClassObject is undefined, and we
+            // skip setting up the names.
+            if (!objectClassObject) break;
+            // Likewise, if the current sequence is empty, we don't process it.
+            if (sequence.length == 0) continue;
+            var diffEncodedString = sequence[0];
+            for (var i = 0; i < diffEncodedString.length; i++) {
+              var codes = [],
+                  diff = 0,
+                  digit = diffEncodedString.charCodeAt(i);
+              for (; digit <= ${$Z};) {
+                diff *= 26;
+                diff += (digit - ${$A});
+                digit = diffEncodedString.charCodeAt(++i);
+              }
+              diff *= 26;
+              diff += (digit - ${$a});
+              nameNumber += diff;
+              for (var remaining = nameNumber;
+                   remaining > 0;
+                   remaining = (remaining / 88) | 0) {
+                codes.unshift(${$HASH} + remaining % 88);
+              }
+              shortNames.push(
+                String.fromCharCode.apply(String, codes));
+            }
+            if (sequence.length > 1) {
+              Array.prototype.push.apply(shortNames, sequence.shift());
+            }
+          }
+        }''', {'objectClass': js.quoteName(namer.className(objectClass)),
+               'diffEncoding': sortedShorts}));
+    } else {
+      // No useDiffEncoding version.
+      statements.add(js.statement(
+          'var objectClassObject = processedClasses.collected[#objectClass],'
+          '    shortNames = #diffEncoding.split(",")',
+          {'objectClass': js.quoteName(namer.className(objectClass)),
+           'diffEncoding': sortedShorts}));
+      if (!minify) {
+        statements.add(js.statement('var longNames = #longs.split(",")',
+                {'longs': js.string(sortedLongs.join(','))}));
+      }
+      statements.add(js.statement(
+          'if (objectClassObject instanceof Array)'
+          '  objectClassObject = objectClassObject[1];'));
+    }
+
+    dynamic isIntercepted =  // jsAst.Expression or bool.
+        interceptedSelectors.isEmpty
+        ? false
+        : ordinarySelectors.isEmpty
+            ? true
+            : js('j < #', js.number(interceptedSelectors.length));
+
+    statements.add(js.statement('''
+      // If we are loading a deferred library the object class will not be in
+      // the collectedClasses so objectClassObject is undefined, and we skip
+      // setting up the names.
+      if (objectClassObject) {
+        for (var j = 0; j < shortNames.length; j++) {
+          var type = 0;
+          var shortName = shortNames[j];
+          if (shortName[0] == "${namer.getterPrefix[0]}") type = 1;
+          if (shortName[0] == "${namer.setterPrefix[0]}") type = 2;
+          // Generate call to:
+          //
+          //     createInvocationMirror(String name, internalName, type,
+          //         arguments, argumentNames)
+          //
+
+          // This 'if' is either a static choice or dynamic choice depending on
+          // [isIntercepted].
+          if (#isIntercepted) {
+            objectClassObject[shortName] =
+                (function(name, shortName, type) {
+                  return function(receiver) {
+                    return this.#noSuchMethodName(
+                      receiver,
+                      #createInvocationMirror(name, shortName, type,
+                          // Create proper Array with all arguments except first
+                          // (receiver).
+                          Array.prototype.slice.call(arguments, 1),
+                          []));
+                  }
+                 })(#names[j], shortName, type);
+          } else {
+            objectClassObject[shortName] =
+                (function(name, shortName, type) {
+                  return function() {
+                    return this.#noSuchMethodName(
+                      // Object.noSuchMethodName ignores the explicit receiver
+                      // argument. We could pass anything in place of [this].
+                      this,
+                      #createInvocationMirror(name, shortName, type,
+                          // Create proper Array with all arguments.
+                          Array.prototype.slice.call(arguments, 0),
+                          []));
+                  }
+                 })(#names[j], shortName, type);
+          }
+        }
+      }''', {
+          'noSuchMethodName': namer.noSuchMethodName,
+          'createInvocationMirror': createInvocationMirror,
+          'names': minify ? 'shortNames' : 'longNames',
+          'isIntercepted': isIntercepted}));
+
+    return statements;
+  }
+}
+
+/// When pretty printed, this node computes a diff-encoded string for the list
+/// of given names.
+///
+/// See [buildTrivialNsmHandlers].
+class _DiffEncodedListOfNames extends jsAst.DeferredString
+                              implements AstContainer {
+  String _cachedValue;
+  jsAst.ArrayInitializer ast;
+
+  _DiffEncodedListOfNames(Iterable<Iterable<jsAst.Name>> names) {
+    // Store the names in ArrayInitializer nodes to make them discoverable
+    // by traversals of the ast.
+    ast = new jsAst.ArrayInitializer(
+        names.map((Iterable i) => new jsAst.ArrayInitializer(i.toList()))
+             .toList());
+  }
+
+  void _computeDiffEncodingForList(Iterable<jsAst.Name> names,
+                                   StringBuffer diffEncoding) {
     // Treat string as a number in base 88 with digits in ASCII order from # to
     // z.  The short name sorting is based on length, and uses ASCII order for
     // equal length strings so this means that names are ascending.  The hash
@@ -186,142 +337,54 @@
       return new String.fromCharCodes(encodingChars.reversed.toList());
     }
 
-    bool minify = compiler.enableMinification;
-    bool useDiffEncoding = minify && shorts.length > 30;
+    // Sort by length, then lexicographic.
+    int compare(String a, String b) {
+      if (a.length != b.length) return a.length - b.length;
+      return a.compareTo(b);
+    }
+
+    List<String> shorts =
+        names.map((jsAst.Name name) => name.name)
+        .toList()
+        ..sort(compare);
 
     int previous = 0;
-    int nameCounter = 0;
     for (String short in shorts) {
-      // Emit period that resets the diff base to zero when we switch to normal
-      // calling convention (this avoids the need to code negative diffs).
-      if (useDiffEncoding && nameCounter == firstNormalSelector) {
-        diffEncoding.write(".");
-        previous = 0;
-      }
-      if (short.length <= MAX_MINIFIED_LENGTH_FOR_DIFF_ENCODING &&
-          useDiffEncoding) {
+      if (short.length <= NsmEmitter.MAX_MINIFIED_LENGTH_FOR_DIFF_ENCODING) {
         int base63 = fromBase88(short);
         int diff = base63 - previous;
         previous = base63;
         String base26Diff = toBase26(diff);
         diffEncoding.write(base26Diff);
       } else {
-        if (useDiffEncoding || diffEncoding.length != 0) {
-          diffEncoding.write(",");
+        if (diffEncoding.length != 0) {
+          diffEncoding.write(',');
         }
         diffEncoding.write(short);
       }
-      nameCounter++;
     }
+  }
 
-    // Startup code that loops over the method names and puts handlers on the
-    // Object class to catch noSuchMethod invocations.
-    ClassElement objectClass = compiler.objectClass;
-    jsAst.Expression createInvocationMirror = backend.emitter
-        .staticFunctionAccess(backend.getCreateInvocationMirror());
-    var type = 0;
-    if (useDiffEncoding) {
-      statements.add(js.statement('''{
-          var objectClassObject = processedClasses.collected[#objectClass],
-              shortNames = #diffEncoding.split(","),
-              nameNumber = 0,
-              diffEncodedString = shortNames[0],
-              calculatedShortNames = [0, 1];    // 0, 1 are args for splice.
-          // If we are loading a deferred library the object class will not be in
-          // the collectedClasses so objectClassObject is undefined, and we skip
-          // setting up the names.
-
-          if (objectClassObject) {
-            if (objectClassObject instanceof Array)
-              objectClassObject = objectClassObject[1];
-            for (var i = 0; i < diffEncodedString.length; i++) {
-              var codes = [],
-                  diff = 0,
-                  digit = diffEncodedString.charCodeAt(i);
-              if (digit == ${$PERIOD}) {
-                nameNumber = 0;
-                digit = diffEncodedString.charCodeAt(++i);
-              }
-              for (; digit <= ${$Z};) {
-                diff *= 26;
-                diff += (digit - ${$A});
-                digit = diffEncodedString.charCodeAt(++i);
-              }
-              diff *= 26;
-              diff += (digit - ${$a});
-              nameNumber += diff;
-              for (var remaining = nameNumber;
-                   remaining > 0;
-                   remaining = (remaining / 88) | 0) {
-                codes.unshift(${$HASH} + remaining % 88);
-              }
-              calculatedShortNames.push(
-                String.fromCharCode.apply(String, codes));
-            }
-            shortNames.splice.apply(shortNames, calculatedShortNames);
-          }
-        }''', {'objectClass': js.string(namer.className(objectClass)),
-               'diffEncoding': js.string('$diffEncoding')}));
-    } else {
-      // No useDiffEncoding version.
-      Iterable<String> longs = trivialNsmHandlers.map((selector) =>
-             selector.invocationMirrorMemberName);
-      statements.add(js.statement(
-          'var objectClassObject = processedClasses.collected[#objectClass],'
-          '    shortNames = #diffEncoding.split(",")',
-          {'objectClass': js.string(namer.className(objectClass)),
-           'diffEncoding': js.string('$diffEncoding')}));
-      if (!minify) {
-        statements.add(js.statement('var longNames = #longs.split(",")',
-                {'longs': js.string(longs.join(','))}));
+  String _computeDiffEncoding() {
+    StringBuffer buffer = new StringBuffer();
+    for (jsAst.ArrayInitializer list in ast.elements) {
+      if (buffer.isNotEmpty) {
+        // Emit period that resets the diff base to zero when we switch to
+        // normal calling convention (this avoids the need to code negative
+        // diffs).
+        buffer.write(".");
       }
-      statements.add(js.statement(
-          'if (objectClassObject instanceof Array)'
-          '  objectClassObject = objectClassObject[1];'));
+      List<jsAst.Name> names = list.elements;
+      _computeDiffEncodingForList(names, buffer);
+    }
+    return '"${buffer.toString()}"';
+  }
+
+  String get value {
+    if (_cachedValue == null) {
+      _cachedValue = _computeDiffEncoding();
     }
 
-    List<jsAst.Expression> sliceOffsetArguments =
-        firstNormalSelector == 0
-        ? []
-        : (firstNormalSelector == shorts.length
-            ? [js.number(1)]
-            : [js('(j < #) ? 1 : 0', js.number(firstNormalSelector))]);
-
-    var sliceOffsetParams = sliceOffsetArguments.isEmpty ? [] : ['sliceOffset'];
-
-    statements.add(js.statement('''
-      // If we are loading a deferred library the object class will not be in
-      // the collectedClasses so objectClassObject is undefined, and we skip
-      // setting up the names.
-      if (objectClassObject) {
-        for (var j = 0; j < shortNames.length; j++) {
-          var type = 0;
-          var short = shortNames[j];
-          if (short[0] == "${namer.getterPrefix[0]}") type = 1;
-          if (short[0] == "${namer.setterPrefix[0]}") type = 2;
-          // Generate call to:
-          //
-          //     createInvocationMirror(String name, internalName, type,
-          //         arguments, argumentNames)
-          //
-          objectClassObject[short] = (function(name, short,
-                                               type, #sliceOffsetParams) {
-              return function() {
-                return this.#noSuchMethodName(this,
-                    #createInvocationMirror(name, short, type,
-                        Array.prototype.slice.call(arguments,
-                                                   #sliceOffsetParams),
-                                                   []));
-              }
-          })(#names[j], short, type, #sliceOffsetArguments);
-        }
-      }''', {
-          'sliceOffsetParams': sliceOffsetParams,
-          'noSuchMethodName': namer.noSuchMethodName,
-          'createInvocationMirror': createInvocationMirror,
-          'names': minify ? 'shortNames' : 'longNames',
-          'sliceOffsetArguments': sliceOffsetArguments}));
-
-    return statements;
+    return _cachedValue;
   }
 }
diff --git a/pkg/compiler/lib/src/js_emitter/old_emitter/setup_program_builder.dart b/pkg/compiler/lib/src/js_emitter/old_emitter/setup_program_builder.dart
index 58ad5bd..115ec4f 100644
--- a/pkg/compiler/lib/src/js_emitter/old_emitter/setup_program_builder.dart
+++ b/pkg/compiler/lib/src/js_emitter/old_emitter/setup_program_builder.dart
@@ -133,7 +133,8 @@
      'trivialNsmHandlers': emitter.buildTrivialNsmHandlers(),
      'hasRetainedMetadata': backend.hasRetainedMetadata,
      'types': typesAccess,
-     'objectClassName': js.string(namer.runtimeTypeName(compiler.objectClass)),
+     'objectClassName': js.quoteName(
+         namer.runtimeTypeName(compiler.objectClass)),
      'needsStructuredMemberInfo': emitter.needsStructuredMemberInfo,
      'usesMangledNames':
           compiler.mirrorsLibrary != null || compiler.enabledFunctionApply,
@@ -577,7 +578,7 @@
         }
       // ${ClassBuilder.fieldEncodingDescription}.
       var s = fields.split(";");
-      fields = s[1] == "" ? [] : s[1].split(",");
+      fields = s[1] ? s[1].split(",") : [];
       supr = s[0];
       // ${ClassBuilder.functionTypeEncodingDescription}.
       split = supr.split(":");
diff --git a/pkg/compiler/lib/src/js_emitter/parameter_stub_generator.dart b/pkg/compiler/lib/src/js_emitter/parameter_stub_generator.dart
index 2e9ed21..92cf30e 100644
--- a/pkg/compiler/lib/src/js_emitter/parameter_stub_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/parameter_stub_generator.dart
@@ -83,7 +83,6 @@
     // Includes extra receiver argument when using interceptor convention
     int indexOfLastOptionalArgumentInParameters = optionalParameterStart - 1;
 
-    int parameterIndex = 0;
     parameters.orderedForEachParameter((ParameterElement element) {
       String jsName = backend.namer.safeVariableName(element.name);
       assert(jsName != receiverArgumentName);
@@ -126,7 +125,7 @@
     } else if (member.isInstanceMember) {
       if (needsSuperGetter(member)) {
         ClassElement superClass = member.enclosingClass;
-        String methodName = namer.instanceMethodName(member);
+        jsAst.Name methodName = namer.instanceMethodName(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.
@@ -149,8 +148,8 @@
 
     jsAst.Fun function = js('function(#) { #; }', [parametersBuffer, body]);
 
-    String name = namer.invocationName(selector);
-    String callName =
+    jsAst.Name name = namer.invocationName(selector);
+    jsAst.Name callName =
         (callSelector != null) ? namer.invocationName(callSelector) : null;
     return new ParameterStubMethod(name, callName, function);
   }
@@ -201,28 +200,28 @@
     // 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;
+    Map<Selector, TypeMaskSet> 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;
+    Map<Selector, TypeMaskSet> callSelectors;
 
     // Only instance members (not static methods) need stubs.
     if (member.isInstanceMember) {
-        selectors = compiler.codegenWorld.invokedNames[member.name];
+        selectors = compiler.codegenWorld.invocationsByName(member.name);
     }
 
     if (canTearOff) {
       String call = namer.closureInvocationSelectorName;
-      callSelectors = compiler.codegenWorld.invokedNames[call];
+      callSelectors = compiler.codegenWorld.invocationsByName(call);
     }
 
     assert(emptySelectorSet.isEmpty);
-    if (selectors == null) selectors = emptySelectorSet;
-    if (callSelectors == null) callSelectors = emptySelectorSet;
+    if (selectors == null) selectors = const <Selector, TypeMaskSet>{};
+    if (callSelectors == null) callSelectors = const <Selector, TypeMaskSet>{};
 
     List<ParameterStubMethod> stubs = <ParameterStubMethod>[];
 
@@ -242,7 +241,7 @@
 
     // Start with the callSelectors since they imply the generation of the
     // non-call version.
-    for (Selector selector in callSelectors) {
+    for (Selector selector in callSelectors.keys) {
       Selector renamedSelector = new Selector(
           SelectorKind.CALL,
           member.memberName,
@@ -251,7 +250,7 @@
 
       if (!renamedSelector.appliesUnnamed(member, compiler.world)) continue;
 
-      if (untypedSelectors.add(renamedSelector.asUntyped)) {
+      if (untypedSelectors.add(renamedSelector)) {
         ParameterStubMethod stub =
             generateParameterStub(member, renamedSelector, selector);
         if (stub != null) {
@@ -263,11 +262,14 @@
     // 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) {
+    for (Selector selector in selectors.keys) {
       if (renamedCallSelectors.contains(selector)) continue;
       if (!selector.appliesUnnamed(member, compiler.world)) continue;
+      if (!selectors[selector].applies(member, selector, compiler.world)) {
+        continue;
+      }
 
-      if (untypedSelectors.add(selector.asUntyped)) {
+      if (untypedSelectors.add(selector)) {
         ParameterStubMethod stub =
             generateParameterStub(member, selector, null);
         if (stub != null) {
diff --git a/pkg/compiler/lib/src/js_emitter/program_builder.dart b/pkg/compiler/lib/src/js_emitter/program_builder.dart
index af92768..834fe03 100644
--- a/pkg/compiler/lib/src/js_emitter/program_builder.dart
+++ b/pkg/compiler/lib/src/js_emitter/program_builder.dart
@@ -26,9 +26,8 @@
 
 import '../elements/elements.dart' show ParameterElement, MethodElement;
 
-import '../universe/universe.dart' show Universe;
+import '../universe/universe.dart' show Universe, TypeMaskSet;
 import '../deferred_load.dart' show DeferredLoadTask, OutputUnit;
-import '../constants/expressions.dart' show ConstantExpression, ConstantValue;
 
 part 'registry.dart';
 
@@ -215,7 +214,7 @@
     // a static field.
     _registry.registerHolder(namer.globalObjectForConstant(initialValue));
     js.Expression code = _task.emitter.constantReference(initialValue);
-    String name = namer.globalPropertyName(element);
+    js.Name name = namer.globalPropertyName(element);
     bool isFinal = false;
     bool isLazy = false;
 
@@ -251,7 +250,7 @@
     // before code generation.
     if (code == null) return null;
 
-    String name = namer.globalPropertyName(element);
+    js.Name name = namer.globalPropertyName(element);
     bool isFinal = element.isFinal;
     bool isLazy = true;
     // TODO(floitsch): we shouldn't update the registry in the middle of
@@ -307,7 +306,7 @@
     assert(_compiler.hasIncrementalSupport);
 
     List<Field> instanceFields = _buildFields(element, false);
-    String name = namer.className(element);
+    js.Name name = namer.className(element);
 
     return new Class(
         element, name, null, [], instanceFields, [], [], [], [], [], null,
@@ -337,13 +336,13 @@
         if (method != null) methods.add(method);
       }
       if (member.isGetter || member.isField) {
-        Set<Selector> selectors =
-            _compiler.codegenWorld.invokedNames[member.name];
+        Map<Selector, TypeMaskSet> selectors =
+            _compiler.codegenWorld.invocationsByName(member.name);
         if (selectors != null && !selectors.isEmpty) {
 
-          Map<String, js.Expression> callStubsForMember =
+          Map<js.Name, js.Expression> callStubsForMember =
               classStubGenerator.generateCallStubsForGetter(member, selectors);
-          callStubsForMember.forEach((String name, js.Expression code) {
+          callStubsForMember.forEach((js.Name name, js.Expression code) {
             callStubs.add(_buildStubMethod(name, code, element: member));
           });
         }
@@ -355,9 +354,9 @@
 
     List<StubMethod> noSuchMethodStubs = <StubMethod>[];
     if (backend.enabledNoSuchMethod && element == _compiler.objectClass) {
-      Map<String, Selector> selectors =
+      Map<js.Name, Selector> selectors =
           classStubGenerator.computeSelectorsForNsmHandlers();
-      selectors.forEach((String name, Selector selector) {
+      selectors.forEach((js.Name name, Selector selector) {
         noSuchMethodStubs
             .add(classStubGenerator.generateStubForNoSuchMethod(name,
                                                                 selector));
@@ -367,7 +366,7 @@
     if (element == backend.closureClass) {
       // We add a special getter here to allow for tearing off a closure from
       // itself.
-      String name = namer.getterForMember(Selector.CALL_NAME);
+      js.Name name = namer.getterForMember(Selector.CALL_NAME);
       js.Fun function = js.js('function() { return this; }');
       callStubs.add(_buildStubMethod(name, function));
     }
@@ -391,11 +390,11 @@
             storeFunctionTypeInMetadata: _storeFunctionTypesInMetadata);
 
     List<StubMethod> isChecks = <StubMethod>[];
-    typeTests.properties.forEach((String name, js.Node code) {
+    typeTests.properties.forEach((js.Name name, js.Node code) {
       isChecks.add(_buildStubMethod(name, code));
     });
 
-    String name = namer.className(element);
+    js.Name name = namer.className(element);
     String holderName = namer.globalObjectFor(element);
     // TODO(floitsch): we shouldn't update the registry in the middle of
     // building a class.
@@ -482,22 +481,21 @@
   }
 
   DartMethod _buildMethod(MethodElement element) {
-    String name = namer.methodPropertyName(element);
+    js.Name name = namer.methodPropertyName(element);
     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;
+    js.Name 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)
+    js.Name aliasName = backend.isAliasedSuperMember(element)
         ? namer.aliasedSuperMemberPropertyName(element)
         : null;
 
@@ -523,7 +521,7 @@
       assert(invariant(element, !element.isConstructor));
     }
 
-    String callName = null;
+    js.Name callName = null;
     if (canTearOff) {
       Selector callSelector =
           new Selector.fromElement(element).toCallSelector();
@@ -572,8 +570,8 @@
       js.Expression thisAccess = js.js(r'this.$receiver');
       return backend.rti.getSignatureEncoding(type, thisAccess);
     } else {
-      return js.number(backend.emitter.metadataCollector.
-          reifyTypeForOutputUnit(type, outputUnit));
+      return backend.emitter.metadataCollector
+          .reifyTypeForOutputUnit(type, outputUnit);
     }
   }
 
@@ -591,7 +589,7 @@
   ///
   /// Stub methods may have an element that can be used for code-size
   /// attribution.
-  Method _buildStubMethod(String name, js.Expression code,
+  Method _buildStubMethod(js.Name name, js.Expression code,
                           {Element element}) {
     return new StubMethod(name, code, element: element);
   }
@@ -600,7 +598,7 @@
   // We must evaluate these classes eagerly so that the prototype is
   // accessible.
   void _markEagerInterceptorClasses() {
-    Map<String, Set<ClassElement>> specializedGetInterceptors =
+    Map<js.Name, Set<ClassElement>> specializedGetInterceptors =
         backend.specializedGetInterceptors;
     for (Set<ClassElement> classes in specializedGetInterceptors.values) {
       for (ClassElement element in classes) {
@@ -619,10 +617,10 @@
     // generating the interceptor methods.
     Holder holder = _registry.registerHolder(holderName);
 
-    Map<String, Set<ClassElement>> specializedGetInterceptors =
+    Map<js.Name, Set<ClassElement>> specializedGetInterceptors =
         backend.specializedGetInterceptors;
-    List<String> names = specializedGetInterceptors.keys.toList()..sort();
-    return names.map((String name) {
+    List<js.Name> names = specializedGetInterceptors.keys.toList()..sort();
+    return names.map((js.Name name) {
       Set<ClassElement> classes = specializedGetInterceptors[name];
       js.Expression code = stubGenerator.generateGetInterceptorMethod(classes);
       return new StaticStubMethod(name, holder, code);
@@ -633,8 +631,8 @@
     List<Field> fields = <Field>[];
     _task.oldEmitter.classEmitter.visitFields(
         holder, visitStatics, (VariableElement field,
-                               String name,
-                               String accessorName,
+                               js.Name name,
+                               js.Name accessorName,
                                bool needsGetter,
                                bool needsSetter,
                                bool needsCheckedSetter) {
@@ -684,15 +682,15 @@
     // generating the interceptor methods.
     Holder holder = _registry.registerHolder(holderName);
 
-    List<String> names = backend.oneShotInterceptors.keys.toList()..sort();
-    return names.map((String name) {
+    List<js.Name> names = backend.oneShotInterceptors.keys.toList()..sort();
+    return names.map((js.Name name) {
       js.Expression code = stubGenerator.generateOneShotInterceptor(name);
       return new StaticStubMethod(name, holder, code);
     });
   }
 
   StaticDartMethod _buildStaticMethod(FunctionElement element) {
-    String name = namer.methodPropertyName(element);
+    js.Name name = namer.methodPropertyName(element);
     String holder = namer.globalObjectFor(element);
     js.Expression code = backend.generatedCode[element];
 
@@ -704,11 +702,11 @@
         (canBeReflected ||
             universe.staticFunctionsNeedingGetter.contains(element));
 
-    String tearOffName =
+    js.Name tearOffName =
         needsTearOff ? namer.staticClosureName(element) : null;
 
 
-    String callName = null;
+    js.Name callName = null;
     if (needsTearOff) {
       Selector callSelector =
           new Selector.fromElement(element).toCallSelector();
@@ -754,7 +752,7 @@
     for (ConstantValue constantValue in constantValues) {
       _registry.registerConstant(outputUnit, constantValue);
       assert(!_constants.containsKey(constantValue));
-      String name = namer.constantName(constantValue);
+      js.Name name = namer.constantName(constantValue);
       String constantObject = namer.globalObjectForConstant(constantValue);
       Holder holder = _registry.registerHolder(constantObject);
       Constant constant = new Constant(name, holder, constantValue);
diff --git a/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart b/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart
index 6f294f6..52c4352 100644
--- a/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart
@@ -12,12 +12,12 @@
   /// If the is tests were generated with `storeFunctionTypeInMetadata` set to
   /// `false`, this field is `null`, and the [properties] contain a property
   /// that encodes the function type.
-  int functionTypeIndex;
+  jsAst.Expression functionTypeIndex;
 
   /// The properties that must be installed on the prototype of the
   /// JS constructor of the [ClassElement] for which the is checks were
   /// generated.
-  final Map<String, jsAst.Node> properties = <String, jsAst.Node>{};
+  final Map<jsAst.Name, jsAst.Node> properties = <jsAst.Name, jsAst.Node>{};
 }
 
 class RuntimeTypeGenerator {
@@ -79,7 +79,7 @@
         ClosureFieldElement thisLocal =
             closureData.freeVariableMap[closureData.thisLocal];
         if (thisLocal != null) {
-          String thisName = namer.instanceFieldPropertyName(thisLocal);
+          jsAst.Name thisName = namer.instanceFieldPropertyName(thisLocal);
           thisAccess = js('this.#', thisName);
         }
       }
@@ -90,7 +90,8 @@
       } else {
         RuntimeTypes rti = backend.rti;
         jsAst.Expression encoding = rti.getSignatureEncoding(type, thisAccess);
-        String operatorSignature = namer.operatorSignature;
+        jsAst.Name operatorSignature =
+            namer.asName(namer.operatorSignature);
         result.properties[operatorSignature] = encoding;
       }
     }
@@ -161,7 +162,6 @@
       }
     }
 
-    RuntimeTypes rti = backend.rti;
     ClassElement superclass = cls.superclass;
 
     bool haveSameTypeVariables(ClassElement a, ClassElement b) {
@@ -213,6 +213,7 @@
         call = cls.lookupBackendMember(Compiler.CALL_OPERATOR_NAME);
       }
       if (call != null && call.isFunction) {
+        FunctionElement callFunction = call;
         // A superclass might already implement the Function interface. In such
         // a case, we can avoid emiting the is test here.
         if (!cls.superclass.implementsFunction(compiler)) {
@@ -221,8 +222,8 @@
                                     generateSubstitution,
                                     generated);
         }
-        FunctionType callType = call.computeType(compiler);
-        generateFunctionTypeSignature(call, callType);
+        FunctionType callType = callFunction.computeType(compiler);
+        generateFunctionTypeSignature(callFunction, callType);
       }
     }
 
@@ -267,7 +268,6 @@
 
   List<StubMethod> generateTypeVariableReaderStubs(ClassElement classElement) {
     List<StubMethod> stubs = <StubMethod>[];
-    List typeVariables = [];
     ClassElement superclass = classElement;
     while (superclass != null) {
         for (TypeVariableType parameter in superclass.typeVariables) {
@@ -284,7 +284,7 @@
 
   StubMethod _generateTypeVariableReader(ClassElement cls,
                                          TypeVariableElement element) {
-    String name = namer.nameForReadTypeVariable(element);
+    jsAst.Name name = namer.nameForReadTypeVariable(element);
     int index = RuntimeTypes.getTypeVariableIndex(element);
     jsAst.Expression computeTypeVariable;
 
diff --git a/pkg/compiler/lib/src/js_emitter/type_test_registry.dart b/pkg/compiler/lib/src/js_emitter/type_test_registry.dart
index b9b1ba9..ac333cc 100644
--- a/pkg/compiler/lib/src/js_emitter/type_test_registry.dart
+++ b/pkg/compiler/lib/src/js_emitter/type_test_registry.dart
@@ -53,10 +53,7 @@
     TypeChecks typeChecks = backend.rti.requiredChecks;
     Set<ClassElement> result = new Set<ClassElement>();
     for (ClassElement cls in typeChecks) {
-      for (TypeCheck check in typeChecks[cls]) {
-        result.add(cls);
-        break;
-      }
+      if (typeChecks[cls].isNotEmpty) result.add(cls);
     }
     return result;
   }
diff --git a/pkg/compiler/lib/src/library_loader.dart b/pkg/compiler/lib/src/library_loader.dart
index 86d14f7f..a566d3f 100644
--- a/pkg/compiler/lib/src/library_loader.dart
+++ b/pkg/compiler/lib/src/library_loader.dart
@@ -27,8 +27,6 @@
     LibraryElementX,
     PrefixElementX;
 
-import 'helpers/helpers.dart';  // Included for debug helpers.
-
 import 'native/native.dart' as native;
 
 import 'tree/tree.dart';
diff --git a/pkg/compiler/lib/src/native/behavior.dart b/pkg/compiler/lib/src/native/behavior.dart
index 3fb1c4b..edbefd1 100644
--- a/pkg/compiler/lib/src/native/behavior.dart
+++ b/pkg/compiler/lib/src/native/behavior.dart
@@ -631,7 +631,7 @@
     return behavior;
   }
 
-  static NativeBehavior ofFieldLoad(Element field, Compiler compiler) {
+  static NativeBehavior ofFieldLoad(MemberElement field, Compiler compiler) {
     DartType type = field.computeType(compiler);
     var behavior = new NativeBehavior();
     behavior.typesReturned.add(type);
@@ -642,7 +642,7 @@
     return behavior;
   }
 
-  static NativeBehavior ofFieldStore(Element field, Compiler compiler) {
+  static NativeBehavior ofFieldStore(MemberElement field, Compiler compiler) {
     DartType type = field.computeType(compiler);
     var behavior = new NativeBehavior();
     behavior._escape(type, compiler);
diff --git a/pkg/compiler/lib/src/native/enqueue.dart b/pkg/compiler/lib/src/native/enqueue.dart
index f1339a1..d936d58 100644
--- a/pkg/compiler/lib/src/native/enqueue.dart
+++ b/pkg/compiler/lib/src/native/enqueue.dart
@@ -174,7 +174,6 @@
     libraries.forEach((library) {
       library.implementation.forEachLocalMember((element) {
         if (element.isClass) {
-          String name = element.name;
           String extendsName = findExtendsNameOfClass(element);
           if (extendsName != null) {
             Set<ClassElement> potentialSubclasses =
diff --git a/pkg/compiler/lib/src/patch_parser.dart b/pkg/compiler/lib/src/patch_parser.dart
index 6957cec..f64c5de 100644
--- a/pkg/compiler/lib/src/patch_parser.dart
+++ b/pkg/compiler/lib/src/patch_parser.dart
@@ -125,11 +125,12 @@
          Script;
 import 'elements/elements.dart';
 import 'elements/modelx.dart'
-    show LibraryElementX,
-         MetadataAnnotationX,
+    show BaseFunctionElementX,
          ClassElementX,
-         BaseFunctionElementX;
-import 'helpers/helpers.dart';  // Included for debug helpers.
+         GetterElementX,
+         LibraryElementX,
+         MetadataAnnotationX,
+         SetterElementX;
 import 'library_loader.dart' show LibraryLoader;
 import 'scanner/scannerlib.dart';  // Scanner, Parsers, Listeners
 import 'util/util.dart';
@@ -484,7 +485,8 @@
         MessageKind.PATCH_POINT_TO_GETTER, {'getterName': patch.name});
     return;
   }
-  patchFunction(listener, originField.getter, patch);
+  GetterElementX getter = originField.getter;
+  patchFunction(listener, getter, patch);
 }
 
 void tryPatchSetter(DiagnosticListener listener,
@@ -507,7 +509,8 @@
         MessageKind.PATCH_POINT_TO_SETTER, {'setterName': patch.name});
     return;
   }
-  patchFunction(listener, originField.setter, patch);
+  SetterElementX setter = originField.setter;
+  patchFunction(listener, setter, patch);
 }
 
 void tryPatchConstructor(DiagnosticListener listener,
diff --git a/pkg/compiler/lib/src/resolution/access_semantics.dart b/pkg/compiler/lib/src/resolution/access_semantics.dart
index 17ec4ad..2c741b3 100644
--- a/pkg/compiler/lib/src/resolution/access_semantics.dart
+++ b/pkg/compiler/lib/src/resolution/access_semantics.dart
@@ -17,6 +17,10 @@
 /// Enum representing the different kinds of destinations which a property
 /// access or method or function invocation might refer to.
 enum AccessKind {
+  /// The destination of the conditional access is an instance method, property,
+  /// or field of a class, and thus must be determined dynamically.
+  CONDITIONAL_DYNAMIC_PROPERTY,
+
   /// The destination of the access is an instance method, property, or field
   /// of a class, and thus must be determined dynamically.
   DYNAMIC_PROPERTY,
@@ -256,6 +260,9 @@
 
   DynamicAccess.dynamicProperty(this.target)
       : super._(AccessKind.DYNAMIC_PROPERTY);
+
+  DynamicAccess.ifNotNullProperty(this.target)
+      : super._(AccessKind.CONDITIONAL_DYNAMIC_PROPERTY);
 }
 
 class ConstantAccess extends AccessSemantics {
diff --git a/pkg/compiler/lib/src/resolution/class_hierarchy.dart b/pkg/compiler/lib/src/resolution/class_hierarchy.dart
index f5534a8..13a6855 100644
--- a/pkg/compiler/lib/src/resolution/class_hierarchy.dart
+++ b/pkg/compiler/lib/src/resolution/class_hierarchy.dart
@@ -102,7 +102,7 @@
           'cyclic resolution of class $element');
     }
 
-    InterfaceType type = element.computeType(compiler);
+    element.computeType(compiler);
     scope = new TypeDeclarationScope(scope, element);
     // TODO(ahe): It is not safe to call resolveTypeVariableBounds yet.
     // As a side-effect, this may get us back here trying to
@@ -165,7 +165,7 @@
       } else {
         ConstructorElement superConstructor = superMember;
         Selector callToMatch = new Selector.call("", element.library, 0);
-        superConstructor.computeSignature(compiler);
+        superConstructor.computeType(compiler);
         if (!callToMatch.applies(superConstructor, compiler.world)) {
           MessageKind kind = MessageKind.NO_MATCHING_CONSTRUCTOR_FOR_IMPLICIT;
           compiler.reportError(node, kind);
@@ -243,7 +243,7 @@
           MessageKind.DEPRECATED_TYPEDEF_MIXIN_SYNTAX);
     }
 
-    InterfaceType type = element.computeType(compiler);
+    element.computeType(compiler);
     scope = new TypeDeclarationScope(scope, element);
     resolveTypeVariableBounds(node.typeParameters);
 
@@ -296,14 +296,15 @@
     mixinApplication.supertypeLoadState = STATE_DONE;
     // Replace the synthetic type variables by the original type variables in
     // the returned type (which should be the type actually extended).
-    InterfaceType mixinThisType = mixinApplication.computeType(compiler);
+    InterfaceType mixinThisType = mixinApplication.thisType;
     return mixinThisType.subst(element.typeVariables,
                                mixinThisType.typeArguments);
   }
 
   bool isDefaultConstructor(FunctionElement constructor) {
-    return constructor.name == '' &&
-        constructor.computeSignature(compiler).parameterCount == 0;
+    if (constructor.name != '') return false;
+    constructor.computeType(compiler);
+    return constructor.functionSignature.parameterCount == 0;
   }
 
   FunctionElement createForwardingConstructor(ConstructorElement target,
diff --git a/pkg/compiler/lib/src/resolution/class_members.dart b/pkg/compiler/lib/src/resolution/class_members.dart
index aaa40aa..8b624ba 100644
--- a/pkg/compiler/lib/src/resolution/class_members.dart
+++ b/pkg/compiler/lib/src/resolution/class_members.dart
@@ -9,6 +9,7 @@
          Name,
          PublicName,
          Member,
+         MemberElement,
          MemberSignature,
          LibraryElement,
          ClassElement,
@@ -19,7 +20,6 @@
          MessageKind,
          invariant,
          isPrivateName;
-import '../helpers/helpers.dart';  // Included for debug helpers.
 import '../util/util.dart';
 
 part 'member_impl.dart';
@@ -163,7 +163,7 @@
       LibraryElement library = cls.library;
       InterfaceType thisType = cls.thisType;
 
-      void createMember(Element element) {
+      void createMember(MemberElement element) {
         if (element.isConstructor) return;
         String elementName = element.name;
         if (shouldSkipName(elementName)) return;
diff --git a/pkg/compiler/lib/src/resolution/constructors.dart b/pkg/compiler/lib/src/resolution/constructors.dart
index 27f7ed2..977b688 100644
--- a/pkg/compiler/lib/src/resolution/constructors.dart
+++ b/pkg/compiler/lib/src/resolution/constructors.dart
@@ -42,7 +42,6 @@
   void checkForDuplicateInitializers(FieldElementX field, Node init) {
     // [field] can be null if it could not be resolved.
     if (field == null) return;
-    String name = field.name;
     if (initialized.containsKey(field)) {
       reportDuplicateInitializerError(field, init, initialized[field]);
     } else if (field.isFinal) {
@@ -103,7 +102,6 @@
                                     FunctionExpression functionNode,
                                     Send call) {
     // Resolve the selector and the arguments.
-    ResolverTask resolver = visitor.compiler.resolver;
     visitor.inStaticContext(() {
       visitor.resolveSelector(call, null);
       visitor.resolveArguments(call.argumentsNode);
@@ -253,7 +251,6 @@
             constructor.isRedirectingGenerative = true;
           }
           // Check that there are no field initializing parameters.
-          Compiler compiler = visitor.compiler;
           FunctionSignature signature = constructor.functionSignature;
           signature.forEachParameter((ParameterElement parameter) {
             if (parameter.isInitializingFormal) {
diff --git a/pkg/compiler/lib/src/resolution/members.dart b/pkg/compiler/lib/src/resolution/members.dart
index 6069d4c..5e5bf53 100644
--- a/pkg/compiler/lib/src/resolution/members.dart
+++ b/pkg/compiler/lib/src/resolution/members.dart
@@ -102,6 +102,8 @@
       inCatchBlock = false,
       super(compiler, registry);
 
+  CoreTypes get coreTypes => compiler.coreTypes;
+
   AsyncMarker get currentAsyncMarker {
     if (enclosingElement is FunctionElement) {
       FunctionElement function = enclosingElement;
@@ -166,8 +168,8 @@
     return result;
   }
 
-  visitInStaticContext(Node node) {
-    inStaticContext(() => visit(node));
+  ResolutionResult visitInStaticContext(Node node) {
+    return inStaticContext(() => visit(node));
   }
 
   ErroneousElement reportAndCreateErroneousElement(
@@ -230,7 +232,7 @@
       if (!inInstanceContext) {
         error(node, MessageKind.NO_INSTANCE_AVAILABLE, {'name': node});
       }
-      return null;
+      return const NoneResult();
     } else if (node.isSuper()) {
       if (!inInstanceContext) {
         error(node, MessageKind.NO_SUPER_IN_STATIC);
@@ -238,7 +240,7 @@
       if ((ElementCategory.SUPER & allowedCategory) == 0) {
         error(node, MessageKind.INVALID_USE_OF_SUPER);
       }
-      return null;
+      return const NoneResult();
     } else {
       String name = node.source;
       Element element = lookupInScope(compiler, node, scope, name);
@@ -272,7 +274,7 @@
     }
   }
 
-  ResolutionResult visitTypeAnnotation(TypeAnnotation node) {
+  TypeResult visitTypeAnnotation(TypeAnnotation node) {
     DartType type = resolveTypeAnnotation(node);
     if (inCheckContext) {
       registry.registerIsCheck(type);
@@ -358,19 +360,17 @@
     }
   }
 
-  visitCascade(Cascade node) {
+  ResolutionResult visitCascade(Cascade node) {
     visit(node.expression);
+    return const NoneResult();
   }
 
-  visitCascadeReceiver(CascadeReceiver node) {
+  ResolutionResult visitCascadeReceiver(CascadeReceiver node) {
     visit(node.expression);
+    return const NoneResult();
   }
 
-  visitClassNode(ClassNode node) {
-    internalError(node, "shouldn't be called");
-  }
-
-  visitIn(Node node, Scope nestedScope) {
+  ResolutionResult visitIn(Node node, Scope nestedScope) {
     Scope oldScope = scope;
     scope = nestedScope;
     ResolutionResult result = visit(node);
@@ -382,7 +382,7 @@
    * Introduces new default targets for break and continue
    * before visiting the body of the loop
    */
-  visitLoopBodyIn(Loop loop, Node body, Scope bodyScope) {
+  void visitLoopBodyIn(Loop loop, Node body, Scope bodyScope) {
     JumpTarget element = getOrDefineTarget(loop);
     statementScope.enterLoop(element);
     visitIn(body, bodyScope);
@@ -392,35 +392,42 @@
     }
   }
 
-  visitBlock(Block node) {
+  ResolutionResult visitBlock(Block node) {
     visitIn(node.statements, new BlockScope(scope));
+    return const NoneResult();
   }
 
-  visitDoWhile(DoWhile node) {
+  ResolutionResult visitDoWhile(DoWhile node) {
     visitLoopBodyIn(node, node.body, new BlockScope(scope));
     visit(node.condition);
+    return const NoneResult();
   }
 
-  visitEmptyStatement(EmptyStatement node) { }
+  ResolutionResult visitEmptyStatement(EmptyStatement node) {
+    return const NoneResult();
+  }
 
-  visitExpressionStatement(ExpressionStatement node) {
+  ResolutionResult visitExpressionStatement(ExpressionStatement node) {
     ExpressionStatement oldExpressionStatement = currentExpressionStatement;
     currentExpressionStatement = node;
     visit(node.expression);
     currentExpressionStatement = oldExpressionStatement;
+    return const NoneResult();
   }
 
-  visitFor(For node) {
+  ResolutionResult visitFor(For node) {
     Scope blockScope = new BlockScope(scope);
     visitIn(node.initializer, blockScope);
     visitIn(node.condition, blockScope);
     visitIn(node.update, blockScope);
     visitLoopBodyIn(node, node.body, blockScope);
+    return const NoneResult();
   }
 
-  visitFunctionDeclaration(FunctionDeclaration node) {
+  ResolutionResult visitFunctionDeclaration(FunctionDeclaration node) {
     assert(node.function.name != null);
     visitFunctionExpression(node.function, inFunctionDeclaration: true);
+    return const NoneResult();
   }
 
 
@@ -431,8 +438,9 @@
   ///
   /// This is used to distinguish local function declarations from anonymous
   /// function expressions.
-  visitFunctionExpression(FunctionExpression node,
-                          {bool inFunctionDeclaration: false}) {
+  ResolutionResult visitFunctionExpression(
+      FunctionExpression node,
+      {bool inFunctionDeclaration: false}) {
     bool doAddToScope = inFunctionDeclaration;
     if (!inFunctionDeclaration && node.name != null) {
       compiler.reportError(
@@ -480,13 +488,15 @@
 
     registry.registerClosure(function);
     registry.registerInstantiatedClass(compiler.functionClass);
+    return const NoneResult();
   }
 
-  visitIf(If node) {
+  ResolutionResult visitIf(If node) {
     doInPromotionScope(node.condition.expression, () => visit(node.condition));
     doInPromotionScope(node.thenPart,
         () => visitIn(node.thenPart, new BlockScope(scope)));
     visitIn(node.elsePart, new BlockScope(scope));
+    return const NoneResult();
   }
 
   ResolutionResult resolveSend(Send node) {
@@ -530,29 +540,27 @@
     Element target;
     String name = node.selector.asIdentifier().source;
     if (identical(name, 'this')) {
-      // TODO(ahe): Why is this using GENERIC?
-      error(node.selector, MessageKind.GENERIC,
-            {'text': "expected an identifier"});
-      return null;
+      error(node.selector, MessageKind.THIS_PROPERTY);
+      return const NoneResult();
     } else if (node.isSuperCall) {
       if (node.isOperator) {
         if (isUserDefinableOperator(name)) {
           name = selector.name;
         } else {
           error(node.selector, MessageKind.ILLEGAL_SUPER_SEND, {'name': name});
-          return null;
+          return const NoneResult();
         }
       }
       if (!inInstanceContext) {
         error(node.receiver, MessageKind.NO_INSTANCE_AVAILABLE, {'name': name});
-        return null;
+        return const NoneResult();
       }
       if (currentClass.supertype == null) {
         // This is just to guard against internal errors, so no need
         // for a real error message.
         error(node.receiver, MessageKind.GENERIC,
               {'text': "Object has no superclass"});
-        return null;
+        return const NoneResult();
       }
       // TODO(johnniwinther): Ensure correct behavior if currentClass is a
       // patch.
@@ -566,12 +574,12 @@
         // We still need to register the invocation, because we might
         // call [:super.noSuchMethod:] which calls
         // [JSInvocationMirror._invokeOn].
-        registry.registerDynamicInvocation(selector);
+        registry.registerDynamicInvocation(
+            new UniverseSelector(selector, null));
         registry.registerSuperNoSuchMethod();
       }
-    } else if (resolvedReceiver == null ||
-               Elements.isUnresolved(resolvedReceiver.element)) {
-      return null;
+    } else if (Elements.isUnresolved(resolvedReceiver.element)) {
+      return const NoneResult();
     } else if (resolvedReceiver.element.isClass) {
       ClassElement receiverClass = resolvedReceiver.element;
       receiverClass.ensureResolved(compiler);
@@ -582,7 +590,7 @@
         // The following code that looks up the selector on the resolved
         // receiver will treat the second as the invocation of a static operator
         // if the resolved receiver is not null.
-        return null;
+        return const NoneResult();
       }
       MembersCreator.computeClassMembersByName(
           compiler, receiverClass.declaration, name);
@@ -630,7 +638,7 @@
         classElement.ensureResolved(compiler);
       }
     }
-    return new ElementResult(target);
+    return new ResolutionResult.forElement(target);
   }
 
   static Selector computeSendSelector(Send node,
@@ -750,7 +758,14 @@
       type = registry.getType(node.selector);
     }
     if (type == null) {
-      type = target.computeType(compiler);
+      if (target.isTypedef || target.isClass) {
+        TypeDeclarationElement typeDeclaration = target;
+        typeDeclaration.computeType(compiler);
+        type = typeDeclaration.rawType;
+      } else {
+        TypeVariableElement typeVariable = target;
+        type = typeVariable.type;
+      }
     }
     registry.registerTypeLiteral(node, type);
 
@@ -804,7 +819,7 @@
   }
 
   /// Compute the [AccessSemantics] corresponding to a super access of [target].
-  AccessSemantics computeSuperAccess(Spannable node, Element target) {
+  AccessSemantics computeSuperAccessSemantics(Spannable node, Element target) {
     if (target.isErroneous) {
       return new StaticAccess.unresolvedSuper(target);
     } else if (target.isGetter) {
@@ -812,7 +827,11 @@
     } else if (target.isSetter) {
       return new StaticAccess.superSetter(target);
     } else if (target.isField) {
-      return new StaticAccess.superField(target);
+      if (target.isFinal) {
+        return new StaticAccess.superFinalField(target);
+      } else {
+        return new StaticAccess.superField(target);
+      }
     } else {
       assert(invariant(node, target.isFunction,
           message: "Unexpected super target '$target'."));
@@ -820,6 +839,78 @@
     }
   }
 
+  /// Compute the [AccessSemantics] corresponding to a local access of [target].
+  AccessSemantics computeLocalAccessSemantics(Spannable node,
+                                              LocalElement target) {
+    if (target.isParameter) {
+      if (target.isFinal || target.isConst) {
+        return new StaticAccess.finalParameter(target);
+      } else {
+        return new StaticAccess.parameter(target);
+      }
+    } else if (target.isVariable) {
+      if (target.isFinal || target.isConst) {
+        return new StaticAccess.finalLocalVariable(target);
+      } else {
+        return new StaticAccess.localVariable(target);
+      }
+    } else {
+      assert(invariant(node, target.isFunction,
+          message: "Unexpected local target '$target'."));
+      return new StaticAccess.localFunction(target);
+    }
+  }
+
+  /// Compute the [AccessSemantics] corresponding to a static or toplevel access
+  /// of [target].
+  AccessSemantics computeStaticOrTopLevelAccessSemantics(
+      Spannable node,
+      Element target) {
+
+    target = target.declaration;
+    if (target.isErroneous) {
+      // This handles elements with parser errors.
+      // TODO(johnniwinther): Elements with parse error should not set
+      // [isErroneous] to `true`.
+      return new StaticAccess.unresolved(target);
+    }
+    if (target.isStatic) {
+      if (target.isGetter) {
+        return new StaticAccess.staticGetter(target);
+      } else if (target.isSetter) {
+        return new StaticAccess.staticSetter(target);
+      } else if (target.isField) {
+        if (target.isFinal || target.isConst) {
+          return new StaticAccess.finalStaticField(target);
+        } else {
+          return new StaticAccess.staticField(target);
+        }
+      } else {
+        assert(invariant(node, target.isFunction,
+            message: "Unexpected static target '$target'."));
+        return new StaticAccess.staticMethod(target);
+      }
+     } else {
+       assert(invariant(node, target.isTopLevel,
+           message: "Unexpected statically resolved target '$target'."));
+       if (target.isGetter) {
+         return new StaticAccess.topLevelGetter(target);
+       } else if (target.isSetter) {
+         return new StaticAccess.topLevelSetter(target);
+       } else if (target.isField) {
+         if (target.isFinal) {
+           return new StaticAccess.finalTopLevelField(target);
+         } else {
+           return new StaticAccess.topLevelField(target);
+         }
+       } else {
+         assert(invariant(node, target.isFunction,
+             message: "Unexpected top level target '$target'."));
+         return new StaticAccess.topLevelMethod(target);
+       }
+     }
+  }
+
   /// Compute the [AccessSemantics] for accessing the name of [selector] on the
   /// super class.
   ///
@@ -836,9 +927,11 @@
   ///       foo => super.name; // Access to the setter.
   ///     }
   ///
-  AccessSemantics computeSuperSemantics(Spannable node,
-                                        Selector selector,
-                                        {Name alternateName}) {
+  AccessSemantics computeSuperAccessSemanticsForSelector(
+      Spannable node,
+      Selector selector,
+      {Name alternateName}) {
+
     Name name = selector.memberName;
     // TODO(johnniwinther): Ensure correct behavior if currentClass is a
     // patch.
@@ -857,13 +950,13 @@
       }
       // We still need to register the invocation, because we might
       // call [:super.noSuchMethod:] which calls [JSInvocationMirror._invokeOn].
-      registry.registerDynamicInvocation(selector);
+      registry.registerDynamicInvocation(new UniverseSelector(selector, null));
       registry.registerSuperNoSuchMethod();
     }
-    return computeSuperAccess(node, target);
+    return computeSuperAccessSemantics(node, target);
   }
 
-  /// Resolve [node] as subexpression that is _not_ the prefix of a member
+  /// Resolve [node] as a subexpression that is _not_ the prefix of a member
   /// access. For instance `a` in `a + b`, as opposed to `a` in `a.b`.
   ResolutionResult visitExpression(Node node) {
     bool oldSendIsMemberAccess = sendIsMemberAccess;
@@ -873,6 +966,39 @@
     return result;
   }
 
+  /// Resolve [node] as a subexpression that _is_ the prefix of a member access.
+  /// For instance `a` in `a.b`, as opposed to `a` in `a + b`.
+  ResolutionResult visitExpressionPrefix(Node node) {
+    int oldAllowedCategory = allowedCategory;
+    bool oldSendIsMemberAccess = sendIsMemberAccess;
+    allowedCategory |= ElementCategory.PREFIX | ElementCategory.SUPER;
+    sendIsMemberAccess = true;
+    ResolutionResult result = visit(node);
+    sendIsMemberAccess = oldSendIsMemberAccess;
+    allowedCategory = oldAllowedCategory;
+    return result;
+  }
+
+  /// Resolved [node] as a subexpression that is the prefix of a conditional
+  /// access. For instance `a` in `a?.b`.
+  // TODO(johnniwinther): Is this equivalent to [visitExpression]?
+  ResolutionResult visitConditionalPrefix(Node node) {
+    // Conditional sends like `e?.foo` treat the receiver as an expression.  So
+    // `C?.foo` needs to be treated like `(C).foo`, not like C.foo. Prefixes and
+    // super are not allowed on their own in that context.
+    int oldAllowedCategory = allowedCategory;
+    bool oldSendIsMemberAccess = sendIsMemberAccess;
+    sendIsMemberAccess = false;
+    allowedCategory =
+        ElementCategory.VARIABLE |
+        ElementCategory.FUNCTION |
+        ElementCategory.IMPLIES_TYPE;
+    ResolutionResult result = visit(node);
+    sendIsMemberAccess = oldSendIsMemberAccess;
+    allowedCategory = oldAllowedCategory;
+    return result;
+  }
+
   /// Handle a type test expression, like `a is T` and `a is! T`.
   ResolutionResult handleIs(Send node) {
     Node expression = node.receiver;
@@ -897,7 +1023,7 @@
     }
     registry.registerIsCheck(type);
     registry.registerSendStructure(node, sendStructure);
-    return null;
+    return const NoneResult();
   }
 
   /// Handle a type cast expression, like `a as T`.
@@ -909,7 +1035,7 @@
     DartType type = resolveTypeAnnotation(typeNode);
     registry.registerAsCheck(type);
     registry.registerSendStructure(node, new AsStructure(type));
-    return null;
+    return const NoneResult();
   }
 
   /// Handle the unary expression of an unresolved unary operator [text], like
@@ -923,12 +1049,13 @@
     }
 
     registry.registerSendStructure(node, const InvalidUnaryStructure());
-    return null;
+    return const NoneResult();
   }
 
   /// Handle the unary expression of a user definable unary [operator], like
   /// `-a`, and `-super`.
   ResolutionResult handleUserDefinableUnary(Send node, UnaryOperator operator) {
+    ResolutionResult result = const NoneResult();
     Node expression = node.receiver;
     Selector selector = operator.selector;
     // TODO(johnniwinther): Remove this when all information goes through the
@@ -938,7 +1065,7 @@
     AccessSemantics semantics;
     if (node.isSuperCall) {
       if (checkSuperAccess(node)) {
-        semantics = computeSuperSemantics(node, selector);
+        semantics = computeSuperAccessSemanticsForSelector(node, selector);
         // TODO(johnniwinther): Add information to [AccessSemantics] about
         // whether it is erroneous.
         if (semantics.kind == AccessKind.SUPER_METHOD) {
@@ -949,9 +1076,38 @@
         registry.useElement(node, semantics.element);
       }
     } else {
-      visitExpression(expression);
+      ResolutionResult expressionResult = visitExpression(expression);
       semantics = new DynamicAccess.dynamicProperty(expression);
-      registry.registerDynamicInvocation(selector);
+      registry.registerDynamicInvocation(new UniverseSelector(selector, null));
+
+      if (expressionResult.isConstant) {
+        bool isValidConstant;
+        ConstantExpression expressionConstant = expressionResult.constant;
+        DartType knownExpressionType =
+            expressionConstant.getKnownType(coreTypes);
+        switch (operator.kind) {
+          case UnaryOperatorKind.COMPLEMENT:
+            isValidConstant =
+                knownExpressionType == coreTypes.intType;
+            break;
+          case UnaryOperatorKind.NEGATE:
+            isValidConstant =
+                knownExpressionType == coreTypes.intType ||
+                knownExpressionType == coreTypes.doubleType;
+            break;
+          case UnaryOperatorKind.NOT:
+            internalError(node,
+                "Unexpected user definable unary operator: $operator");
+        }
+        if (isValidConstant) {
+          // TODO(johnniwinther): Handle potentially invalid constant
+          // expressions.
+          ConstantExpression constant =
+              new UnaryConstantExpression(operator, expressionConstant);
+          registry.setConstant(node, constant);
+          result = new ConstantResult(node, constant);
+        }
+      }
     }
     if (semantics != null) {
       // TODO(johnniwinther): Support invalid super access as an
@@ -959,7 +1115,7 @@
       registry.registerSendStructure(node,
           new UnaryStructure(semantics, operator));
     }
-    return null;
+    return result;
   }
 
   /// Handle a not expression, like `!a`.
@@ -967,30 +1123,75 @@
     assert(invariant(node, operator.kind == UnaryOperatorKind.NOT));
 
     Node expression = node.receiver;
-    visitExpression(expression);
+    ResolutionResult result = visitExpression(expression);
     registry.registerSendStructure(node,
         new NotStructure(new DynamicAccess.dynamicProperty(expression)));
-    return null;
+
+    if (result.isConstant) {
+      ConstantExpression expressionConstant = result.constant;
+      if (expressionConstant.getKnownType(coreTypes) == coreTypes.boolType) {
+        // TODO(johnniwinther): Handle potentially invalid constant expressions.
+        ConstantExpression constant =
+            new UnaryConstantExpression(operator, expressionConstant);
+        registry.setConstant(node, constant);
+        return new ConstantResult(node, constant);
+      }
+    }
+
+    return const NoneResult();
   }
 
   /// Handle a logical and expression, like `a && b`.
   ResolutionResult handleLogicalAnd(Send node) {
     Node left = node.receiver;
     Node right = node.arguments.head;
-    doInPromotionScope(left, () => visitExpression(left));
-    doInPromotionScope(right, () => visitExpression(right));
+    ResolutionResult leftResult =
+        doInPromotionScope(left, () => visitExpression(left));
+    ResolutionResult rightResult =
+        doInPromotionScope(right, () => visitExpression(right));
     registry.registerSendStructure(node, const LogicalAndStructure());
-    return null;
+
+    if (leftResult.isConstant && rightResult.isConstant) {
+      ConstantExpression leftConstant = leftResult.constant;
+      ConstantExpression rightConstant = rightResult.constant;
+      if (leftConstant.getKnownType(coreTypes) == coreTypes.boolType &&
+          rightConstant.getKnownType(coreTypes) == coreTypes.boolType) {
+        // TODO(johnniwinther): Handle potentially invalid constant expressions.
+        ConstantExpression constant = new BinaryConstantExpression(
+            leftConstant,
+            BinaryOperator.LOGICAL_AND,
+            rightConstant);
+        registry.setConstant(node, constant);
+        return new ConstantResult(node, constant);
+      }
+    }
+
+    return const NoneResult();
   }
 
   /// Handle a logical or expression, like `a || b`.
   ResolutionResult handleLogicalOr(Send node) {
     Node left = node.receiver;
     Node right = node.arguments.head;
-    visitExpression(left);
-    visitExpression(right);
+    ResolutionResult leftResult = visitExpression(left);
+    ResolutionResult rightResult = visitExpression(right);
     registry.registerSendStructure(node, const LogicalOrStructure());
-    return null;
+
+    if (leftResult.isConstant && rightResult.isConstant) {
+      ConstantExpression leftConstant = leftResult.constant;
+      ConstantExpression rightConstant = rightResult.constant;
+      if (leftConstant.getKnownType(coreTypes) == coreTypes.boolType &&
+          rightConstant.getKnownType(coreTypes) == coreTypes.boolType) {
+        // TODO(johnniwinther): Handle potentially invalid constant expressions.
+        ConstantExpression constant = new BinaryConstantExpression(
+            leftConstant,
+            BinaryOperator.LOGICAL_OR,
+            rightConstant);
+        registry.setConstant(node, constant);
+        return new ConstantResult(node, constant);
+      }
+    }
+    return const NoneResult();
   }
 
   /// Handle an if-null expression, like `a ?? b`.
@@ -1000,7 +1201,7 @@
     visitExpression(left);
     visitExpression(right);
     registry.registerSendStructure(node, const IfNullStructure());
-    return null;
+    return const NoneResult();
   }
 
   /// Handle the binary expression of an unresolved binary operator [text], like
@@ -1015,13 +1216,14 @@
     }
     visitExpression(right);
     registry.registerSendStructure(node, const InvalidBinaryStructure());
-    return null;
+    return const NoneResult();
   }
 
   /// Handle the binary expression of a user definable binary [operator], like
   /// `a + b`, `super + b`, `a == b` and `a != b`.
   ResolutionResult handleUserDefinableBinary(Send node,
                                              BinaryOperator operator) {
+    ResolutionResult result = const NoneResult();
     Node left = node.receiver;
     Node right = node.arguments.head;
     AccessSemantics semantics;
@@ -1037,7 +1239,7 @@
 
     if (node.isSuperCall) {
       if (checkSuperAccess(node)) {
-        semantics = computeSuperSemantics(node, selector);
+        semantics = computeSuperAccessSemanticsForSelector(node, selector);
         // TODO(johnniwinther): Add information to [AccessSemantics] about
         // whether it is erroneous.
         if (semantics.kind == AccessKind.SUPER_METHOD) {
@@ -1047,12 +1249,88 @@
         // the [SendStructure].
         registry.useElement(node, semantics.element);
       }
+      visitExpression(right);
     } else {
-      visitExpression(left);
-      registry.registerDynamicInvocation(selector);
+      ResolutionResult leftResult = visitExpression(left);
+      ResolutionResult rightResult = visitExpression(right);
+      registry.registerDynamicInvocation(new UniverseSelector(selector, null));
       semantics = new DynamicAccess.dynamicProperty(left);
+
+      if (leftResult.isConstant && rightResult.isConstant) {
+        bool isValidConstant;
+        ConstantExpression leftConstant = leftResult.constant;
+        ConstantExpression rightConstant = leftResult.constant;
+        DartType knownLeftType = leftConstant.getKnownType(coreTypes);
+        DartType knownRightType = rightConstant.getKnownType(coreTypes);
+        switch (operator.kind) {
+          case BinaryOperatorKind.EQ:
+          case BinaryOperatorKind.NOT_EQ:
+            isValidConstant =
+                (knownLeftType == coreTypes.intType ||
+                 knownLeftType == coreTypes.doubleType ||
+                 knownLeftType == coreTypes.stringType ||
+                 knownLeftType == coreTypes.boolType ||
+                 knownLeftType == coreTypes.nullType) &&
+                (knownRightType == coreTypes.intType ||
+                 knownRightType == coreTypes.doubleType ||
+                 knownRightType == coreTypes.stringType ||
+                 knownRightType == coreTypes.boolType ||
+                 knownRightType == coreTypes.nullType);
+            break;
+          case BinaryOperatorKind.ADD:
+            isValidConstant =
+                (knownLeftType == coreTypes.intType ||
+                 knownLeftType == coreTypes.doubleType ||
+                 knownLeftType == coreTypes.stringType) &&
+                (knownRightType == coreTypes.intType ||
+                 knownRightType == coreTypes.doubleType ||
+                 knownRightType == coreTypes.stringType);
+            break;
+          case BinaryOperatorKind.SUB:
+          case BinaryOperatorKind.MUL:
+          case BinaryOperatorKind.DIV:
+          case BinaryOperatorKind.IDIV:
+          case BinaryOperatorKind.MOD:
+          case BinaryOperatorKind.GTEQ:
+          case BinaryOperatorKind.GT:
+          case BinaryOperatorKind.LTEQ:
+          case BinaryOperatorKind.LT:
+            isValidConstant =
+                (knownLeftType == coreTypes.intType ||
+                 knownLeftType == coreTypes.doubleType) &&
+                (knownRightType == coreTypes.intType ||
+                 knownRightType == coreTypes.doubleType);
+            break;
+          case BinaryOperatorKind.SHL:
+          case BinaryOperatorKind.SHR:
+          case BinaryOperatorKind.AND:
+          case BinaryOperatorKind.OR:
+          case BinaryOperatorKind.XOR:
+            isValidConstant =
+                knownLeftType == coreTypes.intType &&
+                knownRightType == coreTypes.intType;
+            break;
+          case BinaryOperatorKind.INDEX:
+            isValidConstant = false;
+            break;
+          case BinaryOperatorKind.LOGICAL_AND:
+          case BinaryOperatorKind.LOGICAL_OR:
+          case BinaryOperatorKind.IF_NULL:
+            internalError(node, "Unexpected binary operator '${operator}'.");
+            break;
+        }
+        if (isValidConstant) {
+          // TODO(johnniwinther): Handle potentially invalid constant
+          // expressions.
+          ConstantExpression constant = new BinaryConstantExpression(
+              leftResult.constant,
+              operator,
+              rightResult.constant);
+          registry.setConstant(node, constant);
+          result = new ConstantResult(node, constant);
+        }
+      }
     }
-    visitExpression(right);
 
     if (semantics != null) {
       // TODO(johnniwinther): Support invalid super access as an
@@ -1093,7 +1371,7 @@
       }
       registry.registerSendStructure(node, sendStructure);
     }
-    return null;
+    return result;
   }
 
   /// Handle an invocation of an expression, like `(){}()` or `(foo)()`.
@@ -1107,10 +1385,10 @@
     // TODO(johnniwinther): Remove this when all information goes through the
     // [SendStructure].
     registry.setSelector(node, selector);
-    registry.registerDynamicInvocation(selector);
+    registry.registerDynamicInvocation(new UniverseSelector(selector, null));
     registry.registerSendStructure(node,
         new InvokeStructure(new AccessSemantics.expression(), selector));
-    return null;
+    return const NoneResult();
   }
 
   /// Handle a, possibly invalid, assertion, like `assert(cond)` or `assert()`.
@@ -1143,26 +1421,8 @@
   /// Handle access of a property of [name] on `this`, like `this.name` and
   /// `this.name()`, or `name` and `name()` in instance context.
   ResolutionResult handleThisPropertyAccess(Send node, Name name) {
-    AccessSemantics accessSemantics = new AccessSemantics.thisProperty();
-    SendStructure sendStructure;
-    Selector selector;
-    if (node.isCall) {
-      CallStructure callStructure = resolveArguments(node.argumentsNode);
-      selector = new Selector(SelectorKind.CALL, name, callStructure);
-      registry.registerDynamicInvocation(selector);
-      sendStructure = new InvokeStructure(accessSemantics, selector);
-    } else {
-      assert(invariant(node, node.isPropertyAccess));
-      selector = new Selector(
-          SelectorKind.GETTER, name, CallStructure.NO_ARGS);
-      registry.registerDynamicGetter(selector);
-      sendStructure = new GetStructure(accessSemantics, selector);
-    }
-    registry.registerSendStructure(node, sendStructure);
-    // TODO(johnniwinther): Remove this when all information goes through
-    // the [SendStructure].
-    registry.setSelector(node, selector);
-    return null;
+    AccessSemantics semantics = new AccessSemantics.thisProperty();
+    return handleDynamicAccessSemantics(node, name, semantics);
   }
 
   /// Handle access on `this`, like `this()` and `this` when it is parsed as a
@@ -1175,7 +1435,8 @@
       // TODO(johnniwinther): Handle invalid this access as an
       // [AccessSemantics].
       if (checkThisAccess(node)) {
-        registry.registerDynamicInvocation(selector);
+        registry.registerDynamicInvocation(
+            new UniverseSelector(selector, null));
         registry.registerSendStructure(node,
             new InvokeStructure(accessSemantics, selector));
       }
@@ -1186,7 +1447,7 @@
       // TODO(johnniwinther): Handle get of `this` when it is a [Send] node.
       internalError(node, "Unexpected node '$node'.");
     }
-    return null;
+    return const NoneResult();
   }
 
   /// Handle access of a super property, like `super.foo` and `super.foo()`.
@@ -1201,7 +1462,7 @@
       selector = new Selector(SelectorKind.GETTER, name, callStructure);
     }
     if (checkSuperAccess(node)) {
-      AccessSemantics semantics = computeSuperSemantics(
+      AccessSemantics semantics = computeSuperAccessSemanticsForSelector(
           node, selector, alternateName: name.setter);
       if (node.isCall) {
         bool isIncompatibleInvoke = false;
@@ -1211,7 +1472,8 @@
             superMethod.computeSignature(compiler);
             if (!callStructure.signatureApplies(superMethod)) {
               registry.registerThrowNoSuchMethod();
-              registry.registerDynamicInvocation(selector);
+              registry.registerDynamicInvocation(
+                  new UniverseSelector(selector, null));
               registry.registerSuperNoSuchMethod();
               isIncompatibleInvoke = true;
             } else {
@@ -1219,10 +1481,12 @@
             }
             break;
           case AccessKind.SUPER_FIELD:
+          case AccessKind.SUPER_FINAL_FIELD:
           case AccessKind.SUPER_GETTER:
             registry.registerStaticUse(semantics.element);
             selector = callStructure.callSelector;
-            registry.registerDynamicInvocation(selector);
+            registry.registerDynamicInvocation(
+                new UniverseSelector(selector, null));
             break;
           case AccessKind.SUPER_SETTER:
           case AccessKind.UNRESOLVED_SUPER:
@@ -1244,6 +1508,7 @@
             registry.registerStaticUse(semantics.element);
             break;
           case AccessKind.SUPER_FIELD:
+          case AccessKind.SUPER_FINAL_FIELD:
           case AccessKind.SUPER_GETTER:
             registry.registerStaticUse(semantics.element);
             break;
@@ -1265,7 +1530,7 @@
     // the [SendStructure].
     registry.useElement(node, target);
     registry.setSelector(node, selector);
-    return null;
+    return const NoneResult();
   }
 
   /// Handle a [Send] whose selector is an [Operator], like `a && b`, `a is T`,
@@ -1328,12 +1593,181 @@
     }
   }
 
+  /// Handle qualified access to an unresolved static class member, like `a.b`
+  /// or `a.b()` where `a` is a class and `b` is unresolved.
+  ResolutionResult handleUnresolvedStaticMemberAccess(
+      Send node, Name name, ClassElement receiverClass) {
+    // TODO(johnniwinther): Share code with [handleStaticInstanceMemberAccess]
+    // and [handlePrivateStaticMemberAccess].
+    registry.registerThrowNoSuchMethod();
+    // TODO(johnniwinther): Produce a different error if [name] is resolves to
+    // a constructor.
+
+    // TODO(johnniwinther): With the simplified [TreeElements] invariant,
+    // try to resolve injected elements if [currentClass] is in the patch
+    // library of [receiverClass].
+
+    // TODO(karlklose): this should be reported by the caller of
+    // [resolveSend] to select better warning messages for getters and
+    // setters.
+    ErroneousElement error = reportAndCreateErroneousElement(
+        node, name.text, MessageKind.MEMBER_NOT_FOUND,
+        {'className': receiverClass.name, 'memberName': name.text});
+    // TODO(johnniwinther): Add an [AccessSemantics] for unresolved static
+    // member access.
+    return handleErroneousAccess(
+        node, name, error, new StaticAccess.unresolved(error));
+  }
+
+  /// Handle qualified access of an instance member, like `a.b` or `a.b()` where
+  /// `a` is a class and `b` is a non-static member.
+  ResolutionResult handleStaticInstanceMemberAccess(
+      Send node, Name name, ClassElement receiverClass, Element member) {
+
+    registry.registerThrowNoSuchMethod();
+    // TODO(johnniwinther): With the simplified [TreeElements] invariant,
+    // try to resolve injected elements if [currentClass] is in the patch
+    // library of [receiverClass].
+
+    // TODO(karlklose): this should be reported by the caller of
+    // [resolveSend] to select better warning messages for getters and
+    // setters.
+    ErroneousElement error = reportAndCreateErroneousElement(
+        node, name.text, MessageKind.MEMBER_NOT_STATIC,
+        {'className': receiverClass.name, 'memberName': name});
+
+    // TODO(johnniwinther): Add an [AccessSemantics] for statically accessed
+    // instance members.
+    return handleErroneousAccess(
+        node, name, error, new StaticAccess.unresolved(error));
+  }
+
+  /// Handle qualified access of an inaccessible private static class member,
+  /// like `a._b` or `a.b()` where `a` is class, `_b` is static member of `a`
+  /// but `a` is not defined in the current library.
+  ResolutionResult handlePrivateStaticMemberAccess(
+      Send node, Name name, ClassElement receiverClass, Element member) {
+    registry.registerThrowNoSuchMethod();
+    ErroneousElement error = reportAndCreateErroneousElement(
+        node, name.text, MessageKind.PRIVATE_ACCESS,
+        {'libraryName': member.library.getLibraryOrScriptName(),
+         'name': name});
+    // TODO(johnniwinther): Add an [AccessSemantics] for unresolved static
+    // member access.
+    return handleErroneousAccess(
+        node, name, error, new StaticAccess.unresolved(error));
+  }
+
+  /// Handle qualified access to a static member, like `a.b` or `a.b()` where
+  /// `a` is a class and `b` is a static member of `a`.
+  ResolutionResult handleStaticMemberAccess(
+      Send node, Name memberName, ClassElement receiverClass) {
+    String name = memberName.text;
+    receiverClass.ensureResolved(compiler);
+    if (node.isOperator) {
+      // When the resolved receiver is a class, we can have two cases:
+      //  1) a static send: C.foo, or
+      //  2) an operator send, where the receiver is a class literal: 'C + 1'.
+      // The following code that looks up the selector on the resolved
+      // receiver will treat the second as the invocation of a static operator
+      // if the resolved receiver is not null.
+      return const NoneResult();
+    }
+    MembersCreator.computeClassMembersByName(
+        compiler, receiverClass.declaration, name);
+    Element member = receiverClass.lookupLocalMember(name);
+    if (member == null) {
+      return handleUnresolvedStaticMemberAccess(
+          node, memberName, receiverClass);
+    } else if (member.isAmbiguous) {
+      return handleAmbiguousSend(node, memberName, member);
+    } else if (member.isInstanceMember) {
+      return handleStaticInstanceMemberAccess(
+          node, memberName, receiverClass, member);
+    } else if (memberName.isPrivate && memberName.library != member.library) {
+      return handlePrivateStaticMemberAccess(
+          node, memberName, receiverClass, member);
+    } else {
+      return handleStaticOrTopLevelAccess(node, memberName, member);
+    }
+  }
+
+  /// Handle qualified [Send] where the receiver resolves to an [Element], like
+  /// `a.b` where `a` is a local, field, class, or prefix, etc.
+  ResolutionResult handleResolvedQualifiedSend(
+      Send node, Name name, Element element) {
+    if (element.isPrefix) {
+      return oldVisitSend(node);
+    } else if (element.isClass) {
+      return handleStaticMemberAccess(node, name, element);
+    }
+    return oldVisitSend(node);
+  }
+
+  /// Handle dynamic access of [semantics].
+  ResolutionResult handleDynamicAccessSemantics(
+      Send node, Name name, AccessSemantics semantics) {
+    SendStructure sendStructure;
+    Selector selector;
+    if (node.isCall) {
+      CallStructure callStructure = resolveArguments(node.argumentsNode);
+      selector = new Selector(SelectorKind.CALL, name, callStructure);
+      registry.registerDynamicInvocation(
+          new UniverseSelector(selector, null));
+      sendStructure = new InvokeStructure(semantics, selector);
+    } else {
+      assert(invariant(node, node.isPropertyAccess));
+      selector = new Selector(
+          SelectorKind.GETTER, name, CallStructure.NO_ARGS);
+      registry.registerDynamicGetter(
+          new UniverseSelector(selector, null));
+      sendStructure = new GetStructure(semantics, selector);
+    }
+    registry.registerSendStructure(node, sendStructure);
+    // TODO(johnniwinther): Remove this when all information goes through
+    // the [SendStructure].
+    registry.setSelector(node, selector);
+    return const NoneResult();
+  }
+
+  /// Handle dynamic property access, like `a.b` or `a.b()` where `a` is not a
+  /// prefix or class.
+  ResolutionResult handleDynamicPropertyAccess(Send node, Name name) {
+    AccessSemantics semantics =
+        new DynamicAccess.dynamicProperty(node.receiver);
+    return handleDynamicAccessSemantics(node, name, semantics);
+  }
+
+  /// Handle conditional access, like `a?.b` or `a?.b()`.
+  ResolutionResult handleConditionalAccess(Send node, Name name) {
+    Node receiver = node.receiver;
+    visitConditionalPrefix(receiver);
+    AccessSemantics semantics =
+        new DynamicAccess.ifNotNullProperty(receiver);
+    return handleDynamicAccessSemantics(node, name, semantics);
+  }
+
+  /// Handle `this` as a qualified property, like `a.this`.
+  ResolutionResult handleQualifiedThisAccess(Send node, Name name) {
+    ErroneousElement error = reportAndCreateErroneousElement(
+        node.selector,
+        name.text,
+        MessageKind.THIS_PROPERTY, {},
+        isError: true);
+    // TODO(johnniwinther): Support `this` as property as an [AccessSemantics].
+    AccessSemantics accessSemantics = new StaticAccess.unresolved(error);
+    return handleErroneousAccess(node, name, error, accessSemantics);
+  }
+
   /// Handle a qualified [Send], that is where the receiver is non-null, like
   /// `a.b`, `a.b()`, `this.a()` and `super.a()`.
   ResolutionResult handleQualifiedSend(Send node) {
     Identifier selector = node.selector.asIdentifier();
-    Name name = new Name(selector.source, enclosingElement.library);
-    if (node.isSuperCall) {
+    String text = selector.source;
+    Name name = new Name(text, enclosingElement.library);
+    if (text == 'this') {
+      return handleQualifiedThisAccess(node, name);
+    } else if (node.isSuperCall) {
       return handleSuperPropertyAccess(node, name);
     } else if (node.receiver.isThis()) {
       if (checkThisAccess(node)) {
@@ -1341,10 +1775,16 @@
       }
       // TODO(johnniwinther): Handle invalid this access as an
       // [AccessSemantics].
-      return null;
+      return const NoneResult();
+    } else if (node.isConditional) {
+      return handleConditionalAccess(node, name);
     }
-    // TODO(johnniwinther): Handle remaining qualified sends.
-    return oldVisitSend(node);
+    ResolutionResult result = visitExpressionPrefix(node.receiver);
+    if (result.element != null) {
+      return handleResolvedQualifiedSend(node, name, result.element);
+    } else {
+      return handleDynamicPropertyAccess(node, name);
+    }
   }
 
   /// Handle access unresolved access to [name] in a non-instance context.
@@ -1353,18 +1793,26 @@
     // TODO(johnniwinther): Support unresolved top level access as an
     // [AccessSemantics].
     AccessSemantics accessSemantics = new StaticAccess.unresolved(element);
+    return handleErroneousAccess(node, name, element, accessSemantics);
+  }
+
+  /// Handle erroneous access of [element] of the given [accessSemantics].
+  ResolutionResult handleErroneousAccess(
+      Send node, Name name, Element element, AccessSemantics accessSemantics) {
     SendStructure sendStructure;
     Selector selector;
     if (node.isCall) {
       CallStructure callStructure = resolveArguments(node.argumentsNode);
       selector = new Selector(SelectorKind.CALL, name, callStructure);
-      registry.registerDynamicInvocation(selector);
+      registry.registerDynamicInvocation(
+          new UniverseSelector(selector, null));
       sendStructure = new InvokeStructure(accessSemantics, selector);
     } else {
       assert(invariant(node, node.isPropertyAccess));
       selector = new Selector(
           SelectorKind.GETTER, name, CallStructure.NO_ARGS);
-      registry.registerDynamicGetter(selector);
+      registry.registerDynamicGetter(
+          new UniverseSelector(selector, null));
       sendStructure = new GetStructure(accessSemantics, selector);
     }
     // TODO(johnniwinther): Remove this when all information goes through
@@ -1372,7 +1820,255 @@
     registry.setSelector(node, selector);
     registry.useElement(node, element);
     registry.registerSendStructure(node, sendStructure);
-    return null;
+    return const NoneResult();
+  }
+
+  /// Handle access to an ambiguous element, that is, a name imported twice.
+  ResolutionResult handleAmbiguousSend(
+      Send node,
+      Name name,
+      AmbiguousElement element) {
+
+    compiler.reportError(
+        node, element.messageKind, element.messageArguments);
+    element.diagnose(enclosingElement, compiler);
+
+    ErroneousElement error = new ErroneousElementX(
+        element.messageKind,
+        element.messageArguments,
+        name.text,
+        enclosingElement);
+
+    // TODO(johnniwinther): Support ambiguous access as an [AccessSemantics].
+    AccessSemantics accessSemantics = new StaticAccess.unresolved(error);
+    return handleErroneousAccess(node, name, error, accessSemantics);
+  }
+
+  /// Handle access of an instance [member] from a non-instance context.
+  ResolutionResult handleStaticInstanceSend(
+      Send node, Name name, MemberElement member) {
+    compiler.reportError(
+        node, MessageKind.NO_INSTANCE_AVAILABLE, {'name': member.name});
+    ErroneousElement error = new ErroneousElementX(
+        MessageKind.NO_INSTANCE_AVAILABLE,
+        {'name': name},
+        name.text,
+        enclosingElement);
+
+    // TODO(johnniwinther): Support static instance access as an
+    // [AccessSemantics].
+    AccessSemantics accessSemantics = new StaticAccess.unresolved(error);
+    return handleErroneousAccess(node, name, error, accessSemantics);
+  }
+
+  /// Handle access of a parameter, local variable or local function.
+  ResolutionResult handleLocalAccess(Send node, Name name, Element element) {
+    AccessSemantics semantics = computeLocalAccessSemantics(node, element);
+    Selector selector;
+    CallStructure callStructure = CallStructure.NO_ARGS;
+    if (node.isCall) {
+      callStructure = resolveArguments(node.argumentsNode);
+      selector = new Selector(SelectorKind.CALL, name, callStructure);
+    } else {
+      selector = new Selector(SelectorKind.GETTER, name, callStructure);
+    }
+    if (node.isCall) {
+      bool isIncompatibleInvoke = false;
+      switch (semantics.kind) {
+        case AccessKind.LOCAL_FUNCTION:
+          LocalFunctionElementX function = semantics.element;
+          function.computeSignature(compiler);
+          if (!callStructure.signatureApplies(function)) {
+            registry.registerThrowNoSuchMethod();
+            registry.registerDynamicInvocation(
+                new UniverseSelector(selector, null));
+            isIncompatibleInvoke = true;
+          }
+          break;
+        case AccessKind.PARAMETER:
+        case AccessKind.FINAL_PARAMETER:
+        case AccessKind.LOCAL_VARIABLE:
+        case AccessKind.FINAL_LOCAL_VARIABLE:
+          selector = callStructure.callSelector;
+          registry.registerDynamicInvocation(
+              new UniverseSelector(selector, null));
+          break;
+        default:
+          internalError(node,
+              "Unexpected local access $semantics.");
+          break;
+      }
+      registry.registerSendStructure(node,
+          isIncompatibleInvoke
+              ? new IncompatibleInvokeStructure(semantics, selector)
+              : new InvokeStructure(semantics, selector));
+    } else {
+      registry.registerSendStructure(node,
+          new GetStructure(semantics, selector));
+    }
+
+    // TODO(johnniwinther): Remove these when all information goes through
+    // the [SendStructure].
+    registry.useElement(node, element);
+    registry.setSelector(node, selector);
+
+    registerPotentialAccessInClosure(node, element);
+
+    return node.isPropertyAccess
+        ? new ElementResult(element) : const NoneResult();
+  }
+
+  /// Handle access of a static or top level [element].
+  ResolutionResult handleStaticOrTopLevelAccess(
+        Send node, Name name, Element element) {
+
+    MemberElement member;
+    if (element.isAbstractField) {
+      AbstractFieldElement abstractField = element;
+      if (abstractField.getter != null) {
+        member = abstractField.getter;
+      } else {
+        member = abstractField.setter;
+      }
+    } else {
+      member = element;
+    }
+    // TODO(johnniwinther): Needed to provoke a parsing and with it discovery
+    // of parse errors to make [element] erroneous. Fix this!
+    member.computeType(compiler);
+
+    Selector selector;
+    CallStructure callStructure = CallStructure.NO_ARGS;
+    if (node.isCall) {
+      callStructure = resolveArguments(node.argumentsNode);
+      selector = new Selector(SelectorKind.CALL, name, callStructure);
+    } else {
+      selector = new Selector(SelectorKind.GETTER, name, callStructure);
+    }
+    AccessSemantics semantics =
+        computeStaticOrTopLevelAccessSemantics(node, member);
+    if (node.isCall) {
+      bool isIncompatibleInvoke = false;
+      switch (semantics.kind) {
+        case AccessKind.STATIC_METHOD:
+        case AccessKind.TOPLEVEL_METHOD:
+          MethodElementX method = semantics.element;
+          method.computeSignature(compiler);
+          if (!callStructure.signatureApplies(method)) {
+            registry.registerThrowNoSuchMethod();
+            registry.registerDynamicInvocation(
+                new UniverseSelector(selector, null));
+            isIncompatibleInvoke = true;
+          } else {
+            registry.registerStaticUse(semantics.element);
+            handleForeignCall(node, semantics.element, selector);
+          }
+          break;
+        case AccessKind.STATIC_FIELD:
+        case AccessKind.FINAL_STATIC_FIELD:
+        case AccessKind.STATIC_GETTER:
+        case AccessKind.TOPLEVEL_FIELD:
+        case AccessKind.FINAL_TOPLEVEL_FIELD:
+        case AccessKind.TOPLEVEL_GETTER:
+          registry.registerStaticUse(semantics.element);
+          selector = callStructure.callSelector;
+          registry.registerDynamicInvocation(
+              new UniverseSelector(selector, null));
+          break;
+        case AccessKind.STATIC_SETTER:
+        case AccessKind.TOPLEVEL_SETTER:
+        case AccessKind.UNRESOLVED:
+          registry.registerThrowNoSuchMethod();
+          member = reportAndCreateErroneousElement(
+              node.selector, name.text,
+              MessageKind.CANNOT_RESOLVE_GETTER, const {});
+          break;
+        default:
+          internalError(node,
+              "Unexpected statically resolved access $semantics.");
+          break;
+      }
+      registry.registerSendStructure(node,
+          isIncompatibleInvoke
+              ? new IncompatibleInvokeStructure(semantics, selector)
+              : new InvokeStructure(semantics, selector));
+    } else {
+      switch (semantics.kind) {
+        case AccessKind.STATIC_METHOD:
+        case AccessKind.TOPLEVEL_METHOD:
+          // TODO(johnniwinther): Method this should be registered as a
+          // closurization.
+          registry.registerStaticUse(semantics.element);
+          registry.registerGetOfStaticFunction(semantics.element);
+          break;
+        case AccessKind.STATIC_FIELD:
+        case AccessKind.FINAL_STATIC_FIELD:
+        case AccessKind.STATIC_GETTER:
+        case AccessKind.TOPLEVEL_FIELD:
+        case AccessKind.FINAL_TOPLEVEL_FIELD:
+        case AccessKind.TOPLEVEL_GETTER:
+          registry.registerStaticUse(semantics.element);
+          break;
+        case AccessKind.STATIC_SETTER:
+        case AccessKind.TOPLEVEL_SETTER:
+        case AccessKind.UNRESOLVED:
+          registry.registerThrowNoSuchMethod();
+          member = reportAndCreateErroneousElement(
+              node.selector, name.text,
+              MessageKind.CANNOT_RESOLVE_GETTER, const {});
+          break;
+        default:
+          internalError(node,
+              "Unexpected statically resolved access $semantics.");
+          break;
+      }
+      registry.registerSendStructure(node,
+          new GetStructure(semantics, selector));
+    }
+
+    // TODO(johnniwinther): Remove these when all information goes through
+    // the [SendStructure].
+    registry.useElement(node, member);
+    registry.setSelector(node, selector);
+
+    return node.isPropertyAccess
+        ? new ElementResult(member) : const NoneResult();
+  }
+
+  /// Handle access to resolved [element].
+  ResolutionResult handleResolvedSend(Send node, Name name, Element element) {
+    if (element.isAmbiguous) {
+      return handleAmbiguousSend(node, name, element);
+    }
+    if (element.isErroneous) {
+      // This handles elements with parser errors.
+      // TODO(johnniwinther): Elements with parse error should not set
+      // [isErroneous] to `true`.
+      assert(invariant(node, element is! ErroneousElement,
+          message: "Unexpected erroneous element $element."));
+      return handleErroneousAccess(node, name, element,
+          new StaticAccess.unresolved(element));
+    }
+    if (element.isInstanceMember) {
+      if (inInstanceContext) {
+        // TODO(johnniwinther): Maybe use the found [element].
+        return handleThisPropertyAccess(node, name);
+      } else {
+        return handleStaticInstanceSend(node, name, element);
+      }
+    }
+    if (element.isClass || element.isTypedef) {
+      return oldVisitSend(node);
+    } else if (element.isTypeVariable) {
+      return oldVisitSend(node);
+    } else if (element.isPrefix) {
+      return oldVisitSend(node);
+    } else if (element.isLocal) {
+      return handleLocalAccess(node, name, element);
+    } else if (element.isStatic || element.isTopLevel) {
+      return handleStaticOrTopLevelAccess(node, name, element);
+    }
+    return internalError(node, "Unexpected resolved send: $element");
   }
 
   /// Handle an unqualified [Send], that is where the `node.receiver` is null,
@@ -1407,19 +2103,33 @@
         ErroneousElement error = reportCannotResolve(node, text);
         return handleUnresolvedAccess(node, name, error);
       }
+    } else {
+      return handleResolvedSend(node, name, element);
     }
-    return oldVisitSend(node);
   }
 
   ResolutionResult visitSend(Send node) {
     if (node.isOperator) {
+      // `a && b`, `a + b`, `-a`, or `a is T`.
       return handleOperatorSend(node);
     } else if (node.receiver != null) {
+      // `a.b`.
       return handleQualifiedSend(node);
     } else {
+      // `a`.
       return handleUnqualifiedSend(node);
     }
-    return oldVisitSend(node);
+  }
+
+  /// Regigster read access of [target] inside a closure.
+  void registerPotentialAccessInClosure(Send node, Element target) {
+    if (isPotentiallyMutableTarget(target)) {
+      if (enclosingElement != target.enclosingElement) {
+        for (Node scope in promotionScope) {
+          registry.setAccessedByClosureIn(scope, target, node);
+        }
+      }
+    }
   }
 
   ResolutionResult oldVisitSend(Send node) {
@@ -1429,7 +2139,7 @@
     ResolutionResult result = resolveSend(node);
     sendIsMemberAccess = oldSendIsMemberAccess;
 
-    Element target = result != null ? result.element : null;
+    Element target = result.element;
 
     if (target != null
         && target == compiler.mirrorSystemGetNameFunction
@@ -1467,22 +2177,15 @@
       } else if (target.impliesType && (!sendIsMemberAccess || node.isCall)) {
         registerTypeLiteralAccess(node, target);
       }
-      if (isPotentiallyMutableTarget(target)) {
-        if (enclosingElement != target.enclosingElement) {
-          for (Node scope in promotionScope) {
-            registry.setAccessedByClosureIn(scope, target, node);
-          }
-        }
-      }
+      registerPotentialAccessInClosure(node, target);
     }
 
-    bool resolvedArguments = false;
     resolveArguments(node.argumentsNode);
 
     // If the selector is null, it means that we will not be generating
     // code for this as a send.
     Selector selector = registry.getSelector(node);
-    if (selector == null) return null;
+    if (selector == null) return const NoneResult();
 
     if (node.isCall) {
       if (Elements.isUnresolved(target) ||
@@ -1493,7 +2196,8 @@
         // we need to register that fact that we may be calling a closure
         // with the same arguments.
         Selector call = new Selector.callClosureFrom(selector);
-        registry.registerDynamicInvocation(call);
+        registry.registerDynamicInvocation(
+            new UniverseSelector(selector, null));
       } else if (target.impliesType) {
         // We call 'call()' on a Type instance returned from the reference to a
         // class or typedef literal. We do not need to register this call as a
@@ -1501,7 +2205,7 @@
       } else {
         if (target is FunctionElement) {
           FunctionElement function = target;
-          function.computeSignature(compiler);
+          function.computeType(compiler);
         }
         if (!selector.applies(target, compiler.world)) {
           registry.registerThrowNoSuchMethod();
@@ -1511,23 +2215,7 @@
         }
       }
 
-      if (target != null && compiler.backend.isForeign(target)) {
-        if (selector.name == 'JS') {
-          registry.registerJsCall(node, this);
-        } else if (selector.name == 'JS_EMBEDDED_GLOBAL') {
-          registry.registerJsEmbeddedGlobalCall(node, this);
-        } else if (selector.name == 'JS_BUILTIN') {
-          registry.registerJsBuiltinCall(node, this);
-        } else if (selector.name == 'JS_INTERCEPTOR_CONSTANT') {
-          if (!node.argumentsNode.isEmpty) {
-            Node argument = node.argumentsNode.nodes.head;
-            if (argumentsToJsInterceptorConstant == null) {
-              argumentsToJsInterceptorConstant = new Set<Node>();
-            }
-            argumentsToJsInterceptorConstant.add(argument);
-          }
-        }
-      }
+      handleForeignCall(node, target, selector);
     }
 
     registry.useElement(node, target);
@@ -1535,7 +2223,29 @@
     if (node.isPropertyAccess && Elements.isStaticOrTopLevelFunction(target)) {
       registry.registerGetOfStaticFunction(target.declaration);
     }
-    return node.isPropertyAccess ? new ElementResult(target) : null;
+    return node.isPropertyAccess
+        ? new ResolutionResult.forElement(target) : const NoneResult();
+  }
+
+  // TODO(johnniwinther): Move this to the backend resolution callbacks.
+  void handleForeignCall(Send node, Element target, Selector selector) {
+    if (target != null && compiler.backend.isForeign(target)) {
+      if (selector.name == 'JS') {
+        registry.registerJsCall(node, this);
+      } else if (selector.name == 'JS_EMBEDDED_GLOBAL') {
+        registry.registerJsEmbeddedGlobalCall(node, this);
+      } else if (selector.name == 'JS_BUILTIN') {
+        registry.registerJsBuiltinCall(node, this);
+      } else if (selector.name == 'JS_INTERCEPTOR_CONSTANT') {
+        if (!node.argumentsNode.isEmpty) {
+          Node argument = node.argumentsNode.nodes.head;
+          if (argumentsToJsInterceptorConstant == null) {
+            argumentsToJsInterceptorConstant = new Set<Node>();
+          }
+          argumentsToJsInterceptorConstant.add(argument);
+        }
+      }
+    }
   }
 
   /// Callback for native enqueuer to parse a type.  Returns [:null:] on error.
@@ -1553,7 +2263,7 @@
     sendIsMemberAccess = node.isPropertyAccess || node.isCall;
     ResolutionResult result = resolveSend(node);
     sendIsMemberAccess = oldSendIsMemberAccess;
-    Element target = result != null ? result.element : null;
+    Element target = result.element;
     Element setter = target;
     Element getter = target;
     String operatorName = node.assignmentOperator.source;
@@ -1662,7 +2372,8 @@
       // the ++ and -- ones.  Also, if op= form is used, include op itself.
       void registerBinaryOperator(String name) {
         Selector binop = new Selector.binaryOperator(name);
-        registry.registerDynamicInvocation(binop);
+        registry.registerDynamicInvocation(
+            new UniverseSelector(binop, null));
         registry.setOperatorSelectorInComplexSendSet(node, binop);
       }
       if (identical(source, '++')) {
@@ -1677,17 +2388,20 @@
     }
 
     registerSend(selector, setter);
-    return new ElementResult(registry.useElement(node, setter));
+    return new ResolutionResult.forElement(registry.useElement(node, setter));
   }
 
   void registerSend(Selector selector, Element target) {
     if (target == null || target.isInstanceMember) {
       if (selector.isGetter) {
-        registry.registerDynamicGetter(selector);
+        registry.registerDynamicGetter(
+            new UniverseSelector(selector, null));
       } else if (selector.isSetter) {
-        registry.registerDynamicSetter(selector);
+        registry.registerDynamicSetter(
+            new UniverseSelector(selector, null));
       } else {
-        registry.registerDynamicInvocation(selector);
+        registry.registerDynamicInvocation(
+            new UniverseSelector(selector, null));
       }
     } else if (Elements.isStaticOrTopLevel(target)) {
       // Avoid registration of type variables since they are not analyzable but
@@ -1700,60 +2414,90 @@
     }
   }
 
-  visitLiteralInt(LiteralInt node) {
-    registry.registerInstantiatedClass(compiler.intClass);
+  ConstantResult visitLiteralInt(LiteralInt node) {
+    registry.registerInstantiatedType(coreTypes.intType);
+    ConstantExpression constant = new IntConstantExpression(node.value);
+    registry.setConstant(node, constant);
+    return new ConstantResult(node, constant);
   }
 
-  visitLiteralDouble(LiteralDouble node) {
-    registry.registerInstantiatedClass(compiler.doubleClass);
+  ConstantResult visitLiteralDouble(LiteralDouble node) {
+    registry.registerInstantiatedType(coreTypes.doubleType);
+    ConstantExpression constant = new DoubleConstantExpression(node.value);
+    registry.setConstant(node, constant);
+    return new ConstantResult(node, constant);
   }
 
-  visitLiteralBool(LiteralBool node) {
-    registry.registerInstantiatedClass(compiler.boolClass);
+  ConstantResult visitLiteralBool(LiteralBool node) {
+    registry.registerInstantiatedType(coreTypes.boolType);
+    ConstantExpression constant = new BoolConstantExpression(node.value);
+    registry.setConstant(node, constant);
+    return new ConstantResult(node, constant);
   }
 
-  visitLiteralString(LiteralString node) {
-    registry.registerInstantiatedClass(compiler.stringClass);
+  ResolutionResult visitLiteralString(LiteralString node) {
+    registry.registerInstantiatedType(coreTypes.stringType);
+    if (node.dartString != null) {
+      // [dartString] might be null on parser errors.
+      ConstantExpression constant =
+          new StringConstantExpression(node.dartString.slowToString());
+      registry.setConstant(node, constant);
+      return new ConstantResult(node, constant);
+    }
+    return const NoneResult();
   }
 
-  visitLiteralNull(LiteralNull node) {
-    registry.registerInstantiatedClass(compiler.nullClass);
+  ConstantResult visitLiteralNull(LiteralNull node) {
+    registry.registerInstantiatedType(coreTypes.nullType);
+    ConstantExpression constant = new NullConstantExpression();
+    registry.setConstant(node, constant);
+    return new ConstantResult(node, constant);
   }
 
-  visitLiteralSymbol(LiteralSymbol node) {
+  ConstantResult visitLiteralSymbol(LiteralSymbol node) {
     registry.registerInstantiatedClass(compiler.symbolClass);
     registry.registerStaticUse(compiler.symbolConstructor.declaration);
-    registry.registerConstSymbol(node.slowNameString);
-    if (!validateSymbol(node, node.slowNameString, reportError: false)) {
+    String name = node.slowNameString;
+    registry.registerConstSymbol(name);
+    if (!validateSymbol(node, name, reportError: false)) {
       compiler.reportError(node,
           MessageKind.UNSUPPORTED_LITERAL_SYMBOL,
-          {'value': node.slowNameString});
+          {'value': name});
     }
     analyzeConstantDeferred(node);
+    ConstantExpression constant = new SymbolConstantExpression(name);
+    registry.setConstant(node, constant);
+    return new ConstantResult(node, constant);
   }
 
-  visitStringJuxtaposition(StringJuxtaposition node) {
-    registry.registerInstantiatedClass(compiler.stringClass);
-    node.visitChildren(this);
+  ResolutionResult visitStringJuxtaposition(StringJuxtaposition node) {
+    registry.registerInstantiatedType(coreTypes.stringType);
+    ResolutionResult first = visit(node.first);
+    ResolutionResult second = visit(node.second);
+    if (first.isConstant && second.isConstant) {
+      ConstantExpression constant = new ConcatenateConstantExpression(
+          <ConstantExpression>[first.constant, second.constant]);
+      registry.setConstant(node, constant);
+      return new ConstantResult(node, constant);
+    }
+    return const NoneResult();
   }
 
-  visitNodeList(NodeList node) {
+  ResolutionResult visitNodeList(NodeList node) {
     for (Link<Node> link = node.nodes; !link.isEmpty; link = link.tail) {
       visit(link.head);
     }
+    return const NoneResult();
   }
 
-  visitOperator(Operator node) {
-    internalError(node, 'operator');
-  }
-
-  visitRethrow(Rethrow node) {
+  ResolutionResult visitRethrow(Rethrow node) {
     if (!inCatchBlock) {
       error(node, MessageKind.THROW_WITHOUT_EXPRESSION);
     }
+    return const NoneResult();
   }
 
-  visitReturn(Return node) {
+  ResolutionResult visitReturn(Return node) {
     Node expression = node.expression;
     if (expression != null) {
       if (enclosingElement.isGenerativeConstructor) {
@@ -1770,15 +2514,17 @@
       }
     }
     visit(node.expression);
+    return const NoneResult();
   }
 
-  visitYield(Yield node) {
+  ResolutionResult visitYield(Yield node) {
     compiler.streamClass.ensureResolved(compiler);
     compiler.iterableClass.ensureResolved(compiler);
     visit(node.expression);
+    return const NoneResult();
   }
 
-  visitRedirectingFactoryBody(RedirectingFactoryBody node) {
+  ResolutionResult visitRedirectingFactoryBody(RedirectingFactoryBody node) {
     final isSymbolConstructor = enclosingElement == compiler.symbolConstructor;
     if (!enclosingElement.isFactoryConstructor) {
       compiler.reportError(
@@ -1802,7 +2548,7 @@
     registry.setRedirectingTargetConstructor(node, redirectionTarget);
     if (Elements.isUnresolved(redirectionTarget)) {
       registry.registerThrowNoSuchMethod();
-      return;
+      return const NoneResult();
     } else {
       if (isConstConstructor &&
           !redirectionTarget.isConst) {
@@ -1826,10 +2572,10 @@
               {'fromType': targetType, 'toType': constructorType});
     }
 
-    FunctionSignature targetSignature =
-        redirectionTarget.computeSignature(compiler);
-    FunctionSignature constructorSignature =
-        constructor.computeSignature(compiler);
+    redirectionTarget.computeType(compiler);
+    FunctionSignature targetSignature = redirectionTarget.functionSignature;
+    constructor.computeType(compiler);
+    FunctionSignature constructorSignature = constructor.functionSignature;
     if (!targetSignature.isCompatibleWith(constructorSignature)) {
       assert(!isSubtype);
       registry.registerThrowNoSuchMethod();
@@ -1848,19 +2594,22 @@
     if (isSymbolConstructor) {
       registry.registerSymbolConstructor();
     }
+    return const NoneResult();
   }
 
-  visitThrow(Throw node) {
+  ResolutionResult visitThrow(Throw node) {
     registry.registerThrowExpression();
     visit(node.expression);
+    return const NoneResult();
   }
 
-  visitAwait(Await node) {
+  ResolutionResult visitAwait(Await node) {
     compiler.futureClass.ensureResolved(compiler);
     visit(node.expression);
+    return const NoneResult();
   }
 
-  visitVariableDefinitions(VariableDefinitions node) {
+  ResolutionResult visitVariableDefinitions(VariableDefinitions node) {
     DartType type;
     if (node.type != null) {
       type = resolveTypeAnnotation(node.type);
@@ -1905,26 +2654,33 @@
           compiler.resolver.resolveMetadata(enclosingElement, node);
     }
     visitor.visit(node.definitions);
+    return const NoneResult();
   }
 
-  visitWhile(While node) {
+  ResolutionResult visitWhile(While node) {
     visit(node.condition);
     visitLoopBodyIn(node, node.body, new BlockScope(scope));
+    return const NoneResult();
   }
 
-  visitParenthesizedExpression(ParenthesizedExpression node) {
+  ResolutionResult visitParenthesizedExpression(ParenthesizedExpression node) {
     bool oldSendIsMemberAccess = sendIsMemberAccess;
     sendIsMemberAccess = false;
     var oldCategory = allowedCategory;
-    allowedCategory = ElementCategory.VARIABLE | ElementCategory.FUNCTION
-        | ElementCategory.IMPLIES_TYPE;
-    visit(node.expression);
+    allowedCategory =
+        ElementCategory.VARIABLE |
+        ElementCategory.FUNCTION |
+        ElementCategory.IMPLIES_TYPE;
+    ResolutionResult result = visit(node.expression);
     allowedCategory = oldCategory;
     sendIsMemberAccess = oldSendIsMemberAccess;
+    if (result.kind == ResultKind.CONSTANT) {
+      return result;
+    }
+    return const NoneResult();
   }
 
   ResolutionResult visitNewExpression(NewExpression node) {
-    Node selector = node.send.selector;
     FunctionElement constructor = resolveConstructor(node);
     final bool isSymbolConstructor = constructor == compiler.symbolConstructor;
     final bool isMirrorsUsedConstant =
@@ -1933,9 +2689,9 @@
     resolveArguments(node.send.argumentsNode);
     registry.useElement(node.send, constructor);
     if (Elements.isUnresolved(constructor)) {
-      return new ElementResult(constructor);
+      return new ResolutionResult.forElement(constructor);
     }
-    constructor.computeSignature(compiler);
+    constructor.computeType(compiler);
     if (!callSelector.applies(constructor, compiler.world)) {
       registry.registerThrowNoSuchMethod();
     }
@@ -1971,7 +2727,7 @@
                 argumentNode, registry.mapping);
         ConstantValue name = compiler.constants.getConstantValue(constant);
         if (!name.isString) {
-          DartType type = name.getType(compiler.coreTypes);
+          DartType type = name.getType(coreTypes);
           compiler.reportError(argumentNode, MessageKind.STRING_EXPECTED,
                                    {'type': type});
         } else {
@@ -1997,7 +2753,7 @@
       analyzeConstantDeferred(node);
     }
 
-    return null;
+    return const NoneResult();
   }
 
   void checkConstMapKeysDontOverrideEquals(Spannable spannable,
@@ -2105,12 +2861,8 @@
     return type;
   }
 
-  visitModifiers(Modifiers node) {
-    internalError(node, 'modifiers');
-  }
-
-  visitLiteralList(LiteralList node) {
-    bool oldSendIsMemberAccess = sendIsMemberAccess;
+  ResolutionResult visitLiteralList(LiteralList node) {
+    bool isValidAsConstant = true;
     sendIsMemberAccess = false;
 
     NodeList arguments = node.typeArguments;
@@ -2120,6 +2872,7 @@
       if (nodes.isEmpty) {
         // The syntax [: <>[] :] is not allowed.
         error(arguments, MessageKind.MISSING_TYPE_ARGUMENT);
+        isValidAsConstant = false;
       } else {
         typeArgument = resolveTypeAnnotation(nodes.head);
         for (nodes = nodes.tail; !nodes.isEmpty; nodes = nodes.tail) {
@@ -2133,47 +2886,98 @@
       if (node.isConst && typeArgument.containsTypeVariables) {
         compiler.reportError(arguments.nodes.head,
             MessageKind.TYPE_VARIABLE_IN_CONSTANT);
+        isValidAsConstant = false;
       }
-      listType = new InterfaceType(compiler.listClass, [typeArgument]);
+      listType = coreTypes.listType(typeArgument);
     } else {
-      compiler.listClass.computeType(compiler);
-      listType = compiler.listClass.rawType;
+      listType = coreTypes.listType();
     }
     registry.setType(node, listType);
     registry.registerInstantiatedType(listType);
     registry.registerRequiredType(listType, enclosingElement);
-    visit(node.elements);
     if (node.isConst) {
+      List<ConstantExpression> constantExpressions = <ConstantExpression>[];
+      for (Node element in node.elements) {
+        ResolutionResult elementResult = visit(element);
+        if (isValidAsConstant && elementResult.isConstant) {
+          constantExpressions.add(elementResult.constant);
+        } else {
+          isValidAsConstant = false;
+        }
+      }
       analyzeConstantDeferred(node);
+      sendIsMemberAccess = false;
+      if (isValidAsConstant) {
+        ConstantExpression constant =
+            new ListConstantExpression(listType, constantExpressions);
+        registry.setConstant(node, constant);
+        return new ConstantResult(node, constant);
+      }
+    } else {
+      visit(node.elements);
+      sendIsMemberAccess = false;
+    }
+    return const NoneResult();
+
+  }
+
+  ResolutionResult visitConditional(Conditional node) {
+    ResolutionResult conditionResult =
+        doInPromotionScope(node.condition, () => visit(node.condition));
+    ResolutionResult thenResult =
+        doInPromotionScope(node.thenExpression, () => visit(node.thenExpression));
+    ResolutionResult elseResult = visit(node.elseExpression);
+    if (conditionResult.isConstant &&
+        thenResult.isConstant &&
+        elseResult.isConstant) {
+      ConstantExpression constant = new ConditionalConstantExpression(
+          conditionResult.constant,
+          thenResult.constant,
+          elseResult.constant);
+      registry.setConstant(node, constant);
+      return new ConstantResult(node, constant);
+    }
+    return const NoneResult();
+  }
+
+  ResolutionResult visitStringInterpolation(StringInterpolation node) {
+    registry.registerInstantiatedType(coreTypes.stringType);
+    registry.registerStringInterpolation();
+    registerImplicitInvocation('toString', 0);
+
+    bool isValidAsConstant = true;
+    List<ConstantExpression> parts = <ConstantExpression>[];
+
+    void resolvePart(Node subnode) {
+      ResolutionResult result = visit(subnode);
+      if (isValidAsConstant && result.isConstant) {
+        parts.add(result.constant);
+      } else {
+        isValidAsConstant = false;
+      }
     }
 
-    sendIsMemberAccess = false;
+    resolvePart(node.string);
+    for (StringInterpolationPart part in node.parts) {
+      resolvePart(part.expression);
+      resolvePart(part.string);
+    }
+
+    if (isValidAsConstant) {
+      ConstantExpression constant = new ConcatenateConstantExpression(parts);
+      registry.setConstant(node, constant);
+      return new ConstantResult(node, constant);
+    }
+    return const NoneResult();
   }
 
-  visitConditional(Conditional node) {
-    doInPromotionScope(node.condition, () => visit(node.condition));
-    doInPromotionScope(node.thenExpression, () => visit(node.thenExpression));
-    visit(node.elseExpression);
-  }
-
-  visitStringInterpolation(StringInterpolation node) {
-    registry.registerInstantiatedClass(compiler.stringClass);
-    registry.registerStringInterpolation();
-    node.visitChildren(this);
-  }
-
-  visitStringInterpolationPart(StringInterpolationPart node) {
-    registerImplicitInvocation('toString', 0);
-    node.visitChildren(this);
-  }
-
-  visitBreakStatement(BreakStatement node) {
+  ResolutionResult visitBreakStatement(BreakStatement node) {
     JumpTarget target;
     if (node.target == null) {
       target = statementScope.currentBreakTarget();
       if (target == null) {
         error(node, MessageKind.NO_BREAK_TARGET);
-        return;
+        return const NoneResult();
       }
       target.isBreakTarget = true;
     } else {
@@ -2181,26 +2985,27 @@
       LabelDefinition label = statementScope.lookupLabel(labelName);
       if (label == null) {
         error(node.target, MessageKind.UNBOUND_LABEL, {'labelName': labelName});
-        return;
+        return const NoneResult();
       }
       target = label.target;
       if (!target.statement.isValidBreakTarget()) {
         error(node.target, MessageKind.INVALID_BREAK);
-        return;
+        return const NoneResult();
       }
       label.setBreakTarget();
       registry.useLabel(node, label);
     }
     registry.registerTargetOf(node, target);
+    return const NoneResult();
   }
 
-  visitContinueStatement(ContinueStatement node) {
+  ResolutionResult visitContinueStatement(ContinueStatement node) {
     JumpTarget target;
     if (node.target == null) {
       target = statementScope.currentContinueTarget();
       if (target == null) {
         error(node, MessageKind.NO_CONTINUE_TARGET);
-        return;
+        return const NoneResult();
       }
       target.isContinueTarget = true;
     } else {
@@ -2208,7 +3013,7 @@
       LabelDefinition label = statementScope.lookupLabel(labelName);
       if (label == null) {
         error(node.target, MessageKind.UNBOUND_LABEL, {'labelName': labelName});
-        return;
+        return const NoneResult();
       }
       target = label.target;
       if (!target.statement.isValidContinueTarget()) {
@@ -2218,45 +3023,55 @@
       registry.useLabel(node, label);
     }
     registry.registerTargetOf(node, target);
+    return const NoneResult();
   }
 
   registerImplicitInvocation(String name, int arity) {
     Selector selector = new Selector.call(name, null, arity);
-    registry.registerDynamicInvocation(selector);
+    registry.registerDynamicInvocation(new UniverseSelector(selector, null));
   }
 
-  visitAsyncForIn(AsyncForIn node) {
+  ResolutionResult visitAsyncForIn(AsyncForIn node) {
     registry.registerAsyncForIn(node);
     registry.setCurrentSelector(node, compiler.currentSelector);
-    registry.registerDynamicGetter(compiler.currentSelector);
+    registry.registerDynamicGetter(
+        new UniverseSelector(compiler.currentSelector, null));
     registry.setMoveNextSelector(node, compiler.moveNextSelector);
-    registry.registerDynamicInvocation(compiler.moveNextSelector);
+    registry.registerDynamicInvocation(
+        new UniverseSelector(compiler.moveNextSelector, null));
 
     visit(node.expression);
 
     Scope blockScope = new BlockScope(scope);
     visitForInDeclaredIdentifierIn(node.declaredIdentifier, node, blockScope);
     visitLoopBodyIn(node, node.body, blockScope);
+    return const NoneResult();
   }
 
-  visitSyncForIn(SyncForIn node) {
+  ResolutionResult visitSyncForIn(SyncForIn node) {
     registry.registerSyncForIn(node);
     registry.setIteratorSelector(node, compiler.iteratorSelector);
-    registry.registerDynamicGetter(compiler.iteratorSelector);
+    registry.registerDynamicGetter(
+        new UniverseSelector(compiler.iteratorSelector, null));
     registry.setCurrentSelector(node, compiler.currentSelector);
-    registry.registerDynamicGetter(compiler.currentSelector);
+    registry.registerDynamicGetter(
+        new UniverseSelector(compiler.currentSelector, null));
     registry.setMoveNextSelector(node, compiler.moveNextSelector);
-    registry.registerDynamicInvocation(compiler.moveNextSelector);
+    registry.registerDynamicInvocation(
+        new UniverseSelector(compiler.moveNextSelector, null));
 
     visit(node.expression);
 
     Scope blockScope = new BlockScope(scope);
     visitForInDeclaredIdentifierIn(node.declaredIdentifier, node, blockScope);
     visitLoopBodyIn(node, node.body, blockScope);
+    return const NoneResult();
   }
 
-  visitForInDeclaredIdentifierIn(Node declaration, ForIn node,
-                                 Scope blockScope) {
+  void visitForInDeclaredIdentifierIn(
+      Node declaration,
+      ForIn node,
+      Scope blockScope) {
     LibraryElement library = enclosingElement.library;
 
     bool oldAllowFinalWithoutInitializer = allowFinalWithoutInitializer;
@@ -2313,7 +3128,7 @@
     // Labels are handled by their containing statements/cases.
   }
 
-  visitLabeledStatement(LabeledStatement node) {
+  ResolutionResult visitLabeledStatement(LabeledStatement node) {
     Statement body = node.statement;
     JumpTarget targetElement = getOrDefineTarget(body);
     Map<String, LabelDefinition> labelElements = <String, LabelDefinition>{};
@@ -2337,9 +3152,11 @@
     if (!targetElement.isTarget) {
       registry.undefineTarget(body);
     }
+    return const NoneResult();
   }
 
-  visitLiteralMap(LiteralMap node) {
+  ResolutionResult visitLiteralMap(LiteralMap node) {
+    bool isValidAsConstant = true;
     sendIsMemberAccess = false;
 
     NodeList arguments = node.typeArguments;
@@ -2350,6 +3167,7 @@
       if (nodes.isEmpty) {
         // The syntax [: <>{} :] is not allowed.
         error(arguments, MessageKind.MISSING_TYPE_ARGUMENT);
+        isValidAsConstant = false;
       } else {
         keyTypeArgument = resolveTypeAnnotation(nodes.head);
         nodes = nodes.tail;
@@ -2366,32 +3184,54 @@
     }
     DartType mapType;
     if (valueTypeArgument != null) {
-      mapType = new InterfaceType(compiler.mapClass,
-          [keyTypeArgument, valueTypeArgument]);
+      mapType = coreTypes.mapType(keyTypeArgument, valueTypeArgument);
     } else {
-      compiler.mapClass.computeType(compiler);
-      mapType = compiler.mapClass.rawType;
+      mapType = coreTypes.mapType();
     }
     if (node.isConst && mapType.containsTypeVariables) {
       compiler.reportError(arguments,
           MessageKind.TYPE_VARIABLE_IN_CONSTANT);
+      isValidAsConstant = false;
     }
     registry.registerMapLiteral(node, mapType, node.isConst);
     registry.registerRequiredType(mapType, enclosingElement);
-    node.visitChildren(this);
     if (node.isConst) {
+      List<ConstantExpression> keyExpressions = <ConstantExpression>[];
+      List<ConstantExpression> valueExpressions = <ConstantExpression>[];
+      for (LiteralMapEntry entry in node.entries) {
+        ResolutionResult keyResult = visit(entry.key);
+        ResolutionResult valueResult = visit(entry.value);
+        if (isValidAsConstant &&
+            keyResult.isConstant &&
+            valueResult.isConstant) {
+          keyExpressions.add(keyResult.constant);
+          valueExpressions.add(valueResult.constant);
+        } else {
+          isValidAsConstant = false;
+        }
+      }
       analyzeConstantDeferred(node);
+      sendIsMemberAccess = false;
+      if (isValidAsConstant) {
+        ConstantExpression constant = new MapConstantExpression(
+            mapType, keyExpressions, valueExpressions);
+        registry.setConstant(node, constant);
+        return new ConstantResult(node, constant);
+      }
+    } else {
+      node.visitChildren(this);
+      sendIsMemberAccess = false;
     }
-
-    sendIsMemberAccess = false;
+    return const NoneResult();
   }
 
-  visitLiteralMapEntry(LiteralMapEntry node) {
+  ResolutionResult visitLiteralMapEntry(LiteralMapEntry node) {
     node.visitChildren(this);
+    return const NoneResult();
   }
 
-  visitNamedArgument(NamedArgument node) {
-    visit(node.expression);
+  ResolutionResult visitNamedArgument(NamedArgument node) {
+    return visit(node.expression);
   }
 
   DartType typeOfConstant(ConstantValue constant) {
@@ -2476,7 +3316,7 @@
     }
   }
 
-  visitSwitchStatement(SwitchStatement node) {
+  ResolutionResult visitSwitchStatement(SwitchStatement node) {
     node.expression.accept(this);
 
     JumpTarget breakElement = getOrDefineTarget(node);
@@ -2547,27 +3387,31 @@
     // TODO(15575): We should warn if we can detect a fall through
     // error.
     registry.registerFallThroughError();
+    return const NoneResult();
   }
 
-  visitSwitchCase(SwitchCase node) {
+  ResolutionResult visitSwitchCase(SwitchCase node) {
     node.labelsAndCases.accept(this);
     visitIn(node.statements, new BlockScope(scope));
+    return const NoneResult();
   }
 
-  visitCaseMatch(CaseMatch node) {
+  ResolutionResult visitCaseMatch(CaseMatch node) {
     visit(node.expression);
+    return const NoneResult();
   }
 
-  visitTryStatement(TryStatement node) {
+  ResolutionResult visitTryStatement(TryStatement node) {
     visit(node.tryBlock);
     if (node.catchBlocks.isEmpty && node.finallyBlock == null) {
       error(node.getEndToken().next, MessageKind.NO_CATCH_NOR_FINALLY);
     }
     visit(node.catchBlocks);
     visit(node.finallyBlock);
+    return const NoneResult();
   }
 
-  visitCatchBlock(CatchBlock node) {
+  ResolutionResult visitCatchBlock(CatchBlock node) {
     registry.registerCatchStatement();
     // Check that if catch part is present, then
     // it has one or two formal parameters.
@@ -2637,10 +3481,7 @@
       registry.registerInstantiatedClass(compiler.stackTraceClass);
       stackTraceElement.variables.type = compiler.stackTraceClass.rawType;
     }
-  }
-
-  visitTypedef(Typedef node) {
-    internalError(node, 'typedef');
+    return const NoneResult();
   }
 }
 
diff --git a/pkg/compiler/lib/src/resolution/registry.dart b/pkg/compiler/lib/src/resolution/registry.dart
index 7d24835..d71e295 100644
--- a/pkg/compiler/lib/src/resolution/registry.dart
+++ b/pkg/compiler/lib/src/resolution/registry.dart
@@ -29,17 +29,17 @@
   }
 
   @override
-  void registerDynamicGetter(Selector selector) {
+  void registerDynamicGetter(UniverseSelector selector) {
     world.registerDynamicGetter(selector);
   }
 
   @override
-  void registerDynamicInvocation(Selector selector) {
+  void registerDynamicInvocation(UniverseSelector selector) {
     world.registerDynamicInvocation(selector);
   }
 
   @override
-  void registerDynamicSetter(Selector selector) {
+  void registerDynamicSetter(UniverseSelector selector) {
     world.registerDynamicSetter(selector);
   }
 
@@ -63,9 +63,9 @@
 
 class ResolutionWorldImpact implements WorldImpact {
   final Registry registry;
-  Setlet<Selector> _dynamicInvocations;
-  Setlet<Selector> _dynamicGetters;
-  Setlet<Selector> _dynamicSetters;
+  Setlet<UniverseSelector> _dynamicInvocations;
+  Setlet<UniverseSelector> _dynamicGetters;
+  Setlet<UniverseSelector> _dynamicSetters;
   Setlet<InterfaceType> _instantiatedTypes;
   Setlet<Element> _staticUses;
   Setlet<DartType> _checkedTypes;
@@ -74,41 +74,43 @@
   ResolutionWorldImpact(Compiler compiler, TreeElementMapping mapping)
       : this.registry = new EagerRegistry(compiler, mapping);
 
-  void registerDynamicGetter(Selector selector) {
+  void registerDynamicGetter(UniverseSelector selector) {
     if (_dynamicGetters == null) {
-      _dynamicGetters = new Setlet<Selector>();
+      _dynamicGetters = new Setlet<UniverseSelector>();
     }
     _dynamicGetters.add(selector);
   }
 
   @override
-  Iterable<Selector> get dynamicGetters {
-    return _dynamicGetters != null ? _dynamicGetters : const <Selector>[];
+  Iterable<UniverseSelector> get dynamicGetters {
+    return _dynamicGetters != null
+        ? _dynamicGetters : const <UniverseSelector>[];
   }
 
-  void registerDynamicInvocation(Selector selector) {
+  void registerDynamicInvocation(UniverseSelector selector) {
     if (_dynamicInvocations == null) {
-      _dynamicInvocations = new Setlet<Selector>();
+      _dynamicInvocations = new Setlet<UniverseSelector>();
     }
     _dynamicInvocations.add(selector);
   }
 
   @override
-  Iterable<Selector> get dynamicInvocations {
+  Iterable<UniverseSelector> get dynamicInvocations {
     return _dynamicInvocations != null
-        ? _dynamicInvocations : const <Selector>[];
+        ? _dynamicInvocations : const <UniverseSelector>[];
   }
 
-  void registerDynamicSetter(Selector selector) {
+  void registerDynamicSetter(UniverseSelector selector) {
     if (_dynamicSetters == null) {
-      _dynamicSetters = new Setlet<Selector>();
+      _dynamicSetters = new Setlet<UniverseSelector>();
     }
     _dynamicSetters.add(selector);
   }
 
   @override
-  Iterable<Selector> get dynamicSetters {
-    return _dynamicSetters != null ? _dynamicSetters : const <Selector>[];
+  Iterable<UniverseSelector> get dynamicSetters {
+    return _dynamicSetters != null
+        ? _dynamicSetters : const <UniverseSelector>[];
   }
 
   void registerInstantiatedType(InterfaceType type) {
@@ -279,6 +281,10 @@
 
   ConstantExpression getConstant(Node node) => mapping.getConstant(node);
 
+  void setConstant(Node node, ConstantExpression constant) {
+    mapping.setConstant(node, constant);
+  }
+
   //////////////////////////////////////////////////////////////////////////////
   //  Target/Label functionality.
   //////////////////////////////////////////////////////////////////////////////
@@ -407,7 +413,7 @@
     mapping.addSuperUse(node);
   }
 
-  void registerDynamicInvocation(Selector selector) {
+  void registerDynamicInvocation(UniverseSelector selector) {
     worldImpact.registerDynamicInvocation(selector);
   }
 
@@ -456,11 +462,11 @@
     worldImpact.registerClosurizedFunction(element);
   }
 
-  void registerDynamicGetter(Selector selector) {
+  void registerDynamicGetter(UniverseSelector selector) {
     worldImpact.registerDynamicGetter(selector);
   }
 
-  void registerDynamicSetter(Selector selector) {
+  void registerDynamicSetter(UniverseSelector selector) {
     worldImpact.registerDynamicSetter(selector);
   }
 
diff --git a/pkg/compiler/lib/src/resolution/resolution.dart b/pkg/compiler/lib/src/resolution/resolution.dart
index 5cb7b3b..ee292e4 100644
--- a/pkg/compiler/lib/src/resolution/resolution.dart
+++ b/pkg/compiler/lib/src/resolution/resolution.dart
@@ -9,6 +9,7 @@
 import '../compile_time_constants.dart';
 import '../constants/expressions.dart';
 import '../constants/values.dart';
+import '../core_types.dart';
 import '../dart_backend/dart_backend.dart' show DartBackend;
 import '../dart_types.dart';
 import '../dart2jslib.dart' hide DynamicAccess;
@@ -28,6 +29,7 @@
     FormalElementX,
     FunctionElementX,
     FunctionSignatureX,
+    GetterElementX,
     InitializingFormalElementX,
     JumpTargetX,
     LabelDefinitionX,
@@ -39,6 +41,7 @@
     MixinApplicationElementX,
     ParameterElementX,
     ParameterMetadataAnnotation,
+    SetterElementX,
     SynthesizedConstructorElementX,
     TypeVariableElementX,
     TypedefElementX,
@@ -46,8 +49,12 @@
     VariableList;
 
 import '../ordered_typeset.dart' show OrderedTypeSet, OrderedTypeSetBuilder;
+import '../types/types.dart' show TypeMask;
 import '../util/util.dart';
-import '../universe/universe.dart' show CallStructure, SelectorKind;
+import '../universe/universe.dart' show
+    CallStructure,
+    SelectorKind,
+    UniverseSelector;
 
 import 'access_semantics.dart';
 import 'class_members.dart' show MembersCreator;
diff --git a/pkg/compiler/lib/src/resolution/resolution_common.dart b/pkg/compiler/lib/src/resolution/resolution_common.dart
index 79741ad..cb045cf 100644
--- a/pkg/compiler/lib/src/resolution/resolution_common.dart
+++ b/pkg/compiler/lib/src/resolution/resolution_common.dart
@@ -13,7 +13,13 @@
 
   WorldImpact resolve(Element element) {
     return measure(() {
-      if (Elements.isErroneous(element)) return null;
+      if (Elements.isErroneous(element)) {
+        // TODO(johnniwinther): Add a predicate for this.
+        assert(invariant(element, element is! ErroneousElement,
+            message: "Element $element expected to have parse errors."));
+        _ensureTreeElements(element);
+        return const WorldImpact();
+      }
 
       WorldImpact processMetadata([WorldImpact result]) {
         for (MetadataAnnotation metadata in element.metadata) {
@@ -734,9 +740,9 @@
     }
     AbstractFieldElement field = lookupElement;
 
-    MethodElementX getter = field.getter;
+    GetterElementX getter = field.getter;
     if (getter == null) return;
-    MethodElementX setter = field.setter;
+    SetterElementX setter = field.setter;
     if (setter == null) return;
     int getterFlags = getter.modifiers.flags | Modifiers.FLAG_ABSTRACT;
     int setterFlags = setter.modifiers.flags | Modifiers.FLAG_ABSTRACT;
@@ -983,7 +989,7 @@
     compiler.reportWarning(node, kind, arguments);
   }
 
-  void internalError(Spannable node, message) {
+  internalError(Spannable node, message) {
     compiler.internalError(node, message);
   }
 
diff --git a/pkg/compiler/lib/src/resolution/resolution_result.dart b/pkg/compiler/lib/src/resolution/resolution_result.dart
index fd2344e..5426fe3 100644
--- a/pkg/compiler/lib/src/resolution/resolution_result.dart
+++ b/pkg/compiler/lib/src/resolution/resolution_result.dart
@@ -4,44 +4,83 @@
 
 part of resolution;
 
-/// The result of resolving a node.
-abstract class ResolutionResult {
-  Element get element;
+enum ResultKind {
+  NONE,
+  ELEMENT,
+  TYPE,
+  ASSERT,
+  CONSTANT,
 }
 
-/// The result for the resolution of a node that points to an [Element].
-class ElementResult implements ResolutionResult {
-  final Element element;
+/// The result of resolving a node.
+abstract class ResolutionResult {
+  const ResolutionResult();
 
   // TODO(johnniwinther): Remove this factory constructor when `null` is never
   // passed as an element result.
-  factory ElementResult(Element element) {
-    return element != null ? new ElementResult.internal(element) : null;
+  factory ResolutionResult.forElement(Element element) {
+    return element != null ? new ElementResult(element) : const NoneResult();
   }
 
-  ElementResult.internal(this.element);
+  ResultKind get kind;
+  Element get element => null;
+  DartType get type => null;
+  ConstantExpression get constant => null;
+  bool get isConstant => false;
+}
+
+/// The result for the resolution of a node that points to an [Element].
+class ElementResult extends ResolutionResult {
+  final Element element;
+
+  ResultKind get kind => ResultKind.ELEMENT;
+
+  ElementResult(this.element);
 
   String toString() => 'ElementResult($element)';
 }
 
 /// The result for the resolution of a node that points to an [DartType].
-class TypeResult implements ResolutionResult {
+class TypeResult extends ResolutionResult {
   final DartType type;
 
   TypeResult(this.type) {
     assert(type != null);
   }
 
+  ResultKind get kind => ResultKind.TYPE;
+
   Element get element => type.element;
 
   String toString() => 'TypeResult($type)';
 }
 
 /// The result for the resolution of the `assert` method.
-class AssertResult implements ResolutionResult {
+class AssertResult extends ResolutionResult {
   const AssertResult();
 
-  Element get element => null;
+  ResultKind get kind => ResultKind.ASSERT;
 
   String toString() => 'AssertResult()';
 }
+
+class ConstantResult extends ResolutionResult {
+  final Node node;
+  final ConstantExpression constant;
+
+  ConstantResult(this.node, this.constant);
+
+  bool get isConstant => true;
+
+  ResultKind get kind => ResultKind.CONSTANT;
+
+  String toString() => 'ConstantResult(${constant.getText()})';
+}
+
+class NoneResult extends ResolutionResult {
+  const NoneResult();
+
+  ResultKind get kind => ResultKind.NONE;
+
+  String toString() => 'NoneResult()';
+}
\ No newline at end of file
diff --git a/pkg/compiler/lib/src/resolution/semantic_visitor.dart b/pkg/compiler/lib/src/resolution/semantic_visitor.dart
index 791a259..131f52d 100644
--- a/pkg/compiler/lib/src/resolution/semantic_visitor.dart
+++ b/pkg/compiler/lib/src/resolution/semantic_visitor.dart
@@ -8,7 +8,6 @@
 import '../dart2jslib.dart' show invariant, MessageKind;
 import '../dart_types.dart';
 import '../elements/elements.dart';
-import '../helpers/helpers.dart';
 import '../tree/tree.dart';
 import '../universe/universe.dart';
 import '../util/util.dart' show Spannable, SpannableAssertionFailure;
@@ -287,6 +286,21 @@
       CallStructure callStructure,
       A arg);
 
+  /// Invocation of the local [function] with incompatible [arguments].
+  ///
+  /// For instance:
+  ///     m() {
+  ///       o(a) {}
+  ///       return o(null, 42);
+  ///     }
+  ///
+  R visitLocalFunctionIncompatibleInvoke(
+      Send node,
+      LocalFunctionElement function,
+      NodeList arguments,
+      CallStructure callStructure,
+      A arg);
+
   /// Getter call on [receiver] of the property defined by [selector].
   ///
   /// For instance
diff --git a/pkg/compiler/lib/src/resolution/semantic_visitor_mixins.dart b/pkg/compiler/lib/src/resolution/semantic_visitor_mixins.dart
index a3587f8..f366052 100644
--- a/pkg/compiler/lib/src/resolution/semantic_visitor_mixins.dart
+++ b/pkg/compiler/lib/src/resolution/semantic_visitor_mixins.dart
@@ -1409,6 +1409,16 @@
   }
 
   @override
+  R visitLocalFunctionIncompatibleInvoke(
+      Send node,
+      LocalFunctionElement function,
+      NodeList arguments,
+      CallStructure callStructure,
+      A arg) {
+    return bulkHandleInvoke(node, arg);
+  }
+
+  @override
   R visitLocalVariableInvoke(
       Send node,
       LocalVariableElement variable,
@@ -4218,6 +4228,17 @@
   }
 
   @override
+  R visitLocalFunctionIncompatibleInvoke(
+      Send node,
+      LocalFunctionElement function,
+      NodeList arguments,
+      CallStructure callStructure,
+      A arg) {
+    apply(arguments, arg);
+    return null;
+  }
+
+  @override
   R visitLocalVariableCompound(
       Send node,
       LocalVariableElement variable,
@@ -7439,6 +7460,16 @@
   }
 
   @override
+  R visitLocalFunctionIncompatibleInvoke(
+      Send node,
+      LocalFunctionElement function,
+      NodeList arguments,
+      CallStructure callStructure,
+      A arg) {
+    return handleLocalInvoke(node, function, arguments, callStructure, arg);
+  }
+
+  @override
   R visitLocalVariableGet(
       Send node,
       LocalVariableElement variable,
diff --git a/pkg/compiler/lib/src/resolution/send_resolver.dart b/pkg/compiler/lib/src/resolution/send_resolver.dart
index 64d62dd..fa8cacc 100644
--- a/pkg/compiler/lib/src/resolution/send_resolver.dart
+++ b/pkg/compiler/lib/src/resolution/send_resolver.dart
@@ -212,7 +212,6 @@
     }
 
     AssignmentOperator assignmentOperator;
-    UnaryOperator unaryOperator;
     BinaryOperator binaryOperator;
     IncDecOperator incDecOperator;
 
@@ -499,11 +498,12 @@
       } else {
         return new StaticAccess.superMethod(element);
       }
-    } else if (node.isOperator || node.isConditional) {
+    } else if (node.isConditional) {
       // Conditional sends (e?.x) are treated as dynamic property reads because
       // they are equivalent to do ((a) => a == null ? null : a.x)(e). If `e` is
       // a type `A`, this is equivalent to write `(A).x`.
-      // TODO(johnniwinther): maybe add DynamicAccess.conditionalDynamicProperty
+      return new DynamicAccess.ifNotNullProperty(node.receiver);
+    } else if (node.isOperator) {
       return new DynamicAccess.dynamicProperty(node.receiver);
     } else if (Elements.isClosureSend(node, element)) {
       if (element == null) {
diff --git a/pkg/compiler/lib/src/resolution/send_structure.dart b/pkg/compiler/lib/src/resolution/send_structure.dart
index 60d6189..cc4a9ab 100644
--- a/pkg/compiler/lib/src/resolution/send_structure.dart
+++ b/pkg/compiler/lib/src/resolution/send_structure.dart
@@ -175,15 +175,14 @@
 
   R dispatch(SemanticSendVisitor<R, A> visitor, Send node, A arg) {
     switch (semantics.kind) {
+      case AccessKind.CONDITIONAL_DYNAMIC_PROPERTY:
+        return visitor.visitIfNotNullDynamicPropertyInvoke(
+            node,
+            node.receiver,
+            node.argumentsNode,
+            selector,
+            arg);
       case AccessKind.DYNAMIC_PROPERTY:
-        if (node.isConditional) {
-          return visitor.visitIfNotNullDynamicPropertyInvoke(
-              node,
-              node.receiver,
-              node.argumentsNode,
-              selector,
-              arg);
-        }
         return visitor.visitDynamicPropertyInvoke(
             node,
             node.receiver,
@@ -423,6 +422,13 @@
             node.argumentsNode,
             callStructure,
             arg);
+      case AccessKind.LOCAL_FUNCTION:
+        return visitor.visitLocalFunctionIncompatibleInvoke(
+            node,
+            semantics.element,
+            node.argumentsNode,
+            callStructure,
+            arg);
      default:
         // TODO(johnniwinther): Support more variants of this invoke structure.
         break;
@@ -446,14 +452,13 @@
 
   R dispatch(SemanticSendVisitor<R, A> visitor, Send node, A arg) {
     switch (semantics.kind) {
+      case AccessKind.CONDITIONAL_DYNAMIC_PROPERTY:
+        return visitor.visitIfNotNullDynamicPropertyGet(
+            node,
+            node.receiver,
+            selector,
+            arg);
       case AccessKind.DYNAMIC_PROPERTY:
-        if (node.isConditional) {
-          return visitor.visitIfNotNullDynamicPropertyGet(
-              node,
-              node.receiver,
-              selector,
-              arg);
-        }
         return visitor.visitDynamicPropertyGet(
             node,
             node.receiver,
@@ -607,15 +612,14 @@
 
   R dispatch(SemanticSendVisitor<R, A> visitor, Send node, A arg) {
     switch (semantics.kind) {
+      case AccessKind.CONDITIONAL_DYNAMIC_PROPERTY:
+        return visitor.visitIfNotNullDynamicPropertySet(
+          node,
+          node.receiver,
+          selector,
+          node.arguments.single,
+          arg);
       case AccessKind.DYNAMIC_PROPERTY:
-        if (node.isConditional) {
-          return visitor.visitIfNotNullDynamicPropertySet(
-            node,
-            node.receiver,
-            selector,
-            node.arguments.single,
-            arg);
-        }
         return visitor.visitDynamicPropertySet(
           node,
           node.receiver,
@@ -1271,17 +1275,16 @@
 
   R dispatch(SemanticSendVisitor<R, A> visitor, Send node, A arg) {
     switch (semantics.kind) {
+      case AccessKind.CONDITIONAL_DYNAMIC_PROPERTY:
+        return visitor.visitIfNotNullDynamicPropertyCompound(
+            node,
+            node.receiver,
+            operator,
+            node.arguments.single,
+            getterSelector,
+            setterSelector,
+            arg);
       case AccessKind.DYNAMIC_PROPERTY:
-        if (node.isConditional) {
-          return visitor.visitIfNotNullDynamicPropertyCompound(
-              node,
-              node.receiver,
-              operator,
-              node.arguments.single,
-              getterSelector,
-              setterSelector,
-              arg);
-        }
         return visitor.visitDynamicPropertyCompound(
             node,
             node.receiver,
@@ -1698,16 +1701,15 @@
 
   R dispatch(SemanticSendVisitor<R, A> visitor, Send node, A arg) {
     switch (semantics.kind) {
+      case AccessKind.CONDITIONAL_DYNAMIC_PROPERTY:
+        return visitor.visitIfNotNullDynamicPropertyPrefix(
+            node,
+            node.receiver,
+            operator,
+            getterSelector,
+            setterSelector,
+            arg);
       case AccessKind.DYNAMIC_PROPERTY:
-        if (node.isConditional) {
-          return visitor.visitIfNotNullDynamicPropertyPrefix(
-              node,
-              node.receiver,
-              operator,
-              getterSelector,
-              setterSelector,
-              arg);
-        }
         return visitor.visitDynamicPropertyPrefix(
             node,
             node.receiver,
@@ -2015,16 +2017,15 @@
 
   R dispatch(SemanticSendVisitor<R, A> visitor, Send node, A arg) {
     switch (semantics.kind) {
+      case AccessKind.CONDITIONAL_DYNAMIC_PROPERTY:
+        return visitor.visitIfNotNullDynamicPropertyPostfix(
+            node,
+            node.receiver,
+            operator,
+            getterSelector,
+            setterSelector,
+            arg);
       case AccessKind.DYNAMIC_PROPERTY:
-        if (node.isConditional) {
-          return visitor.visitIfNotNullDynamicPropertyPostfix(
-              node,
-              node.receiver,
-              operator,
-              getterSelector,
-              setterSelector,
-              arg);
-        }
         return visitor.visitDynamicPropertyPostfix(
             node,
             node.receiver,
diff --git a/pkg/compiler/lib/src/resolution/signatures.dart b/pkg/compiler/lib/src/resolution/signatures.dart
index 02c86a7..93ae3db 100644
--- a/pkg/compiler/lib/src/resolution/signatures.dart
+++ b/pkg/compiler/lib/src/resolution/signatures.dart
@@ -79,7 +79,6 @@
   }
 
   void validateName(Identifier node) {
-    String name = node.source;
     if (isOptionalParameter &&
         optionalParametersAreNamed &&
         isPrivateName(node.source)) {
diff --git a/pkg/compiler/lib/src/resolution/tree_elements.dart b/pkg/compiler/lib/src/resolution/tree_elements.dart
index a9e9366..993c3cc 100644
--- a/pkg/compiler/lib/src/resolution/tree_elements.dart
+++ b/pkg/compiler/lib/src/resolution/tree_elements.dart
@@ -25,18 +25,24 @@
   Selector getGetterSelectorInComplexSendSet(SendSet node);
   Selector getOperatorSelectorInComplexSendSet(SendSet node);
   DartType getType(Node node);
-  void setSelector(Node node, Selector selector);
-  void setGetterSelectorInComplexSendSet(SendSet node, Selector selector);
-  void setOperatorSelectorInComplexSendSet(SendSet node, Selector selector);
+  TypeMask getTypeMask(Node node);
+  TypeMask getGetterTypeMaskInComplexSendSet(SendSet node);
+  TypeMask getOperatorTypeMaskInComplexSendSet(SendSet node);
+  void setTypeMask(Node node, TypeMask mask);
+  void setGetterTypeMaskInComplexSendSet(SendSet node, TypeMask mask);
+  void setOperatorTypeMaskInComplexSendSet(SendSet node, TypeMask mask);
 
   /// Returns the for-in loop variable for [node].
   Element getForInVariable(ForIn node);
   Selector getIteratorSelector(ForIn node);
   Selector getMoveNextSelector(ForIn node);
   Selector getCurrentSelector(ForIn node);
-  void setIteratorSelector(ForIn node, Selector selector);
-  void setMoveNextSelector(ForIn node, Selector selector);
-  void setCurrentSelector(ForIn node, Selector selector);
+  TypeMask getIteratorTypeMask(ForIn node);
+  TypeMask getMoveNextTypeMask(ForIn node);
+  TypeMask getCurrentTypeMask(ForIn node);
+  void setIteratorTypeMask(ForIn node, TypeMask mask);
+  void setMoveNextTypeMask(ForIn node, TypeMask mask);
+  void setCurrentTypeMask(ForIn node, TypeMask mask);
   void setConstant(Node node, ConstantExpression constant);
   ConstantExpression getConstant(Node node);
   bool isAssert(Send send);
@@ -89,9 +95,10 @@
   LabelDefinition getTargetLabel(GotoStatement node);
 }
 
-class TreeElementMapping implements TreeElements {
+class TreeElementMapping extends TreeElements {
   final AnalyzableElement analyzedElement;
   Map<Spannable, Selector> _selectors;
+  Map<Spannable, TypeMask> _typeMasks;
   Map<Node, DartType> _types;
   Setlet<Node> _superUses;
   Setlet<Element> _otherDependencies;
@@ -441,6 +448,67 @@
     assert(node.target != null);
     return _targetLabels != null ? _targetLabels[node] : null;
   }
+
+  TypeMask _getTypeMask(Spannable node) {
+    return _typeMasks != null ? _typeMasks[node] : null;
+  }
+
+  void _setTypeMask(Spannable node, TypeMask mask) {
+    if (_typeMasks == null) {
+      _typeMasks = new Maplet<Spannable, TypeMask>();
+    }
+    _typeMasks[node] = mask;
+  }
+
+  void setTypeMask(Node node, TypeMask mask) {
+    _setTypeMask(node, mask);
+  }
+
+  TypeMask getTypeMask(Node node) => _getTypeMask(node);
+
+  void setGetterTypeMaskInComplexSendSet(SendSet node, TypeMask mask) {
+    _setTypeMask(node.selector, mask);
+  }
+
+  TypeMask getGetterTypeMaskInComplexSendSet(SendSet node) {
+    return _getTypeMask(node.selector);
+  }
+
+  void setOperatorTypeMaskInComplexSendSet(SendSet node, TypeMask mask) {
+    _setTypeMask(node.assignmentOperator, mask);
+  }
+
+  TypeMask getOperatorTypeMaskInComplexSendSet(SendSet node) {
+    return _getTypeMask(node.assignmentOperator);
+  }
+
+  // The following methods set selectors on the "for in" node. Since
+  // we're using three selectors, we need to use children of the node,
+  // and we arbitrarily choose which ones.
+
+  void setIteratorTypeMask(ForIn node, TypeMask mask) {
+    _setTypeMask(node, mask);
+  }
+
+  TypeMask getIteratorTypeMask(ForIn node) {
+    return _getTypeMask(node);
+  }
+
+  void setMoveNextTypeMask(ForIn node, TypeMask mask) {
+    _setTypeMask(node.forToken, mask);
+  }
+
+  TypeMask getMoveNextTypeMask(ForIn node) {
+    return _getTypeMask(node.forToken);
+  }
+
+  void setCurrentTypeMask(ForIn node, TypeMask mask) {
+    _setTypeMask(node.inToken, mask);
+  }
+
+  TypeMask getCurrentTypeMask(ForIn node) {
+    return _getTypeMask(node.inToken);
+  }
 }
 
 TreeElements _ensureTreeElements(AnalyzableElementX element) {
diff --git a/pkg/compiler/lib/src/resolution/type_resolver.dart b/pkg/compiler/lib/src/resolution/type_resolver.dart
index 85c2171..2bc9bbd 100644
--- a/pkg/compiler/lib/src/resolution/type_resolver.dart
+++ b/pkg/compiler/lib/src/resolution/type_resolver.dart
@@ -15,7 +15,6 @@
                           Scope scope,
                           {bool deferredIsMalformed: true}) {
     Element element;
-    bool deferredTypeAnnotation = false;
     if (prefixName != null) {
       Element prefixElement =
           lookupInScope(compiler, prefixName, scope, prefixName.source);
@@ -40,7 +39,6 @@
         element = null;
       }
     } else {
-      String stringValue = typeName.source;
       element = lookupInScope(compiler, typeName, scope, typeName.source);
     }
     return element;
@@ -140,7 +138,7 @@
         // TODO(johnniwinther): [_ensureClassWillBeResolved] should imply
         // [computeType].
         compiler.resolver._ensureClassWillBeResolved(cls);
-        element.computeType(compiler);
+        cls.computeType(compiler);
         List<DartType> arguments = <DartType>[];
         bool hasTypeArgumentMismatch = resolveTypeArguments(
             visitor, node, cls.typeVariables, arguments);
@@ -160,7 +158,7 @@
         TypedefElement typdef = element;
         // TODO(johnniwinther): [ensureResolved] should imply [computeType].
         typdef.ensureResolved(compiler);
-        element.computeType(compiler);
+        typdef.computeType(compiler);
         List<DartType> arguments = <DartType>[];
         bool hasTypeArgumentMismatch = resolveTypeArguments(
             visitor, node, typdef.typeVariables, arguments);
@@ -176,10 +174,9 @@
           }
         }
       } else if (element.isTypeVariable) {
+        TypeVariableElement typeVariable = element;
         Element outer =
             visitor.enclosingElement.outermostEnclosingMemberOrTopLevel;
-        bool isInFactoryConstructor =
-            outer != null && outer.isFactoryConstructor;
         if (!outer.isClass &&
             !outer.isTypedef &&
             !Elements.hasAccessToTypeVariables(visitor.enclosingElement)) {
@@ -187,9 +184,9 @@
           type = reportFailureAndCreateType(
               MessageKind.TYPE_VARIABLE_WITHIN_STATIC_MEMBER,
               {'typeVariableName': node},
-              userProvidedBadType: element.computeType(compiler));
+              userProvidedBadType: typeVariable.type);
         } else {
-          type = element.computeType(compiler);
+          type = typeVariable.type;
         }
         type = checkNoTypeArguments(type);
       } else {
diff --git a/pkg/compiler/lib/src/resolution/typedefs.dart b/pkg/compiler/lib/src/resolution/typedefs.dart
index 0c3badd..7f5e820 100644
--- a/pkg/compiler/lib/src/resolution/typedefs.dart
+++ b/pkg/compiler/lib/src/resolution/typedefs.dart
@@ -13,7 +13,7 @@
       : super(compiler, typedefElement, registry);
 
   visitTypedef(Typedef node) {
-    TypedefType type = element.computeType(compiler);
+    element.computeType(compiler);
     scope = new TypeDeclarationScope(scope, element);
     resolveTypeVariableBounds(node.typeParameters);
 
diff --git a/pkg/compiler/lib/src/resolved_visitor.dart b/pkg/compiler/lib/src/resolved_visitor.dart
index 6828a79..b07c36d 100644
--- a/pkg/compiler/lib/src/resolved_visitor.dart
+++ b/pkg/compiler/lib/src/resolved_visitor.dart
@@ -805,4 +805,14 @@
       ResolvedKindVisitor<R> visitor) {
     return visitor.visitSuperSend(node);
   }
+
+  @override
+  R visitLocalFunctionIncompatibleInvoke(
+      Send node,
+      LocalFunctionElement function,
+      NodeList arguments,
+      CallStructure callStructure,
+      ResolvedKindVisitor<R> visitor) {
+    return visitor.visitClosureSend(node);
+  }
 }
diff --git a/pkg/compiler/lib/src/scanner/class_element_parser.dart b/pkg/compiler/lib/src/scanner/class_element_parser.dart
index 67fe480..627b0ad 100644
--- a/pkg/compiler/lib/src/scanner/class_element_parser.dart
+++ b/pkg/compiler/lib/src/scanner/class_element_parser.dart
@@ -57,7 +57,7 @@
               invariant(
                   beginToken, listener.nodes.isEmpty,
                   message: "Non-empty listener stack: ${listener.nodes}"));
-        } on ParserError catch (e) {
+        } on ParserError {
           // TODO(ahe): Often, a ParserError is thrown while parsing the class
           // body. This means that the stack actually contains most of the
           // information synthesized below. Consider rewriting the parser so
@@ -186,7 +186,6 @@
                                  {'name': enclosingClass.name});
       }
     }
-    ElementKind kind = ElementKind.FUNCTION;
     Element memberElement = new PartialConstructorElement(
         name, beginToken, endToken,
         ElementKind.FUNCTION,
diff --git a/pkg/compiler/lib/src/scanner/listener.dart b/pkg/compiler/lib/src/scanner/listener.dart
index cd747b9..b6c356a 100644
--- a/pkg/compiler/lib/src/scanner/listener.dart
+++ b/pkg/compiler/lib/src/scanner/listener.dart
@@ -945,10 +945,9 @@
   void endClassDeclaration(int interfacesCount, Token beginToken,
                            Token extendsKeyword, Token implementsKeyword,
                            Token endToken) {
-    NodeList interfaces =
-        makeNodeList(interfacesCount, implementsKeyword, null, ",");
-    Node supertype = popNode();
-    NodeList typeParameters = popNode();
+    makeNodeList(interfacesCount, implementsKeyword, null, ","); // interfaces
+    popNode(); // superType
+    popNode(); // typeParameters
     Identifier name = popNode();
     int id = idGenerator();
     PartialClassElement element = new PartialClassElement(
@@ -967,9 +966,9 @@
   }
 
   void endFunctionTypeAlias(Token typedefKeyword, Token endToken) {
-    NodeList typeVariables = popNode(); // TOOD(karlklose): do not throw away.
+    popNode(); // TODO(karlklose): do not throw away typeVariables.
     Identifier name = popNode();
-    TypeAnnotation returnType = popNode();
+    popNode(); // returnType
     pushElement(
         new PartialTypedefElement(
             name.source, compilationUnitElement, typedefKeyword, endToken));
@@ -1010,7 +1009,7 @@
     bool hasParseError = currentMemberHasParseError;
     memberErrors = memberErrors.tail;
     Identifier name = popNode();
-    TypeAnnotation type = popNode();
+    popNode(); // type
     Modifiers modifiers = popNode();
     PartialFunctionElement element = new PartialFunctionElement(
         name.source, beginToken, getOrSet, endToken,
@@ -1027,7 +1026,7 @@
           new FieldElementX(name, compilationUnitElement, fields));
     }
     NodeList variables = makeNodeList(count, null, null, ",");
-    TypeAnnotation type = popNode();
+    popNode(); // type
     Modifiers modifiers = popNode();
     buildFieldElements(modifiers, variables, compilationUnitElement,
                        buildFieldElement,
@@ -1553,10 +1552,10 @@
   }
 
   void endTopLevelMethod(Token beginToken, Token getOrSet, Token endToken) {
-    Statement body = popNode();
-    NodeList formalParameters = popNode();
+    popNode(); // body
+    popNode(); // formalParameters
     Identifier name = popNode();
-    TypeAnnotation type = popNode();
+    popNode(); // type
     Modifiers modifiers = popNode();
     PartialFunctionElement element = new PartialFunctionElement(
         name.source, beginToken, getOrSet, endToken,
diff --git a/pkg/compiler/lib/src/scanner/parser.dart b/pkg/compiler/lib/src/scanner/parser.dart
index 10e7dfc..66d26bd 100644
--- a/pkg/compiler/lib/src/scanner/parser.dart
+++ b/pkg/compiler/lib/src/scanner/parser.dart
@@ -1326,10 +1326,8 @@
       externalModifier = token;
       token = token.next;
     }
-    Token constKeyword = null;
     if (optional('const', token)) {
-      constKeyword = token;
-      token = token.next;
+      token = token.next; // Skip const.
     }
     Token factoryKeyword = token;
     listener.beginFactoryMethod(factoryKeyword);
diff --git a/pkg/compiler/lib/src/scanner/scannerlib.dart b/pkg/compiler/lib/src/scanner/scannerlib.dart
index 7b6ebb7..d0c3a2e 100644
--- a/pkg/compiler/lib/src/scanner/scannerlib.dart
+++ b/pkg/compiler/lib/src/scanner/scannerlib.dart
@@ -38,7 +38,6 @@
 import '../util/util.dart';
 import '../io/source_file.dart' show SourceFile, Utf8BytesSourceFile;
 import 'dart:convert' show UTF8, UNICODE_BOM_CHARACTER_RUNE;
-import 'dart:typed_data' show Uint8List;
 
 part 'class_element_parser.dart';
 part 'keyword.dart';
diff --git a/pkg/compiler/lib/src/source_file_provider.dart b/pkg/compiler/lib/src/source_file_provider.dart
index 30a7559..b47fc64 100644
--- a/pkg/compiler/lib/src/source_file_provider.dart
+++ b/pkg/compiler/lib/src/source_file_provider.dart
@@ -173,10 +173,9 @@
 
     message = prefixMessage(message, kind);
 
-    // [previousKind]/[lastKind] records the previous non-INFO kind we saw.
+    // [lastKind] records the previous non-INFO kind we saw.
     // This is used to suppress info about a warning when warnings are
     // suppressed, and similar for hints.
-    var previousKind = lastKind;
     if (kind != api.Diagnostic.INFO) {
       lastKind = kind;
     }
@@ -254,7 +253,6 @@
 
   EventSink<String> call(String name, String extension) {
     Uri uri;
-    String sourceMapFileName;
     bool isPrimaryOutput = false;
     // TODO (johnniwinther, sigurdm): Make a better interface for
     // output-providers.
@@ -264,8 +262,6 @@
       if (extension == 'js' || extension == 'dart') {
         isPrimaryOutput = true;
         uri = out;
-        sourceMapFileName =
-            sourceMapOut.path.substring(sourceMapOut.path.lastIndexOf('/') + 1);
       } else if (extension == 'precompiled.js') {
         uri = computePrecompiledUri(out);
         onInfo("File ($uri) is compatible with header"
diff --git a/pkg/compiler/lib/src/ssa/builder.dart b/pkg/compiler/lib/src/ssa/builder.dart
index 98b0fca..50fa510 100644
--- a/pkg/compiler/lib/src/ssa/builder.dart
+++ b/pkg/compiler/lib/src/ssa/builder.dart
@@ -26,7 +26,7 @@
       JavaScriptBackend backend = builder.backend;
 
       AsyncRewriterBase rewriter = null;
-      String name = backend.namer.methodPropertyName(element);
+      js.Name name = backend.namer.methodPropertyName(element);
       if (element.asyncMarker == AsyncMarker.ASYNC) {
         rewriter = new AsyncRewriter(
             backend.compiler,
@@ -35,8 +35,8 @@
                 backend.emitter.staticFunctionAccess(backend.getAsyncHelper()),
             newCompleter: backend.emitter.staticFunctionAccess(
                 backend.getCompleterConstructor()),
-            safeVariableName: backend.namer.safeVariableName,
-            bodyName: name);
+            safeVariableName: backend.namer.safeVariablePrefixForAsyncRewrite,
+            bodyName: backend.namer.deriveAsyncBodyName(name));
       } else if (element.asyncMarker == AsyncMarker.SYNC_STAR) {
         rewriter = new SyncStarRewriter(
             backend.compiler,
@@ -49,8 +49,8 @@
                 backend.getYieldStar()),
             uncaughtErrorExpression: backend.emitter.staticFunctionAccess(
                 backend.getSyncStarUncaughtError()),
-            safeVariableName: backend.namer.safeVariableName,
-            bodyName: name);
+            safeVariableName: backend.namer.safeVariablePrefixForAsyncRewrite,
+            bodyName: backend.namer.deriveAsyncBodyName(name));
       }
       else if (element.asyncMarker == AsyncMarker.ASYNC_STAR) {
         rewriter = new AsyncStarRewriter(
@@ -62,12 +62,12 @@
                 backend.getStreamOfController()),
             newController: backend.emitter.staticFunctionAccess(
                 backend.getASyncStarControllerConstructor()),
-            safeVariableName: backend.namer.safeVariableName,
+            safeVariableName: backend.namer.safeVariablePrefixForAsyncRewrite,
             yieldExpression: backend.emitter.staticFunctionAccess(
                 backend.getYieldSingle()),
             yieldStarExpression: backend.emitter.staticFunctionAccess(
                 backend.getYieldStar()),
-            bodyName: name);
+            bodyName: backend.namer.deriveAsyncBodyName(name));
       }
       if (rewriter != null) {
         result = rewriter.rewrite(result);
@@ -1297,6 +1297,7 @@
    */
   bool tryInlineMethod(Element element,
                        Selector selector,
+                       TypeMask mask,
                        List<HInstruction> providedArguments,
                        ast.Node currentNode,
                        {InterfaceType instanceType}) {
@@ -1322,11 +1323,17 @@
     bool meetsHardConstraints() {
       if (compiler.disableInlining) return false;
 
-      assert(selector != null
-             || Elements.isStaticOrTopLevel(element)
-             || element.isGenerativeConstructorBody);
-      if (selector != null && !selector.applies(function, compiler.world)) {
-        return false;
+      assert(invariant(
+          currentNode != null ? currentNode : element,
+          selector != null ||
+          Elements.isStaticOrTopLevel(element) ||
+          element.isGenerativeConstructorBody,
+          message: "Missing selector for inlining of $element."));
+      if (selector != null) {
+        if (!selector.applies(function, compiler.world)) return false;
+        if (mask != null && !mask.canHit(function, selector, compiler.world)) {
+          return false;
+        }
       }
 
       // Don't inline operator== methods if the parameter can be null.
@@ -1445,9 +1452,9 @@
       // Add an explicit null check on the receiver before doing the
       // inlining. We use [element] to get the same name in the
       // NoSuchMethodError message as if we had called it.
-      if (element.isInstanceMember
-          && !element.isGenerativeConstructorBody
-          && (selector.mask == null || selector.mask.isNullable)) {
+      if (element.isInstanceMember &&
+          !element.isGenerativeConstructorBody &&
+          (mask == null || mask.isNullable)) {
         addWithPosition(
             new HFieldGet(null, providedArguments[0], backend.dynamicType,
                           isAssignable: false),
@@ -2258,7 +2265,6 @@
       }
       bodyCallInputs.add(newObject);
       ResolvedAst resolvedAst = constructor.resolvedAst;
-      TreeElements elements = resolvedAst.elements;
       ast.Node node = resolvedAst.node;
       ClosureClassMap parameterClosureData =
           compiler.closureToClassMapper.getMappingForNestedFunction(node);
@@ -2295,7 +2301,7 @@
       }
 
       if (!isNativeUpgradeFactory && // TODO(13836): Fix inlining.
-          tryInlineMethod(body, null, bodyCallInputs, function)) {
+          tryInlineMethod(body, null, null, bodyCallInputs, function)) {
         pop();
       } else {
         HInvokeConstructorBody invoke = new HInvokeConstructorBody(
@@ -2444,10 +2450,12 @@
       String name = kind == HTypeConversion.CAST_TYPE_CHECK
           ? '_asCheck' : '_assertCheck';
 
-      List arguments = [buildFunctionType(type), original];
+      List<HInstruction> arguments =
+          <HInstruction>[buildFunctionType(type), original];
       pushInvokeDynamic(
           null,
           new Selector.call(name, backend.jsHelperLibrary, 1),
+          null,
           arguments);
 
       return new HTypeConversion(type, kind, original.instructionType, pop());
@@ -2783,7 +2791,6 @@
       localsHandler =
           continueHandlers[0].mergeMultiple(continueHandlers, updateBlock);
 
-      HLabeledBlockInformation labelInfo;
       List<LabelDefinition> labels = jumpHandler.labels();
       JumpTarget target = elements.getTargetDefinition(loop);
       if (!labels.isEmpty) {
@@ -2919,7 +2926,7 @@
         assert(!isAborted());
         // The result of the update instruction isn't used, and can just
         // be dropped.
-        HInstruction updateInstruction = pop();
+        pop();
       }
     }
     void buildBody() {
@@ -3105,9 +3112,7 @@
     push(new HForeignNew(closureClassElement, type, capturedVariables));
 
     Element methodElement = nestedClosureData.closureElement;
-    if (compiler.backend.methodNeedsRti(methodElement)) {
-      registry.registerClosureWithFreeTypeVariables(methodElement);
-    }
+    registry.registerInstantiatedClosure(methodElement);
   }
 
   visitFunctionDeclaration(ast.FunctionDeclaration node) {
@@ -3191,7 +3196,11 @@
       }
     }
 
-    pushInvokeDynamic(node, elements.getSelector(node), [operand]);
+    pushInvokeDynamic(
+        node,
+        elements.getSelector(node),
+        elements.getTypeMask(node),
+        [operand]);
   }
 
   @override
@@ -3223,6 +3232,7 @@
         visitAndPop(left),
         visitAndPop(right),
         elements.getSelector(node),
+        elements.getTypeMask(node),
         node,
         location: node.selector);
   }
@@ -3232,9 +3242,10 @@
   void visitBinarySend(HInstruction left,
                        HInstruction right,
                        Selector selector,
+                       TypeMask mask,
                        ast.Send send,
                        {ast.Node location}) {
-    pushInvokeDynamic(send, selector, [left, right], location: location);
+    pushInvokeDynamic(send, selector, mask, [left, right], location: location);
   }
 
   HInstruction generateInstanceSendReceiver(ast.Send send) {
@@ -3246,8 +3257,7 @@
     return pop();
   }
 
-  String noSuchMethodTargetSymbolString(ErroneousElement error,
-                                        [String prefix]) {
+  String noSuchMethodTargetSymbolString(Element error, [String prefix]) {
     String result = error.name;
     if (prefix == "set") return "$result=";
     return result;
@@ -3257,12 +3267,14 @@
    * Returns a set of interceptor classes that contain the given
    * [selector].
    */
-  void generateInstanceGetterWithCompiledReceiver(ast.Send send,
-                                                  Selector selector,
-                                                  HInstruction receiver) {
+  void generateInstanceGetterWithCompiledReceiver(
+      ast.Send send,
+      Selector selector,
+      TypeMask mask,
+      HInstruction receiver) {
     assert(Elements.isInstanceSend(send, elements));
     assert(selector.isGetter);
-    pushInvokeDynamic(send, selector, [receiver]);
+    pushInvokeDynamic(send, selector, mask, [receiver]);
   }
 
   /// Inserts a call to checkDeferredIsLoaded for [prefixElement].
@@ -3288,14 +3300,18 @@
         node);
   }
 
+  void handleInvalidStaticGet(ast.Send node, Element element) {
+    generateThrowNoSuchMethod(
+        node,
+        noSuchMethodTargetSymbolString(element, 'get'),
+        argumentNodes: const Link<ast.Node>());
+  }
+
   /// Generate read access of an unresolved static or top level entity.
   void generateStaticUnresolvedGet(ast.Send node, Element element) {
     if (element is ErroneousElement) {
       // An erroneous element indicates an unresolved static getter.
-      generateThrowNoSuchMethod(
-          node,
-          noSuchMethodTargetSymbolString(element, 'get'),
-          argumentNodes: const Link<ast.Node>());
+      handleInvalidStaticGet(node, element);
     } else {
       // This happens when [element] has parse errors.
       assert(invariant(node, element == null || element.isErroneous));
@@ -3376,7 +3392,7 @@
   void generateDynamicGet(ast.Send node) {
     HInstruction receiver = generateInstanceSendReceiver(node);
     generateInstanceGetterWithCompiledReceiver(
-        node, elements.getSelector(node), receiver);
+        node, elements.getSelector(node), elements.getTypeMask(node), receiver);
   }
 
   /// Generate a closurization of the static or top level [function].
@@ -3423,8 +3439,13 @@
           pushCheckNull(expression);
         },
         () => stack.add(expression),
-        () => generateInstanceGetterWithCompiledReceiver(
-            node, elements.getSelector(node), expression));
+        () {
+          generateInstanceGetterWithCompiledReceiver(
+              node,
+              elements.getSelector(node),
+              elements.getTypeMask(node),
+              expression);
+        });
   }
 
   /// Pushes a boolean checking [expression] against null.
@@ -3504,53 +3525,26 @@
     generateStaticGetterGet(node, getter);
   }
 
-  void generatePossiblyConditionalInstanceSetter(ast.Send send,
-                                                 HInstruction pushReceiver(),
-                                                 HInstruction pushValue(),
-                                                 {Selector selector,
-                                                  ast.Node location}) {
-    if (send.isConditional) {
-      SsaBranchBuilder brancher = new SsaBranchBuilder(this, send);
-      // compile e?.x = e2 to:
-      //
-      // t1 = e
-      // if (t1 == null)
-      //   result = t1 // same as result = null
-      // else
-      //   result = e.x = e2
-      HInstruction receiver;
-      brancher.handleConditional(
-          () {
-            receiver = pushReceiver();
-            pushCheckNull(receiver);
-          },
-          () => stack.add(receiver),
-          () => generateInstanceSetterWithCompiledReceiver(
-                    send, receiver, pushValue(),
-                    selector: selector, location: location));
-    } else {
-      generateInstanceSetterWithCompiledReceiver(
-          send, pushReceiver(), pushValue(),
-          selector: selector, location: location);
-    }
-  }
-
   void generateInstanceSetterWithCompiledReceiver(ast.Send send,
                                                   HInstruction receiver,
                                                   HInstruction value,
                                                   {Selector selector,
+                                                   TypeMask mask,
                                                    ast.Node location}) {
     assert(send == null || Elements.isInstanceSend(send, elements));
     if (selector == null) {
       assert(send != null);
       selector = elements.getSelector(send);
+      if (mask == null) {
+        mask = elements.getTypeMask(send);
+      }
     }
     if (location == null) {
       assert(send != null);
       location = send;
     }
     assert(selector.isSetter);
-    pushInvokeDynamic(location, selector, [receiver, value]);
+    pushInvokeDynamic(location, selector, mask, [receiver, value]);
     pop();
     stack.add(value);
   }
@@ -3625,13 +3619,17 @@
       assert(type.element.isClass);
       InterfaceType interface = type;
       List<HInstruction> inputs = <HInstruction>[];
-      bool first = true;
       List<js.Expression> templates = <js.Expression>[];
       for (DartType argument in interface.typeArguments) {
-        templates.add(rti.getTypeRepresentationWithPlaceholders(argument, (variable) {
-          HInstruction runtimeType = addTypeVariableReference(variable);
-          inputs.add(runtimeType);
-        }, firstPlaceholderIndex : inputs.length));
+        // As we construct the template in stages, we have to make sure that for
+        // each part the generated sub-template's holes match the index of the
+        // inputs that are later used to instantiate it. We do this by starting
+        // the indexing with the number of inputs from previous sub-templates.
+        templates.add(
+            rti.getTypeRepresentationWithPlaceholders(argument, (variable) {
+              HInstruction runtimeType = addTypeVariableReference(variable);
+              inputs.add(runtimeType);
+            }, firstPlaceholderIndex: inputs.length));
       }
       // TODO(sra): This is a fresh template each time.  We can't let the
       // template manager build them.
@@ -3681,7 +3679,9 @@
     if (type.isFunctionType) {
       List arguments = [buildFunctionType(type), expression];
       pushInvokeDynamic(
-          node, new Selector.call('_isTest', backend.jsHelperLibrary, 1),
+          node,
+          new Selector.call('_isTest', backend.jsHelperLibrary, 1),
+          null,
           arguments);
       return new HIs.compound(type, expression, pop(), backend.boolType);
     } else if (type.isTypeVariable) {
@@ -3697,10 +3697,10 @@
       HInstruction representations =
           buildTypeArgumentRepresentations(type);
       add(representations);
-      String operator = backend.namer.operatorIs(element);
-      HInstruction isFieldName = addConstantString(operator);
+      js.Name operator = backend.namer.operatorIs(element);
+      HInstruction isFieldName = addConstantStringFromName(operator);
       HInstruction asFieldName = compiler.world.hasAnyStrictSubtype(element)
-          ? addConstantString(backend.namer.substitutionName(element))
+          ? addConstantStringFromName(backend.namer.substitutionName(element))
           : graph.addConstantNull(compiler);
       List<HInstruction> inputs = <HInstruction>[expression,
                                                  isFieldName,
@@ -3803,12 +3803,13 @@
 
   void _generateDynamicSend(ast.Send node, HInstruction receiver) {
     Selector selector = elements.getSelector(node);
+    TypeMask mask = elements.getTypeMask(node);
 
     List<HInstruction> inputs = <HInstruction>[];
     inputs.add(receiver);
     addDynamicSendArgumentsToList(node, inputs);
 
-    pushInvokeDynamic(node, selector, inputs);
+    pushInvokeDynamic(node, selector, mask, inputs);
     if (selector.isSetter || selector.isIndexSet) {
       pop();
       stack.add(inputs.last);
@@ -3902,6 +3903,16 @@
     generateCallInvoke(node, localsHandler.readLocal(function));
   }
 
+  @override
+  visitLocalFunctionIncompatibleInvoke(
+      ast.Send node,
+      LocalFunctionElement function,
+      ast.NodeList arguments,
+      CallStructure callStructure,
+      _) {
+    generateCallInvoke(node, localsHandler.readLocal(function));
+  }
+
   void handleForeignJs(ast.Send node) {
     Link<ast.Node> link = node.arguments;
     // Don't visit the first argument, which is the type, and the second
@@ -3968,7 +3979,7 @@
     }
   }
 
-  void handleForeingJsGetFlag(ast.Send node) {
+  void handleForeignJsGetFlag(ast.Send node) {
     List<ast.Node> arguments = node.arguments.toList();
      ast.Node argument;
      switch (arguments.length) {
@@ -4042,7 +4053,7 @@
     EnumClassElement enumClass = element.enclosingClass;
     int index = enumClass.enumValues.indexOf(element);
     stack.add(
-        addConstantString(
+        addConstantStringFromName(
             backend.namer.getNameForJsGetName(
                 argument, JsGetName.values[index])));
   }
@@ -4162,8 +4173,7 @@
       // If the isolate library is not used, we just invoke the
       // closure.
       visit(link.tail.head);
-      Selector selector = new Selector.callClosure(0);
-      push(new HInvokeClosure(selector,
+      push(new HInvokeClosure(new Selector.callClosure(0),
                               <HInstruction>[pop()],
                               backend.dynamicType));
     } else {
@@ -4258,10 +4268,6 @@
       handleForeignRawFunctionRef(node, 'RAW_DART_FUNCTION_REF');
     } else if (name == 'JS_SET_CURRENT_ISOLATE') {
       handleForeignSetCurrentIsolate(node);
-    } else if (name == 'JS_IS_INDEXABLE_FIELD_NAME') {
-      // TODO(floitsch): this should be a JS_NAME.
-      Element element = backend.findHelper('JavaScriptIndexingBehavior');
-      stack.add(addConstantString(backend.namer.operatorIs(element)));
     } else if (name == 'JS_CURRENT_ISOLATE') {
       handleForeignJsCurrentIsolate(node);
     } else if (name == 'JS_GET_NAME') {
@@ -4271,7 +4277,7 @@
     } else if (name == 'JS_BUILTIN') {
       handleForeignJsBuiltin(node);
     } else if (name == 'JS_GET_FLAG') {
-      handleForeingJsGetFlag(node);
+      handleForeignJsGetFlag(node);
     } else if (name == 'JS_EFFECT') {
       stack.add(graph.addConstantNull(compiler));
     } else if (name == 'JS_INTERCEPTOR_CONSTANT') {
@@ -4309,7 +4315,7 @@
       // class is _not_ the default implementation from [Object], in
       // case the [noSuchMethod] implementation calls
       // [JSInvocationMirror._invokeOn].
-      registry.registerSelectorUse(selector.asUntyped);
+      registry.registerSelectorUse(selector);
     }
     String publicName = name;
     if (selector.isSetter) publicName += '=';
@@ -4317,9 +4323,7 @@
     ConstantValue nameConstant = constantSystem.createString(
         new ast.DartString.literal(publicName));
 
-    String internalName = backend.namer.invocationName(selector);
-    ConstantValue internalNameConstant =
-        constantSystem.createString(new ast.DartString.literal(internalName));
+    js.Name internalName = backend.namer.invocationName(selector);
 
     Element createInvocationMirror = backend.getCreateInvocationMirror();
     var argumentsInstruction = buildLiteralList(arguments);
@@ -4340,7 +4344,7 @@
     pushInvokeStatic(null,
                      createInvocationMirror,
                      [graph.addConstant(nameConstant, compiler),
-                      graph.addConstant(internalNameConstant, compiler),
+                      graph.addConstantStringFromName(internalName, compiler),
                       graph.addConstant(kindConstant, compiler),
                       argumentsInstruction,
                       argumentNamesInstruction],
@@ -4606,12 +4610,12 @@
       // TODO(ahe): Creating a string here is unfortunate. It is slow (due to
       // string concatenation in the implementation), and may prevent
       // segmentation of '$'.
-      String substitutionNameString = backend.namer.runtimeTypeName(cls);
-      HInstruction substitutionName = graph.addConstantString(
-          new ast.LiteralDartString(substitutionNameString), compiler);
+      js.Name substitutionName = backend.namer.runtimeTypeName(cls);
+      HInstruction substitutionNameInstr = graph.addConstantStringFromName(
+          substitutionName, compiler);
       pushInvokeStatic(null,
                        backend.getGetRuntimeTypeArgument(),
-                       [target, substitutionName, index],
+                       [target, substitutionNameInstr, index],
                        typeMask: backend.dynamicType);
     } else {
       pushInvokeStatic(null, backend.getGetTypeArgumentByIndex(),
@@ -5142,6 +5146,22 @@
   }
 
   @override
+  void visitTopLevelSetterGet(
+      ast.Send node,
+      MethodElement setter,
+      _) {
+    handleInvalidStaticGet(node, setter);
+  }
+
+  @override
+  void visitStaticSetterGet(
+      ast.Send node,
+      MethodElement setter,
+      _) {
+    handleInvalidStaticGet(node, setter);
+  }
+
+  @override
   void visitUnresolvedGet(
       ast.Send node,
       Element element,
@@ -5149,6 +5169,32 @@
     generateStaticUnresolvedGet(node, element);
   }
 
+  void handleInvalidStaticInvoke(ast.Send node, Element element) {
+    generateThrowNoSuchMethod(node,
+                              noSuchMethodTargetSymbolString(element),
+                              argumentNodes: node.arguments);
+  }
+
+  @override
+  void visitStaticSetterInvoke(
+      ast.Send node,
+      MethodElement setter,
+      ast.NodeList arguments,
+      CallStructure callStructure,
+      _) {
+    handleInvalidStaticInvoke(node, setter);
+  }
+
+  @override
+  void visitTopLevelSetterInvoke(
+      ast.Send node,
+      MethodElement setter,
+      ast.NodeList arguments,
+      CallStructure callStructure,
+      _) {
+    handleInvalidStaticInvoke(node, setter);
+  }
+
   @override
   void visitUnresolvedInvoke(
       ast.Send node,
@@ -5157,11 +5203,9 @@
       Selector selector,
       _) {
     if (element is ErroneousElement) {
-      // An erroneous element indicates that the funciton could not be
+      // An erroneous element indicates that the function could not be
       // resolved (a warning has been issued).
-      generateThrowNoSuchMethod(node,
-                                noSuchMethodTargetSymbolString(element),
-                                argumentNodes: node.arguments);
+      handleInvalidStaticInvoke(node, element);
     } else {
       // TODO(ahe): Do something like [generateWrongArgumentCountError].
       stack.add(graph.addConstantNull(compiler));
@@ -5171,8 +5215,11 @@
 
   HConstant addConstantString(String string) {
     ast.DartString dartString = new ast.DartString.literal(string);
-    ConstantValue constant = constantSystem.createString(dartString);
-    return graph.addConstant(constant, compiler);
+    return graph.addConstantString(dartString, compiler);
+  }
+
+  HConstant addConstantStringFromName(js.Name name) {
+    return graph.addConstantStringFromName(name, compiler);
   }
 
   visitClassTypeLiteralGet(
@@ -5285,9 +5332,11 @@
     Selector selector = elements.getSelector(node);
     List<HInstruction> inputs = <HInstruction>[target];
     addDynamicSendArgumentsToList(node, inputs);
-    Selector closureSelector = new Selector.callClosureFrom(selector);
     pushWithPosition(
-        new HInvokeClosure(closureSelector, inputs, backend.dynamicType), node);
+        new HInvokeClosure(
+            new Selector.callClosureFrom(selector),
+            inputs, backend.dynamicType),
+        node);
   }
 
   visitGetterSend(ast.Send node) {
@@ -5416,6 +5465,7 @@
 
   void pushInvokeDynamic(ast.Node node,
                          Selector selector,
+                         TypeMask mask,
                          List<HInstruction> arguments,
                          {ast.Node location}) {
     if (location == null) location = node;
@@ -5456,13 +5506,13 @@
       return false;
     }
 
-    Element element = compiler.world.locateSingleElement(selector);
-    if (element != null
-        && !element.isField
-        && !(element.isGetter && selector.isCall)
-        && !(element.isFunction && selector.isGetter)
-        && !isOptimizableOperation(selector, element)) {
-      if (tryInlineMethod(element, selector, arguments, node)) {
+    Element element = compiler.world.locateSingleElement(selector, mask);
+    if (element != null &&
+        !element.isField &&
+        !(element.isGetter && selector.isCall) &&
+        !(element.isFunction && selector.isGetter) &&
+        !isOptimizableOperation(selector, element)) {
+      if (tryInlineMethod(element, selector, mask, arguments, node)) {
         return;
       }
     }
@@ -5474,18 +5524,19 @@
       inputs.add(invokeInterceptor(receiver));
     }
     inputs.addAll(arguments);
-    TypeMask type = TypeMaskFactory.inferredTypeForSelector(selector, compiler);
+    TypeMask type =
+        TypeMaskFactory.inferredTypeForSelector(selector, mask, compiler);
     if (selector.isGetter) {
       pushWithPosition(
-          new HInvokeDynamicGetter(selector, null, inputs, type),
+          new HInvokeDynamicGetter(selector, mask, null, inputs, type),
           location);
     } else if (selector.isSetter) {
       pushWithPosition(
-          new HInvokeDynamicSetter(selector, null, inputs, type),
+          new HInvokeDynamicSetter(selector, mask, null, inputs, type),
           location);
     } else {
       pushWithPosition(
-          new HInvokeDynamicMethod(selector, inputs, type, isIntercepted),
+          new HInvokeDynamicMethod(selector, mask, inputs, type, isIntercepted),
           location);
     }
   }
@@ -5495,7 +5546,7 @@
                         List<HInstruction> arguments,
                         {TypeMask typeMask,
                          InterfaceType instanceType}) {
-    if (tryInlineMethod(element, null, arguments, location,
+    if (tryInlineMethod(element, null, null, arguments, location,
                         instanceType: instanceType)) {
       return;
     }
@@ -5550,7 +5601,8 @@
         inputs,
         type,
         isSetter: selector.isSetter || selector.isIndexSet);
-    instruction.sideEffects = compiler.world.getSideEffectsOfSelector(selector);
+    instruction.sideEffects =
+        compiler.world.getSideEffectsOfSelector(selector, null);
     return instruction;
   }
 
@@ -5567,235 +5619,515 @@
     }
     visitBinarySend(receiver, rhs,
                     elements.getOperatorSelectorInComplexSendSet(node),
+                    elements.getOperatorTypeMaskInComplexSendSet(node),
                     node,
                     location: node.assignmentOperator);
   }
 
+  void handleSuperSendSet(ast.SendSet node) {
+    Element element = elements[node];
+    List<HInstruction> setterInputs = <HInstruction>[];
+    void generateSuperSendSet() {
+      Selector setterSelector = elements.getSelector(node);
+      if (Elements.isUnresolved(element)
+          || !setterSelector.applies(element, compiler.world)) {
+        generateSuperNoSuchMethodSend(
+            node, setterSelector, setterInputs);
+        pop();
+      } else {
+        add(buildInvokeSuper(setterSelector, element, setterInputs));
+      }
+    }
+    if (identical(node.assignmentOperator.source, '=')) {
+      addDynamicSendArgumentsToList(node, setterInputs);
+      generateSuperSendSet();
+      stack.add(setterInputs.last);
+    } else {
+      Element getter = elements[node.selector];
+      List<HInstruction> getterInputs = <HInstruction>[];
+      Link<ast.Node> arguments = node.arguments;
+      if (node.isIndex) {
+        // If node is of the form [:super.foo[0] += 2:], the send has
+        // two arguments: the index and the left hand side. We get
+        // the index and add it as input of the getter and the
+        // setter.
+        visit(arguments.head);
+        arguments = arguments.tail;
+        HInstruction index = pop();
+        getterInputs.add(index);
+        setterInputs.add(index);
+      }
+      HInstruction getterInstruction;
+      Selector getterSelector =
+          elements.getGetterSelectorInComplexSendSet(node);
+      if (Elements.isUnresolved(getter)) {
+        generateSuperNoSuchMethodSend(
+            node,
+            getterSelector,
+            getterInputs);
+        getterInstruction = pop();
+      } else {
+        getterInstruction = buildInvokeSuper(
+            getterSelector, getter, getterInputs);
+        add(getterInstruction);
+      }
+
+      if (node.isIfNullAssignment) {
+        SsaBranchBuilder brancher = new SsaBranchBuilder(this, node);
+        brancher.handleIfNull(() => stack.add(getterInstruction),
+            () {
+              addDynamicSendArgumentsToList(node, setterInputs);
+              generateSuperSendSet();
+              stack.add(setterInputs.last);
+            });
+      } else {
+        handleComplexOperatorSend(node, getterInstruction, arguments);
+        setterInputs.add(pop());
+        generateSuperSendSet();
+        stack.add(node.isPostfix ? getterInstruction : setterInputs.last);
+      }
+    }
+  }
+
+  @override
+  void visitIndexSet(
+      ast.SendSet node,
+      ast.Node receiver,
+      ast.Node index,
+      ast.Node rhs,
+      _) {
+    generateDynamicSend(node);
+  }
+
+  void handleIndexSendSet(ast.SendSet node) {
+    ast.Operator op = node.assignmentOperator;
+    if ("=" == op.source) {
+      internalError(node, "Unexpected index set.");
+    } else {
+      visit(node.receiver);
+      HInstruction receiver = pop();
+      Link<ast.Node> arguments = node.arguments;
+      HInstruction index;
+      if (node.isIndex) {
+        visit(arguments.head);
+        arguments = arguments.tail;
+        index = pop();
+      }
+
+      pushInvokeDynamic(
+          node,
+          elements.getGetterSelectorInComplexSendSet(node),
+          elements.getGetterTypeMaskInComplexSendSet(node),
+          [receiver, index]);
+      HInstruction getterInstruction = pop();
+      if (node.isIfNullAssignment) {
+        // Compile x[i] ??= e as:
+        //   t1 = x[i]
+        //   if (t1 == null)
+        //      t1 = x[i] = e;
+        //   result = t1
+        SsaBranchBuilder brancher = new SsaBranchBuilder(this, node);
+        brancher.handleIfNull(() => stack.add(getterInstruction),
+            () {
+              visit(arguments.head);
+              HInstruction value = pop();
+              pushInvokeDynamic(
+                  node,
+                  elements.getSelector(node),
+                  elements.getTypeMask(node),
+                  [receiver, index, value]);
+              pop();
+              stack.add(value);
+            });
+      } else {
+        handleComplexOperatorSend(node, getterInstruction, arguments);
+        HInstruction value = pop();
+        pushInvokeDynamic(
+            node,
+            elements.getSelector(node),
+            elements.getTypeMask(node),
+            [receiver, index, value]);
+        pop();
+        if (node.isPostfix) {
+          stack.add(getterInstruction);
+        } else {
+          stack.add(value);
+        }
+      }
+    }
+  }
+
+  @override
+  void visitThisPropertySet(
+      ast.SendSet node,
+      Selector selector,
+      ast.Node rhs,
+      _) {
+    generateInstanceSetterWithCompiledReceiver(
+        node,
+        localsHandler.readThis(),
+        visitAndPop(rhs));
+  }
+
+  @override
+  void visitDynamicPropertySet(
+      ast.SendSet node,
+      ast.Node receiver,
+      Selector selector,
+      ast.Node rhs,
+      _) {
+    generateInstanceSetterWithCompiledReceiver(
+        node,
+        generateInstanceSendReceiver(node),
+        visitAndPop(rhs));
+  }
+
+  @override
+  void visitIfNotNullDynamicPropertySet(
+      ast.SendSet node,
+      ast.Node receiver,
+      Selector selector,
+      ast.Node rhs,
+      _) {
+    // compile e?.x = e2 to:
+    //
+    // t1 = e
+    // if (t1 == null)
+    //   result = t1 // same as result = null
+    // else
+    //   result = e.x = e2
+    HInstruction receiverInstruction;
+    SsaBranchBuilder brancher = new SsaBranchBuilder(this, node);
+    brancher.handleConditional(
+        () {
+          receiverInstruction = generateInstanceSendReceiver(node);
+          pushCheckNull(receiverInstruction);
+        },
+        () => stack.add(receiverInstruction),
+        () {
+          generateInstanceSetterWithCompiledReceiver(
+              node,
+              receiverInstruction,
+              visitAndPop(rhs));
+        });
+  }
+
+  @override
+  void visitParameterSet(
+      ast.SendSet node,
+      ParameterElement parameter,
+      ast.Node rhs,
+      _) {
+    generateNonInstanceSetter(node, parameter, visitAndPop(rhs));
+  }
+
+  @override
+  void visitFinalParameterSet(
+      ast.SendSet node,
+      ParameterElement parameter,
+      ast.Node rhs,
+      _) {
+    generateNonInstanceSetter(node, parameter, visitAndPop(rhs));
+  }
+
+  @override
+  void visitLocalVariableSet(
+      ast.SendSet node,
+      LocalVariableElement variable,
+      ast.Node rhs,
+      _) {
+    generateNonInstanceSetter(node, variable, visitAndPop(rhs));
+  }
+
+  @override
+  void visitFinalLocalVariableSet(
+      ast.SendSet node,
+      LocalVariableElement variable,
+      ast.Node rhs,
+      _) {
+    generateNonInstanceSetter(node, variable, visitAndPop(rhs));
+  }
+
+  @override
+  void visitLocalFunctionSet(
+      ast.SendSet node,
+      LocalFunctionElement function,
+      ast.Node rhs,
+      _) {
+    generateNonInstanceSetter(node, function, visitAndPop(rhs));
+  }
+
+  @override
+  void visitTopLevelFieldSet(
+      ast.SendSet node,
+      FieldElement field,
+      ast.Node rhs,
+      _) {
+    generateIsDeferredLoadedCheckOfSend(node);
+    generateNonInstanceSetter(node, field, visitAndPop(rhs));
+  }
+
+  @override
+  void visitFinalTopLevelFieldSet(
+      ast.SendSet node,
+      FieldElement field,
+      ast.Node rhs,
+      _) {
+    generateIsDeferredLoadedCheckOfSend(node);
+    generateNonInstanceSetter(node, field, visitAndPop(rhs));
+  }
+
+  @override
+  void visitTopLevelGetterSet(
+      ast.SendSet node,
+      GetterElement getter,
+      ast.Node rhs,
+      _) {
+    generateIsDeferredLoadedCheckOfSend(node);
+    generateNonInstanceSetter(node, getter, visitAndPop(rhs));
+  }
+
+  @override
+  void visitTopLevelSetterSet(
+      ast.SendSet node,
+      SetterElement setter,
+      ast.Node rhs,
+      _) {
+    generateIsDeferredLoadedCheckOfSend(node);
+    generateNonInstanceSetter(node, setter, visitAndPop(rhs));
+  }
+
+  @override
+  void visitTopLevelFunctionSet(
+      ast.SendSet node,
+      MethodElement function,
+      ast.Node rhs,
+      _) {
+    generateIsDeferredLoadedCheckOfSend(node);
+    generateNonInstanceSetter(node, function, visitAndPop(rhs));
+  }
+
+  @override
+  void visitStaticFieldSet(
+      ast.SendSet node,
+      FieldElement field,
+      ast.Node rhs,
+      _) {
+    generateIsDeferredLoadedCheckOfSend(node);
+    generateNonInstanceSetter(node, field, visitAndPop(rhs));
+  }
+
+  @override
+  void visitFinalStaticFieldSet(
+      ast.SendSet node,
+      FieldElement field,
+      ast.Node rhs,
+      _) {
+    generateIsDeferredLoadedCheckOfSend(node);
+    generateNonInstanceSetter(node, field, visitAndPop(rhs));
+  }
+
+  @override
+  void visitStaticGetterSet(
+      ast.SendSet node,
+      GetterElement getter,
+      ast.Node rhs,
+      _) {
+    generateIsDeferredLoadedCheckOfSend(node);
+    generateNonInstanceSetter(node, getter, visitAndPop(rhs));
+  }
+
+  @override
+  void visitStaticSetterSet(
+      ast.SendSet node,
+      SetterElement setter,
+      ast.Node rhs,
+      _) {
+    generateIsDeferredLoadedCheckOfSend(node);
+    generateNonInstanceSetter(node, setter, visitAndPop(rhs));
+  }
+
+  @override
+  void visitStaticFunctionSet(
+      ast.SendSet node,
+      MethodElement function,
+      ast.Node rhs,
+      _) {
+    generateIsDeferredLoadedCheckOfSend(node);
+    generateNonInstanceSetter(node, function, visitAndPop(rhs));
+  }
+
+  @override
+  void visitUnresolvedSet(
+      ast.SendSet node,
+      Element element,
+      ast.Node rhs,
+      _) {
+    if (node.isSuperCall) {
+      // TODO(johnniwinther): Remove this when final super field assignment is
+      // not an unresolved set.
+      handleSuperSendSet(node);
+    } else {
+      generateIsDeferredLoadedCheckOfSend(node);
+      generateNonInstanceSetter(node, element, visitAndPop(rhs));
+    }
+  }
+
+  @override
+  void visitClassTypeLiteralSet(
+      ast.SendSet node,
+      TypeConstantExpression constant,
+      ast.Node rhs,
+      _) {
+    generateThrowNoSuchMethod(node, constant.type.name,
+                              argumentNodes: node.arguments);
+  }
+
+  @override
+  void visitTypedefTypeLiteralSet(
+      ast.SendSet node,
+      TypeConstantExpression constant,
+      ast.Node rhs,
+      _) {
+    generateThrowNoSuchMethod(node, constant.type.name,
+                              argumentNodes: node.arguments);
+  }
+
+  @override
+  void visitDynamicTypeLiteralSet(
+      ast.SendSet node,
+      TypeConstantExpression constant,
+      ast.Node rhs,
+      _) {
+    generateThrowNoSuchMethod(node, constant.type.name,
+                              argumentNodes: node.arguments);
+  }
+
+  @override
+  void visitTypeVariableTypeLiteralSet(
+      ast.SendSet node,
+      TypeVariableElement element,
+      ast.Node rhs,
+      _) {
+    generateThrowNoSuchMethod(node, element.name,
+                              argumentNodes: node.arguments);
+  }
+
+  void handleCompoundSendSet(ast.SendSet node) {
+    Element element = elements[node];
+    Element getter = elements[node.selector];
+
+    if (!Elements.isUnresolved(getter) && getter.impliesType) {
+      if (node.isIfNullAssignment) {
+        // C ??= x is compiled just as C.
+        stack.add(addConstant(node.selector));
+      } else {
+        ast.Identifier selector = node.selector;
+        generateThrowNoSuchMethod(node, selector.source,
+                                  argumentNodes: node.arguments);
+      }
+      return;
+    }
+
+    if (Elements.isInstanceSend(node, elements)) {
+      void generateAssignment(HInstruction receiver) {
+        // desugars `e.x op= e2` to `e.x = e.x op e2`
+        generateInstanceGetterWithCompiledReceiver(
+            node,
+            elements.getGetterSelectorInComplexSendSet(node),
+            elements.getGetterTypeMaskInComplexSendSet(node),
+            receiver);
+        HInstruction getterInstruction = pop();
+        if (node.isIfNullAssignment) {
+          SsaBranchBuilder brancher = new SsaBranchBuilder(this, node);
+          brancher.handleIfNull(() => stack.add(getterInstruction),
+              () {
+                visit(node.arguments.head);
+                generateInstanceSetterWithCompiledReceiver(
+                    node, receiver, pop());
+              });
+        } else {
+          handleComplexOperatorSend(node, getterInstruction, node.arguments);
+          HInstruction value = pop();
+          generateInstanceSetterWithCompiledReceiver(node, receiver, value);
+        }
+        if (node.isPostfix) {
+          pop();
+          stack.add(getterInstruction);
+        }
+      }
+      if (node.isConditional) {
+        // generate `e?.x op= e2` as:
+        //   t1 = e
+        //   t1 == null ? t1 : (t1.x = t1.x op e2);
+        HInstruction receiver;
+        SsaBranchBuilder brancher = new SsaBranchBuilder(this, node);
+        brancher.handleConditional(
+            () {
+              receiver = generateInstanceSendReceiver(node);
+              pushCheckNull(receiver);
+            },
+            () => stack.add(receiver),
+            () => generateAssignment(receiver));
+      } else {
+        generateAssignment(generateInstanceSendReceiver(node));
+      }
+      return;
+    }
+
+    if (getter.isErroneous) {
+      generateStaticUnresolvedGet(node, getter);
+    } else if (getter.isField) {
+      generateStaticFieldGet(node, getter);
+    } else if (getter.isGetter) {
+      generateStaticGetterGet(node, getter);
+    } else if (getter.isFunction) {
+      generateStaticFunctionGet(node, getter);
+    } else if (getter.isLocal) {
+      handleLocalGet(getter);
+    } else {
+      internalError(node, "Unexpected getter: $getter");
+    }
+    HInstruction getterInstruction = pop();
+    if (node.isIfNullAssignment) {
+      SsaBranchBuilder brancher = new SsaBranchBuilder(this, node);
+      brancher.handleIfNull(() => stack.add(getterInstruction),
+          () {
+            visit(node.arguments.head);
+            generateNonInstanceSetter(node, element, pop());
+          });
+    } else {
+      handleComplexOperatorSend(node, getterInstruction, node.arguments);
+      HInstruction value = pop();
+      generateNonInstanceSetter(node, element, value);
+    }
+    if (node.isPostfix) {
+      pop();
+      stack.add(getterInstruction);
+    }
+  }
+
   @override
   handleSendSet(ast.SendSet node) {
+    ast.Operator op = node.assignmentOperator;
     generateIsDeferredLoadedCheckOfSend(node);
     Element element = elements[node];
     if (!Elements.isUnresolved(element) && element.impliesType) {
       ast.Identifier selector = node.selector;
       generateThrowNoSuchMethod(node, selector.source,
                                 argumentNodes: node.arguments);
-      return;
-    }
-    ast.Operator op = node.assignmentOperator;
-    if (node.isSuperCall) {
-      List<HInstruction> setterInputs = <HInstruction>[];
-      void generateSuperSendSet() {
-        Selector setterSelector = elements.getSelector(node);
-        if (Elements.isUnresolved(element)
-            || !setterSelector.applies(element, compiler.world)) {
-          generateSuperNoSuchMethodSend(
-              node, setterSelector, setterInputs);
-          pop();
-        } else {
-          add(buildInvokeSuper(setterSelector, element, setterInputs));
-        }
-      }
-      if (identical(node.assignmentOperator.source, '=')) {
-        addDynamicSendArgumentsToList(node, setterInputs);
-        generateSuperSendSet();
-        stack.add(setterInputs.last);
-      } else {
-        Element getter = elements[node.selector];
-        List<HInstruction> getterInputs = <HInstruction>[];
-        Link<ast.Node> arguments = node.arguments;
-        if (node.isIndex) {
-          // If node is of the from [:super.foo[0] += 2:], the send has
-          // two arguments: the index and the left hand side. We get
-          // the index and add it as input of the getter and the
-          // setter.
-          visit(arguments.head);
-          arguments = arguments.tail;
-          HInstruction index = pop();
-          getterInputs.add(index);
-          setterInputs.add(index);
-        }
-        HInstruction getterInstruction;
-        Selector getterSelector =
-            elements.getGetterSelectorInComplexSendSet(node);
-        if (Elements.isUnresolved(getter)) {
-          generateSuperNoSuchMethodSend(
-              node,
-              getterSelector,
-              getterInputs);
-          getterInstruction = pop();
-        } else {
-          getterInstruction = buildInvokeSuper(
-              getterSelector, getter, getterInputs);
-          add(getterInstruction);
-        }
-
-        if (node.isIfNullAssignment) {
-          SsaBranchBuilder brancher = new SsaBranchBuilder(this, node);
-          brancher.handleIfNull(() => stack.add(getterInstruction),
-              () {
-                addDynamicSendArgumentsToList(node, setterInputs);
-                generateSuperSendSet();
-                stack.add(setterInputs.last);
-              });
-        } else {
-          handleComplexOperatorSend(node, getterInstruction, arguments);
-          setterInputs.add(pop());
-          generateSuperSendSet();
-          stack.add(node.isPostfix ? getterInstruction : setterInputs.last);
-        }
-      }
+    } else if (node.isSuperCall) {
+      handleSuperSendSet(node);
     } else if (node.isIndex) {
-      if ("=" == op.source) {
-        generateDynamicSend(node);
-      } else {
-        visit(node.receiver);
-        HInstruction receiver = pop();
-        Link<ast.Node> arguments = node.arguments;
-        HInstruction index;
-        if (node.isIndex) {
-          visit(arguments.head);
-          arguments = arguments.tail;
-          index = pop();
-        }
-
-        pushInvokeDynamic(
-            node,
-            elements.getGetterSelectorInComplexSendSet(node),
-            [receiver, index]);
-        HInstruction getterInstruction = pop();
-        if (node.isIfNullAssignment) {
-          // Compile x[i] ??= e as:
-          //   t1 = x[i]
-          //   if (t1 == null)
-          //      t1 = x[i] = e;
-          //   result = t1
-          SsaBranchBuilder brancher = new SsaBranchBuilder(this, node);
-          brancher.handleIfNull(() => stack.add(getterInstruction),
-              () {
-                visit(arguments.head);
-                HInstruction value = pop();
-                pushInvokeDynamic(
-                    node, elements.getSelector(node), [receiver, index, value]);
-                pop();
-                stack.add(value);
-              });
-        } else {
-          handleComplexOperatorSend(node, getterInstruction, arguments);
-          HInstruction value = pop();
-          pushInvokeDynamic(
-              node, elements.getSelector(node), [receiver, index, value]);
-          pop();
-          if (node.isPostfix) {
-            stack.add(getterInstruction);
-          } else {
-            stack.add(value);
-          }
-        }
-      }
+      handleIndexSendSet(node);
     } else if ("=" == op.source) {
-      Link<ast.Node> link = node.arguments;
-      assert(!link.isEmpty && link.tail.isEmpty);
-      if (Elements.isInstanceSend(node, elements)) {
-        generatePossiblyConditionalInstanceSetter(node,
-            () => generateInstanceSendReceiver(node),
-            () => visitAndPop(link.head));
-      } else {
-        visit(link.head);
-        generateNonInstanceSetter(node, element, pop());
-      }
+      internalError(node, "Unexpected assignment.");
     } else if (identical(op.source, "is")) {
       compiler.internalError(op, "is-operator as SendSet.");
     } else {
       assert("++" == op.source || "--" == op.source ||
              node.assignmentOperator.source.endsWith("="));
-
-      Element getter = elements[node.selector];
-
-      if (!Elements.isUnresolved(getter) && getter.impliesType) {
-        if (node.isIfNullAssignment) {
-          // C ??= x is compiled just as C.
-          stack.add(addConstant(node.selector));
-        } else {
-          ast.Identifier selector = node.selector;
-          generateThrowNoSuchMethod(node, selector.source,
-                                    argumentNodes: node.arguments);
-        }
-        return;
-      }
-
-      if (Elements.isInstanceSend(node, elements)) {
-        void generateAssignment(HInstruction receiver) {
-          // desugars `e.x op= e2` to `e.x = e.x op e2`
-          generateInstanceGetterWithCompiledReceiver(
-              node, elements.getGetterSelectorInComplexSendSet(node), receiver);
-          HInstruction getterInstruction = pop();
-          if (node.isIfNullAssignment) {
-            SsaBranchBuilder brancher = new SsaBranchBuilder(this, node);
-            brancher.handleIfNull(() => stack.add(getterInstruction),
-                () {
-                  visit(node.arguments.head);
-                  generateInstanceSetterWithCompiledReceiver(
-                      node, receiver, pop());
-                });
-          } else {
-            handleComplexOperatorSend(node, getterInstruction, node.arguments);
-            HInstruction value = pop();
-            generateInstanceSetterWithCompiledReceiver(node, receiver, value);
-          }
-          if (node.isPostfix) {
-            pop();
-            stack.add(getterInstruction);
-          }
-        }
-        if (node.isConditional) {
-          // generate `e?.x op= e2` as:
-          //   t1 = e
-          //   t1 == null ? t1 : (t1.x = t1.x op e2);
-          HInstruction receiver;
-          SsaBranchBuilder brancher = new SsaBranchBuilder(this, node);
-          brancher.handleConditional(
-              () {
-                receiver = generateInstanceSendReceiver(node);
-                pushCheckNull(receiver);
-              },
-              () => stack.add(receiver),
-              () => generateAssignment(receiver));
-        } else {
-          generateAssignment(generateInstanceSendReceiver(node));
-        }
-        return;
-      }
-
-      if (getter.isErroneous) {
-        generateStaticUnresolvedGet(node, getter);
-      } else if (getter.isField) {
-        generateStaticFieldGet(node, getter);
-      } else if (getter.isGetter) {
-        generateStaticGetterGet(node, getter);
-      } else if (getter.isFunction) {
-        generateStaticFunctionGet(node, getter);
-      } else if (getter.isLocal) {
-        handleLocalGet(getter);
-      } else {
-        internalError(node, "Unexpected getter: $getter");
-      }
-      HInstruction getterInstruction = pop();
-      if (node.isIfNullAssignment) {
-        SsaBranchBuilder brancher = new SsaBranchBuilder(this, node);
-        brancher.handleIfNull(() => stack.add(getterInstruction),
-            () {
-              visit(node.arguments.head);
-              generateNonInstanceSetter(node, element, pop());
-            });
-      } else {
-        handleComplexOperatorSend(node, getterInstruction, node.arguments);
-        HInstruction value = pop();
-        generateNonInstanceSetter(node, element, value);
-      }
-      if (node.isPostfix) {
-        pop();
-        stack.add(getterInstruction);
-      }
+      handleCompoundSendSet(node);
     }
   }
 
@@ -6155,7 +6487,8 @@
 
     HInstruction buildCondition() {
       Selector selector = elements.getMoveNextSelector(node);
-      pushInvokeDynamic(node, selector, [streamIterator]);
+      TypeMask mask = elements.getMoveNextTypeMask(node);
+      pushInvokeDynamic(node, selector, mask, [streamIterator]);
       HInstruction future = pop();
       push(new HAwait(future, new TypeMask.subclass(compiler.objectClass,
                                                     compiler.world)));
@@ -6163,11 +6496,13 @@
     }
     void buildBody() {
       Selector call = elements.getCurrentSelector(node);
-      pushInvokeDynamic(node, call, [streamIterator]);
+      TypeMask callMask = elements.getCurrentTypeMask(node);
+      pushInvokeDynamic(node, call, callMask, [streamIterator]);
 
       ast.Node identifier = node.declaredIdentifier;
       Element variable = elements.getForInVariable(node);
       Selector selector = elements.getSelector(identifier);
+      TypeMask mask = elements.getTypeMask(identifier);
 
       HInstruction value = pop();
       if (identifier.asSend() != null
@@ -6179,6 +6514,7 @@
             receiver,
             value,
             selector: selector,
+            mask: mask,
             location: identifier);
       } else {
         generateNonInstanceSetter(
@@ -6198,7 +6534,9 @@
                  buildUpdate,
                  buildBody);
     }, () {
-      pushInvokeDynamic(node, new Selector.call("cancel", null, 0),
+      pushInvokeDynamic(node,
+          new Selector.call("cancel", null, 0),
+          null,
           [streamIterator]);
       push(new HAwait(pop(), new TypeMask.subclass(compiler.objectClass,
           compiler.world)));
@@ -6218,7 +6556,7 @@
     // case.
 
     Selector selector = elements.getIteratorSelector(node);
-    TypeMask mask = selector.mask;
+    TypeMask mask = elements.getIteratorTypeMask(node);
 
     ClassWorld classWorld = compiler.world;
     if (mask != null && mask.satisfies(backend.jsIndexableClass, classWorld)) {
@@ -6240,21 +6578,24 @@
 
     void buildInitializer() {
       Selector selector = elements.getIteratorSelector(node);
+      TypeMask mask = elements.getIteratorTypeMask(node);
       visit(node.expression);
       HInstruction receiver = pop();
-      pushInvokeDynamic(node, selector, [receiver]);
+      pushInvokeDynamic(node, selector, mask, [receiver]);
       iterator = pop();
     }
 
     HInstruction buildCondition() {
       Selector selector = elements.getMoveNextSelector(node);
-      pushInvokeDynamic(node, selector, [iterator]);
+      TypeMask mask = elements.getMoveNextTypeMask(node);
+      pushInvokeDynamic(node, selector, mask, [iterator]);
       return popBoolified();
     }
 
     void buildBody() {
       Selector call = elements.getCurrentSelector(node);
-      pushInvokeDynamic(node, call, [iterator]);
+      TypeMask mask = elements.getCurrentTypeMask(node);
+      pushInvokeDynamic(node, call, mask, [iterator]);
       buildAssignLoopVariable(node, pop());
       visit(node.body);
     }
@@ -6266,6 +6607,7 @@
     ast.Node identifier = node.declaredIdentifier;
     Element variable = elements.getForInVariable(node);
     Selector selector = elements.getSelector(identifier);
+    TypeMask mask = elements.getTypeMask(identifier);
 
     if (identifier.asSend() != null &&
         Elements.isInstanceSend(identifier, elements)) {
@@ -6276,6 +6618,7 @@
           receiver,
           value,
           selector: selector,
+          mask: mask,
           location: identifier);
     } else {
       generateNonInstanceSetter(null, variable, value, location: identifier);
@@ -6355,9 +6698,8 @@
       // example, `get current` includes null.
       // TODO(sra): The element type of a container type mask might be better.
       Selector selector = new Selector.index();
-      Selector refined = new TypedSelector(arrayType, selector, compiler.world);
-      TypeMask type =
-          TypeMaskFactory.inferredTypeForSelector(refined, compiler);
+      TypeMask type = TypeMaskFactory.inferredTypeForSelector(
+          selector, arrayType, compiler);
 
       HInstruction index = localsHandler.readLocal(indexVariable);
       HInstruction value = new HIndex(array, index, null, type);
@@ -6472,7 +6814,6 @@
 
     if (backend.classNeedsRti(cls)) {
       List<HInstruction> typeInputs = <HInstruction>[];
-      List<DartType> typeVariable = cls.typeVariables;
       expectedType.typeArguments.forEach((DartType argument) {
         typeInputs.add(analyzeTypeArgument(argument));
       });
@@ -6770,9 +7111,6 @@
       bool isDefaultCase(ast.SwitchCase switchCase),
       void buildSwitchCase(ast.SwitchCase switchCase)) {
 
-    Map<ast.CaseMatch, ConstantValue> constants =
-        new Map<ast.CaseMatch, ConstantValue>();
-
     HBasicBlock expressionStart = openNewBlock();
     HInstruction expression = buildExpression();
     if (switchCases.isEmpty) {
@@ -7278,12 +7616,12 @@
 
     // If the `toString` method is guaranteed to return a string we can call it
     // directly.
-    Selector selector =
-        new TypedSelector(expression.instructionType,
-            new Selector.call('toString', null, 0), compiler.world);
-    TypeMask type = TypeMaskFactory.inferredTypeForSelector(selector, compiler);
+    Selector selector = new Selector.call('toString', null, 0);
+    TypeMask type = TypeMaskFactory.inferredTypeForSelector(
+        selector, expression.instructionType, compiler);
     if (type.containsOnlyString(compiler.world)) {
-      builder.pushInvokeDynamic(node, selector, <HInstruction>[expression]);
+      builder.pushInvokeDynamic(
+          node, selector, expression.instructionType, <HInstruction>[expression]);
       append(builder.pop());
       return;
     }
diff --git a/pkg/compiler/lib/src/ssa/codegen.dart b/pkg/compiler/lib/src/ssa/codegen.dart
index c59b1a3..c588a00 100644
--- a/pkg/compiler/lib/src/ssa/codegen.dart
+++ b/pkg/compiler/lib/src/ssa/codegen.dart
@@ -1493,7 +1493,7 @@
     } else {
       assert(node.inputs.length == 1);
       registry.registerSpecializedGetInterceptor(node.interceptedClasses);
-      String name =
+      js.Name name =
           backend.namer.nameForGetInterceptor(node.interceptedClasses);
       var isolate = new js.VariableUse(
           backend.namer.globalObjectFor(backend.interceptorsLibrary));
@@ -1507,11 +1507,11 @@
   visitInvokeDynamicMethod(HInvokeDynamicMethod node) {
     use(node.receiver);
     js.Expression object = pop();
-    String name = node.selector.name;
     String methodName;
     List<js.Expression> arguments = visitArguments(node.inputs);
     Element target = node.element;
 
+    // TODO(herhut): The namer should return the appropriate backendname here.
     if (target != null && !node.isInterceptedCall) {
       if (target == backend.jsArrayAdd) {
         methodName = 'push';
@@ -1531,17 +1531,20 @@
       }
     }
 
+    js.Name methodLiteral;
     if (methodName == null) {
-      methodName = backend.namer.invocationName(node.selector);
+      methodLiteral = backend.namer.invocationName(node.selector);
       registerMethodInvoke(node);
+    } else {
+      methodLiteral = backend.namer.asName(methodName);
     }
-    push(js.propertyCall(object, methodName, arguments), node);
+    push(js.propertyCall(object, methodLiteral, arguments), node);
   }
 
   void visitInvokeConstructorBody(HInvokeConstructorBody node) {
     use(node.inputs[0]);
     js.Expression object = pop();
-    String methodName = backend.namer.instanceMethodName(node.element);
+    js.Name methodName = backend.namer.instanceMethodName(node.element);
     List<js.Expression> arguments = visitArguments(node.inputs);
     push(js.propertyCall(object, methodName, arguments), node);
     registry.registerStaticUse(node.element);
@@ -1551,8 +1554,9 @@
     List<js.Expression> arguments = visitArguments(node.inputs);
     var isolate = new js.VariableUse(
         backend.namer.globalObjectFor(backend.interceptorsLibrary));
-    Selector selector = getOptimizedSelectorFor(node, node.selector);
-    String methodName = backend.registerOneShotInterceptor(selector);
+    Selector selector = node.selector;
+    TypeMask mask = getOptimizedSelectorFor(node, selector, node.mask);
+    js.Name methodName = backend.registerOneShotInterceptor(selector);
     push(js.propertyCall(isolate, methodName, arguments), node);
     if (selector.isGetter) {
       registerGetter(node);
@@ -1564,24 +1568,26 @@
     registry.registerUseInterceptor();
   }
 
-  Selector getOptimizedSelectorFor(HInvokeDynamic node, Selector selector) {
+  TypeMask getOptimizedSelectorFor(HInvokeDynamic node,
+                                   Selector selector,
+                                   TypeMask mask) {
     if (node.element != null) {
       // Create an artificial type mask to make sure only
       // [node.element] will be enqueued. We're not using the receiver
       // type because our optimizations might end up in a state where the
       // invoke dynamic knows more than the receiver.
       ClassElement enclosing = node.element.enclosingClass;
-      TypeMask receiverType =
+      return
           new TypeMask.nonNullExact(enclosing.declaration, compiler.world);
-      return new TypedSelector(receiverType, selector, compiler.world);
     }
     // If [JSInvocationMirror._invokeOn] is enabled, and this call
     // might hit a `noSuchMethod`, we register an untyped selector.
-    return selector.extendIfReachesAll(compiler);
+    return compiler.world.extendMaskIfReachesAll(selector, mask);
   }
 
   void registerMethodInvoke(HInvokeDynamic node) {
-    Selector selector = getOptimizedSelectorFor(node, node.selector);
+    Selector selector = node.selector;
+    TypeMask mask = getOptimizedSelectorFor(node, selector, node.mask);
 
     // If we don't know what we're calling or if we are calling a getter,
     // we need to register that fact that we may be calling a closure
@@ -1592,31 +1598,37 @@
       // may know something about the types of closures that need
       // the specific closure call method.
       Selector call = new Selector.callClosureFrom(selector);
-      registry.registerDynamicInvocation(call);
+      registry.registerDynamicInvocation(
+          new UniverseSelector(call, null));
     }
-    registry.registerDynamicInvocation(selector);
+    registry.registerDynamicInvocation(
+        new UniverseSelector(selector, mask));
   }
 
   void registerSetter(HInvokeDynamic node) {
-    Selector selector = getOptimizedSelectorFor(node, node.selector);
-    registry.registerDynamicSetter(selector);
+    Selector selector = node.selector;
+    TypeMask mask = getOptimizedSelectorFor(node, selector, node.mask);
+    registry.registerDynamicSetter(
+        new UniverseSelector(selector, mask));
   }
 
   void registerGetter(HInvokeDynamic node) {
-    Selector selector = getOptimizedSelectorFor(node, node.selector);
-    registry.registerDynamicGetter(selector);
+    Selector selector = node.selector;
+    TypeMask mask = getOptimizedSelectorFor(node, selector, node.mask);
+    registry.registerDynamicGetter(
+        new UniverseSelector(selector, mask));
   }
 
   visitInvokeDynamicSetter(HInvokeDynamicSetter node) {
     use(node.receiver);
-    String name = backend.namer.invocationName(node.selector);
+    js.Name name = backend.namer.invocationName(node.selector);
     push(js.propertyCall(pop(), name, visitArguments(node.inputs)), node);
     registerSetter(node);
   }
 
   visitInvokeDynamicGetter(HInvokeDynamicGetter node) {
     use(node.receiver);
-    String name = backend.namer.invocationName(node.selector);
+    js.Name name = backend.namer.invocationName(node.selector);
     push(js.propertyCall(pop(), name, visitArguments(node.inputs)), node);
     registerGetter(node);
   }
@@ -1628,7 +1640,8 @@
                          backend.namer.invocationName(call),
                          visitArguments(node.inputs)),
          node);
-    registry.registerDynamicInvocation(call);
+    registry.registerDynamicInvocation(
+        new UniverseSelector(call, null));
   }
 
   visitInvokeStatic(HInvokeStatic node) {
@@ -1678,10 +1691,10 @@
     registry.registerSuperInvocation(superMethod);
     ClassElement superClass = superMethod.enclosingClass;
     if (superMethod.kind == ElementKind.FIELD) {
-      String fieldName = backend.namer.instanceFieldPropertyName(superMethod);
+      js.Name fieldName =
+          backend.namer.instanceFieldPropertyName(superMethod);
       use(node.inputs[0]);
-      js.PropertyAccess access =
-          new js.PropertyAccess.field(pop(), fieldName);
+      js.PropertyAccess access = new js.PropertyAccess(pop(), fieldName);
       if (node.isSetter) {
         use(node.value);
         push(new js.Assignment(access, pop()), node);
@@ -1692,17 +1705,17 @@
       Selector selector = node.selector;
 
       if (!backend.maybeRegisterAliasedSuperMember(superMethod, selector)) {
-        String methodName;
+        js.Name methodName;
         if (selector.isGetter) {
           // If the selector we need to register a typed getter to the
           // [world]. The emitter needs to know if it needs to emit a
           // bound closure for a method.
           TypeMask receiverType =
               new TypeMask.nonNullExact(superClass, compiler.world);
-          selector = new TypedSelector(receiverType, selector, compiler.world);
           // TODO(floitsch): we know the target. We shouldn't register a
           // dynamic getter.
-          registry.registerDynamicGetter(selector);
+          registry.registerDynamicGetter(
+              new UniverseSelector(selector, receiverType));
           registry.registerGetterForSuperMethod(node.element);
           methodName = backend.namer.invocationName(selector);
         } else {
@@ -1739,8 +1752,8 @@
       // property should not be mangled.
       push(new js.PropertyAccess.field(pop(), 'length'), node);
     } else {
-      String name = backend.namer.instanceFieldPropertyName(element);
-      push(new js.PropertyAccess.field(pop(), name), node);
+      js.Name name = backend.namer.instanceFieldPropertyName(element);
+      push(new js.PropertyAccess(pop(), name), node);
       registry.registerFieldGetter(element);
     }
   }
@@ -1748,20 +1761,20 @@
   visitFieldSet(HFieldSet node) {
     Element element = node.element;
     registry.registerFieldSetter(element);
-    String name = backend.namer.instanceFieldPropertyName(element);
+    js.Name name = backend.namer.instanceFieldPropertyName(element);
     use(node.receiver);
     js.Expression receiver = pop();
     use(node.value);
-    push(new js.Assignment(new js.PropertyAccess.field(receiver, name), pop()),
+    push(new js.Assignment(new js.PropertyAccess(receiver, name), pop()),
         node);
   }
 
   visitReadModifyWrite(HReadModifyWrite node) {
     Element element = node.element;
     registry.registerFieldSetter(element);
-    String name = backend.namer.instanceFieldPropertyName(element);
+    js.Name name = backend.namer.instanceFieldPropertyName(element);
     use(node.receiver);
-    js.Expression fieldReference = new js.PropertyAccess.field(pop(), name);
+    js.Expression fieldReference = new js.PropertyAccess(pop(), name);
     if (node.isPreOp) {
       push(new js.Prefix(node.jsOp, fieldReference), node);
     } else if (node.isPostOp) {
@@ -1892,7 +1905,6 @@
       if (instruction is !HRelational) return false;
 
       HRelational relational = instruction;
-      BinaryOperation operation = relational.operation(backend.constantSystem);
 
       HInstruction left = relational.left;
       HInstruction right = relational.right;
@@ -2356,7 +2368,7 @@
     use(input);
 
     js.PropertyAccess field =
-        new js.PropertyAccess.field(pop(), backend.namer.operatorIsType(type));
+        new js.PropertyAccess(pop(), backend.namer.operatorIsType(type));
     // We always negate at least once so that the result is boolified.
     push(new js.Prefix('!', field));
     // If the result is not negated, put another '!' in front.
@@ -2460,7 +2472,6 @@
     } else {
       assert(node.isRawCheck);
       HInstruction interceptor = node.interceptor;
-      LibraryElement coreLibrary = compiler.coreLibrary;
       ClassElement objectClass = compiler.objectClass;
       Element element = type.element;
       if (element == compiler.nullClass) {
@@ -2588,7 +2599,7 @@
         generateThrowWithHelper('iae', node.checkedInput);
       } else if (node.isReceiverTypeCheck) {
         use(node.checkedInput);
-        String methodName =
+        js.Name methodName =
             backend.namer.invocationName(node.receiverTypeCheckSelector);
         js.Expression call = js.propertyCall(pop(), methodName, []);
         pushStatement(new js.Return(call));
diff --git a/pkg/compiler/lib/src/ssa/codegen_helpers.dart b/pkg/compiler/lib/src/ssa/codegen_helpers.dart
index e6bf13d..bafa560 100644
--- a/pkg/compiler/lib/src/ssa/codegen_helpers.dart
+++ b/pkg/compiler/lib/src/ssa/codegen_helpers.dart
@@ -111,8 +111,9 @@
       //     b.get$thing().foo$1(0, x)
       //
       Selector selector = node.selector;
+      TypeMask mask = node.mask;
       if (backend.isInterceptedSelector(selector) &&
-          !backend.isInterceptedMixinSelector(selector)) {
+          !backend.isInterceptedMixinSelector(selector, mask)) {
         HInstruction interceptor = node.inputs[0];
         HInstruction receiverArgument = node.inputs[1];
 
@@ -120,7 +121,8 @@
           // TODO(15933): Make automatically generated property extraction
           // closures work with the dummy receiver optimization.
           if (!selector.isGetter) {
-            ConstantValue constant = new DummyConstantValue(
+            ConstantValue constant = new SyntheticConstantValue(
+                SyntheticConstantKind.DUMMY_INTERCEPTOR,
                 receiverArgument.instructionType);
             HConstant dummy = graph.addConstant(constant, compiler);
             receiverArgument.usedBy.remove(node);
diff --git a/pkg/compiler/lib/src/ssa/interceptor_simplifier.dart b/pkg/compiler/lib/src/ssa/interceptor_simplifier.dart
index a22b94d..97b4b17 100644
--- a/pkg/compiler/lib/src/ssa/interceptor_simplifier.dart
+++ b/pkg/compiler/lib/src/ssa/interceptor_simplifier.dart
@@ -347,7 +347,8 @@
         List<HInstruction> inputs = new List<HInstruction>.from(user.inputs);
         inputs[0] = nullConstant;
         HOneShotInterceptor oneShotInterceptor = new HOneShotInterceptor(
-            user.selector, inputs, user.instructionType, interceptedClasses);
+            user.selector, user.mask,
+            inputs, user.instructionType, interceptedClasses);
         oneShotInterceptor.sourceInformation = user.sourceInformation;
         oneShotInterceptor.sourceElement = user.sourceElement;
         return replaceUserWith(oneShotInterceptor);
@@ -380,16 +381,19 @@
     if (constant == null) return false;
 
     Selector selector = node.selector;
+    TypeMask mask = node.mask;
     HInstruction instruction;
     if (selector.isGetter) {
       instruction = new HInvokeDynamicGetter(
           selector,
+          mask,
           node.element,
           <HInstruction>[constant, node.inputs[1]],
           node.instructionType);
     } else if (selector.isSetter) {
       instruction = new HInvokeDynamicSetter(
           selector,
+          mask,
           node.element,
           <HInstruction>[constant, node.inputs[1], node.inputs[2]],
           node.instructionType);
@@ -397,7 +401,7 @@
       List<HInstruction> inputs = new List<HInstruction>.from(node.inputs);
       inputs[0] = constant;
       instruction = new HInvokeDynamicMethod(
-          selector, inputs, node.instructionType, true);
+          selector, mask, inputs, node.instructionType, true);
     }
 
     HBasicBlock block = node.block;
diff --git a/pkg/compiler/lib/src/ssa/invoke_dynamic_specializers.dart b/pkg/compiler/lib/src/ssa/invoke_dynamic_specializers.dart
index dbc5e5f..be3406f 100644
--- a/pkg/compiler/lib/src/ssa/invoke_dynamic_specializers.dart
+++ b/pkg/compiler/lib/src/ssa/invoke_dynamic_specializers.dart
@@ -15,8 +15,8 @@
 
   TypeMask computeTypeFromInputTypes(HInvokeDynamic instruction,
                                      Compiler compiler) {
-    Selector selector = instruction.selector;
-    return TypeMaskFactory.inferredTypeForSelector(selector, compiler);
+    return TypeMaskFactory.inferredTypeForSelector(
+        instruction.selector, instruction.mask, compiler);
   }
 
   HInstruction tryConvertToBuiltin(HInvokeDynamic instruction,
@@ -113,9 +113,8 @@
     }
     TypeMask receiverType =
         instruction.getDartReceiver(compiler).instructionType;
-    Selector refined = new TypedSelector(receiverType, instruction.selector,
-        compiler.world);
-    TypeMask type = TypeMaskFactory.inferredTypeForSelector(refined, compiler);
+    TypeMask type = TypeMaskFactory.inferredTypeForSelector(
+        instruction.selector, receiverType, compiler);
     return new HIndex(
         instruction.inputs[1], instruction.inputs[2],
         instruction.selector, type);
@@ -239,12 +238,9 @@
                                      Compiler compiler) {
     if (selector.name == name) return selector;
     JavaScriptBackend backend = compiler.backend;
-    Selector newSelector = new Selector(
+    return new Selector(
         SelectorKind.CALL, new Name(name, backend.interceptorsLibrary),
         new CallStructure(selector.argumentCount));
-    return selector.mask == null
-        ? newSelector
-        : new TypedSelector(selector.mask, newSelector, compiler.world);
   }
 }
 
@@ -669,10 +665,9 @@
       return newBuiltinVariant(instruction, compiler);
     }
     World world = compiler.world;
-    Selector selector =
-        new TypedSelector(instructionType, instruction.selector, world);
     JavaScriptBackend backend = compiler.backend;
-    Iterable<Element> matches = world.allFunctions.filter(selector);
+    Iterable<Element> matches = world.allFunctions.filter(
+        instruction.selector, instructionType);
     // This test relies the on `Object.==` and `Interceptor.==` always being
     // implemented because if the selector matches by subtype, it still will be
     // a regular object or an interceptor.
diff --git a/pkg/compiler/lib/src/ssa/nodes.dart b/pkg/compiler/lib/src/ssa/nodes.dart
index 5750445..765ce05 100644
--- a/pkg/compiler/lib/src/ssa/nodes.dart
+++ b/pkg/compiler/lib/src/ssa/nodes.dart
@@ -211,6 +211,14 @@
         compiler);
   }
 
+  HConstant addConstantStringFromName(js.Name name,
+                                      Compiler compiler) {
+    return addConstant(
+        new SyntheticConstantValue(SyntheticConstantKind.NAME,
+                                   js.quoteName(name)),
+        compiler);
+  }
+
   HConstant addConstantBool(bool value, Compiler compiler) {
     return addConstant(
         compiler.backend.constantSystem.createBool(value), compiler);
@@ -1393,16 +1401,19 @@
     // We know it's a selector call if it follows the interceptor
     // calling convention, which adds the actual receiver as a
     // parameter to the call.
-    return (selector != null) && (inputs.length - 2 == selector.argumentCount);
+    return (selector != null) &&
+           (inputs.length - 2 == selector.argumentCount);
   }
 }
 
 abstract class HInvokeDynamic extends HInvoke {
   final InvokeDynamicSpecializer specializer;
   Selector selector;
+  TypeMask mask;
   Element element;
 
   HInvokeDynamic(Selector selector,
+                 this.mask,
                  this.element,
                  List<HInstruction> inputs,
                  TypeMask type,
@@ -1412,7 +1423,7 @@
       specializer = isIntercepted
           ? InvokeDynamicSpecializer.lookupSpecializer(selector)
           : const InvokeDynamicSpecializer();
-  toString() => 'invoke dynamic: $selector';
+  toString() => 'invoke dynamic: selector=$selector, mask=$mask';
   HInstruction get receiver => inputs[0];
   HInstruction getDartReceiver(Compiler compiler) {
     return isCallOnInterceptor(compiler) ? inputs[1] : inputs[0];
@@ -1437,8 +1448,10 @@
 }
 
 class HInvokeClosure extends HInvokeDynamic {
-  HInvokeClosure(Selector selector, List<HInstruction> inputs, TypeMask type)
-    : super(selector, null, inputs, type) {
+  HInvokeClosure(Selector selector,
+                 List<HInstruction> inputs,
+                 TypeMask type)
+      : super(selector, null, null, inputs, type) {
     assert(selector.isClosureCall);
   }
   accept(HVisitor visitor) => visitor.visitInvokeClosure(this);
@@ -1446,34 +1459,38 @@
 
 class HInvokeDynamicMethod extends HInvokeDynamic {
   HInvokeDynamicMethod(Selector selector,
+                       TypeMask mask,
                        List<HInstruction> inputs,
                        TypeMask type,
                        [bool isIntercepted = false])
-    : super(selector, null, inputs, type, isIntercepted);
+    : super(selector, mask, null, inputs, type, isIntercepted);
 
-  String toString() => 'invoke dynamic method: $selector';
+  String toString() => 'invoke dynamic method: selector=$selector, mask=$mask';
   accept(HVisitor visitor) => visitor.visitInvokeDynamicMethod(this);
 }
 
 abstract class HInvokeDynamicField extends HInvokeDynamic {
   HInvokeDynamicField(
-      Selector selector, Element element, List<HInstruction> inputs,
+      Selector selector, TypeMask mask,
+      Element element, List<HInstruction> inputs,
       TypeMask type)
-      : super(selector, element, inputs, type);
-  toString() => 'invoke dynamic field: $selector';
+      : super(selector, mask, element, inputs, type);
+  toString() => 'invoke dynamic field: selector=$selector, mask=$mask';
 }
 
 class HInvokeDynamicGetter extends HInvokeDynamicField {
-  HInvokeDynamicGetter(selector, element, inputs, type)
-    : super(selector, element, inputs, type);
-  toString() => 'invoke dynamic getter: $selector';
+  HInvokeDynamicGetter(Selector selector, TypeMask mask,
+      Element element, List<HInstruction> inputs, TypeMask type)
+    : super(selector, mask, element, inputs, type);
+  toString() => 'invoke dynamic getter: selector=$selector, mask=$mask';
   accept(HVisitor visitor) => visitor.visitInvokeDynamicGetter(this);
 }
 
 class HInvokeDynamicSetter extends HInvokeDynamicField {
-  HInvokeDynamicSetter(selector, element, inputs, type)
-    : super(selector, element, inputs, type);
-  toString() => 'invoke dynamic setter: $selector';
+  HInvokeDynamicSetter(Selector selector, TypeMask mask,
+      Element element, List<HInstruction> inputs, TypeMask type)
+    : super(selector, mask, element, inputs, type);
+  toString() => 'invoke dynamic setter: selector=$selector, mask=$mask';
   accept(HVisitor visitor) => visitor.visitInvokeDynamicSetter(this);
 }
 
@@ -1792,7 +1809,8 @@
 
 abstract class HInvokeBinary extends HInstruction {
   final Selector selector;
-  HInvokeBinary(HInstruction left, HInstruction right, this.selector, type)
+  HInvokeBinary(
+      HInstruction left, HInstruction right, this.selector, TypeMask type)
       : super(<HInstruction>[left, right], type) {
     sideEffects.clearAllSideEffects();
     sideEffects.clearAllDependencies();
@@ -1806,13 +1824,15 @@
 }
 
 abstract class HBinaryArithmetic extends HInvokeBinary {
-  HBinaryArithmetic(left, right, selector, type)
+  HBinaryArithmetic(
+      HInstruction left, HInstruction right, Selector selector, TypeMask type)
       : super(left, right, selector, type);
   BinaryOperation operation(ConstantSystem constantSystem);
 }
 
 class HAdd extends HBinaryArithmetic {
-  HAdd(left, right, selector, type) : super(left, right, selector, type);
+  HAdd(HInstruction left, HInstruction right, Selector selector, TypeMask type)
+      : super(left, right, selector, type);
   accept(HVisitor visitor) => visitor.visitAdd(this);
 
   BinaryOperation operation(ConstantSystem constantSystem)
@@ -1823,7 +1843,9 @@
 }
 
 class HDivide extends HBinaryArithmetic {
-  HDivide(left, right, selector, type) : super(left, right, selector, type);
+  HDivide(
+      HInstruction left, HInstruction right, Selector selector, TypeMask type)
+      : super(left, right, selector, type);
   accept(HVisitor visitor) => visitor.visitDivide(this);
 
   BinaryOperation operation(ConstantSystem constantSystem)
@@ -1834,7 +1856,9 @@
 }
 
 class HMultiply extends HBinaryArithmetic {
-  HMultiply(left, right, selector, type) : super(left, right, selector, type);
+  HMultiply(
+      HInstruction left, HInstruction right, Selector selector, TypeMask type)
+      : super(left, right, selector, type);
   accept(HVisitor visitor) => visitor.visitMultiply(this);
 
   BinaryOperation operation(ConstantSystem operations)
@@ -1845,7 +1869,9 @@
 }
 
 class HSubtract extends HBinaryArithmetic {
-  HSubtract(left, right, selector, type) : super(left, right, selector, type);
+  HSubtract(
+      HInstruction left, HInstruction right, Selector selector, TypeMask type)
+      : super(left, right, selector, type);
   accept(HVisitor visitor) => visitor.visitSubtract(this);
 
   BinaryOperation operation(ConstantSystem constantSystem)
@@ -1856,7 +1882,8 @@
 }
 
 class HTruncatingDivide extends HBinaryArithmetic {
-  HTruncatingDivide(left, right, selector, type)
+  HTruncatingDivide(
+      HInstruction left, HInstruction right, Selector selector, TypeMask type)
       : super(left, right, selector, type);
   accept(HVisitor visitor) => visitor.visitTruncatingDivide(this);
 
@@ -1891,12 +1918,15 @@
 }
 
 abstract class HBinaryBitOp extends HInvokeBinary {
-  HBinaryBitOp(left, right, selector, type)
+  HBinaryBitOp(
+      HInstruction left, HInstruction right, Selector selector, TypeMask type)
       : super(left, right, selector, type);
 }
 
 class HShiftLeft extends HBinaryBitOp {
-  HShiftLeft(left, right, selector, type) : super(left, right, selector, type);
+  HShiftLeft(
+      HInstruction left, HInstruction right, Selector selector, TypeMask type)
+      : super(left, right, selector, type);
   accept(HVisitor visitor) => visitor.visitShiftLeft(this);
 
   BinaryOperation operation(ConstantSystem constantSystem)
@@ -1907,7 +1937,9 @@
 }
 
 class HShiftRight extends HBinaryBitOp {
-  HShiftRight(left, right, selector, type) : super(left, right, selector, type);
+  HShiftRight(
+      HInstruction left, HInstruction right, Selector selector, TypeMask type)
+      : super(left, right, selector, type);
   accept(HVisitor visitor) => visitor.visitShiftRight(this);
 
   BinaryOperation operation(ConstantSystem constantSystem)
@@ -1918,7 +1950,9 @@
 }
 
 class HBitOr extends HBinaryBitOp {
-  HBitOr(left, right, selector, type) : super(left, right, selector, type);
+  HBitOr(
+      HInstruction left, HInstruction right, Selector selector, TypeMask type)
+      : super(left, right, selector, type);
   accept(HVisitor visitor) => visitor.visitBitOr(this);
 
   BinaryOperation operation(ConstantSystem constantSystem)
@@ -1929,7 +1963,9 @@
 }
 
 class HBitAnd extends HBinaryBitOp {
-  HBitAnd(left, right, selector, type) : super(left, right, selector, type);
+  HBitAnd(
+      HInstruction left, HInstruction right, Selector selector, TypeMask type)
+      : super(left, right, selector, type);
   accept(HVisitor visitor) => visitor.visitBitAnd(this);
 
   BinaryOperation operation(ConstantSystem constantSystem)
@@ -1940,7 +1976,9 @@
 }
 
 class HBitXor extends HBinaryBitOp {
-  HBitXor(left, right, selector, type) : super(left, right, selector, type);
+  HBitXor(
+      HInstruction left, HInstruction right, Selector selector, TypeMask type)
+      : super(left, right, selector, type);
   accept(HVisitor visitor) => visitor.visitBitXor(this);
 
   BinaryOperation operation(ConstantSystem constantSystem)
@@ -1965,7 +2003,8 @@
 }
 
 class HNegate extends HInvokeUnary {
-  HNegate(input, selector, type) : super(input, selector, type);
+  HNegate(HInstruction input, Selector selector, TypeMask type)
+      : super(input, selector, type);
   accept(HVisitor visitor) => visitor.visitNegate(this);
 
   UnaryOperation operation(ConstantSystem constantSystem)
@@ -1976,7 +2015,8 @@
 }
 
 class HBitNot extends HInvokeUnary {
-  HBitNot(input, selector, type) : super(input, selector, type);
+  HBitNot(HInstruction input, Selector selector, TypeMask type)
+      : super(input, selector, type);
   accept(HVisitor visitor) => visitor.visitBitNot(this);
 
   UnaryOperation operation(ConstantSystem constantSystem)
@@ -2379,16 +2419,17 @@
 class HOneShotInterceptor extends HInvokeDynamic {
   Set<ClassElement> interceptedClasses;
   HOneShotInterceptor(Selector selector,
+                      TypeMask mask,
                       List<HInstruction> inputs,
                       TypeMask type,
                       this.interceptedClasses)
-      : super(selector, null, inputs, type, true) {
+      : super(selector, mask, null, inputs, type, true) {
     assert(inputs[0] is HConstant);
     assert(inputs[0].isNull());
   }
   bool isCallOnInterceptor(Compiler compiler) => true;
 
-  String toString() => 'one shot interceptor on $selector';
+  String toString() => 'one shot interceptor: selector=$selector, mask=$mask';
   accept(HVisitor visitor) => visitor.visitOneShotInterceptor(this);
 }
 
@@ -2442,7 +2483,10 @@
  */
 class HIndex extends HInstruction {
   final Selector selector;
-  HIndex(HInstruction receiver, HInstruction index, this.selector, type)
+  HIndex(HInstruction receiver,
+         HInstruction index,
+         this.selector,
+         TypeMask type)
       : super(<HInstruction>[receiver, index], type) {
     sideEffects.clearAllSideEffects();
     sideEffects.clearAllDependencies();
diff --git a/pkg/compiler/lib/src/ssa/optimize.dart b/pkg/compiler/lib/src/ssa/optimize.dart
index 953a6f4..977900c 100644
--- a/pkg/compiler/lib/src/ssa/optimize.dart
+++ b/pkg/compiler/lib/src/ssa/optimize.dart
@@ -301,15 +301,22 @@
     if (instruction != null) return instruction;
 
     Selector selector = node.selector;
+    TypeMask mask = node.mask;
     HInstruction input = node.inputs[1];
 
     World world = compiler.world;
+
+    bool applies(Element element) {
+      return selector.applies(element, world) &&
+             (mask == null || mask.canHit(element, selector, world));
+    }
+
     if (selector.isCall || selector.isOperator) {
       Element target;
       if (input.isExtendableArray(compiler)) {
-        if (selector.applies(backend.jsArrayRemoveLast, world)) {
+        if (applies(backend.jsArrayRemoveLast)) {
           target = backend.jsArrayRemoveLast;
-        } else if (selector.applies(backend.jsArrayAdd, world)) {
+        } else if (applies(backend.jsArrayAdd)) {
           // The codegen special cases array calls, but does not
           // inline argument type checks.
           if (!compiler.enableTypeAssertions) {
@@ -317,12 +324,12 @@
           }
         }
       } else if (input.isStringOrNull(compiler)) {
-        if (selector.applies(backend.jsStringSplit, world)) {
+        if (applies(backend.jsStringSplit)) {
           HInstruction argument = node.inputs[2];
           if (argument.isString(compiler)) {
             target = backend.jsStringSplit;
           }
-        } else if (selector.applies(backend.jsStringOperatorAdd, world)) {
+        } else if (applies(backend.jsStringOperatorAdd)) {
           // `operator+` is turned into a JavaScript '+' so we need to
           // make sure the receiver and the argument are not null.
           // TODO(sra): Do this via [node.specializer].
@@ -332,7 +339,7 @@
             return new HStringConcat(input, argument, null,
                                      node.instructionType);
           }
-        } else if (selector.applies(backend.jsStringToString, world)
+        } else if (applies(backend.jsStringToString)
                    && !input.canBeNull()) {
           return input;
         }
@@ -347,12 +354,13 @@
         // bounds check will become explicit, so we won't need this
         // optimization.
         HInvokeDynamicMethod result = new HInvokeDynamicMethod(
-            node.selector, node.inputs.sublist(1), node.instructionType);
+            node.selector, node.mask,
+            node.inputs.sublist(1), node.instructionType);
         result.element = target;
         return result;
       }
     } else if (selector.isGetter) {
-      if (selector.asUntyped.applies(backend.jsIndexableLength, world)) {
+      if (selector.applies(backend.jsIndexableLength, world)) {
         HInstruction optimized = tryOptimizeLengthInterceptedGetter(node);
         if (optimized != null) return optimized;
       }
@@ -368,15 +376,14 @@
     }
 
     TypeMask receiverType = node.getDartReceiver(compiler).instructionType;
-    Selector selector =
-        new TypedSelector(receiverType, node.selector, compiler.world);
-    Element element = compiler.world.locateSingleElement(selector);
+    Element element =
+        compiler.world.locateSingleElement(node.selector, receiverType);
     // TODO(ngeoffray): Also fold if it's a getter or variable.
     if (element != null
         && element.isFunction
         // If we found out that the only target is a [:noSuchMethod:],
         // we just ignore it.
-        && element.name == selector.name) {
+        && element.name == node.selector.name) {
       FunctionElement method = element;
 
       if (method.isNative) {
@@ -386,8 +393,9 @@
         // TODO(ngeoffray): If the method has optional parameters,
         // we should pass the default values.
         FunctionSignature parameters = method.functionSignature;
-        if (parameters.optionalParameterCount == 0
-            || parameters.parameterCount == node.selector.argumentCount) {
+        if (parameters.optionalParameterCount == 0 ||
+            parameters.parameterCount ==
+                node.selector.argumentCount) {
           node.element = element;
         }
       }
@@ -426,8 +434,7 @@
     int inputPosition = 1;  // Skip receiver.
     bool canInline = true;
     signature.forEachParameter((ParameterElement element) {
-      if (inputPosition < inputs.length && canInline) {
-        HInstruction input = inputs[inputPosition++];
+      if (inputPosition++ < inputs.length && canInline) {
         DartType type = element.type.unalias(compiler);
         if (type is FunctionType) {
           canInline = false;
@@ -451,7 +458,7 @@
     TypeMask returnType =
         TypeMaskFactory.fromNativeBehavior(nativeBehavior, compiler);
     HInvokeDynamicMethod result =
-        new HInvokeDynamicMethod(node.selector, inputs, returnType);
+        new HInvokeDynamicMethod(node.selector, node.mask, inputs, returnType);
     result.element = method;
     return result;
   }
@@ -697,7 +704,6 @@
   }
 
   HInstruction visitTypeConversion(HTypeConversion node) {
-    HInstruction value = node.inputs[0];
     DartType type = node.typeExpression;
     if (type != null) {
       if (type.isMalformed) {
@@ -731,8 +737,7 @@
   VariableElement findConcreteFieldForDynamicAccess(HInstruction receiver,
                                                     Selector selector) {
     TypeMask receiverType = receiver.instructionType;
-    return compiler.world.locateSingleField(
-        new TypedSelector(receiverType, selector, compiler.world));
+    return compiler.world.locateSingleField(selector, receiverType);
   }
 
   HInstruction visitFieldGet(HFieldGet node) {
@@ -804,7 +809,8 @@
       if (folded != node) return folded;
     }
     HInstruction receiver = node.getDartReceiver(compiler);
-    Element field = findConcreteFieldForDynamicAccess(receiver, node.selector);
+    Element field = findConcreteFieldForDynamicAccess(
+        receiver, node.selector);
     if (field == null) return node;
     return directFieldGet(receiver, field);
   }
@@ -1037,6 +1043,7 @@
   Map<HInstruction, bool> trivialDeadStoreReceivers =
       new Maplet<HInstruction, bool>();
   bool eliminatedSideEffects = false;
+
   SsaDeadCodeEliminator(this.compiler, this.optimizer);
 
   HInstruction zapInstructionCache;
@@ -1044,7 +1051,9 @@
     if (zapInstructionCache == null) {
       // A constant with no type does not pollute types at phi nodes.
       ConstantValue constant =
-          new DummyConstantValue(const TypeMask.nonNullEmpty());
+          new SyntheticConstantValue(
+              SyntheticConstantKind.EMPTY_VALUE,
+              const TypeMask.nonNullEmpty());
       zapInstructionCache = analyzer.graph.addConstant(constant, compiler);
     }
     return zapInstructionCache;
@@ -1142,7 +1151,8 @@
       }
       return false;
     }
-    return instruction is HForeignNew
+    return instruction.isAllocation
+        && instruction.isPure()
         && trivialDeadStoreReceivers.putIfAbsent(instruction,
             () => instruction.usedBy.every(isDeadUse));
   }
@@ -1156,14 +1166,14 @@
     if (!instruction.usedBy.isEmpty) return false;
     if (isTrivialDeadStore(instruction)) return true;
     if (instruction.sideEffects.hasSideEffects()) return false;
-    if (instruction.canThrow()
-        && instruction.onlyThrowsNSM()
-        && hasFollowingThrowingNSM(instruction)) {
+    if (instruction.canThrow() &&
+        instruction.onlyThrowsNSM() &&
+        hasFollowingThrowingNSM(instruction)) {
       return true;
     }
     return !instruction.canThrow()
-           && instruction is !HParameterValue
-           && instruction is !HLocalSet;
+        && instruction is !HParameterValue
+        && instruction is !HLocalSet;
   }
 
   void visitGraph(HGraph graph) {
diff --git a/pkg/compiler/lib/src/ssa/ssa.dart b/pkg/compiler/lib/src/ssa/ssa.dart
index 2bef586..a40d75e 100644
--- a/pkg/compiler/lib/src/ssa/ssa.dart
+++ b/pkg/compiler/lib/src/ssa/ssa.dart
@@ -11,7 +11,6 @@
 import '../constants/constant_system.dart';
 import '../constants/expressions.dart';
 import '../constants/values.dart';
-import '../deferred_load.dart' show DeferredLoadTask;
 import '../dart2jslib.dart' hide Selector, TypedSelector;
 import '../dart_types.dart';
 import '../elements/elements.dart';
@@ -19,16 +18,13 @@
     show ElementX,
          VariableElementX,
          ConstructorBodyElementX;
-import '../helpers/helpers.dart';
-import '../io/source_file.dart';
+
 import '../io/source_information.dart';
 import '../js/js.dart' as js;
 import '../js_backend/js_backend.dart';
 import '../js_emitter/js_emitter.dart' show CodeEmitterTask, NativeEmitter;
 import '../native/native.dart' as native;
 import '../resolution/operators.dart';
-import '../scanner/scannerlib.dart'
-    show PartialFunctionElement, Token, PLUS_TOKEN;
 import '../tree/tree.dart' as ast;
 import '../types/types.dart';
 import '../types/constants.dart' show computeTypeMask;
diff --git a/pkg/compiler/lib/src/ssa/ssa_tracer.dart b/pkg/compiler/lib/src/ssa/ssa_tracer.dart
index ccecc67..0b50f8c 100644
--- a/pkg/compiler/lib/src/ssa/ssa_tracer.dart
+++ b/pkg/compiler/lib/src/ssa/ssa_tracer.dart
@@ -306,7 +306,7 @@
     int offset = HInvoke.ARGUMENTS_OFFSET;
     List arguments = invoke.inputs.sublist(offset);
     return visitGenericInvoke("Invoke", target, arguments) +
-        "(${invoke.selector.mask})";
+        "(${invoke.mask})";
   }
 
   String visitInvokeDynamicMethod(HInvokeDynamicMethod node)
diff --git a/pkg/compiler/lib/src/ssa/types.dart b/pkg/compiler/lib/src/ssa/types.dart
index cc95023..c8a39fa 100644
--- a/pkg/compiler/lib/src/ssa/types.dart
+++ b/pkg/compiler/lib/src/ssa/types.dart
@@ -24,9 +24,11 @@
         compiler);
   }
 
-  static TypeMask inferredTypeForSelector(Selector selector, Compiler compiler) {
+  static TypeMask inferredTypeForSelector(Selector selector,
+                                          TypeMask mask,
+                                          Compiler compiler) {
     return fromInferredType(
-        compiler.typesTask.getGuaranteedTypeOfSelector(selector),
+        compiler.typesTask.getGuaranteedTypeOfSelector(selector, mask),
         compiler);
   }
 
diff --git a/pkg/compiler/lib/src/ssa/types_propagation.dart b/pkg/compiler/lib/src/ssa/types_propagation.dart
index 71abe6c..8556472 100644
--- a/pkg/compiler/lib/src/ssa/types_propagation.dart
+++ b/pkg/compiler/lib/src/ssa/types_propagation.dart
@@ -252,7 +252,8 @@
       return true;
     } else if (instruction.element == null) {
       Iterable<Element> targets =
-          compiler.world.allFunctions.filter(instruction.selector);
+          compiler.world.allFunctions.filter(
+              instruction.selector, instruction.mask);
       if (targets.length == 1) {
         Element target = targets.first;
         ClassElement cls = target.enclosingClass;
@@ -335,7 +336,8 @@
           if (checkReceiver(instruction)) {
             addAllUsersBut(instruction, instruction.inputs[1]);
           }
-          if (!selector.isUnaryOperator && checkArgument(instruction)) {
+          if (!selector.isUnaryOperator &&
+              checkArgument(instruction)) {
             addAllUsersBut(instruction, instruction.inputs[2]);
           }
         }
@@ -344,14 +346,13 @@
 
     HInstruction receiver = instruction.getDartReceiver(compiler);
     TypeMask receiverType = receiver.instructionType;
-    Selector selector =
-        new TypedSelector(receiverType, instruction.selector, classWorld);
-    instruction.selector = selector;
+    instruction.mask = receiverType;
 
     // Try to specialize the receiver after this call.
     if (receiver.dominatedUsers(instruction).length != 1
-        && !selector.isClosureCall) {
-      TypeMask newType = compiler.world.allFunctions.receiverType(selector);
+        && !instruction.selector.isClosureCall) {
+      TypeMask newType = compiler.world.allFunctions.receiverType(
+              instruction.selector, instruction.mask);
       newType = newType.intersection(receiverType, classWorld);
       var next = instruction.next;
       if (next is HTypeKnown && next.checkedInput == receiver) {
diff --git a/pkg/compiler/lib/src/tree_ir/optimization/logical_rewriter.dart b/pkg/compiler/lib/src/tree_ir/optimization/logical_rewriter.dart
index 4bef70a..65ca23a 100644
--- a/pkg/compiler/lib/src/tree_ir/optimization/logical_rewriter.dart
+++ b/pkg/compiler/lib/src/tree_ir/optimization/logical_rewriter.dart
@@ -8,8 +8,6 @@
 import 'optimization.dart' show Pass;
 import '../../constants/values.dart' as values;
 
-// TODO(asgerf): Update this class to use JS semantics for && and ||.
-
 /// Rewrites logical expressions to be more compact in the Tree IR.
 ///
 /// In this class an expression is said to occur in "boolean context" if
@@ -49,16 +47,10 @@
 ///
 ///   x ? true : false  ==>  !!x
 ///
-/// If an operand is known to be a boolean, we can introduce a logical operator:
+/// If the possible falsy values of the condition are known, we can sometimes
+/// introduce a logical operator:
 ///
-///   x ? y : false  ==>  x && y   (if y is known to be a boolean)
-///
-/// The following sequence of rewrites demonstrates the merit of these rules:
-///
-///   x ? (y ? true : false) : false
-///   x ? !!y : false   (double negation introduced by [toBoolean])
-///   x && !!y          (!!y validated by [isBooleanValued])
-///   x && y            (double negation removed by [putInBooleanContext])
+///   !x ? y : false  ==>  !x && y
 ///
 class LogicalRewriter extends RecursiveTransformer
                       implements Pass {
@@ -94,7 +86,7 @@
 
   Statement visitIf(If node) {
     // If one of the branches is empty (i.e. just a fallthrough), then that
-    // branch should preferrably be the 'else' so we won't have to print it.
+    // branch should preferably be the 'else' so we won't have to print it.
     // In other words, we wish to perform this rewrite:
     //   if (E) {} else {S}
     //     ==>
@@ -143,6 +135,31 @@
     return toBoolean(makeCondition(node.operand, false, liftNots: false));
   }
 
+  /// True if the only possible falsy return value of [condition] is [value].
+  ///
+  /// If [value] is `null` or a truthy value, false is returned. This is to make
+  /// pattern matching more convenient.
+  bool matchesFalsyValue(Expression condition, values.ConstantValue value) {
+    if (value == null) return false;
+    // TODO(asgerf): Here we could really use some more type information,
+    //               this is just the best we can do at the moment.
+    return isBooleanValued(condition) && value.isFalse;
+  }
+
+  /// True if the only possible truthy return value of [condition] is [value].
+  ///
+  /// If [value] is `null` or a falsy value, false is returned. This is to make
+  /// pattern matching more convenient.
+  bool matchesTruthyValue(Expression condition, values.ConstantValue value) {
+    if (value == null) return false;
+    // TODO(asgerf): Again, more type information could really beef this up.
+    return isBooleanValued(condition) && value.isTrue;
+  }
+
+  values.ConstantValue getConstant(Expression exp) {
+    return exp is Constant ? exp.value : null;
+  }
+
   Expression visitConditional(Conditional node) {
     // node.condition will be visited after the then and else parts, because its
     // polarity depends on what rewrite we use.
@@ -161,29 +178,32 @@
       return toBoolean(makeCondition(node.condition, false, liftNots: false));
     }
 
-    // x ? y : false ==> x && y  (if y is known to be a boolean)
-    if (isBooleanValued(node.thenExpression) && isFalse(node.elseExpression)) {
+    // x ? y : false ==> x && y  (if x is truthy or false)
+    // x ? y : null  ==> x && y  (if x is truthy or null)
+    // x ? y : 0     ==> x && y  (if x is truthy or zero) (and so on...)
+    if (matchesFalsyValue(node.condition, getConstant(node.elseExpression))) {
       return new LogicalOperator.and(
-          makeCondition(node.condition, true, liftNots:false),
-          putInBooleanContext(node.thenExpression));
+          visitExpression(node.condition),
+          node.thenExpression);
     }
-    // x ? y : true ==> !x || y  (if y is known to be a boolean)
-    if (isBooleanValued(node.thenExpression) && isTrue(node.elseExpression)) {
+    // x ? true : y ==> x || y  (if x is falsy or true)
+    // x ? 1    : y ==> x || y  (if x is falsy or one) (and so on...)
+    if (matchesTruthyValue(node.condition, getConstant(node.thenExpression))) {
       return new LogicalOperator.or(
-          makeCondition(node.condition, false, liftNots: false),
-          putInBooleanContext(node.thenExpression));
+          visitExpression(node.condition),
+          node.elseExpression);
     }
-    // x ? true : y ==> x || y  (if y if known to be boolean)
-    if (isBooleanValued(node.elseExpression) && isTrue(node.thenExpression)) {
+    // x ? y : true ==> !x || y
+    if (isTrue(node.elseExpression)) {
       return new LogicalOperator.or(
-          makeCondition(node.condition, true, liftNots: false),
-          putInBooleanContext(node.elseExpression));
+          toBoolean(makeCondition(node.condition, false, liftNots: false)),
+          node.thenExpression);
     }
-    // x ? false : y ==> !x && y  (if y is known to be a boolean)
-    if (isBooleanValued(node.elseExpression) && isFalse(node.thenExpression)) {
+    // x ? false : y ==> !x && y
+    if (isFalse(node.thenExpression)) {
       return new LogicalOperator.and(
-          makeCondition(node.condition, false, liftNots: false),
-          putInBooleanContext(node.elseExpression));
+          toBoolean(makeCondition(node.condition, false, liftNots: false)),
+          node.elseExpression);
     }
 
     node.condition = makeCondition(node.condition, true);
@@ -200,8 +220,8 @@
   }
 
   Expression visitLogicalOperator(LogicalOperator node) {
-    node.left = makeCondition(node.left, true);
-    node.right = makeCondition(node.right, true);
+    node.left = visitExpression(node.left);
+    node.right = visitExpression(node.right);
     return node;
   }
 
@@ -210,16 +230,52 @@
   /// applied to the result of [visitExpression] conditionals will have been
   /// rewritten anyway.
   bool isBooleanValued(Expression e) {
-    return isTrue(e) || isFalse(e) || e is Not || e is LogicalOperator;
+    return isTrue(e) ||
+           isFalse(e) ||
+           e is Not ||
+           e is LogicalOperator ||
+           e is ApplyBuiltinOperator && operatorReturnsBool(e.operator);
   }
 
-  /// Rewrite an expression that was originally processed in a non-boolean
-  /// context.
-  Expression putInBooleanContext(Expression e) {
-    if (e is Not && e.operand is Not) {
-      return (e.operand as Not).operand;
-    } else {
-      return e;
+  /// True if the given operator always returns `true` or `false`.
+  bool operatorReturnsBool(BuiltinOperator operator) {
+    switch (operator) {
+      case BuiltinOperator.StrictEq:
+      case BuiltinOperator.StrictNeq:
+      case BuiltinOperator.LooseEq:
+      case BuiltinOperator.LooseNeq:
+      case BuiltinOperator.NumLt:
+      case BuiltinOperator.NumLe:
+      case BuiltinOperator.NumGt:
+      case BuiltinOperator.NumGe:
+      case BuiltinOperator.IsNumber:
+      case BuiltinOperator.IsNotNumber:
+      case BuiltinOperator.IsFloor:
+      case BuiltinOperator.IsNumberAndFloor:
+        return true;
+      default:
+        return false;
+    }
+  }
+
+  BuiltinOperator negateBuiltin(BuiltinOperator operator) {
+    switch (operator) {
+      case BuiltinOperator.StrictEq: return BuiltinOperator.StrictNeq;
+      case BuiltinOperator.StrictNeq: return BuiltinOperator.StrictEq;
+      case BuiltinOperator.LooseEq: return BuiltinOperator.LooseNeq;
+      case BuiltinOperator.LooseNeq: return BuiltinOperator.LooseEq;
+      case BuiltinOperator.IsNumber: return BuiltinOperator.IsNotNumber;
+      case BuiltinOperator.IsNotNumber: return BuiltinOperator.IsNumber;
+
+      // Because of NaN, these do not have a negated form.
+      case BuiltinOperator.NumLt:
+      case BuiltinOperator.NumLe:
+      case BuiltinOperator.NumGt:
+      case BuiltinOperator.NumGe:
+        return null;
+
+      default:
+        return null;
     }
   }
 
@@ -235,7 +291,7 @@
   /// context where its result is immediately subject to boolean conversion.
   /// If [polarity] if false, the negated condition will be created instead.
   /// If [liftNots] is true (default) then Not expressions will be lifted toward
-  /// the root the condition so they can be eliminated by the caller.
+  /// the root of the condition so they can be eliminated by the caller.
   Expression makeCondition(Expression e, bool polarity, {bool liftNots:true}) {
     if (e is Not) {
       // !!E ==> E
@@ -257,6 +313,15 @@
       }
       return e;
     }
+    if (e is ApplyBuiltinOperator && polarity == false) {
+      BuiltinOperator negated = negateBuiltin(e.operator);
+      if (negated != null) {
+        e.operator = negated;
+        return visitExpression(e);
+      } else {
+        return new Not(visitExpression(e));
+      }
+    }
     if (e is Conditional) {
       // Handle polarity by: !(x ? y : z) ==> x ? !y : !z
       // Rewrite individual branches now. The condition will be rewritten
diff --git a/pkg/compiler/lib/src/tree_ir/optimization/pull_into_initializers.dart b/pkg/compiler/lib/src/tree_ir/optimization/pull_into_initializers.dart
index a19aeba..a6acceb 100644
--- a/pkg/compiler/lib/src/tree_ir/optimization/pull_into_initializers.dart
+++ b/pkg/compiler/lib/src/tree_ir/optimization/pull_into_initializers.dart
@@ -7,6 +7,15 @@
 import 'optimization.dart' show Pass;
 import '../tree_ir_nodes.dart';
 
+/// Where a variable has been assigned.
+enum AssignArea {
+  /// The variable is only assigned in the initializer block.
+  Initializer,
+
+  // The variable has at least one assignment outside the initializer block.
+  Anywhere,
+}
+
 /// Pulls assignment expressions to the top of the function body so they can be
 /// translated into declaration-site variable initializaters.
 ///
@@ -48,30 +57,50 @@
 /// [PullIntoInitializers] cannot pull `y` into an initializer because
 /// the impure expressions `foo()` and `bar()` would then be swapped.
 ///
-class PullIntoInitializers extends ExpressionVisitor<Expression>
+class PullIntoInitializers extends RecursiveTransformer
                            implements Pass {
   String get passName => 'Pull into initializers';
 
-  Set<Variable> assignedVariables = new Set<Variable>();
+  /// Denotes where each variable is currently assigned.
+  ///
+  /// Variables without assignments are absent from the map.
+  Map<Variable, AssignArea> assignArea = <Variable, AssignArea>{};
 
   /// The fragment between [first] and [last] holds the statements
   /// we pulled into the initializer block.
   ///
-  /// The *initializer block* is a sequence of [ExpressionStatement]s with
+  /// The "initializer block" is a sequence of [ExpressionStatement]s with
   /// [Assign]s that we create in the beginning of the body, with the intent
   /// that code generation will convert them to variable initializers.
   ///
   /// The block is empty when both are `null`.
   Statement first, last;
 
-  /// True if an impure expression has been returned by visitExpression.
+  /// The number of impure expressions separating the current program point
+  /// from the initializer block.
   ///
-  /// Expressions cannot be pulled into an initializer if this might reorder
-  /// impure expressions.
+  /// A pure expression is an expression that cannot throw, diverge, have side
+  /// effects, or depend on mutable state.
   ///
-  /// A visit method may not be called while this flag is set, meaning all
-  /// visitor methods must check the flag between visiting subexpressions.
-  bool seenImpure;
+  /// As a special case, variable uses are also considered pure when their only
+  /// reaching definition is an assignment in the initializer block.
+  int impureCounter = 0;
+
+  /// The number of assignments separating the current program point from the
+  /// initializer block. Note that these are also counted as impure expressions.
+  ///
+  /// Assignments are given special treatment because hoisting an assignment
+  /// may change the reaching definitions of a variable use. The analysis may
+  /// already have considered such a use to be pure, and we must then ensure
+  /// that it remains pure.
+  int assignCounter = 0;
+
+  /// The number of branch points separating the current program point from
+  /// the initializer block.
+  ///
+  /// We do not pull expressions out of branches, not even pure ones, but
+  /// we sometimes want to traverse branches to check if they are pure.
+  int branchCounter = 0;
 
   /// Appends a statement to the initializer block.
   void append(Statement node) {
@@ -83,54 +112,13 @@
     }
   }
 
-  /// Pulls assignment expressions from [node] into the initializer block
-  /// by calling [append].
-  ///
-  /// Returns a transformed expression where the pulled assignments are
-  /// replaced by variable uses.
-  Expression rewriteExpression(Expression node) {
-    seenImpure = false;
-    return visitExpression(node);
-  }
-
   void rewrite(FunctionDefinition node) {
-    Statement body = node.body;
-    assignedVariables.addAll(node.parameters);
-
-    // [body] represents the first statement after the initializer block.
-    // Repeatedly pull assignment statements into the initializer block.
-    while (body is ExpressionStatement) {
-      ExpressionStatement stmt = body;
-      stmt.expression = rewriteExpression(stmt.expression);
-      if (stmt.expression is VariableUse) {
-        // The entire expression was pulled into an initializer.
-        // This can happen when the expression was an assignment that was
-        // pulled into the initializer block and replaced by a variable use.
-        // Discard the statement and try to pull in more initializers from
-        // the next statement.
-        destroyVariableUse(stmt.expression);
-        body = stmt.next;
-      } else {
-        // The whole expression could not be pulled into an initializer, so we
-        // have reached the end of the initializer block.
-        break;
-      }
+    for (Variable param in node.parameters) {
+      assignArea[param] = AssignArea.Initializer;
     }
-
-    // [If] and [Return] statements terminate the initializer block, but the
-    // initial expression they contain may be pulled up into an initializer.
-    // It's ok to pull an assignment across a label so look for the first
-    // non-labeled statement and try to pull its initial subexpression.
-    Statement entryNode = unfoldLabeledStatements(body);
-    if (entryNode is If) {
-      entryNode.condition = rewriteExpression(entryNode.condition);
-    } else if (entryNode is Return) {
-      entryNode.value = rewriteExpression(entryNode.value);
-    }
-
+    Statement body = visitStatement(node.body);
     append(body);
-    assert(first != null); // Because we just appended the body.
-
+    assert(first != null);
     node.body = first;
   }
 
@@ -138,116 +126,192 @@
     --node.variable.readCount;
   }
 
-  Statement unfoldLabeledStatements(Statement node) {
-    while (node is LabeledStatement) {
-      node = (node as LabeledStatement).body;
+  Statement visitExpressionStatement(ExpressionStatement node) {
+    node.expression = visitExpression(node.expression);
+    if (node.expression is VariableUse) {
+      // The entire expression was pulled into an initializer.
+      // This can happen when the expression was an assignment that was
+      // pulled into the initializer block and replaced by a variable use.
+      // Discard the statement and try to pull in more initializers from
+      // the next statement.
+      destroyVariableUse(node.expression);
+      return visitStatement(node.next);
     }
+    node.next = visitStatement(node.next);
+    return node;
+  }
+
+  Statement visitIf(If node) {
+    node.condition = visitExpression(node.condition);
+    // We could traverse the branches and pull out pure expressions, but
+    // some pure expressions might be too slow for this to pay off.
+    // A CPS transform should decide when things get hoisted out of branches.
+    return node;
+  }
+
+  Statement visitLabeledStatement(LabeledStatement node) {
+    node.body = visitStatement(node.body);
+    // The 'next' statement might not always get reached, so do not try to
+    // pull expressions up from there.
+    return node;
+  }
+
+  Statement visitWhileTrue(WhileTrue node) {
+    return node;
+  }
+
+  Statement visitWhileCondition(WhileCondition node) {
+    return node;
+  }
+
+  Statement visitTry(Try node) {
     return node;
   }
 
   Expression visitAssign(Assign node) {
-    assert(!seenImpure);
+    bool inImpureContext = impureCounter > 0;
+    bool inBranch = branchCounter > 0;
+
+    // Remember the number of impure expression seen yet, so we can tell if
+    // there are any impure expressions on the right-hand side.
+    int impureBefore = impureCounter;
+    int assignmentsBefore = assignCounter;
     node.value = visitExpression(node.value);
-    if (!assignedVariables.add(node.variable)) {
-      // This is not the first assignment to the variable, so it cannot be
-      // pulled into an initializer.
-      // We have to leave the assignment here, and assignments are impure.
-      seenImpure = true;
+    bool rightHandSideIsImpure = (impureCounter > impureBefore);
+    bool rightHandSideHasAssign = (assignCounter > assignmentsBefore);
+
+    bool alreadyAssigned = assignArea.containsKey(node.variable);
+
+    // An impure right-hand side cannot be pulled out of impure context.
+    // Expressions should not be pulled out of branches.
+    // If this is not the first assignment, it cannot be hoisted.
+    // If the right-hand side contains an unhoistable assignment, this
+    // assignment cannot be hoisted either.
+    if (inImpureContext && rightHandSideIsImpure ||
+        inBranch ||
+        alreadyAssigned ||
+        rightHandSideHasAssign) {
+      assignArea[node.variable] = AssignArea.Anywhere;
+      ++impureCounter;
+      ++assignCounter;
       return node;
-    } else {
-      // Pull the assignment into an initializer.
-      // We will leave behind a variable use, which is pure, so we can
-      // disregard any impure expressions seen in the right-hand side.
-      seenImpure = false;
-      append(new ExpressionStatement(node, null));
-      return new VariableUse(node.variable);
     }
+
+    // Pull the assignment into the initializer. Any side-effects in the
+    // right-hand side will move into the initializer block, so reset the
+    // impure counter.
+    assignArea[node.variable] = AssignArea.Initializer;
+    impureCounter = impureBefore;
+    append(new ExpressionStatement(node, null));
+    return new VariableUse(node.variable);
   }
 
-  void rewriteList(List<Expression> list) {
-    for (int i = 0; i < list.length; i++) {
-      list[i] = visitExpression(list[i]);
-      if (seenImpure) return;
+  Expression visitVariableUse(VariableUse node) {
+    if (assignArea[node.variable] == AssignArea.Anywhere) {
+      // There is a reaching definition outside the initializer block.
+      ++impureCounter;
     }
-  }
-
-  Expression visitInvokeStatic(InvokeStatic node) {
-    rewriteList(node.arguments);
-    seenImpure = true;
     return node;
   }
 
+  void rewriteList(List<Expression> nodes) {
+    for (int i = 0; i < nodes.length; ++i) {
+      nodes[i] = visitExpression(nodes[i]);
+    }
+  }
+
   Expression visitInvokeMethod(InvokeMethod node) {
     node.receiver = visitExpression(node.receiver);
-    if (seenImpure) return node;
+    if (!node.receiverIsNotNull) {
+      // If the receiver is null, the method lookup throws.
+      ++impureCounter;
+    }
     rewriteList(node.arguments);
-    seenImpure = true;
+    ++impureCounter;
+    return node;
+  }
+
+  Expression visitInvokeStatic(InvokeStatic node) {
+    super.visitInvokeStatic(node);
+    ++impureCounter;
     return node;
   }
 
   Expression visitInvokeMethodDirectly(InvokeMethodDirectly node) {
-    node.receiver = visitExpression(node.receiver);
-    if (seenImpure) return node;
-    rewriteList(node.arguments);
-    seenImpure = true;
+    super.visitInvokeMethodDirectly(node);
+    ++impureCounter;
     return node;
   }
 
   Expression visitInvokeConstructor(InvokeConstructor node) {
-    rewriteList(node.arguments);
-    seenImpure = true;
-    return node;
-  }
-
-  Expression visitConcatenateStrings(ConcatenateStrings node) {
-    rewriteList(node.arguments);
-    seenImpure = true;
-    return node;
-  }
-
-  Expression visitTypeExpression(TypeExpression node) {
-    rewriteList(node.arguments);
+    super.visitInvokeConstructor(node);
+    ++impureCounter;
     return node;
   }
 
   Expression visitConditional(Conditional node) {
     node.condition = visitExpression(node.condition);
-    if (seenImpure) return node;
+    // Visit the branches to detect impure subexpressions, but do not pull
+    // expressions out of the branch.
+    ++branchCounter;
     node.thenExpression = visitExpression(node.thenExpression);
-    if (seenImpure) return node;
     node.elseExpression = visitExpression(node.elseExpression);
+    --branchCounter;
     return node;
   }
 
   Expression visitLogicalOperator(LogicalOperator node) {
     node.left = visitExpression(node.left);
-    if (seenImpure) return node;
+    ++branchCounter;
     node.right = visitExpression(node.right);
+    --branchCounter;
     return node;
   }
 
   Expression visitLiteralList(LiteralList node) {
-    rewriteList(node.values);
-    if (node.type != null) seenImpure = true; // Type casts can throw.
+    super.visitLiteralList(node);
+    if (node.type != null) {
+      ++impureCounter; // Type casts can throw.
+    }
     return node;
   }
 
   Expression visitLiteralMap(LiteralMap node) {
-    for (LiteralMapEntry entry in node.entries) {
-      entry.key = visitExpression(entry.key);
-      if (seenImpure) return node;
-      entry.value = visitExpression(entry.value);
-      if (seenImpure) return node;
+    super.visitLiteralMap(node);
+    if (node.type != null) {
+      ++impureCounter; // Type casts can throw.
     }
-    if (node.type != null) seenImpure = true; // Type casts can throw.
     return node;
   }
 
   Expression visitTypeOperator(TypeOperator node) {
-    node.value = visitExpression(node.value);
-    if (seenImpure) return node;
-    rewriteList(node.typeArguments);
-    if (!node.isTypeTest) seenImpure = true; // Type cast can throw.
+    super.visitTypeOperator(node);
+    if (!node.isTypeTest) {
+      ++impureCounter; // Type casts can throw.
+    }
+    return node;
+  }
+
+  Expression visitGetField(GetField node) {
+    super.visitGetField(node);
+    ++impureCounter;
+    return node;
+  }
+
+  Expression visitSetField(SetField node) {
+    super.visitSetField(node);
+    ++impureCounter;
+    return node;
+  }
+
+  Expression visitGetStatic(GetStatic node) {
+    ++impureCounter;
+    return node;
+  }
+
+  Expression visitSetStatic(SetStatic node) {
+    super.visitSetStatic(node);
+    ++impureCounter;
     return node;
   }
 
@@ -260,69 +324,17 @@
     return node;
   }
 
-  Expression visitGetField(GetField node) {
-    node.object = visitExpression(node.object);
-    seenImpure = true;
-    return node;
-  }
-
-  Expression visitSetField(SetField node) {
-    node.object = visitExpression(node.object);
-    if (seenImpure) return node;
-    node.value = visitExpression(node.value);
-    seenImpure = true;
-    return node;
-  }
-
-  Expression visitGetStatic(GetStatic node) {
-    seenImpure = true;
-    return node;
-  }
-
-  Expression visitSetStatic(SetStatic node) {
-    node.value = visitExpression(node.value);
-    seenImpure = true;
-    return node;
-  }
-
-  Expression visitCreateBox(CreateBox node) {
-    return node;
-  }
-
-  Expression visitCreateInstance(CreateInstance node) {
+  Expression visitApplyBuiltinOperator(ApplyBuiltinOperator node) {
     rewriteList(node.arguments);
     return node;
   }
 
-  Expression visitReifyRuntimeType(ReifyRuntimeType node) {
-    node.value = visitExpression(node.value);
-    return node;
-  }
-
-  Expression visitReadTypeVariable(ReadTypeVariable node) {
-    node.target = visitExpression(node.target);
-    return node;
-  }
-
-  Expression visitConstant(Constant node) {
-    return node;
-  }
-
-  Expression visitThis(This node) {
-    return node;
-  }
-
-  Expression visitNot(Not node) {
-    node.operand = visitExpression(node.operand);
-    return node;
-  }
-
-  Expression visitVariableUse(VariableUse node) {
-    return node;
-  }
-
-  Expression visitCreateInvocationMirror(CreateInvocationMirror node) {
+  @override
+  Expression visitForeignExpression(ForeignExpression node) {
     rewriteList(node.arguments);
+    if (node.nativeBehavior.sideEffects.hasSideEffects()) {
+      ++impureCounter;
+    }
     return node;
   }
 }
diff --git a/pkg/compiler/lib/src/tree_ir/optimization/statement_rewriter.dart b/pkg/compiler/lib/src/tree_ir/optimization/statement_rewriter.dart
index 691e206..68b8459 100644
--- a/pkg/compiler/lib/src/tree_ir/optimization/statement_rewriter.dart
+++ b/pkg/compiler/lib/src/tree_ir/optimization/statement_rewriter.dart
@@ -116,9 +116,6 @@
     node.body = visitStatement(node.body);
   }
 
-  /// True if targeting Dart.
-  final bool isDartMode;
-
   /// The most recently evaluated impure expressions, with the most recent
   /// expression being last.
   ///
@@ -127,6 +124,9 @@
   /// we can propagate to a variable use if they are known to return the value
   /// of that variable.
   ///
+  /// Assignments with constant right-hand sides (see [isEffectivelyConstant])
+  /// are not considered impure and are put in [constantEnvironment] instead.
+  ///
   /// Except for [Conditional]s, expressions in the environment have
   /// not been processed, and all their subexpressions must therefore be
   /// variables uses.
@@ -146,16 +146,12 @@
   Map<Variable, int> unseenUses = <Variable, int>{};
 
   /// Rewriter for methods.
-  StatementRewriter({this.isDartMode})
-      : constantEnvironment = <Variable, Expression>{} {
-    assert(isDartMode != null);
-  }
+  StatementRewriter() : constantEnvironment = <Variable, Expression>{};
 
   /// Rewriter for nested functions.
   StatementRewriter.nested(StatementRewriter parent)
       : constantEnvironment = parent.constantEnvironment,
-        unseenUses = parent.unseenUses,
-        isDartMode = parent.isDartMode;
+        unseenUses = parent.unseenUses;
 
   /// A set of labels that can be safely inlined at their use.
   ///
@@ -188,11 +184,6 @@
   /// If the given expression always returns the value of one of its
   /// subexpressions, returns that subexpression, otherwise `null`.
   Expression getValueSubexpression(Expression e) {
-    if (isDartMode &&
-        e is InvokeMethod &&
-        (e.selector.isSetter || e.selector.isIndexSet)) {
-      return e.arguments.last;
-    }
     if (e is SetField) return e.value;
     return null;
   }
@@ -264,6 +255,29 @@
     return node;
   }
 
+  /// True if [exp] contains a use of a variable that was assigned to by the
+  /// most recently evaluated impure expression (constant assignments are not
+  /// considered impure).
+  ///
+  /// This implies that the assignment can be propagated into this use unless
+  /// the use is moved further away.
+  ///
+  /// In this case, we will refrain from moving [exp] across other impure
+  /// expressions, even when this is safe, because doing so would immediately
+  /// prevent the previous expression from propagating, canceling out the
+  /// benefit we might otherwise gain from propagating [exp].
+  ///
+  /// [exp] must be an unprocessed expression, i.e. either a [Conditional] or
+  /// an expression whose subexpressions are all variable uses.
+  bool usesRecentlyAssignedVariable(Expression exp) {
+    if (environment.isEmpty) return false;
+    Variable variable = getLeftHand(environment.last);
+    if (variable == null) return false;
+    IsVariableUsedVisitor visitor = new IsVariableUsedVisitor(variable);
+    visitor.visitExpression(exp);
+    return visitor.wasFound;
+  }
+
   /// Returns true if [exp] has no side effects and has a constant value within
   /// any given activation of the enclosing method.
   bool isEffectivelyConstant(Expression exp) {
@@ -274,6 +288,8 @@
            exp is This ||
            exp is CreateInvocationMirror ||
            exp is InvokeStatic && exp.isEffectivelyConstant ||
+           exp is Interceptor ||
+           exp is ApplyBuiltinOperator ||
            exp is VariableUse && constantEnvironment.containsKey(exp.variable);
   }
 
@@ -285,7 +301,8 @@
   }
 
   Statement visitExpressionStatement(ExpressionStatement stmt) {
-    if (isEffectivelyConstantAssignment(stmt.expression)) {
+    if (isEffectivelyConstantAssignment(stmt.expression) &&
+        !usesRecentlyAssignedVariable(stmt.expression)) {
       Assign assign = stmt.expression;
       // Handle constant assignments specially.
       // They are always safe to propagate (though we should avoid duplication).
@@ -372,11 +389,6 @@
     return node;
   }
 
-  Expression visitConcatenateStrings(ConcatenateStrings node) {
-    _rewriteList(node.arguments);
-    return node;
-  }
-
   Expression visitConditional(Conditional node) {
     // Conditional expressions do not exist in the input, but they are
     // introduced by if-to-conditional conversion.
@@ -435,6 +447,10 @@
     return node;
   }
 
+  Statement visitUnreachable(Unreachable node) {
+    return node;
+  }
+
   Statement visitBreak(Break node) {
     // Redirect through chain of breaks.
     // Note that useCount was accounted for at visitLabeledStatement.
@@ -615,6 +631,85 @@
     return node;
   }
 
+  Expression visitInterceptor(Interceptor node) {
+    node.input = visitExpression(node.input);
+    return node;
+  }
+
+  /// True if [operator] is a binary operator that always has the same value
+  /// if its arguments are swapped.
+  bool isSymmetricOperator(BuiltinOperator operator) {
+    switch (operator) {
+      case BuiltinOperator.StrictEq:
+      case BuiltinOperator.StrictNeq:
+      case BuiltinOperator.LooseEq:
+      case BuiltinOperator.LooseNeq:
+      case BuiltinOperator.NumAnd:
+      case BuiltinOperator.NumOr:
+      case BuiltinOperator.NumXor:
+      case BuiltinOperator.NumAdd:
+      case BuiltinOperator.NumMultiply:
+        return true;
+      default:
+        return false;
+    }
+  }
+
+  /// If [operator] is a commutable binary operator, returns the commuted
+  /// operator, possibly the operator itself, otherwise returns `null`.
+  BuiltinOperator commuteBinaryOperator(BuiltinOperator operator) {
+    if (isSymmetricOperator(operator)) {
+      // Symmetric operators are their own commutes.
+      return operator;
+    }
+    switch(operator) {
+      case BuiltinOperator.NumLt: return BuiltinOperator.NumGt;
+      case BuiltinOperator.NumLe: return BuiltinOperator.NumGe;
+      case BuiltinOperator.NumGt: return BuiltinOperator.NumLt;
+      case BuiltinOperator.NumGe: return BuiltinOperator.NumLe;
+      default: return null;
+    }
+  }
+
+  /// Built-in binary operators are commuted when it is safe and can enable an
+  /// assignment propagation. For example:
+  ///
+  ///    var x = foo();
+  ///    var y = bar();
+  ///    var z = y < x;
+  ///
+  ///      ==>
+  ///
+  ///    var z = foo() > bar();
+  ///
+  /// foo() must be evaluated before bar(), so the propagation is only possible
+  /// by commuting the operator.
+  Expression visitApplyBuiltinOperator(ApplyBuiltinOperator node) {
+    if (environment.isEmpty || getLeftHand(environment.last) == null) {
+      // If there is no recent assignment that might propagate, so there is no
+      // opportunity for optimization here.
+      _rewriteList(node.arguments);
+      return node;
+    }
+    Variable propagatableVariable = getLeftHand(environment.last);
+    BuiltinOperator commuted = commuteBinaryOperator(node.operator);
+    if (commuted != null) {
+      assert(node.arguments.length == 2); // Only binary operators can commute.
+      VariableUse arg1 = node.arguments[0];
+      VariableUse arg2 = node.arguments[1];
+      if (propagatableVariable == arg1.variable &&
+          propagatableVariable != arg2.variable &&
+          !constantEnvironment.containsKey(arg2.variable)) {
+        // An assignment can be propagated if we commute the operator.
+        node.operator = commuted;
+        node.arguments[0] = arg2;
+        node.arguments[1] = arg1;
+      }
+    }
+    _rewriteList(node.arguments);
+    return node;
+  }
+
   /// If [s] and [t] are similar statements we extract their subexpressions
   /// and returns a new statement of the same type using expressions combined
   /// with the [combine] callback. For example:
@@ -858,6 +953,18 @@
   Statement getBranch(If node, bool polarity) {
     return polarity ? node.thenStatement : node.elseStatement;
   }
+
+  @override
+  Expression visitForeignExpression(ForeignExpression node) {
+    _rewriteList(node.arguments);
+    return node;
+  }
+
+  @override
+  Statement visitForeignStatement(ForeignStatement node) {
+    _rewriteList(node.arguments);
+    return node;
+  }
 }
 
 /// Result of combining two expressions, with the potential for reverting the
@@ -919,3 +1026,23 @@
 
   void uncombine() {}
 }
+
+/// Looks for uses of a specific variable.
+///
+/// Note that this visitor is only applied to expressions where all
+/// sub-expressions are known to be variable uses, so there is no risk of
+/// explosive reprocessing.
+class IsVariableUsedVisitor extends RecursiveVisitor {
+  Variable variable;
+  bool wasFound = false;
+
+  IsVariableUsedVisitor(this.variable);
+
+  visitVariableUse(VariableUse node) {
+    if (node.variable == variable) {
+      wasFound = true;
+    }
+  }
+
+  visitInnerFunction(FunctionDefinition node) {}
+}
diff --git a/pkg/compiler/lib/src/tree_ir/optimization/variable_merger.dart b/pkg/compiler/lib/src/tree_ir/optimization/variable_merger.dart
index 141e646..79f018b 100644
--- a/pkg/compiler/lib/src/tree_ir/optimization/variable_merger.dart
+++ b/pkg/compiler/lib/src/tree_ir/optimization/variable_merger.dart
@@ -133,6 +133,14 @@
     _currentBlock = newBlock(catchBlock: catchBlock)..predecessors.add(block);
   }
 
+  /// Starts a new block with the given blocks as predecessors.
+  void joinFrom(Block block1, Block block2) {
+    assert(block1.catchBlock == block2.catchBlock);
+    _currentBlock = newBlock(catchBlock: block1.catchBlock);
+    _currentBlock.predecessors.add(block1);
+    _currentBlock.predecessors.add(block2);
+  }
+
   /// Called when reading from [variable].
   ///
   /// Appends a read operation to the current basic block.
@@ -172,8 +180,10 @@
     Block afterCondition = _currentBlock;
     branchFrom(afterCondition);
     visitStatement(node.thenStatement);
+    Block afterThen = _currentBlock;
     branchFrom(afterCondition);
     visitStatement(node.elseStatement);
+    joinFrom(_currentBlock, afterThen);
   }
 
   visitLabeledStatement(LabeledStatement node) {
@@ -211,14 +221,20 @@
   }
 
   visitTry(Try node) {
-    Block catchBlock = newBlock();
+    Block outerCatchBlock = _currentBlock.catchBlock;
+    Block catchBlock = newBlock(catchBlock: outerCatchBlock);
     branchFrom(_currentBlock, catchBlock: catchBlock);
     visitStatement(node.tryBody);
+    Block afterTry = _currentBlock;
     _currentBlock = catchBlock;
     // Catch parameters cannot be hoisted to the top of the function, so to
     // avoid complications with scoping, we do not attempt to merge them.
     node.catchParameters.forEach(ignoreVariable);
     visitStatement(node.catchBody);
+    Block afterCatch = _currentBlock;
+    _currentBlock = newBlock(catchBlock: outerCatchBlock);
+    _currentBlock.predecessors.add(afterCatch);
+    _currentBlock.predecessors.add(afterTry);
   }
 
   visitConditional(Conditional node) {
@@ -226,15 +242,18 @@
     Block afterCondition = _currentBlock;
     branchFrom(afterCondition);
     visitExpression(node.thenExpression);
+    Block afterThen = _currentBlock;
     branchFrom(afterCondition);
     visitExpression(node.elseExpression);
+    joinFrom(_currentBlock, afterThen);
   }
 
   visitLogicalOperator(LogicalOperator node) {
     visitExpression(node.left);
-    Block afterCondition = _currentBlock;
-    branchFrom(afterCondition);
+    Block afterLeft = _currentBlock;
+    branchFrom(afterLeft);
     visitExpression(node.right);
+    joinFrom(_currentBlock, afterLeft);
   }
 }
 
@@ -324,7 +343,7 @@
 /// For testing purposes, this flag can be passed to merge variables that
 /// originated from different source variables.
 ///
-/// Correctness should not depend on the fact that we only merge variable
+/// Correctness should not depend on the fact that we only merge variables
 /// originating from the same source variable. Setting this flag makes a bug
 /// more likely to provoke a test case failure.
 const bool NO_PRESERVE_VARS = const bool.fromEnvironment('NO_PRESERVE_VARS');
@@ -426,7 +445,7 @@
       continue;
     }
 
-    // Optimization: If there are no inteference edges for this variable,
+    // Optimization: If there are no interference edges for this variable,
     // assign it the first color without copying the register list.
     Set<Variable> interferenceSet = interference[v1];
     if (interferenceSet.isEmpty) {
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 ec566d2..0d663c5 100644
--- a/pkg/compiler/lib/src/tree_ir/tree_ir_builder.dart
+++ b/pkg/compiler/lib/src/tree_ir/tree_ir_builder.dart
@@ -5,7 +5,6 @@
 library tree_ir_builder;
 
 import '../dart2jslib.dart' as dart2js;
-import '../dart_types.dart';
 import '../elements/elements.dart';
 import '../cps_ir/cps_ir_nodes.dart' as cps_ir;
 import '../util/util.dart' show CURRENT_ELEMENT_SPANNABLE;
@@ -268,15 +267,37 @@
     internalError(CURRENT_ELEMENT_SPANNABLE, 'Unexpected IR node: $node');
   }
 
-  // JS-specific nodes are handled by a subclass.
-  visitSetField(cps_ir.SetField node) => unexpectedNode(node);
-  visitIdentical(cps_ir.Identical node) => unexpectedNode(node);
-  visitInterceptor(cps_ir.Interceptor node) => unexpectedNode(node);
-  visitCreateInstance(cps_ir.CreateInstance node) => unexpectedNode(node);
-  visitGetField(cps_ir.GetField node) => unexpectedNode(node);
-  visitCreateBox(cps_ir.CreateBox node) => unexpectedNode(node);
+  Statement visitSetField(cps_ir.SetField node) {
+    return new ExpressionStatement(
+        new SetField(getVariableUse(node.object),
+                     node.field,
+                     getVariableUse(node.value)),
+        visit(node.body));
+  }
+
+  Expression visitInterceptor(cps_ir.Interceptor node) {
+    return new Interceptor(getVariableUse(node.input), node.interceptedClasses);
+  }
+
+  Expression visitCreateInstance(cps_ir.CreateInstance node) {
+    return new CreateInstance(
+        node.classElement,
+        translateArguments(node.arguments),
+        translateArguments(node.typeInformation));
+  }
+
+  Expression visitGetField(cps_ir.GetField node) {
+    return new GetField(getVariableUse(node.object), node.field);
+  }
+
+  Expression visitCreateBox(cps_ir.CreateBox node) {
+    return new CreateBox();
+  }
+
   visitCreateInvocationMirror(cps_ir.CreateInvocationMirror node) {
-    return unexpectedNode(node);
+    return new CreateInvocationMirror(
+        node.selector,
+        translateArguments(node.arguments));
   }
 
   // Executable definitions are not visited directly.  They have 'build'
@@ -352,6 +373,7 @@
   Statement visitInvokeMethod(cps_ir.InvokeMethod node) {
     InvokeMethod invoke = new InvokeMethod(getVariableUse(node.receiver),
                                            node.selector,
+                                           node.mask,
                                            translateArguments(node.arguments));
     invoke.receiverIsNotNull = node.receiverIsNotNull;
     return continueWithExpression(node.continuation, invoke);
@@ -365,12 +387,6 @@
     return continueWithExpression(node.continuation, invoke);
   }
 
-  Statement visitConcatenateStrings(cps_ir.ConcatenateStrings node) {
-    List<Expression> arguments = translateArguments(node.arguments);
-    Expression concat = new ConcatenateStrings(arguments);
-    return continueWithExpression(node.continuation, concat);
-  }
-
   Statement visitThrow(cps_ir.Throw node) {
     Expression value = getVariableUse(node.value);
     return new Throw(value);
@@ -380,8 +396,12 @@
     return new Rethrow();
   }
 
+  Statement visitUnreachable(cps_ir.Unreachable node) {
+    return new Unreachable();
+  }
+
   Expression visitNonTailThrow(cps_ir.NonTailThrow node) {
-    unexpectedNode(node);
+    return unexpectedNode(node);
   }
 
   Statement continueWithExpression(cps_ir.Reference continuation,
@@ -415,13 +435,18 @@
     return Assign.makeStatement(variable, value, visit(node.body));
   }
 
-  Statement visitTypeOperator(cps_ir.TypeOperator node) {
+  Statement visitTypeCast(cps_ir.TypeCast node) {
     Expression value = getVariableUse(node.value);
     List<Expression> typeArgs = translateArguments(node.typeArguments);
-    Expression concat =
-        new TypeOperator(value, node.type, typeArgs,
-                         isTypeTest: node.isTypeTest);
-    return continueWithExpression(node.continuation, concat);
+    Expression expression =
+        new TypeOperator(value, node.type, typeArgs, isTypeTest: false);
+    return continueWithExpression(node.continuation, expression);
+  }
+
+  Expression visitTypeTest(cps_ir.TypeTest node) {
+    Expression value = getVariableUse(node.value);
+    List<Expression> typeArgs = translateArguments(node.typeArguments);
+    return new TypeOperator(value, node.type, typeArgs, isTypeTest: true);
   }
 
   Statement visitInvokeConstructor(cps_ir.InvokeConstructor node) {
@@ -491,7 +516,7 @@
   }
 
   Expression visitConstant(cps_ir.Constant node) {
-    return new Constant(node.expression, node.value);
+    return new Constant(node.value);
   }
 
   Expression visitLiteralList(cps_ir.LiteralList node) {
@@ -517,8 +542,6 @@
 
   Expression visitCreateFunction(cps_ir.CreateFunction node) {
     FunctionDefinition def = makeSubFunction(node.definition);
-    FunctionType type = node.definition.element.type;
-    bool hasReturnType = !type.returnType.treatAsDynamic;
     return new FunctionExpression(def);
   }
 
@@ -577,5 +600,33 @@
         node.sourceInformation);
     return new ExpressionStatement(setStatic, visit(node.body));
   }
+
+  Expression visitApplyBuiltinOperator(cps_ir.ApplyBuiltinOperator node) {
+    if (node.operator == BuiltinOperator.IsFalsy) {
+      return new Not(getVariableUse(node.arguments.single));
+    }
+    return new ApplyBuiltinOperator(node.operator,
+                                    translateArguments(node.arguments));
+  }
+
+  Statement visitForeignCode(cps_ir.ForeignCode node) {
+    if (node.codeTemplate.isExpression) {
+      Expression foreignCode = new ForeignExpression(
+          node.codeTemplate,
+          node.type,
+          node.arguments.map(getVariableUse).toList(growable: false),
+          node.nativeBehavior,
+          node.dependency);
+      return continueWithExpression(node.continuation, foreignCode);
+    } else {
+      assert(node.continuation == null);
+      return new ForeignStatement(
+          node.codeTemplate,
+          node.type,
+          node.arguments.map(getVariableUse).toList(growable: false),
+          node.nativeBehavior,
+          node.dependency);
+    }
+  }
 }
 
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 b8d554f..3c937f1 100644
--- a/pkg/compiler/lib/src/tree_ir/tree_ir_nodes.dart
+++ b/pkg/compiler/lib/src/tree_ir/tree_ir_nodes.dart
@@ -9,8 +9,19 @@
 import '../dart_types.dart' show DartType, InterfaceType, TypeVariableType;
 import '../elements/elements.dart';
 import '../io/source_information.dart' show SourceInformation;
+import '../types/types.dart' show TypeMask;
 import '../universe/universe.dart' show Selector;
 
+import '../cps_ir/builtin_operator.dart';
+export '../cps_ir/builtin_operator.dart';
+
+// These imports are only used for the JavaScript specific nodes.  If we want to
+// support more than one native backend, we should probably create better
+// abstractions for native code and its type and effect system.
+import '../js/js.dart' as js show Template;
+import '../native/native.dart' as native show NativeBehavior;
+import '../types/types.dart' as types show TypeMask;
+
 // The Tree language is the target of translation out of the CPS-based IR.
 //
 // The translation from CPS to Dart consists of several stages.  Among the
@@ -78,8 +89,7 @@
 /**
  * A local variable in the tree IR.
  *
- * All tree IR variables are mutable, and may in Dart-mode be referenced inside
- * nested functions.
+ * All tree IR variables are mutable.
  *
  * To use a variable as an expression, reference it from a [VariableUse], with
  * one [VariableUse] per expression.
@@ -158,7 +168,6 @@
  */
 abstract class Invoke {
   List<Expression> get arguments;
-  Selector get selector;
 }
 
 /**
@@ -198,12 +207,13 @@
 class InvokeMethod extends Expression implements Invoke {
   Expression receiver;
   final Selector selector;
+  final TypeMask mask;
   final List<Expression> arguments;
 
   /// If true, it is known that the receiver cannot be `null`.
   bool receiverIsNotNull = false;
 
-  InvokeMethod(this.receiver, this.selector, this.arguments) {
+  InvokeMethod(this.receiver, this.selector, this.mask, this.arguments) {
     assert(receiver != null);
   }
 
@@ -258,31 +268,16 @@
   }
 }
 
-/// Calls [toString] on each argument and concatenates the results.
-class ConcatenateStrings extends Expression {
-  final List<Expression> arguments;
-
-  ConcatenateStrings(this.arguments);
-
-  accept(ExpressionVisitor visitor) => visitor.visitConcatenateStrings(this);
-  accept1(ExpressionVisitor1 visitor, arg) {
-    return visitor.visitConcatenateStrings(this, arg);
-  }
-}
-
 /**
  * A constant.
  */
 class Constant extends Expression {
-  final ConstantExpression expression;
   final values.ConstantValue value;
 
-  Constant(this.expression, this.value);
+  Constant(this.value);
 
   Constant.bool(values.BoolConstantValue constantValue)
-      : expression = new BoolConstantExpression(
-          constantValue.primitiveValue),
-        value = constantValue;
+      : value = constantValue;
 
   accept(ExpressionVisitor visitor) => visitor.visitConstant(this);
   accept1(ExpressionVisitor1 visitor, arg) => visitor.visitConstant(this, arg);
@@ -324,6 +319,10 @@
   }
 }
 
+/// Type test or type cast.
+///
+/// Note that if this is a type test, then [type] cannot be `Object`, `dynamic`,
+/// or the `Null` type. These cases are compiled to other node types.
 class TypeOperator extends Expression {
   Expression value;
   final DartType type;
@@ -341,6 +340,26 @@
   String get operator => isTypeTest ? 'is' : 'as';
 }
 
+/**
+ * Apply a built-in operator.
+ *
+ * It must be known that the arguments have the proper types.
+ * Null is not a valid argument to any of the built-in operators.
+ */
+class ApplyBuiltinOperator extends Expression {
+  BuiltinOperator operator;
+  List<Expression> arguments;
+
+  ApplyBuiltinOperator(this.operator, this.arguments);
+
+  accept(ExpressionVisitor visitor) {
+    return visitor.visitApplyBuiltinOperator(this);
+  }
+  accept1(ExpressionVisitor1 visitor, arg) {
+    return visitor.visitApplyBuiltinOperator(this, arg);
+  }
+}
+
 /// A conditional expression.
 class Conditional extends Expression {
   Expression condition;
@@ -375,6 +394,8 @@
 }
 
 /// Logical negation.
+// TODO(asgerf): Replace this class with the IsFalsy builtin operator?
+//               Right now the tree builder compiles IsFalsy to Not.
 class Not extends Expression {
   Expression operand;
 
@@ -618,6 +639,17 @@
   }
 }
 
+/// A statement that is known to be unreachable.
+class Unreachable extends Statement {
+  Statement get next => null;
+  void set next(Statement value) => throw 'UNREACHABLE';
+
+  accept(StatementVisitor visitor) => visitor.visitUnreachable(this);
+  accept1(StatementVisitor1 visitor, arg) {
+    return visitor.visitUnreachable(this, arg);
+  }
+}
+
 class FunctionDefinition extends Node {
   final ExecutableElement element;
   final List<Variable> parameters;
@@ -737,6 +769,70 @@
   }
 }
 
+class Interceptor extends Expression {
+  Expression input;
+  Set<ClassElement> interceptedClasses;
+
+  Interceptor(this.input, this.interceptedClasses);
+
+  accept(ExpressionVisitor visitor) {
+    return visitor.visitInterceptor(this);
+  }
+
+  accept1(ExpressionVisitor1 visitor, arg) {
+    return visitor.visitInterceptor(this, arg);
+  }
+}
+
+class ForeignCode extends Node {
+  final js.Template codeTemplate;
+  final types.TypeMask type;
+  final List<Expression> arguments;
+  final native.NativeBehavior nativeBehavior;
+  final Element dependency;
+
+  ForeignCode(this.codeTemplate, this.type, this.arguments, this.nativeBehavior,
+      this.dependency);
+}
+
+class ForeignExpression extends ForeignCode implements Expression {
+  ForeignExpression(js.Template codeTemplate, types.TypeMask type,
+      List<Expression> arguments, native.NativeBehavior nativeBehavior,
+      Element dependency)
+      : super(codeTemplate, type, arguments, nativeBehavior,
+          dependency);
+
+  accept(ExpressionVisitor visitor) {
+    return visitor.visitForeignExpression(this);
+  }
+
+  accept1(ExpressionVisitor1 visitor, arg) {
+    return visitor.visitForeignExpression(this, arg);
+  }
+}
+
+class ForeignStatement extends ForeignCode implements Statement {
+  ForeignStatement(js.Template codeTemplate, types.TypeMask type,
+      List<Expression> arguments, native.NativeBehavior nativeBehavior,
+      Element dependency)
+      : super(codeTemplate, type, arguments, nativeBehavior,
+          dependency);
+
+  accept(StatementVisitor visitor) {
+    return visitor.visitForeignStatement(this);
+  }
+
+  accept1(StatementVisitor1 visitor, arg) {
+    return visitor.visitForeignStatement(this, arg);
+  }
+
+  @override
+  Statement get next => null;
+
+  @override
+  void set next(Statement s) => throw 'UNREACHABLE';
+}
+
 /// Denotes the internal representation of [dartType], where all type variables
 /// are replaced by the values in [arguments].
 /// (See documentation on the TypeExpression CPS node for more details.)
@@ -763,7 +859,6 @@
   E visitInvokeMethod(InvokeMethod node);
   E visitInvokeMethodDirectly(InvokeMethodDirectly node);
   E visitInvokeConstructor(InvokeConstructor node);
-  E visitConcatenateStrings(ConcatenateStrings node);
   E visitConstant(Constant node);
   E visitThis(This node);
   E visitConditional(Conditional node);
@@ -783,6 +878,9 @@
   E visitReadTypeVariable(ReadTypeVariable node);
   E visitTypeExpression(TypeExpression node);
   E visitCreateInvocationMirror(CreateInvocationMirror node);
+  E visitInterceptor(Interceptor node);
+  E visitApplyBuiltinOperator(ApplyBuiltinOperator node);
+  E visitForeignExpression(ForeignExpression node);
 }
 
 abstract class ExpressionVisitor1<E, A> {
@@ -793,7 +891,6 @@
   E visitInvokeMethod(InvokeMethod node, A arg);
   E visitInvokeMethodDirectly(InvokeMethodDirectly node, A arg);
   E visitInvokeConstructor(InvokeConstructor node, A arg);
-  E visitConcatenateStrings(ConcatenateStrings node, A arg);
   E visitConstant(Constant node, A arg);
   E visitThis(This node, A arg);
   E visitConditional(Conditional node, A arg);
@@ -813,6 +910,9 @@
   E visitReadTypeVariable(ReadTypeVariable node, A arg);
   E visitTypeExpression(TypeExpression node, A arg);
   E visitCreateInvocationMirror(CreateInvocationMirror node, A arg);
+  E visitInterceptor(Interceptor node, A arg);
+  E visitApplyBuiltinOperator(ApplyBuiltinOperator node, A arg);
+  E visitForeignExpression(ForeignExpression node, A arg);
 }
 
 abstract class StatementVisitor<S> {
@@ -828,6 +928,8 @@
   S visitWhileCondition(WhileCondition node);
   S visitExpressionStatement(ExpressionStatement node);
   S visitTry(Try node);
+  S visitUnreachable(Unreachable node);
+  S visitForeignStatement(ForeignStatement node);
 }
 
 abstract class StatementVisitor1<S, A> {
@@ -843,6 +945,8 @@
   S visitWhileCondition(WhileCondition node, A arg);
   S visitExpressionStatement(ExpressionStatement node, A arg);
   S visitTry(Try node, A arg);
+  S visitUnreachable(Unreachable node, A arg);
+  S visitForeignStatement(ForeignStatement node, A arg);
 }
 
 abstract class RecursiveVisitor implements StatementVisitor, ExpressionVisitor {
@@ -880,10 +984,6 @@
     node.arguments.forEach(visitExpression);
   }
 
-  visitConcatenateStrings(ConcatenateStrings node) {
-    node.arguments.forEach(visitExpression);
-  }
-
   visitConstant(Constant node) {}
 
   visitThis(This node) {}
@@ -1007,6 +1107,24 @@
   visitCreateInvocationMirror(CreateInvocationMirror node) {
     node.arguments.forEach(visitExpression);
   }
+
+  visitUnreachable(Unreachable node) {
+  }
+
+  visitApplyBuiltinOperator(ApplyBuiltinOperator node) {
+    node.arguments.forEach(visitExpression);
+  }
+
+  visitInterceptor(Interceptor node) {
+    visitExpression(node.input);
+  }
+
+  visitForeignCode(ForeignCode node) {
+    node.arguments.forEach(visitExpression);
+  }
+
+  visitForeignExpression(ForeignExpression node) => visitForeignCode(node);
+  visitForeignStatement(ForeignStatement node) => visitForeignCode(node);
 }
 
 abstract class Transformer implements ExpressionVisitor<Expression>,
@@ -1055,11 +1173,6 @@
     return node;
   }
 
-  visitConcatenateStrings(ConcatenateStrings node) {
-    _replaceExpressions(node.arguments);
-    return node;
-  }
-
   visitConstant(Constant node) => node;
 
   visitThis(This node) => node;
@@ -1203,4 +1316,28 @@
     _replaceExpressions(node.arguments);
     return node;
   }
+
+  visitForeignExpression(ForeignExpression node) {
+    _replaceExpressions(node.arguments);
+    return node;
+  }
+
+  visitForeignStatement(ForeignStatement node) {
+    _replaceExpressions(node.arguments);
+    return node;
+  }
+
+  visitUnreachable(Unreachable node) {
+    return node;
+  }
+
+  visitApplyBuiltinOperator(ApplyBuiltinOperator node) {
+    _replaceExpressions(node.arguments);
+    return node;
+  }
+
+  visitInterceptor(Interceptor node) {
+    node.input = visitExpression(node.input);
+    return node;
+  }
 }
diff --git a/pkg/compiler/lib/src/tree_ir/tree_ir_tracer.dart b/pkg/compiler/lib/src/tree_ir/tree_ir_tracer.dart
index acf3133..ab4b5b0 100644
--- a/pkg/compiler/lib/src/tree_ir/tree_ir_tracer.dart
+++ b/pkg/compiler/lib/src/tree_ir/tree_ir_tracer.dart
@@ -86,6 +86,10 @@
     _addStatement(node);
   }
 
+  visitUnreachable(Unreachable node) {
+    _addStatement(node);
+  }
+
   visitBreak(Break node) {
     _addStatement(node);
     blocks.last.addEdgeTo(breakTargets[node.target]);
@@ -168,6 +172,10 @@
     _addStatement(node);
     visitStatement(node.next);
   }
+
+  visitForeignStatement(ForeignStatement node) {
+    _addStatement(node);
+  }
 }
 
 class TreeTracer extends TracerUtil with StatementVisitor {
@@ -261,6 +269,10 @@
     printStatement(null, "rethrow");
   }
 
+  visitUnreachable(Unreachable node) {
+    printStatement(null, "unreachable");
+  }
+
   visitBreak(Break node) {
     printStatement(null, "break ${collector.breakTargets[node.target].name}");
   }
@@ -313,6 +325,11 @@
   String expr(Expression e) {
     return e.accept(new SubexpressionVisitor(names));
   }
+
+  @override
+  visitForeignStatement(ForeignStatement node) {
+    printStatement(null, 'foreign');
+  }
 }
 
 class SubexpressionVisitor extends ExpressionVisitor<String> {
@@ -368,11 +385,6 @@
     return "$keyword $callName($args)";
   }
 
-  String visitConcatenateStrings(ConcatenateStrings node) {
-    String args = node.arguments.map(visitExpression).join(', ');
-    return "concat [$args]";
-  }
-
   String visitLiteralList(LiteralList node) {
     String values = node.values.map(visitExpression).join(', ');
     return "list [$values]";
@@ -501,6 +513,23 @@
     String args = node.arguments.map(visitExpression).join(', ');
     return 'CreateInvocationMirror(${node.selector.name}, $args)';
   }
+
+  @override
+  String visitInterceptor(Interceptor node) {
+    return 'Interceptor(${visitExpression(node.input)})';
+  }
+
+  @override
+  String visitForeignExpression(ForeignExpression node) {
+    String arguments = node.arguments.map(visitExpression).join(', ');
+    return 'Foreign "${node.codeTemplate}"($arguments)';
+  }
+
+  @override
+  String visitApplyBuiltinOperator(ApplyBuiltinOperator node) {
+    String args = node.arguments.map(visitExpression).join(', ');
+    return 'ApplyBuiltinOperator ${node.operator} ($args)';
+  }
 }
 
 /**
diff --git a/pkg/compiler/lib/src/typechecker.dart b/pkg/compiler/lib/src/typechecker.dart
index 85d82b3..2d854a2 100644
--- a/pkg/compiler/lib/src/typechecker.dart
+++ b/pkg/compiler/lib/src/typechecker.dart
@@ -126,18 +126,26 @@
 
   DartType computeType(Compiler compiler) {
     if (element.isGetter) {
-      FunctionType functionType = element.computeType(compiler);
+      GetterElement getter = element;
+      FunctionType functionType = getter.computeType(compiler);
       return functionType.returnType;
     } else if (element.isSetter) {
-      FunctionType functionType = element.computeType(compiler);
+      SetterElement setter = element;
+      FunctionType functionType = setter.computeType(compiler);
       if (functionType.parameterTypes.length != 1) {
         // TODO(johnniwinther,karlklose): this happens for malformed static
         // setters. Treat them the same as instance members.
         return const DynamicType();
       }
       return functionType.parameterTypes.first;
+    } else if (element.isTypedef || element.isClass) {
+      TypeDeclarationElement typeDeclaration = element;
+      typeDeclaration.computeType(compiler);
+      return typeDeclaration.thisType;
     } else {
-      return element.computeType(compiler);
+      TypedElement typedElement = element;
+      typedElement.computeType(compiler);
+      return typedElement.type;
     }
   }
 
@@ -637,7 +645,7 @@
     } else if (node.isSuper()) {
       return superType;
     } else {
-      Element element = elements[node];
+      TypedElement element = elements[node];
       assert(invariant(node, element != null,
           message: 'Missing element for identifier'));
       assert(invariant(node, element.isVariable ||
@@ -1524,7 +1532,8 @@
     return compiler.symbolClass.rawType;
   }
 
-  DartType computeConstructorType(Element constructor, DartType type) {
+  DartType computeConstructorType(ConstructorElement constructor,
+                                  DartType type) {
     if (Elements.isUnresolved(constructor)) return const DynamicType();
     DartType constructorType = constructor.computeType(compiler);
     if (identical(type.kind, TypeKind.INTERFACE)) {
diff --git a/pkg/compiler/lib/src/types/constants.dart b/pkg/compiler/lib/src/types/constants.dart
index 7ba2621..1bcc1be 100644
--- a/pkg/compiler/lib/src/types/constants.dart
+++ b/pkg/compiler/lib/src/types/constants.dart
@@ -7,6 +7,7 @@
 import '../constants/values.dart';

 import '../dart2jslib.dart';

 import 'types.dart';

+import '../js_backend/js_backend.dart' show SyntheticConstantKind;

 

 /// Computes the [TypeMask] for the constant [value].

 TypeMask computeTypeMask(Compiler compiler, ConstantValue value) {

@@ -45,8 +46,21 @@
   }

 

   @override

-  TypeMask visitDummy(DummyConstantValue constant, Compiler compiler) {

-    return constant.typeMask;

+  TypeMask visitSynthetic(SyntheticConstantValue constant, Compiler compiler) {

+    switch (constant.kind) {

+      case SyntheticConstantKind.DUMMY_INTERCEPTOR:

+        return constant.payload;

+      case SyntheticConstantKind.EMPTY_VALUE:

+        return constant.payload;

+      case SyntheticConstantKind.TYPEVARIABLE_REFERENCE:

+        return compiler.typesTask.intType;

+      case SyntheticConstantKind.NAME:

+        return compiler.typesTask.stringType;

+      default:

+        compiler.internalError(compiler.currentElement,

+                               "Unexpected DummyConstantKind.");

+        return null;

+    }

   }

 

   @override

diff --git a/pkg/compiler/lib/src/types/flat_type_mask.dart b/pkg/compiler/lib/src/types/flat_type_mask.dart
index 2fa32ef..17d0fc5 100644
--- a/pkg/compiler/lib/src/types/flat_type_mask.dart
+++ b/pkg/compiler/lib/src/types/flat_type_mask.dart
@@ -57,7 +57,14 @@
     if (((flags >> 1) == SUBCLASS) && !world.hasAnySubclass(base)) {
       flags = (flags & 0x1) | (EXACT << 1);
     }
-    return new FlatTypeMask.internal(base, flags);
+    Map<ClassElement, TypeMask> cachedMasks =
+        world.canonicalizedTypeMasks[flags];
+    if (cachedMasks == null) {
+      world.canonicalizedTypeMasks[flags] = cachedMasks =
+          <ClassElement, TypeMask>{};
+    }
+    return cachedMasks.putIfAbsent(base,
+        () => new FlatTypeMask.internal(base, flags));
   }
 
   bool get isEmpty => (flags >> 1) == EMPTY;
@@ -634,9 +641,12 @@
            subclassesToCheck.any(needsNoSuchMethod);
   }
 
-  Element locateSingleElement(Selector selector, Compiler compiler) {
+  Element locateSingleElement(Selector selector,
+                              TypeMask mask,
+                              Compiler compiler) {
     if (isEmpty) return null;
-    Iterable<Element> targets = compiler.world.allFunctions.filter(selector);
+    Iterable<Element> targets =
+        compiler.world.allFunctions.filter(selector, mask);
     if (targets.length != 1) return null;
     Element result = targets.first;
     ClassElement enclosing = result.enclosingClass;
@@ -648,6 +658,7 @@
   }
 
   bool operator ==(var other) {
+    if (identical(this, other)) return true;
     if (other is !FlatTypeMask) return false;
     FlatTypeMask otherMask = other;
     return (flags == otherMask.flags) && (base == otherMask.base);
diff --git a/pkg/compiler/lib/src/types/forwarding_type_mask.dart b/pkg/compiler/lib/src/types/forwarding_type_mask.dart
index c57817a..ce29f50 100644
--- a/pkg/compiler/lib/src/types/forwarding_type_mask.dart
+++ b/pkg/compiler/lib/src/types/forwarding_type_mask.dart
@@ -96,8 +96,10 @@
     return forwardTo.canHit(element, selector, classWorld);
   }
 
-  Element locateSingleElement(Selector selector, Compiler compiler) {
-    return forwardTo.locateSingleElement(selector, compiler);
+  Element locateSingleElement(Selector selector,
+                              TypeMask mask,
+                              Compiler compiler) {
+    return forwardTo.locateSingleElement(selector, mask, compiler);
   }
 
   bool equalsDisregardNull(other) {
diff --git a/pkg/compiler/lib/src/types/type_mask.dart b/pkg/compiler/lib/src/types/type_mask.dart
index 753faf2..8e4e2d2 100644
--- a/pkg/compiler/lib/src/types/type_mask.dart
+++ b/pkg/compiler/lib/src/types/type_mask.dart
@@ -22,7 +22,8 @@
 
   factory TypeMask.exact(ClassElement base, ClassWorld classWorld) {
     assert(invariant(base, classWorld.isInstantiated(base),
-        message: "Cannot create extact type mask for uninstantiated class"));
+        message: "Cannot create extact type mask for uninstantiated class "
+          "${base.name}"));
     return new FlatTypeMask.exact(base);
   }
 
@@ -265,5 +266,8 @@
    * on this mask. Returns null if there is none.
    */
   // TODO(johnniwinther): Move this method to [World].
-  Element locateSingleElement(Selector selector, Compiler compiler);
+  Element locateSingleElement(
+      Selector selector,
+      TypeMask mask,
+      Compiler compiler);
 }
diff --git a/pkg/compiler/lib/src/types/types.dart b/pkg/compiler/lib/src/types/types.dart
index ec1d4d6..9db71f1 100644
--- a/pkg/compiler/lib/src/types/types.dart
+++ b/pkg/compiler/lib/src/types/types.dart
@@ -29,7 +29,7 @@
   TypeMask getReturnTypeOfElement(Element element);
   TypeMask getTypeOfElement(Element element);
   TypeMask getTypeOfNode(Element owner, Node node);
-  TypeMask getTypeOfSelector(Selector selector);
+  TypeMask getTypeOfSelector(Selector selector, TypeMask mask);
   void clear();
   bool isCalledOnce(Element element);
   bool isFixedArrayCheckedForGrowable(Node node);
@@ -322,15 +322,16 @@
   /**
    * Return the (inferred) guaranteed type of [selector] or null.
    */
-  TypeMask getGuaranteedTypeOfSelector(Selector selector) {
+  TypeMask getGuaranteedTypeOfSelector(Selector selector, TypeMask mask) {
     return measure(() {
       TypeMask guaranteedType =
-          typesInferrer.getTypeOfSelector(selector);
+          typesInferrer.getTypeOfSelector(selector, mask);
       return (concreteTypesInferrer == null)
           ? guaranteedType
-          : intersection(guaranteedType,
-                         concreteTypesInferrer.getTypeOfSelector(selector),
-                         selector);
+          : intersection(
+              guaranteedType,
+              concreteTypesInferrer.getTypeOfSelector(selector, mask),
+              selector);
     });
   }
 }
diff --git a/pkg/compiler/lib/src/types/union_type_mask.dart b/pkg/compiler/lib/src/types/union_type_mask.dart
index 3b0f139..f4c45e7 100644
--- a/pkg/compiler/lib/src/types/union_type_mask.dart
+++ b/pkg/compiler/lib/src/types/union_type_mask.dart
@@ -311,10 +311,12 @@
     return disjointMasks.any((e) => e.canHit(element, selector, classWorld));
   }
 
-  Element locateSingleElement(Selector selector, Compiler compiler) {
+  Element locateSingleElement(Selector selector,
+                              TypeMask mask,
+                              Compiler compiler) {
     Element candidate;
     for (FlatTypeMask mask in disjointMasks) {
-      Element current = mask.locateSingleElement(selector, compiler);
+      Element current = mask.locateSingleElement(selector, mask, compiler);
       if (current == null) {
         return null;
       } else if (candidate == null) {
diff --git a/pkg/compiler/lib/src/universe/function_set.dart b/pkg/compiler/lib/src/universe/function_set.dart
index 11baf76..db99578 100644
--- a/pkg/compiler/lib/src/universe/function_set.dart
+++ b/pkg/compiler/lib/src/universe/function_set.dart
@@ -48,30 +48,26 @@
    * Returns an object that allows iterating over all the functions
    * that may be invoked with the given [selector].
    */
-  Iterable<Element> filter(Selector selector) {
-    return query(selector).functions;
+  Iterable<Element> filter(Selector selector, TypeMask mask) {
+    return query(selector, mask).functions;
   }
 
-  TypeMask receiverType(Selector selector) {
-    return query(selector).computeMask(compiler.world);
+  TypeMask receiverType(Selector selector, TypeMask mask) {
+    return query(selector, mask).computeMask(compiler.world);
   }
 
-  FunctionSetQuery query(Selector selector) {
+  FunctionSetQuery query(Selector selector, TypeMask mask) {
     String name = selector.name;
     FunctionSetNode node = nodes[name];
     FunctionSetNode noSuchMethods = nodes[Compiler.NO_SUCH_METHOD];
     if (node != null) {
-      return node.query(selector, compiler, noSuchMethods);
+      return node.query(selector, mask, compiler, noSuchMethods);
     }
     // If there is no method that matches [selector] we know we can
     // only hit [:noSuchMethod:].
     if (noSuchMethods == null) return const FunctionSetQuery(const <Element>[]);
-    selector = (selector.mask == null)
-        ? compiler.noSuchMethodSelector
-        : new TypedSelector(selector.mask, compiler.noSuchMethodSelector,
-            compiler.world);
-
-    return noSuchMethods.query(selector, compiler, null);
+    return noSuchMethods.query(
+        compiler.noSuchMethodSelector, mask, compiler, null);
   }
 
   void forEach(Function action) {
@@ -81,11 +77,37 @@
   }
 }
 
+class SelectorMask {
+  final Selector selector;
+  final TypeMask mask;
+  final int hashCode;
+
+  SelectorMask(Selector selector, TypeMask mask)
+      : this.selector = selector,
+        this.mask = mask,
+        this.hashCode =
+            Hashing.mixHashCodeBits(selector.hashCode, mask.hashCode);
+
+  String get name => selector.name;
+
+  bool applies(Element element, ClassWorld classWorld) {
+    if (!selector.appliesUnnamed(element, classWorld)) return false;
+    if (mask == null) return true;
+    return mask.canHit(element, selector, classWorld);
+  }
+
+  bool operator ==(other) {
+    if (identical(this, other)) return true;
+    return selector == other.selector && mask == other.mask;
+  }
+
+  String toString() => '($selector,$mask)';
+}
 
 class FunctionSetNode {
   final String name;
-  final Map<Selector, FunctionSetQuery> cache =
-      new Map<Selector, FunctionSetQuery>();
+  final Map<SelectorMask, FunctionSetQuery> cache =
+      <SelectorMask, FunctionSetQuery>{};
 
   // Initially, we keep the elements in a list because it is more
   // compact than a hash set. Once we get enough elements, we change
@@ -142,24 +164,30 @@
     elements.forEach(action);
   }
 
-  TypeMask getNonNullTypeMaskOfSelector(Selector selector, Compiler compiler) {
+  TypeMask getNonNullTypeMaskOfSelector(TypeMask mask, ClassWorld classWorld) {
     // TODO(ngeoffray): We should probably change untyped selector
     // to always be a subclass of Object.
-    return selector.mask != null
-        ? selector.mask
-        : new TypeMask.subclass(compiler.objectClass, compiler.world);
+    return mask != null
+        ? mask
+        : new TypeMask.subclass(classWorld.objectClass, classWorld);
     }
 
+  // TODO(johnniwinther): Use [SelectorMask] instead of [Selector] and
+  // [TypeMask].
   FunctionSetQuery query(Selector selector,
+                         TypeMask mask,
                          Compiler compiler,
                          FunctionSetNode noSuchMethods) {
+    mask = getNonNullTypeMaskOfSelector(mask, compiler.world);
+    SelectorMask selectorMask = new SelectorMask(selector, mask);
     ClassWorld classWorld = compiler.world;
     assert(selector.name == name);
-    FunctionSetQuery result = cache[selector];
+    FunctionSetQuery result = cache[selectorMask];
     if (result != null) return result;
+
     Setlet<Element> functions;
     for (Element element in elements) {
-      if (selector.appliesUnnamed(element, classWorld)) {
+      if (selectorMask.applies(element, classWorld)) {
         if (functions == null) {
           // Defer the allocation of the functions set until we are
           // sure we need it. This allows us to return immutable empty
@@ -170,15 +198,14 @@
       }
     }
 
-    TypeMask mask = getNonNullTypeMaskOfSelector(selector, compiler);
     // If we cannot ensure a method will be found at runtime, we also
     // add [noSuchMethod] implementations that apply to [mask] as
     // potential targets.
     if (noSuchMethods != null
         && mask.needsNoSuchMethodHandling(selector, classWorld)) {
       FunctionSetQuery noSuchMethodQuery = noSuchMethods.query(
-          new TypedSelector(
-              mask, compiler.noSuchMethodSelector, classWorld),
+          compiler.noSuchMethodSelector,
+          mask,
           compiler,
           null);
       if (!noSuchMethodQuery.functions.isEmpty) {
@@ -189,14 +216,15 @@
         }
       }
     }
-    cache[selector] = result = (functions != null)
-        ? newQuery(functions, selector, compiler)
+    cache[selectorMask] = result = (functions != null)
+        ? newQuery(functions, selector, mask, compiler)
         : const FunctionSetQuery(const <Element>[]);
     return result;
   }
 
   FunctionSetQuery newQuery(Iterable<Element> functions,
                             Selector selector,
+                            TypeMask mask,
                             Compiler compiler) {
     return new FullFunctionSetQuery(functions);
   }
diff --git a/pkg/compiler/lib/src/universe/universe.dart b/pkg/compiler/lib/src/universe/universe.dart
index f5cc710..8af7763 100644
--- a/pkg/compiler/lib/src/universe/universe.dart
+++ b/pkg/compiler/lib/src/universe/universe.dart
@@ -14,6 +14,72 @@
 part 'function_set.dart';
 part 'side_effects.dart';
 
+class UniverseSelector {
+  final Selector selector;
+  final TypeMask mask;
+
+  UniverseSelector(this.selector, this.mask);
+
+  bool appliesUnnamed(Element element, ClassWorld world) {
+    return selector.appliesUnnamed(element, world) &&
+        (mask == null || mask.canHit(element, selector, world));
+  }
+
+  String toString() => '$selector,$mask';
+}
+
+abstract class TypeMaskSet {
+  bool applies(Element element, Selector selector, ClassWorld world);
+  Iterable<TypeMask> get masks;
+}
+
+/// An implementation of a [TypeMaskSet] that is only increasing, that is, once
+/// a mask is added it cannot be removed.
+class IncreasingTypeMaskSet extends TypeMaskSet {
+  bool isAll = false;
+  Set<TypeMask> _masks;
+
+  bool applies(Element element, Selector selector, ClassWorld world) {
+    if (isAll) return true;
+    if (_masks == null) return false;
+    for (TypeMask mask in _masks) {
+      if (mask.canHit(element, selector, world)) return true;
+    }
+    return false;
+  }
+
+  bool add(TypeMask mask) {
+    if (isAll) return false;
+    if (mask == null) {
+      isAll = true;
+      _masks = null;
+      return true;
+    }
+    if (_masks == null) {
+      _masks = new Setlet<TypeMask>();
+    }
+    return _masks.add(mask);
+  }
+
+  Iterable<TypeMask> get masks {
+    if (isAll) return const [null];
+    if (_masks == null) return const [];
+    return _masks;
+  }
+
+  String toString() {
+    if (isAll) {
+      return '<all>';
+    } else if (_masks != null) {
+      return '$_masks';
+    } else {
+      return '<none>';
+    }
+  }
+}
+
+
+
 class Universe {
   /// The set of all directly instantiated classes, that is, classes with a
   /// generative constructor that has been called directly and not only through
@@ -51,12 +117,12 @@
       new Set<FunctionElement>();
   final Set<FunctionElement> methodsNeedingSuperGetter =
       new Set<FunctionElement>();
-  final Map<String, Set<Selector>> invokedNames =
-      new Map<String, Set<Selector>>();
-  final Map<String, Set<Selector>> invokedGetters =
-      new Map<String, Set<Selector>>();
-  final Map<String, Set<Selector>> invokedSetters =
-      new Map<String, Set<Selector>>();
+  final Map<String, Map<Selector, TypeMaskSet>> _invokedNames =
+      <String, Map<Selector, TypeMaskSet>>{};
+  final Map<String, Map<Selector, TypeMaskSet>> _invokedGetters =
+      <String, Map<Selector, TypeMaskSet>>{};
+  final Map<String, Map<Selector, TypeMaskSet>> _invokedSetters =
+      <String, Map<Selector, TypeMaskSet>>{};
 
   /**
    * Fields accessed. Currently only the codegen knows this
@@ -159,26 +225,75 @@
     });
   }
 
-  bool hasMatchingSelector(Set<Selector> selectors,
-                           Element member,
-                           World world) {
+  bool _hasMatchingSelector(Map<Selector, TypeMaskSet> selectors,
+                            Element member,
+                            World world) {
     if (selectors == null) return false;
-    for (Selector selector in selectors) {
-      if (selector.appliesUnnamed(member, world)) return true;
+    for (Selector selector in selectors.keys) {
+      if (selector.appliesUnnamed(member, world)) {
+        TypeMaskSet masks = selectors[selector];
+        if (masks.applies(member, selector, world)) {
+          return true;
+        }
+      }
     }
     return false;
   }
 
   bool hasInvocation(Element member, World world) {
-    return hasMatchingSelector(invokedNames[member.name], member, world);
+    return _hasMatchingSelector(_invokedNames[member.name], member, world);
   }
 
   bool hasInvokedGetter(Element member, World world) {
-    return hasMatchingSelector(invokedGetters[member.name], member, world);
+    return _hasMatchingSelector(_invokedGetters[member.name], member, world);
   }
 
   bool hasInvokedSetter(Element member, World world) {
-    return hasMatchingSelector(invokedSetters[member.name], member, world);
+    return _hasMatchingSelector(_invokedSetters[member.name], member, world);
+  }
+
+  bool registerInvocation(UniverseSelector selector) {
+    return _registerNewSelector(selector, _invokedNames);
+  }
+
+  bool registerInvokedGetter(UniverseSelector selector) {
+    return _registerNewSelector(selector, _invokedGetters);
+  }
+
+  bool registerInvokedSetter(UniverseSelector selector) {
+    return _registerNewSelector(selector, _invokedSetters);
+  }
+
+  bool _registerNewSelector(
+      UniverseSelector universeSelector,
+      Map<String, Map<Selector, TypeMaskSet>> selectorMap) {
+    Selector selector = universeSelector.selector;
+    String name = selector.name;
+    TypeMask mask = universeSelector.mask;
+    Map<Selector, TypeMaskSet> selectors = selectorMap.putIfAbsent(
+        name, () => new Maplet<Selector, TypeMaskSet>());
+    IncreasingTypeMaskSet masks = selectors.putIfAbsent(
+        selector, () => new IncreasingTypeMaskSet());
+    return masks.add(mask);
+  }
+
+  Map<Selector, TypeMaskSet> invocationsByName(String name) {
+    return _invokedNames[name];
+  }
+
+  void forEachInvokedName(
+      f(String name, Map<Selector, TypeMaskSet> selectors)) {
+    _invokedNames.forEach(f);
+  }
+
+  void forEachInvokedGetter(
+      f(String name, Map<Selector, TypeMaskSet> selectors)) {
+    _invokedGetters.forEach(f);
+  }
+
+  void forEachInvokedSetter(
+      f(String name, Map<Selector, TypeMaskSet> selectors)) {
+    _invokedSetters.forEach(f);
   }
 
   DartType registerIsCheck(DartType type, Compiler compiler) {
@@ -568,7 +683,6 @@
       Selector existing = list[i];
       if (existing.match(kind, name, callStructure)) {
         assert(existing.hashCode == hashCode);
-        assert(existing.mask == null);
         return existing;
       }
     }
@@ -693,10 +807,6 @@
   /** Check whether this is a call to 'assert'. */
   bool get isAssert => isCall && identical(name, "assert");
 
-  bool get hasExactMask => false;
-  TypeMask get mask => null;
-  Selector get asUntyped => this;
-
   /**
    * The member name for invocation mirrors created from this selector.
    */
@@ -776,96 +886,8 @@
   }
 
   String toString() {
-    String type = '';
-    if (mask != null) type = ', mask=$mask';
-    return 'Selector($kind, $name, ${callStructure.structureToString()}$type)';
-  }
-
-  Selector extendIfReachesAll(Compiler compiler) {
-    return new TypedSelector(
-        compiler.typesTask.dynamicType, this, compiler.world);
+    return 'Selector($kind, $name, ${callStructure.structureToString()})';
   }
 
   Selector toCallSelector() => new Selector.callClosureFrom(this);
 }
-
-class TypedSelector extends Selector {
-  final Selector asUntyped;
-  final TypeMask mask;
-
-  TypedSelector.internal(this.mask, Selector selector, int hashCode)
-      : asUntyped = selector,
-        super.internal(selector.kind,
-                       selector.memberName,
-                       selector.callStructure,
-                       hashCode) {
-    assert(mask != null);
-    assert(asUntyped.mask == null);
-  }
-
-
-  factory TypedSelector(TypeMask mask, Selector selector, World world) {
-    if (!world.hasClosedWorldAssumption) {
-      // TODO(johnniwinther): Improve use of TypedSelector in an open world.
-      bool isNullable = mask.isNullable;
-      mask = world.compiler.typesTask.dynamicType;
-      if (isNullable) {
-        mask = mask.nullable();
-      }
-    }
-    // TODO(johnniwinther): Allow more TypeSelector kinds during resoluton.
-    assert(world.isClosed || mask.isExact);
-    if (selector.mask == mask) return selector;
-    Selector untyped = selector.asUntyped;
-    Map<TypeMask, TypedSelector> map = world.canonicalizedValues
-        .putIfAbsent(untyped, () => new Map<TypeMask, TypedSelector>());
-    TypedSelector result = map[mask];
-    if (result == null) {
-      int hashCode = Hashing.mixHashCodeBits(untyped.hashCode, mask.hashCode);
-      result = map[mask] = new TypedSelector.internal(mask, untyped, hashCode);
-    }
-    return result;
-  }
-
-  factory TypedSelector.exact(
-      ClassElement base, Selector selector, World world)
-          => new TypedSelector(new TypeMask.exact(base, world), selector,
-              world);
-
-  factory TypedSelector.subclass(
-      ClassElement base, Selector selector, World world)
-          => new TypedSelector(new TypeMask.subclass(base, world),
-                               selector, world);
-
-  factory TypedSelector.subtype(
-      ClassElement base, Selector selector, World world)
-          => new TypedSelector(new TypeMask.subtype(base, world),
-                               selector, world);
-
-  bool appliesUnnamed(Element element, World world) {
-    assert(sameNameHack(element, world));
-    // [TypedSelector] are only used after resolution.
-    if (!element.isClassMember) return false;
-
-    // A closure can be called through any typed selector:
-    // class A {
-    //   get foo => () => 42;
-    //   bar() => foo(); // The call to 'foo' is a typed selector.
-    // }
-    if (element.enclosingClass.isClosure) {
-      return appliesUntyped(element, world);
-    }
-
-    if (!mask.canHit(element, this, world)) return false;
-    return appliesUntyped(element, world);
-  }
-
-  Selector extendIfReachesAll(Compiler compiler) {
-    bool canReachAll = compiler.enabledInvokeOn
-        && mask.needsNoSuchMethodHandling(this, compiler.world);
-    return canReachAll
-        ? new TypedSelector(
-            compiler.typesTask.dynamicType, this, compiler.world)
-        : this;
-  }
-}
diff --git a/pkg/compiler/lib/src/use_unused_api.dart b/pkg/compiler/lib/src/use_unused_api.dart
index 998b39b..a15b716 100644
--- a/pkg/compiler/lib/src/use_unused_api.dart
+++ b/pkg/compiler/lib/src/use_unused_api.dart
@@ -36,7 +36,6 @@
 import 'source_file_provider.dart' as source_file_provider;
 import 'ssa/ssa.dart' as ssa;
 import 'tree/tree.dart' as tree;
-import 'universe/universe.dart' as universe;
 import 'util/util.dart' as util;
 
 import 'scanner/scannerlib.dart' show
@@ -48,7 +47,7 @@
 }
 
 void main(List<String> arguments) {
-  useApi();
+  useApi(null);
   dart2js.main(arguments);
   dart2jslib.isPublicName(null);
   useConstant(null, null, null, null, null);
@@ -79,8 +78,7 @@
   useTreeVisitors();
 }
 
-useApi() {
-  api.ReadStringFromUri uri;
+useApi(api.ReadStringFromUri uri) {
 }
 
 void useConstant(constants.ConstantValue constant,
@@ -234,13 +232,10 @@
   compiler.currentlyInUserCode();
   type_graph_inferrer.TypeGraphInferrer typeGraphInferrer = null;
   source_file_provider.SourceFileProvider sourceFileProvider = null;
-  world.hasAnyUserDefinedGetter(null);
+  world.hasAnyUserDefinedGetter(null, null);
   typeGraphInferrer.getCallersOf(null);
   dart_types.Types.sorted(null);
   new dart_types.Types(compiler).copy(compiler);
-  new universe.TypedSelector.subclass(null, null, compiler.world);
-  new universe.TypedSelector.subtype(null, null, compiler.world);
-  new universe.TypedSelector.exact(null, null, compiler.world);
   sourceFileProvider.readStringFromUri(null);
 }
 
@@ -263,7 +258,7 @@
 useIr(ir_builder.IrBuilder builder) {
   builder
     ..buildStringConstant(null)
-    ..buildDynamicGet(null, null);
+    ..buildDynamicGet(null, null, null);
 }
 
 useCompiler(dart2jslib.Compiler compiler) {
diff --git a/pkg/compiler/lib/src/warnings.dart b/pkg/compiler/lib/src/warnings.dart
index 9bad54e..eb32045 100644
--- a/pkg/compiler/lib/src/warnings.dart
+++ b/pkg/compiler/lib/src/warnings.dart
@@ -530,6 +530,9 @@
   static const MessageKind NOT_INSTANCE_FIELD = const MessageKind(
       "'#{fieldName}' is not an instance field.");
 
+  static const MessageKind THIS_PROPERTY = const MessageKind(
+      "Expected an identifier.");
+
   static const MessageKind NO_CATCH_NOR_FINALLY = const MessageKind(
       "Expected 'catch' or 'finally'.");
 
@@ -1364,7 +1367,7 @@
 
   static const MessageKind DEFERRED_LIBRARY_DART_2_DART =
       const MessageKind(
-          "Deferred loading is not supported by the dart backend yet."
+          "Deferred loading is not supported by the dart backend yet. "
           "The output will not be split.");
 
   static const MessageKind DEFERRED_LIBRARY_WITHOUT_PREFIX =
@@ -1614,8 +1617,8 @@
 
 main() {}
 """, """
-// package name must be a valid identifier
-import 'package:not-valid/foo.dart';
+// package name must be valid
+import 'package:not\valid/foo.dart';
 
 main() {}
 """]);
diff --git a/pkg/compiler/lib/src/world.dart b/pkg/compiler/lib/src/world.dart
index 99b4493..21dc96e 100644
--- a/pkg/compiler/lib/src/world.dart
+++ b/pkg/compiler/lib/src/world.dart
@@ -111,8 +111,10 @@
   ClassElement get doubleClass => compiler.doubleClass;
   ClassElement get stringClass => compiler.stringClass;
 
-  Map<Selector, Map<ti.TypeMask, TypedSelector>> canonicalizedValues =
-     new Map<Selector, Map<ti.TypeMask, TypedSelector>>();
+  /// Cache of [ti.FlatTypeMask]s grouped by the 8 possible values of the
+  /// [ti.FlatTypeMask.flags] property.
+  List<Map<ClassElement, ti.TypeMask>> canonicalizedTypeMasks =
+      new List<Map<ClassElement, ti.TypeMask>>.filled(8, null);
 
   bool checkInvariants(ClassElement cls, {bool mustBeInstantiated: true}) {
     return
@@ -405,8 +407,8 @@
     users.add(mixinApplication);
   }
 
-  bool hasAnyUserDefinedGetter(Selector selector) {
-    return allFunctions.filter(selector).any((each) => each.isGetter);
+  bool hasAnyUserDefinedGetter(Selector selector, ti.TypeMask mask) {
+    return allFunctions.filter(selector, mask).any((each) => each.isGetter);
   }
 
   void registerUsedElement(Element element) {
@@ -415,16 +417,26 @@
     }
   }
 
-  VariableElement locateSingleField(Selector selector) {
-    Element result = locateSingleElement(selector);
+  VariableElement locateSingleField(Selector selector, ti.TypeMask mask) {
+    Element result = locateSingleElement(selector, mask);
     return (result != null && result.isField) ? result : null;
   }
 
-  Element locateSingleElement(Selector selector) {
-    ti.TypeMask mask = selector.mask == null
+  Element locateSingleElement(Selector selector, ti.TypeMask mask) {
+    mask = mask == null
         ? compiler.typesTask.dynamicType
-        : selector.mask;
-    return mask.locateSingleElement(selector, compiler);
+        : mask;
+    return mask.locateSingleElement(selector, mask, compiler);
+  }
+
+  ti.TypeMask extendMaskIfReachesAll(Selector selector, ti.TypeMask mask) {
+    bool canReachAll = true;
+    if (mask != null) {
+      canReachAll =
+          compiler.enabledInvokeOn &&
+          mask.needsNoSuchMethodHandling(selector, this);
+    }
+    return canReachAll ? compiler.typesTask.dynamicType : mask;
   }
 
   void addFunctionCalledInLoop(Element element) {
@@ -475,11 +487,11 @@
     sideEffectsFreeElements.add(element);
   }
 
-  SideEffects getSideEffectsOfSelector(Selector selector) {
+  SideEffects getSideEffectsOfSelector(Selector selector, ti.TypeMask mask) {
     // We're not tracking side effects of closures.
     if (selector.isClosureCall) return new SideEffects();
     SideEffects sideEffects = new SideEffects.empty();
-    for (Element e in allFunctions.filter(selector)) {
+    for (Element e in allFunctions.filter(selector, mask)) {
       if (e.isField) {
         if (selector.isGetter) {
           if (!fieldNeverChanges(e)) {
diff --git a/pkg/expect/lib/expect.dart b/pkg/expect/lib/expect.dart
index 82e604a..e7eb892 100644
--- a/pkg/expect/lib/expect.dart
+++ b/pkg/expect/lib/expect.dart
@@ -363,7 +363,7 @@
     if (f is! _Nullary) {
       // Only throws from executing the funtion body should count as throwing.
       // The failure to even call `f` should throw outside the try/catch.
-      _fail("Expect.throws$msg: Funciton f not callable with zero arguments");
+      _fail("Expect.throws$msg: Function f not callable with zero arguments");
     }
     try {
       f();
@@ -406,12 +406,12 @@
 /// Annotation class for testing of dart2js. Use this as metadata on method
 /// declarations to make the type inferrer trust the parameter and return types,
 /// effectively asserting the runtime values will (at least) be subtypes of the
-/// annotated types. 
+/// annotated types.
 ///
-/// While the actually inferred type is guaranteed to be a subtype of the 
-/// annotation, it often is more precise. In particular, if a method is only 
+/// While the actually inferred type is guaranteed to be a subtype of the
+/// annotation, it often is more precise. In particular, if a method is only
 /// called with `null`, the inferrer will still infer null. To ensure that
-/// the annotated type is also the inferred type, additionally use 
+/// the annotated type is also the inferred type, additionally use
 /// [AssumeDynamic].
 class TrustTypeAnnotations {
   const TrustTypeAnnotations();
@@ -420,7 +420,7 @@
 /// Annotation class for testing of dart2js. Use this as metadata on method
 /// declarations to disable closed world assumptions on parameters, effectively
 /// assuming that the runtime arguments could be any value. Note that the
-/// constraints due to [TrustTypeAnnotations] still apply. 
+/// constraints due to [TrustTypeAnnotations] still apply.
 class AssumeDynamic {
   const AssumeDynamic();
 }
diff --git a/pkg/fixnum/lib/src/int32.dart b/pkg/fixnum/lib/src/int32.dart
index 09317b6..8e0dcca 100644
--- a/pkg/fixnum/lib/src/int32.dart
+++ b/pkg/fixnum/lib/src/int32.dart
@@ -57,15 +57,18 @@
     }
   }
 
+  static int _validateRadix(int radix) {
+    if (2 <= radix && radix <= 36) return radix;
+    throw new RangeError.range(radix, 2, 36, 'radix');
+  }
+
   /**
    * Parses a [String] in a given [radix] between 2 and 16 and returns an
    * [Int32].
    */
   // TODO(rice) - Make this faster by converting several digits at once.
   static Int32 parseRadix(String s, int radix) {
-    if ((radix <= 1) || (radix > 16)) {
-      throw new ArgumentError("Bad radix: $radix");
-    }
+    _validateRadix(radix);
     Int32 x = ZERO;
     for (int i = 0; i < s.length; i++) {
       int c = s.codeUnitAt(i);
@@ -348,12 +351,12 @@
   int numberOfTrailingZeros() => _numberOfTrailingZeros(_i);
 
   Int32 toSigned(int width) {
-    if (width < 1 || width > 32) throw new ArgumentError(width);
+    if (width < 1 || width > 32) throw new RangeError.range(width, 1, 32);
     return new Int32(_i.toSigned(width));
   }
 
   Int32 toUnsigned(int width) {
-    if (width < 0 || width > 32) throw new ArgumentError(width);
+    if (width < 0 || width > 32) throw new RangeError.range(width, 0, 32);
     return new Int32(_i.toUnsigned(width));
   }
 
diff --git a/pkg/fixnum/lib/src/int64.dart b/pkg/fixnum/lib/src/int64.dart
index 9ccf059..7ff28d2 100644
--- a/pkg/fixnum/lib/src/int64.dart
+++ b/pkg/fixnum/lib/src/int64.dart
@@ -70,10 +70,7 @@
    * [Int64].
    */
   static Int64 parseRadix(String s, int radix) {
-    if ((radix <= 1) || (radix > 36)) {
-      throw new ArgumentError("Bad radix: $radix");
-    }
-    return _parseRadix(s, radix);
+    return _parseRadix(s, Int32._validateRadix(radix));
   }
 
   static Int64 _parseRadix(String s, int radix) {
@@ -210,15 +207,15 @@
 
   // Returns the [Int64] representation of the specified value. Throws
   // [ArgumentError] for non-integer arguments.
-  static Int64 _promote(val) {
-    if (val is Int64) {
-      return val;
-    } else if (val is int) {
-      return new Int64(val);
-    } else if (val is Int32) {
-      return val.toInt64();
+  static Int64 _promote(value) {
+    if (value is Int64) {
+      return value;
+    } else if (value is int) {
+      return new Int64(value);
+    } else if (value is Int32) {
+      return value.toInt64();
     }
-    throw new ArgumentError(val);
+    throw new ArgumentError.value(value);
   }
 
   Int64 operator +(other) {
@@ -353,7 +350,7 @@
 
   Int64 operator <<(int n) {
     if (n < 0) {
-      throw new ArgumentError(n);
+      throw new ArgumentError.value(n);
     }
     n &= 63;
 
@@ -377,7 +374,7 @@
 
   Int64 operator >>(int n) {
     if (n < 0) {
-      throw new ArgumentError(n);
+      throw new ArgumentError.value(n);
     }
     n &= 63;
 
@@ -420,7 +417,7 @@
 
   Int64 shiftRightUnsigned(int n) {
     if (n < 0) {
-      throw new ArgumentError(n);
+      throw new ArgumentError.value(n);
     }
     n &= 63;
 
@@ -583,7 +580,7 @@
   }
 
   Int64 toSigned(int width) {
-    if (width < 1 || width > 64) throw new ArgumentError(width);
+    if (width < 1 || width > 64) throw new RangeError.range(width, 1, 64);
     if (width > _BITS01) {
       return Int64._masked(_l, _m, _h.toSigned(width - _BITS01));
     } else if (width > _BITS) {
@@ -600,7 +597,7 @@
   }
 
   Int64 toUnsigned(int width) {
-    if (width < 0 || width > 64) throw new ArgumentError(width);
+    if (width < 0 || width > 64) throw new RangeError.range(width, 0, 64);
     if (width > _BITS01) {
       int h = _h.toUnsigned(width - _BITS01);
       return Int64._masked(_l, _m, h);
@@ -684,10 +681,7 @@
   }
 
   String toRadixString(int radix) {
-    if ((radix <= 1) || (radix > 36)) {
-      throw new ArgumentError("Bad radix: $radix");
-    }
-    return _toRadixString(radix);
+    return _toRadixString(Int32._validateRadix(radix));
   }
 
   String _toRadixString(int radix) {
diff --git a/pkg/fixnum/pubspec.yaml b/pkg/fixnum/pubspec.yaml
index 4b0662f..b657f19 100644
--- a/pkg/fixnum/pubspec.yaml
+++ b/pkg/fixnum/pubspec.yaml
@@ -1,5 +1,5 @@
 name: fixnum
-version: 0.10.1
+version: 0.10.2
 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/fixnum/test/int_32_test.dart b/pkg/fixnum/test/int_32_test.dart
index 8ce7824..9773deb 100644
--- a/pkg/fixnum/test/int_32_test.dart
+++ b/pkg/fixnum/test/int_32_test.dart
@@ -273,8 +273,8 @@
       expect(Int32.MIN_VALUE.toSigned(32), Int32.MIN_VALUE);
       expect(Int32.MAX_VALUE.toSigned(31), -Int32.ONE);
       expect(Int32.MIN_VALUE.toSigned(31), Int32.ZERO);
-      expect(() => Int32.ONE.toSigned(0), throws);
-      expect(() => Int32.ONE.toSigned(33), throws);
+      expect(() => Int32.ONE.toSigned(0), throwsRangeError);
+      expect(() => Int32.ONE.toSigned(33), throwsRangeError);
     });
     test("toUnsigned", () {
       expect(Int32.ONE.toUnsigned(1), Int32.ONE);
@@ -283,8 +283,8 @@
       expect(Int32.MIN_VALUE.toUnsigned(32), Int32.MIN_VALUE);
       expect(Int32.MAX_VALUE.toUnsigned(31), Int32.MAX_VALUE);
       expect(Int32.MIN_VALUE.toUnsigned(31), Int32.ZERO);
-      expect(() => Int32.ONE.toUnsigned(-1), throws);
-      expect(() => Int32.ONE.toUnsigned(33), throws);
+      expect(() => Int32.ONE.toUnsigned(-1), throwsRangeError);
+      expect(() => Int32.ONE.toUnsigned(33), throwsRangeError);
     });
     test("toDouble", () {
       expect(new Int32(17).toDouble(), same(17.0));
diff --git a/pkg/fixnum/test/int_64_test.dart b/pkg/fixnum/test/int_64_test.dart
index a392182..1e17dae 100644
--- a/pkg/fixnum/test/int_64_test.dart
+++ b/pkg/fixnum/test/int_64_test.dart
@@ -7,6 +7,15 @@
 import 'package:unittest/unittest.dart';
 
 void main() {
+
+  argumentErrorTest(name, op, [receiver = Int64.ONE]) {
+    throwsArgumentErrorMentioning(substring) =>
+        throwsA((e) => e is ArgumentError && '$e'.contains(substring));
+
+    expect(() => op(receiver, null), throwsArgumentErrorMentioning('null'));
+    expect(() => op(receiver, 'foo'), throwsArgumentErrorMentioning(r'"foo"'));
+  }
+
   group("is-tests", () {
     test("isEven", () {
       expect((-Int64.ONE).isEven, false);
@@ -68,6 +77,7 @@
       expect(n3 + n4, new Int64(-11110));
       expect(n5 + n6, new Int64.fromInts(0x89ab89ab, 0xcdeff011));
       expect(Int64.MAX_VALUE + 1, Int64.MIN_VALUE);
+      argumentErrorTest("+", (a, b) => a + b);
     });
 
     test("-", () {
@@ -76,6 +86,7 @@
       expect(n3 - n4, new Int64(8642));
       expect(n5 - n6, new Int64.fromInts(0x9abd2345, 0x89ab6789));
       expect(Int64.MIN_VALUE - 1, Int64.MAX_VALUE);
+      argumentErrorTest("-", (a, b) => a - b);
     });
 
     test("unary -", () {
@@ -113,6 +124,7 @@
       expect(Int64.MIN_VALUE * new Int64(2), Int64.ZERO);
       expect(Int64.MIN_VALUE * new Int64(1), Int64.MIN_VALUE);
       expect(Int64.MIN_VALUE * new Int64(-1), Int64.MIN_VALUE);
+      argumentErrorTest("*", (a, b) => a * b);
     });
 
     test("~/", () {
@@ -185,7 +197,7 @@
       expect(Int64.MIN_VALUE ~/ new Int64(1), Int64.MIN_VALUE);
       expect(Int64.MIN_VALUE ~/ new Int64(-1), Int64.MIN_VALUE);
       expect(() => new Int64(17) ~/ Int64.ZERO, throws);
-      expect(() => new Int64(17) ~/ null, throwsArgumentError);
+      argumentErrorTest("~/", (a, b) => a ~/ b);
     });
 
     test("%", () {
@@ -225,6 +237,7 @@
           new Int64(-0x12345678.remainder(0x22)));
       expect(new Int32(0x12345678).remainder(new Int64(0x22)),
           new Int64(0x12345678.remainder(0x22)));
+      argumentErrorTest("%", (a, b) => a % b);
     });
 
     test("clamp", () {
@@ -268,7 +281,7 @@
       expect(largePosPlusOne < largePos, false);
       expect(Int64.MIN_VALUE < Int64.MAX_VALUE, true);
       expect(Int64.MAX_VALUE < Int64.MIN_VALUE, false);
-      expect(() => new Int64(17) < null, throwsArgumentError);
+      argumentErrorTest("<", (a, b) => a < b);
     });
 
     test("<=", () {
@@ -287,7 +300,7 @@
       expect(largePosPlusOne <= largePos, false);
       expect(Int64.MIN_VALUE <= Int64.MAX_VALUE, true);
       expect(Int64.MAX_VALUE <= Int64.MIN_VALUE, false);
-      expect(() => new Int64(17) <= null, throwsArgumentError);
+      argumentErrorTest("<=", (a, b) => a <= b);
     });
 
     test("==", () {
@@ -323,7 +336,7 @@
       expect(largePosPlusOne >= largePos, true);
       expect(Int64.MIN_VALUE >= Int64.MAX_VALUE, false);
       expect(Int64.MAX_VALUE >= Int64.MIN_VALUE, true);
-      expect(() => new Int64(17) >= null, throwsArgumentError);
+      argumentErrorTest(">=", (a, b) => a >= b);
     });
 
     test(">", () {
@@ -344,7 +357,7 @@
       expect(Int64.ZERO > Int64.MIN_VALUE, true);
       expect(Int64.MIN_VALUE > Int64.MAX_VALUE, false);
       expect(Int64.MAX_VALUE > Int64.MIN_VALUE, true);
-      expect(() => new Int64(17) > null, throwsArgumentError);
+      argumentErrorTest(">", (a, b) => a > b);
     });
   });
 
@@ -360,6 +373,7 @@
       expect(n3 & n2, new Int64(8708));
       expect(n4 & n5, new Int64(0x1034) << 32);
       expect(() => n1 & null, throwsArgumentError);
+      argumentErrorTest("&", (a, b) => a & b);
     });
 
     test("|", () {
@@ -367,6 +381,7 @@
       expect(n3 | n2, new Int64(-66));
       expect(n4 | n5, new Int64(0x9a76) << 32);
       expect(() => n1 | null, throwsArgumentError);
+      argumentErrorTest("|", (a, b) => a | b);
     });
 
     test("^", () {
@@ -374,6 +389,7 @@
       expect(n3 ^ n2, new Int64(-8774));
       expect(n4 ^ n5, new Int64(0x8a42) << 32);
       expect(() => n1 ^ null, throwsArgumentError);
+      argumentErrorTest("^", (a, b) => a ^ b);
     });
 
     test("~", () {
@@ -523,8 +539,8 @@
       expect(Int64.MIN_VALUE.toSigned(64), Int64.MIN_VALUE);
       expect(Int64.MAX_VALUE.toSigned(63), -Int64.ONE);
       expect(Int64.MIN_VALUE.toSigned(63), Int64.ZERO);
-      expect(() => Int64.ONE.toSigned(0), throws);
-      expect(() => Int64.ONE.toSigned(65), throws);
+      expect(() => Int64.ONE.toSigned(0), throwsRangeError);
+      expect(() => Int64.ONE.toSigned(65), throwsRangeError);
     });
     test("toUnsigned", () {
       expect((Int64.ONE << 44).toUnsigned(45), Int64.ONE << 44);
@@ -537,8 +553,8 @@
       expect(Int64.MIN_VALUE.toUnsigned(64), Int64.MIN_VALUE);
       expect(Int64.MAX_VALUE.toUnsigned(63), Int64.MAX_VALUE);
       expect(Int64.MIN_VALUE.toUnsigned(63), Int64.ZERO);
-      expect(() => Int64.ONE.toUnsigned(-1), throws);
-      expect(() => Int64.ONE.toUnsigned(65), throws);
+      expect(() => Int64.ONE.toUnsigned(-1), throwsRangeError);
+      expect(() => Int64.ONE.toUnsigned(65), throwsRangeError);
     });
     test("toDouble", () {
       expect(new Int64(0).toDouble(), same(0.0));
@@ -658,9 +674,6 @@
       checkInt(4294967296);
       checkInt(-4294967295);
       checkInt(-4294967296);
-      expect(() => Int64.parseRadix('xyzzy', -1), throwsArgumentError);
-      expect(() => Int64.parseRadix('plugh', 10),
-          throwsA(new isInstanceOf<FormatException>()));
     });
 
     test("parseRadix", () {
@@ -674,6 +687,11 @@
       check("9223372036854775807", 10, "9223372036854775807");
       // Overflow during parsing.
       check("9223372036854775808", 10, "-9223372036854775808");
+
+      expect(() => Int64.parseRadix('0', 1), throwsRangeError);
+      expect(() => Int64.parseRadix('0', 37), throwsRangeError);
+      expect(() => Int64.parseRadix('xyzzy', -1), throwsRangeError);
+      expect(() => Int64.parseRadix('xyzzy', 10), throwsFormatException);
     });
 
     test("parseRadixN", () {
@@ -748,7 +766,8 @@
       expect(Int64.MAX_VALUE.toRadixString(13), "10b269549075433c37");
       expect(Int64.MAX_VALUE.toRadixString(14), "4340724c6c71dc7a7");
       expect(Int64.MAX_VALUE.toRadixString(15), "160e2ad3246366807");
-      expect(Int64.MAX_VALUE.toRadixString(16), "7fffffffffffffff");
+      expect(() => Int64.ZERO.toRadixString(1), throwsRangeError);
+      expect(() => Int64.ZERO.toRadixString(37), throwsRangeError);
     });
   });
 }
diff --git a/pkg/js_ast/lib/js_ast.dart b/pkg/js_ast/lib/js_ast.dart
index 27773b5..a9f0fc9 100644
--- a/pkg/js_ast/lib/js_ast.dart
+++ b/pkg/js_ast/lib/js_ast.dart
@@ -4,6 +4,7 @@
 
 library js_ast;
 
+import 'dart:collection' show IterableBase;
 import 'src/precedence.dart';
 import 'src/characters.dart' as charCodes;
 
diff --git a/pkg/js_ast/lib/src/builder.dart b/pkg/js_ast/lib/src/builder.dart
index 12f204e..076ff65 100644
--- a/pkg/js_ast/lib/src/builder.dart
+++ b/pkg/js_ast/lib/src/builder.dart
@@ -329,6 +329,37 @@
   /// [escapedString].
   LiteralString string(String value) => new LiteralString('"$value"');
 
+  /// Creates an instance of [LiteralString] from [value].
+  ///
+  /// Does not add quotes or do any escaping.
+  LiteralString stringPart(String value) => new LiteralString(value);
+
+  StringConcatenation concatenateStrings(Iterable<Literal> parts,
+                                         {addQuotes: false}) {
+    List<Literal> _parts;
+    if (addQuotes) {
+      Literal quote = stringPart('"');
+      _parts = <Literal>[quote]
+          ..addAll(parts)
+          ..add(quote);
+    } else {
+      _parts = new List.from(parts, growable: false);
+    }
+    return new StringConcatenation(_parts);
+  }
+
+  Iterable<Literal> joinLiterals(Iterable<Literal> list, Literal separator) {
+    return new _InterleaveIterable(list, separator);
+  }
+
+  LiteralString quoteName(Name name, {allowNull: false}) {
+    if (name == null) {
+      assert(allowNull);
+      return new LiteralString('""');
+    }
+    return new LiteralStringFromName(name);
+  }
+
   LiteralNumber number(num value) => new LiteralNumber('$value');
 
   LiteralBool boolean(bool value) => new LiteralBool(value);
@@ -342,18 +373,30 @@
   Comment comment(String text) => new Comment(text);
 
   Call propertyCall(Expression receiver,
-                      String fieldName,
-                      List<Expression> arguments) {
-    return new Call(new PropertyAccess.field(receiver, fieldName), arguments);
+                    Expression fieldName,
+                    List<Expression> arguments) {
+    return new Call(new PropertyAccess(receiver, fieldName), arguments);
   }
 }
 
 LiteralString string(String value) => js.string(value);
+LiteralString quoteName(Name name, {allowNull: false}) {
+  return js.quoteName(name, allowNull: allowNull);
+}
+LiteralString stringPart(String value) => js.stringPart(value);
+Iterable<Literal> joinLiterals(Iterable<Literal> list, Literal separator) {
+  return js.joinLiterals(list, separator);
+}
+StringConcatenation concatenateStrings(Iterable<Literal> parts,
+                                       {addQuotes: false}) {
+  return js.concatenateStrings(parts, addQuotes: addQuotes);
+}
+
 LiteralNumber number(num value) => js.number(value);
 ArrayInitializer numArray(Iterable<int> list) => js.numArray(list);
 ArrayInitializer stringArray(Iterable<String> list) => js.stringArray(list);
 Call propertyCall(Expression receiver,
-                  String fieldName,
+                  Expression fieldName,
                   List<Expression> arguments) {
   return js.propertyCall(receiver, fieldName, arguments);
 }
@@ -772,7 +815,6 @@
   }
 
   Expression parseFunctionExpression() {
-    String last = lastToken;
     if (lastCategory == ALPHA || lastCategory == HASH) {
       Declaration name = parseVariableDeclaration();
       return new NamedFunction(name, parseFun());
@@ -1272,7 +1314,6 @@
   Statement parseTry() {
     expectCategory(LBRACE);
     Block body = parseBlock();
-    String token = lastToken;
     Catch catchPart = null;
     if (acceptString('catch')) catchPart = parseCatch();
     Block finallyPart = null;
@@ -1348,3 +1389,40 @@
     return new Catch(errorName, body);
   }
 }
+
+class _InterleaveIterator implements Iterator<Node> {
+  Iterator<Node> source;
+  Node separator;
+  bool isNextSeparator = false;
+  bool isInitialized = false;
+
+  _InterleaveIterator(this.source, this.separator);
+
+  bool moveNext() {
+    if (!isInitialized) {
+      isInitialized = true;
+      return source.moveNext();
+    } else if (isNextSeparator) {
+      isNextSeparator = false;
+      return true;
+    } else {
+      return isNextSeparator = source.moveNext();
+    }
+  }
+
+  Node get current {
+    if (isNextSeparator) return separator;
+    return source.current;
+  }
+}
+
+class _InterleaveIterable extends IterableBase {
+  Iterable<Node> source;
+  Node separator;
+
+  _InterleaveIterable(this.source, this.separator);
+
+  Iterator<Node> get iterator {
+    return new _InterleaveIterator(source.iterator, separator);
+  }
+}
\ No newline at end of file
diff --git a/pkg/js_ast/lib/src/nodes.dart b/pkg/js_ast/lib/src/nodes.dart
index 7c8293e..33b5c58 100644
--- a/pkg/js_ast/lib/src/nodes.dart
+++ b/pkg/js_ast/lib/src/nodes.dart
@@ -49,11 +49,19 @@
   T visitNamedFunction(NamedFunction node);
   T visitFun(Fun node);
 
+  T visitDeferredExpression(DeferredExpression node);
+  T visitDeferredNumber(DeferredNumber node);
+  T visitDeferredString(DeferredString node);
+
   T visitLiteralBool(LiteralBool node);
   T visitLiteralString(LiteralString node);
   T visitLiteralNumber(LiteralNumber node);
   T visitLiteralNull(LiteralNull node);
 
+  T visitStringConcatenation(StringConcatenation node);
+
+  T visitName(Name node);
+
   T visitArrayInitializer(ArrayInitializer node);
   T visitArrayHole(ArrayHole node);
   T visitObjectInitializer(ObjectInitializer node);
@@ -139,6 +147,12 @@
   T visitNamedFunction(NamedFunction node) => visitExpression(node);
   T visitFun(Fun node) => visitExpression(node);
 
+  T visitToken(DeferredToken node) => visitExpression(node);
+
+  T visitDeferredExpression(DeferredExpression node) => visitExpression(node);
+  T visitDeferredNumber(DeferredNumber node) => visitToken(node);
+  T visitDeferredString(DeferredString node) => visitToken(node);
+
   T visitLiteral(Literal node) => visitExpression(node);
 
   T visitLiteralBool(LiteralBool node) => visitLiteral(node);
@@ -146,6 +160,10 @@
   T visitLiteralNumber(LiteralNumber node) => visitLiteral(node);
   T visitLiteralNull(LiteralNull node) => visitLiteral(node);
 
+  T visitStringConcatenation(StringConcatenation node) => visitLiteral(node);
+
+  T visitName(Name node) => visitNode(node);
+
   T visitArrayInitializer(ArrayInitializer node) => visitExpression(node);
   T visitArrayHole(ArrayHole node) => visitExpression(node);
   T visitObjectInitializer(ObjectInitializer node) => visitExpression(node);
@@ -559,6 +577,28 @@
 
 }
 
+/// An implementation of [Name] represents a potentially late bound name in
+/// the generated ast.
+///
+/// While [Name] implements comparable, there is no requirement on the actual
+/// implementation of [compareTo] other than that it needs to be stable.
+/// In particular, there is no guarantee that implementations of [compareTo]
+/// will implement some form of lexicographic ordering like [String.compareTo].
+abstract class Name extends Literal
+    implements Declaration, Parameter, Comparable {
+  accept(NodeVisitor visitor) => visitor.visitName(this);
+
+  bool get allowRename => false;
+}
+
+class LiteralStringFromName extends LiteralString {
+  Name name;
+
+  LiteralStringFromName(this.name) : super(null);
+
+  String get value => '"${name.name}"';
+}
+
 class LiteralExpression extends Expression {
   final String template;
   final List<Expression> inputs;
@@ -675,7 +715,9 @@
 
   void visitChildren(NodeVisitor visitor) {
     target.accept(visitor);
-    for (Expression arg in arguments) arg.accept(visitor);
+    for (Expression arg in arguments) {
+      arg.accept(visitor);
+    }
   }
 
   Call _clone() => new Call(target, arguments);
@@ -916,6 +958,46 @@
   int get precedenceLevel => CALL;
 }
 
+/// A [DeferredToken] is a placeholder for some [Expression] that is not known
+/// at construction time of an ast. Unlike [InterpolatedExpression],
+/// [DeferredToken] is not limited to templates but may also occur in
+/// fully instantiated asts.
+abstract class DeferredToken extends Expression {
+  void visitChildren(NodeVisitor visitor) {}
+
+  DeferredToken _clone() => this;
+}
+
+/// Interace for a deferred integer value. An implementation has to provide
+/// a value via the [value] getter the latest when the ast is printed.
+abstract class DeferredNumber extends DeferredToken implements Literal {
+  accept(NodeVisitor visitor) => visitor.visitDeferredNumber(this);
+
+  int get value;
+
+  int get precedenceLevel => PRIMARY;
+}
+
+/// Interace for a deferred string value. An implementation has to provide
+/// a value via the [value] getter the latest when the ast is printed.
+abstract class DeferredString extends DeferredToken implements Literal {
+  accept(NodeVisitor visitor) => visitor.visitDeferredString(this);
+
+  String get value;
+
+  int get precedenceLevel => PRIMARY;
+}
+
+/// Interace for a deferred [Expression] value. An implementation has to provide
+/// a value via the [value] getter the latest when the ast is printed.
+/// Also, [precedenceLevel] has to return the same value that
+/// [value.precedenceLevel] returns once [value] is bound to an [Expression].
+abstract class DeferredExpression extends DeferredToken {
+  accept(NodeVisitor visitor) => visitor.visitDeferredExpression(this);
+
+  Expression get value;
+}
+
 abstract class Literal extends Expression {
   void visitChildren(NodeVisitor visitor) {}
 
@@ -946,7 +1028,7 @@
    * Constructs a LiteralString from a string value.
    *
    * The constructor does not add the required quotes.  If [value] is not
-   * surrounded by quotes and property escaped, the resulting object is invalid
+   * surrounded by quotes and properly escaped, the resulting object is invalid
    * as a JS value.
    *
    * TODO(sra): Introduce variants for known valid strings that don't allocate a
@@ -958,6 +1040,25 @@
   LiteralString _clone() => new LiteralString(value);
 }
 
+class StringConcatenation extends Literal {
+  final List<Literal> parts;
+
+  /**
+   * Constructs a StringConcatenation from a list of Literal elements.
+   * The constructor does not add surrounding quotes to the resulting
+   * concatenated string.
+   */
+  StringConcatenation(this.parts);
+
+  accept(NodeVisitor visitor) => visitor.visitStringConcatenation(this);
+
+  void visitChildren(NodeVisitor visitor) {
+    for (Literal part in parts) part.accept(visitor);
+  }
+
+  StringConcatenation _clone() => new StringConcatenation(this.parts);
+}
+
 class LiteralNumber extends Literal {
   final String value;  // Must be a valid JavaScript number literal.
 
@@ -1161,7 +1262,6 @@
   accept(NodeVisitor visitor) => visitor.visitAwait(this);
   void visitChildren(NodeVisitor visitor) => expression.accept(visitor);
   Await _clone() => new Await(expression);
-
 }
 
 /**
diff --git a/pkg/js_ast/lib/src/printer.dart b/pkg/js_ast/lib/src/printer.dart
index 57b35cf..ff757b4 100644
--- a/pkg/js_ast/lib/src/printer.dart
+++ b/pkg/js_ast/lib/src/printer.dart
@@ -927,6 +927,11 @@
         out(fieldWithQuotes.substring(1, fieldWithQuotes.length - 1));
         return;
       }
+    } else if (selector is Name) {
+      if (access.receiver is LiteralNumber) out(" ", isWhitespace: true);
+      out(".");
+      out(selector.name);
+      return;
     }
     out("[");
     visitNestedExpression(selector, EXPRESSION,
@@ -952,7 +957,32 @@
   }
 
   @override
-  void visitLiteralBool(LiteralBool node) {
+  visitDeferredExpression(DeferredExpression node) {
+    // Continue printing with the expression value.
+    assert(node.precedenceLevel == node.value.precedenceLevel);
+    node.value.accept(this);
+  }
+
+  outputNumberWithRequiredWhitespace(String number) {
+    int charCode = number.codeUnitAt(0);
+    if (charCode == charCodes.$MINUS && lastCharCode == charCodes.$MINUS) {
+      out(" ", isWhitespace: true);
+    }
+    out(number);
+  }
+
+  @override
+  visitDeferredNumber(DeferredNumber node) {
+    outputNumberWithRequiredWhitespace("${node.value}");
+  }
+
+  @override
+  visitDeferredString(DeferredString node) {
+    out(node.value);
+  }
+
+  @override
+  visitLiteralBool(LiteralBool node) {
     out(node.value ? "true" : "false");
   }
 
@@ -962,12 +992,18 @@
   }
 
   @override
-  void visitLiteralNumber(LiteralNumber node) {
-    int charCode = node.value.codeUnitAt(0);
-    if (charCode == charCodes.$MINUS && lastCharCode == charCodes.$MINUS) {
-      out(" ", isWhitespace: true);
-    }
-    out(node.value);
+  visitStringConcatenation(StringConcatenation node) {
+    node.visitChildren(this);
+  }
+
+  @override
+  visitName(Name node) {
+    out(node.name);
+  }
+
+  @override
+  visitLiteralNumber(LiteralNumber node) {
+    outputNumberWithRequiredWhitespace(node.value);
   }
 
   @override
@@ -1013,7 +1049,6 @@
     out("{");
     indentMore();
     for (int i = 0; i < properties.length; i++) {
-      Expression value = properties[i].value;
       if (i != 0) {
         out(",");
         if (node.isOneLiner) spaceOut();
@@ -1042,6 +1077,8 @@
       } else {
         out(name);
       }
+    } else if (node.name is Name) {
+      node.name.accept(this);
     } else {
       assert(node.name is LiteralNumber);
       LiteralNumber nameNumber = node.name;
diff --git a/pkg/js_ast/lib/src/template.dart b/pkg/js_ast/lib/src/template.dart
index e7aa863..632f273 100644
--- a/pkg/js_ast/lib/src/template.dart
+++ b/pkg/js_ast/lib/src/template.dart
@@ -654,6 +654,13 @@
     };
   }
 
+  Instantiator visitDeferredExpression(DeferredExpression node) => same(node);
+
+  Instantiator visitDeferredNumber(DeferredNumber node) => same(node);
+
+  Instantiator visitDeferredString(DeferredString node) =>
+      (arguments) => node;
+
   Instantiator visitLiteralBool(LiteralBool node) =>
       (arguments) => new LiteralBool(node.value);
 
@@ -666,6 +673,20 @@
   Instantiator visitLiteralNull(LiteralNull node) =>
       (arguments) => new LiteralNull();
 
+  Instantiator visitStringConcatenation(StringConcatenation node) {
+    List<Instantiator> partMakers = node.parts
+        .map(visit)
+        .toList(growable: false);
+    return (arguments) {
+      List<Literal> parts = partMakers
+          .map((Instantiator instantiator) => instantiator(arguments))
+          .toList(growable: false);
+      return new StringConcatenation(parts);
+    };
+  }
+
+  Instantiator visitName(Name node) => same(node);
+
   Instantiator visitArrayInitializer(ArrayInitializer node) {
     // TODO(sra): Implement splicing?
     List<Instantiator> elementMakers = node.elements
diff --git a/pkg/pkg.status b/pkg/pkg.status
index 78179ad..86cc7f1 100644
--- a/pkg/pkg.status
+++ b/pkg/pkg.status
@@ -49,6 +49,7 @@
 analyzer/test/generated/compile_time_error_code_test: Pass, Slow
 
 analyzer/test/enum_test: Slow, Pass, Fail # Issue 21323
+analyzer/test/src/context/context_test: Pass, Timeout # dartbug.com/23658
 
 analysis_server/test/*: Skip # Issue 22161
 analysis_server/test/search/element_references_test: Pass, Slow
@@ -74,16 +75,20 @@
 analysis_server/index/store/codec_test: Pass, Slow # Issue 19756
 
 [ $compiler == dart2js ]
-analysis_server/test/edit/refactoring_test: Pass, Slow # Issue 16473, 19756
-analysis_server/test/analysis_notification_occurrences_test: Pass, Slow # Issue 16473, 19756
-analysis_server/test/analysis_notification_outline_test: Pass, Slow # Issue 16473, 19756
-analysis_server/test/analysis_notification_navigation_test: Pass, Slow # Issue 16473, 19756
-analysis_server/test/domain_analysis_test: Pass, Slow # Issue 16473, 19756
-analysis_server/test/analysis_notification_highlights_test: Pass, Slow # 16473, 19756
-analysis_server/test/search/top_level_declarations_test: Pass, Slow # 16473, 19756
-analysis_server/test/socket_server_test: Pass, Slow # Issue 16473, 19756
-analyzer/test/generated/element_test: Pass, Slow # Issue 16473
-analyzer/test/generated/incremental_resolver_test: Pass, Slow # Issue 16473
+analysis_server/test/edit/refactoring_test: Pass, Slow # Issue 19756, 21628
+analysis_server/test/analysis_notification_occurrences_test: Pass, Slow # Issue 19756, 21628
+analysis_server/test/analysis_notification_outline_test: Pass, Slow # Issue 19756, 21628
+analysis_server/test/analysis_notification_navigation_test: Pass, Slow # Issue 19756, 21628
+analysis_server/test/domain_analysis_test: Pass, Slow # Issue 19756, 21628
+analysis_server/test/analysis_notification_highlights_test: Pass, Slow # 19756, 21628
+analysis_server/test/search/top_level_declarations_test: Pass, Slow # 19756, 21628
+analysis_server/test/socket_server_test: Pass, Slow # Issue 19756, 21628
+analyzer/test/generated/all_the_rest_test: Pass, Slow # Issue 21628
+analyzer/test/generated/element_test: Pass, Slow # Issue 21628
+analyzer/test/generated/incremental_resolver_test: Pass, Slow # Issue 21628
+analyzer/test/generated/utilities_test: Pass, Slow # Issue 21628
+analyzer/test/generated/parser_test: Pass, Slow # Issue 21628
+analyzer/test/src/task/dart_test: Pass, Slow # Issue 21628
 
 [ $runtime == jsshell ]
 async/test/stream_zip_test: RuntimeError, OK # Timers are not supported.
@@ -145,48 +150,50 @@
 analyzer/test/*: PubGetError
 
 [ $compiler == dart2js && $cps_ir ]
-analyzer_cli/test/error_test: Crash # (try {return fn(tempDir);}finally {new Directory(tempDir).deleteSync(recursive:true);}): try/finally
-analyzer_cli/test/options_test: Crash #  try/finally
-analysis_server/tool/spec/check_all_test: Crash #  Unhandled node
-analyzer/test/cancelable_future_test: Crash # (try {test(spec,body);}finally {environment.soloNestingLevel-- ;}): try/finally
-analyzer/test/enum_test: Crash # (try {test(spec,body);}finally {environment.soloNestingLevel-- ;}): try/finally
-analyzer/test/file_system/memory_file_system_test: Crash # (try {test(spec,body);}finally {environment.soloNestingLevel-- ;}): try/finally
-analyzer/test/file_system/physical_resource_provider_test: Crash # (try {test(spec,body);}finally {environment.soloNestingLevel-- ;}): try/finally
-analyzer/test/file_system/resource_uri_resolver_test: Crash # (try {test(spec,body);}finally {environment.soloNestingLevel-- ;}): try/finally
-analyzer/test/generated/all_the_rest_test: Crash #  try/finally
-analyzer/test/generated/ast_test: Crash # (try {test(spec,body);}finally {environment.soloNestingLevel-- ;}): try/finally
-analyzer/test/generated/compile_time_error_code_test: Crash # (try {test(spec,body);}finally {environment.soloNestingLevel-- ;}): try/finally
-analyzer/test/generated/element_test: Crash # (try {test(spec,body);}finally {environment.soloNestingLevel-- ;}): try/finally
-analyzer/test/generated/incremental_resolver_test: Crash # (try {test(spec,body);}finally {environment.soloNestingLevel-- ;}): try/finally
-analyzer/test/generated/incremental_scanner_test: Crash # (try {test(spec,body);}finally {environment.soloNestingLevel-- ;}): try/finally
-analyzer/test/generated/java_core_test: Crash #  try/finally
-analyzer/test/generated/java_io_test: Crash #  try/finally
-analyzer/test/generated/non_error_resolver_test: Crash # (try {test(spec,body);}finally {environment.soloNestingLevel-- ;}): try/finally
-analyzer/test/generated/parser_test: Crash # (try {test(spec,body);}finally {environment.soloNestingLevel-- ;}): try/finally
-analyzer/test/generated/resolver_test: Crash # (try {test(spec,body);}finally {environment.soloNestingLevel-- ;}): try/finally
-analyzer/test/generated/scanner_test: Crash # (try {test(spec,body);}finally {environment.soloNestingLevel-- ;}): try/finally
-analyzer/test/generated/static_type_warning_code_test: Crash # (try {test(spec,body);}finally {environment.soloNestingLevel-- ;}): try/finally
-analyzer/test/generated/static_warning_code_test: Crash # (try {test(spec,body);}finally {environment.soloNestingLevel-- ;}): try/finally
-analyzer/test/generated/utilities_test: Crash # (try {test(spec,body);}finally {environment.soloNestingLevel-- ;}): try/finally
-analyzer/test/instrumentation/instrumentation_test: Crash #  try/finally
-analyzer/test/parse_compilation_unit_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-analyzer/test/source/package_map_provider_test: Crash #  try/finally
-analyzer/test/source/package_map_resolver_test: Crash # (try {test(spec,body);}finally {environment.soloNestingLevel-- ;}): try/finally
-analyzer/test/src/context/cache_test: Crash #  try/finally
-analyzer/test/src/context/context_test: Crash #  try/finally
-analyzer/test/src/task/dart_test: Crash # (try {test(spec,body);}finally {environment.soloNestingLevel-- ;}): try/finally
-analyzer/test/src/task/dart_work_manager_test: Crash #  try/finally
-analyzer/test/src/task/driver_test: Crash #  try/finally
-analyzer/test/src/task/general_test: Crash #  try/finally
-analyzer/test/src/task/incremental_element_builder_test: Crash # (try {test(spec,body);}finally {environment.soloNestingLevel-- ;}): try/finally
-analyzer/test/src/task/inputs_test: Crash # (try {test(spec,body);}finally {environment.soloNestingLevel-- ;}): try/finally
-analyzer/test/src/task/manager_test: Crash # (try {test(spec,body);}finally {environment.soloNestingLevel-- ;}): try/finally
-analyzer/test/src/task/model_test: Crash # (try {test(spec,body);}finally {environment.soloNestingLevel-- ;}): try/finally
-analyzer/test/src/util/asserts_test: Crash # (try {test(spec,body);}finally {environment.soloNestingLevel-- ;}): try/finally
-analyzer/test/src/util/lru_map_test: Crash # (try {test(spec,body);}finally {environment.soloNestingLevel-- ;}): try/finally
-fixnum/test/int_32_test: Crash #  try/finally
-fixnum/test/int_64_test: Crash #  try/finally
-js_ast/test/printer_callback_test: Crash #  Unhandled node
-typed_data/test/typed_buffers_test/01: Crash # Instance of 'TypeOperator': type casts not implemented.
-typed_data/test/typed_buffers_test/none: Crash # Instance of 'TypeOperator': type casts not implemented.
-typed_mock/test/typed_mock_test: Crash #  try/finally
+analysis_server/tool/spec/check_all_test: Crash # Invalid argument(s)
+analyzer/test/cancelable_future_test: Crash # Invalid argument(s)
+analyzer/test/enum_test: Crash # Invalid argument(s)
+analyzer/test/file_system/memory_file_system_test: Crash # Invalid argument(s)
+analyzer/test/file_system/physical_resource_provider_test: Crash # Invalid argument(s)
+analyzer/test/file_system/resource_uri_resolver_test: Crash # Invalid argument(s)
+analyzer/test/generated/all_the_rest_test: Crash # Invalid argument(s)
+analyzer/test/generated/ast_test: Crash # Invalid argument(s)
+analyzer/test/generated/compile_time_error_code_test: Crash # Invalid argument(s)
+analyzer/test/generated/element_test: Crash # Invalid argument(s)
+analyzer/test/generated/incremental_resolver_test: Crash # Invalid argument(s)
+analyzer/test/generated/incremental_scanner_test: Crash # Invalid argument(s)
+analyzer/test/generated/java_core_test: Crash # Invalid argument(s)
+analyzer/test/generated/java_io_test: Crash # Invalid argument(s)
+analyzer/test/generated/non_error_resolver_test: Crash # Invalid argument(s)
+analyzer/test/generated/parser_test: Crash # Invalid argument(s)
+analyzer/test/generated/resolver_test: Crash # Invalid argument(s)
+analyzer/test/generated/scanner_test: Crash # Invalid argument(s)
+analyzer/test/generated/static_type_warning_code_test: Crash # Invalid argument(s)
+analyzer/test/generated/static_warning_code_test: Crash # Invalid argument(s)
+analyzer/test/generated/type_system_test: Crash # Invalid argument(s)
+analyzer/test/generated/utilities_test: Crash # Invalid argument(s)
+analyzer/test/instrumentation/instrumentation_test: Crash # Invalid argument(s)
+analyzer/test/parse_compilation_unit_test: Crash # Invalid argument(s)
+analyzer/test/source/package_map_provider_test: Crash # Invalid argument(s)
+analyzer/test/source/package_map_resolver_test: Crash # Invalid argument(s)
+analyzer/test/src/context/cache_test: Crash # Invalid argument(s)
+analyzer/test/src/context/context_test: Crash # Invalid argument(s)
+analyzer/test/src/task/dart_test: Crash # Invalid argument(s)
+analyzer/test/src/task/dart_work_manager_test: Crash # Invalid argument(s)
+analyzer/test/src/task/driver_test: Crash # Invalid argument(s)
+analyzer/test/src/task/general_test: Crash # Invalid argument(s)
+analyzer/test/src/task/html_test: Crash # Invalid argument(s)
+analyzer/test/src/task/html_work_manager_test: Crash # Invalid argument(s)
+analyzer/test/src/task/incremental_element_builder_test: Crash # Invalid argument(s)
+analyzer/test/src/task/inputs_test: Crash # Invalid argument(s)
+analyzer/test/src/task/manager_test: Crash # Invalid argument(s)
+analyzer/test/src/task/model_test: Crash # Invalid argument(s)
+analyzer/test/src/util/asserts_test: Crash # Invalid argument(s)
+analyzer/test/src/util/lru_map_test: Crash # Invalid argument(s)
+fixnum/test/int_32_test: Crash # Invalid argument(s)
+fixnum/test/int_64_test: Crash # Invalid argument(s)
+js_ast/test/printer_callback_test: RuntimeError # Please triage this failure.
+microlytics/test/dart_microlytics_test: RuntimeError # Please triage this failure.
+typed_data/test/typed_buffers_test/01: Crash # Invalid argument(s)
+typed_data/test/typed_buffers_test/none: Crash # Invalid argument(s)
+typed_mock/test/typed_mock_test: Crash # Invalid argument(s)
diff --git a/pkg/pkg_files.gyp b/pkg/pkg_files.gyp
index 14653b2..78a751f 100644
--- a/pkg/pkg_files.gyp
+++ b/pkg/pkg_files.gyp
@@ -31,7 +31,8 @@
           'action_name': 'make_third_party_pkg_files_stamp',
           'inputs': [
             '../tools/create_timestamp_file.py',
-            '<!@(["python", "../tools/list_files.py", "\\.dart$",'
+            '<!@(["python", "../tools/list_files.py",'
+                '"^(?!.*_test.dart).*dart$",'
                 '"../third_party/pkg"])',
           ],
           'outputs': [
diff --git a/runtime/BUILD.gn b/runtime/BUILD.gn
index ad90805..e9c339a 100644
--- a/runtime/BUILD.gn
+++ b/runtime/BUILD.gn
@@ -68,9 +68,9 @@
   ]
   sources = [
     "include/dart_api.h",
-    "include/dart_debugger_api.h",
     "include/dart_mirrors_api.h",
     "include/dart_native_api.h",
+    "include/dart_tools_api.h",
     "vm/dart_api_impl.cc",
     "vm/debugger_api_impl.cc",
     "vm/mirrors_api_impl.cc",
diff --git a/runtime/bin/BUILD.gn b/runtime/bin/BUILD.gn
index a7604ff..2ee4114 100644
--- a/runtime/bin/BUILD.gn
+++ b/runtime/bin/BUILD.gn
@@ -120,9 +120,9 @@
 
   sources = [
     "../include/dart_api.h",
-    "../include/dart_debugger_api.h",
     "../include/dart_mirrors_api.h",
     "../include/dart_native_api.h",
+    "../include/dart_tools_api.h",
     "../vm/dart_api_impl.cc",
     "../vm/debugger_api_impl.cc",
     "../vm/mirrors_api_impl.cc",
@@ -208,7 +208,7 @@
     "builtin.cc",
     "builtin_gen_snapshot.cc",
   ]
-  if (!is_mac) {
+  if (!is_mac && !is_ios) {
     # Dart tree uses *_macos.* instead of *_mac.*
     custom_sources_filter += [
       "*_macos.h",
diff --git a/runtime/bin/bin.gypi b/runtime/bin/bin.gypi
index 51437ef..7caf19b 100644
--- a/runtime/bin/bin.gypi
+++ b/runtime/bin/bin.gypi
@@ -362,9 +362,9 @@
       ],
       'sources': [
         '../include/dart_api.h',
-        '../include/dart_debugger_api.h',
         '../include/dart_mirrors_api.h',
         '../include/dart_native_api.h',
+        '../include/dart_tools_api.h',
         '../vm/dart_api_impl.cc',
         '../vm/debugger_api_impl.cc',
         '../vm/mirrors_api_impl.cc',
diff --git a/runtime/bin/dartutils.cc b/runtime/bin/dartutils.cc
index c443fc9..11c5f5b4 100644
--- a/runtime/bin/dartutils.cc
+++ b/runtime/bin/dartutils.cc
@@ -5,6 +5,7 @@
 #include "bin/dartutils.h"
 
 #include "include/dart_api.h"
+#include "include/dart_tools_api.h"
 #include "include/dart_native_api.h"
 
 #include "platform/assert.h"
@@ -15,6 +16,7 @@
 #include "bin/extensions.h"
 #include "bin/file.h"
 #include "bin/io_buffer.h"
+#include "bin/isolate_data.h"
 #include "bin/platform.h"
 #include "bin/socket.h"
 #include "bin/utils.h"
@@ -486,7 +488,9 @@
     return NewDartUnsupportedError("Service did not return load port.");
   }
   Builtin::SetLoadPort(load_port);
-
+  IsolateData* isolate_data =
+      reinterpret_cast<IsolateData*>(Dart_CurrentIsolateData());
+  Dart_TimelineAsyncBegin("LoadScript", &(isolate_data->load_async_id));
   return LoadDataAsync_Invoke(Dart_Null(), uri, Dart_Null(), builtin_lib);
 }
 
@@ -591,6 +595,11 @@
 // no more outstanding load requests.
 void FUNCTION_NAME(Builtin_DoneLoading)(Dart_NativeArguments args) {
   Dart_Handle res = Dart_FinalizeLoading(true);
+  IsolateData* isolate_data =
+      reinterpret_cast<IsolateData*>(Dart_CurrentIsolateData());
+  if (isolate_data->load_async_id >= 0) {
+    Dart_TimelineAsyncEnd("LoadScript", isolate_data->load_async_id);
+  }
   if (Dart_IsError(res)) {
     // TODO(hausner): If compilation/loading errors are supposed to
     // be observable by the program, we need to mark the bad library
diff --git a/runtime/bin/dbg_connection.h b/runtime/bin/dbg_connection.h
index d7941f0..bd4f4dd 100644
--- a/runtime/bin/dbg_connection.h
+++ b/runtime/bin/dbg_connection.h
@@ -8,7 +8,7 @@
 #include "bin/builtin.h"
 #include "bin/utils.h"
 
-#include "include/dart_debugger_api.h"
+#include "include/dart_tools_api.h"
 
 #include "platform/globals.h"
 #include "platform/json.h"
diff --git a/runtime/bin/dbg_message.cc b/runtime/bin/dbg_message.cc
index 1d8c22c..a635880 100644
--- a/runtime/bin/dbg_message.cc
+++ b/runtime/bin/dbg_message.cc
@@ -1409,14 +1409,15 @@
     msg_queue->SendIsolateEvent(isolate_id, kind);
   } else {
     DbgMsgQueue* msg_queue = GetIsolateMsgQueue(isolate_id);
-    ASSERT(msg_queue != NULL);
-    msg_queue->SendQueuedMsgs();
-    msg_queue->SendIsolateEvent(isolate_id, kind);
-    if (kind == kInterrupted) {
-      msg_queue->MessageLoop();
-    } else {
-      ASSERT(kind == kShutdown);
-      RemoveIsolateMsgQueue(isolate_id);
+    if (msg_queue != NULL) {
+      msg_queue->SendQueuedMsgs();
+      msg_queue->SendIsolateEvent(isolate_id, kind);
+      if (kind == kInterrupted) {
+        msg_queue->MessageLoop();
+      } else {
+        ASSERT(kind == kShutdown);
+        RemoveIsolateMsgQueue(isolate_id);
+      }
     }
   }
   Dart_ExitScope();
diff --git a/runtime/bin/dbg_message.h b/runtime/bin/dbg_message.h
index bce9106..0714174 100644
--- a/runtime/bin/dbg_message.h
+++ b/runtime/bin/dbg_message.h
@@ -9,7 +9,7 @@
 #include "bin/thread.h"
 #include "bin/utils.h"
 
-#include "include/dart_debugger_api.h"
+#include "include/dart_tools_api.h"
 
 #include "platform/globals.h"
 #include "platform/json.h"
diff --git a/runtime/bin/directory_win.cc b/runtime/bin/directory_win.cc
index e7cd895..40bfb9b 100644
--- a/runtime/bin/directory_win.cc
+++ b/runtime/bin/directory_win.cc
@@ -8,6 +8,7 @@
 #include "bin/directory.h"
 #include "bin/file.h"
 #include "bin/utils.h"
+#include "bin/utils_win.h"
 
 #include <errno.h>  // NOLINT
 #include <sys/stat.h>  // NOLINT
@@ -26,7 +27,7 @@
 }
 
 char* PathBuffer::AsString() const {
-  return StringUtils::WideToUtf8(AsStringW());
+  return StringUtilsWin::WideToUtf8(AsStringW());
 }
 
 wchar_t* PathBuffer::AsStringW() const {
@@ -34,7 +35,7 @@
 }
 
 bool PathBuffer::Add(const char* name) {
-  const wchar_t* wide_name = StringUtils::Utf8ToWide(name);
+  const wchar_t* wide_name = StringUtilsWin::Utf8ToWide(name);
   bool success = AddW(wide_name);
   free(const_cast<wchar_t*>(wide_name));
   return success;
@@ -352,7 +353,7 @@
 
 
 Directory::ExistsResult Directory::Exists(const char* dir_name) {
-  const wchar_t* system_name = StringUtils::Utf8ToWide(dir_name);
+  const wchar_t* system_name = StringUtilsWin::Utf8ToWide(dir_name);
   Directory::ExistsResult result = ExistsHelper(system_name);
   free(const_cast<wchar_t*>(system_name));
   return result;
@@ -364,14 +365,14 @@
   if (length == 0) return NULL;
   wchar_t* current = new wchar_t[length + 1];
   GetCurrentDirectoryW(length + 1, current);
-  char* result = StringUtils::WideToUtf8(current);
+  char* result = StringUtilsWin::WideToUtf8(current);
   delete[] current;
   return result;
 }
 
 
 bool Directory::SetCurrent(const char* path) {
-  const wchar_t* system_path = StringUtils::Utf8ToWide(path);
+  const wchar_t* system_path = StringUtilsWin::Utf8ToWide(path);
   bool result = SetCurrentDirectoryW(system_path) != 0;
   free(const_cast<wchar_t*>(system_path));
   return result;
@@ -379,7 +380,7 @@
 
 
 bool Directory::Create(const char* dir_name) {
-  const wchar_t* system_name = StringUtils::Utf8ToWide(dir_name);
+  const wchar_t* system_name = StringUtilsWin::Utf8ToWide(dir_name);
   int create_status = CreateDirectoryW(system_name, NULL);
   // If the directory already existed, treat it as a success.
   if (create_status == 0 &&
@@ -408,7 +409,7 @@
   // descriptor inherited from its parent directory.
   // The return value must be freed by the caller.
   PathBuffer path;
-  const wchar_t* system_prefix = StringUtils::Utf8ToWide(prefix);
+  const wchar_t* system_prefix = StringUtilsWin::Utf8ToWide(prefix);
   path.AddW(system_prefix);
   free(const_cast<wchar_t*>(system_prefix));
 
@@ -441,7 +442,7 @@
 
 bool Directory::Delete(const char* dir_name, bool recursive) {
   bool result = false;
-  const wchar_t* system_dir_name = StringUtils::Utf8ToWide(dir_name);
+  const wchar_t* system_dir_name = StringUtilsWin::Utf8ToWide(dir_name);
   if (!recursive) {
     if (File::GetType(dir_name, true) == File::kIsDirectory) {
       result = (RemoveDirectoryW(system_dir_name) != 0);
@@ -460,8 +461,8 @@
 
 
 bool Directory::Rename(const char* path, const char* new_path) {
-  const wchar_t* system_path = StringUtils::Utf8ToWide(path);
-  const wchar_t* system_new_path = StringUtils::Utf8ToWide(new_path);
+  const wchar_t* system_path = StringUtilsWin::Utf8ToWide(path);
+  const wchar_t* system_new_path = StringUtilsWin::Utf8ToWide(new_path);
   ExistsResult exists = ExistsHelper(system_path);
   if (exists != EXISTS) return false;
   ExistsResult new_exists = ExistsHelper(system_new_path);
diff --git a/runtime/bin/extensions_win.cc b/runtime/bin/extensions_win.cc
index dea586c..63462ee 100644
--- a/runtime/bin/extensions_win.cc
+++ b/runtime/bin/extensions_win.cc
@@ -7,13 +7,14 @@
 
 #include "bin/extensions.h"
 #include "bin/utils.h"
+#include "bin/utils_win.h"
 
 
 namespace dart {
 namespace bin {
 
 void* Extensions::LoadExtensionLibrary(const char* library_file) {
-  return LoadLibraryW(StringUtils::Utf8ToWide(library_file));
+  return LoadLibraryW(StringUtilsWin::Utf8ToWide(library_file));
 }
 
 void* Extensions::ResolveSymbol(void* lib_handle, const char* symbol) {
diff --git a/runtime/bin/file.cc b/runtime/bin/file.cc
index 15088ca..59f8300 100644
--- a/runtime/bin/file.cc
+++ b/runtime/bin/file.cc
@@ -59,13 +59,21 @@
 File::FileOpenMode File::DartModeToFileMode(DartFileOpenMode mode) {
   ASSERT(mode == File::kDartRead ||
          mode == File::kDartWrite ||
-         mode == File::kDartAppend);
+         mode == File::kDartAppend ||
+         mode == File::kDartWriteOnly ||
+         mode == File::kDartWriteOnlyAppend);
   if (mode == File::kDartWrite) {
     return File::kWriteTruncate;
   }
   if (mode == File::kDartAppend) {
     return File::kWrite;
   }
+  if (mode == File::kDartWriteOnly) {
+    return File::kWriteOnlyTruncate;
+  }
+  if (mode == File::kDartWriteOnlyAppend) {
+    return File::kWriteOnly;
+  }
   return File::kRead;
 }
 
diff --git a/runtime/bin/file.h b/runtime/bin/file.h
index 7a8107f..633c006 100644
--- a/runtime/bin/file.h
+++ b/runtime/bin/file.h
@@ -26,15 +26,20 @@
     kRead = 0,
     kWrite = 1,
     kTruncate = 1 << 2,
-    kWriteTruncate = kWrite | kTruncate
+    kWriteOnly = 1 << 3,
+    kWriteTruncate = kWrite | kTruncate,
+    kWriteOnlyTruncate = kWriteOnly | kTruncate
   };
 
   // These values have to be kept in sync with the mode values of
-  // FileMode.READ, FileMode.WRITE and FileMode.APPEND in file.dart.
+  // FileMode.READ, FileMode.WRITE, FileMode.APPEND,
+  // FileMode.WRITE_ONLY and FileMode.WRITE_ONLY_APPEND in file.dart.
   enum DartFileOpenMode {
     kDartRead = 0,
     kDartWrite = 1,
-    kDartAppend = 2
+    kDartAppend = 2,
+    kDartWriteOnly = 3,
+    kDartWriteOnlyAppend = 4
   };
 
   enum Type {
diff --git a/runtime/bin/file_android.cc b/runtime/bin/file_android.cc
index 015fc0a..35b6388 100644
--- a/runtime/bin/file_android.cc
+++ b/runtime/bin/file_android.cc
@@ -158,8 +158,13 @@
   }
   int flags = O_RDONLY;
   if ((mode & kWrite) != 0) {
+    ASSERT((mode & kWriteOnly) == 0);
     flags = (O_RDWR | O_CREAT);
   }
+  if ((mode & kWriteOnly) != 0) {
+    ASSERT((mode & kWrite) == 0);
+    flags = (O_WRONLY | O_CREAT);
+  }
   if ((mode & kTruncate) != 0) {
     flags = flags | O_TRUNC;
   }
@@ -168,7 +173,8 @@
   if (fd < 0) {
     return NULL;
   }
-  if (((mode & kWrite) != 0) && ((mode & kTruncate) == 0)) {
+  if ((((mode & kWrite) != 0) && ((mode & kTruncate) == 0)) ||
+      (((mode & kWriteOnly) != 0) && ((mode & kTruncate) == 0))) {
     int64_t position = lseek64(fd, 0, SEEK_END);
     if (position < 0) {
       return NULL;
diff --git a/runtime/bin/file_linux.cc b/runtime/bin/file_linux.cc
index 0a437f1..ff801ad 100644
--- a/runtime/bin/file_linux.cc
+++ b/runtime/bin/file_linux.cc
@@ -157,8 +157,13 @@
   }
   int flags = O_RDONLY;
   if ((mode & kWrite) != 0) {
+    ASSERT((mode & kWriteOnly) == 0);
     flags = (O_RDWR | O_CREAT);
   }
+  if ((mode & kWriteOnly) != 0) {
+    ASSERT((mode & kWrite) == 0);
+    flags = (O_WRONLY | O_CREAT);
+  }
   if ((mode & kTruncate) != 0) {
     flags = flags | O_TRUNC;
   }
@@ -167,7 +172,8 @@
   if (fd < 0) {
     return NULL;
   }
-  if (((mode & kWrite) != 0) && ((mode & kTruncate) == 0)) {
+  if ((((mode & kWrite) != 0) && ((mode & kTruncate) == 0)) ||
+      (((mode & kWriteOnly) != 0) && ((mode & kTruncate) == 0))) {
     int64_t position = NO_RETRY_EXPECTED(lseek64(fd, 0, SEEK_END));
     if (position < 0) {
       return NULL;
diff --git a/runtime/bin/file_macos.cc b/runtime/bin/file_macos.cc
index 9fc33c5..ddc19cc 100644
--- a/runtime/bin/file_macos.cc
+++ b/runtime/bin/file_macos.cc
@@ -159,8 +159,13 @@
   }
   int flags = O_RDONLY;
   if ((mode & kWrite) != 0) {
+    ASSERT((mode & kWriteOnly) == 0);
     flags = (O_RDWR | O_CREAT);
   }
+  if ((mode & kWriteOnly) != 0) {
+    ASSERT((mode & kWrite) == 0);
+    flags = (O_WRONLY | O_CREAT);
+  }
   if ((mode & kTruncate) != 0) {
     flags = flags | O_TRUNC;
   }
@@ -169,7 +174,8 @@
     return NULL;
   }
   FDUtils::SetCloseOnExec(fd);
-  if (((mode & kWrite) != 0) && ((mode & kTruncate) == 0)) {
+  if ((((mode & kWrite) != 0) && ((mode & kTruncate) == 0)) ||
+      (((mode & kWriteOnly) != 0) && ((mode & kTruncate) == 0))) {
     int64_t position = lseek(fd, 0, SEEK_END);
     if (position < 0) {
       return NULL;
diff --git a/runtime/bin/file_system_watcher_macos.cc b/runtime/bin/file_system_watcher_macos.cc
index 2e24122..fbecffa5 100644
--- a/runtime/bin/file_system_watcher_macos.cc
+++ b/runtime/bin/file_system_watcher_macos.cc
@@ -7,6 +7,8 @@
 
 #include "bin/file_system_watcher.h"
 
+#if !defined(TARGET_OS_IOS)
+
 #include <errno.h>  // NOLINT
 #include <fcntl.h>  // NOLINT
 #include <unistd.h>  // NOLINT
@@ -392,4 +394,44 @@
 }  // namespace bin
 }  // namespace dart
 
+#else  // !defined(TARGET_OS_IOS)
+
+namespace dart {
+namespace bin {
+
+// FSEvents are unavailable on iOS. Stub out related methods
+Dart_Handle FileSystemWatcher::ReadEvents(intptr_t id, intptr_t path_id) {
+  return DartUtils::NewDartOSError();
+}
+
+intptr_t FileSystemWatcher::GetSocketId(intptr_t id, intptr_t path_id) {
+  return -1;
+}
+
+bool FileSystemWatcher::IsSupported() {
+  return false;
+}
+
+void FileSystemWatcher::UnwatchPath(intptr_t id, intptr_t path_id) {
+}
+
+intptr_t FileSystemWatcher::Init() {
+  return -1;
+}
+
+void FileSystemWatcher::Close(intptr_t id) {
+}
+
+intptr_t FileSystemWatcher::WatchPath(intptr_t id,
+                                      const char* path,
+                                      int events,
+                                      bool recursive) {
+  return -1;
+}
+
+}  // namespace bin
+}  // namespace dart
+
+#endif  // !defined(TARGET_OS_IOS)
+
 #endif  // defined(TARGET_OS_MACOS)
diff --git a/runtime/bin/file_system_watcher_win.cc b/runtime/bin/file_system_watcher_win.cc
index f0b71f1..98642ab 100644
--- a/runtime/bin/file_system_watcher_win.cc
+++ b/runtime/bin/file_system_watcher_win.cc
@@ -13,6 +13,7 @@
 #include "bin/builtin.h"
 #include "bin/log.h"
 #include "bin/utils.h"
+#include "bin/utils_win.h"
 
 
 namespace dart {
@@ -38,7 +39,7 @@
                                       int events,
                                       bool recursive) {
   USE(id);
-  const wchar_t* name = StringUtils::Utf8ToWide(path);
+  const wchar_t* name = StringUtilsWin::Utf8ToWide(path);
   HANDLE dir = CreateFileW(name,
                            FILE_LIST_DIRECTORY,
                            FILE_SHARE_READ |
diff --git a/runtime/bin/file_win.cc b/runtime/bin/file_win.cc
index 67b97f5..8ba4a30 100644
--- a/runtime/bin/file_win.cc
+++ b/runtime/bin/file_win.cc
@@ -17,6 +17,7 @@
 #include "bin/builtin.h"
 #include "bin/log.h"
 #include "bin/utils.h"
+#include "bin/utils_win.h"
 #include "platform/utils.h"
 
 
@@ -157,18 +158,24 @@
 File* File::Open(const char* name, FileOpenMode mode) {
   int flags = O_RDONLY | O_BINARY | O_NOINHERIT;
   if ((mode & kWrite) != 0) {
+    ASSERT((mode & kWriteOnly) == 0);
     flags = (O_RDWR | O_CREAT | O_BINARY | O_NOINHERIT);
   }
+  if ((mode & kWriteOnly) != 0) {
+    ASSERT((mode & kWrite) == 0);
+    flags = (O_WRONLY | O_CREAT | O_BINARY | O_NOINHERIT);
+  }
   if ((mode & kTruncate) != 0) {
     flags = flags | O_TRUNC;
   }
-  const wchar_t* system_name = StringUtils::Utf8ToWide(name);
+  const wchar_t* system_name = StringUtilsWin::Utf8ToWide(name);
   int fd = _wopen(system_name, flags, 0666);
   free(const_cast<wchar_t*>(system_name));
   if (fd < 0) {
     return NULL;
   }
-  if (((mode & kWrite) != 0) && ((mode & kTruncate) == 0)) {
+  if ((((mode & kWrite) != 0) && ((mode & kTruncate) == 0)) ||
+      (((mode & kWriteOnly) != 0) && ((mode & kTruncate) == 0))) {
     int64_t position = _lseeki64(fd, 0, SEEK_END);
     if (position < 0) {
       return NULL;
@@ -195,7 +202,7 @@
 
 bool File::Exists(const char* name) {
   struct __stat64 st;
-  const wchar_t* system_name = StringUtils::Utf8ToWide(name);
+  const wchar_t* system_name = StringUtilsWin::Utf8ToWide(name);
   bool stat_status = _wstat64(system_name, &st);
   free(const_cast<wchar_t*>(system_name));
   if (stat_status == 0) {
@@ -207,7 +214,7 @@
 
 
 bool File::Create(const char* name) {
-  const wchar_t* system_name = StringUtils::Utf8ToWide(name);
+  const wchar_t* system_name = StringUtilsWin::Utf8ToWide(name);
   int fd = _wopen(system_name, O_RDONLY | O_CREAT, 0666);
   free(const_cast<wchar_t*>(system_name));
   if (fd < 0) {
@@ -253,7 +260,7 @@
 
 
 bool File::CreateLink(const char* utf8_name, const char* utf8_target) {
-  const wchar_t* name = StringUtils::Utf8ToWide(utf8_name);
+  const wchar_t* name = StringUtilsWin::Utf8ToWide(utf8_name);
   int create_status = CreateDirectoryW(name, NULL);
   // If the directory already existed, treat it as a success.
   if (create_status == 0 &&
@@ -276,7 +283,7 @@
     return false;
   }
 
-  const wchar_t* target = StringUtils::Utf8ToWide(utf8_target);
+  const wchar_t* target = StringUtilsWin::Utf8ToWide(utf8_target);
   int target_len = wcslen(target);
   if (target_len > MAX_PATH - 1) {
     free(const_cast<wchar_t*>(target));
@@ -320,7 +327,7 @@
 
 
 bool File::Delete(const char* name) {
-  const wchar_t* system_name = StringUtils::Utf8ToWide(name);
+  const wchar_t* system_name = StringUtilsWin::Utf8ToWide(name);
   int status = _wremove(system_name);
   free(const_cast<wchar_t*>(system_name));
   return status != -1;
@@ -328,7 +335,7 @@
 
 
 bool File::DeleteLink(const char* name) {
-  const wchar_t* system_name = StringUtils::Utf8ToWide(name);
+  const wchar_t* system_name = StringUtilsWin::Utf8ToWide(name);
   bool result = false;
   DWORD attributes = GetFileAttributesW(system_name);
   if ((attributes != INVALID_FILE_ATTRIBUTES) &&
@@ -346,8 +353,8 @@
 bool File::Rename(const char* old_path, const char* new_path) {
   File::Type type = GetType(old_path, false);
   if (type == kIsFile) {
-    const wchar_t* system_old_path = StringUtils::Utf8ToWide(old_path);
-    const wchar_t* system_new_path = StringUtils::Utf8ToWide(new_path);
+    const wchar_t* system_old_path = StringUtilsWin::Utf8ToWide(old_path);
+    const wchar_t* system_new_path = StringUtilsWin::Utf8ToWide(new_path);
     DWORD flags = MOVEFILE_WRITE_THROUGH | MOVEFILE_REPLACE_EXISTING;
     int move_status =
         MoveFileExW(system_old_path, system_new_path, flags);
@@ -364,8 +371,8 @@
 bool File::RenameLink(const char* old_path, const char* new_path) {
   File::Type type = GetType(old_path, false);
   if (type == kIsLink) {
-    const wchar_t* system_old_path = StringUtils::Utf8ToWide(old_path);
-    const wchar_t* system_new_path = StringUtils::Utf8ToWide(new_path);
+    const wchar_t* system_old_path = StringUtilsWin::Utf8ToWide(old_path);
+    const wchar_t* system_new_path = StringUtilsWin::Utf8ToWide(new_path);
     DWORD flags = MOVEFILE_WRITE_THROUGH | MOVEFILE_REPLACE_EXISTING;
     int move_status =
         MoveFileExW(system_old_path, system_new_path, flags);
@@ -382,8 +389,8 @@
 bool File::Copy(const char* old_path, const char* new_path) {
   File::Type type = GetType(old_path, false);
   if (type == kIsFile) {
-    const wchar_t* system_old_path = StringUtils::Utf8ToWide(old_path);
-    const wchar_t* system_new_path = StringUtils::Utf8ToWide(new_path);
+    const wchar_t* system_old_path = StringUtilsWin::Utf8ToWide(old_path);
+    const wchar_t* system_new_path = StringUtilsWin::Utf8ToWide(new_path);
     bool success = CopyFileExW(system_old_path,
                                system_new_path,
                                NULL,
@@ -402,7 +409,7 @@
 
 int64_t File::LengthFromPath(const char* name) {
   struct __stat64 st;
-  const wchar_t* system_name = StringUtils::Utf8ToWide(name);
+  const wchar_t* system_name = StringUtilsWin::Utf8ToWide(name);
   int stat_status = _wstat64(system_name, &st);
   free(const_cast<wchar_t*>(system_name));
   if (stat_status == 0) {
@@ -413,7 +420,7 @@
 
 
 char* File::LinkTarget(const char* pathname) {
-  const wchar_t* name = StringUtils::Utf8ToWide(pathname);
+  const wchar_t* name = StringUtilsWin::Utf8ToWide(pathname);
   HANDLE dir_handle = CreateFileW(
       name,
       GENERIC_READ,
@@ -510,7 +517,7 @@
   data[kType] = type;
   if (type != kDoesNotExist) {
     struct _stat64 st;
-    const wchar_t* system_name = StringUtils::Utf8ToWide(name);
+    const wchar_t* system_name = StringUtilsWin::Utf8ToWide(name);
     int stat_status = _wstat64(system_name, &st);
     free(const_cast<wchar_t*>(system_name));
     if (stat_status == 0) {
@@ -528,7 +535,7 @@
 
 time_t File::LastModified(const char* name) {
   struct __stat64 st;
-  const wchar_t* system_name = StringUtils::Utf8ToWide(name);
+  const wchar_t* system_name = StringUtilsWin::Utf8ToWide(name);
   int stat_status = _wstat64(system_name, &st);
   free(const_cast<wchar_t*>(system_name));
   if (stat_status == 0) {
@@ -548,7 +555,7 @@
 
 
 char* File::GetCanonicalPath(const char* pathname) {
-  const wchar_t* system_name = StringUtils::Utf8ToWide(pathname);
+  const wchar_t* system_name = StringUtilsWin::Utf8ToWide(pathname);
   HANDLE file_handle = CreateFileW(
         system_name,
         0,
@@ -586,9 +593,9 @@
       result_size > 4 &&
       wcsncmp(path, L"\\\\?\\", 4) == 0 &&
       wcsncmp(system_name, L"\\\\?\\", 4) != 0) {
-    result = StringUtils::WideToUtf8(path + 4);
+    result = StringUtilsWin::WideToUtf8(path + 4);
   } else {
-    result = StringUtils::WideToUtf8(path);
+    result = StringUtilsWin::WideToUtf8(path);
   }
   free(const_cast<wchar_t*>(system_name));
   free(path);
@@ -617,7 +624,7 @@
 
 
 File::Type File::GetType(const char* pathname, bool follow_links) {
-  const wchar_t* name = StringUtils::Utf8ToWide(pathname);
+  const wchar_t* name = StringUtilsWin::Utf8ToWide(pathname);
   DWORD attributes = GetFileAttributesW(name);
   File::Type result = kIsFile;
   if (attributes == INVALID_FILE_ATTRIBUTES) {
@@ -653,7 +660,7 @@
   BY_HANDLE_FILE_INFORMATION file_info[2];
   const char* file_names[2] = { file_1, file_2 };
   for (int i = 0; i < 2; ++i) {
-    const wchar_t* wide_name = StringUtils::Utf8ToWide(file_names[i]);
+    const wchar_t* wide_name = StringUtilsWin::Utf8ToWide(file_names[i]);
     HANDLE file_handle = CreateFileW(
         wide_name,
         0,
diff --git a/runtime/bin/gen_snapshot.cc b/runtime/bin/gen_snapshot.cc
index 1aaf192..0b69d91 100644
--- a/runtime/bin/gen_snapshot.cc
+++ b/runtime/bin/gen_snapshot.cc
@@ -335,8 +335,8 @@
   }
 
   Builtin::BuiltinLibraryId builtinId = BuiltinId(url_string);
-  if (builtinId != Builtin::kInvalidLibrary) {
-    // Special case for importing a builtin library.
+  if ((builtinId != Builtin::kInvalidLibrary) && (mapped_url_string == NULL)) {
+    // Special case for importing a builtin library that isn't remapped.
     if (tag == Dart_kImportTag) {
       return Builtin::LoadLibrary(url, builtinId);
     }
@@ -516,7 +516,7 @@
 
 
 int main(int argc, char** argv) {
-  const int EXTRA_VM_ARGUMENTS = 1;
+  const int EXTRA_VM_ARGUMENTS = 2;
   CommandLineOptions vm_options(argc + EXTRA_VM_ARGUMENTS);
 
   // Initialize the URL mapping array.
@@ -536,7 +536,9 @@
   DartUtils::SetOriginalWorkingDirectory();
 
   vm_options.AddArgument("--load_deferred_eagerly");
-
+  // Workaround until issue 21620 is fixed.
+  // (https://github.com/dart-lang/sdk/issues/21620)
+  vm_options.AddArgument("--no-concurrent_sweep");
   Dart_SetVMFlags(vm_options.count(), vm_options.arguments());
 
   // Initialize the Dart VM.
diff --git a/runtime/bin/isolate_data.h b/runtime/bin/isolate_data.h
index eaaa3fb..179bde5 100644
--- a/runtime/bin/isolate_data.h
+++ b/runtime/bin/isolate_data.h
@@ -23,7 +23,8 @@
   explicit IsolateData(const char* url, const char* package_root)
       : script_url(strdup(url)),
         package_root(NULL),
-        udp_receive_buffer(NULL) {
+        udp_receive_buffer(NULL),
+        load_async_id(-1) {
     if (package_root != NULL) {
       this->package_root = strdup(package_root);
     }
@@ -37,6 +38,7 @@
   char* script_url;
   char* package_root;
   uint8_t* udp_receive_buffer;
+  int64_t load_async_id;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(IsolateData);
diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc
index bb01402..cebd7e6 100644
--- a/runtime/bin/main.cc
+++ b/runtime/bin/main.cc
@@ -7,7 +7,7 @@
 #include <stdio.h>
 
 #include "include/dart_api.h"
-#include "include/dart_debugger_api.h"
+#include "include/dart_tools_api.h"
 
 #include "bin/builtin.h"
 #include "bin/dartutils.h"
@@ -404,24 +404,6 @@
 }
 
 
-// Convert all the arguments to UTF8. On Windows, the arguments are
-// encoded in the current code page and not UTF8.
-//
-// Returns true if the arguments are converted. In that case
-// each of the arguments need to be deallocated using free.
-static bool Utf8ConvertArgv(int argc, char** argv) {
-  int unicode_argc = 0;
-  wchar_t** unicode_argv = ShellUtils::GetUnicodeArgv(&unicode_argc);
-  if (unicode_argv == NULL) return false;
-  for (int i = 0; i < unicode_argc; i++) {
-    wchar_t* arg = unicode_argv[i];
-    argv[i] = StringUtils::WideToUtf8(arg);
-  }
-  ShellUtils::FreeUnicodeArgv(unicode_argv);
-  return true;
-}
-
-
 // Parse out the command line arguments. Returns -1 if the arguments
 // are incorrect, 0 otherwise.
 static int ParseArguments(int argc,
@@ -893,7 +875,7 @@
 
   // On Windows, the argv strings are code page encoded and not
   // utf8. We need to convert them to utf8.
-  bool argv_converted = Utf8ConvertArgv(argc, argv);
+  bool argv_converted = ShellUtils::GetUtf8Argv(argc, argv);
 
   // Parse command line arguments.
   if (ParseArguments(argc,
diff --git a/runtime/bin/platform_macos.cc b/runtime/bin/platform_macos.cc
index 351a829..6c83fc8 100644
--- a/runtime/bin/platform_macos.cc
+++ b/runtime/bin/platform_macos.cc
@@ -6,6 +6,8 @@
 #if defined(TARGET_OS_MACOS)
 
 #include <mach-o/dyld.h>
+#include <sys/types.h>
+#include <sys/sysctl.h>
 
 #include "bin/file.h"
 #include "bin/platform.h"
@@ -37,7 +39,14 @@
 
 
 int Platform::NumberOfProcessors() {
-  return sysconf(_SC_NPROCESSORS_ONLN);
+  int32_t cpus = -1;
+  size_t cpus_length = sizeof(cpus);
+  if (sysctlbyname("hw.logicalcpu", &cpus, &cpus_length, NULL, 0) == 0) {
+    return cpus;
+  } else {
+    // Failed, fallback to using sysconf.
+    return sysconf(_SC_NPROCESSORS_ONLN);
+  }
 }
 
 
@@ -57,6 +66,16 @@
 
 
 char** Platform::Environment(intptr_t* count) {
+#if defined(TARGET_OS_IOS)
+  // TODO(iposva): On Mac (desktop), _NSGetEnviron() is used to access the
+  // environ from shared libraries or bundles. This is present in crt_externs.h
+  // which is unavailable on iOS. On iOS, everything is statically linked for
+  // now. So arguably, accessing the environ directly with a "extern char
+  // **environ" will work. But this approach is brittle as the target with this
+  // CU could be a dynamic framework (introduced in iOS 8). A more elegant
+  // approach needs to be devised.
+  return NULL;
+#else
   // Using environ directly is only safe as long as we do not
   // provide access to modifying environment variables.
   // On MacOS you have to do a bit of magic to get to the
@@ -71,6 +90,7 @@
     result[current] = environ[current];
   }
   return result;
+#endif
 }
 
 
diff --git a/runtime/bin/platform_win.cc b/runtime/bin/platform_win.cc
index d109c82..9830db2 100644
--- a/runtime/bin/platform_win.cc
+++ b/runtime/bin/platform_win.cc
@@ -10,6 +10,7 @@
 #include "bin/log.h"
 #include "bin/socket.h"
 #include "bin/utils.h"
+#include "bin/utils_win.h"
 
 
 namespace dart {
@@ -66,7 +67,7 @@
   tmp = strings;
   for (intptr_t current = 0; current < i;) {
     // Skip the strings that were not counted above.
-    if (*tmp != '=') result[current++] = StringUtils::WideToUtf8(tmp);
+    if (*tmp != '=') result[current++] = StringUtilsWin::WideToUtf8(tmp);
     tmp += (wcslen(tmp) + 1);
   }
   FreeEnvironmentStringsW(strings);
@@ -96,7 +97,7 @@
     free(tmp_buffer);
     return NULL;
   }
-  char* path = StringUtils::WideToUtf8(tmp_buffer);
+  char* path = StringUtilsWin::WideToUtf8(tmp_buffer);
   free(tmp_buffer);
   // Return the canonical path as the returned path might contain symlinks.
   char* canon_path = File::GetCanonicalPath(path);
diff --git a/runtime/bin/process.cc b/runtime/bin/process.cc
index 88ace0e..2c90c11 100644
--- a/runtime/bin/process.cc
+++ b/runtime/bin/process.cc
@@ -291,29 +291,53 @@
   intptr_t bytes_length = 0;
   Dart_Handle result = Dart_ListLength(bytes, &bytes_length);
   if (Dart_IsError(result)) Dart_PropagateError(result);
-  uint8_t* buffer = new uint8_t[bytes_length + 1];
+  uint8_t* buffer =
+      reinterpret_cast<uint8_t*>(Dart_ScopeAllocate(bytes_length + 1));
   result = Dart_ListGetAsBytes(bytes, 0, buffer, bytes_length);
   buffer[bytes_length] = '\0';
-  if (Dart_IsError(result)) {
-    delete[] buffer;
-    Dart_PropagateError(result);
-  }
+  if (Dart_IsError(result)) Dart_PropagateError(result);
+  intptr_t len;
   char* str =
-      StringUtils::ConsoleStringToUtf8(reinterpret_cast<char*>(buffer));
-  Dart_SetReturnValue(args, DartUtils::NewString(str));
-  if (str != reinterpret_cast<char*>(buffer)) free(str);
+      StringUtils::ConsoleStringToUtf8(
+          reinterpret_cast<char*>(buffer),
+          bytes_length,
+          &len);
+  if (str == NULL) {
+    Dart_ThrowException(
+        DartUtils::NewInternalError("SystemEncodingToString failed"));
+  }
+  result =
+      Dart_NewStringFromUTF8(reinterpret_cast<const uint8_t*>(str), len);
+  free(str);
+  if (Dart_IsError(result)) Dart_PropagateError(result);
+  Dart_SetReturnValue(args, result);
 }
 
 
 void FUNCTION_NAME(StringToSystemEncoding)(Dart_NativeArguments args) {
   Dart_Handle str = Dart_GetNativeArgument(args, 0);
-  const char* utf8 = DartUtils::GetStringValue(str);
-  const char* system_string = StringUtils::Utf8ToConsoleString(utf8);
-  int external_length = strlen(system_string);
+  char* utf8;
+  intptr_t utf8_len;
+  Dart_Handle result = Dart_StringToUTF8(
+      str, reinterpret_cast<uint8_t **>(&utf8), &utf8_len);
+  if (Dart_IsError(result)) {
+    Dart_PropagateError(result);
+  }
+  intptr_t system_len;
+  const char* system_string =
+      StringUtils::Utf8ToConsoleString(utf8, utf8_len, &system_len);
+  if (system_string == NULL) {
+    Dart_ThrowException(
+        DartUtils::NewInternalError("StringToSystemEncoding failed"));
+  }
   uint8_t* buffer = NULL;
-  Dart_Handle external_array = IOBuffer::Allocate(external_length, &buffer);
-  memmove(buffer, system_string, external_length);
-  if (utf8 != system_string) free(const_cast<char*>(system_string));
+  Dart_Handle external_array = IOBuffer::Allocate(system_len, &buffer);
+  if (Dart_IsError(external_array)) {
+    free(const_cast<char*>(system_string));
+    Dart_PropagateError(result);
+  }
+  memmove(buffer, system_string, system_len);
+  free(const_cast<char*>(system_string));
   Dart_SetReturnValue(args, external_array);
 }
 
diff --git a/runtime/bin/process_macos.cc b/runtime/bin/process_macos.cc
index 7ef89b1..bf81a8c 100644
--- a/runtime/bin/process_macos.cc
+++ b/runtime/bin/process_macos.cc
@@ -7,7 +7,9 @@
 
 #include "bin/process.h"
 
+#if !defined(TARGET_OS_IOS)
 #include <crt_externs.h>  // NOLINT
+#endif
 #include <errno.h>  // NOLINT
 #include <fcntl.h>  // NOLINT
 #include <poll.h>  // NOLINT
@@ -449,12 +451,14 @@
       ReportChildError();
     }
 
+#if !defined(TARGET_OS_IOS)
     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_;
     }
+#endif
 
     VOID_TEMP_FAILURE_RETRY(
         execvp(path_, const_cast<char* const*>(program_arguments_)));
diff --git a/runtime/bin/process_win.cc b/runtime/bin/process_win.cc
index d57cde0..ebf4ce3 100644
--- a/runtime/bin/process_win.cc
+++ b/runtime/bin/process_win.cc
@@ -309,7 +309,7 @@
   const int kMaxMessageLength = 256;
   wchar_t message[kMaxMessageLength];
   FormatMessageIntoBuffer(error_code, message, kMaxMessageLength);
-  *os_error_message = StringUtils::WideToUtf8(message);
+  *os_error_message = StringUtilsWin::WideToUtf8(message);
   return error_code;
 }
 
@@ -433,10 +433,10 @@
     exit_handles_[kWriteHandle] = INVALID_HANDLE_VALUE;
 
     // Transform input strings to system format.
-    const wchar_t* system_path = StringUtils::Utf8ToWide(path_);
+    const wchar_t* system_path = StringUtilsWin::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]);
+       system_arguments[i] = StringUtilsWin::Utf8ToWide(arguments[i]);
     }
 
     // Compute command-line length.
@@ -474,7 +474,7 @@
       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]);
+        system_environment[i] = StringUtilsWin::Utf8ToWide(environment[i]);
       }
 
       // An environment block is a sequence of zero-terminated strings
@@ -506,7 +506,8 @@
 
     system_working_directory_ = NULL;
     if (working_directory_ != NULL) {
-      system_working_directory_ = StringUtils::Utf8ToWide(working_directory_);
+      system_working_directory_ =
+          StringUtilsWin::Utf8ToWide(working_directory_);
     }
 
     attribute_list_ = NULL;
diff --git a/runtime/bin/socket_win.cc b/runtime/bin/socket_win.cc
index 451d7f6..19625e7 100644
--- a/runtime/bin/socket_win.cc
+++ b/runtime/bin/socket_win.cc
@@ -13,6 +13,8 @@
 #include "bin/socket.h"
 #include "bin/thread.h"
 #include "bin/utils.h"
+#include "bin/utils_win.h"
+
 
 namespace dart {
 namespace bin {
@@ -357,7 +359,7 @@
 
 bool Socket::ParseAddress(int type, const char* address, RawAddr* addr) {
   int result;
-  const wchar_t* system_address = StringUtils::Utf8ToWide(address);
+  const wchar_t* system_address = StringUtilsWin::Utf8ToWide(address);
   if (type == SocketAddress::TYPE_IPV4) {
     result = InetPton(AF_INET, system_address, &addr->in.sin_addr);
   } else {
@@ -454,7 +456,7 @@
          u != NULL; u = u->Next) {
       addresses->SetAt(i, new InterfaceSocketAddress(
           u->Address.lpSockaddr,
-          StringUtils::WideToUtf8(a->FriendlyName),
+          StringUtilsWin::WideToUtf8(a->FriendlyName),
           a->Ipv6IfIndex));
       i++;
     }
diff --git a/runtime/bin/utils.h b/runtime/bin/utils.h
index 60beef1..10ca3735 100644
--- a/runtime/bin/utils.h
+++ b/runtime/bin/utils.h
@@ -57,29 +57,44 @@
   DISALLOW_COPY_AND_ASSIGN(OSError);
 };
 
+
 class StringUtils {
  public:
   // The following methods convert the argument if needed.  The
   // conversions are only needed on Windows. If the methods returns a
-  // pointer that is different from the input pointer the returned
+  // pointer that is different from the input pointer, the returned
   // pointer is allocated with malloc and should be freed using free.
-  static const char* ConsoleStringToUtf8(const char* str);
-  static char* ConsoleStringToUtf8(char* str);
-  static const char* Utf8ToConsoleString(const char* utf8);
-  static char* Utf8ToConsoleString(char* utf8);
-  static char* WideToUtf8(wchar_t* wide);
-  static const char* WideToUtf8(const wchar_t* wide);
-  static wchar_t* Utf8ToWide(char* utf8);
-  static const wchar_t* Utf8ToWide(const char* utf8);
+  //
+  // If the len argument is passed then that number of characters are
+  // converted. If len is -1, conversion will stop at the first NUL
+  // character. If result_len is not NUL, it is used to set the number
+  // of characters in the result.
+  //
+  // These conversion functions are only implemented on Windows as the
+  // Dart code only hit this path on Windows.
+  static const char* ConsoleStringToUtf8(const char* str,
+                                         intptr_t len = -1,
+                                         intptr_t* result_len = NULL);
+  static char* ConsoleStringToUtf8(char* str,
+                                   intptr_t len = -1,
+                                   intptr_t* result_len = NULL);
+  static const char* Utf8ToConsoleString(const char* utf8,
+                                         intptr_t len = -1,
+                                         intptr_t* result_len = NULL);
+  static char* Utf8ToConsoleString(char* utf8,
+                                   intptr_t len = -1,
+                                   intptr_t* result_len = NULL);
 };
 
+
 class ShellUtils {
  public:
-  // Get the arguments passed to the program as unicode strings.
-  // If GetUnicodeArgv returns a pointer that pointer has to be
-  // deallocated with a call to FreeUnicodeArgv.
-  static wchar_t** GetUnicodeArgv(int* argc);
-  static void FreeUnicodeArgv(wchar_t** argv);
+  // Convert all the arguments to UTF8. On Windows, the arguments are
+  // encoded in the current code page and not UTF8.
+  //
+  // Returns true if the arguments are converted. In that case
+  // each of the arguments need to be deallocated using free.
+  static bool GetUtf8Argv(int argc, char** argv);
 };
 
 class TimerUtils {
diff --git a/runtime/bin/utils_android.cc b/runtime/bin/utils_android.cc
index 615dae9..00cf93d 100644
--- a/runtime/bin/utils_android.cc
+++ b/runtime/bin/utils_android.cc
@@ -42,47 +42,32 @@
   }
 }
 
-const char* StringUtils::ConsoleStringToUtf8(const char* str) {
-  return str;
-}
-
-const char* StringUtils::Utf8ToConsoleString(const char* utf8) {
-  return utf8;
-}
-
-char* StringUtils::ConsoleStringToUtf8(char* str) {
-  return str;
-}
-
-char* StringUtils::Utf8ToConsoleString(char* utf8) {
-  return utf8;
-}
-
-wchar_t* StringUtils::Utf8ToWide(char* utf8) {
+const char* StringUtils::ConsoleStringToUtf8(
+    const char* str, intptr_t len, intptr_t* result_len) {
   UNIMPLEMENTED();
   return NULL;
 }
 
-const wchar_t* StringUtils::Utf8ToWide(const char* utf8) {
+const char* StringUtils::Utf8ToConsoleString(
+    const char* utf8, intptr_t len, intptr_t* result_len) {
   UNIMPLEMENTED();
   return NULL;
 }
 
-char* StringUtils::WideToUtf8(wchar_t* str) {
+char* StringUtils::ConsoleStringToUtf8(
+    char* str, intptr_t len, intptr_t* result_len) {
   UNIMPLEMENTED();
   return NULL;
 }
 
-const char* StringUtils::WideToUtf8(const wchar_t* str) {
+char* StringUtils::Utf8ToConsoleString(
+    char* utf8, intptr_t len, intptr_t* result_len) {
   UNIMPLEMENTED();
   return NULL;
 }
 
-wchar_t** ShellUtils::GetUnicodeArgv(int* argc) {
-  return NULL;
-}
-
-void ShellUtils::FreeUnicodeArgv(wchar_t** argv) {
+bool ShellUtils::GetUtf8Argv(int argc, char** argv) {
+  return false;
 }
 
 int64_t TimerUtils::GetCurrentTimeMilliseconds() {
diff --git a/runtime/bin/utils_linux.cc b/runtime/bin/utils_linux.cc
index ce35eb7..f3d8654 100644
--- a/runtime/bin/utils_linux.cc
+++ b/runtime/bin/utils_linux.cc
@@ -40,47 +40,32 @@
   }
 }
 
-const char* StringUtils::ConsoleStringToUtf8(const char* str) {
-  return str;
-}
-
-const char* StringUtils::Utf8ToConsoleString(const char* utf8) {
-  return utf8;
-}
-
-char* StringUtils::ConsoleStringToUtf8(char* str) {
-  return str;
-}
-
-char* StringUtils::Utf8ToConsoleString(char* utf8) {
-  return utf8;
-}
-
-wchar_t* StringUtils::Utf8ToWide(char* utf8) {
+const char* StringUtils::ConsoleStringToUtf8(
+    const char* str, intptr_t len, intptr_t* result_len) {
   UNIMPLEMENTED();
   return NULL;
 }
 
-const wchar_t* StringUtils::Utf8ToWide(const char* utf8) {
+const char* StringUtils::Utf8ToConsoleString(
+    const char* utf8, intptr_t len, intptr_t* result_len) {
   UNIMPLEMENTED();
   return NULL;
 }
 
-char* StringUtils::WideToUtf8(wchar_t* str) {
+char* StringUtils::ConsoleStringToUtf8(
+    char* str, intptr_t len, intptr_t* result_len) {
   UNIMPLEMENTED();
   return NULL;
 }
 
-const char* StringUtils::WideToUtf8(const wchar_t* str) {
+char* StringUtils::Utf8ToConsoleString(
+    char* utf8, intptr_t len, intptr_t* result_len) {
   UNIMPLEMENTED();
   return NULL;
 }
 
-wchar_t** ShellUtils::GetUnicodeArgv(int* argc) {
-  return NULL;
-}
-
-void ShellUtils::FreeUnicodeArgv(wchar_t** argv) {
+bool ShellUtils::GetUtf8Argv(int argc, char** argv) {
+  return false;
 }
 
 int64_t TimerUtils::GetCurrentTimeMilliseconds() {
diff --git a/runtime/bin/utils_macos.cc b/runtime/bin/utils_macos.cc
index 460da35..4004f38 100644
--- a/runtime/bin/utils_macos.cc
+++ b/runtime/bin/utils_macos.cc
@@ -42,47 +42,32 @@
   }
 }
 
-const char* StringUtils::ConsoleStringToUtf8(const char* str) {
-  return str;
-}
-
-const char* StringUtils::Utf8ToConsoleString(const char* utf8) {
-  return utf8;
-}
-
-char* StringUtils::ConsoleStringToUtf8(char* str) {
-  return str;
-}
-
-char* StringUtils::Utf8ToConsoleString(char* utf8) {
-  return utf8;
-}
-
-wchar_t* StringUtils::Utf8ToWide(char* utf8) {
+const char* StringUtils::ConsoleStringToUtf8(
+    const char* str, intptr_t len, intptr_t* result_len) {
   UNIMPLEMENTED();
   return NULL;
 }
 
-const wchar_t* StringUtils::Utf8ToWide(const char* utf8) {
+const char* StringUtils::Utf8ToConsoleString(
+    const char* utf8, intptr_t len, intptr_t* result_len) {
   UNIMPLEMENTED();
   return NULL;
 }
 
-char* StringUtils::WideToUtf8(wchar_t* str) {
+char* StringUtils::ConsoleStringToUtf8(
+    char* str, intptr_t len, intptr_t* result_len) {
   UNIMPLEMENTED();
   return NULL;
 }
 
-const char* StringUtils::WideToUtf8(const wchar_t* str) {
+char* StringUtils::Utf8ToConsoleString(
+    char* utf8, intptr_t len, intptr_t* result_len) {
   UNIMPLEMENTED();
   return NULL;
 }
 
-wchar_t** ShellUtils::GetUnicodeArgv(int* argc) {
-  return NULL;
-}
-
-void ShellUtils::FreeUnicodeArgv(wchar_t** argv) {
+bool ShellUtils::GetUtf8Argv(int argc, char** argv) {
+  return false;
 }
 
 int64_t TimerUtils::GetCurrentTimeMilliseconds() {
diff --git a/runtime/bin/utils_win.cc b/runtime/bin/utils_win.cc
index dab7355..65d4c65 100644
--- a/runtime/bin/utils_win.cc
+++ b/runtime/bin/utils_win.cc
@@ -11,6 +11,7 @@
 #include "bin/utils.h"
 #include "bin/utils_win.h"
 #include "bin/log.h"
+#include "platform/assert.h"
 
 
 namespace dart {
@@ -44,7 +45,7 @@
   static const int kMaxMessageLength = 256;
   wchar_t message[kMaxMessageLength];
   FormatMessageIntoBuffer(code_, message, kMaxMessageLength);
-  char* utf8 = StringUtils::WideToUtf8(message);
+  char* utf8 = StringUtilsWin::WideToUtf8(message);
   SetMessage(utf8);
   free(utf8);
 }
@@ -56,72 +57,115 @@
   static const int kMaxMessageLength = 256;
   wchar_t message[kMaxMessageLength];
   FormatMessageIntoBuffer(code_, message, kMaxMessageLength);
-  char* utf8 = StringUtils::WideToUtf8(message);
+  char* utf8 = StringUtilsWin::WideToUtf8(message);
   SetMessage(utf8);
   free(utf8);
 }
 
-char* StringUtils::ConsoleStringToUtf8(char* str) {
-  int len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
-  wchar_t* unicode = new wchar_t[len+1];
-  MultiByteToWideChar(CP_ACP, 0, str, -1, unicode, len);
-  unicode[len] = '\0';
-  char* utf8 = StringUtils::WideToUtf8(unicode);
-  delete[] unicode;
+char* StringUtils::ConsoleStringToUtf8(char* str,
+                                       intptr_t len,
+                                       intptr_t* result_len) {
+  int wide_len = MultiByteToWideChar(CP_ACP, 0, str, len, NULL, 0);
+  wchar_t* wide = new wchar_t[wide_len];
+  MultiByteToWideChar(CP_ACP, 0, str, len, wide, wide_len);
+  char* utf8 = StringUtilsWin::WideToUtf8(wide, wide_len, result_len);
+  delete[] wide;
   return utf8;
 }
 
-char* StringUtils::Utf8ToConsoleString(char* utf8) {
-  wchar_t* unicode = Utf8ToWide(utf8);
-  int len = WideCharToMultiByte(CP_ACP, 0, unicode, -1, NULL, 0, NULL, NULL);
-  char* ansi = reinterpret_cast<char*>(malloc(len + 1));
-  WideCharToMultiByte(CP_ACP, 0, unicode, -1, ansi, len, NULL, NULL);
-  ansi[len] = '\0';
-  free(unicode);
+char* StringUtils::Utf8ToConsoleString(char* utf8,
+                                       intptr_t len,
+                                       intptr_t* result_len) {
+  intptr_t wide_len;
+  wchar_t* wide = StringUtilsWin::Utf8ToWide(utf8, len, &wide_len);
+  int system_len = WideCharToMultiByte(
+      CP_ACP, 0, wide, wide_len, NULL, 0, NULL, NULL);
+  char* ansi = reinterpret_cast<char*>(malloc(system_len));
+  if (ansi == NULL) {
+    free(wide);
+    return NULL;
+  }
+  WideCharToMultiByte(CP_ACP, 0, wide, wide_len, ansi, system_len, NULL, NULL);
+  free(wide);
+  if (result_len != NULL) {
+    *result_len = system_len;
+  }
   return ansi;
 }
 
-char* StringUtils::WideToUtf8(wchar_t* wide) {
-  int len = WideCharToMultiByte(CP_UTF8, 0, wide, -1, NULL, 0, NULL, NULL);
-  char* utf8 = reinterpret_cast<char*>(malloc(len + 1));
-  WideCharToMultiByte(CP_UTF8, 0, wide, -1, utf8, len, NULL, NULL);
-  utf8[len] = '\0';
+char* StringUtilsWin::WideToUtf8(wchar_t* wide,
+                                 intptr_t len,
+                                 intptr_t* result_len) {
+  // If len is -1 then WideCharToMultiByte will include the terminating
+  // NUL byte in the length.
+  int utf8_len = WideCharToMultiByte(
+      CP_UTF8, 0, wide, len, NULL, 0, NULL, NULL);
+  char* utf8 = reinterpret_cast<char*>(malloc(utf8_len));
+  WideCharToMultiByte(CP_UTF8, 0, wide, len, utf8, utf8_len, NULL, NULL);
+  if (result_len != NULL) {
+    *result_len = utf8_len;
+  }
   return utf8;
 }
 
 
-wchar_t* StringUtils::Utf8ToWide(char* utf8) {
-  int len = MultiByteToWideChar(CP_UTF8, 0, utf8, -1, NULL, 0);
-  wchar_t* unicode =
-      reinterpret_cast<wchar_t*>(malloc((len + 1) * sizeof(wchar_t)));
-  MultiByteToWideChar(CP_UTF8, 0, utf8, -1, unicode, len);
-  unicode[len] = '\0';
-  return unicode;
+wchar_t* StringUtilsWin::Utf8ToWide(char* utf8,
+                                    intptr_t len,
+                                    intptr_t* result_len) {
+  // If len is -1 then MultiByteToWideChar will include the terminating
+  // NUL byte in the length.
+  int wide_len = MultiByteToWideChar(CP_UTF8, 0, utf8, len, NULL, 0);
+  wchar_t* wide =
+      reinterpret_cast<wchar_t*>(malloc((wide_len) * sizeof(wchar_t)));
+  MultiByteToWideChar(CP_UTF8, 0, utf8, len, wide, wide_len);
+  if (result_len != NULL) {
+    *result_len = wide_len;
+  }
+  return wide;
 }
 
-const char* StringUtils::Utf8ToConsoleString(const char* utf8) {
-  return const_cast<const char*>(Utf8ToConsoleString(const_cast<char*>(utf8)));
+const char* StringUtils::Utf8ToConsoleString(
+    const char* utf8, intptr_t len, intptr_t* result_len) {
+  return const_cast<const char*>(
+      StringUtils::Utf8ToConsoleString(
+          const_cast<char*>(utf8), len, result_len));
 }
 
-const char* StringUtils::ConsoleStringToUtf8(const char* str) {
-  return const_cast<const char*>(ConsoleStringToUtf8(const_cast<char*>(str)));
+const char* StringUtils::ConsoleStringToUtf8(
+    const char* str, intptr_t len, intptr_t* result_len) {
+  return const_cast<const char*>(
+      StringUtils::ConsoleStringToUtf8(
+          const_cast<char*>(str), len, result_len));
 }
 
-const char* StringUtils::WideToUtf8(const wchar_t* wide) {
-  return const_cast<const char*>(WideToUtf8(const_cast<wchar_t*>(wide)));
+const char* StringUtilsWin::WideToUtf8(
+    const wchar_t* wide, intptr_t len, intptr_t* result_len) {
+  return const_cast<const char*>(
+      StringUtilsWin::WideToUtf8(const_cast<wchar_t*>(wide), len, result_len));
 }
 
-const wchar_t* StringUtils::Utf8ToWide(const char* utf8) {
-  return const_cast<const wchar_t*>(Utf8ToWide(const_cast<char*>(utf8)));
+const wchar_t* StringUtilsWin::Utf8ToWide(
+    const char* utf8, intptr_t len, intptr_t* result_len) {
+  return const_cast<const wchar_t*>(
+      StringUtilsWin::Utf8ToWide(const_cast<char*>(utf8), len, result_len));
 }
 
-wchar_t** ShellUtils::GetUnicodeArgv(int* argc) {
+bool ShellUtils::GetUtf8Argv(int argc, char** argv) {
   wchar_t* command_line = GetCommandLineW();
-  return CommandLineToArgvW(command_line, argc);
-}
-
-void ShellUtils::FreeUnicodeArgv(wchar_t** argv) {
-  LocalFree(argv);
+  int unicode_argc;
+  wchar_t** unicode_argv = CommandLineToArgvW(command_line, &unicode_argc);
+  if (unicode_argv == NULL) return false;
+  // The argc passed to main should have the same argc as we get here.
+  ASSERT(argc == unicode_argc);
+  if (argc < unicode_argc) {
+    unicode_argc = argc;
+  }
+  for (int i = 0; i < unicode_argc; i++) {
+    wchar_t* arg = unicode_argv[i];
+    argv[i] = StringUtilsWin::WideToUtf8(arg);
+  }
+  LocalFree(unicode_argv);
+  return true;
 }
 
 int64_t TimerUtils::GetCurrentTimeMilliseconds() {
diff --git a/runtime/bin/utils_win.h b/runtime/bin/utils_win.h
index a044760..92de84e 100644
--- a/runtime/bin/utils_win.h
+++ b/runtime/bin/utils_win.h
@@ -12,6 +12,22 @@
 
 void FormatMessageIntoBuffer(DWORD code, wchar_t* buffer, int buffer_length);
 
+class StringUtilsWin {
+ public:
+  static char* WideToUtf8(wchar_t* wide,
+                          intptr_t len = -1,
+                          intptr_t* result_len = NULL);
+  static const char* WideToUtf8(const wchar_t* wide,
+                                intptr_t len = -1,
+                                intptr_t* result_len = NULL);
+  static wchar_t* Utf8ToWide(char* utf8,
+                             intptr_t len = -1,
+                             intptr_t* result_len = NULL);
+  static const wchar_t* Utf8ToWide(const char* utf8,
+                                   intptr_t len = -1,
+                                   intptr_t* result_len = NULL);
+};
+
 }  // namespace bin
 }  // namespace dart
 
diff --git a/runtime/bin/vmservice/server.dart b/runtime/bin/vmservice/server.dart
index bd84a2f..4723ca5 100644
--- a/runtime/bin/vmservice/server.dart
+++ b/runtime/bin/vmservice/server.dart
@@ -141,8 +141,8 @@
       request.response.close();
       return;
     }
-    var message = new Message.fromUri(this, request.uri);
     var client = new HttpRequestClient(request, _service);
+    var message = new Message.fromUri(client, request.uri);
     client.onMessage(null, message);
   }
 
diff --git a/runtime/dart-runtime.gyp b/runtime/dart-runtime.gyp
index f9795a8..e5c8805 100644
--- a/runtime/dart-runtime.gyp
+++ b/runtime/dart-runtime.gyp
@@ -34,9 +34,9 @@
       ],
       'sources': [
         'include/dart_api.h',
-        'include/dart_debugger_api.h',
         'include/dart_mirrors_api.h',
         'include/dart_native_api.h',
+        'include/dart_tools_api.h',
         'vm/dart_api_impl.cc',
         'vm/debugger_api_impl.cc',
         'vm/mirrors_api_impl.cc',
diff --git a/runtime/include/dart_api.h b/runtime/include/dart_api.h
index 89131ff..d3f54b1 100755
--- a/runtime/include/dart_api.h
+++ b/runtime/include/dart_api.h
@@ -308,7 +308,11 @@
  *
  * Requires there to be a current isolate.
  *
- * \param exception An instance of a Dart object to be thrown.
+ * \param exception An instance of a Dart object to be thrown or
+ *        an ApiError or CompilationError handle.
+ *        When an ApiError or CompilationError handle is passed in
+ *        a string object of the error message is created and it becomes
+ *        the Dart object to be thrown.
  */
 DART_EXPORT Dart_Handle Dart_NewUnhandledExceptionError(Dart_Handle exception);
 
@@ -1056,6 +1060,27 @@
                                                   intptr_t* size);
 
 /**
+ * Creates a snapshot of the specified library loaded in the isolate.
+ *
+ * A library snapshot can be used for implementing fast startup of applications
+ * (skips tokenizing and parsing process). A Snapshot of the library
+ * can only be created before any dart code has executed.
+ *
+ * Requires there to be a current isolate which already has loaded the library.
+ *
+ * \param library A library for which the snapshot needs to be created.
+ * \param buffer Returns a pointer to a buffer containing
+ *   the snapshot. This buffer is scope allocated and is only valid
+ *   until the next call to Dart_ExitScope.
+ * \param size Returns the size of the buffer.
+ *
+ * \return A valid handle if no error occurs during the operation.
+ */
+DART_EXPORT Dart_Handle Dart_CreateLibrarySnapshot(Dart_Handle library,
+                                                   uint8_t** buffer,
+                                                   intptr_t* size);
+
+/**
  * Schedules an interrupt for the specified isolate.
  *
  * When the isolate is interrupted, the isolate interrupt callback
@@ -2814,64 +2839,4 @@
  */
 DART_EXPORT Dart_Port Dart_ServiceWaitForLoadPort();
 
-
-/**
- * A service request callback function.
- *
- * These callbacks, registered by the embedder, are called when the VM receives
- * a service request it can't handle and the service request command name
- * matches one of the embedder registered handlers.
- *
- * \param method The rpc method name.
- * \param param_keys Service requests can have key-value pair parameters. The
- *   keys and values are flattened and stored in arrays.
- * \param param_values The values associated with the keys.
- * \param num_params The length of the param_keys and param_values arrays.
- * \param user_data The user_data pointer registered with this handler.
- *
- * \return Returns a C string containing a valid JSON object. The returned
- * pointer will be freed by the VM by calling free.
- */
-typedef const char* (*Dart_ServiceRequestCallback)(
-    const char* method,
-    const char** param_keys,
-    const char** param_values,
-    intptr_t num_params,
-    void* user_data);
-
-/**
- * Register a Dart_ServiceRequestCallback to be called to handle
- * requests for the named rpc on a specific isolate. The callback will
- * be invoked with the current isolate set to the request target.
- *
- * \param method The name of the method that this callback is responsible for.
- * \param callback The callback to invoke.
- * \param user_data The user data passed to the callback.
- *
- * NOTE: If multiple callbacks with the same name are registered, only
- * the last callback registered will be remembered.
- */
-DART_EXPORT void Dart_RegisterIsolateServiceRequestCallback(
-    const char* method,
-    Dart_ServiceRequestCallback callback,
-    void* user_data);
-
-/**
- * Register a Dart_ServiceRequestCallback to be called to handle
- * requests for the named rpc. The callback will be invoked without a
- * current isolate.
- *
- * \param method The name of the command that this callback is responsible for.
- * \param callback The callback to invoke.
- * \param user_data The user data passed to the callback.
- *
- * NOTE: If multiple callbacks with the same name are registered, only
- * the last callback registered will be remembered.
- */
-DART_EXPORT void Dart_RegisterRootServiceRequestCallback(
-    const char* method,
-    Dart_ServiceRequestCallback callback,
-    void* user_data);
-
-
 #endif  /* INCLUDE_DART_API_H_ */  /* NOLINT */
diff --git a/runtime/include/dart_debugger_api.h b/runtime/include/dart_tools_api.h
old mode 100755
new mode 100644
similarity index 79%
rename from runtime/include/dart_debugger_api.h
rename to runtime/include/dart_tools_api.h
index 06efa30..f2bc2a4
--- a/runtime/include/dart_debugger_api.h
+++ b/runtime/include/dart_tools_api.h
@@ -2,11 +2,27 @@
 // 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 INCLUDE_DART_DEBUGGER_API_H_
-#define INCLUDE_DART_DEBUGGER_API_H_
+#ifndef INCLUDE_DART_TOOLS_API_H_
+#define INCLUDE_DART_TOOLS_API_H_
 
 #include "include/dart_api.h"
 
+/** \mainpage Dart Tools Embedding API Reference
+ *
+ * This reference describes the Dart embedding API for tools. Tools include
+ * a debugger, service protocol, and timeline.
+ *
+ * NOTE: The APIs described in this file are unstable and subject to change.
+ *
+ * This reference is generated from the header include/dart_tools_api.h.
+ */
+
+
+ /*
+  * ========
+  * Debugger
+  * ========
+  */
 typedef struct _Dart_Breakpoint* Dart_Breakpoint;
 
 typedef struct _Dart_StackTrace* Dart_StackTrace;
@@ -477,7 +493,7 @@
  * Returns origin class of a function.
  *
  * Requires there to be a current isolate.
- * 
+ *
  * \return Returns the class id (a handle to an integer) of the class in
  * which \function is defined. Returns a null handle if \function is defined
  * at the top level. Returns an error object otherwise.
@@ -520,7 +536,7 @@
  * were a static method of that class.
  * If \target is a Library, the expression is evaluated as if it
  * were a top-level function in that library.
- * 
+ *
  * \return A handle to the computed value, or an error object if
  * the compilation of the expression fails, or if the evaluation throws
  * an error.
@@ -721,4 +737,154 @@
  */
 DART_EXPORT Dart_IsolateId Dart_GetIsolateId(Dart_Isolate isolate);
 
-#endif  // INCLUDE_DART_DEBUGGER_API_H_
+
+/*
+ * =======
+ * Service
+ * =======
+ */
+
+/**
+ * A service request callback function.
+ *
+ * These callbacks, registered by the embedder, are called when the VM receives
+ * a service request it can't handle and the service request command name
+ * matches one of the embedder registered handlers.
+ *
+ * \param method The rpc method name.
+ * \param param_keys Service requests can have key-value pair parameters. The
+ *   keys and values are flattened and stored in arrays.
+ * \param param_values The values associated with the keys.
+ * \param num_params The length of the param_keys and param_values arrays.
+ * \param user_data The user_data pointer registered with this handler.
+ *
+ * \return Returns a C string containing a valid JSON object. The returned
+ * pointer will be freed by the VM by calling free.
+ */
+typedef const char* (*Dart_ServiceRequestCallback)(
+    const char* method,
+    const char** param_keys,
+    const char** param_values,
+    intptr_t num_params,
+    void* user_data);
+
+
+/**
+ * Register a Dart_ServiceRequestCallback to be called to handle
+ * requests for the named rpc on a specific isolate. The callback will
+ * be invoked with the current isolate set to the request target.
+ *
+ * \param method The name of the method that this callback is responsible for.
+ * \param callback The callback to invoke.
+ * \param user_data The user data passed to the callback.
+ *
+ * NOTE: If multiple callbacks with the same name are registered, only
+ * the last callback registered will be remembered.
+ */
+DART_EXPORT void Dart_RegisterIsolateServiceRequestCallback(
+    const char* method,
+    Dart_ServiceRequestCallback callback,
+    void* user_data);
+
+
+/**
+ * Register a Dart_ServiceRequestCallback to be called to handle
+ * requests for the named rpc. The callback will be invoked without a
+ * current isolate.
+ *
+ * \param method The name of the command that this callback is responsible for.
+ * \param callback The callback to invoke.
+ * \param user_data The user data passed to the callback.
+ *
+ * NOTE: If multiple callbacks with the same name are registered, only
+ * the last callback registered will be remembered.
+ */
+DART_EXPORT void Dart_RegisterRootServiceRequestCallback(
+    const char* method,
+    Dart_ServiceRequestCallback callback,
+    void* user_data);
+
+
+/*
+ * ========
+ * Timeline
+ * ========
+ */
+
+/**
+ * Add a duration timeline event to the embedder stream for the current isolate.
+ *
+ * \param label The name of the event.
+ * \param start_micros The start of the duration (in microseconds)
+ * \param end_micros The end of the duration (in microseconds)
+ *
+ * NOTE: On Posix platforms you should use gettimeofday and on Windows platforms
+ * you should use GetSystemTimeAsFileTime to get the time values.
+ */
+DART_EXPORT Dart_Handle Dart_TimelineDuration(const char* label,
+                                              int64_t start_micros,
+                                              int64_t end_micros);
+
+
+/**
+ * Add an instant timeline event to the embedder stream for the current isolate.
+ *
+ * \param label The name of event.
+ *
+ * NOTE: On Posix platforms this call uses gettimeofday and on Windows platforms
+ * this call uses GetSystemTimeAsFileTime to get the current time.
+ */
+DART_EXPORT Dart_Handle Dart_TimelineInstant(const char* label);
+
+
+/**
+ * Adds an asynchronous begin timeline event to the embedder stream for the
+ * current isolate.
+ *
+ * \param label The name of event.
+ *
+ * \return Returns an asynchronous id that must be passed to
+ * Dart_TimelineAsyncInstant and Dart_TimelineAsyncEnd. If the asynchronous
+ * id is less than 0 the event was not added to the timeline and subsequent
+ * calls to Dart_TimelineAsyncInstant and Dart_TimelineAsyncEnd will become
+ * no-ops.
+ *
+ * NOTE: On Posix platforms this call uses gettimeofday and on Windows platforms
+ * this call uses GetSystemTimeAsFileTime to get the current time.
+ */
+DART_EXPORT Dart_Handle Dart_TimelineAsyncBegin(const char* label,
+                                                int64_t* async_id);
+
+
+/**
+ * Adds an asynchronous instant timeline event to the embedder stream for the
+ * current isolate.
+ *
+ * \param label The name of event.
+ *
+ * \return Returns an asynchronous id that must be passed to
+ * Dart_TimelineAsyncInstant and Dart_TimelineAsyncEnd.
+ *
+ * NOTE: On Posix platforms this call uses gettimeofday and on Windows platforms
+ * this call uses GetSystemTimeAsFileTime to get the current time.
+ */
+DART_EXPORT Dart_Handle Dart_TimelineAsyncInstant(const char* label,
+                                                  int64_t async_id);
+
+
+/**
+ * Adds an asynchronous end timeline event to the embedder stream for the
+ * current isolate.
+ *
+ * \param label The name of event.
+ *
+ * \return Returns an asynchronous id that must be passed to
+ * Dart_TimelineAsyncInstant and Dart_TimelineAsyncEnd.
+ *
+ * NOTE: On Posix platforms this call uses gettimeofday and on Windows platforms
+ * this call uses GetSystemTimeAsFileTime to get the current time.
+ */
+DART_EXPORT Dart_Handle Dart_TimelineAsyncEnd(const char* label,
+                                              int64_t async_id);
+
+#endif  // INCLUDE_DART_TOOLS_API_H_
diff --git a/runtime/lib/mirrors.cc b/runtime/lib/mirrors.cc
index a7c11d7..3ffbff8 100644
--- a/runtime/lib/mirrors.cc
+++ b/runtime/lib/mirrors.cc
@@ -47,6 +47,7 @@
                               const String& function_name,
                               const Function& function,
                               const Array& arguments,
+                              const Array& argument_names,
                               const InvocationMirror::Call call,
                               const InvocationMirror::Type type) {
   const Smi& invocation_type = Smi::Handle(Smi::New(
@@ -57,19 +58,26 @@
   args.SetAt(1, function_name);
   args.SetAt(2, invocation_type);
   args.SetAt(3, arguments);
-  // TODO(rmacnak): Argument 4 (attempted argument names).
+  if (!argument_names.IsNull() && (argument_names.Length() > 0)) {
+    // Empty and null are treated differently for some reason. Don't pass empty
+    // to match the non-reflective error.
+    args.SetAt(4, argument_names);
+  }
   if (!function.IsNull()) {
-    const intptr_t total_num_parameters = function.NumParameters();
-    const Array& array = Array::Handle(Array::New(total_num_parameters));
-    String& param_name = String::Handle();
-    for (int i = 0; i < total_num_parameters; i++) {
-      param_name = function.ParameterNameAt(i);
-      array.SetAt(i, param_name);
-    }
+    const Array& array = Array::Handle(Array::New(1));
+    array.SetAt(0, String::Handle(function.UserVisibleFormalParameters()));
     args.SetAt(5, array);
   }
 
-  Exceptions::ThrowByType(Exceptions::kNoSuchMethod, args);
+  const Library& libcore = Library::Handle(Library::CoreLibrary());
+  const Class& NoSuchMethodError = Class::Handle(
+      libcore.LookupClass(Symbols::NoSuchMethodError()));
+  const Function& throwNew = Function::Handle(
+      NoSuchMethodError.LookupFunctionAllowPrivate(Symbols::ThrowNew()));
+  const Object& result = Object::Handle(
+      DartEntry::InvokeFunction(throwNew, args));
+  ASSERT(result.IsError());
+  Exceptions::PropagateError(Error::Cast(result));
   UNREACHABLE();
 }
 
@@ -672,6 +680,7 @@
                       getter_name,
                       getter,
                       Object::null_array(),
+                      Object::null_array(),
                       InvocationMirror::kTopLevel,
                       InvocationMirror::kGetter);
     UNREACHABLE();
@@ -710,6 +719,7 @@
                           getter_name,
                           getter,
                           Object::null_array(),
+                          Object::null_array(),
                           InvocationMirror::kStatic,
                           InvocationMirror::kGetter);
         UNREACHABLE();
@@ -1513,7 +1523,8 @@
     ThrowNoSuchMethod(AbstractType::Handle(klass.RareType()),
                       function_name,
                       function,
-                      Object::null_array(),
+                      args,
+                      arg_names,
                       InvocationMirror::kStatic,
                       InvocationMirror::kMethod);
     UNREACHABLE();
@@ -1567,6 +1578,7 @@
                         internal_setter_name,
                         setter,
                         args,
+                        Object::null_array(),
                         InvocationMirror::kStatic,
                         InvocationMirror::kSetter);
       UNREACHABLE();
@@ -1587,6 +1599,7 @@
                       internal_setter_name,
                       setter,
                       Object::null_array(),
+                      Object::null_array(),
                       InvocationMirror::kStatic,
                       InvocationMirror::kSetter);
     UNREACHABLE();
@@ -1611,11 +1624,13 @@
   // unnamed constructor for class 'A' is labeled 'A.'.
   // This convention prevents users from explicitly calling constructors.
   const String& klass_name = String::Handle(klass.Name());
+  String& external_constructor_name = String::Handle(klass_name.raw());
   String& internal_constructor_name =
       String::Handle(String::Concat(klass_name, Symbols::Dot()));
-  if (!constructor_name.IsNull()) {
+  if (!constructor_name.IsNull() && constructor_name.Length() > 0) {
     internal_constructor_name =
         String::Concat(internal_constructor_name, constructor_name);
+    external_constructor_name = internal_constructor_name.raw();
   }
 
   Function& lookup_constructor = Function::Handle(
@@ -1624,13 +1639,11 @@
   if (lookup_constructor.IsNull() ||
       (lookup_constructor.kind() != RawFunction::kConstructor) ||
       !lookup_constructor.is_reflectable()) {
-    // Pretend we didn't find the constructor at all when the arity is wrong
-    // so as to produce the same NoSuchMethodError as the non-reflective case.
-    lookup_constructor = Function::null();
     ThrowNoSuchMethod(AbstractType::Handle(klass.RareType()),
-                      internal_constructor_name,
+                      external_constructor_name,
                       lookup_constructor,
-                      Object::null_array(),
+                      explicit_args,
+                      arg_names,
                       InvocationMirror::kConstructor,
                       InvocationMirror::kMethod);
     UNREACHABLE();
@@ -1702,13 +1715,12 @@
   ArgumentsDescriptor args_descriptor(args_descriptor_array);
   if (!redirected_constructor.AreValidArguments(args_descriptor, NULL) ||
       !redirected_constructor.is_reflectable()) {
-    // Pretend we didn't find the constructor at all when the arity is wrong
-    // so as to produce the same NoSuchMethodError as the non-reflective case.
-    redirected_constructor = Function::null();
+    external_constructor_name = redirected_constructor.name();
     ThrowNoSuchMethod(AbstractType::Handle(klass.RareType()),
-                      internal_constructor_name,
+                      external_constructor_name,
                       redirected_constructor,
-                      Object::null_array(),
+                      explicit_args,
+                      arg_names,
                       InvocationMirror::kConstructor,
                       InvocationMirror::kMethod);
     UNREACHABLE();
@@ -1805,7 +1817,8 @@
     ThrowNoSuchMethod(Instance::null_instance(),
                       function_name,
                       function,
-                      Object::null_array(),
+                      args,
+                      arg_names,
                       InvocationMirror::kTopLevel,
                       InvocationMirror::kMethod);
     UNREACHABLE();
@@ -1862,6 +1875,7 @@
                         internal_setter_name,
                         setter,
                         args,
+                        Object::null_array(),
                         InvocationMirror::kTopLevel,
                         InvocationMirror::kSetter);
       UNREACHABLE();
@@ -1882,6 +1896,7 @@
                       internal_setter_name,
                       setter,
                       Object::null_array(),
+                      Object::null_array(),
                       InvocationMirror::kTopLevel,
                       InvocationMirror::kSetter);
     UNREACHABLE();
diff --git a/runtime/observatory/lib/base64.dart b/runtime/observatory/lib/base64.dart
new file mode 100644
index 0000000..4bb0f70
--- /dev/null
+++ b/runtime/observatory/lib/base64.dart
@@ -0,0 +1,69 @@
+// 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 base64;
+
+import 'dart:typed_data';
+
+const _decodeTable =
+    const [null, null, null, null, null, null, null, null,
+           null, null, null, null, null, null, null, null,
+           null, null, null, null, null, null, null, null,
+           null, null, null, null, null, null, null, null,
+           null, null, null, null, null, null, null, null,
+           null, null, null, 62, null, null, null, 63,
+           52, 53, 54, 55, 56, 57, 58, 59,
+           60, 61, null, null, null, 0, null, null,
+           null, 0, 1, 2, 3, 4, 5, 6,
+           7, 8, 9, 10, 11, 12, 13, 14,
+           15, 16, 17, 18, 19, 20, 21, 22,
+           23, 24, 25, null, null, null, null, null,
+           null, 26, 27, 28, 29, 30, 31, 32,
+           33, 34, 35, 36, 37, 38, 39, 40,
+           41, 42, 43, 44, 45, 46, 47, 48,
+           49, 50, 51];
+
+Uint8List decodeBase64(String s) {
+  if (s.length % 4 != 0) throw "Malformed Base64: $s";
+
+  var odd_bits = 0;
+  if (s[s.length - 1] == '=') {
+    if (s[s.length - 2] == '=') {
+      odd_bits = 2;
+    } else {
+      odd_bits = 1;
+    }
+  }
+
+  var decodedByteLength = s.length ~/ 4 * 3 - odd_bits;
+  var result = new Uint8List(decodedByteLength);
+  var limit = s.length;
+  if (odd_bits != 0) {
+    limit = limit - 4;
+  }
+
+  var i = 0, j = 0;
+  while (i < limit) {
+    var triple = _decodeTable[s.codeUnitAt(i++)];
+    triple = (triple << 6) | _decodeTable[s.codeUnitAt(i++)];
+    triple = (triple << 6) | _decodeTable[s.codeUnitAt(i++)];
+    triple = (triple << 6) | _decodeTable[s.codeUnitAt(i++)];
+    result[j++] = triple >> 16;
+    result[j++] = (triple >> 8) & 255;
+    result[j++] = triple & 255;
+  }
+
+  if (odd_bits != 0) {
+    var triple = _decodeTable[s.codeUnitAt(i++)];
+    triple = (triple << 6) | _decodeTable[s.codeUnitAt(i++)];
+    triple = (triple << 6) | _decodeTable[s.codeUnitAt(i++)];
+    triple = (triple << 6) | _decodeTable[s.codeUnitAt(i++)];
+    result[j++] = triple >> 16;
+    if (odd_bits == 1) {
+      result[j++] = (triple >> 8) & 255;
+    }
+  }
+  assert(j == decodedByteLength);
+  return result;
+}
diff --git a/runtime/observatory/lib/elements.dart b/runtime/observatory/lib/elements.dart
index 72ff047..e43b658 100644
--- a/runtime/observatory/lib/elements.dart
+++ b/runtime/observatory/lib/elements.dart
@@ -40,6 +40,7 @@
 export 'package:observatory/src/elements/object_view.dart';
 export 'package:observatory/src/elements/observatory_application.dart';
 export 'package:observatory/src/elements/observatory_element.dart';
+export 'package:observatory/src/elements/ports.dart';
 export 'package:observatory/src/elements/script_inset.dart';
 export 'package:observatory/src/elements/script_ref.dart';
 export 'package:observatory/src/elements/script_view.dart';
diff --git a/runtime/observatory/lib/elements.html b/runtime/observatory/lib/elements.html
index 419e2b3..0eeabc9 100644
--- a/runtime/observatory/lib/elements.html
+++ b/runtime/observatory/lib/elements.html
@@ -33,6 +33,7 @@
 <link rel="import" href="src/elements/object_view.html">
 <link rel="import" href="src/elements/observatory_application.html">
 <link rel="import" href="src/elements/observatory_element.html">
+<link rel="import" href="src/elements/ports.html">
 <link rel="import" href="src/elements/script_inset.html">
 <link rel="import" href="src/elements/script_ref.html">
 <link rel="import" href="src/elements/script_view.html">
diff --git a/runtime/observatory/lib/service.dart b/runtime/observatory/lib/service.dart
index 7715717..62b99dd 100644
--- a/runtime/observatory/lib/service.dart
+++ b/runtime/observatory/lib/service.dart
@@ -12,6 +12,7 @@
 import 'package:observatory/cpu_profile.dart';
 import 'package:observatory/object_graph.dart';
 import 'package:observatory/tracer.dart';
+import 'package:observatory/base64.dart';
 import 'package:observe/observe.dart';
 
 part 'src/service/object.dart';
diff --git a/runtime/observatory/lib/src/app/application.dart b/runtime/observatory/lib/src/app/application.dart
index 8c8e00e..ef565f5 100644
--- a/runtime/observatory/lib/src/app/application.dart
+++ b/runtime/observatory/lib/src/app/application.dart
@@ -93,6 +93,7 @@
       case ServiceEvent.kBreakpointResolved:
       case ServiceEvent.kBreakpointRemoved:
       case ServiceEvent.kGC:
+      case ServiceEvent.kDebuggerSettingsUpdate:
         // Ignore for now.
         break;
 
@@ -136,6 +137,7 @@
     _pageRegistry.add(new IsolateReconnectPage(this));
     _pageRegistry.add(new ErrorViewPage(this));
     _pageRegistry.add(new MetricsPage(this));
+    _pageRegistry.add(new PortsPage(this));
     // Note that ErrorPage must be the last entry in the list as it is
     // the catch all.
     _pageRegistry.add(new ErrorPage(this));
diff --git a/runtime/observatory/lib/src/app/page.dart b/runtime/observatory/lib/src/app/page.dart
index 1151f67..d678926 100644
--- a/runtime/observatory/lib/src/app/page.dart
+++ b/runtime/observatory/lib/src/app/page.dart
@@ -250,6 +250,21 @@
   }
 }
 
+class PortsPage extends SimplePage {
+  PortsPage(app)
+      : super('ports', 'ports-page', app);
+
+  void _visit(Uri uri) {
+    super._visit(uri);
+    getIsolate(uri).then((isolate) {
+      if (element != null) {
+        PortsPageElement page = element;
+        page.isolate = isolate;
+      }
+    });
+  }
+}
+
 class HeapMapPage extends SimplePage {
   HeapMapPage(app) : super('heap-map', 'heap-map', app);
 
diff --git a/runtime/observatory/lib/src/elements/debugger.dart b/runtime/observatory/lib/src/elements/debugger.dart
index 70d8516..2fc89da 100644
--- a/runtime/observatory/lib/src/elements/debugger.dart
+++ b/runtime/observatory/lib/src/elements/debugger.dart
@@ -110,21 +110,24 @@
     alias = 'p';
   }
 
-  Future run(List<String> args) {
+  Future run(List<String> args) async {
     if (args.length < 1) {
       debugger.console.print('print expects arguments');
-      return new Future.value(null);
+      return;
     }
-    var expr = args.join('');
-    return debugger.isolate.evalFrame(debugger.currentFrame, expr)
-      .then((ServiceObject response) {
-        if (response is DartError) {
-          debugger.console.print(response.message);
-        } else {
-          debugger.console.print('= ', newline:false);
-          debugger.console.printRef(response);
-        }
-      });
+    if (debugger.currentFrame == null) {
+      debugger.console.print('No stack');
+      return;
+    }
+    var expression = args.join('');
+    var response = await debugger.isolate.evalFrame(debugger.currentFrame,
+                                                    expression);
+    if (response is DartError) {
+      debugger.console.print(response.message);
+    } else {
+      debugger.console.print('= ', newline:false);
+      debugger.console.printRef(response);
+    }
   }
 
   String helpShort = 'Evaluate and print an expression in the current frame';
@@ -315,7 +318,9 @@
 }
 
 class StepCommand extends DebuggerCommand {
-  StepCommand(Debugger debugger) : super(debugger, 'step', []);
+  StepCommand(Debugger debugger) : super(debugger, 'step', []) {
+    alias = 's';
+  }
 
   Future run(List<String> args) {
     if (debugger.isolatePaused()) {
@@ -366,6 +371,35 @@
       'Syntax: finish\n';
 }
 
+class SetCommand extends DebuggerCommand {
+  SetCommand(Debugger debugger)
+      : super(debugger, 'set', []);
+
+  Future run(List<String> args) async {
+    if (args.length == 2) {
+      var option = args[0].trim();
+      if (option == 'break-on-exceptions') {
+        var result = await debugger.isolate.setExceptionPauseInfo(args[1]);
+        if (result.isError) {
+          debugger.console.print(result.toString());
+        }
+      } else {
+        debugger.console.print("unknown option '$option'");
+      }
+    } else {
+      debugger.console.print("set expects 2 arguments");
+    }
+  }
+
+  String helpShort =
+      'Set a debugger option';
+
+  String helpLong =
+      'Set a debugger option'
+      '\n'
+      'Syntax: set break-on-exceptions "all" | "none" | "unhandled"\n';
+}
+
 class BreakCommand extends DebuggerCommand {
   BreakCommand(Debugger debugger) : super(debugger, 'break', []);
 
@@ -826,8 +860,10 @@
   RootCommand cmd;
   DebuggerPageElement page;
   DebuggerConsoleElement console;
+  DebuggerInputElement input;
   DebuggerStackElement stackElement;
   ServiceMap stack;
+  String exceptions = "none";  // Last known setting.
 
   int get currentFrame => _currentFrame;
   void set currentFrame(int value) {
@@ -856,6 +892,7 @@
         new StepCommand(this),
         new FinishCommand(this),
         new BreakCommand(this),
+        new SetCommand(this),
         new ClearCommand(this),
         new DeleteCommand(this),
         new InfoCommand(this),
@@ -869,6 +906,11 @@
   void updateIsolate(Isolate iso) {
     _isolate = iso;
     if (_isolate != null) {
+      if (exceptions != iso.exceptionsPauseInfo) {
+        exceptions = iso.exceptionsPauseInfo;
+        console.print("Now pausing for $exceptions exceptions");
+      }
+
       _isolate.reload().then((response) {
         // TODO(turnidge): Currently the debugger relies on all libs
         // being loaded.  Fix this.
@@ -955,6 +997,7 @@
       } else {
         currentFrame = null;
       }
+      input.focus();
     });
   }
 
@@ -992,9 +1035,12 @@
           console.print('Paused at breakpoint ${bpId} at '
                         '${script.name}:${line}:${col}');
         } else if (event.exception != null) {
-          // TODO(turnidge): Test this.
-          console.print('Paused due to exception ${event.exception} at '
+          console.print('Paused due to exception at '
                         '${script.name}:${line}:${col}');
+          // This seems to be missing if we are paused-at-exception after
+          // paused-at-isolate-exit. Maybe we shutdown part of the debugger too
+          // soon?
+          console.printRef(event.exception);
         } else {
           console.print('Paused at ${script.name}:${line}:${col}');
         }
@@ -1056,6 +1102,13 @@
         }
         break;
 
+      case ServiceEvent.kDebuggerSettingsUpdate:
+        if (exceptions != event.exceptions) {
+          exceptions = event.exceptions;
+          console.print("Now pausing for $exceptions exceptions");
+        }
+        break;
+
       case ServiceEvent.kIsolateUpdate:
         var iso = event.owner;
         console.print("Isolate ${iso.number} renamed to '${iso.name}'");
@@ -1131,7 +1184,7 @@
         return completions[0];
       } else {
         // Ambigous completion.
-        completions = completions.map((s )=> s.trimRight()).toList();
+        completions = completions.map((s) => s.trimRight()).toList();
         console.printBold(completions.toString());
         return _foldCompletions(completions);
       }
@@ -1211,10 +1264,10 @@
     debugger.stackElement = stackElement;
     stackElement.debugger = debugger;
     debugger.console = $['console'];
-    $['commandline'].debugger = debugger;
+    debugger.input = $['commandline'];
+    debugger.input.debugger = debugger;
     debugger.init();
   }
-
 }
 
 @CustomTag('debugger-stack')
@@ -1667,6 +1720,10 @@
       });
   }
 
+  void focus() {
+    $['textBox'].focus();
+  }
+
   DebuggerInputElement.created() : super.created();
 }
 
diff --git a/runtime/observatory/lib/src/elements/function_view.html b/runtime/observatory/lib/src/elements/function_view.html
index 813fb2a..4b75325 100644
--- a/runtime/observatory/lib/src/elements/function_view.html
+++ b/runtime/observatory/lib/src/elements/function_view.html
@@ -54,7 +54,7 @@
 
         <template if="{{ function.code != null }}">
           <div class="memberItem">
-            <div class="memberName">optimized code</div>
+            <div class="memberName">current code</div>
             <div class="memberValue">
               <code-ref ref="{{ function.code }}"></code-ref>
             </div>
diff --git a/runtime/observatory/lib/src/elements/instance_ref.html b/runtime/observatory/lib/src/elements/instance_ref.html
index b6e86f4..10782d5 100644
--- a/runtime/observatory/lib/src/elements/instance_ref.html
+++ b/runtime/observatory/lib/src/elements/instance_ref.html
@@ -95,6 +95,20 @@
         </curly-block>
       </template>
 
+      <template if="{{ ref.isTypedData }}">
+        <a on-click="{{ goto }}" _href="{{ url }}"><em>{{ ref.clazz.name }}</em> ({{ ref.length }})</a>
+        <curly-block callback="{{ expander() }}">
+          <div class="memberList">
+            <template repeat="{{ index in ref.typedElements.asMap().keys }}">
+              <div class="memberItem">
+                <div class="memberName">[{{ index }}]</div>
+                <div class="memberValue">{{ ref.typedElements[index].toString() }}</div>
+              </div>
+            </template>
+          </div>
+        </curly-block>
+      </template>
+
       <template if="{{ ref.isMirrorReference }}">
         <a on-click="{{ goto }}" _href="{{ url }}"><em>{{ ref.clazz.name }}</em></a>
         <curly-block callback="{{ expander() }}">
diff --git a/runtime/observatory/lib/src/elements/instance_view.dart b/runtime/observatory/lib/src/elements/instance_view.dart
index 1513558..96a3b74 100644
--- a/runtime/observatory/lib/src/elements/instance_view.dart
+++ b/runtime/observatory/lib/src/elements/instance_view.dart
@@ -19,6 +19,16 @@
     return instance.evaluate(expression);
   }
 
+  Future setBreakOnActivation() {
+    return instance.isolate.addBreakOnActivation(instance)
+        .then((_) => refresh());
+  }
+
+  Future clearBreakOnActivation() {
+    return instance.isolate.removeBreakpoint(instance.activationBreakpoint)
+        .then((_) => refresh());
+  }
+
   Future refresh() {
     return instance.reload();
   }
diff --git a/runtime/observatory/lib/src/elements/instance_view.html b/runtime/observatory/lib/src/elements/instance_view.html
index fb39377..76a8bce 100644
--- a/runtime/observatory/lib/src/elements/instance_view.html
+++ b/runtime/observatory/lib/src/elements/instance_view.html
@@ -95,6 +95,22 @@
                 </any-service-ref>
               </div>
             </div>
+            <div class="memberItem">
+              <div class="memberName">closure breakpoint</div>
+              <div class="memberValue">
+                <template if="{{ instance.activationBreakpoint == null }}">
+                  <action-link callback="{{ setBreakOnActivation }}"
+                               label="break on activation">
+                  </action-link>
+                </template>
+                <template if="{{ instance.activationBreakpoint != null }}">
+                  {{ instance.activationBreakpoint.toString() }}
+                  <action-link callback="{{ clearBreakOnActivation }}"
+                               label="remove">
+                  </action-link>
+                </template>
+              </div>
+            </div>
           </template>
 
           <template if="{{ instance.isWeakProperty }}">
@@ -199,6 +215,25 @@
           </curly-block><br><br>
         </template>
 
+        <template if="{{ instance.typedElements.isNotEmpty }}">
+          elements ({{ instance.typedElements.length }})
+          <curly-block expand="{{ instance.typedElements.length <= 100 }}">
+            <div class="memberList">
+              <template repeat="{{ index in instance.typedElements.asMap().keys }}">
+                <div class="memberItem">
+                  <div class="memberName">[{{ index }}]</div>
+                  <div class="memberValue">{{ instance.typedElements[index].toString() }}</div>
+                </div>
+              </template>
+            </div>
+          </curly-block><br><br>
+        </template>
+      </div>
+
+      <div class="content-centered-big">
+        <template if="{{ instance.isClosure }}">
+          <source-inset location="{{ instance.function.location }}"></source-inset>
+        </template>
       </div>
 
     </template>
diff --git a/runtime/observatory/lib/src/elements/isolate_summary.html b/runtime/observatory/lib/src/elements/isolate_summary.html
index 2840e2a..823b581 100644
--- a/runtime/observatory/lib/src/elements/isolate_summary.html
+++ b/runtime/observatory/lib/src/elements/isolate_summary.html
@@ -186,6 +186,11 @@
             See <a on-click="{{ goto }}" _href="{{ gotoLink('/heap-snapshot', isolate) }}">heap snapshot</a>
           </div>
         </div>
+        <div class="memberItem">
+          <div class="memberValue">
+            See <a on-click="{{ goto }}" _href="{{ gotoLink('/ports', isolate) }}">ports</a>
+          </div>
+        </div>
         <!-- Temporarily disabled until UI for dart:io is acceptable.
         <template if="{{ isolate.ioEnabled }}">
           <div class="memberItem">
diff --git a/runtime/observatory/lib/src/elements/ports.dart b/runtime/observatory/lib/src/elements/ports.dart
new file mode 100644
index 0000000..dbe230e
--- /dev/null
+++ b/runtime/observatory/lib/src/elements/ports.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.
+
+library ports;
+
+import 'dart:async';
+import 'dart:html';
+import 'observatory_element.dart';
+import 'package:observatory/app.dart';
+import 'package:observatory/service.dart';
+import 'package:polymer/polymer.dart';
+
+@CustomTag('ports-page')
+class PortsPageElement extends ObservatoryElement {
+  PortsPageElement.created() : super.created();
+
+  @observable Isolate isolate;
+  @observable /*ObservableList | ServiceObject*/ ports;
+
+  void isolateChanged(oldValue) {
+    if (isolate != null) {
+      isolate.getPorts().then(_refreshView);
+    }
+  }
+
+  Future refresh() {
+    return isolate.getPorts().then(_refreshView);
+  }
+
+  _refreshView(/*ObservableList | ServiceObject*/ object) {
+    ports = object['ports'];
+  }
+}
diff --git a/runtime/observatory/lib/src/elements/ports.html b/runtime/observatory/lib/src/elements/ports.html
new file mode 100644
index 0000000..70aac0b
--- /dev/null
+++ b/runtime/observatory/lib/src/elements/ports.html
@@ -0,0 +1,43 @@
+<link rel="import" href="../../../../packages/polymer/polymer.html">
+<link rel="import" href="nav_bar.html">
+<link rel="import" href="observatory_element.html">
+
+<polymer-element name="ports-page" extends="observatory-element">
+  <template>
+    <link rel="stylesheet" href="css/shared.css">
+    <style>
+      ul li:hover:not(.selected) {
+        background-color: #FFF3E3;
+      }
+      .selected {
+        background-color: #0489c3;
+      }
+      .graph {
+        min-height: 600px;
+      }
+    </style>
+    <nav-bar>
+      <top-nav-menu></top-nav-menu>
+      <vm-nav-menu vm="{{ isolate.vm }}"></vm-nav-menu>
+      <isolate-nav-menu isolate="{{ isolate }}"></isolate-nav-menu>
+      <nav-menu link="{{ makeLink('/ports', isolate) }}" anchor="ports" last="{{ true }}"></nav-menu>
+      <nav-refresh callback="{{ refresh }}"></nav-refresh>
+    </nav-bar>
+    <div class="content">
+      <h1>Ports</h1>
+      <hr>
+      <div class="memberList">
+        <template repeat="{{ port in ports }}">
+          <div class="memberItem">
+            <div class="memberName">{{ port['name'] }}</div>
+            <div class="memberValue">
+              <any-service-ref ref="{{ port['handler'] }}"></any-service-ref>
+            </div>
+          </div>
+        </template>
+      </div>
+      <hr>
+      <view-footer></view-footer>
+    </div>
+  </template>
+</polymer-element>
diff --git a/runtime/observatory/lib/src/elements/script_inset.dart b/runtime/observatory/lib/src/elements/script_inset.dart
index 3a2cb6c..791534f 100644
--- a/runtime/observatory/lib/src/elements/script_inset.dart
+++ b/runtime/observatory/lib/src/elements/script_inset.dart
@@ -449,7 +449,7 @@
 
     addCurrentExecutionAnnotation();
 
-    if (!inDebuggerContext) {
+    if (!inDebuggerContext && script.library != null) {
       loadDeclarationsOfLibrary(script.library);
 
       // Add fields before functions so they beat out conflicting
diff --git a/runtime/observatory/lib/src/service/object.dart b/runtime/observatory/lib/src/service/object.dart
index 75c0918..4a7ad32 100644
--- a/runtime/observatory/lib/src/service/object.dart
+++ b/runtime/observatory/lib/src/service/object.dart
@@ -117,6 +117,7 @@
   bool get isInt => false;
   bool get isList => false;
   bool get isMap => false;
+  bool get isTypedData => false;
   bool get isMirrorReference => false;
   bool get isWeakProperty => false;
   bool get isClosure => false;
@@ -130,7 +131,8 @@
 
   /// Is this object cacheable?  That is, is it impossible for the [id]
   /// of this object to change?
-  bool get canCache => false;
+  bool _canCache;
+  bool get canCache => _canCache;
 
   /// Is this object immutable after it is [loaded]?
   bool get immutable => false;
@@ -303,6 +305,7 @@
     var mapType = _stripRef(map['type']);
     assert(_type == null || _type == mapType);
 
+    _canCache = map['fixedId'] == true;
     if (_id != null && _id != map['id']) {
       // It is only safe to change an id when the object isn't cacheable.
       assert(!canCache);
@@ -881,6 +884,10 @@
         .then(_buildClassHierarchy);
   }
 
+  Future<ServiceObject> getPorts() {
+    return invokeRpc('_getPorts', {});
+  }
+
   Future<List<Class>> getClassRefs() async {
     ServiceMap classList = await invokeRpc('getClassList', {});
     assert(classList.type == 'ClassList');
@@ -1107,6 +1114,7 @@
 
     updateHeapsFromMap(map['_heaps']);
     _updateBreakpoints(map['breakpoints']);
+    exceptionsPauseInfo = map['_debuggerSettings']['_exceptions'];
 
     pauseEvent = map['pauseEvent'];
     _updateRunState();
@@ -1127,6 +1135,7 @@
   }
 
   ObservableMap<int, Breakpoint> breakpoints = new ObservableMap();
+  String exceptionsPauseInfo;
 
   void _updateBreakpoints(List newBpts) {
     // Build a set of new breakpoints.
@@ -1169,6 +1178,7 @@
 
       case ServiceEvent.kIsolateUpdate:
       case ServiceEvent.kBreakpointResolved:
+      case ServiceEvent.kDebuggerSettingsUpdate:
         // Update occurs as side-effect of caching.
         break;
 
@@ -1264,6 +1274,10 @@
     return invokeRpc('setName', {'name': newName});
   }
 
+  Future setExceptionPauseInfo(String exceptions) {
+    return invokeRpc('_setExceptionPauseInfo', {'exceptions': exceptions});
+  }
+
   Future<ServiceMap> getStack() {
     return invokeRpc('getStack', {});
   }
@@ -1454,22 +1468,23 @@
 /// A [ServiceEvent] is an asynchronous event notification from the vm.
 class ServiceEvent extends ServiceObject {
   /// The possible 'kind' values.
-  static const kIsolateStart       = 'IsolateStart';
-  static const kIsolateExit        = 'IsolateExit';
-  static const kIsolateUpdate      = 'IsolateUpdate';
-  static const kPauseStart         = 'PauseStart';
-  static const kPauseExit          = 'PauseExit';
-  static const kPauseBreakpoint    = 'PauseBreakpoint';
-  static const kPauseInterrupted   = 'PauseInterrupted';
-  static const kPauseException     = 'PauseException';
-  static const kResume             = 'Resume';
-  static const kBreakpointAdded    = 'BreakpointAdded';
-  static const kBreakpointResolved = 'BreakpointResolved';
-  static const kBreakpointRemoved  = 'BreakpointRemoved';
-  static const kGraph              = '_Graph';
-  static const kGC                 = 'GC';
-  static const kInspect            = 'Inspect';
-  static const kConnectionClosed   = 'ConnectionClosed';
+  static const kIsolateStart           = 'IsolateStart';
+  static const kIsolateExit            = 'IsolateExit';
+  static const kIsolateUpdate          = 'IsolateUpdate';
+  static const kPauseStart             = 'PauseStart';
+  static const kPauseExit              = 'PauseExit';
+  static const kPauseBreakpoint        = 'PauseBreakpoint';
+  static const kPauseInterrupted       = 'PauseInterrupted';
+  static const kPauseException         = 'PauseException';
+  static const kResume                 = 'Resume';
+  static const kBreakpointAdded        = 'BreakpointAdded';
+  static const kBreakpointResolved     = 'BreakpointResolved';
+  static const kBreakpointRemoved      = 'BreakpointRemoved';
+  static const kGraph                  = '_Graph';
+  static const kGC                     = 'GC';
+  static const kInspect                = 'Inspect';
+  static const kDebuggerSettingsUpdate = '_DebuggerSettingsUpdate';
+  static const kConnectionClosed       = 'ConnectionClosed';
 
   ServiceEvent._empty(ServiceObjectOwner owner) : super._empty(owner);
 
@@ -1480,11 +1495,12 @@
   @observable String kind;
   @observable Breakpoint breakpoint;
   @observable Frame topFrame;
-  @observable ServiceMap exception;
+  @observable Instance exception;
   @observable ServiceObject inspectee;
   @observable ByteData data;
   @observable int count;
   @observable String reason;
+  @observable String exceptions;
   int chunkIndex, chunkCount, nodeCount;
 
   @observable bool get isPauseEvent {
@@ -1536,6 +1552,10 @@
     if (map['count'] != null) {
       count = map['count'];
     }
+    if (map['_debuggerSettings'] != null &&
+        map['_debuggerSettings']['_exceptions'] != null) {
+      exceptions = map['_debuggerSettings']['_exceptions'];
+    }
   }
 
   String toString() {
@@ -1854,16 +1874,18 @@
   @observable ServiceFunction function;  // If a closure.
   @observable Context context;  // If a closure.
   @observable String name;  // If a Type.
-  @observable int length; // If a List or Map.
+  @observable int length; // If a List, Map or TypedData.
 
   @observable var typeClass;
   @observable var fields;
   @observable var nativeFields;
   @observable var elements;  // If a List.
   @observable var associations;  // If a Map.
+  @observable var typedElements;  // If a TypedData.
   @observable var referent;  // If a MirrorReference.
   @observable Instance key;  // If a WeakProperty.
   @observable Instance value;  // If a WeakProperty.
+  @observable Breakpoint activationBreakpoint;  // If a Closure.
 
   bool get isAbstractType {
     return (kind == 'Type' || kind == 'TypeRef' ||
@@ -1876,6 +1898,22 @@
   bool get isInt => kind == 'Int';
   bool get isList => kind == 'List';
   bool get isMap => kind == 'Map';
+  bool get isTypedData {
+    return kind == 'Uint8ClampedList'
+        || kind == 'Uint8List'
+        || kind == 'Uint16List'
+        || kind == 'Uint32List'
+        || kind == 'Uint64List'
+        || kind == 'Int8List'
+        || kind == 'Int16List'
+        || kind == 'Int32List'
+        || kind == 'Int64List'
+        || kind == 'Float32List'
+        || kind == 'Float64List'
+        || kind == 'Int32x4List'
+        || kind == 'Float32x4List'
+        || kind == 'Float64x2List';
+  }
   bool get isMirrorReference => kind == 'MirrorReference';
   bool get isWeakProperty => kind == 'WeakProperty';
   bool get isClosure => kind == 'Closure';
@@ -1909,10 +1947,44 @@
     fields = map['fields'];
     elements = map['elements'];
     associations = map['associations'];
+    if (map['bytes'] != null) {
+      var bytes = decodeBase64(map['bytes']);
+      switch (map['kind']) {
+        case "Uint8ClampedList":
+          typedElements = bytes.buffer.asUint8ClampedList(); break;
+        case "Uint8List":
+          typedElements = bytes.buffer.asUint8List(); break;
+        case "Uint16List":
+          typedElements = bytes.buffer.asUint16List(); break;
+        case "Uint32List":
+          typedElements = bytes.buffer.asUint32List(); break;
+        case "Uint64List":
+          typedElements = bytes.buffer.asUint64List(); break;
+        case "Int8List":
+          typedElements = bytes.buffer.asInt8List(); break;
+        case "Int16List":
+          typedElements = bytes.buffer.asInt16List(); break;
+        case "Int32List":
+          typedElements = bytes.buffer.asInt32List(); break;
+        case "Int64List":
+          typedElements = bytes.buffer.asInt64List(); break;
+        case "Float32List":
+          typedElements = bytes.buffer.asFloat32List(); break;
+        case "Float64List":
+          typedElements = bytes.buffer.asFloat64List(); break;
+        case "Int32x4List":
+          typedElements = bytes.buffer.asInt32x4List(); break;
+        case "Float32x4List":
+          typedElements = bytes.buffer.asFloat32x4List(); break;
+        case "Float64x2List":
+          typedElements = bytes.buffer.asFloat64x2List(); break;
+      }
+    }
     typeClass = map['typeClass'];
     referent = map['mirrorReferent'];
     key = map['propertyKey'];
     value = map['propertyValue'];
+    activationBreakpoint = map['_activationBreakpoint'];
 
     // We are fully loaded.
     _loaded = true;
@@ -2040,7 +2112,6 @@
   @observable bool isDart;
   @observable ProfileFunction profile;
 
-  bool get canCache => true;
   bool get immutable => false;
 
   ServiceFunction._empty(ServiceObject owner) : super._empty(owner);
@@ -2101,7 +2172,7 @@
   @observable String vmName;
 
   @observable bool guardNullable;
-  @observable String guardClass;
+  @observable var /* Class | String */ guardClass;
   @observable String guardLength;
   @observable SourceLocation location;
 
@@ -2293,7 +2364,7 @@
   @observable int lineOffset;
   @observable int columnOffset;
   @observable Library library;
-  bool get canCache => true;
+
   bool get immutable => true;
 
   String _shortUri;
@@ -2483,7 +2554,7 @@
       return r;
     }
 
-    final lastColumn = tokenToCol(endTokenPos);
+    var lastColumn = tokenToCol(endTokenPos);
     if (lastColumn == null) {
       return r;
     }
@@ -2507,6 +2578,11 @@
     if (line == lastLine) {
       // Only one line.
       if (!getLine(line).isTrivialLine) {
+        // TODO(johnmccutchan): end token pos -> column can lie for snapshotted
+        // code. e.g.:
+        // io_sink.dart source line 23 ends at column 39
+        // io_sink.dart snapshotted source line 23 ends at column 35.
+        lastColumn = math.min(getLine(line).text.length, lastColumn);
         lineContents = getLine(line).text.substring(column, lastColumn - 1);
         return scanLineForLocalVariableLocations(pattern,
                                                   name,
@@ -2543,6 +2619,11 @@
 
     // Scan last line.
     if (!getLine(line).isTrivialLine) {
+      // TODO(johnmccutchan): end token pos -> column can lie for snapshotted
+      // code. e.g.:
+      // io_sink.dart source line 23 ends at column 39
+      // io_sink.dart snapshotted source line 23 ends at column 35.
+      lastColumn = math.min(getLine(line).text.length, lastColumn);
       lineContents = getLine(line).text.substring(0, lastColumn - 1);
       r.addAll(
           scanLineForLocalVariableLocations(pattern,
@@ -2782,7 +2863,7 @@
 
 class Code extends ServiceObject {
   @observable CodeKind kind;
-  @observable Instance objectPool;
+  @observable ServiceObject objectPool;
   @observable ServiceFunction function;
   @observable Script script;
   @observable bool isOptimized = false;
@@ -2794,7 +2875,7 @@
       new List<CodeInlineInterval>();
   final ObservableList<ServiceFunction> inlinedFunctions =
       new ObservableList<ServiceFunction>();
-  bool get canCache => true;
+
   bool get immutable => true;
 
   Code._empty(ServiceObjectOwner owner) : super._empty(owner);
@@ -2819,7 +2900,8 @@
     if (function == null) {
       return;
     }
-    if (function.location.script == null) {
+    if ((function.location == null) ||
+        (function.location.script == null)) {
       // Attempt to load the function.
       function.load().then((func) {
         var script = function.location.script;
@@ -3202,6 +3284,8 @@
     this.code = map['code'];
     this.variables = map['vars'];
   }
+
+  String toString() => "Frame(${function.qualifiedName})";
 }
 
 
diff --git a/runtime/observatory/observatory_sources.gypi b/runtime/observatory/observatory_sources.gypi
index ea6c1e2..7b5f63d 100644
--- a/runtime/observatory/observatory_sources.gypi
+++ b/runtime/observatory/observatory_sources.gypi
@@ -6,6 +6,7 @@
 {
   'sources': [
     'lib/app.dart',
+    'lib/base64.dart',
     'lib/cli.dart',
     'lib/cpu_profile.dart',
     'lib/debugger.dart',
@@ -110,6 +111,8 @@
     'lib/src/elements/observatory_application.html',
     'lib/src/elements/observatory_element.dart',
     'lib/src/elements/observatory_element.html',
+    'lib/src/elements/ports.dart',
+    'lib/src/elements/ports.html',
     'lib/src/elements/script_inset.dart',
     'lib/src/elements/script_inset.html',
     'lib/src/elements/script_ref.dart',
diff --git a/runtime/observatory/tests/service/break_on_activation_test.dart b/runtime/observatory/tests/service/break_on_activation_test.dart
index 9029587..b266954 100644
--- a/runtime/observatory/tests/service/break_on_activation_test.dart
+++ b/runtime/observatory/tests/service/break_on_activation_test.dart
@@ -75,6 +75,8 @@
   print("Added breakpoint $bpt1");
   expect(bpt1 is Breakpoint, isTrue);
   expect(breaksHit, equals(0));
+  await r1Ref.reload();
+  expect(r1Ref.activationBreakpoint, equals(bpt1));
   print("testeeDo()");
   var res = await rootLib.evaluate("testeeDo()");
   expect(res is Instance, isTrue); // Not error.
@@ -83,6 +85,8 @@
   await isolate.removeBreakpoint(bpt1);
   print("Removed breakpoint $bpt1");
   print("testeeDo()");
+  await r1Ref.reload();
+  expect(r1Ref.activationBreakpoint, equals(null));
   res = await rootLib.evaluate("testeeDo()");
   expect(res is Instance, isTrue); // Not error.
   expect(breaksHit, equals(1));
@@ -115,6 +119,8 @@
   print("Added breakpoint $bpt1");
   expect(bpt1 is Breakpoint, isTrue);
   expect(breaksHit, equals(0));
+  await r1Ref.reload();
+  expect(r1Ref.activationBreakpoint, equals(bpt1));
   print("testeeDoNamed()");
   var res = await rootLib.evaluate("testeeDoNamed()");
   expect(res is Instance, isTrue); // Not error.
@@ -122,6 +128,8 @@
 
   await isolate.removeBreakpoint(bpt1);
   print("Removed breakpoint $bpt1");
+  await r1Ref.reload();
+  expect(r1Ref.activationBreakpoint, equals(null));
   print("testeeDoNamed()");
   res = await rootLib.evaluate("testeeDoNamed()");
   expect(res is Instance, isTrue); // Not error.
@@ -156,6 +164,8 @@
   print("Added breakpoint $bpt1");
   expect(bpt1 is Breakpoint, isTrue);
   expect(breaksHit, equals(0));
+  await r1Ref.reload();
+  expect(r1Ref.activationBreakpoint, equals(bpt1));
   print("testeeDo()");
   var res = await rootLib.evaluate("testeeDo()");
   expect(res is Instance, isTrue); // Not error.
@@ -165,6 +175,8 @@
   print("Added breakpoint $bpt2");
   expect(bpt2 is Breakpoint, isTrue);
   expect(breaksHit, equals(1));
+  await r2Ref.reload();
+  expect(r2Ref.activationBreakpoint, equals(bpt2));
   print("testeeDo()");
   res = await rootLib.evaluate("testeeDo()");
   expect(res is Instance, isTrue); // Not error.
@@ -172,6 +184,8 @@
 
   await isolate.removeBreakpoint(bpt1);
   print("Removed breakpoint $bpt1");
+  await r1Ref.reload();
+  expect(r1Ref.activationBreakpoint, equals(null));
   print("testeeDo()");
   res = await rootLib.evaluate("testeeDo()");
   expect(res is Instance, isTrue); // Not error.
@@ -179,6 +193,8 @@
 
   await isolate.removeBreakpoint(bpt2);
   print("Removed breakpoint $bpt2");
+  await r2Ref.reload();
+  expect(r2Ref.activationBreakpoint, equals(null));
   print("testeeDo()");
   res = await rootLib.evaluate("testeeDo()");
   expect(res is Instance, isTrue); // Not error.
diff --git a/runtime/observatory/tests/service/get_ports_rpc_test.dart b/runtime/observatory/tests/service/get_ports_rpc_test.dart
new file mode 100644
index 0000000..58081a0
--- /dev/null
+++ b/runtime/observatory/tests/service/get_ports_rpc_test.dart
@@ -0,0 +1,56 @@
+// 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.
+// VMOptions=--compile-all --error_on_bad_type --error_on_bad_override
+
+library get_ports_rpc_test;
+
+import 'dart:async';
+import 'dart:isolate' hide Isolate;
+import 'package:observatory/service_io.dart';
+import 'package:unittest/unittest.dart';
+
+import 'test_helper.dart';
+
+var port1;
+var port2;
+
+void warmup() {
+  port1 = new RawReceivePort(null);
+  port2 = new RawReceivePort((_) {
+  });
+}
+
+int countHandlerMatches(ports, matcher) {
+  var matches = 0;
+  for (var port in ports) {
+    if (matcher(port['handler'])) {
+      matches++;
+    }
+  }
+  return matches;
+}
+
+bool nullMatcher(handler) {
+  return handler.isNull;
+}
+
+bool closureMatcher(handler) {
+  return handler.isClosure;
+}
+
+var tests = [
+  (Isolate isolate) async {
+    var result = await isolate.invokeRpc('_getPorts', {});
+    expect(result['type'], equals('_Ports'));
+    expect(result['ports'], isList);
+    var ports = result['ports'];
+    // There are three ports: the two created in warmup and the stdin listener
+    // created by the test harness.
+    expect(ports.length, equals(3));
+    expect(countHandlerMatches(ports, nullMatcher), equals(1));
+    expect(countHandlerMatches(ports, closureMatcher), equals(2));
+  },
+];
+
+main(args) async => runIsolateTests(args, tests, testeeBefore:warmup);
diff --git a/runtime/observatory/tests/service/graph_test.dart b/runtime/observatory/tests/service/graph_test.dart
index dd94d5c..c3de708 100644
--- a/runtime/observatory/tests/service/graph_test.dart
+++ b/runtime/observatory/tests/service/graph_test.dart
@@ -71,7 +71,7 @@
                                       bVertex.shallowSize +
                                       rVertex.shallowSize));
 
-  const int fixedSizeListCid = 61;
+  const int fixedSizeListCid = 62;
   List<ObjectVertex> lists = new List.from(graph.vertices.where(
       (ObjectVertex obj) => obj.vmCid == fixedSizeListCid));
   expect(lists.length >= 2, isTrue);
diff --git a/runtime/observatory/tests/service/pause_on_exceptions_test.dart b/runtime/observatory/tests/service/pause_on_exceptions_test.dart
new file mode 100644
index 0000000..d8926fe
--- /dev/null
+++ b/runtime/observatory/tests/service/pause_on_exceptions_test.dart
@@ -0,0 +1,111 @@
+// 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.
+// VMOptions=--compile_all --error_on_bad_type --error_on_bad_override
+
+import 'package:observatory/service_io.dart';
+import 'package:unittest/unittest.dart';
+import 'test_helper.dart';
+import 'dart:async';
+import 'dart:developer';
+
+doThrow() {
+  throw "TheException"; // Line 13.
+  return "end of doThrow";
+}
+
+doCaught() {
+  try {
+    doThrow();
+  } catch (e) {}
+  return "end of doCaught";
+}
+
+doUncaught() {
+  doThrow();
+  return "end of doUncaught";
+}
+
+var tests = [
+
+(Isolate isolate) async {
+  var lib = await isolate.rootLibrary.reload();
+
+  var onPaused = null;
+  var onResume = null;
+
+  var subscription;
+  subscription = isolate.vm.events.stream.listen((ServiceEvent event) {
+    print("Event $event");
+    if (event.kind == ServiceEvent.kPauseException) {
+      if (onPaused == null) throw "Unexpected pause event $event";
+      var t = onPaused;
+      onPaused = null;
+      t.complete(event);
+    }
+    if (event.kind == ServiceEvent.kResume) {
+      if (onResume == null) throw "Unexpected resume event $event";
+      var t = onResume;
+      onResume = null;
+      t.complete(event);
+    }
+  });
+
+  test(String pauseInfo,
+       String expression,
+       bool shouldPause,
+       bool shouldBeCaught) async {
+    print("Evaluating $expression with pause on $pauseInfo exception");
+
+    expect((await isolate.setExceptionPauseInfo(pauseInfo)) is DartError,
+           isFalse);
+
+    var t;
+    if (shouldPause) {
+      t = new Completer();
+      onPaused = t;
+    }
+    var fres = lib.evaluate(expression);
+    if (shouldPause) {
+      await t.future;
+
+      var stack = await isolate.getStack();
+      expect(stack['frames'][0].function.name, equals('doThrow'));
+      // Ugh, no .line. expect(stack['frames'][0].location.line, equals(17));
+
+      t = new Completer();
+      onResume = t;
+      isolate.resume();
+      await t.future;
+    }
+
+    var res = await fres;
+    print(res);
+    if (shouldBeCaught) {
+      expect(res.isInstance, isTrue);
+      expect(res.isString, isTrue);
+      expect(res.valueAsString, equals("end of doCaught"));
+    } else {
+      expect(res.isError, isTrue);
+      await res.load(); // Weird?
+      expect(res.exception.isInstance, isTrue);
+      expect(res.exception.isString, isTrue);
+      expect(res.exception.valueAsString, equals("TheException"));
+    }
+  }
+
+  await test("all", "doCaught()", true, true);
+  await test("all", "doUncaught()", true, false);
+
+  await test("unhandled", "doCaught()", false, true);
+  await test("unhandled", "doUncaught()", true, false);
+
+  await test("none", "doCaught()", false, true);
+  await test("none", "doUncaught()", false, false);
+
+  subscription.cancel();
+},
+
+];
+
+main(args) => runIsolateTests(args, tests);
diff --git a/runtime/observatory/tests/service/typed_data_test.dart b/runtime/observatory/tests/service/typed_data_test.dart
new file mode 100644
index 0000000..f0070a0
--- /dev/null
+++ b/runtime/observatory/tests/service/typed_data_test.dart
@@ -0,0 +1,139 @@
+// 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.
+// VMOptions=--compile-all --error_on_bad_type --error_on_bad_override
+
+library typed_data_test;
+
+import 'dart:typed_data';
+import 'package:observatory/service_io.dart';
+import 'package:unittest/unittest.dart';
+import 'test_helper.dart';
+
+var int8List;
+var int16List;
+var int32List;
+var int64List;
+
+var uint8List;
+var uint16List;
+var uint32List;
+var uint64List;
+var uint8ClampedList;
+
+var float32List;
+var float64List;
+
+var int32x4;
+var float32x4;
+var float64x2;
+var int32x4List;
+var float32x4List;
+var float64x2List;
+
+void script() {
+  int8List = new Int8List(2);
+  int8List[0] = -1;
+  int8List[1] = -2;
+  int16List = new Int16List(2);
+  int16List[0] = -3;
+  int16List[1] = -4;
+  int32List = new Int32List(2);
+  int32List[0] = -5;
+  int32List[1] = -6;
+  int64List = new Int64List(2);
+  int64List[0] = -7;
+  int64List[1] = -8;
+
+  uint8List = new Uint8List(2);
+  uint8List[0] = 1;
+  uint8List[1] = 2;
+  uint16List = new Uint16List(2);
+  uint16List[0] = 3;
+  uint16List[1] = 4;
+  uint32List = new Uint32List(2);
+  uint32List[0] = 5;
+  uint32List[1] = 6;
+  uint64List = new Uint64List(2);
+  uint64List[0] = 7;
+  uint64List[1] = 8;
+  uint8ClampedList = new Uint8ClampedList(2);
+  uint8ClampedList[0] = 9;
+  uint8ClampedList[1] = 10;
+
+  float32List = new Float32List(2);
+  float32List[0] = 4.25;
+  float32List[1] = 8.50;
+  float64List = new Float64List(2);
+  float64List[0] = 16.25;
+  float64List[1] = 32.50;
+
+  int32x4 = new Int32x4(1, 2, 3, 4);
+  float32x4 = new Float32x4(1.0, 2.0, 4.0, 8.0);
+  float64x2 = new Float64x2(16.0, 32.0);
+  int32x4List = new Int32x4List(2);
+  float32x4List = new Float32x4List(2);
+  float64x2List = new Float64x2List(2);
+}
+
+var tests = [
+
+  (Isolate isolate) async {
+    script();
+    var lib = await isolate.rootLibrary.load();
+
+    // Pre-load all the fields so we don't use await below and get better
+    // stacktraces.
+    for (var v in lib.variables) {
+      await v.load();
+      await v.staticValue.load();
+    }
+
+    expectTypedData(name, expectedValue) {
+      var variable = lib.variables.singleWhere((v) => v.name == name);
+      var actualValue = variable.staticValue.typedElements;
+      if (expectedValue is Int32x4List) {
+        expect(actualValue.length, equals(expectedValue.length));
+        for (var i = 0; i < actualValue.length; i++) {
+          expect(actualValue[i].x, equals(expectedValue[i].x));
+          expect(actualValue[i].y, equals(expectedValue[i].y));
+          expect(actualValue[i].z, equals(expectedValue[i].z));
+          expect(actualValue[i].w, equals(expectedValue[i].w));
+        }
+      } else if (expectedValue is Float32x4List) {
+        expect(actualValue.length, equals(expectedValue.length));
+        for (var i = 0; i < actualValue.length; i++) {
+          expect(actualValue[i].x, equals(expectedValue[i].x));
+          expect(actualValue[i].y, equals(expectedValue[i].y));
+          expect(actualValue[i].z, equals(expectedValue[i].z));
+          expect(actualValue[i].w, equals(expectedValue[i].w));
+        }
+      } else if (expectedValue is Float64x2List) {
+        expect(actualValue.length, equals(expectedValue.length));
+        for (var i = 0; i < actualValue.length; i++) {
+          expect(actualValue[i].x, equals(expectedValue[i].x));
+          expect(actualValue[i].y, equals(expectedValue[i].y));
+        }
+      } else {
+        expect(actualValue, equals(expectedValue));
+      }
+    }
+    expectTypedData("int8List", int8List);
+    expectTypedData("int16List", int16List);
+    expectTypedData("int32List", int32List);
+    expectTypedData("int64List", int64List);
+    expectTypedData("uint8List", uint8List);
+    expectTypedData("uint16List", uint16List);
+    expectTypedData("uint32List", uint32List);
+    expectTypedData("uint64List", uint64List);
+    expectTypedData("uint8ClampedList", uint8ClampedList);
+    expectTypedData("float32List", float32List);
+    expectTypedData("float64List", float64List);
+    expectTypedData("int32x4List", int32x4List);
+    expectTypedData("float32x4List", float32x4List);
+    expectTypedData("float64x2List", float64x2List);
+  },
+
+];
+
+main(args) => runIsolateTests(args, tests, testeeBefore: script);
diff --git a/runtime/observatory/web/main.dart b/runtime/observatory/web/main.dart
index 8e316d9..928bd61 100644
--- a/runtime/observatory/web/main.dart
+++ b/runtime/observatory/web/main.dart
@@ -19,7 +19,8 @@
       print('${rec.level.name}: ${rec.time}: ${rec.message}');
   });
   Logger.root.info('Starting Observatory');
-  GoogleChart.initOnce().then((_) {
+  var chartsLoaded = GoogleChart.initOnce();
+  chartsLoaded.then((_) {
     // Charts loaded, initialize polymer.
     initPolymer().then((zone) {
       Logger.root.info('Polymer initialized');
diff --git a/runtime/platform/globals.h b/runtime/platform/globals.h
index c4343b5..cdca889 100644
--- a/runtime/platform/globals.h
+++ b/runtime/platform/globals.h
@@ -341,6 +341,15 @@
 typedef intptr_t word;
 typedef uintptr_t uword;
 
+// Size of a class id.
+#if defined(ARCH_IS_32_BIT)
+typedef uint16_t classid_t;
+#elif defined(ARCH_IS_64_BIT)
+typedef uint32_t classid_t;
+#else
+#error Unexpected architecture word size
+#endif
+
 // Byte sizes.
 const int kWordSize = sizeof(word);
 const int kDoubleSize = sizeof(double);  // NOLINT
@@ -348,6 +357,7 @@
 const int kQuadSize = 4 * kFloatSize;
 const int kSimd128Size = sizeof(simd128_value_t);  // NOLINT
 const int kInt32Size = sizeof(int32_t);  // NOLINT
+const int kInt16Size = sizeof(int16_t);  // NOLINT
 #ifdef ARCH_IS_32_BIT
 const int kWordSizeLog2 = 2;
 const uword kUwordMax = kMaxUint32;
diff --git a/runtime/vm/assembler.cc b/runtime/vm/assembler.cc
index 23d08e0..cefafb8 100644
--- a/runtime/vm/assembler.cc
+++ b/runtime/vm/assembler.cc
@@ -242,61 +242,94 @@
 }
 
 
-intptr_t ObjectPool::AddObject(const Object& obj, Patchability patchable) {
+intptr_t ObjectPoolWrapper::AddObject(const Object& obj) {
+  return AddObject(ObjectPool::Entry(&obj), kNotPatchable);
+}
+
+
+intptr_t ObjectPoolWrapper::AddImmediate(uword imm) {
+  return AddObject(ObjectPool::Entry(imm, ObjectPool::kImmediate),
+                   kNotPatchable);
+}
+
+intptr_t ObjectPoolWrapper::AddObject(ObjectPool::Entry entry,
+                                      Patchability patchable) {
   // The object pool cannot be used in the vm isolate.
   ASSERT(Isolate::Current() != Dart::vm_isolate());
-  if (object_pool_.IsNull()) {
-    object_pool_ = GrowableObjectArray::New(Heap::kOld);
-  }
-  object_pool_.Add(obj, Heap::kOld);
-  patchable_pool_entries_.Add(patchable);
+  object_pool_.Add(entry);
   if (patchable == kNotPatchable) {
     // The object isn't patchable. Record the index for fast lookup.
     object_pool_index_table_.Insert(
-        ObjIndexPair(&obj, object_pool_.Length() - 1));
+        ObjIndexPair(entry, object_pool_.length() - 1));
   }
-  return object_pool_.Length() - 1;
+  return object_pool_.length() - 1;
 }
 
 
-intptr_t ObjectPool::AddExternalLabel(const ExternalLabel* label,
-                                      Patchability patchable) {
+intptr_t ObjectPoolWrapper::AddExternalLabel(const ExternalLabel* label,
+                                             Patchability patchable) {
   ASSERT(Isolate::Current() != Dart::vm_isolate());
-  const uword address = label->address();
-  ASSERT(Utils::IsAligned(address, 4));
-  // The address is stored in the object array as a RawSmi.
-  const Smi& smi = Smi::Handle(reinterpret_cast<RawSmi*>(address));
-  return AddObject(smi, patchable);
+  return AddObject(ObjectPool::Entry(label->address(),
+                                     ObjectPool::kImmediate),
+                   patchable);
 }
 
 
-intptr_t ObjectPool::FindObject(const Object& obj, Patchability patchable) {
+intptr_t ObjectPoolWrapper::FindObject(ObjectPool::Entry entry,
+                                       Patchability patchable) {
   // The object pool cannot be used in the vm isolate.
   ASSERT(Isolate::Current() != Dart::vm_isolate());
 
   // If the object is not patchable, check if we've already got it in the
   // object pool.
-  if (patchable == kNotPatchable && !object_pool_.IsNull()) {
-    intptr_t idx = object_pool_index_table_.Lookup(&obj);
+  if (patchable == kNotPatchable) {
+    intptr_t idx = object_pool_index_table_.Lookup(entry);
     if (idx != ObjIndexPair::kNoIndex) {
-      ASSERT(patchable_pool_entries_[idx] == kNotPatchable);
       return idx;
     }
   }
 
-  return AddObject(obj, patchable);
+  return AddObject(entry, patchable);
 }
 
 
-intptr_t ObjectPool::FindExternalLabel(const ExternalLabel* label,
-                                       Patchability patchable) {
+intptr_t ObjectPoolWrapper::FindObject(const Object& obj) {
+  return FindObject(ObjectPool::Entry(&obj), kNotPatchable);
+}
+
+
+intptr_t ObjectPoolWrapper::FindImmediate(uword imm) {
+  return FindObject(ObjectPool::Entry(imm, ObjectPool::kImmediate),
+                    kNotPatchable);
+}
+
+
+intptr_t ObjectPoolWrapper::FindExternalLabel(const ExternalLabel* label,
+                                              Patchability patchable) {
   // The object pool cannot be used in the vm isolate.
   ASSERT(Isolate::Current() != Dart::vm_isolate());
-  const uword address = label->address();
-  ASSERT(Utils::IsAligned(address, 4));
-  // The address is stored in the object array as a RawSmi.
-  const Smi& smi = Smi::Handle(reinterpret_cast<RawSmi*>(address));
-  return FindObject(smi, patchable);
+  return FindObject(ObjectPool::Entry(label->address(),
+                                      ObjectPool::kImmediate),
+                    patchable);
+}
+
+
+RawObjectPool* ObjectPoolWrapper::MakeObjectPool() {
+  intptr_t len = object_pool_.length();
+  if (len == 0) {
+    return Object::empty_object_pool().raw();
+  }
+  const ObjectPool& result = ObjectPool::Handle(ObjectPool::New(len));
+  for (intptr_t i = 0; i < len; ++i) {
+    ObjectPool::EntryType info = object_pool_[i].type_;
+    result.SetInfoAt(i, info);
+    if (info == ObjectPool::kTaggedObject) {
+      result.SetObjectAt(i, *object_pool_[i].obj_);
+    } else {
+      result.SetRawValueAt(i, object_pool_[i].raw_value_);
+    }
+  }
+  return result.raw();
 }
 
 
diff --git a/runtime/vm/assembler.h b/runtime/vm/assembler.h
index 26f7b66..f2ad6fe 100644
--- a/runtime/vm/assembler.h
+++ b/runtime/vm/assembler.h
@@ -216,45 +216,61 @@
 class ObjIndexPair {
  public:
   // Typedefs needed for the DirectChainedHashMap template.
-  typedef const Object* Key;
+  typedef ObjectPool::Entry Key;
   typedef intptr_t Value;
   typedef ObjIndexPair Pair;
 
   static const intptr_t kNoIndex = -1;
 
-  ObjIndexPair() : key_(NULL), value_(kNoIndex) { }
+  ObjIndexPair() : key_(static_cast<uword>(NULL), ObjectPool::kTaggedObject),
+                   value_(kNoIndex) { }
 
-  ObjIndexPair(Key key, Value value)
-     : key_(key->IsNotTemporaryScopedHandle()
-         ? key : &Object::ZoneHandle(key->raw())),
-       value_(value) { }
+  ObjIndexPair(Key key, Value value) : value_(value) {
+    key_.type_ = key.type_;
+    if (key.type_ == ObjectPool::kTaggedObject) {
+      if (key.obj_->IsNotTemporaryScopedHandle()) {
+        key_.obj_ = key.obj_;
+      } else {
+        key_.obj_ = &Object::ZoneHandle(key.obj_->raw());
+      }
+    } else {
+      key_.raw_value_ = key.raw_value_;
+    }
+  }
 
   static Key KeyOf(Pair kv) { return kv.key_; }
 
   static Value ValueOf(Pair kv) { return kv.value_; }
 
   static intptr_t Hashcode(Key key) {
-    if (key->IsSmi()) {
-      return Smi::Cast(*key).Value();
+    if (key.type_ != ObjectPool::kTaggedObject) {
+      return key.raw_value_;
     }
-    if (key->IsDouble()) {
+    if (key.obj_->IsSmi()) {
+      return Smi::Cast(*key.obj_).Value();
+    }
+    if (key.obj_->IsDouble()) {
       return static_cast<intptr_t>(
           bit_cast<int32_t, float>(
-              static_cast<float>(Double::Cast(*key).value())));
+              static_cast<float>(Double::Cast(*key.obj_).value())));
     }
-    if (key->IsMint()) {
-      return static_cast<intptr_t>(Mint::Cast(*key).value());
+    if (key.obj_->IsMint()) {
+      return static_cast<intptr_t>(Mint::Cast(*key.obj_).value());
     }
-    if (key->IsString()) {
-      return String::Cast(*key).Hash();
+    if (key.obj_->IsString()) {
+      return String::Cast(*key.obj_).Hash();
     }
     // TODO(fschneider): Add hash function for other classes commonly used as
     // compile-time constants.
-    return key->GetClassId();
+    return key.obj_->GetClassId();
   }
 
   static inline bool IsKeyEqual(Pair kv, Key key) {
-    return kv.key_->raw() == key->raw();
+    if (kv.key_.type_ != key.type_) return false;
+    if (kv.key_.type_ == ObjectPool::kTaggedObject) {
+      return kv.key_.obj_->raw() == key.obj_->raw();
+    }
+    return kv.key_.raw_value_ == key.raw_value_;
   }
 
  private:
@@ -269,25 +285,26 @@
 };
 
 
-class ObjectPool : public ValueObject {
+class ObjectPoolWrapper : public ValueObject {
  public:
-  ObjectPool() : object_pool_(GrowableObjectArray::Handle()) { }
-
-  intptr_t AddObject(const Object& obj, Patchability patchable);
+  intptr_t AddObject(const Object& obj);
+  intptr_t AddImmediate(uword imm);
   intptr_t AddExternalLabel(const ExternalLabel* label,
                             Patchability patchable);
 
-  intptr_t FindObject(const Object& obj, Patchability patchable);
+  intptr_t FindObject(const Object& obj);
+  intptr_t FindImmediate(uword imm);
   intptr_t FindExternalLabel(const ExternalLabel* label,
                              Patchability patchable);
-  const GrowableObjectArray& data() const { return object_pool_; }
+
+  RawObjectPool* MakeObjectPool();
 
  private:
-  // Objects and jump targets.
-  GrowableObjectArray& object_pool_;
+  intptr_t AddObject(ObjectPool::Entry entry, Patchability patchable);
+  intptr_t FindObject(ObjectPool::Entry entry, Patchability patchable);
 
-  // Patchability of pool entries.
-  GrowableArray<Patchability> patchable_pool_entries_;
+  // Objects and jump targets.
+  GrowableArray<ObjectPool::Entry> object_pool_;
 
   // Hashmap for fast lookup in object pool.
   DirectChainedHashMap<ObjIndexPair> object_pool_index_table_;
diff --git a/runtime/vm/assembler_arm.cc b/runtime/vm/assembler_arm.cc
index e7c2150..6367d4d 100644
--- a/runtime/vm/assembler_arm.cc
+++ b/runtime/vm/assembler_arm.cc
@@ -1575,12 +1575,22 @@
     // Make sure that class CallPattern is able to decode this load from the
     // object pool.
     const int32_t offset =
-        Array::element_offset(object_pool_.FindObject(object, kNotPatchable));
+        ObjectPool::element_offset(object_pool_wrapper_.FindObject(object));
     LoadWordFromPoolOffset(rd, offset - kHeapObjectTag, cond);
   }
 }
 
 
+void Assembler::LoadExternalLabel(Register rd,
+                                  const ExternalLabel* label,
+                                  Patchability patchable,
+                                  Condition cond) {
+  const int32_t offset = ObjectPool::element_offset(
+      object_pool_wrapper_.FindExternalLabel(label, patchable));
+  LoadWordFromPoolOffset(rd, offset - kHeapObjectTag, cond);
+}
+
+
 void Assembler::PushObject(const Object& object) {
   LoadObject(IP, object);
   Push(IP);
@@ -2655,18 +2665,23 @@
 }
 
 
-void Assembler::BranchLinkPatchable(const ExternalLabel* label) {
+void Assembler::BranchLink(const ExternalLabel* label, Patchability patchable) {
   // Make sure that class CallPattern is able to patch the label referred
   // to by this code sequence.
   // For added code robustness, use 'blx lr' in a patchable sequence and
   // use 'blx ip' in a non-patchable sequence (see other BranchLink flavors).
-  const int32_t offset =
-      Array::element_offset(object_pool_.FindExternalLabel(label, kPatchable));
+  const int32_t offset = ObjectPool::element_offset(
+      object_pool_wrapper_.FindExternalLabel(label, patchable));
   LoadWordFromPoolOffset(LR, offset - kHeapObjectTag);
   blx(LR);  // Use blx instruction so that the return branch prediction works.
 }
 
 
+void Assembler::BranchLinkPatchable(const ExternalLabel* label) {
+  BranchLink(label, kPatchable);
+}
+
+
 void Assembler::BranchLinkOffset(Register base, int32_t offset) {
   ASSERT(base != PC);
   ASSERT(base != IP);
@@ -3282,16 +3297,14 @@
 }
 
 
-void Assembler::EnterStubFrame(bool load_pp) {
+void Assembler::EnterStubFrame() {
   // Push 0 as saved PC for stub frames.
   mov(IP, Operand(LR));
   mov(LR, Operand(0));
   RegList regs = (1 << PP) | (1 << FP) | (1 << IP) | (1 << LR);
   EnterFrame(regs, 0);
-  if (load_pp) {
-    // Setup pool pointer for this stub.
-    LoadPoolPointer();
-  }
+  // Setup pool pointer for this stub.
+  LoadPoolPointer();
 }
 
 
diff --git a/runtime/vm/assembler_arm.h b/runtime/vm/assembler_arm.h
index e8b72d9..24e41b0 100644
--- a/runtime/vm/assembler_arm.h
+++ b/runtime/vm/assembler_arm.h
@@ -341,11 +341,11 @@
     return buffer_.pointer_offsets();
   }
 
-  const GrowableObjectArray& object_pool_data() const {
-    return object_pool_.data();
-  }
+  ObjectPoolWrapper& object_pool_wrapper() { return object_pool_wrapper_; }
 
-  ObjectPool& object_pool() { return object_pool_; }
+  RawObjectPool* MakeObjectPool() {
+    return object_pool_wrapper_.MakeObjectPool();
+  }
 
   bool use_far_branches() const {
     return FLAG_use_far_branches || use_far_branches_;
@@ -615,6 +615,8 @@
   // Branch and link to an entry address. Call sequence is never patched.
   void BranchLink(const ExternalLabel* label);
 
+  void BranchLink(const ExternalLabel* label, Patchability patchable);
+
   // Branch and link to an entry address. Call sequence can be patched.
   void BranchLinkPatchable(const ExternalLabel* label);
 
@@ -664,6 +666,10 @@
   void LoadIsolate(Register rd);
 
   void LoadObject(Register rd, const Object& object, Condition cond = AL);
+  void LoadExternalLabel(Register dst,
+                         const ExternalLabel* label,
+                         Patchability patchable,
+                         Condition cond = AL);
   void PushObject(const Object& object);
   void CompareObject(Register rn, const Object& object);
 
@@ -886,7 +892,7 @@
 
   // Set up a stub frame so that the stack traversal code can easily identify
   // a stub frame.
-  void EnterStubFrame(bool load_pp = false);
+  void EnterStubFrame();
   void LeaveStubFrame();
 
   // Instruction pattern from entrypoint is used in Dart frame prologs
@@ -961,7 +967,7 @@
 
  private:
   AssemblerBuffer buffer_;  // Contains position independent code.
-  ObjectPool object_pool_;  // Objects and patchable jump targets.
+  ObjectPoolWrapper object_pool_wrapper_;
 
   int32_t prologue_offset_;
 
diff --git a/runtime/vm/assembler_arm64.cc b/runtime/vm/assembler_arm64.cc
index 91b2962..7b71e57 100644
--- a/runtime/vm/assembler_arm64.cc
+++ b/runtime/vm/assembler_arm64.cc
@@ -35,29 +35,29 @@
     // These objects and labels need to be accessible through every pool-pointer
     // at the same index.
     intptr_t index =
-        object_pool_.AddObject(Object::null_object(), kNotPatchable);
+        object_pool_wrapper_.AddObject(Object::null_object());
     ASSERT(index == 0);
 
-    index = object_pool_.AddObject(Bool::True(), kNotPatchable);
+    index = object_pool_wrapper_.AddObject(Bool::True());
     ASSERT(index == 1);
 
-    index = object_pool_.AddObject(Bool::False(), kNotPatchable);
+    index = object_pool_wrapper_.AddObject(Bool::False());
     ASSERT(index == 2);
 
     const Smi& vacant = Smi::Handle(Smi::New(0xfa >> kSmiTagShift));
     StubCode* stub_code = Isolate::Current()->stub_code();
     if (stub_code->UpdateStoreBuffer_entry() != NULL) {
-      object_pool_.AddExternalLabel(
+      object_pool_wrapper_.AddExternalLabel(
           &stub_code->UpdateStoreBufferLabel(), kNotPatchable);
     } else {
-      object_pool_.AddObject(vacant, kNotPatchable);
+      object_pool_wrapper_.AddObject(vacant);
     }
 
     if (stub_code->CallToRuntime_entry() != NULL) {
-      object_pool_.AddExternalLabel(
+      object_pool_wrapper_.AddExternalLabel(
           &stub_code->CallToRuntimeLabel(), kNotPatchable);
     } else {
-      object_pool_.AddObject(vacant, kNotPatchable);
+      object_pool_wrapper_.AddObject(vacant);
     }
   }
 }
@@ -390,8 +390,7 @@
 
 intptr_t Assembler::FindImmediate(int64_t imm) {
   ASSERT(Isolate::Current() != Dart::vm_isolate());
-  const Smi& smi = Smi::Handle(reinterpret_cast<RawSmi*>(imm));
-  return object_pool_.FindObject(smi, kNotPatchable);
+  return object_pool_wrapper_.FindImmediate(imm);
 }
 
 
@@ -441,8 +440,8 @@
                                   Register pp) {
   const int64_t target = static_cast<int64_t>(label->address());
   if (CanLoadImmediateFromPool(target, pp)) {
-    const int32_t offset =
-        Array::element_offset(object_pool_.FindExternalLabel(label, patchable));
+    const int32_t offset = ObjectPool::element_offset(
+        object_pool_wrapper_.FindExternalLabel(label, patchable));
     LoadWordFromPoolOffset(dst, pp, offset);
   } else {
     LoadImmediate(dst, target, kNoPP);
@@ -454,8 +453,8 @@
                                        const ExternalLabel* label,
                                        Patchability patchable,
                                        Register pp) {
-  const int32_t offset =
-      Array::element_offset(object_pool_.FindExternalLabel(label, patchable));
+  const int32_t offset = ObjectPool::element_offset(
+      object_pool_wrapper_.FindExternalLabel(label, patchable));
   LoadWordFromPoolOffsetFixed(dst, pp, offset);
 }
 
@@ -468,7 +467,7 @@
 void Assembler::LoadObject(Register dst, const Object& object, Register pp) {
   if (CanLoadObjectFromPool(object)) {
     const int32_t offset =
-        Array::element_offset(object_pool_.FindObject(object, kNotPatchable));
+        ObjectPool::element_offset(object_pool_wrapper_.FindObject(object));
     LoadWordFromPoolOffset(dst, pp, offset);
   } else {
     ASSERT((Isolate::Current() == Dart::vm_isolate()) ||
@@ -495,7 +494,7 @@
       allow_constant_pool()) {
     int64_t val_smi_tag = imm & kSmiTagMask;
     imm &= ~kSmiTagMask;  // Mask off the tag bits.
-    const int32_t offset = Array::element_offset(FindImmediate(imm));
+    const int32_t offset = ObjectPool::element_offset(FindImmediate(imm));
     LoadWordFromPoolOffset(reg, pp, offset);
     if (val_smi_tag != 0) {
       // Add back the tag bits.
@@ -531,7 +530,7 @@
     // Save the bits that must be masked-off for the SmiTag
     int64_t val_smi_tag = imm & kSmiTagMask;
     imm &= ~kSmiTagMask;  // Mask off the tag bits.
-    const int32_t offset = Array::element_offset(FindImmediate(imm));
+    const int32_t offset = ObjectPool::element_offset(FindImmediate(imm));
     LoadWordFromPoolOffset(reg, pp, offset);
     if (val_smi_tag != 0) {
       // Add back the tag bits.
@@ -986,12 +985,12 @@
 
 
 void Assembler::LoadClassId(Register result, Register object, Register pp) {
-  ASSERT(RawObject::kClassIdTagPos == 16);
-  ASSERT(RawObject::kClassIdTagSize == 16);
+  ASSERT(RawObject::kClassIdTagPos == kBitsPerInt32);
+  ASSERT(RawObject::kClassIdTagSize == kBitsPerInt32);
   const intptr_t class_id_offset = Object::tags_offset() +
       RawObject::kClassIdTagPos / kBitsPerByte;
   LoadFromOffset(result, object, class_id_offset - kHeapObjectTag, pp,
-                 kUnsignedHalfword);
+                 kUnsignedWord);
 }
 
 
@@ -1238,13 +1237,11 @@
 }
 
 
-void Assembler::EnterStubFrame(bool load_pp) {
+void Assembler::EnterStubFrame() {
   EnterFrame(0);
   // Save caller's pool pointer. Push 0 in the saved PC area for stub frames.
   TagAndPushPPAndPcMarker(ZR);
-  if (load_pp) {
-    LoadPoolPointer(PP);
-  }
+  LoadPoolPointer(PP);
 }
 
 
diff --git a/runtime/vm/assembler_arm64.h b/runtime/vm/assembler_arm64.h
index 98e3f36..0ac4a69 100644
--- a/runtime/vm/assembler_arm64.h
+++ b/runtime/vm/assembler_arm64.h
@@ -476,11 +476,11 @@
     return buffer_.pointer_offsets();
   }
 
-  const GrowableObjectArray& object_pool_data() const {
-    return object_pool_.data();
-  }
+  ObjectPoolWrapper& object_pool_wrapper() { return object_pool_wrapper_; }
 
-  ObjectPool& object_pool() { return object_pool_; }
+  RawObjectPool* MakeObjectPool() {
+    return object_pool_wrapper_.MakeObjectPool();
+  }
 
   bool use_far_branches() const {
     return FLAG_use_far_branches || use_far_branches_;
@@ -1373,7 +1373,7 @@
 
   // Set up a stub frame so that the stack traversal code can easily identify
   // a stub frame.
-  void EnterStubFrame(bool load_pp = false);
+  void EnterStubFrame();
   void LeaveStubFrame();
 
   void UpdateAllocationStats(intptr_t cid,
@@ -1418,8 +1418,7 @@
  private:
   AssemblerBuffer buffer_;  // Contains position independent code.
 
-  // Objects and patchable jump targets.
-  ObjectPool object_pool_;
+  ObjectPoolWrapper object_pool_wrapper_;
 
   int32_t prologue_offset_;
 
diff --git a/runtime/vm/assembler_ia32.cc b/runtime/vm/assembler_ia32.cc
index 6ccb225..bb54355 100644
--- a/runtime/vm/assembler_ia32.cc
+++ b/runtime/vm/assembler_ia32.cc
@@ -268,6 +268,16 @@
 }
 
 
+void Assembler::movw(const Address& dst, const Immediate& imm) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitOperandSizeOverride();
+  EmitUint8(0xC7);
+  EmitOperand(0, dst);
+  EmitUint8(imm.value() & 0xFF);
+  EmitUint8((imm.value() >> 8) & 0xFF);
+}
+
+
 void Assembler::leal(Register dst, const Address& src) {
   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
   EmitUint8(0x8D);
@@ -1417,6 +1427,24 @@
 }
 
 
+void Assembler::cmpw(Register reg, const Address& address) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitOperandSizeOverride();
+  EmitUint8(0x3B);
+  EmitOperand(reg, address);
+}
+
+
+void Assembler::cmpw(const Address& address, const Immediate& imm) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitOperandSizeOverride();
+  EmitUint8(0x81);
+  EmitOperand(7, address);
+  EmitUint8(imm.value() & 0xFF);
+  EmitUint8((imm.value() >> 8) & 0xFF);
+}
+
+
 void Assembler::cmpb(const Address& address, const Immediate& imm) {
   ASSERT(imm.is_int8());
   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
diff --git a/runtime/vm/assembler_ia32.h b/runtime/vm/assembler_ia32.h
index 5c0ec98..1b386a3 100644
--- a/runtime/vm/assembler_ia32.h
+++ b/runtime/vm/assembler_ia32.h
@@ -356,6 +356,7 @@
   void movsxw(Register dst, const Address& src);
   void movw(Register dst, const Address& src);
   void movw(const Address& dst, Register src);
+  void movw(const Address& dst, const Immediate& imm);
 
   void leal(Register dst, const Address& src);
 
@@ -531,6 +532,8 @@
 
   void cmpl(const Address& address, Register reg);
   void cmpl(const Address& address, const Immediate& imm);
+  void cmpw(Register reg, const Address& address);
+  void cmpw(const Address& address, const Immediate& imm);
   void cmpb(const Address& address, const Immediate& imm);
 
   void testl(Register reg1, Register reg2);
@@ -806,11 +809,11 @@
     return buffer_.pointer_offsets();
   }
 
-  const GrowableObjectArray& object_pool_data() const {
-    return object_pool_.data();
-  }
+  ObjectPoolWrapper& object_pool_wrapper() { return object_pool_wrapper_; }
 
-  ObjectPool& object_pool() { return object_pool_; }
+  RawObjectPool* MakeObjectPool() {
+    return object_pool_wrapper_.MakeObjectPool();
+  }
 
   void FinalizeInstructions(const MemoryRegion& region) {
     buffer_.FinalizeInstructions(region);
@@ -992,7 +995,7 @@
   int32_t jit_cookie();
 
   AssemblerBuffer buffer_;
-  ObjectPool object_pool_;
+  ObjectPoolWrapper object_pool_wrapper_;
   intptr_t prologue_offset_;
   int32_t jit_cookie_;
   GrowableArray<CodeComment*> comments_;
diff --git a/runtime/vm/assembler_mips.cc b/runtime/vm/assembler_mips.cc
index ef1857c..29644ab 100644
--- a/runtime/vm/assembler_mips.cc
+++ b/runtime/vm/assembler_mips.cc
@@ -472,12 +472,21 @@
     // Make sure that class CallPattern is able to decode this load from the
     // object pool.
     const int32_t offset =
-        Array::element_offset(object_pool_.FindObject(object, kNotPatchable));
+        ObjectPool::element_offset(object_pool_wrapper_.FindObject(object));
     LoadWordFromPoolOffset(rd, offset - kHeapObjectTag);
   }
 }
 
 
+void Assembler::LoadExternalLabel(Register rd,
+                                  const ExternalLabel* label,
+                                  Patchability patchable) {
+  const int32_t offset = ObjectPool::element_offset(
+      object_pool_wrapper_.FindExternalLabel(label, patchable));
+  LoadWordFromPoolOffset(rd, offset - kHeapObjectTag);
+}
+
+
 void Assembler::PushObject(const Object& object) {
   ASSERT(!in_delay_slot_);
   LoadObject(TMP, object);
@@ -734,7 +743,7 @@
 }
 
 
-void Assembler::EnterStubFrame(bool load_pp) {
+void Assembler::EnterStubFrame() {
   ASSERT(!in_delay_slot_);
   SetPrologueOffset();
   addiu(SP, SP, Immediate(-4 * kWordSize));
@@ -743,10 +752,8 @@
   sw(FP, Address(SP, 1 * kWordSize));
   sw(PP, Address(SP, 0 * kWordSize));
   addiu(FP, SP, Immediate(1 * kWordSize));
-  if (load_pp) {
-    // Setup pool pointer for this stub.
-    LoadPoolPointer();
-  }
+  // Setup pool pointer for this stub.
+  LoadPoolPointer();
 }
 
 
diff --git a/runtime/vm/assembler_mips.h b/runtime/vm/assembler_mips.h
index 0ccfb86..79e6539 100644
--- a/runtime/vm/assembler_mips.h
+++ b/runtime/vm/assembler_mips.h
@@ -263,11 +263,11 @@
     return buffer_.pointer_offsets();
   }
 
-  const GrowableObjectArray& object_pool_data() const {
-    return object_pool_.data();
-  }
+  ObjectPoolWrapper& object_pool_wrapper() { return object_pool_wrapper_; }
 
-  ObjectPool& object_pool() { return object_pool_; }
+  RawObjectPool* MakeObjectPool() {
+    return object_pool_wrapper_.MakeObjectPool();
+  }
 
   void FinalizeInstructions(const MemoryRegion& region) {
     buffer_.FinalizeInstructions(region);
@@ -287,7 +287,7 @@
 
   // Set up a stub frame so that the stack traversal code can easily identify
   // a stub frame.
-  void EnterStubFrame(bool load_pp = false);
+  void EnterStubFrame();
   void LeaveStubFrame();
   // A separate macro for when a Ret immediately follows, so that we can use
   // the branch delay slot.
@@ -926,13 +926,19 @@
     jalr(T9);
   }
 
-  void BranchLinkPatchable(const ExternalLabel* label) {
+  void BranchLink(const ExternalLabel* label, Patchability patchable) {
     ASSERT(!in_delay_slot_);
-    const int32_t offset = Array::element_offset(
-        object_pool_.FindExternalLabel(label, kPatchable));
+    const int32_t offset = ObjectPool::element_offset(
+        object_pool_wrapper_.FindExternalLabel(label, patchable));
     LoadWordFromPoolOffset(T9, offset - kHeapObjectTag);
     jalr(T9);
-    delay_slot_available_ = false;  // CodePatcher expects a nop.
+    if (patchable == kPatchable) {
+      delay_slot_available_ = false;  // CodePatcher expects a nop.
+    }
+  }
+
+  void BranchLinkPatchable(const ExternalLabel* label) {
+    BranchLink(label, kPatchable);
   }
 
   void Drop(intptr_t stack_elements) {
@@ -1533,6 +1539,9 @@
 
   void LoadWordFromPoolOffset(Register rd, int32_t offset);
   void LoadObject(Register rd, const Object& object);
+  void LoadExternalLabel(Register rd,
+                         const ExternalLabel* label,
+                         Patchability patchable);
   void PushObject(const Object& object);
 
   void LoadIsolate(Register result);
@@ -1614,7 +1623,7 @@
 
  private:
   AssemblerBuffer buffer_;
-  ObjectPool object_pool_;  // Objects and patchable jump targets.
+  ObjectPoolWrapper object_pool_wrapper_;
 
   intptr_t prologue_offset_;
 
diff --git a/runtime/vm/assembler_test.cc b/runtime/vm/assembler_test.cc
index 088e48c..5933488 100644
--- a/runtime/vm/assembler_test.cc
+++ b/runtime/vm/assembler_test.cc
@@ -41,37 +41,37 @@
   Thread* thread = Thread::Current();
 
   EXPECT(old_array.raw() == grow_old_array.data());
-  EXPECT(!Isolate::Current()->store_buffer()->Contains(grow_old_array.raw()));
+  EXPECT(!thread->StoreBufferContains(grow_old_array.raw()));
   EXPECT(old_array.raw() == grow_new_array.data());
-  EXPECT(!Isolate::Current()->store_buffer()->Contains(grow_new_array.raw()));
+  EXPECT(!thread->StoreBufferContains(grow_new_array.raw()));
 
   // Store Smis into the old object.
   for (int i = -128; i < 128; i++) {
     smi = Smi::New(i);
     test_code(ctx.raw(), smi.raw(), grow_old_array.raw(), thread);
     EXPECT(reinterpret_cast<RawArray*>(smi.raw()) == grow_old_array.data());
-    EXPECT(!Isolate::Current()->store_buffer()->Contains(grow_old_array.raw()));
+    EXPECT(!thread->StoreBufferContains(grow_old_array.raw()));
   }
 
   // Store an old object into the old object.
   test_code(ctx.raw(), old_array.raw(), grow_old_array.raw(), thread);
   EXPECT(old_array.raw() == grow_old_array.data());
-  EXPECT(!Isolate::Current()->store_buffer()->Contains(grow_old_array.raw()));
+  EXPECT(!thread->StoreBufferContains(grow_old_array.raw()));
 
   // Store a new object into the old object.
   test_code(ctx.raw(), new_array.raw(), grow_old_array.raw(), thread);
   EXPECT(new_array.raw() == grow_old_array.data());
-  EXPECT(Isolate::Current()->store_buffer()->Contains(grow_old_array.raw()));
+  EXPECT(thread->StoreBufferContains(grow_old_array.raw()));
 
   // Store a new object into the new object.
   test_code(ctx.raw(), new_array.raw(), grow_new_array.raw(), thread);
   EXPECT(new_array.raw() == grow_new_array.data());
-  EXPECT(!Isolate::Current()->store_buffer()->Contains(grow_new_array.raw()));
+  EXPECT(!thread->StoreBufferContains(grow_new_array.raw()));
 
   // Store an old object into the new object.
   test_code(ctx.raw(), old_array.raw(), grow_new_array.raw(), thread);
   EXPECT(old_array.raw() == grow_new_array.data());
-  EXPECT(!Isolate::Current()->store_buffer()->Contains(grow_new_array.raw()));
+  EXPECT(!thread->StoreBufferContains(grow_new_array.raw()));
 }
 
 }  // namespace dart
diff --git a/runtime/vm/assembler_x64.cc b/runtime/vm/assembler_x64.cc
index 660c047..02f85df 100644
--- a/runtime/vm/assembler_x64.cc
+++ b/runtime/vm/assembler_x64.cc
@@ -32,30 +32,29 @@
   if (isolate != Dart::vm_isolate()) {
     // These objects and labels need to be accessible through every pool-pointer
     // at the same index.
-    intptr_t index =
-        object_pool_.AddObject(Object::null_object(), kNotPatchable);
+    intptr_t index = object_pool_wrapper_.AddObject(Object::null_object());
     ASSERT(index == 0);
 
-    index = object_pool_.AddObject(Bool::True(), kNotPatchable);
+    index = object_pool_wrapper_.AddObject(Bool::True());
     ASSERT(index == 1);
 
-    index = object_pool_.AddObject(Bool::False(), kNotPatchable);
+    index = object_pool_wrapper_.AddObject(Bool::False());
     ASSERT(index == 2);
 
     const Smi& vacant = Smi::Handle(Smi::New(0xfa >> kSmiTagShift));
     StubCode* stub_code = isolate->stub_code();
     if (stub_code->UpdateStoreBuffer_entry() != NULL) {
-      object_pool_.AddExternalLabel(&stub_code->UpdateStoreBufferLabel(),
-                                    kNotPatchable);
+      object_pool_wrapper_.AddExternalLabel(
+          &stub_code->UpdateStoreBufferLabel(), kNotPatchable);
     } else {
-      object_pool_.AddObject(vacant, kNotPatchable);
+      object_pool_wrapper_.AddObject(vacant);
     }
 
     if (stub_code->CallToRuntime_entry() != NULL) {
-      object_pool_.AddExternalLabel(&stub_code->CallToRuntimeLabel(),
-                                    kNotPatchable);
+      object_pool_wrapper_.AddExternalLabel(
+          &stub_code->CallToRuntimeLabel(), kNotPatchable);
     } else {
-      object_pool_.AddObject(vacant, kNotPatchable);
+      object_pool_wrapper_.AddObject(vacant);
     }
   }
 }
@@ -95,8 +94,8 @@
                                   const ExternalLabel* label,
                                   Patchability patchable,
                                   Register pp) {
-  const int32_t offset =
-      Array::element_offset(object_pool_.FindExternalLabel(label, patchable));
+  const int32_t offset = ObjectPool::element_offset(
+      object_pool_wrapper_.FindExternalLabel(label, patchable));
   LoadWordFromPoolOffset(dst, pp, offset - kHeapObjectTag);
 }
 
@@ -115,8 +114,8 @@
 void Assembler::CallPatchable(const ExternalLabel* label) {
   ASSERT(allow_constant_pool());
   intptr_t call_start = buffer_.GetPosition();
-  const int32_t offset =
-      Array::element_offset(object_pool_.FindExternalLabel(label, kPatchable));
+  const int32_t offset = ObjectPool::element_offset(
+      object_pool_wrapper_.FindExternalLabel(label, kPatchable));
   call(Address::AddressBaseImm32(PP, offset - kHeapObjectTag));
   ASSERT((buffer_.GetPosition() - call_start) == kCallExternalLabelSize);
 }
@@ -126,8 +125,8 @@
   if (Isolate::Current() == Dart::vm_isolate()) {
     call(label);
   } else {
-    const int32_t offset = Array::element_offset(
-        object_pool_.FindExternalLabel(label, kNotPatchable));
+    const int32_t offset = ObjectPool::element_offset(
+        object_pool_wrapper_.FindExternalLabel(label, kNotPatchable));
     call(Address::AddressBaseImm32(pp, offset - kHeapObjectTag));
   }
 }
@@ -351,6 +350,16 @@
 }
 
 
+void Assembler::movw(const Address& dst, const Immediate& imm) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitOperandSizeOverride();
+  EmitUint8(0xC7);
+  EmitOperand(0, dst);
+  EmitUint8(imm.value() & 0xFF);
+  EmitUint8((imm.value() >> 8) & 0xFF);
+}
+
+
 void Assembler::movq(Register dst, const Immediate& imm) {
   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
   if (imm.is_int32()) {
@@ -1420,6 +1429,24 @@
 }
 
 
+void Assembler::cmpw(Register reg, const Address& address) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitOperandSizeOverride();
+  EmitUint8(0x3B);
+  EmitOperand(reg, address);
+}
+
+
+void Assembler::cmpw(const Address& address, const Immediate& imm) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitOperandSizeOverride();
+  EmitUint8(0x81);
+  EmitOperand(7, address);
+  EmitUint8(imm.value() & 0xFF);
+  EmitUint8((imm.value() >> 8) & 0xFF);
+}
+
+
 void Assembler::cmpl(Register reg, const Immediate& imm) {
   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
   EmitRegisterREX(reg, REX_NONE);
@@ -2607,8 +2634,8 @@
 void Assembler::JmpPatchable(const ExternalLabel* label, Register pp) {
   ASSERT(allow_constant_pool());
   intptr_t call_start = buffer_.GetPosition();
-  const int32_t offset =
-      Array::element_offset(object_pool_.FindExternalLabel(label, kPatchable));
+  const int32_t offset = ObjectPool::element_offset(
+      object_pool_wrapper_.FindExternalLabel(label, kPatchable));
   // Patchable jumps always use a 32-bit immediate encoding.
   jmp(Address::AddressBaseImm32(pp, offset - kHeapObjectTag));
   ASSERT((buffer_.GetPosition() - call_start) == JumpPattern::kLengthInBytes);
@@ -2616,8 +2643,8 @@
 
 
 void Assembler::Jmp(const ExternalLabel* label, Register pp) {
-  const int32_t offset = Array::element_offset(
-      object_pool_.FindExternalLabel(label, kNotPatchable));
+  const int32_t offset = ObjectPool::element_offset(
+      object_pool_wrapper_.FindExternalLabel(label, kNotPatchable));
   jmp(Address(pp, offset - kHeapObjectTag));
 }
 
@@ -2817,7 +2844,7 @@
 void Assembler::LoadObject(Register dst, const Object& object, Register pp) {
   if (CanLoadFromObjectPool(object)) {
     const int32_t offset =
-        Array::element_offset(object_pool_.FindObject(object, kNotPatchable));
+        ObjectPool::element_offset(object_pool_wrapper_.FindObject(object));
     LoadWordFromPoolOffset(dst, pp, offset - kHeapObjectTag);
   } else {
     ASSERT((Isolate::Current() == Dart::vm_isolate()) ||
@@ -2852,7 +2879,7 @@
 void Assembler::CompareObject(Register reg, const Object& object, Register pp) {
   if (CanLoadFromObjectPool(object)) {
     const int32_t offset =
-        Array::element_offset(object_pool_.FindObject(object, kNotPatchable));
+        ObjectPool::element_offset(object_pool_wrapper_.FindObject(object));
     cmpq(reg, Address(pp, offset-kHeapObjectTag));
   } else {
     CompareImmediate(
@@ -2863,8 +2890,7 @@
 
 intptr_t Assembler::FindImmediate(int64_t imm) {
   ASSERT(Isolate::Current() != Dart::vm_isolate());
-  const Smi& smi = Smi::Handle(reinterpret_cast<RawSmi*>(imm));
-  return object_pool_.FindObject(smi, kNotPatchable);
+  return object_pool_wrapper_.FindImmediate(imm);
 }
 
 
@@ -2882,16 +2908,8 @@
   if (CanLoadImmediateFromPool(imm, pp)) {
     // It's a 64-bit constant and we're not in the VM isolate, so load from
     // object pool.
-    int64_t val = imm.value();
-    // Save the bits that must be masked-off for the SmiTag
-    int64_t val_smi_tag = val & kSmiTagMask;
-    val &= ~kSmiTagMask;  // Mask off the tag bits.
-    const int32_t offset = Array::element_offset(FindImmediate(val));
+    int32_t offset = ObjectPool::element_offset(FindImmediate(imm.value()));
     LoadWordFromPoolOffset(reg, pp, offset - kHeapObjectTag);
-    if (val_smi_tag != 0) {
-      // Add back the tag bits.
-      orq(reg, Immediate(val_smi_tag));
-    }
   } else {
     movq(reg, imm);
   }
@@ -3188,7 +3206,7 @@
     } else {
       LoadImmediate(RDI, Immediate(message_address), PP);
     }
-    call(&StubCode::PrintStopMessageLabel());
+    call(&Isolate::Current()->stub_code()->PrintStopMessageLabel());
     popq(RDI);  // Restore RDI register.
     popq(TMP);  // Restore TMP register.
   } else {
@@ -3426,13 +3444,11 @@
 }
 
 
-void Assembler::EnterStubFrame(bool load_pp) {
+void Assembler::EnterStubFrame() {
   EnterFrame(0);
   pushq(Immediate(0));  // Push 0 in the saved PC area for stub frames.
   pushq(PP);  // Save caller's pool pointer
-  if (load_pp) {
-    LoadPoolPointer(PP);
-  }
+  LoadPoolPointer(PP);
 }
 
 
@@ -3727,11 +3743,12 @@
 
 
 void Assembler::LoadClassId(Register result, Register object) {
-  ASSERT(RawObject::kClassIdTagPos == 16);
-  ASSERT(RawObject::kClassIdTagSize == 16);
+  ASSERT(RawObject::kClassIdTagPos == kBitsPerInt32);
+  ASSERT(RawObject::kClassIdTagSize == kBitsPerInt32);
+  ASSERT(sizeof(classid_t) == sizeof(uint32_t));
   const intptr_t class_id_offset = Object::tags_offset() +
       RawObject::kClassIdTagPos / kBitsPerByte;
-  movzxw(result, FieldAddress(object, class_id_offset));
+  movl(result, FieldAddress(object, class_id_offset));
 }
 
 
@@ -3760,8 +3777,9 @@
                                      intptr_t class_id,
                                      Label* is_smi) {
   ASSERT(kSmiTagShift == 1);
-  ASSERT(RawObject::kClassIdTagPos == 16);
-  ASSERT(RawObject::kClassIdTagSize == 16);
+  ASSERT(RawObject::kClassIdTagPos == kBitsPerInt32);
+  ASSERT(RawObject::kClassIdTagSize == kBitsPerInt32);
+  ASSERT(sizeof(classid_t) == sizeof(uint32_t));
   const intptr_t class_id_offset = Object::tags_offset() +
       RawObject::kClassIdTagPos / kBitsPerByte;
 
@@ -3770,7 +3788,7 @@
   j(NOT_CARRY, is_smi, kNearJump);
   // Load cid: can't use LoadClassId, object is untagged. Use TIMES_2 scale
   // factor in the addressing mode to compensate for this.
-  movzxw(TMP, Address(object, TIMES_2, class_id_offset));
+  movl(TMP, Address(object, TIMES_2, class_id_offset));
   cmpl(TMP, Immediate(class_id));
 }
 
diff --git a/runtime/vm/assembler_x64.h b/runtime/vm/assembler_x64.h
index 4bf6a57..c3ea20d 100644
--- a/runtime/vm/assembler_x64.h
+++ b/runtime/vm/assembler_x64.h
@@ -397,6 +397,7 @@
   void movsxw(Register dst, const Address& src);
   void movw(Register dst, const Address& src);
   void movw(const Address& dst, Register src);
+  void movw(const Address& dst, const Immediate& imm);
 
   void movq(Register dst, const Immediate& imm);
   void movq(Register dst, Register src);
@@ -512,6 +513,9 @@
 
   void cmpb(const Address& address, const Immediate& imm);
 
+  void cmpw(Register reg, const Address& address);
+  void cmpw(const Address& address, const Immediate& imm);
+
   void cmpl(Register reg, const Immediate& imm);
   void cmpl(Register reg0, Register reg1);
   void cmpl(Register reg, const Address& address);
@@ -758,6 +762,10 @@
   void LoadImmediate(Register reg, const Immediate& imm, Register pp);
   void LoadIsolate(Register dst);
   void LoadObject(Register dst, const Object& obj, Register pp);
+  void LoadExternalLabel(Register dst,
+                         const ExternalLabel* label,
+                         Patchability patchable,
+                         Register pp);
   void JmpPatchable(const ExternalLabel* label, Register pp);
   void Jmp(const ExternalLabel* label, Register pp);
   void J(Condition condition, const ExternalLabel* label, Register pp);
@@ -902,11 +910,12 @@
   const ZoneGrowableArray<intptr_t>& GetPointerOffsets() const {
     return buffer_.pointer_offsets();
   }
-  const GrowableObjectArray& object_pool_data() const {
-    return object_pool_.data();
-  }
 
-  ObjectPool& object_pool() { return object_pool_; }
+  ObjectPoolWrapper& object_pool_wrapper() { return object_pool_wrapper_; }
+
+  RawObjectPool* MakeObjectPool() {
+    return object_pool_wrapper_.MakeObjectPool();
+  }
 
   void FinalizeInstructions(const MemoryRegion& region) {
     buffer_.FinalizeInstructions(region);
@@ -957,7 +966,7 @@
   //   movq rbp, rsp
   //   pushq immediate(0)
   //   .....
-  void EnterStubFrame(bool load_pp = false);
+  void EnterStubFrame();
   void LeaveStubFrame();
 
   // Instruction pattern from entrypoint is used in dart frame prologues
@@ -1033,8 +1042,7 @@
  private:
   AssemblerBuffer buffer_;
 
-  // Objects and jump targets.
-  ObjectPool object_pool_;
+  ObjectPoolWrapper object_pool_wrapper_;
 
   intptr_t prologue_offset_;
 
@@ -1057,10 +1065,6 @@
   bool allow_constant_pool_;
 
   intptr_t FindImmediate(int64_t imm);
-  void LoadExternalLabel(Register dst,
-                         const ExternalLabel* label,
-                         Patchability patchable,
-                         Register pp);
   bool CanLoadFromObjectPool(const Object& object);
   void LoadWordFromPoolOffset(Register dst, Register pp, int32_t offset);
 
diff --git a/runtime/vm/ast.cc b/runtime/vm/ast.cc
index fdd39e4..ef224e2 100644
--- a/runtime/vm/ast.cc
+++ b/runtime/vm/ast.cc
@@ -262,6 +262,7 @@
     case Token::kMOD:
     case Token::kOR:
     case Token::kAND:
+    case Token::kIFNULL:
     case Token::kBIT_OR:
     case Token::kBIT_XOR:
     case Token::kBIT_AND:
@@ -529,18 +530,23 @@
 
 
 AstNode* InstanceGetterNode::MakeAssignmentNode(AstNode* rhs) {
-  return new InstanceSetterNode(token_pos(), receiver(), field_name(), rhs);
+  return new InstanceSetterNode(token_pos(),
+                                receiver(),
+                                field_name(),
+                                rhs,
+                                is_conditional());
 }
 
 
 bool InstanceGetterNode::IsPotentiallyConst() const {
   return field_name().Equals(Symbols::Length()) &&
+    !is_conditional() &&
     receiver()->IsPotentiallyConst();
 }
 
 
 const Instance* InstanceGetterNode::EvalConstExpr() const {
-  if (field_name().Equals(Symbols::Length())) {
+  if (field_name().Equals(Symbols::Length()) && !is_conditional()) {
     const Instance* receiver_val = receiver()->EvalConstExpr();
     if ((receiver_val != NULL) && receiver_val->IsString()) {
       return &Instance::ZoneHandle(Smi::New(1));
diff --git a/runtime/vm/ast.h b/runtime/vm/ast.h
index 4848a3f..79283b3 100644
--- a/runtime/vm/ast.h
+++ b/runtime/vm/ast.h
@@ -1421,11 +1421,13 @@
   InstanceCallNode(intptr_t token_pos,
                    AstNode* receiver,
                    const String& function_name,
-                   ArgumentListNode* arguments)
+                   ArgumentListNode* arguments,
+                   bool is_conditional = false)
       : AstNode(token_pos),
         receiver_(receiver),
         function_name_(function_name),
-        arguments_(arguments) {
+        arguments_(arguments),
+        is_conditional_(is_conditional) {
     ASSERT(receiver_ != NULL);
     ASSERT(function_name_.IsNotTemporaryScopedHandle());
     ASSERT(function_name_.IsSymbol());
@@ -1435,6 +1437,7 @@
   AstNode* receiver() const { return receiver_; }
   const String& function_name() const { return function_name_; }
   ArgumentListNode* arguments() const { return arguments_; }
+  bool is_conditional() const { return is_conditional_; }
 
   virtual void VisitChildren(AstNodeVisitor* visitor) const {
     receiver()->Visit(visitor);
@@ -1447,6 +1450,7 @@
   AstNode* receiver_;
   const String& function_name_;
   ArgumentListNode* arguments_;
+  const bool is_conditional_;
 
   DISALLOW_IMPLICIT_CONSTRUCTORS(InstanceCallNode);
 };
@@ -1456,10 +1460,12 @@
  public:
   InstanceGetterNode(intptr_t token_pos,
                      AstNode* receiver,
-                     const String& field_name)
+                     const String& field_name,
+                     bool is_conditional = false)
       : AstNode(token_pos),
         receiver_(receiver),
-        field_name_(field_name) {
+        field_name_(field_name),
+        is_conditional_(is_conditional) {
     ASSERT(receiver_ != NULL);
     ASSERT(field_name_.IsNotTemporaryScopedHandle());
     ASSERT(field_name_.IsSymbol());
@@ -1467,6 +1473,7 @@
 
   AstNode* receiver() const { return receiver_; }
   const String& field_name() const { return field_name_; }
+  bool is_conditional() const { return is_conditional_; }
 
   virtual void VisitChildren(AstNodeVisitor* visitor) const {
     receiver()->Visit(visitor);
@@ -1482,6 +1489,7 @@
  private:
   AstNode* receiver_;
   const String& field_name_;
+  const bool is_conditional_;
 
   DISALLOW_IMPLICIT_CONSTRUCTORS(InstanceGetterNode);
 };
@@ -1492,11 +1500,13 @@
   InstanceSetterNode(intptr_t token_pos,
                      AstNode* receiver,
                      const String& field_name,
-                     AstNode* value)
+                     AstNode* value,
+                     bool is_conditional = false)
       : AstNode(token_pos),
         receiver_(receiver),
         field_name_(field_name),
-        value_(value) {
+        value_(value),
+        is_conditional_(is_conditional) {
     ASSERT(receiver_ != NULL);
     ASSERT(value_ != NULL);
     ASSERT(field_name_.IsZoneHandle());
@@ -1506,6 +1516,7 @@
   AstNode* receiver() const { return receiver_; }
   const String& field_name() const { return field_name_; }
   AstNode* value() const { return value_; }
+  bool is_conditional() const { return is_conditional_; }
 
   virtual void VisitChildren(AstNodeVisitor* visitor) const {
     receiver()->Visit(visitor);
@@ -1518,6 +1529,7 @@
   AstNode* receiver_;
   const String& field_name_;
   AstNode* value_;
+  const bool is_conditional_;
 
   DISALLOW_IMPLICIT_CONSTRUCTORS(InstanceSetterNode);
 };
diff --git a/runtime/vm/ast_transformer.cc b/runtime/vm/ast_transformer.cc
index b6d20c1..ac3f9f1 100644
--- a/runtime/vm/ast_transformer.cc
+++ b/runtime/vm/ast_transformer.cc
@@ -436,7 +436,8 @@
       new(Z) InstanceCallNode(node->token_pos(),
                               new_receiver,
                               node->function_name(),
-                              new_args));
+                              new_args,
+                              node->is_conditional()));
   result_ = new(Z) LoadLocalNode(Scanner::kNoSourcePos, result);
 }
 
@@ -469,7 +470,8 @@
   LocalVariable* result = AddToPreambleNewTempVar(
       new(Z) InstanceGetterNode(node->token_pos(),
                                 new_receiver,
-                                node->field_name()));
+                                node->field_name(),
+                                node->is_conditional()));
   result_ = new(Z) LoadLocalNode(Scanner::kNoSourcePos, result);
 }
 
@@ -484,7 +486,8 @@
       new(Z) InstanceSetterNode(node->token_pos(),
                                 new_receiver,
                                 node->field_name(),
-                                new_value));
+                                new_value,
+                                node->is_conditional()));
   result_ = new(Z) LoadLocalNode(Scanner::kNoSourcePos, result);
 }
 
diff --git a/runtime/vm/base_isolate.h b/runtime/vm/base_isolate.h
index 067c708..dccb44b 100644
--- a/runtime/vm/base_isolate.h
+++ b/runtime/vm/base_isolate.h
@@ -26,8 +26,16 @@
   }
 
   // DEPRECATED: Use Thread::current_zone.
-  Zone* current_zone() const { return current_zone_; }
+  Zone* current_zone() const {
+    AssertCurrentThreadIsMutator();
+    return current_zone_;
+  }
   void set_current_zone(Zone* zone) { current_zone_ = zone; }
+#if defined(DEBUG)
+  void AssertCurrentThreadIsMutator() const;
+#else
+  void AssertCurrentThreadIsMutator() const {}
+#endif  // DEBUG
 
   HandleScope* top_handle_scope() const {
 #if defined(DEBUG)
diff --git a/runtime/vm/cha.cc b/runtime/vm/cha.cc
index 4b00504..a2f50a3 100644
--- a/runtime/vm/cha.cc
+++ b/runtime/vm/cha.cc
@@ -36,12 +36,12 @@
     return true;
   }
   const GrowableObjectArray& direct_subclasses =
-      GrowableObjectArray::Handle(thread_->zone(), cls.direct_subclasses());
+      GrowableObjectArray::Handle(cls.direct_subclasses());
   return !direct_subclasses.IsNull() && (direct_subclasses.Length() > 0);
 }
 
 
-bool CHA::HasSubclasses(intptr_t cid) {
+bool CHA::HasSubclasses(intptr_t cid) const {
   const ClassTable& class_table = *thread_->isolate()->class_table();
   Class& cls = Class::Handle(thread_->zone(), class_table.At(cid));
   return HasSubclasses(cls);
diff --git a/runtime/vm/cha.h b/runtime/vm/cha.h
index 8860a8b..b4007b2 100644
--- a/runtime/vm/cha.h
+++ b/runtime/vm/cha.h
@@ -32,11 +32,11 @@
   }
 
   // Returns true if the class has subclasses.
-  bool HasSubclasses(const Class& cls);
-  bool HasSubclasses(intptr_t cid);
+  static bool HasSubclasses(const Class& cls);
+  bool HasSubclasses(intptr_t cid) const;
 
   // Return true if the class is implemented by some other class.
-  bool IsImplemented(const Class& cls);
+  static bool IsImplemented(const Class& cls);
 
   // Returns true if any subclass of 'cls' contains the function.
   bool HasOverride(const Class& cls, const String& function_name);
diff --git a/runtime/vm/cha_test.cc b/runtime/vm/cha_test.cc
index 1cd95dc..a7c998d 100644
--- a/runtime/vm/cha_test.cc
+++ b/runtime/vm/cha_test.cc
@@ -86,11 +86,11 @@
   EXPECT(!cha.HasSubclasses(kSmiCid));
   EXPECT(!cha.HasSubclasses(kNullCid));
 
-  EXPECT(cha.HasSubclasses(class_a));
-  EXPECT(cha.HasSubclasses(class_b));
-  EXPECT(!cha.HasSubclasses(class_c));
+  EXPECT(CHA::HasSubclasses(class_a));
+  EXPECT(CHA::HasSubclasses(class_b));
+  EXPECT(!CHA::HasSubclasses(class_c));
   cha.AddToLeafClasses(class_c);
-  EXPECT(!cha.HasSubclasses(class_d));
+  EXPECT(!CHA::HasSubclasses(class_d));
   cha.AddToLeafClasses(class_d);
 
   EXPECT(!ContainsCid(cha.leaf_classes(), class_a.id()));
diff --git a/runtime/vm/class_finalizer.cc b/runtime/vm/class_finalizer.cc
index c3c152b..46f3f4d 100644
--- a/runtime/vm/class_finalizer.cc
+++ b/runtime/vm/class_finalizer.cc
@@ -2332,6 +2332,9 @@
   if (cls.is_finalized()) {
     return;
   }
+  if (FLAG_trace_class_finalization) {
+    OS::Print("Finalize %s\n", cls.ToCString());
+  }
   if (cls.is_patch()) {
     // The fields and functions of a patch class are copied to the
     // patched class after parsing. There is nothing to finalize.
@@ -2340,9 +2343,6 @@
     cls.set_is_finalized();
     return;
   }
-  if (FLAG_trace_class_finalization) {
-    OS::Print("Finalize %s\n", cls.ToCString());
-  }
   if (cls.IsMixinApplication()) {
     // Copy instance methods and fields from the mixin class.
     // This has to happen before the check whether the methods of
diff --git a/runtime/vm/code_generator.cc b/runtime/vm/code_generator.cc
index 4485c58..a4359a7 100644
--- a/runtime/vm/code_generator.cc
+++ b/runtime/vm/code_generator.cc
@@ -69,6 +69,7 @@
             "Deoptimize on every N stack overflow checks");
 DEFINE_FLAG(charp, deoptimize_filter, NULL,
             "Deoptimize in named function on stack overflow checks");
+DEFINE_FLAG(bool, lazy_dispatchers, true, "Lazily generate dispatchers");
 
 #ifdef DEBUG
 DEFINE_FLAG(charp, gc_at_instance_allocation, NULL,
@@ -698,7 +699,6 @@
 // Gets called from debug stub when code reaches a breakpoint
 // set on a runtime stub call.
 DEFINE_RUNTIME_ENTRY(BreakpointRuntimeHandler, 0) {
-  ASSERT(isolate->debugger() != NULL);
   DartFrameIterator iterator;
   StackFrame* caller_frame = iterator.NextFrame();
   ASSERT(caller_frame != NULL);
@@ -711,7 +711,6 @@
 
 
 DEFINE_RUNTIME_ENTRY(SingleStepHandler, 0) {
-  ASSERT(isolate->debugger() != NULL);
   isolate->debugger()->DebuggerStepCallback();
 }
 
@@ -776,6 +775,9 @@
                                 target_name,
                                 args_descriptor,
                                 &result)) {
+    if (!FLAG_lazy_dispatchers) {
+      return result.raw();  // Return null.
+    }
     ArgumentsDescriptor desc(args_descriptor);
     const Function& target_function =
         Function::Handle(receiver_class.GetInvocationDispatcher(
@@ -811,7 +813,10 @@
     }
     target_function = InlineCacheMissHelper(receiver, ic_data);
   }
-  ASSERT(!target_function.IsNull());
+  if (target_function.IsNull()) {
+    ASSERT(!FLAG_lazy_dispatchers);
+    return target_function.raw();
+  }
   if (args.length() == 1) {
     ic_data.AddReceiverCheck(args[0]->GetClassId(), target_function);
   } else {
@@ -1012,8 +1017,11 @@
   if (target_function.IsNull()) {
     target_function = InlineCacheMissHelper(receiver, ic_data);
   }
-
-  ASSERT(!target_function.IsNull());
+  if (target_function.IsNull()) {
+    ASSERT(!FLAG_lazy_dispatchers);
+    arguments.SetReturn(target_function);
+    return;
+  }
   // Insert function found into cache and return it.
   cache.EnsureCapacity();
   const Smi& class_id = Smi::Handle(Smi::New(cls.id()));
@@ -1022,6 +1030,30 @@
 }
 
 
+// Invoke appropriate noSuchMethod or closure from getter.
+// Arg0: receiver
+// Arg1: IC data
+// Arg2: arguments descriptor array
+// Arg3: arguments array
+DEFINE_RUNTIME_ENTRY(InvokeNoSuchMethodDispatcher, 4) {
+  ASSERT(!FLAG_lazy_dispatchers);
+  const Instance& receiver = Instance::CheckedHandle(arguments.ArgAt(0));
+  const ICData& ic_data = ICData::CheckedHandle(arguments.ArgAt(1));
+  const Array& orig_arguments_desc = Array::CheckedHandle(arguments.ArgAt(2));
+  const Array& orig_arguments = Array::CheckedHandle(arguments.ArgAt(3));
+  const String& target_name = String::Handle(ic_data.target_name());
+  // Handle noSuchMethod invocation.
+  const Object& result = Object::Handle(
+      DartEntry::InvokeNoSuchMethod(receiver,
+                                    target_name,
+                                    orig_arguments,
+                                    orig_arguments_desc));
+  CheckResultError(result);
+  arguments.SetReturn(result);
+}
+
+
+
 // Invoke appropriate noSuchMethod function.
 // Arg0: receiver (closure object)
 // Arg1: arguments descriptor array.
diff --git a/runtime/vm/code_generator.h b/runtime/vm/code_generator.h
index 131f7ee..49a63f6 100644
--- a/runtime/vm/code_generator.h
+++ b/runtime/vm/code_generator.h
@@ -37,6 +37,7 @@
 DECLARE_RUNTIME_ENTRY(InstantiateType);
 DECLARE_RUNTIME_ENTRY(InstantiateTypeArguments);
 DECLARE_RUNTIME_ENTRY(InvokeClosureNoSuchMethod);
+DECLARE_RUNTIME_ENTRY(InvokeNoSuchMethodDispatcher);
 DECLARE_RUNTIME_ENTRY(MegamorphicCacheMissHandler);
 DECLARE_RUNTIME_ENTRY(OptimizeInvokedFunction);
 DECLARE_RUNTIME_ENTRY(TraceICCall);
diff --git a/runtime/vm/code_patcher_arm.cc b/runtime/vm/code_patcher_arm.cc
index b633fb7..f443c13 100644
--- a/runtime/vm/code_patcher_arm.cc
+++ b/runtime/vm/code_patcher_arm.cc
@@ -86,7 +86,7 @@
  public:
   EdgeCounter(uword pc, const Code& code)
       : end_(pc - FlowGraphCompiler::EdgeCounterIncrementSizeInBytes()),
-        object_pool_(Array::Handle(code.ObjectPool())) {
+        object_pool_(ObjectPool::Handle(code.GetObjectPool())) {
     // An IsValid predicate is complicated and duplicates the code in the
     // decoding function.  Instead we rely on decoding the pattern which
     // will assert partial validity.
@@ -97,7 +97,7 @@
     intptr_t index;
     InstructionPattern::DecodeLoadWordFromPool(end_, &ignored, &index);
     ASSERT(ignored == R0);
-    return object_pool_.At(index);
+    return object_pool_.ObjectAt(index);
   }
 
  private:
@@ -109,7 +109,7 @@
   static const intptr_t kAdjust = 3 * Instr::kInstrSize;
 
   uword end_;
-  const Array& object_pool_;
+  const ObjectPool& object_pool_;
 };
 
 
diff --git a/runtime/vm/code_patcher_arm64.cc b/runtime/vm/code_patcher_arm64.cc
index f44da2f..7b0afef 100644
--- a/runtime/vm/code_patcher_arm64.cc
+++ b/runtime/vm/code_patcher_arm64.cc
@@ -25,7 +25,7 @@
  public:
   PoolPointerCall(uword pc, const Code& code)
       : end_(pc),
-        object_pool_(Array::Handle(code.ObjectPool())) {
+        object_pool_(ObjectPool::Handle(code.GetObjectPool())) {
     // Last instruction: blr ip0.
     ASSERT(*(reinterpret_cast<uint32_t*>(end_) - 1) == 0xd63f0200);
     InstructionPattern::DecodeLoadWordFromPool(
@@ -37,19 +37,18 @@
   }
 
   uword Target() const {
-    return reinterpret_cast<uword>(object_pool_.At(pp_index()));
+    return object_pool_.RawValueAt(pp_index());
   }
 
   void SetTarget(uword target) const {
-    const Smi& smi = Smi::Handle(reinterpret_cast<RawSmi*>(target));
-    object_pool_.SetAt(pp_index(), smi);
+    object_pool_.SetRawValueAt(pp_index(), target);
     // No need to flush the instruction cache, since the code is not modified.
   }
 
  private:
   static const int kCallPatternSize = 3 * Instr::kInstrSize;
   uword end_;
-  const Array& object_pool_;
+  const ObjectPool& object_pool_;
   Register reg_;
   intptr_t index_;
   DISALLOW_IMPLICIT_CONSTRUCTORS(PoolPointerCall);
@@ -126,7 +125,8 @@
 class EdgeCounter : public ValueObject {
  public:
   EdgeCounter(uword pc, const Code& code)
-      : end_(pc - kAdjust), object_pool_(Array::Handle(code.ObjectPool())) {
+      : end_(pc - kAdjust),
+        object_pool_(ObjectPool::Handle(code.GetObjectPool())) {
     // An IsValid predicate is complicated and duplicates the code in the
     // decoding function.  Instead we rely on decoding the pattern which
     // will assert partial validity.
@@ -137,7 +137,7 @@
     intptr_t index;
     InstructionPattern::DecodeLoadWordFromPool(end_, &ignored, &index);
     ASSERT(ignored == R0);
-    return object_pool_.At(index);
+    return object_pool_.ObjectAt(index);
   }
 
  private:
@@ -149,7 +149,7 @@
   static const intptr_t kAdjust = 3 * Instr::kInstrSize;
 
   uword end_;
-  const Array& object_pool_;
+  const ObjectPool& object_pool_;
 };
 
 
diff --git a/runtime/vm/code_patcher_mips.cc b/runtime/vm/code_patcher_mips.cc
index 95d220b..1794ab8 100644
--- a/runtime/vm/code_patcher_mips.cc
+++ b/runtime/vm/code_patcher_mips.cc
@@ -84,7 +84,8 @@
 class EdgeCounter : public ValueObject {
  public:
   EdgeCounter(uword pc, const Code& code)
-      : end_(pc - kAdjust), object_pool_(Array::Handle(code.ObjectPool())) {
+      : end_(pc - kAdjust),
+        object_pool_(ObjectPool::Handle(code.GetObjectPool())) {
     // An IsValid predicate is complicated and duplicates the code in the
     // decoding function.  Instead we rely on decoding the pattern which
     // will assert partial validity.
@@ -95,7 +96,7 @@
     intptr_t index;
     InstructionPattern::DecodeLoadWordFromPool(end_, &ignored, &index);
     ASSERT(ignored == T0);
-    return object_pool_.At(index);
+    return object_pool_.ObjectAt(index);
   }
 
  private:
@@ -107,7 +108,7 @@
   static const intptr_t kAdjust = 3 * Instr::kInstrSize;
 
   uword end_;
-  const Array& object_pool_;
+  const ObjectPool& object_pool_;
 };
 
 
diff --git a/runtime/vm/code_patcher_x64.cc b/runtime/vm/code_patcher_x64.cc
index 4a6da2b..1f3f8e1 100644
--- a/runtime/vm/code_patcher_x64.cc
+++ b/runtime/vm/code_patcher_x64.cc
@@ -24,7 +24,7 @@
  public:
   UnoptimizedCall(uword return_address, const Code& code)
       : start_(return_address - kCallPatternSize),
-        object_pool_(Array::Handle(code.ObjectPool())) {
+        object_pool_(ObjectPool::Handle(code.GetObjectPool())) {
     ASSERT(IsValid(return_address));
     ASSERT((kCallPatternSize - 7) == Assembler::kCallExternalLabelSize);
   }
@@ -42,24 +42,23 @@
 
   RawObject* ic_data() const {
     intptr_t index = InstructionPattern::IndexFromPPLoad(start_ + 3);
-    return object_pool_.At(index);
+    return object_pool_.ObjectAt(index);
   }
 
   uword target() const {
     intptr_t index = InstructionPattern::IndexFromPPLoad(start_ + 10);
-    return reinterpret_cast<uword>(object_pool_.At(index));
+    return object_pool_.RawValueAt(index);
   }
 
   void set_target(uword target) const {
     intptr_t index = InstructionPattern::IndexFromPPLoad(start_ + 10);
-    const Smi& smi = Smi::Handle(reinterpret_cast<RawSmi*>(target));
-    object_pool_.SetAt(index, smi);
+    object_pool_.SetRawValueAt(index, target);
     // No need to flush the instruction cache, since the code is not modified.
   }
 
  private:
   uword start_;
-  const Array& object_pool_;
+  const ObjectPool& object_pool_;
   DISALLOW_IMPLICIT_CONSTRUCTORS(UnoptimizedCall);
 };
 
@@ -104,7 +103,7 @@
  public:
   explicit PoolPointerCall(uword return_address, const Code& code)
       : start_(return_address - kCallPatternSize),
-        object_pool_(Array::Handle(code.ObjectPool())) {
+        object_pool_(ObjectPool::Handle(code.GetObjectPool())) {
     ASSERT(IsValid(return_address));
   }
 
@@ -122,18 +121,17 @@
   }
 
   uword Target() const {
-    return reinterpret_cast<uword>(object_pool_.At(pp_index()));
+    return object_pool_.RawValueAt(pp_index());
   }
 
   void SetTarget(uword target) const {
-    const Smi& smi = Smi::Handle(reinterpret_cast<RawSmi*>(target));
-    object_pool_.SetAt(pp_index(), smi);
+    object_pool_.SetRawValueAt(pp_index(), target);
     // No need to flush the instruction cache, since the code is not modified.
   }
 
  protected:
   uword start_;
-  const Array& object_pool_;
+  const ObjectPool& object_pool_;
 
  private:
   DISALLOW_IMPLICIT_CONSTRUCTORS(PoolPointerCall);
@@ -219,7 +217,7 @@
  public:
   EdgeCounter(uword pc, const Code& code)
       : end_(pc - FlowGraphCompiler::EdgeCounterIncrementSizeInBytes()),
-        object_pool_(Array::Handle(code.ObjectPool())) {
+        object_pool_(ObjectPool::Handle(code.GetObjectPool())) {
     ASSERT(IsValid(end_));
   }
 
@@ -229,12 +227,12 @@
   }
 
   RawObject* edge_counter() const {
-    return object_pool_.At(InstructionPattern::IndexFromPPLoad(end_ - 4));
+    return object_pool_.ObjectAt(InstructionPattern::IndexFromPPLoad(end_ - 4));
   }
 
  private:
   uword end_;
-  const Array& object_pool_;
+  const ObjectPool& object_pool_;
 };
 
 
diff --git a/runtime/vm/compiler.cc b/runtime/vm/compiler.cc
index 05093ea..885208b 100644
--- a/runtime/vm/compiler.cc
+++ b/runtime/vm/compiler.cc
@@ -71,7 +71,6 @@
 
 
 bool Compiler::always_optimize_ = false;
-bool Compiler::guess_other_cid_ = true;
 
 
 // TODO(zerny): Factor out unoptimizing/optimizing pipelines and remove
@@ -344,6 +343,12 @@
       ClassFinalizer::FinalizeClass(parse_class);
       parse_class.reset_is_marked_for_parsing();
     }
+    for (intptr_t i = (patch_list.Length() - 1); i >=0 ; i--) {
+      parse_class ^= patch_list.At(i);
+      ASSERT(!parse_class.IsNull());
+      ClassFinalizer::FinalizeClass(parse_class);
+      parse_class.reset_is_marked_for_parsing();
+    }
 
     return Error::null();
   } else {
@@ -880,15 +885,8 @@
     ISL_Print("}\n");
   }
 
-  const Array& object_pool = Array::Handle(code.ObjectPool());
-  if (object_pool.Length() > 0) {
-    ISL_Print("Object Pool: {\n");
-    for (intptr_t i = 0; i < object_pool.Length(); i++) {
-      ISL_Print("  %" Pd ": %s\n", i,
-          Object::Handle(object_pool.At(i)).ToCString());
-    }
-    ISL_Print("}\n");
-  }
+  const ObjectPool& object_pool = ObjectPool::Handle(code.GetObjectPool());
+  object_pool.DebugPrint();
 
   ISL_Print("Stackmaps for function '%s' {\n", function_fullname);
   if (code.stackmaps() != Array::null()) {
@@ -1071,7 +1069,10 @@
 
 RawError* Compiler::CompileFunction(Thread* thread,
                                     const Function& function) {
-  VMTagScope tagScope(thread->isolate(), VMTag::kCompileUnoptimizedTagId);
+  Isolate* isolate = thread->isolate();
+  VMTagScope tagScope(isolate, VMTag::kCompileUnoptimizedTagId);
+  TIMELINE_FUNCTION_COMPILATION_DURATION(isolate, "Function", function);
+
   CompilationPipeline* pipeline =
       CompilationPipeline::New(thread->zone(), function);
 
@@ -1116,7 +1117,11 @@
 RawError* Compiler::CompileOptimizedFunction(Thread* thread,
                                              const Function& function,
                                              intptr_t osr_id) {
-  VMTagScope tagScope(thread->isolate(), VMTag::kCompileOptimizedTagId);
+  Isolate* isolate = thread->isolate();
+  VMTagScope tagScope(isolate, VMTag::kCompileOptimizedTagId);
+  TIMELINE_FUNCTION_COMPILATION_DURATION(isolate,
+                                         "OptimizedFunction", function);
+
   CompilationPipeline* pipeline =
       CompilationPipeline::New(thread->zone(), function);
   return CompileFunctionHelper(pipeline, function, true, osr_id);
diff --git a/runtime/vm/compiler.h b/runtime/vm/compiler.h
index c510cd2..d4099cc 100644
--- a/runtime/vm/compiler.h
+++ b/runtime/vm/compiler.h
@@ -90,13 +90,8 @@
   static bool always_optimize() { return always_optimize_; }
   static void set_always_optimize(bool value) { always_optimize_ = value; }
 
-  // Default: true.
-  static bool guess_other_cid() { return guess_other_cid_; }
-  static void set_guess_other_cid(bool value) { guess_other_cid_ = value; }
-
  private:
   static bool always_optimize_;
-  static bool guess_other_cid_;
 };
 
 }  // namespace dart
diff --git a/runtime/vm/compiler_test.cc b/runtime/vm/compiler_test.cc
index 7b6ada7..18a47ac 100644
--- a/runtime/vm/compiler_test.cc
+++ b/runtime/vm/compiler_test.cc
@@ -162,16 +162,26 @@
   const String& expression = String::Handle(String::New("3 + 4"));
   Object& val = Object::Handle();
 
-  const intptr_t classTableSize = 1 << RawObject::kClassIdTagSize;
-  for (intptr_t i = 0; i < classTableSize; i++) {
-    StackZone zone(Isolate::Current());
-    val = lib.Evaluate(expression, Array::empty_array(), Array::empty_array());
-  }
-
+  // Run once to ensure everything we touch is compiled.
+  val = lib.Evaluate(expression, Array::empty_array(), Array::empty_array());
   EXPECT(!val.IsNull());
   EXPECT(!val.IsError());
   EXPECT(val.IsInteger());
   EXPECT_EQ(7, Integer::Cast(val).AsInt64Value());
+
+  intptr_t initial_class_table_size =
+      Isolate::Current()->class_table()->NumCids();
+
+  val = lib.Evaluate(expression, Array::empty_array(), Array::empty_array());
+  EXPECT(!val.IsNull());
+  EXPECT(!val.IsError());
+  EXPECT(val.IsInteger());
+  EXPECT_EQ(7, Integer::Cast(val).AsInt64Value());
+
+  intptr_t final_class_table_size =
+      Isolate::Current()->class_table()->NumCids();
+  // Eval should not eat into this non-renewable resource.
+  EXPECT_EQ(initial_class_table_size, final_class_table_size);
 }
 
 }  // namespace dart
diff --git a/runtime/vm/custom_isolate_test.cc b/runtime/vm/custom_isolate_test.cc
index a2e2e44..af30507 100644
--- a/runtime/vm/custom_isolate_test.cc
+++ b/runtime/vm/custom_isolate_test.cc
@@ -312,6 +312,8 @@
 
 
 UNIT_TEST_CASE(CustomIsolates) {
+  FLAG_verify_handles = true;
+  FLAG_verify_on_transition = true;
   event_queue = new EventQueue();
 
   Dart_Isolate dart_isolate = TestCase::CreateTestIsolate();
diff --git a/runtime/vm/dart.cc b/runtime/vm/dart.cc
index d49b7f4..4fd93cb 100644
--- a/runtime/vm/dart.cc
+++ b/runtime/vm/dart.cc
@@ -27,6 +27,7 @@
 #include "vm/symbols.h"
 #include "vm/thread_interrupter.h"
 #include "vm/thread_pool.h"
+#include "vm/timeline.h"
 #include "vm/virtual_memory.h"
 #include "vm/zone.h"
 
@@ -69,6 +70,7 @@
 
  private:
   VMHandles handles_;
+  LocalHandles api_handles_;
 
   friend class Dart;
   DISALLOW_COPY_AND_ASSIGN(ReadOnlyHandles);
@@ -103,6 +105,7 @@
   Profiler::InitOnce();
   SemiSpace::InitOnce();
   Metric::InitOnce();
+  StoreBuffer::InitOnce();
 
 #if defined(USING_SIMULATOR)
   Simulator::InitOnce();
@@ -131,6 +134,7 @@
                0,  // New gen size 0; VM isolate should only allocate in old.
                FLAG_old_gen_heap_size * MBInWords,
                FLAG_external_max_size * MBInWords);
+    Object::InitNull(vm_isolate_);
     ObjectStore::Init(vm_isolate_);
     TargetCPUFeatures::InitOnce();
     Object::InitOnce(vm_isolate_);
@@ -177,10 +181,8 @@
     vm_isolate_->heap()->Verify(kRequireMarked);
 #endif
   }
-  // There is a planned and known asymmetry here: We enter one scope for the VM
-  // isolate so that we can allocate the "persistent" scoped handles for the
-  // predefined API values (such as Dart_True, Dart_False and Dart_Null).
-  Dart_EnterScope();
+  // Allocate the "persistent" scoped handles for the predefined API
+  // values (such as Dart_True, Dart_False and Dart_Null).
   Api::InitHandles();
 
   Thread::ExitIsolate();  // Unregister the VM isolate from this thread.
@@ -298,12 +300,12 @@
   Object::VerifyBuiltinVtables();
 
   StubCode::Init(isolate);
+  isolate->megamorphic_cache_table()->InitMissHandler();
   if (snapshot_buffer == NULL) {
     if (!isolate->object_store()->PreallocateObjects()) {
       return isolate->object_store()->sticky_error();
     }
   }
-  isolate->megamorphic_cache_table()->InitMissHandler();
 
   isolate->heap()->EnableGrowthControl();
   isolate->set_init_callback_data(data);
@@ -324,6 +326,8 @@
   const UserTag& default_tag = UserTag::Handle(UserTag::DefaultTag());
   isolate->set_current_tag(default_tag);
 
+  isolate->SetTimelineEventRecorder(new TimelineEventRingRecorder());
+
   if (FLAG_keep_code) {
     isolate->set_deoptimized_code_array(
       GrowableObjectArray::Handle(GrowableObjectArray::New()));
@@ -357,9 +361,22 @@
 }
 
 
+LocalHandle* Dart::AllocateReadOnlyApiHandle() {
+  ASSERT(Isolate::Current() == Dart::vm_isolate());
+  ASSERT(predefined_handles_ != NULL);
+  return predefined_handles_->api_handles_.AllocateHandle();
+}
+
+
 bool Dart::IsReadOnlyHandle(uword address) {
   ASSERT(predefined_handles_ != NULL);
   return predefined_handles_->handles_.IsValidScopedHandle(address);
 }
 
+
+bool Dart::IsReadOnlyApiHandle(Dart_Handle handle) {
+  ASSERT(predefined_handles_ != NULL);
+  return predefined_handles_->api_handles_.IsValidHandle(handle);
+}
+
 }  // namespace dart
diff --git a/runtime/vm/dart.h b/runtime/vm/dart.h
index a3234ca..be6db3b 100644
--- a/runtime/vm/dart.h
+++ b/runtime/vm/dart.h
@@ -13,6 +13,7 @@
 // Forward declarations.
 class DebugInfo;
 class Isolate;
+class LocalHandle;
 class RawError;
 class ReadOnlyHandles;
 class ThreadPool;
@@ -46,6 +47,9 @@
   }
   static DebugInfo* pprof_symbol_generator() { return pprof_symbol_generator_; }
 
+  static LocalHandle* AllocateReadOnlyApiHandle();
+  static bool IsReadOnlyApiHandle(Dart_Handle handle);
+
   static uword AllocateReadOnlyHandle();
   static bool IsReadOnlyHandle(uword address);
 
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index 15ef1ad..9868346 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -36,6 +36,7 @@
 #include "vm/stack_frame.h"
 #include "vm/symbols.h"
 #include "vm/tags.h"
+#include "vm/timeline.h"
 #include "vm/timer.h"
 #include "vm/unicode.h"
 #include "vm/verifier.h"
@@ -71,6 +72,46 @@
 }
 
 
+#if defined(DEBUG)
+// An object visitor which will iterate over all the function objects in the
+// heap and check if the result type and parameter types are canonicalized
+// or not. An assertion is raised if a type is not canonicalized.
+class FunctionVisitor : public ObjectVisitor {
+ public:
+  explicit FunctionVisitor(Isolate* isolate) :
+      ObjectVisitor(isolate),
+      classHandle_(Class::Handle(isolate)),
+      funcHandle_(Function::Handle(isolate)),
+      typeHandle_(AbstractType::Handle(isolate)) {}
+
+  void VisitObject(RawObject* obj) {
+    if (obj->IsFunction()) {
+      funcHandle_ ^= obj;
+      classHandle_ ^= funcHandle_.Owner();
+      // Verify that the result type of a function is canonical or a
+      // TypeParameter.
+      typeHandle_ ^= funcHandle_.result_type();
+      ASSERT(typeHandle_.IsNull() ||
+             typeHandle_.IsTypeParameter() ||
+             typeHandle_.IsCanonical());
+      // Verify that the types in the function signature are all canonical or
+      // a TypeParameter.
+      const intptr_t num_parameters = funcHandle_.NumParameters();
+      for (intptr_t i = 0; i < num_parameters; i++) {
+        typeHandle_ = funcHandle_.ParameterTypeAt(i);
+        ASSERT(typeHandle_.IsTypeParameter() || typeHandle_.IsCanonical());
+      }
+    }
+  }
+
+ private:
+  Class& classHandle_;
+  Function& funcHandle_;
+  AbstractType& typeHandle_;
+};
+#endif  // #if defined(DEBUG).
+
+
 static RawInstance* GetListInstance(Isolate* isolate, const Object& obj) {
   if (obj.IsInstance()) {
     const Library& core_lib = Library::Handle(Library::CoreLibrary());
@@ -309,7 +350,7 @@
   ASSERT(local_handles != NULL);
   LocalHandle* ref = local_handles->AllocateHandle();
   ref->set_raw(raw);
-  return reinterpret_cast<Dart_Handle>(ref);
+  return ref->apiHandle();
 }
 
 
@@ -335,7 +376,7 @@
   ASSERT(state != NULL);
   ASSERT(!FLAG_verify_handles ||
          state->IsValidLocalHandle(object) ||
-         Dart::vm_isolate()->api_state()->IsValidLocalHandle(object));
+         Dart::IsReadOnlyApiHandle(object));
   ASSERT(FinalizablePersistentHandle::raw_offset() == 0 &&
          PersistentHandle::raw_offset() == 0 &&
          LocalHandle::raw_offset() == 0);
@@ -452,23 +493,32 @@
 }
 
 
+static Dart_Handle InitNewReadOnlyApiHandle(RawObject* raw) {
+  ASSERT(raw->IsVMHeapObject());
+  LocalHandle* ref = Dart::AllocateReadOnlyApiHandle();
+  ref->set_raw(raw);
+  return ref->apiHandle();
+}
+
+
 void Api::InitHandles() {
   Isolate* isolate = Isolate::Current();
   ASSERT(isolate != NULL);
   ASSERT(isolate == Dart::vm_isolate());
   ApiState* state = isolate->api_state();
   ASSERT(state != NULL);
+
   ASSERT(true_handle_ == NULL);
-  true_handle_ = Api::InitNewHandle(isolate, Bool::True().raw());
+  true_handle_ = InitNewReadOnlyApiHandle(Bool::True().raw());
 
   ASSERT(false_handle_ == NULL);
-  false_handle_ = Api::InitNewHandle(isolate, Bool::False().raw());
+  false_handle_ = InitNewReadOnlyApiHandle(Bool::False().raw());
 
   ASSERT(null_handle_ == NULL);
-  null_handle_ = Api::InitNewHandle(isolate, Object::null());
+  null_handle_ = InitNewReadOnlyApiHandle(Object::null());
 
   ASSERT(empty_string_handle_ == NULL);
-  empty_string_handle_ = Api::InitNewHandle(isolate, Symbols::Empty().raw());
+  empty_string_handle_ = InitNewReadOnlyApiHandle(Symbols::Empty().raw());
 }
 
 
@@ -764,9 +814,15 @@
   DARTSCOPE(isolate);
   CHECK_CALLBACK_STATE(isolate);
 
-  const Instance& obj = Api::UnwrapInstanceHandle(isolate, exception);
-  if (obj.IsNull()) {
-    RETURN_TYPE_ERROR(isolate, exception, Instance);
+  Instance& obj = Instance::Handle(isolate);
+  intptr_t class_id = Api::ClassId(exception);
+  if ((class_id == kApiErrorCid) || (class_id == kLanguageErrorCid)) {
+    obj = String::New(::Dart_GetError(exception));
+  } else {
+    obj = Api::UnwrapInstanceHandle(isolate, exception).raw();
+    if (obj.IsNull()) {
+      RETURN_TYPE_ERROR(isolate, exception, Instance);
+    }
   }
   const Stacktrace& stacktrace = Stacktrace::Handle(isolate);
   return Api::NewHandle(isolate, UnhandledException::New(obj, stacktrace));
@@ -1463,6 +1519,12 @@
   if (::Dart_IsError(state)) {
     return state;
   }
+  isolate->heap()->CollectAllGarbage();
+#if defined(DEBUG)
+  FunctionVisitor check_canonical(isolate);
+  isolate->heap()->VisitObjects(&check_canonical);
+#endif  // #if defined(DEBUG).
+
   // Since this is only a snapshot the root library should not be set.
   isolate->object_store()->set_root_library(Library::Handle(isolate));
   FullSnapshotWriter writer(vm_isolate_snapshot_buffer,
@@ -1475,8 +1537,9 @@
 }
 
 
-DART_EXPORT Dart_Handle Dart_CreateScriptSnapshot(uint8_t** buffer,
-                                                  intptr_t* size) {
+static Dart_Handle createLibrarySnapshot(Dart_Handle library,
+                                         uint8_t** buffer,
+                                         intptr_t* size) {
   Isolate* isolate = Isolate::Current();
   DARTSCOPE(isolate);
   TIMERSCOPE(isolate, time_creating_snapshot);
@@ -1491,20 +1554,32 @@
   if (::Dart_IsError(state)) {
     return state;
   }
-  Library& library =
-      Library::Handle(isolate, isolate->object_store()->root_library());
-  if (library.IsNull()) {
-    return
-        Api::NewError("%s expects the isolate to have a script loaded in it.",
-                      CURRENT_FUNC);
+  Library& lib = Library::Handle(isolate);
+  if (library == Dart_Null()) {
+    lib ^= isolate->object_store()->root_library();
+  } else {
+    lib ^= Api::UnwrapHandle(library);
   }
   ScriptSnapshotWriter writer(buffer, ApiReallocate);
-  writer.WriteScriptSnapshot(library);
+  writer.WriteScriptSnapshot(lib);
   *size = writer.BytesWritten();
   return Api::Success();
 }
 
 
+DART_EXPORT Dart_Handle Dart_CreateScriptSnapshot(uint8_t** buffer,
+                                                  intptr_t* size) {
+  return createLibrarySnapshot(Dart_Null(), buffer, size);
+}
+
+
+DART_EXPORT Dart_Handle Dart_CreateLibrarySnapshot(Dart_Handle library,
+                                                   uint8_t** buffer,
+                                                   intptr_t* size) {
+  return createLibrarySnapshot(library, buffer, size);
+}
+
+
 DART_EXPORT void Dart_InterruptIsolate(Dart_Isolate isolate) {
   TRACE_API_CALL(CURRENT_FUNC);
   if (isolate == NULL) {
@@ -3572,6 +3647,11 @@
     }
   }
   if (FLAG_verify_acquired_data) {
+    if (external) {
+      ASSERT(!isolate->heap()->Contains(reinterpret_cast<uword>(data_tmp)));
+    } else {
+      ASSERT(isolate->heap()->Contains(reinterpret_cast<uword>(data_tmp)));
+    }
     const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(object));
     WeakTable* table = isolate->api_state()->acquired_table();
     intptr_t current = table->GetValue(obj.raw());
@@ -5609,4 +5689,108 @@
   Service::RegisterRootEmbedderCallback(name, callback, user_data);
 }
 
+
+DART_EXPORT Dart_Handle Dart_TimelineDuration(const char* label,
+                                              int64_t start_micros,
+                                              int64_t end_micros) {
+  Isolate* isolate = Isolate::Current();
+  CHECK_ISOLATE(isolate);
+  if (label == NULL) {
+    RETURN_NULL_ERROR(label);
+  }
+  if (start_micros > end_micros) {
+    const char* msg = "%s: start_micros must be <= end_micros";
+    return Api::NewError(msg, CURRENT_FUNC);
+  }
+  TimelineStream* stream = isolate->GetEmbedderStream();
+  ASSERT(stream != NULL);
+  TimelineEvent* event = stream->StartEvent();
+  if (event != NULL) {
+    event->Duration(label, start_micros, end_micros);
+    event->Complete();
+  }
+  return Api::Success();
+}
+
+
+DART_EXPORT Dart_Handle Dart_TimelineInstant(const char* label) {
+  Isolate* isolate = Isolate::Current();
+  CHECK_ISOLATE(isolate);
+  if (label == NULL) {
+    RETURN_NULL_ERROR(label);
+  }
+  TimelineStream* stream = isolate->GetEmbedderStream();
+  ASSERT(stream != NULL);
+  TimelineEvent* event = stream->StartEvent();
+  if (event != NULL) {
+    event->Instant(label);
+    event->Complete();
+  }
+  return Api::Success();
+}
+
+
+DART_EXPORT Dart_Handle Dart_TimelineAsyncBegin(const char* label,
+                                                int64_t* async_id) {
+  Isolate* isolate = Isolate::Current();
+  CHECK_ISOLATE(isolate);
+  if (label == NULL) {
+    RETURN_NULL_ERROR(label);
+  }
+  if (async_id == NULL) {
+    RETURN_NULL_ERROR(async_id);
+  }
+  *async_id = -1;
+  TimelineStream* stream = isolate->GetEmbedderStream();
+  ASSERT(stream != NULL);
+  TimelineEvent* event = stream->StartEvent();
+  if (event != NULL) {
+    *async_id = event->AsyncBegin(label);
+    event->Complete();
+  }
+  return Api::Success();
+}
+
+
+DART_EXPORT Dart_Handle Dart_TimelineAsyncInstant(const char* label,
+                                                  int64_t async_id) {
+  if (async_id < 0) {
+    return Api::Success();
+  }
+  Isolate* isolate = Isolate::Current();
+  CHECK_ISOLATE(isolate);
+  if (label == NULL) {
+    RETURN_NULL_ERROR(label);
+  }
+  TimelineStream* stream = isolate->GetEmbedderStream();
+  ASSERT(stream != NULL);
+  TimelineEvent* event = stream->StartEvent();
+  if (event != NULL) {
+    event->AsyncInstant(label, async_id);
+    event->Complete();
+  }
+  return Api::Success();
+}
+
+
+DART_EXPORT Dart_Handle Dart_TimelineAsyncEnd(const char* label,
+                                              int64_t async_id) {
+  if (async_id < 0) {
+    return Api::Success();
+  }
+  Isolate* isolate = Isolate::Current();
+  CHECK_ISOLATE(isolate);
+  if (label == NULL) {
+    RETURN_NULL_ERROR(label);
+  }
+  TimelineStream* stream = isolate->GetEmbedderStream();
+  ASSERT(stream != NULL);
+  TimelineEvent* event = stream->StartEvent();
+  if (event != NULL) {
+    event->AsyncEnd(label, async_id);
+    event->Complete();
+  }
+  return Api::Success();
+}
+
 }  // namespace dart
diff --git a/runtime/vm/dart_api_impl_test.cc b/runtime/vm/dart_api_impl_test.cc
index b79780c..896e14e 100644
--- a/runtime/vm/dart_api_impl_test.cc
+++ b/runtime/vm/dart_api_impl_test.cc
@@ -4,9 +4,9 @@
 
 #include "bin/builtin.h"
 #include "include/dart_api.h"
-#include "include/dart_debugger_api.h"
 #include "include/dart_mirrors_api.h"
 #include "include/dart_native_api.h"
+#include "include/dart_tools_api.h"
 #include "platform/assert.h"
 #include "platform/json.h"
 #include "platform/utils.h"
@@ -448,6 +448,59 @@
 }
 
 
+TEST_CASE(UnhandleExceptionError) {
+  Isolate* isolate = Isolate::Current();
+  const char* exception_cstr = "";
+
+  // Test with an API Error.
+  const char* kApiError = "Api Error Exception Test.";
+  Dart_Handle api_error = Api::NewHandle(
+      isolate,
+      ApiError::New(String::Handle(String::New(kApiError))));
+  Dart_Handle exception_error = Dart_NewUnhandledExceptionError(api_error);
+  EXPECT(!Dart_IsApiError(exception_error));
+  EXPECT(Dart_IsUnhandledExceptionError(exception_error));
+  EXPECT(Dart_IsString(Dart_ErrorGetException(exception_error)));
+  EXPECT_VALID(Dart_StringToCString(Dart_ErrorGetException(exception_error),
+                                    &exception_cstr));
+  EXPECT_STREQ(kApiError, exception_cstr);
+
+  // Test with a Compilation Error.
+  const char* kCompileError = "CompileError Exception Test.";
+  const String& compile_message =
+      String::Handle(String::New(kCompileError));
+  Dart_Handle compile_error =
+      Api::NewHandle(isolate, LanguageError::New(compile_message));
+  exception_error = Dart_NewUnhandledExceptionError(compile_error);
+  EXPECT(!Dart_IsApiError(exception_error));
+  EXPECT(Dart_IsUnhandledExceptionError(exception_error));
+  EXPECT(Dart_IsString(Dart_ErrorGetException(exception_error)));
+  EXPECT_VALID(Dart_StringToCString(Dart_ErrorGetException(exception_error),
+                                    &exception_cstr));
+  EXPECT_STREQ(kCompileError, exception_cstr);
+
+  // Test with a Fatal Error.
+  const String& fatal_message =
+      String::Handle(String::New("FatalError Exception Test."));
+  Dart_Handle fatal_error =
+      Api::NewHandle(isolate, UnwindError::New(fatal_message));
+  exception_error = Dart_NewUnhandledExceptionError(fatal_error);
+  EXPECT(Dart_IsError(exception_error));
+  EXPECT(!Dart_IsUnhandledExceptionError(exception_error));
+
+  // Test with a Regular object.
+  const char* kRegularString = "Regular String Exception Test.";
+  Dart_Handle obj = Api::NewHandle(isolate, String::New(kRegularString));
+  exception_error = Dart_NewUnhandledExceptionError(obj);
+  EXPECT(!Dart_IsApiError(exception_error));
+  EXPECT(Dart_IsUnhandledExceptionError(exception_error));
+  EXPECT(Dart_IsString(Dart_ErrorGetException(exception_error)));
+  EXPECT_VALID(Dart_StringToCString(Dart_ErrorGetException(exception_error),
+                                    &exception_cstr));
+  EXPECT_STREQ(kRegularString, exception_cstr);
+}
+
+
 void PropagateErrorNative(Dart_NativeArguments args) {
   Dart_EnterScope();
   Dart_Handle closure = Dart_GetNativeArgument(args, 0);
@@ -9056,6 +9109,7 @@
   EXPECT_EQ(6, value);
 }
 
+
 TEST_CASE(StringFromExternalTypedData) {
   const char* kScriptChars =
     "test(external) {\n"
@@ -9152,4 +9206,76 @@
   }
 }
 
+
+TEST_CASE(Timeline_Dart_TimelineDuration) {
+  Isolate* isolate = Isolate::Current();
+  // Grab embedder stream.
+  TimelineStream* stream = isolate->GetEmbedderStream();
+  // Make sure it is enabled.
+  stream->set_enabled(true);
+  // Add a duration event.
+  Dart_TimelineDuration("testDurationEvent", 0, 1);
+  // Check that it is in the output.
+  TimelineEventRecorder* recorder = isolate->timeline_event_recorder();
+  JSONStream js;
+  recorder->PrintJSON(&js);
+  EXPECT_SUBSTRING("testDurationEvent", js.ToCString());
+}
+
+
+TEST_CASE(Timeline_Dart_TimelineInstant) {
+  Isolate* isolate = Isolate::Current();
+  // Grab embedder stream.
+  TimelineStream* stream = isolate->GetEmbedderStream();
+  // Make sure it is enabled.
+  stream->set_enabled(true);
+  Dart_TimelineInstant("testInstantEvent");
+  // Check that it is in the output.
+  TimelineEventRecorder* recorder = isolate->timeline_event_recorder();
+  JSONStream js;
+  recorder->PrintJSON(&js);
+  EXPECT_SUBSTRING("testInstantEvent", js.ToCString());
+}
+
+
+TEST_CASE(Timeline_Dart_TimelineAsyncDisabled) {
+  Isolate* isolate = Isolate::Current();
+  // Grab embedder stream.
+  TimelineStream* stream = isolate->GetEmbedderStream();
+  // Make sure it is disabled.
+  stream->set_enabled(false);
+  int64_t async_id = -1;
+  Dart_TimelineAsyncBegin("testAsyncEvent", &async_id);
+  // Expect that the |async_id| is negative because the stream is disabled.
+  EXPECT(async_id < 0);
+  // Call Dart_TimelineAsyncEnd with a negative async_id.
+  Dart_TimelineAsyncEnd("testAsyncEvent", async_id);
+  // Check that testAsync is not in the output.
+  TimelineEventRecorder* recorder = isolate->timeline_event_recorder();
+  JSONStream js;
+  recorder->PrintJSON(&js);
+  EXPECT_NOTSUBSTRING("testAsyncEvent", js.ToCString());
+}
+
+
+TEST_CASE(Timeline_Dart_TimelineAsync) {
+  Isolate* isolate = Isolate::Current();
+  // Grab embedder stream.
+  TimelineStream* stream = isolate->GetEmbedderStream();
+  // Make sure it is enabled.
+  stream->set_enabled(true);
+  int64_t async_id = -1;
+  Dart_TimelineAsyncBegin("testAsyncEvent", &async_id);
+  // Expect that the |async_id| is >= 0.
+  EXPECT(async_id >= 0);
+
+  Dart_TimelineAsyncEnd("testAsyncEvent", async_id);
+
+  // Check that it is in the output.
+  TimelineEventRecorder* recorder = isolate->timeline_event_recorder();
+  JSONStream js;
+  recorder->PrintJSON(&js);
+  EXPECT_SUBSTRING("testAsyncEvent", js.ToCString());
+}
+
 }  // namespace dart
diff --git a/runtime/vm/dart_api_state.h b/runtime/vm/dart_api_state.h
index 34b9f9a..4f293540 100644
--- a/runtime/vm/dart_api_state.h
+++ b/runtime/vm/dart_api_state.h
@@ -53,6 +53,12 @@
   // Delete all memory associated with the zone.
   ~ApiZone() {
     Isolate* isolate = Isolate::Current();
+#if defined(DEBUG)
+    if (isolate == NULL) {
+      ASSERT(zone_.handles()->CountScopedHandles() == 0);
+      ASSERT(zone_.handles()->CountZoneHandles() == 0);
+    }
+#endif
     if ((isolate != NULL) && (isolate->current_zone() == &zone_)) {
       isolate->set_current_zone(zone_.previous_);
     }
@@ -129,6 +135,10 @@
   void set_raw(RawObject* raw) { raw_ = raw; }
   static intptr_t raw_offset() { return OFFSET_OF(LocalHandle, raw_); }
 
+  Dart_Handle apiHandle() {
+    return reinterpret_cast<Dart_Handle>(this);
+  }
+
  private:
   LocalHandle() { }
   ~LocalHandle() { }
@@ -632,7 +642,12 @@
         OSThread::GetThreadLocal(Api::api_native_key_));
   }
 
-  Zone* zone() { return zone_.GetZone(); }
+  Zone* zone() {
+    Zone* result = zone_.GetZone();
+    ASSERT(result->handles()->CountScopedHandles() == 0);
+    ASSERT(result->handles()->CountZoneHandles() == 0);
+    return result;
+  }
 
  private:
   ApiZone zone_;
diff --git a/runtime/vm/dart_entry.cc b/runtime/vm/dart_entry.cc
index 10c194b..9a1ea76 100644
--- a/runtime/vm/dart_entry.cc
+++ b/runtime/vm/dart_entry.cc
@@ -16,6 +16,8 @@
 
 namespace dart {
 
+DECLARE_FLAG(bool, lazy_dispatchers);
+
 // A cache of VM heap allocated arguments descriptors.
 RawArray* ArgumentsDescriptor::cached_args_descriptors_[kCachedDescriptorCount];
 
@@ -187,10 +189,19 @@
   const int kNumArguments = 2;
   ArgumentsDescriptor args_desc(
       Array::Handle(ArgumentsDescriptor::New(kNumArguments)));
-  const Function& function = Function::Handle(
+  Function& function = Function::Handle(
       Resolver::ResolveDynamic(receiver,
                                Symbols::NoSuchMethod(),
                                args_desc));
+  if (function.IsNull()) {
+    ASSERT(!FLAG_lazy_dispatchers);
+    // If noSuchMethod(invocation) is not found, call Object::noSuchMethod.
+    Isolate* isolate = Isolate::Current();
+    function ^= Resolver::ResolveDynamicForReceiverClass(
+        Class::Handle(isolate, isolate->object_store()->object_class()),
+        Symbols::NoSuchMethod(),
+        args_desc);
+  }
   ASSERT(!function.IsNull());
   const Array& args = Array::Handle(Array::New(kNumArguments));
   args.SetAt(0, receiver);
diff --git a/runtime/vm/debugger.cc b/runtime/vm/debugger.cc
index 939dafd..0364ac8 100644
--- a/runtime/vm/debugger.cc
+++ b/runtime/vm/debugger.cc
@@ -317,7 +317,6 @@
 void Debugger::SignalIsolateInterrupted() {
   if (HasEventHandler()) {
     Debugger* debugger = Isolate::Current()->debugger();
-    ASSERT(debugger != NULL);
     debugger->SignalIsolateEvent(DebuggerEvent::kIsolateInterrupted);
   }
 }
@@ -480,6 +479,24 @@
 }
 
 
+void Debugger::PrintSettingsToJSONObject(JSONObject* jsobj) const {
+  // This won't cut it when we support filtering by class, etc.
+  switch (GetExceptionPauseInfo()) {
+    case kNoPauseOnExceptions:
+      jsobj->AddProperty("_exceptions", "none");
+      break;
+    case kPauseOnAllExceptions:
+      jsobj->AddProperty("_exceptions", "all");
+      break;
+    case kPauseOnUnhandledExceptions:
+      jsobj->AddProperty("_exceptions", "unhandled");
+      break;
+    default:
+      UNREACHABLE();
+  }
+}
+
+
 RawString* ActivationFrame::QualifiedFunctionName() {
   return String::New(Debugger::QualifiedFunctionName(function()));
 }
@@ -1507,7 +1524,7 @@
 }
 
 
-Dart_ExceptionPauseInfo Debugger::GetExceptionPauseInfo() {
+Dart_ExceptionPauseInfo Debugger::GetExceptionPauseInfo() const {
   return exc_pause_info_;
 }
 
@@ -1949,17 +1966,39 @@
 }
 
 
-Breakpoint* Debugger::SetBreakpointAtActivation(
-    const Instance& closure) {
+Breakpoint* Debugger::SetBreakpointAtActivation(const Instance& closure) {
   if (!closure.IsClosure()) {
     return NULL;
   }
   const Function& func = Function::Handle(Closure::function(closure));
   const Script& script = Script::Handle(func.script());
-  BreakpointLocation* bpt = SetBreakpoint(script,
-                                          func.token_pos(),
-                                          func.end_token_pos());
-  return bpt->AddPerClosure(this, closure);
+  BreakpointLocation* bpt_location = SetBreakpoint(script,
+                                                   func.token_pos(),
+                                                   func.end_token_pos());
+  return bpt_location->AddPerClosure(this, closure);
+}
+
+
+Breakpoint* Debugger::BreakpointAtActivation(const Instance& closure) {
+  if (!closure.IsClosure()) {
+    return NULL;
+  }
+
+  BreakpointLocation* loc = breakpoint_locations_;
+  while (loc != NULL) {
+    Breakpoint* bpt = loc->breakpoints();
+    while (bpt != NULL) {
+      if (bpt->IsPerClosure()) {
+        if (closure.raw() == bpt->closure()) {
+          return bpt;
+        }
+      }
+      bpt = bpt->next();
+    }
+    loc = loc->next();
+  }
+
+  return NULL;
 }
 
 
diff --git a/runtime/vm/debugger.h b/runtime/vm/debugger.h
index 5fb4565..2a25220 100644
--- a/runtime/vm/debugger.h
+++ b/runtime/vm/debugger.h
@@ -5,7 +5,7 @@
 #ifndef VM_DEBUGGER_H_
 #define VM_DEBUGGER_H_
 
-#include "include/dart_debugger_api.h"
+#include "include/dart_tools_api.h"
 
 #include "vm/object.h"
 #include "vm/port.h"
@@ -427,6 +427,7 @@
   Breakpoint* SetBreakpointAtEntry(const Function& target_function,
                                    bool single_shot);
   Breakpoint* SetBreakpointAtActivation(const Instance& closure);
+  Breakpoint* BreakpointAtActivation(const Instance& closure);
 
   // TODO(turnidge): script_url may no longer be specific enough.
   Breakpoint* SetBreakpointAtLine(const String& script_url,
@@ -454,7 +455,7 @@
   const DebuggerEvent* PauseEvent() const { return pause_event_; }
 
   void SetExceptionPauseInfo(Dart_ExceptionPauseInfo pause_info);
-  Dart_ExceptionPauseInfo GetExceptionPauseInfo();
+  Dart_ExceptionPauseInfo GetExceptionPauseInfo() const;
 
   void VisitObjectPointers(ObjectPointerVisitor* visitor);
 
@@ -516,6 +517,7 @@
   uword GetPatchedStubAddress(uword breakpoint_address);
 
   void PrintBreakpointsToJSONArray(JSONArray* jsarr) const;
+  void PrintSettingsToJSONObject(JSONObject* jsobj) const;
 
   static bool IsDebuggable(const Function& func);
 
diff --git a/runtime/vm/debugger_api_impl.cc b/runtime/vm/debugger_api_impl.cc
index fc6a5ea..84c245a 100644
--- a/runtime/vm/debugger_api_impl.cc
+++ b/runtime/vm/debugger_api_impl.cc
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-#include "include/dart_debugger_api.h"
+#include "include/dart_tools_api.h"
 
 #include "vm/class_finalizer.h"
 #include "vm/compiler.h"
@@ -110,7 +110,6 @@
 static void DebuggerEventHandler(DebuggerEvent* event) {
   Isolate* isolate = Isolate::Current();
   ASSERT(isolate != NULL);
-  ASSERT(isolate->debugger() != NULL);
   Dart_EnterScope();
   Dart_IsolateId isolate_id = isolate->debugger()->GetIsolateId();
   if (event->type() == DebuggerEvent::kBreakpointReached) {
@@ -340,7 +339,6 @@
   UNWRAP_AND_CHECK_PARAM(String, script_url, script_url_in);
 
   Debugger* debugger = isolate->debugger();
-  ASSERT(debugger != NULL);
   Breakpoint* bpt =
       debugger->SetBreakpointAtLine(script_url, line_number);
   if (bpt == NULL) {
@@ -355,7 +353,6 @@
   Isolate* isolate = Isolate::Current();
   DARTSCOPE(isolate);
   Debugger* debugger = isolate->debugger();
-  ASSERT(debugger != NULL);
 
   Breakpoint* bpt = debugger->GetBreakpointById(bp_id);
   if (bpt == NULL) {
@@ -370,7 +367,6 @@
   Isolate* isolate = Isolate::Current();
   DARTSCOPE(isolate);
   Debugger* debugger = isolate->debugger();
-  ASSERT(debugger != NULL);
 
   Breakpoint* bpt = debugger->GetBreakpointById(bp_id);
   if (bpt == NULL) {
@@ -463,9 +459,6 @@
 DART_EXPORT Dart_Handle Dart_RemoveBreakpoint(intptr_t bp_id) {
   Isolate* isolate = Isolate::Current();
   DARTSCOPE(isolate);
-  Debugger* debugger = isolate->debugger();
-  ASSERT(debugger != NULL);
-
   isolate->debugger()->RemoveBreakpoint(bp_id);
   return Api::Success();
 }
diff --git a/runtime/vm/debugger_api_impl_test.cc b/runtime/vm/debugger_api_impl_test.cc
index 4bbc7e8..925e95a 100644
--- a/runtime/vm/debugger_api_impl_test.cc
+++ b/runtime/vm/debugger_api_impl_test.cc
@@ -2,8 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-#include "include/dart_debugger_api.h"
 #include "include/dart_mirrors_api.h"
+#include "include/dart_tools_api.h"
 #include "platform/assert.h"
 #include "vm/dart_api_impl.h"
 #include "vm/lockers.h"
diff --git a/runtime/vm/deferred_objects.cc b/runtime/vm/deferred_objects.cc
index ba620c4..a647af1 100644
--- a/runtime/vm/deferred_objects.cc
+++ b/runtime/vm/deferred_objects.cc
@@ -214,13 +214,13 @@
   }
   const Code& code = Code::Handle(zone, function.unoptimized_code());
   ASSERT(!code.IsNull());
-  ASSERT(code.ObjectPool() != Object::null());
-  *slot() = code.ObjectPool();
+  ASSERT(code.GetObjectPool() != Object::null());
+  *slot() = code.GetObjectPool();
 
   if (FLAG_trace_deoptimization_verbose) {
     OS::PrintErr("materializing pp at 0x%" Px ": 0x%" Px "\n",
                  reinterpret_cast<uword>(slot()),
-                 reinterpret_cast<uword>(code.ObjectPool()));
+                 reinterpret_cast<uword>(code.GetObjectPool()));
   }
 }
 
diff --git a/runtime/vm/deopt_instructions.cc b/runtime/vm/deopt_instructions.cc
index 22ecaf5..3260760 100644
--- a/runtime/vm/deopt_instructions.cc
+++ b/runtime/vm/deopt_instructions.cc
@@ -12,6 +12,7 @@
 #include "vm/parser.h"
 #include "vm/stack_frame.h"
 #include "vm/thread.h"
+#include "vm/timeline.h"
 
 namespace dart {
 
@@ -27,7 +28,7 @@
                            fpu_register_t* fpu_registers,
                            intptr_t* cpu_registers)
     : code_(code.raw()),
-      object_pool_(code.ObjectPool()),
+      object_pool_(code.GetObjectPool()),
       deopt_info_(TypedData::null()),
       dest_frame_is_allocated_(false),
       dest_frame_(NULL),
@@ -41,6 +42,7 @@
       deopt_reason_(ICData::kDeoptUnknown),
       deopt_flags_(0),
       thread_(Thread::Current()),
+      timeline_event_(NULL),
       deferred_slots_(NULL),
       deferred_objects_count_(0),
       deferred_objects_(NULL) {
@@ -92,6 +94,19 @@
     dest_frame_is_allocated_ = true;
   }
 
+  if (dest_options != kDestIsAllocated) {
+    // kDestIsAllocated is used by the debugger to generate a stack trace
+    // and does not signal a real deopt.
+    Isolate* isolate = Isolate::Current();
+    TimelineStream* compiler_stream = isolate->GetCompilerStream();
+    ASSERT(compiler_stream != NULL);
+    timeline_event_ = compiler_stream->StartEvent();
+    if (timeline_event_ != NULL) {
+      timeline_event_->DurationBegin("Deoptimize");
+      timeline_event_->SetNumArguments(3);
+    }
+  }
+
   if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) {
     OS::PrintErr(
         "Deoptimizing (reason %d '%s') at pc %#" Px " '%s' (count %d)\n",
@@ -126,6 +141,25 @@
   delete[] deferred_objects_;
   deferred_objects_ = NULL;
   deferred_objects_count_ = 0;
+  if (timeline_event_ != NULL) {
+    const Code& code = Code::Handle(zone(), code_);
+    const Function& function = Function::Handle(zone(), code.function());
+    timeline_event_->CopyArgument(
+        0,
+        "function",
+        const_cast<char*>(function.QualifiedUserVisibleNameCString()));
+    timeline_event_->CopyArgument(
+        1,
+        "reason",
+        const_cast<char*>(DeoptReasonToCString(deopt_reason())));
+    timeline_event_->FormatArgument(
+        2,
+        "deoptimizationCount",
+        "%d",
+        function.deoptimization_counter());
+    timeline_event_->DurationEnd();
+    timeline_event_->Complete();
+  }
 }
 
 
@@ -774,7 +808,7 @@
 
 
 uword DeoptInstr::GetRetAddress(DeoptInstr* instr,
-                                const Array& object_table,
+                                const ObjectPool& object_table,
                                 Code* code) {
   ASSERT(instr->kind() == kRetAddress);
   DeoptRetAddressInstr* ret_address_instr =
@@ -786,7 +820,7 @@
   Thread* thread = Thread::Current();
   Zone* zone = thread->zone();
   Function& function = Function::Handle(zone);
-  function ^= object_table.At(ret_address_instr->object_table_index());
+  function ^= object_table.ObjectAt(ret_address_instr->object_table_index());
   ASSERT(code != NULL);
   const Error& error = Error::Handle(zone,
       Compiler::EnsureUnoptimizedCode(thread, function));
@@ -937,7 +971,7 @@
 
 
 intptr_t DeoptInfoBuilder::FindOrAddObjectInTable(const Object& obj) const {
-  return assembler_->object_pool().FindObject(obj, kNotPatchable);
+  return assembler_->object_pool_wrapper().FindObject(obj);
 }
 
 
diff --git a/runtime/vm/deopt_instructions.h b/runtime/vm/deopt_instructions.h
index 68e92df..188e95c 100644
--- a/runtime/vm/deopt_instructions.h
+++ b/runtime/vm/deopt_instructions.h
@@ -20,6 +20,7 @@
 class Value;
 class MaterializeObjectInstr;
 class StackFrame;
+class TimelineEvent;
 
 // Holds all data relevant for execution of deoptimization instructions.
 class DeoptContext {
@@ -54,8 +55,8 @@
   void SetCallerFp(intptr_t callers_fp);
 
   RawObject* ObjectAt(intptr_t index) const {
-    const Array& object_pool = Array::Handle(object_pool_);
-    return object_pool.At(index);
+    const ObjectPool& object_pool = ObjectPool::Handle(object_pool_);
+    return object_pool.ObjectAt(index);
   }
 
   intptr_t RegisterValue(Register reg) const {
@@ -205,7 +206,7 @@
   }
 
   RawCode* code_;
-  RawArray* object_pool_;
+  RawObjectPool* object_pool_;
   RawTypedData* deopt_info_;
   bool dest_frame_is_allocated_;
   intptr_t* dest_frame_;
@@ -220,6 +221,7 @@
   uint32_t deopt_flags_;
   intptr_t caller_fp_;
   Thread* thread_;
+  TimelineEvent* timeline_event_;
 
   DeferredSlot* deferred_slots_;
 
@@ -287,7 +289,7 @@
   // Get the code and return address which is encoded in this
   // kRetAfterAddress deopt instruction.
   static uword GetRetAddress(DeoptInstr* instr,
-                             const Array& object_pool,
+                             const ObjectPool& object_pool,
                              Code* code);
 
   // Return number of initialized fields in the object that will be
diff --git a/runtime/vm/disassembler_ia32.cc b/runtime/vm/disassembler_ia32.cc
index b933302..c63057b 100644
--- a/runtime/vm/disassembler_ia32.cc
+++ b/runtime/vm/disassembler_ia32.cc
@@ -347,7 +347,7 @@
   int PrintRightXmmOperand(uint8_t* modrmp);
   int PrintRightByteOperand(uint8_t* modrmp);
   int PrintOperands(const char* mnem, OperandOrder op_order, uint8_t* data);
-  int PrintImmediateOp(uint8_t* data);
+  int PrintImmediateOp(uint8_t* data, bool size_override = false);
 
   // Handle special encodings.
   int JumpShort(uint8_t* data);
@@ -711,7 +711,7 @@
 }
 
 
-int X86Decoder::PrintImmediateOp(uint8_t* data) {
+int X86Decoder::PrintImmediateOp(uint8_t* data, bool size_override) {
   bool sign_extension_bit = (*data & 0x02) != 0;
   uint8_t modrm = *(data+1);
   int mod, regop, rm;
@@ -731,12 +731,14 @@
   Print(mnem);
   Print(" ");
   int count = PrintRightOperand(data+1);
-  if (sign_extension_bit) {
-    Print(",");
+  Print(",");
+  if (size_override) {
+    PrintHex(*reinterpret_cast<int16_t*>(data + 1 + count));
+    return 1 + count + 2 /*int16_t*/;
+  } else if (sign_extension_bit) {
     PrintHex(*(data + 1 + count));
-    return 1 + count + 1 /*int8*/;
+    return 1 + count + 1 /*int8_t*/;
   } else {
-    Print(",");
     PrintHex(*reinterpret_cast<int32_t*>(data + 1 + count));
     return 1 + count + 4 /*int32_t*/;
   }
@@ -1677,8 +1679,26 @@
             Print("]");
             data++;
           } else {
-              UNIMPLEMENTED();
+            UNIMPLEMENTED();
           }
+        } else if (*data == 0x3B) {
+          data++;
+          Print("cmp_w ");
+          int mod, regop, rm;
+          GetModRm(*data, &mod, &regop, &rm);
+          PrintCPURegister(regop);
+          Print(",");
+          data += PrintRightOperand(data);
+        } else if ((*data == 0x81) || (*data == 0x83)) {
+          data += PrintImmediateOp(data, true /* size_override */);
+        } else if (*data == 0xC7) {
+          data++;
+          Print("mov_w ");
+          data += PrintRightOperand(data);
+          int16_t imm = *reinterpret_cast<int16_t*>(data);
+          Print(",");
+          PrintHex(imm);
+          data += 2;
         } else if (*data == 0x90) {
           data++;
           Print("nop");
diff --git a/runtime/vm/flow_graph_builder.cc b/runtime/vm/flow_graph_builder.cc
index a90c9fa..0329ca3 100644
--- a/runtime/vm/flow_graph_builder.cc
+++ b/runtime/vm/flow_graph_builder.cc
@@ -1335,6 +1335,36 @@
       }
     }
     return;
+  } else if (node->kind() == Token::kIFNULL) {
+    // left ?? right. This operation cannot be overloaded.
+    // temp = left; temp === null ? right : temp
+    ValueGraphVisitor for_left_value(owner());
+    node->left()->Visit(&for_left_value);
+    Append(for_left_value);
+    Do(BuildStoreExprTemp(for_left_value.value()));
+
+    LocalVariable* temp_var = owner()->parsed_function().expression_temp_var();
+    LoadLocalNode* load_temp =
+        new(Z) LoadLocalNode(Scanner::kNoSourcePos, temp_var);
+    LiteralNode* null_constant =
+        new(Z) LiteralNode(Scanner::kNoSourcePos, Object::null_instance());
+    ComparisonNode* check_is_null =
+        new(Z) ComparisonNode(Scanner::kNoSourcePos,
+                              Token::kEQ_STRICT,
+                              load_temp,
+                              null_constant);
+    TestGraphVisitor for_test(owner(), Scanner::kNoSourcePos);
+    check_is_null->Visit(&for_test);
+
+    ValueGraphVisitor for_right_value(owner());
+    node->right()->Visit(&for_right_value);
+    for_right_value.Do(BuildStoreExprTemp(for_right_value.value()));
+
+    ValueGraphVisitor for_temp(owner());
+    // Nothing to do, left value is already loaded into temp.
+
+    Join(for_test, for_right_value, for_temp);
+    return;
   }
   ValueGraphVisitor for_left_value(owner());
   node->left()->Visit(&for_left_value);
@@ -1410,7 +1440,39 @@
     }
     ReturnDefinition(BuildLoadExprTemp());
     return;
+  } else if (node->kind() == Token::kIFNULL) {
+    // left ?? right. This operation cannot be overloaded.
+    // temp = left; temp === null ? right : temp
+    ValueGraphVisitor for_left_value(owner());
+    node->left()->Visit(&for_left_value);
+    Append(for_left_value);
+    Do(BuildStoreExprTemp(for_left_value.value()));
+
+    LocalVariable* temp_var = owner()->parsed_function().expression_temp_var();
+    LoadLocalNode* load_temp =
+        new(Z) LoadLocalNode(Scanner::kNoSourcePos, temp_var);
+    LiteralNode* null_constant =
+        new(Z) LiteralNode(Scanner::kNoSourcePos, Object::null_instance());
+    ComparisonNode* check_is_null =
+        new(Z) ComparisonNode(Scanner::kNoSourcePos,
+                              Token::kEQ_STRICT,
+                              load_temp,
+                              null_constant);
+    TestGraphVisitor for_test(owner(), Scanner::kNoSourcePos);
+    check_is_null->Visit(&for_test);
+
+    ValueGraphVisitor for_right_value(owner());
+    node->right()->Visit(&for_right_value);
+    for_right_value.Do(BuildStoreExprTemp(for_right_value.value()));
+
+    ValueGraphVisitor for_temp(owner());
+    // Nothing to do, left value is already loaded into temp.
+
+    Join(for_test, for_right_value, for_temp);
+    ReturnDefinition(BuildLoadExprTemp());
+    return;
   }
+
   EffectGraphVisitor::VisitBinaryOpNode(node);
 }
 
@@ -2421,10 +2483,10 @@
 
 
 Definition* EffectGraphVisitor::ExitTempLocalScope(LocalVariable* var) {
-    Value* tmp = Bind(new(Z) LoadLocalInstr(*var));
-    owner()->DeallocateTemps(1);
-    ASSERT(GetCurrentTempLocalIndex() == var->index());
-    return new(Z) DropTempsInstr(1, tmp);
+  Value* tmp = Bind(new(Z) LoadLocalInstr(*var));
+  owner()->DeallocateTemps(1);
+  ASSERT(GetCurrentTempLocalIndex() == var->index());
+  return new(Z) DropTempsInstr(1, tmp);
 }
 
 
@@ -2699,26 +2761,80 @@
 }
 
 
+void EffectGraphVisitor::BuildInstanceCallConditional(InstanceCallNode* node) {
+  LocalVariable* temp_var = owner()->parsed_function().expression_temp_var();
+  LoadLocalNode* load_temp =
+      new(Z) LoadLocalNode(Scanner::kNoSourcePos, temp_var);
+
+  LiteralNode* null_constant =
+      new(Z) LiteralNode(Scanner::kNoSourcePos, Object::null_instance());
+  ComparisonNode* check_is_null =
+      new(Z) ComparisonNode(Scanner::kNoSourcePos,
+                            Token::kEQ,
+                            load_temp,
+                            null_constant);
+  TestGraphVisitor for_test(owner(), Scanner::kNoSourcePos);
+  check_is_null->Visit(&for_test);
+
+  EffectGraphVisitor for_true(owner());
+  EffectGraphVisitor for_false(owner());
+
+  StoreLocalNode* store_null =
+      new(Z) StoreLocalNode(Scanner::kNoSourcePos, temp_var, null_constant);
+  store_null->Visit(&for_true);
+
+  InstanceCallNode* call =
+      new(Z) InstanceCallNode(node->token_pos(),
+                              load_temp,
+                              node->function_name(),
+                              node->arguments());
+  StoreLocalNode* store_result =
+      new(Z) StoreLocalNode(Scanner::kNoSourcePos, temp_var, call);
+  store_result->Visit(&for_false);
+
+  Join(for_test, for_true, for_false);
+}
+
+
+void ValueGraphVisitor::VisitInstanceCallNode(InstanceCallNode* node) {
+  if (node->is_conditional()) {
+    ValueGraphVisitor for_receiver(owner());
+    node->receiver()->Visit(&for_receiver);
+    Append(for_receiver);
+    Do(BuildStoreExprTemp(for_receiver.value()));
+    BuildInstanceCallConditional(node);
+    ReturnDefinition(BuildLoadExprTemp());
+  } else {
+    EffectGraphVisitor::VisitInstanceCallNode(node);
+  }
+}
+
+
 void EffectGraphVisitor::VisitInstanceCallNode(InstanceCallNode* node) {
   ValueGraphVisitor for_receiver(owner());
   node->receiver()->Visit(&for_receiver);
   Append(for_receiver);
-  PushArgumentInstr* push_receiver = PushArgument(for_receiver.value());
-  ZoneGrowableArray<PushArgumentInstr*>* arguments =
-      new(Z) ZoneGrowableArray<PushArgumentInstr*>(
-          node->arguments()->length() + 1);
-  arguments->Add(push_receiver);
+  if (node->is_conditional()) {
+    Do(BuildStoreExprTemp(for_receiver.value()));
+    BuildInstanceCallConditional(node);
+  } else {
+    PushArgumentInstr* push_receiver = PushArgument(for_receiver.value());
+    ZoneGrowableArray<PushArgumentInstr*>* arguments =
+        new(Z) ZoneGrowableArray<PushArgumentInstr*>(
+            node->arguments()->length() + 1);
+    arguments->Add(push_receiver);
 
-  BuildPushArguments(*node->arguments(), arguments);
-  InstanceCallInstr* call = new(Z) InstanceCallInstr(
-      node->token_pos(),
-      node->function_name(),
-      Token::kILLEGAL,
-      arguments,
-      node->arguments()->names(),
-      1,
-      owner()->ic_data_array());
-  ReturnDefinition(call);
+    BuildPushArguments(*node->arguments(), arguments);
+    InstanceCallInstr* call = new(Z) InstanceCallInstr(
+        node->token_pos(),
+        node->function_name(),
+        Token::kILLEGAL,
+        arguments,
+        node->arguments()->names(),
+        1,
+        owner()->ic_data_array());
+    ReturnDefinition(call);
+  }
 }
 
 
@@ -3059,24 +3175,79 @@
 }
 
 
+
+void EffectGraphVisitor::BuildInstanceGetterConditional(
+    InstanceGetterNode* node) {
+  LocalVariable* temp_var = owner()->parsed_function().expression_temp_var();
+  LoadLocalNode* load_temp =
+      new(Z) LoadLocalNode(Scanner::kNoSourcePos, temp_var);
+
+  LiteralNode* null_constant =
+      new(Z) LiteralNode(Scanner::kNoSourcePos, Object::null_instance());
+  ComparisonNode* check_is_null =
+      new(Z) ComparisonNode(Scanner::kNoSourcePos,
+                            Token::kEQ,
+                            load_temp,
+                            null_constant);
+  TestGraphVisitor for_test(owner(), Scanner::kNoSourcePos);
+  check_is_null->Visit(&for_test);
+
+  EffectGraphVisitor for_true(owner());
+  EffectGraphVisitor for_false(owner());
+
+  StoreLocalNode* store_null =
+      new(Z) StoreLocalNode(Scanner::kNoSourcePos, temp_var, null_constant);
+  store_null->Visit(&for_true);
+
+  InstanceGetterNode* getter =
+      new(Z) InstanceGetterNode(node->token_pos(),
+                                load_temp,
+                                node->field_name());
+  StoreLocalNode* store_getter =
+      new(Z) StoreLocalNode(Scanner::kNoSourcePos, temp_var, getter);
+  store_getter->Visit(&for_false);
+
+  Join(for_test, for_true, for_false);
+}
+
+
+void ValueGraphVisitor::VisitInstanceGetterNode(InstanceGetterNode* node) {
+  if (node->is_conditional()) {
+    ValueGraphVisitor for_receiver(owner());
+    node->receiver()->Visit(&for_receiver);
+    Append(for_receiver);
+    Do(BuildStoreExprTemp(for_receiver.value()));
+    BuildInstanceGetterConditional(node);
+    ReturnDefinition(BuildLoadExprTemp());
+  } else {
+    EffectGraphVisitor::VisitInstanceGetterNode(node);
+  }
+}
+
+
 void EffectGraphVisitor::VisitInstanceGetterNode(InstanceGetterNode* node) {
   ValueGraphVisitor for_receiver(owner());
   node->receiver()->Visit(&for_receiver);
   Append(for_receiver);
-  PushArgumentInstr* push_receiver = PushArgument(for_receiver.value());
-  ZoneGrowableArray<PushArgumentInstr*>* arguments =
-      new(Z) ZoneGrowableArray<PushArgumentInstr*>(1);
-  arguments->Add(push_receiver);
-  const String& name =
-      String::ZoneHandle(Z, Field::GetterSymbol(node->field_name()));
-  InstanceCallInstr* call = new(Z) InstanceCallInstr(
-      node->token_pos(),
-      name,
-      Token::kGET,
-      arguments, Object::null_array(),
-      1,
-      owner()->ic_data_array());
-  ReturnDefinition(call);
+  if (node->is_conditional()) {
+    Do(BuildStoreExprTemp(for_receiver.value()));
+    BuildInstanceGetterConditional(node);
+  } else {
+    PushArgumentInstr* push_receiver = PushArgument(for_receiver.value());
+    ZoneGrowableArray<PushArgumentInstr*>* arguments =
+        new(Z) ZoneGrowableArray<PushArgumentInstr*>(1);
+    arguments->Add(push_receiver);
+    const String& name =
+        String::ZoneHandle(Z, Field::GetterSymbol(node->field_name()));
+    InstanceCallInstr* call = new(Z) InstanceCallInstr(
+        node->token_pos(),
+        name,
+        Token::kGET,
+        arguments, Object::null_array(),
+        1,
+        owner()->ic_data_array());
+    ReturnDefinition(call);
+  }
 }
 
 
@@ -3104,6 +3275,37 @@
 
 
 void EffectGraphVisitor::VisitInstanceSetterNode(InstanceSetterNode* node) {
+  if (node->is_conditional()) {
+    ValueGraphVisitor for_receiver(owner());
+    node->receiver()->Visit(&for_receiver);
+    Append(for_receiver);
+    Do(BuildStoreExprTemp(for_receiver.value()));
+
+    LocalVariable* temp_var = owner()->parsed_function().expression_temp_var();
+    LoadLocalNode* load_temp =
+        new(Z) LoadLocalNode(Scanner::kNoSourcePos, temp_var);
+    LiteralNode* null_constant =
+        new(Z) LiteralNode(Scanner::kNoSourcePos, Object::null_instance());
+    ComparisonNode* check_is_null =
+        new(Z) ComparisonNode(Scanner::kNoSourcePos,
+                              Token::kEQ,
+                              load_temp,
+                              null_constant);
+    TestGraphVisitor for_test(owner(), Scanner::kNoSourcePos);
+    check_is_null->Visit(&for_test);
+
+    EffectGraphVisitor for_true(owner());
+    EffectGraphVisitor for_false(owner());
+
+    InstanceSetterNode* setter =
+        new(Z) InstanceSetterNode(node->token_pos(),
+                                  load_temp,
+                                  node->field_name(),
+                                  node->value());
+    setter->Visit(&for_false);
+    Join(for_test, for_true, for_false);
+    return;
+  }
   ZoneGrowableArray<PushArgumentInstr*>* arguments =
       new(Z) ZoneGrowableArray<PushArgumentInstr*>(2);
   BuildInstanceSetterArguments(node, arguments, kResultNotNeeded);
@@ -3122,6 +3324,42 @@
 
 
 void ValueGraphVisitor::VisitInstanceSetterNode(InstanceSetterNode* node) {
+  if (node->is_conditional()) {
+    ValueGraphVisitor for_receiver(owner());
+    node->receiver()->Visit(&for_receiver);
+    Append(for_receiver);
+    Do(BuildStoreExprTemp(for_receiver.value()));
+
+    LocalVariable* temp_var = owner()->parsed_function().expression_temp_var();
+    LoadLocalNode* load_temp =
+        new(Z) LoadLocalNode(Scanner::kNoSourcePos, temp_var);
+    LiteralNode* null_constant =
+        new(Z) LiteralNode(Scanner::kNoSourcePos, Object::null_instance());
+    ComparisonNode* check_is_null =
+        new(Z) ComparisonNode(Scanner::kNoSourcePos,
+                              Token::kEQ,
+                              load_temp,
+                              null_constant);
+    TestGraphVisitor for_test(owner(), Scanner::kNoSourcePos);
+    check_is_null->Visit(&for_test);
+
+    ValueGraphVisitor for_true(owner());
+    null_constant->Visit(&for_true);
+    for_true.Do(BuildStoreExprTemp(for_true.value()));
+
+    ValueGraphVisitor for_false(owner());
+    InstanceSetterNode* setter =
+        new(Z) InstanceSetterNode(node->token_pos(),
+                                  load_temp,
+                                  node->field_name(),
+                                  node->value());
+    setter->Visit(&for_false);
+    for_false.Do(BuildStoreExprTemp(for_false.value()));
+
+    Join(for_test, for_true, for_false);
+    ReturnDefinition(BuildLoadExprTemp());
+    return;
+  }
   ZoneGrowableArray<PushArgumentInstr*>* arguments =
       new(Z) ZoneGrowableArray<PushArgumentInstr*>(2);
   BuildInstanceSetterArguments(node, arguments, kResultNeeded);
diff --git a/runtime/vm/flow_graph_builder.h b/runtime/vm/flow_graph_builder.h
index 2115065..2211da4 100644
--- a/runtime/vm/flow_graph_builder.h
+++ b/runtime/vm/flow_graph_builder.h
@@ -477,6 +477,9 @@
                       const intptr_t old_ctx_level,
                       JoinEntryInstr* target);
 
+  void BuildInstanceGetterConditional(InstanceGetterNode* node);
+  void BuildInstanceCallConditional(InstanceCallNode* node);
+
   Isolate* isolate() const { return owner()->isolate(); }
   Zone* zone() const { return owner()->zone(); }
 
@@ -525,12 +528,14 @@
   virtual void VisitLoadLocalNode(LoadLocalNode* node);
   virtual void VisitStoreIndexedNode(StoreIndexedNode* node);
   virtual void VisitInstanceSetterNode(InstanceSetterNode* node);
+  virtual void VisitInstanceGetterNode(InstanceGetterNode* node);
   virtual void VisitThrowNode(ThrowNode* node);
   virtual void VisitClosureCallNode(ClosureCallNode* node);
   virtual void VisitStaticSetterNode(StaticSetterNode* node);
   virtual void VisitStoreStaticFieldNode(StoreStaticFieldNode* node);
   virtual void VisitTypeNode(TypeNode* node);
   virtual void VisitLetNode(LetNode* node);
+  virtual void VisitInstanceCallNode(InstanceCallNode* node);
 
   Value* value() const { return value_; }
 
diff --git a/runtime/vm/flow_graph_compiler.cc b/runtime/vm/flow_graph_compiler.cc
index 169c857..0cc4f2b3 100644
--- a/runtime/vm/flow_graph_compiler.cc
+++ b/runtime/vm/flow_graph_compiler.cc
@@ -30,15 +30,18 @@
 
 DEFINE_FLAG(bool, always_megamorphic_calls, false,
     "Instance call always as megamorphic.");
-DEFINE_FLAG(bool, trace_inlining_intervals, false,
-    "Inlining interval diagnostics");
 DEFINE_FLAG(bool, enable_simd_inline, true,
     "Enable inlining of SIMD related method calls.");
 DEFINE_FLAG(int, min_optimization_counter_threshold, 5000,
     "The minimum invocation count for a function.");
 DEFINE_FLAG(int, optimization_counter_scale, 2000,
     "The scale of invocation count, by size of the function.");
+DEFINE_FLAG(bool, polymorphic_with_deopt, true,
+    "Polymorphic calls can be generated so that failure either causes "
+    "deoptimization or falls through to a megamorphic call");
 DEFINE_FLAG(bool, source_lines, false, "Emit source line as assembly comment.");
+DEFINE_FLAG(bool, trace_inlining_intervals, false,
+    "Inlining interval diagnostics");
 DEFINE_FLAG(bool, use_megamorphic_stub, true, "Out of line megamorphic lookup");
 
 DECLARE_FLAG(bool, code_comments);
@@ -48,6 +51,7 @@
 DECLARE_FLAG(bool, disassemble);
 DECLARE_FLAG(bool, disassemble_optimized);
 DECLARE_FLAG(bool, emit_edge_counters);
+DECLARE_FLAG(bool, guess_other_cid);
 DECLARE_FLAG(bool, ic_range_profiling);
 DECLARE_FLAG(bool, intrinsify);
 DECLARE_FLAG(bool, load_deferred_eagerly);
@@ -66,7 +70,8 @@
 
 static void NooptModeHandler(bool value) {
   if (value) {
-    FLAG_always_megamorphic_calls = value;
+    FLAG_always_megamorphic_calls = true;
+    FLAG_polymorphic_with_deopt = false;
     FLAG_optimization_counter_threshold = -1;
     FLAG_use_field_guards = false;
     FLAG_use_osr = false;
@@ -78,8 +83,8 @@
     FLAG_deoptimize_alot = false;  // Used in some tests.
     FLAG_deoptimize_every = 0;  // Used in some tests.
     FLAG_collect_code = false;
+    FLAG_guess_other_cid = false;
     Compiler::set_always_optimize(true);
-    Compiler::set_guess_other_cid(false);
     // TODO(srdjan): Enable CHA deoptimization when eager class finalization is
     // implemented, either with precompilation or as a special pass.
     FLAG_use_cha_deopt = false;
@@ -1669,6 +1674,40 @@
 }
 
 
+void FlowGraphCompiler::EmitPolymorphicInstanceCall(
+    const ICData& ic_data,
+    intptr_t argument_count,
+    const Array& argument_names,
+    intptr_t deopt_id,
+    intptr_t token_pos,
+    LocationSummary* locs) {
+  if (FLAG_polymorphic_with_deopt) {
+    Label* deopt = AddDeoptStub(deopt_id,
+                                ICData::kDeoptPolymorphicInstanceCallTestFail);
+    Label ok;
+    EmitTestAndCall(ic_data, argument_count, argument_names,
+                    deopt,  // No cid match.
+                    &ok,    // Found cid.
+                    deopt_id, token_pos, locs);
+    assembler()->Bind(&ok);
+  } else {
+    // Instead of deoptimizing, do a megamorphic call when no matching
+    // cid found.
+    Label megamorphic, ok;
+    EmitTestAndCall(ic_data, argument_count, argument_names,
+                    &megamorphic,  // No cid match.
+                    &ok,           // Found cid.
+                    deopt_id, token_pos, locs);
+    // Fall through if last test is match.
+    assembler()->Jump(&ok);
+    assembler()->Bind(&megamorphic);
+    EmitMegamorphicInstanceCall(ic_data, argument_count, deopt_id,
+                                token_pos, locs);
+    assembler()->Bind(&ok);
+  }
+}
+
+
 #if defined(DEBUG)
 void FlowGraphCompiler::FrameStateUpdateWith(Instruction* instr) {
   ASSERT(!is_optimizing());
diff --git a/runtime/vm/flow_graph_compiler.h b/runtime/vm/flow_graph_compiler.h
index d69cb1e..17b2612 100644
--- a/runtime/vm/flow_graph_compiler.h
+++ b/runtime/vm/flow_graph_compiler.h
@@ -407,6 +407,13 @@
                         intptr_t token_pos,
                         LocationSummary* locs);
 
+  void EmitPolymorphicInstanceCall(const ICData& ic_data,
+                                   intptr_t argument_count,
+                                   const Array& argument_names,
+                                   intptr_t deopt_id,
+                                   intptr_t token_pos,
+                                   LocationSummary* locs);
+
   void EmitMegamorphicInstanceCall(const ICData& ic_data,
                                    intptr_t argument_count,
                                    intptr_t deopt_id,
@@ -414,10 +421,10 @@
                                    LocationSummary* locs);
 
   void EmitTestAndCall(const ICData& ic_data,
-                       Register class_id_reg,
                        intptr_t arg_count,
                        const Array& arg_names,
-                       Label* deopt,
+                       Label* failed,
+                       Label* match_found,
                        intptr_t deopt_id,
                        intptr_t token_index,
                        LocationSummary* locs);
diff --git a/runtime/vm/flow_graph_compiler_arm.cc b/runtime/vm/flow_graph_compiler_arm.cc
index 71bb862..5fdb2d8 100644
--- a/runtime/vm/flow_graph_compiler_arm.cc
+++ b/runtime/vm/flow_graph_compiler_arm.cc
@@ -608,7 +608,7 @@
     // time, since an uninstantiated type at compile time could be Object or
     // dynamic at run time.
     __ CompareImmediate(R0, reinterpret_cast<int32_t>(Object::null()));
-    __ b(&is_not_instance, EQ);
+    __ b(type.IsNullType() ? &is_instance : &is_not_instance, EQ);
   }
 
   // Generate inline instanceof test.
@@ -1512,33 +1512,76 @@
 
 
 void FlowGraphCompiler::EmitTestAndCall(const ICData& ic_data,
-                                        Register class_id_reg,
                                         intptr_t argument_count,
                                         const Array& argument_names,
-                                        Label* deopt,
+                                        Label* failed,
+                                        Label* match_found,
                                         intptr_t deopt_id,
                                         intptr_t token_index,
                                         LocationSummary* locs) {
   ASSERT(is_optimizing());
-  ASSERT(!ic_data.IsNull() && (ic_data.NumberOfUsedChecks() > 0));
-  Label match_found;
-  const intptr_t len = ic_data.NumberOfChecks();
-  GrowableArray<CidTarget> sorted(len);
-  SortICDataByCount(ic_data, &sorted, /* drop_smi = */ false);
-  ASSERT(class_id_reg != R4);
-  ASSERT(len > 0);  // Why bother otherwise.
+  __ Comment("EmitTestAndCall");
   const Array& arguments_descriptor =
       Array::ZoneHandle(ArgumentsDescriptor::New(argument_count,
                                                  argument_names));
   StubCode* stub_code = isolate()->stub_code();
 
+  // Load receiver into R0.
+  __ LoadFromOffset(kWord, R0, SP, (argument_count - 1) * kWordSize);
   __ LoadObject(R4, arguments_descriptor);
-  for (intptr_t i = 0; i < len; i++) {
-    const bool is_last_check = (i == (len - 1));
+
+  const bool kFirstCheckIsSmi = ic_data.GetReceiverClassIdAt(0) == kSmiCid;
+  const intptr_t kNumChecks = ic_data.NumberOfChecks();
+
+  ASSERT(!ic_data.IsNull() && (kNumChecks > 0));
+
+  Label after_smi_test;
+  __ tst(R0, Operand(kSmiTagMask));
+  if (kFirstCheckIsSmi) {
+    // Jump if receiver is not Smi.
+    if (kNumChecks == 1) {
+      __ b(failed, NE);
+    } else {
+      __ b(&after_smi_test, NE);
+    }
+    // Do not use the code from the function, but let the code be patched so
+    // that we can record the outgoing edges to other code.
+    GenerateDartCall(deopt_id,
+                     token_index,
+                     &stub_code->CallStaticFunctionLabel(),
+                     RawPcDescriptors::kOther,
+                     locs);
+    const Function& function = Function::Handle(ic_data.GetTargetAt(0));
+    AddStaticCallTarget(function);
+    __ Drop(argument_count);
+    if (kNumChecks > 1) {
+      __ b(match_found);
+    }
+  } else {
+    // Receiver is Smi, but Smi is not a valid class therefore fail.
+    // (Smi class must be first in the list).
+    __ b(failed, EQ);
+  }
+  __ Bind(&after_smi_test);
+
+  ASSERT(!ic_data.IsNull() && (kNumChecks > 0));
+  GrowableArray<CidTarget> sorted(kNumChecks);
+  SortICDataByCount(ic_data, &sorted, /* drop_smi = */ true);
+
+  // Value is not Smi,
+  const intptr_t kSortedLen = sorted.length();
+  // If kSortedLen is 0 then only a Smi check was needed; the Smi check above
+  // will fail if there was only one check and receiver is not Smi.
+  if (kSortedLen == 0) return;
+
+  __ LoadClassId(R2, R0);
+  for (intptr_t i = 0; i < kSortedLen; i++) {
+    const bool kIsLastCheck = (i == (kSortedLen - 1));
+    ASSERT(sorted[i].cid != kSmiCid);
     Label next_test;
-    __ CompareImmediate(class_id_reg, sorted[i].cid);
-    if (is_last_check) {
-      __ b(deopt, NE);
+    __ CompareImmediate(R2, sorted[i].cid);
+    if (kIsLastCheck) {
+      __ b(failed, NE);
     } else {
       __ b(&next_test, NE);
     }
@@ -1552,12 +1595,11 @@
     const Function& function = *sorted[i].target;
     AddStaticCallTarget(function);
     __ Drop(argument_count);
-    if (!is_last_check) {
-      __ b(&match_found);
+    if (!kIsLastCheck) {
+      __ b(match_found);
     }
     __ Bind(&next_test);
   }
-  __ Bind(&match_found);
 }
 
 
diff --git a/runtime/vm/flow_graph_compiler_arm64.cc b/runtime/vm/flow_graph_compiler_arm64.cc
index ffd907b..e2b8308 100644
--- a/runtime/vm/flow_graph_compiler_arm64.cc
+++ b/runtime/vm/flow_graph_compiler_arm64.cc
@@ -596,7 +596,7 @@
     // time, since an uninstantiated type at compile time could be Object or
     // dynamic at run time.
     __ CompareObject(R0, Object::null_object(), PP);
-    __ b(&is_not_instance, EQ);
+    __ b(type.IsNullType() ? &is_instance : &is_not_instance, EQ);
   }
 
   // Generate inline instanceof test.
@@ -1476,33 +1476,77 @@
 
 
 void FlowGraphCompiler::EmitTestAndCall(const ICData& ic_data,
-                                        Register class_id_reg,
                                         intptr_t argument_count,
                                         const Array& argument_names,
-                                        Label* deopt,
+                                        Label* failed,
+                                        Label* match_found,
                                         intptr_t deopt_id,
                                         intptr_t token_index,
                                         LocationSummary* locs) {
   ASSERT(is_optimizing());
-  ASSERT(!ic_data.IsNull() && (ic_data.NumberOfUsedChecks() > 0));
-  Label match_found;
-  const intptr_t len = ic_data.NumberOfChecks();
-  GrowableArray<CidTarget> sorted(len);
-  SortICDataByCount(ic_data, &sorted, /* drop_smi = */ false);
-  ASSERT(class_id_reg != R4);
-  ASSERT(len > 0);  // Why bother otherwise.
+
+  __ Comment("EmitTestAndCall");
   const Array& arguments_descriptor =
       Array::ZoneHandle(ArgumentsDescriptor::New(argument_count,
                                                  argument_names));
   StubCode* stub_code = isolate()->stub_code();
 
+  // Load receiver into R0.
+  __ LoadFromOffset(R0, SP, (argument_count - 1) * kWordSize, PP);
   __ LoadObject(R4, arguments_descriptor, PP);
-  for (intptr_t i = 0; i < len; i++) {
-    const bool is_last_check = (i == (len - 1));
+
+  const bool kFirstCheckIsSmi = ic_data.GetReceiverClassIdAt(0) == kSmiCid;
+  const intptr_t kNumChecks = ic_data.NumberOfChecks();
+
+  ASSERT(!ic_data.IsNull() && (kNumChecks > 0));
+
+  Label after_smi_test;
+  __ tsti(R0, Immediate(kSmiTagMask));
+  if (kFirstCheckIsSmi) {
+    // Jump if receiver is not Smi.
+    if (kNumChecks == 1) {
+      __ b(failed, NE);
+    } else {
+      __ b(&after_smi_test, NE);
+    }
+    // Do not use the code from the function, but let the code be patched so
+    // that we can record the outgoing edges to other code.
+    GenerateDartCall(deopt_id,
+                     token_index,
+                     &stub_code->CallStaticFunctionLabel(),
+                     RawPcDescriptors::kOther,
+                     locs);
+    const Function& function = Function::Handle(ic_data.GetTargetAt(0));
+    AddStaticCallTarget(function);
+    __ Drop(argument_count);
+    if (kNumChecks > 1) {
+      __ b(match_found);
+    }
+  } else {
+    // Receiver is Smi, but Smi is not a valid class therefore fail.
+    // (Smi class must be first in the list).
+    __ b(failed, EQ);
+  }
+  __ Bind(&after_smi_test);
+
+  ASSERT(!ic_data.IsNull() && (kNumChecks > 0));
+  GrowableArray<CidTarget> sorted(kNumChecks);
+  SortICDataByCount(ic_data, &sorted, /* drop_smi = */ true);
+
+  // Value is not Smi,
+  const intptr_t kSortedLen = sorted.length();
+  // If kSortedLen is 0 then only a Smi check was needed; the Smi check above
+  // will fail if there was only one check and receiver is not Smi.
+  if (kSortedLen == 0) return;
+
+  __ LoadClassId(R2, R0, PP);
+  for (intptr_t i = 0; i < kSortedLen; i++) {
+    const bool kIsLastCheck = (i == (kSortedLen - 1));
+    ASSERT(sorted[i].cid != kSmiCid);
     Label next_test;
-    __ CompareImmediate(class_id_reg, sorted[i].cid, PP);
-    if (is_last_check) {
-      __ b(deopt, NE);
+    __ CompareImmediate(R2, sorted[i].cid, PP);
+    if (kIsLastCheck) {
+      __ b(failed, NE);
     } else {
       __ b(&next_test, NE);
     }
@@ -1516,12 +1560,11 @@
     const Function& function = *sorted[i].target;
     AddStaticCallTarget(function);
     __ Drop(argument_count);
-    if (!is_last_check) {
-      __ b(&match_found);
+    if (!kIsLastCheck) {
+      __ b(match_found);
     }
     __ Bind(&next_test);
   }
-  __ Bind(&match_found);
 }
 
 
diff --git a/runtime/vm/flow_graph_compiler_ia32.cc b/runtime/vm/flow_graph_compiler_ia32.cc
index 3b83202..46ce12d 100644
--- a/runtime/vm/flow_graph_compiler_ia32.cc
+++ b/runtime/vm/flow_graph_compiler_ia32.cc
@@ -613,7 +613,7 @@
     // time, since an uninstantiated type at compile time could be Object or
     // dynamic at run time.
     __ cmpl(EAX, raw_null);
-    __ j(EQUAL, &is_not_instance);
+    __ j(EQUAL, type.IsNullType() ? &is_instance : &is_not_instance);
   }
 
   // Generate inline instanceof test.
@@ -1509,35 +1509,78 @@
 
 
 void FlowGraphCompiler::EmitTestAndCall(const ICData& ic_data,
-                                        Register class_id_reg,
                                         intptr_t argument_count,
                                         const Array& argument_names,
-                                        Label* deopt,
+                                        Label* failed,
+                                        Label* match_found,
                                         intptr_t deopt_id,
                                         intptr_t token_index,
                                         LocationSummary* locs) {
   ASSERT(is_optimizing());
-  ASSERT(!ic_data.IsNull() && (ic_data.NumberOfUsedChecks() > 0));
-  Label match_found;
-  const intptr_t len = ic_data.NumberOfChecks();
-  GrowableArray<CidTarget> sorted(len);
-  SortICDataByCount(ic_data, &sorted, /* drop_smi = */ false);
-  ASSERT(class_id_reg != EDX);
-  ASSERT(len > 0);  // Why bother otherwise.
+  __ Comment("EmitTestAndCall");
   const Array& arguments_descriptor =
       Array::ZoneHandle(ArgumentsDescriptor::New(argument_count,
                                                  argument_names));
   StubCode* stub_code = isolate()->stub_code();
-
+  // Load receiver into EAX.
+  __ movl(EAX, Address(ESP, (argument_count - 1) * kWordSize));
   __ LoadObject(EDX, arguments_descriptor);
-  for (intptr_t i = 0; i < len; i++) {
-    const bool is_last_check = (i == (len - 1));
-    Label next_test;
-    assembler()->cmpl(class_id_reg, Immediate(sorted[i].cid));
-    if (is_last_check) {
-      assembler()->j(NOT_EQUAL, deopt);
+
+  const bool kFirstCheckIsSmi = ic_data.GetReceiverClassIdAt(0) == kSmiCid;
+  const intptr_t kNumChecks = ic_data.NumberOfChecks();
+
+  ASSERT(!ic_data.IsNull() && (kNumChecks > 0));
+
+  Label after_smi_test;
+  __ testl(EAX, Immediate(kSmiTagMask));
+  if (kFirstCheckIsSmi) {
+    // Jump if receiver is not Smi.
+    if (kNumChecks == 1) {
+      __ j(NOT_ZERO, failed);
     } else {
-      assembler()->j(NOT_EQUAL, &next_test);
+      __ j(NOT_ZERO, &after_smi_test);
+    }
+    // Do not use the code from the function, but let the code be patched so
+    // that we can record the outgoing edges to other code.
+    GenerateDartCall(deopt_id,
+                     token_index,
+                     &stub_code->CallStaticFunctionLabel(),
+                     RawPcDescriptors::kOther,
+                     locs);
+    const Function& function = Function::Handle(ic_data.GetTargetAt(0));
+    AddStaticCallTarget(function);
+    __ Drop(argument_count);
+    if (kNumChecks > 1) {
+      __ jmp(match_found);
+    }
+  } else {
+    // Receiver is Smi, but Smi is not a valid class therefore fail.
+    // (Smi class must be first in the list).
+    __ j(ZERO, failed);
+  }
+  __ Bind(&after_smi_test);
+
+  ASSERT(!ic_data.IsNull() && (kNumChecks > 0));
+  GrowableArray<CidTarget> sorted(kNumChecks);
+  SortICDataByCount(ic_data, &sorted, /* drop_smi = */ true);
+
+  // Value is not Smi,
+  // LoadValueCid(this, EDI, EAX, failed);
+  const intptr_t kSortedLen = sorted.length();
+  // If kSortedLen is 0 then only a Smi check was needed; the Smi check above
+  // will fail if there was only one check and receiver is not Smi.
+  if (kSortedLen == 0) return;
+
+  __ LoadClassId(EDI, EAX);
+  for (intptr_t i = 0; i < kSortedLen; i++) {
+    const bool kIsLastCheck = (i == (kSortedLen - 1));
+    ASSERT(sorted[i].cid != kSmiCid);
+    Label next_test;
+    __ cmpl(EDI, Immediate(sorted[i].cid));
+    if (kIsLastCheck) {
+      __ j(NOT_EQUAL, failed);
+    } else {
+      __ j(NOT_EQUAL, &next_test);
     }
     // Do not use the code from the function, but let the code be patched so
     // that we can record the outgoing edges to other code.
@@ -1549,12 +1592,11 @@
     const Function& function = *sorted[i].target;
     AddStaticCallTarget(function);
     __ Drop(argument_count);
-    if (!is_last_check) {
-      assembler()->jmp(&match_found);
+    if (!kIsLastCheck) {
+      __ jmp(match_found);
     }
-    assembler()->Bind(&next_test);
+    __ Bind(&next_test);
   }
-  assembler()->Bind(&match_found);
 }
 
 
diff --git a/runtime/vm/flow_graph_compiler_mips.cc b/runtime/vm/flow_graph_compiler_mips.cc
index 925796d..7a59b43 100644
--- a/runtime/vm/flow_graph_compiler_mips.cc
+++ b/runtime/vm/flow_graph_compiler_mips.cc
@@ -591,7 +591,8 @@
     // We can only inline this null check if the type is instantiated at compile
     // time, since an uninstantiated type at compile time could be Object or
     // dynamic at run time.
-    __ BranchEqual(A0, Object::null_object(), &is_not_instance);
+    __ BranchEqual(A0, Object::null_object(),
+        type.IsNullType() ? &is_instance : &is_not_instance);
   }
 
   // Generate inline instanceof test.
@@ -1539,35 +1540,77 @@
 
 
 void FlowGraphCompiler::EmitTestAndCall(const ICData& ic_data,
-                                        Register class_id_reg,
                                         intptr_t argument_count,
                                         const Array& argument_names,
-                                        Label* deopt,
+                                        Label* failed,
+                                        Label* match_found,
                                         intptr_t deopt_id,
                                         intptr_t token_index,
                                         LocationSummary* locs) {
   ASSERT(is_optimizing());
-  ASSERT(!ic_data.IsNull() && (ic_data.NumberOfUsedChecks() > 0));
-  Label match_found;
-  const intptr_t len = ic_data.NumberOfChecks();
-  GrowableArray<CidTarget> sorted(len);
-  SortICDataByCount(ic_data, &sorted, /* drop_smi = */ false);
-  ASSERT(class_id_reg != S4);
-  ASSERT(len > 0);  // Why bother otherwise.
+  __ Comment("EmitTestAndCall");
   const Array& arguments_descriptor =
       Array::ZoneHandle(ArgumentsDescriptor::New(argument_count,
                                                  argument_names));
   StubCode* stub_code = isolate()->stub_code();
 
-  __ Comment("EmitTestAndCall");
+  // Load receiver into T0.
+  __ LoadFromOffset(T0, SP, (argument_count - 1) * kWordSize);
   __ LoadObject(S4, arguments_descriptor);
-  for (intptr_t i = 0; i < len; i++) {
-    const bool is_last_check = (i == (len - 1));
-    Label next_test;
-    if (is_last_check) {
-      __ BranchNotEqual(class_id_reg, Immediate(sorted[i].cid), deopt);
+
+  const bool kFirstCheckIsSmi = ic_data.GetReceiverClassIdAt(0) == kSmiCid;
+  const intptr_t kNumChecks = ic_data.NumberOfChecks();
+
+  ASSERT(!ic_data.IsNull() && (kNumChecks > 0));
+
+  Label after_smi_test;
+  __ andi(CMPRES1, T0, Immediate(kSmiTagMask));
+  if (kFirstCheckIsSmi) {
+    // Jump if receiver is not Smi.
+    if (kNumChecks == 1) {
+      __ bne(CMPRES1, ZR, failed);
     } else {
-      __ BranchNotEqual(class_id_reg, Immediate(sorted[i].cid), &next_test);
+      __ bne(CMPRES1, ZR, &after_smi_test);
+    }
+    // Do not use the code from the function, but let the code be patched so
+    // that we can record the outgoing edges to other code.
+    GenerateDartCall(deopt_id,
+                     token_index,
+                     &stub_code->CallStaticFunctionLabel(),
+                     RawPcDescriptors::kOther,
+                     locs);
+    const Function& function = Function::Handle(ic_data.GetTargetAt(0));
+    AddStaticCallTarget(function);
+    __ Drop(argument_count);
+    if (kNumChecks > 1) {
+      __ b(match_found);
+    }
+  } else {
+    // Receiver is Smi, but Smi is not a valid class therefore fail.
+    // (Smi class must be first in the list).
+    __ beq(CMPRES1, ZR, failed);
+  }
+
+  __ Bind(&after_smi_test);
+
+  GrowableArray<CidTarget> sorted(kNumChecks);
+  SortICDataByCount(ic_data, &sorted, /* drop_smi = */ true);
+
+  // Value is not Smi,
+  const intptr_t kSortedLen = sorted.length();
+  // If kSortedLen is 0 then only a Smi check was needed; the Smi check above
+  // will fail if there was only one check and receiver is not Smi.
+  if (kSortedLen == 0) return;
+
+  __ LoadClassId(T2, T0);
+  for (intptr_t i = 0; i < kSortedLen; i++) {
+    const bool kIsLastCheck = (i == (kSortedLen - 1));
+    ASSERT(sorted[i].cid != kSmiCid);
+    Label next_test;
+    if (kIsLastCheck) {
+      __ BranchNotEqual(T2, Immediate(sorted[i].cid), failed);
+    } else {
+      __ BranchNotEqual(T2, Immediate(sorted[i].cid), &next_test);
     }
     // Do not use the code from the function, but let the code be patched so
     // that we can record the outgoing edges to other code.
@@ -1579,12 +1622,11 @@
     const Function& function = *sorted[i].target;
     AddStaticCallTarget(function);
     __ Drop(argument_count);
-    if (!is_last_check) {
-      __ b(&match_found);
+    if (!kIsLastCheck) {
+      __ b(match_found);
     }
     __ Bind(&next_test);
   }
-  __ Bind(&match_found);
 }
 
 
diff --git a/runtime/vm/flow_graph_compiler_x64.cc b/runtime/vm/flow_graph_compiler_x64.cc
index b3bbe79..649e919 100644
--- a/runtime/vm/flow_graph_compiler_x64.cc
+++ b/runtime/vm/flow_graph_compiler_x64.cc
@@ -604,7 +604,7 @@
     // time, since an uninstantiated type at compile time could be Object or
     // dynamic at run time.
     __ CompareObject(RAX, Object::null_object(), PP);
-    __ j(EQUAL, &is_not_instance);
+    __ j(EQUAL, type.IsNullType() ? &is_instance : &is_not_instance);
   }
 
   // Generate inline instanceof test.
@@ -1471,33 +1471,77 @@
 
 
 void FlowGraphCompiler::EmitTestAndCall(const ICData& ic_data,
-                                        Register class_id_reg,
                                         intptr_t argument_count,
                                         const Array& argument_names,
-                                        Label* deopt,
+                                        Label* failed,
+                                        Label* match_found,
                                         intptr_t deopt_id,
                                         intptr_t token_index,
                                         LocationSummary* locs) {
   ASSERT(is_optimizing());
-  ASSERT(!ic_data.IsNull() && (ic_data.NumberOfUsedChecks() > 0));
-  Label match_found;
-  const intptr_t len = ic_data.NumberOfChecks();
-  GrowableArray<CidTarget> sorted(len);
-  SortICDataByCount(ic_data, &sorted, /* drop_smi = */ false);
-  ASSERT(class_id_reg != R10);
-  ASSERT(len > 0);  // Why bother otherwise.
+
+  __ Comment("EmitTestAndCall");
   const Array& arguments_descriptor =
       Array::ZoneHandle(ArgumentsDescriptor::New(argument_count,
                                                  argument_names));
   StubCode* stub_code = isolate()->stub_code();
-
+  // Load receiver into RAX.
+  __ movq(RAX,
+      Address(RSP, (argument_count - 1) * kWordSize));
   __ LoadObject(R10, arguments_descriptor, PP);
-  for (intptr_t i = 0; i < len; i++) {
-    const bool is_last_check = (i == (len - 1));
+
+  const bool kFirstCheckIsSmi = ic_data.GetReceiverClassIdAt(0) == kSmiCid;
+  const intptr_t kNumChecks = ic_data.NumberOfChecks();
+
+  ASSERT(!ic_data.IsNull() && (kNumChecks > 0));
+
+  Label after_smi_test;
+  __ testq(RAX, Immediate(kSmiTagMask));
+  if (kFirstCheckIsSmi) {
+    // Jump if receiver is not Smi.
+    if (kNumChecks == 1) {
+      __ j(NOT_ZERO, failed);
+    } else {
+      __ j(NOT_ZERO, &after_smi_test);
+    }
+    // Do not use the code from the function, but let the code be patched so
+    // that we can record the outgoing edges to other code.
+    GenerateDartCall(deopt_id,
+                     token_index,
+                     &stub_code->CallStaticFunctionLabel(),
+                     RawPcDescriptors::kOther,
+                     locs);
+    const Function& function = Function::Handle(ic_data.GetTargetAt(0));
+    AddStaticCallTarget(function);
+    __ Drop(argument_count, RCX);
+    if (kNumChecks > 1) {
+      __ jmp(match_found);
+    }
+  } else {
+    // Receiver is Smi, but Smi is not a valid class therefore fail.
+    // (Smi class must be first in the list).
+    __ j(ZERO, failed);
+  }
+  __ Bind(&after_smi_test);
+
+  ASSERT(!ic_data.IsNull() && (kNumChecks > 0));
+  GrowableArray<CidTarget> sorted(kNumChecks);
+  SortICDataByCount(ic_data, &sorted, /* drop_smi = */ true);
+
+  const intptr_t kSortedLen = sorted.length();
+  // If kSortedLen is 0 then only a Smi check was needed; the Smi check above
+  // will fail if there was only one check and receiver is not Smi.
+  if (kSortedLen == 0) return;
+
+  // Value is not Smi,
+  __ LoadClassId(RDI, RAX);
+  for (intptr_t i = 0; i < kSortedLen; i++) {
+    const bool kIsLastCheck = (i == (kSortedLen - 1));
+    ASSERT(sorted[i].cid != kSmiCid);
     Label next_test;
-    __ cmpl(class_id_reg, Immediate(sorted[i].cid));
-    if (is_last_check) {
-      __ j(NOT_EQUAL, deopt);
+    __ cmpl(RDI, Immediate(sorted[i].cid));
+    if (kIsLastCheck) {
+      __ j(NOT_EQUAL, failed);
     } else {
       __ j(NOT_EQUAL, &next_test);
     }
@@ -1511,12 +1555,11 @@
     const Function& function = *sorted[i].target;
     AddStaticCallTarget(function);
     __ Drop(argument_count, RCX);
-    if (!is_last_check) {
-      __ jmp(&match_found);
+    if (!kIsLastCheck) {
+      __ jmp(match_found);
     }
     __ Bind(&next_test);
   }
-  __ Bind(&match_found);
 }
 
 
diff --git a/runtime/vm/flow_graph_inliner.cc b/runtime/vm/flow_graph_inliner.cc
index 5e79772..a433948 100644
--- a/runtime/vm/flow_graph_inliner.cc
+++ b/runtime/vm/flow_graph_inliner.cc
@@ -59,6 +59,7 @@
 
 DECLARE_FLAG(bool, compiler_stats);
 DECLARE_FLAG(int, deoptimization_counter_threshold);
+DECLARE_FLAG(bool, polymorphic_with_deopt);
 DECLARE_FLAG(bool, print_flow_graph);
 DECLARE_FLAG(bool, print_flow_graph_optimized);
 DECLARE_FLAG(bool, verify_compiler);
@@ -1134,6 +1135,8 @@
     for (intptr_t call_idx = 0; call_idx < call_info.length(); ++call_idx) {
       PolymorphicInstanceCallInstr* call = call_info[call_idx].call;
       if (call->with_checks()) {
+        // PolymorphicInliner introduces deoptimization paths.
+        if (!FLAG_polymorphic_with_deopt) return;
         const Function& cl = call_info[call_idx].caller();
         intptr_t caller_inlining_id =
             call_info[call_idx].caller_graph->inlining_id();
diff --git a/runtime/vm/flow_graph_optimizer.cc b/runtime/vm/flow_graph_optimizer.cc
index 2db078f..6f2f635 100644
--- a/runtime/vm/flow_graph_optimizer.cc
+++ b/runtime/vm/flow_graph_optimizer.cc
@@ -27,6 +27,11 @@
 
 DEFINE_FLAG(int, getter_setter_ratio, 13,
     "Ratio of getter/setter usage used for double field unboxing heuristics");
+// Setting 'guess_other_cid' to true causes issue 23693 crash.
+// TODO(srdjan): Evaluate if that optimization is wrong.
+DEFINE_FLAG(bool, guess_other_cid, false,
+    "Artificially create type feedback for arithmetic etc. operations"
+    " by guessing the other unknown argument cid");
 DEFINE_FLAG(bool, load_cse, true, "Use redundant load elimination.");
 DEFINE_FLAG(bool, dead_store_elimination, true, "Eliminate dead stores");
 DEFINE_FLAG(int, max_polymorphic_checks, 4,
@@ -45,6 +50,8 @@
 #if defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_IA32)
 DEFINE_FLAG(bool, trace_smi_widening, false, "Trace Smi->Int32 widening pass.");
 #endif
+
+DECLARE_FLAG(bool, polymorphic_with_deopt);
 DECLARE_FLAG(bool, source_lines);
 DECLARE_FLAG(bool, trace_type_check_elimination);
 DECLARE_FLAG(bool, warn_on_javascript_compatibility);
@@ -159,7 +166,6 @@
 }
 
 
-// Attempt to build ICData for call using propagated class-ids.
 bool FlowGraphOptimizer::TryCreateICData(InstanceCallInstr* call) {
   ASSERT(call->HasICData());
   if (call->ic_data()->NumberOfUsedChecks() > 0) {
@@ -191,7 +197,9 @@
       Token::IsBinaryOperator(op_kind)) {
     // Guess cid: if one of the inputs is a number assume that the other
     // is a number of same type.
-    if (Compiler::guess_other_cid()) {
+    // Issue 23693. It is potentially wrong to assign types here that may
+    // conflict with other graph analysis.
+    if (FLAG_guess_other_cid) {
       const intptr_t cid_0 = class_ids[0];
       const intptr_t cid_1 = class_ids[1];
       if ((cid_0 == kDynamicCid) && (IsNumberCid(cid_1))) {
@@ -202,44 +210,74 @@
     }
   }
 
+  bool all_cids_known = true;
   for (intptr_t i = 0; i < class_ids.length(); i++) {
     if (class_ids[i] == kDynamicCid) {
       // Not all cid-s known.
-      return false;
+      all_cids_known = false;
+      break;
     }
   }
 
-  const Array& args_desc_array = Array::Handle(Z,
-      ArgumentsDescriptor::New(call->ArgumentCount(), call->argument_names()));
-  ArgumentsDescriptor args_desc(args_desc_array);
-  const Class& receiver_class = Class::Handle(Z,
-      isolate()->class_table()->At(class_ids[0]));
-  const Function& function = Function::Handle(Z,
-      Resolver::ResolveDynamicForReceiverClass(
-          receiver_class,
-          call->function_name(),
-          args_desc));
-  if (function.IsNull()) {
-    return false;
+  if (all_cids_known) {
+    const Array& args_desc_array = Array::Handle(Z,
+        ArgumentsDescriptor::New(call->ArgumentCount(),
+                                 call->argument_names()));
+    ArgumentsDescriptor args_desc(args_desc_array);
+    const Class& receiver_class = Class::Handle(Z,
+        isolate()->class_table()->At(class_ids[0]));
+    const Function& function = Function::Handle(Z,
+        Resolver::ResolveDynamicForReceiverClass(
+            receiver_class,
+            call->function_name(),
+            args_desc));
+    if (function.IsNull()) {
+      return false;
+    }
+
+    // Create new ICData, do not modify the one attached to the instruction
+    // since it is attached to the assembly instruction itself.
+    // TODO(srdjan): Prevent modification of ICData object that is
+    // referenced in assembly code.
+    const ICData& ic_data = ICData::ZoneHandle(Z,
+        ICData::NewFrom(*call->ic_data(), class_ids.length()));
+    if (class_ids.length() > 1) {
+      ic_data.AddCheck(class_ids, function);
+    } else {
+      ASSERT(class_ids.length() == 1);
+      ic_data.AddReceiverCheck(class_ids[0], function);
+    }
+    call->set_ic_data(&ic_data);
+    return true;
   }
-  // Create new ICData, do not modify the one attached to the instruction
-  // since it is attached to the assembly instruction itself.
-  // TODO(srdjan): Prevent modification of ICData object that is
-  // referenced in assembly code.
-  ICData& ic_data = ICData::ZoneHandle(Z, ICData::New(
-      flow_graph_->function(),
-      call->function_name(),
-      args_desc_array,
-      call->deopt_id(),
-      class_ids.length()));
-  if (class_ids.length() > 1) {
-    ic_data.AddCheck(class_ids, function);
-  } else {
-    ASSERT(class_ids.length() == 1);
-    ic_data.AddReceiverCheck(class_ids[0], function);
+
+  // Check if getter or setter in function's class and class is currently leaf.
+  if ((call->token_kind() == Token::kGET) ||
+      (call->token_kind() == Token::kSET)) {
+    const Class& owner_class = Class::Handle(Z, function().Owner());
+    if (!owner_class.is_abstract() &&
+        !CHA::HasSubclasses(owner_class) &&
+        !CHA::IsImplemented(owner_class)) {
+      const Array& args_desc_array = Array::Handle(Z,
+          ArgumentsDescriptor::New(call->ArgumentCount(),
+                                   call->argument_names()));
+      ArgumentsDescriptor args_desc(args_desc_array);
+      const Function& function = Function::Handle(Z,
+          Resolver::ResolveDynamicForReceiverClass(owner_class,
+                                                   call->function_name(),
+                                                   args_desc));
+      if (function.IsNull()) {
+        return false;
+      }
+      const ICData& ic_data = ICData::ZoneHandle(Z,
+          ICData::NewFrom(*call->ic_data(), class_ids.length()));
+      ic_data.AddReceiverCheck(owner_class.id(), function);
+      call->set_ic_data(&ic_data);
+      return true;
+    }
   }
-  call->set_ic_data(&ic_data);
-  return true;
+
+  return false;
 }
 
 
@@ -273,6 +311,10 @@
 
 void FlowGraphOptimizer::SpecializePolymorphicInstanceCall(
     PolymorphicInstanceCallInstr* call) {
+  if (!FLAG_polymorphic_with_deopt) {
+    // Specialization adds receiver checks which can lead to deoptimization.
+    return;
+  }
   if (!call->with_checks()) {
     return;  // Already specialized.
   }
@@ -3981,9 +4023,9 @@
   // Signature classes have different type checking rules.
   if (type_class.IsSignatureClass()) return false;
   // Could be an interface check?
-  if (thread()->cha()->IsImplemented(type_class)) return false;
+  if (CHA::IsImplemented(type_class)) return false;
   // Check if there are subclasses.
-  if (thread()->cha()->HasSubclasses(type_class)) {
+  if (CHA::HasSubclasses(type_class)) {
     return false;
   }
 
@@ -4088,7 +4130,8 @@
     // reported, so do not replace the instance call.
     return;
   }
-  if (unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks) {
+  if ((unary_checks.NumberOfChecks() > 0) &&
+      (unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks)) {
     ZoneGrowableArray<intptr_t>* results =
         new(Z) ZoneGrowableArray<intptr_t>(unary_checks.NumberOfChecks() * 2);
     Bool& as_bool =
@@ -4179,7 +4222,8 @@
     // reported, so do not replace the instance call.
     return;
   }
-  if (unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks) {
+  if ((unary_checks.NumberOfChecks() > 0) &&
+      (unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks)) {
     ZoneGrowableArray<intptr_t>* results =
         new(Z) ZoneGrowableArray<intptr_t>(unary_checks.NumberOfChecks() * 2);
     const Bool& as_bool = Bool::ZoneHandle(Z,
@@ -4213,22 +4257,46 @@
 }
 
 
-// Tries to optimize instance call by replacing it with a faster instruction
-// (e.g, binary op, field load, ..).
-void FlowGraphOptimizer::VisitInstanceCall(InstanceCallInstr* instr) {
-  if (!instr->HasICData() || (instr->ic_data()->NumberOfUsedChecks() == 0)) {
+// Special optimizations when running in --noopt mode.
+void FlowGraphOptimizer::InstanceCallNoopt(InstanceCallInstr* instr) {
+  // TODO(srdjan): Investigate other attempts, as they are not allowed to
+  // deoptimize.
+  const Token::Kind op_kind = instr->token_kind();
+  if (instr->HasICData() && (instr->ic_data()->NumberOfUsedChecks() > 0)) {
+    const ICData& unary_checks =
+        ICData::ZoneHandle(Z, instr->ic_data()->AsUnaryClassChecks());
+
+    PolymorphicInstanceCallInstr* call =
+        new(Z) PolymorphicInstanceCallInstr(instr, unary_checks,
+                                            true /* call_with_checks*/);
+    instr->ReplaceWith(call, current_iterator());
     return;
   }
 
-  const Token::Kind op_kind = instr->token_kind();
-  if (Compiler::always_optimize()) {
-    // TODO(srdjan): Investigate other attempts, as they are not allowed to
-    // deoptimize.
-    if ((op_kind == Token::kGET) && TryInlineInstanceGetter(instr, false)) {
-      return;
-    }
+  // Type test is special as it always gets converted into inlined code.
+  if (Token::IsTypeTestOperator(op_kind)) {
+    ReplaceWithInstanceOf(instr);
     return;
   }
+  if (Token::IsTypeCastOperator(op_kind)) {
+    ReplaceWithTypeCast(instr);
+    return;
+  }
+}
+
+
+// Tries to optimize instance call by replacing it with a faster instruction
+// (e.g, binary op, field load, ..).
+void FlowGraphOptimizer::VisitInstanceCall(InstanceCallInstr* instr) {
+  if (Compiler::always_optimize()) {
+    InstanceCallNoopt(instr);
+    return;
+  }
+
+  if (!instr->HasICData() || (instr->ic_data()->NumberOfUsedChecks() == 0)) {
+    return;
+  }
+  const Token::Kind op_kind = instr->token_kind();
 
   // Type test is special as it always gets converted into inlined code.
   if (Token::IsTypeTestOperator(op_kind)) {
@@ -4315,7 +4383,7 @@
 
   if (unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks) {
     bool call_with_checks;
-    if (has_one_target) {
+    if (has_one_target && FLAG_polymorphic_with_deopt) {
       // Type propagation has not run yet, we cannot eliminate the check.
       AddReceiverCheck(instr);
       // Call can still deoptimize, do not detach environment from instr.
diff --git a/runtime/vm/flow_graph_optimizer.h b/runtime/vm/flow_graph_optimizer.h
index 92b6042..0df970b 100644
--- a/runtime/vm/flow_graph_optimizer.h
+++ b/runtime/vm/flow_graph_optimizer.h
@@ -258,6 +258,8 @@
                                        Representation rep, intptr_t cid);
   bool TryStringLengthOneEquality(InstanceCallInstr* call, Token::Kind op_kind);
 
+  void InstanceCallNoopt(InstanceCallInstr* instr);
+
   Thread* thread() const { return flow_graph_->thread(); }
   Isolate* isolate() const { return flow_graph_->isolate(); }
   Zone* zone() const { return flow_graph_->zone(); }
diff --git a/runtime/vm/flow_graph_type_propagator.cc b/runtime/vm/flow_graph_type_propagator.cc
index f1ec8ba..f22c50f 100644
--- a/runtime/vm/flow_graph_type_propagator.cc
+++ b/runtime/vm/flow_graph_type_propagator.cc
@@ -543,8 +543,8 @@
       // Don't infer a cid from an abstract type for signature classes since
       // there can be multiple compatible classes with different cids.
       if (!type_class.IsSignatureClass() &&
-          !cha->IsImplemented(type_class) &&
-          !cha->HasSubclasses(type_class)) {
+          !CHA::IsImplemented(type_class) &&
+          !CHA::HasSubclasses(type_class)) {
         if (type_class.IsPrivate()) {
           // Type of a private class cannot change through later loaded libs.
           cid_ = type_class.id();
@@ -780,7 +780,7 @@
     if (type.HasResolvedTypeClass()) {
       Thread* thread = Thread::Current();
       const Class& type_class = Class::Handle(type.type_class());
-      if (!thread->cha()->HasSubclasses(type_class)) {
+      if (!CHA::HasSubclasses(type_class)) {
         if (type_class.IsPrivate()) {
           // Private classes can never be subclassed by later loaded libs.
           cid = type_class.id();
diff --git a/runtime/vm/gc_marker.cc b/runtime/vm/gc_marker.cc
index 34811cb..d7e05f1 100644
--- a/runtime/vm/gc_marker.cc
+++ b/runtime/vm/gc_marker.cc
@@ -15,6 +15,7 @@
 #include "vm/pages.h"
 #include "vm/raw_object.h"
 #include "vm/stack_frame.h"
+#include "vm/thread_pool.h"
 #include "vm/visitor.h"
 #include "vm/object_id_ring.h"
 
@@ -120,22 +121,80 @@
 };
 
 
+class DelaySet {
+ private:
+  typedef std::multimap<RawObject*, RawWeakProperty*> Map;
+  typedef std::pair<RawObject*, RawWeakProperty*> MapEntry;
+
+ public:
+  DelaySet() : mutex_(new Mutex()) {}
+  ~DelaySet() { delete mutex_; }
+
+  // Returns 'true' if this inserted a new key (not just added a value).
+  bool Insert(RawWeakProperty* raw_weak) {
+    MutexLocker ml(mutex_);
+    RawObject* raw_key = raw_weak->ptr()->key_;
+    bool new_key = (delay_set_.find(raw_key) == delay_set_.end());
+    delay_set_.insert(std::make_pair(raw_key, raw_weak));
+    return new_key;
+  }
+
+  void ClearReferences() {
+    MutexLocker ml(mutex_);
+    for (Map::iterator it = delay_set_.begin(); it != delay_set_.end(); ++it) {
+      WeakProperty::Clear(it->second);
+    }
+  }
+
+  // Visit all values with a key equal to raw_obj.
+  void VisitValuesForKey(RawObject* raw_obj, ObjectPointerVisitor* visitor) {
+    // Extract the range into a temporary vector to iterate over it
+    // while delay_set_ may be modified.
+    std::vector<MapEntry> temp_copy;
+    {
+      MutexLocker ml(mutex_);
+      std::pair<Map::iterator, Map::iterator> ret =
+          delay_set_.equal_range(raw_obj);
+      temp_copy.insert(temp_copy.end(), ret.first, ret.second);
+      delay_set_.erase(ret.first, ret.second);
+    }
+    for (std::vector<MapEntry>::iterator it = temp_copy.begin();
+         it != temp_copy.end(); ++it) {
+      it->second->VisitPointers(visitor);
+    }
+  }
+
+ private:
+  Map delay_set_;
+  Mutex* mutex_;
+};
+
+
 class MarkingVisitor : public ObjectPointerVisitor {
  public:
   MarkingVisitor(Isolate* isolate,
                  Heap* heap,
                  PageSpace* page_space,
                  MarkingStack* marking_stack,
+                 DelaySet* delay_set,
                  bool visit_function_code)
       : ObjectPointerVisitor(isolate),
+        thread_(Thread::Current()),
         heap_(heap),
         vm_heap_(Dart::vm_isolate()->heap()),
         class_table_(isolate->class_table()),
         page_space_(page_space),
         marking_stack_(marking_stack),
+        delay_set_(delay_set),
         visiting_old_object_(NULL),
         visit_function_code_(visit_function_code) {
     ASSERT(heap_ != vm_heap_);
+    ASSERT(thread_->isolate() == isolate);
+  }
+
+  ~MarkingVisitor() {
+    // 'Finalize' should be explicitly called before destruction.
+    ASSERT(marking_stack_ == NULL);
   }
 
   MarkingStack* marking_stack() const { return marking_stack_; }
@@ -148,30 +207,49 @@
 
   bool visit_function_code() const { return visit_function_code_; }
 
-  virtual GrowableArray<RawFunction*>* skipped_code_functions() {
+  virtual MallocGrowableArray<RawFunction*>* skipped_code_functions() {
     return &skipped_code_functions_;
   }
 
-  void DelayWeakProperty(RawWeakProperty* raw_weak) {
-    RawObject* raw_key = raw_weak->ptr()->key_;
-    DelaySet::iterator it = delay_set_.find(raw_key);
-    if (it != delay_set_.end()) {
-      ASSERT(raw_key->IsWatched());
-    } else {
-      ASSERT(!raw_key->IsWatched());
-      raw_key->SetWatchedBitUnsynchronized();
+  // Returns the mark bit. Sets the watch bit if unmarked. (The prior value of
+  // the watched bit is returned in 'watched_before' for validation purposes.)
+  // TODO(koda): When synchronizing header bits, this goes in a single CAS loop.
+  static bool EnsureWatchedIfWhite(RawObject* obj, bool* watched_before) {
+    if (obj->IsMarked()) {
+      return false;
     }
-    delay_set_.insert(std::make_pair(raw_key, raw_weak));
+    if (!obj->IsWatched()) {
+      *watched_before = false;
+      obj->SetWatchedBitUnsynchronized();
+    } else {
+      *watched_before = true;
+    }
+    return true;
   }
 
-  void Finalize() {
-    DelaySet::iterator it = delay_set_.begin();
-    for (; it != delay_set_.end(); ++it) {
-      WeakProperty::Clear(it->second);
+  void ProcessWeakProperty(RawWeakProperty* raw_weak) {
+    // The fate of the weak property is determined by its key.
+    RawObject* raw_key = raw_weak->ptr()->key_;
+    bool watched_before = false;
+    if (raw_key->IsHeapObject() &&
+        raw_key->IsOldObject() &&
+        EnsureWatchedIfWhite(raw_key, &watched_before)) {
+      // Key is white.  Delay the weak property.
+      bool new_key = delay_set_->Insert(raw_weak);
+      ASSERT(new_key == !watched_before);
+    } else {
+      // Key is gray or black.  Make the weak property black.
+      raw_weak->VisitPointers(this);
     }
+  }
+
+  // Called when all marking is complete.
+  void Finalize() {
     if (!visit_function_code_) {
       DetachCode();
     }
+    // Fail fast on attempts to mark after finalizing.
+    marking_stack_ = NULL;
   }
 
   void VisitingOldObject(RawObject* obj) {
@@ -193,17 +271,7 @@
     raw_obj->ClearRememberedBitUnsynchronized();
     raw_obj->ClearWatchedBitUnsynchronized();
     if (is_watched) {
-      std::pair<DelaySet::iterator, DelaySet::iterator> ret;
-      // Visit all elements with a key equal to raw_obj.
-      ret = delay_set_.equal_range(raw_obj);
-      // Create a copy of the range in a temporary vector to iterate over it
-      // while delay_set_ may be modified.
-      std::vector<DelaySetEntry> temp_copy(ret.first, ret.second);
-      delay_set_.erase(ret.first, ret.second);
-      for (std::vector<DelaySetEntry>::iterator it = temp_copy.begin();
-           it != temp_copy.end(); ++it) {
-        it->second->VisitPointers(this);
-      }
+      delay_set_->VisitValuesForKey(raw_obj, this);
     }
     marking_stack_->Push(raw_obj);
   }
@@ -226,7 +294,7 @@
           !visiting_old_object_->IsRemembered()) {
         ASSERT(p != NULL);
         visiting_old_object_->SetRememberedBitUnsynchronized();
-        isolate()->store_buffer()->AddObjectGC(visiting_old_object_);
+        thread_->StoreBufferAddObjectGC(visiting_old_object_);
       }
       return;
     }
@@ -283,19 +351,20 @@
       ISL_Print("  total detached unoptimized: %" Pd "\n",
                 unoptimized_code_count);
     }
+    // Clean up.
+    skipped_code_functions_.Clear();
   }
 
+  Thread* thread_;
   Heap* heap_;
   Heap* vm_heap_;
   ClassTable* class_table_;
   PageSpace* page_space_;
   MarkingStack* marking_stack_;
+  DelaySet* delay_set_;
   RawObject* visiting_old_object_;
-  typedef std::multimap<RawObject*, RawWeakProperty*> DelaySet;
-  typedef std::pair<RawObject*, RawWeakProperty*> DelaySetEntry;
-  DelaySet delay_set_;
   const bool visit_function_code_;
-  GrowableArray<RawFunction*> skipped_code_functions_;
+  MallocGrowableArray<RawFunction*> skipped_code_functions_;
 
   DISALLOW_IMPLICIT_CONSTRUCTORS(MarkingVisitor);
 };
@@ -338,6 +407,7 @@
   if (invoke_api_callbacks && (isolate->gc_prologue_callback() != NULL)) {
     (isolate->gc_prologue_callback())();
   }
+  Thread::PrepareForGC();
   // The store buffers will be rebuilt as part of marking, reset them now.
   isolate->store_buffer()->Reset();
 }
@@ -445,29 +515,13 @@
     } else {
       RawWeakProperty* raw_weak = reinterpret_cast<RawWeakProperty*>(raw_obj);
       marked_bytes_ += raw_weak->Size();
-      ProcessWeakProperty(raw_weak, visitor);
+      visitor->ProcessWeakProperty(raw_weak);
     }
   }
   visitor->VisitingOldObject(NULL);
 }
 
 
-void GCMarker::ProcessWeakProperty(RawWeakProperty* raw_weak,
-                                   MarkingVisitor* visitor) {
-  // The fate of the weak property is determined by its key.
-  RawObject* raw_key = raw_weak->ptr()->key_;
-  if (raw_key->IsHeapObject() &&
-      raw_key->IsOldObject() &&
-      !raw_key->IsMarked()) {
-    // Key is white.  Delay the weak property.
-    visitor->DelayWeakProperty(raw_weak);
-  } else {
-    // Key is gray or black.  Make the weak property black.
-    raw_weak->VisitPointers(visitor);
-  }
-}
-
-
 void GCMarker::ProcessWeakTables(PageSpace* page_space) {
   for (int sel = 0;
        sel < Heap::kNumWeakSelectors;
@@ -526,14 +580,16 @@
   {
     StackZone zone(isolate);
     MarkingStack marking_stack;
-    MarkingVisitor mark(
-        isolate, heap_, page_space, &marking_stack, visit_function_code);
+    DelaySet delay_set;
+    MarkingVisitor mark(isolate, heap_, page_space, &marking_stack,
+                        &delay_set, visit_function_code);
     IterateRoots(isolate, &mark, !invoke_api_callbacks);
     DrainMarkingStack(isolate, &mark);
     IterateWeakReferences(isolate, &mark);
     MarkingWeakVisitor mark_weak;
     IterateWeakRoots(isolate, &mark_weak, invoke_api_callbacks);
     mark.Finalize();
+    delay_set.ClearReferences();
     ProcessWeakTables(page_space);
     ProcessObjectIdTable(isolate);
   }
diff --git a/runtime/vm/gc_marker.h b/runtime/vm/gc_marker.h
index 5e74014..95666b3 100644
--- a/runtime/vm/gc_marker.h
+++ b/runtime/vm/gc_marker.h
@@ -43,7 +43,6 @@
                         bool visit_prologue_weak_persistent_handles);
   void IterateWeakReferences(Isolate* isolate, MarkingVisitor* visitor);
   void DrainMarkingStack(Isolate* isolate, MarkingVisitor* visitor);
-  void ProcessWeakProperty(RawWeakProperty* raw_weak, MarkingVisitor* visitor);
   void ProcessWeakTables(PageSpace* page_space);
   void ProcessObjectIdTable(Isolate* isolate);
 
diff --git a/runtime/vm/handles.cc b/runtime/vm/handles.cc
index 6a8d6ca..bd45c73 100644
--- a/runtime/vm/handles.cc
+++ b/runtime/vm/handles.cc
@@ -6,6 +6,7 @@
 
 #include "platform/assert.h"
 #include "platform/utils.h"
+#include "vm/dart_api_state.h"
 #include "vm/flags.h"
 #include "vm/isolate.h"
 #include "vm/os.h"
@@ -43,7 +44,16 @@
 }
 
 
+#if defined(DEBUG)
+static bool IsCurrentApiNativeScope(Zone* zone) {
+  ApiNativeScope* scope = ApiNativeScope::Current();
+  return (scope != NULL) && (scope->zone() == zone);
+}
+#endif  // DEBUG
+
+
 uword VMHandles::AllocateHandle(Zone* zone) {
+  DEBUG_ASSERT(!IsCurrentApiNativeScope(zone));
   return Handles<kVMHandleSizeInWords,
                  kVMHandlesPerChunk,
                  kOffsetOfRawPtr>::AllocateHandle(zone);
@@ -51,6 +61,7 @@
 
 
 uword VMHandles::AllocateZoneHandle(Zone* zone) {
+  DEBUG_ASSERT(!IsCurrentApiNativeScope(zone));
   return Handles<kVMHandleSizeInWords,
                  kVMHandlesPerChunk,
                  kOffsetOfRawPtr>::AllocateZoneHandle(zone);
diff --git a/runtime/vm/handles.h b/runtime/vm/handles.h
index 52ba6e8..da283d7 100644
--- a/runtime/vm/handles.h
+++ b/runtime/vm/handles.h
@@ -283,6 +283,9 @@
   // Returns number of handles, these functions are used for testing purposes.
   static int ScopedHandleCount();
   static int ZoneHandleCount();
+
+  friend class ApiZone;
+  friend class ApiNativeScope;
 };
 
 
diff --git a/runtime/vm/heap.cc b/runtime/vm/heap.cc
index 3b92f94..27d39d3 100644
--- a/runtime/vm/heap.cc
+++ b/runtime/vm/heap.cc
@@ -19,6 +19,7 @@
 #include "vm/service_event.h"
 #include "vm/stack_frame.h"
 #include "vm/tags.h"
+#include "vm/timeline.h"
 #include "vm/verifier.h"
 #include "vm/virtual_memory.h"
 #include "vm/weak_table.h"
@@ -271,6 +272,9 @@
   switch (space) {
     case kNew: {
       VMTagScope tagScope(isolate(), VMTag::kGCNewSpaceTagId);
+      TimelineDurationScope tds(isolate(),
+                                isolate()->GetGCStream(),
+                                "CollectNewGeneration");
       RecordBeforeGC(kNew, reason);
       UpdateClassHeapStatsBeforeGC(kNew);
       new_space_->Scavenge(invoke_api_callbacks);
@@ -287,6 +291,9 @@
     case kOld:
     case kCode: {
       VMTagScope tagScope(isolate(), VMTag::kGCOldSpaceTagId);
+      TimelineDurationScope tds(isolate(),
+                                isolate()->GetGCStream(),
+                                "CollectOldGeneration");
       RecordBeforeGC(kOld, reason);
       UpdateClassHeapStatsBeforeGC(kOld);
       old_space_->MarkSweep(invoke_api_callbacks);
@@ -324,6 +331,9 @@
   TIMERSCOPE(isolate(), time_gc);
   {
     VMTagScope tagScope(isolate(), VMTag::kGCNewSpaceTagId);
+    TimelineDurationScope tds(isolate(),
+                              isolate()->GetGCStream(),
+                              "CollectNewGeneration");
     RecordBeforeGC(kNew, kFull);
     UpdateClassHeapStatsBeforeGC(kNew);
     new_space_->Scavenge(kInvokeApiCallbacks);
@@ -334,6 +344,9 @@
   }
   {
     VMTagScope tagScope(isolate(), VMTag::kGCOldSpaceTagId);
+    TimelineDurationScope tds(isolate(),
+                              isolate()->GetGCStream(),
+                              "CollectOldGeneration");
     RecordBeforeGC(kOld, kFull);
     UpdateClassHeapStatsBeforeGC(kOld);
     old_space_->MarkSweep(kInvokeApiCallbacks);
diff --git a/runtime/vm/instructions_arm.cc b/runtime/vm/instructions_arm.cc
index 2d14ba3..6709c19 100644
--- a/runtime/vm/instructions_arm.cc
+++ b/runtime/vm/instructions_arm.cc
@@ -14,7 +14,7 @@
 namespace dart {
 
 CallPattern::CallPattern(uword pc, const Code& code)
-    : object_pool_(Array::Handle(code.ObjectPool())),
+    : object_pool_(ObjectPool::Handle(code.GetObjectPool())),
       end_(pc),
       args_desc_load_end_(0),
       ic_data_load_end_(0),
@@ -51,7 +51,7 @@
 // and the loaded object in the output parameters 'reg' and 'obj'
 // respectively.
 uword InstructionPattern::DecodeLoadObject(uword end,
-                                           const Array& object_pool,
+                                           const ObjectPool& object_pool,
                                            Register* reg,
                                            Object* obj) {
   uword start = 0;
@@ -60,7 +60,7 @@
     // ldr reg, [reg, #+offset]
     intptr_t index = 0;
     start = DecodeLoadWordFromPool(end, reg, &index);
-    *obj = object_pool.At(index);
+    *obj = object_pool.ObjectAt(index);
   } else {
     intptr_t value = 0;
     start = DecodeLoadWordImmediate(end, reg, &value);
@@ -186,20 +186,12 @@
 
 
 uword CallPattern::TargetAddress() const {
-  ASSERT(target_address_pool_index_ >= 0);
-  const Object& target_address =
-      Object::Handle(object_pool_.At(target_address_pool_index_));
-  ASSERT(target_address.IsSmi());
-  // The address is stored in the object array as a RawSmi.
-  return reinterpret_cast<uword>(target_address.raw());
+  return object_pool_.RawValueAt(target_address_pool_index_);
 }
 
 
 void CallPattern::SetTargetAddress(uword target_address) const {
-  ASSERT(Utils::IsAligned(target_address, 4));
-  // The address is stored in the object array as a RawSmi.
-  const Smi& smi = Smi::Handle(reinterpret_cast<RawSmi*>(target_address));
-  object_pool_.SetAt(target_address_pool_index_, smi);
+  object_pool_.SetRawValueAt(target_address_pool_index_, target_address);
   // No need to flush the instruction cache, since the code is not modified.
 }
 
diff --git a/runtime/vm/instructions_arm.h b/runtime/vm/instructions_arm.h
index b36d04f..4d708ca 100644
--- a/runtime/vm/instructions_arm.h
+++ b/runtime/vm/instructions_arm.h
@@ -23,7 +23,7 @@
   // being loaded and the loaded object in the output parameters 'reg' and
   // 'obj' respectively.
   static uword DecodeLoadObject(uword end,
-                                const Array& object_pool,
+                                const ObjectPool& object_pool,
                                 Register* reg,
                                 Object* obj);
 
@@ -64,7 +64,7 @@
   static void InsertAt(uword pc, uword target_address);
 
  private:
-  const Array& object_pool_;
+  const ObjectPool& object_pool_;
 
   uword end_;
   uword args_desc_load_end_;
diff --git a/runtime/vm/instructions_arm64.cc b/runtime/vm/instructions_arm64.cc
index aea111f..1690456 100644
--- a/runtime/vm/instructions_arm64.cc
+++ b/runtime/vm/instructions_arm64.cc
@@ -14,7 +14,7 @@
 namespace dart {
 
 CallPattern::CallPattern(uword pc, const Code& code)
-    : object_pool_(Array::Handle(code.ObjectPool())),
+    : object_pool_(ObjectPool::Handle(code.GetObjectPool())),
       end_(pc),
       args_desc_load_end_(0),
       ic_data_load_end_(0),
@@ -45,7 +45,7 @@
 // and the loaded object in the output parameters 'reg' and 'obj'
 // respectively.
 uword InstructionPattern::DecodeLoadObject(uword end,
-                                           const Array& object_pool,
+                                           const ObjectPool& object_pool,
                                            Register* reg,
                                            Object* obj) {
   // 1. LoadWordFromPool
@@ -57,7 +57,7 @@
     // Case 1.
     intptr_t index = 0;
     start = DecodeLoadWordFromPool(end, reg, &index);
-    *obj = object_pool.At(index);
+    *obj = object_pool.ObjectAt(index);
   } else {
     // Case 2.
     intptr_t value = 0;
@@ -264,20 +264,12 @@
 
 
 uword CallPattern::TargetAddress() const {
-  ASSERT(target_address_pool_index_ >= 0);
-  const Object& target_address =
-      Object::Handle(object_pool_.At(target_address_pool_index_));
-  ASSERT(target_address.IsSmi());
-  // The address is stored in the object array as a RawSmi.
-  return reinterpret_cast<uword>(target_address.raw());
+  return object_pool_.RawValueAt(target_address_pool_index_);
 }
 
 
 void CallPattern::SetTargetAddress(uword target_address) const {
-  ASSERT(Utils::IsAligned(target_address, 4));
-  // The address is stored in the object array as a RawSmi.
-  const Smi& smi = Smi::Handle(reinterpret_cast<RawSmi*>(target_address));
-  object_pool_.SetAt(target_address_pool_index_, smi);
+  object_pool_.SetRawValueAt(target_address_pool_index_, target_address);
   // No need to flush the instruction cache, since the code is not modified.
 }
 
diff --git a/runtime/vm/instructions_arm64.h b/runtime/vm/instructions_arm64.h
index 12584fe..568d57e 100644
--- a/runtime/vm/instructions_arm64.h
+++ b/runtime/vm/instructions_arm64.h
@@ -23,7 +23,7 @@
   // being loaded and the loaded object in the output parameters 'reg' and
   // 'obj' respectively.
   static uword DecodeLoadObject(uword end,
-                                const Array& object_pool,
+                                const ObjectPool& object_pool,
                                 Register* reg,
                                 Object* obj);
 
@@ -71,7 +71,7 @@
   static void InsertAt(uword pc, uword target_address);
 
  private:
-  const Array& object_pool_;
+  const ObjectPool& object_pool_;
 
   uword end_;
   uword args_desc_load_end_;
diff --git a/runtime/vm/instructions_mips.cc b/runtime/vm/instructions_mips.cc
index 3e8cbe8..34a5c3a 100644
--- a/runtime/vm/instructions_mips.cc
+++ b/runtime/vm/instructions_mips.cc
@@ -13,7 +13,7 @@
 namespace dart {
 
 CallPattern::CallPattern(uword pc, const Code& code)
-    : object_pool_(Array::Handle(code.ObjectPool())),
+    : object_pool_(ObjectPool::Handle(code.GetObjectPool())),
       end_(pc),
       args_desc_load_end_(0),
       ic_data_load_end_(0),
@@ -39,7 +39,7 @@
 // and the loaded object in the output parameters 'reg' and 'obj'
 // respectively.
 uword InstructionPattern::DecodeLoadObject(uword end,
-                                           const Array& object_pool,
+                                           const ObjectPool& object_pool,
                                            Register* reg,
                                            Object* obj) {
   uword start = 0;
@@ -47,7 +47,7 @@
   if (instr->OpcodeField() == LW) {
     intptr_t index = 0;
     start = DecodeLoadWordFromPool(end, reg, &index);
-    *obj = object_pool.At(index);
+    *obj = object_pool.ObjectAt(index);
   } else {
     intptr_t value = 0;
     start = DecodeLoadWordImmediate(end, reg, &value);
@@ -154,20 +154,12 @@
 
 
 uword CallPattern::TargetAddress() const {
-  ASSERT(target_address_pool_index_ >= 0);
-  const Object& target_address =
-      Object::Handle(object_pool_.At(target_address_pool_index_));
-  ASSERT(target_address.IsSmi());
-  // The address is stored in the object array as a RawSmi.
-  return reinterpret_cast<uword>(target_address.raw());
+  return object_pool_.RawValueAt(target_address_pool_index_);
 }
 
 
 void CallPattern::SetTargetAddress(uword target_address) const {
-  ASSERT(Utils::IsAligned(target_address, 4));
-  // The address is stored in the object array as a RawSmi.
-  const Smi& smi = Smi::Handle(reinterpret_cast<RawSmi*>(target_address));
-  object_pool_.SetAt(target_address_pool_index_, smi);
+  object_pool_.SetRawValueAt(target_address_pool_index_, target_address);
   // No need to flush the instruction cache, since the code is not modified.
 }
 
diff --git a/runtime/vm/instructions_mips.h b/runtime/vm/instructions_mips.h
index 2a9e2e1..0091a95 100644
--- a/runtime/vm/instructions_mips.h
+++ b/runtime/vm/instructions_mips.h
@@ -23,7 +23,7 @@
   // being loaded and the loaded object in the output parameters 'reg' and
   // 'obj' respectively.
   static uword DecodeLoadObject(uword end,
-                                const Array& object_pool,
+                                const ObjectPool& object_pool,
                                 Register* reg,
                                 Object* obj);
 
@@ -64,7 +64,7 @@
   static void InsertAt(uword pc, uword target_address);
 
  private:
-  const Array& object_pool_;
+  const ObjectPool& object_pool_;
 
   uword end_;
   uword args_desc_load_end_;
diff --git a/runtime/vm/instructions_x64.cc b/runtime/vm/instructions_x64.cc
index 98ffcd9..51128dd 100644
--- a/runtime/vm/instructions_x64.cc
+++ b/runtime/vm/instructions_x64.cc
@@ -13,13 +13,12 @@
 
 intptr_t InstructionPattern::IndexFromPPLoad(uword start) {
   int32_t offset = *reinterpret_cast<int32_t*>(start);
-  offset += kHeapObjectTag;
-  return (offset - Array::data_offset()) / kWordSize;
+  return ObjectPool::IndexFromOffset(offset);
 }
 
 
 intptr_t InstructionPattern::OffsetFromPPIndex(intptr_t index) {
-  intptr_t offset = Array::element_offset(index);
+  intptr_t offset = ObjectPool::element_offset(index);
   return offset - kHeapObjectTag;
 }
 
@@ -40,15 +39,14 @@
 uword JumpPattern::TargetAddress() const {
   ASSERT(IsValid());
   int index = InstructionPattern::IndexFromPPLoad(start() + 3);
-  return reinterpret_cast<uword>(object_pool_.At(index));
+  return object_pool_.RawValueAt(index);
 }
 
 
 void JumpPattern::SetTargetAddress(uword target) const {
   ASSERT(IsValid());
   int index = InstructionPattern::IndexFromPPLoad(start() + 3);
-  const Smi& smi = Smi::Handle(reinterpret_cast<RawSmi*>(target));
-  object_pool_.SetAt(index, smi);
+  object_pool_.SetRawValueAt(index, target);
   // No need to flush the instruction cache, since the code is not modified.
 }
 
diff --git a/runtime/vm/instructions_x64.h b/runtime/vm/instructions_x64.h
index 0d6bb08..8f5cda4 100644
--- a/runtime/vm/instructions_x64.h
+++ b/runtime/vm/instructions_x64.h
@@ -60,7 +60,7 @@
  public:
   JumpPattern(uword pc, const Code& code)
       : InstructionPattern(pc),
-        object_pool_(Array::Handle(code.ObjectPool())) {}
+        object_pool_(ObjectPool::Handle(code.GetObjectPool())) {}
   static int InstructionLength() {
     return kLengthInBytes;
   }
@@ -73,7 +73,7 @@
   static const int kLengthInBytes = 7;
  private:
   virtual const int* pattern() const;
-  const Array& object_pool_;
+  const ObjectPool& object_pool_;
 
   DISALLOW_COPY_AND_ASSIGN(JumpPattern);
 };
diff --git a/runtime/vm/intermediate_language.cc b/runtime/vm/intermediate_language.cc
index 1bdd070..cc17570 100644
--- a/runtime/vm/intermediate_language.cc
+++ b/runtime/vm/intermediate_language.cc
@@ -28,13 +28,13 @@
 
 namespace dart {
 
+DEFINE_FLAG(bool, ic_range_profiling, true,
+    "Generate special IC stubs collecting range information "
+    "for binary and unary arithmetic operations");
 DEFINE_FLAG(bool, propagate_ic_data, true,
     "Propagate IC data from unoptimized to optimized IC calls.");
 DEFINE_FLAG(bool, two_args_smi_icd, true,
     "Generate special IC stubs for two args Smi operations");
-DEFINE_FLAG(bool, ic_range_profiling, true,
-    "Generate special IC stubs collecting range information "
-    "for binary and unary arithmetic operations");
 DEFINE_FLAG(bool, unbox_numeric_fields, true,
     "Support unboxed double and float32x4 fields.");
 DECLARE_FLAG(bool, eliminate_type_checks);
@@ -3058,6 +3058,29 @@
   return true;
 }
 
+void PolymorphicInstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  ASSERT(ic_data().NumArgsTested() == 1);
+  if (!with_checks()) {
+    ASSERT(ic_data().HasOneTarget());
+    const Function& target = Function::ZoneHandle(ic_data().GetTargetAt(0));
+    compiler->GenerateStaticCall(deopt_id(),
+                                 instance_call()->token_pos(),
+                                 target,
+                                 instance_call()->ArgumentCount(),
+                                 instance_call()->argument_names(),
+                                 locs(),
+                                 ICData::Handle());
+    return;
+  }
+
+  compiler->EmitPolymorphicInstanceCall(ic_data(),
+                                        instance_call()->ArgumentCount(),
+                                        instance_call()->argument_names(),
+                                        deopt_id(),
+                                        instance_call()->token_pos(),
+                                        locs());
+}
+
 
 LocationSummary* StaticCallInstr::MakeLocationSummary(Zone* zone,
                                                       bool optimizing) const {
diff --git a/runtime/vm/intermediate_language_arm.cc b/runtime/vm/intermediate_language_arm.cc
index 34ab638..6538dec 100644
--- a/runtime/vm/intermediate_language_arm.cc
+++ b/runtime/vm/intermediate_language_arm.cc
@@ -1571,6 +1571,8 @@
 
 
 void GuardFieldClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  ASSERT(sizeof(classid_t) == kInt16Size);
+
   const intptr_t value_cid = value()->Type()->ToCid();
   const intptr_t field_cid = field().guarded_cid();
   const intptr_t nullability = field().is_nullable() ? kNullCid : kIllegalCid;
@@ -1612,16 +1614,16 @@
 
     if (value_cid == kDynamicCid) {
       LoadValueCid(compiler, value_cid_reg, value_reg);
-      __ ldr(IP, field_cid_operand);
+      __ ldrh(IP, field_cid_operand);
       __ cmp(value_cid_reg, Operand(IP));
       __ b(&ok, EQ);
-      __ ldr(IP, field_nullability_operand);
+      __ ldrh(IP, field_nullability_operand);
       __ cmp(value_cid_reg, Operand(IP));
     } else if (value_cid == kNullCid) {
-      __ ldr(value_cid_reg, field_nullability_operand);
+      __ ldrh(value_cid_reg, field_nullability_operand);
       __ CompareImmediate(value_cid_reg, value_cid);
     } else {
-      __ ldr(value_cid_reg, field_cid_operand);
+      __ ldrh(value_cid_reg, field_cid_operand);
       __ CompareImmediate(value_cid_reg, value_cid);
     }
     __ b(&ok, EQ);
@@ -1635,17 +1637,17 @@
     if (!field().needs_length_check()) {
       // Uninitialized field can be handled inline. Check if the
       // field is still unitialized.
-      __ ldr(IP, field_cid_operand);
+      __ ldrh(IP, field_cid_operand);
       __ CompareImmediate(IP, kIllegalCid);
       __ b(fail, NE);
 
       if (value_cid == kDynamicCid) {
-        __ str(value_cid_reg, field_cid_operand);
-        __ str(value_cid_reg, field_nullability_operand);
+        __ strh(value_cid_reg, field_cid_operand);
+        __ strh(value_cid_reg, field_nullability_operand);
       } else {
         __ LoadImmediate(IP, value_cid);
-        __ str(IP, field_cid_operand);
-        __ str(IP, field_nullability_operand);
+        __ strh(IP, field_cid_operand);
+        __ strh(IP, field_nullability_operand);
       }
 
       if (deopt == NULL) {
@@ -1658,7 +1660,7 @@
       ASSERT(!compiler->is_optimizing());
       __ Bind(fail);
 
-      __ ldr(IP, FieldAddress(field_reg, Field::guarded_cid_offset()));
+      __ ldrh(IP, FieldAddress(field_reg, Field::guarded_cid_offset()));
       __ CompareImmediate(IP, kDynamicCid);
       __ b(&ok, EQ);
 
@@ -2034,6 +2036,8 @@
 
 
 void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  ASSERT(sizeof(classid_t) == kInt16Size);
+
   Label skip_store;
 
   const Register instance_reg = locs()->in(0).reg();
@@ -2108,7 +2112,7 @@
 
     __ LoadObject(temp, Field::ZoneHandle(field().raw()));
 
-    __ ldr(temp2, FieldAddress(temp, Field::is_nullable_offset()));
+    __ ldrh(temp2, FieldAddress(temp, Field::is_nullable_offset()));
     __ CompareImmediate(temp2, kNullCid);
     __ b(&store_pointer, EQ);
 
@@ -2116,15 +2120,15 @@
     __ tst(temp2, Operand(1 << Field::kUnboxingCandidateBit));
     __ b(&store_pointer, EQ);
 
-    __ ldr(temp2, FieldAddress(temp, Field::guarded_cid_offset()));
+    __ ldrh(temp2, FieldAddress(temp, Field::guarded_cid_offset()));
     __ CompareImmediate(temp2, kDoubleCid);
     __ b(&store_double, EQ);
 
-    __ ldr(temp2, FieldAddress(temp, Field::guarded_cid_offset()));
+    __ ldrh(temp2, FieldAddress(temp, Field::guarded_cid_offset()));
     __ CompareImmediate(temp2, kFloat32x4Cid);
     __ b(&store_float32x4, EQ);
 
-    __ ldr(temp2, FieldAddress(temp, Field::guarded_cid_offset()));
+    __ ldrh(temp2, FieldAddress(temp, Field::guarded_cid_offset()));
     __ CompareImmediate(temp2, kFloat64x2Cid);
     __ b(&store_float64x2, EQ);
 
@@ -2427,6 +2431,8 @@
 
 
 void LoadFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  ASSERT(sizeof(classid_t) == kInt16Size);
+
   const Register instance_reg = locs()->in(0).reg();
   if (IsUnboxedLoad() && compiler->is_optimizing()) {
     const DRegister result = EvenDRegisterOf(locs()->out(0).fpu_reg());
@@ -2473,19 +2479,19 @@
     FieldAddress field_nullability_operand(result_reg,
                                            Field::is_nullable_offset());
 
-    __ ldr(temp, field_nullability_operand);
+    __ ldrh(temp, field_nullability_operand);
     __ CompareImmediate(temp, kNullCid);
     __ b(&load_pointer, EQ);
 
-    __ ldr(temp, field_cid_operand);
+    __ ldrh(temp, field_cid_operand);
     __ CompareImmediate(temp, kDoubleCid);
     __ b(&load_double, EQ);
 
-    __ ldr(temp, field_cid_operand);
+    __ ldrh(temp, field_cid_operand);
     __ CompareImmediate(temp, kFloat32x4Cid);
     __ b(&load_float32x4, EQ);
 
-    __ ldr(temp, field_cid_operand);
+    __ ldrh(temp, field_cid_operand);
     __ CompareImmediate(temp, kFloat64x2Cid);
     __ b(&load_float64x2, EQ);
 
@@ -5857,41 +5863,6 @@
 }
 
 
-void PolymorphicInstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  ASSERT(ic_data().NumArgsTested() == 1);
-  if (!with_checks()) {
-    ASSERT(ic_data().HasOneTarget());
-    const Function& target = Function::ZoneHandle(ic_data().GetTargetAt(0));
-    compiler->GenerateStaticCall(deopt_id(),
-                                 instance_call()->token_pos(),
-                                 target,
-                                 instance_call()->ArgumentCount(),
-                                 instance_call()->argument_names(),
-                                 locs(),
-                                 ICData::Handle());
-    return;
-  }
-
-  // Load receiver into R0.
-  __ LoadFromOffset(kWord, R0, SP,
-                    (instance_call()->ArgumentCount() - 1) * kWordSize);
-
-  Label* deopt = compiler->AddDeoptStub(
-      deopt_id(), ICData::kDeoptPolymorphicInstanceCallTestFail);
-  LoadValueCid(compiler, R2, R0,
-               (ic_data().GetReceiverClassIdAt(0) == kSmiCid) ? NULL : deopt);
-
-  compiler->EmitTestAndCall(ic_data(),
-                            R2,  // Class id register.
-                            instance_call()->ArgumentCount(),
-                            instance_call()->argument_names(),
-                            deopt,
-                            deopt_id(),
-                            instance_call()->token_pos(),
-                            locs());
-}
-
-
 LocationSummary* BranchInstr::MakeLocationSummary(Zone* zone,
                                                   bool opt) const {
   comparison()->InitializeLocationSummary(zone, opt);
diff --git a/runtime/vm/intermediate_language_arm64.cc b/runtime/vm/intermediate_language_arm64.cc
index 38edabd..1f12744 100644
--- a/runtime/vm/intermediate_language_arm64.cc
+++ b/runtime/vm/intermediate_language_arm64.cc
@@ -931,7 +931,8 @@
 void LoadClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   const Register object = locs()->in(0).reg();
   const Register result = locs()->out(0).reg();
-  static const intptr_t kSmiCidSource = kSmiCid << RawObject::kClassIdTagPos;
+  static const intptr_t kSmiCidSource =
+      static_cast<intptr_t>(kSmiCid) << RawObject::kClassIdTagPos;
 
   __ LoadImmediate(TMP, reinterpret_cast<int64_t>(&kSmiCidSource) + 1, PP);
   __ tsti(object, Immediate(kSmiTagMask));
@@ -1434,6 +1435,7 @@
 
 
 void GuardFieldClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  ASSERT(sizeof(classid_t) == kInt32Size);
   const intptr_t value_cid = value()->Type()->ToCid();
   const intptr_t field_cid = field().guarded_cid();
   const intptr_t nullability = field().is_nullable() ? kNullCid : kIllegalCid;
@@ -1470,24 +1472,24 @@
     __ LoadObject(field_reg, Field::ZoneHandle(field().raw()), PP);
 
     FieldAddress field_cid_operand(
-        field_reg, Field::guarded_cid_offset(), kWord);
+        field_reg, Field::guarded_cid_offset(), kUnsignedWord);
     FieldAddress field_nullability_operand(
-        field_reg, Field::is_nullable_offset(), kWord);
+        field_reg, Field::is_nullable_offset(), kUnsignedWord);
 
     if (value_cid == kDynamicCid) {
       LoadValueCid(compiler, value_cid_reg, value_reg);
       Label skip_length_check;
-      __ ldr(TMP, field_cid_operand, kWord);
+      __ ldr(TMP, field_cid_operand, kUnsignedWord);
       __ CompareRegisters(value_cid_reg, TMP);
       __ b(&ok, EQ);
-      __ ldr(TMP, field_nullability_operand, kWord);
+      __ ldr(TMP, field_nullability_operand, kUnsignedWord);
       __ CompareRegisters(value_cid_reg, TMP);
     } else if (value_cid == kNullCid) {
-      __ ldr(value_cid_reg, field_nullability_operand, kWord);
+      __ ldr(value_cid_reg, field_nullability_operand, kUnsignedWord);
       __ CompareImmediate(value_cid_reg, value_cid, PP);
     } else {
       Label skip_length_check;
-      __ ldr(value_cid_reg, field_cid_operand, kWord);
+      __ ldr(value_cid_reg, field_cid_operand, kUnsignedWord);
       __ CompareImmediate(value_cid_reg, value_cid, PP);
     }
     __ b(&ok, EQ);
@@ -1501,17 +1503,17 @@
     if (!field().needs_length_check()) {
       // Uninitialized field can be handled inline. Check if the
       // field is still unitialized.
-      __ ldr(TMP, field_cid_operand, kWord);
+      __ ldr(TMP, field_cid_operand, kUnsignedWord);
       __ CompareImmediate(TMP, kIllegalCid, PP);
       __ b(fail, NE);
 
       if (value_cid == kDynamicCid) {
-        __ str(value_cid_reg, field_cid_operand, kWord);
-        __ str(value_cid_reg, field_nullability_operand, kWord);
+        __ str(value_cid_reg, field_cid_operand, kUnsignedWord);
+        __ str(value_cid_reg, field_nullability_operand, kUnsignedWord);
       } else {
         __ LoadImmediate(TMP, value_cid, PP);
-        __ str(TMP, field_cid_operand, kWord);
-        __ str(TMP, field_nullability_operand, kWord);
+        __ str(TMP, field_cid_operand, kUnsignedWord);
+        __ str(TMP, field_nullability_operand, kUnsignedWord);
       }
 
       if (deopt == NULL) {
@@ -1525,7 +1527,7 @@
       __ Bind(fail);
 
       __ LoadFieldFromOffset(
-          TMP, field_reg, Field::guarded_cid_offset(), PP, kWord);
+          TMP, field_reg, Field::guarded_cid_offset(), PP, kUnsignedWord);
       __ CompareImmediate(TMP, kDynamicCid, PP);
       __ b(&ok, EQ);
 
@@ -1774,6 +1776,7 @@
 
 
 void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  ASSERT(sizeof(classid_t) == kInt32Size);
   Label skip_store;
 
   const Register instance_reg = locs()->in(0).reg();
@@ -1844,7 +1847,8 @@
 
     __ LoadObject(temp, Field::ZoneHandle(field().raw()), PP);
 
-    __ LoadFieldFromOffset(temp2, temp, Field::is_nullable_offset(), PP, kWord);
+    __ LoadFieldFromOffset(temp2, temp, Field::is_nullable_offset(), PP,
+                           kUnsignedWord);
     __ CompareImmediate(temp2, kNullCid, PP);
     __ b(&store_pointer, EQ);
 
@@ -1854,15 +1858,18 @@
     __ tsti(temp2, Immediate(1 << Field::kUnboxingCandidateBit));
     __ b(&store_pointer, EQ);
 
-    __ LoadFieldFromOffset(temp2, temp, Field::guarded_cid_offset(), PP, kWord);
+    __ LoadFieldFromOffset(temp2, temp, Field::guarded_cid_offset(), PP,
+                           kUnsignedWord);
     __ CompareImmediate(temp2, kDoubleCid, PP);
     __ b(&store_double, EQ);
 
-    __ LoadFieldFromOffset(temp2, temp, Field::guarded_cid_offset(), PP, kWord);
+    __ LoadFieldFromOffset(temp2, temp, Field::guarded_cid_offset(), PP,
+                           kUnsignedWord);
     __ CompareImmediate(temp2, kFloat32x4Cid, PP);
     __ b(&store_float32x4, EQ);
 
-    __ LoadFieldFromOffset(temp2, temp, Field::guarded_cid_offset(), PP, kWord);
+    __ LoadFieldFromOffset(temp2, temp, Field::guarded_cid_offset(), PP,
+                           kUnsignedWord);
     __ CompareImmediate(temp2, kFloat64x2Cid, PP);
     __ b(&store_float64x2, EQ);
 
@@ -2161,6 +2168,7 @@
 
 
 void LoadFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  ASSERT(sizeof(classid_t) == kInt32Size);
   const Register instance_reg = locs()->in(0).reg();
   if (IsUnboxedLoad() && compiler->is_optimizing()) {
     const VRegister result = locs()->out(0).fpu_reg();
@@ -2197,23 +2205,23 @@
     __ LoadObject(result_reg, Field::ZoneHandle(field()->raw()), PP);
 
     FieldAddress field_cid_operand(
-        result_reg, Field::guarded_cid_offset(), kWord);
+        result_reg, Field::guarded_cid_offset(), kUnsignedWord);
     FieldAddress field_nullability_operand(
-        result_reg, Field::is_nullable_offset(), kWord);
+        result_reg, Field::is_nullable_offset(), kUnsignedWord);
 
-    __ ldr(temp, field_nullability_operand, kWord);
+    __ ldr(temp, field_nullability_operand, kUnsignedWord);
     __ CompareImmediate(temp, kNullCid, PP);
     __ b(&load_pointer, EQ);
 
-    __ ldr(temp, field_cid_operand, kWord);
+    __ ldr(temp, field_cid_operand, kUnsignedWord);
     __ CompareImmediate(temp, kDoubleCid, PP);
     __ b(&load_double, EQ);
 
-    __ ldr(temp, field_cid_operand, kWord);
+    __ ldr(temp, field_cid_operand, kUnsignedWord);
     __ CompareImmediate(temp, kFloat32x4Cid, PP);
     __ b(&load_float32x4, EQ);
 
-    __ ldr(temp, field_cid_operand, kWord);
+    __ ldr(temp, field_cid_operand, kUnsignedWord);
     __ CompareImmediate(temp, kFloat64x2Cid, PP);
     __ b(&load_float64x2, EQ);
 
@@ -5024,41 +5032,6 @@
 }
 
 
-void PolymorphicInstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  ASSERT(ic_data().NumArgsTested() == 1);
-  if (!with_checks()) {
-    ASSERT(ic_data().HasOneTarget());
-    const Function& target = Function::ZoneHandle(ic_data().GetTargetAt(0));
-    compiler->GenerateStaticCall(deopt_id(),
-                                 instance_call()->token_pos(),
-                                 target,
-                                 instance_call()->ArgumentCount(),
-                                 instance_call()->argument_names(),
-                                 locs(),
-                                 ICData::Handle());
-    return;
-  }
-
-  // Load receiver into R0.
-  __ LoadFromOffset(
-      R0, SP, (instance_call()->ArgumentCount() - 1) * kWordSize, PP);
-
-  Label* deopt = compiler->AddDeoptStub(
-      deopt_id(), ICData::kDeoptPolymorphicInstanceCallTestFail);
-  LoadValueCid(compiler, R2, R0,
-               (ic_data().GetReceiverClassIdAt(0) == kSmiCid) ? NULL : deopt);
-
-  compiler->EmitTestAndCall(ic_data(),
-                            R2,  // Class id register.
-                            instance_call()->ArgumentCount(),
-                            instance_call()->argument_names(),
-                            deopt,
-                            deopt_id(),
-                            instance_call()->token_pos(),
-                            locs());
-}
-
-
 LocationSummary* BranchInstr::MakeLocationSummary(Zone* zone,
                                                   bool opt) const {
   comparison()->InitializeLocationSummary(zone, opt);
diff --git a/runtime/vm/intermediate_language_ia32.cc b/runtime/vm/intermediate_language_ia32.cc
index 06300e6..2865b26 100644
--- a/runtime/vm/intermediate_language_ia32.cc
+++ b/runtime/vm/intermediate_language_ia32.cc
@@ -24,8 +24,8 @@
 
 DECLARE_FLAG(bool, emit_edge_counters);
 DECLARE_FLAG(int, optimization_counter_threshold);
-DECLARE_FLAG(bool, use_osr);
 DECLARE_FLAG(bool, throw_on_javascript_int_overflow);
+DECLARE_FLAG(bool, use_osr);
 
 // Generic summary for call instructions that have all arguments pushed
 // on the stack and return the result in a fixed register EAX.
@@ -1419,6 +1419,7 @@
 
 
 void GuardFieldClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  ASSERT(sizeof(classid_t) == kInt16Size);
   const intptr_t value_cid = value()->Type()->ToCid();
   const intptr_t field_cid = field().guarded_cid();
   const intptr_t nullability = field().is_nullable() ? kNullCid : kIllegalCid;
@@ -1460,17 +1461,17 @@
 
     if (value_cid == kDynamicCid) {
       LoadValueCid(compiler, value_cid_reg, value_reg);
-      __ cmpl(value_cid_reg, field_cid_operand);
+      __ cmpw(value_cid_reg, field_cid_operand);
       __ j(EQUAL, &ok);
-      __ cmpl(value_cid_reg, field_nullability_operand);
+      __ cmpw(value_cid_reg, field_nullability_operand);
     } else if (value_cid == kNullCid) {
       // Value in graph known to be null.
       // Compare with null.
-      __ cmpl(field_nullability_operand, Immediate(value_cid));
+      __ cmpw(field_nullability_operand, Immediate(value_cid));
     } else {
       // Value in graph known to be non-null.
       // Compare class id with guard field class id.
-      __ cmpl(field_cid_operand, Immediate(value_cid));
+      __ cmpw(field_cid_operand, Immediate(value_cid));
     }
     __ j(EQUAL, &ok);
 
@@ -1483,19 +1484,19 @@
     if (!field().needs_length_check()) {
       // Uninitialized field can be handled inline. Check if the
       // field is still unitialized.
-      __ cmpl(field_cid_operand, Immediate(kIllegalCid));
+      __ cmpw(field_cid_operand, Immediate(kIllegalCid));
       // Jump to failure path when guard field has been initialized and
       // the field and value class ids do not not match.
       __ j(NOT_EQUAL, fail);
 
       if (value_cid == kDynamicCid) {
         // Do not know value's class id.
-        __ movl(field_cid_operand, value_cid_reg);
-        __ movl(field_nullability_operand, value_cid_reg);
+        __ movw(field_cid_operand, value_cid_reg);
+        __ movw(field_nullability_operand, value_cid_reg);
       } else {
         ASSERT(field_reg != kNoRegister);
-        __ movl(field_cid_operand, Immediate(value_cid));
-        __ movl(field_nullability_operand, Immediate(value_cid));
+        __ movw(field_cid_operand, Immediate(value_cid));
+        __ movw(field_nullability_operand, Immediate(value_cid));
       }
 
       if (deopt == NULL) {
@@ -1508,7 +1509,7 @@
       ASSERT(!compiler->is_optimizing());
       __ Bind(fail);
 
-      __ cmpl(FieldAddress(field_reg, Field::guarded_cid_offset()),
+      __ cmpw(FieldAddress(field_reg, Field::guarded_cid_offset()),
               Immediate(kDynamicCid));
       __ j(EQUAL, &ok);
 
@@ -1766,6 +1767,7 @@
 
 
 void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  ASSERT(sizeof(classid_t) == kInt16Size);
   Label skip_store;
 
   Register instance_reg = locs()->in(0).reg();
@@ -1839,7 +1841,7 @@
 
     __ LoadObject(temp, Field::ZoneHandle(field().raw()));
 
-    __ cmpl(FieldAddress(temp, Field::is_nullable_offset()),
+    __ cmpw(FieldAddress(temp, Field::is_nullable_offset()),
             Immediate(kNullCid));
     __ j(EQUAL, &store_pointer);
 
@@ -1847,15 +1849,15 @@
     __ testl(temp2, Immediate(1 << Field::kUnboxingCandidateBit));
     __ j(ZERO, &store_pointer);
 
-    __ cmpl(FieldAddress(temp, Field::guarded_cid_offset()),
+    __ cmpw(FieldAddress(temp, Field::guarded_cid_offset()),
             Immediate(kDoubleCid));
     __ j(EQUAL, &store_double);
 
-    __ cmpl(FieldAddress(temp, Field::guarded_cid_offset()),
+    __ cmpw(FieldAddress(temp, Field::guarded_cid_offset()),
             Immediate(kFloat32x4Cid));
     __ j(EQUAL, &store_float32x4);
 
-    __ cmpl(FieldAddress(temp, Field::guarded_cid_offset()),
+    __ cmpw(FieldAddress(temp, Field::guarded_cid_offset()),
             Immediate(kFloat64x2Cid));
     __ j(EQUAL, &store_float64x2);
 
@@ -2168,6 +2170,8 @@
 
 
 void LoadFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  ASSERT(sizeof(classid_t) == kInt16Size);
+
   Register instance_reg = locs()->in(0).reg();
   if (IsUnboxedLoad() && compiler->is_optimizing()) {
     XmmRegister result = locs()->out(0).fpu_reg();
@@ -2210,16 +2214,16 @@
     FieldAddress field_cid_operand(result, Field::guarded_cid_offset());
     FieldAddress field_nullability_operand(result, Field::is_nullable_offset());
 
-    __ cmpl(field_nullability_operand, Immediate(kNullCid));
+    __ cmpw(field_nullability_operand, Immediate(kNullCid));
     __ j(EQUAL, &load_pointer);
 
-    __ cmpl(field_cid_operand, Immediate(kDoubleCid));
+    __ cmpw(field_cid_operand, Immediate(kDoubleCid));
     __ j(EQUAL, &load_double);
 
-    __ cmpl(field_cid_operand, Immediate(kFloat32x4Cid));
+    __ cmpw(field_cid_operand, Immediate(kFloat32x4Cid));
     __ j(EQUAL, &load_float32x4);
 
-    __ cmpl(field_cid_operand, Immediate(kFloat64x2Cid));
+    __ cmpw(field_cid_operand, Immediate(kFloat64x2Cid));
     __ j(EQUAL, &load_float64x2);
 
     // Fall through.
@@ -5686,41 +5690,6 @@
 }
 
 
-void PolymorphicInstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  ASSERT(ic_data().NumArgsTested() == 1);
-  if (!with_checks()) {
-    ASSERT(ic_data().HasOneTarget());
-    const Function& target = Function::ZoneHandle(ic_data().GetTargetAt(0));
-    compiler->GenerateStaticCall(deopt_id(),
-                                 instance_call()->token_pos(),
-                                 target,
-                                 instance_call()->ArgumentCount(),
-                                 instance_call()->argument_names(),
-                                 locs(),
-                                 ICData::Handle());
-    return;
-  }
-
-  // Load receiver into EAX.
-  __ movl(EAX,
-      Address(ESP, (instance_call()->ArgumentCount() - 1) * kWordSize));
-
-  Label* deopt = compiler->AddDeoptStub(
-      deopt_id(), ICData::kDeoptPolymorphicInstanceCallTestFail);
-  LoadValueCid(compiler, EDI, EAX,
-               (ic_data().GetReceiverClassIdAt(0) == kSmiCid) ? NULL : deopt);
-
-  compiler->EmitTestAndCall(ic_data(),
-                            EDI,  // Class id register.
-                            instance_call()->ArgumentCount(),
-                            instance_call()->argument_names(),
-                            deopt,
-                            deopt_id(),
-                            instance_call()->token_pos(),
-                            locs());
-}
-
-
 LocationSummary* BranchInstr::MakeLocationSummary(Zone* zone,
                                                   bool opt) const {
   comparison()->InitializeLocationSummary(zone, opt);
diff --git a/runtime/vm/intermediate_language_mips.cc b/runtime/vm/intermediate_language_mips.cc
index b26ab16..07a8242 100644
--- a/runtime/vm/intermediate_language_mips.cc
+++ b/runtime/vm/intermediate_language_mips.cc
@@ -1606,6 +1606,7 @@
 
 
 void GuardFieldClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  ASSERT(sizeof(classid_t) == kInt16Size);
   __ Comment("GuardFieldClassInstr");
 
   const intptr_t value_cid = value()->Type()->ToCid();
@@ -1650,16 +1651,16 @@
     if (value_cid == kDynamicCid) {
       LoadValueCid(compiler, value_cid_reg, value_reg);
 
-      __ lw(CMPRES1, field_cid_operand);
+      __ lhu(CMPRES1, field_cid_operand);
       __ beq(value_cid_reg, CMPRES1, &ok);
-      __ lw(TMP, field_nullability_operand);
+      __ lhu(TMP, field_nullability_operand);
       __ subu(CMPRES1, value_cid_reg, TMP);
     } else if (value_cid == kNullCid) {
-      __ lw(TMP, field_nullability_operand);
+      __ lhu(TMP, field_nullability_operand);
       __ LoadImmediate(CMPRES1, value_cid);
       __ subu(CMPRES1, TMP, CMPRES1);
     } else {
-      __ lw(TMP, field_cid_operand);
+      __ lhu(TMP, field_cid_operand);
       __ LoadImmediate(CMPRES1, value_cid);
       __ subu(CMPRES1, TMP, CMPRES1);
     }
@@ -1674,16 +1675,16 @@
     if (!field().needs_length_check()) {
       // Uninitialized field can be handled inline. Check if the
       // field is still unitialized.
-      __ lw(CMPRES1, field_cid_operand);
+      __ lhu(CMPRES1, field_cid_operand);
       __ BranchNotEqual(CMPRES1, Immediate(kIllegalCid), fail);
 
       if (value_cid == kDynamicCid) {
-        __ sw(value_cid_reg, field_cid_operand);
-        __ sw(value_cid_reg, field_nullability_operand);
+        __ sh(value_cid_reg, field_cid_operand);
+        __ sh(value_cid_reg, field_nullability_operand);
       } else {
         __ LoadImmediate(TMP, value_cid);
-        __ sw(TMP, field_cid_operand);
-        __ sw(TMP, field_nullability_operand);
+        __ sh(TMP, field_cid_operand);
+        __ sh(TMP, field_nullability_operand);
       }
 
       if (deopt == NULL) {
@@ -1696,7 +1697,7 @@
       ASSERT(!compiler->is_optimizing());
       __ Bind(fail);
 
-      __ lw(CMPRES1, FieldAddress(field_reg, Field::guarded_cid_offset()));
+      __ lhu(CMPRES1, FieldAddress(field_reg, Field::guarded_cid_offset()));
       __ BranchEqual(CMPRES1, Immediate(kDynamicCid), &ok);
 
       __ addiu(SP, SP, Immediate(-2 * kWordSize));
@@ -1947,6 +1948,7 @@
 
 
 void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  ASSERT(sizeof(classid_t) == kInt16Size);
   Label skip_store;
 
   Register instance_reg = locs()->in(0).reg();
@@ -2000,14 +2002,14 @@
 
     __ LoadObject(temp, Field::ZoneHandle(field().raw()));
 
-    __ lw(temp2, FieldAddress(temp, Field::is_nullable_offset()));
+    __ lhu(temp2, FieldAddress(temp, Field::is_nullable_offset()));
     __ BranchEqual(temp2, Immediate(kNullCid), &store_pointer);
 
     __ lbu(temp2, FieldAddress(temp, Field::kind_bits_offset()));
     __ andi(CMPRES1, temp2, Immediate(1 << Field::kUnboxingCandidateBit));
     __ beq(CMPRES1, ZR, &store_pointer);
 
-    __ lw(temp2, FieldAddress(temp, Field::guarded_cid_offset()));
+    __ lhu(temp2, FieldAddress(temp, Field::guarded_cid_offset()));
     __ BranchEqual(temp2, Immediate(kDoubleCid), &store_double);
 
     // Fall through.
@@ -2285,6 +2287,8 @@
 
 
 void LoadFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  ASSERT(sizeof(classid_t) == kInt16Size);
+
   Register instance_reg = locs()->in(0).reg();
   if (IsUnboxedLoad() && compiler->is_optimizing()) {
     DRegister result = locs()->out(0).fpu_reg();
@@ -2317,10 +2321,10 @@
     FieldAddress field_nullability_operand(result_reg,
                                            Field::is_nullable_offset());
 
-    __ lw(temp, field_nullability_operand);
+    __ lhu(temp, field_nullability_operand);
     __ BranchEqual(temp, Immediate(kNullCid), &load_pointer);
 
-    __ lw(temp, field_cid_operand);
+    __ lhu(temp, field_cid_operand);
     __ BranchEqual(temp, Immediate(kDoubleCid), &load_double);
 
     // Fall through.
@@ -4582,41 +4586,6 @@
 }
 
 
-void PolymorphicInstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  __ Comment("PolymorphicInstanceCallInstr");
-  ASSERT(ic_data().NumArgsTested() == 1);
-  if (!with_checks()) {
-    ASSERT(ic_data().HasOneTarget());
-    const Function& target = Function::ZoneHandle(ic_data().GetTargetAt(0));
-    compiler->GenerateStaticCall(deopt_id(),
-                                 instance_call()->token_pos(),
-                                 target,
-                                 instance_call()->ArgumentCount(),
-                                 instance_call()->argument_names(),
-                                 locs(),
-                                 ICData::Handle());
-    return;
-  }
-
-  // Load receiver into T0.
-  __ LoadFromOffset(T0, SP, (instance_call()->ArgumentCount() - 1) * kWordSize);
-
-  Label* deopt = compiler->AddDeoptStub(
-      deopt_id(), ICData::kDeoptPolymorphicInstanceCallTestFail);
-  LoadValueCid(compiler, T2, T0,
-               (ic_data().GetReceiverClassIdAt(0) == kSmiCid) ? NULL : deopt);
-
-  compiler->EmitTestAndCall(ic_data(),
-                            T2,  // Class id register.
-                            instance_call()->ArgumentCount(),
-                            instance_call()->argument_names(),
-                            deopt,
-                            deopt_id(),
-                            instance_call()->token_pos(),
-                            locs());
-}
-
-
 LocationSummary* BranchInstr::MakeLocationSummary(Zone* zone,
                                                   bool opt) const {
   comparison()->InitializeLocationSummary(zone, opt);
diff --git a/runtime/vm/intermediate_language_x64.cc b/runtime/vm/intermediate_language_x64.cc
index 9474ebd..ec0bbc7 100644
--- a/runtime/vm/intermediate_language_x64.cc
+++ b/runtime/vm/intermediate_language_x64.cc
@@ -1438,6 +1438,7 @@
 
 
 void GuardFieldClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  ASSERT(sizeof(classid_t) == kInt32Size);
   const intptr_t value_cid = value()->Type()->ToCid();
   const intptr_t field_cid = field().guarded_cid();
   const intptr_t nullability = field().is_nullable() ? kNullCid : kIllegalCid;
@@ -1770,6 +1771,7 @@
 
 
 void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  ASSERT(sizeof(classid_t) == kInt32Size);
   Label skip_store;
 
   Register instance_reg = locs()->in(0).reg();
@@ -2164,6 +2166,7 @@
 
 
 void LoadFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  ASSERT(sizeof(classid_t) == kInt32Size);
   Register instance_reg = locs()->in(0).reg();
   if (IsUnboxedLoad() && compiler->is_optimizing()) {
     XmmRegister result = locs()->out(0).fpu_reg();
@@ -5438,41 +5441,6 @@
 }
 
 
-void PolymorphicInstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  ASSERT(ic_data().NumArgsTested() == 1);
-  if (!with_checks()) {
-    ASSERT(ic_data().HasOneTarget());
-    const Function& target = Function::ZoneHandle(ic_data().GetTargetAt(0));
-    compiler->GenerateStaticCall(deopt_id(),
-                                 instance_call()->token_pos(),
-                                 target,
-                                 instance_call()->ArgumentCount(),
-                                 instance_call()->argument_names(),
-                                 locs(),
-                                 ICData::Handle());
-    return;
-  }
-
-  // Load receiver into RAX.
-  __ movq(RAX,
-      Address(RSP, (instance_call()->ArgumentCount() - 1) * kWordSize));
-
-  Label* deopt = compiler->AddDeoptStub(
-      deopt_id(), ICData::kDeoptPolymorphicInstanceCallTestFail);
-  LoadValueCid(compiler, RDI, RAX,
-               (ic_data().GetReceiverClassIdAt(0) == kSmiCid) ? NULL : deopt);
-
-  compiler->EmitTestAndCall(ic_data(),
-                            RDI,  // Class id register.
-                            instance_call()->ArgumentCount(),
-                            instance_call()->argument_names(),
-                            deopt,
-                            deopt_id(),
-                            instance_call()->token_pos(),
-                            locs());
-}
-
-
 LocationSummary* BranchInstr::MakeLocationSummary(Zone* zone,
                                                   bool opt) const {
   comparison()->InitializeLocationSummary(zone, opt);
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index 2432df9..195623b 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -31,10 +31,12 @@
 #include "vm/service_isolate.h"
 #include "vm/simulator.h"
 #include "vm/stack_frame.h"
+#include "vm/store_buffer.h"
 #include "vm/stub_code.h"
 #include "vm/symbols.h"
 #include "vm/tags.h"
 #include "vm/thread_interrupter.h"
+#include "vm/timeline.h"
 #include "vm/timer.h"
 #include "vm/visitor.h"
 
@@ -54,6 +56,10 @@
             "Log isolates whose name include the filter. "
             "Default: service isolate log messages are suppressed.");
 
+DEFINE_FLAG(charp, timeline_trace_dir, NULL,
+            "Enable all timeline trace streams and output traces "
+            "into specified directory.");
+
 // TODO(iposva): Make these isolate specific flags inaccessible using the
 // regular FLAG_xyz pattern.
 // These flags are per-isolate and only influence the defaults.
@@ -368,6 +374,8 @@
 bool IsolateMessageHandler::HandleMessage(Message* message) {
   StackZone zone(I);
   HandleScope handle_scope(I);
+  TimelineDurationScope tds(I, I->GetIsolateStream(), "HandleMessage");
+
   // TODO(turnidge): Rework collection total dart execution.  This can
   // overcount when other things (gc, compilation) are active.
   TIMERSCOPE(isolate_, time_dart_execution);
@@ -596,6 +604,11 @@
 void BaseIsolate::AssertCurrent(BaseIsolate* isolate) {
   ASSERT(isolate == Isolate::Current());
 }
+
+void BaseIsolate::AssertCurrentThreadIsMutator() const {
+  ASSERT(Isolate::Current() == this);
+  ASSERT(Isolate::Current()->mutator_thread() == Thread::Current());
+}
 #endif  // defined(DEBUG)
 
 #if defined(DEBUG)
@@ -611,7 +624,7 @@
 Isolate::Isolate(const Dart_IsolateFlags& api_flags)
   :   mutator_thread_(NULL),
       vm_tag_(0),
-      store_buffer_(),
+      store_buffer_(new StoreBuffer()),
       message_notify_callback_(NULL),
       name_(NULL),
       debugger_name_(NULL),
@@ -662,6 +675,7 @@
       last_allocationprofile_gc_timestamp_(0),
       object_id_ring_(NULL),
       trace_buffer_(NULL),
+      timeline_event_recorder_(NULL),
       profiler_data_(NULL),
       thread_state_(NULL),
       tag_table_(GrowableObjectArray::null()),
@@ -686,6 +700,7 @@
 Isolate::~Isolate() {
   free(name_);
   free(debugger_name_);
+  delete store_buffer_;
   delete heap_;
   delete object_store_;
   delete api_state_;
@@ -710,6 +725,7 @@
     delete compiler_stats_;
     compiler_stats_ = NULL;
   }
+  RemoveTimelineEventRecorder();
 }
 
 
@@ -739,6 +755,15 @@
   ISOLATE_METRIC_LIST(ISOLATE_METRIC_INIT);
 #undef ISOLATE_METRIC_INIT
 
+  const bool force_streams = FLAG_timeline_trace_dir != NULL;
+
+  // Initialize Timeline streams.
+#define ISOLATE_TIMELINE_STREAM_INIT(name, enabled_by_default)                 \
+  result->stream_##name##_.Init(#name, force_streams || enabled_by_default);
+  ISOLATE_TIMELINE_STREAM_LIST(ISOLATE_TIMELINE_STREAM_INIT);
+#undef ISOLATE_TIMELINE_STREAM_INIT
+
+
   // TODO(5411455): For now just set the recently created isolate as
   // the current isolate.
   Thread::EnterIsolate(result);
@@ -963,6 +988,13 @@
     ASSERT(this == state->isolate());
     Run();
   }
+  TimelineStream* stream = GetIsolateStream();
+  ASSERT(stream != NULL);
+  TimelineEvent* event = stream->StartEvent();
+  if (event != NULL) {
+    event->Instant("Runnable");
+    event->Complete();
+  }
   return true;
 }
 
@@ -1452,6 +1484,11 @@
       OS::Print("[-] Stopping isolate:\n"
                 "\tisolate:    %s\n", name());
     }
+
+    if ((timeline_event_recorder_ != NULL) &&
+        (FLAG_timeline_trace_dir != NULL)) {
+      timeline_event_recorder_->WriteTo(FLAG_timeline_trace_dir);
+    }
   }
 
   // TODO(5411455): For now just make sure there are no current isolates
@@ -1550,6 +1587,21 @@
 }
 
 
+void Isolate::SetTimelineEventRecorder(
+    TimelineEventRecorder* timeline_event_recorder) {
+#define ISOLATE_TIMELINE_STREAM_SET_BUFFER(name, enabled_by_default)           \
+  stream_##name##_.set_recorder(timeline_event_recorder);
+  ISOLATE_TIMELINE_STREAM_LIST(ISOLATE_TIMELINE_STREAM_SET_BUFFER)
+#undef ISOLATE_TIMELINE_STREAM_SET_BUFFER
+  timeline_event_recorder_ = timeline_event_recorder;
+}
+
+void Isolate::RemoveTimelineEventRecorder() {
+  SetTimelineEventRecorder(NULL);
+  delete timeline_event_recorder_;
+}
+
+
 void Isolate::PrintJSON(JSONStream* stream, bool ref) {
   JSONObject jsobj(stream);
   jsobj.AddProperty("type", (ref ? "@Isolate" : "Isolate"));
@@ -1636,6 +1688,11 @@
     JSONArray breakpoints(&jsobj, "breakpoints");
     debugger()->PrintBreakpointsToJSONArray(&breakpoints);
   }
+
+  {
+    JSONObject jssettings(&jsobj, "_debuggerSettings");
+    debugger()->PrintSettingsToJSONObject(&jssettings);
+  }
 }
 
 
diff --git a/runtime/vm/isolate.h b/runtime/vm/isolate.h
index a3758a2..2b1256f 100644
--- a/runtime/vm/isolate.h
+++ b/runtime/vm/isolate.h
@@ -14,12 +14,12 @@
 #include "vm/megamorphic_cache_table.h"
 #include "vm/metrics.h"
 #include "vm/random.h"
-#include "vm/store_buffer.h"
 #include "vm/tags.h"
 #include "vm/thread.h"
 #include "vm/os_thread.h"
-#include "vm/trace_buffer.h"
+#include "vm/timeline.h"
 #include "vm/timer.h"
+#include "vm/trace_buffer.h"
 
 namespace dart {
 
@@ -76,6 +76,7 @@
 class Simulator;
 class StackResource;
 class StackZone;
+class StoreBuffer;
 class StubCode;
 class TypeArguments;
 class TypeParameter;
@@ -141,10 +142,7 @@
                                   bool visit_prologue_weak_persistent_handles);
   void VisitPrologueWeakPersistentHandles(HandleVisitor* visitor);
 
-  StoreBuffer* store_buffer() { return &store_buffer_; }
-  static intptr_t store_buffer_offset() {
-    return OFFSET_OF(Isolate, store_buffer_);
-  }
+  StoreBuffer* store_buffer() { return store_buffer_; }
 
   ClassTable* class_table() { return &class_table_; }
   static intptr_t class_table_offset() {
@@ -369,7 +367,10 @@
 
   Mutex* mutex() const { return mutex_; }
 
-  Debugger* debugger() const { return debugger_; }
+  Debugger* debugger() const {
+    ASSERT(debugger_ != NULL);
+    return debugger_;
+  }
 
   void set_single_step(bool value) { single_step_ = value; }
   bool single_step() const { return single_step_; }
@@ -555,6 +556,14 @@
     return trace_buffer_;
   }
 
+  void SetTimelineEventRecorder(TimelineEventRecorder* timeline_event_recorder);
+
+  TimelineEventRecorder* timeline_event_recorder() const {
+    return timeline_event_recorder_;
+  }
+
+  void RemoveTimelineEventRecorder();
+
   DeoptContext* deopt_context() const { return deopt_context_; }
   void set_deopt_context(DeoptContext* value) {
     ASSERT(value == NULL || deopt_context_ == NULL);
@@ -654,6 +663,11 @@
   ISOLATE_METRIC_LIST(ISOLATE_METRIC_ACCESSOR);
 #undef ISOLATE_METRIC_ACCESSOR
 
+#define ISOLATE_TIMELINE_STREAM_ACCESSOR(name, enabled_by_default)             \
+  TimelineStream* Get##name##Stream() { return &stream_##name##_; }
+  ISOLATE_TIMELINE_STREAM_LIST(ISOLATE_TIMELINE_STREAM_ACCESSOR)
+#undef ISOLATE_TIMELINE_STREAM_ACCESSOR
+
   static intptr_t IsolateListLength();
 
   RawGrowableObjectArray* tag_table() const { return tag_table_; }
@@ -725,7 +739,7 @@
 
   Thread* mutator_thread_;
   uword vm_tag_;
-  StoreBuffer store_buffer_;
+  StoreBuffer* store_buffer_;
   ClassTable class_table_;
   MegamorphicCacheTable megamorphic_cache_table_;
   Dart_MessageNotifyCallback message_notify_callback_;
@@ -790,6 +804,9 @@
   // Trace buffer support.
   TraceBuffer* trace_buffer_;
 
+  // TimelineEvent buffer.
+  TimelineEventRecorder* timeline_event_recorder_;
+
   IsolateProfilerData* profiler_data_;
   Mutex profiler_data_mutex_;
   InterruptableThreadState* thread_state_;
@@ -832,6 +849,11 @@
   ISOLATE_METRIC_LIST(ISOLATE_METRIC_VARIABLE);
 #undef ISOLATE_METRIC_VARIABLE
 
+#define ISOLATE_TIMELINE_STREAM_VARIABLE(name, enabled_by_default)             \
+  TimelineStream stream_##name##_;
+  ISOLATE_TIMELINE_STREAM_LIST(ISOLATE_TIMELINE_STREAM_VARIABLE)
+#undef ISOLATE_TIMELINE_STREAM_VARIABLE
+
   VMHandles reusable_handles_;
 
   static Dart_IsolateCreateCallback create_callback_;
diff --git a/runtime/vm/json_stream.cc b/runtime/vm/json_stream.cc
index 71d30a9..e716e50 100644
--- a/runtime/vm/json_stream.cc
+++ b/runtime/vm/json_stream.cc
@@ -12,6 +12,7 @@
 #include "vm/object.h"
 #include "vm/service_event.h"
 #include "vm/service.h"
+#include "vm/timeline.h"
 #include "vm/unicode.h"
 
 
@@ -277,6 +278,42 @@
 }
 
 
+static const char base64_digits[65] =
+  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+static const char base64_pad = '=';
+
+
+void JSONStream::PrintValueBase64(const uint8_t* bytes, intptr_t length) {
+  PrintCommaIfNeeded();
+  buffer_.AddChar('"');
+
+  intptr_t odd_bits = length % 3;
+  intptr_t even_bits = length - odd_bits;
+  for (intptr_t i = 0; i < even_bits; i += 3) {
+    intptr_t triplet = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2];
+    buffer_.AddChar(base64_digits[triplet >> 18]);
+    buffer_.AddChar(base64_digits[(triplet >> 12) & 63]);
+    buffer_.AddChar(base64_digits[(triplet >> 6) & 63]);
+    buffer_.AddChar(base64_digits[triplet & 63]);
+  }
+  if (odd_bits == 1) {
+    intptr_t triplet = bytes[even_bits] << 16;
+    buffer_.AddChar(base64_digits[triplet >> 18]);
+    buffer_.AddChar(base64_digits[(triplet >> 12) & 63]);
+    buffer_.AddChar(base64_pad);
+    buffer_.AddChar(base64_pad);
+  } else if (odd_bits == 2) {
+    intptr_t triplet = (bytes[even_bits] << 16) | (bytes[even_bits + 1] << 8);
+    buffer_.AddChar(base64_digits[triplet >> 18]);
+    buffer_.AddChar(base64_digits[(triplet >> 12) & 63]);
+    buffer_.AddChar(base64_digits[(triplet >> 6) & 63]);
+    buffer_.AddChar(base64_pad);
+  }
+
+  buffer_.AddChar('"');
+}
+
+
 void JSONStream::PrintValue(const char* s) {
   PrintCommaIfNeeded();
   buffer_.AddChar('"');
@@ -355,6 +392,12 @@
 }
 
 
+void JSONStream::PrintValue(TimelineEvent* timeline_event) {
+  PrintCommaIfNeeded();
+  timeline_event->PrintJSON(this);
+}
+
+
 void JSONStream::PrintServiceId(const Object& o) {
   ASSERT(id_zone_ != NULL);
   PrintProperty("id", id_zone_->GetServiceId(o));
@@ -393,6 +436,14 @@
 }
 
 
+void JSONStream::PrintPropertyBase64(const char* name,
+                                     const uint8_t* b,
+                                     intptr_t len) {
+  PrintPropertyName(name);
+  PrintValueBase64(b, len);
+}
+
+
 bool JSONStream::PrintPropertyStr(const char* name,
                                   const String& s,
                                   intptr_t limit) {
@@ -437,6 +488,13 @@
 }
 
 
+void JSONStream::PrintProperty(const char* name,
+                               TimelineEvent* timeline_event) {
+  PrintPropertyName(name);
+  PrintValue(timeline_event);
+}
+
+
 void JSONStream::PrintfProperty(const char* name, const char* format, ...) {
   PrintPropertyName(name);
   va_list args;
diff --git a/runtime/vm/json_stream.h b/runtime/vm/json_stream.h
index 4a06178..4ada4e7 100644
--- a/runtime/vm/json_stream.h
+++ b/runtime/vm/json_stream.h
@@ -10,9 +10,11 @@
 #include "vm/allocation.h"
 #include "vm/service.h"
 
+
 namespace dart {
 
 class Array;
+class Breakpoint;
 class Field;
 class GrowableObjectArray;
 class Instance;
@@ -23,8 +25,8 @@
 class Object;
 class Script;
 class ServiceEvent;
-class Breakpoint;
 class String;
+class TimelineEvent;
 class Zone;
 
 
@@ -116,6 +118,7 @@
   void PrintValue(intptr_t i);
   void PrintValue64(int64_t i);
   void PrintValue(double d);
+  void PrintValueBase64(const uint8_t* bytes, intptr_t length);
   void PrintValue(const char* s);
   void PrintValue(const char* s, intptr_t len);
   void PrintValueNoEscape(const char* s);
@@ -127,12 +130,16 @@
   void PrintValue(MessageQueue* queue);
   void PrintValue(Isolate* isolate, bool ref = true);
   bool PrintValueStr(const String& s, intptr_t limit);
+  void PrintValue(TimelineEvent* timeline_event);
 
   void PrintServiceId(const Object& o);
   void PrintPropertyBool(const char* name, bool b);
   void PrintProperty(const char* name, intptr_t i);
   void PrintProperty64(const char* name, int64_t i);
   void PrintProperty(const char* name, double d);
+  void PrintPropertyBase64(const char* name,
+                           const uint8_t* bytes,
+                           intptr_t length);
   void PrintProperty(const char* name, const char* s);
   bool PrintPropertyStr(const char* name, const String& s, intptr_t limit);
   void PrintPropertyNoEscape(const char* name, const char* s);
@@ -145,6 +152,7 @@
   void PrintProperty(const char* name, Metric* metric);
   void PrintProperty(const char* name, MessageQueue* queue);
   void PrintProperty(const char* name, Isolate* isolate);
+  void PrintProperty(const char* name, TimelineEvent* timeline_event);
   void PrintPropertyName(const char* name);
   void PrintCommaIfNeeded();
   bool NeedComma();
@@ -209,6 +217,11 @@
   void AddProperty(const char* name, double d) const {
     stream_->PrintProperty(name, d);
   }
+  void AddPropertyBase64(const char* name,
+                         const uint8_t* bytes,
+                         intptr_t length) const {
+    stream_->PrintPropertyBase64(name, bytes, length);
+  }
   void AddProperty(const char* name, const char* s) const {
     stream_->PrintProperty(name, s);
   }
@@ -238,6 +251,9 @@
   void AddProperty(const char* name, Isolate* isolate) const {
     stream_->PrintProperty(name, isolate);
   }
+  void AddProperty(const char* name, TimelineEvent* timeline_event) const {
+    stream_->PrintProperty(name, timeline_event);
+  }
   void AddPropertyF(const char* name, const char* format, ...) const
       PRINTF_ATTRIBUTE(3, 4);
 
@@ -289,6 +305,9 @@
   void AddValue(MessageQueue* queue) const {
     stream_->PrintValue(queue);
   }
+  void AddValue(TimelineEvent* timeline_event) const {
+    stream_->PrintValue(timeline_event);
+  }
   void AddValueF(const char* format, ...) const PRINTF_ATTRIBUTE(2, 3);
 
  private:
diff --git a/runtime/vm/log_test.cc b/runtime/vm/log_test.cc
index eaaa7ad..370fefc 100644
--- a/runtime/vm/log_test.cc
+++ b/runtime/vm/log_test.cc
@@ -4,7 +4,7 @@
 
 #include "platform/globals.h"
 
-#include "include/dart_debugger_api.h"
+#include "include/dart_tools_api.h"
 #include "vm/dart_api_impl.h"
 #include "vm/dart_entry.h"
 #include "vm/debugger.h"
diff --git a/runtime/vm/mirrors_api_impl.cc b/runtime/vm/mirrors_api_impl.cc
index e5e667c..d775e22 100644
--- a/runtime/vm/mirrors_api_impl.cc
+++ b/runtime/vm/mirrors_api_impl.cc
@@ -158,7 +158,7 @@
       func = cls.LookupFunctionAllowPrivate(tmp_name);
     }
 
-    // Case 3.  Lookup the funciton with the getter prefix prepended.
+    // Case 3.  Lookup the function with the getter prefix prepended.
     if (func.IsNull()) {
       tmp_name = Field::GetterName(func_name);
       func = cls.LookupFunctionAllowPrivate(tmp_name);
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index d95d307..4274060 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -34,6 +34,7 @@
 #include "vm/intrinsifier.h"
 #include "vm/object_store.h"
 #include "vm/parser.h"
+#include "vm/profiler.h"
 #include "vm/report.h"
 #include "vm/reusable_handles.h"
 #include "vm/runtime_entry.h"
@@ -94,6 +95,7 @@
 TypeArguments* Object::null_type_arguments_ = NULL;
 Array* Object::empty_array_ = NULL;
 Array* Object::zero_array_ = NULL;
+ObjectPool* Object::empty_object_pool_ = NULL;
 PcDescriptors* Object::empty_descriptors_ = NULL;
 LocalVarDescriptors* Object::empty_var_descriptors_ = NULL;
 ExceptionHandlers* Object::empty_exception_handlers_ = NULL;
@@ -132,6 +134,7 @@
 RawClass* Object::namespace_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
 RawClass* Object::code_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
 RawClass* Object::instructions_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
+RawClass* Object::object_pool_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
 RawClass* Object::pc_descriptors_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
 RawClass* Object::stackmap_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
 RawClass* Object::var_descriptors_class_ =
@@ -378,12 +381,31 @@
 }
 
 
-void Object::InitOnce(Isolate* isolate) {
+void Object::InitNull(Isolate* isolate) {
   // Should only be run by the vm isolate.
   ASSERT(isolate == Dart::vm_isolate());
 
   // TODO(iposva): NoSafepointScope needs to be added here.
   ASSERT(class_class() == null_);
+
+  Heap* heap = isolate->heap();
+
+  // Allocate and initialize the null instance.
+  // 'null_' must be the first object allocated as it is used in allocation to
+  // clear the object.
+  {
+    uword address = heap->Allocate(Instance::InstanceSize(), Heap::kOld);
+    null_ = reinterpret_cast<RawInstance*>(address + kHeapObjectTag);
+    // The call below is using 'null_' to initialize itself.
+    InitializeObject(address, kNullCid, Instance::InstanceSize());
+  }
+}
+
+
+void Object::InitOnce(Isolate* isolate) {
+  // Should only be run by the vm isolate.
+  ASSERT(isolate == Dart::vm_isolate());
+
   // Initialize the static vtable values.
   {
     Object fake_object;
@@ -402,6 +424,7 @@
   null_type_arguments_ = TypeArguments::ReadOnlyHandle();
   empty_array_ = Array::ReadOnlyHandle();
   zero_array_ = Array::ReadOnlyHandle();
+  empty_object_pool_ = ObjectPool::ReadOnlyHandle();
   empty_descriptors_ = PcDescriptors::ReadOnlyHandle();
   empty_var_descriptors_ = LocalVarDescriptors::ReadOnlyHandle();
   empty_exception_handlers_ = ExceptionHandlers::ReadOnlyHandle();
@@ -418,17 +441,6 @@
   branch_offset_error_ = LanguageError::ReadOnlyHandle();
   vm_isolate_snapshot_object_table_ = Array::ReadOnlyHandle();
 
-
-  // Allocate and initialize the null instance.
-  // 'null_' must be the first object allocated as it is used in allocation to
-  // clear the object.
-  {
-    uword address = heap->Allocate(Instance::InstanceSize(), Heap::kOld);
-    null_ = reinterpret_cast<RawInstance*>(address + kHeapObjectTag);
-    // The call below is using 'null_' to initialize itself.
-    InitializeObject(address, kNullCid, Instance::InstanceSize());
-  }
-
   *null_object_ = Object::null();
   *null_array_ = Array::null();
   *null_string_ = String::null();
@@ -543,6 +555,9 @@
   cls = Class::New<Instructions>();
   instructions_class_ = cls.raw();
 
+  cls = Class::New<ObjectPool>();
+  object_pool_class_ = cls.raw();
+
   cls = Class::New<PcDescriptors>();
   pc_descriptors_class_ = cls.raw();
 
@@ -635,6 +650,20 @@
     zero_array_->SetAt(0, smi);
   }
 
+  // Allocate and initialize the canonical empty object pool object.
+  {
+    uword address =
+        heap->Allocate(ObjectPool::InstanceSize(0), Heap::kOld);
+    InitializeObject(address,
+                     kObjectPoolCid,
+                     ObjectPool::InstanceSize(0));
+    ObjectPool::initializeHandle(
+        empty_object_pool_,
+        reinterpret_cast<RawObjectPool*>(address + kHeapObjectTag));
+    empty_object_pool_->StoreNonPointer(
+        &empty_object_pool_->raw_ptr()->length_, 0);
+  }
+
   // Allocate and initialize the empty_descriptors instance.
   {
     uword address = heap->Allocate(PcDescriptors::InstanceSize(0), Heap::kOld);
@@ -821,6 +850,7 @@
   SET_CLASS_NAME(namespace, Namespace);
   SET_CLASS_NAME(code, Code);
   SET_CLASS_NAME(instructions, Instructions);
+  SET_CLASS_NAME(object_pool, ObjectPool);
   SET_CLASS_NAME(pc_descriptors, PcDescriptors);
   SET_CLASS_NAME(stackmap, Stackmap);
   SET_CLASS_NAME(var_descriptors, LocalVarDescriptors);
@@ -1702,10 +1732,15 @@
     Exceptions::Throw(thread, exception);
     UNREACHABLE();
   }
+  ClassTable* class_table = isolate->class_table();
   if (space == Heap::kNew) {
-    isolate->class_table()->UpdateAllocatedNew(cls_id, size);
+    class_table->UpdateAllocatedNew(cls_id, size);
   } else {
-    isolate->class_table()->UpdateAllocatedOld(cls_id, size);
+    class_table->UpdateAllocatedOld(cls_id, size);
+  }
+  const Class& cls = Class::Handle(class_table->At(cls_id));
+  if (cls.trace_allocation()) {
+    Profiler::RecordAllocation(isolate, cls_id);
   }
   NoSafepointScope no_safepoint;
   InitializeObject(address, cls_id, size);
@@ -1717,8 +1752,8 @@
 
 class StoreBufferUpdateVisitor : public ObjectPointerVisitor {
  public:
-  explicit StoreBufferUpdateVisitor(Isolate* isolate, RawObject* obj) :
-      ObjectPointerVisitor(isolate), old_obj_(obj) {
+  explicit StoreBufferUpdateVisitor(Thread* thread, RawObject* obj) :
+      ObjectPointerVisitor(thread->isolate()), thread_(thread), old_obj_(obj) {
     ASSERT(old_obj_->IsOldObject());
   }
 
@@ -1727,7 +1762,7 @@
       RawObject* raw_obj = *curr;
       if (raw_obj->IsHeapObject() && raw_obj->IsNewObject()) {
         old_obj_->SetRememberedBit();
-        isolate()->store_buffer()->AddObject(old_obj_);
+        thread_->StoreBufferAddObject(old_obj_);
         // Remembered this object. There is no need to continue searching.
         return;
       }
@@ -1735,6 +1770,7 @@
   }
 
  private:
+  Thread* thread_;
   RawObject* old_obj_;
 
   DISALLOW_COPY_AND_ASSIGN(StoreBufferUpdateVisitor);
@@ -1776,7 +1812,7 @@
     // Old original doesn't need to be remembered, so neither does the clone.
     return raw_clone;
   }
-  StoreBufferUpdateVisitor visitor(Isolate::Current(), raw_clone);
+  StoreBufferUpdateVisitor visitor(Thread::Current(), raw_clone);
   raw_clone->VisitPointers(&visitor);
   return raw_clone;
 }
@@ -2695,6 +2731,16 @@
 }
 
 
+void Class::SetTraceAllocation(bool trace_allocation) const {
+  const bool changed = trace_allocation != this->trace_allocation();
+  set_state_bits(
+      TraceAllocationBit::update(trace_allocation, raw_ptr()->state_bits_));
+  if (changed) {
+    // TODO(johnmccutchan): Deoptimize the world?
+  }
+}
+
+
 void Class::set_cha_codes(const Array& cache) const {
   StorePointer(&raw_ptr()->cha_codes_, cache.raw());
 }
@@ -2846,7 +2892,7 @@
   Script& script = Script::Handle();
   script = Script::New(Symbols::EvalSourceUri(),
                        func_src,
-                       RawScript::kSourceTag);
+                       RawScript::kEvaluateTag);
   // In order to tokenize the source, we need to get the key to mangle
   // private names from the library from which the class originates.
   const Library& lib = Library::Handle(cls.library());
@@ -3228,6 +3274,8 @@
       return Symbols::Code().raw();
     case kInstructionsCid:
       return Symbols::Instructions().raw();
+    case kObjectPoolCid:
+      return Symbols::ObjectPool().raw();
     case kPcDescriptorsCid:
       return Symbols::PcDescriptors().raw();
     case kStackmapCid:
@@ -3301,9 +3349,15 @@
     case kTypedDataUint64ArrayCid:
     case kExternalTypedDataUint64ArrayCid:
       return Symbols::Uint64List().raw();
+    case kTypedDataInt32x4ArrayCid:
+    case kExternalTypedDataInt32x4ArrayCid:
+      return Symbols::Int32x4List().raw();
     case kTypedDataFloat32x4ArrayCid:
     case kExternalTypedDataFloat32x4ArrayCid:
       return Symbols::Float32x4List().raw();
+    case kTypedDataFloat64x2ArrayCid:
+    case kExternalTypedDataFloat64x2ArrayCid:
+      return Symbols::Float64x2List().raw();
     case kTypedDataFloat32ArrayCid:
     case kExternalTypedDataFloat32ArrayCid:
       return Symbols::Float32List().raw();
@@ -6262,7 +6316,7 @@
                     0));
   ASSERT(!script.IsNull());
   result.set_is_debuggable(false);
-  result.set_is_visible(false);
+  result.set_is_visible(true);
   result.set_eval_script(script);
   return result.raw();
 }
@@ -6574,6 +6628,12 @@
 }
 
 
+const char* Function::QualifiedUserVisibleNameCString() const {
+  const String& str = String::Handle(QualifiedUserVisibleName());
+  return str.ToCString();
+}
+
+
 RawString* Function::UserVisibleName() const {
   return PrettyName();
 }
@@ -8287,6 +8347,8 @@
       return "source";
     case RawScript::kPatchTag:
       return "patch";
+    case RawScript::kEvaluateTag:
+      return "evaluate";
     default:
       UNIMPLEMENTED();
   }
@@ -8562,16 +8624,22 @@
   const String& encoded_uri = String::Handle(String::EncodeIRI(uri));
   ASSERT(!encoded_uri.IsNull());
   const Library& lib = Library::Handle(FindLibrary());
-  // TODO(rmacnak): This can fail for eval scripts. Use a ring-id for those.
-  intptr_t lib_index = (lib.IsNull()) ? -1 : lib.index();
-  jsobj.AddFixedServiceId("libraries/%" Pd "/scripts/%s",
-      lib_index, encoded_uri.ToCString());
+  if (lib.IsNull()) {
+    ASSERT(kind() == RawScript::kEvaluateTag);
+    jsobj.AddServiceId(*this);
+  } else {
+    ASSERT(kind() != RawScript::kEvaluateTag);
+    jsobj.AddFixedServiceId("libraries/%" Pd "/scripts/%s",
+        lib.index(), encoded_uri.ToCString());
+  }
   jsobj.AddPropertyStr("uri", uri);
   jsobj.AddProperty("_kind", GetKindAsCString());
   if (ref) {
     return;
   }
-  jsobj.AddProperty("library", lib);
+  if (!lib.IsNull()) {
+    jsobj.AddProperty("library", lib);
+  }
   const String& source = String::Handle(Source());
   jsobj.AddProperty("lineOffset", line_offset());
   jsobj.AddProperty("columnOffset", col_offset());
@@ -8698,6 +8766,25 @@
 }
 
 
+static void ReportTooManyImports(const Library& lib) {
+  const String& url = String::Handle(lib.url());
+  Report::MessageF(Report::kError,
+                   Script::Handle(lib.LookupScript(url)),
+                   Scanner::kNoSourcePos,
+                   "too many imports in library '%s'",
+                   url.ToCString());
+  UNREACHABLE();
+}
+
+
+void Library::set_num_imports(intptr_t value) const {
+  if (!Utils::IsUint(16, value)) {
+    ReportTooManyImports(*this);
+  }
+  StoreNonPointer(&raw_ptr()->num_imports_, value);
+}
+
+
 void Library::SetName(const String& name) const {
   // Only set name once.
   ASSERT(!Loaded());
@@ -10294,6 +10381,9 @@
 
 
 void LibraryPrefix::set_num_imports(intptr_t value) const {
+  if (!Utils::IsUint(16, value)) {
+    ReportTooManyImports(Library::Handle(importer()));
+  }
   StoreNonPointer(&raw_ptr()->num_imports_, value);
 }
 
@@ -10662,6 +10752,73 @@
 }
 
 
+RawObjectPool* ObjectPool::New(intptr_t len) {
+  ASSERT(Object::object_pool_class() != Class::null());
+  if (len < 0 || len > kMaxElements) {
+    // This should be caught before we reach here.
+    FATAL1("Fatal error in ObjectPool::New: invalid length %" Pd "\n", len);
+  }
+  ObjectPool& result = ObjectPool::Handle();
+  {
+    uword size = ObjectPool::InstanceSize(len);
+    RawObject* raw = Object::Allocate(ObjectPool::kClassId,
+                                      size,
+                                      Heap::kOld);
+    NoSafepointScope no_safepoint;
+    result ^= raw;
+    result.SetLength(len);
+  }
+
+  // TODO(fschneider): Compress info array to just use just enough bits for
+  // the entry type enum.
+  const TypedData& info_array = TypedData::Handle(
+      TypedData::New(kTypedDataInt8ArrayCid, len, Heap::kOld));
+  result.set_info_array(info_array);
+  return result.raw();
+}
+
+
+void ObjectPool::set_info_array(const TypedData& info_array) const {
+  StorePointer(&raw_ptr()->info_array_, info_array.raw());
+}
+
+
+ObjectPool::EntryType ObjectPool::InfoAt(intptr_t index) const {
+  const TypedData& array = TypedData::Handle(info_array());
+  return static_cast<EntryType>(array.GetInt8(index));
+}
+
+
+void ObjectPool::SetInfoAt(intptr_t index, EntryType info) const {
+  const TypedData& array = TypedData::Handle(info_array());
+  array.SetInt8(index, static_cast<int8_t>(info));
+}
+
+const char* ObjectPool::ToCString() const {
+  return "ObjectPool";
+}
+
+
+void ObjectPool::PrintJSONImpl(JSONStream* stream, bool ref) const {
+  Object::PrintJSONImpl(stream, ref);
+}
+
+
+void ObjectPool::DebugPrint() const {
+  ISL_Print("Object Pool: {\n");
+  for (intptr_t i = 0; i < Length(); i++) {
+    if (InfoAt(i) == kTaggedObject) {
+      ISL_Print("  %" Pd ": 0x%" Px " %s (obj)\n", i,
+          reinterpret_cast<uword>(ObjectAt(i)),
+          Object::Handle(ObjectAt(i)).ToCString());
+    } else {
+      ISL_Print("  %" Pd ": 0x%" Px " (raw)\n", i, RawValueAt(i));
+    }
+  }
+  ISL_Print("}\n");
+}
+
+
 intptr_t PcDescriptors::Length() const {
   return raw_ptr()->length_;
 }
@@ -10701,6 +10858,25 @@
 }
 
 
+RawPcDescriptors* PcDescriptors::New(intptr_t length) {
+  ASSERT(Object::pc_descriptors_class() != Class::null());
+  Isolate* isolate = Isolate::Current();
+  PcDescriptors& result = PcDescriptors::Handle(isolate);
+  {
+    uword size = PcDescriptors::InstanceSize(length);
+    RawObject* raw = Object::Allocate(PcDescriptors::kClassId,
+                                      size,
+                                      Heap::kOld);
+    INC_STAT(isolate, total_code_size, size);
+    INC_STAT(isolate, pc_desc_size, size);
+    NoSafepointScope no_safepoint;
+    result ^= raw;
+    result.SetLength(length);
+  }
+  return result.raw();
+}
+
+
 const char* PcDescriptors::KindAsStr(RawPcDescriptors::Kind kind) {
   switch (kind) {
     case RawPcDescriptors::kDeopt:           return "deopt        ";
@@ -10898,6 +11074,40 @@
 }
 
 
+RawStackmap* Stackmap::New(intptr_t length,
+                           intptr_t register_bit_count,
+                           intptr_t pc_offset) {
+  ASSERT(Object::stackmap_class() != Class::null());
+  Stackmap& result = Stackmap::Handle();
+  // Guard against integer overflow of the instance size computation.
+  intptr_t payload_size =
+  Utils::RoundUp(length, kBitsPerByte) / kBitsPerByte;
+  if ((payload_size < 0) ||
+      (payload_size > kMaxLengthInBytes)) {
+    // This should be caught before we reach here.
+    FATAL1("Fatal error in Stackmap::New: invalid length %" Pd "\n",
+           length);
+  }
+  {
+    // Stackmap data objects are associated with a code object, allocate them
+    // in old generation.
+    RawObject* raw = Object::Allocate(Stackmap::kClassId,
+                                      Stackmap::InstanceSize(length),
+                                      Heap::kOld);
+    NoSafepointScope no_safepoint;
+    result ^= raw;
+    result.SetLength(length);
+  }
+  // When constructing a stackmap we store the pc offset in the stackmap's
+  // PC. StackmapTableBuilder::FinalizeStackmaps will replace it with the pc
+  // address.
+  ASSERT(pc_offset >= 0);
+  result.SetPcOffset(pc_offset);
+  result.SetRegisterBitCount(register_bit_count);
+  return result.raw();
+}
+
+
 const char* Stackmap::ToCString() const {
   if (IsNull()) {
     return "{null}";
@@ -11219,6 +11429,29 @@
 }
 
 
+RawExceptionHandlers* ExceptionHandlers::New(const Array& handled_types_data) {
+  ASSERT(Object::exception_handlers_class() != Class::null());
+  const intptr_t num_handlers = handled_types_data.Length();
+  if ((num_handlers < 0) || (num_handlers >= kMaxHandlers)) {
+    FATAL1("Fatal error in ExceptionHandlers::New(): "
+           "invalid num_handlers %" Pd "\n",
+           num_handlers);
+  }
+  ExceptionHandlers& result = ExceptionHandlers::Handle();
+  {
+    uword size = ExceptionHandlers::InstanceSize(num_handlers);
+    RawObject* raw = Object::Allocate(ExceptionHandlers::kClassId,
+                                      size,
+                                      Heap::kOld);
+    NoSafepointScope no_safepoint;
+    result ^= raw;
+    result.StoreNonPointer(&result.raw_ptr()->num_entries_, num_handlers);
+  }
+  result.set_handled_types_data(handled_types_data);
+  return result.raw();
+}
+
+
 const char* ExceptionHandlers::ToCString() const {
   if (num_entries() == 0) {
     return "No exception handlers\n";
@@ -12459,6 +12692,8 @@
                             Assembler* assembler,
                             bool optimized) {
   ASSERT(assembler != NULL);
+  const ObjectPool& object_pool =
+      ObjectPool::Handle(assembler->object_pool_wrapper().MakeObjectPool());
 
   // Allocate the Code and Instructions objects.  Code is allocated first
   // because a GC during allocation of the code will leave the instruction
@@ -12484,7 +12719,6 @@
                            assembler->prologue_offset(),
                            instrs.size(),
                            optimized);
-
   {
     NoSafepointScope no_safepoint;
     const ZoneGrowableArray<intptr_t>& pointer_offsets =
@@ -12509,17 +12743,10 @@
     code.set_is_alive(true);
 
     // Set object pool in Instructions object.
-    const GrowableObjectArray& object_pool = assembler->object_pool_data();
-    if (object_pool.IsNull()) {
-      instrs.set_object_pool(Object::empty_array().raw());
-    } else {
-      INC_STAT(Isolate::Current(),
-               total_code_size, object_pool.Length() * sizeof(uintptr_t));
-      // TODO(regis): Once MakeArray takes a Heap::Space argument, call it here
-      // with Heap::kOld and change the ARM and MIPS assemblers to work with a
-      // GrowableObjectArray in new space.
-      instrs.set_object_pool(Array::MakeArray(object_pool));
-    }
+    INC_STAT(Isolate::Current(),
+             total_code_size, object_pool.Length() * sizeof(uintptr_t));
+    instrs.set_object_pool(object_pool.raw());
+
     if (FLAG_write_protect_code) {
       uword address = RawObject::ToAddr(instrs.raw());
       bool status = VirtualMemory::Protect(
@@ -12754,8 +12981,8 @@
   jsobj.AddPropertyF("_startAddress", "%" Px "", EntryPoint());
   jsobj.AddPropertyF("_endAddress", "%" Px "", EntryPoint() + Size());
   jsobj.AddProperty("_alive", is_alive());
-  const Array& array = Array::Handle(ObjectPool());
-  jsobj.AddProperty("_objectPool", array);
+  const ObjectPool& object_pool = ObjectPool::Handle(GetObjectPool());
+  jsobj.AddProperty("_objectPool", object_pool);
   {
     JSONArray jsarr(&jsobj, "_disassembly");
     if (is_alive()) {
@@ -13229,6 +13456,7 @@
   }
   const intptr_t capacity = kInitialCapacity;
   const Array& buckets = Array::Handle(Array::New(kEntryLength * capacity));
+  ASSERT(Isolate::Current()->megamorphic_cache_table()->miss_handler() != NULL);
   const Function& handler = Function::Handle(
       Isolate::Current()->megamorphic_cache_table()->miss_handler());
   for (intptr_t i = 0; i < capacity; ++i) {
@@ -14236,6 +14464,13 @@
   if (ref) {
     return;
   }
+  if (IsClosure()) {
+    Debugger* debugger = Isolate::Current()->debugger();
+    Breakpoint* bpt = debugger->BreakpointAtActivation(*this);
+    if (bpt != NULL) {
+      jsobj.AddProperty("_activationBreakpoint", bpt);
+    }
+  }
 }
 
 
@@ -15568,6 +15803,7 @@
 
 void TypeParameter::set_index(intptr_t value) const {
   ASSERT(value >= 0);
+  ASSERT(Utils::IsInt(16, value));
   StoreNonPointer(&raw_ptr()->index_, value);
 }
 
@@ -20108,7 +20344,23 @@
 
 
 void TypedData::PrintJSONImpl(JSONStream* stream, bool ref) const {
-  Instance::PrintJSONImpl(stream, ref);
+  JSONObject jsobj(stream);
+  PrintSharedInstanceJSON(&jsobj, ref);
+  const Class& cls = Class::Handle(clazz());
+  const String& kind = String::Handle(cls.UserVisibleName());
+  jsobj.AddProperty("kind", kind.ToCString());
+  jsobj.AddServiceId(*this);
+  jsobj.AddProperty("length", Length());
+  if (ref) {
+    return;
+  }
+
+  {
+    NoSafepointScope no_safepoint;
+    jsobj.AddPropertyBase64("bytes",
+                            reinterpret_cast<const uint8_t*>(DataAddr(0)),
+                            LengthInBytes());
+  }
 }
 
 
@@ -20143,7 +20395,23 @@
 
 void ExternalTypedData::PrintJSONImpl(JSONStream* stream,
                                       bool ref) const {
-  Instance::PrintJSONImpl(stream, ref);
+  JSONObject jsobj(stream);
+  PrintSharedInstanceJSON(&jsobj, ref);
+  const Class& cls = Class::Handle(clazz());
+  const String& kind = String::Handle(cls.UserVisibleName());
+  jsobj.AddProperty("kind", kind.ToCString());
+  jsobj.AddServiceId(*this);
+  jsobj.AddProperty("length", Length());
+  if (ref) {
+    return;
+  }
+
+  {
+    NoSafepointScope no_safepoint;
+    jsobj.AddPropertyBase64("bytes",
+                            reinterpret_cast<const uint8_t*>(DataAddr(0)),
+                            LengthInBytes());
+  }
 }
 
 
@@ -20440,6 +20708,7 @@
         char* chars = isolate->current_zone()->Alloc<char>(truncated_len);
         OS::SNPrint(chars, truncated_len, "%s", kTruncated);
         frame_strings.Add(chars);
+        total_len += truncated_len;
       }
     } else if (function.is_visible() || FLAG_show_invisible_frames) {
       code = CodeAtFrame(i);
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 612a80b..ad21c1a 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -413,6 +413,11 @@
     return *zero_array_;
   }
 
+  static const ObjectPool& empty_object_pool() {
+    ASSERT(empty_object_pool_ != NULL);
+    return *empty_object_pool_;
+  }
+
   static const PcDescriptors& empty_descriptors() {
     ASSERT(empty_descriptors_ != NULL);
     return *empty_descriptors_;
@@ -510,6 +515,7 @@
   static RawClass* namespace_class() { return namespace_class_; }
   static RawClass* code_class() { return code_class_; }
   static RawClass* instructions_class() { return instructions_class_; }
+  static RawClass* object_pool_class() { return object_pool_class_; }
   static RawClass* pc_descriptors_class() { return pc_descriptors_class_; }
   static RawClass* stackmap_class() { return stackmap_class_; }
   static RawClass* var_descriptors_class() { return var_descriptors_class_; }
@@ -532,6 +538,7 @@
   static RawClass* subtypetestcache_class() { return subtypetestcache_class_; }
 
   // Initialize the VM isolate.
+  static void InitNull(Isolate* isolate);
   static void InitOnce(Isolate* isolate);
   static void FinalizeVMIsolate(Isolate* isolate);
 
@@ -768,6 +775,7 @@
   static RawClass* namespace_class_;  // Class of Namespace vm object.
   static RawClass* code_class_;  // Class of the Code vm object.
   static RawClass* instructions_class_;  // Class of the Instructions vm object.
+  static RawClass* object_pool_class_;  // Class of the ObjectPool vm object.
   static RawClass* pc_descriptors_class_;  // Class of PcDescriptors vm object.
   static RawClass* stackmap_class_;  // Class of Stackmap vm object.
   static RawClass* var_descriptors_class_;  // Class of LocalVarDescriptors.
@@ -792,6 +800,7 @@
   static TypeArguments* null_type_arguments_;
   static Array* empty_array_;
   static Array* zero_array_;
+  static ObjectPool* empty_object_pool_;
   static PcDescriptors* empty_descriptors_;
   static LocalVarDescriptors* empty_var_descriptors_;
   static ExceptionHandlers* empty_exception_handlers_;
@@ -1354,6 +1363,11 @@
   RawArray* cha_codes() const { return raw_ptr()->cha_codes_; }
   void set_cha_codes(const Array& value) const;
 
+  bool trace_allocation() const {
+    return TraceAllocationBit::decode(raw_ptr()->state_bits_);
+  }
+  void SetTraceAllocation(bool trace_allocation) const;
+
  private:
   enum MemberKind {
     kAny = 0,
@@ -1377,6 +1391,7 @@
     kFieldsMarkedNullableBit = 11,
     kCycleFreeBit = 12,
     kEnumBit = 13,
+    kTraceAllocationBit = 14,
   };
   class ConstBit : public BitField<bool, kConstBit, 1> {};
   class ImplementedBit : public BitField<bool, kImplementedBit, 1> {};
@@ -1393,6 +1408,7 @@
       kFieldsMarkedNullableBit, 1> {};  // NOLINT
   class CycleFreeBit : public BitField<bool, kCycleFreeBit, 1> {};
   class EnumBit : public BitField<bool, kEnumBit, 1> {};
+  class TraceAllocationBit : public BitField<bool, kTraceAllocationBit, 1> {};
 
   void set_name(const String& value) const;
   void set_pretty_name(const String& value) const;
@@ -2031,6 +2047,7 @@
   RawString* UserVisibleName() const;
   RawString* QualifiedPrettyName() const;
   RawString* QualifiedUserVisibleName() const;
+  const char* QualifiedUserVisibleNameCString() const;
   virtual RawString* DictionaryName() const { return name(); }
 
   RawString* GetSource() const;
@@ -3419,9 +3436,7 @@
 
   static RawLibrary* New();
 
-  void set_num_imports(intptr_t value) const {
-    StoreNonPointer(&raw_ptr()->num_imports_, value);
-  }
+  void set_num_imports(intptr_t value) const;
   bool HasExports() const;
   RawArray* loaded_scripts() const { return raw_ptr()->loaded_scripts_; }
   RawGrowableObjectArray* metadata() const { return raw_ptr()->metadata_; }
@@ -3495,6 +3510,108 @@
 };
 
 
+// ObjectPool contains constants, immediates and addresses embedded in code
+// and deoptimization infos. Each entry has an type-info associated with it
+// which is stored in a typed data array (info_array).
+class ObjectPool : public Object {
+ public:
+  enum EntryType {
+    kTaggedObject,
+    kImmediate,
+  };
+
+  struct Entry {
+    Entry() : raw_value_(), type_() { }
+    explicit Entry(const Object* obj) : obj_(obj), type_(kTaggedObject) { }
+    Entry(uword value, EntryType info) : raw_value_(value), type_(info) { }
+    union {
+      const Object* obj_;
+      uword raw_value_;
+    };
+    EntryType type_;
+  };
+
+  intptr_t Length() const {
+    return raw_ptr()->length_;
+  }
+  void SetLength(intptr_t value) const {
+    StoreNonPointer(&raw_ptr()->length_, value);
+  }
+
+  RawTypedData* info_array() const {
+    return raw_ptr()->info_array_;
+  }
+
+  void set_info_array(const TypedData& info_array) const;
+
+  static intptr_t length_offset() { return OFFSET_OF(RawObjectPool, length_); }
+  static intptr_t data_offset() {
+    return OFFSET_OF_RETURNED_VALUE(RawObjectPool, data);
+  }
+  static intptr_t element_offset(intptr_t index) {
+    return OFFSET_OF_RETURNED_VALUE(RawObjectPool, data)
+        + kBytesPerElement * index;
+  }
+
+  EntryType InfoAt(intptr_t index) const;
+  void SetInfoAt(intptr_t index, EntryType info) const;
+
+  RawObject* ObjectAt(intptr_t index) const {
+    ASSERT(InfoAt(index) == kTaggedObject);
+    return EntryAddr(index)->raw_obj_;
+  }
+  void SetObjectAt(intptr_t index, const Object& obj) const {
+    ASSERT(InfoAt(index) == kTaggedObject);
+    StorePointer(&EntryAddr(index)->raw_obj_, obj.raw());
+  }
+
+  uword RawValueAt(intptr_t index) const {
+    ASSERT(InfoAt(index) != kTaggedObject);
+    return EntryAddr(index)->raw_value_;
+  }
+  void SetRawValueAt(intptr_t index, uword raw_value) const {
+    ASSERT(InfoAt(index) != kTaggedObject);
+    StoreNonPointer(&EntryAddr(index)->raw_value_, raw_value);
+  }
+
+  static intptr_t InstanceSize() {
+    ASSERT(sizeof(RawObjectPool) ==
+           OFFSET_OF_RETURNED_VALUE(RawObjectPool, data));
+    return 0;
+  }
+
+  static const intptr_t kBytesPerElement = sizeof(RawObjectPool::Entry);
+  static const intptr_t kMaxElements = kSmiMax / kBytesPerElement;
+
+  static intptr_t InstanceSize(intptr_t len) {
+    // Ensure that variable length data is not adding to the object length.
+    ASSERT(sizeof(RawObjectPool) == (sizeof(RawObject) + (2 * kWordSize)));
+    ASSERT(0 <= len && len <= kMaxElements);
+    return RoundedAllocationSize(
+        sizeof(RawObjectPool) + (len * kBytesPerElement));
+  }
+
+  static RawObjectPool* New(intptr_t len);
+
+  static intptr_t IndexFromOffset(intptr_t offset) {
+    return (offset + kHeapObjectTag - data_offset()) / kBytesPerElement;
+  }
+
+  void DebugPrint() const;
+
+ private:
+  RawObjectPool::Entry const* EntryAddr(intptr_t index) const {
+    ASSERT((index >= 0) && (index < Length()));
+    return &raw_ptr()->data()[index];
+  }
+
+  FINAL_HEAP_OBJECT_IMPLEMENTATION(ObjectPool, Object);
+  friend class Class;
+  friend class Object;
+  friend class RawObjectPool;
+};
+
+
 class Instructions : public Object {
  public:
   intptr_t size() const { return raw_ptr()->size_; }  // Excludes HeaderSize().
@@ -3502,7 +3619,7 @@
   static intptr_t code_offset() {
     return OFFSET_OF(RawInstructions, code_);
   }
-  RawArray* object_pool() const { return raw_ptr()->object_pool_; }
+  RawObjectPool* object_pool() const { return raw_ptr()->object_pool_; }
   static intptr_t object_pool_offset() {
     return OFFSET_OF(RawInstructions, object_pool_);
   }
@@ -3547,7 +3664,7 @@
   void set_code(RawCode* code) const {
     StorePointer(&raw_ptr()->code_, code);
   }
-  void set_object_pool(RawArray* object_pool) const {
+  void set_object_pool(RawObjectPool* object_pool) const {
     StorePointer(&raw_ptr()->object_pool_, object_pool);
   }
 
@@ -3706,6 +3823,8 @@
  private:
   static const char* KindAsStr(RawPcDescriptors::Kind kind);
 
+  static RawPcDescriptors* New(intptr_t length);
+
   intptr_t Length() const;
   void SetLength(intptr_t value) const;
   void CopyData(GrowableArray<uint8_t>* data);
@@ -3757,6 +3876,10 @@
                           BitmapBuilder* bmap,
                           intptr_t register_bit_count);
 
+  static RawStackmap* New(intptr_t length,
+                          intptr_t register_bit_count,
+                          intptr_t pc_offset);
+
  private:
   void SetLength(intptr_t length) const {
       StoreNonPointer(&raw_ptr()->length_, length);
@@ -3808,6 +3931,7 @@
   }
 
   static RawExceptionHandlers* New(intptr_t num_handlers);
+  static RawExceptionHandlers* New(const Array& handled_types_data);
 
   // We would have a VisitPointers function here to traverse the
   // exception handler table to visit objects if any in the table.
@@ -3899,7 +4023,7 @@
     const Instructions& instr = Instructions::Handle(instructions());
     return instr.size();
   }
-  RawArray* ObjectPool() const {
+  RawObjectPool* GetObjectPool() const {
     const Instructions& instr = Instructions::Handle(instructions());
     return instr.object_pool();
   }
@@ -4728,7 +4852,7 @@
   virtual RawString* DictionaryName() const { return name(); }
 
   RawArray* imports() const { return raw_ptr()->imports_; }
-  int32_t num_imports() const { return raw_ptr()->num_imports_; }
+  intptr_t num_imports() const { return raw_ptr()->num_imports_; }
   RawLibrary* importer() const { return raw_ptr()->importer_; }
 
   RawInstance* LoadError() const;
@@ -6308,6 +6432,8 @@
   static void SetExternalData(const String& str,
                               ExternalStringData<uint8_t>* data) {
     ASSERT(str.IsExternalOneByteString());
+    ASSERT(!Isolate::Current()->heap()->Contains(
+        reinterpret_cast<uword>(data->data())));
     str.StoreNonPointer(&raw_ptr(str)->external_data_, data);
   }
 
@@ -6384,6 +6510,8 @@
   static void SetExternalData(const String& str,
                               ExternalStringData<uint16_t>* data) {
     ASSERT(str.IsExternalTwoByteString());
+    ASSERT(!Isolate::Current()->heap()->Contains(
+        reinterpret_cast<uword>(data->data())));
     str.StoreNonPointer(&raw_ptr(str)->external_data_, data);
   }
 
@@ -6803,7 +6931,6 @@
     return ElementSizeInBytes(cid);
   }
 
-
   TypedDataElementType ElementType() const {
     intptr_t cid = raw()->GetClassId();
     return ElementType(cid);
@@ -7066,6 +7193,8 @@
   }
 
   void SetData(uint8_t* data) const {
+    ASSERT(!Isolate::Current()->heap()->Contains(
+        reinterpret_cast<uword>(data)));
     StoreNonPointer(&raw_ptr()->data_, data);
   }
 
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
index 0307c90..a8fc76a 100644
--- a/runtime/vm/parser.cc
+++ b/runtime/vm/parser.cc
@@ -44,7 +44,8 @@
 DEFINE_FLAG(bool, warn_mixin_typedef, true, "Warning on legacy mixin typedef.");
 DECLARE_FLAG(bool, throw_on_javascript_int_overflow);
 DECLARE_FLAG(bool, warn_on_javascript_compatibility);
-
+DEFINE_FLAG(bool, enable_mirrors, true,
+    "Disable to make importing dart:mirrors an error.");
 
 // Quick access to the current isolate and zone.
 #define I (isolate())
@@ -968,8 +969,8 @@
       ExpectIdentifier("identifier expected");
     }
     // Reject expressions with deferred library prefix eagerly.
-    Object& obj = Object::Handle(Z,
-                                 library_.LookupLocalObject(*CurrentLiteral()));
+    Object& obj =
+        Object::Handle(Z, library_.LookupLocalObject(*CurrentLiteral()));
     if (!obj.IsNull() && obj.IsLibraryPrefix()) {
       if (LibraryPrefix::Cast(obj).is_deferred_load()) {
         ReportError("Metadata must be compile-time constant");
@@ -2978,8 +2979,7 @@
     for (int i = 2; i < ctor_args->length(); i++) {
       AstNode* arg = ctor_args->NodeAt(i);
       if (!IsSimpleLocalOrLiteralNode(arg)) {
-        LocalVariable* temp =
-            CreateTempConstVariable(arg->token_pos(), "sca");
+        LocalVariable* temp = CreateTempConstVariable(arg->token_pos(), "sca");
         AstNode* save_temp = new StoreLocalNode(arg->token_pos(), temp, arg);
         ctor_args->SetNodeAt(i, save_temp);
       }
@@ -5775,14 +5775,20 @@
     ns.AddMetadata(metadata_pos, current_class());
   }
 
+  // Ensure that private dart:_ libraries are only imported into dart:
+  // libraries, including indirectly through exports.
+  const String& lib_url = String::Handle(Z, library_.url());
+  if (canon_url.StartsWith(Symbols::DartSchemePrivate()) &&
+      !lib_url.StartsWith(Symbols::DartScheme())) {
+    ReportError(import_pos, "private library is not accessible");
+  }
+
+  if (!FLAG_enable_mirrors && Symbols::DartMirrors().Equals(canon_url)) {
+    ReportError(import_pos,
+                "import of dart:mirrors with --enable-mirrors=false");
+  }
+
   if (is_import) {
-    // Ensure that private dart:_ libraries are only imported into dart:
-    // libraries.
-    const String& lib_url = String::Handle(Z, library_.url());
-    if (canon_url.StartsWith(Symbols::DartSchemePrivate()) &&
-        !lib_url.StartsWith(Symbols::DartScheme())) {
-      ReportError(import_pos, "private library is not accessible");
-    }
     if (prefix.IsNull() || (prefix.Length() == 0)) {
       ASSERT(!is_deferred_import);
       library_.AddImport(ns);
@@ -7129,9 +7135,9 @@
 }
 
 
-AstNode* Parser::CallGetter(intptr_t token_pos,
-                            AstNode* object,
-                            const String& name) {
+InstanceGetterNode* Parser::CallGetter(intptr_t token_pos,
+                                       AstNode* object,
+                                       const String& name) {
   return new(Z) InstanceGetterNode(token_pos, object, name);
 }
 
@@ -10134,7 +10140,7 @@
 
 AstNode* Parser::ParseBinaryExpr(int min_preced) {
   TRACE_PARSER("ParseBinaryExpr");
-  ASSERT(min_preced >= Token::Precedence(Token::kOR));
+  ASSERT(min_preced >= Token::Precedence(Token::kIFNULL));
   AstNode* left_operand = ParseUnaryExpr();
   if (left_operand->IsPrimaryNode() &&
       (left_operand->AsPrimaryNode()->IsSuper())) {
@@ -10184,12 +10190,6 @@
           || Token::IsTypeTestOperator(op_kind)
           || Token::IsTypeCastOperator(op_kind)
           || Token::IsEqualityOperator(op_kind)) {
-        if (Token::IsTypeTestOperator(op_kind) ||
-            Token::IsTypeCastOperator(op_kind)) {
-          if (!right_operand->AsTypeNode()->type().IsInstantiated()) {
-            EnsureExpressionTemp();
-          }
-        }
         left_operand = new(Z) ComparisonNode(
             op_pos, op_kind, left_operand, right_operand);
         break;  // Equality and relational operators cannot be chained.
@@ -10272,9 +10272,6 @@
       }
     }
   }
-  if ((binary_op == Token::kAND) || (binary_op == Token::kOR)) {
-    EnsureExpressionTemp();
-  }
   if (binary_op == Token::kBIT_AND) {
     // Normalize so that rhs is a literal if any is.
     if ((rhs_literal == NULL) && (lhs_literal != NULL)) {
@@ -10332,6 +10329,8 @@
       return new(Z) BinaryOpNode(op_pos, Token::kBIT_AND, lhs, rhs);
     case Token::kASSIGN_XOR:
       return new(Z) BinaryOpNode(op_pos, Token::kBIT_XOR, lhs, rhs);
+    case Token::kASSIGN_COND:
+      return new(Z) BinaryOpNode(op_pos, Token::kIFNULL, lhs, rhs);
     default:
       ReportError(op_pos,
                   "internal error: ExpandAssignableOp '%s' unimplemented",
@@ -10387,7 +10386,7 @@
       receiver = new(Z) LoadLocalNode(token_pos, t0);
     }
     *expr = new(Z) InstanceGetterNode(
-        token_pos, receiver, getter->field_name());
+        token_pos, receiver, getter->field_name(), getter->is_conditional());
     return result;
   }
   return result;
@@ -10450,13 +10449,25 @@
          InvocationMirror::kLocalVar : InvocationMirror::kSetter,
          NULL));  // No existing function.
     result = let_node;
-  } else if (result->IsStoreIndexedNode() ||
-             result->IsInstanceSetterNode() ||
-             result->IsStaticSetterNode() ||
-             result->IsStoreStaticFieldNode() ||
-             result->IsStoreLocalNode()) {
-    // Ensure that the expression temp is allocated for nodes that may need it.
-    EnsureExpressionTemp();
+  }
+  // The compound assignment operator a ??= b is different from other
+  // a op= b assignments. If a is non-null, the assignment to a must be
+  // dropped:
+  // normally: a op= b ==> a = a op b
+  // however:  a ??= b ==> a ?? (a = b)
+  // Therefore, we need to transform a = (a ?? b) into a ?? (a = b)
+  if (rhs->IsBinaryOpNode() &&
+      (rhs->AsBinaryOpNode()->kind() == Token::kIFNULL)) {
+    BinaryOpNode* ifnull = rhs->AsBinaryOpNode();
+    AstNode* modified_assign =
+        CreateAssignmentNode(ifnull->left(),
+                             ifnull->right(),
+                             left_ident,
+                             left_pos);
+    result = new(Z) BinaryOpNode(rhs->token_pos(),
+                                 Token::kIFNULL,
+                                 original,
+                                 modified_assign);
   }
   return result;
 }
@@ -10638,7 +10649,7 @@
 AstNode* Parser::ParseConditionalExpr() {
   TRACE_PARSER("ParseConditionalExpr");
   const intptr_t expr_pos = TokenPos();
-  AstNode* expr = ParseBinaryExpr(Token::Precedence(Token::kOR));
+  AstNode* expr = ParseBinaryExpr(Token::Precedence(Token::kIFNULL));
   if (CurrentToken() == Token::kCONDITIONAL) {
     EnsureExpressionTemp();
     ConsumeToken();
@@ -10845,11 +10856,16 @@
 
 AstNode* Parser::ParseInstanceCall(AstNode* receiver,
                                    const String& func_name,
-                                   intptr_t ident_pos) {
+                                   intptr_t ident_pos,
+                                   bool is_conditional) {
   TRACE_PARSER("ParseInstanceCall");
   CheckToken(Token::kLPAREN);
   ArgumentListNode* arguments = ParseActualParameters(NULL, kAllowConst);
-  return new(Z) InstanceCallNode(ident_pos, receiver, func_name, arguments);
+  return new(Z) InstanceCallNode(ident_pos,
+                                 receiver,
+                                 func_name,
+                                 arguments,
+                                 is_conditional);
 }
 
 
@@ -10995,7 +11011,10 @@
   AstNode* left = primary;
   while (true) {
     AstNode* selector = NULL;
-    if (CurrentToken() == Token::kPERIOD) {
+    if ((CurrentToken() == Token::kPERIOD) ||
+        (CurrentToken() == Token::kQM_PERIOD)) {
+      // Unconditional or conditional property extraction or method call.
+      bool is_conditional = CurrentToken() == Token::kQM_PERIOD;
       ConsumeToken();
       if (left->IsPrimaryNode()) {
         PrimaryNode* primary_node = left->AsPrimaryNode();
@@ -11004,7 +11023,7 @@
           left = LoadClosure(primary_node);
         } else if (primary_node->primary().IsTypeParameter()) {
           if (ParsingStaticMember()) {
-            const String& name = String::ZoneHandle(Z,
+            const String& name = String::Handle(Z,
                 TypeParameter::Cast(primary_node->primary()).name());
             ReportError(primary_pos,
                         "cannot access type parameter '%s' "
@@ -11022,6 +11041,18 @@
               ClassFinalizer::kCanonicalize);
           ASSERT(!type_parameter.IsMalformed());
           left = new(Z) TypeNode(primary->token_pos(), type_parameter);
+        } else if (is_conditional && primary_node->primary().IsClass()) {
+          // The left-hand side of ?. is interpreted as an expression
+          // of type Type, not as a class literal.
+          const Class& type_class = Class::Cast(primary_node->primary());
+          AbstractType& type = Type::ZoneHandle(Z,
+              Type::New(type_class, TypeArguments::Handle(Z),
+              primary_pos, Heap::kOld));
+          type ^= ClassFinalizer::FinalizeType(
+              current_class(), type, ClassFinalizer::kCanonicalize);
+          // Type may be malbounded, but not malformed.
+          ASSERT(!type.IsMalformed());
+          left = new(Z) TypeNode(primary_pos, type);
         } else {
           // Super field access handled in ParseSuperFieldAccess(),
           // super calls handled in ParseSuperCall().
@@ -11036,10 +11067,11 @@
         if (left->IsPrimaryNode() &&
             left->AsPrimaryNode()->primary().IsClass()) {
           // Static method call prefixed with class name.
+          ASSERT(!is_conditional);
           const Class& cls = Class::Cast(left->AsPrimaryNode()->primary());
           selector = ParseStaticCall(cls, *ident, ident_pos);
         } else {
-          selector = ParseInstanceCall(left, *ident, ident_pos);
+          selector = ParseInstanceCall(left, *ident, ident_pos, is_conditional);
         }
       } else {
         // Field access.
@@ -11056,9 +11088,13 @@
         }
         if (cls.IsNull()) {
           // Instance field access.
-          selector = CallGetter(ident_pos, left, *ident);
+          selector = new(Z) InstanceGetterNode(ident_pos,
+                                               left,
+                                               *ident,
+                                               is_conditional);
         } else {
           // Static field access.
+          ASSERT(!is_conditional);
           selector = GenerateStaticFieldAccess(cls, *ident, ident_pos);
           ASSERT(selector != NULL);
           if (selector->IsLoadStaticFieldNode()) {
@@ -11142,7 +11178,8 @@
             }
             selector = ParseInstanceCall(LoadReceiver(primary_pos),
                                          func_name,
-                                         primary_pos);
+                                         primary_pos,
+                                         false /* is_conditional */);
           }
         } else if (primary_node->primary().IsString()) {
           // Primary is an unresolved name.
@@ -11158,7 +11195,8 @@
             // Treat as call to unresolved (instance) method.
             selector = ParseInstanceCall(LoadReceiver(primary_pos),
                                          name,
-                                         primary_pos);
+                                         primary_pos,
+                                         false /* is_conditional */);
           }
         } else if (primary_node->primary().IsTypeParameter()) {
           const String& name = String::ZoneHandle(Z,
@@ -11173,7 +11211,8 @@
             // Treat as call to unresolved (instance) method.
             selector = ParseInstanceCall(LoadReceiver(primary_pos),
                                          name,
-                                         primary_pos);
+                                         primary_pos,
+                                         false /* is_conditional */);
           }
         } else if (primary_node->primary().IsClass()) {
           const Class& type_class = Class::Cast(primary_node->primary());
@@ -11738,8 +11777,13 @@
     } else {
       return new(Z) PrimaryNode(ident_pos, Function::ZoneHandle(Z, func.raw()));
     }
+  } else if (obj.IsLibraryPrefix()) {
+    const LibraryPrefix& prefix = LibraryPrefix::Cast(obj);
+    ReportError(ident_pos,
+                "illegal use of library prefix '%s'",
+                String::Handle(prefix.name()).ToCString());
   } else {
-    ASSERT(obj.IsNull() || obj.IsLibraryPrefix());
+    ASSERT(obj.IsNull());
   }
   // Lexically unresolved primary identifiers are referenced by their name.
   return new(Z) PrimaryNode(ident_pos, ident);
@@ -13095,6 +13139,8 @@
         Token::CanBeOverloaded(CurrentToken()) ||
         (CurrentToken() == Token::kNE)) {
       primary = ParseSuperOperator();
+    } else if (CurrentToken() == Token::kQM_PERIOD) {
+      ReportError("super call or super getter may not use ?.");
     } else {
       primary = new(Z) PrimaryNode(super_pos, Symbols::Super());
     }
@@ -13381,7 +13427,8 @@
       } else {
         ExpectIdentifier("identifier or [ expected after ..");
       }
-    } else if (current_token == Token::kPERIOD) {
+    } else if ((current_token == Token::kPERIOD) ||
+        (current_token == Token::kQM_PERIOD)) {
       ConsumeToken();
       ExpectIdentifier("identifier expected");
     } else if (current_token == Token::kLBRACK) {
@@ -13419,7 +13466,7 @@
 
 void Parser::SkipBinaryExpr() {
   SkipUnaryExpr();
-  const int min_prec = Token::Precedence(Token::kOR);
+  const int min_prec = Token::Precedence(Token::kIFNULL);
   const int max_prec = Token::Precedence(Token::kMUL);
   while (((min_prec <= Token::Precedence(CurrentToken())) &&
       (Token::Precedence(CurrentToken()) <= max_prec))) {
diff --git a/runtime/vm/parser.h b/runtime/vm/parser.h
index a2492a6..ba56ec9 100644
--- a/runtime/vm/parser.h
+++ b/runtime/vm/parser.h
@@ -577,7 +577,9 @@
   AstNode* LoadReceiver(intptr_t token_pos);
   AstNode* LoadFieldIfUnresolved(AstNode* node);
   AstNode* LoadClosure(PrimaryNode* primary);
-  AstNode* CallGetter(intptr_t token_pos, AstNode* object, const String& name);
+  InstanceGetterNode* CallGetter(intptr_t token_pos,
+                                 AstNode* object,
+                                 const String& name);
 
   AstNode* ParseAssertStatement();
   AstNode* ParseJump(String* label_name);
@@ -708,7 +710,8 @@
                            intptr_t ident_pos);
   AstNode* ParseInstanceCall(AstNode* receiver,
                              const String& method_name,
-                             intptr_t ident_pos);
+                             intptr_t ident_pos,
+                             bool is_conditional);
   AstNode* ParseClosureCall(AstNode* closure);
   AstNode* GenerateStaticFieldLookup(const Field& field,
                                      intptr_t ident_pos);
diff --git a/runtime/vm/port.cc b/runtime/vm/port.cc
index 5a75068..3451ec6 100644
--- a/runtime/vm/port.cc
+++ b/runtime/vm/port.cc
@@ -4,6 +4,7 @@
 
 #include "vm/port.h"
 
+#include "vm/dart_entry.h"
 #include "platform/utils.h"
 #include "vm/dart_api_impl.h"
 #include "vm/isolate.h"
@@ -301,4 +302,27 @@
   deleted_ = 0;
 }
 
+
+void PortMap::PrintPortsForMessageHandler(MessageHandler* handler,
+                                          JSONStream* stream) {
+  JSONObject jsobj(stream);
+  jsobj.AddProperty("type", "_Ports");
+  Object& msg_handler = Object::Handle();
+  {
+    JSONArray ports(&jsobj, "ports");
+    MutexLocker ml(mutex_);
+    for (intptr_t i = 0; i < capacity_; i++) {
+      if (map_[i].handler == handler) {
+        if (map_[i].state == kLivePort) {
+          JSONObject port(&ports);
+          port.AddProperty("type", "_Port");
+          port.AddPropertyF("name", "Isolate Port (%" Pd64 ")", map_[i].port);
+          msg_handler = DartLibraryCalls::LookupHandler(map_[i].port);
+          port.AddProperty("handler", msg_handler);
+        }
+      }
+    }
+  }
+}
+
 }  // namespace dart
diff --git a/runtime/vm/port.h b/runtime/vm/port.h
index f62ac8b..9ec7e7b 100644
--- a/runtime/vm/port.h
+++ b/runtime/vm/port.h
@@ -8,6 +8,7 @@
 #include "include/dart_api.h"
 #include "vm/allocation.h"
 #include "vm/globals.h"
+#include "vm/json_stream.h"
 #include "vm/random.h"
 
 namespace dart {
@@ -18,7 +19,7 @@
 class Mutex;
 class PortMapTestPeer;
 
-class PortMap: public AllStatic {
+class PortMap : public AllStatic {
  public:
   enum PortState {
     kNewPort = 0,      // a newly allocated port
@@ -55,6 +56,9 @@
 
   static void InitOnce();
 
+  static void PrintPortsForMessageHandler(MessageHandler* handler,
+                                          JSONStream* stream);
+
  private:
   friend class dart::PortMapTestPeer;
 
diff --git a/runtime/vm/profiler.cc b/runtime/vm/profiler.cc
index 620d8c0..b674952 100644
--- a/runtime/vm/profiler.cc
+++ b/runtime/vm/profiler.cc
@@ -277,14 +277,23 @@
 class ReturnAddressLocator : public ValueObject {
  public:
   ReturnAddressLocator(Sample* sample, const Code& code)
-      : sample_(sample),
+      : stack_buffer_(sample->GetStackBuffer()),
+        pc_(sample->pc()),
         code_(Code::ZoneHandle(code.raw())) {
     ASSERT(!code_.IsNull());
     ASSERT(code_.ContainsInstructionAt(pc()));
   }
 
+  ReturnAddressLocator(uword pc, uword* stack_buffer, const Code& code)
+      : stack_buffer_(stack_buffer),
+        pc_(pc),
+        code_(Code::ZoneHandle(code.raw())) {
+    ASSERT(!code_.IsNull());
+    ASSERT(code_.ContainsInstructionAt(pc_));
+  }
+
   uword pc() {
-    return sample_->pc();
+    return pc_;
   }
 
   // Returns false on failure.
@@ -307,11 +316,12 @@
   uword StackAt(intptr_t i) {
     ASSERT(i >= 0);
     ASSERT(i < Sample::kStackBufferSizeInWords);
-    return sample_->GetStackBuffer()[i];
+    return stack_buffer_[i];
   }
 
  private:
-  Sample* sample_;
+  uword* stack_buffer_;
+  uword pc_;
   const Code& code_;
 };
 
@@ -385,109 +395,6 @@
 #endif
 
 
-PreprocessVisitor::PreprocessVisitor(Isolate* isolate)
-    : SampleVisitor(isolate),
-      vm_isolate_(Dart::vm_isolate()) {
-}
-
-
-void PreprocessVisitor::VisitSample(Sample* sample) {
-  if (sample->processed()) {
-    // Already processed.
-    return;
-  }
-  // Mark that we've processed this sample.
-  sample->set_processed(true);
-
-  if (sample->exit_frame_sample()) {
-    // Exit frame sample, no preprocessing required.
-    return;
-  }
-  REUSABLE_CODE_HANDLESCOPE(isolate());
-  // Lookup code object for leaf frame.
-  Code& code = reused_code_handle.Handle();
-  code = FindCodeForPC(sample->At(0));
-  sample->set_leaf_frame_is_dart(!code.IsNull());
-  if (!code.IsNull() && (code.compile_timestamp() > sample->timestamp())) {
-    // Code compiled after sample. Ignore.
-    return;
-  }
-  if (sample->leaf_frame_is_dart()) {
-    CheckForMissingDartFrame(code, sample);
-  }
-}
-
-
-void PreprocessVisitor::CheckForMissingDartFrame(const Code& code,
-                                                 Sample* sample) const {
-  // Some stubs (and intrinsics) do not push a frame onto the stack leaving
-  // the frame pointer in the caller.
-  //
-  // PC -> STUB
-  // FP -> DART3  <-+
-  //       DART2  <-|  <- TOP FRAME RETURN ADDRESS.
-  //       DART1  <-|
-  //       .....
-  //
-  // In this case, traversing the linked stack frames will not collect a PC
-  // inside DART3. The stack will incorrectly be: STUB, DART2, DART1.
-  // In Dart code, after pushing the FP onto the stack, an IP in the current
-  // function is pushed onto the stack as well. This stack slot is called
-  // the PC marker. We can use the PC marker to insert DART3 into the stack
-  // so that it will correctly be: STUB, DART3, DART2, DART1. Note the
-  // inserted PC may not accurately reflect the true return address into DART3.
-  ASSERT(!code.IsNull());
-
-  // The pc marker is our current best guess of a return address.
-  uword return_address = sample->pc_marker();
-
-  // Attempt to find a better return address.
-  ReturnAddressLocator ral(sample, code);
-
-  if (!ral.LocateReturnAddress(&return_address)) {
-    ASSERT(return_address == sample->pc_marker());
-    if (code.GetPrologueOffset() == 0) {
-      // Code has the prologue at offset 0. The frame is already setup and
-      // can be trusted.
-      return;
-    }
-    // Could not find a better return address than the pc_marker.
-    if (code.ContainsInstructionAt(return_address)) {
-      // PC marker is in the same code as pc, no missing frame.
-      return;
-    }
-  }
-
-  if (!ContainedInDartCodeHeaps(return_address)) {
-    // return address is not from the Dart heap. Do not insert.
-    return;
-  }
-
-  if (return_address != 0) {
-    sample->InsertCallerForTopFrame(return_address);
-  }
-}
-
-
-bool PreprocessVisitor::ContainedInDartCodeHeaps(uword pc) const {
-  return isolate()->heap()->CodeContains(pc) ||
-         vm_isolate()->heap()->CodeContains(pc);
-}
-
-
-RawCode* PreprocessVisitor::FindCodeForPC(uword pc) const {
-  // Check current isolate for pc.
-  if (isolate()->heap()->CodeContains(pc)) {
-    return Code::LookupCode(pc);
-  }
-  // Check VM isolate for pc.
-  if (vm_isolate()->heap()->CodeContains(pc)) {
-    return Code::LookupCodeInVmIsolate(pc);
-  }
-  return Code::null();
-}
-
-
 ClearProfileVisitor::ClearProfileVisitor(Isolate* isolate)
     : SampleVisitor(isolate) {
 }
@@ -798,7 +705,7 @@
 };
 
 
-static void CopyPCMarkerIfSafe(Sample* sample) {
+static void CopyPCMarkerIfSafe(Sample* sample, uword fp_addr, uword sp_addr) {
   ASSERT(sample != NULL);
 
   if (sample->vm_tag() != VMTag::kDartTagId) {
@@ -806,8 +713,8 @@
     // See http://dartbug.com/20421 for details.
     return;
   }
-  uword* fp = reinterpret_cast<uword*>(sample->fp());
-  uword* sp = reinterpret_cast<uword*>(sample->sp());
+  uword* fp = reinterpret_cast<uword*>(fp_addr);
+  uword* sp = reinterpret_cast<uword*>(sp_addr);
 
   // If FP == SP, the pc marker hasn't been pushed.
   if (fp > sp) {
@@ -820,14 +727,14 @@
 }
 
 
-static void CopyStackBuffer(Sample* sample) {
+static void CopyStackBuffer(Sample* sample, uword sp_addr) {
   ASSERT(sample != NULL);
   if (sample->vm_tag() != VMTag::kDartTagId) {
     // We can only trust the stack pointer if we are executing Dart code.
     // See http://dartbug.com/20421 for details.
     return;
   }
-  uword* sp = reinterpret_cast<uword*>(sample->sp());
+  uword* sp = reinterpret_cast<uword*>(sp_addr);
   uword* buffer = sample->GetStackBuffer();
   if (sp != NULL) {
     for (intptr_t i = 0; i < Sample::kStackBufferSizeInWords; i++) {
@@ -865,14 +772,16 @@
                           ProfilerNativeStackWalker* native_stack_walker,
                           ProfilerDartExitStackWalker* dart_exit_stack_walker,
                           ProfilerDartStackWalker* dart_stack_walker,
-                          uword pc) {
+                          uword pc,
+                          uword fp,
+                          uword sp) {
 #if defined(TARGET_OS_WINDOWS)
   // Use structured exception handling to trap guard page access on Windows.
   __try {
 #endif
 
-  CopyStackBuffer(sample);
-  CopyPCMarkerIfSafe(sample);
+  CopyStackBuffer(sample, sp);
+  CopyPCMarkerIfSafe(sample, fp, sp);
 
   if (FLAG_profile_vm) {
     // Always walk the native stack collecting both native and Dart frames.
@@ -911,6 +820,58 @@
 }
 
 
+void Profiler::RecordAllocation(Isolate* isolate, intptr_t cid) {
+  if ((isolate == NULL) || (Dart::vm_isolate() == NULL)) {
+    // No isolate.
+    return;
+  }
+  ASSERT(isolate != Dart::vm_isolate());
+
+  const bool exited_dart_code = (isolate->stub_code() != NULL) &&
+                                (isolate->top_exit_frame_info() != 0) &&
+                                (isolate->vm_tag() != VMTag::kDartTagId);
+
+  if (!exited_dart_code) {
+    // No Dart frames on stack.
+    // TODO(johnmccutchan): Support collecting native stack.
+    return;
+  }
+
+  IsolateProfilerData* profiler_data = isolate->profiler_data();
+  if (profiler_data == NULL) {
+    // Profiler not initialized.
+    return;
+  }
+
+  SampleBuffer* sample_buffer = profiler_data->sample_buffer();
+  if (sample_buffer == NULL) {
+    // Profiler not initialized.
+    return;
+  }
+
+  const ThreadId thread_id = OSThread::GetCurrentThreadId();
+  // Setup sample.
+  Sample* sample = sample_buffer->ReserveSample();
+  sample->Init(isolate, OS::GetCurrentTimeMicros(), thread_id);
+  uword vm_tag = isolate->vm_tag();
+  #if defined(USING_SIMULATOR)
+  // When running in the simulator, the runtime entry function address
+  // (stored as the vm tag) is the address of a redirect function.
+  // Attempt to find the real runtime entry function address and use that.
+  uword redirect_vm_tag = Simulator::FunctionForRedirect(vm_tag);
+  if (redirect_vm_tag != 0) {
+    vm_tag = redirect_vm_tag;
+  }
+  #endif
+  sample->set_vm_tag(vm_tag);
+  sample->set_user_tag(isolate->user_tag());
+  sample->SetAllocationCid(cid);
+
+  ProfilerDartExitStackWalker dart_exit_stack_walker(isolate, sample);
+  dart_exit_stack_walker.walk();
+}
+
+
 void Profiler::RecordSampleInterruptCallback(
     const InterruptedThreadState& state,
     void* data) {
@@ -1046,8 +1007,6 @@
   counters->Increment(vm_tag);
   sample->set_vm_tag(vm_tag);
   sample->set_user_tag(isolate->user_tag());
-  sample->set_sp(sp);
-  sample->set_fp(fp);
   sample->set_lr(lr);
 
   ProfilerNativeStackWalker native_stack_walker(sample,
@@ -1075,7 +1034,208 @@
                 &native_stack_walker,
                 &dart_exit_stack_walker,
                 &dart_stack_walker,
-                pc);
+                pc,
+                fp,
+                sp);
+}
+
+
+ProcessedSampleBuffer* SampleBuffer::BuildProcessedSampleBuffer(
+    SampleFilter* filter) {
+  ASSERT(filter != NULL);
+  Thread* thread = Thread::Current();
+  Zone* zone = thread->zone();
+
+  ProcessedSampleBuffer* buffer = new(zone) ProcessedSampleBuffer();
+
+  const intptr_t length = capacity();
+  for (intptr_t i = 0; i < length; i++) {
+    Sample* sample = At(i);
+    if (sample->ignore_sample()) {
+      // Bad sample.
+      continue;
+    }
+    if (sample->isolate() != filter->isolate()) {
+      // Another isolate.
+      continue;
+    }
+    if (sample->timestamp() == 0) {
+      // Empty.
+      continue;
+    }
+    if (sample->At(0) == 0) {
+      // No frames.
+      continue;
+    }
+    if (!filter->FilterSample(sample)) {
+      // Did not pass filter.
+      continue;
+    }
+    buffer->Add(BuildProcessedSample(sample));
+  }
+  return buffer;
+}
+
+
+ProcessedSample* SampleBuffer::BuildProcessedSample(Sample* sample) {
+  Thread* thread = Thread::Current();
+  Zone* zone = thread->zone();
+
+  ProcessedSample* processed_sample = new(zone) ProcessedSample();
+
+  // Copy state bits from sample.
+  processed_sample->set_timestamp(sample->timestamp());
+  processed_sample->set_vm_tag(sample->vm_tag());
+  processed_sample->set_user_tag(sample->user_tag());
+  if (sample->is_allocation_sample()) {
+    processed_sample->set_allocation_cid(sample->allocation_cid());
+  }
+  processed_sample->set_first_frame_executing(!sample->exit_frame_sample());
+
+  // Copy stack trace from sample(s).
+  bool truncated = false;
+  Sample* current = sample;
+  while (current != NULL) {
+    for (intptr_t i = 0; i < FLAG_profile_depth; i++) {
+      if (current->At(i) == 0) {
+        break;
+      }
+      processed_sample->Add(current->At(i));
+    }
+
+    truncated = truncated || current->truncated_trace();
+    current = Next(sample);
+  }
+
+  if (!sample->exit_frame_sample()) {
+    Isolate* isolate = thread->isolate();
+    Isolate* vm_isolate = Dart::vm_isolate();
+    processed_sample->FixupCaller(isolate,
+                                  vm_isolate,
+                                  sample->pc_marker(),
+                                  sample->GetStackBuffer());
+  }
+
+  processed_sample->set_truncated(truncated);
+  return processed_sample;
+}
+
+
+Sample* SampleBuffer::Next(Sample* sample) {
+  // TODO(johnmccutchan): Support chaining samples for complete stack traces.
+  return NULL;
+}
+
+
+ProcessedSample::ProcessedSample()
+    : pcs_(FLAG_profile_depth),
+      timestamp_(0),
+      vm_tag_(0),
+      user_tag_(0),
+      allocation_cid_(-1),
+      truncated_(false) {
+}
+
+
+void ProcessedSample::FixupCaller(Isolate* isolate,
+                                  Isolate* vm_isolate,
+                                  uword pc_marker,
+                                  uword* stack_buffer) {
+  REUSABLE_CODE_HANDLESCOPE(isolate);
+  // Lookup code object for leaf frame.
+  Code& code = reused_code_handle.Handle();
+  code = FindCodeForPC(isolate, vm_isolate, At(0));
+  if (code.IsNull()) {
+    return;
+  }
+  if (code.compile_timestamp() > timestamp()) {
+    // Code compiled after sample. Ignore.
+    return;
+  }
+  CheckForMissingDartFrame(isolate, vm_isolate, code, pc_marker, stack_buffer);
+}
+
+
+void ProcessedSample::CheckForMissingDartFrame(Isolate* isolate,
+                                               Isolate* vm_isolate,
+                                               const Code& code,
+                                               uword pc_marker,
+                                               uword* stack_buffer) {
+  // Some stubs (and intrinsics) do not push a frame onto the stack leaving
+  // the frame pointer in the caller.
+  //
+  // PC -> STUB
+  // FP -> DART3  <-+
+  //       DART2  <-|  <- TOP FRAME RETURN ADDRESS.
+  //       DART1  <-|
+  //       .....
+  //
+  // In this case, traversing the linked stack frames will not collect a PC
+  // inside DART3. The stack will incorrectly be: STUB, DART2, DART1.
+  // In Dart code, after pushing the FP onto the stack, an IP in the current
+  // function is pushed onto the stack as well. This stack slot is called
+  // the PC marker. We can use the PC marker to insert DART3 into the stack
+  // so that it will correctly be: STUB, DART3, DART2, DART1. Note the
+  // inserted PC may not accurately reflect the true return address into DART3.
+  ASSERT(!code.IsNull());
+
+  // The pc marker is our current best guess of a return address.
+  uword return_address = pc_marker;
+
+  // Attempt to find a better return address.
+  ReturnAddressLocator ral(At(0), stack_buffer, code);
+
+  if (!ral.LocateReturnAddress(&return_address)) {
+    ASSERT(return_address == pc_marker);
+    if (code.GetPrologueOffset() == 0) {
+      // Code has the prologue at offset 0. The frame is already setup and
+      // can be trusted.
+      return;
+    }
+    // Could not find a better return address than the pc_marker.
+    if (code.ContainsInstructionAt(return_address)) {
+      // PC marker is in the same code as pc, no missing frame.
+      return;
+    }
+  }
+
+  if (!ContainedInDartCodeHeaps(isolate, vm_isolate, return_address)) {
+    // return address is not from the Dart heap. Do not insert.
+    return;
+  }
+
+  if (return_address != 0) {
+    InsertAt(1, return_address);
+  }
+}
+
+
+RawCode* ProcessedSample::FindCodeForPC(Isolate* isolate,
+                                        Isolate* vm_isolate,
+                                        uword pc) {
+  // Check current isolate for pc.
+  if (isolate->heap()->CodeContains(pc)) {
+    return Code::LookupCode(pc);
+  }
+
+  // Check VM isolate for pc.
+  if (vm_isolate->heap()->CodeContains(pc)) {
+    return Code::LookupCodeInVmIsolate(pc);
+  }
+
+  return Code::null();
+}
+
+
+bool ProcessedSample::ContainedInDartCodeHeaps(Isolate* isolate,
+                                               Isolate* vm_isolate,
+                                               uword pc) {
+  return vm_isolate->heap()->CodeContains(pc)
+         || isolate->heap()->CodeContains(pc);
+}
+
+
+ProcessedSampleBuffer::ProcessedSampleBuffer() {
 }
 
 }  // namespace dart
diff --git a/runtime/vm/profiler.h b/runtime/vm/profiler.h
index 03d632e..b4a4d0b 100644
--- a/runtime/vm/profiler.h
+++ b/runtime/vm/profiler.h
@@ -9,6 +9,7 @@
 #include "vm/bitfield.h"
 #include "vm/code_observers.h"
 #include "vm/globals.h"
+#include "vm/growable_array.h"
 #include "vm/tags.h"
 #include "vm/thread_interrupter.h"
 
@@ -18,10 +19,12 @@
 namespace dart {
 
 // Forward declarations.
+class ProcessedSample;
+class ProcessedSampleBuffer;
+
 class Sample;
 class SampleBuffer;
 
-
 class Profiler : public AllStatic {
  public:
   static void InitOnce();
@@ -41,6 +44,8 @@
     return sample_buffer_;
   }
 
+  static void RecordAllocation(Isolate* isolate, intptr_t cid);
+
  private:
   static bool initialized_;
   static Monitor* monitor_;
@@ -107,24 +112,23 @@
 };
 
 
-class PreprocessVisitor : public SampleVisitor {
+class SampleFilter : public ValueObject {
  public:
-  explicit PreprocessVisitor(Isolate* isolate);
+  explicit SampleFilter(Isolate* isolate) : isolate_(isolate) { }
+  virtual ~SampleFilter() { }
 
-  virtual void VisitSample(Sample* sample);
-
- private:
-  void CheckForMissingDartFrame(const Code& code, Sample* sample) const;
-
-  bool ContainedInDartCodeHeaps(uword pc) const;
-
-  Isolate* vm_isolate() const {
-    return vm_isolate_;
+  // Override this function.
+  // Return |true| if |sample| passes the filter.
+  virtual bool FilterSample(Sample* sample) {
+    return true;
   }
 
-  RawCode* FindCodeForPC(uword pc) const;
+  Isolate* isolate() const {
+    return isolate_;
+  }
 
-  Isolate* vm_isolate_;
+ private:
+  Isolate* isolate_;
 };
 
 
@@ -159,9 +163,8 @@
     }
     vm_tag_ = VMTag::kInvalidTagId;
     user_tag_ = UserTags::kDefaultUserTag;
-    sp_ = 0;
     lr_ = 0;
-    fp_ = 0;
+    metadata_ = 0;
     state_ = 0;
     uword* pcs = GetPCArray();
     for (intptr_t i = 0; i < pcs_length_; i++) {
@@ -218,22 +221,6 @@
     pc_marker_ = pc_marker;
   }
 
-  uword sp() const {
-    return sp_;
-  }
-
-  void set_sp(uword sp) {
-    sp_ = sp;
-  }
-
-  uword fp() const {
-    return fp_;
-  }
-
-  void set_fp(uword fp) {
-    fp_ = fp;
-  }
-
   uword lr() const {
     return lr_;
   }
@@ -306,6 +293,28 @@
     state_ = TruncatedTraceBit::update(truncated_trace, state_);
   }
 
+  bool is_allocation_sample() const {
+    return ClassAllocationSampleBit::decode(state_);
+  }
+
+  void set_is_allocation_sample(bool allocation_sample) {
+    state_ = ClassAllocationSampleBit::update(allocation_sample, state_);
+  }
+
+  intptr_t allocation_cid() const {
+    ASSERT(is_allocation_sample());
+    return metadata_;
+  }
+
+  void set_metadata(intptr_t metadata) {
+    metadata_ = metadata;
+  }
+
+  void SetAllocationCid(intptr_t cid) {
+    set_is_allocation_sample(true);
+    set_metadata(cid);
+  }
+
   static void InitOnce();
 
   static intptr_t instance_size() {
@@ -329,6 +338,7 @@
     kExitFrameBit = 3,
     kMissingFrameInsertedBit = 4,
     kTruncatedTrace = 5,
+    kClassAllocationSample = 6,
   };
   class ProcessedBit : public BitField<bool, kProcessedBit, 1> {};
   class LeafFrameIsDart : public BitField<bool, kLeafFrameIsDartBit, 1> {};
@@ -337,6 +347,8 @@
   class MissingFrameInsertedBit
     : public BitField<bool, kMissingFrameInsertedBit, 1> {};
   class TruncatedTraceBit : public BitField<bool, kTruncatedTrace, 1> {};
+  class ClassAllocationSampleBit
+      : public BitField<bool, kClassAllocationSample, 1> {};
 
   int64_t timestamp_;
   ThreadId tid_;
@@ -345,8 +357,7 @@
   uword stack_buffer_[kStackBufferSizeInWords];
   uword vm_tag_;
   uword user_tag_;
-  uword sp_;
-  uword fp_;
+  uword metadata_;
   uword lr_;
   uword state_;
 
@@ -404,7 +415,12 @@
     }
   }
 
+  ProcessedSampleBuffer* BuildProcessedSampleBuffer(SampleFilter* filter);
+
  private:
+  ProcessedSample* BuildProcessedSample(Sample* sample);
+  Sample* Next(Sample* sample);
+
   Sample* samples_;
   intptr_t capacity_;
   uintptr_t cursor_;
@@ -413,6 +429,115 @@
 };
 
 
+// A |ProcessedSample| is a combination of 1 (or more) |Sample|(s) that have
+// been merged into a logical sample. The raw data may have been processed to
+// improve the quality of the stack trace.
+class ProcessedSample : public ZoneAllocated {
+ public:
+  ProcessedSample();
+
+  // Add |pc| to stack trace.
+  void Add(uword pc) {
+    pcs_.Add(pc);
+  }
+
+  // Insert |pc| at |index|.
+  void InsertAt(intptr_t index, uword pc) {
+    pcs_.InsertAt(index, pc);
+  }
+
+  // Number of pcs in stack trace.
+  intptr_t length() const { return pcs_.length(); }
+
+  // Get |pc| at |index|.
+  uword At(intptr_t index) const {
+    ASSERT(index >= 0);
+    ASSERT(index < length());
+    return pcs_[index];
+  }
+
+  // Timestamp sample was taken at.
+  int64_t timestamp() const { return timestamp_; }
+  void set_timestamp(int64_t timestamp) { timestamp_ = timestamp; }
+
+  // The VM tag.
+  uword vm_tag() const { return vm_tag_; }
+  void set_vm_tag(uword tag) { vm_tag_ = tag; }
+
+  // The user tag.
+  uword user_tag() const { return user_tag_; }
+  void set_user_tag(uword tag) { user_tag_ = tag; }
+
+  // The class id if this is an allocation profile sample. -1 otherwise.
+  intptr_t allocation_cid() const { return allocation_cid_; }
+  void set_allocation_cid(intptr_t cid) { allocation_cid_ = cid; }
+
+  // Was the stack trace truncated?
+  bool truncated() const { return truncated_; }
+  void set_truncated(bool truncated) { truncated_ = truncated; }
+
+  // Was the first frame in the stack trace executing?
+  bool first_frame_executing() const { return first_frame_executing_; }
+  void set_first_frame_executing(bool first_frame_executing) {
+    first_frame_executing_ = first_frame_executing;
+  }
+
+ private:
+  void FixupCaller(Isolate* isolate,
+                   Isolate* vm_isolate,
+                   uword pc_marker,
+                   uword* stack_buffer);
+
+  void CheckForMissingDartFrame(Isolate* isolate,
+                                Isolate* vm_isolate,
+                                const Code& code,
+                                uword pc_marker,
+                                uword* stack_buffer);
+
+  static RawCode* FindCodeForPC(Isolate* isolate,
+                                Isolate* vm_isolate,
+                                uword pc);
+
+  static bool ContainedInDartCodeHeaps(Isolate* isolate,
+                                       Isolate* vm_isolate,
+                                       uword pc);
+
+  ZoneGrowableArray<uword> pcs_;
+  int64_t timestamp_;
+  uword vm_tag_;
+  uword user_tag_;
+  intptr_t allocation_cid_;
+  bool truncated_;
+  bool first_frame_executing_;
+
+  friend class SampleBuffer;
+  DISALLOW_COPY_AND_ASSIGN(ProcessedSample);
+};
+
+
+// A collection of |ProcessedSample|s.
+class ProcessedSampleBuffer : public ZoneAllocated {
+ public:
+  ProcessedSampleBuffer();
+
+  void Add(ProcessedSample* sample) {
+    samples_.Add(sample);
+  }
+
+  intptr_t length() const {
+    return samples_.length();
+  }
+
+  ProcessedSample* At(intptr_t index) {
+    return samples_.At(index);
+  }
+
+ private:
+  ZoneGrowableArray<ProcessedSample*> samples_;
+
+  DISALLOW_COPY_AND_ASSIGN(ProcessedSampleBuffer);
+};
+
 }  // namespace dart
 
 #endif  // VM_PROFILER_H_
diff --git a/runtime/vm/profiler_service.cc b/runtime/vm/profiler_service.cc
index 9fd95f2..188d7cd 100644
--- a/runtime/vm/profiler_service.cc
+++ b/runtime/vm/profiler_service.cc
@@ -384,7 +384,6 @@
         inclusive_tick_serial_(0),
         name_(NULL),
         compile_timestamp_(timestamp),
-        creation_serial_(0),
         code_(Code::ZoneHandle(code.raw())),
         profile_function_(NULL),
         code_table_index_(-1) {
@@ -425,10 +424,6 @@
            contains(other->end() - 1);
   }
 
-  intptr_t creation_serial() const { return creation_serial_; }
-  void set_creation_serial(intptr_t serial) {
-    creation_serial_ = serial;
-  }
   int64_t compile_timestamp() const { return compile_timestamp_; }
   void set_compile_timestamp(int64_t timestamp) {
     compile_timestamp_ = timestamp;
@@ -563,11 +558,10 @@
   }
 
   void DebugPrint() const {
-    OS::Print("%s [%" Px ", %" Px ") %" Pd " %" Pd64 "\n",
+    OS::Print("%s [%" Px ", %" Px ") %" Pd64 "\n",
               KindToCString(kind_),
               start(),
               end(),
-              creation_serial_,
               compile_timestamp_);
   }
 
@@ -739,8 +733,6 @@
   const char* name_;
   // The compilation timestamp associated with this code region.
   int64_t compile_timestamp_;
-  // Serial number at which this CodeRegion was created.
-  intptr_t creation_serial_;
   // Dart code object (may be null).
   const Code& code_;
   // Pointer to ProfileFunction.
@@ -766,7 +758,9 @@
   }
 
   // Ticks the CodeRegion containing pc if it is alive at timestamp.
-  TickResult Tick(uword pc, bool exclusive, intptr_t serial,
+  TickResult Tick(uword pc,
+                  bool exclusive,
+                  intptr_t serial,
                   int64_t timestamp) {
     intptr_t index = FindIndex(pc);
     if (index < 0) {
@@ -950,15 +944,14 @@
 };
 
 
-class CodeRegionTableBuilder : public SampleVisitor {
+class CodeRegionTableBuilder {
  public:
   CodeRegionTableBuilder(Isolate* isolate,
                          CodeRegionTable* live_code_table,
                          CodeRegionTable* dead_code_table,
                          CodeRegionTable* tag_code_table,
                          DeoptimizedCodeSet* deoptimized_code)
-      : SampleVisitor(isolate),
-        live_code_table_(live_code_table),
+      : live_code_table_(live_code_table),
         dead_code_table_(dead_code_table),
         tag_code_table_(tag_code_table),
         isolate_(isolate),
@@ -976,34 +969,10 @@
     max_time_ = 0;
   }
 
-  void VisitSample(Sample* sample) {
-    int64_t timestamp = sample->timestamp();
-    if (timestamp > max_time_) {
-      max_time_ = timestamp;
-    }
-    if (timestamp < min_time_) {
-      min_time_ = timestamp;
-    }
-    // Make sure VM tag is created.
-    if (VMTag::IsNativeEntryTag(sample->vm_tag())) {
-      CreateTag(VMTag::kNativeTagId);
-    } else if (VMTag::IsRuntimeEntryTag(sample->vm_tag())) {
-      CreateTag(VMTag::kRuntimeTagId);
-    }
-    CreateTag(sample->vm_tag());
-    // Make sure user tag is created.
-    CreateUserTag(sample->user_tag());
-    // Exclusive tick for top frame if we aren't sampled from an exit frame.
-    if (!sample->exit_frame_sample()) {
-      Tick(sample->At(0), true, timestamp);
-    }
-    // Inclusive tick for all frames.
-    for (intptr_t i = 0; i < FLAG_profile_depth; i++) {
-      if (sample->At(i) == 0) {
-        break;
-      }
-      frames_++;
-      Tick(sample->At(i), false, timestamp);
+  void Build(ProcessedSampleBuffer* buffer) {
+    for (intptr_t i = 0; i < buffer->length(); i++) {
+      ProcessedSample* sample = buffer->At(i);
+      VisitSample(i, sample);
     }
   }
 
@@ -1015,6 +984,39 @@
   int64_t  max_time() const { return max_time_; }
 
  private:
+  void VisitSample(intptr_t serial, ProcessedSample* sample) {
+    int64_t timestamp = sample->timestamp();
+    if (timestamp > max_time_) {
+      max_time_ = timestamp;
+    }
+    if (timestamp < min_time_) {
+      min_time_ = timestamp;
+    }
+
+    // Make sure VM tag is created.
+    if (VMTag::IsNativeEntryTag(sample->vm_tag())) {
+      CreateTag(VMTag::kNativeTagId);
+    } else if (VMTag::IsRuntimeEntryTag(sample->vm_tag())) {
+      CreateTag(VMTag::kRuntimeTagId);
+    }
+    CreateTag(sample->vm_tag());
+
+    // Make sure user tag is created.
+    CreateUserTag(sample->user_tag());
+
+    // Exclusive tick for top frame if the first frame was executing.
+    if (!sample->first_frame_executing()) {
+      Tick(sample->At(0), true, serial, timestamp);
+    }
+
+    // Inclusive tick for all frames.
+    for (intptr_t i = 0; i < sample->length(); i++) {
+      ASSERT(sample->At(i) != 0);
+      frames_++;
+      Tick(sample->At(i), false, serial, timestamp);
+    }
+  }
+
   void CreateTag(uword tag) {
     intptr_t index = tag_code_table_->FindIndex(tag);
     if (index >= 0) {
@@ -1028,7 +1030,6 @@
                                         null_code_);
     index = tag_code_table_->InsertCodeRegion(region);
     ASSERT(index >= 0);
-    region->set_creation_serial(visited());
   }
 
   void CreateUserTag(uword tag) {
@@ -1039,14 +1040,19 @@
     return CreateTag(tag);
   }
 
-  void Tick(uword pc, bool exclusive, int64_t timestamp) {
+  void Tick(uword pc, bool exclusive, intptr_t serial, int64_t timestamp) {
     CodeRegionTable::TickResult r;
-    intptr_t serial = exclusive ? -1 : visited();
+    if (exclusive) {
+      // Exclusive ticks do not have an associated serial.
+      serial = -1;
+    }
+
     r = live_code_table_->Tick(pc, exclusive, serial, timestamp);
     if (r == CodeRegionTable::kTicked) {
       // Live code found and ticked.
       return;
     }
+
     if (r == CodeRegionTable::kNewerCode) {
       // Code has been overwritten by newer code.
       // Update shadow table of dead code regions.
@@ -1060,10 +1066,10 @@
       CreateAndTickDeadCodeRegion(pc, exclusive, serial);
       return;
     }
+
     // Create new live CodeRegion.
     ASSERT(r == CodeRegionTable::kNotFound);
     CodeRegion* region = CreateCodeRegion(pc);
-    region->set_creation_serial(visited());
     intptr_t index = live_code_table_->InsertCodeRegion(region);
     ASSERT(index >= 0);
     region = live_code_table_->At(index);
@@ -1071,6 +1077,7 @@
       region->Tick(pc, exclusive, serial);
       return;
     }
+
     // We have created a new code region but it's for a CodeRegion
     // compiled after the sample.
     ASSERT(region->kind() == CodeRegion::kDartCode);
@@ -1085,7 +1092,6 @@
                                         0,
                                         null_code_);
     intptr_t index = dead_code_table_->InsertCodeRegion(region);
-    region->set_creation_serial(visited());
     ASSERT(index >= 0);
     dead_code_table_->At(index)->Tick(pc, exclusive, serial);
   }
@@ -1094,6 +1100,7 @@
     const intptr_t kDartCodeAlignment = OS::PreferredCodeAlignment();
     const intptr_t kDartCodeAlignmentMask = ~(kDartCodeAlignment - 1);
     Code& code = Code::Handle(isolate_);
+
     // Check current isolate for pc.
     if (isolate_->heap()->CodeContains(pc)) {
       code ^= Code::LookupCode(pc);
@@ -1111,6 +1118,7 @@
                             0,
                             code);
     }
+
     // Check VM isolate for pc.
     if (vm_isolate_->heap()->CodeContains(pc)) {
       code ^= Code::LookupCodeInVmIsolate(pc);
@@ -1127,6 +1135,7 @@
                             0,
                             code);
     }
+
     // Check NativeSymbolResolver for pc.
     uintptr_t native_start = 0;
     char* native_name = NativeSymbolResolver::LookupSymbolName(pc,
@@ -1198,7 +1207,6 @@
                        null_code);
     truncated_index = tag_code_table_->InsertCodeRegion(truncated);
     ASSERT(truncated_index >= 0);
-    truncated->set_creation_serial(0);
 
     // Create the root tag.
     intptr_t root_index = tag_code_table_->FindIndex(VMTag::kRootTagId);
@@ -1210,7 +1218,6 @@
                                       null_code);
     root_index = tag_code_table_->InsertCodeRegion(root);
     ASSERT(root_index >= 0);
-    root->set_creation_serial(0);
   }
 
   void Map() {
@@ -1409,24 +1416,116 @@
 };
 
 
-class ProfileFunctionTrieBuilder : public SampleVisitor {
+class TrieBuilder : public ValueObject {
  public:
-  ProfileFunctionTrieBuilder(Isolate* isolate,
-                             CodeRegionTable* live_code_table,
-                             CodeRegionTable* dead_code_table,
-                             CodeRegionTable* tag_code_table,
-                             ProfileFunctionTable* function_table)
-      : SampleVisitor(isolate),
-        live_code_table_(live_code_table),
+  TrieBuilder(CodeRegionTable* live_code_table,
+              CodeRegionTable* dead_code_table,
+              CodeRegionTable* tag_code_table)
+      : live_code_table_(live_code_table),
         dead_code_table_(dead_code_table),
-        tag_code_table_(tag_code_table),
-        function_table_(function_table),
-        inclusive_tree_(false),
-        trace_(false),
-        trace_code_filter_(NULL) {
+        tag_code_table_(tag_code_table) {
     ASSERT(live_code_table_ != NULL);
     ASSERT(dead_code_table_ != NULL);
     ASSERT(tag_code_table_ != NULL);
+  }
+
+  ProfilerService::TagOrder tag_order() const {
+    return tag_order_;
+  }
+
+  void set_tag_order(ProfilerService::TagOrder tag_order) {
+    tag_order_ = tag_order;
+  }
+
+ protected:
+  intptr_t FindTagIndex(uword tag) const {
+    if (tag == 0) {
+      UNREACHABLE();
+      return -1;
+    }
+    intptr_t index = tag_code_table_->FindIndex(tag);
+    if (index < 0) {
+      UNREACHABLE();
+      return -1;
+    }
+    ASSERT(index >= 0);
+    CodeRegion* region = tag_code_table_->At(index);
+    ASSERT(region->contains(tag));
+    return region->code_table_index();
+  }
+
+  intptr_t FindDeadIndex(uword pc, int64_t timestamp) const {
+    intptr_t index = dead_code_table_->FindIndex(pc);
+    if (index < 0) {
+      OS::Print("%" Px " cannot be found\n", pc);
+      return -1;
+    }
+    CodeRegion* region = dead_code_table_->At(index);
+    ASSERT(region->contains(pc));
+    ASSERT(region->compile_timestamp() <= timestamp);
+    return region->code_table_index();
+  }
+
+  intptr_t FindFinalIndex(uword pc, int64_t timestamp) const {
+    intptr_t index = live_code_table_->FindIndex(pc);
+    if (index < 0) {
+      // Try dead code table.
+      return FindDeadIndex(pc, timestamp);
+    }
+    CodeRegion* region = live_code_table_->At(index);
+    ASSERT(region->contains(pc));
+    if (region->compile_timestamp() > timestamp) {
+      // Overwritten code, find in dead code table.
+      return FindDeadIndex(pc, timestamp);
+    }
+    ASSERT(region->compile_timestamp() <= timestamp);
+    return region->code_table_index();
+  }
+
+  bool vm_tags_emitted() const {
+    return (tag_order_ == ProfilerService::kUserVM) ||
+           (tag_order_ == ProfilerService::kVMUser) ||
+           (tag_order_ == ProfilerService::kVM);
+  }
+
+  CodeRegion* FindCodeObject(uword pc, int64_t timestamp) const {
+    intptr_t index = live_code_table_->FindIndex(pc);
+    if (index < 0) {
+      return NULL;
+    }
+    CodeRegion* region = live_code_table_->At(index);
+    ASSERT(region->contains(pc));
+    if (region->compile_timestamp() > timestamp) {
+      // Overwritten code, find in dead code table.
+      index = dead_code_table_->FindIndex(pc);
+      if (index < 0) {
+        return NULL;
+      }
+      region = dead_code_table_->At(index);
+      ASSERT(region->contains(pc));
+      ASSERT(region->compile_timestamp() <= timestamp);
+      return region;
+    }
+    ASSERT(region->compile_timestamp() <= timestamp);
+    return region;
+  }
+
+  CodeRegionTable* live_code_table_;
+  CodeRegionTable* dead_code_table_;
+  CodeRegionTable* tag_code_table_;
+  ProfilerService::TagOrder tag_order_;
+};
+
+
+class ProfileFunctionTrieBuilder : public TrieBuilder {
+ public:
+  ProfileFunctionTrieBuilder(CodeRegionTable* live_code_table,
+                             CodeRegionTable* dead_code_table,
+                             CodeRegionTable* tag_code_table,
+                             ProfileFunctionTable* function_table)
+      : TrieBuilder(live_code_table, dead_code_table, tag_code_table),
+        function_table_(function_table),
+        inclusive_tree_(false) {
     ASSERT(function_table_ != NULL);
     set_tag_order(ProfilerService::kUserVM);
 
@@ -1447,11 +1546,18 @@
     inclusive_root_ = new ProfileFunctionTrieNode(function->index());
   }
 
-  void VisitSample(Sample* sample) {
+  void VisitSample(intptr_t sample_idx, ProcessedSample* sample) {
     inclusive_tree_ = false;
-    ProcessSampleExclusive(sample);
+    ProcessSampleExclusive(sample_idx, sample);
     inclusive_tree_ = true;
-    ProcessSampleInclusive(sample);
+    ProcessSampleInclusive(sample_idx, sample);
+  }
+
+  void Build(ProcessedSampleBuffer* buffer) {
+    for (intptr_t i = 0; i < buffer->length(); i++) {
+      ProcessedSample* sample = buffer->At(i);
+      VisitSample(i, sample);
+    }
   }
 
   ProfileFunctionTrieNode* exclusive_root() const {
@@ -1477,56 +1583,50 @@
   }
 
  private:
-  void ProcessSampleInclusive(Sample* sample) {
+  void ProcessSampleInclusive(intptr_t sample_idx, ProcessedSample* sample) {
     // Give the root a tick.
     inclusive_root_->Tick();
     ProfileFunctionTrieNode* current = inclusive_root_;
     current = AppendTags(sample, current);
-    if (sample->truncated_trace()) {
+    if (sample->truncated()) {
       InclusiveTickTruncatedTag();
       current = AppendTruncatedTag(current);
     }
     // Walk the sampled PCs.
-    for (intptr_t i = FLAG_profile_depth - 1; i >= 0; i--) {
-      if (sample->At(i) == 0) {
-        continue;
-      }
+    for (intptr_t i = sample->length() - 1; i >= 0; i--) {
+      ASSERT(sample->At(i) != 0);
       current = ProcessPC(sample->At(i),
                           sample->timestamp(),
                           current,
-                          visited(),
+                          sample_idx,
                           (i == 0),
-                          sample->exit_frame_sample() && (i == 0),
-                          sample->missing_frame_inserted());
+                          !sample->first_frame_executing() && (i == 0));
     }
   }
 
-  void ProcessSampleExclusive(Sample* sample) {
+  void ProcessSampleExclusive(intptr_t sample_idx, ProcessedSample* sample) {
     // Give the root a tick.
     exclusive_root_->Tick();
     ProfileFunctionTrieNode* current = exclusive_root_;
     current = AppendTags(sample, current);
     // Walk the sampled PCs.
-    for (intptr_t i = 0; i < FLAG_profile_depth; i++) {
-      if (sample->At(i) == 0) {
-        break;
-      }
+    for (intptr_t i = 0; i < sample->length(); i++) {
+      ASSERT(sample->At(i) != 0);
       current = ProcessPC(sample->At(i),
                           sample->timestamp(),
                           current,
-                          visited(),
+                          sample_idx,
                           (i == 0),
-                          sample->exit_frame_sample() && (i == 0),
-                          sample->missing_frame_inserted());
+                          !sample->first_frame_executing() && (i == 0));
     }
-    if (sample->truncated_trace()) {
+    if (sample->truncated()) {
       current = AppendTruncatedTag(current);
     }
   }
 
-  ProfileFunctionTrieNode* AppendUserTag(Sample* sample,
+  ProfileFunctionTrieNode* AppendUserTag(ProcessedSample* sample,
                                          ProfileFunctionTrieNode* current) {
-    intptr_t user_tag_index = FindTagIndex(sample->user_tag());
+    intptr_t user_tag_index = FindTagFunctionIndex(sample->user_tag());
     if (user_tag_index >= 0) {
       current = current->GetChild(user_tag_index);
       // Give the tag a tick.
@@ -1538,7 +1638,7 @@
 
   ProfileFunctionTrieNode* AppendTruncatedTag(
       ProfileFunctionTrieNode* current) {
-    intptr_t truncated_tag_index = FindTagIndex(VMTag::kTruncatedTagId);
+    intptr_t truncated_tag_index = FindTagFunctionIndex(VMTag::kTruncatedTagId);
     ASSERT(truncated_tag_index >= 0);
     current = current->GetChild(truncated_tag_index);
     current->Tick();
@@ -1552,22 +1652,22 @@
     function->inc_inclusive_ticks();
   }
 
-  ProfileFunctionTrieNode* AppendVMTag(Sample* sample,
+  ProfileFunctionTrieNode* AppendVMTag(ProcessedSample* sample,
                                        ProfileFunctionTrieNode* current) {
     if (VMTag::IsNativeEntryTag(sample->vm_tag())) {
       // Insert a dummy kNativeTagId node.
-      intptr_t tag_index = FindTagIndex(VMTag::kNativeTagId);
+      intptr_t tag_index = FindTagFunctionIndex(VMTag::kNativeTagId);
       current = current->GetChild(tag_index);
       // Give the tag a tick.
       current->Tick();
     } else if (VMTag::IsRuntimeEntryTag(sample->vm_tag())) {
       // Insert a dummy kRuntimeTagId node.
-      intptr_t tag_index = FindTagIndex(VMTag::kRuntimeTagId);
+      intptr_t tag_index = FindTagFunctionIndex(VMTag::kRuntimeTagId);
       current = current->GetChild(tag_index);
       // Give the tag a tick.
       current->Tick();
     } else {
-      intptr_t tag_index = FindTagIndex(sample->vm_tag());
+      intptr_t tag_index = FindTagFunctionIndex(sample->vm_tag());
       current = current->GetChild(tag_index);
       // Give the tag a tick.
       current->Tick();
@@ -1576,27 +1676,27 @@
   }
 
   ProfileFunctionTrieNode* AppendSpecificNativeRuntimeEntryVMTag(
-      Sample* sample, ProfileFunctionTrieNode* current) {
+      ProcessedSample* sample, ProfileFunctionTrieNode* current) {
     // Only Native and Runtime entries have a second VM tag.
     if (!VMTag::IsNativeEntryTag(sample->vm_tag()) &&
         !VMTag::IsRuntimeEntryTag(sample->vm_tag())) {
       return current;
     }
-    intptr_t tag_index = FindTagIndex(sample->vm_tag());
+    intptr_t tag_index = FindTagFunctionIndex(sample->vm_tag());
     current = current->GetChild(tag_index);
     // Give the tag a tick.
     current->Tick();
     return current;
   }
 
-  ProfileFunctionTrieNode* AppendVMTags(Sample* sample,
+  ProfileFunctionTrieNode* AppendVMTags(ProcessedSample* sample,
                                         ProfileFunctionTrieNode* current) {
     current = AppendVMTag(sample, current);
     current = AppendSpecificNativeRuntimeEntryVMTag(sample, current);
     return current;
   }
 
-  ProfileFunctionTrieNode* AppendTags(Sample* sample,
+  ProfileFunctionTrieNode* AppendTags(ProcessedSample* sample,
                                       ProfileFunctionTrieNode* current) {
     // None.
     if (tag_order() == ProfilerService::kNoTags) {
@@ -1623,7 +1723,7 @@
     return AppendUserTag(sample, current);
   }
 
-  intptr_t FindTagIndex(uword tag) const {
+  intptr_t FindTagFunctionIndex(uword tag) const {
     if (tag == 0) {
       UNREACHABLE();
       return -1;
@@ -1653,8 +1753,7 @@
                                      ProfileFunctionTrieNode* current,
                                      intptr_t inclusive_serial,
                                      bool top_frame,
-                                     bool exit_frame,
-                                     bool missing_frame_inserted) {
+                                     bool exit_frame) {
     CodeRegion* region = FindCodeObject(pc, timestamp);
     if (region == NULL) {
       return current;
@@ -1674,23 +1773,12 @@
       // No inlined functions.
       ProfileFunction* function = region->function();
       ASSERT(function != NULL);
-      if (trace_) {
-        OS::Print("[%" Px "] X - %s (%s)\n",
-                  pc, function->name(), region_name);
-      }
       current = ProcessFunction(function,
                                 current,
                                 inclusive_serial,
                                 top_frame,
                                 exit_frame,
                                 code_index);
-      if ((trace_code_filter_ != NULL) &&
-          (strstr(region_name, trace_code_filter_) != NULL)) {
-        trace_ = true;
-        OS::Print("Tracing from: %" Px " [%s] ", pc,
-                  missing_frame_inserted ? "INSERTED" : "");
-        Dump(current);
-      }
       return current;
     }
 
@@ -1712,11 +1800,6 @@
         Function* inlined_function = inlined_functions[i];
         ASSERT(inlined_function != NULL);
         ASSERT(!inlined_function->IsNull());
-        const char* inline_name = inlined_function->ToQualifiedCString();
-        if (trace_) {
-          OS::Print("[%" Px "] %" Pd " - %s (%s)\n",
-                  pc, i, inline_name, region_name);
-        }
         current = ProcessInlinedFunction(inlined_function,
                                          current,
                                          inclusive_serial,
@@ -1724,13 +1807,6 @@
                                          exit_frame,
                                          code_index);
         top_frame = false;
-        if ((trace_code_filter_ != NULL) &&
-            (strstr(region_name, trace_code_filter_) != NULL)) {
-          trace_ = true;
-          OS::Print("Tracing from: %" Px " [%s] ",
-                    pc, missing_frame_inserted ? "INSERTED" : "");
-          Dump(current);
-        }
       }
     }
 
@@ -1781,38 +1857,10 @@
     return current;
   }
 
-  CodeRegion* FindCodeObject(uword pc, int64_t timestamp) const {
-    intptr_t index = live_code_table_->FindIndex(pc);
-    if (index < 0) {
-      return NULL;
-    }
-    CodeRegion* region = live_code_table_->At(index);
-    ASSERT(region->contains(pc));
-    if (region->compile_timestamp() > timestamp) {
-      // Overwritten code, find in dead code table.
-      index = dead_code_table_->FindIndex(pc);
-      if (index < 0) {
-        return NULL;
-      }
-      region = dead_code_table_->At(index);
-      ASSERT(region->contains(pc));
-      ASSERT(region->compile_timestamp() <= timestamp);
-      return region;
-    }
-    ASSERT(region->compile_timestamp() <= timestamp);
-    return region;
-  }
-
-  ProfilerService::TagOrder tag_order_;
   ProfileFunctionTrieNode* exclusive_root_;
   ProfileFunctionTrieNode* inclusive_root_;
-  CodeRegionTable* live_code_table_;
-  CodeRegionTable* dead_code_table_;
-  CodeRegionTable* tag_code_table_;
   ProfileFunctionTable* function_table_;
   bool inclusive_tree_;
-  bool trace_;
-  const char* trace_code_filter_;
 };
 
 
@@ -1908,19 +1956,13 @@
 };
 
 
-class CodeRegionTrieBuilder : public SampleVisitor {
+class CodeRegionTrieBuilder : public TrieBuilder {
  public:
   CodeRegionTrieBuilder(Isolate* isolate,
                         CodeRegionTable* live_code_table,
                         CodeRegionTable* dead_code_table,
                         CodeRegionTable* tag_code_table)
-      : SampleVisitor(isolate),
-        live_code_table_(live_code_table),
-        dead_code_table_(dead_code_table),
-        tag_code_table_(tag_code_table) {
-    ASSERT(live_code_table_ != NULL);
-    ASSERT(dead_code_table_ != NULL);
-    ASSERT(tag_code_table_ != NULL);
+      : TrieBuilder(live_code_table, dead_code_table, tag_code_table) {
     set_tag_order(ProfilerService::kUserVM);
 
     // Verify that the truncated tag exists.
@@ -1936,9 +1978,11 @@
     inclusive_root_ = new CodeRegionTrieNode(region->code_table_index());
   }
 
-  void VisitSample(Sample* sample) {
-    ProcessSampleExclusive(sample);
-    ProcessSampleInclusive(sample);
+  void Build(ProcessedSampleBuffer* buffer) {
+    for (intptr_t i = 0; i < buffer->length(); i++) {
+      ProcessedSample* sample = buffer->At(i);
+      VisitSample(sample);
+    }
   }
 
   CodeRegionTrieNode* inclusive_root() const {
@@ -1949,34 +1993,23 @@
     return exclusive_root_;
   }
 
-  ProfilerService::TagOrder tag_order() const {
-    return tag_order_;
-  }
-
-  bool vm_tags_emitted() const {
-    return (tag_order_ == ProfilerService::kUserVM) ||
-           (tag_order_ == ProfilerService::kVMUser) ||
-           (tag_order_ == ProfilerService::kVM);
-  }
-
-  void set_tag_order(ProfilerService::TagOrder tag_order) {
-    tag_order_ = tag_order;
-  }
-
  private:
-  void ProcessSampleInclusive(Sample* sample) {
+  void VisitSample(ProcessedSample* sample) {
+    ProcessSampleExclusive(sample);
+    ProcessSampleInclusive(sample);
+  }
+
+  void ProcessSampleInclusive(ProcessedSample* sample) {
     // Give the root a tick.
     inclusive_root_->Tick();
     CodeRegionTrieNode* current = inclusive_root_;
     current = AppendTags(sample, current);
-    if (sample->truncated_trace()) {
+    if (sample->truncated()) {
       current = AppendTruncatedTag(current);
     }
     // Walk the sampled PCs.
-    for (intptr_t i = FLAG_profile_depth - 1; i >= 0; i--) {
-      if (sample->At(i) == 0) {
-        continue;
-      }
+    for (intptr_t i = sample->length() - 1; i >= 0; i--) {
+      ASSERT(sample->At(i) != 0);
       intptr_t index = FindFinalIndex(sample->At(i), sample->timestamp());
       if (index < 0) {
         continue;
@@ -1986,16 +2019,14 @@
     }
   }
 
-  void ProcessSampleExclusive(Sample* sample) {
+  void ProcessSampleExclusive(ProcessedSample* sample) {
     // Give the root a tick.
     exclusive_root_->Tick();
     CodeRegionTrieNode* current = exclusive_root_;
     current = AppendTags(sample, current);
     // Walk the sampled PCs.
-    for (intptr_t i = 0; i < FLAG_profile_depth; i++) {
-      if (sample->At(i) == 0) {
-        break;
-      }
+    for (intptr_t i = 0; i < sample->length(); i++) {
+      ASSERT(sample->At(i) != 0);
       intptr_t index = FindFinalIndex(sample->At(i), sample->timestamp());
       if (index < 0) {
         continue;
@@ -2003,7 +2034,7 @@
       current = current->GetChild(index);
       if (i == 0) {
         // Executing PC.
-        if (!sample->exit_frame_sample() || vm_tags_emitted()) {
+        if (!sample->first_frame_executing() || vm_tags_emitted()) {
           // Only tick if this isn't an exit frame or VM tags are emitted.
           current->Tick();
         }
@@ -2012,12 +2043,12 @@
         current->Tick();
       }
     }
-    if (sample->truncated_trace()) {
+    if (sample->truncated()) {
       current = AppendTruncatedTag(current);
     }
   }
 
-  CodeRegionTrieNode* AppendUserTag(Sample* sample,
+  CodeRegionTrieNode* AppendUserTag(ProcessedSample* sample,
                                     CodeRegionTrieNode* current) {
     intptr_t user_tag_index = FindTagIndex(sample->user_tag());
     if (user_tag_index >= 0) {
@@ -2036,7 +2067,7 @@
     return current;
   }
 
-  CodeRegionTrieNode* AppendVMTag(Sample* sample,
+  CodeRegionTrieNode* AppendVMTag(ProcessedSample* sample,
                                   CodeRegionTrieNode* current) {
     if (VMTag::IsNativeEntryTag(sample->vm_tag())) {
       // Insert a dummy kNativeTagId node.
@@ -2060,7 +2091,7 @@
   }
 
   CodeRegionTrieNode* AppendSpecificNativeRuntimeEntryVMTag(
-      Sample* sample, CodeRegionTrieNode* current) {
+      ProcessedSample* sample, CodeRegionTrieNode* current) {
     // Only Native and Runtime entries have a second VM tag.
     if (!VMTag::IsNativeEntryTag(sample->vm_tag()) &&
         !VMTag::IsRuntimeEntryTag(sample->vm_tag())) {
@@ -2073,14 +2104,15 @@
     return current;
   }
 
-  CodeRegionTrieNode* AppendVMTags(Sample* sample,
+  CodeRegionTrieNode* AppendVMTags(ProcessedSample* sample,
                                    CodeRegionTrieNode* current) {
     current = AppendVMTag(sample, current);
     current = AppendSpecificNativeRuntimeEntryVMTag(sample, current);
     return current;
   }
 
-  CodeRegionTrieNode* AppendTags(Sample* sample, CodeRegionTrieNode* current) {
+  CodeRegionTrieNode* AppendTags(ProcessedSample* sample,
+                                 CodeRegionTrieNode* current) {
     // None.
     if (tag_order() == ProfilerService::kNoTags) {
       return current;
@@ -2106,56 +2138,20 @@
     return AppendUserTag(sample, current);
   }
 
-  intptr_t FindTagIndex(uword tag) const {
-    if (tag == 0) {
-      UNREACHABLE();
-      return -1;
-    }
-    intptr_t index = tag_code_table_->FindIndex(tag);
-    if (index < 0) {
-      UNREACHABLE();
-      return -1;
-    }
-    ASSERT(index >= 0);
-    CodeRegion* region = tag_code_table_->At(index);
-    ASSERT(region->contains(tag));
-    return region->code_table_index();
-  }
-
-  intptr_t FindDeadIndex(uword pc, int64_t timestamp) const {
-    intptr_t index = dead_code_table_->FindIndex(pc);
-    if (index < 0) {
-      OS::Print("%" Px " cannot be found\n", pc);
-      return -1;
-    }
-    CodeRegion* region = dead_code_table_->At(index);
-    ASSERT(region->contains(pc));
-    ASSERT(region->compile_timestamp() <= timestamp);
-    return region->code_table_index();
-  }
-
-  intptr_t FindFinalIndex(uword pc, int64_t timestamp) const {
-    intptr_t index = live_code_table_->FindIndex(pc);
-    if (index < 0) {
-      // Try dead code table.
-      return FindDeadIndex(pc, timestamp);
-    }
-    CodeRegion* region = live_code_table_->At(index);
-    ASSERT(region->contains(pc));
-    if (region->compile_timestamp() > timestamp) {
-      // Overwritten code, find in dead code table.
-      return FindDeadIndex(pc, timestamp);
-    }
-    ASSERT(region->compile_timestamp() <= timestamp);
-    return region->code_table_index();
-  }
-
-  ProfilerService::TagOrder tag_order_;
   CodeRegionTrieNode* exclusive_root_;
   CodeRegionTrieNode* inclusive_root_;
-  CodeRegionTable* live_code_table_;
-  CodeRegionTable* dead_code_table_;
-  CodeRegionTable* tag_code_table_;
+};
+
+
+class NoAllocationSampleFilter : public SampleFilter {
+ public:
+  explicit NoAllocationSampleFilter(Isolate* isolate)
+      : SampleFilter(isolate) {
+  }
+
+  bool FilterSample(Sample* sample) {
+    return !sample->is_allocation_sample();
+  }
 };
 
 
@@ -2175,6 +2171,14 @@
   {
     StackZone zone(isolate);
     HANDLESCOPE(isolate);
+
+    ProcessedSampleBuffer* processed_samples = NULL;
+    {
+      ScopeTimer sw("BuildProcessedSampleBuffer", FLAG_trace_profiler);
+      NoAllocationSampleFilter filter(isolate);
+      processed_samples = sample_buffer->BuildProcessedSampleBuffer(&filter);
+    }
+
     {
       // Live code holds Dart, Native, and Collected CodeRegions.
       CodeRegionTable live_code_table;
@@ -2187,13 +2191,6 @@
       // Set of deoptimized code still referenced by the profiler.
       DeoptimizedCodeSet* deoptimized_code = new DeoptimizedCodeSet(isolate);
 
-      {
-        ScopeTimer sw("PreprocessSamples", FLAG_trace_profiler);
-        // Preprocess samples.
-        PreprocessVisitor preprocessor(isolate);
-        sample_buffer->VisitSamples(&preprocessor);
-      }
-
       // Build CodeRegion tables.
       CodeRegionTableBuilder builder(isolate,
                                      &live_code_table,
@@ -2201,10 +2198,10 @@
                                      &tag_code_table,
                                      deoptimized_code);
       {
-        ScopeTimer sw("CodeRegionTableBuilder", FLAG_trace_profiler);
-        sample_buffer->VisitSamples(&builder);
+        ScopeTimer sw("CodeRegionTableBuilder::Build", FLAG_trace_profiler);
+        builder.Build(processed_samples);
       }
-      intptr_t samples = builder.visited();
+      intptr_t samples = processed_samples->length();
       intptr_t frames = builder.frames();
       if (FLAG_trace_profiler) {
         intptr_t total_live_code_objects = live_code_table.Length();
@@ -2244,8 +2241,8 @@
       code_trie_builder.set_tag_order(tag_order);
       {
         // Build CodeRegion trie.
-        ScopeTimer sw("CodeRegionTrieBuilder", FLAG_trace_profiler);
-        sample_buffer->VisitSamples(&code_trie_builder);
+        ScopeTimer sw("CodeRegionTrieBuilder::Build", FLAG_trace_profiler);
+        code_trie_builder.Build(processed_samples);
         code_trie_builder.exclusive_root()->SortByCount();
         code_trie_builder.inclusive_root()->SortByCount();
       }
@@ -2254,17 +2251,16 @@
                   code_trie_builder.exclusive_root()->count(),
                   code_trie_builder.inclusive_root()->count());
       }
-      ProfileFunctionTrieBuilder function_trie_builder(isolate,
-                                                       &live_code_table,
+      ProfileFunctionTrieBuilder function_trie_builder(&live_code_table,
                                                        &dead_code_table,
                                                        &tag_code_table,
                                                        &function_table);
       function_trie_builder.set_tag_order(tag_order);
       {
         // Build ProfileFunction trie.
-        ScopeTimer sw("ProfileFunctionTrieBuilder",
+        ScopeTimer sw("ProfileFunctionTrieBuilder::Build",
                       FLAG_trace_profiler);
-        sample_buffer->VisitSamples(&function_trie_builder);
+        function_trie_builder.Build(processed_samples);
         function_trie_builder.exclusive_root()->SortByCount();
         function_trie_builder.inclusive_root()->SortByCount();
       }
diff --git a/runtime/vm/profiler_test.cc b/runtime/vm/profiler_test.cc
index 63b77d4..561bb69 100644
--- a/runtime/vm/profiler_test.cc
+++ b/runtime/vm/profiler_test.cc
@@ -43,7 +43,7 @@
 };
 
 
-TEST_CASE(ProfilerSampleBufferWrapTest) {
+TEST_CASE(Profiler_SampleBufferWrapTest) {
   SampleBuffer* sample_buffer = new SampleBuffer(3);
   Isolate* i = reinterpret_cast<Isolate*>(0x1);
   EXPECT_EQ(0, ProfileSampleBufferTestHelper::IterateSumPC(i, *sample_buffer));
@@ -68,7 +68,7 @@
 }
 
 
-TEST_CASE(ProfilerSampleBufferIterateTest) {
+TEST_CASE(Profiler_SampleBufferIterateTest) {
   SampleBuffer* sample_buffer = new SampleBuffer(3);
   Isolate* i = reinterpret_cast<Isolate*>(0x1);
   EXPECT_EQ(0, ProfileSampleBufferTestHelper::IterateCount(i, *sample_buffer));
@@ -88,4 +88,48 @@
   delete sample_buffer;
 }
 
+
+TEST_CASE(Profiler_AllocationSampleTest) {
+  Isolate* isolate = Isolate::Current();
+  SampleBuffer* sample_buffer = new SampleBuffer(3);
+  Sample* sample = sample_buffer->ReserveSample();
+  sample->Init(isolate, 0, 0);
+  sample->set_metadata(99);
+  sample->set_is_allocation_sample(true);
+  EXPECT_EQ(99, sample->allocation_cid());
+  delete sample_buffer;
+}
+
+static RawClass* GetClass(const Library& lib, const char* name) {
+  const Class& cls = Class::Handle(
+      lib.LookupClass(String::Handle(Symbols::New(name))));
+  EXPECT(!cls.IsNull());  // No ambiguity error expected.
+  return cls.raw();
+}
+
+
+TEST_CASE(Profiler_TrivialRecordAllocation) {
+  const char* kScript =
+      "class A {\n"
+      "  var a;\n"
+      "  var b;\n"
+      "}\n"
+      "main() {\n"
+      "  var z = new A();\n"
+      "  return z;\n"
+      "}\n";
+
+  Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
+  EXPECT_VALID(lib);
+  Library& root_library = Library::Handle();
+  root_library ^= Api::UnwrapHandle(lib);
+
+  const Class& class_a = Class::Handle(GetClass(root_library, "A"));
+  EXPECT(!class_a.IsNull());
+  class_a.SetTraceAllocation(true);
+
+  Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL);
+  EXPECT_VALID(result);
+}
+
 }  // namespace dart
diff --git a/runtime/vm/raw_object.cc b/runtime/vm/raw_object.cc
index 04378e7..67f0afc 100644
--- a/runtime/vm/raw_object.cc
+++ b/runtime/vm/raw_object.cc
@@ -115,6 +115,13 @@
       instance_size = Array::InstanceSize(array_length);
       break;
     }
+    case kObjectPoolCid: {
+      const RawObjectPool* raw_object_pool =
+          reinterpret_cast<const RawObjectPool*>(this);
+      intptr_t len = raw_object_pool->ptr()->length_;
+      instance_size = ObjectPool::InstanceSize(len);
+      break;
+    }
 #define SIZE_FROM_CLASS(clazz)                                                 \
     case kTypedData##clazz##Cid:
     CLASS_LIST_TYPED_DATA(SIZE_FROM_CLASS) {
@@ -523,6 +530,24 @@
 }
 
 
+intptr_t RawObjectPool::VisitObjectPoolPointers(
+    RawObjectPool* raw_obj, ObjectPointerVisitor* visitor) {
+  visitor->VisitPointer(
+      reinterpret_cast<RawObject**>(&raw_obj->ptr()->info_array_));
+  const intptr_t len = raw_obj->ptr()->length_;
+  RawTypedData* info_array = raw_obj->ptr()->info_array_->ptr();
+  Entry* first = raw_obj->first_entry();
+  for (intptr_t i = 0; i < len; ++i) {
+    ObjectPool::EntryType entry_type =
+        static_cast<ObjectPool::EntryType>(info_array->data()[i]);
+    if (entry_type == ObjectPool::kTaggedObject) {
+      visitor->VisitPointer(&(first + i)->raw_obj_);
+    }
+  }
+  return ObjectPool::InstanceSize(raw_obj->ptr()->length_);
+}
+
+
 intptr_t RawInstructions::VisitInstructionsPointers(
     RawInstructions* raw_obj, ObjectPointerVisitor* visitor) {
   RawInstructions* obj = raw_obj->ptr();
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index 349ad59..3be710b 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -31,6 +31,7 @@
   V(Namespace)                                                                 \
   V(Code)                                                                      \
   V(Instructions)                                                              \
+  V(ObjectPool)                                                                \
   V(PcDescriptors)                                                             \
   V(Stackmap)                                                                  \
   V(LocalVarDescriptors)                                                       \
@@ -237,14 +238,27 @@
     kCanonicalBit = 2,
     kFromSnapshotBit = 3,
     kRememberedBit = 4,
-    kReservedTagPos = 5,  // kReservedBit{10K,100K,1M,10M}
+#if defined(ARCH_IS_32_BIT)
+    kReservedTagPos = 5,  // kReservedBit{100K,1M,10M}
     kReservedTagSize = 3,
     kSizeTagPos = kReservedTagPos + kReservedTagSize,  // = 8
     kSizeTagSize = 8,
     kClassIdTagPos = kSizeTagPos + kSizeTagSize,  // = 16
     kClassIdTagSize = 16,
+#elif defined(ARCH_IS_64_BIT)
+    kReservedTagPos = 5,  // kReservedBit{100K,1M,10M}
+    kReservedTagSize = 11,
+    kSizeTagPos = kReservedTagPos + kReservedTagSize,  // = 16
+    kSizeTagSize = 16,
+    kClassIdTagPos = kSizeTagPos + kSizeTagSize,  // = 32
+    kClassIdTagSize = 32,
+#else
+#error Unexpected architecture word size
+#endif
   };
 
+  COMPILE_ASSERT(kClassIdTagSize == (sizeof(classid_t) * kBitsPerByte));
+
   // Encodes the object size in the tag in units of object alignment.
   class SizeTag {
    public:
@@ -392,6 +406,9 @@
   bool IsScript() {
     return ((GetClassId() == kScriptCid));
   }
+  bool IsFunction() {
+    return ((GetClassId() == kFunctionCid));
+  }
 
   intptr_t Size() const {
     uword tags = ptr()->tags_;
@@ -508,7 +525,7 @@
     if (value->IsNewObject() && this->IsOldObject() &&
         !this->IsRemembered()) {
       this->SetRememberedBit();
-      Isolate::Current()->store_buffer()->AddObject(this);
+      Thread::Current()->StoreBufferAddObject(this);
     }
   }
 
@@ -539,9 +556,11 @@
   friend class Api;
   friend class ApiMessageReader;  // GetClassId
   friend class Array;
+  friend class Bigint;
   friend class ByteBuffer;
   friend class Code;
   friend class Closure;
+  friend class Double;
   friend class FreeListElement;
   friend class Function;
   friend class GCMarker;
@@ -552,6 +571,7 @@
   friend class HeapMapAsJSONVisitor;
   friend class ClassStatsVisitor;
   friend class MarkingVisitor;
+  friend class Mint;
   friend class Object;
   friend class OneByteString;  // StoreSmi
   friend class RawExternalTypedData;
@@ -613,11 +633,11 @@
   }
 
   cpp_vtable handle_vtable_;
-  int32_t id_;  // Class Id, also index in the class table.
   int32_t token_pos_;
   int32_t instance_size_in_words_;  // Size if fixed len or 0 if variable len.
   int32_t type_arguments_field_offset_in_words_;  // Offset of type args fld.
   int32_t next_field_offset_in_words_;  // Offset of the next instance field.
+  classid_t id_;  // Class Id, also index in the class table.
   int16_t num_type_arguments_;  // Number of type arguments in flatten vector.
   int16_t num_own_type_arguments_;  // Number of non-overlapping type arguments.
   uint16_t num_native_fields_;  // Number of native fields in class.
@@ -756,7 +776,7 @@
   int16_t num_fixed_parameters_;
   int16_t num_optional_parameters_;  // > 0: positional; < 0: named.
   int16_t deoptimization_counter_;
-  int16_t regexp_cid_;
+  classid_t regexp_cid_;
   uint32_t kind_tag_;  // See Function::KindTagBits.
   uint16_t optimized_instruction_count_;
   uint16_t optimized_call_site_count_;
@@ -814,9 +834,9 @@
   }
 
   int32_t token_pos_;
-  int32_t guarded_cid_;
-  int32_t is_nullable_;  // kNullCid if field can contain null value and
-                         // any other value otherwise.
+  classid_t guarded_cid_;
+  classid_t is_nullable_;  // kNullCid if field can contain null value and
+                           // any other value otherwise.
   // Offset to the guarded length field inside an instance of class matching
   // guarded_cid_. Stored corrected by -kHeapObjectTag to simplify code
   // generated on platforms with weak addressing modes (ARM, MIPS).
@@ -867,6 +887,7 @@
     kLibraryTag,
     kSourceTag,
     kPatchTag,
+    kEvaluateTag,
   };
 
  private:
@@ -915,15 +936,15 @@
     return reinterpret_cast<RawObject**>(&ptr()->load_error_);
   }
 
-  int32_t index_;               // Library id number.
-  int32_t num_imports_;         // Number of entries in imports_.
-  int32_t num_anonymous_;       // Number of entries in anonymous_classes_.
   Dart_NativeEntryResolver native_entry_resolver_;  // Resolves natives.
   Dart_NativeEntrySymbol native_entry_symbol_resolver_;
+  classid_t index_;             // Library id number.
+  classid_t num_anonymous_;     // Number of entries in anonymous_classes_.
+  uint16_t num_imports_;        // Number of entries in imports_.
+  int8_t load_state_;           // Of type LibraryState.
   bool corelib_imported_;
   bool is_dart_scheme_;
-  bool debuggable_;              // True if debugger can stop in library.
-  int8_t load_state_;            // Of type LibraryState.
+  bool debuggable_;             // True if debugger can stop in library.
 
   friend class Isolate;
 };
@@ -1002,6 +1023,27 @@
 };
 
 
+class RawObjectPool : public RawObject {
+  RAW_HEAP_OBJECT_IMPLEMENTATION(ObjectPool);
+
+  intptr_t length_;
+  RawTypedData* info_array_;
+
+  struct Entry {
+    union {
+      RawObject* raw_obj_;
+      uword raw_value_;
+    };
+  };
+  Entry* data() { OPEN_ARRAY_START(Entry, Entry); }
+  Entry const* data() const { OPEN_ARRAY_START(Entry, Entry); }
+
+  Entry* first_entry() { return &ptr()->data()[0]; }
+
+  friend class Object;
+};
+
+
 class RawInstructions : public RawObject {
   RAW_HEAP_OBJECT_IMPLEMENTATION(Instructions);
 
@@ -1009,7 +1051,7 @@
     return reinterpret_cast<RawObject**>(&ptr()->code_);
   }
   RawCode* code_;
-  RawArray* object_pool_;
+  RawObjectPool* object_pool_;
   RawObject** to() {
     return reinterpret_cast<RawObject**>(&ptr()->object_pool_);
   }
@@ -1399,7 +1441,7 @@
   RawObject** to() {
     return reinterpret_cast<RawObject**>(&ptr()->dependent_code_);
   }
-  int32_t num_imports_;          // Number of library entries in libraries_.
+  uint16_t num_imports_;          // Number of library entries in libraries_.
   bool is_deferred_load_;
   bool is_loaded_;
 };
@@ -1465,8 +1507,8 @@
   RawString* name_;
   RawAbstractType* bound_;  // ObjectType if no explicit bound specified.
   RawObject** to() { return reinterpret_cast<RawObject**>(&ptr()->bound_); }
-  int32_t index_;
   int32_t token_pos_;
+  int16_t index_;
   int8_t type_state_;
 };
 
@@ -1780,6 +1822,8 @@
   friend class Object;
   friend class Instance;
   friend class SnapshotReader;
+  friend class ObjectPool;
+  friend class RawObjectPool;
 };
 
 
@@ -1883,6 +1927,7 @@
     return reinterpret_cast<RawObject**>(&ptr()->value_);
   }
 
+  friend class DelaySet;
   friend class GCMarker;
   friend class MarkingVisitor;
   friend class Scavenger;
@@ -2112,6 +2157,7 @@
          (index == kContextCid) ||
          (index == kTypeArgumentsCid) ||
          (index == kInstructionsCid) ||
+         (index == kObjectPoolCid) ||
          (index == kPcDescriptorsCid) ||
          (index == kStackmapCid) ||
          (index == kLocalVarDescriptorsCid) ||
diff --git a/runtime/vm/raw_object_snapshot.cc b/runtime/vm/raw_object_snapshot.cc
index 152c4b0..092ddcd 100644
--- a/runtime/vm/raw_object_snapshot.cc
+++ b/runtime/vm/raw_object_snapshot.cc
@@ -32,7 +32,7 @@
   if ((kind == Snapshot::kFull) ||
       (kind == Snapshot::kScript && !RawObject::IsCreatedFromSnapshot(tags))) {
     // Read in the base information.
-    int32_t class_id = reader->Read<int32_t>();
+    classid_t class_id = reader->ReadClassIDValue();
 
     // Allocate class object of specified kind.
     if (kind == Snapshot::kFull) {
@@ -96,8 +96,8 @@
 
     // Write out all the non object pointer fields.
     // NOTE: cpp_vtable_ is not written.
-    int32_t class_id = ptr()->id_;
-    writer->Write<int32_t>(class_id);
+    classid_t class_id = ptr()->id_;
+    writer->Write<classid_t>(class_id);
     if (!RawObject::IsInternalVMdefinedClassId(class_id)) {
       // We don't write the instance size of VM defined classes as they
       // are already setup during initialization as part of pre populating
@@ -106,8 +106,8 @@
       writer->Write<int32_t>(ptr()->next_field_offset_in_words_);
     }
     writer->Write<int32_t>(ptr()->type_arguments_field_offset_in_words_);
-    writer->Write<int16_t>(ptr()->num_type_arguments_);
-    writer->Write<int16_t>(ptr()->num_own_type_arguments_);
+    writer->Write<uint16_t>(ptr()->num_type_arguments_);
+    writer->Write<uint16_t>(ptr()->num_own_type_arguments_);
     writer->Write<uint16_t>(ptr()->num_native_fields_);
     writer->Write<int32_t>(ptr()->token_pos_);
     writer->Write<uint16_t>(ptr()->state_bits_);
@@ -332,8 +332,8 @@
   type_parameter.set_tags(tags);
 
   // Set all non object fields.
-  type_parameter.set_index(reader->Read<int32_t>());
   type_parameter.set_token_pos(reader->Read<int32_t>());
+  type_parameter.set_index(reader->Read<int16_t>());
   type_parameter.set_type_state(reader->Read<int8_t>());
 
   // Set all the object fields.
@@ -367,8 +367,8 @@
   writer->WriteTags(writer->GetObjectTags(this));
 
   // Write out all the non object pointer fields.
-  writer->Write<int32_t>(ptr()->index_);
   writer->Write<int32_t>(ptr()->token_pos_);
+  writer->Write<int16_t>(ptr()->index_);
   writer->Write<int8_t>(ptr()->type_state_);
 
   // Write out all the object pointer fields.
@@ -706,7 +706,7 @@
   func.set_num_fixed_parameters(reader->Read<int16_t>());
   func.set_num_optional_parameters(reader->Read<int16_t>());
   func.set_deoptimization_counter(reader->Read<int16_t>());
-  func.set_regexp_cid(reader->Read<int16_t>());
+  func.set_regexp_cid(reader->ReadClassIDValue());
   func.set_kind_tag(reader->Read<uint32_t>());
   func.set_optimized_instruction_count(reader->Read<uint16_t>());
   func.set_optimized_call_site_count(reader->Read<uint16_t>());
@@ -750,7 +750,7 @@
   writer->Write<int16_t>(ptr()->num_fixed_parameters_);
   writer->Write<int16_t>(ptr()->num_optional_parameters_);
   writer->Write<int16_t>(ptr()->deoptimization_counter_);
-  writer->Write<int16_t>(ptr()->regexp_cid_);
+  writer->WriteClassIDValue(ptr()->regexp_cid_);
   writer->Write<uint32_t>(ptr()->kind_tag_);
   writer->Write<uint16_t>(ptr()->optimized_instruction_count_);
   writer->Write<uint16_t>(ptr()->optimized_call_site_count_);
@@ -1039,29 +1039,22 @@
 
     // Set all non object fields.
     library.StoreNonPointer(&library.raw_ptr()->index_,
-                            reader->Read<int32_t>());
-    library.StoreNonPointer(&library.raw_ptr()->num_imports_,
-                            reader->Read<int32_t>());
+                            reader->ReadClassIDValue());
     library.StoreNonPointer(&library.raw_ptr()->num_anonymous_,
-                            reader->Read<int32_t>());
+                            reader->ReadClassIDValue());
+    library.StoreNonPointer(&library.raw_ptr()->num_imports_,
+                            reader->Read<uint16_t>());
+    library.StoreNonPointer(&library.raw_ptr()->load_state_,
+                            reader->Read<int8_t>());
     library.StoreNonPointer(&library.raw_ptr()->corelib_imported_,
                             reader->Read<bool>());
     library.StoreNonPointer(&library.raw_ptr()->is_dart_scheme_,
                             reader->Read<bool>());
     library.StoreNonPointer(&library.raw_ptr()->debuggable_,
                             reader->Read<bool>());
-    library.StoreNonPointer(&library.raw_ptr()->load_state_,
-                            reader->Read<int8_t>());
-    // The native resolver is not serialized.
-    Dart_NativeEntryResolver resolver =
-        reader->Read<Dart_NativeEntryResolver>();
-    ASSERT(resolver == NULL);
-    library.set_native_entry_resolver(resolver);
-    // The symbol resolver is not serialized.
-    Dart_NativeEntrySymbol symbol_resolver =
-        reader->Read<Dart_NativeEntrySymbol>();
-    ASSERT(symbol_resolver == NULL);
-    library.set_native_entry_symbol_resolver(symbol_resolver);
+    // The native resolver and symbolizer are not serialized.
+    library.set_native_entry_resolver(NULL);
+    library.set_native_entry_symbol_resolver(NULL);
     // The cache of loaded scripts is not serialized.
     library.StorePointer(&library.raw_ptr()->loaded_scripts_, Array::null());
 
@@ -1102,19 +1095,15 @@
     writer->WriteObjectImpl(ptr()->url_);
   } else {
     // Write out all non object fields.
-    writer->Write<int32_t>(ptr()->index_);
-    writer->Write<int32_t>(ptr()->num_imports_);
-    writer->Write<int32_t>(ptr()->num_anonymous_);
+    writer->WriteClassIDValue(ptr()->index_);
+    writer->WriteClassIDValue(ptr()->num_anonymous_);
+    writer->Write<uint16_t>(ptr()->num_imports_);
+    writer->Write<int8_t>(ptr()->load_state_);
     writer->Write<bool>(ptr()->corelib_imported_);
     writer->Write<bool>(ptr()->is_dart_scheme_);
     writer->Write<bool>(ptr()->debuggable_);
-    writer->Write<int8_t>(ptr()->load_state_);
-    // We do not serialize the native resolver over, this needs to be explicitly
-    // set after deserialization.
-    writer->Write<Dart_NativeEntryResolver>(NULL);
-    // We do not serialize the native entry symbol, this needs to be explicitly
-    // set after deserialization.
-    writer->Write<Dart_NativeEntrySymbol>(NULL);
+    // We do not serialize the native resolver or symbolizer. These need to be
+    // explicitly set after deserialization.
     // We do not write the loaded_scripts_ cache to the snapshot. It gets
     // set to NULL when reading the library from the snapshot, and will
     // be rebuilt lazily.
@@ -1145,7 +1134,7 @@
 
   // Set all non object fields.
   prefix.StoreNonPointer(&prefix.raw_ptr()->num_imports_,
-                         reader->Read<int32_t>());
+                         reader->Read<int16_t>());
   prefix.StoreNonPointer(&prefix.raw_ptr()->is_deferred_load_,
                          reader->Read<bool>());
   prefix.StoreNonPointer(&prefix.raw_ptr()->is_loaded_, reader->Read<bool>());
@@ -1180,7 +1169,7 @@
   writer->WriteTags(writer->GetObjectTags(this));
 
   // Write out all non object fields.
-  writer->Write<int32_t>(ptr()->num_imports_);
+  writer->Write<int16_t>(ptr()->num_imports_);
   writer->Write<bool>(ptr()->is_deferred_load_);
   writer->Write<bool>(ptr()->is_loaded_);
 
@@ -1276,19 +1265,62 @@
 }
 
 
+RawObjectPool* ObjectPool::ReadFrom(SnapshotReader* reader,
+                                    intptr_t object_id,
+                                    intptr_t tags,
+                                    Snapshot::Kind kind) {
+  UNREACHABLE();
+  return ObjectPool::null();
+}
+
+
+void RawObjectPool::WriteTo(SnapshotWriter* writer,
+                            intptr_t object_id,
+                            Snapshot::Kind kind) {
+  UNREACHABLE();
+}
+
+
 RawPcDescriptors* PcDescriptors::ReadFrom(SnapshotReader* reader,
                                           intptr_t object_id,
                                           intptr_t tags,
                                           Snapshot::Kind kind) {
-  UNREACHABLE();
-  return PcDescriptors::null();
+  ASSERT(reader->allow_code());
+
+  const int32_t length = reader->Read<int32_t>();
+  PcDescriptors& result = PcDescriptors::ZoneHandle(reader->zone(),
+                                                    PcDescriptors::New(length));
+  reader->AddBackRef(object_id, &result, kIsDeserialized);
+
+  // Set the object tags.
+  result.set_tags(tags);
+
+  if (result.Length() > 0) {
+    NoSafepointScope no_safepoint;
+    intptr_t len = result.Length();
+    uint8_t* data = result.UnsafeMutableNonPointer(result.raw_ptr()->data());
+    reader->ReadBytes(data, len);
+  }
+
+  return result.raw();
 }
 
 
 void RawPcDescriptors::WriteTo(SnapshotWriter* writer,
                                intptr_t object_id,
                                Snapshot::Kind kind) {
-  UNREACHABLE();
+  ASSERT(writer->allow_code());
+
+  // Write out the serialization header value for this object.
+  writer->WriteInlinedObjectHeader(object_id);
+  writer->WriteIndexedObject(kPcDescriptorsCid);
+  writer->WriteTags(writer->GetObjectTags(this));
+  writer->Write<int32_t>(ptr()->length_);
+  if (ptr()->length_ > 0) {
+    intptr_t len = ptr()->length_;
+    uint8_t* data = reinterpret_cast<uint8_t*>(ptr()->data());
+    writer->WriteBytes(data, len);
+  }
 }
 
 
@@ -1296,15 +1328,48 @@
                                 intptr_t object_id,
                                 intptr_t tags,
                                 Snapshot::Kind kind) {
-  UNREACHABLE();
-  return Stackmap::null();
+  ASSERT(reader->allow_code());
+
+  const int32_t length = reader->Read<int32_t>();
+  const int32_t register_bit_count = reader->Read<int32_t>();
+  const uword pc_offset = reader->Read<uint32_t>();
+
+  Stackmap& result =
+      Stackmap::ZoneHandle(reader->zone(),
+        Stackmap::New(length, register_bit_count, pc_offset));
+  reader->AddBackRef(object_id, &result, kIsDeserialized);
+
+  // Set the object tags.
+  result.set_tags(tags);
+
+  if (result.Length() > 0) {
+    NoSafepointScope no_safepoint;
+    intptr_t len = (result.Length() + 7) / 8;
+    uint8_t* data = result.UnsafeMutableNonPointer(result.raw_ptr()->data());
+    reader->ReadBytes(data, len);
+  }
+
+  return result.raw();
 }
 
 
 void RawStackmap::WriteTo(SnapshotWriter* writer,
                           intptr_t object_id,
                           Snapshot::Kind kind) {
-  UNREACHABLE();
+  ASSERT(writer->allow_code());
+
+  // Write out the serialization header value for this object.
+  writer->WriteInlinedObjectHeader(object_id);
+  writer->WriteIndexedObject(kStackmapCid);
+  writer->WriteTags(writer->GetObjectTags(this));
+  writer->Write<int32_t>(ptr()->length_);
+  writer->Write<int32_t>(ptr()->register_bit_count_);
+  writer->Write<uint32_t>(ptr()->pc_offset_);
+  if (ptr()->length_ > 0) {
+    intptr_t len = (ptr()->length_ + 7) / 8;
+    uint8_t* data = reinterpret_cast<uint8_t*>(ptr()->data());
+    writer->WriteBytes(data, len);
+  }
 }
 
 
@@ -1312,15 +1377,54 @@
                                                       intptr_t object_id,
                                                       intptr_t tags,
                                                       Snapshot::Kind kind) {
-  UNREACHABLE();
-  return LocalVarDescriptors::null();
+  ASSERT(reader->allow_code());
+
+  const int32_t num_entries = reader->Read<int32_t>();
+
+  LocalVarDescriptors& result =
+      LocalVarDescriptors::ZoneHandle(reader->zone(),
+        LocalVarDescriptors::New(num_entries));
+  reader->AddBackRef(object_id, &result, kIsDeserialized);
+
+  // Set the object tags.
+  result.set_tags(tags);
+
+  for (intptr_t i = 0; i < num_entries; i++) {
+    (*reader->StringHandle()) ^= reader->ReadObjectRef();
+    result.StorePointer(result.raw()->nameAddrAt(i),
+                        reader->StringHandle()->raw());
+  }
+
+  if (num_entries > 0) {
+    NoSafepointScope no_safepoint;
+    intptr_t len = num_entries * sizeof(RawLocalVarDescriptors::VarInfo);
+    uint8_t* data = result.UnsafeMutableNonPointer(
+        reinterpret_cast<const uint8_t*>(result.raw()->data()));
+    reader->ReadBytes(data, len);
+  }
+
+  return result.raw();
 }
 
 
 void RawLocalVarDescriptors::WriteTo(SnapshotWriter* writer,
                                      intptr_t object_id,
                                      Snapshot::Kind kind) {
-  UNREACHABLE();
+  ASSERT(writer->allow_code());
+
+  // Write out the serialization header value for this object.
+  writer->WriteInlinedObjectHeader(object_id);
+  writer->WriteIndexedObject(kLocalVarDescriptorsCid);
+  writer->WriteTags(writer->GetObjectTags(this));
+  writer->Write<int32_t>(ptr()->num_entries_);
+  for (intptr_t i = 0; i < ptr()->num_entries_; i++) {
+    writer->WriteObjectImpl(ptr()->names()[i]);
+  }
+  if (ptr()->num_entries_ > 0) {
+    intptr_t len = ptr()->num_entries_ * sizeof(VarInfo);
+    uint8_t* data = reinterpret_cast<uint8_t*>(this->data());
+    writer->WriteBytes(data, len);
+  }
 }
 
 
@@ -1328,15 +1432,47 @@
                                                   intptr_t object_id,
                                                   intptr_t tags,
                                                   Snapshot::Kind kind) {
-  UNREACHABLE();
-  return ExceptionHandlers::null();
+  ASSERT(reader->allow_code());
+
+  *(reader->ArrayHandle()) ^= reader->ReadObjectImpl();  // handled_types_data_
+
+  ExceptionHandlers& result =
+      ExceptionHandlers::ZoneHandle(reader->zone(),
+        ExceptionHandlers::New(*reader->ArrayHandle()));
+  reader->AddBackRef(object_id, &result, kIsDeserialized);
+
+  // Set the object tags.
+  result.set_tags(tags);
+
+  if (result.num_entries() > 0) {
+    NoSafepointScope no_safepoint;
+    const intptr_t len =
+        result.num_entries() * sizeof(RawExceptionHandlers::HandlerInfo);
+    uint8_t* data = result.UnsafeMutableNonPointer(
+        reinterpret_cast<const uint8_t*>(result.raw_ptr()->data()));
+    reader->ReadBytes(data, len);
+  }
+
+  return result.raw();
 }
 
 
 void RawExceptionHandlers::WriteTo(SnapshotWriter* writer,
                                    intptr_t object_id,
                                    Snapshot::Kind kind) {
-  UNREACHABLE();
+  ASSERT(writer->allow_code());
+
+  // Write out the serialization header value for this object.
+  writer->WriteInlinedObjectHeader(object_id);
+  writer->WriteIndexedObject(kExceptionHandlersCid);
+  writer->WriteTags(writer->GetObjectTags(this));
+  writer->WriteObjectImpl(ptr()->handled_types_data_);
+
+  if (ptr()->num_entries_ > 0) {
+    intptr_t len = ptr()->num_entries_ * sizeof(HandlerInfo);
+    uint8_t* data = reinterpret_cast<uint8_t*>(ptr()->data());
+    writer->WriteBytes(data, len);
+  }
 }
 
 
@@ -1700,6 +1836,8 @@
   Mint& mint = Mint::ZoneHandle(reader->zone(), Mint::null());
   if (kind == Snapshot::kFull) {
     mint = reader->NewMint(value);
+    // Set the object tags.
+    mint.set_tags(tags);
   } else {
     // When reading a script snapshot we need to canonicalize only those object
     // references that are objects from the core library (loaded from a
@@ -1710,15 +1848,16 @@
         (RawObject::IsCreatedFromSnapshot(tags) ||
          (kind == Snapshot::kMessage))) {
       mint = Mint::NewCanonical(value);
+      ASSERT(mint.IsCanonical() &&
+             (kind == Snapshot::kMessage ||
+              RawObject::IsCreatedFromSnapshot(mint.raw()->ptr()->tags_)));
     } else {
       mint = Mint::New(value, HEAP_SPACE(kind));
+      // Set the object tags.
+      mint.set_tags(tags);
     }
   }
   reader->AddBackRef(object_id, &mint, kIsDeserialized);
-
-  // Set the object tags.
-  mint.set_tags(tags);
-
   return mint.raw();
 }
 
@@ -1768,16 +1907,21 @@
   // full snapshot). Objects that are only in the script need not be
   // canonicalized as they are already canonical.
   // When reading a message snapshot we always have to canonicalize the object.
-  if ((kind != Snapshot::kFull) && RawObject::IsCanonical(tags) &&
-      (RawObject::IsCreatedFromSnapshot(tags) ||
-       (kind == Snapshot::kMessage))) {
+  if (kind == Snapshot::kFull) {
+    // Set the object tags.
+    obj.set_tags(tags);
+  } else if (RawObject::IsCanonical(tags) &&
+             (RawObject::IsCreatedFromSnapshot(tags) ||
+              (kind == Snapshot::kMessage))) {
     obj ^= obj.CheckAndCanonicalize(NULL);
     ASSERT(!obj.IsNull());
+    ASSERT(obj.IsCanonical() &&
+           (kind == Snapshot::kMessage ||
+            RawObject::IsCreatedFromSnapshot(obj.raw()->ptr()->tags_)));
+  } else {
+    // Set the object tags.
+    obj.set_tags(tags);
   }
-
-  // Set the object tags.
-  obj.set_tags(tags);
-
   return obj.raw();
 }
 
@@ -1813,6 +1957,8 @@
   Double& dbl = Double::ZoneHandle(reader->zone(), Double::null());
   if (kind == Snapshot::kFull) {
     dbl = reader->NewDouble(value);
+    // Set the object tags.
+    dbl.set_tags(tags);
   } else {
     // When reading a script snapshot we need to canonicalize only those object
     // references that are objects from the core library (loaded from a
@@ -1821,15 +1967,16 @@
     if (RawObject::IsCanonical(tags) &&
         RawObject::IsCreatedFromSnapshot(tags)) {
       dbl = Double::NewCanonical(value);
+      ASSERT(dbl.IsCanonical() &&
+             (kind == Snapshot::kMessage ||
+              RawObject::IsCreatedFromSnapshot(dbl.raw()->ptr()->tags_)));
     } else {
       dbl = Double::New(value, HEAP_SPACE(kind));
+      // Set the object tags.
+      dbl.set_tags(tags);
     }
   }
   reader->AddBackRef(object_id, &dbl, kIsDeserialized);
-
-  // Set the object tags.
-  dbl.set_tags(tags);
-
   return dbl.raw();
 }
 
diff --git a/runtime/vm/report_test.cc b/runtime/vm/report_test.cc
index 24a1825..73f2108 100644
--- a/runtime/vm/report_test.cc
+++ b/runtime/vm/report_test.cc
@@ -15,7 +15,7 @@
   const String& url = String::Handle(isolate, String::New("Plug"));
   const String& source = String::Handle(isolate, String::New("240 100"));
   const Script& script = Script::Handle(isolate,
-      Script::New(url, source, RawScript::kScriptTag));
+      Script::New(url, source, RawScript::kEvaluateTag));
   script.Tokenize(String::Handle(String::New("")));
   {
     const intptr_t token_pos = 0;
@@ -29,10 +29,11 @@
                        js.ToCString());
       // Skip time.
       EXPECT_SUBSTRING("\"message\":{\"type\":\"JSCompatibilityWarning\","
-                       "\"script\":{\"type\":\"@Script\",\"fixedId\":true,"
-                       "\"id\":\"libraries\\/-1\\/scripts\\/Plug\","
-                       "\"uri\":\"Plug\","
-                       "\"_kind\":\"script\"},\"tokenPos\":0,"
+                       "\"script\":{\"type\":\"@Script\"",
+                       js.ToCString());
+      // Skip object ring id.
+      EXPECT_SUBSTRING("\"uri\":\"Plug\","
+                       "\"_kind\":\"evaluate\"},\"tokenPos\":0,"
                        "\"message\":{\"type\":\"@Instance\"",
                        js.ToCString());
       // Skip private _OneByteString.
@@ -47,10 +48,11 @@
   }
   EXPECT_EQ(2, trace_buffer->Length());
   EXPECT_SUBSTRING("{\"type\":\"JSCompatibilityWarning\",\"script\":{\"type\":"
-                   "\"@Script\",\"fixedId\":true,"
-                   "\"id\":\"libraries\\/-1\\/scripts\\/Plug\","
-                   "\"uri\":\"Plug\","
-                   "\"_kind\":\"script\"},\"tokenPos\":0,"
+                   "\"@Script\"",
+                   trace_buffer->At(0)->message);
+  // Skip object ring id.
+  EXPECT_SUBSTRING("\"uri\":\"Plug\","
+                   "\"_kind\":\"evaluate\"},\"tokenPos\":0,"
                    "\"message\":{\"type\":\"@Instance\"",
                    trace_buffer->At(0)->message);
   // Skip private _OneByteString.
@@ -58,10 +60,11 @@
                    trace_buffer->At(0)->message);
 
   EXPECT_SUBSTRING("{\"type\":\"JSCompatibilityWarning\",\"script\":{\"type\":"
-                   "\"@Script\",\"fixedId\":true,"
-                   "\"id\":\"libraries\\/-1\\/scripts\\/Plug\","
-                   "\"uri\":\"Plug\","
-                   "\"_kind\":\"script\"},\"tokenPos\":1,"
+                   "\"@Script\"",
+                   trace_buffer->At(1)->message);
+  // Skip object ring id.
+  EXPECT_SUBSTRING("\"uri\":\"Plug\","
+                   "\"_kind\":\"evaluate\"},\"tokenPos\":1,"
                    "\"message\":{\"type\":\"@Instance\"",
                    trace_buffer->At(1)->message);
   // Skip private _OneByteString.
diff --git a/runtime/vm/runtime_entry_arm.cc b/runtime/vm/runtime_entry_arm.cc
index 09cb5de..e3aceb0 100644
--- a/runtime/vm/runtime_entry_arm.cc
+++ b/runtime/vm/runtime_entry_arm.cc
@@ -40,16 +40,17 @@
   entry =
       Simulator::RedirectExternalReference(entry, call_kind, argument_count);
 #endif
+  ExternalLabel label(entry);
   if (is_leaf()) {
     ASSERT(argument_count == this->argument_count());
-    ExternalLabel label(entry);
     __ BranchLink(&label);
   } else {
     // Argument count is not checked here, but in the runtime entry for a more
     // informative error message.
-    __ LoadImmediate(R5, entry);
+    __ LoadExternalLabel(R5, &label, kNotPatchable);
     __ LoadImmediate(R4, argument_count);
-    __ BranchLink(&Isolate::Current()->stub_code()->CallToRuntimeLabel());
+    __ BranchLink(&Isolate::Current()->stub_code()->CallToRuntimeLabel(),
+                  kNotPatchable);
   }
 }
 
diff --git a/runtime/vm/runtime_entry_arm64.cc b/runtime/vm/runtime_entry_arm64.cc
index 553f64c..a2edb95 100644
--- a/runtime/vm/runtime_entry_arm64.cc
+++ b/runtime/vm/runtime_entry_arm64.cc
@@ -37,9 +37,9 @@
   entry =
       Simulator::RedirectExternalReference(entry, call_kind, argument_count);
 #endif
+  ExternalLabel label(entry);
   if (is_leaf()) {
     ASSERT(argument_count == this->argument_count());
-    ExternalLabel label(entry);
     // Since we are entering C++ code, we must restore the C stack pointer from
     // the stack limit to an aligned value nearer to the top of the stack.
     // We cache the Dart stack pointer and the stack limit in callee-saved
@@ -55,7 +55,7 @@
   } else {
     // Argument count is not checked here, but in the runtime entry for a more
     // informative error message.
-    __ LoadImmediate(R5, entry, kNoPP);
+    __ LoadExternalLabel(R5, &label, kNotPatchable, PP);
     __ LoadImmediate(R4, argument_count, kNoPP);
     __ BranchLink(&Isolate::Current()->stub_code()->CallToRuntimeLabel(), PP);
   }
diff --git a/runtime/vm/runtime_entry_mips.cc b/runtime/vm/runtime_entry_mips.cc
index 70f51cc..872a37c 100644
--- a/runtime/vm/runtime_entry_mips.cc
+++ b/runtime/vm/runtime_entry_mips.cc
@@ -40,16 +40,17 @@
   entry =
       Simulator::RedirectExternalReference(entry, call_kind, argument_count);
 #endif
+  ExternalLabel label(entry);
   if (is_leaf()) {
     ASSERT(argument_count == this->argument_count());
-    ExternalLabel label(entry);
     __ BranchLink(&label);
   } else {
     // Argument count is not checked here, but in the runtime entry for a more
     // informative error message.
-    __ LoadImmediate(S5, entry);
+    __ LoadExternalLabel(S5, &label, kNotPatchable);
     __ LoadImmediate(S4, argument_count);
-    __ BranchLink(&Isolate::Current()->stub_code()->CallToRuntimeLabel());
+    __ BranchLink(&Isolate::Current()->stub_code()->CallToRuntimeLabel(),
+                  kNotPatchable);
   }
 }
 
diff --git a/runtime/vm/runtime_entry_x64.cc b/runtime/vm/runtime_entry_x64.cc
index 7d07795..705eacd 100644
--- a/runtime/vm/runtime_entry_x64.cc
+++ b/runtime/vm/runtime_entry_x64.cc
@@ -28,7 +28,8 @@
   } else {
     // Argument count is not checked here, but in the runtime entry for a more
     // informative error message.
-    __ movq(RBX, Immediate(GetEntryPoint()));
+    ExternalLabel label(GetEntryPoint());
+    __ LoadExternalLabel(RBX, &label, kNotPatchable, PP);
     __ movq(R10, Immediate(argument_count));
     __ Call(&Isolate::Current()->stub_code()->CallToRuntimeLabel(), PP);
   }
diff --git a/runtime/vm/scanner.cc b/runtime/vm/scanner.cc
index f33d0b4..3e7f028 100644
--- a/runtime/vm/scanner.cc
+++ b/runtime/vm/scanner.cc
@@ -786,8 +786,16 @@
         }
         break;
 
-      case '?':
+      case '?':  // ?  ?.  ??  ??=
         Recognize(Token::kCONDITIONAL);
+        if (c0_ == '.') {
+          Recognize(Token::kQM_PERIOD);
+        } else if (c0_ == '?') {
+          Recognize(Token::kIFNULL);
+          if (c0_ == '=') {
+            Recognize(Token::kASSIGN_COND);
+          }
+        }
         break;
 
       case ':':
diff --git a/runtime/vm/scavenger.cc b/runtime/vm/scavenger.cc
index d0e6954..2ad8e1f 100644
--- a/runtime/vm/scavenger.cc
+++ b/runtime/vm/scavenger.cc
@@ -80,6 +80,7 @@
  public:
   explicit ScavengerVisitor(Isolate* isolate, Scavenger* scavenger)
       : ObjectPointerVisitor(isolate),
+        thread_(Thread::Current()),
         scavenger_(scavenger),
         from_start_(scavenger_->from_->start()),
         from_size_(scavenger_->from_->end() - scavenger_->from_->start()),
@@ -139,7 +140,7 @@
       return;
     }
     visiting_old_object_->SetRememberedBit();
-    isolate()->store_buffer()->AddObjectGC(visiting_old_object_);
+    thread_->StoreBufferAddObjectGC(visiting_old_object_);
   }
 
   void ScavengePointer(RawObject** p) {
@@ -239,6 +240,7 @@
     }
   }
 
+  Thread* thread_;
   Scavenger* scavenger_;
   uword from_start_;
   uword from_size_;
@@ -456,6 +458,7 @@
   if (invoke_api_callbacks && (isolate->gc_prologue_callback() != NULL)) {
     (isolate->gc_prologue_callback())();
   }
+  Thread::PrepareForGC();
   // Flip the two semi-spaces so that to_ is always the space for allocating
   // objects.
   from_ = to_;
@@ -513,27 +516,28 @@
 
 void Scavenger::IterateStoreBuffers(Isolate* isolate,
                                     ScavengerVisitor* visitor) {
-  StoreBuffer* buffer = isolate->store_buffer();
-  heap_->RecordData(kStoreBufferEntries, buffer->Count());
-
   // Iterating through the store buffers.
-  // Grab the deduplication sets out of the store buffer.
+  // Grab the deduplication sets out of the isolate's consolidated store buffer.
   StoreBufferBlock* pending = isolate->store_buffer()->Blocks();
+  intptr_t total_count = 0;
   while (pending != NULL) {
     StoreBufferBlock* next = pending->next();
     // Generated code appends to store buffers; tell MemorySanitizer.
     MSAN_UNPOISON(pending, sizeof(*pending));
     intptr_t count = pending->Count();
-    for (intptr_t i = 0; i < count; i++) {
-      RawObject* raw_object = pending->At(i);
+    total_count += count;
+    while (!pending->IsEmpty()) {
+      RawObject* raw_object = pending->Pop();
       ASSERT(raw_object->IsRemembered());
       raw_object->ClearRememberedBit();
       visitor->VisitingOldObject(raw_object);
       raw_object->VisitPointers(visitor);
     }
-    delete pending;
+    pending->Reset();
+    isolate->store_buffer()->PushBlock(pending);
     pending = next;
   }
+  heap_->RecordData(kStoreBufferEntries, total_count);
   heap_->RecordData(kDataUnused1, 0);
   heap_->RecordData(kDataUnused2, 0);
   // Done iterating through old objects remembered in the store buffers.
diff --git a/runtime/vm/service.cc b/runtime/vm/service.cc
index 0593f7f..25de978 100644
--- a/runtime/vm/service.cc
+++ b/runtime/vm/service.cc
@@ -2436,6 +2436,19 @@
 }
 
 
+static const MethodParameter* get_ports_params[] = {
+  ISOLATE_PARAMETER,
+  NULL,
+};
+
+
+static bool GetPorts(Isolate* isolate, JSONStream* js) {
+  MessageHandler* message_handler = isolate->message_handler();
+  PortMap::PrintPortsForMessageHandler(message_handler, js);
+  return true;
+}
+
+
 static bool RespondWithMalformedJson(Isolate* isolate,
                                       JSONStream* js) {
   JSONObject jsobj(js);
@@ -2620,6 +2633,43 @@
 }
 
 
+static const MethodParameter* set_exception_pause_info_params[] = {
+  ISOLATE_PARAMETER,
+  NULL,
+};
+
+
+static bool SetExceptionPauseInfo(Isolate* isolate, JSONStream* js) {
+  const char* exceptions = js->LookupParam("exceptions");
+  if (exceptions == NULL) {
+    PrintMissingParamError(js, "exceptions");
+    return true;
+  }
+
+  Dart_ExceptionPauseInfo info = kNoPauseOnExceptions;
+  if (strcmp(exceptions, "none") == 0) {
+    info = kNoPauseOnExceptions;
+  } else if (strcmp(exceptions, "all") == 0) {
+    info = kPauseOnAllExceptions;
+  } else if (strcmp(exceptions, "unhandled") == 0) {
+    info = kPauseOnUnhandledExceptions;
+  } else {
+    JSONObject jsobj(js);
+    jsobj.AddProperty("type", "Error");
+    jsobj.AddProperty("message", "illegal value for parameter 'exceptions'");
+    return true;
+  }
+
+  isolate->debugger()->SetExceptionPauseInfo(info);
+  if (Service::NeedsDebugEvents()) {
+    ServiceEvent event(isolate, ServiceEvent::kDebuggerSettingsUpdate);
+    Service::HandleEvent(&event);
+  }
+  PrintSuccess(js);
+  return true;
+}
+
+
 static const MethodParameter* get_flag_list_params[] = {
   NO_ISOLATE_PARAMETER,
   NULL,
@@ -2738,7 +2788,7 @@
     get_coverage_params },
   { "_getCpuProfile", GetCpuProfile,
     get_cpu_profile_params },
-  { "getFlagList", GetFlagList ,
+  { "getFlagList", GetFlagList,
     get_flag_list_params },
   { "_getHeapMap", GetHeapMap,
     get_heap_map_params },
@@ -2756,6 +2806,8 @@
     get_object_params },
   { "_getObjectByAddress", GetObjectByAddress,
     get_object_by_address_params },
+  { "_getPorts", GetPorts,
+    get_ports_params },
   { "_getRetainedSize", GetRetainedSize,
     get_retained_size_params },
   { "_getRetainingPath", GetRetainingPath,
@@ -2782,6 +2834,8 @@
     resume_params },
   { "_requestHeapSnapshot", RequestHeapSnapshot,
     request_heap_snapshot_params },
+  { "_setExceptionPauseInfo", SetExceptionPauseInfo,
+    set_exception_pause_info_params },
   { "_setFlag", SetFlag,
     set_flags_params },
   { "setLibraryDebuggable", SetLibraryDebuggable,
diff --git a/runtime/vm/service.h b/runtime/vm/service.h
index a7a7569..85c607f 100644
--- a/runtime/vm/service.h
+++ b/runtime/vm/service.h
@@ -5,7 +5,7 @@
 #ifndef VM_SERVICE_H_
 #define VM_SERVICE_H_
 
-#include "include/dart_api.h"
+#include "include/dart_tools_api.h"
 
 #include "vm/allocation.h"
 #include "vm/object_id_ring.h"
diff --git a/runtime/vm/service/message.dart b/runtime/vm/service/message.dart
index 7b07baa..631f0a7 100644
--- a/runtime/vm/service/message.dart
+++ b/runtime/vm/service/message.dart
@@ -36,7 +36,9 @@
 
   Message.fromJsonRpc(this.client, Map map)
       : serial = map['id'], method = map['method'] {
-    params.addAll(map['params']);
+    if (map['params'] != null) {
+      params.addAll(map['params']);
+    }
   }
 
   static String _methodNameFromUri(Uri uri) {
diff --git a/runtime/vm/service/service.md b/runtime/vm/service/service.md
index a42486596..d764864 100644
--- a/runtime/vm/service/service.md
+++ b/runtime/vm/service/service.md
@@ -1229,6 +1229,21 @@
   //
   // Provided for instance kinds:
   //   List
+  //   Map
+  //   Uint8ClampedList
+  //   Uint8List
+  //   Uint16List
+  //   Uint32List
+  //   Uint64List
+  //   Int8List
+  //   Int16List
+  //   Int32List
+  //   Int64List
+  //   Float32List
+  //   Float64List
+  //   Int32x4List
+  //   Float32x4List
+  //   Float64x2List
   int length [optional];
 
   // The name of a Type instance.
@@ -1278,6 +1293,21 @@
   //
   // Provided for instance kinds:
   //   List
+  //   Map
+  //   Uint8ClampedList
+  //   Uint8List
+  //   Uint16List
+  //   Uint32List
+  //   Uint64List
+  //   Int8List
+  //   Int16List
+  //   Int32List
+  //   Int64List
+  //   Float32List
+  //   Float64List
+  //   Int32x4List
+  //   Float32x4List
+  //   Float64x2List
   int length [optional];
 
   // The name of a Type instance.
@@ -1313,6 +1343,25 @@
   //   Map
   MapAssociation[] associations [optional];
 
+  // The bytes of a TypedData instance.
+  //
+  // Provided for instance kinds:
+  //   Uint8ClampedList
+  //   Uint8List
+  //   Uint16List
+  //   Uint32List
+  //   Uint64List
+  //   Int8List
+  //   Int16List
+  //   Int32List
+  //   Int64List
+  //   Float32List
+  //   Float64List
+  //   Int32x4List
+  //   Float32x4List
+  //   Float64x2List
+  int[] bytes [optional];
+
   // The function associated with a Closure instance.
   //
   // Provided for instance kinds:
@@ -1411,6 +1460,23 @@
   // Maps will be PlainInstance.
   Map,
 
+  // An instance of the built-in VM TypedData implementations.  User-defined
+  // TypedDatas will be PlainInstance.
+  Uint8ClampedList,
+  Uint8List,
+  Uint16List,
+  Uint32List,
+  Uint64List,
+  Int8List,
+  Int16List,
+  Int32List,
+  Int64List,
+  Float32List,
+  Float64List,
+  Int32x4List,
+  Float32x4List,
+  Float64x2List,
+
   // An instance of the built-in VM Closure implementation. User-defined
   // Closures will be PlainInstance.
   Closure,
diff --git a/runtime/vm/service_event.cc b/runtime/vm/service_event.cc
index 2c6680d..4b75a16 100644
--- a/runtime/vm/service_event.cc
+++ b/runtime/vm/service_event.cc
@@ -84,6 +84,8 @@
       return "GC";  // TODO(koda): Change to GarbageCollected.
     case kInspect:
       return "Inspect";
+    case kDebuggerSettingsUpdate:
+      return "_DebuggerSettingsUpdate";
     case kIllegal:
       return "Illegal";
     default:
@@ -110,6 +112,7 @@
     case kBreakpointResolved:
     case kBreakpointRemoved:
     case kInspect:
+    case kDebuggerSettingsUpdate:
       return "Debug";
 
     case kGC:
@@ -139,6 +142,10 @@
       jsobj.AddProperty("breakpoint", breakpoint());
     }
   }
+  if (type() == kDebuggerSettingsUpdate) {
+    JSONObject jssettings(&jsobj, "_debuggerSettings");
+    isolate()->debugger()->PrintSettingsToJSONObject(&jssettings);
+  }
   if (top_frame() != NULL) {
     JSONObject jsFrame(&jsobj, "topFrame");
     top_frame()->PrintToJSONObject(&jsFrame);
diff --git a/runtime/vm/service_event.h b/runtime/vm/service_event.h
index f835498..7a5a8ba 100644
--- a/runtime/vm/service_event.h
+++ b/runtime/vm/service_event.h
@@ -28,6 +28,7 @@
     kBreakpointResolved,
     kBreakpointRemoved,
     kInspect,
+    kDebuggerSettingsUpdate,
 
     kGC,
 
diff --git a/runtime/vm/service_isolate.cc b/runtime/vm/service_isolate.cc
index 89d93b6..3126678 100644
--- a/runtime/vm/service_isolate.cc
+++ b/runtime/vm/service_isolate.cc
@@ -642,6 +642,8 @@
       return;
     }
 
+    isolate->RemoveTimelineEventRecorder();
+
     Thread::ExitIsolate();
 
     ServiceIsolate::ConstructExitMessageAndCache(isolate);
diff --git a/runtime/vm/service_test.cc b/runtime/vm/service_test.cc
index 5b119b8..80d6ca3 100644
--- a/runtime/vm/service_test.cc
+++ b/runtime/vm/service_test.cc
@@ -4,7 +4,7 @@
 
 #include "platform/globals.h"
 
-#include "include/dart_debugger_api.h"
+#include "include/dart_tools_api.h"
 #include "vm/dart_api_impl.h"
 #include "vm/dart_entry.h"
 #include "vm/debugger.h"
diff --git a/runtime/vm/signal_handler_android.cc b/runtime/vm/signal_handler_android.cc
index cc42e69..6540751 100644
--- a/runtime/vm/signal_handler_android.cc
+++ b/runtime/vm/signal_handler_android.cc
@@ -12,7 +12,9 @@
 uintptr_t SignalHandler::GetProgramCounter(const mcontext_t& mcontext) {
   uintptr_t pc = 0;
 
-#if defined(HOST_ARCH_ARM)
+#if defined(HOST_ARCH_IA32)
+  pc = static_cast<uintptr_t>(mcontext.gregs[REG_EIP]);
+#elif defined(HOST_ARCH_ARM)
   pc = static_cast<uintptr_t>(mcontext.arm_pc);
 #elif defined(HOST_ARCH_ARM64)
   pc = static_cast<uintptr_t>(mcontext.pc);
@@ -26,7 +28,9 @@
 uintptr_t SignalHandler::GetFramePointer(const mcontext_t& mcontext) {
   uintptr_t fp = 0;
 
-#if defined(HOST_ARCH_ARM)
+#if defined(HOST_ARCH_IA32)
+  fp = static_cast<uintptr_t>(mcontext.gregs[REG_EBP]);
+#elif defined(HOST_ARCH_ARM)
   fp = static_cast<uintptr_t>(mcontext.arm_fp);
 #elif defined(HOST_ARCH_ARM64)
   fp = static_cast<uintptr_t>(mcontext.regs[29]);
@@ -41,7 +45,9 @@
 uintptr_t SignalHandler::GetCStackPointer(const mcontext_t& mcontext) {
   uintptr_t sp = 0;
 
-#if defined(HOST_ARCH_ARM)
+#if defined(HOST_ARCH_IA32)
+  sp = static_cast<uintptr_t>(mcontext.gregs[REG_ESP]);
+#elif defined(HOST_ARCH_ARM)
   sp = static_cast<uintptr_t>(mcontext.arm_sp);
 #elif defined(HOST_ARCH_ARM64)
   sp = static_cast<uintptr_t>(mcontext.sp);
@@ -55,7 +61,9 @@
 uintptr_t SignalHandler::GetDartStackPointer(const mcontext_t& mcontext) {
   uintptr_t sp = 0;
 
-#if defined(HOST_ARCH_ARM)
+#if defined(HOST_ARCH_IA32)
+  sp = static_cast<uintptr_t>(mcontext.gregs[REG_ESP]);
+#elif defined(HOST_ARCH_ARM)
   sp = static_cast<uintptr_t>(mcontext.arm_sp);
 #elif defined(HOST_ARCH_ARM64)
   sp = static_cast<uintptr_t>(mcontext.regs[18]);
@@ -68,7 +76,10 @@
 
 uintptr_t SignalHandler::GetLinkRegister(const mcontext_t& mcontext) {
   uintptr_t lr = 0;
-#if defined(HOST_ARCH_ARM)
+
+#if defined(HOST_ARCH_IA32)
+  lr = 0;
+#elif defined(HOST_ARCH_ARM)
   lr = static_cast<uintptr_t>(mcontext.arm_lr);
 #elif defined(HOST_ARCH_ARM64)
   lr = static_cast<uintptr_t>(mcontext.regs[30]);
diff --git a/runtime/vm/snapshot.cc b/runtime/vm/snapshot.cc
index 28cf4b5..135c559 100644
--- a/runtime/vm/snapshot.cc
+++ b/runtime/vm/snapshot.cc
@@ -1282,6 +1282,19 @@
   WriteForwardedObjects();
 }
 
+#define VM_OBJECT_CLASS_LIST(V)                                                \
+  V(OneByteString)                                                             \
+  V(Mint)                                                                      \
+  V(Bigint)                                                                    \
+  V(Double)                                                                    \
+
+#define VM_OBJECT_WRITE(clazz)                                                 \
+  case clazz::kClassId: {                                                      \
+    object_id = forward_list_->AddObject(rawobj, kIsSerialized);               \
+    Raw##clazz* raw_obj = reinterpret_cast<Raw##clazz*>(rawobj);               \
+    raw_obj->WriteTo(this, object_id, kind());                                 \
+    return;                                                                    \
+  }                                                                            \
 
 void SnapshotWriter::HandleVMIsolateObject(RawObject* rawobj) {
   // Check if it is a singleton null object.
@@ -1345,22 +1358,48 @@
     }
   }
 
-  // Check it is a predefined symbol in the VM isolate.
-  id = Symbols::LookupVMSymbol(rawobj);
-  if (id != kInvalidIndex) {
-    WriteVMIsolateObject(id);
-    return;
-  }
+  if (kind() == Snapshot::kFull) {
+    // Check it is a predefined symbol in the VM isolate.
+    id = Symbols::LookupVMSymbol(rawobj);
+    if (id != kInvalidIndex) {
+      WriteVMIsolateObject(id);
+      return;
+    }
 
-  // Check if it is an object from the vm isolate snapshot object table.
-  id = FindVmSnapshotObject(rawobj);
-  if (id != kInvalidIndex) {
-    WriteIndexedObject(id);
-    return;
+    // Check if it is an object from the vm isolate snapshot object table.
+    id = FindVmSnapshotObject(rawobj);
+    if (id != kInvalidIndex) {
+      WriteIndexedObject(id);
+      return;
+    }
+  } else {
+    // In the case of script snapshots or for messages we do not use
+    // the index into the vm isolate snapshot object table, instead we
+    // explicitly write the object out.
+    intptr_t object_id = forward_list_->FindObject(rawobj);
+    if (object_id != -1) {
+      WriteIndexedObject(object_id);
+      return;
+    } else {
+      switch (id) {
+        VM_OBJECT_CLASS_LIST(VM_OBJECT_WRITE)
+        case kTypedDataUint32ArrayCid: {
+          object_id = forward_list_->AddObject(rawobj, kIsSerialized);
+          RawTypedData* raw_obj = reinterpret_cast<RawTypedData*>(rawobj);
+          raw_obj->WriteTo(this, object_id, kind());
+          return;
+        }
+        default:
+          OS::Print("class id = %" Pd "\n", id);
+          break;
+      }
+    }
   }
   UNREACHABLE();
 }
 
+#undef VM_OBJECT_WRITE
+
 
 void SnapshotWriter::WriteObjectRef(RawObject* raw) {
   // First check if object can be written as a simple predefined type.
@@ -1460,20 +1499,6 @@
 }
 
 
-FullSnapshotWriter::FullSnapshotWriter(uint8_t** vm_isolate_snapshot_buffer,
-                                       uint8_t** isolate_snapshot_buffer,
-                                       ReAlloc alloc)
-    : vm_isolate_snapshot_buffer_(vm_isolate_snapshot_buffer),
-      isolate_snapshot_buffer_(isolate_snapshot_buffer),
-      alloc_(alloc),
-      vm_isolate_snapshot_size_(0),
-      isolate_snapshot_size_(0),
-      forward_list_(SnapshotWriter::FirstObjectId()) {
-  ASSERT(isolate_snapshot_buffer_ != NULL);
-  ASSERT(alloc_ != NULL);
-}
-
-
 // An object visitor which will iterate over all the script objects in the heap
 // and either count them or collect them into an array. This is used during
 // full snapshot generation of the VM isolate to write out all script
@@ -1511,36 +1536,69 @@
 };
 
 
-void FullSnapshotWriter::WriteVmIsolateSnapshot() {
-  ASSERT(vm_isolate_snapshot_buffer_ != NULL);
-  SnapshotWriter writer(Snapshot::kFull,
-                        vm_isolate_snapshot_buffer_,
-                        alloc_,
-                        kInitialSize,
-                        &forward_list_,
-                        true);  // Can send any kind of object.
-  Isolate* isolate = writer.isolate();
-  ASSERT(isolate != NULL);
-  ObjectStore* object_store = isolate->object_store();
-  ASSERT(object_store != NULL);
+FullSnapshotWriter::FullSnapshotWriter(uint8_t** vm_isolate_snapshot_buffer,
+                                       uint8_t** isolate_snapshot_buffer,
+                                       ReAlloc alloc)
+    : isolate_(Isolate::Current()),
+      vm_isolate_snapshot_buffer_(vm_isolate_snapshot_buffer),
+      isolate_snapshot_buffer_(isolate_snapshot_buffer),
+      alloc_(alloc),
+      vm_isolate_snapshot_size_(0),
+      isolate_snapshot_size_(0),
+      forward_list_(NULL),
+      scripts_(Array::Handle(isolate_)),
+      symbol_table_(Array::Handle(isolate_)) {
+  ASSERT(isolate_snapshot_buffer_ != NULL);
+  ASSERT(alloc_ != NULL);
+  ASSERT(isolate_ != NULL);
   ASSERT(ClassFinalizer::AllClassesFinalized());
-
+  ObjectStore* object_store = isolate_->object_store();
+  ASSERT(object_store != NULL);
+  Heap* heap = isolate_->heap();
+  ASSERT(heap != NULL);
   // Ensure the class table is valid.
 #if defined(DEBUG)
-  isolate->ValidateClassTable();
+  isolate_->ValidateClassTable();
 #endif
 
   // Collect all the script objects and their accompanying token stream objects
   // into an array so that we can write it out as part of the VM isolate
   // snapshot. We first count the number of script objects, allocate an array
   // and then fill it up with the script objects.
-  ScriptVisitor scripts_counter(isolate);
-  isolate->heap()->old_space()->VisitObjects(&scripts_counter);
+  ASSERT(isolate_ != NULL);
+  ScriptVisitor scripts_counter(isolate_);
+  heap->old_space()->VisitObjects(&scripts_counter);
   intptr_t count = scripts_counter.count();
-  const Array& scripts = Array::Handle(isolate, Array::New(count, Heap::kOld));
-  ScriptVisitor script_visitor(isolate, &scripts);
-  isolate->heap()->old_space()->VisitObjects(&script_visitor);
+  scripts_ = Array::New(count, Heap::kOld);
+  ScriptVisitor script_visitor(isolate_, &scripts_);
+  heap->old_space()->VisitObjects(&script_visitor);
 
+  // Stash the symbol table away for writing and reading into the vm isolate,
+  // and reset the symbol table for the regular isolate so that we do not
+  // write these symbols into the snapshot of a regular dart isolate.
+  symbol_table_ = object_store->symbol_table();
+  Symbols::SetupSymbolTable(isolate_);
+
+  forward_list_ = new ForwardList(SnapshotWriter::FirstObjectId());
+  ASSERT(forward_list_ != NULL);
+}
+
+
+FullSnapshotWriter::~FullSnapshotWriter() {
+  delete forward_list_;
+  symbol_table_ = Array::null();
+  scripts_ = Array::null();
+}
+
+
+void FullSnapshotWriter::WriteVmIsolateSnapshot() {
+  ASSERT(vm_isolate_snapshot_buffer_ != NULL);
+  SnapshotWriter writer(Snapshot::kFull,
+                        vm_isolate_snapshot_buffer_,
+                        alloc_,
+                        kInitialSize,
+                        forward_list_,
+                        true);  // Can send any kind of object.
   // Write full snapshot for the VM isolate.
   // Setup for long jump in case there is an exception while writing
   // the snapshot.
@@ -1558,28 +1616,20 @@
      * - all the scripts and token streams for these scripts
      *
      **/
-    {
-      NoSafepointScope no_safepoint;
+    // Write out the symbol table.
+    writer.WriteObject(symbol_table_.raw());
 
-      // Write out the symbol table and reset the symbol table for the
-      // regular isolate so that we do not write these symbols into the
-      // snapshot of a regular dart isolate.
-      writer.WriteObject(object_store->symbol_table());
+    // Write out all the script objects and the accompanying token streams
+    // for the bootstrap libraries so that they are in the VM isolate
+    // read only memory.
+    writer.WriteObject(scripts_.raw());
 
-      // Write out all the script objects and the accompanying token streams
-      // for the bootstrap libraries so that they are in the VM isolate
-      // read only memory.
-      writer.WriteObject(scripts.raw());
+    // Write out all forwarded objects.
+    writer.WriteForwardedObjects();
 
-      // Write out all forwarded objects.
-      writer.WriteForwardedObjects();
+    writer.FillHeader(writer.kind());
 
-      writer.FillHeader(writer.kind());
-    }
     vm_isolate_snapshot_size_ = writer.BytesWritten();
-    // Reset the symbol table for the regular isolate so that we do not
-    // write these symbols into the snapshot of a regular dart isolate.
-    Symbols::SetupSymbolTable(isolate);
   } else {
     writer.ThrowException(writer.exception_type(), writer.exception_msg());
   }
@@ -1591,18 +1641,10 @@
                         isolate_snapshot_buffer_,
                         alloc_,
                         kInitialSize,
-                        &forward_list_,
+                        forward_list_,
                         true);
-  Isolate* isolate = writer.isolate();
-  ASSERT(isolate != NULL);
-  ObjectStore* object_store = isolate->object_store();
+  ObjectStore* object_store = isolate_->object_store();
   ASSERT(object_store != NULL);
-  ASSERT(ClassFinalizer::AllClassesFinalized());
-
-  // Ensure the class table is valid.
-#if defined(DEBUG)
-  isolate->ValidateClassTable();
-#endif
 
   // Write full snapshot for a regular isolate.
   // Setup for long jump in case there is an exception while writing
@@ -1616,20 +1658,18 @@
     writer.WriteVersion();
 
     // Write out the full snapshot.
-    {
-      NoSafepointScope no_safepoint;
 
-      // Write out all the objects in the object store of the isolate which
-      // is the root set for all dart allocated objects at this point.
-      SnapshotWriterVisitor visitor(&writer, false);
-      object_store->VisitObjectPointers(&visitor);
+    // Write out all the objects in the object store of the isolate which
+    // is the root set for all dart allocated objects at this point.
+    SnapshotWriterVisitor visitor(&writer, false);
+    object_store->VisitObjectPointers(&visitor);
 
-      // Write out all forwarded objects.
-      writer.WriteForwardedObjects();
+    // Write out all forwarded objects.
+    writer.WriteForwardedObjects();
 
-      writer.FillHeader(writer.kind());
-      writer.UnmarkAll();
-    }
+    writer.FillHeader(writer.kind());
+    writer.UnmarkAll();
+
     isolate_snapshot_size_ = writer.BytesWritten();
   } else {
     writer.ThrowException(writer.exception_type(), writer.exception_msg());
@@ -1662,21 +1702,18 @@
       first_unprocessed_object_id_(first_object_id) {
   // The ForwardList encodes information in the header tag word. There cannot
   // be any concurrent GC tasks while it is in use.
-  PageSpace* page_space = Isolate::Current()->heap()->old_space();
+  Isolate* isolate = Isolate::Current();
+  PageSpace* page_space = isolate->heap()->old_space();
   MonitorLocker ml(page_space->tasks_lock());
   while (page_space->tasks() > 0) {
     ml.Wait();
   }
-  page_space->set_tasks(1);
+  // Ensure that no GC happens while we are writing out the full snapshot.
+  isolate->IncrementNoSafepointScopeDepth();
 }
 
 
 ForwardList::~ForwardList() {
-  PageSpace* page_space = Isolate::Current()->heap()->old_space();
-  MonitorLocker ml(page_space->tasks_lock());
-  ASSERT(page_space->tasks() == 1);
-  page_space->set_tasks(0);
-  ml.Notify();
 }
 
 
@@ -1697,15 +1734,41 @@
 }
 
 
+intptr_t ForwardList::AddObject(RawObject* raw, SerializeState state) {
+  NoSafepointScope no_safepoint;
+  intptr_t object_id = next_object_id();
+  ASSERT(object_id > 0 && object_id <= kMaxObjectId);
+  uword tags = raw->ptr()->tags_;
+  ASSERT(SerializedHeaderTag::decode(tags) != kObjectId);
+  Node* node = new Node(raw, tags, state);
+  ASSERT(node != NULL);
+  nodes_.Add(node);
+  return object_id;
+}
+
+
+intptr_t ForwardList::FindObject(RawObject* raw) {
+  NoSafepointScope no_safepoint;
+  intptr_t id;
+  for (id = first_object_id(); id < next_object_id(); ++id) {
+    const Node* node = NodeForObjectId(id);
+    if (raw == node->raw()) {
+      return id;
+    }
+  }
+  return kInvalidIndex;
+}
+
+
 void ForwardList::UnmarkAll() const {
-  {
-    NoSafepointScope no_safepoint;
-    for (intptr_t id = first_object_id(); id < next_object_id(); ++id) {
-      const Node* node = NodeForObjectId(id);
-      RawObject* raw = node->raw();
+  for (intptr_t id = first_object_id(); id < next_object_id(); ++id) {
+    const Node* node = NodeForObjectId(id);
+    RawObject* raw = node->raw();
+    if (SerializedHeaderTag::decode(raw->ptr()->tags_) == kObjectId) {
       raw->ptr()->tags_ = node->tags();  // Restore original tags.
     }
   }
+  Isolate::Current()->DecrementNoSafepointScopeDepth();
 }
 
 
diff --git a/runtime/vm/snapshot.h b/runtime/vm/snapshot.h
index 13c2ecd..1989c7b 100644
--- a/runtime/vm/snapshot.h
+++ b/runtime/vm/snapshot.h
@@ -195,6 +195,12 @@
     return static_cast<intptr_t>(value);
   }
 
+  classid_t ReadClassIDValue() {
+    uint32_t value = Read<uint32_t>();
+    return static_cast<classid_t>(value);
+  }
+  COMPILE_ASSERT(sizeof(uint32_t) >= sizeof(classid_t));
+
   void ReadBytes(uint8_t* addr, intptr_t len) {
     stream_.ReadBytes(addr, len);
   }
@@ -278,6 +284,7 @@
   ExternalTypedData* DataHandle() { return &data_; }
   TypedData* TypedDataHandle() { return &typed_data_; }
   Snapshot::Kind kind() const { return kind_; }
+  bool allow_code() const { return false; }
 
   // Reads an object.
   RawObject* ReadObject();
@@ -440,6 +447,8 @@
   friend class UnhandledException;
   friend class WeakProperty;
   friend class MirrorReference;
+  friend class ExceptionHandlers;
+  friend class LocalVarDescriptors;
   DISALLOW_COPY_AND_ASSIGN(SnapshotReader);
 };
 
@@ -511,6 +520,11 @@
     Write<int64_t>(value);
   }
 
+  void WriteClassIDValue(classid_t value) {
+    Write<uint32_t>(value);
+  }
+  COMPILE_ASSERT(sizeof(uint32_t) >= sizeof(classid_t));
+
   // Write an object that is serialized as an Id (singleton in object store,
   // or an object that was already serialized before).
   void WriteIndexedObject(intptr_t object_id) {
@@ -615,6 +629,12 @@
   // Returns the id for the added object.
   intptr_t MarkAndAddObject(RawObject* raw, SerializeState state);
 
+  // Returns the id for the added object without marking it.
+  intptr_t AddObject(RawObject* raw, SerializeState state);
+
+  // Returns the id for the object it it exists in the list.
+  intptr_t FindObject(RawObject* raw);
+
   // Exhaustively processes all unserialized objects in this list. 'writer' may
   // concurrently add more objects.
   void SerializeAll(ObjectVisitor* writer);
@@ -647,6 +667,7 @@
  public:
   // Snapshot kind.
   Snapshot::Kind kind() const { return kind_; }
+  bool allow_code() const { return false; }
 
   // Serialize an object into the buffer.
   void WriteObject(RawObject* raw);
@@ -748,6 +769,8 @@
   friend class RawTokenStream;
   friend class RawTypeArguments;
   friend class RawUserTag;
+  friend class RawExceptionHandlers;
+  friend class RawLocalVarDescriptors;
   friend class SnapshotWriterVisitor;
   friend class WriteInlinedObjectVisitor;
   DISALLOW_COPY_AND_ASSIGN(SnapshotWriter);
@@ -760,7 +783,7 @@
   FullSnapshotWriter(uint8_t** vm_isolate_snapshot_buffer,
                      uint8_t** isolate_snapshot_buffer,
                      ReAlloc alloc);
-  ~FullSnapshotWriter() { }
+  ~FullSnapshotWriter();
 
   uint8_t** vm_isolate_snapshot_buffer() {
     return vm_isolate_snapshot_buffer_;
@@ -787,12 +810,15 @@
   // Writes a full snapshot of a regular Dart Isolate.
   void WriteIsolateFullSnapshot();
 
+  Isolate* isolate_;
   uint8_t** vm_isolate_snapshot_buffer_;
   uint8_t** isolate_snapshot_buffer_;
   ReAlloc alloc_;
   intptr_t vm_isolate_snapshot_size_;
   intptr_t isolate_snapshot_size_;
-  ForwardList forward_list_;
+  ForwardList* forward_list_;
+  Array& scripts_;
+  Array& symbol_table_;
 
   DISALLOW_COPY_AND_ASSIGN(FullSnapshotWriter);
 };
diff --git a/runtime/vm/snapshot_test.cc b/runtime/vm/snapshot_test.cc
index 6707566..3933f3dc 100644
--- a/runtime/vm/snapshot_test.cc
+++ b/runtime/vm/snapshot_test.cc
@@ -4,7 +4,7 @@
 
 #include "platform/globals.h"
 
-#include "include/dart_debugger_api.h"
+#include "include/dart_tools_api.h"
 #include "platform/assert.h"
 #include "vm/class_finalizer.h"
 #include "vm/dart_api_impl.h"
@@ -20,6 +20,7 @@
 
 DECLARE_FLAG(bool, enable_type_checks);
 DECLARE_FLAG(bool, load_deferred_eagerly);
+DECLARE_FLAG(bool, concurrent_sweep);
 
 // Check if serialized and deserialized objects are equal.
 static bool Equals(const Object& expected, const Object& actual) {
@@ -151,9 +152,9 @@
   StackZone zone(Isolate::Current());
 
   // Write snapshot with object content.
+  const Object& null_object = Object::Handle();
   uint8_t* buffer;
   MessageWriter writer(&buffer, &zone_allocator, true);
-  const Object& null_object = Object::Handle();
   writer.WriteMessage(null_object);
   intptr_t buffer_len = writer.BytesWritten();
 
@@ -179,9 +180,9 @@
   StackZone zone(Isolate::Current());
 
   // Write snapshot with object content.
+  const Smi& smi = Smi::Handle(Smi::New(124));
   uint8_t* buffer;
   MessageWriter writer(&buffer, &zone_allocator, true);
-  const Smi& smi = Smi::Handle(Smi::New(124));
   writer.WriteMessage(smi);
   intptr_t buffer_len = writer.BytesWritten();
 
@@ -208,9 +209,9 @@
   StackZone zone(Isolate::Current());
 
   // Write snapshot with object content.
+  const Smi& smi = Smi::Handle(Smi::New(-1));
   uint8_t* buffer;
   MessageWriter writer(&buffer, &zone_allocator, true);
-  const Smi& smi = Smi::Handle(Smi::New(-1));
   writer.WriteMessage(smi);
   intptr_t buffer_len = writer.BytesWritten();
 
@@ -240,13 +241,17 @@
   writer.WriteMessage(mint);
   intptr_t buffer_len = writer.BytesWritten();
 
-  // Read object back from the snapshot.
-  MessageSnapshotReader reader(buffer,
-                               buffer_len,
-                               Isolate::Current(),
-                               Thread::Current()->zone());
-  const Object& serialized_object = Object::Handle(reader.ReadObject());
-  EXPECT(serialized_object.IsMint());
+  {
+    // Switch to a regular zone, where VM handle allocation is allowed.
+    StackZone zone(Isolate::Current());
+    // Read object back from the snapshot.
+    MessageSnapshotReader reader(buffer,
+                                 buffer_len,
+                                 Isolate::Current(),
+                                 Thread::Current()->zone());
+    const Object& serialized_object = Object::Handle(reader.ReadObject());
+    EXPECT(serialized_object.IsMint());
+  }
 
   // Read object back from the snapshot into a C structure.
   ApiMessageReader api_reader(buffer, buffer_len, &zone_allocator);
@@ -307,9 +312,9 @@
   StackZone zone(Isolate::Current());
 
   // Write snapshot with object content.
+  const Double& dbl = Double::Handle(Double::New(101.29));
   uint8_t* buffer;
   MessageWriter writer(&buffer, &zone_allocator, true);
-  const Double& dbl = Double::Handle(Double::New(101.29));
   writer.WriteMessage(dbl);
   intptr_t buffer_len = writer.BytesWritten();
 
@@ -336,9 +341,9 @@
   StackZone zone(Isolate::Current());
 
   // Write snapshot with true object.
+  const Bool& bl = Bool::True();
   uint8_t* buffer;
   MessageWriter writer(&buffer, &zone_allocator, true);
-  const Bool& bl = Bool::True();
   writer.WriteMessage(bl);
   intptr_t buffer_len = writer.BytesWritten();
 
@@ -367,9 +372,9 @@
   StackZone zone(Isolate::Current());
 
   // Write snapshot with false object.
+  const Bool& bl = Bool::False();
   uint8_t* buffer;
   MessageWriter writer(&buffer, &zone_allocator, true);
-  const Bool& bl = Bool::False();
   writer.WriteMessage(bl);
   intptr_t buffer_len = writer.BytesWritten();
 
@@ -401,12 +406,12 @@
   StackZone zone(Isolate::Current());
 
   // Write snapshot with object content.
-  uint8_t* buffer;
-  MessageWriter writer(&buffer, &zone_allocator, true);
   const char* cstr = "0x270FFFFFFFFFFFFFD8F0";
   const String& str = String::Handle(String::New(cstr));
   Bigint& bigint = Bigint::Handle();
   bigint ^= Integer::NewCanonical(str);
+  uint8_t* buffer;
+  MessageWriter writer(&buffer, &zone_allocator, true);
   writer.WriteMessage(bigint);
   intptr_t buffer_len = writer.BytesWritten();
 
@@ -440,18 +445,22 @@
   writer.WriteMessage(bigint);
   intptr_t buffer_len = writer.BytesWritten();
 
-  // Read object back from the snapshot.
-  MessageSnapshotReader reader(buffer,
-                               buffer_len,
-                               Isolate::Current(),
-                               Thread::Current()->zone());
-  Bigint& serialized_bigint = Bigint::Handle();
-  serialized_bigint ^= reader.ReadObject();
-  const char* str1 = bigint.ToHexCString(allocator);
-  const char* str2 = serialized_bigint.ToHexCString(allocator);
-  EXPECT_STREQ(str1, str2);
-  free(const_cast<char*>(str1));
-  free(const_cast<char*>(str2));
+  {
+    // Switch to a regular zone, where VM handle allocation is allowed.
+    StackZone zone(Isolate::Current());
+    // Read object back from the snapshot.
+    MessageSnapshotReader reader(buffer,
+                                 buffer_len,
+                                 Isolate::Current(),
+                                 Thread::Current()->zone());
+    Bigint& serialized_bigint = Bigint::Handle();
+    serialized_bigint ^= reader.ReadObject();
+    const char* str1 = bigint.ToHexCString(allocator);
+    const char* str2 = serialized_bigint.ToHexCString(allocator);
+    EXPECT_STREQ(str1, str2);
+    free(const_cast<char*>(str1));
+    free(const_cast<char*>(str2));
+  }
 
   // Read object back from the snapshot into a C structure.
   ApiMessageReader api_reader(buffer, buffer_len, &zone_allocator);
@@ -465,10 +474,9 @@
 
 void CheckBigint(const char* bigint_value) {
   StackZone zone(Isolate::Current());
-  ApiNativeScope scope;
-
   Bigint& bigint = Bigint::Handle();
   bigint ^= Bigint::NewFromCString(bigint_value);
+  ApiNativeScope scope;
   Dart_CObject* bigint_cobject = SerializeAndDeserializeBigint(bigint);
   EXPECT_EQ(Dart_CObject_kBigint, bigint_cobject->type);
   char* hex_value = TestCase::BigintToHexValue(bigint_cobject);
@@ -533,9 +541,9 @@
   StackZone zone(Isolate::Current());
   EXPECT(Utf8::IsValid(reinterpret_cast<const uint8_t*>(cstr), strlen(cstr)));
   // Write snapshot with object content.
+  String& str = String::Handle(String::New(cstr));
   uint8_t* buffer;
   MessageWriter writer(&buffer, &zone_allocator, true);
-  String& str = String::Handle(String::New(cstr));
   writer.WriteMessage(str);
   intptr_t buffer_len = writer.BytesWritten();
 
@@ -577,8 +585,6 @@
   StackZone zone(Isolate::Current());
 
   // Write snapshot with object content.
-  uint8_t* buffer;
-  MessageWriter writer(&buffer, &zone_allocator, true);
   const int kArrayLength = 10;
   Array& array = Array::Handle(Array::New(kArrayLength));
   Smi& smi = Smi::Handle();
@@ -586,6 +592,8 @@
     smi ^= Smi::New(i);
     array.SetAt(i, smi);
   }
+  uint8_t* buffer;
+  MessageWriter writer(&buffer, &zone_allocator, true);
   writer.WriteMessage(array);
   intptr_t buffer_len = writer.BytesWritten();
 
@@ -669,10 +677,10 @@
   StackZone zone(Isolate::Current());
 
   // Write snapshot with object content.
-  uint8_t* buffer;
-  MessageWriter writer(&buffer, &zone_allocator, true);
   const int kArrayLength = 0;
   Array& array = Array::Handle(Array::New(kArrayLength));
+  uint8_t* buffer;
+  MessageWriter writer(&buffer, &zone_allocator, true);
   writer.WriteMessage(array);
   intptr_t buffer_len = writer.BytesWritten();
 
@@ -700,14 +708,14 @@
   StackZone zone(Isolate::Current());
 
   // Write snapshot with object content.
-  uint8_t* buffer;
-  MessageWriter writer(&buffer, &zone_allocator, true);
   const int kTypedDataLength = 256;
   TypedData& typed_data = TypedData::Handle(
       TypedData::New(kTypedDataUint8ArrayCid, kTypedDataLength));
   for (int i = 0; i < kTypedDataLength; i++) {
     typed_data.SetUint8(i, i);
   }
+  uint8_t* buffer;
+  MessageWriter writer(&buffer, &zone_allocator, true);
   writer.WriteMessage(typed_data);
   intptr_t buffer_len = writer.BytesWritten();
 
@@ -736,8 +744,6 @@
 #define TEST_TYPED_ARRAY(darttype, ctype)                                     \
   {                                                                           \
     StackZone zone(Isolate::Current());                                       \
-    uint8_t* buffer;                                                          \
-    MessageWriter writer(&buffer, &zone_allocator, true);                     \
     const int kArrayLength = 127;                                             \
     TypedData& array = TypedData::Handle(                                     \
         TypedData::New(kTypedData##darttype##ArrayCid, kArrayLength));        \
@@ -745,6 +751,8 @@
     for (int i = 0; i < kArrayLength; i++) {                                  \
       array.Set##darttype((i * scale), i);                                    \
     }                                                                         \
+    uint8_t* buffer;                                                          \
+    MessageWriter writer(&buffer, &zone_allocator, true);                     \
     writer.WriteMessage(array);                                               \
     intptr_t buffer_len = writer.BytesWritten();                              \
     MessageSnapshotReader reader(buffer, buffer_len,                          \
@@ -816,11 +824,11 @@
   StackZone zone(Isolate::Current());
 
   // Write snapshot with object content.
-  uint8_t* buffer;
-  MessageWriter writer(&buffer, &zone_allocator, true);
   const int kTypedDataLength = 0;
   TypedData& typed_data = TypedData::Handle(
       TypedData::New(kTypedDataUint8ArrayCid, kTypedDataLength));
+  uint8_t* buffer;
+  MessageWriter writer(&buffer, &zone_allocator, true);
   writer.WriteMessage(typed_data);
   intptr_t buffer_len = writer.BytesWritten();
 
@@ -1086,10 +1094,12 @@
     OS::PrintErr("Without Snapshot: %" Pd64 "us\n", timer1.TotalElapsedTime());
 
     // Write snapshot with object content.
-    FullSnapshotWriter writer(NULL,
-                              &isolate_snapshot_buffer,
-                              &malloc_allocator);
-    writer.WriteFullSnapshot();
+    {
+      FullSnapshotWriter writer(NULL,
+                                &isolate_snapshot_buffer,
+                                &malloc_allocator);
+      writer.WriteFullSnapshot();
+    }
   }
 
   // Now Create another isolate using the snapshot and execute a method
@@ -1142,10 +1152,12 @@
     OS::PrintErr("Without Snapshot: %" Pd64 "us\n", timer1.TotalElapsedTime());
 
     // Write snapshot with object content.
-    FullSnapshotWriter writer(NULL,
-                              &isolate_snapshot_buffer,
-                              &malloc_allocator);
-    writer.WriteFullSnapshot();
+    {
+      FullSnapshotWriter writer(NULL,
+                                &isolate_snapshot_buffer,
+                                &malloc_allocator);
+      writer.WriteFullSnapshot();
+    }
 
     // Invoke a function which returns an object.
     Dart_Handle cls = Dart_GetClass(lib, NewString("FieldsTest"));
@@ -1235,7 +1247,10 @@
 
   bool saved_load_deferred_eagerly_mode = FLAG_load_deferred_eagerly;
   FLAG_load_deferred_eagerly = true;
-
+  // Workaround until issue 21620 is fixed.
+  // (https://github.com/dart-lang/sdk/issues/21620)
+  bool saved_concurrent_sweep_mode = FLAG_concurrent_sweep;
+  FLAG_concurrent_sweep = false;
   {
     // Start an Isolate, and create a full snapshot of it.
     TestIsolateScope __test_isolate__;
@@ -1251,8 +1266,10 @@
     memmove(full_snapshot, isolate_snapshot, isolate_snapshot_size);
     Dart_ExitScope();
   }
-
   FLAG_load_deferred_eagerly = saved_load_deferred_eagerly_mode;
+  FLAG_concurrent_sweep = saved_concurrent_sweep_mode;
+
+  // Test for Dart_CreateScriptSnapshot.
   {
     // Create an Isolate using the full snapshot, load a script and create
     // a script snapshot of the script.
@@ -1310,8 +1327,50 @@
     result = Dart_Invoke(cls, NewString("testMain"), 0, NULL);
     EXPECT_VALID(result);
     Dart_ExitScope();
+    Dart_ShutdownIsolate();
   }
-  Dart_ShutdownIsolate();
+  free(script_snapshot);
+
+  // Test for Dart_CreateLibrarySnapshot.
+  {
+    // Create an Isolate using the full snapshot, load a script and create
+    // a script snapshot of the script.
+    TestCase::CreateTestIsolateFromSnapshot(full_snapshot);
+    Dart_EnterScope();  // Start a Dart API scope for invoking API functions.
+
+    // Load the library.
+    Dart_Handle lib = Dart_LoadLibrary(NewString("dart_lib"),
+                                       NewString(kScriptChars),
+                                       0, 0);
+    EXPECT_VALID(lib);
+
+    // Write out the script snapshot.
+    result = Dart_CreateLibrarySnapshot(lib, &buffer, &size);
+    EXPECT_VALID(result);
+    script_snapshot = reinterpret_cast<uint8_t*>(malloc(size));
+    memmove(script_snapshot, buffer, size);
+    Dart_ExitScope();
+    Dart_ShutdownIsolate();
+  }
+
+  {
+    // Now Create an Isolate using the full snapshot and load the
+    // script snapshot created above and execute it.
+    TestCase::CreateTestIsolateFromSnapshot(full_snapshot);
+    Dart_EnterScope();  // Start a Dart API scope for invoking API functions.
+
+    // Load the test library from the snapshot.
+    EXPECT(script_snapshot != NULL);
+    result = Dart_LoadScriptFromSnapshot(script_snapshot, size);
+    EXPECT_VALID(result);
+
+    // Invoke a function which returns an object.
+    Dart_Handle cls = Dart_GetClass(result, NewString("FieldsTest"));
+    result = Dart_Invoke(cls, NewString("testMain"), 0, NULL);
+    EXPECT_VALID(result);
+    Dart_ExitScope();
+    Dart_ShutdownIsolate();
+  }
   free(full_snapshot);
   free(script_snapshot);
 }
@@ -1335,6 +1394,8 @@
 
   bool saved_load_deferred_eagerly_mode = FLAG_load_deferred_eagerly;
   FLAG_load_deferred_eagerly = true;
+  bool saved_concurrent_sweep_mode = FLAG_concurrent_sweep;
+  FLAG_concurrent_sweep = false;
   {
     // Start an Isolate, and create a full snapshot of it.
     TestIsolateScope __test_isolate__;
@@ -1350,6 +1411,7 @@
     memmove(full_snapshot, isolate_snapshot, isolate_snapshot_size);
     Dart_ExitScope();
   }
+  FLAG_concurrent_sweep = saved_concurrent_sweep_mode;
 
   {
     // Create an Isolate using the full snapshot, load a script and create
@@ -1425,7 +1487,8 @@
   FLAG_enable_type_checks = false;
   bool saved_load_deferred_eagerly_mode = FLAG_load_deferred_eagerly;
   FLAG_load_deferred_eagerly = true;
-
+  bool saved_concurrent_sweep_mode = FLAG_concurrent_sweep;
+  FLAG_concurrent_sweep = false;
   {
     // Start an Isolate, and create a full snapshot of it.
     TestIsolateScope __test_isolate__;
@@ -1441,6 +1504,7 @@
     memmove(full_snapshot, isolate_snapshot, isolate_snapshot_size);
     Dart_ExitScope();
   }
+  FLAG_concurrent_sweep = saved_concurrent_sweep_mode;
 
   {
     // Create an Isolate using the full snapshot, load a script and create
@@ -1532,21 +1596,26 @@
 }
 
 
-// Helper function to call a top level Dart function, serialize the
-// result and deserialize the result into a Dart_CObject structure.
-static Dart_CObject* GetDeserializedDartMessage(Dart_Handle lib,
-                                                const char* dart_function) {
+// Helper function to call a top level Dart function and serialize the result.
+static uint8_t* GetSerialized(Dart_Handle lib,
+                              const char* dart_function,
+                              intptr_t* buffer_len) {
   Dart_Handle result;
   result = Dart_Invoke(lib, NewString(dart_function), 0, NULL);
   EXPECT_VALID(result);
+  Object& obj = Object::Handle(Api::UnwrapHandle(result));
 
-  // Serialize the list into a message.
+  // Serialize the object into a message.
   uint8_t* buffer;
   MessageWriter writer(&buffer, &zone_allocator, false);
-  const Object& list = Object::Handle(Api::UnwrapHandle(result));
-  writer.WriteMessage(list);
-  intptr_t buffer_len = writer.BytesWritten();
+  writer.WriteMessage(obj);
+  *buffer_len = writer.BytesWritten();
+  return buffer;
+}
 
+
+// Helper function to deserialize the result into a Dart_CObject structure.
+static Dart_CObject* GetDeserialized(uint8_t* buffer, intptr_t buffer_len) {
   // Read object back from the snapshot into a C structure.
   ApiMessageReader api_reader(buffer, buffer_len, &zone_allocator);
   return api_reader.ReadMessage();
@@ -1555,10 +1624,10 @@
 
 static void CheckString(Dart_Handle dart_string, const char* expected) {
   StackZone zone(Isolate::Current());
-  uint8_t* buffer;
-  MessageWriter writer(&buffer, &zone_allocator, false);
   String& str = String::Handle();
   str ^= Api::UnwrapHandle(dart_string);
+  uint8_t* buffer;
+  MessageWriter writer(&buffer, &zone_allocator, false);
   writer.WriteMessage(str);
   intptr_t buffer_len = writer.BytesWritten();
 
@@ -1575,10 +1644,10 @@
 
 static void CheckStringInvalid(Dart_Handle dart_string) {
   StackZone zone(Isolate::Current());
-  uint8_t* buffer;
-  MessageWriter writer(&buffer, &zone_allocator, false);
   String& str = String::Handle();
   str ^= Api::UnwrapHandle(dart_string);
+  uint8_t* buffer;
+  MessageWriter writer(&buffer, &zone_allocator, false);
   writer.WriteMessage(str);
   intptr_t buffer_len = writer.BytesWritten();
 
@@ -1685,10 +1754,10 @@
 
     {
       StackZone zone(Isolate::Current());
-      uint8_t* buffer;
-      MessageWriter writer(&buffer, &zone_allocator, false);
       Smi& smi = Smi::Handle();
       smi ^= Api::UnwrapHandle(smi_result);
+      uint8_t* buffer;
+      MessageWriter writer(&buffer, &zone_allocator, false);
       writer.WriteMessage(smi);
       intptr_t buffer_len = writer.BytesWritten();
 
@@ -1703,10 +1772,10 @@
     }
     {
       StackZone zone(Isolate::Current());
-      uint8_t* buffer;
-      MessageWriter writer(&buffer, &zone_allocator, false);
       Bigint& bigint = Bigint::Handle();
       bigint ^= Api::UnwrapHandle(bigint_result);
+      uint8_t* buffer;
+      MessageWriter writer(&buffer, &zone_allocator, false);
       writer.WriteMessage(bigint);
       intptr_t buffer_len = writer.BytesWritten();
 
@@ -1774,10 +1843,13 @@
 
   {
     DARTSCOPE(isolate);
+    StackZone zone(isolate);
+    intptr_t buf_len = 0;
     {
       // Generate a list of nulls from Dart code.
+      uint8_t* buf = GetSerialized(lib, "getList", &buf_len);
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserializedDartMessage(lib, "getList");
+      Dart_CObject* root = GetDeserialized(buf, buf_len);
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1788,8 +1860,9 @@
     }
     {
       // Generate a list of ints from Dart code.
+      uint8_t* buf = GetSerialized(lib, "getIntList", &buf_len);
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserializedDartMessage(lib, "getIntList");
+      Dart_CObject* root = GetDeserialized(buf, buf_len);
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1801,8 +1874,9 @@
     }
     {
       // Generate a list of strings from Dart code.
+      uint8_t* buf = GetSerialized(lib, "getStringList", &buf_len);
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserializedDartMessage(lib, "getStringList");
+      Dart_CObject* root = GetDeserialized(buf, buf_len);
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1815,8 +1889,9 @@
     }
     {
       // Generate a list of objects of different types from Dart code.
+      uint8_t* buf = GetSerialized(lib, "getMixedList", &buf_len);
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserializedDartMessage(lib, "getMixedList");
+      Dart_CObject* root = GetDeserialized(buf, buf_len);
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1892,10 +1967,13 @@
 
   {
     DARTSCOPE(isolate);
+    StackZone zone(isolate);
+    intptr_t buf_len = 0;
     {
       // Generate a list of nulls from Dart code.
+      uint8_t* buf = GetSerialized(lib, "getList", &buf_len);
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserializedDartMessage(lib, "getList");
+      Dart_CObject* root = GetDeserialized(buf, buf_len);
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1906,8 +1984,9 @@
     }
     {
       // Generate a list of ints from Dart code.
+      uint8_t* buf = GetSerialized(lib, "getIntList", &buf_len);
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserializedDartMessage(lib, "getIntList");
+      Dart_CObject* root = GetDeserialized(buf, buf_len);
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1919,8 +1998,9 @@
     }
     {
       // Generate a list of strings from Dart code.
+      uint8_t* buf = GetSerialized(lib, "getStringList", &buf_len);
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserializedDartMessage(lib, "getStringList");
+      Dart_CObject* root = GetDeserialized(buf, buf_len);
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1933,8 +2013,9 @@
     }
     {
       // Generate a list of lists from Dart code.
+      uint8_t* buf = GetSerialized(lib, "getListList", &buf_len);
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserializedDartMessage(lib, "getListList");
+      Dart_CObject* root = GetDeserialized(buf, buf_len);
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1951,8 +2032,9 @@
     }
     {
       // Generate a list of objects of different types from Dart code.
+      uint8_t* buf = GetSerialized(lib, "getMixedList", &buf_len);
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserializedDartMessage(lib, "getMixedList");
+      Dart_CObject* root = GetDeserialized(buf, buf_len);
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -2124,11 +2206,13 @@
 
   {
     DARTSCOPE(isolate);
-
+    StackZone zone(isolate);
+    intptr_t buf_len = 0;
     {
       // Generate a list of strings from Dart code.
+      uint8_t* buf = GetSerialized(lib, "getStringList", &buf_len);
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserializedDartMessage(lib, "getStringList");
+      Dart_CObject* root = GetDeserialized(buf, buf_len);
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -2141,8 +2225,9 @@
     }
     {
       // Generate a list of medium ints from Dart code.
+      uint8_t* buf = GetSerialized(lib, "getMintList", &buf_len);
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserializedDartMessage(lib, "getMintList");
+      Dart_CObject* root = GetDeserialized(buf, buf_len);
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -2155,8 +2240,9 @@
     }
     {
       // Generate a list of bigints from Dart code.
+      uint8_t* buf = GetSerialized(lib, "getBigintList", &buf_len);
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserializedDartMessage(lib, "getBigintList");
+      Dart_CObject* root = GetDeserialized(buf, buf_len);
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -2171,8 +2257,9 @@
     }
     {
       // Generate a list of doubles from Dart code.
+      uint8_t* buf = GetSerialized(lib, "getDoubleList", &buf_len);
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserializedDartMessage(lib, "getDoubleList");
+      Dart_CObject* root = GetDeserialized(buf, buf_len);
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -2189,8 +2276,9 @@
     }
     {
       // Generate a list of Uint8Lists from Dart code.
+      uint8_t* buf = GetSerialized(lib, "getTypedDataList", &buf_len);
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserializedDartMessage(lib, "getTypedDataList");
+      Dart_CObject* root = GetDeserialized(buf, buf_len);
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -2204,9 +2292,9 @@
     }
     {
       // Generate a list of Uint8List views from Dart code.
+      uint8_t* buf = GetSerialized(lib, "getTypedDataViewList", &buf_len);
       ApiNativeScope scope;
-      Dart_CObject* root =
-          GetDeserializedDartMessage(lib, "getTypedDataViewList");
+      Dart_CObject* root = GetDeserialized(buf, buf_len);
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -2222,8 +2310,9 @@
     }
     {
       // Generate a list of objects of different types from Dart code.
+      uint8_t* buf = GetSerialized(lib, "getMixedList", &buf_len);
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserializedDartMessage(lib, "getMixedList");
+      Dart_CObject* root = GetDeserialized(buf, buf_len);
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -2249,8 +2338,9 @@
     }
     {
       // Generate a list of objects of different types from Dart code.
+      uint8_t* buf = GetSerialized(lib, "getSelfRefList", &buf_len);
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserializedDartMessage(lib, "getSelfRefList");
+      Dart_CObject* root = GetDeserialized(buf, buf_len);
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -2341,10 +2431,13 @@
 
   {
     DARTSCOPE(isolate);
+    StackZone zone(isolate);
+    intptr_t buf_len = 0;
     {
       // Generate a list of strings from Dart code.
+      uint8_t* buf = GetSerialized(lib, "getStringList", &buf_len);
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserializedDartMessage(lib, "getStringList");
+      Dart_CObject* root = GetDeserialized(buf, buf_len);
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -2357,8 +2450,9 @@
     }
     {
       // Generate a list of medium ints from Dart code.
+      uint8_t* buf = GetSerialized(lib, "getMintList", &buf_len);
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserializedDartMessage(lib, "getMintList");
+      Dart_CObject* root = GetDeserialized(buf, buf_len);
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -2371,8 +2465,9 @@
     }
     {
       // Generate a list of bigints from Dart code.
+      uint8_t* buf = GetSerialized(lib, "getBigintList", &buf_len);
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserializedDartMessage(lib, "getBigintList");
+      Dart_CObject* root = GetDeserialized(buf, buf_len);
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -2387,8 +2482,9 @@
     }
     {
       // Generate a list of doubles from Dart code.
+      uint8_t* buf = GetSerialized(lib, "getDoubleList", &buf_len);
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserializedDartMessage(lib, "getDoubleList");
+      Dart_CObject* root = GetDeserialized(buf, buf_len);
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -2406,8 +2502,9 @@
     }
     {
       // Generate a list of Uint8Lists from Dart code.
+      uint8_t* buf = GetSerialized(lib, "getTypedDataList", &buf_len);
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserializedDartMessage(lib, "getTypedDataList");
+      Dart_CObject* root = GetDeserialized(buf, buf_len);
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -2421,9 +2518,9 @@
     }
     {
       // Generate a list of Uint8List views from Dart code.
+      uint8_t* buf = GetSerialized(lib, "getTypedDataViewList", &buf_len);
       ApiNativeScope scope;
-      Dart_CObject* root =
-          GetDeserializedDartMessage(lib, "getTypedDataViewList");
+      Dart_CObject* root = GetDeserialized(buf, buf_len);
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -2439,8 +2536,9 @@
     }
     {
       // Generate a list of objects of different types from Dart code.
+      uint8_t* buf = GetSerialized(lib, "getMixedList", &buf_len);
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserializedDartMessage(lib, "getMixedList");
+      Dart_CObject* root = GetDeserialized(buf, buf_len);
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -2466,8 +2564,9 @@
     }
     {
       // Generate a list of objects of different types from Dart code.
+      uint8_t* buf = GetSerialized(lib, "getSelfRefList", &buf_len);
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserializedDartMessage(lib, "getSelfRefList");
+      Dart_CObject* root = GetDeserialized(buf, buf_len);
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -2573,10 +2672,13 @@
 
   {
     DARTSCOPE(isolate);
+    StackZone zone(isolate);
+    intptr_t buf_len = 0;
     {
       // Generate a list of Uint8Lists from Dart code.
+      uint8_t* buf = GetSerialized(lib, "getTypedDataList", &buf_len);
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserializedDartMessage(lib, "getTypedDataList");
+      Dart_CObject* root = GetDeserialized(buf, buf_len);
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       struct {
@@ -2607,10 +2709,9 @@
     }
     {
       // Generate a list of Uint8List views from Dart code.
-
+      uint8_t* buf = GetSerialized(lib, "getTypedDataViewList", &buf_len);
       ApiNativeScope scope;
-      Dart_CObject* root =
-          GetDeserializedDartMessage(lib, "getTypedDataViewList");
+      Dart_CObject* root = GetDeserialized(buf, buf_len);
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       struct {
@@ -2664,9 +2765,10 @@
     }
     {
       // Generate a list of Uint8Lists from Dart code.
+      uint8_t* buf =
+          GetSerialized(lib, "getMultipleTypedDataViewList", &buf_len);
       ApiNativeScope scope;
-      Dart_CObject* root =
-          GetDeserializedDartMessage(lib, "getMultipleTypedDataViewList");
+      Dart_CObject* root = GetDeserialized(buf, buf_len);
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       struct {
diff --git a/runtime/vm/stack_frame.cc b/runtime/vm/stack_frame.cc
index 2f3480a..a8ceedf 100644
--- a/runtime/vm/stack_frame.cc
+++ b/runtime/vm/stack_frame.cc
@@ -434,7 +434,7 @@
     function_(Function::Handle()),
     pc_(pc),
     deopt_instructions_(),
-    object_table_(Array::Handle()) {
+    object_table_(ObjectPool::Handle()) {
   ASSERT(code_.is_optimized());
   ASSERT(pc_ != 0);
   ASSERT(code.ContainsInstructionAt(pc));
@@ -452,7 +452,7 @@
     ASSERT(!deopt_table.IsNull());
     DeoptInfo::Unpack(deopt_table, deopt_info_, &deopt_instructions_);
     num_materializations_ = DeoptInfo::NumMaterializations(deopt_instructions_);
-    object_table_ = code_.ObjectPool();
+    object_table_ = code_.GetObjectPool();
     Advance();
   }
 }
diff --git a/runtime/vm/stack_frame.h b/runtime/vm/stack_frame.h
index a3cc4a0..dd849e5 100644
--- a/runtime/vm/stack_frame.h
+++ b/runtime/vm/stack_frame.h
@@ -323,7 +323,7 @@
   Function& function_;
   uword pc_;
   GrowableArray<DeoptInstr*> deopt_instructions_;
-  Array& object_table_;
+  ObjectPool& object_table_;
 
   DISALLOW_COPY_AND_ASSIGN(InlinedFunctionsIterator);
 };
diff --git a/runtime/vm/stack_frame_test.cc b/runtime/vm/stack_frame_test.cc
index 2472160..fd72877 100644
--- a/runtime/vm/stack_frame_test.cc
+++ b/runtime/vm/stack_frame_test.cc
@@ -16,6 +16,8 @@
 
 namespace dart {
 
+DECLARE_FLAG(bool, lazy_dispatchers);
+
 // Unit test for empty stack frame iteration.
 TEST_CASE(EmptyStackFrameIteration) {
   StackFrameIterator iterator(StackFrameIterator::kValidateFrames);
@@ -246,7 +248,12 @@
 
 // Unit test case to verify stack frame iteration.
 TEST_CASE(ValidateNoSuchMethodStackFrameIteration) {
-  const char* kScriptChars =
+  const char* kScriptChars;
+  // The true stack depends on which strategy we are using for noSuchMethod. The
+  // stacktrace as seen by Dart is the same either way because dispatcher
+  // methods are marked invisible.
+  if (FLAG_lazy_dispatchers) {
+    kScriptChars =
       "class StackFrame {"
       "  static equals(var obj1, var obj2) native \"StackFrame_equals\";"
       "  static int frameCount() native \"StackFrame_frameCount\";"
@@ -278,6 +285,41 @@
       "    StackFrame.equals(5, obj.foo(101, 202));"
       "  }"
       "}";
+  } else {
+    kScriptChars =
+      "class StackFrame {"
+      "  static equals(var obj1, var obj2) native \"StackFrame_equals\";"
+      "  static int frameCount() native \"StackFrame_frameCount\";"
+      "  static int dartFrameCount() native \"StackFrame_dartFrameCount\";"
+      "  static validateFrame(int index,"
+      "                       String name) native \"StackFrame_validateFrame\";"
+      "} "
+      "class StackFrame2Test {"
+      "  StackFrame2Test() {}"
+      "  noSuchMethod(Invocation im) {"
+      "    /* We should have 8 general frames and 3 dart frames as follows:"
+      "     * exit frame"
+      "     * dart frame corresponding to StackFrame.frameCount"
+      "     * dart frame corresponding to StackFrame2Test.noSuchMethod"
+      "     * entry frame"
+      "     * exit frame (call to runtime InvokeNoSuchMethodDispatcher)"
+      "     * IC stub"
+      "     * dart frame corresponding to StackFrame2Test.testMain"
+      "     * entry frame"
+      "     */"
+      "    StackFrame.equals(8, StackFrame.frameCount());"
+      "    StackFrame.equals(3, StackFrame.dartFrameCount());"
+      "    StackFrame.validateFrame(0, \"StackFrame_validateFrame\");"
+      "    StackFrame.validateFrame(1, \"StackFrame2Test_noSuchMethod\");"
+      "    StackFrame.validateFrame(2, \"StackFrame2Test_testMain\");"
+      "    return 5;"
+      "  }"
+      "  static testMain() {"
+      "    var obj = new StackFrame2Test();"
+      "    StackFrame.equals(5, obj.foo(101, 202));"
+      "  }"
+      "}";
+  }
   Dart_Handle lib = TestCase::LoadTestScript(
       kScriptChars,
       reinterpret_cast<Dart_NativeEntryResolver>(native_lookup));
diff --git a/runtime/vm/store_buffer.cc b/runtime/vm/store_buffer.cc
index acf7ca6..a590c28 100644
--- a/runtime/vm/store_buffer.cc
+++ b/runtime/vm/store_buffer.cc
@@ -5,72 +5,157 @@
 #include "vm/store_buffer.h"
 
 #include "platform/assert.h"
+#include "vm/lockers.h"
 #include "vm/runtime_entry.h"
 
 namespace dart {
 
-DEFINE_LEAF_RUNTIME_ENTRY(void, StoreBufferBlockProcess, 1, Isolate* isolate) {
-  StoreBuffer* buffer = isolate->store_buffer();
-  buffer->Expand(true);
+DEFINE_LEAF_RUNTIME_ENTRY(void, StoreBufferBlockProcess, 1, Thread* thread) {
+  thread->StoreBufferBlockProcess(true);
 }
 END_LEAF_RUNTIME_ENTRY
 
 
+StoreBuffer::List* StoreBuffer::global_empty_ = NULL;
+Mutex* StoreBuffer::global_mutex_ = NULL;
+
+
+void StoreBuffer::InitOnce() {
+  global_empty_ = new List();
+  global_mutex_ = new Mutex();
+}
+
+
+StoreBuffer::StoreBuffer() : mutex_(new Mutex()) {
+}
+
+
 StoreBuffer::~StoreBuffer() {
-  StoreBufferBlock* block = blocks_;
-  blocks_ = NULL;
-  while (block != NULL) {
-    StoreBufferBlock* next = block->next();
-    delete block;
-    block = next;
-  }
+  Reset();
+  delete mutex_;
 }
 
 
 void StoreBuffer::Reset() {
-  StoreBufferBlock* block = blocks_->next_;
-  while (block != NULL) {
-    StoreBufferBlock* next = block->next_;
-    delete block;
-    block = next;
-  }
-  blocks_->next_ = NULL;
-  blocks_->top_ = 0;
-  full_count_ = 0;
-}
-
-
-bool StoreBuffer::Contains(RawObject* raw) {
-  StoreBufferBlock* block = blocks_;
-  while (block != NULL) {
-    intptr_t count = block->Count();
-    for (intptr_t i = 0; i < count; i++) {
-      if (block->At(i) == raw) {
-        return true;
-      }
+  MutexLocker local_mutex_locker(mutex_);
+  {
+    // Empty all blocks and move them to the global cache.
+    MutexLocker global_mutex_locker(global_mutex_);
+    while (!full_.IsEmpty()) {
+      StoreBufferBlock* block = full_.Pop();
+      block->Reset();
+      global_empty_->Push(block);
     }
-    block = block->next_;
-  }
-  return false;
-}
-
-
-void StoreBuffer::Expand(bool check) {
-  ASSERT(blocks_->Count() == StoreBufferBlock::kSize);
-  blocks_ = new StoreBufferBlock(blocks_);
-  full_count_++;
-  if (check) {
-    CheckThreshold();
+    while (!partial_.IsEmpty()) {
+      StoreBufferBlock* block = partial_.Pop();
+      block->Reset();
+      global_empty_->Push(block);
+    }
+    TrimGlobalEmpty();
   }
 }
 
 
-void StoreBuffer::CheckThreshold() {
-  // Schedule an interrupt if we have run over the max number of
-  // StoreBufferBlocks.
-  // TODO(iposva): Fix magic number.
-  if (full_count_ > 100) {
-    Isolate::Current()->ScheduleInterrupts(Isolate::kStoreBufferInterrupt);
+StoreBufferBlock* StoreBuffer::Blocks() {
+  MutexLocker ml(mutex_);
+  while (!partial_.IsEmpty()) {
+    full_.Push(partial_.Pop());
+  }
+  return full_.PopAll();
+}
+
+
+void StoreBuffer::PushBlock(StoreBufferBlock* block, bool check_threshold) {
+  ASSERT(block->next() == NULL);  // Should be just a single block.
+  if (block->IsFull()) {
+    MutexLocker ml(mutex_);
+    full_.Push(block);
+  } else if (block->IsEmpty()) {
+    MutexLocker ml(global_mutex_);
+    global_empty_->Push(block);
+    TrimGlobalEmpty();
+  } else {
+    MutexLocker ml(mutex_);
+    partial_.Push(block);
+  }
+  if (check_threshold) {
+    MutexLocker ml(mutex_);
+    CheckThresholdNonEmpty();
+  }
+}
+
+
+StoreBufferBlock* StoreBuffer::PopBlock() {
+  {
+    MutexLocker ml(mutex_);
+    if (!partial_.IsEmpty()) {
+      return partial_.Pop();
+    }
+  }
+  return PopEmptyBlock();
+}
+
+
+StoreBufferBlock* StoreBuffer::PopEmptyBlock() {
+  {
+    MutexLocker ml(global_mutex_);
+    if (!global_empty_->IsEmpty()) {
+      global_empty_->Pop();
+    }
+  }
+  return new StoreBufferBlock();
+}
+
+
+StoreBuffer::List::~List() {
+  while (!IsEmpty()) {
+    delete Pop();
+  }
+}
+
+
+StoreBufferBlock* StoreBuffer::List::Pop() {
+  StoreBufferBlock* result = head_;
+  head_ = head_->next_;
+  --length_;
+  result->next_ = NULL;
+  return result;
+}
+
+
+StoreBufferBlock* StoreBuffer::List::PopAll() {
+  StoreBufferBlock* result = head_;
+  head_ = NULL;
+  length_ = 0;
+  return result;
+}
+
+
+void StoreBuffer::List::Push(StoreBufferBlock* block) {
+  ASSERT(block->next_ == NULL);
+  block->next_ = head_;
+  head_ = block;
+  ++length_;
+}
+
+
+void StoreBuffer::CheckThresholdNonEmpty() {
+  DEBUG_ASSERT(mutex_->IsOwnedByCurrentThread());
+  if (full_.length() + partial_.length() > kMaxNonEmpty) {
+    Isolate* isolate = Isolate::Current();
+    // Sanity check: it makes no sense to schedule the GC in another isolate.
+    // (If Isolate ever gets multiple store buffers, we should avoid this
+    // coupling by passing in an explicit callback+parameter at construction.)
+    ASSERT(isolate->store_buffer() == this);
+    isolate->ScheduleInterrupts(Isolate::kStoreBufferInterrupt);
+  }
+}
+
+
+void StoreBuffer::TrimGlobalEmpty() {
+  DEBUG_ASSERT(global_mutex_->IsOwnedByCurrentThread());
+  while (global_empty_->length() > kMaxGlobalEmpty) {
+    delete global_empty_->Pop();
   }
 }
 
diff --git a/runtime/vm/store_buffer.h b/runtime/vm/store_buffer.h
index cc92d72..b8f36a5 100644
--- a/runtime/vm/store_buffer.h
+++ b/runtime/vm/store_buffer.h
@@ -12,33 +12,58 @@
 
 // Forward declarations.
 class Isolate;
+class Mutex;
 class RawObject;
 
+// A set of RawObject*. Must be emptied before destruction (using Pop/Reset).
 class StoreBufferBlock {
  public:
-  // Each block contains kSize pointers.
+  // Each full block contains kSize pointers.
   static const int32_t kSize = 1024;
 
-  explicit StoreBufferBlock(StoreBufferBlock* next) : next_(next), top_(0) {}
-
-  void Reset() { top_ = 0; }
+  void Reset() {
+    top_ = 0;
+    next_ = NULL;
+  }
 
   StoreBufferBlock* next() const { return next_; }
 
   intptr_t Count() const { return top_; }
+  bool IsFull() const { return Count() == kSize; }
+  bool IsEmpty() const { return Count() == 0; }
 
-  RawObject* At(intptr_t i) const {
-    ASSERT(i >= 0);
-    ASSERT(i < top_);
-    return pointers_[i];
+  void Push(RawObject* obj) {
+    ASSERT(!IsFull());
+    pointers_[top_++] = obj;
   }
 
+  RawObject* Pop() {
+    ASSERT(!IsEmpty());
+    return pointers_[--top_];
+  }
+
+#if defined(TESTING)
+  bool Contains(RawObject* obj) const {
+    for (intptr_t i = 0; i < Count(); i++) {
+      if (pointers_[i] == obj) {
+        return true;
+      }
+    }
+    return false;
+  }
+#endif  // TESTING
+
   static intptr_t top_offset() { return OFFSET_OF(StoreBufferBlock, top_); }
   static intptr_t pointers_offset() {
     return OFFSET_OF(StoreBufferBlock, pointers_);
   }
 
  private:
+  StoreBufferBlock() : next_(NULL), top_(0) {}
+  ~StoreBufferBlock() {
+    ASSERT(IsEmpty());  // Guard against unintentionally discarding pointers.
+  }
+
   StoreBufferBlock* next_;
   int32_t top_;
   RawObject* pointers_[kSize];
@@ -51,59 +76,57 @@
 
 class StoreBuffer {
  public:
-  StoreBuffer() : blocks_(new StoreBufferBlock(NULL)), full_count_(0) {}
-  explicit StoreBuffer(bool shallow_copy) : blocks_(NULL), full_count_(0) {
-    // The value shallow_copy is only used to select this non-allocating
-    // constructor. It is always expected to be true.
-    ASSERT(shallow_copy);
-  }
+  StoreBuffer();
   ~StoreBuffer();
+  static void InitOnce();
 
-  intptr_t Count() const {
-    return blocks_->Count() + (full_count_ * StoreBufferBlock::kSize);
-  }
+  // Interrupt when crossing this threshold of non-empty blocks in the buffer.
+  static const intptr_t kMaxNonEmpty = 100;
 
+  // Adds and transfers ownership of the block to the buffer.
+  void PushBlock(StoreBufferBlock* block, bool check_threshold = true);
+  // Partially filled blocks can be reused, and there is an "inifite" supply
+  // of empty blocks (reused or newly allocated). In any case, the caller
+  // takes ownership of the returned block.
+  StoreBufferBlock* PopBlock();
+  StoreBufferBlock* PopEmptyBlock();
+
+  // Pops and returns all non-empty blocks as a linked list (owned by caller).
+  StoreBufferBlock* Blocks();
+
+  // Discards the contents of this store buffer.
   void Reset();
 
-  void AddObject(RawObject* obj) {
-    StoreBufferBlock* block = blocks_;
-    ASSERT(block->top_ < StoreBufferBlock::kSize);
-    block->pointers_[block->top_++] = obj;
-    if (block->top_ == StoreBufferBlock::kSize) {
-      Expand(true);
-    }
-  }
-
-  void AddObjectGC(RawObject* obj) {
-    StoreBufferBlock* block = blocks_;
-    ASSERT(block->top_ < StoreBufferBlock::kSize);
-    block->pointers_[block->top_++] = obj;
-    if (block->top_ == StoreBufferBlock::kSize) {
-      Expand(false);
-    }
-  }
-
-  StoreBufferBlock* Blocks() {
-    StoreBufferBlock* result = blocks_;
-    blocks_ = new StoreBufferBlock(NULL);
-    full_count_ = 0;
-    return result;
-  }
-
-  // Expand the storage and optionally check whethe to schedule an interrupt.
-  void Expand(bool check);
-
-  bool Contains(RawObject* raw);
-
-  static int blocks_offset() { return OFFSET_OF(StoreBuffer, blocks_); }
-
  private:
+  class List {
+   public:
+    List() : head_(NULL), length_(0) {}
+    ~List();
+    void Push(StoreBufferBlock* block);
+    StoreBufferBlock* Pop();
+    intptr_t length() const { return length_; }
+    bool IsEmpty() const { return head_ == NULL; }
+    StoreBufferBlock* PopAll();
+   private:
+    StoreBufferBlock* head_;
+    intptr_t length_;
+    DISALLOW_COPY_AND_ASSIGN(List);
+  };
+
   // Check if we run over the max number of deduplication sets.
   // If we did schedule an interrupt.
-  void CheckThreshold();
+  void CheckThresholdNonEmpty();
 
-  StoreBufferBlock* blocks_;
-  intptr_t full_count_;
+  // If needed, trims the the global cache of empty blocks.
+  static void TrimGlobalEmpty();
+
+  List full_;
+  List partial_;
+  Mutex* mutex_;
+
+  static const intptr_t kMaxGlobalEmpty = 100;
+  static List* global_empty_;
+  static Mutex* global_mutex_;
 
   DISALLOW_COPY_AND_ASSIGN(StoreBuffer);
 };
diff --git a/runtime/vm/stub_code.cc b/runtime/vm/stub_code.cc
index 2f41ba0..38fd623 100644
--- a/runtime/vm/stub_code.cc
+++ b/runtime/vm/stub_code.cc
@@ -156,6 +156,9 @@
       DisassembleToStdout formatter;
       stub.Disassemble(&formatter);
       ISL_Print("}\n");
+      const ObjectPool& object_pool = ObjectPool::Handle(
+          Instructions::Handle(stub.instructions()).object_pool());
+      object_pool.DebugPrint();
     }
     stub.set_entry_patch_pc_offset(entry_patch_offset);
     stub.set_patch_code_pc_offset(patch_code_offset);
@@ -190,6 +193,9 @@
     DisassembleToStdout formatter;
     code.Disassemble(&formatter);
     ISL_Print("}\n");
+    const ObjectPool& object_pool = ObjectPool::Handle(
+        Instructions::Handle(code.instructions()).object_pool());
+    object_pool.DebugPrint();
   }
   return code.raw();
 }
diff --git a/runtime/vm/stub_code.h b/runtime/vm/stub_code.h
index 6852f3b..67e022d 100644
--- a/runtime/vm/stub_code.h
+++ b/runtime/vm/stub_code.h
@@ -20,7 +20,6 @@
 // List of stubs created in the VM isolate, these stubs are shared by different
 // isolates running in this dart process.
 #define VM_STUB_CODE_LIST(V)                                                   \
-  V(PrintStopMessage)                                                          \
   V(GetStackPointer)                                                           \
   V(JumpToExceptionHandler)                                                    \
 
@@ -35,6 +34,7 @@
 // The initial stubs are needed for loading bootstrapping scripts and have to
 // be generated before Object::Init is called.
 #define BOOTSTRAP_STUB_CODE_LIST(V)                                            \
+  V(PrintStopMessage)                                                          \
   V(CallToRuntime)                                                             \
   V(LazyCompile)                                                               \
 
diff --git a/runtime/vm/stub_code_arm.cc b/runtime/vm/stub_code_arm.cc
index 08a6d0e..d657120 100644
--- a/runtime/vm/stub_code_arm.cc
+++ b/runtime/vm/stub_code_arm.cc
@@ -28,6 +28,7 @@
 DECLARE_FLAG(bool, trace_optimized_ic_calls);
 DECLARE_FLAG(int, optimization_counter_threshold);
 DECLARE_FLAG(bool, support_debugger);
+DECLARE_FLAG(bool, lazy_dispatchers);
 
 // Input parameters:
 //   LR : return address.
@@ -43,9 +44,7 @@
   const intptr_t retval_offset = NativeArguments::retval_offset();
   const intptr_t exitframe_last_param_slot_from_fp = 2;
 
-  __ mov(IP, Operand(0));
-  __ Push(IP);  // Push 0 for the PC marker.
-  __ EnterFrame((1 << FP) | (1 << LR), 0);
+  __ EnterStubFrame();
 
   COMPILE_ASSERT((kAbiPreservedCpuRegs & (1 << R9)) != 0);
   __ LoadIsolate(R9);
@@ -104,9 +103,7 @@
   __ LoadImmediate(R2, 0);
   __ StoreToOffset(kWord, R2, R9, Isolate::top_exit_frame_info_offset());
 
-  __ LeaveFrame((1 << FP) | (1 << LR));
-  // Adjust SP for the empty PC marker.
-  __ AddImmediate(SP, kWordSize);
+  __ LeaveStubFrame();
   __ Ret();
 }
 
@@ -142,9 +139,7 @@
   const intptr_t argv_offset = NativeArguments::argv_offset();
   const intptr_t retval_offset = NativeArguments::retval_offset();
 
-  __ mov(IP, Operand(0));
-  __ Push(IP);  // Push 0 for the PC marker.
-  __ EnterFrame((1 << FP) | (1 << LR), 0);
+  __ EnterStubFrame();
 
   COMPILE_ASSERT((kAbiPreservedCpuRegs & (1 << R9)) != 0);
   __ LoadIsolate(R9);
@@ -216,9 +211,7 @@
   __ LoadImmediate(R2, 0);
   __ StoreToOffset(kWord, R2, R9, Isolate::top_exit_frame_info_offset());
 
-  __ LeaveFrame((1 << FP) | (1 << LR));
-  // Adjust SP for the empty PC marker.
-  __ AddImmediate(SP, kWordSize);
+  __ LeaveStubFrame();
   __ Ret();
 }
 
@@ -235,9 +228,7 @@
   const intptr_t argv_offset = NativeArguments::argv_offset();
   const intptr_t retval_offset = NativeArguments::retval_offset();
 
-  __ mov(IP, Operand(0));
-  __ Push(IP);  // Push 0 for the PC marker.
-  __ EnterFrame((1 << FP) | (1 << LR), 0);
+  __ EnterStubFrame();
 
   COMPILE_ASSERT((kAbiPreservedCpuRegs & (1 << R9)) != 0);
   __ LoadIsolate(R9);
@@ -300,9 +291,7 @@
   __ LoadImmediate(R2, 0);
   __ StoreToOffset(kWord, R2, R9, Isolate::top_exit_frame_info_offset());
 
-  __ LeaveFrame((1 << FP) | (1 << LR));
-  // Adjust SP for the empty PC marker.
-  __ AddImmediate(SP, kWordSize);
+  __ LeaveStubFrame();
   __ Ret();
 }
 
@@ -534,7 +523,7 @@
   // Materialize any objects that were deferred by FillFrame because they
   // require allocation.
   // Enter stub frame with loading PP. The caller's PP is not materialized yet.
-  __ EnterStubFrame(true);
+  __ EnterStubFrame();
   if (preserve_result) {
     __ Push(R1);  // Preserve result, it will be GC-d here.
   }
@@ -566,6 +555,33 @@
 }
 
 
+static void GenerateDispatcherCode(Assembler* assembler,
+                                   Label* call_target_function) {
+  __ Comment("NoSuchMethodDispatch");
+  // When lazily generated invocation dispatchers are disabled, the
+  // miss-handler may return null.
+  __ CompareObject(R0, Object::null_object());
+  __ b(call_target_function, NE);
+  __ EnterStubFrame();
+  // Load the receiver.
+  __ ldr(R2, FieldAddress(R4, ArgumentsDescriptor::count_offset()));
+  __ add(IP, FP, Operand(R2, LSL, 1));  // R2 is Smi.
+  __ ldr(R6, Address(IP, kParamEndSlotFromFp * kWordSize));
+  __ PushObject(Object::null_object());
+  __ Push(R6);
+  __ Push(R5);
+  __ Push(R4);
+  // R2: Smi-tagged arguments array length.
+  PushArgumentsArray(assembler);
+  const intptr_t kNumArgs = 4;
+  __ CallRuntime(kInvokeNoSuchMethodDispatcherRuntimeEntry, kNumArgs);
+  __ Drop(4);
+  __ Pop(R0);  // Return value.
+  __ LeaveStubFrame();
+  __ Ret();
+}
+
+
 void StubCode::GenerateMegamorphicMissStub(Assembler* assembler) {
   __ EnterStubFrame();
 
@@ -593,6 +609,12 @@
 
   __ LeaveStubFrame();
 
+  if (!FLAG_lazy_dispatchers) {
+    Label call_target_function;
+    GenerateDispatcherCode(assembler, &call_target_function);
+    __ Bind(&call_target_function);
+  }
+
   // Tail-call to target function.
   __ ldr(R2, FieldAddress(R0, Function::instructions_offset()));
   __ AddImmediate(R2, Instructions::HeaderSize() - kHeapObjectTag);
@@ -1009,15 +1031,9 @@
     __ b(&retry, EQ);
   }
 
-  // Load the isolate.
-  // Spilled: R1, R2, R3.
-  // R0: address being stored.
-  __ LoadIsolate(R1);
-
-  // Load the StoreBuffer block out of the isolate. Then load top_ out of the
+  // Load the StoreBuffer block out of the thread. Then load top_ out of the
   // StoreBufferBlock and add the address to the pointers_.
-  // R1: isolate.
-  __ ldr(R1, Address(R1, Isolate::store_buffer_offset()));
+  __ ldr(R1, Address(THR, Thread::store_buffer_block_offset()));
   __ ldr(R2, Address(R1, StoreBufferBlock::top_offset()));
   __ add(R3, R1, Operand(R2, LSL, 2));
   __ str(R0, Address(R3, StoreBufferBlock::pointers_offset()));
@@ -1039,7 +1055,7 @@
   // Setup frame, push callee-saved registers.
 
   __ EnterCallRuntimeFrame(0 * kWordSize);
-  __ LoadIsolate(R0);
+  __ mov(R0, Operand(THR));
   __ CallRuntime(kStoreBufferBlockProcessRuntimeEntry, 1);
   // Restore callee-saved registers, tear down frame.
   __ LeaveCallRuntimeFrame();
@@ -1163,7 +1179,7 @@
   // R4: new object type arguments.
   // Create a stub frame as we are pushing some objects on the stack before
   // calling into the runtime.
-  __ EnterStubFrame(true);  // Uses pool pointer to pass cls to runtime.
+  __ EnterStubFrame();  // Uses pool pointer to pass cls to runtime.
   __ LoadImmediate(R2, reinterpret_cast<intptr_t>(Object::null()));
   __ Push(R2);  // Setup space on stack for return value.
   __ PushObject(cls);  // Push class of object to be allocated.
@@ -1464,7 +1480,11 @@
   __ PopList((1 << R0) | (1 << R4) | (1 << R5));
   __ LeaveStubFrame();
   Label call_target_function;
-  __ b(&call_target_function);
+  if (!FLAG_lazy_dispatchers) {
+    GenerateDispatcherCode(assembler, &call_target_function);
+  } else {
+    __ b(&call_target_function);
+  }
 
   __ Bind(&found);
   // R6: pointer to an IC data check group.
diff --git a/runtime/vm/stub_code_arm64.cc b/runtime/vm/stub_code_arm64.cc
index af419b2..5d07451 100644
--- a/runtime/vm/stub_code_arm64.cc
+++ b/runtime/vm/stub_code_arm64.cc
@@ -27,6 +27,7 @@
 DECLARE_FLAG(bool, trace_optimized_ic_calls);
 DECLARE_FLAG(int, optimization_counter_threshold);
 DECLARE_FLAG(bool, support_debugger);
+DECLARE_FLAG(bool, lazy_dispatchers);
 
 // Input parameters:
 //   LR : return address.
@@ -44,7 +45,7 @@
 
   __ SetPrologueOffset();
   __ Comment("CallToRuntimeStub");
-  __ EnterFrame(0);
+  __ EnterStubFrame();
 
   COMPILE_ASSERT((kAbiPreservedCpuRegs & (1 << R28)) != 0);
   __ LoadIsolate(R28, kNoPP);
@@ -122,7 +123,7 @@
   // Reset exit frame information in Isolate structure.
   __ StoreToOffset(ZR, R28, Isolate::top_exit_frame_info_offset(), kNoPP);
 
-  __ LeaveFrame();
+  __ LeaveStubFrame();
   __ ret();
 }
 
@@ -144,7 +145,7 @@
   const intptr_t argv_offset = NativeArguments::argv_offset();
   const intptr_t retval_offset = NativeArguments::retval_offset();
 
-  __ EnterFrame(0);
+  __ EnterStubFrame();
 
   COMPILE_ASSERT((kAbiPreservedCpuRegs & (1 << R28)) != 0);
   __ LoadIsolate(R28, kNoPP);
@@ -229,7 +230,7 @@
   // Reset exit frame information in Isolate structure.
   __ StoreToOffset(ZR, R28, Isolate::top_exit_frame_info_offset(), kNoPP);
 
-  __ LeaveFrame();
+  __ LeaveStubFrame();
   __ ret();
 }
 
@@ -246,7 +247,7 @@
   const intptr_t argv_offset = NativeArguments::argv_offset();
   const intptr_t retval_offset = NativeArguments::retval_offset();
 
-  __ EnterFrame(0);
+  __ EnterStubFrame();
 
   COMPILE_ASSERT((kAbiPreservedCpuRegs & (1 << R28)) != 0);
   __ LoadIsolate(R28, kNoPP);
@@ -322,7 +323,7 @@
   // Reset exit frame information in Isolate structure.
   __ StoreToOffset(ZR, R28, Isolate::top_exit_frame_info_offset(), kNoPP);
 
-  __ LeaveFrame();
+  __ LeaveStubFrame();
   __ ret();
 }
 
@@ -542,7 +543,7 @@
   // Materialize any objects that were deferred by FillFrame because they
   // require allocation.
   // Enter stub frame with loading PP. The caller's PP is not materialized yet.
-  __ EnterStubFrame(true);
+  __ EnterStubFrame();
   if (preserve_result) {
     __ Push(ZR);  // Workaround for dropped stack slot during GC.
     __ Push(R1);  // Preserve result, it will be GC-d here.
@@ -577,6 +578,34 @@
 }
 
 
+static void GenerateDispatcherCode(Assembler* assembler,
+                                   Label* call_target_function) {
+  __ Comment("NoSuchMethodDispatch");
+  // When lazily generated invocation dispatchers are disabled, the
+  // miss-handler may return null.
+  __ CompareObject(R0, Object::null_object(), PP);
+  __ b(call_target_function, NE);
+  __ EnterStubFrame();
+
+  // Load the receiver.
+  __ LoadFieldFromOffset(R2, R4, ArgumentsDescriptor::count_offset(), kNoPP);
+  __ add(TMP, FP, Operand(R2, LSL, 2));  // R2 is Smi.
+  __ LoadFromOffset(R6, TMP, kParamEndSlotFromFp * kWordSize, kNoPP);
+  __ PushObject(Object::null_object(), PP);
+  __ Push(R6);
+  __ Push(R5);
+  __ Push(R4);
+  // R2: Smi-tagged arguments array length.
+  PushArgumentsArray(assembler);
+  const intptr_t kNumArgs = 4;
+  __ CallRuntime(kInvokeNoSuchMethodDispatcherRuntimeEntry, kNumArgs);
+  __ Drop(4);
+  __ Pop(R0);  // Return value.
+  __ LeaveStubFrame();
+  __ ret();
+}
+
+
 void StubCode::GenerateMegamorphicMissStub(Assembler* assembler) {
   __ EnterStubFrame();
 
@@ -608,6 +637,12 @@
 
   __ LeaveStubFrame();
 
+  if (!FLAG_lazy_dispatchers) {
+    Label call_target_function;
+    GenerateDispatcherCode(assembler, &call_target_function);
+    __ Bind(&call_target_function);
+  }
+
   // Tail-call to target function.
   __ LoadFieldFromOffset(R2, R0, Function::instructions_offset(), kNoPP);
   __ AddImmediate(R2, R2, Instructions::HeaderSize() - kHeapObjectTag, PP);
@@ -1035,15 +1070,9 @@
   __ orri(R2, TMP, Immediate(1 << RawObject::kRememberedBit));
   __ StoreFieldToOffset(R2, R0, Object::tags_offset(), kNoPP);
 
-  // Load the isolate.
-  // Spilled: R1, R2, R3.
-  // R0: address being stored.
-  __ LoadIsolate(R1, kNoPP);
-
-  // Load the StoreBuffer block out of the isolate. Then load top_ out of the
+  // Load the StoreBuffer block out of the thread. Then load top_ out of the
   // StoreBufferBlock and add the address to the pointers_.
-  // R1: isolate.
-  __ LoadFromOffset(R1, R1, Isolate::store_buffer_offset(), kNoPP);
+  __ LoadFromOffset(R1, THR, Thread::store_buffer_block_offset(), kNoPP);
   __ LoadFromOffset(R2, R1, StoreBufferBlock::top_offset(),
                     kNoPP, kUnsignedWord);
   __ add(R3, R1, Operand(R2, LSL, 3));
@@ -1069,7 +1098,7 @@
   // Setup frame, push callee-saved registers.
 
   __ EnterCallRuntimeFrame(0 * kWordSize);
-  __ LoadIsolate(R0, kNoPP);
+  __ mov(R0, THR);
   __ CallRuntime(kStoreBufferBlockProcessRuntimeEntry, 1);
   // Restore callee-saved registers, tear down frame.
   __ LeaveCallRuntimeFrame();
@@ -1185,7 +1214,7 @@
   // R1: new object type arguments.
   // Create a stub frame as we are pushing some objects on the stack before
   // calling into the runtime.
-  __ EnterStubFrame(true);  // Uses pool pointer to pass cls to runtime.
+  __ EnterStubFrame();  // Uses pool pointer to pass cls to runtime.
   // Setup space on stack for return value.
   __ PushObject(Object::null_object(), PP);
   __ PushObject(cls, PP);  // Push class of object to be allocated.
@@ -1217,7 +1246,7 @@
 //  SP : address of last argument.
 //  R4: arguments descriptor array.
 void StubCode::GenerateCallClosureNoSuchMethodStub(Assembler* assembler) {
-  __ EnterStubFrame(true);
+  __ EnterStubFrame();
 
   // Load the receiver.
   __ LoadFieldFromOffset(R2, R4, ArgumentsDescriptor::count_offset(), kNoPP);
@@ -1524,7 +1553,11 @@
   __ Pop(R4);  // Restore arguments descriptor array.
   __ LeaveStubFrame();
   Label call_target_function;
-  __ b(&call_target_function);
+  if (!FLAG_lazy_dispatchers) {
+    GenerateDispatcherCode(assembler, &call_target_function);
+  } else {
+    __ b(&call_target_function);
+  }
 
   __ Bind(&found);
   __ Comment("Update caller's counter");
@@ -2036,13 +2069,13 @@
   __ b(&reference_compare, NE);
   __ CompareClassId(right, kBigintCid, kNoPP);
   __ b(&done, NE);
-  __ EnterFrame(0);
+  __ EnterStubFrame();
   __ ReserveAlignedFrameSpace(2 * kWordSize);
   __ StoreToOffset(left, SP, 0 * kWordSize, kNoPP);
   __ StoreToOffset(right, SP, 1 * kWordSize, kNoPP);
   __ CallRuntime(kBigintCompareRuntimeEntry, 2);
   // Result in R0, 0 means equal.
-  __ LeaveFrame();
+  __ LeaveStubFrame();
   __ cmp(R0, Operand(0));
   __ b(&done);
 
diff --git a/runtime/vm/stub_code_ia32.cc b/runtime/vm/stub_code_ia32.cc
index 5837c80..e6f8818 100644
--- a/runtime/vm/stub_code_ia32.cc
+++ b/runtime/vm/stub_code_ia32.cc
@@ -29,6 +29,7 @@
 DECLARE_FLAG(bool, trace_optimized_ic_calls);
 DECLARE_FLAG(int, optimization_counter_threshold);
 DECLARE_FLAG(bool, support_debugger);
+DECLARE_FLAG(bool, lazy_dispatchers);
 
 #define INT32_SIZEOF(x) static_cast<int32_t>(sizeof(x))
 
@@ -505,6 +506,36 @@
 }
 
 
+static void GenerateDispatcherCode(Assembler* assembler,
+                                   Label* call_target_function) {
+  __ Comment("NoSuchMethodDispatch");
+  // When lazily generated invocation dispatchers are disabled, the
+  // miss-handler may return null.
+  const Immediate& raw_null =
+      Immediate(reinterpret_cast<intptr_t>(Object::null()));
+  __ cmpl(EAX, raw_null);
+  __ j(NOT_EQUAL, call_target_function);
+  __ EnterStubFrame();
+  // Load the receiver.
+  __ movl(EDI, FieldAddress(EDX, ArgumentsDescriptor::count_offset()));
+  __ movl(EAX, Address(
+      EBP, EDI, TIMES_HALF_WORD_SIZE, kParamEndSlotFromFp * kWordSize));
+  __ pushl(raw_null);  // Setup space on stack for result.
+  __ pushl(EAX);  // Receiver.
+  __ pushl(ECX);
+  __ pushl(EDX);  // Arguments descriptor array.
+  __ movl(EDX, EDI);
+  // EDX: Smi-tagged arguments array length.
+  PushArgumentsArray(assembler);
+  const intptr_t kNumArgs = 4;
+  __ CallRuntime(kInvokeNoSuchMethodDispatcherRuntimeEntry, kNumArgs);
+  __ Drop(4);
+  __ popl(EAX);  // Return value.
+  __ LeaveFrame();
+  __ ret();
+}
+
+
 void StubCode::GenerateMegamorphicMissStub(Assembler* assembler) {
   __ EnterStubFrame();
   // Load the receiver into EAX.  The argument count in the arguments
@@ -533,6 +564,12 @@
   __ popl(ECX);  // Restore IC data.
   __ LeaveFrame();
 
+  if (!FLAG_lazy_dispatchers) {
+    Label call_target_function;
+    GenerateDispatcherCode(assembler, &call_target_function);
+    __ Bind(&call_target_function);
+  }
+
   __ movl(EBX, FieldAddress(EAX, Function::instructions_offset()));
   __ addl(EBX, Immediate(Instructions::HeaderSize() - kHeapObjectTag));
   __ jmp(EBX);
@@ -954,17 +991,11 @@
   __ LockCmpxchgl(FieldAddress(EDX, Object::tags_offset()), ECX);
   __ j(NOT_EQUAL, &reload);
 
-  // Load the isolate.
-  // Spilled: EAX, ECX
-  // EDX: Address being stored
-  __ LoadIsolate(EAX);
-
-  // Load the StoreBuffer block out of the isolate. Then load top_ out of the
+  // Load the StoreBuffer block out of the thread. Then load top_ out of the
   // StoreBufferBlock and add the address to the pointers_.
   // Spilled: EAX, ECX
   // EDX: Address being stored
-  // EAX: Isolate
-  __ movl(EAX, Address(EAX, Isolate::store_buffer_offset()));
+  __ movl(EAX, Address(THR, Thread::store_buffer_block_offset()));
   __ movl(ECX, Address(EAX, StoreBufferBlock::top_offset()));
   __ movl(Address(EAX, ECX, TIMES_4, StoreBufferBlock::pointers_offset()), EDX);
 
@@ -988,8 +1019,7 @@
   // Setup frame, push callee-saved registers.
 
   __ EnterCallRuntimeFrame(1 * kWordSize);
-  __ LoadIsolate(EDX);
-  __ movl(Address(ESP, 0), EDX);  // Push the isolate as the only argument.
+  __ movl(Address(ESP, 0), THR);  // Push the thread as the only argument.
   __ CallRuntime(kStoreBufferBlockProcessRuntimeEntry, 1);
   // Restore callee-saved registers, tear down frame.
   __ LeaveCallRuntimeFrame();
@@ -1377,7 +1407,7 @@
       __ j(NOT_EQUAL, &update);  // Continue.
     } else {
       // Last check, all checks before matched.
-      __ j(EQUAL, &found, Assembler::kNearJump);  // Break.
+      __ j(EQUAL, &found);  // Break.
     }
   }
   __ Bind(&update);
@@ -1425,7 +1455,11 @@
   __ popl(EDX);  // Restore arguments descriptor array.
   __ LeaveFrame();
   Label call_target_function;
-  __ jmp(&call_target_function);
+  if (!FLAG_lazy_dispatchers) {
+    GenerateDispatcherCode(assembler, &call_target_function);
+  } else {
+    __ jmp(&call_target_function);
+  }
 
   __ Bind(&found);
 
diff --git a/runtime/vm/stub_code_mips.cc b/runtime/vm/stub_code_mips.cc
index 9210b45..a65cb5b 100644
--- a/runtime/vm/stub_code_mips.cc
+++ b/runtime/vm/stub_code_mips.cc
@@ -27,6 +27,7 @@
 DECLARE_FLAG(bool, trace_optimized_ic_calls);
 DECLARE_FLAG(int, optimization_counter_threshold);
 DECLARE_FLAG(bool, support_debugger);
+DECLARE_FLAG(bool, lazy_dispatchers);
 
 // Input parameters:
 //   RA : return address.
@@ -44,11 +45,7 @@
 
   __ SetPrologueOffset();
   __ Comment("CallToRuntimeStub");
-  __ addiu(SP, SP, Immediate(-3 * kWordSize));
-  __ sw(ZR, Address(SP, 2 * kWordSize));  // Push 0 for the PC marker
-  __ sw(RA, Address(SP, 1 * kWordSize));
-  __ sw(FP, Address(SP, 0 * kWordSize));
-  __ mov(FP, SP);
+  __ EnterStubFrame();
 
   COMPILE_ASSERT((kAbiPreservedCpuRegs & (1 << S6)) != 0);
   __ LoadIsolate(S6);
@@ -112,11 +109,7 @@
   // Reset exit frame information in Isolate structure.
   __ sw(ZR, Address(S6, Isolate::top_exit_frame_info_offset()));
 
-  __ mov(SP, FP);
-  __ lw(RA, Address(SP, 1 * kWordSize));
-  __ lw(FP, Address(SP, 0 * kWordSize));
-  __ Ret();
-  __ delay_slot()->addiu(SP, SP, Immediate(3 * kWordSize));
+  __ LeaveStubFrameAndReturn();
 }
 
 
@@ -153,11 +146,7 @@
 
   __ SetPrologueOffset();
   __ Comment("CallNativeCFunctionStub");
-  __ addiu(SP, SP, Immediate(-3 * kWordSize));
-  __ sw(ZR, Address(SP, 2 * kWordSize));  // Push 0 for the PC marker
-  __ sw(RA, Address(SP, 1 * kWordSize));
-  __ sw(FP, Address(SP, 0 * kWordSize));
-  __ mov(FP, SP);
+  __ EnterStubFrame();
 
   COMPILE_ASSERT((kAbiPreservedCpuRegs & (1 << S6)) != 0);
   __ LoadIsolate(S6);
@@ -229,11 +218,7 @@
   // Reset exit frame information in Isolate structure.
   __ sw(ZR, Address(S6, Isolate::top_exit_frame_info_offset()));
 
-  __ mov(SP, FP);
-  __ lw(RA, Address(SP, 1 * kWordSize));
-  __ lw(FP, Address(SP, 0 * kWordSize));
-  __ Ret();
-  __ delay_slot()->addiu(SP, SP, Immediate(3 * kWordSize));
+  __ LeaveStubFrameAndReturn();
 }
 
 
@@ -251,11 +236,7 @@
 
   __ SetPrologueOffset();
   __ Comment("CallNativeCFunctionStub");
-  __ addiu(SP, SP, Immediate(-3 * kWordSize));
-  __ sw(ZR, Address(SP, 2 * kWordSize));  // Push 0 for the PC marker
-  __ sw(RA, Address(SP, 1 * kWordSize));
-  __ sw(FP, Address(SP, 0 * kWordSize));
-  __ mov(FP, SP);
+  __ EnterStubFrame();
 
   COMPILE_ASSERT((kAbiPreservedCpuRegs & (1 << S6)) != 0);
   __ LoadIsolate(S6);
@@ -322,11 +303,7 @@
   // Reset exit frame information in Isolate structure.
   __ sw(ZR, Address(S6, Isolate::top_exit_frame_info_offset()));
 
-  __ mov(SP, FP);
-  __ lw(RA, Address(SP, 1 * kWordSize));
-  __ lw(FP, Address(SP, 0 * kWordSize));
-  __ Ret();
-  __ delay_slot()->addiu(SP, SP, Immediate(3 * kWordSize));
+  __ LeaveStubFrameAndReturn();
 }
 
 
@@ -591,7 +568,7 @@
   // Materialize any objects that were deferred by FillFrame because they
   // require allocation.
   // Enter stub frame with loading PP. The caller's PP is not materialized yet.
-  __ EnterStubFrame(true);
+  __ EnterStubFrame();
   if (preserve_result) {
     __ Push(T1);  // Preserve result, it will be GC-d here.
   }
@@ -624,6 +601,41 @@
 }
 
 
+static void GenerateDispatcherCode(Assembler* assembler,
+                                   Label* call_target_function) {
+  __ Comment("NoSuchMethodDispatch");
+  // When lazily generated invocation dispatchers are disabled, the
+  // miss-handler may return null.
+  __ BranchNotEqual(T0, Object::null_object(), call_target_function);
+  __ EnterStubFrame();
+  // Load the receiver.
+  __ lw(A1, FieldAddress(S4, ArgumentsDescriptor::count_offset()));
+  __ sll(TMP, A1, 1);  // A1 is a Smi.
+  __ addu(TMP, FP, TMP);
+  __ lw(T6, Address(TMP, kParamEndSlotFromFp * kWordSize));
+
+  // Push space for the return value.
+  // Push the receiver.
+  // Push IC data object.
+  // Push arguments descriptor array.
+  // Push original arguments array.
+  __ addiu(SP, SP, Immediate(-4 * kWordSize));
+  __ LoadImmediate(TMP, reinterpret_cast<intptr_t>(Object::null()));
+  __ sw(TMP, Address(SP, 3 * kWordSize));
+  __ sw(T6, Address(SP, 2 * kWordSize));
+  __ sw(S5, Address(SP, 1 * kWordSize));
+  __ sw(S4, Address(SP, 0 * kWordSize));
+  // A1: Smi-tagged arguments array length.
+  PushArgumentsArray(assembler);
+  const intptr_t kNumArgs = 4;
+  __ CallRuntime(kInvokeNoSuchMethodDispatcherRuntimeEntry, kNumArgs);
+  __ lw(V0, Address(SP, 4 * kWordSize));  // Return value.
+  __ addiu(SP, SP, Immediate(5 * kWordSize));
+  __ LeaveStubFrame();
+  __ Ret();
+}
+
+
 void StubCode::GenerateMegamorphicMissStub(Assembler* assembler) {
   __ EnterStubFrame();
 
@@ -657,6 +669,12 @@
 
   __ LeaveStubFrame();
 
+  if (!FLAG_lazy_dispatchers) {
+    Label call_target_function;
+    GenerateDispatcherCode(assembler, &call_target_function);
+    __ Bind(&call_target_function);
+  }
+
   __ lw(T2, FieldAddress(T0, Function::instructions_offset()));
   __ AddImmediate(T2, Instructions::HeaderSize() - kHeapObjectTag);
   __ jr(T2);
@@ -1098,15 +1116,9 @@
   __ ori(T2, T2, Immediate(1 << RawObject::kRememberedBit));
   __ sw(T2, FieldAddress(T0, Object::tags_offset()));
 
-  // Load the isolate.
-  // Spilled: T1, T2, T3.
-  // T0: Address being stored.
-  __ LoadIsolate(T1);
-
-  // Load the StoreBuffer block out of the isolate. Then load top_ out of the
+  // Load the StoreBuffer block out of the thread. Then load top_ out of the
   // StoreBufferBlock and add the address to the pointers_.
-  // T1: Isolate.
-  __ lw(T1, Address(T1, Isolate::store_buffer_offset()));
+  __ lw(T1, Address(THR, Thread::store_buffer_block_offset()));
   __ lw(T2, Address(T1, StoreBufferBlock::top_offset()));
   __ sll(T3, T2, 2);
   __ addu(T3, T1, T3);
@@ -1132,7 +1144,7 @@
   // Setup frame, push callee-saved registers.
 
   __ EnterCallRuntimeFrame(1 * kWordSize);
-  __ LoadIsolate(A0);
+  __ mov(A0, THR);
   __ CallRuntime(kStoreBufferBlockProcessRuntimeEntry, 1);
   __ Comment("UpdateStoreBufferStub return");
   // Restore callee-saved registers, tear down frame.
@@ -1249,7 +1261,7 @@
   // T1: new object type arguments (instantiated or not).
   // Create a stub frame as we are pushing some objects on the stack before
   // calling into the runtime.
-  __ EnterStubFrame(true);  // Uses pool pointer to pass cls to runtime.
+  __ EnterStubFrame();  // Uses pool pointer to pass cls to runtime.
   __ LoadObject(TMP, cls);
 
   __ addiu(SP, SP, Immediate(-3 * kWordSize));
@@ -1598,7 +1610,12 @@
   __ LeaveStubFrame();
 
   Label call_target_function;
-  __ b(&call_target_function);
+  if (!FLAG_lazy_dispatchers) {
+    __ mov(T0, T3);
+    GenerateDispatcherCode(assembler, &call_target_function);
+  } else {
+    __ b(&call_target_function);
+  }
 
   __ Bind(&found);
   __ Comment("Update caller's counter");
diff --git a/runtime/vm/stub_code_x64.cc b/runtime/vm/stub_code_x64.cc
index 7016668..2a15822 100644
--- a/runtime/vm/stub_code_x64.cc
+++ b/runtime/vm/stub_code_x64.cc
@@ -28,6 +28,7 @@
 DECLARE_FLAG(bool, trace_optimized_ic_calls);
 DECLARE_FLAG(int, optimization_counter_threshold);
 DECLARE_FLAG(bool, support_debugger);
+DECLARE_FLAG(bool, lazy_dispatchers);
 
 // Input parameters:
 //   RSP : points to return address.
@@ -43,7 +44,7 @@
   const intptr_t argv_offset = NativeArguments::argv_offset();
   const intptr_t retval_offset = NativeArguments::retval_offset();
 
-  __ EnterFrame(0);
+  __ EnterStubFrame();
 
   COMPILE_ASSERT(
       (CallingConventions::kCalleeSaveCpuRegisters & (1 << R12)) != 0);
@@ -95,7 +96,7 @@
   // Reset exit frame information in Isolate structure.
   __ movq(Address(R12, Isolate::top_exit_frame_info_offset()), Immediate(0));
 
-  __ LeaveFrame();
+  __ LeaveStubFrame();
   __ ret();
 }
 
@@ -140,7 +141,7 @@
   const intptr_t retval_offset =
       NativeArguments::retval_offset() + native_args_struct_offset;
 
-  __ EnterFrame(0);
+  __ EnterStubFrame();
 
   COMPILE_ASSERT(
       (CallingConventions::kCalleeSaveCpuRegisters & (1 << R12)) != 0);
@@ -192,7 +193,7 @@
   // Reset exit frame information in Isolate structure.
   __ movq(Address(R12, Isolate::top_exit_frame_info_offset()), Immediate(0));
 
-  __ LeaveFrame();
+  __ LeaveStubFrame();
   __ ret();
 }
 
@@ -214,7 +215,7 @@
   const intptr_t retval_offset =
       NativeArguments::retval_offset() + native_args_struct_offset;
 
-  __ EnterFrame(0);
+  __ EnterStubFrame();
 
   COMPILE_ASSERT(
       (CallingConventions::kCalleeSaveCpuRegisters & (1 << R12)) != 0);
@@ -264,7 +265,7 @@
   // Reset exit frame information in Isolate structure.
   __ movq(Address(R12, Isolate::top_exit_frame_info_offset()), Immediate(0));
 
-  __ LeaveFrame();
+  __ LeaveStubFrame();
   __ ret();
 }
 
@@ -486,7 +487,7 @@
   // Materialize any objects that were deferred by FillFrame because they
   // require allocation.
   // Enter stub frame with loading PP. The caller's PP is not materialized yet.
-  __ EnterStubFrame(true);
+  __ EnterStubFrame();
   if (preserve_result) {
     __ pushq(Immediate(0));  // Workaround for dropped stack slot during GC.
     __ pushq(RBX);  // Preserve result, it will be GC-d here.
@@ -527,6 +528,36 @@
 }
 
 
+static void GenerateDispatcherCode(Assembler* assembler,
+                                   Label* call_target_function) {
+  __ Comment("NoSuchMethodDispatch");
+  // When lazily generated invocation dispatchers are disabled, the
+  // miss-handler may return null.
+  const Immediate& raw_null =
+      Immediate(reinterpret_cast<intptr_t>(Object::null()));
+  __ cmpq(RAX, raw_null);
+  __ j(NOT_EQUAL, call_target_function);
+  __ EnterStubFrame();
+  // Load the receiver.
+  __ movq(RDI, FieldAddress(R10, ArgumentsDescriptor::count_offset()));
+  __ movq(RAX, Address(
+      RBP, RDI, TIMES_HALF_WORD_SIZE, kParamEndSlotFromFp * kWordSize));
+  __ pushq(raw_null);  // Setup space on stack for result.
+  __ pushq(RAX);  // Receiver.
+  __ pushq(RBX);
+  __ pushq(R10);  // Arguments descriptor array.
+  __ movq(R10, RDI);
+  // EDX: Smi-tagged arguments array length.
+  PushArgumentsArray(assembler);
+  const intptr_t kNumArgs = 4;
+  __ CallRuntime(kInvokeNoSuchMethodDispatcherRuntimeEntry, kNumArgs);
+  __ Drop(4);
+  __ popq(RAX);  // Return value.
+  __ LeaveStubFrame();
+  __ ret();
+}
+
+
 void StubCode::GenerateMegamorphicMissStub(Assembler* assembler) {
   __ EnterStubFrame();
   // Load the receiver into RAX.  The argument count in the arguments
@@ -555,6 +586,12 @@
   __ popq(RBX);  // Restore IC data.
   __ LeaveStubFrame();
 
+  if (!FLAG_lazy_dispatchers) {
+    Label call_target_function;
+    GenerateDispatcherCode(assembler, &call_target_function);
+    __ Bind(&call_target_function);
+  }
+
   __ movq(RCX, FieldAddress(RAX, Function::instructions_offset()));
   __ addq(RCX, Immediate(Instructions::HeaderSize() - kHeapObjectTag));
   __ jmp(RCX);
@@ -993,15 +1030,10 @@
   __ LockCmpxchgq(FieldAddress(RDX, Object::tags_offset()), RCX);
   __ j(NOT_EQUAL, &reload);
 
-  // Load the isolate.
-  // RDX: Address being stored
-  __ LoadIsolate(RAX);
-
-  // Load the StoreBuffer block out of the isolate. Then load top_ out of the
+  // Load the StoreBuffer block out of the thread. Then load top_ out of the
   // StoreBufferBlock and add the address to the pointers_.
   // RDX: Address being stored
-  // RAX: Isolate
-  __ movq(RAX, Address(RAX, Isolate::store_buffer_offset()));
+  __ movq(RAX, Address(THR, Thread::store_buffer_block_offset()));
   __ movl(RCX, Address(RAX, StoreBufferBlock::top_offset()));
   __ movq(Address(RAX, RCX, TIMES_8, StoreBufferBlock::pointers_offset()), RDX);
 
@@ -1022,7 +1054,7 @@
   __ Bind(&L);
   // Setup frame, push callee-saved registers.
   __ EnterCallRuntimeFrame(0);
-  __ LoadIsolate(CallingConventions::kArg1Reg);
+  __ movq(CallingConventions::kArg1Reg, THR);
   __ CallRuntime(kStoreBufferBlockProcessRuntimeEntry, 1);
   __ LeaveCallRuntimeFrame();
   __ ret();
@@ -1145,7 +1177,7 @@
   // If is_cls_parameterized:
   // RDX: new object type arguments.
   // Create a stub frame.
-  __ EnterStubFrame(true);  // Uses PP to access class object.
+  __ EnterStubFrame();  // Uses PP to access class object.
   __ pushq(R12);  // Setup space on stack for return value.
   __ PushObject(cls, PP);  // Push class of object to be allocated.
   if (is_cls_parameterized) {
@@ -1464,7 +1496,11 @@
   __ popq(R10);  // Restore arguments descriptor array.
   __ LeaveStubFrame();
   Label call_target_function;
-  __ jmp(&call_target_function);
+  if (!FLAG_lazy_dispatchers) {
+    GenerateDispatcherCode(assembler, &call_target_function);
+  } else {
+    __ jmp(&call_target_function);
+  }
 
   __ Bind(&found);
   // R12: Pointer to an IC data check group.
@@ -2024,13 +2060,13 @@
   __ j(NOT_EQUAL, &reference_compare, Assembler::kNearJump);
   __ CompareClassId(right, kBigintCid);
   __ j(NOT_EQUAL, &done, Assembler::kNearJump);
-  __ EnterFrame(0);
+  __ EnterStubFrame();
   __ ReserveAlignedFrameSpace(0);
   __ movq(CallingConventions::kArg1Reg, left);
   __ movq(CallingConventions::kArg2Reg, right);
   __ CallRuntime(kBigintCompareRuntimeEntry, 2);
   // Result in RAX, 0 means equal.
-  __ LeaveFrame();
+  __ LeaveStubFrame();
   __ cmpq(RAX, Immediate(0));
   __ jmp(&done);
 
diff --git a/runtime/vm/stub_code_x64_test.cc b/runtime/vm/stub_code_x64_test.cc
index 348d493..c91ae77 100644
--- a/runtime/vm/stub_code_x64_test.cc
+++ b/runtime/vm/stub_code_x64_test.cc
@@ -44,7 +44,7 @@
   const int argc = 2;
   const Smi& smi1 = Smi::ZoneHandle(Smi::New(value1));
   const Smi& smi2 = Smi::ZoneHandle(Smi::New(value2));
-  __ EnterStubFrame(true);
+  __ EnterStubFrame();
   __ PushObject(Object::null_object(), PP);  // Push Null obj for return value.
   __ PushObject(smi1, PP);  // Push argument 1 smi1.
   __ PushObject(smi2, PP);  // Push argument 2 smi2.
diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h
index ab8e379..68f4751 100644
--- a/runtime/vm/symbols.h
+++ b/runtime/vm/symbols.h
@@ -150,6 +150,7 @@
   V(Namespace, "Namespace")                                                    \
   V(Code, "Code")                                                              \
   V(Instructions, "Instructions")                                              \
+  V(ObjectPool, "ObjectPool")                                                  \
   V(PcDescriptors, "PcDescriptors")                                            \
   V(Stackmap, "Stackmap")                                                      \
   V(LocalVarDescriptors, "LocalVarDescriptors")                                \
diff --git a/runtime/vm/thread.cc b/runtime/vm/thread.cc
index 79919d4..ba6db93 100644
--- a/runtime/vm/thread.cc
+++ b/runtime/vm/thread.cc
@@ -72,6 +72,8 @@
   Profiler::BeginExecution(isolate);
   isolate->set_thread_state(thread_state);
   isolate->set_vm_tag(VMTag::kVMTagId);
+  ASSERT(thread->store_buffer_block_ == NULL);
+  thread->store_buffer_block_ = isolate->store_buffer()->PopBlock();
 }
 
 
@@ -80,6 +82,9 @@
   // TODO(koda): Audit callers; they should know whether they're in an isolate.
   if (thread == NULL || thread->isolate() == NULL) return;
   Isolate* isolate = thread->isolate();
+  StoreBufferBlock* block = thread->store_buffer_block_;
+  thread->store_buffer_block_ = NULL;
+  isolate->store_buffer()->PushBlock(block);
   if (isolate->is_runnable()) {
     isolate->set_vm_tag(VMTag::kIdleTagId);
   } else {
@@ -106,6 +111,9 @@
 
 void Thread::ExitIsolateAsHelper() {
   Thread* thread = Thread::Current();
+  // If the helper thread chose to use the store buffer, check that it has
+  // already been flushed manually.
+  ASSERT(thread->store_buffer_block_ == NULL);
   Isolate* isolate = thread->isolate();
   ASSERT(isolate != NULL);
   thread->isolate_ = NULL;
@@ -113,6 +121,42 @@
 }
 
 
+void Thread::PrepareForGC() {
+  Thread* thread = Thread::Current();
+  StoreBuffer* sb = thread->isolate()->store_buffer();
+  StoreBufferBlock* block = thread->store_buffer_block_;
+  thread->store_buffer_block_ = NULL;
+  const bool kCheckThreshold = false;  // Prevent scheduling another GC.
+  sb->PushBlock(block, kCheckThreshold);
+  thread->store_buffer_block_ = sb->PopEmptyBlock();
+}
+
+
+void Thread::StoreBufferBlockProcess(bool check_threshold) {
+  StoreBuffer* sb = isolate()->store_buffer();
+  StoreBufferBlock* block = store_buffer_block_;
+  store_buffer_block_ = NULL;
+  sb->PushBlock(block, check_threshold);
+  store_buffer_block_ = sb->PopBlock();
+}
+
+
+void Thread::StoreBufferAddObject(RawObject* obj) {
+  store_buffer_block_->Push(obj);
+  if (store_buffer_block_->IsFull()) {
+    StoreBufferBlockProcess(true);
+  }
+}
+
+
+void Thread::StoreBufferAddObjectGC(RawObject* obj) {
+  store_buffer_block_->Push(obj);
+  if (store_buffer_block_->IsFull()) {
+    StoreBufferBlockProcess(false);
+  }
+}
+
+
 CHA* Thread::cha() const {
   ASSERT(isolate_ != NULL);
   return isolate_->cha_;
diff --git a/runtime/vm/thread.h b/runtime/vm/thread.h
index 457f1a4..3a8dacd 100644
--- a/runtime/vm/thread.h
+++ b/runtime/vm/thread.h
@@ -8,6 +8,7 @@
 #include "vm/base_isolate.h"
 #include "vm/globals.h"
 #include "vm/os_thread.h"
+#include "vm/store_buffer.h"
 
 namespace dart {
 
@@ -41,6 +42,11 @@
   static void EnterIsolateAsHelper(Isolate* isolate);
   static void ExitIsolateAsHelper();
 
+  // Called when the current thread transitions from mutator to collector.
+  // Empties the store buffer block into the isolate.
+  // TODO(koda): Always run GC in separate thread.
+  static void PrepareForGC();
+
 #if defined(TARGET_OS_WINDOWS)
   // Clears the state of the current thread and frees the allocation.
   static void CleanUp();
@@ -65,13 +71,26 @@
   CHA* cha() const;
   void set_cha(CHA* value);
 
+  void StoreBufferAddObject(RawObject* obj);
+  void StoreBufferAddObjectGC(RawObject* obj);
+#if defined(TESTING)
+  bool StoreBufferContains(RawObject* obj) const {
+    return store_buffer_block_->Contains(obj);
+  }
+#endif
+  void StoreBufferBlockProcess(bool check_threshold);
+  static intptr_t store_buffer_block_offset() {
+    return OFFSET_OF(Thread, store_buffer_block_);
+  }
+
  private:
   static ThreadLocalKey thread_key_;
 
   Isolate* isolate_;
+  StoreBufferBlock* store_buffer_block_;
 
   Thread()
-      : isolate_(NULL) {}
+      : isolate_(NULL), store_buffer_block_(NULL) {}
 
   static void SetCurrent(Thread* current);
 
diff --git a/runtime/vm/timeline.cc b/runtime/vm/timeline.cc
new file mode 100644
index 0000000..2fc1440
--- /dev/null
+++ b/runtime/vm/timeline.cc
@@ -0,0 +1,517 @@
+// 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 <cstdlib>
+
+#include "vm/isolate.h"
+#include "vm/json_stream.h"
+#include "vm/object.h"
+#include "vm/thread.h"
+#include "vm/timeline.h"
+
+namespace dart {
+
+DEFINE_FLAG(bool, trace_timeline, false, "Timeline trace");
+
+TimelineEvent::TimelineEvent()
+    : timestamp0_(0),
+      timestamp1_(0),
+      arguments_(NULL),
+      arguments_length_(0),
+      state_(0),
+      label_(NULL),
+      stream_(NULL),
+      thread_(NULL) {
+}
+
+
+TimelineEvent::~TimelineEvent() {
+  Reset();
+}
+
+
+void TimelineEvent::Reset() {
+  set_event_type(kNone);
+  thread_ = NULL;
+  stream_ = NULL;
+  label_ = NULL;
+  FreeArguments();
+}
+
+
+int64_t TimelineEvent::AsyncBegin(const char* label) {
+  Init(kAsyncBegin, label);
+  timestamp0_ = OS::GetCurrentTimeMicros();
+  ASSERT(stream_ != NULL);
+  int64_t async_id = stream_->GetNextSeq();
+  // Overload timestamp1_ with the async_id.
+  timestamp1_ = async_id;
+  return async_id;
+}
+
+
+void TimelineEvent::AsyncInstant(const char* label,
+                                 int64_t async_id) {
+  Init(kAsyncInstant, label);
+  timestamp0_ = OS::GetCurrentTimeMicros();
+  // Overload timestamp1_ with the async_id.
+  timestamp1_ = async_id;
+}
+
+
+void TimelineEvent::AsyncEnd(const char* label,
+                             int64_t async_id) {
+  Init(kAsyncEnd, label);
+  timestamp0_ = OS::GetCurrentTimeMicros();
+  // Overload timestamp1_ with the async_id.
+  timestamp1_ = async_id;
+}
+
+
+void TimelineEvent::DurationBegin(const char* label) {
+  Init(kDuration, label);
+  timestamp0_ = OS::GetCurrentTimeMicros();
+}
+
+
+void TimelineEvent::DurationEnd() {
+  timestamp1_ = OS::GetCurrentTimeMicros();
+}
+
+
+void TimelineEvent::Instant(const char* label) {
+  Init(kInstant, label);
+  timestamp0_ = OS::GetCurrentTimeMicros();
+}
+
+
+void TimelineEvent::Duration(const char* label,
+                             int64_t start_micros,
+                             int64_t end_micros) {
+  Init(kDuration, label);
+  timestamp0_ = start_micros;
+  timestamp1_ = end_micros;
+}
+
+
+void TimelineEvent::SetNumArguments(intptr_t length) {
+  // Cannot call this twice.
+  ASSERT(arguments_ == NULL);
+  ASSERT(arguments_length_ == 0);
+  arguments_length_ = length;
+  arguments_ = reinterpret_cast<TimelineEventArgument*>(
+      calloc(sizeof(TimelineEventArgument), length));
+}
+
+
+void TimelineEvent::SetArgument(intptr_t i, const char* name, char* argument) {
+  ASSERT(i >= 0);
+  ASSERT(i < arguments_length_);
+  arguments_[i].name = name;
+  arguments_[i].value = argument;
+}
+
+
+void TimelineEvent::FormatArgument(intptr_t i, const char* name,
+                                   const char* fmt, ...) {
+  ASSERT(i >= 0);
+  ASSERT(i < arguments_length_);
+  va_list args;
+  va_start(args, fmt);
+  intptr_t len = OS::VSNPrint(NULL, 0, fmt, args);
+  va_end(args);
+
+  char* buffer = reinterpret_cast<char*>(malloc(len + 1));
+  va_list args2;
+  va_start(args2, fmt);
+  OS::VSNPrint(buffer, (len + 1), fmt, args2);
+  va_end(args2);
+
+  SetArgument(i, name, buffer);
+}
+
+
+void TimelineEvent::CopyArgument(intptr_t i,
+                                 const char* name,
+                                 const char* argument) {
+  SetArgument(i, name, strdup(argument));
+}
+
+
+void TimelineEvent::Complete() {
+  stream_->CompleteEvent(this);
+}
+
+
+void TimelineEvent::FreeArguments() {
+  if (arguments_ == NULL) {
+    return;
+  }
+  for (intptr_t i = 0; i < arguments_length_; i++) {
+    free(arguments_[i].value);
+  }
+  free(arguments_);
+  arguments_ = NULL;
+  arguments_length_ = 0;
+}
+
+
+void TimelineEvent::StreamInit(TimelineStream* stream) {
+  ASSERT(stream != NULL);
+  stream_ = stream;
+}
+
+
+void TimelineEvent::Init(EventType event_type,
+                         const char* label) {
+  ASSERT(label != NULL);
+  set_event_type(event_type);
+  timestamp0_ = 0;
+  timestamp1_ = 0;
+  thread_ = Thread::Current();
+  label_ = label;
+  FreeArguments();
+}
+
+
+static int64_t GetPid(Isolate* isolate) {
+  // Some mapping from Isolate* to an integer process id.
+  // TODO(Cutch): Investigate if process ids can be strings.
+  return static_cast<int64_t>(reinterpret_cast<uintptr_t>(isolate));
+}
+
+
+static int64_t GetTid(Thread* thread) {
+  // Some mapping from Thread* to an integer thread id.
+  // TODO(Cutch): Investigate if process ids can be strings.
+  return static_cast<int64_t>(reinterpret_cast<uintptr_t>(thread));
+}
+
+
+void TimelineEvent::PrintJSON(JSONStream* stream) const {
+  JSONObject obj(stream);
+  int64_t pid = GetPid(Isolate::Current());
+  int64_t tid = GetTid(thread_);
+  obj.AddProperty("name", label_);
+  obj.AddProperty("cat", stream_->name());
+  obj.AddProperty64("tid", tid);
+  obj.AddProperty64("pid", pid);
+  obj.AddProperty("ts", static_cast<double>(TimeOrigin()));
+
+  switch (event_type()) {
+    case kDuration: {
+      obj.AddProperty("ph", "X");
+      obj.AddProperty("dur", static_cast<double>(TimeDuration()));
+    }
+    break;
+    case kInstant: {
+      obj.AddProperty("ph", "i");
+      obj.AddProperty("s", "p");
+    }
+    break;
+    case kAsyncBegin: {
+      obj.AddProperty("ph", "b");
+      obj.AddPropertyF("id", "%" Px64 "", AsyncId());
+    }
+    break;
+    case kAsyncInstant: {
+      obj.AddProperty("ph", "n");
+      obj.AddPropertyF("id", "%" Px64 "", AsyncId());
+    }
+    break;
+    case kAsyncEnd: {
+      obj.AddProperty("ph", "e");
+      obj.AddPropertyF("id", "%" Px64 "", AsyncId());
+    }
+    break;
+    default:
+      UNIMPLEMENTED();
+  }
+  {
+    JSONObject args(&obj, "args");
+    for (intptr_t i = 0; i < arguments_length_; i++) {
+      const TimelineEventArgument& arg = arguments_[i];
+      args.AddProperty(arg.name, arg.value);
+    }
+  }
+}
+
+
+int64_t TimelineEvent::TimeOrigin() const {
+  return timestamp0_;
+}
+
+
+int64_t TimelineEvent::AsyncId() const {
+  return timestamp1_;
+}
+
+
+int64_t TimelineEvent::TimeDuration() const {
+  if (timestamp1_ == 0) {
+    // This duration is still open, use current time as end.
+    return OS::GetCurrentTimeMicros() - timestamp0_;
+  }
+  return timestamp1_ - timestamp0_;
+}
+
+
+TimelineStream::TimelineStream()
+    : recorder_(NULL),
+      name_(NULL),
+      enabled_(false),
+      seq_(0) {
+}
+
+
+void TimelineStream::Init(const char* name, bool enabled) {
+  name_ = name;
+  enabled_ = enabled;
+}
+
+
+TimelineEvent* TimelineStream::StartEvent(const Object& obj) {
+  if (!enabled_ || (recorder_ == NULL)) {
+    return NULL;
+  }
+  ASSERT(name_ != NULL);
+  ASSERT(recorder_ != NULL);
+  TimelineEvent* event = recorder_->StartEvent(obj);
+  if (event != NULL) {
+    event->StreamInit(this);
+  }
+  return event;
+}
+
+
+TimelineEvent* TimelineStream::StartEvent() {
+  if (!enabled_ || (recorder_ == NULL)) {
+    return NULL;
+  }
+  ASSERT(name_ != NULL);
+  TimelineEvent* event = recorder_->StartEvent();
+  if (event != NULL) {
+    event->StreamInit(this);
+  }
+  return event;
+}
+
+
+void TimelineStream::CompleteEvent(TimelineEvent* event) {
+  if (!enabled_ || (recorder_ == NULL)) {
+    return;
+  }
+  recorder_->CompleteEvent(event);
+}
+
+
+int64_t TimelineStream::GetNextSeq() {
+  seq_++;
+  if (seq_ < 0) {
+    seq_ = 0;
+  }
+  return seq_;
+}
+
+
+void TimelineDurationScope::FormatArgument(intptr_t i,
+                                           const char* name,
+                                           const char* fmt, ...) {
+  if (event_ == NULL) {
+    return;
+  }
+  va_list args;
+  va_start(args, fmt);
+  intptr_t len = OS::VSNPrint(NULL, 0, fmt, args);
+  va_end(args);
+
+  char* buffer = reinterpret_cast<char*>(malloc(len + 1));
+  va_list args2;
+  va_start(args2, fmt);
+  OS::VSNPrint(buffer, (len + 1), fmt, args2);
+  va_end(args2);
+
+  event_->SetArgument(i, name, buffer);
+}
+
+
+TimelineEventRecorder::TimelineEventRecorder() {
+}
+
+
+void TimelineEventRecorder::PrintJSONMeta(JSONArray* events) const {
+  Isolate* isolate = Isolate::Current();
+  JSONObject obj(events);
+  int64_t pid = GetPid(isolate);
+  obj.AddProperty("ph", "M");
+  obj.AddProperty64("pid", pid);
+  obj.AddProperty("name", "process_name");
+  {
+    JSONObject args(&obj, "args");
+    args.AddProperty("name", isolate->debugger_name());
+  }
+}
+
+
+void TimelineEventRecorder::WriteTo(const char* directory) {
+  Isolate* isolate = Isolate::Current();
+
+  Dart_FileOpenCallback file_open = Isolate::file_open_callback();
+  Dart_FileWriteCallback file_write = Isolate::file_write_callback();
+  Dart_FileCloseCallback file_close = Isolate::file_close_callback();
+  if ((file_open == NULL) || (file_write == NULL) || (file_close == NULL)) {
+    return;
+  }
+
+  JSONStream js;
+  PrintJSON(&js);
+
+  const char* format = "%s/dart-timeline-%" Pd "-%" Pd ".json";
+  intptr_t pid = OS::ProcessId();
+  intptr_t len = OS::SNPrint(NULL, 0, format,
+                             directory, pid, isolate->main_port());
+  char* filename = isolate->current_zone()->Alloc<char>(len + 1);
+  OS::SNPrint(filename, len + 1, format,
+              directory, pid, isolate->main_port());
+  void* file = (*file_open)(filename, true);
+  if (file == NULL) {
+    OS::Print("Failed to write timeline file: %s\n", filename);
+    return;
+  }
+  (*file_write)(js.buffer()->buf(), js.buffer()->length(), file);
+  (*file_close)(file);
+}
+
+
+intptr_t TimelineEventRingRecorder::SizeForCapacity(intptr_t capacity) {
+  return sizeof(TimelineEvent) * capacity;
+}
+
+
+TimelineEventRingRecorder::TimelineEventRingRecorder(intptr_t capacity)
+    : events_(NULL),
+      event_objects_(Array::null()),
+      cursor_(0),
+      capacity_(capacity) {
+  if (FLAG_trace_timeline) {
+    // 32-bit: 262,144 bytes per isolate.
+    // 64-bit: 393,216 bytes per isolate.
+    // NOTE: Internal isolates (vm and service) do not have a timeline
+    // event buffer.
+    OS::Print("TimelineEventRingRecorder is %" Pd " bytes (%" Pd " events)\n",
+              SizeForCapacity(capacity),
+              capacity);
+  }
+  events_ =
+      reinterpret_cast<TimelineEvent*>(calloc(capacity, sizeof(TimelineEvent)));
+  const Array& array = Array::Handle(Array::New(capacity, Heap::kOld));
+  event_objects_ = array.raw();
+}
+
+
+TimelineEventRingRecorder::~TimelineEventRingRecorder() {
+  for (intptr_t i = 0; i < capacity_; i++) {
+    // Clear any extra data.
+    events_[i].Reset();
+  }
+  free(events_);
+  event_objects_ = Array::null();
+}
+
+
+void TimelineEventRingRecorder::PrintJSONEvents(JSONArray* events) const {
+  for (intptr_t i = 0; i < capacity_; i++) {
+    if (events_[i].IsValid()) {
+      events->AddValue(&events_[i]);
+    }
+  }
+}
+
+
+void TimelineEventRingRecorder::PrintJSON(JSONStream* js) const {
+  JSONObject topLevel(js);
+  topLevel.AddProperty("type", "_Timeline");
+  {
+    JSONArray events(&topLevel, "traceEvents");
+    PrintJSONMeta(&events);
+    PrintJSONEvents(&events);
+  }
+}
+
+
+intptr_t TimelineEventRingRecorder::GetNextIndex() {
+  uintptr_t cursor = AtomicOperations::FetchAndIncrement(&cursor_);
+  return cursor % capacity_;
+}
+
+
+void TimelineEventRingRecorder::VisitObjectPointers(
+    ObjectPointerVisitor* visitor) {
+  visitor->VisitPointer(reinterpret_cast<RawObject**>(&event_objects_));
+}
+
+
+TimelineEvent* TimelineEventRingRecorder::StartEvent(const Object& obj) {
+  ASSERT(events_ != NULL);
+  uintptr_t index = GetNextIndex();
+  const Array& event_objects = Array::Handle(event_objects_);
+  event_objects.SetAt(index, obj);
+  return &events_[index];
+}
+
+
+TimelineEvent* TimelineEventRingRecorder::StartEvent() {
+  ASSERT(events_ != NULL);
+  uintptr_t index = GetNextIndex();
+  return &events_[index];
+}
+
+void TimelineEventRingRecorder::CompleteEvent(TimelineEvent* event) {
+  ASSERT(events_ != NULL);
+  // no-op.
+}
+
+
+TimelineEventStreamingRecorder::TimelineEventStreamingRecorder() {
+}
+
+
+TimelineEventStreamingRecorder::~TimelineEventStreamingRecorder() {
+}
+
+
+void TimelineEventStreamingRecorder::PrintJSON(JSONStream* js) const {
+  JSONObject topLevel(js);
+  topLevel.AddProperty("type", "_Timeline");
+  {
+    JSONArray events(&topLevel, "traceEvents");
+    PrintJSONMeta(&events);
+  }
+}
+
+void TimelineEventStreamingRecorder::VisitObjectPointers(
+    ObjectPointerVisitor* visitor) {
+  // no-op.
+}
+
+
+TimelineEvent* TimelineEventStreamingRecorder::StartEvent(
+    const Object& object) {
+  // The streaming recorder does not track Dart objects.
+  return StartEvent();
+}
+
+
+TimelineEvent* TimelineEventStreamingRecorder::StartEvent() {
+  TimelineEvent* event = new TimelineEvent();
+  return event;
+}
+
+
+void TimelineEventStreamingRecorder::CompleteEvent(TimelineEvent* event) {
+  StreamEvent(event);
+  delete event;
+}
+
+}  // namespace dart
diff --git a/runtime/vm/timeline.h b/runtime/vm/timeline.h
new file mode 100644
index 0000000..81977ad
--- /dev/null
+++ b/runtime/vm/timeline.h
@@ -0,0 +1,330 @@
+// 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 VM_TIMELINE_H_
+#define VM_TIMELINE_H_
+
+#include "vm/bitfield.h"
+
+namespace dart {
+
+class JSONStream;
+class Object;
+class RawArray;
+class Thread;
+class TimelineEvent;
+class TimelineEventRecorder;
+class TimelineStream;
+
+// You should get a |TimelineEvent| from a |TimelineStream|.
+class TimelineEvent {
+ public:
+  // Keep in sync with StateBits below.
+  enum EventType {
+    kNone,
+    kDuration,
+    kInstant,
+    kAsyncBegin,
+    kAsyncInstant,
+    kAsyncEnd,
+    kNumEventTypes,
+  };
+
+  TimelineEvent();
+  ~TimelineEvent();
+
+  void Reset();
+
+  bool IsValid() const {
+    return (event_type() > kNone) && (event_type() < kNumEventTypes);
+  }
+
+  // Marks the beginning of an asynchronous operation.
+  // Returns |async_id| which must be passed to |AsyncInstant| and |AsyncEnd|.
+  int64_t AsyncBegin(const char* label);
+  // Marks an instantaneous event associated with |async_id|.
+  void AsyncInstant(const char* label,
+                    int64_t async_id);
+  // Marks the end of an asynchronous operation associated with |async_id|.
+  void AsyncEnd(const char* label,
+                int64_t async_id);
+
+  void DurationBegin(const char* label);
+  void DurationEnd();
+  void Instant(const char* label);
+
+  void Duration(const char* label,
+                int64_t start_micros,
+                int64_t end_micros);
+
+  // Set the number of arguments in the event.
+  void SetNumArguments(intptr_t length);
+  // |name| must be a compile time constant. Takes ownership of |argumentp|.
+  void SetArgument(intptr_t i, const char* name, char* argument);
+  // |name| must be a compile time constant. Copies |argument|.
+  void CopyArgument(intptr_t i, const char* name, const char* argument);
+  // |name| must be a compile time constant.
+  void FormatArgument(intptr_t i,
+                      const char* name,
+                      const char* fmt, ...) PRINTF_ATTRIBUTE(4, 5);
+
+  // Mandatory to call when this event is completely filled out.
+  void Complete();
+
+  EventType event_type() const {
+    return EventTypeField::decode(state_);
+  }
+
+  int64_t TimeOrigin() const;
+  int64_t AsyncId() const;
+  int64_t TimeDuration() const;
+
+  void PrintJSON(JSONStream* stream) const;
+
+ private:
+  struct TimelineEventArgument {
+    const char* name;
+    char* value;
+  };
+
+  int64_t timestamp0_;
+  int64_t timestamp1_;
+  TimelineEventArgument* arguments_;
+  intptr_t arguments_length_;
+  uword state_;
+  const char* label_;
+  TimelineStream* stream_;
+  Thread* thread_;
+
+  void FreeArguments();
+
+  void StreamInit(TimelineStream* stream);
+  void Init(EventType event_type, const char* label);
+
+  void set_event_type(EventType event_type) {
+    state_ = EventTypeField::update(event_type, state_);
+  }
+
+  enum StateBits {
+    kEventTypeBit = 0,
+    // reserve 4 bits for type.
+    kNextBit = 4,
+  };
+
+  class EventTypeField : public BitField<EventType, kEventTypeBit, 4> {};
+
+  friend class TimelineTestHelper;
+  friend class TimelineStream;
+  DISALLOW_COPY_AND_ASSIGN(TimelineEvent);
+};
+
+
+// A stream of timeline events. A stream has a name and can be enabled or
+// disabled.
+class TimelineStream {
+ public:
+  TimelineStream();
+
+  void Init(const char* name, bool enabled);
+
+  const char* name() const {
+    return name_;
+  }
+
+  bool enabled() const {
+    return enabled_;
+  }
+
+  void set_enabled(bool enabled) {
+    enabled_ = enabled;
+  }
+
+  TimelineEventRecorder* recorder() const {
+    return recorder_;
+  }
+
+  // TODO(johnmccutchan): Disallow setting recorder after Init?
+  void set_recorder(TimelineEventRecorder* recorder) {
+    recorder_ = recorder;
+  }
+
+  // Records an event. Will return |NULL| if not enabled. The returned
+  // |TimelineEvent| is in an undefined state and must be initialized.
+  // |obj| is associated with the returned |TimelineEvent|.
+  TimelineEvent* StartEvent(const Object& obj);
+
+  // Records an event. Will return |NULL| if not enabled. The returned
+  // |TimelineEvent| is in an undefined state and must be initialized.
+  TimelineEvent* StartEvent();
+
+  void CompleteEvent(TimelineEvent* event);
+
+  int64_t GetNextSeq();
+
+ private:
+  TimelineEventRecorder* recorder_;
+  const char* name_;
+  bool enabled_;
+  int64_t seq_;
+};
+
+
+// (name, enabled by default).
+#define ISOLATE_TIMELINE_STREAM_LIST(V)                                        \
+  V(API, false)                                                                \
+  V(Compiler, false)                                                           \
+  V(Embedder, false)                                                           \
+  V(GC, false)                                                                 \
+  V(Isolate, false)                                                            \
+
+
+#define TIMELINE_FUNCTION_COMPILATION_DURATION(isolate, suffix, function)      \
+  TimelineDurationScope tds(isolate,                                           \
+                            isolate->GetCompilerStream(),                      \
+                            "Compile"#suffix);                                 \
+  if (tds.enabled()) {                                                         \
+    tds.SetNumArguments(1);                                                    \
+    tds.CopyArgument(                                                          \
+        0,                                                                     \
+        "function",                                                            \
+        const_cast<char*>(function.QualifiedUserVisibleNameCString()));        \
+  }
+
+class TimelineDurationScope : public StackResource {
+ public:
+  TimelineDurationScope(Isolate* isolate,
+                        TimelineStream* stream,
+                        const char* label)
+      : StackResource(isolate) {
+    event_ = stream->StartEvent();
+    if (event_ == NULL) {
+      return;
+    }
+    event_->DurationBegin(label);
+  }
+
+  bool enabled() const {
+    return event_ != NULL;
+  }
+
+  void SetNumArguments(intptr_t length) {
+    if (event_ == NULL) {
+      return;
+    }
+    event_->SetNumArguments(length);
+  }
+
+  void SetArgument(intptr_t i, const char* name, char* argument) {
+    if (event_ == NULL) {
+      return;
+    }
+    event_->SetArgument(i, name, argument);
+  }
+
+  void CopyArgument(intptr_t i, const char* name, const char* argument) {
+    if (event_ == NULL) {
+      return;
+    }
+    event_->CopyArgument(i, name, argument);
+  }
+
+  void FormatArgument(intptr_t i,
+                      const char* name,
+                      const char* fmt, ...)  PRINTF_ATTRIBUTE(4, 5);
+
+  ~TimelineDurationScope() {
+    if (event_ == NULL) {
+      return;
+    }
+    event_->DurationEnd();
+    event_->Complete();
+  }
+
+ private:
+  TimelineEvent* event_;
+};
+
+
+// Recorder of |TimelineEvent|s.
+class TimelineEventRecorder {
+ public:
+  TimelineEventRecorder();
+  virtual ~TimelineEventRecorder() {}
+
+  // Interface method(s) which must be implemented.
+  virtual void PrintJSON(JSONStream* js) const = 0;
+
+  void WriteTo(const char* directory);
+
+ protected:
+  // Interface method(s) which must be implemented.
+  virtual void VisitObjectPointers(ObjectPointerVisitor* visitor) = 0;
+  virtual TimelineEvent* StartEvent(const Object& object) = 0;
+  virtual TimelineEvent* StartEvent() = 0;
+  virtual void CompleteEvent(TimelineEvent* event) = 0;
+
+  // Utility method(s).
+  void PrintJSONMeta(JSONArray* array) const;
+
+  friend class TimelineStream;
+  friend class Isolate;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(TimelineEventRecorder);
+};
+
+
+// A recorder that stores events in a ring buffer of fixed capacity.
+class TimelineEventRingRecorder : public TimelineEventRecorder {
+ public:
+  static const intptr_t kDefaultCapacity = 8192;
+
+  static intptr_t SizeForCapacity(intptr_t capacity);
+
+  explicit TimelineEventRingRecorder(intptr_t capacity = kDefaultCapacity);
+  ~TimelineEventRingRecorder();
+
+  void PrintJSON(JSONStream* js) const;
+
+ protected:
+  void VisitObjectPointers(ObjectPointerVisitor* visitor);
+  TimelineEvent* StartEvent(const Object& object);
+  TimelineEvent* StartEvent();
+  void CompleteEvent(TimelineEvent* event);
+
+  void PrintJSONEvents(JSONArray* array) const;
+
+  intptr_t GetNextIndex();
+
+  // events_[i] and event_objects_[i] are indexed together.
+  TimelineEvent* events_;
+  RawArray* event_objects_;
+  uintptr_t cursor_;
+  intptr_t capacity_;
+};
+
+
+// An abstract recorder that calls |StreamEvent| whenever an event is complete.
+// This recorder does not track Dart objects.
+class TimelineEventStreamingRecorder : public TimelineEventRecorder {
+ public:
+  TimelineEventStreamingRecorder();
+  ~TimelineEventStreamingRecorder();
+
+  void PrintJSON(JSONStream* js) const;
+
+  // Called when |event| is ready to be streamed. It is unsafe to keep a
+  // reference to |event| as it may be freed as soon as this function returns.
+  virtual void StreamEvent(TimelineEvent* event) = 0;
+
+ protected:
+  void VisitObjectPointers(ObjectPointerVisitor* visitor);
+  TimelineEvent* StartEvent(const Object& object);
+  TimelineEvent* StartEvent();
+  void CompleteEvent(TimelineEvent* event);
+};
+
+}  // namespace dart
+
+#endif  // VM_TIMELINE_H_
diff --git a/runtime/vm/timeline_test.cc b/runtime/vm/timeline_test.cc
new file mode 100644
index 0000000..38f907b
--- /dev/null
+++ b/runtime/vm/timeline_test.cc
@@ -0,0 +1,228 @@
+// 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 "platform/assert.h"
+
+#include "vm/dart_api_impl.h"
+#include "vm/dart_api_state.h"
+#include "vm/globals.h"
+#include "vm/timeline.h"
+#include "vm/unit_test.h"
+
+namespace dart {
+
+class TimelineTestHelper : public AllStatic {
+ public:
+  static void SetStream(TimelineEvent* event, TimelineStream* stream) {
+    event->StreamInit(stream);
+  }
+};
+
+
+TEST_CASE(TimelineEventIsValid) {
+  // Create a test stream.
+  TimelineStream stream;
+  stream.Init("testStream", true);
+
+  TimelineEvent event;
+  TimelineTestHelper::SetStream(&event, &stream);
+
+  // Starts invalid.
+  EXPECT(!event.IsValid());
+
+  // Becomes valid.
+  event.Instant("hello");
+  EXPECT(event.IsValid());
+
+  // Becomes invalid.
+  event.Reset();
+  EXPECT(!event.IsValid());
+}
+
+
+TEST_CASE(TimelineEventDuration) {
+  // Create a test stream.
+  TimelineStream stream;
+  stream.Init("testStream", true);
+
+  // Create a test event.
+  TimelineEvent event;
+  TimelineTestHelper::SetStream(&event, &stream);
+  event.DurationBegin("apple");
+  // Measure the duration.
+  int64_t current_duration = event.TimeDuration();
+  event.DurationEnd();
+  // Verify that duration is larger.
+  EXPECT_GE(event.TimeDuration(), current_duration);
+}
+
+
+TEST_CASE(TimelineEventDurationPrintJSON) {
+  // Create a test stream.
+  TimelineStream stream;
+  stream.Init("testStream", true);
+
+  // Create a test event.
+  TimelineEvent event;
+  TimelineTestHelper::SetStream(&event, &stream);
+  event.DurationBegin("apple");
+  {
+    // Test printing to JSON.
+    JSONStream js;
+    event.PrintJSON(&js);
+    // Check category
+    EXPECT_SUBSTRING("\"cat\":\"testStream\"", js.ToCString());
+    // Check name.
+    EXPECT_SUBSTRING("\"name\":\"apple\"", js.ToCString());
+    // Check phase.
+    EXPECT_SUBSTRING("\"ph\":\"X\"", js.ToCString());
+    // Check that ts key is present.
+    EXPECT_SUBSTRING("\"ts\":", js.ToCString());
+    // Check that dur key is present.
+    EXPECT_SUBSTRING("\"dur\":", js.ToCString());
+  }
+  event.DurationEnd();
+}
+
+
+TEST_CASE(TimelineEventArguments) {
+  // Create a test stream.
+  TimelineStream stream;
+  stream.Init("testStream", true);
+
+  // Create a test event.
+  TimelineEvent event;
+  TimelineTestHelper::SetStream(&event, &stream);
+
+  // Allocate room for four arguments.
+  event.SetNumArguments(4);
+  // Reset.
+  event.Reset();
+
+  event.DurationBegin("apple");
+  event.SetNumArguments(2);
+  event.CopyArgument(0, "arg1", "value1");
+  event.CopyArgument(1, "arg2", "value2");
+  event.DurationEnd();
+}
+
+
+TEST_CASE(TimelineEventArgumentsPrintJSON) {
+  // Create a test stream.
+  TimelineStream stream;
+  stream.Init("testStream", true);
+
+  // Create a test event.
+  TimelineEvent event;
+  TimelineTestHelper::SetStream(&event, &stream);
+
+  event.DurationBegin("apple");
+  event.SetNumArguments(2);
+  event.CopyArgument(0, "arg1", "value1");
+  event.CopyArgument(1, "arg2", "value2");
+  event.DurationEnd();
+
+  {
+    // Test printing to JSON.
+    JSONStream js;
+    event.PrintJSON(&js);
+
+    // Check both arguments.
+    EXPECT_SUBSTRING("\"arg1\":\"value1\"", js.ToCString());
+    EXPECT_SUBSTRING("\"arg2\":\"value2\"", js.ToCString());
+  }
+}
+
+
+TEST_CASE(TimelineEventBufferPrintJSON) {
+  Isolate* isolate = Isolate::Current();
+  TimelineEventRecorder* recorder = isolate->timeline_event_recorder();
+  JSONStream js;
+  recorder->PrintJSON(&js);
+  // Check the type. This test will fail if we ever make Timeline public.
+  EXPECT_SUBSTRING("\"type\":\"_Timeline\"", js.ToCString());
+  // Check that there is a traceEvents array.
+  EXPECT_SUBSTRING("\"traceEvents\":[", js.ToCString());
+}
+
+
+// Count the number of each event type seen.
+class EventCounterRecorder : public TimelineEventStreamingRecorder {
+ public:
+  EventCounterRecorder() {
+    for (intptr_t i = 0; i < TimelineEvent::kNumEventTypes; i++) {
+      counts_[i] = 0;
+    }
+  }
+
+  void StreamEvent(TimelineEvent* event) {
+    counts_[event->event_type()]++;
+  }
+
+  intptr_t CountFor(TimelineEvent::EventType type) {
+    return counts_[type];
+  }
+
+ private:
+  intptr_t counts_[TimelineEvent::kNumEventTypes];
+};
+
+
+TEST_CASE(TimelineEventStreamingRecorderBasic) {
+  EventCounterRecorder* recorder = new EventCounterRecorder();
+
+  // Initial counts are all zero.
+  for (intptr_t i = TimelineEvent::kNone + 1;
+       i < TimelineEvent::kNumEventTypes;
+       i++) {
+    EXPECT_EQ(0, recorder->CountFor(static_cast<TimelineEvent::EventType>(i)));
+  }
+
+  // Create a test stream.
+  TimelineStream stream;
+  stream.Init("testStream", true);
+  stream.set_recorder(recorder);
+
+  TimelineEvent* event = NULL;
+
+  event = stream.StartEvent();
+  EXPECT_EQ(0, recorder->CountFor(TimelineEvent::kDuration));
+  event->DurationBegin("cabbage");
+  EXPECT_EQ(0, recorder->CountFor(TimelineEvent::kDuration));
+  event->DurationEnd();
+  EXPECT_EQ(0, recorder->CountFor(TimelineEvent::kDuration));
+  event->Complete();
+  EXPECT_EQ(1, recorder->CountFor(TimelineEvent::kDuration));
+
+  event = stream.StartEvent();
+  EXPECT_EQ(0, recorder->CountFor(TimelineEvent::kInstant));
+  event->Instant("instantCabbage");
+  EXPECT_EQ(0, recorder->CountFor(TimelineEvent::kInstant));
+  event->Complete();
+  EXPECT_EQ(1, recorder->CountFor(TimelineEvent::kInstant));
+
+  event = stream.StartEvent();
+  EXPECT_EQ(0, recorder->CountFor(TimelineEvent::kAsyncBegin));
+  int64_t async_id = event->AsyncBegin("asyncBeginCabbage");
+  EXPECT(async_id >= 0);
+  EXPECT_EQ(0, recorder->CountFor(TimelineEvent::kAsyncBegin));
+  event->Complete();
+  EXPECT_EQ(1, recorder->CountFor(TimelineEvent::kAsyncBegin));
+
+  event = stream.StartEvent();
+  EXPECT_EQ(0, recorder->CountFor(TimelineEvent::kAsyncInstant));
+  event->AsyncInstant("asyncInstantCabbage", async_id);
+  EXPECT_EQ(0, recorder->CountFor(TimelineEvent::kAsyncInstant));
+  event->Complete();
+  EXPECT_EQ(1, recorder->CountFor(TimelineEvent::kAsyncInstant));
+
+  event = stream.StartEvent();
+  EXPECT_EQ(0, recorder->CountFor(TimelineEvent::kAsyncEnd));
+  event->AsyncEnd("asyncEndCabbage", async_id);
+  EXPECT_EQ(0, recorder->CountFor(TimelineEvent::kAsyncEnd));
+  event->Complete();
+  EXPECT_EQ(1, recorder->CountFor(TimelineEvent::kAsyncEnd));
+}
+
+}  // namespace dart
diff --git a/runtime/vm/visitor.h b/runtime/vm/visitor.h
index 8667383..70fe619 100644
--- a/runtime/vm/visitor.h
+++ b/runtime/vm/visitor.h
@@ -26,7 +26,7 @@
   virtual void VisitPointers(RawObject** first, RawObject** last) = 0;
 
   virtual bool visit_function_code() const { return true; }
-  virtual GrowableArray<RawFunction*>* skipped_code_functions() {
+  virtual MallocGrowableArray<RawFunction*>* skipped_code_functions() {
     return NULL;
   }
   // len argument is the number of pointers to visit starting from 'p'.
diff --git a/runtime/vm/vm_sources.gypi b/runtime/vm/vm_sources.gypi
index 709be94..a8fb214 100644
--- a/runtime/vm/vm_sources.gypi
+++ b/runtime/vm/vm_sources.gypi
@@ -445,6 +445,9 @@
     'thread_pool.h',
     'thread_pool_test.cc',
     'thread_test.cc',
+    'timeline.cc',
+    'timeline.h',
+    'timeline_test.cc',
     'timer.cc',
     'timer.h',
     'token.cc',
diff --git a/samples/samples.status b/samples/samples.status
index d0d70d65..92b4837 100644
--- a/samples/samples.status
+++ b/samples/samples.status
@@ -25,4 +25,4 @@
 *: Skip
 
 [ $compiler == dart2js && $cps_ir ]
-sample_extension/test/sample_extension_test: Crash #  Unhandled node
+sample_extension/test/sample_extension_test: Crash # Invalid argument(s)
diff --git a/sdk/api_readme.md b/sdk/api_readme.md
index 4df6470..68b662c 100644
--- a/sdk/api_readme.md
+++ b/sdk/api_readme.md
@@ -1,5 +1,6 @@
 Welcome to the Dart API reference documentation,
 covering the official Dart API libraries.
+
 Some of the most fundamental Dart libraries include:
    
   * [dart:core](./dart_core/index.html):
diff --git a/sdk/bin/pub b/sdk/bin/pub
index 96cc0df..e927731 100755
--- a/sdk/bin/pub
+++ b/sdk/bin/pub
@@ -53,5 +53,5 @@
 PACKAGES_DIR="$BUILD_DIR/packages/"
 
 # Run pub.
-PUB="$SDK_DIR/../third_party/pkg_tested/pub/bin/pub.dart"
+PUB="$SDK_DIR/../third_party/pkg/pub/bin/pub.dart"
 exec "$DART" "${VM_OPTIONS[@]}" "--package-root=$PACKAGES_DIR" "$PUB" "$@"
diff --git a/sdk/bin/pub.bat b/sdk/bin/pub.bat
index d64b492..1326b57 100644
--- a/sdk/bin/pub.bat
+++ b/sdk/bin/pub.bat
@@ -35,7 +35,7 @@
 set DART=%BUILD_DIR%\dart-sdk\bin\dart
 
 rem Run pub.
-set PUB="%SDK_DIR%\..\third_party\pkg_tested\pub\bin\pub.dart"
+set PUB="%SDK_DIR%\..\third_party\pkg\pub\bin\pub.dart"
 "%DART%" %VM_OPTIONS% --package-root="%PACKAGES_DIR%" "%PUB%" %*
 
 endlocal
diff --git a/sdk/lib/_internal/compiler/js_lib/collection_patch.dart b/sdk/lib/_internal/compiler/js_lib/collection_patch.dart
index 9df7c99..74582ba 100644
--- a/sdk/lib/_internal/compiler/js_lib/collection_patch.dart
+++ b/sdk/lib/_internal/compiler/js_lib/collection_patch.dart
@@ -9,6 +9,8 @@
     JsLinkedHashMap, LinkedHashMapCell, LinkedHashMapKeyIterable,
     LinkedHashMapKeyIterator;
 
+const _USE_ES6_MAPS = const bool.fromEnvironment("dart2js.use.es6.maps");
+
 @patch
 class HashMap<K, V> {
   @patch
@@ -500,7 +502,7 @@
       } else {
         if (identical(identityHashCode, hashCode) &&
             identical(identical, equals)) {
-          return new _LinkedIdentityHashMap<K, V>();
+          return new _LinkedIdentityHashMap<K, V>.es6();
         }
         if (equals == null) {
           equals = _defaultEquals;
@@ -518,7 +520,7 @@
   }
 
   @patch
-  factory LinkedHashMap.identity() = _LinkedIdentityHashMap<K, V>;
+  factory LinkedHashMap.identity() = _LinkedIdentityHashMap<K, V>.es6;
 
   // Private factory constructor called by generated code for map literals.
   @NoInline()
@@ -544,8 +546,20 @@
       fillLiteralMap(keyValuePairs, new JsLinkedHashMap());
 }
 
-// TODO(floitsch): use ES6 Maps when available.
 class _LinkedIdentityHashMap<K, V> extends JsLinkedHashMap<K, V> {
+  static bool get _supportsEs6Maps {
+    return JS('returns:bool;depends:none;effects:none;throws:never;gvn:true',
+              'typeof Map != "undefined"');
+  }
+
+  factory _LinkedIdentityHashMap.es6() {
+    return (_USE_ES6_MAPS && _LinkedIdentityHashMap._supportsEs6Maps)
+        ? new _Es6LinkedIdentityHashMap<K, V>()
+        : new _LinkedIdentityHashMap<K, V>();
+  }
+
+  _LinkedIdentityHashMap();
+
   int internalComputeHashCode(var key) {
     // We force the hash codes to be unsigned 30-bit integers to avoid
     // issues with problematic keys like '__proto__'. Another option
@@ -564,6 +578,166 @@
   }
 }
 
+class _Es6LinkedIdentityHashMap<K, V>
+    extends _LinkedIdentityHashMap<K, V> implements InternalMap {
+  final _map;
+  int _modifications = 0;
+
+  _Es6LinkedIdentityHashMap() : _map = JS('var', 'new Map()');
+
+  int get length => JS('int', '#.size', _map);
+  bool get isEmpty => length == 0;
+  bool get isNotEmpty => !isEmpty;
+
+  Iterable<K> get keys => new _Es6MapIterable<K>(this, true);
+
+  Iterable<V> get values =>
+      new _Es6MapIterable<V>(this, false);
+
+  bool containsKey(Object key) {
+    return JS('bool', '#.has(#)', _map, key);
+  }
+
+  bool containsValue(Object value) {
+    return values.any((each) => each == value);
+  }
+
+  void addAll(Map<K, V> other) {
+    other.forEach((K key, V value) {
+      this[key] = value;
+    });
+  }
+
+  V operator[](Object key) {
+    return JS('var', '#.get(#)', _map, key);
+  }
+
+  void operator[]=(K key, V value) {
+    JS('var', '#.set(#, #)', _map, key, value);
+    _modified();
+  }
+
+  V putIfAbsent(K key, V ifAbsent()) {
+    if (containsKey(key)) return this[key];
+    V value = ifAbsent();
+    this[key] = value;
+    return value;
+  }
+
+  V remove(Object key) {
+    V value = this[key];
+    JS('bool', '#.delete(#)', _map, key);
+    _modified();
+    return value;
+  }
+
+  void clear() {
+    JS('void', '#.clear()', _map);
+    _modified();
+  }
+
+  void forEach(void action(K key, V value)) {
+    var jsEntries = JS('var', '#.entries()', _map);
+    int modifications = _modifications;
+    while (true) {
+      var next = JS('var', '#.next()', jsEntries);
+      bool done = JS('bool', '#.done', next);
+      if (done) break;
+      var entry = JS('var', '#.value', next);
+      var key = JS('var', '#[0]', entry);
+      var value = JS('var', '#[1]', entry);
+      action(key, value);
+      if (modifications != _modifications) {
+        throw new ConcurrentModificationError(this);
+      }
+    }
+  }
+
+  void _modified() {
+    // Value cycles after 2^30 modifications so that modification counts are
+    // always unboxed (Smi) values. Modification detection will be missed if you
+    // make exactly some multiple of 2^30 modifications between advances of an
+    // iterator.
+    _modifications = (_modifications + 1) & 0x3ffffff;
+  }
+
+  String toString() => Maps.mapToString(this);
+}
+
+class _Es6MapIterable<E> extends Iterable<E>
+                         implements EfficientLength {
+  final _map;
+  final bool _isKeys;
+
+  _Es6MapIterable(this._map, this._isKeys);
+
+  int get length => _map.length;
+  bool get isEmpty => _map.isEmpty;
+
+  Iterator<E> get iterator =>
+      new _Es6MapIterator<E>(_map, _map._modifications, _isKeys);
+
+  bool contains(Object element) => _map.containsKey(element);
+
+  void forEach(void f(E element)) {
+    var jsIterator;
+    if (_isKeys) {
+      jsIterator = JS('var', '#.keys()', _map._map);
+    } else {
+      jsIterator = JS('var', '#.values()', _map._map);
+    }
+    int modifications = _map._modifications;
+    while (true) {
+      var next = JS('var', '#.next()', jsIterator);
+      bool done = JS('bool', '#.done', next);
+      if (done) break;
+      var value = JS('var', '#.value', next);
+      f(value);
+      if (modifications != _map._modifications) {
+        throw new ConcurrentModificationError(_map);
+      }
+    }
+  }
+}
+
+class _Es6MapIterator<E> implements Iterator<E> {
+  final _map;
+  final int _modifications;
+  final bool _isKeys;
+  var _jsIterator;
+  var _next;
+  E _current;
+  bool _done;
+
+  _Es6MapIterator(this._map, this._modifications, this._isKeys) {
+    if (_isKeys) {
+      _jsIterator = JS('var', '#.keys()', _map._map);
+    } else {
+      _jsIterator = JS('var', '#.values()', _map._map);
+    }
+    _done = false;
+  }
+
+  E get current => _current;
+
+  bool moveNext() {
+    if (_modifications != _map._modifications) {
+      throw new ConcurrentModificationError(_map);
+    }
+    if (_done) return false;
+    _next = JS('var', '#.next()', _jsIterator);
+    bool done = JS('bool', '#.done', _next);
+    if (done) {
+      _current = null;
+      _done = true;
+      return false;
+    } else {
+      _current = JS('var', '#.value', _next);
+      return true;
+    }
+  }
+}
+
 // TODO(floitsch): use ES6 maps when available.
 class _LinkedCustomHashMap<K, V> extends JsLinkedHashMap<K, V> {
   final _Equality<K> _equals;
diff --git a/sdk/lib/_internal/compiler/js_lib/constant_map.dart b/sdk/lib/_internal/compiler/js_lib/constant_map.dart
index ccc210e..8f813fc 100644
--- a/sdk/lib/_internal/compiler/js_lib/constant_map.dart
+++ b/sdk/lib/_internal/compiler/js_lib/constant_map.dart
@@ -6,7 +6,7 @@
 
 class ConstantMapView<K, V> extends UnmodifiableMapView
                       implements ConstantMap {
- ConstantMapView(Map base) : super(base);
+  ConstantMapView(Map base) : super(base);
 }
 
 abstract class ConstantMap<K, V> implements Map<K, V> {
diff --git a/sdk/lib/_internal/compiler/js_lib/convert_patch.dart b/sdk/lib/_internal/compiler/js_lib/convert_patch.dart
index bb4443e..1b987ed 100644
--- a/sdk/lib/_internal/compiler/js_lib/convert_patch.dart
+++ b/sdk/lib/_internal/compiler/js_lib/convert_patch.dart
@@ -4,7 +4,7 @@
 
 // Patch file for dart:convert library.
 
-import 'dart:_js_helper' show patch;
+import 'dart:_js_helper' show argumentErrorValue, patch;
 import 'dart:_foreign_helper' show JS;
 import 'dart:_interceptors' show JSExtendableArray;
 import 'dart:_internal' show MappedIterable, ListIterable;
@@ -28,7 +28,7 @@
  */
 @patch
 _parseJson(String source, reviver(key, value)) {
-  if (source is! String) throw new ArgumentError(source);
+  if (source is! String) throw argumentErrorValue(source);
 
   var parsed;
   try {
diff --git a/sdk/lib/_internal/compiler/js_lib/core_patch.dart b/sdk/lib/_internal/compiler/js_lib/core_patch.dart
index d42f9a85..7045e05 100644
--- a/sdk/lib/_internal/compiler/js_lib/core_patch.dart
+++ b/sdk/lib/_internal/compiler/js_lib/core_patch.dart
@@ -180,7 +180,9 @@
                      bool isUtc)
         // checkBool is manually inlined here because dart2js doesn't inline it
         // and [isUtc] is usually a constant.
-      : this.isUtc = isUtc is bool ? isUtc : throw new ArgumentError(isUtc),
+      : this.isUtc = isUtc is bool
+            ? isUtc
+            : throw new ArgumentError.value(isUtc, 'isUtc'),
         millisecondsSinceEpoch = checkInt(Primitives.valueFromDecomposedDate(
             year, month, day, hour, minute, second, millisecond, isUtc));
 
diff --git a/sdk/lib/_internal/compiler/js_lib/foreign_helper.dart b/sdk/lib/_internal/compiler/js_lib/foreign_helper.dart
index cec0b8d..5ce8113 100644
--- a/sdk/lib/_internal/compiler/js_lib/foreign_helper.dart
+++ b/sdk/lib/_internal/compiler/js_lib/foreign_helper.dart
@@ -41,7 +41,7 @@
  *    described:
  *
  *    + `=Object` is a plain JavaScript object.  Some DOM methods return
- *       instances that have no corresponing Dart type (e.g. cross-frame
+ *       instances that have no corresponding Dart type (e.g. cross-frame
  *       documents), `=Object` can be used to describe these untyped' values.
  *
  *    + `var` (or empty string).  If the entire [typeDescription] is `var` (or
@@ -142,14 +142,13 @@
  */
 // Add additional optional arguments if needed. The method is treated internally
 // as a variable argument method.
-JS(String typeDescription, String codeTemplate,
-    [arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11])
-{}
+external JS(String typeDescription, String codeTemplate,
+    [arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11]);
 
 /**
  * Returns the isolate in which this code is running.
  */
-IsolateContext JS_CURRENT_ISOLATE_CONTEXT() {}
+external IsolateContext JS_CURRENT_ISOLATE_CONTEXT();
 
 abstract class IsolateContext {
   /// Holds a (native) JavaScript instance of Isolate, see
@@ -160,7 +159,7 @@
 /**
  * Invokes [function] in the context of [isolate].
  */
-JS_CALL_IN_ISOLATE(isolate, Function function) {}
+external JS_CALL_IN_ISOLATE(isolate, Function function);
 
 /**
  * Converts the Dart closure [function] into a JavaScript closure.
@@ -168,7 +167,7 @@
  * Warning: This is no different from [RAW_DART_FUNCTION_REF] which means care
  * must be taken to store the current isolate.
  */
-DART_CLOSURE_TO_JS(Function function) {}
+external DART_CLOSURE_TO_JS(Function function);
 
 /**
  * Returns a raw reference to the JavaScript function which implements
@@ -182,12 +181,12 @@
  * to V8's Error.captureStackTrace. See
  * https://code.google.com/p/v8/wiki/JavaScriptStackTraceApi.
  */
-RAW_DART_FUNCTION_REF(Function function) {}
+external RAW_DART_FUNCTION_REF(Function function);
 
 /**
  * Sets the current isolate to [isolate].
  */
-void JS_SET_CURRENT_ISOLATE(isolate) {}
+external void JS_SET_CURRENT_ISOLATE(isolate);
 
 /**
  * Returns the interceptor for class [type].  The interceptor is the type's
@@ -195,67 +194,20 @@
  * an interface, e.g. `JS_INTERCEPTOR_CONSTANT(JSInt)`, not
  * `JS_INTERCEPTOR_CONSTANT(int)`.
  */
-JS_INTERCEPTOR_CONSTANT(Type type) {}
-
-/**
- * Returns the prefix used for generated type argument substitutions on classes.
- */
-String JS_OPERATOR_AS_PREFIX() {}
-
-/**
- * Returns the field name used for determining if an object or its
- * interceptor has JavaScript indexing behavior.
- */
-String JS_IS_INDEXABLE_FIELD_NAME() {}
+external JS_INTERCEPTOR_CONSTANT(Type type);
 
 /**
  * Returns the object corresponding to Namer.CURRENT_ISOLATE.
  */
-JS_CURRENT_ISOLATE() {}
-
-/// Returns the name used for generated function types on classes and methods.
-String JS_SIGNATURE_NAME() {}
-
-/// Returns the name used to tag typedefs.
-String JS_TYPEDEF_TAG() {}
-
-/**
- * Returns the name used to tag void return in function type representations
- * in JavaScript.
- */
-String JS_FUNCTION_TYPE_VOID_RETURN_TAG() {}
-
-/**
- * Returns the name used to tag return types in function type representations
- * in JavaScript.
- */
-String JS_FUNCTION_TYPE_RETURN_TYPE_TAG() {}
-
-/**
- * Returns the name used to tag required parameters in function type
- * representations in JavaScript.
- */
-String JS_FUNCTION_TYPE_REQUIRED_PARAMETERS_TAG() {}
-
-/**
- * Returns the name used to tag optional parameters in function type
- * representations in JavaScript.
- */
-String JS_FUNCTION_TYPE_OPTIONAL_PARAMETERS_TAG() {}
-
-/**
- * Returns the name used to tag named parameters in function type
- * representations in JavaScript.
- */
-String JS_FUNCTION_TYPE_NAMED_PARAMETERS_TAG() {}
+external JS_CURRENT_ISOLATE();
 
 /// Returns the JS name for [name] from the Namer.
-String JS_GET_NAME(JsGetName name) {}
+external String JS_GET_NAME(JsGetName name);
 
 /// Reads an embedded global.
 ///
 /// The [name] should be a constant defined in the `_embedded_names` library.
-JS_EMBEDDED_GLOBAL(String typeDescription, String name) {}
+external JS_EMBEDDED_GLOBAL(String typeDescription, String name);
 
 /// Instructs the compiler to execute the [builtinName] action at the call-site.
 ///
@@ -263,13 +215,13 @@
 /// library.
 // Add additional optional arguments if needed. The method is treated internally
 // as a variable argument method.
-JS_BUILTIN(String typeDescription, JsBuiltin builtin,
-           [arg0, arg1, arg2, arg3, arg4, arg5, arg6,
-            arg7, arg8, arg9, arg10, arg11]) {}
+external JS_BUILTIN(String typeDescription, JsBuiltin builtin,
+                    [arg0, arg1, arg2, arg3, arg4, arg5, arg6,
+                     arg7, arg8, arg9, arg10, arg11]);
 
 /// Returns the state of a flag that is determined by the state of the compiler
 /// when the program has been analyzed.
-bool JS_GET_FLAG(String name) {}
+external bool JS_GET_FLAG(String name);
 
 /**
  * Pretend [code] is executed.  Generates no executable code.  This is used to
diff --git a/sdk/lib/_internal/compiler/js_lib/interceptors.dart b/sdk/lib/_internal/compiler/js_lib/interceptors.dart
index 200f2b9..cf4d39b 100644
--- a/sdk/lib/_internal/compiler/js_lib/interceptors.dart
+++ b/sdk/lib/_internal/compiler/js_lib/interceptors.dart
@@ -15,11 +15,13 @@
                               Null,
                               JSSyntaxRegExp,
                               Primitives,
+                              argumentErrorValue,
                               checkInt,
                               checkNull,
                               checkNum,
                               checkString,
                               defineProperty,
+                              diagnoseIndexError,
                               getRuntimeType,
                               initNativeDispatch,
                               initNativeDispatchFlag,
@@ -248,8 +250,8 @@
  * interceptor, methods of that name on plain unintercepted classes also use the
  * interceptor calling convention.  The plain classes are _self-interceptors_,
  * and for them, `getInterceptor(r)` returns `r`.  Methods on plain
- * unintercepted classes have a redundant `receiver` argument and should ignore
- * it in favour of `this`.
+ * unintercepted classes have a redundant `receiver` argument and, to enable
+ * some optimizations, must ignore `receiver` in favour of `this`.
  *
  * In the case of mixins, a method may be placed on both an intercepted class
  * and an unintercepted class.  In this case, the method must use the `receiver`
@@ -292,6 +294,20 @@
 
   String toString() => Primitives.objectToHumanReadableString(this);
 
+  // [Interceptor.noSuchMethod] is identical to [Object.noSuchMethod].  However,
+  // each copy is compiled differently.  The presence of the method on an
+  // Interceptor class forces [noSuchMethod] to use interceptor calling
+  // convention.  In the [Interceptor] version, `this` is the explicit receiver
+  // argument. In the [Object] version, as Object is not an intercepted class,
+  // `this` is the JavaScript receiver, and the explicit receiver is ignored.
+  // The noSuchMethod stubs for selectors that use the interceptor calling
+  // convention do not know the calling convention and forward `this` and
+  // `receiver` to one of these noSuchMethod implementations which selects the
+  // correct Dart receiver.
+  //
+  // We don't allow [noSuchMethod] on intercepted classes (that would force all
+  // calls to use interceptor calling convention).  If we did allow it, the
+  // interceptor context would select the correct `this`.
   dynamic noSuchMethod(Invocation invocation) {
     throw new NoSuchMethodError(
         this,
diff --git a/sdk/lib/_internal/compiler/js_lib/isolate_helper.dart b/sdk/lib/_internal/compiler/js_lib/isolate_helper.dart
index ad6883c..e3f13bf 100644
--- a/sdk/lib/_internal/compiler/js_lib/isolate_helper.dart
+++ b/sdk/lib/_internal/compiler/js_lib/isolate_helper.dart
@@ -24,6 +24,7 @@
     Null,
     Primitives,
     convertDartClosureToJS,
+    isDartObject,
     random64,
     requiresPreamble;
 
diff --git a/sdk/lib/_internal/compiler/js_lib/isolate_serialization.dart b/sdk/lib/_internal/compiler/js_lib/isolate_serialization.dart
index 51a2943..9230bba 100644
--- a/sdk/lib/_internal/compiler/js_lib/isolate_serialization.dart
+++ b/sdk/lib/_internal/compiler/js_lib/isolate_serialization.dart
@@ -165,6 +165,7 @@
   }
 
   serializeDartObject(x) {
+    if (!isDartObject(x)) unsupported(x);
     var classExtractor = JS_EMBEDDED_GLOBAL('', CLASS_ID_EXTRACTOR);
     var fieldsExtractor = JS_EMBEDDED_GLOBAL('', CLASS_FIELDS_EXTRACTOR);
     String classId = JS('String', '#(#)', classExtractor, x);
diff --git a/sdk/lib/_internal/compiler/js_lib/js_array.dart b/sdk/lib/_internal/compiler/js_lib/js_array.dart
index d706b75..f6bcbbb 100644
--- a/sdk/lib/_internal/compiler/js_lib/js_array.dart
+++ b/sdk/lib/_internal/compiler/js_lib/js_array.dart
@@ -105,7 +105,7 @@
 
   E removeAt(int index) {
     checkGrowable('removeAt');
-    if (index is !int) throw new ArgumentError(index);
+    if (index is !int) throw argumentErrorValue(index);
     if (index < 0 || index >= length) {
       throw new RangeError.value(index);
     }
@@ -114,7 +114,7 @@
 
   void insert(int index, E value) {
     checkGrowable('insert');
-    if (index is !int) throw new ArgumentError(index);
+    if (index is !int) throw argumentErrorValue(index);
     if (index < 0 || index > length) {
       throw new RangeError.value(index);
     }
@@ -341,14 +341,14 @@
 
   List<E> sublist(int start, [int end]) {
     checkNull(start); // TODO(ahe): This is not specified but co19 tests it.
-    if (start is !int) throw new ArgumentError(start);
+    if (start is !int) throw argumentErrorValue(start);
     if (start < 0 || start > length) {
       throw new RangeError.range(start, 0, length);
     }
     if (end == null) {
       end = length;
     } else {
-      if (end is !int) throw new ArgumentError(end);
+      if (end is !int) throw argumentErrorValue(end);
       if (end < start || end > length) {
         throw new RangeError.range(end, start, length);
       }
@@ -575,21 +575,28 @@
 
   void set length(int newLength) {
     checkGrowable('set length');
-    if (newLength is !int) throw new ArgumentError(newLength);
-    if (newLength < 0) throw new RangeError.value(newLength);
+    if (newLength is !int) {
+      throw new ArgumentError.value(newLength, 'newLength');
+    }
+    // TODO(sra): Remove this test and let JavaScript throw an error.
+    if (newLength < 0) {
+      throw new RangeError.range(newLength, 0, null, 'newLength');
+    }
+    // JavaScript with throw a RangeError for numbers that are too big. The
+    // message does not contain the value.
     JS('void', r'#.length = #', this, newLength);
   }
 
   E operator [](int index) {
-    if (index is !int) throw new ArgumentError(index);
-    if (index >= length || index < 0) throw new RangeError.value(index);
+    if (index is !int) throw diagnoseIndexError(this, index);
+    if (index >= length || index < 0) throw diagnoseIndexError(this, index);
     return JS('var', '#[#]', this, index);
   }
 
   void operator []=(int index, E value) {
     checkMutable('indexed set');
-    if (index is !int) throw new ArgumentError(index);
-    if (index >= length || index < 0) throw new RangeError.value(index);
+    if (index is !int) throw diagnoseIndexError(this, index);
+    if (index >= length || index < 0) throw diagnoseIndexError(this, index);
     JS('void', r'#[#] = #', this, index, value);
   }
 
diff --git a/sdk/lib/_internal/compiler/js_lib/js_helper.dart b/sdk/lib/_internal/compiler/js_lib/js_helper.dart
index 3fa9543..291e178 100644
--- a/sdk/lib/_internal/compiler/js_lib/js_helper.dart
+++ b/sdk/lib/_internal/compiler/js_lib/js_helper.dart
@@ -48,17 +48,9 @@
     JS_CURRENT_ISOLATE_CONTEXT,
     JS_EFFECT,
     JS_EMBEDDED_GLOBAL,
-    JS_FUNCTION_TYPE_NAMED_PARAMETERS_TAG,
-    JS_FUNCTION_TYPE_OPTIONAL_PARAMETERS_TAG,
-    JS_FUNCTION_TYPE_REQUIRED_PARAMETERS_TAG,
-    JS_FUNCTION_TYPE_RETURN_TYPE_TAG,
-    JS_FUNCTION_TYPE_VOID_RETURN_TAG,
     JS_GET_FLAG,
     JS_GET_NAME,
     JS_HAS_EQUALS,
-    JS_IS_INDEXABLE_FIELD_NAME,
-    JS_OPERATOR_AS_PREFIX,
-    JS_SIGNATURE_NAME,
     JS_STRING_CONCAT,
     RAW_DART_FUNCTION_REF;
 
@@ -155,7 +147,9 @@
 @ForceInline()
 bool isDartFunctionTypeRti(Object type) {
   return JS_BUILTIN('returns:bool;effects:none;depends:none',
-                    JsBuiltin.isFunctionTypeRti, type);
+                    JsBuiltin.isGivenTypeRti, 
+                    type,
+                    JS_GET_NAME(JsGetName.FUNCTION_CLASS_TYPE_NAME));
 }
 
 /// Returns whether the given type is _the_ Dart Object type.
@@ -163,7 +157,9 @@
 @ForceInline()
 bool isDartObjectTypeRti(type) {
   return JS_BUILTIN('returns:bool;effects:none;depends:none',
-                    JsBuiltin.isDartObjectTypeRti, type);
+                    JsBuiltin.isGivenTypeRti, 
+                    type,
+                    JS_GET_NAME(JsGetName.OBJECT_CLASS_TYPE_NAME));
 }
 
 /// Returns whether the given type is _the_ null type.
@@ -171,7 +167,9 @@
 @ForceInline()
 bool isNullTypeRti(type) {
   return JS_BUILTIN('returns:bool;effects:none;depends:none',
-                    JsBuiltin.isNullTypeRti, type);
+                    JsBuiltin.isGivenTypeRti, 
+                    type,
+                    JS_GET_NAME(JsGetName.NULL_CLASS_TYPE_NAME));
 }
 
 /// Returns the metadata of the given [index].
@@ -218,7 +216,7 @@
     return 'null';
   }
   var res = value.toString();
-  if (res is !String) throw _argumentError(value);
+  if (res is !String) throw argumentErrorValue(value);
   return res;
 }
 
@@ -308,21 +306,20 @@
     for (var index = 0 ; index < argumentCount ; index++) {
       list.add(_arguments[index]);
     }
-    return makeLiteralListConst(list);
+    return JSArray.markUnmodifiableList(list);
   }
 
   Map<Symbol, dynamic> get namedArguments {
-    // TODO: Make maps const (issue 10471)
-    if (isAccessor) return <Symbol, dynamic>{};
+    if (isAccessor) return const <Symbol, dynamic>{};
     int namedArgumentCount = _namedArgumentNames.length;
     int namedArgumentsStartIndex = _arguments.length - namedArgumentCount;
-    if (namedArgumentCount == 0) return <Symbol, dynamic>{};
+    if (namedArgumentCount == 0) return const <Symbol, dynamic>{};
     var map = new Map<Symbol, dynamic>();
     for (int i = 0; i < namedArgumentCount; i++) {
       map[new _symbol_dev.Symbol.unvalidated(_namedArgumentNames[i])] =
           _arguments[namedArgumentsStartIndex + i];
     }
-    return map;
+    return new ConstantMapView<Symbol, dynamic>(map);
   }
 
   _getCachedInvocation(Object object) {
@@ -889,14 +886,14 @@
   static String stringFromCodePoints(codePoints) {
     List<int> a = <int>[];
     for (var i in codePoints) {
-      if (i is !int) throw _argumentError(i);
+      if (i is !int) throw argumentErrorValue(i);
       if (i <= 0xffff) {
         a.add(i);
       } else if (i <= 0x10ffff) {
         a.add(0xd800 + ((((i - 0x10000) >> 10) & 0x3ff)));
         a.add(0xdc00 + (i & 0x3ff));
       } else {
-        throw _argumentError(i);
+        throw argumentErrorValue(i);
       }
     }
     return _fromCharCodeApply(a);
@@ -904,8 +901,8 @@
 
   static String stringFromCharCodes(charCodes) {
     for (var i in charCodes) {
-      if (i is !int) throw _argumentError(i);
-      if (i < 0) throw _argumentError(i);
+      if (i is !int) throw argumentErrorValue(i);
+      if (i < 0) throw argumentErrorValue(i);
       if (i > 0xffff) return stringFromCodePoints(charCodes);
     }
     return _fromCharCodeApply(charCodes);
@@ -1094,22 +1091,22 @@
   }
 
   static valueFromDateString(str) {
-    if (str is !String) throw _argumentError(str);
+    if (str is !String) throw argumentErrorValue(str);
     var value = JS('num', r'Date.parse(#)', str);
-    if (value.isNaN) throw _argumentError(str);
+    if (value.isNaN) throw argumentErrorValue(str);
     return value;
   }
 
   static getProperty(object, key) {
     if (object == null || object is bool || object is num || object is String) {
-      throw _argumentError(object);
+      throw argumentErrorValue(object);
     }
     return JS('var', '#[#]', object, key);
   }
 
   static void setProperty(object, key, value) {
     if (object == null || object is bool || object is num || object is String) {
-      throw _argumentError(object);
+      throw argumentErrorValue(object);
     }
     JS('void', '#[#] = #', object, key, value);
   }
@@ -1396,55 +1393,73 @@
  * for example, if a non-integer index is given to an optimized
  * indexed access.
  */
+@NoInline()
 iae(argument) {
-  throw _argumentError(argument);
+  throw argumentErrorValue(argument);
 }
 
 /**
- * Called by generated code to throw an index-out-of-range exception,
- * for example, if a bounds check fails in an optimized indexed
- * access.  This may also be called when the index is not an integer, in
- * which case it throws an illegal-argument exception instead, like
- * [iae], or when the receiver is null.
+ * Called by generated code to throw an index-out-of-range exception, for
+ * example, if a bounds check fails in an optimized indexed access.  This may
+ * also be called when the index is not an integer, in which case it throws an
+ * illegal-argument exception instead, like [iae], or when the receiver is null.
  */
+@NoInline()
 ioore(receiver, index) {
   if (receiver == null) receiver.length; // Force a NoSuchMethodError.
-  if (index is !int) iae(index);
-  throw new RangeError.value(index);
+  throw diagnoseIndexError(receiver, index);
 }
 
+/**
+ * Diagnoses an indexing error. Returns the ArgumentError or RangeError that
+ * describes the problem.
+ */
+@NoInline()
+Error diagnoseIndexError(indexable, index) {
+  if (index is !int) return new ArgumentError.value(index, 'index');
+  int length = indexable.length;
+  // The following returns the same error that would be thrown by calling
+  // [RangeError.checkValidIndex] with no optional parameters provided.
+  if (index < 0 || index >= length) {
+    return new RangeError.index(index, indexable, 'index', null, length);
+  }
+  // The above should always match, but if it does not, use the following.
+  return new RangeError.value(index, 'index');
+}
+
+
 stringLastIndexOfUnchecked(receiver, element, start)
   => JS('int', r'#.lastIndexOf(#, #)', receiver, element, start);
 
 
 /// 'factory' for constructing ArgumentError.value to keep the call sites small.
 @NoInline()
-ArgumentError _argumentError(object) {
+ArgumentError argumentErrorValue(object) {
   return new ArgumentError.value(object);
 }
 
 checkNull(object) {
-  if (object == null) throw _argumentError(object);
+  if (object == null) throw argumentErrorValue(object);
   return object;
 }
 
 checkNum(value) {
-  if (value is !num) throw _argumentError(value);
+  if (value is !num) throw argumentErrorValue(value);
   return value;
 }
 
 checkInt(value) {
-  if (value is !int) throw _argumentError(value);
+  if (value is !int) throw argumentErrorValue(value);
   return value;
 }
 
 checkBool(value) {
-  if (value is !bool) throw _argumentError(value);
+  if (value is !bool) throw argumentErrorValue(value);
   return value;
 }
 
 checkString(value) {
-  if (value is !String) throw _argumentError(value);
+  if (value is !String) throw argumentErrorValue(value);
   return value;
 }
 
@@ -1495,12 +1510,6 @@
   JS('void', 'throw #', wrapException(ex));
 }
 
-makeLiteralListConst(list) {
-  JS('bool', r'#.immutable$list = #', list, true);
-  JS('bool', r'#.fixed$length = #', list, true);
-  return list;
-}
-
 throwRuntimeError(message) {
   throw new RuntimeError(message);
 }
@@ -2023,10 +2032,15 @@
       return new StackOverflowError();
     }
 
-    // In general, a RangeError is thrown when trying to pass a number
-    // as an argument to a function that does not allow a range that
-    // includes that number.
-    return saveStackTrace(new ArgumentError());
+    // In general, a RangeError is thrown when trying to pass a number as an
+    // argument to a function that does not allow a range that includes that
+    // number. Translate to a Dart ArgumentError with the same message.
+    // TODO(sra): Translate to RangeError.
+    String message = tryStringifyException(ex);
+    if (message is String) {
+      message = JS('String', r'#.replace(/^RangeError:\s*/, "")', message);
+    }
+    return saveStackTrace(new ArgumentError(message));
   }
 
   // Check for the Firefox specific stack overflow signal.
@@ -2044,6 +2058,20 @@
   return ex;
 }
 
+String tryStringifyException(ex) {
+  // Since this function is called from [unwrapException] which is called from
+  // code injected into a catch-clause, use JavaScript try-catch to avoid a
+  // potential loop if stringifying crashes.
+  return JS('String|Null', r'''
+    (function(ex) {
+      try {
+        return String(ex);
+      } catch (e) {}
+      return null;
+    })(#)
+    ''', ex);
+}
+
 /**
  * Called by generated code to fetch the stack trace from an
  * exception. Should never return null.
@@ -2052,7 +2080,11 @@
   if (exception is ExceptionAndStackTrace) {
     return exception.stackTrace;
   }
-  return new _StackTrace(exception);
+  if (exception == null) return new _StackTrace(exception);
+  _StackTrace trace = JS('_StackTrace|Null', r'#.$cachedTrace', exception);
+  if (trace != null) return trace;
+  trace = new _StackTrace(exception);
+  return JS('_StackTrace', r'#.$cachedTrace = #', exception, trace);
 }
 
 class _StackTrace implements StackTrace {
@@ -4092,7 +4124,7 @@
 /// An Iterable corresponding to a sync* method.
 ///
 /// Each invocation of a sync* method will return a new instance of this class.
-class SyncStarIterable extends Iterable {
+class SyncStarIterable extends IterableBase {
   // This is a function that will return a helper function that does the
   // iteration of the sync*.
   //
diff --git a/sdk/lib/_internal/compiler/js_lib/js_mirrors.dart b/sdk/lib/_internal/compiler/js_lib/js_mirrors.dart
index 1ab1cfc..5815a32 100644
--- a/sdk/lib/_internal/compiler/js_lib/js_mirrors.dart
+++ b/sdk/lib/_internal/compiler/js_lib/js_mirrors.dart
@@ -1984,7 +1984,7 @@
         var type = getType(typeInformation[0]);
         _superclass = typeMirrorFromRuntimeTypeRepresentation(this, type);
       } else {
-        var superclassName = _fieldsDescriptor.split(';')[0];
+        var superclassName = _fieldsDescriptor.split(';')[0].split(':')[0];
         // TODO(zarah): Remove special handing of mixins.
         var mixins = superclassName.split('+');
         if (mixins.length > 1) {
@@ -2170,7 +2170,7 @@
         }
       }
     }
-    int type = int.parse(fieldInformation[1]);
+    int type = int.parse(fieldInformation[1], onError: (_) => null);
     return new JsVariableMirror(s(unmangledName),
                                 jsName,
                                 type,
diff --git a/sdk/lib/_internal/compiler/js_lib/js_number.dart b/sdk/lib/_internal/compiler/js_lib/js_number.dart
index 64df825..b340247 100644
--- a/sdk/lib/_internal/compiler/js_lib/js_number.dart
+++ b/sdk/lib/_internal/compiler/js_lib/js_number.dart
@@ -17,7 +17,7 @@
   const JSNumber();
 
   int compareTo(num b) {
-    if (b is! num) throw new ArgumentError(b);
+    if (b is! num) throw argumentErrorValue(b);
     if (this < b) {
       return -1;
     } else if (this > b) {
@@ -45,15 +45,14 @@
   bool get isNaN => JS('bool', r'isNaN(#)', this);
 
   bool get isInfinite {
-    return JS('bool', r'# == Infinity', this)
-        || JS('bool', r'# == -Infinity', this);
+    return JS('bool', r'# == (1/0)', this)
+        || JS('bool', r'# == (-1/0)', this);
   }
 
   bool get isFinite => JS('bool', r'isFinite(#)', this);
 
   num remainder(num b) {
-    checkNull(b); // TODO(ngeoffray): This is not specified but co19 tests it.
-    if (b is! num) throw new ArgumentError(b);
+    if (b is! num) throw argumentErrorValue(b);
     return JS('num', r'# % #', this, b);
   }
 
@@ -116,10 +115,10 @@
   double truncateToDouble() => this < 0 ? ceilToDouble() : floorToDouble();
 
   num clamp(lowerLimit, upperLimit) {
-    if (lowerLimit is! num) throw new ArgumentError(lowerLimit);
-    if (upperLimit is! num) throw new ArgumentError(upperLimit);
+    if (lowerLimit is! num) throw argumentErrorValue(lowerLimit);
+    if (upperLimit is! num) throw argumentErrorValue(upperLimit);
     if (lowerLimit.compareTo(upperLimit) > 0) {
-      throw new ArgumentError(lowerLimit);
+      throw argumentErrorValue(lowerLimit);
     }
     if (this.compareTo(lowerLimit) < 0) return lowerLimit;
     if (this.compareTo(upperLimit) > 0) return upperLimit;
@@ -212,27 +211,27 @@
   num operator -() => JS('num', r'-#', this);
 
   num operator +(num other) {
-    if (other is !num) throw new ArgumentError(other);
+    if (other is !num) throw argumentErrorValue(other);
     return JS('num', '# + #', this, other);
   }
 
   num operator -(num other) {
-    if (other is !num) throw new ArgumentError(other);
+    if (other is !num) throw argumentErrorValue(other);
     return JS('num', '# - #', this, other);
   }
 
   num operator /(num other) {
-    if (other is !num) throw new ArgumentError(other);
+    if (other is !num) throw argumentErrorValue(other);
     return JS('num', '# / #', this, other);
   }
 
   num operator *(num other) {
-    if (other is !num) throw new ArgumentError(other);
+    if (other is !num) throw argumentErrorValue(other);
     return JS('num', '# * #', this, other);
   }
 
   num operator %(num other) {
-    if (other is !num) throw new ArgumentError(other);
+    if (other is !num) throw argumentErrorValue(other);
     // Euclidean Modulo.
     num result = JS('num', r'# % #', this, other);
     if (result == 0) return 0;  // Make sure we don't return -0.0.
@@ -262,7 +261,7 @@
   }
 
   int _tdivSlow(num other) {
-    if (other is !num) throw new ArgumentError(other);
+    if (other is !num) throw argumentErrorValue(other);
     return (JS('num', r'# / #', this, other)).toInt();
   }
 
@@ -272,8 +271,8 @@
   // the grain at which we do the type checks.
 
   num operator <<(num other) {
-    if (other is !num) throw new ArgumentError(other);
-    if (JS('num', '#', other) < 0) throw new ArgumentError(other);
+    if (other is !num) throw argumentErrorValue(other);
+    if (JS('num', '#', other) < 0) throw argumentErrorValue(other);
     return _shlPositive(other);
   }
 
@@ -287,8 +286,8 @@
 
   num operator >>(num other) {
     if (false) _shrReceiverPositive(other);
-    if (other is !num) throw new ArgumentError(other);
-    if (JS('num', '#', other) < 0) throw new ArgumentError(other);
+    if (other is !num) throw argumentErrorValue(other);
+    if (JS('num', '#', other) < 0) throw argumentErrorValue(other);
     return _shrOtherPositive(other);
   }
 
@@ -303,7 +302,7 @@
   }
 
   num _shrReceiverPositive(num other) {
-    if (JS('num', '#', other) < 0) throw new ArgumentError(other);
+    if (JS('num', '#', other) < 0) throw argumentErrorValue(other);
     return _shrBothPositive(other);
   }
 
@@ -320,37 +319,37 @@
   }
 
   num operator &(num other) {
-    if (other is !num) throw new ArgumentError(other);
+    if (other is !num) throw argumentErrorValue(other);
     return JS('JSUInt32', r'(# & #) >>> 0', this, other);
   }
 
   num operator |(num other) {
-    if (other is !num) throw new ArgumentError(other);
+    if (other is !num) throw argumentErrorValue(other);
     return JS('JSUInt32', r'(# | #) >>> 0', this, other);
   }
 
   num operator ^(num other) {
-    if (other is !num) throw new ArgumentError(other);
+    if (other is !num) throw argumentErrorValue(other);
     return JS('JSUInt32', r'(# ^ #) >>> 0', this, other);
   }
 
   bool operator <(num other) {
-    if (other is !num) throw new ArgumentError(other);
+    if (other is !num) throw argumentErrorValue(other);
     return JS('bool', '# < #', this, other);
   }
 
   bool operator >(num other) {
-    if (other is !num) throw new ArgumentError(other);
+    if (other is !num) throw argumentErrorValue(other);
     return JS('bool', '# > #', this, other);
   }
 
   bool operator <=(num other) {
-    if (other is !num) throw new ArgumentError(other);
+    if (other is !num) throw argumentErrorValue(other);
     return JS('bool', '# <= #', this, other);
   }
 
   bool operator >=(num other) {
-    if (other is !num) throw new ArgumentError(other);
+    if (other is !num) throw argumentErrorValue(other);
     return JS('bool', '# >= #', this, other);
   }
 
@@ -391,8 +390,8 @@
 
   // Returns 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) throw argumentErrorValue(e);
+    if (m is! int) throw argumentErrorValue(m);
     if (e < 0) throw new RangeError(e);
     if (m <= 0) throw new RangeError(m);
     if (e == 0) return 1;
diff --git a/sdk/lib/_internal/compiler/js_lib/js_rti.dart b/sdk/lib/_internal/compiler/js_lib/js_rti.dart
index f153150..e5669e2 100644
--- a/sdk/lib/_internal/compiler/js_lib/js_rti.dart
+++ b/sdk/lib/_internal/compiler/js_lib/js_rti.dart
@@ -389,7 +389,8 @@
     rti = JS('JSExtendableArray', '#.slice()', rti);  // Make a copy.
     JS('', '#.splice(0, 0, #)', rti, type);  // Insert type at position 0.
     type = rti;
-  } else if (isDartFunctionType(t)) {
+  }
+  if (isDartFunctionType(t)) {
     // Functions are treated specially and have their type information stored
     // directly in the instance.
     var targetSignatureFunction =
diff --git a/sdk/lib/_internal/compiler/js_lib/js_string.dart b/sdk/lib/_internal/compiler/js_lib/js_string.dart
index 43f9380..ed8189d 100644
--- a/sdk/lib/_internal/compiler/js_lib/js_string.dart
+++ b/sdk/lib/_internal/compiler/js_lib/js_string.dart
@@ -14,9 +14,9 @@
   const JSString();
 
   int codeUnitAt(int index) {
-    if (index is !int) throw new ArgumentError(index);
-    if (index < 0) throw new RangeError.value(index);
-    if (index >= length) throw new RangeError.value(index);
+    if (index is !int) throw diagnoseIndexError(this, index);
+    if (index < 0) throw diagnoseIndexError(this, index);
+    if (index >= length) throw diagnoseIndexError(this, index);
     return JS('JSUInt31', r'#.charCodeAt(#)', this, index);
   }
 
@@ -44,7 +44,7 @@
   }
 
   String operator +(String other) {
-    if (other is !String) throw new ArgumentError(other);
+    if (other is !String) throw new ArgumentError.value(other);
     return JS('String', r'# + #', this, other);
   }
 
@@ -383,7 +383,7 @@
 
   int indexOf(Pattern pattern, [int start = 0]) {
     checkNull(pattern);
-    if (start is! int) throw new ArgumentError(start);
+    if (start is! int) throw argumentErrorValue(start);
     if (start < 0 || start > this.length) {
       throw new RangeError.range(start, 0, this.length);
     }
@@ -406,7 +406,7 @@
     if (start == null) {
       start = length;
     } else if (start is! int) {
-      throw new ArgumentError(start);
+      throw argumentErrorValue(start);
     } else if (start < 0 || start > this.length) {
       throw new RangeError.range(start, 0, this.length);
     }
@@ -436,7 +436,7 @@
   bool get isNotEmpty => !isEmpty;
 
   int compareTo(String other) {
-    if (other is !String) throw new ArgumentError(other);
+    if (other is !String) throw argumentErrorValue(other);
     return this == other ? 0
         : JS('bool', r'# < #', this, other) ? -1 : 1;
   }
@@ -469,8 +469,8 @@
   int get length => JS('int', r'#.length', this);
 
   String operator [](int index) {
-    if (index is !int) throw new ArgumentError(index);
-    if (index >= length || index < 0) throw new RangeError.value(index);
+    if (index is !int) throw diagnoseIndexError(this, index);
+    if (index >= length || index < 0) throw diagnoseIndexError(this, index);
     return JS('String', '#[#]', this, index);
   }
 }
diff --git a/sdk/lib/_internal/compiler/js_lib/linked_hash_map.dart b/sdk/lib/_internal/compiler/js_lib/linked_hash_map.dart
index bbf76d3..cef7f93 100644
--- a/sdk/lib/_internal/compiler/js_lib/linked_hash_map.dart
+++ b/sdk/lib/_internal/compiler/js_lib/linked_hash_map.dart
@@ -44,7 +44,7 @@
   /// If ES6 Maps are available returns a linked hash-map backed by an ES6 Map.
   @ForceInline()
   factory JsLinkedHashMap.es6() {
-    return (_USE_ES6_MAPS  && JsLinkedHashMap._supportsEs6Maps)
+    return (_USE_ES6_MAPS && JsLinkedHashMap._supportsEs6Maps)
         ? new Es6LinkedHashMap<K, V>()
         : new JsLinkedHashMap<K, V>();
   }
@@ -223,9 +223,10 @@
   }
 
   void _modified() {
-    // Value cycles after 2^30 modifications. If you keep hold of an
-    // iterator for that long, you might miss a modification
-    // detection, and iteration can go sour. Don't do that.
+    // Value cycles after 2^30 modifications so that modification counts are
+    // always unboxed (Smi) values. Modification detection will be missed if you
+    // make exactly some multiple of 2^30 modifications between advances of an
+    // iterator.
     _modifications = (_modifications + 1) & 0x3ffffff;
   }
 
diff --git a/sdk/lib/_internal/compiler/js_lib/native_helper.dart b/sdk/lib/_internal/compiler/js_lib/native_helper.dart
index 82f97f5..e87ace9 100644
--- a/sdk/lib/_internal/compiler/js_lib/native_helper.dart
+++ b/sdk/lib/_internal/compiler/js_lib/native_helper.dart
@@ -258,7 +258,7 @@
 
 
 makeLeafDispatchRecord(interceptor) {
-  var fieldName = JS_IS_INDEXABLE_FIELD_NAME();
+  var fieldName = JS_GET_NAME(JsGetName.IS_INDEXABLE_FIELD_NAME);
   bool indexability = JS('bool', r'!!#[#]', interceptor, fieldName);
   return makeDispatchRecord(interceptor, false, null, indexability);
 }
diff --git a/sdk/lib/_internal/compiler/js_lib/native_typed_data.dart b/sdk/lib/_internal/compiler/js_lib/native_typed_data.dart
index b09537d..d134c6d 100644
--- a/sdk/lib/_internal/compiler/js_lib/native_typed_data.dart
+++ b/sdk/lib/_internal/compiler/js_lib/native_typed_data.dart
@@ -11,8 +11,9 @@
 import 'dart:collection';
 import 'dart:_internal';
 import 'dart:_interceptors' show JSIndexable, JSUInt32, JSUInt31;
-import 'dart:_js_helper'
-show Creates, JavaScriptIndexingBehavior, JSName, Native, Null, Returns;
+import 'dart:_js_helper' show
+    Creates, JavaScriptIndexingBehavior, JSName, Native, Null, Returns,
+    diagnoseIndexError;
 import 'dart:_foreign_helper' show JS;
 import 'dart:math' as Math;
 
@@ -445,35 +446,34 @@
   @JSName('BYTES_PER_ELEMENT')
   final int elementSizeInBytes;
 
-  void _invalidIndex(int index, int length) {
-    if (index < 0 || index >= length) {
-      if (this is List) {
-        var list = this;  // Typed as dynamic to avoid warning.
-        if (length == list.length) {
-          throw new RangeError.index(index, this);
-        }
-      }
-      throw new RangeError.range(index, 0, length - 1);
-    } else {
-      throw new ArgumentError('Invalid list index $index');
-    }
-  }
-
   void _checkIndex(int index, int length) {
     if (JS('bool', '(# >>> 0) !== #', index, index) ||
         JS('int', '#', index) >= length) {  // 'int' guaranteed by above test.
-      _invalidIndex(index, length);
+      throw diagnoseIndexError(this, index);
+    }
+  }
+
+  void _invalidPosition(int position, int length) {
+    if (position is !int) {
+      throw new ArgumentError.value(position, null, 'Invalid list position');
+    } else {
+      throw new RangeError.range(position, 0, length);
+    }
+  }
+
+  void _checkPosition(int position, int length) {
+    if (JS('bool', '(# >>> 0) !== #', position, position) ||
+        JS('int', '#', position) > length) {  // 'int' guaranteed by above test.
+      _invalidPosition(position, length);
     }
   }
 
   int _checkSublistArguments(int start, int end, int length) {
     // For `sublist` the [start] and [end] indices are allowed to be equal to
-    // [length]. However, [_checkIndex] only allows indices in the range
-    // 0 .. length - 1. We therefore increment the [length] argument by one
-    // for the [_checkIndex] checks.
-    _checkIndex(start, length + 1);
+    // [length].
+    _checkPosition(start, length);
     if (end == null) return length;
-    _checkIndex(end, length + 1);
+    _checkPosition(end, length);
     if (start > end) throw new RangeError.range(start, 0, end);
     return end;
   }
@@ -862,8 +862,8 @@
   void _setRangeFast(int start, int end,
       NativeTypedArray source, int skipCount) {
     int targetLength = this.length;
-    _checkIndex(start, targetLength + 1);
-    _checkIndex(end, targetLength + 1);
+    _checkPosition(start, targetLength);
+    _checkPosition(end, targetLength);
     if (start > end) throw new RangeError.range(start, 0, end);
     int count = end - start;
 
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 9118548..8e11da3 100644
--- a/sdk/lib/_internal/compiler/js_lib/shared/embedded_names.dart
+++ b/sdk/lib/_internal/compiler/js_lib/shared/embedded_names.dart
@@ -93,14 +93,36 @@
   DEFAULT_VALUES_PROPERTY,
   CALL_NAME_PROPERTY,
   DEFERRED_ACTION_PROPERTY,
+  /// Prefix used for generated type argument substitutions on classes.
   OPERATOR_AS_PREFIX,
+  /// Name used for generated function types on classes and methods.
   SIGNATURE_NAME,
+  /// Name used to tag typedefs.
   TYPEDEF_TAG,
+  /// Name used to tag void return in function type representations in
+  /// JavaScript.
   FUNCTION_TYPE_VOID_RETURN_TAG,
+  /// Name used to tag return types in function type representations in
+  /// JavaScript.
   FUNCTION_TYPE_RETURN_TYPE_TAG,
+  /// Name used to tag required parameters in function type representations
+  /// in JavaScript.
   FUNCTION_TYPE_REQUIRED_PARAMETERS_TAG,
+  /// Name used to tag optional parameters in function type representations
+  /// in JavaScript.
   FUNCTION_TYPE_OPTIONAL_PARAMETERS_TAG,
+  /// Name used to tag named parameters in function type representations in
+  /// JavaScript.
   FUNCTION_TYPE_NAMED_PARAMETERS_TAG,
+  /// Field name used for determining if an object or its interceptor has
+  /// JavaScript indexing behavior.
+  IS_INDEXABLE_FIELD_NAME,
+  /// String representation of the type of the null class.
+  NULL_CLASS_TYPE_NAME,
+  /// String representation of the type of the object class.
+  OBJECT_CLASS_TYPE_NAME,
+  /// String representation of the type of the function class.
+  FUNCTION_CLASS_TYPE_NAME,
 }
 
 enum JsBuiltin {
@@ -156,25 +178,13 @@
   ///                JsBuiltin.isSubtype, other, type);
   isSubtype,
 
-  /// Returns true if the given type is _the_ `Function` type.
-  /// That is, it returns true if the given [type] is exactly the `Function`
-  /// type rti-encoding.
+  /// Returns true if the given type equals the type given as second
+  /// argument. Use the JS_GET_NAME helpers to get the type representation
+  /// for various Dart classes.
   ///
   ///     JS_BUILTIN('returns:bool;effects:none;depends:none',
-  ///                JsBuiltin.isFunctionTypeLiteral, type);
-  isFunctionTypeRti,
-
-  /// Returns whether the given type is _the_ null-type..
-  ///
-  ///     JS_BUILTIN('returns:bool;effects:none;depends:none',
-  ///                JsBuiltin.isNullType, type);
-  isNullTypeRti,
-
-  /// Returns whether the given type is _the_ Dart Object type.
-  ///
-  ///     JS_BUILTIN('returns:bool;effects:none;depends:none',
-  ///                JsBuiltin.isDartObjectType, type);
-  isDartObjectTypeRti,
+  ///                JsBuiltin.isFunctionTypeLiteral, type, name);
+  isGivenTypeRti,
 
   /// Returns the metadata of the given [index].
   ///
diff --git a/sdk/lib/_internal/compiler/js_lib/string_helper.dart b/sdk/lib/_internal/compiler/js_lib/string_helper.dart
index 0206fe1..51b696b 100644
--- a/sdk/lib/_internal/compiler/js_lib/string_helper.dart
+++ b/sdk/lib/_internal/compiler/js_lib/string_helper.dart
@@ -145,10 +145,11 @@
     return stringReplaceAllStringFuncUnchecked(receiver, pattern,
                                                onMatch, onNonMatch);
   }
-  // Pattern test here is indistingishable from at the top of the method but we
-  // don't need to do it on the `pattern is String` path.
+  // Placing the Pattern test here is indistingishable from placing it at the
+  // top of the method but it saves an extra check on the `pattern is String`
+  // path.
   if (pattern is! Pattern) {
-    throw new ArgumentError("${pattern} is not a Pattern");
+    throw new ArgumentError.value(pattern, 'pattern', 'is not a Pattern');
   }
   StringBuffer buffer = new StringBuffer();
   int startIndex = 0;
diff --git a/sdk/lib/async/future_impl.dart b/sdk/lib/async/future_impl.dart
index 7297754..980f0ca 100644
--- a/sdk/lib/async/future_impl.dart
+++ b/sdk/lib/async/future_impl.dart
@@ -233,7 +233,7 @@
     return result;
   }
 
-  Stream<T> asStream() => new Stream.fromFuture(this);
+  Stream<T> asStream() => new Stream<T>.fromFuture(this);
 
   void _markPendingCompletion() {
     if (!_mayComplete) throw new StateError("Future already completed");
diff --git a/sdk/lib/async/stream.dart b/sdk/lib/async/stream.dart
index 77420d0..7256445 100644
--- a/sdk/lib/async/stream.dart
+++ b/sdk/lib/async/stream.dart
@@ -75,6 +75,22 @@
   Stream();
 
   /**
+   * Internal use only. We do not want to promise that Stream stays const.
+   *
+   * If mixins become compatible with const constructors, we may use a
+   * stream mixin instead of extending Stream from a const class.
+   */
+  const Stream._internal();
+
+  /**
+   * Creates an empty broadcast stream.
+   *
+   * This is a stream which does nothing except sending a done event
+   * when it's listened to.
+   */
+  const factory Stream.empty() = _EmptyStream<T>;
+
+  /**
    * Creates a new single-subscription stream from the future.
    *
    * When the future completes, the stream will fire one event, either
@@ -462,12 +478,22 @@
   }
 
   /**
-   * Binds this stream as the input of the provided [StreamConsumer].
+   * Pipe the events of this stream into [streamConsumer].
    *
-   * The `streamConsumer` is closed when the stream has been added to it.
+   * The events of this stream are added to `streamConsumer` using
+   * [StreamConsumer.addStream].
+   * The `streamConsumer` is closed when this stream has been successfully added
+   * to it - when the future returned by `addStream` completes without an error.
    *
    * Returns a future which completes when the stream has been consumed
    * and the consumer has been closed.
+   *
+   * The returned future completes with the same result as the future returned
+   * by [StreamConsumer.close].
+   * If the adding of the stream itself fails in some way,
+   * then the consumer is expected to be closed, and won't be closed again.
+   * In that case the returned future completes with the error from calling
+   * `addStream`.
    */
   Future pipe(StreamConsumer<T> streamConsumer) {
     return streamConsumer.addStream(this).then((_) => streamConsumer.close());
@@ -1423,11 +1449,19 @@
 
 
 /**
- * The target of a [Stream.pipe] call.
+ * Abstract interface for a "sink" accepting multiple entire streams.
  *
- * The [Stream.pipe] call will pass itself to this object, and then return
- * the resulting [Future]. The pipe should complete the future when it's
- * done.
+ * A consumer can accept a number of consequtive streams using [addStream],
+ * and when no further data need to be added, the [close] method tells the
+ * consumer to complete its work and shut down.
+ *
+ * This class is not just a [Sink<Stream>] because it is also combined with
+ * other [Sink] classes, like it's combined with [EventSink] in the
+ * [StreamSink] class.
+ *
+ * The [Stream.pipe] accepts a `StreamConsumer` and will pass the stream
+ * to the consumer's [addStream] method. When that completes, it will
+ * call [close] and then complete its own returned future.
  */
 abstract class StreamConsumer<S> {
   /**
@@ -1435,22 +1469,38 @@
    *
    * Listens on [stream] and does something for each event.
    *
-   * The consumer may stop listening after an error, or it may consume
-   * all the errors and only stop at a done event.
+   * Returns a future which is completed when the stream is done being added,
+   * and the consumer is ready to accept a new stream.
+   * No further calls to [addStream] or [close] should happen before the
+   * returned future has completed.
+   *
+   * The consumer may stop listening to the stream after an error,
+   * it may consume all the errors and only stop at a done event,
+   * or it may be canceled early if the receiver don't want any further events.
+   *
+   * If the consumer stops listening because of some error preventing it
+   * from continuing, it may report this error in the returned future,
+   * otherwise it will just complete the future with `null`.
    */
   Future addStream(Stream<S> stream);
 
   /**
-   * Tell the consumer that no futher streams will be added.
+   * Tells the consumer that no futher streams will be added.
    *
-   * Returns a future that is completed when the consumer is done handling
-   * events.
+   * This allows the consumer to complete any remaining work and release
+   * resources that are no longer needed
+   *
+   * Returns a future which is completed when the consumer has shut down.
+   * If cleaning up can fail, the error may be reported in the returned future,
+   * otherwise it completes with `null`.
    */
   Future close();
 }
 
 
 /**
+ * A object that accepts stream events both synchronously and asynchronously.
+ *
  * A [StreamSink] unifies the asynchronous methods from [StreamConsumer] and
  * the synchronous methods from [EventSink].
  *
@@ -1467,11 +1517,26 @@
  *
  * When [close] is called, it will return the [done] [Future].
  */
-abstract class StreamSink<S> implements StreamConsumer<S>, EventSink<S> {
+abstract class StreamSink<S> implements EventSink<S>, StreamConsumer<S> {
   /**
-   * As [EventSink.close], but returns a future.
+   * Tells the stream sink that no futher streams will be added.
+   *
+   * This allows the stream sink to complete any remaining work and release
+   * resources that are no longer needed
+   *
+   * Returns a future which is completed when the stream sink has shut down.
+   * If cleaning up can fail, the error may be reported in the returned future,
+   * otherwise it completes with `null`.
    *
    * Returns the same future as [done].
+   *
+   * The stream sink may close before the [close] method is called, either due
+   * to an error or because it is itself provding events to someone who has
+   * stopped listening. In that case, the [done] future is completed first,
+   * and the `close` method will return the `done` future when called.
+   *
+   * Unifies [StreamConsumer.close] and [EventSink.close] which both mark their
+   * object as not expecting any further events.
    */
   Future close();
 
diff --git a/sdk/lib/async/stream_controller.dart b/sdk/lib/async/stream_controller.dart
index a4116cd..5764ecd 100644
--- a/sdk/lib/async/stream_controller.dart
+++ b/sdk/lib/async/stream_controller.dart
@@ -80,8 +80,8 @@
     if (onListen == null && onPause == null &&
         onResume == null && onCancel == null) {
       return sync
-          ? new _NoCallbackSyncStreamController/*<T>*/()
-          : new _NoCallbackAsyncStreamController/*<T>*/();
+          ? new _NoCallbackSyncStreamController<T>()
+          : new _NoCallbackAsyncStreamController<T>();
     }
     return sync
          ? new _SyncStreamController<T>(onListen, onPause, onResume, onCancel)
@@ -176,9 +176,6 @@
    * Send or enqueue an error event.
    *
    * If [error] is `null`, it is replaced by a [NullThrownError].
-   *
-   * Also allows an objection stack trace object, on top of what [EventSink]
-   * allows.
    */
   void addError(Object error, [StackTrace stackTrace]);
 
@@ -394,7 +391,7 @@
   _NotificationHandler get _onCancel;
 
   // Return a new stream every time. The streams are equal, but not identical.
-  Stream<T> get stream => new _ControllerStream(this);
+  Stream<T> get stream => new _ControllerStream<T>(this);
 
   /**
    * Returns a view of this object that only exposes the [StreamSink] interface.
@@ -758,11 +755,11 @@
   _NotificationHandler get _onCancel => null;
 }
 
-class _NoCallbackAsyncStreamController/*<T>*/ = _StreamController/*<T>*/
-       with _AsyncStreamControllerDispatch/*<T>*/, _NoCallbacks;
+class _NoCallbackAsyncStreamController<T> = _StreamController<T>
+       with _AsyncStreamControllerDispatch<T>, _NoCallbacks;
 
-class _NoCallbackSyncStreamController/*<T>*/ = _StreamController/*<T>*/
-       with _SyncStreamControllerDispatch/*<T>*/, _NoCallbacks;
+class _NoCallbackSyncStreamController<T> = _StreamController<T>
+       with _SyncStreamControllerDispatch<T>, _NoCallbacks;
 
 typedef _NotificationHandler();
 
diff --git a/sdk/lib/async/stream_impl.dart b/sdk/lib/async/stream_impl.dart
index 3f77294..19bdb69 100644
--- a/sdk/lib/async/stream_impl.dart
+++ b/sdk/lib/async/stream_impl.dart
@@ -1081,3 +1081,15 @@
     _state = _STATE_EXTRA_DONE;
   }
 }
+
+/** An empty broadcast stream, sending a done event as soon as possible. */
+class _EmptyStream<T> extends Stream<T> {
+  const _EmptyStream() : super._internal();
+  bool get isBroadcast => true;
+  StreamSubscription<T> listen(void onData(T data),
+                               {Function onError,
+                                void onDone(),
+                                bool cancelOnError}) {
+    return new _DoneStreamSubscription<T>(onDone);
+  }
+}
diff --git a/sdk/lib/core/errors.dart b/sdk/lib/core/errors.dart
index 144921a..0e99b0b 100644
--- a/sdk/lib/core/errors.dart
+++ b/sdk/lib/core/errors.dart
@@ -282,7 +282,8 @@
   static void checkValidIndex(int index, var indexable,
                               [String name, int length, String message]) {
     if (length == null) length = indexable.length;
-    if (index < 0 || index >= length) {
+    // Comparing with `0` as receiver produces better dart2js type inference.
+    if (0 > index || index >= length) {
       if (name == null) name = "index";
       throw new RangeError.index(index, indexable, name, message, length);
     }
diff --git a/sdk/lib/html/dart2js/html_dart2js.dart b/sdk/lib/html/dart2js/html_dart2js.dart
index 34cbd41..ffe111f 100644
--- a/sdk/lib/html/dart2js/html_dart2js.dart
+++ b/sdk/lib/html/dart2js/html_dart2js.dart
@@ -12895,8 +12895,12 @@
    */
   void insertAdjacentHtml(String where, String html, {NodeValidator validator,
       NodeTreeSanitizer treeSanitizer}) {
-      _insertAdjacentNode(where, new DocumentFragment.html(html,
-          validator: validator, treeSanitizer: treeSanitizer));
+      if (treeSanitizer is _TrustedHtmlTreeSanitizer) {
+        _insertAdjacentHtml(where, html);
+      } else {
+        _insertAdjacentNode(where, new DocumentFragment.html(html,
+            validator: validator, treeSanitizer: treeSanitizer));
+      }
   }
 
 
@@ -13247,8 +13251,12 @@
   void setInnerHtml(String html,
     {NodeValidator validator, NodeTreeSanitizer treeSanitizer}) {
     text = null;
-    append(createFragment(
-        html, validator: validator, treeSanitizer: treeSanitizer));
+    if (treeSanitizer is _TrustedHtmlTreeSanitizer) {
+      _innerHtml = html;
+    } else {
+      append(createFragment(
+          html, validator: validator, treeSanitizer: treeSanitizer));
+    }
   }
   String get innerHtml => _innerHtml;
 
@@ -40692,9 +40700,27 @@
    * will mark the entire tree as unsafe.
    */
   void sanitizeTree(Node node);
+
+  /**
+   * A sanitizer for trees that we trust. It does no validation and allows
+   * any elements. It is also more efficient, since it can pass the text
+   * directly through to the underlying APIs without creating a document 
+   * fragment to be sanitized.
+   */
+  static const trusted = const _TrustedHtmlTreeSanitizer();
 }
 
 /**
+ * A sanitizer for trees that we trust. It does no validation and allows
+ * any elements.
+ */
+class _TrustedHtmlTreeSanitizer implements NodeTreeSanitizer {
+  const _TrustedHtmlTreeSanitizer();
+
+  sanitizeTree(Node node) {}
+}
+  
+/**
  * Defines the policy for what types of uris are allowed for particular
  * attribute values.
  *
diff --git a/sdk/lib/html/dartium/html_dartium.dart b/sdk/lib/html/dartium/html_dartium.dart
index 5ab6241..1de3e1c 100644
--- a/sdk/lib/html/dartium/html_dartium.dart
+++ b/sdk/lib/html/dartium/html_dartium.dart
@@ -12423,8 +12423,12 @@
    */
   void insertAdjacentHtml(String where, String html, {NodeValidator validator,
       NodeTreeSanitizer treeSanitizer}) {
-      _insertAdjacentNode(where, new DocumentFragment.html(html,
-          validator: validator, treeSanitizer: treeSanitizer));
+      if (treeSanitizer is _TrustedHtmlTreeSanitizer) {
+        _insertAdjacentHtml(where, html);
+      } else {
+        _insertAdjacentNode(where, new DocumentFragment.html(html,
+            validator: validator, treeSanitizer: treeSanitizer));
+      }
   }
 
 
@@ -12695,8 +12699,12 @@
   void setInnerHtml(String html,
     {NodeValidator validator, NodeTreeSanitizer treeSanitizer}) {
     text = null;
-    append(createFragment(
-        html, validator: validator, treeSanitizer: treeSanitizer));
+    if (treeSanitizer is _TrustedHtmlTreeSanitizer) {
+      _innerHtml = html;
+    } else {
+      append(createFragment(
+          html, validator: validator, treeSanitizer: treeSanitizer));
+    }
   }
   String get innerHtml => _innerHtml;
 
@@ -40622,9 +40630,27 @@
    * will mark the entire tree as unsafe.
    */
   void sanitizeTree(Node node);
+
+  /**
+   * A sanitizer for trees that we trust. It does no validation and allows
+   * any elements. It is also more efficient, since it can pass the text
+   * directly through to the underlying APIs without creating a document 
+   * fragment to be sanitized.
+   */
+  static const trusted = const _TrustedHtmlTreeSanitizer();
 }
 
 /**
+ * A sanitizer for trees that we trust. It does no validation and allows
+ * any elements.
+ */
+class _TrustedHtmlTreeSanitizer implements NodeTreeSanitizer {
+  const _TrustedHtmlTreeSanitizer();
+
+  sanitizeTree(Node node) {}
+}
+  
+/**
  * Defines the policy for what types of uris are allowed for particular
  * attribute values.
  *
diff --git a/sdk/lib/io/file.dart b/sdk/lib/io/file.dart
index 8799158..691d783 100644
--- a/sdk/lib/io/file.dart
+++ b/sdk/lib/io/file.dart
@@ -10,13 +10,20 @@
 class FileMode {
   /// The mode for opening a file only for reading.
   static const READ = const FileMode._internal(0);
-  /// The mode for opening a file for reading and writing. The file is
+  /// Mode for opening a file for reading and writing. The file is
   /// overwritten if it already exists. The file is created if it does not
   /// already exist.
   static const WRITE = const FileMode._internal(1);
-  /// The mode for opening a file for reading and writing to the
+  /// Mode for opening a file for reading and writing to the
   /// end of it. The file is created if it does not already exist.
   static const APPEND = const FileMode._internal(2);
+  /// Mode for opening a file for writing *only*. The file is
+  /// overwritten if it already exists. The file is created if it does not
+  /// already exist.
+  static const WRITE_ONLY = const FileMode._internal(3);
+  /// Mode for opening a file for writing *only* to the
+  /// end of it. The file is created if it does not already exist.
+  static const WRITE_ONLY_APPEND = const FileMode._internal(4);
   final int _mode;
 
   const FileMode._internal(this._mode);
@@ -31,6 +38,13 @@
 /// The mode for opening a file for reading and writing to the
 /// end of it. The file is created if it does not already exist.
 const APPEND = FileMode.APPEND;
+/// Mode for opening a file for writing *only*. The file is
+/// overwritten if it already exists. The file is created if it does not
+/// already exist.
+const WRITE_ONLY = FileMode.WRITE_ONLY;
+/// Mode for opening a file for writing *only* to the
+/// end of it. The file is created if it does not already exist.
+const WRITE_ONLY_APPEND = FileMode.WRITE_ONLY_APPEND;
 
 
 /// Type of lock when requesting a lock on a file.
diff --git a/sdk/lib/io/file_impl.dart b/sdk/lib/io/file_impl.dart
index a98d948..8ed6c58 100644
--- a/sdk/lib/io/file_impl.dart
+++ b/sdk/lib/io/file_impl.dart
@@ -344,8 +344,11 @@
   Future<RandomAccessFile> open({FileMode mode: FileMode.READ}) {
     if (mode != FileMode.READ &&
         mode != FileMode.WRITE &&
-        mode != FileMode.APPEND) {
-      return new Future.error(new ArgumentError());
+        mode != FileMode.APPEND &&
+        mode != FileMode.WRITE_ONLY &&
+        mode != FileMode.WRITE_ONLY_APPEND) {
+      return new Future.error(
+          new ArgumentError('Invalid file mode for this operation'));
     }
     return _IOService._dispatch(_FILE_OPEN, [path, mode._mode])
         .then((response) {
@@ -401,10 +404,10 @@
   RandomAccessFile openSync({FileMode mode: FileMode.READ}) {
     if (mode != FileMode.READ &&
         mode != FileMode.WRITE &&
-        mode != FileMode.APPEND) {
-      throw new FileSystemException("Unknown file mode. Use FileMode.READ, "
-                              "FileMode.WRITE or FileMode.APPEND.",
-                              path);
+        mode != FileMode.APPEND &&
+        mode != FileMode.WRITE_ONLY &&
+        mode != FileMode.WRITE_ONLY_APPEND) {
+      throw new ArgumentError('Invalid file mode for this operation');
     }
     var id = _open(path, mode._mode);
     throwIfError(id, "Cannot open file", path);
@@ -428,9 +431,10 @@
   IOSink openWrite({FileMode mode: FileMode.WRITE,
                     Encoding encoding: UTF8}) {
     if (mode != FileMode.WRITE &&
-        mode != FileMode.APPEND) {
-      throw new ArgumentError(
-          "Wrong FileMode. Use FileMode.WRITE or FileMode.APPEND");
+        mode != FileMode.APPEND &&
+        mode != FileMode.WRITE_ONLY &&
+        mode != FileMode.WRITE_ONLY_APPEND) {
+      throw new ArgumentError('Invalid file mode for this operation');
     }
     var consumer = new _FileStreamConsumer(this, mode);
     return new IOSink(consumer, encoding: encoding);
diff --git a/sdk/lib/io/string_transformer.dart b/sdk/lib/io/string_transformer.dart
index 423a61c..16e721b 100644
--- a/sdk/lib/io/string_transformer.dart
+++ b/sdk/lib/io/string_transformer.dart
@@ -5,6 +5,12 @@
 part of dart.io;
 
 /// The current system encoding.
+///
+/// This us used for converting from bytes to/from String when
+/// communicating on stdin, stdout and stderr.
+///
+/// On Windows this will use the currently active code page for the
+/// conversion. On all other systems it will always use UTF-8.
 const SystemEncoding SYSTEM_ENCODING = const SystemEncoding();
 
 /**
diff --git a/sdk/lib/isolate/isolate.dart b/sdk/lib/isolate/isolate.dart
index 8372eaf..9b488c2 100644
--- a/sdk/lib/isolate/isolate.dart
+++ b/sdk/lib/isolate/isolate.dart
@@ -276,6 +276,10 @@
    * If `response` cannot be sent to the isolate, then the request is ignored.
    * It is recommended to only use simple values that can be sent to all
    * isolates, like `null`, booleans, numbers or strings.
+   * 
+   * Since isolates run concurrently, it's possible for it to exit before the
+   * exit listener is established. To avoid this, start the isolate paused,
+   * add the listener, then resume it.
    */
   /* TODO(lrn): Can we do better? Can the system recognize this message and
    * send a reply if the receiving isolate is dead?
@@ -364,6 +368,10 @@
    *
    * Listening using the same port more than once does nothing. It will only
    * get each error once.
+   * 
+   * Since isolates run concurrently, it's possible for it to exit before the
+   * error listener is established. To avoid this, start the isolate paused,
+   * add the listener, then resume it.
    */
   external void addErrorListener(SendPort port);
 
diff --git a/sdk/lib/mirrors/mirrors.dart b/sdk/lib/mirrors/mirrors.dart
index 5d73641..d0f8379 100644
--- a/sdk/lib/mirrors/mirrors.dart
+++ b/sdk/lib/mirrors/mirrors.dart
@@ -14,13 +14,13 @@
 
 /**
  * Basic reflection in Dart,
- * with support for introspection and dynamic evaluation.
+ * with support for introspection and dynamic invocation.
  *
  * *Introspection* is that subset of reflection by which a running
  * program can examine its own structure. For example, a function
  * that prints out the names of all the members of an arbitrary object.
  *
- * *Dynamic evaluation* refers the ability to evaluate code that
+ * *Dynamic invocation* refers the ability to evaluate code that
  * has not been literally specified at compile time, such as calling a method
  * whose name is provided as an argument (because it is looked up
  * in a database, or provided interactively by the user).
@@ -371,7 +371,7 @@
    * of *o* (if *o* is a class or library) or the private members of the
    * class of *o* (otherwise).
    * If the invocation returns a result *r*, this method returns
-   * the result of calling [reflect](*r*).
+   * the result of calling [reflect]\(*r*\).
    * If the invocation causes a compilation error
    * the effect is the same as if a non-reflective compilation error
    * had been encountered.
@@ -412,7 +412,7 @@
    * mirror on a closure corresponding to that method.
    *
    * If the invocation returns a result *r*, this method returns
-   * the result of calling [reflect](*r*).
+   * the result of calling [reflect]\(*r*\).
    * If the invocation causes a compilation error
    * the effect is the same as if a non-reflective compilation error
    * had been encountered.
@@ -437,7 +437,7 @@
    * of *o* (if *o* is a class or library) or the private members of the
    * class of *o* (otherwise).
    * If the invocation returns a result *r*, this method returns
-   * the result of calling [reflect]([value]).
+   * the result of calling [reflect]\([value]\).
    * If the invocation causes a compilation error
    * the effect is the same as if a non-reflective compilation error
    * had been encountered.
@@ -504,9 +504,16 @@
    * Perform [invocation] on [reflectee].
    * Equivalent to
    *
-   * this.invoke(invocation.memberName,
-   *             invocation.positionalArguments,
-   *             invocation.namedArguments);
+   *     if (invocation.isGetter) {
+   *       return this.getField(invocation.memberName).reflectee;
+   *     } else if (invocation.isSetter) {
+   *       return this.setField(invocation.memberName,
+   *                            invocation.positionArguments[0]).reflectee;
+   *     } else {
+   *       return this.invoke(invocation.memberName,
+   *                          invocation.positionalArguments,
+   *                          invocation.namedArguments).reflectee;
+   *     }
    */
   delegate(Invocation invocation);
 }
@@ -514,8 +521,8 @@
 /**
  * A [ClosureMirror] reflects a closure.
  *
- * A [ClosureMirror] provides access to its captured variables and
- * provides the ability to execute its reflectee.
+ * A [ClosureMirror] provides the ability to execute its reflectee and
+ * introspect its function.
  */
 abstract class ClosureMirror implements InstanceMirror {
   /**
@@ -549,7 +556,7 @@
    * Then this method will perform the method invocation
    *  *f(a1, ..., an, k1: v1, ..., km: vm)*
    * If the invocation returns a result *r*, this method returns
-   * the result of calling [reflect](*r*).
+   * the result of calling [reflect]\(*r*\).
    * If the invocation causes a compilation error
    * the effect is the same as if a non-reflective compilation error
    * had been encountered.
@@ -830,7 +837,7 @@
    * of *c*.
    * In either case:
    * If the expression evaluates to a result *r*, this method returns
-   * the result of calling [reflect](*r*).
+   * the result of calling [reflect]\(*r*\).
    * If evaluating the expression causes a compilation error
    * the effect is the same as if a non-reflective compilation error
    * had been encountered.
diff --git a/tests/benchmark_smoke/benchmark_smoke.status b/tests/benchmark_smoke/benchmark_smoke.status
index 286af69..7eef00b 100644
--- a/tests/benchmark_smoke/benchmark_smoke.status
+++ b/tests/benchmark_smoke/benchmark_smoke.status
@@ -9,4 +9,4 @@
 *: Fail, Pass # TODO(ahe): Triage these tests.
 
 [ $compiler == dart2js && $cps_ir ]
-benchmark_smoke_test: Crash # Instance of 'TypeOperator': type casts not implemented.
+benchmark_smoke_test: Crash # Invalid argument(s)
diff --git a/tests/co19/co19-analyzer2.status b/tests/co19/co19-analyzer2.status
index 8d35bf6..42ad5a8 100644
--- a/tests/co19/co19-analyzer2.status
+++ b/tests/co19/co19-analyzer2.status
@@ -287,3 +287,5 @@
 Language/15_Types/4_Interface_Types_A10_t03: StaticWarning # co19 issue 745
 Language/15_Types/4_Interface_Types_A10_t07: StaticWarning # co19 issue 745
 Language/15_Types/4_Interface_Types_A10_t09: StaticWarning # co19 issue 745
+Language/13_Statements/15_Assert_A04_t07: StaticWarning # Issue 23663
+Language/13_Statements/15_Assert_A03_t08: StaticWarning # Issue 23663
diff --git a/tests/co19/co19-co19.status b/tests/co19/co19-co19.status
index a500f54..f18e7f4 100644
--- a/tests/co19/co19-co19.status
+++ b/tests/co19/co19-co19.status
@@ -33,7 +33,6 @@
 LibTest/isolate/ReceivePort/asBroadcastStream_A02_t01: Fail # co19 issue 687
 LibTest/async/Stream/asBroadcastStream_A02_t01: Fail # co19 issue 687
 
-LibTest/core/Invocation/namedArguments_A01_t01: RuntimeError # co19-roll r607: Please triage this failure
 LibTest/core/Symbol/Symbol_A01_t04: RuntimeError # co19-roll r607: Please triage this failure
 
 Language/07_Classes/07_Classes_A13_t01: Pass, MissingCompileTimeError, Fail # co19-roll r623: Please triage this failure
diff --git a/tests/co19/co19-dart2js.status b/tests/co19/co19-dart2js.status
index dfe9a16..4a74533 100644
--- a/tests/co19/co19-dart2js.status
+++ b/tests/co19/co19-dart2js.status
@@ -54,8 +54,6 @@
 Language/15_Types/4_Interface_Types_A11_t04: fail # Issue 14654
 Language/16_Reference/1_Lexical_Rules/1_Reserved_Words_A40_t04: MissingCompileTimeError # Checks that other Unicode whitespaces are not allowed:  check NO-BREAK SPACE (U+00A0)
 Language/16_Reference/1_Lexical_Rules_A02_t06: MissingCompileTimeError # Checks that Unicode whitespaces other than WHITESPACE are not permitted in the source code. Checks symbol U+00a0.
-LibTest/async/Stream/handleError_A04_t01: RuntimeError # co19-roll r641: Please triage this failure
-LibTest/async/Stream/listen_A05_t01: RuntimeError # co19 issue 736. Issue 15171
 LibTest/collection/LinkedList/add_A01_t01: Pass, Slow # Slow tests that needs extra time to finish.
 LibTest/collection/ListBase/ListBase_class_A01_t01: RuntimeError # Please triage this failure
 LibTest/collection/ListMixin/ListMixin_class_A01_t01: RuntimeError # Please triage this failure
@@ -270,7 +268,6 @@
 
 [ $compiler == dart2js && $runtime == jsshell ]
 Language/12_Expressions/00_Object_Identity/1_Object_Identity_A05_t02: RuntimeError # Issue 21198 (int/double related)
-Language/12_Expressions/17_Getter_Invocation_A07_t02: RuntimeError # Issue 21199
 LibTest/async/Future/Future.delayed_A01_t01: RuntimeError # Issue 7728, timer not supported in jsshell
 LibTest/async/Future/Future.delayed_A03_t01: fail # Issue 7728, timer not supported in jsshell
 LibTest/async/Future/wait_A01_t07: RuntimeError # Issue 7728, timer not supported in jsshell
@@ -350,10 +347,8 @@
 LibTest/core/int/toRadixString_A01_t01: RuntimeError, OK # Bad test: uses Expect.fail, Expect.throws, assumes case of result, and uses unsupported radixes.
 
 [ $compiler == dart2js && $runtime == d8 ]
-LibTest/math/sin_A01_t02: RuntimeError # V8 issue 3006, https://code.google.com/p/v8/issues/detail?id=3006
 LibTest/typed_data/Float32x4List/Float32x4List.view_A06_t01: fail # co19-roll r587: Please triage this failure
 Language/12_Expressions/00_Object_Identity/1_Object_Identity_A05_t02: RuntimeError # Issue 21198 (int/double related)
-Language/12_Expressions/17_Getter_Invocation_A07_t02: RuntimeError # Issue 21199
 LibTest/typed_data/Int32x4/operator_OR_A01_t01: RuntimeError # Issue 7728, timer not supported in jsshell
 
 [ $compiler == dart2js && $runtime == d8 && $system == windows ]
@@ -564,7 +559,6 @@
 Language/12_Expressions/00_Object_Identity/1_Object_Identity_A05_t02: RuntimeError # Please triage this failure.
 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_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.
@@ -594,7 +588,6 @@
 
 [ $compiler == dart2js && $runtime == chrome ]
 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
 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
@@ -1577,7 +1570,6 @@
 
 [ $compiler == dart2js && $runtime == ff ]
 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/28_Postfix_Expressions_A07_t02: 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
@@ -3137,7 +3129,6 @@
 
 [ $compiler == dart2js && $runtime == safari ]
 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
 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
@@ -4390,7 +4381,6 @@
 
 [ $compiler == dart2js && $runtime == safarimobilesim ]
 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
 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
@@ -5719,7 +5709,6 @@
 [ $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
@@ -7749,7 +7738,6 @@
 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
@@ -9614,302 +9602,736 @@
 WebPlatformTest/webstorage/storage_session_setitem_t01: RuntimeError # Please triage this failure
 
 [ $compiler == dart2js && $cps_ir ]
-Language/03_Overview/1_Scoping_A01_t39: Crash # Instance of 'TypeOperator': type check unimplemented for f.
-Language/03_Overview/1_Scoping_A02_t19: Crash # (switch (1){case 1:var x;break;case 2:var x;break;}): Unhandled node
-Language/07_Classes/07_Classes_A02_t17: Crash # Please triage this failure.
-Language/07_Classes/07_Classes_A02_t18: Crash # Please triage this failure.
-Language/07_Classes/07_Classes_A02_t19: Crash # Please triage this failure.
-Language/07_Classes/1_Instance_Methods/2_Operators_A02_t06: Crash # Please triage this failure.
-Language/07_Classes/6_Constructors/1_Generative_Constructors_A04_t02: Crash # Please triage this failure.
-Language/07_Classes/6_Constructors/1_Generative_Constructors_A04_t03: Crash # Please triage this failure.
-Language/07_Classes/6_Constructors/1_Generative_Constructors_A04_t05: Crash # Please triage this failure.
-Language/07_Classes/6_Constructors/1_Generative_Constructors_A04_t07: Crash # Please triage this failure.
-Language/07_Classes/6_Constructors/1_Generative_Constructors_A04_t09: Crash # Please triage this failure.
-Language/07_Classes/6_Constructors/1_Generative_Constructors_A04_t10: Crash # Please triage this failure.
-Language/07_Classes/6_Constructors/1_Generative_Constructors_A04_t11: Crash # Please triage this failure.
-Language/07_Classes/6_Constructors/1_Generative_Constructors_A04_t16: Crash # Please triage this failure.
-Language/07_Classes/6_Constructors/2_Factories_A09_t01: Crash # Please triage this failure.
-Language/07_Classes/6_Constructors/2_Factories_A09_t02: Crash # Please triage this failure.
-Language/07_Classes/6_Constructors/2_Factories_A09_t03: Crash # Please triage this failure.
-Language/07_Classes/6_Constructors/2_Factories_A09_t04: Crash # Please triage this failure.
-Language/10_Generics/09_Generics_A04_t03: Crash # Please triage this failure.
+Language/07_Classes/6_Constructors/1_Generative_Constructors_A02_t01: RuntimeError # Please triage this failure.
+Language/12_Expressions/05_Strings/1_String_Interpolation_A01_t12: RuntimeError # Cannot read property 'prototype' of undefined
+Language/12_Expressions/05_Strings/1_String_Interpolation_A02_t02: RuntimeError # Cannot read property 'prototype' of undefined
 Language/12_Expressions/12_Instance_Creation/1_New_A06_t12: RuntimeError # Please triage this failure.
-Language/12_Expressions/13_Property_Extraction_A03_t01: RuntimeError # Please triage this failure.
-Language/12_Expressions/13_Property_Extraction_A03_t02: RuntimeError # Please triage this failure.
-Language/12_Expressions/13_Property_Extraction_A03_t03: RuntimeError # Please triage this failure.
-Language/12_Expressions/15_Method_Invocation/4_Super_Invocation_A01_t01: RuntimeError # Please triage this failure.
-Language/12_Expressions/22_Equality_A03_t01: RuntimeError # Please triage this failure.
+Language/12_Expressions/12_Instance_Creation/1_New_A08_t01: RuntimeError # Please triage this failure.
+Language/12_Expressions/12_Instance_Creation/1_New_A08_t02: RuntimeError # Please triage this failure.
+Language/12_Expressions/12_Instance_Creation/1_New_A08_t03: RuntimeError # Please triage this failure.
+Language/12_Expressions/13_Property_Extraction_A01_t01: RuntimeError # Cannot read property 'prototype' of undefined
+Language/12_Expressions/13_Property_Extraction_A01_t02: RuntimeError # Cannot read property 'prototype' of undefined
+Language/12_Expressions/13_Property_Extraction_A01_t03: RuntimeError # Cannot read property 'prototype' of undefined
+Language/12_Expressions/13_Property_Extraction_A03_t01: RuntimeError # Cannot read property 'call' of undefined
+Language/12_Expressions/13_Property_Extraction_A03_t02: RuntimeError # Cannot read property 'call' of undefined
+Language/12_Expressions/13_Property_Extraction_A03_t03: RuntimeError # Cannot read property 'call' of undefined
+Language/12_Expressions/13_Spawning_an_Isolate_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+Language/12_Expressions/14_Function_Invocation/4_Function_Expression_Invocation_A01_t02: RuntimeError # Please triage this failure.
+Language/12_Expressions/15_Method_Invocation/1_Ordinary_Invocation_A05_t04: RuntimeError # Cannot read property 'prototype' of undefined
+Language/12_Expressions/15_Method_Invocation/3_Static_Invocation_A04_t05: RuntimeError # Cannot read property 'prototype' of undefined
+Language/12_Expressions/15_Method_Invocation/4_Super_Invocation_A01_t01: RuntimeError # Cannot read property 'call' of undefined
+Language/12_Expressions/15_Method_Invocation/4_Super_Invocation_A03_t04: RuntimeError # Cannot read property 'prototype' of undefined
+Language/12_Expressions/18_Assignment_A05_t02: RuntimeError # Please triage this failure.
+Language/12_Expressions/18_Assignment_A05_t05: RuntimeError # Please triage this failure.
+Language/12_Expressions/26_Multiplicative_Expressions_A02_t01: RuntimeError # Please triage this failure.
+Language/12_Expressions/26_Multiplicative_Expressions_A03_t01: RuntimeError # Please triage this failure.
+Language/12_Expressions/28_Postfix_Expressions_A05_t02: RuntimeError # Please triage this failure.
+Language/12_Expressions/28_Postfix_Expressions_A09_t02: RuntimeError # Please triage this failure.
+Language/12_Expressions/29_Assignable_Expressions_A01_t08: RuntimeError # receiver.get$_first is not a function
 Language/12_Expressions/30_Identifier_Reference_A09_t03: Crash # (i=0): For-loop variable captured in loop header
-Language/12_Expressions/33_Type_Cast_A01_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
-Language/12_Expressions/33_Type_Cast_A01_t04: Crash # Instance of 'TypeOperator': type casts not implemented.
-Language/12_Expressions/33_Type_Cast_A02_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
-Language/12_Expressions/33_Type_Cast_A02_t02: Crash # Instance of 'TypeOperator': type casts not implemented.
-Language/12_Expressions/33_Type_Cast_A02_t03: Crash # Instance of 'TypeOperator': type casts not implemented.
-Language/12_Expressions/33_Type_Cast_A02_t06: Crash # Instance of 'TypeOperator': type casts not implemented.
-Language/12_Expressions/33_Type_Cast_A02_t07: Crash # Instance of 'TypeOperator': type casts not implemented.
-Language/12_Expressions/33_Type_Cast_A02_t08: Crash # Instance of 'TypeOperator': type casts not implemented.
-Language/12_Expressions/33_Type_Cast_A02_t09: Crash # Instance of 'TypeOperator': type casts not implemented.
-Language/12_Expressions/33_Type_Cast_A04_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
-Language/12_Expressions/33_Type_Cast_A04_t02: Crash # Instance of 'TypeOperator': type casts not implemented.
-Language/12_Expressions/Expressions_A01_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
-Language/12_Expressions/Expressions_A01_t02: Crash # Instance of 'TypeOperator': type casts not implemented.
-Language/13_Statements/06_For_A01_t07: Crash # Please triage this failure.
-Language/13_Statements/09_Switch_A01_t01: Crash # (switch (1){case 0:case 1:}): Unhandled node
-Language/13_Statements/09_Switch_A01_t02: Crash # (switch (1){l1:l2:l3:case (1):}): Unhandled node
-Language/13_Statements/09_Switch_A01_t03: Crash #  Unhandled node
-Language/13_Statements/09_Switch_A01_t19: Crash # (switch (1){case 0:break;label:print("hello");}): Unhandled node
-Language/13_Statements/09_Switch_A02_t03: Crash # (switch (null){case null:}): Unhandled node
-Language/13_Statements/09_Switch_A05_t01: Crash # (switch ('abc'){case 1:break;}): Unhandled node
-Language/13_Statements/09_Switch_A05_t02: Crash # (switch (p){default:return 1;}): Unhandled node
-Language/13_Statements/09_Switch_A06_t01: Crash # (switch (p){case 1:var x=2;return x;case 2:var x=4;return x;}): Unhandled node
-Language/13_Statements/09_Switch_A06_t02: Crash # (switch (2){case 1:var x=2;break;case 2:x++ ;}): Unhandled node
-Language/13_Statements/09_Switch_A07_t01: Crash #  Unhandled node
-Language/13_Statements/09_Switch_A07_t02: Crash #  Unhandled node
-Language/13_Statements/09_Switch_A08_t01: Crash #  Unhandled node
-Language/13_Statements/09_Switch_A08_t02: Crash # (switch (value){case 1:case 2:result=1;case 3:case 4:result=2;break;case 5:case 6:}): Unhandled node
-Language/13_Statements/09_Switch_A09_t01: Crash # (switch (false){case 0:case 1:}): Unhandled node
-Language/13_Statements/09_Switch_A10_t01: Crash # (switch (1){case 0:false;case 1:true;break;}): Unhandled node
-Language/13_Statements/09_Switch_A10_t02: Crash # (switch (1){case 0:false;break;case 1:true;}): Unhandled node
-Language/13_Statements/09_Switch_A10_t03: Crash # (switch (1){case 0:false;break;default:true;}): Unhandled node
-Language/13_Statements/11_Return_A02_t02: Crash # (try {return 1;}finally {flag=true;}): try/finally
-Language/13_Statements/11_Return_A02_t03: Crash # (try {return 1;}finally {return 2;}): try/finally
-Language/13_Statements/11_Try_A01_t01: Crash # (try {throw "";}on int catch (ok){}catch (ok){}finally {}): try/finally
-Language/13_Statements/11_Try_A07_t02: Crash # (try {throw ex;}on int catch (i){}on bool catch (b){}finally {isFinallyExecuted=true;}): try/finally
-Language/13_Statements/11_Try_A08_t01: Crash #  try/finally
-Language/13_Statements/11_Try_A09_t01: Crash #  try/finally
-Language/13_Statements/11_Try_A10_t01: Crash #  try/finally
-Language/13_Statements/11_Try_A11_t01: Crash #  try/finally
-Language/13_Statements/11_Try_A11_t02: Crash #  try/finally
-Language/13_Statements/11_Try_A11_t03: Crash # (try {throw 42;}finally {return true;}): try/finally
-Language/13_Statements/11_Try_A11_t04: Crash # (try {throw 42;}finally {throw true;}): try/finally
-Language/13_Statements/11_Try_A12_t01: Crash #  try/finally
-Language/13_Statements/12_Labels_A01_t01: Crash # (switch (1){K:case 2:L:case 1:break;case 0:M:default:N:var x=0;}): Unhandled node
-Language/13_Statements/12_Labels_A03_t04: Crash # (switch (i){L:case 0:flag=true;break;case 2:continue L;}): Unhandled node
-Language/13_Statements/12_Labels_A03_t06: Crash # (switch (1){Label:case 1:break;default:break;}): Unhandled node
-Language/13_Statements/13_Break_A03_t01: Crash #  try/finally
-Language/13_Statements/13_Break_A03_t02: Crash #  try/finally
-Language/13_Statements/13_Break_A03_t03: Crash #  try/finally
-Language/13_Statements/13_Break_A03_t04: Crash #  try/finally
-Language/13_Statements/13_Break_A03_t05: Crash # (switch (1){case 0:break;case 1:break L;}): Unhandled node
-Language/13_Statements/13_Break_A03_t06: Crash #  try/finally
-Language/13_Statements/13_Break_A03_t07: Crash #  Unhandled node
-Language/13_Statements/13_Break_A03_t08: Crash # (try {try {break;}finally {order.add(2);}}finally {order.add(1);}): try/finally
-Language/13_Statements/13_Break_A03_t09: Crash #  try/finally
-Language/13_Statements/14_Continue_A02_t12: Crash # (switch (2){L:case 1:flag=true;break;case 2:continue L;}): Unhandled node
-Language/13_Statements/14_Continue_A02_t13: Crash # (switch (2){case 2:continue L;L:case 1:flag=true;}): Unhandled node
-Language/13_Statements/14_Continue_A03_t01: Crash #  try/finally
-Language/13_Statements/14_Continue_A03_t02: Crash #  try/finally
-Language/13_Statements/14_Continue_A03_t03: Crash #  try/finally
-Language/13_Statements/14_Continue_A03_t04: Crash #  try/finally
-Language/13_Statements/14_Continue_A03_t05: Crash #  Unhandled node
-Language/13_Statements/14_Continue_A03_t06: Crash #  try/finally
-Language/13_Statements/14_Continue_A03_t07: Crash #  try/finally
-Language/14_Libraries_and_Scripts/13_Libraries_and_Scripts_A05_t02: Crash # Instance of 'TypeOperator': type check unimplemented for _td.
-Language/14_Libraries_and_Scripts/1_Imports_A02_t26: Crash # Instance of 'TypeOperator': type check unimplemented for prefix.
-Language/14_Libraries_and_Scripts/1_Imports_A02_t27: Crash # Instance of 'TypeOperator': type check unimplemented for bar.
-Language/14_Libraries_and_Scripts/1_Imports_A02_t28: Crash # Instance of 'TypeOperator': type check unimplemented for bar.
-Language/14_Libraries_and_Scripts/1_Imports_A03_t04: Crash # Instance of 'TypeOperator': type casts not implemented.
-Language/14_Libraries_and_Scripts/1_Imports_A03_t24: Crash # Instance of 'TypeOperator': type casts not implemented.
-Language/14_Libraries_and_Scripts/1_Imports_A03_t44: Crash # Instance of 'TypeOperator': type casts not implemented.
-Language/14_Libraries_and_Scripts/1_Imports_A03_t45: Crash # Instance of 'TypeOperator': type casts not implemented.
-Language/14_Libraries_and_Scripts/1_Imports_A03_t64: Crash # Instance of 'TypeOperator': type casts not implemented.
-Language/14_Libraries_and_Scripts/1_Imports_A03_t65: Crash # Instance of 'TypeOperator': type casts not implemented.
-Language/14_Libraries_and_Scripts/2_Exports_A06_t02: Crash # Instance of 'TypeOperator': type check unimplemented for foo.
-Language/15_Types/3_Type_Declarations/1_Typedef_A01_t03: Crash # Instance of 'TypeOperator': type check unimplemented for f.
-Language/15_Types/3_Type_Declarations/1_Typedef_A02_t01: Crash # Instance of 'TypeOperator': type check unimplemented for f_t.
-Language/15_Types/3_Type_Declarations/1_Typedef_A02_t02: Crash # Instance of 'TypeOperator': type check unimplemented for f_t.
-Language/15_Types/3_Type_Declarations/1_Typedef_A02_t03: Crash # Instance of 'TypeOperator': type check unimplemented for f_t.
-Language/15_Types/3_Type_Declarations/1_Typedef_A03_t01: Crash # Instance of 'TypeOperator': type check unimplemented for f1.
-Language/15_Types/3_Type_Declarations/1_Typedef_A04_t01: Crash # Instance of 'TypeOperator': type check unimplemented for f1.
-Language/15_Types/3_Type_Declarations/1_Typedef_A04_t02: Crash # Instance of 'TypeOperator': type check unimplemented for f1.
-Language/15_Types/3_Type_Declarations/1_Typedef_A07_t05: Crash # Instance of 'TypeOperator': type check unimplemented for f.
-Language/15_Types/3_Type_Declarations/1_Typedef_A07_t06: Crash # Instance of 'TypeOperator': type check unimplemented for f.
-Language/15_Types/3_Type_Declarations/1_Typedef_A07_t07: Crash # Instance of 'TypeOperator': type check unimplemented for f.
-Language/15_Types/4_Interface_Types_A05_t04: Crash # type expression t1 (typedef)
-Language/15_Types/4_Interface_Types_A10_t04: Crash # type expression param1 (typedef)
-Language/15_Types/4_Interface_Types_A10_t06: Crash # type expression f (typedef)
-Language/15_Types/4_Interface_Types_A10_t07: Crash # type expression f_1 (typedef)
-Language/15_Types/4_Interface_Types_A10_t08: Crash # type expression t1 (typedef)
-Language/15_Types/4_Interface_Types_A10_t09: Crash # type expression param1 (typedef)
-Language/15_Types/4_Interface_Types_A12_t18: Crash # Instance of 'TypeOperator': type check unimplemented for F1.
-Language/15_Types/5_Function_Types_A01_t01: Crash # Instance of 'TypeOperator': type check unimplemented for check_t.
-Language/15_Types/5_Function_Types_A01_t02: Crash # Instance of 'TypeOperator': type check unimplemented for t1.
-Language/15_Types/5_Function_Types_A01_t03: Crash # Instance of 'TypeOperator': type check unimplemented for returnsDynamic.
-Language/15_Types/5_Function_Types_A01_t04: Crash # Instance of 'TypeOperator': type check unimplemented for t8.
-Language/15_Types/5_Function_Types_A01_t05: Crash # Instance of 'TypeOperator': type check unimplemented for t1.
-Language/15_Types/5_Function_Types_A01_t06: Crash # Instance of 'TypeOperator': type check unimplemented for classesFunc.
-Language/15_Types/5_Function_Types_A01_t07: Crash # Instance of 'TypeOperator': type check unimplemented for f.
-Language/15_Types/5_Function_Types_A01_t08: Crash # Instance of 'TypeOperator': type check unimplemented for t1.
-Language/15_Types/5_Function_Types_A01_t09: Crash # Instance of 'TypeOperator': type check unimplemented for t1.
-Language/15_Types/5_Function_Types_A01_t11: Crash # Instance of 'TypeOperator': type check unimplemented for t1.
-Language/15_Types/5_Function_Types_A02_t01: Crash # Instance of 'TypeOperator': type check unimplemented for t1.
-Language/15_Types/5_Function_Types_A02_t02: Crash # Instance of 'TypeOperator': type check unimplemented for classesFunc.
-Language/15_Types/5_Function_Types_A02_t03: Crash # Instance of 'TypeOperator': type check unimplemented for classesFunc.
-Language/15_Types/5_Function_Types_A02_t04: Crash # Instance of 'TypeOperator': type check unimplemented for t1.
-Language/15_Types/5_Function_Types_A02_t05: Crash # Instance of 'TypeOperator': type check unimplemented for t1.
-Language/15_Types/5_Function_Types_A02_t06: Crash # Instance of 'TypeOperator': type check unimplemented for t1.
-Language/15_Types/5_Function_Types_A02_t07: Crash # Instance of 'TypeOperator': type check unimplemented for t1.
-Language/15_Types/5_Function_Types_A02_t08: Crash # Instance of 'TypeOperator': type check unimplemented for t2.
-Language/15_Types/5_Function_Types_A02_t09: Crash # Instance of 'TypeOperator': type check unimplemented for t1.
-Language/15_Types/5_Function_Types_A02_t10: Crash # Instance of 'TypeOperator': type check unimplemented for t1.
-Language/15_Types/5_Function_Types_A02_t11: Crash # Instance of 'TypeOperator': type check unimplemented for t1.
-Language/15_Types/5_Function_Types_A02_t12: Crash # Instance of 'TypeOperator': type check unimplemented for t1.
-Language/15_Types/5_Function_Types_A03_t01: Crash # Instance of 'TypeOperator': type check unimplemented for t1.
-Language/15_Types/5_Function_Types_A03_t02: Crash # Instance of 'TypeOperator': type check unimplemented for classesFunc.
-Language/15_Types/5_Function_Types_A03_t03: Crash # Instance of 'TypeOperator': type check unimplemented for classesFunc.
-Language/15_Types/5_Function_Types_A03_t04: Crash # Instance of 'TypeOperator': type check unimplemented for t1.
-Language/15_Types/5_Function_Types_A03_t06: Crash # Instance of 'TypeOperator': type check unimplemented for t1.
-Language/15_Types/5_Function_Types_A03_t07: Crash # Instance of 'TypeOperator': type check unimplemented for t1.
-Language/15_Types/5_Function_Types_A03_t08: Crash # Instance of 'TypeOperator': type check unimplemented for t1.
-Language/15_Types/5_Function_Types_A03_t09: Crash # Instance of 'TypeOperator': type check unimplemented for t1.
-Language/15_Types/5_Function_Types_A03_t10: Crash # Instance of 'TypeOperator': type check unimplemented for t1.
-Language/15_Types/5_Function_Types_A03_t11: Crash # Instance of 'TypeOperator': type check unimplemented for t1.
-Language/15_Types/5_Function_Types_A03_t12: Crash # Instance of 'TypeOperator': type check unimplemented for classesFunc.
-Language/15_Types/5_Function_Types_A03_t13: Crash # Instance of 'TypeOperator': type check unimplemented for t1.
-Language/15_Types/5_Function_Types_A06_t01: Crash # Instance of 'TypeOperator': type check unimplemented for f.
-LayoutTests/fast/backgrounds/multiple-backgrounds-computed-style_t01: Crash #  Unhandled node
-LayoutTests/fast/canvas/webgl/compressed-tex-image_t01: Crash # Please triage this failure.
-LayoutTests/fast/canvas/webgl/framebuffer-object-attachment_t01: Crash # Please triage this failure.
-LayoutTests/fast/canvas/webgl/gl-uniformmatrix4fv_t01: Crash #  Unhandled node
-LayoutTests/fast/canvas/webgl/index-validation_t01: Crash #  Unhandled node
-LayoutTests/fast/canvas/webgl/oes-element-index-uint_t01: Crash #  Unhandled node
-LayoutTests/fast/canvas/webgl/read-pixels-pack-alignment_t01: Crash #  Unhandled node
-LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-array-buffer-view_t01: Crash #  Unhandled node
-LayoutTests/fast/css/css-keyframe-style-crash_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
-LayoutTests/fast/css/first-line-parent-style-different_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
-LayoutTests/fast/css/media-rule-dyn_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
-LayoutTests/fast/css/parsing-css-allowed-string-characters_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
-LayoutTests/fast/css/parsing-css-comment_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
-LayoutTests/fast/css/parsing-css-escapes_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
-LayoutTests/fast/css/parsing-css-nonascii_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
-LayoutTests/fast/css/parsing-css-nth-child_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
-LayoutTests/fast/css/parsing-css-surrogate-pairs_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
-LayoutTests/fast/css/pseudo-out-of-range_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
-LayoutTests/fast/css/pseudo-valid-dynamic_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
-LayoutTests/fast/css/readonly-pseudoclass-opera-005_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
-LayoutTests/fast/css/visited-link-hang_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
-LayoutTests/fast/dom/location-hash_t01: Crash #  Unhandled node
-LayoutTests/fast/dynamic/inline-to-block-crash_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
-LayoutTests/fast/encoding/css-charset-dom_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
-LayoutTests/fast/events/event-attributes-after-exception_t01: Crash #  try/finally
-LayoutTests/fast/files/file-reader-methods-illegal-arguments_t01: Crash #  Unhandled node
-LayoutTests/fast/forms/autofocus-focus-only-once_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
-LayoutTests/fast/forms/datalist/datalist-child-validation_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
-LayoutTests/fast/forms/datalist/datalist_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
-LayoutTests/fast/forms/date/date-interactive-validation-required_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
-LayoutTests/fast/forms/date/date-pseudo-classes_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
-LayoutTests/fast/forms/datetimelocal/datetimelocal-interactive-validation-required_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
-LayoutTests/fast/forms/datetimelocal/datetimelocal-pseudo-classes_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
-LayoutTests/fast/forms/fieldset/fieldset-elements_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
-LayoutTests/fast/forms/search-popup-crasher_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
-LayoutTests/fast/loader/hashchange-event-properties_t01: Crash #  Unhandled node
-LayoutTests/fast/media/media-query-list-syntax_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
-LayoutTests/fast/mediastream/getusermedia_t01: Crash # Please triage this failure.
-LayoutTests/fast/multicol/hit-test-above-or-below_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
-LayoutTests/fast/parser/parse-wbr_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
-LayoutTests/fast/replaced/table-replaced-element_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
-LayoutTests/fast/selectors/style-sharing-last-child_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
-LayoutTests/fast/svg/getbbox_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
-LayoutTests/fast/svg/tabindex-focus_t01: Crash #  try/finally
-LayoutTests/fast/svg/whitespace-angle_t01: Crash #  try/finally
-LayoutTests/fast/svg/whitespace-integer_t01: Crash #  try/finally
-LayoutTests/fast/svg/whitespace-length-invalid_t01: Crash #  try/finally
-LayoutTests/fast/svg/whitespace-length_t01: Crash #  try/finally
-LayoutTests/fast/svg/whitespace-number_t01: Crash #  try/finally
-LayoutTests/fast/table/hittest-tablecell-bottom-edge_t01: Crash #  Unhandled node
-LayoutTests/fast/table/hittest-tablecell-right-edge_t01: Crash #  Unhandled node
-LayoutTests/fast/table/hittest-tablecell-with-borders-bottom-edge_t01: Crash #  Unhandled node
-LayoutTests/fast/table/hittest-tablecell-with-borders-right-edge_t01: Crash #  Unhandled node
-LayoutTests/fast/table/incorrect-colgroup-span-values_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
-LayoutTests/fast/table/rowindex-comment-nodes_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
-LayoutTests/fast/text/font-ligature-letter-spacing_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
-LayoutTests/fast/url/anchor_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
-LayoutTests/fast/url/file-http-base_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
-LayoutTests/fast/url/file_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
-LayoutTests/fast/url/host-lowercase-per-scheme_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
-LayoutTests/fast/url/host_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
-LayoutTests/fast/url/idna2003_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
-LayoutTests/fast/url/idna2008_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
-LayoutTests/fast/url/invalid-urls-utf8_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
-LayoutTests/fast/url/ipv4_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
-LayoutTests/fast/url/ipv6_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
-LayoutTests/fast/url/mailto_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
-LayoutTests/fast/url/path-url_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
-LayoutTests/fast/url/path_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
-LayoutTests/fast/url/port_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
-LayoutTests/fast/url/query_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
-LayoutTests/fast/url/relative-unix_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
-LayoutTests/fast/url/relative-win_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
-LayoutTests/fast/url/relative_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
-LayoutTests/fast/url/safari-extension_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
-LayoutTests/fast/url/scheme_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
-LayoutTests/fast/url/segments-from-data-url_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
-LayoutTests/fast/url/segments_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
-LayoutTests/fast/url/standard-url_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
-LayoutTests/fast/url/trivial-segments_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
-LayoutTests/fast/url/trivial_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
-LayoutTests/fast/xpath/name-null-namespace_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
-LayoutTests/fast/xsl/default-html_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
-LayoutTests/fast/xsl/extra-lf-at-end_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
-LibTest/async/DeferredLibrary/DeferredLibrary_A01_t01: RuntimeError # Please triage this failure.
-LibTest/async/Stream/Stream.periodic_A01_t01: Crash # Please triage this failure.
-LibTest/async/Stream/drain_A01_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
-LibTest/async/Stream/drain_A02_t01: Crash # Please triage this failure.
-LibTest/async/Stream/elementAt_A02_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
-LibTest/async/Stream/handleError_A01_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
-LibTest/async/Stream/handleError_A03_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
-LibTest/async/Stream/listen_A03_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
-LibTest/async/Stream/listen_A04_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
-LibTest/async/Stream/take_A01_t02: Crash # Instance of 'TypeOperator': type casts not implemented.
-LibTest/async/Zone/registerBinaryCallback_A01_t01: Crash # Instance of 'TypeOperator': type check unimplemented for ZoneBinaryCallback.
-LibTest/async/Zone/registerCallback_A01_t01: Crash # Instance of 'TypeOperator': type check unimplemented for ZoneCallback.
-LibTest/async/Zone/registerUnaryCallback_A01_t01: Crash # Instance of 'TypeOperator': type check unimplemented for ZoneUnaryCallback.
-LibTest/collection/ListBase/ListBase_class_A01_t02: Crash # Please triage this failure.
-LibTest/collection/ListMixin/ListMixin_class_A01_t02: Crash # Please triage this failure.
-LibTest/core/FallThroughError/toString_A01_t02: Crash #  Unhandled node
-LibTest/core/Invocation/isAccessor_A01_t01: Crash # Please triage this failure.
+Language/12_Expressions/30_Identifier_Reference_A09_t04: RuntimeError # Please triage this failure.
+Language/12_Expressions/30_Identifier_Reference_A10_t01: RuntimeError # Cannot read property 'prototype' of undefined
+Language/12_Expressions/30_Identifier_Reference_A10_t02: RuntimeError # Cannot read property 'prototype' of undefined
+Language/13_Statements/02_Expression_Statements_A01_t06: RuntimeError # Cannot read property 'prototype' of undefined
+Language/13_Statements/06_For/1_For_Loop_A01_t09: RuntimeError # Please triage this failure.
+Language/13_Statements/06_For_A01_t07: Crash # unsupported operation on erroneous element
+Language/13_Statements/12_Labels_A03_t04: Crash # (switch (i){L:case 0:flag=true;break;case 2:continue L;}): continue to a labeled switch case
+Language/13_Statements/13_Break_A03_t01: RuntimeError # Issue 23708.
+Language/13_Statements/13_Break_A03_t03: RuntimeError # Issue 23708.
+Language/13_Statements/13_Break_A03_t04: RuntimeError # Please triage this failure.
+Language/13_Statements/13_Break_A03_t06: RuntimeError # Issue 23708.
+Language/13_Statements/13_Break_A03_t07: RuntimeError # Please triage this failure.
+Language/13_Statements/13_Break_A03_t08: RuntimeError # Please triage this failure.
+Language/13_Statements/13_Break_A03_t09: RuntimeError # Issue 23708.
+Language/13_Statements/14_Continue_A02_t12: Crash # (switch (2){L:case 1:flag=true;break;case 2:continue L;}): continue to a labeled switch case
+Language/13_Statements/14_Continue_A02_t13: Crash # (switch (2){case 2:continue L;L:case 1:flag=true;}): continue to a labeled switch case
+Language/13_Statements/14_Continue_A03_t01: RuntimeError # Issue 23708.
+Language/13_Statements/14_Continue_A03_t02: RuntimeError # Please triage this failure.
+Language/13_Statements/14_Continue_A03_t03: RuntimeError # Please triage this failure.
+Language/13_Statements/14_Continue_A03_t04: RuntimeError # Issue 23708.
+Language/13_Statements/14_Continue_A03_t05: RuntimeError # Please triage this failure.
+Language/13_Statements/14_Continue_A03_t06: RuntimeError # Issue 23708.
+Language/13_Statements/14_Continue_A03_t07: RuntimeError # Issue 23708.
+Language/14_Libraries_and_Scripts/1_Imports_A02_t06: RuntimeError # Please triage this failure.
+Language/14_Libraries_and_Scripts/4_Scripts_A03_t03: RuntimeError # receiver.get$_collection$_nums is not a function
+Language/15_Types/3_Type_Declarations/1_Typedef_A02_t01: RuntimeError # Cannot read property 'prototype' of undefined
+Language/15_Types/3_Type_Declarations/1_Typedef_A02_t02: RuntimeError # Cannot read property 'prototype' of undefined
+Language/15_Types/3_Type_Declarations/1_Typedef_A02_t03: RuntimeError # Cannot read property 'prototype' of undefined
+Language/15_Types/3_Type_Declarations/1_Typedef_A03_t01: RuntimeError # Cannot read property 'prototype' of undefined
+Language/15_Types/3_Type_Declarations/1_Typedef_A04_t02: RuntimeError # Cannot read property 'prototype' of undefined
+Language/15_Types/4_Interface_Types_A12_t18: RuntimeError # Cannot read property 'prototype' of undefined
+Language/15_Types/5_Function_Types_A01_t01: RuntimeError # Cannot read property 'prototype' of undefined
+Language/15_Types/5_Function_Types_A01_t03: RuntimeError # Cannot read property 'prototype' of undefined
+Language/15_Types/5_Function_Types_A01_t04: RuntimeError # Cannot read property 'prototype' of undefined
+Language/15_Types/5_Function_Types_A01_t05: RuntimeError # Cannot read property 'prototype' of undefined
+Language/15_Types/5_Function_Types_A01_t06: RuntimeError # Cannot read property 'prototype' of undefined
+Language/15_Types/5_Function_Types_A01_t08: RuntimeError # Cannot read property 'prototype' of undefined
+Language/15_Types/5_Function_Types_A01_t09: RuntimeError # Cannot read property 'prototype' of undefined
+Language/15_Types/5_Function_Types_A01_t11: RuntimeError # Cannot read property 'prototype' of undefined
+Language/15_Types/5_Function_Types_A02_t01: RuntimeError # Cannot read property 'prototype' of undefined
+Language/15_Types/5_Function_Types_A02_t02: RuntimeError # Cannot read property 'prototype' of undefined
+Language/15_Types/5_Function_Types_A02_t03: RuntimeError # Cannot read property 'prototype' of undefined
+Language/15_Types/5_Function_Types_A02_t04: RuntimeError # Cannot read property 'prototype' of undefined
+Language/15_Types/5_Function_Types_A02_t05: RuntimeError # Cannot read property 'prototype' of undefined
+Language/15_Types/5_Function_Types_A02_t09: RuntimeError # Cannot read property 'prototype' of undefined
+Language/15_Types/5_Function_Types_A02_t10: RuntimeError # Cannot read property 'prototype' of undefined
+Language/15_Types/5_Function_Types_A03_t01: RuntimeError # Cannot read property 'prototype' of undefined
+Language/15_Types/5_Function_Types_A03_t02: RuntimeError # Cannot read property 'prototype' of undefined
+Language/15_Types/5_Function_Types_A03_t03: RuntimeError # Cannot read property 'prototype' of undefined
+Language/15_Types/5_Function_Types_A03_t04: RuntimeError # Cannot read property 'prototype' of undefined
+Language/15_Types/5_Function_Types_A03_t06: RuntimeError # Cannot read property 'prototype' of undefined
+Language/15_Types/5_Function_Types_A03_t08: RuntimeError # Cannot read property 'prototype' of undefined
+Language/15_Types/5_Function_Types_A03_t09: RuntimeError # Cannot read property 'prototype' of undefined
+Language/15_Types/5_Function_Types_A03_t10: RuntimeError # Cannot read property 'prototype' of undefined
+Language/15_Types/5_Function_Types_A03_t11: RuntimeError # Cannot read property 'prototype' of undefined
+Language/15_Types/5_Function_Types_A03_t12: RuntimeError # Cannot read property 'prototype' of undefined
+Language/15_Types/5_Function_Types_A03_t13: RuntimeError # Cannot read property 'prototype' of undefined
+Language/15_Types/5_Function_Types_A05_t02: RuntimeError # Cannot read property 'prototype' of undefined
+Language/15_Types/5_Function_Types_A05_t05: RuntimeError # Cannot read property 'prototype' of undefined
+Language/15_Types/5_Function_Types_A06_t01: RuntimeError # Cannot read property 'prototype' of undefined
+Language/16_Reference/1_Lexical_Rules/2_Comments_A02_t10: RuntimeError # Please triage this failure.
+LayoutTests/fast/canvas/webgl/compressed-tex-image_t01: Crash # Invalid argument(s)
+LayoutTests/fast/canvas/webgl/framebuffer-object-attachment_t01: Crash # Invalid argument(s)
+LayoutTests/fast/events/clipboard-dataTransferItemList_t01: Crash # Internal Error: No default constructor available.
+LayoutTests/fast/forms/date/date-interactive-validation-required_t01: Crash # Invalid argument(s)
+LayoutTests/fast/forms/datetimelocal/datetimelocal-interactive-validation-required_t01: Crash # Invalid argument(s)
+LibTest/async/Completer/Completer.sync_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Completer/completeError_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Completer/completeError_A01_t02: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Completer/completeError_A01_t03: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Completer/completeError_A01_t04: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Completer/completeError_A03_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Completer/completeError_A03_t02: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Completer/complete_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Completer/complete_A01_t02: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Completer/complete_A01_t03: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Completer/complete_A01_t04: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Completer/complete_A01_t05: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Completer/complete_A01_t06: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Completer/complete_A02_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Completer/complete_A02_t02: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Completer/isCompleted_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/DeferredLibrary/DeferredLibrary_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Future/Future.delayed_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Future/Future.delayed_A02_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Future/Future.delayed_A03_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Future/Future.error_A01_t02: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Future/Future.microtask_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Future/Future.microtask_A01_t02: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Future/Future.microtask_A01_t03: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Future/Future.microtask_A01_t04: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Future/Future.sync_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Future/Future.sync_A01_t02: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Future/Future.sync_A01_t03: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Future/Future.sync_A01_t04: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Future/Future.value_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Future/Future.value_A01_t02: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Future/Future_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Future/Future_A01_t02: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Future/Future_A01_t03: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Future/Future_A01_t04: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Future/asStream_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Future/asStream_A01_t02: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Future/asStream_A02_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Future/asStream_A02_t02: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Future/catchError_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Future/catchError_A01_t02: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Future/catchError_A02_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Future/catchError_A03_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Future/catchError_A03_t02: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Future/catchError_A03_t03: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Future/catchError_A03_t04: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Future/catchError_A03_t05: RuntimeError # receiver.get$_nums is not a function
+LibTest/async/Future/forEach_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Future/forEach_A02_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Future/forEach_A03_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Future/then_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Future/then_A01_t02: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Future/then_A01_t03: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Future/then_A01_t04: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Future/then_A02_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Future/then_A03_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Future/then_A03_t02: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Future/then_A04_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Future/then_A05_t01: RuntimeError # receiver.get$_nums is not a function
+LibTest/async/Future/then_A05_t02: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Future/then_A05_t03: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Future/wait_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Future/wait_A01_t03: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Future/wait_A01_t04: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Future/wait_A01_t05: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Future/wait_A01_t06: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Future/wait_A01_t07: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Future/wait_A02_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Future/wait_A02_t02: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Future/whenComplete_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Future/whenComplete_A02_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Future/whenComplete_A03_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Future/whenComplete_A04_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Future/whenComplete_A04_t02: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/Stream.eventTransformed_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/Stream.eventTransformed_A01_t02: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/Stream.fromFuture_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/Stream.fromFuture_A02_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/Stream.fromFuture_A02_t02: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/Stream.fromIterable_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/Stream.fromIterable_A01_t02: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/Stream.fromIterable_A02_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/Stream.periodic_A01_t01: Crash # Invalid argument(s)
+LibTest/async/Stream/Stream.periodic_A02_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/Stream.periodic_A03_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/Stream_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/any_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/any_A01_t02: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/any_A02_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/asBroadcastStream_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/asBroadcastStream_A01_t02: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/asBroadcastStream_A01_t03: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/asBroadcastStream_A01_t04: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/asBroadcastStream_A03_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/asBroadcastStream_A03_t02: RuntimeError # receiver.get$_nums is not a function
+LibTest/async/Stream/asBroadcastStream_A03_t03: RuntimeError # receiver.get$_nums is not a function
+LibTest/async/Stream/asBroadcastStream_A04_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/asBroadcastStream_A04_t02: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/asBroadcastStream_A04_t03: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/contains_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/contains_A02_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/contains_A03_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/distinct_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/distinct_A01_t02: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/drain_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/drain_A02_t01: Crash # Invalid argument(s)
+LibTest/async/Stream/drain_A02_t02: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/elementAt_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/elementAt_A01_t02: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/elementAt_A02_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/elementAt_A03_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/every_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/every_A02_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/expand_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/firstWhere_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/firstWhere_A02_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/firstWhere_A03_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/firstWhere_A03_t02: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/first_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/first_A02_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/first_A02_t02: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/first_A03_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/fold_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/fold_A01_t02: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/forEach_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/forEach_A02_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/forEach_A02_t02: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/handleError_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/handleError_A02_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/handleError_A03_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/handleError_A04_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/handleError_A04_t02: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/handleError_A04_t03: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/isBroadcast_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/isBroadcast_A01_t02: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/isEmpty_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/join_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/join_A01_t02: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/join_A02_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/join_A02_t02: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/lastWhere_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/lastWhere_A02_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/lastWhere_A03_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/lastWhere_A04_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/last_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/last_A02_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/last_A03_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/length_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/listen_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/listen_A02_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/listen_A03_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/listen_A04_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/listen_A05_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/listen_A05_t02: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/listen_A05_t03: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/listen_A06_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/map_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/pipe_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/reduce_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/reduce_A01_t02: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/reduce_A01_t03: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/singleWhere_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/singleWhere_A02_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/single_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/single_A02_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/skipWhile_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/skip_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/takeWhile_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/take_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/take_A01_t02: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/take_A01_t03: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/toList_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/toSet_A01_t01: RuntimeError # receiver.get$_nums is not a function
+LibTest/async/Stream/transform_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/transform_A01_t02: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Stream/where_A01_t01: RuntimeError # receiver.get$_nums is not a function
+LibTest/async/Stream/where_A01_t02: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/StreamController/StreamController.broadcast_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/StreamController/StreamController.broadcast_A03_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/StreamController/StreamController.broadcast_A04_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/StreamController/StreamController.broadcast_A05_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/StreamController/StreamController.broadcast_A06_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/StreamController/StreamController.broadcast_A07_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/StreamController/StreamController.broadcast_A07_t02: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/StreamController/StreamController.broadcast_A08_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/StreamController/StreamController_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/StreamController/StreamController_A02_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/StreamController/StreamController_A03_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/StreamController/StreamController_A04_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/StreamController/StreamController_A05_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/StreamController/StreamController_A06_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/StreamController/StreamController_A06_t02: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/StreamController/addError_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/StreamController/addError_A01_t02: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/StreamController/addStream_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/StreamController/addStream_A02_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/StreamController/addStream_A02_t02: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/StreamController/addStream_A03_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/StreamController/addStream_A03_t02: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/StreamController/add_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/StreamController/close_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/StreamController/close_A01_t02: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/StreamController/done_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/StreamController/done_A01_t02: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/StreamController/done_A01_t03: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/StreamController/hasListener_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/StreamController/hasListener_A01_t02: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/StreamController/isClosed_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/StreamController/isClosed_A01_t02: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/StreamController/isPaused_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/StreamController/isPaused_A01_t02: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/StreamController/isPaused_A01_t03: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/StreamController/sink_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/StreamController/stream_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/StreamIterator/StreamIterator_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/StreamIterator/cancel_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/StreamIterator/current_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/StreamIterator/moveNext_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/StreamIterator/moveNext_A01_t02: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/StreamSink/addError_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/StreamSink/addStream_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/StreamSink/addStream_A01_t02: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/StreamSink/addStream_A01_t03: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/StreamSink/addStream_A01_t04: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/StreamSink/addStream_A01_t05: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/StreamSink/add_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/StreamSink/close_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/StreamSink/done_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/StreamTransformer/StreamTransformer.fromHandlers_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/StreamTransformer/StreamTransformer.fromHandlers_A01_t02: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/StreamTransformer/StreamTransformer.fromHandlers_A01_t03: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/StreamTransformer/StreamTransformer.fromHandlers_A01_t04: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/StreamTransformer/StreamTransformer_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/StreamTransformer/StreamTransformer_A01_t02: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/StreamTransformer/StreamTransformer_A01_t03: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/StreamTransformer/StreamTransformer_A02_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/StreamTransformer/StreamTransformer_A02_t02: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/StreamTransformer/StreamTransformer_A03_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/StreamTransformer/StreamTransformer_A03_t02: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/StreamTransformer/bind_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Timer/Timer.periodic_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Timer/Timer.periodic_A02_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Timer/Timer_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Timer/Timer_A02_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Timer/cancel_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Timer/isActive_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Timer/isActive_A01_t02: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Timer/run_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Timer/run_A01_t02: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Zone/bindBinaryCallback_A01_t01: RuntimeError # receiver.get$_nums is not a function
+LibTest/async/Zone/bindBinaryCallback_A01_t02: RuntimeError # receiver.get$_nums is not a function
+LibTest/async/Zone/bindCallback_A01_t01: RuntimeError # receiver.get$_nums is not a function
+LibTest/async/Zone/bindCallback_A01_t02: RuntimeError # receiver.get$_nums is not a function
+LibTest/async/Zone/bindUnaryCallback_A01_t01: RuntimeError # receiver.get$_nums is not a function
+LibTest/async/Zone/bindUnaryCallback_A01_t02: RuntimeError # receiver.get$_nums is not a function
+LibTest/async/Zone/createPeriodicTimer_A01_t01: RuntimeError # receiver.get$_nums is not a function
+LibTest/async/Zone/createTimer_A01_t01: RuntimeError # receiver.get$_nums is not a function
+LibTest/async/Zone/current_A01_t01: RuntimeError # receiver.get$_nums is not a function
+LibTest/async/Zone/current_A01_t02: RuntimeError # receiver.get$_nums is not a function
+LibTest/async/Zone/fork_A01_t01: RuntimeError # receiver.get$_nums is not a function
+LibTest/async/Zone/handleUncaughtError_A01_t01: RuntimeError # receiver.get$_nums is not a function
+LibTest/async/Zone/handleUncaughtError_A01_t02: RuntimeError # receiver.get$_nums is not a function
+LibTest/async/Zone/handleUncaughtError_A01_t03: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Zone/handleUncaughtError_A01_t04: RuntimeError # receiver.get$_nums is not a function
+LibTest/async/Zone/inSameErrorZone_A01_t01: RuntimeError # receiver.get$_nums is not a function
+LibTest/async/Zone/inSameErrorZone_A01_t02: RuntimeError # receiver.get$_nums is not a function
+LibTest/async/Zone/inSameErrorZone_A01_t03: RuntimeError # receiver.get$_nums is not a function
+LibTest/async/Zone/inSameErrorZone_A01_t04: RuntimeError # receiver.get$_nums is not a function
+LibTest/async/Zone/inSameErrorZone_A01_t05: RuntimeError # receiver.get$_nums is not a function
+LibTest/async/Zone/operator_subscript_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Zone/parent_A01_t01: RuntimeError # receiver.get$_nums is not a function
+LibTest/async/Zone/registerBinaryCallback_A01_t01: RuntimeError # receiver.get$_nums is not a function
+LibTest/async/Zone/registerCallback_A01_t01: RuntimeError # receiver.get$_nums is not a function
+LibTest/async/Zone/registerUnaryCallback_A01_t01: RuntimeError # receiver.get$_nums is not a function
+LibTest/async/Zone/runBinaryGuarded_A01_t01: RuntimeError # receiver.get$_nums is not a function
+LibTest/async/Zone/runBinary_A01_t01: RuntimeError # receiver.get$_nums is not a function
+LibTest/async/Zone/runGuarded_A01_t01: RuntimeError # receiver.get$_nums is not a function
+LibTest/async/Zone/runUnaryGuarded_A01_t01: RuntimeError # receiver.get$_nums is not a function
+LibTest/async/Zone/runUnary_A01_t01: RuntimeError # receiver.get$_nums is not a function
+LibTest/async/Zone/run_A01_t01: RuntimeError # receiver.get$_nums is not a function
+LibTest/async/Zone/scheduleMicrotask_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/async/Zone/scheduleMicrotask_A01_t02: RuntimeError # receiver.get$_nums is not a function
+LibTest/collection/DoubleLinkedQueue/DoubleLinkedQueue_class_A01_t01: RuntimeError # Please triage this failure.
+LibTest/collection/DoubleLinkedQueue/every_A01_t01: RuntimeError # Please triage this failure.
+LibTest/collection/DoubleLinkedQueue/expand_A01_t02: RuntimeError # Please triage this failure.
+LibTest/collection/DoubleLinkedQueue/forEachEntry_A01_t01: RuntimeError # Please triage this failure.
+LibTest/collection/DoubleLinkedQueue/forEach_A01_t01: RuntimeError # Please triage this failure.
+LibTest/collection/DoubleLinkedQueue/iterator_A01_t02: RuntimeError # Please triage this failure.
+LibTest/collection/DoubleLinkedQueue/join_A01_t01: RuntimeError # Please triage this failure.
+LibTest/collection/DoubleLinkedQueue/map_A03_t01: RuntimeError # Please triage this failure.
+LibTest/collection/DoubleLinkedQueue/removeFirst_A01_t01: RuntimeError # Please triage this failure.
+LibTest/collection/DoubleLinkedQueue/remove_A01_t01: RuntimeError # Please triage this failure.
+LibTest/collection/DoubleLinkedQueue/skipWhile_A03_t01: RuntimeError # Please triage this failure.
+LibTest/collection/DoubleLinkedQueue/toList_A01_t02: RuntimeError # Please triage this failure.
+LibTest/collection/HashMap/allTests_A01_t01: RuntimeError # Please triage this failure.
+LibTest/collection/HashSet/HashSet.from_A01_t01: RuntimeError # Please triage this failure.
+LibTest/collection/HashSet/HashSet_class_A01_t01: RuntimeError # Please triage this failure.
+LibTest/collection/IterableBase/IterableBase_class_A01_t02: RuntimeError # Please triage this failure.
+LibTest/collection/LinkedHashMap/LinkedHashMap_class_A01_t01: RuntimeError # Please triage this failure.
+LibTest/collection/LinkedHashSet/LinkedHashSet_class_A01_t01: RuntimeError # Please triage this failure.
+LibTest/collection/LinkedList/addAll_A01_t01: RuntimeError # Please triage this failure.
+LibTest/collection/LinkedList/expand_A01_t01: RuntimeError # Please triage this failure.
+LibTest/collection/LinkedList/expand_A02_t01: RuntimeError # Please triage this failure.
+LibTest/collection/LinkedList/forEach_A01_t01: RuntimeError # Please triage this failure.
+LibTest/collection/LinkedList/iterator_A01_t01: RuntimeError # Please triage this failure.
+LibTest/collection/LinkedList/iterator_current_A01_t01: RuntimeError # Please triage this failure.
+LibTest/collection/LinkedList/map_A01_t01: RuntimeError # Please triage this failure.
+LibTest/collection/LinkedList/map_A02_t01: RuntimeError # Please triage this failure.
+LibTest/collection/LinkedList/map_A03_t01: RuntimeError # Please triage this failure.
+LibTest/collection/LinkedList/single_A01_t01: RuntimeError # Please triage this failure.
+LibTest/collection/LinkedList/skipWhile_A03_t01: RuntimeError # Please triage this failure.
+LibTest/collection/LinkedList/toList_A01_t02: RuntimeError # Please triage this failure.
+LibTest/collection/ListBase/ListBase_class_A01_t02: Crash # Stack Overflow
+LibTest/collection/ListMixin/ListMixin_class_A01_t02: Crash # Stack Overflow
+LibTest/collection/ListQueue/ListQueue.from_A01_t01: RuntimeError # Please triage this failure.
+LibTest/collection/ListQueue/ListQueue.from_A01_t02: RuntimeError # Please triage this failure.
+LibTest/collection/ListQueue/ListQueue_class_A01_t01: RuntimeError # Please triage this failure.
+LibTest/collection/Maps/forEach_A01_t01: RuntimeError # Please triage this failure.
+LibTest/collection/Maps/mapToString_A01_t02: RuntimeError # Please triage this failure.
+LibTest/collection/Queue/Queue.from_A01_t01: RuntimeError # Please triage this failure.
+LibTest/collection/Queue/Queue.from_A01_t02: RuntimeError # Please triage this failure.
+LibTest/collection/Queue/Queue_class_A01_t01: RuntimeError # Please triage this failure.
+LibTest/collection/SplayTreeMap/allTests_A01_t01: RuntimeError # Please triage this failure.
+LibTest/convert/JsonCodec/JsonCodec.withReviver_A01_t01: Crash # Internal Error: No default constructor available.
+LibTest/convert/JsonCodec/JsonCodec_A01_t01: Crash # Internal Error: No default constructor available.
+LibTest/convert/JsonCodec/encode_A01_t01: Crash # Internal Error: No default constructor available.
+LibTest/convert/JsonCodec/encode_A01_t02: Crash # Internal Error: No default constructor available.
+LibTest/convert/JsonCodec/encode_A02_t01: Crash # Internal Error: No default constructor available.
+LibTest/convert/JsonCodec/encode_A02_t02: Crash # Internal Error: No default constructor available.
+LibTest/convert/JsonCodec/encode_A02_t03: Crash # Internal Error: No default constructor available.
+LibTest/convert/JsonCodec/encode_A03_t01: Crash # Internal Error: No default constructor available.
+LibTest/convert/JsonDecoder/fuse_A01_t01: Crash # Internal Error: No default constructor available.
+LibTest/convert/JsonEncoder/convert_A01_t01: Crash # Internal Error: No default constructor available.
+LibTest/convert/JsonEncoder/convert_A02_t01: Crash # Internal Error: No default constructor available.
+LibTest/convert/JsonEncoder/fuse_A01_t01: Crash # Internal Error: No default constructor available.
+LibTest/core/DateTime/parse_A01_t01: RuntimeError # Cannot read property 'prototype' of undefined
+LibTest/core/DateTime/parse_A01_t02: RuntimeError # Cannot read property 'prototype' of undefined
+LibTest/core/DateTime/parse_A03_t01: Pass # Please triage this failure.
+LibTest/core/DateTime/timeZoneName_A01_t01: RuntimeError # Cannot read property 'prototype' of undefined
+LibTest/core/Function/apply_A01_t01: RuntimeError # Please triage this failure.
+LibTest/core/Invocation/isAccessor_A01_t01: Crash # Class 'PartialMethodElement' has no instance getter 'initializer'.
 LibTest/core/Invocation/isGetter_A01_t01: RuntimeError # Please triage this failure.
 LibTest/core/Invocation/isGetter_A01_t02: RuntimeError # Please triage this failure.
-LibTest/core/Invocation/isMethod_A01_t02: Crash # Please triage this failure.
-LibTest/core/Invocation/isSetter_A01_t01: Crash # Please triage this failure.
+LibTest/core/Invocation/isMethod_A01_t02: Crash # Class 'PartialMethodElement' has no instance getter 'initializer'.
+LibTest/core/Invocation/isSetter_A01_t01: Crash # Class 'PartialMethodElement' has no instance getter 'initializer'.
 LibTest/core/Invocation/isSetter_A01_t02: RuntimeError # Please triage this failure.
-LibTest/core/Invocation/memberName_A01_t01: Crash # Please triage this failure.
+LibTest/core/Invocation/memberName_A01_t01: Crash # Class 'PartialMethodElement' has no instance getter 'initializer'.
 LibTest/core/Invocation/positionalArguments_A01_t01: RuntimeError # Please triage this failure.
-LibTest/core/List/List_class_A01_t02: Crash # Please triage this failure.
-LibTest/core/Map/Map_A01_t01: Crash # type expression SomeFunction (typedef)
-LibTest/core/Object/operator_equality_A01_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
-LibTest/core/Object/toString_A01_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
-LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterClassEscape_A03_t01: Crash #  Unhandled node
-LibTest/core/RegExp/Pattern_semantics/splitQueryString_A02_t01: Crash #  Unhandled node
-LibTest/core/Set/add_A01_t03: RuntimeError # Please triage this failure.
+LibTest/core/List/List.from_A01_t01: RuntimeError # Please triage this failure.
+LibTest/core/List/List.from_A01_t02: RuntimeError # Please triage this failure.
+LibTest/core/List/List.generate_A01_t01: RuntimeError # Please triage this failure.
+LibTest/core/List/List.generate_A01_t02: RuntimeError # Please triage this failure.
+LibTest/core/List/List.generate_A01_t03: RuntimeError # Please triage this failure.
+LibTest/core/List/List_A01_t01: RuntimeError # Please triage this failure.
+LibTest/core/List/List_A01_t02: 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/List/List_class_A01_t02: Crash # Stack Overflow
+LibTest/core/Map/allTests_A01_t01: RuntimeError # Please triage this failure.
+LibTest/core/Match/end_A01_t01: RuntimeError # Cannot read property 'prototype' of undefined
+LibTest/core/Match/groupCount_A01_t01: RuntimeError # Cannot read property 'prototype' of undefined
+LibTest/core/Match/groups_A01_t01: RuntimeError # Please triage this failure.
+LibTest/core/Match/groups_A02_t01: RuntimeError # Please triage this failure.
+LibTest/core/NoSuchMethodError/toString_A01_t01: RuntimeError # receiver.get$_first is not a function
+LibTest/core/RegExp/Pattern_semantics/firstMatch_Atom_A03_t02: RuntimeError # Please triage this failure.
+LibTest/core/RegExp/stringMatch_A01_t01: RuntimeError # Cannot read property 'prototype' of undefined
+LibTest/core/Runes/toList_A02_t02: RuntimeError # Please triage this failure.
+LibTest/core/Set/IterableBase_A01_t01: RuntimeError # Please triage this failure.
+LibTest/core/Set/Set.from_A01_t01: RuntimeError # Please triage this failure.
+LibTest/core/Set/forEach_A01_t01: RuntimeError # Please triage this failure.
+LibTest/core/Stopwatch/Stopwatch_A01_t01: RuntimeError # Cannot read property 'prototype' of undefined
+LibTest/core/Stopwatch/elapsedInMs_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/core/Stopwatch/elapsedInUs_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/core/Stopwatch/elapsedTicks_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/core/Stopwatch/elapsedTicks_A01_t02: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/core/Stopwatch/elapsedTicks_A01_t03: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/core/Stopwatch/elapsed_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/core/Stopwatch/elapsed_A01_t02: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/core/Stopwatch/elapsed_A01_t03: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/core/Stopwatch/frequency_A01_t01: RuntimeError # Cannot read property 'prototype' of undefined
+LibTest/core/Stopwatch/start_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/core/Stopwatch/start_A01_t02: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/core/Stopwatch/start_A01_t03: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/core/Stopwatch/stop_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
 LibTest/core/Symbol/Symbol_A01_t03: RuntimeError # Please triage this failure.
 LibTest/core/Symbol/Symbol_A01_t05: RuntimeError # Please triage this failure.
+LibTest/core/Uri/Uri.http_A02_t01: RuntimeError # Please triage this failure.
+LibTest/core/Uri/Uri.https_A02_t01: RuntimeError # Please triage this failure.
+LibTest/core/Uri/Uri_A03_t01: RuntimeError # Please triage this failure.
+LibTest/core/Uri/authority_A01_t01: Crash # Invalid argument(s)
+LibTest/core/Uri/decodeComponent_A01_t01: RuntimeError # Please triage this failure.
+LibTest/core/Uri/decodeFull_A01_t01: RuntimeError # Please triage this failure.
+LibTest/core/Uri/decodeQueryComponent_A01_t01: RuntimeError # Please triage this failure.
+LibTest/core/Uri/decodeQueryComponent_A02_t01: RuntimeError # Please triage this failure.
+LibTest/core/Uri/hasAuthority_A01_t01: Crash # Invalid argument(s)
+LibTest/core/Uri/host_A01_t01: Crash # Invalid argument(s)
+LibTest/core/Uri/isAbsolute_A01_t01: Crash # Invalid argument(s)
+LibTest/core/Uri/operator_eq_A01_t01: Crash # Invalid argument(s)
+LibTest/core/Uri/origin_A01_t01: Crash # Invalid argument(s)
+LibTest/core/Uri/parse_A01_t01: Crash # Invalid argument(s)
+LibTest/core/Uri/parse_A02_t01: Crash # Invalid argument(s)
+LibTest/core/Uri/parse_A03_t01: Crash # Invalid argument(s)
+LibTest/core/Uri/pathSegments_A01_t01: RuntimeError # Please triage this failure.
+LibTest/core/Uri/pathSegments_A01_t02: Crash # Invalid argument(s)
+LibTest/core/Uri/pathSegments_A01_t03: RuntimeError # Please triage this failure.
+LibTest/core/Uri/pathSegments_A02_t01: Crash # Invalid argument(s)
+LibTest/core/Uri/path_A02_t01: Crash # Invalid argument(s)
+LibTest/core/Uri/port_A01_t01: Crash # Invalid argument(s)
+LibTest/core/Uri/queryParameters_A01_t01: Crash # Invalid argument(s)
+LibTest/core/Uri/queryParameters_A01_t02: Crash # Invalid argument(s)
+LibTest/core/Uri/queryParameters_A01_t03: Crash # Invalid argument(s)
+LibTest/core/Uri/query_A01_t01: Crash # Invalid argument(s)
+LibTest/core/Uri/query_A01_t02: Crash # Invalid argument(s)
+LibTest/core/Uri/resolveUri_A01_t01: Crash # Invalid argument(s)
+LibTest/core/Uri/resolve_A01_t01: Crash # Invalid argument(s)
+LibTest/core/Uri/scheme_A01_t01: Crash # Invalid argument(s)
+LibTest/core/Uri/splitQueryString_A01_t01: RuntimeError # Please triage this failure.
+LibTest/core/Uri/toFilePath_A01_t01: Crash # Invalid argument(s)
+LibTest/core/Uri/toFilePath_A01_t02: Crash # Invalid argument(s)
+LibTest/core/Uri/toFilePath_A01_t03: Crash # Invalid argument(s)
+LibTest/core/Uri/toFilePath_A02_t01: Crash # Invalid argument(s)
+LibTest/core/Uri/toFilePath_A03_t01: Crash # Invalid argument(s)
+LibTest/core/Uri/toFilePath_A04_t01: Crash # Invalid argument(s)
+LibTest/core/Uri/userInfo_A01_t01: Crash # Invalid argument(s)
 LibTest/core/double/INFINITY_A01_t04: Pass # Please triage this failure.
 LibTest/core/double/NEGATIVE_INFINITY_A01_t04: Pass # Please triage this failure.
-LibTest/html/HttpRequest/abort_A01_t01: Crash #  Unhandled node
-LibTest/html/HttpRequest/getAllResponseHeaders_A01_t01: Crash #  Unhandled node
-LibTest/html/HttpRequest/getResponseHeader_A01_t01: Crash #  Unhandled node
-LibTest/html/HttpRequest/onLoad_A01_t01: Crash #  Unhandled node
-LibTest/html/HttpRequest/overrideMimeType_A01_t01: Crash #  Unhandled node
-LibTest/html/HttpRequest/readyStateChangeEvent_A01_t01: Crash #  Unhandled node
-LibTest/html/HttpRequest/setRequestHeader_A01_t01: Crash #  Unhandled node
-LibTest/html/HttpRequestUpload/onLoad_A01_t01: Crash #  Unhandled node
-LibTest/html/Window/moveBy_A01_t01: Crash #  try/finally
-LibTest/html/Window/moveTo_A01_t01: Crash #  try/finally
-LibTest/html/Window/moveTo_A02_t01: Crash #  try/finally
-LibTest/html/Window/resizeBy_A01_t01: Crash #  try/finally
-LibTest/html/Window/resizeTo_A01_t01: Crash #  try/finally
-LibTest/isolate/ReceivePort/drain_A02_t01: Crash # Please triage this failure.
-LibTest/isolate/ReceivePort/take_A01_t02: Crash # Instance of 'TypeOperator': type casts not implemented.
-Utils/tests/Expect/approxEquals_A04_t01: RuntimeError # Please triage this failure.
-Utils/tests/Expect/stringEquals_A02_t01: RuntimeError # Please triage this failure.
-WebPlatformTest/custom-elements/instantiating/createElementNS_A02_t01: Crash #  Unhandled node
-WebPlatformTest/custom-elements/instantiating/createElementNS_A03_t01: Crash #  Unhandled node
-WebPlatformTest/custom-elements/instantiating/createElementNS_A04_t01: Crash #  Unhandled node
-WebPlatformTest/custom-elements/instantiating/createElement_A02_t01: Crash #  Unhandled node
-WebPlatformTest/custom-elements/instantiating/createElement_A03_t01: Crash #  Unhandled node
-WebPlatformTest/custom-elements/instantiating/createElement_A04_t01: Crash #  Unhandled node
-WebPlatformTest/custom-elements/instantiating/isAttribute_A01_t01: Crash #  Unhandled node
-WebPlatformTest/custom-elements/instantiating/isAttribute_A01_t02: Crash #  Unhandled node
-WebPlatformTest/html/semantics/forms/the-input-element/datetime_t01: Crash # Instance of 'TypeOperator': type casts not implemented.
-WebPlatformTest/html/semantics/forms/the-input-element/valueMode_t01: Crash #  Unhandled node
+LibTest/core/int/parse_A01_t01: RuntimeError # Cannot read property 'prototype' of undefined
+LibTest/isolate/Isolate/spawnUri_A02_t02: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/isolate/Isolate/spawnUri_A02_t03: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/isolate/Isolate/spawnUri_A02_t04: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/isolate/Isolate/spawn_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/isolate/Isolate/spawn_A01_t02: RuntimeError # receiver.get$_nums is not a function
+LibTest/isolate/Isolate/spawn_A01_t03: RuntimeError # receiver.get$_nums is not a function
+LibTest/isolate/Isolate/spawn_A01_t04: RuntimeError # receiver.get$_nums is not a function
+LibTest/isolate/Isolate/spawn_A01_t05: RuntimeError # receiver.get$_nums is not a function
+LibTest/isolate/Isolate/spawn_A02_t01: RuntimeError # receiver.get$_nums is not a function
+LibTest/isolate/RawReceivePort/RawReceivePort_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/isolate/RawReceivePort/RawReceivePort_A01_t02: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/isolate/RawReceivePort/close_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/isolate/RawReceivePort/handler_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/isolate/RawReceivePort/sendPort_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/isolate/ReceivePort/ReceivePort.fromRawReceivePort_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/isolate/ReceivePort/ReceivePort.fromRawReceivePort_A02_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/isolate/ReceivePort/ReceivePort_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/isolate/ReceivePort/any_A01_t01: RuntimeError # receiver.get$_nums is not a function
+LibTest/isolate/ReceivePort/any_A01_t02: RuntimeError # receiver.get$_nums is not a function
+LibTest/isolate/ReceivePort/asBroadcastStream_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/isolate/ReceivePort/asBroadcastStream_A01_t02: RuntimeError # receiver.get$_nums is not a function
+LibTest/isolate/ReceivePort/asBroadcastStream_A01_t03: RuntimeError # receiver.get$_nums is not a function
+LibTest/isolate/ReceivePort/asBroadcastStream_A01_t04: RuntimeError # receiver.get$_nums is not a function
+LibTest/isolate/ReceivePort/asBroadcastStream_A03_t01: RuntimeError # receiver.get$_nums is not a function
+LibTest/isolate/ReceivePort/asBroadcastStream_A03_t02: RuntimeError # receiver.get$_nums is not a function
+LibTest/isolate/ReceivePort/asBroadcastStream_A03_t03: RuntimeError # receiver.get$_nums is not a function
+LibTest/isolate/ReceivePort/asBroadcastStream_A04_t01: RuntimeError # receiver.get$_nums is not a function
+LibTest/isolate/ReceivePort/asBroadcastStream_A04_t02: RuntimeError # receiver.get$_nums is not a function
+LibTest/isolate/ReceivePort/asBroadcastStream_A04_t03: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/isolate/ReceivePort/close_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/isolate/ReceivePort/close_A02_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/isolate/ReceivePort/contains_A01_t01: RuntimeError # receiver.get$_nums is not a function
+LibTest/isolate/ReceivePort/distinct_A01_t01: RuntimeError # receiver.get$_nums is not a function
+LibTest/isolate/ReceivePort/distinct_A01_t02: RuntimeError # receiver.get$_nums is not a function
+LibTest/isolate/ReceivePort/drain_A02_t01: Crash # Invalid argument(s)
+LibTest/isolate/ReceivePort/drain_A02_t02: RuntimeError # receiver.get$_nums is not a function
+LibTest/isolate/ReceivePort/elementAt_A01_t01: RuntimeError # receiver.get$_nums is not a function
+LibTest/isolate/ReceivePort/elementAt_A03_t01: RuntimeError # receiver.get$_nums is not a function
+LibTest/isolate/ReceivePort/every_A01_t01: RuntimeError # receiver.get$_nums is not a function
+LibTest/isolate/ReceivePort/expand_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/isolate/ReceivePort/firstWhere_A01_t01: RuntimeError # receiver.get$_nums is not a function
+LibTest/isolate/ReceivePort/firstWhere_A02_t01: RuntimeError # receiver.get$_nums is not a function
+LibTest/isolate/ReceivePort/firstWhere_A03_t02: RuntimeError # receiver.get$_nums is not a function
+LibTest/isolate/ReceivePort/first_A01_t01: RuntimeError # receiver.get$_nums is not a function
+LibTest/isolate/ReceivePort/first_A02_t01: RuntimeError # receiver.get$_nums is not a function
+LibTest/isolate/ReceivePort/first_A02_t02: RuntimeError # receiver.get$_nums is not a function
+LibTest/isolate/ReceivePort/fold_A01_t01: RuntimeError # receiver.get$_nums is not a function
+LibTest/isolate/ReceivePort/fold_A01_t02: RuntimeError # receiver.get$_nums is not a function
+LibTest/isolate/ReceivePort/forEach_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/isolate/ReceivePort/isBroadcast_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/isolate/ReceivePort/isBroadcast_A01_t02: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/isolate/ReceivePort/isEmpty_A01_t01: RuntimeError # receiver.get$_nums is not a function
+LibTest/isolate/ReceivePort/join_A01_t01: RuntimeError # receiver.get$_nums is not a function
+LibTest/isolate/ReceivePort/join_A01_t02: RuntimeError # receiver.get$_nums is not a function
+LibTest/isolate/ReceivePort/lastWhere_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/isolate/ReceivePort/lastWhere_A02_t01: RuntimeError # receiver.get$_nums is not a function
+LibTest/isolate/ReceivePort/lastWhere_A04_t01: RuntimeError # receiver.get$_nums is not a function
+LibTest/isolate/ReceivePort/last_A01_t01: RuntimeError # receiver.get$_nums is not a function
+LibTest/isolate/ReceivePort/last_A02_t01: RuntimeError # receiver.get$_nums is not a function
+LibTest/isolate/ReceivePort/length_A01_t01: RuntimeError # receiver.get$_nums is not a function
+LibTest/isolate/ReceivePort/listen_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/isolate/ReceivePort/map_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/isolate/ReceivePort/pipe_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/isolate/ReceivePort/reduce_A01_t01: RuntimeError # receiver.get$_nums is not a function
+LibTest/isolate/ReceivePort/reduce_A01_t02: RuntimeError # receiver.get$_nums is not a function
+LibTest/isolate/ReceivePort/reduce_A01_t03: RuntimeError # receiver.get$_nums is not a function
+LibTest/isolate/ReceivePort/singleWhere_A01_t01: RuntimeError # receiver.get$_nums is not a function
+LibTest/isolate/ReceivePort/singleWhere_A02_t01: RuntimeError # receiver.get$_nums is not a function
+LibTest/isolate/ReceivePort/single_A01_t01: RuntimeError # receiver.get$_nums is not a function
+LibTest/isolate/ReceivePort/single_A02_t01: RuntimeError # receiver.get$_nums is not a function
+LibTest/isolate/ReceivePort/skipWhile_A01_t01: RuntimeError # receiver.get$_nums is not a function
+LibTest/isolate/ReceivePort/skip_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/isolate/ReceivePort/takeWhile_A01_t01: RuntimeError # receiver.get$_nums is not a function
+LibTest/isolate/ReceivePort/take_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/isolate/ReceivePort/take_A01_t02: RuntimeError # receiver.get$_nums is not a function
+LibTest/isolate/ReceivePort/take_A01_t03: RuntimeError # receiver.get$_nums is not a function
+LibTest/isolate/ReceivePort/toList_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/isolate/ReceivePort/toSet_A01_t01: RuntimeError # receiver.get$_nums is not a function
+LibTest/isolate/ReceivePort/transform_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/isolate/ReceivePort/transform_A01_t02: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/isolate/ReceivePort/where_A01_t01: RuntimeError # receiver.get$_nums is not a function
+LibTest/isolate/ReceivePort/where_A01_t02: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/isolate/SendPort/hashCode_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/isolate/SendPort/operator_equality_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/isolate/SendPort/send_A01_t04: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/isolate/SendPort/send_A02_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/math/atan2_A01_t01: RuntimeError # Please triage this failure.
+LibTest/math/exp_A01_t01: RuntimeError # Please triage this failure.
+LibTest/math/log_A01_t01: RuntimeError # Please triage this failure.
+LibTest/math/pow_A01_t01: RuntimeError # Please triage this failure.
+LibTest/math/sin_A01_t01: RuntimeError # Please triage this failure.
+LibTest/math/sqrt_A01_t01: RuntimeError # Please triage this failure.
+LibTest/typed_data/Float32List/iterator_A01_t01: RuntimeError # Please triage this failure.
+LibTest/typed_data/Float32List/iterator_current_A01_t01: RuntimeError # Please triage this failure.
+LibTest/typed_data/Float32List/operator_subscript_A01_t01: RuntimeError # Please triage this failure.
+LibTest/typed_data/Float32List/operator_subscript_A02_t01: RuntimeError # Please triage this failure.
+LibTest/typed_data/Float32List/reversed_A01_t01: RuntimeError # Please triage this failure.
+LibTest/typed_data/Float32List/reversed_A01_t02: RuntimeError # Please triage this failure.
+LibTest/typed_data/Float32List/setAll_A01_t01: RuntimeError # this.get$length is not a function
+LibTest/typed_data/Float32List/setRange_A01_t01: RuntimeError # this.get$length is not a function
+LibTest/typed_data/Float32List/setRange_A02_t01: RuntimeError # this.get$length is not a function
+LibTest/typed_data/Float32List/toList_A01_t01: RuntimeError # Please triage this failure.
+LibTest/typed_data/Float32List/toList_A02_t01: RuntimeError # Please triage this failure.
+LibTest/typed_data/Float32List/toList_A02_t02: RuntimeError # Please triage this failure.
+LibTest/typed_data/Float32x4List/iterator_A01_t01: RuntimeError # Please triage this failure.
+LibTest/typed_data/Float32x4List/iterator_current_A01_t01: RuntimeError # Please triage this failure.
+LibTest/typed_data/Float32x4List/operator_subscript_A01_t01: RuntimeError # Please triage this failure.
+LibTest/typed_data/Float32x4List/operator_subscript_A02_t01: RuntimeError # Please triage this failure.
+LibTest/typed_data/Float32x4List/reversed_A01_t01: RuntimeError # Please triage this failure.
+LibTest/typed_data/Float32x4List/reversed_A01_t02: RuntimeError # Please triage this failure.
+LibTest/typed_data/Float32x4List/toList_A01_t01: RuntimeError # Please triage this failure.
+LibTest/typed_data/Float32x4List/toList_A02_t01: RuntimeError # Please triage this failure.
+LibTest/typed_data/Float32x4List/toList_A02_t02: RuntimeError # Please triage this failure.
+LibTest/typed_data/Float64List/iterator_A01_t01: RuntimeError # Please triage this failure.
+LibTest/typed_data/Float64List/iterator_current_A01_t01: RuntimeError # Please triage this failure.
+LibTest/typed_data/Float64List/operator_subscript_A01_t01: RuntimeError # Please triage this failure.
+LibTest/typed_data/Float64List/operator_subscript_A02_t01: RuntimeError # Please triage this failure.
+LibTest/typed_data/Float64List/reversed_A01_t01: RuntimeError # Please triage this failure.
+LibTest/typed_data/Float64List/reversed_A01_t02: RuntimeError # Please triage this failure.
+LibTest/typed_data/Float64List/setAll_A01_t01: RuntimeError # this.get$length is not a function
+LibTest/typed_data/Float64List/setRange_A01_t01: RuntimeError # this.get$length is not a function
+LibTest/typed_data/Float64List/setRange_A02_t01: RuntimeError # this.get$length is not a function
+LibTest/typed_data/Float64List/toList_A01_t01: RuntimeError # Please triage this failure.
+LibTest/typed_data/Float64List/toList_A02_t01: RuntimeError # Please triage this failure.
+LibTest/typed_data/Float64List/toList_A02_t02: RuntimeError # Please triage this failure.
+LibTest/typed_data/Int16List/iterator_A01_t01: RuntimeError # Please triage this failure.
+LibTest/typed_data/Int16List/iterator_current_A01_t01: RuntimeError # Please triage this failure.
+LibTest/typed_data/Int16List/operator_subscript_A01_t01: RuntimeError # Please triage this failure.
+LibTest/typed_data/Int16List/operator_subscript_A02_t01: RuntimeError # Please triage this failure.
+LibTest/typed_data/Int16List/reversed_A01_t01: RuntimeError # Please triage this failure.
+LibTest/typed_data/Int16List/reversed_A01_t02: RuntimeError # Please triage this failure.
+LibTest/typed_data/Int16List/setAll_A01_t01: RuntimeError # this.get$length is not a function
+LibTest/typed_data/Int16List/setRange_A01_t01: RuntimeError # this.get$length is not a function
+LibTest/typed_data/Int16List/setRange_A02_t01: RuntimeError # this.get$length is not a function
+LibTest/typed_data/Int16List/toList_A01_t01: RuntimeError # Please triage this failure.
+LibTest/typed_data/Int16List/toList_A02_t01: RuntimeError # Please triage this failure.
+LibTest/typed_data/Int16List/toList_A02_t02: RuntimeError # Please triage this failure.
+LibTest/typed_data/Int32List/Int32List.fromList_A01_t02: RuntimeError # Please triage this failure.
+LibTest/typed_data/Int32List/iterator_A01_t01: RuntimeError # Please triage this failure.
+LibTest/typed_data/Int32List/iterator_current_A01_t01: RuntimeError # Please triage this failure.
+LibTest/typed_data/Int32List/operator_subscript_A01_t01: RuntimeError # Please triage this failure.
+LibTest/typed_data/Int32List/operator_subscript_A02_t01: RuntimeError # Please triage this failure.
+LibTest/typed_data/Int32List/reversed_A01_t01: RuntimeError # Please triage this failure.
+LibTest/typed_data/Int32List/reversed_A01_t02: RuntimeError # Please triage this failure.
+LibTest/typed_data/Int32List/setAll_A01_t01: RuntimeError # this.get$length is not a function
+LibTest/typed_data/Int32List/setRange_A01_t01: RuntimeError # this.get$length is not a function
+LibTest/typed_data/Int32List/setRange_A02_t01: RuntimeError # this.get$length is not a function
+LibTest/typed_data/Int32List/toList_A01_t01: RuntimeError # Please triage this failure.
+LibTest/typed_data/Int32List/toList_A02_t01: RuntimeError # Please triage this failure.
+LibTest/typed_data/Int32List/toList_A02_t02: RuntimeError # Please triage this failure.
+LibTest/typed_data/Int8List/Int8List.fromList_A01_t02: RuntimeError # Please triage this failure.
+LibTest/typed_data/Int8List/iterator_A01_t01: RuntimeError # Please triage this failure.
+LibTest/typed_data/Int8List/iterator_current_A01_t01: RuntimeError # Please triage this failure.
+LibTest/typed_data/Int8List/operator_subscript_A01_t01: RuntimeError # Please triage this failure.
+LibTest/typed_data/Int8List/operator_subscript_A02_t01: RuntimeError # Please triage this failure.
+LibTest/typed_data/Int8List/reversed_A01_t01: RuntimeError # Please triage this failure.
+LibTest/typed_data/Int8List/reversed_A01_t02: RuntimeError # Please triage this failure.
+LibTest/typed_data/Int8List/setAll_A01_t01: RuntimeError # this.get$length is not a function
+LibTest/typed_data/Int8List/setRange_A01_t01: RuntimeError # this.get$length is not a function
+LibTest/typed_data/Int8List/setRange_A02_t01: RuntimeError # this.get$length is not a function
+LibTest/typed_data/Int8List/toList_A01_t01: RuntimeError # Please triage this failure.
+LibTest/typed_data/Int8List/toList_A02_t01: RuntimeError # Please triage this failure.
+LibTest/typed_data/Int8List/toList_A02_t02: RuntimeError # Please triage this failure.
+LibTest/typed_data/Uint16List/iterator_A01_t01: RuntimeError # Please triage this failure.
+LibTest/typed_data/Uint16List/iterator_current_A01_t01: RuntimeError # Please triage this failure.
+LibTest/typed_data/Uint16List/operator_subscript_A01_t01: RuntimeError # Please triage this failure.
+LibTest/typed_data/Uint16List/operator_subscript_A02_t01: RuntimeError # Please triage this failure.
+LibTest/typed_data/Uint16List/reversed_A01_t01: RuntimeError # Please triage this failure.
+LibTest/typed_data/Uint16List/reversed_A01_t02: RuntimeError # Please triage this failure.
+LibTest/typed_data/Uint16List/setAll_A01_t01: RuntimeError # this.get$length is not a function
+LibTest/typed_data/Uint16List/setRange_A01_t01: RuntimeError # this.get$length is not a function
+LibTest/typed_data/Uint16List/setRange_A02_t01: RuntimeError # this.get$length is not a function
+LibTest/typed_data/Uint16List/toList_A01_t01: RuntimeError # Please triage this failure.
+LibTest/typed_data/Uint16List/toList_A02_t01: RuntimeError # Please triage this failure.
+LibTest/typed_data/Uint16List/toList_A02_t02: RuntimeError # Please triage this failure.
+LibTest/typed_data/Uint32List/iterator_A01_t01: RuntimeError # Please triage this failure.
+LibTest/typed_data/Uint32List/iterator_current_A01_t01: RuntimeError # Please triage this failure.
+LibTest/typed_data/Uint32List/operator_subscript_A01_t01: RuntimeError # Please triage this failure.
+LibTest/typed_data/Uint32List/operator_subscript_A02_t01: RuntimeError # Please triage this failure.
+LibTest/typed_data/Uint32List/reversed_A01_t01: RuntimeError # Please triage this failure.
+LibTest/typed_data/Uint32List/reversed_A01_t02: RuntimeError # Please triage this failure.
+LibTest/typed_data/Uint32List/setAll_A01_t01: RuntimeError # this.get$length is not a function
+LibTest/typed_data/Uint32List/setRange_A01_t01: RuntimeError # this.get$length is not a function
+LibTest/typed_data/Uint32List/setRange_A02_t01: RuntimeError # this.get$length is not a function
+LibTest/typed_data/Uint32List/toList_A01_t01: RuntimeError # Please triage this failure.
+LibTest/typed_data/Uint32List/toList_A02_t01: RuntimeError # Please triage this failure.
+LibTest/typed_data/Uint32List/toList_A02_t02: RuntimeError # Please triage this failure.
+LibTest/typed_data/Uint8ClampedList/iterator_A01_t01: RuntimeError # Please triage this failure.
+LibTest/typed_data/Uint8ClampedList/iterator_current_A01_t01: RuntimeError # Please triage this failure.
+LibTest/typed_data/Uint8ClampedList/operator_subscript_A01_t01: RuntimeError # Please triage this failure.
+LibTest/typed_data/Uint8ClampedList/operator_subscript_A02_t01: RuntimeError # Please triage this failure.
+LibTest/typed_data/Uint8ClampedList/reversed_A01_t01: RuntimeError # Please triage this failure.
+LibTest/typed_data/Uint8ClampedList/reversed_A01_t02: RuntimeError # Please triage this failure.
+LibTest/typed_data/Uint8ClampedList/setAll_A01_t01: RuntimeError # this.get$length is not a function
+LibTest/typed_data/Uint8ClampedList/setRange_A01_t01: RuntimeError # this.get$length is not a function
+LibTest/typed_data/Uint8ClampedList/setRange_A02_t01: RuntimeError # this.get$length is not a function
+LibTest/typed_data/Uint8ClampedList/toList_A01_t01: RuntimeError # Please triage this failure.
+LibTest/typed_data/Uint8ClampedList/toList_A02_t01: RuntimeError # Please triage this failure.
+LibTest/typed_data/Uint8ClampedList/toList_A02_t02: RuntimeError # Please triage this failure.
+LibTest/typed_data/Uint8List/iterator_A01_t01: RuntimeError # Please triage this failure.
+LibTest/typed_data/Uint8List/iterator_current_A01_t01: RuntimeError # Please triage this failure.
+LibTest/typed_data/Uint8List/operator_subscript_A01_t01: RuntimeError # Please triage this failure.
+LibTest/typed_data/Uint8List/operator_subscript_A02_t01: RuntimeError # Please triage this failure.
+LibTest/typed_data/Uint8List/reversed_A01_t01: RuntimeError # Please triage this failure.
+LibTest/typed_data/Uint8List/reversed_A01_t02: RuntimeError # Please triage this failure.
+LibTest/typed_data/Uint8List/setAll_A01_t01: RuntimeError # this.get$length is not a function
+LibTest/typed_data/Uint8List/setRange_A01_t01: RuntimeError # this.get$length is not a function
+LibTest/typed_data/Uint8List/setRange_A02_t01: RuntimeError # this.get$length is not a function
+LibTest/typed_data/Uint8List/toList_A01_t01: RuntimeError # Please triage this failure.
+LibTest/typed_data/Uint8List/toList_A02_t01: RuntimeError # Please triage this failure.
+LibTest/typed_data/Uint8List/toList_A02_t02: RuntimeError # Please triage this failure.
+Utils/tests/Expect/setEquals_A01_t01: RuntimeError # Please triage this failure.
+Utils/tests/Expect/setEquals_A01_t02: RuntimeError # Please triage this failure.
diff --git a/tests/co19/co19-runtime.status b/tests/co19/co19-runtime.status
index b5c5bc4c..f29cfd3 100644
--- a/tests/co19/co19-runtime.status
+++ b/tests/co19/co19-runtime.status
@@ -5,6 +5,7 @@
 
 [ $compiler == none && ($runtime == vm || $runtime == dartium || $runtime == ContentShellOnAndroid) ]
 
+LibTest/core/Invocation/namedArguments_A01_t01: RuntimeError # Issue 13714
 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
diff --git a/tests/compiler/dart2js/analyze_only_test.dart b/tests/compiler/dart2js/analyze_only_test.dart
index 516c0d1..785d3f8 100644
--- a/tests/compiler/dart2js/analyze_only_test.dart
+++ b/tests/compiler/dart2js/analyze_only_test.dart
@@ -64,7 +64,7 @@
 main() {
   runCompiler(
     "",
-    [],
+    ['--generate-code-with-compile-time-errors'],
     (String code, List errors, List warnings) {
       Expect.isNotNull(code);
       Expect.isTrue(errors.isEmpty, 'errors is not empty: $errors');
@@ -75,7 +75,7 @@
 
   runCompiler(
     "main() {}",
-    [],
+    ['--generate-code-with-compile-time-errors'],
     (String code, List errors, List warnings) {
       Expect.isNotNull(code);
       Expect.isTrue(errors.isEmpty);
diff --git a/tests/compiler/dart2js/analyze_unused_dart2js_test.dart b/tests/compiler/dart2js/analyze_unused_dart2js_test.dart
index 9ae51b7..e5c9deb 100644
--- a/tests/compiler/dart2js/analyze_unused_dart2js_test.dart
+++ b/tests/compiler/dart2js/analyze_unused_dart2js_test.dart
@@ -50,8 +50,6 @@
   "/lib/src/dart_backend/backend_ast_to_frontend_ast.dart": const [
     " is never "
   ],
-
-  "/lib/src/cps_ir/type_propagation.dart": const ["UnitTypeSystem"],
 };
 
 void main() {
diff --git a/tests/compiler/dart2js/async_await_js_transform_test.dart b/tests/compiler/dart2js/async_await_js_transform_test.dart
index f1f2d32..0cce49c 100644
--- a/tests/compiler/dart2js/async_await_js_transform_test.dart
+++ b/tests/compiler/dart2js/async_await_js_transform_test.dart
@@ -5,6 +5,7 @@
 import "package:expect/expect.dart";
 import "package:compiler/src/js/js.dart";
 import "package:compiler/src/js/rewrite_async.dart";
+import "package:compiler/src/js_backend/js_backend.dart" show StringBackedName;
 
 import "backend_dart/dart_printer_test.dart" show PrintDiagnosticListener;
 
@@ -16,7 +17,7 @@
       asyncHelper: new VariableUse("thenHelper"),
       newCompleter: new VariableUse("Completer"),
       safeVariableName: (String name) => "__$name",
-      bodyName: "body").rewrite(fun);
+      bodyName: new StringBackedName("body")).rewrite(fun);
 
   JavaScriptPrintingOptions options = new JavaScriptPrintingOptions();
   SimpleJavaScriptPrintingContext context =
@@ -34,7 +35,7 @@
 }""", """
 function(a) {
   var __goto = 0, __completer = new Completer(), __handler = 1, __currentError, __self = this;
-  function __body(__errorCode, __result) {
+  function body(__errorCode, __result) {
     if (__errorCode === 1) {
       __currentError = __result;
       __goto = __handler;
@@ -45,7 +46,7 @@
           // Function start
           print(__self.x);
           __goto = 2;
-          return thenHelper(foo(), __body, __completer);
+          return thenHelper(foo(), body, __completer);
         case 2:
           // returning from await.
           // implicit return
@@ -55,7 +56,7 @@
           return thenHelper(__currentError, 1, __completer);
       }
   }
-  return thenHelper(null, __body, __completer, null);
+  return thenHelper(null, body, __completer, null);
 }""");
 
   testTransform("""
@@ -84,7 +85,7 @@
   }""", """
 function(b) {
   var __goto = 0, __completer = new Completer(), __returnValue, __handler = 2, __currentError, __next = [], __helper;
-  function __body(__errorCode, __result) {
+  function body(__errorCode, __result) {
     if (__errorCode === 1) {
       __currentError = __result;
       __goto = __handler;
@@ -113,7 +114,7 @@
               break __outer1;
             }
             __goto = 12;
-            return thenHelper(foo(), __body, __completer);
+            return thenHelper(foo(), body, __completer);
           case 12:
             // returning from await.
             __helper = __result;
@@ -179,7 +180,7 @@
             return thenHelper(__currentError, 1, __completer);
         }
   }
-  return thenHelper(null, __body, __completer, null);
+  return thenHelper(null, body, __completer, null);
 }""");
 
     testTransform("""
@@ -194,7 +195,7 @@
 }""", """
 function(c) {
   var __goto = 0, __completer = new Completer(), __handler = 1, __currentError, a, b, c, d, e, f, __temp1;
-  function __body(__errorCode, __result) {
+  function body(__errorCode, __result) {
     if (__errorCode === 1) {
       __currentError = __result;
       __goto = __handler;
@@ -206,24 +207,24 @@
           a = b++;
           b = --b;
           __goto = 2;
-          return thenHelper(foo(), __body, __completer);
+          return thenHelper(foo(), body, __completer);
         case 2:
           // returning from await.
           c = __result.a++;
           __goto = 3;
-          return thenHelper(foo(), __body, __completer);
+          return thenHelper(foo(), body, __completer);
         case 3:
           // returning from await.
           d = ++__result.a;
           __temp1 = foo1();
           __goto = 4;
-          return thenHelper(foo2(), __body, __completer);
+          return thenHelper(foo2(), body, __completer);
         case 4:
           // returning from await.
           e = __temp1[__result]--;
           __temp1 = foo1();
           __goto = 5;
-          return thenHelper(foo2(), __body, __completer);
+          return thenHelper(foo2(), body, __completer);
         case 5:
           // returning from await.
           f = --__temp1[__result];
@@ -234,7 +235,7 @@
           return thenHelper(__currentError, 1, __completer);
       }
   }
-  return thenHelper(null, __body, __completer, null);
+  return thenHelper(null, body, __completer, null);
 }""");
 
   testTransform("""
@@ -251,7 +252,7 @@
   }""", """
 function(d2) {
   var __goto = 0, __completer = new Completer(), __handler = 1, __currentError, a, b, c, d, e, f, g, h, __temp1;
-  function __body(__errorCode, __result) {
+  function body(__errorCode, __result) {
     if (__errorCode === 1) {
       __currentError = __result;
       __goto = __handler;
@@ -274,19 +275,19 @@
         case 2:
           // then
           __goto = 4;
-          return thenHelper(foo2(), __body, __completer);
+          return thenHelper(foo2(), body, __completer);
         case 4:
           // returning from await.
         case 3:
           // join
           a = __result;
           __goto = 5;
-          return thenHelper(foo1(), __body, __completer);
+          return thenHelper(foo1(), body, __completer);
         case 5:
           // returning from await.
           b = __result || foo2();
           __goto = 8;
-          return thenHelper(foo1(), __body, __completer);
+          return thenHelper(foo1(), body, __completer);
         case 8:
           // returning from await.
           __temp1 = __result;
@@ -304,7 +305,7 @@
           // then
           __temp1 = foo3;
           __goto = 9;
-          return thenHelper(foo2(), __body, __completer);
+          return thenHelper(foo2(), body, __completer);
         case 9:
           // returning from await.
           __result = __temp1(__result);
@@ -325,19 +326,19 @@
         case 10:
           // then
           __goto = 12;
-          return thenHelper(foo2(), __body, __completer);
+          return thenHelper(foo2(), body, __completer);
         case 12:
           // returning from await.
         case 11:
           // join
           e = __result;
           __goto = 13;
-          return thenHelper(foo1(), __body, __completer);
+          return thenHelper(foo1(), body, __completer);
         case 13:
           // returning from await.
           f = __result && foo2();
           __goto = 16;
-          return thenHelper(foo1(), __body, __completer);
+          return thenHelper(foo1(), body, __completer);
         case 16:
           // returning from await.
           __temp1 = __result;
@@ -353,7 +354,7 @@
         case 14:
           // then
           __goto = 17;
-          return thenHelper(foo2(), __body, __completer);
+          return thenHelper(foo2(), body, __completer);
         case 17:
           // returning from await.
         case 15:
@@ -367,7 +368,7 @@
           return thenHelper(__currentError, 1, __completer);
       }
   }
-  return thenHelper(null, __body, __completer, null);
+  return thenHelper(null, body, __completer, null);
 }""");
 
     testTransform("""
@@ -388,7 +389,7 @@
 }""", """
 function(x, y) {
   var __goto = 0, __completer = new Completer(), __handler = 1, __currentError;
-  function __body(__errorCode, __result) {
+  function body(__errorCode, __result) {
     if (__errorCode === 1) {
       __currentError = __result;
       __goto = __handler;
@@ -429,7 +430,7 @@
         case 7:
           // case
           __goto = 10;
-          return thenHelper(foo(), __body, __completer);
+          return thenHelper(foo(), body, __completer);
         case 10:
           // returning from await.
           // goto while condition
@@ -438,7 +439,7 @@
         case 8:
           // case
           __goto = 11;
-          return thenHelper(foo(), __body, __completer);
+          return thenHelper(foo(), body, __completer);
         case 11:
           // returning from await.
           // goto after switch
@@ -461,7 +462,7 @@
           return thenHelper(__currentError, 1, __completer);
       }
   }
-  return thenHelper(null, __body, __completer, null);
+  return thenHelper(null, body, __completer, null);
 }""");
 
   testTransform("""
@@ -477,7 +478,7 @@
   """, """
 function(f) {
   var __goto = 0, __completer = new Completer(), __handler = 1, __currentError, a;
-  function __body(__errorCode, __result) {
+  function body(__errorCode, __result) {
     if (__errorCode === 1) {
       __currentError = __result;
       __goto = __handler;
@@ -489,7 +490,7 @@
         case 2:
           // do body
           __goto = 5;
-          return thenHelper(foo(), __body, __completer);
+          return thenHelper(foo(), body, __completer);
         case 5:
           // returning from await.
           a = __result;
@@ -505,7 +506,7 @@
         case 3:
           // do condition
           __goto = 6;
-          return thenHelper(foo(), __body, __completer);
+          return thenHelper(foo(), body, __completer);
         case 6:
           // returning from await.
           if (__result) {
@@ -522,7 +523,7 @@
           return thenHelper(__currentError, 1, __completer);
       }
   }
-  return thenHelper(null, __body, __completer, null);
+  return thenHelper(null, body, __completer, null);
 }""");
 
     testTransform("""
@@ -542,7 +543,7 @@
 """, """
 function(g) {
   var __goto = 0, __completer = new Completer(), __returnValue, __handler = 2, __currentError, i, __temp1;
-  function __body(__errorCode, __result) {
+  function body(__errorCode, __result) {
     if (__errorCode === 1) {
       __currentError = __result;
       __goto = __handler;
@@ -556,7 +557,7 @@
           // for condition
           __temp1 = i;
           __goto = 6;
-          return thenHelper(foo1(), __body, __completer);
+          return thenHelper(foo1(), body, __completer);
         case 6:
           // returning from await.
           if (!(__temp1 < __result)) {
@@ -578,7 +579,7 @@
         case 7:
           // then
           __goto = 9;
-          return thenHelper(foo(), __body, __completer);
+          return thenHelper(foo(), body, __completer);
         case 9:
           // returning from await.
           // goto return
@@ -588,14 +589,14 @@
           // join
           __temp1 = print;
           __goto = 10;
-          return thenHelper(foo(i), __body, __completer);
+          return thenHelper(foo(i), body, __completer);
         case 10:
           // returning from await.
           __temp1(__result);
         case 4:
           // for update
           __goto = 11;
-          return thenHelper(foo2(), __body, __completer);
+          return thenHelper(foo2(), body, __completer);
         case 11:
           // returning from await.
           i += __result;
@@ -612,7 +613,7 @@
           return thenHelper(__currentError, 1, __completer);
       }
   }
-  return thenHelper(null, __body, __completer, null);
+  return thenHelper(null, body, __completer, null);
 }""");
 
   testTransform("""
@@ -627,7 +628,7 @@
   """, """
 function(a, h) {
   var __goto = 0, __completer = new Completer(), __handler = 1, __currentError, x, __temp1, __temp2;
-  function __body(__errorCode, __result) {
+  function body(__errorCode, __result) {
     if (__errorCode === 1) {
       __currentError = __result;
       __goto = __handler;
@@ -638,45 +639,45 @@
           // Function start
           __temp1 = foo1();
           __goto = 2;
-          return thenHelper(foo2(), __body, __completer);
+          return thenHelper(foo2(), body, __completer);
         case 2:
           // returning from await.
           x = {a: __temp1, b: __result, c: foo3()};
           x.a = 2;
           __goto = 3;
-          return thenHelper(foo(), __body, __completer);
+          return thenHelper(foo(), body, __completer);
         case 3:
           // returning from await.
           __result.a = 3;
           __temp1 = x;
           __goto = 4;
-          return thenHelper(foo(), __body, __completer);
+          return thenHelper(foo(), body, __completer);
         case 4:
           // returning from await.
           __temp1[__result] = 4;
           __temp1 = x;
           __goto = 5;
-          return thenHelper(foo1(), __body, __completer);
+          return thenHelper(foo1(), body, __completer);
         case 5:
           // returning from await.
           __temp2 = __result;
           __goto = 6;
-          return thenHelper(foo2(), __body, __completer);
+          return thenHelper(foo2(), body, __completer);
         case 6:
           // returning from await.
           __temp1[__temp2.a = __result] = 5;
           __goto = 7;
-          return thenHelper(foo1(), __body, __completer);
+          return thenHelper(foo1(), body, __completer);
         case 7:
           // returning from await.
           __temp1 = __result;
           __goto = 8;
-          return thenHelper(foo2(), __body, __completer);
+          return thenHelper(foo2(), body, __completer);
         case 8:
           // returning from await.
           __temp2 = __result;
           __goto = 9;
-          return thenHelper(foo3(6), __body, __completer);
+          return thenHelper(foo3(6), body, __completer);
         case 9:
           // returning from await.
           __temp1[__temp2] = __result;
@@ -687,7 +688,7 @@
           return thenHelper(__currentError, 1, __completer);
       }
   }
-  return thenHelper(null, __body, __completer, null);
+  return thenHelper(null, body, __completer, null);
 }""");
 
     testTransform("""
@@ -708,7 +709,7 @@
 """, """
 function(c, i) {
   var __goto = 0, __completer = new Completer(), __handler = 1, __currentError, __next = [], x, y, __error, __error1;
-  function __body(__errorCode, __result) {
+  function body(__errorCode, __result) {
     if (__errorCode === 1) {
       __currentError = __result;
       __goto = __handler;
@@ -723,7 +724,7 @@
         case 6:
           // then
           __goto = 9;
-          return thenHelper(foo(), __body, __completer);
+          return thenHelper(foo(), body, __completer);
         case 9:
           // returning from await.
           // goto join
@@ -750,7 +751,7 @@
         case 14:
           // then
           __goto = 17;
-          return thenHelper(fooError(__error), __body, __completer);
+          return thenHelper(fooError(__error), body, __completer);
         case 17:
           // returning from await.
           // goto join
@@ -804,7 +805,7 @@
           return thenHelper(__currentError, 1, __completer);
       }
   }
-  return thenHelper(null, __body, __completer, null);
+  return thenHelper(null, body, __completer, null);
 }""");
 
   testTransform("""
@@ -818,7 +819,7 @@
   """, """
 function(x, y, j) {
   var __goto = 0, __completer = new Completer(), __handler = 1, __currentError, __temp1, __temp2, __temp3;
-  function __body(__errorCode, __result) {
+  function body(__errorCode, __result) {
     if (__errorCode === 1) {
       __currentError = __result;
       __goto = __handler;
@@ -829,37 +830,37 @@
           // Function start
           __temp1 = print;
           __goto = 2;
-          return thenHelper(foo(x), __body, __completer);
+          return thenHelper(foo(x), body, __completer);
         case 2:
           // returning from await.
           __temp1(__result);
           __goto = 3;
-          return thenHelper(print, __body, __completer);
+          return thenHelper(print, body, __completer);
         case 3:
           // returning from await.
           __result(foo(x));
           __temp1 = print;
           __temp2 = foo;
           __goto = 4;
-          return thenHelper(x, __body, __completer);
+          return thenHelper(x, body, __completer);
         case 4:
           // returning from await.
           __temp1(__temp2(__result));
           __temp1 = print;
           __temp2 = foo;
           __goto = 6;
-          return thenHelper(x, __body, __completer);
+          return thenHelper(x, body, __completer);
         case 6:
           // returning from await.
           __goto = 5;
-          return thenHelper(__temp1(__temp2(__result)), __body, __completer);
+          return thenHelper(__temp1(__temp2(__result)), body, __completer);
         case 5:
           // returning from await.
           __temp1 = print;
           __temp2 = foo;
           __temp3 = x;
           __goto = 7;
-          return thenHelper(y, __body, __completer);
+          return thenHelper(y, body, __completer);
         case 7:
           // returning from await.
           __temp1(__temp2(__temp3, __result, z));
@@ -870,7 +871,7 @@
           return thenHelper(__currentError, 1, __completer);
       }
   }
-  return thenHelper(null, __body, __completer, null);
+  return thenHelper(null, body, __completer, null);
 }""");
 
     testTransform("""
@@ -901,7 +902,7 @@
 }""", """
 function(x, y, k) {
   var __goto = 0, __completer = new Completer(), __returnValue, __handler = 2, __currentError, __temp1;
-  function __body(__errorCode, __result) {
+  function body(__errorCode, __result) {
     if (__errorCode === 1) {
       __currentError = __result;
       __goto = __handler;
@@ -913,7 +914,7 @@
         case 3:
           // while condition
           __goto = 5;
-          return thenHelper(foo(), __body, __completer);
+          return thenHelper(foo(), body, __completer);
         case 5:
           // returning from await.
           if (!__result) {
@@ -935,7 +936,7 @@
             break;
           }
           __goto = 12;
-          return thenHelper(bar(), __body, __completer);
+          return thenHelper(bar(), body, __completer);
         case 12:
           // returning from await.
           if (__temp1 === __result) {
@@ -958,7 +959,7 @@
           // case
           __temp1 = print;
           __goto = 15;
-          return thenHelper(foo1(x), __body, __completer);
+          return thenHelper(foo1(x), body, __completer);
         case 15:
           // returning from await.
           __temp1(__result);
@@ -970,7 +971,7 @@
           // case
           __temp1 = print;
           __goto = 16;
-          return thenHelper(foobar(x), __body, __completer);
+          return thenHelper(foobar(x), body, __completer);
         case 16:
           // returning from await.
           __temp1(__result);
@@ -1010,7 +1011,7 @@
           return thenHelper(__currentError, 1, __completer);
       }
   }
-  return thenHelper(null, __body, __completer, null);
+  return thenHelper(null, body, __completer, null);
 }""");
   testTransform("""
   function(l) async {
@@ -1028,7 +1029,7 @@
   }""", """
 function(l) {
   var __goto = 0, __completer = new Completer(), __handler = 1, __currentError;
-  function __body(__errorCode, __result) {
+  function body(__errorCode, __result) {
     if (__errorCode === 1) {
       __currentError = __result;
       __goto = __handler;
@@ -1038,7 +1039,7 @@
         case 0:
           // Function start
           __goto = 2;
-          return thenHelper(l, __body, __completer);
+          return thenHelper(l, body, __completer);
         case 2:
           // returning from await.
           switch (__result) {
@@ -1058,7 +1059,7 @@
           return thenHelper(__currentError, 1, __completer);
       }
   }
-  return thenHelper(null, __body, __completer, null);
+  return thenHelper(null, body, __completer, null);
 }""");
 
   testTransform("""
@@ -1080,7 +1081,7 @@
   }""", """
 function(m) {
   var __goto = 0, __completer = new Completer(), __handler = 1, __currentError, __next = [], exception, __exception;
-  function __body(__errorCode, __result) {
+  function body(__errorCode, __result) {
     if (__errorCode === 1) {
       __currentError = __result;
       __goto = __handler;
@@ -1092,7 +1093,7 @@
           exception = 1;
           __handler = 3;
           __goto = 6;
-          return thenHelper(42, __body, __completer);
+          return thenHelper(42, body, __completer);
         case 6:
           // returning from await.
           throw 42;
@@ -1105,12 +1106,12 @@
           __handler = 2;
           __exception = __currentError;
           __goto = 7;
-          return thenHelper(10, __body, __completer);
+          return thenHelper(10, body, __completer);
         case 7:
           // returning from await.
           __exception = __result;
           __goto = 8;
-          return thenHelper(10, __body, __completer);
+          return thenHelper(10, body, __completer);
         case 8:
           // returning from await.
           __exception += __result;
@@ -1137,6 +1138,6 @@
           return thenHelper(__currentError, 1, __completer);
       }
   }
-  return thenHelper(null, __body, __completer, null);
+  return thenHelper(null, body, __completer, null);
 }""");
 }
diff --git a/tests/compiler/dart2js/backend_dart/sexpr_unstringifier.dart b/tests/compiler/dart2js/backend_dart/sexpr_unstringifier.dart
index 211d526..809aa99 100644
--- a/tests/compiler/dart2js/backend_dart/sexpr_unstringifier.dart
+++ b/tests/compiler/dart2js/backend_dart/sexpr_unstringifier.dart
@@ -135,9 +135,10 @@
   static const String LET_CONT = "LetCont";
   static const String LET_MUTABLE = "LetMutable";
   static const String SET_MUTABLE_VARIABLE = "SetMutableVariable";
-  static const String TYPE_OPERATOR = "TypeOperator";
+  static const String TYPE_CAST = "TypeCast";
   static const String SET_STATIC = "SetStatic";
   static const String GET_LAZY_STATIC = "GetLazyStatic";
+  static const String UNREACHABLE = "Unreachable";
 
   // Primitives
   static const String CONSTANT = "Constant";
@@ -147,6 +148,8 @@
   static const String LITERAL_MAP = "LiteralMap";
   static const String REIFY_TYPE_VAR = "ReifyTypeVar";
   static const String GET_STATIC = "GetStatic";
+  static const String TYPE_TEST = "TypeTest";
+  static const String APPLY_BUILTIN_OPERATOR = "ApplyBuiltinOperator";
 
   // Other
   static const String FUNCTION_DEFINITION = "FunctionDefinition";
@@ -247,12 +250,14 @@
         return parseLetMutable();
       case SET_MUTABLE_VARIABLE:
         return parseSetMutableVariable();
-      case TYPE_OPERATOR:
-        return parseTypeOperator();
+      case TYPE_CAST:
+        return parseTypeCast();
       case SET_STATIC:
         return parseSetStatic();
       case GET_LAZY_STATIC:
         return parseGetLazyStatic();
+      case UNREACHABLE:
+        return parseUnreachable();
       default:
         assert(false);
     }
@@ -553,14 +558,12 @@
                   ..plug(body);
   }
 
-  /// (TypeOperator operator recv type cont)
-  TypeOperator parseTypeOperator() {
-    tokens.consumeStart(TYPE_OPERATOR);
+  /// (TypeCast value type args cont)
+  TypeCast parseTypeCast() {
+    tokens.consumeStart(TYPE_CAST);
 
-    String operator = tokens.read();
-
-    Primitive recv = name2variable[tokens.read()];
-    assert(recv != null);
+    Primitive value = name2variable[tokens.read()];
+    assert(value != null);
 
     dart_types.DartType type = new DummyNamedType(tokens.read());
 
@@ -570,8 +573,41 @@
     assert(cont != null);
 
     tokens.consumeEnd();
-    return new TypeOperator(recv, type, typeArguments, cont,
-                            isTypeTest: operator == 'is');
+    return new TypeCast(value, type, typeArguments, cont);
+  }
+
+  /// (TypeTest value type args)
+  TypeTest parseTypeTest() {
+    tokens.consumeStart(TYPE_TEST);
+
+    Primitive value = name2variable[tokens.read()];
+    assert(value != null);
+
+    dart_types.DartType type = new DummyNamedType(tokens.read());
+
+    List<ir.Primitive> typeArguments = parsePrimitiveList();
+
+    tokens.consumeEnd();
+    return new TypeTest(value, type, typeArguments);
+  }
+
+  /// (ApplyBuiltinOperator operator args)
+  ApplyBuiltinOperator parseApplyBuiltinOperator() {
+    tokens.consumeStart(APPLY_BUILTIN_OPERATOR);
+
+    String operatorName = tokens.read();
+    BuiltinOperator operator;
+    for (BuiltinOperator op in BuiltinOperator.values) {
+      if (op.toString() == operatorName) {
+        operator = op;
+        break;
+      }
+    }
+    assert(operator != null);
+    List<ir.Primitive> arguments = parsePrimitiveList();
+
+    tokens.consumeEnd();
+    return new ApplyBuiltinOperator(operator, arguments);
   }
 
   /// (SetStatic field value body)
@@ -599,6 +635,13 @@
     return new GetLazyStatic(fieldElement, cont, null);
   }
 
+  /// (Unreachable)
+  Unreachable parseUnreachable() {
+    tokens.consumeStart(UNREACHABLE);
+    tokens.consumeEnd();
+    return new Unreachable();
+  }
+
   /// (LetPrim (name primitive) body)
   LetPrim parseLetPrim() {
     tokens.consumeStart(LET_PRIM);
@@ -637,6 +680,10 @@
         return parseReifyTypeVar();
       case GET_STATIC:
         return parseGetStatic();
+      case TYPE_TEST:
+        return parseTypeTest();
+      case APPLY_BUILTIN_OPERATOR:
+        return parseApplyBuiltinOperator();
       default:
         assert(false);
     }
diff --git a/tests/compiler/dart2js/compiler_helper.dart b/tests/compiler/dart2js/compiler_helper.dart
index e139a0e..90dd441 100644
--- a/tests/compiler/dart2js/compiler_helper.dart
+++ b/tests/compiler/dart2js/compiler_helper.dart
@@ -109,6 +109,7 @@
       expectedWarnings: expectedWarnings,
       outputProvider: outputProvider);
   compiler.registerSource(uri, code);
+  compiler.diagnosticHandler = createHandler(compiler, code);
   return compiler;
 }
 
diff --git a/tests/compiler/dart2js/cpa_inference_test.dart b/tests/compiler/dart2js/cpa_inference_test.dart
index d22efb7..0d36b71 100644
--- a/tests/compiler/dart2js/cpa_inference_test.dart
+++ b/tests/compiler/dart2js/cpa_inference_test.dart
@@ -144,8 +144,10 @@
   }
 
   /** Checks that the inferred type for [selector] is [mask]. */
-  void checkSelectorHasType(Selector selector, TypeMask mask) {
-    Expect.equals(mask, inferrer.getTypeOfSelector(selector));
+  void checkSelectorHasType(Selector selector,
+                            TypeMask mask,
+                            TypeMask expectedMask) {
+    Expect.equals(expectedMask, inferrer.getTypeOfSelector(selector, mask));
   }
 }
 
@@ -1648,24 +1650,29 @@
 
     result.checkSelectorHasType(
         foo,
+        null,
         new TypeMask.unionOf([a, b, c]
             .map((cls) => new TypeMask.nonNullExact(cls, world)),
             result.compiler.world));
     result.checkSelectorHasType(
-        new TypedSelector.subclass(x, foo, world),
+        foo,
+        new TypeMask.subclass(x, world),
         new TypeMask.nonNullExact(b, world));
     result.checkSelectorHasType(
-        new TypedSelector.subclass(y, foo, world),
+        foo,
+        new TypeMask.subclass(y, world),
         new TypeMask.nonNullExact(c, world));
     result.checkSelectorHasType(
-        new TypedSelector.subclass(z, foo, world),
+        foo,
+        new TypeMask.subclass(z, world),
         new TypeMask.nonNullExact(a, world));
     result.checkSelectorHasType(
-        new TypedSelector.subclass(xy, foo, world),
+        foo,
+        new TypeMask.subclass(xy, world),
         new TypeMask.unionOf([b, c].map((cls) =>
             new TypeMask.nonNullExact(cls, world)), world));
 
-    result.checkSelectorHasType(new Selector.call("bar", null, 0), null);
+    result.checkSelectorHasType(new Selector.call("bar", null, 0), null, null);
   });
 }
 
@@ -1678,6 +1685,7 @@
   return analyze(source).then((result) {
     ClassElement bool = result.compiler.backend.boolImplementation;
     result.checkSelectorHasType(new Selector.binaryOperator('=='),
+                                null,
                                 new TypeMask.nonNullExact(bool,
                                     result.compiler.world));
   });
diff --git a/tests/compiler/dart2js/diagnose_ambiguous_test.dart b/tests/compiler/dart2js/diagnose_ambiguous_test.dart
index f73c43f..c6b3061 100644
--- a/tests/compiler/dart2js/diagnose_ambiguous_test.dart
+++ b/tests/compiler/dart2js/diagnose_ambiguous_test.dart
@@ -38,7 +38,7 @@
         "memory:library.dart:41:45:'hest' is defined here.:info",
         "memory:main.dart:0:22:'hest' is imported here.:info",
         "memory:main.dart:23:46:'hest' is imported here.:info",
-        "memory:main.dart:86:90:Duplicate import of 'hest'.:error"
+        "memory:main.dart:86:92:Duplicate import of 'hest'.:error"
     ];
     Expect.listEquals(expected, diagnostics);
     Expect.isTrue(compiler.compilationFailed);
diff --git a/tests/compiler/dart2js/generate_code_with_compile_time_errors_test.dart b/tests/compiler/dart2js/generate_code_with_compile_time_errors_test.dart
new file mode 100644
index 0000000..bf9b86e
--- /dev/null
+++ b/tests/compiler/dart2js/generate_code_with_compile_time_errors_test.dart
@@ -0,0 +1,142 @@
+// 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 that the compiler can generates code with compile time error according
+// to the compiler options.
+
+library dart2js.test.import;
+
+import 'package:expect/expect.dart';
+import 'package:async_helper/async_helper.dart';
+import 'package:compiler/src/dart2jslib.dart';
+import 'package:compiler/src/dart_backend/dart_backend.dart';
+import 'package:compiler/src/js_backend/js_backend.dart';
+import 'memory_compiler.dart';
+import 'output_collector.dart';
+
+const MEMORY_SOURCE_FILES = const {
+  'main.dart': ''' 
+foo() {
+ const list = [];
+}
+
+main() {
+  foo();
+}
+''',
+};
+
+test(List<String> options,
+     {bool expectedOutput,
+      bool expectedCodeGenerated,
+      bool expectHint: false}) async {
+  DiagnosticCollector collector = new DiagnosticCollector();
+  OutputCollector outputCollector = new OutputCollector();
+  Compiler compiler = compilerFor(
+      MEMORY_SOURCE_FILES,
+      diagnosticHandler: collector,
+      outputProvider: outputCollector,
+      options: options);
+
+  return compiler.run(Uri.parse('memory:main.dart')).then(
+      (bool success) {
+    Expect.isFalse(
+        success,
+        "Expected compilation failure.");
+    Expect.isTrue(
+        collector.warnings.isEmpty,
+        "Unexpected warnings: ${collector.warnings}");
+    Expect.isFalse(
+        collector.errors.isEmpty,
+        "Expected compile-time errors.");
+    Expect.equals(
+        expectHint,
+        collector.hints.isNotEmpty,
+        "Unexpected hints: ${collector.warnings}");
+
+    bool isCodeGenerated;
+    if (options.contains('--output-type=dart')) {
+      DartBackend backend = compiler.backend;
+      isCodeGenerated = backend.outputter.libraryInfo != null;
+    } else {
+      JavaScriptBackend backend = compiler.backend;
+      isCodeGenerated = backend.generatedCode.isNotEmpty;
+    }
+    Expect.equals(
+        expectedCodeGenerated,
+        isCodeGenerated,
+        expectedCodeGenerated
+            ? "Expected generated code for options $options."
+            : "Expected no code generated for options $options.");
+    Expect.equals(
+        expectedOutput,
+        outputCollector.outputMap.isNotEmpty,
+        expectedOutput
+            ? "Expected output for options $options."
+            : "Expected no output for options $options.");
+  });
+}
+
+void main() {
+  asyncTest(() async {
+    await test(
+       [],
+       expectedCodeGenerated: false,
+       expectedOutput: false);
+    await test(
+       ['--test-mode'],
+       expectedCodeGenerated: false,
+       expectedOutput: false);
+    await test(
+       ['--generate-code-with-compile-time-errors'],
+       expectedCodeGenerated: true,
+       expectedOutput: true);
+    await test(
+       ['--generate-code-with-compile-time-errors', '--test-mode'],
+       expectedCodeGenerated: true,
+       expectedOutput: false);
+
+    await test(
+       ['--use-cps-ir'],
+       expectedCodeGenerated: false,
+       expectedOutput: false);
+    await test(
+       ['--use-cps-ir', '--test-mode'],
+       expectedCodeGenerated: false,
+       expectedOutput: false);
+    await test(
+       ['--use-cps-ir', '--generate-code-with-compile-time-errors'],
+       expectedCodeGenerated: false,
+       expectedOutput: false,
+       expectHint: true);
+    await test(
+       ['--use-cps-ir',
+        '--generate-code-with-compile-time-errors',
+        '--test-mode'],
+       expectedCodeGenerated: false,
+       expectedOutput: false,
+       expectHint: true);
+
+    await test(
+       ['--output-type=dart'],
+       expectedCodeGenerated: false,
+       expectedOutput: false);
+    await test(
+       ['--output-type=dart', '--test-mode'],
+       expectedCodeGenerated: false,
+       expectedOutput: false);
+    await test(
+       ['--output-type=dart', '--generate-code-with-compile-time-errors'],
+       expectedCodeGenerated: false,
+       expectedOutput: false,
+       expectHint: true);
+    await test(
+       ['--output-type=dart',
+        '--generate-code-with-compile-time-errors',
+        '--test-mode'],
+       expectedCodeGenerated: false,
+       expectedOutput: false,
+       expectHint: true);
+  });
+}
diff --git a/tests/compiler/dart2js/gvn_dynamic_field_get_test.dart b/tests/compiler/dart2js/gvn_dynamic_field_get_test.dart
index afa0af3..2da3b97 100644
--- a/tests/compiler/dart2js/gvn_dynamic_field_get_test.dart
+++ b/tests/compiler/dart2js/gvn_dynamic_field_get_test.dart
@@ -36,6 +36,6 @@
     var element = cls.lookupLocalMember(name);
     Expect.isNotNull(element);
     Selector selector = new Selector.getter(name, null);
-    Expect.isFalse(compiler.world.hasAnyUserDefinedGetter(selector));
+    Expect.isFalse(compiler.world.hasAnyUserDefinedGetter(selector, null));
   }));
 }
diff --git a/tests/compiler/dart2js/interceptor_test.dart b/tests/compiler/dart2js/interceptor_test.dart
index 619d018..c9bd14c 100644
--- a/tests/compiler/dart2js/interceptor_test.dart
+++ b/tests/compiler/dart2js/interceptor_test.dart
@@ -31,7 +31,7 @@
     // https://code.google.com/p/dart/issues/detail?id=8106.
     compile(TEST_ONE, entry: 'foo', check: (String generated) {
       Expect.isTrue(
-          generated.contains(new RegExp(r'[$A-Z]+\.toString\$0\(a\)')));
+          generated.contains(new RegExp(r'[$A-Z]+\.toString\$0\$\(a\)')));
       Expect.isTrue(generated.contains('myVariableName'));
     }),
     // Check that an intercepted getter that does not need to be
diff --git a/tests/compiler/dart2js/js_backend_cps_ir_basic_test.dart b/tests/compiler/dart2js/js_backend_cps_ir_basic_test.dart
index b9183bc..264dc65 100644
--- a/tests/compiler/dart2js/js_backend_cps_ir_basic_test.dart
+++ b/tests/compiler/dart2js/js_backend_cps_ir_basic_test.dart
@@ -27,11 +27,11 @@
 function() {
   var l = [1, 2, 3], m = P.LinkedHashMap_LinkedHashMap$_literal(["s", 1]);
   P.print("()");
-  P.print("(" + true + ")");
-  P.print("(" + 1 + ")");
+  P.print("(true)");
+  P.print("(1)");
   P.print("(" + H.S([1, 2, 3]) + ")");
   P.print("(" + H.S(P.LinkedHashMap_LinkedHashMap$_literal(["s", 1])) + ")");
-  P.print("(" + 1 + ")");
+  P.print("(1)");
   P.print("(" + H.S(l) + ")");
   P.print("(" + H.S(m) + ")");
   return null;
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 083e407..e58e474 100644
--- a/tests/compiler/dart2js/js_backend_cps_ir_closures_test.dart
+++ b/tests/compiler/dart2js/js_backend_cps_ir_closures_test.dart
@@ -20,9 +20,8 @@
 """,
 r"""
 function(x) {
-  var _box_0 = {}, a;
+  var _box_0 = {}, a = new V.main_a(_box_0);
   _box_0._captured_x_0 = x;
-  a = new V.main_a(_box_0);
   _box_0._captured_x_0 = J.getInterceptor$ns(x = _box_0._captured_x_0).$add(x, "1");
   P.print(a.call$0());
   return null;
@@ -52,10 +51,9 @@
 """,
 r"""
 function() {
-  var _box_0 = {}, a, x;
+  var _box_0 = {}, a = new V.main_closure(_box_0);
   _box_0._captured_x_0 = 122;
-  a = new V.main_closure(_box_0);
-  _box_0._captured_x_0 = J.getInterceptor$ns(x = _box_0._captured_x_0).$add(x, 1);
+  _box_0._captured_x_0 = _box_0._captured_x_0 + 1;
   P.print(a.call$0());
   return null;
 }"""),
@@ -73,10 +71,9 @@
 """,
 r"""
 function() {
-  var _box_0 = {}, a, x;
+  var _box_0 = {}, a = new V.main_closure(_box_0);
   _box_0._captured_x_0 = 122;
-  a = new V.main_closure(_box_0);
-  _box_0._captured_x_0 = J.getInterceptor$ns(x = _box_0._captured_x_0).$add(x, 1);
+  _box_0._captured_x_0 = _box_0._captured_x_0 + 1;
   P.print(a.call$0().call$0());
   return null;
 }"""),
@@ -93,9 +90,9 @@
 r"""
 function() {
   var a = null, i = 0;
-  while (J.getInterceptor$n(i).$lt(i, 10)) {
+  while (i < 10) {
     a = new V.main_closure(i);
-    i = J.getInterceptor$ns(i).$add(i, 1);
+    i = i + 1;
   }
   P.print(a.call$0());
   return null;
diff --git a/tests/compiler/dart2js/js_backend_cps_ir_constructor_test.dart b/tests/compiler/dart2js/js_backend_cps_ir_constructor_test.dart
index 93bcb7b..ff798ac 100644
--- a/tests/compiler/dart2js/js_backend_cps_ir_constructor_test.dart
+++ b/tests/compiler/dart2js/js_backend_cps_ir_constructor_test.dart
@@ -96,9 +96,9 @@
 }""",
 r"""
 function(x, y) {
-  var _box_0 = {}, v0;
+  var _box_0 = {}, v0 = new V.Sub(y, new V.Base_closure(_box_0));
   _box_0._captured_x1_0 = x;
-  (v0 = new V.Sub(y, new V.Base_closure(_box_0))).Base0$0();
+  v0.Base0$0();
   v0.Base$1(_box_0);
   v0.Sub$2(x, y);
   return v0;
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 1efa4f7..41073af 100644
--- a/tests/compiler/dart2js/js_backend_cps_ir_interceptors_test.dart
+++ b/tests/compiler/dart2js/js_backend_cps_ir_interceptors_test.dart
@@ -18,8 +18,7 @@
 }""",
 r"""
 function() {
-  var g = 1;
-  P.print(J.getInterceptor$ns(g).$add(g, 3));
+  P.print(4);
   return null;
 }"""),
   const TestEntry("""
@@ -35,17 +34,16 @@
 }""",
 r"""
 function() {
-  var l = ["hest", ["h", "e", "s", "t"]], i, x, j;
+  var l = ["hest", ["h", "e", "s", "t"]], i = 0, x, j;
   P.print(J.getInterceptor$as(l).get$length(l));
-  i = 0;
-  while (J.getInterceptor$n(i).$lt(i, J.getInterceptor$as(l).get$length(l))) {
+  while (i < J.getInterceptor$as(l).get$length(l)) {
     x = J.getInterceptor$as(l).$index(l, i);
     j = 0;
-    while (J.getInterceptor$n(j).$lt(j, J.getInterceptor$as(x).get$length(x))) {
+    while (j < J.getInterceptor$as(x).get$length(x)) {
       P.print(J.getInterceptor$as(x).$index(x, j));
-      j = J.getInterceptor$ns(j).$add(j, 1);
+      j = j + 1;
     }
-    i = J.getInterceptor$ns(i).$add(i, 1);
+    i = i + 1;
   }
   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 aa72895..332af73 100644
--- a/tests/compiler/dart2js/js_backend_cps_ir_supercall_test.dart
+++ b/tests/compiler/dart2js/js_backend_cps_ir_supercall_test.dart
@@ -23,7 +23,7 @@
 }""",
 r"""
 function(x) {
-  return V.Base.prototype.m$1.call(this, J.getInterceptor$ns(x).$add(x, 10));
+  return V.Base.prototype.m$1.call(this, x + 10);
 }"""),
 
   // Reenable when we support compiling functions that
diff --git a/tests/compiler/dart2js/mirrors_used_test.dart b/tests/compiler/dart2js/mirrors_used_test.dart
index 653135f..3b2bb39 100644
--- a/tests/compiler/dart2js/mirrors_used_test.dart
+++ b/tests/compiler/dart2js/mirrors_used_test.dart
@@ -86,6 +86,7 @@
         ];
     JavaScriptBackend backend = compiler.backend;
     Iterable<String> nativeNames = nativeClasses.map(backend.namer.className);
+    expectedNames = expectedNames.map(backend.namer.asName).toList();
     expectedNames.addAll(nativeNames);
 
     Set recordedNames = new Set()
diff --git a/tests/compiler/dart2js/mock_compiler.dart b/tests/compiler/dart2js/mock_compiler.dart
index 3eb6a81..3d879df 100644
--- a/tests/compiler/dart2js/mock_compiler.dart
+++ b/tests/compiler/dart2js/mock_compiler.dart
@@ -9,6 +9,7 @@
 import 'dart:collection';
 
 import 'package:compiler/compiler.dart' as api;
+import 'package:compiler/src/constants/expressions.dart';
 import 'package:compiler/src/elements/elements.dart';
 import 'package:compiler/src/js_backend/js_backend.dart'
     show JavaScriptBackend;
@@ -360,6 +361,12 @@
   void remove(Node node) {
     map.remove(node);
   }
+
+  List<ConstantExpression> get constants {
+    List<ConstantExpression> list = <ConstantExpression>[];
+    forEachConstantNode((_, c) => list.add(c));
+    return list;
+  }
 }
 
 // The mock compiler does not split the program in output units.
@@ -382,9 +389,9 @@
       sourceFile = compiler.sourceFiles[uri.toString()];
     }
     if (sourceFile != null && begin != null && end != null) {
-      print(sourceFile.getLocationMessage(message, begin, end));
+      print('${kind}: ${sourceFile.getLocationMessage(message, begin, end)}');
     } else {
-      print(message);
+      print('${kind}: $message');
     }
   };
 }
diff --git a/tests/compiler/dart2js/patch_test.dart b/tests/compiler/dart2js/patch_test.dart
index 167b096..6f59878 100644
--- a/tests/compiler/dart2js/patch_test.dart
+++ b/tests/compiler/dart2js/patch_test.dart
@@ -8,6 +8,7 @@
 import "package:compiler/src/dart2jslib.dart";
 import "package:compiler/src/elements/elements.dart";
 import "package:compiler/src/tree/tree.dart";
+import "package:compiler/src/types/types.dart";
 import "mock_compiler.dart";
 import "mock_libraries.dart";
 import 'package:compiler/src/elements/modelx.dart';
@@ -868,28 +869,28 @@
     // Check that a method just in the patch class is a target for a
     // typed selector.
     Selector selector = new Selector.call('method', compiler.coreLibrary, 0);
-    TypedSelector typedSelector = new TypedSelector.exact(cls, selector, world);
+    TypeMask typeMask = new TypeMask.exact(cls, world);
     FunctionElement method = cls.implementation.lookupLocalMember('method');
-    method.computeSignature(compiler);
+    method.computeType(compiler);
     Expect.isTrue(selector.applies(method, world));
-    Expect.isTrue(typedSelector.applies(method, world));
+    Expect.isTrue(typeMask.canHit(method, selector, world));
 
     // Check that the declaration method in the declaration class is a target
     // for a typed selector.
     selector = new Selector.call('clear', compiler.coreLibrary, 0);
-    typedSelector = new TypedSelector.exact(cls, selector, world);
+    typeMask = new TypeMask.exact(cls, world);
     method = cls.lookupLocalMember('clear');
-    method.computeSignature(compiler);
+    method.computeType(compiler);
     Expect.isTrue(selector.applies(method, world));
-    Expect.isTrue(typedSelector.applies(method, world));
+    Expect.isTrue(typeMask.canHit(method, selector, world));
 
     // Check that the declaration method in the declaration class is a target
     // for a typed selector on a subclass.
     cls = ensure(compiler, "B", compiler.coreLibrary.find);
     cls.ensureResolved(compiler);
-    typedSelector = new TypedSelector.exact(cls, selector, world);
+    typeMask = new TypeMask.exact(cls, world);
     Expect.isTrue(selector.applies(method, world));
-    Expect.isTrue(typedSelector.applies(method, world));
+    Expect.isTrue(typeMask.canHit(method, selector, world));
   }));
 }
 
@@ -953,16 +954,12 @@
     ClassElement clsA = compiler.coreLibrary.find("A");
     ClassElement clsB = compiler.coreLibrary.find("B");
 
-    Selector forwardCall = new Selector.callConstructor("forward",
-        compiler.coreLibrary);
-    ConstructorElement forward = clsA.lookupConstructor(forwardCall);
+    ConstructorElement forward = clsA.lookupConstructor("forward");
     ConstructorElement target = forward.effectiveTarget;
     Expect.isTrue(target.isPatch);
     Expect.equals("patchTarget", target.name);
 
-    Selector forwardTwoCall = new Selector.callConstructor("forwardTwo",
-        compiler.coreLibrary);
-    ConstructorElement forwardTwo = clsA.lookupConstructor(forwardTwoCall);
+    ConstructorElement forwardTwo = clsA.lookupConstructor("forwardTwo");
     target = forwardTwo.effectiveTarget;
     Expect.isFalse(forwardTwo.isErroneous);
     Expect.isFalse(target.isPatch);
diff --git a/tests/compiler/dart2js/resolver_test.dart b/tests/compiler/dart2js/resolver_test.dart
index dd41c57..5084fe3 100644
--- a/tests/compiler/dart2js/resolver_test.dart
+++ b/tests/compiler/dart2js/resolver_test.dart
@@ -2,18 +2,19 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import "package:expect/expect.dart";
 import 'dart:async';
-import "package:async_helper/async_helper.dart";
 import 'dart:collection';
 
-import "package:compiler/src/resolution/resolution.dart";
-import "compiler_helper.dart";
-import "parser_helper.dart";
-
+import 'package:async_helper/async_helper.dart';
+import 'package:expect/expect.dart';
+import 'package:compiler/src/constants/expressions.dart';
 import 'package:compiler/src/dart_types.dart';
 import 'package:compiler/src/elements/modelx.dart';
+import 'package:compiler/src/resolution/resolution.dart';
+
+import 'compiler_helper.dart';
 import 'link_helper.dart';
+import 'parser_helper.dart';
 
 Node buildIdentifier(String name) => new Identifier(scan(name));
 
@@ -40,17 +41,15 @@
   return MockCompiler.create((MockCompiler compiler) {
     ResolverVisitor visitor = compiler.resolverVisitor();
     ResolutionResult result = visitor.visit(createLocals(variables));
-    Element element = result != null ? result.element : null;
     // A VariableDefinitions does not have an element.
-    Expect.equals(null, element);
+    Expect.equals(const NoneResult(), result);
     Expect.equals(variables.length, map(visitor).length);
 
     for (final variable in variables) {
       final name = variable[0];
       Identifier id = buildIdentifier(name);
       ResolutionResult result = visitor.visit(id);
-      final VariableElement variableElement =
-          result != null ? result.element : null;
+      final VariableElement variableElement = result.element;
       MethodScope scope = visitor.scope;
       Expect.equals(variableElement, scope.elements[name]);
     }
@@ -91,6 +90,7 @@
     testCantAssignMethods,
     testCantAssignFinalAndConsts,
     testAwaitHint,
+    testConstantExpressions,
   ], (f) => f()));
 }
 
@@ -318,8 +318,8 @@
   return MockCompiler.create((MockCompiler compiler) {
     ResolverVisitor visitor = compiler.resolverVisitor();
     Node tree = parseStatement("if (true) { var a = 1; var b = 2; }");
-    ResolutionResult element = visitor.visit(tree);
-    Expect.equals(null, element);
+    ResolutionResult result = visitor.visit(tree);
+    Expect.equals(const NoneResult(), result);
     MethodScope scope = visitor.scope;
     Expect.equals(0, scope.elements.length);
     Expect.equals(2, map(visitor).length);
@@ -333,11 +333,11 @@
   return MockCompiler.create((MockCompiler compiler) {
     ResolverVisitor visitor = compiler.resolverVisitor();
     Node tree = parseStatement("{ var a = 1; if (true) { a; } }");
-    ResolutionResult element = visitor.visit(tree);
-    Expect.equals(null, element);
+    ResolutionResult result = visitor.visit(tree);
+    Expect.equals(const NoneResult(), result);
     MethodScope scope = visitor.scope;
     Expect.equals(0, scope.elements.length);
-    Expect.equals(3, map(visitor).length);
+    Expect.equals(2, map(visitor).length);
     List<Element> elements = map(visitor).values.toList();
     Expect.equals(elements[0], elements[1]);
   });
@@ -347,8 +347,8 @@
   return MockCompiler.create((MockCompiler compiler) {
     ResolverVisitor visitor = compiler.resolverVisitor();
     Node tree = parseStatement("{ var a = 1; if (true) { var a = 1; } }");
-    ResolutionResult element = visitor.visit(tree);
-    Expect.equals(null, element);
+    ResolutionResult result = visitor.visit(tree);
+    Expect.equals(const NoneResult(), result);
     MethodScope scope = visitor.scope;
     Expect.equals(0, scope.elements.length);
     Expect.equals(2, map(visitor).length);
@@ -362,11 +362,11 @@
     ResolverVisitor visitor = compiler.resolverVisitor();
     If tree =
         parseStatement("if (true) { var a = 1; a; } else { var a = 2; a;}");
-    ResolutionResult element = visitor.visit(tree);
-    Expect.equals(null, element);
+    ResolutionResult result = visitor.visit(tree);
+    Expect.equals(const NoneResult(), result);
     MethodScope scope = visitor.scope;
     Expect.equals(0, scope.elements.length);
-    Expect.equals(6, map(visitor).length);
+    Expect.equals(4, map(visitor).length);
 
     Block thenPart = tree.thenPart;
     List statements1 = thenPart.statements.nodes.toList();
@@ -419,7 +419,7 @@
 
     MethodScope scope = visitor.scope;
     Expect.equals(0, scope.elements.length);
-    Expect.equals(9, map(visitor).length);
+    Expect.equals(7, map(visitor).length);
 
     VariableDefinitions initializer = tree.initializer;
     Node iNode = initializer.definitions.nodes.head;
@@ -437,35 +437,27 @@
 
     // for (int i = 0; i < 10; i = i + 1) { i = 5; };
     //                 ^
-    checkIdentifier(iElement, nodes[1], elements[1]);
-
-    // for (int i = 0; i < 10; i = i + 1) { i = 5; };
-    //                 ^
-    checkSend(iElement, nodes[2], elements[2]);
+    checkSend(iElement, nodes[1], elements[1]);
 
     // for (int i = 0; i < 10; i = i + 1) { i = 5; };
     //                         ^
-    checkIdentifier(iElement, nodes[3], elements[3]);
+    checkIdentifier(iElement, nodes[2], elements[2]);
 
     // for (int i = 0; i < 10; i = i + 1) { i = 5; };
     //                             ^
-    checkIdentifier(iElement, nodes[4], elements[4]);
-
-    // for (int i = 0; i < 10; i = i + 1) { i = 5; };
-    //                             ^
-    checkSend(iElement, nodes[5], elements[5]);
+    checkSend(iElement, nodes[3], elements[3]);
 
     // for (int i = 0; i < 10; i = i + 1) { i = 5; };
     //                         ^^^^^^^^^
-    checkSendSet(iElement, nodes[6], elements[6]);
+    checkSendSet(iElement, nodes[4], elements[4]);
 
     // for (int i = 0; i < 10; i = i + 1) { i = 5; };
     //                                      ^
-    checkIdentifier(iElement, nodes[7], elements[7]);
+    checkIdentifier(iElement, nodes[5], elements[5]);
 
     // for (int i = 0; i < 10; i = i + 1) { i = 5; };
     //                                      ^^^^^
-    checkSendSet(iElement, nodes[8], elements[8]);
+    checkSendSet(iElement, nodes[6], elements[6]);
   });
 }
 
@@ -927,7 +919,7 @@
                int bar;
                A() : this.foo = bar;
              }""";
-      return resolveConstructor(script, "A a = new A();", "A", "", 3,
+      return resolveConstructor(script, "A a = new A();", "A", "", 2,
           expectedWarnings: [],
           expectedErrors: [MessageKind.NO_INSTANCE_AVAILABLE]);
     },
@@ -999,6 +991,63 @@
   ], (f) => f());
 }
 
+Future testConstantExpressions() {
+  const Map<String, List<String>> testedConstants = const {
+    'null': const ['null'],
+    'true': const ['true'],
+    '0': const ['0'],
+    '0.0': const ['0.0'],
+    '"foo"': const ['"foo"'],
+    '#a': const ['#a'],
+    '0 + 1': const ['0', '1', '0 + 1'],
+    '0 * 1': const ['0', '1', '0 * 1'],
+    '0 * 1 + 2': const ['0', '1', '0 * 1', '2', '0 * 1 + 2'],
+    '0 + 1 * 2': const ['0', '1', '2', '1 * 2', '0 + 1 * 2'],
+    '-(1)': const ['1', '-1'],
+    '-(1 * 4)': const ['1', '4', '1 * 4', '-(1 * 4)'],
+    'true ? 0 : 1': const ['true', '0', '1', 'true ? 0 : 1'],
+    '"a" "b"': const ['"a"', '"b"', '"ab"'],
+    '"a" "b" "c"': const ['"a"', '"b"', '"c"', '"bc"', r'"a${"bc"}"'],
+    r'"a${0}b"': const ['"a"', '0', '"b"', r'"a${0}b"'],
+    r'"a${0}b${1}"': const ['"a"', '0', '"b"', '1', '""', r'"a${0}b${1}"'],
+    'true || false': const ['true', 'false', 'true || false'],
+    'true && false': const ['true', 'false', 'true && false'],
+    '!true': const ['true', '!true'],
+    'const []': const ['const []'],
+    'const <int>[]': const ['const <int>[]'],
+    'const [0, 1, 2]': const ['0', '1', '2', 'const [0, 1, 2]'],
+    'const <int>[0, 1, 2]': const ['0', '1', '2', 'const <int>[0, 1, 2]'],
+    'const {}': const ['const {}'],
+    'const <String, int>{}': const ['const <String, int>{}'],
+    'const {"a": 0, "b": 1, "c": 2}':
+        const ['"a"', '0', '"b"', '1', '"c"', '2',
+               'const {"a": 0, "b": 1, "c": 2}'],
+    'const <String, int>{"a": 0, "b": 1, "c": 2}':
+        const ['"a"', '0', '"b"', '1', '"c"', '2',
+               'const <String, int>{"a": 0, "b": 1, "c": 2}'],
+  };
+  return Future.forEach(testedConstants.keys, (String constant) {
+    return MockCompiler.create((MockCompiler compiler) {
+      CollectingTreeElements elements =
+          compiler.resolveStatement("main() => $constant;");
+      List<String> expectedConstants = testedConstants[constant];
+      Expect.equals(0, compiler.warnings.length);
+      Expect.equals(0, compiler.errors.length);
+      List<ConstantExpression> constants = elements.constants;
+      String constantsText =
+          '[${constants.map((c) => c.getText()).join(', ')}]';
+      Expect.equals(expectedConstants.length, constants.length,
+          "Expected ${expectedConstants.length} constants for `${constant}` "
+          "found $constantsText.");
+      for (int index = 0; index < expectedConstants.length; index++) {
+        Expect.equals(expectedConstants[index], constants[index].getText(),
+            "Expected ${expectedConstants} for `$constant`, "
+            "found $constantsText.");
+      }
+    });
+  });
+}
+
 map(ResolverVisitor visitor) {
   CollectingTreeElements elements = visitor.registry.mapping;
   return elements.map;
diff --git a/tests/compiler/dart2js/semantic_visitor_test.dart b/tests/compiler/dart2js/semantic_visitor_test.dart
index 21ab642..69fad43 100644
--- a/tests/compiler/dart2js/semantic_visitor_test.dart
+++ b/tests/compiler/dart2js/semantic_visitor_test.dart
@@ -184,11 +184,6 @@
   VisitKind.VISIT_SUPER_METHOD_SETTER_COMPOUND,

   VisitKind.VISIT_SUPER_METHOD_SETTER_PREFIX,

   VisitKind.VISIT_SUPER_METHOD_SETTER_POSTFIX,

-  // Invalid use of setters is currently reported through an erroneous element.

-  VisitKind.VISIT_STATIC_SETTER_INVOKE,

-  VisitKind.VISIT_STATIC_SETTER_GET,

-  VisitKind.VISIT_TOP_LEVEL_SETTER_GET,

-  VisitKind.VISIT_TOP_LEVEL_SETTER_INVOKE,

   // The constant expressions of assignment to constant type literals cannot be

   // handled the compile constant evaluator.

   VisitKind.VISIT_CLASS_TYPE_LITERAL_SET,

@@ -344,7 +339,9 @@
         }

         Expect.listEquals(expectedVisits, visitor.visits,

             "In test:\n"

-            "${library.compilationUnit.script.text}");

+            "${library.compilationUnit.script.text}\n\n"

+            "Expected: $expectedVisits\n"

+            "Found: ${visitor.visits}");

         unvisitedKinds.removeAll(visitor.visits.map((visit) => visit.method));

       }

       if (element.isAbstractField) {

@@ -400,6 +397,7 @@
 

   VISIT_LOCAL_FUNCTION_GET,

   VISIT_LOCAL_FUNCTION_INVOKE,

+  VISIT_LOCAL_FUNCTION_INCOMPATIBLE_INVOKE,

   VISIT_LOCAL_FUNCTION_DECL,

   VISIT_CLOSURE_DECL,

   VISIT_LOCAL_FUNCTION_SET,

diff --git a/tests/compiler/dart2js/semantic_visitor_test_send_data.dart b/tests/compiler/dart2js/semantic_visitor_test_send_data.dart
index e99f58b..ebad789 100644
--- a/tests/compiler/dart2js/semantic_visitor_test_send_data.dart
+++ b/tests/compiler/dart2js/semantic_visitor_test_send_data.dart
@@ -60,6 +60,11 @@
                     element: 'function(m#o)',

                     arguments: '(null,42)',

                     selector: 'CallStructure(arity=2)')),

+    const Test('m() { o(a) {}; o(null, 42); }',

+        const Visit(VisitKind.VISIT_LOCAL_FUNCTION_INCOMPATIBLE_INVOKE,

+                    element: 'function(m#o)',

+                    arguments: '(null,42)',

+                    selector: 'CallStructure(arity=2)')),

     // TODO(johnniwinther): Expect [VISIT_LOCAL_FUNCTION_SET] instead.

     const Test('m() { o(a, b) {}; o = 42; }',

         const Visit(VisitKind.VISIT_UNRESOLVED_SET,

@@ -104,6 +109,30 @@
                     element: 'field(C#o)')),

     const Test(

         '''

+        class C {

+          var o;

+        }

+        m() => C.o;

+        ''',

+        const Visit(VisitKind.VISIT_UNRESOLVED_GET,

+                    name: 'o')),

+    const Test(

+        '''

+        class C {

+          C.o();

+        }

+        m() => C.o;

+        ''',

+        const Visit(VisitKind.VISIT_UNRESOLVED_GET,

+                    name: 'o')),

+    const Test(

+        '''

+        class C {}

+        m() => C.this;

+        ''',

+        null),

+    const Test(

+        '''

         class C { static var o; }

         m() { C.o = 42; }

         ''',

@@ -178,6 +207,13 @@
         const Visit(VisitKind.VISIT_STATIC_FIELD_INVOKE,

                     element: 'field(C#o)',

                     arguments: '(null,42)')),

+    const Test(

+        '''

+        class C {}

+        m() => C.this(null, 42);

+        ''',

+        const Visit(VisitKind.VISIT_UNRESOLVED_INVOKE,

+                    name: 'this', arguments: '(null,42)')),

     // TODO(johnniwinther): Expect [VISIT_FINAL_STATIC_FIELD_SET] instead.

     const Test(

         '''

@@ -333,7 +369,6 @@
         const Visit(VisitKind.VISIT_UNRESOLVED_SET,

                     name: 'o',

                     rhs: '42')),

-    // TODO(johnniwinther): Expected [VISIT_STATIC_SETTER_GET] instead.

     const Test(

         '''

         class C {

@@ -341,8 +376,8 @@
         }

         m() => C.o;

         ''',

-        const Visit(VisitKind.VISIT_UNRESOLVED_GET,

-                    name: 'o')),

+        const Visit(VisitKind.VISIT_STATIC_SETTER_GET,

+                    element: 'setter(C#o)')),

     const Test.clazz(

         '''

         class C {

@@ -350,8 +385,9 @@
           m() => o;

         }

         ''',

-        const Visit(VisitKind.VISIT_UNRESOLVED_GET,

-                    name: 'o')),

+        const Visit(VisitKind.VISIT_STATIC_SETTER_GET,

+                    element: 'setter(C#o)')),

+

     const Test.clazz(

         '''

         class C {

@@ -359,8 +395,8 @@
           m() => C.o;

         }

         ''',

-        const Visit(VisitKind.VISIT_UNRESOLVED_GET,

-                    name: 'o')),

+        const Visit(VisitKind.VISIT_STATIC_SETTER_GET,

+                    element: 'setter(C#o)')),

     const Test.prefix(

         '''

         class C {

@@ -368,8 +404,8 @@
         }

         ''',

         'm() => p.C.o;',

-        const Visit(VisitKind.VISIT_UNRESOLVED_GET,

-                    name: 'o')),

+        const Visit(VisitKind.VISIT_STATIC_SETTER_GET,

+                    element: 'setter(C#o)')),

     const Test(

         '''

         class C { static set o(_) {} }

@@ -446,14 +482,13 @@
         const Visit(VisitKind.VISIT_STATIC_GETTER_INVOKE,

                     element: 'getter(C#o)',

                     arguments: '(null,42)')),

-    // TODO(johnniwinther): Expect [VISIT_STATIC_SETTER_INVOKE] instead.

     const Test(

         '''

         class C { static set o(_) {} }

         m() => C.o(null, 42);

         ''',

-        const Visit(VisitKind.VISIT_UNRESOLVED_INVOKE,

-                    name: 'o',

+        const Visit(VisitKind.VISIT_STATIC_SETTER_INVOKE,

+                    element: 'setter(C#o)',

                     arguments: '(null,42)')),

     const Test.clazz(

         '''

@@ -462,8 +497,8 @@
           m() { o(null, 42); }

         }

         ''',

-        const Visit(VisitKind.VISIT_UNRESOLVED_INVOKE,

-                    name: 'o',

+        const Visit(VisitKind.VISIT_STATIC_SETTER_INVOKE,

+                    element: 'setter(C#o)',

                     arguments: '(null,42)')),

     const Test.clazz(

         '''

@@ -472,8 +507,8 @@
           m() { C.o(null, 42); }

         }

         ''',

-        const Visit(VisitKind.VISIT_UNRESOLVED_INVOKE,

-                    name: 'o',

+        const Visit(VisitKind.VISIT_STATIC_SETTER_INVOKE,

+                    element: 'setter(C#o)',

                     arguments: '(null,42)')),

     const Test.prefix(

         '''

@@ -482,8 +517,8 @@
         }

         ''',

         'm() { p.C.o(null, 42); }',

-        const Visit(VisitKind.VISIT_UNRESOLVED_INVOKE,

-                    name: 'o',

+        const Visit(VisitKind.VISIT_STATIC_SETTER_INVOKE,

+                    element: 'setter(C#o)',

                     arguments: '(null,42)')),

   ],

   'Static functions': const [

@@ -720,8 +755,8 @@
         set o(_) {}

         m() => o;

         ''',

-        const Visit(VisitKind.VISIT_UNRESOLVED_GET,

-                    name: 'o')),

+        const Visit(VisitKind.VISIT_TOP_LEVEL_SETTER_GET,

+                    element: 'setter(o)')),

     const Test.prefix(

         '''

         set o(_) {}

@@ -786,8 +821,8 @@
         set o(_) {}

         m() => o(null, 42);

         ''',

-        const Visit(VisitKind.VISIT_UNRESOLVED_INVOKE,

-                    name: 'o',

+        const Visit(VisitKind.VISIT_TOP_LEVEL_SETTER_INVOKE,

+                    element: 'setter(o)',

                     arguments: '(null,42)')),

     const Test.prefix(

         '''

@@ -1237,10 +1272,14 @@
     const Test(

         '''

         class C {}

-        m() => C;

+        m() => (C).hashCode;

         ''',

-        const Visit(VisitKind.VISIT_CLASS_TYPE_LITERAL_GET,

-                    constant: 'C')),

+        const [

+          const Visit(VisitKind.VISIT_DYNAMIC_PROPERTY_GET,

+                      receiver: '(C)', name: 'hashCode'),

+          const Visit(VisitKind.VISIT_CLASS_TYPE_LITERAL_GET,

+                      constant: 'C'),

+        ]),

   ],

   'Typedef type literals': const [

     // Typedef type literals

@@ -3413,6 +3452,22 @@
         ]),

     const Test(

         '''

+        class C {

+          static var b;

+        }

+        m(a) => C?.b;

+        ''',

+        const [

+          const Visit(

+              VisitKind.VISIT_IF_NOT_NULL_DYNAMIC_PROPERTY_GET,

+              receiver: 'C',

+              name: 'b'),

+          const Visit(

+              VisitKind.VISIT_CLASS_TYPE_LITERAL_GET,

+              constant: 'C'),

+        ]),

+    const Test(

+        '''

         m(a) => a?.b = 42;

         ''',

         const [

diff --git a/tests/compiler/dart2js/semantic_visitor_test_send_visitor.dart b/tests/compiler/dart2js/semantic_visitor_test_send_visitor.dart
index 196df43..511b1f7 100644
--- a/tests/compiler/dart2js/semantic_visitor_test_send_visitor.dart
+++ b/tests/compiler/dart2js/semantic_visitor_test_send_visitor.dart
@@ -298,7 +298,21 @@
       arg) {

     visits.add(new Visit(VisitKind.VISIT_LOCAL_FUNCTION_INVOKE,

         element: function, arguments: arguments, selector: callStructure));

-    apply(arguments, arg);

+    super.visitLocalFunctionInvoke(

+        node, function, arguments, callStructure, arg);

+  }

+

+  @override

+  visitLocalFunctionIncompatibleInvoke(

+      Send node,

+      LocalFunctionElement function,

+      NodeList arguments,

+      CallStructure callStructure,

+      arg) {

+    visits.add(new Visit(VisitKind.VISIT_LOCAL_FUNCTION_INCOMPATIBLE_INVOKE,

+        element: function, arguments: arguments, selector: callStructure));

+    super.visitLocalFunctionInvoke(

+        node, function, arguments, callStructure, arg);

   }

 

   @override

diff --git a/tests/compiler/dart2js/simple_inferrer_test.dart b/tests/compiler/dart2js/simple_inferrer_test.dart
index 33fb4fad..5999741 100644
--- a/tests/compiler/dart2js/simple_inferrer_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_test.dart
@@ -618,7 +618,7 @@
   returnNum1(true);
   returnNum2(true);
   returnInt1(true);
-  returnInt2(true);
+  returnInt2();
   returnInt3(true);
   returnInt4();
   returnDouble(true);
@@ -667,7 +667,7 @@
   returnAsTypedef();
   returnTopLevelGetter();
   testDeadCode();
-  testLabeledIf();
+  testLabeledIf(true);
   testSwitch1();
   testSwitch2();
   testSwitch3();
@@ -727,6 +727,7 @@
 void main() {
   Uri uri = new Uri(scheme: 'source');
   var compiler = compilerFor(TEST, uri);
+  compiler.diagnosticHandler = createHandler(compiler, TEST);
   asyncTest(() => compiler.runCompiler(uri).then((_) {
     var typesTask = compiler.typesTask;
     var typesInferrer = typesTask.typesInferrer;
diff --git a/tests/compiler/dart2js/static_closure_test.dart b/tests/compiler/dart2js/static_closure_test.dart
index 9581ac9..5bf9171 100644
--- a/tests/compiler/dart2js/static_closure_test.dart
+++ b/tests/compiler/dart2js/static_closure_test.dart
@@ -18,6 +18,6 @@
     // If this test fail, please take a look at the use of
     // toStringWrapper in captureStackTrace in js_helper.dart.
     Expect.isTrue(code.contains(
-        new RegExp(r'print\([$A-Z]+\.main\$closure\(\)\);')), code);
+        new RegExp(r'print\([$A-Z]+\.lib___main\$closure\(\)\);')), code);
   }));
 }
diff --git a/tests/compiler/dart2js_extra/consistent_index_error_array_test.dart b/tests/compiler/dart2js_extra/consistent_index_error_array_test.dart
new file mode 100644
index 0000000..90b9ac2
--- /dev/null
+++ b/tests/compiler/dart2js_extra/consistent_index_error_array_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:expect/expect.dart";
+import "dart:typed_data";
+
+// Test that optimized indexing and slow path indexing produce the same error.
+
+@NoInline()
+@AssumeDynamic()
+confuse(x) => x;
+
+class TooHigh {
+  static load1() {
+    var a = confuse(true) ? [10,11] : [10,11,12,13,14];
+    try {
+      // dynamic receiver causes method to be called via interceptor.
+      return confuse(a)[3];
+    } catch (e) {
+      return e;
+    }
+    Expect.fail('unreached');
+  }
+
+  static load2() {
+    try {
+      confuse(load2x)(3);
+    } catch (e) {
+      return e;
+    }
+    Expect.fail('unreached');
+  }
+  static load2x(i) {
+    var a = confuse(true) ? [10,11] : [10,11,12,13,14];
+    // 'a' is inferred as JSArray of unknown length so has optimized check.
+    return a[i];
+  }
+
+  static test() {
+    var e1 = load1();
+    var e2 = load2();
+    Expect.equals('$e1', '$e2', '\n  A: "$e1"\n  B: "$e2"\n');
+  }
+}
+
+class Negative {
+  static load1() {
+    var a = confuse(true) ? [10,11] : [10,11,12,13,14];
+    try {
+      // dynamic receiver causes method to be called via interceptor.
+      return confuse(a)[-3];
+    } catch (e) {
+      return e;
+    }
+    Expect.fail('unreached');
+  }
+
+  static load2() {
+    try {
+      confuse(load2x)(-3);
+    } catch (e) {
+      return e;
+    }
+    Expect.fail('unreached');
+  }
+  static load2x(i) {
+    var a = confuse(true) ? [10,11] : [10,11,12,13,14];
+    // 'a' is inferred as JSArray of unknown length so has optimized check.
+    return a[i];
+  }
+
+  static test() {
+    var e1 = load1();
+    var e2 = load2();
+    Expect.equals('$e1', '$e2', '\n  A: "$e1"\n  B: "$e2"\n');
+  }
+}
+
+class Empty {
+  static load1() {
+    var a = confuse(true) ? [] : [10,11,12,13,14];
+    try {
+      // dynamic receiver causes method to be called via interceptor.
+      return confuse(a)[-3];
+    } catch (e) {
+      return e;
+    }
+    Expect.fail('unreached');
+  }
+
+  static load2() {
+    try {
+      confuse(load2x)(-3);
+    } catch (e) {
+      return e;
+    }
+    Expect.fail('unreached');
+  }
+  static load2x(i) {
+    var a = confuse(true) ? [] : [10,11,12,13,14];
+    // 'a' is inferred as JSArray of unknown length so has optimized check.
+    return a[i];
+  }
+
+  static test() {
+    var e1 = load1();
+    var e2 = load2();
+    Expect.equals('$e1', '$e2', '\n  A: "$e1"\n  B: "$e2"\n');
+  }
+}
+
+class BadType {
+  static load1() {
+    var a = confuse(true) ? [10,11] : [10,11,12,13,14];
+    try {
+      // dynamic receiver causes method to be called via interceptor.
+      return confuse(a)['a'];
+    } catch (e) {
+      return e;
+    }
+    Expect.fail('unreached');
+  }
+
+  static load2() {
+    try {
+      confuse(load2x)('a');
+    } catch (e) {
+      return e;
+    }
+    Expect.fail('unreached');
+  }
+  static load2x(i) {
+    var a = confuse(true) ? [10,11] : [10,11,12,13,14];
+    // 'a' is inferred as JSArray of unknown length so has optimized check.
+    return a[i];
+  }
+
+  static test() {
+    var e1 = load1();
+    var e2 = load2();
+    Expect.equals('$e1', '$e2', '\n  A: "$e1"\n  B: "$e2"\n');
+  }
+}
+
+main() {
+  TooHigh.test();
+  Negative.test();
+  Empty.test();
+  BadType.test();
+}
diff --git a/tests/compiler/dart2js_extra/consistent_index_error_string_test.dart b/tests/compiler/dart2js_extra/consistent_index_error_string_test.dart
new file mode 100644
index 0000000..836a13d
--- /dev/null
+++ b/tests/compiler/dart2js_extra/consistent_index_error_string_test.dart
@@ -0,0 +1,147 @@
+// 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";
+import "dart:typed_data";
+
+// Test that optimized indexing and slow path indexing produce the same error.
+
+@NoInline()
+@AssumeDynamic()
+confuse(x) => x;
+
+class TooHigh {
+  static load1() {
+    var a = confuse(true) ? 'AB' : 'ABCDE';
+    try {
+      return confuse(a)[3];  // dynamic receiver for indexer.
+    } catch (e) {
+      return e;
+    }
+    Expect.fail('unreached');
+  }
+
+  static load2() {
+    try {
+      confuse(load2x)(3);
+    } catch (e) {
+      return e;
+    }
+    Expect.fail('unreached');
+  }
+  static load2x(i) {
+    var a = confuse(true) ? 'AB' : 'ABCDE';
+    return a[i];  // 'a' is String of unknown length.
+  }
+
+  static test() {
+    var e1 = load1();
+    var e2 = load2();
+    print("  A: '$e1'\n  B: '$e2'");
+    Expect.equals('$e1', '$e2');
+  }
+}
+
+class Negative {
+  static load1() {
+    var a = confuse(true) ? 'AB' : 'ABCDE';
+    try {
+      return confuse(a)[-3];  // dynamic receiver for indexer.
+    } catch (e) {
+      return e;
+    }
+    Expect.fail('unreached');
+  }
+
+  static load2() {
+    try {
+      confuse(load2x)(-3);
+    } catch (e) {
+      return e;
+    }
+    Expect.fail('unreached');
+  }
+  static load2x(i) {
+    var a = confuse(true) ? 'AB' : 'ABCDE';
+    return a[i];  // 'a' is String of unknown length.
+  }
+
+  static test() {
+    var e1 = load1();
+    var e2 = load2();
+    print("  A: '$e1'\n  B: '$e2'");
+    Expect.equals('$e1', '$e2');
+  }
+}
+
+class Empty {
+  static load1() {
+    var a = confuse(true) ? '' : 'ABCDE';
+    try {
+      return confuse(a)[-3];  // dynamic receiver for indexer.
+    } catch (e) {
+      return e;
+    }
+    Expect.fail('unreached');
+  }
+
+  static load2() {
+    try {
+      confuse(load2x)(-3);
+    } catch (e) {
+      return e;
+    }
+    Expect.fail('unreached');
+  }
+  static load2x(i) {
+    var a = confuse(true) ? '' : 'ABCDE';
+    return a[i];  // 'a' is String of unknown length.
+  }
+
+  static test() {
+    var e1 = load1();
+    var e2 = load2();
+    print("  A: '$e1'\n  B: '$e2'");
+    Expect.equals('$e1', '$e2');
+  }
+}
+
+class BadType {
+  static load1() {
+    var a = confuse(true) ? 'AB' : 'ABCDE';
+    try {
+      return confuse(a)['a'];  // dynamic receiver for indexer.
+    } catch (e) {
+      return e;
+    }
+    Expect.fail('unreached');
+  }
+
+  static load2() {
+    try {
+      confuse(load2x)('a');
+    } catch (e) {
+      return e;
+    }
+    Expect.fail('unreached');
+  }
+  static load2x(i) {
+    var a = confuse(true) ? 'AB' : 'ABCDE';
+    return a[i];  // 'a' is String of unknown length.
+  }
+
+  static test() {
+    var e1 = load1();
+    var e2 = load2();
+    print("  A: '$e1'\n  B: '$e2'");
+    Expect.equals('$e1', '$e2');
+  }
+}
+
+main() {
+  TooHigh.test();
+  Negative.test();
+  Empty.test();
+  BadType.test();
+}
diff --git a/tests/compiler/dart2js_extra/consistent_index_error_typed_list_test.dart b/tests/compiler/dart2js_extra/consistent_index_error_typed_list_test.dart
new file mode 100644
index 0000000..1cd949d
--- /dev/null
+++ b/tests/compiler/dart2js_extra/consistent_index_error_typed_list_test.dart
@@ -0,0 +1,159 @@
+// 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";
+import "dart:typed_data";
+
+// Test that optimized indexing and slow path indexing produce the same error.
+
+@NoInline()
+@AssumeDynamic()
+confuse(x) => x;
+
+class TooHigh {
+  static load1() {
+    var a = confuse(true)
+        ? new Uint8List.fromList([10,11])
+        : new Uint8List.fromList([10,11,12,13,14]);
+    try {
+      return confuse(a)[3];  // dynamic receiver for indexer.
+    } catch (e) {
+      return e;
+    }
+    Expect.fail('unreached');
+  }
+
+  static load2() {
+    try {
+      confuse(load2x)(3);
+    } catch (e) {
+      return e;
+    }
+    Expect.fail('unreached');
+  }
+  static load2x(i) {
+    var a = confuse(true)
+        ? new Uint8List.fromList([10,11])
+        : new Uint8List.fromList([10,11,12,13,14]);
+    return a[i];
+  }
+
+  static test() {
+    var e1 = load1();
+    var e2 = load2();
+    Expect.equals('$e1', '$e2', '\n  A: "$e1"\n  B: "$e2"\n');
+  }
+}
+
+class Negative {
+  static load1() {
+    var a = confuse(true)
+        ? new Uint8List.fromList([10,11])
+        : new Uint8List.fromList([10,11,12,13,14]);
+    try {
+      return confuse(a)[-3];  // dynamic receiver for indexer.
+    } catch (e) {
+      return e;
+    }
+    Expect.fail('unreached');
+  }
+
+  static load2() {
+    try {
+      confuse(load2x)(-3);
+    } catch (e) {
+      return e;
+    }
+    Expect.fail('unreached');
+  }
+  static load2x(i) {
+    var a = confuse(true)
+        ? new Uint8List.fromList([10,11])
+        : new Uint8List.fromList([10,11,12,13,14]);
+    return a[i];
+  }
+
+  static test() {
+    var e1 = load1();
+    var e2 = load2();
+    Expect.equals('$e1', '$e2', '\n  A: "$e1"\n  B: "$e2"\n');
+  }
+}
+
+class Empty {
+  static load1() {
+    var a = confuse(true)
+        ? new Uint8List.fromList([])
+        : new Uint8List.fromList([10,11,12,13,14]);
+    try {
+      return confuse(a)[-3];  // dynamic receiver for indexer.
+    } catch (e) {
+      return e;
+    }
+    Expect.fail('unreached');
+  }
+
+  static load2() {
+    try {
+      confuse(load2x)(-3);
+    } catch (e) {
+      return e;
+    }
+    Expect.fail('unreached');
+  }
+  static load2x(i) {
+    var a = confuse(true)
+        ? new Uint8List.fromList([])
+        : new Uint8List.fromList([10,11,12,13,14]);
+    return a[i];
+  }
+
+  static test() {
+    var e1 = load1();
+    var e2 = load2();
+    Expect.equals('$e1', '$e2', '\n  A: "$e1"\n  B: "$e2"\n');
+  }
+}
+
+class BadType {
+  static load1() {
+    var a = confuse(true)
+        ? new Uint8List.fromList([10,11])
+        : new Uint8List.fromList([10,11,12,13,14]);
+    try {
+      return confuse(a)['a'];  // dynamic receiver for indexer.
+    } catch (e) {
+      return e;
+    }
+    Expect.fail('unreached');
+  }
+
+  static load2() {
+    try {
+      confuse(load2x)('a');
+    } catch (e) {
+      return e;
+    }
+    Expect.fail('unreached');
+  }
+  static load2x(i) {
+    var a = confuse(true)
+        ? new Uint8List.fromList([10,11])
+        : new Uint8List.fromList([10,11,12,13,14]);
+    return a[i];
+  }
+
+  static test() {
+    var e1 = load1();
+    var e2 = load2();
+    Expect.equals('$e1', '$e2', '\n  A: "$e1"\n  B: "$e2"\n');
+  }
+}
+
+main() {
+  TooHigh.test();
+  Negative.test();
+  Empty.test();
+  BadType.test();
+}
diff --git a/tests/compiler/dart2js_extra/dart2js_extra.status b/tests/compiler/dart2js_extra/dart2js_extra.status
index b848d9d..2399b15 100644
--- a/tests/compiler/dart2js_extra/dart2js_extra.status
+++ b/tests/compiler/dart2js_extra/dart2js_extra.status
@@ -4,7 +4,6 @@
 
 [ $compiler == dart2js ]
 16407_test: Fail # Issue 16407
-23432_test: Fail # Issue 23432
 class_test: Fail
 statements_test: Fail
 typed_locals_test: Fail
@@ -61,63 +60,71 @@
 deferred_fail_and_retry_test: SkipByDesign # Uses eval to simulate failed loading.
 deferred_fail_and_retry_worker_test: SkipByDesign # Uses eval to simulate failed loading.
 
+[ $host_checked && $compiler == dart2js && $cps_ir ]
+21724_test: Crash # Please triage this failure.
+
 [ $compiler == dart2js && $cps_ir ]
-10216a_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-10216b_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-12320_test: Crash #  Unhandled node
+11673_test: RuntimeError # Cannot read property 'prototype' of undefined
+12320_test: RuntimeError # Cannot read property 'prototype' of undefined
 16407_test: Pass # Please triage this failure.
-17094_test: RuntimeError # Please triage this failure.
-21666_test: Crash # Instance of 'TypeOperator': type check unimplemented for fInt.
-22868_test: Crash #  cannot handle async/sync*/async* functions
-22895_test: Crash #  cannot handle async/sync*/async* functions
-22917_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-23264_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-23486_test/01: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-23486_test/02: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-23486_test/03: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-LayoutTests_fast_mediastream_getusermedia_t01_test/01: Crash # Please triage this failure.
-async_stacktrace_test/asyncStar: Crash #  cannot handle async/sync*/async* functions
-async_stacktrace_test/none: Crash #  cannot handle async/sync*/async* functions
-bailout8_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-bound_closure_interceptor_type_test: Crash # Instance of 'TypeOperator': type check unimplemented for IntToT<String>.
-checked_accessor_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
+17645_test: RuntimeError # Please triage this failure.
+19191_test: RuntimeError # Please triage this failure.
+21166_test: RuntimeError # Please triage this failure.
+21579_test: RuntimeError # Please triage this failure.
+21666_test: Crash # Internal Error: No default constructor available.
+22487_test: RuntimeError # Cannot read property 'prototype' of undefined
+22868_test: Crash # (main()async{var clo...  cannot handle async/sync*/async* functions
+22895_test: Crash # (main()async{var clo...  cannot handle async/sync*/async* functions
+23404_test: RuntimeError # Cannot read property 'prototype' of undefined
+23432_test: RuntimeError # Please triage this failure.
+LayoutTests_fast_mediastream_getusermedia_t01_test/none: RuntimeError # Cannot read property 'prototype' of undefined
+async_stacktrace_test/asyncStar: Crash # (runTests()async{awa...  cannot handle async/sync*/async* functions
+async_stacktrace_test/none: Crash # (runTests()async{awa...  cannot handle async/sync*/async* functions
+bounds_check_test/none: RuntimeError # Please triage this failure.
+closure5_test: RuntimeError # Cannot read property 'prototype' of undefined
+closure_capture4_test: RuntimeError # Please triage this failure.
 closure_capture5_test: Crash # (i=0): For-loop variable captured in loop header
-code_motion_exception_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-conditional_send_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-constant_javascript_semantics2_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-constant_javascript_semantics3_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-deferred/deferred_class_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-deferred/deferred_constant2_test: RuntimeError # Please triage this failure.
-deferred/deferred_constant3_test: RuntimeError # Please triage this failure.
-deferred/deferred_constant4_test: RuntimeError # Please triage this failure.
-deferred/deferred_function_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-deferred/deferred_mirrors1_test: RuntimeError # Please triage this failure.
-deferred/deferred_overlapping_test: RuntimeError # Please triage this failure.
-generics_factories_test: Crash # Please triage this failure.
-inference_nsm_mirrors_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-inferrer_is_int_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-interface_type_optimization_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirror_invalid_field_access2_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirror_invalid_field_access3_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirror_invalid_field_access4_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirror_invalid_field_access_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirror_invalid_invoke2_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirror_invalid_invoke3_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirror_invalid_invoke_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirror_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors_declarations_filtering_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors_used_closure_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors_used_native_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-no_such_method_mirrors_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-reflect_native_types_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-regress/4492_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-regress/4515_1_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-regress/4515_2_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-regress/4740_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-super_constructor1_test: RuntimeError # Please triage this failure.
-switch_test/01: Crash #  Unhandled node
-switch_test/02: Crash #  Unhandled node
-switch_test/none: Crash # (switch (val){}): Unhandled node
-this_phi_elimination_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-type_constant_switch_test/none: Crash # (switch (v){}): Unhandled node
-typevariable_factory_test: Crash # Please triage this failure.
+closure_type_reflection2_test: Crash # Internal Error: No default constructor available.
+closure_type_reflection_test: Crash # Internal Error: No default constructor available.
+compound_operator_index_test: RuntimeError # Please triage this failure.
+conditional_send_test: RuntimeError # receiver.get$_collection$_nums is not a function
+conflict_index_test: RuntimeError # Please triage this failure.
+deferred/deferred_class_test: RuntimeError # receiver.get$_collection$_nums is not a function
+deferred/deferred_constant2_test: RuntimeError # receiver.get$_collection$_nums is not a function
+deferred/deferred_constant3_test: RuntimeError # receiver.get$_collection$_nums is not a function
+deferred/deferred_constant4_test: RuntimeError # receiver.get$_collection$_nums is not a function
+deferred/deferred_function_test: RuntimeError # receiver.get$_collection$_nums is not a function
+deferred/deferred_mirrors1_test: RuntimeError # receiver.get$_collection$_nums is not a function
+deferred/deferred_mirrors2_test: Crash # Internal Error: No default constructor available.
+deferred/deferred_overlapping_test: RuntimeError # receiver.get$_collection$_nums is not a function
+deferred_fail_and_retry_test: Crash # Internal Error: No default constructor available.
+deferred_fail_and_retry_worker_test: Crash # Internal Error: No default constructor available.
+for_test: RuntimeError # Please triage this failure.
+if_null_test: RuntimeError # receiver.get$_collection$_nums is not a function
+index_test: RuntimeError # Please triage this failure.
+int_index_test/none: RuntimeError # Please triage this failure.
+invalid_length_negative_test: Fail # Please triage this failure.
+is_check_instanceof_test: RuntimeError # Please triage this failure.
+list_factory_test: RuntimeError # Please triage this failure.
+mirror_invalid_field_access2_test: RuntimeError # Please triage this failure.
+mirror_invalid_field_access3_test: Crash # Internal Error: No default constructor available.
+mirror_invalid_field_access4_test: RuntimeError # Please triage this failure.
+mirror_invalid_field_access_test: Crash # Internal Error: No default constructor available.
+mirror_invalid_invoke3_test: Crash # Internal Error: No default constructor available.
+mirror_invalid_invoke_test: Crash # Internal Error: No default constructor available.
+mirror_printer_test: Crash # Internal Error: No default constructor available.
+mirror_test: Crash # Internal Error: No default constructor available.
+mirror_type_inference_field2_test: Crash # Internal Error: No default constructor available.
+mirror_type_inference_field_test: Crash # Internal Error: No default constructor available.
+mirror_type_inference_function_test: Crash # Internal Error: No default constructor available.
+mirrors_declarations_filtering_test: Crash # Internal Error: No default constructor available.
+mirrors_used_native_test: RuntimeError # Please triage this failure.
+mirrors_used_warning2_test: RuntimeError # receiver.get$_nums is not a function
+mirrors_used_warning_test/minif: RuntimeError # receiver.get$_nums is not a function
+mirrors_used_warning_test/none: RuntimeError # receiver.get$_nums is not a function
+no_such_method_mirrors_test: RuntimeError # Please triage this failure.
+reflect_native_types_test: Crash # Internal Error: No default constructor available.
+runtime_type_test: RuntimeError # Cannot read property 'prototype' of undefined
+string_interpolation_opt1_test: RuntimeError # Please triage this failure.
+switch_test/none: Crash # (switch (val){foo:ba...  continue to a labeled switch case
+timer_test: RuntimeError # receiver.get$_collection$_nums is not a function
diff --git a/tests/compiler/dart2js_extra/identical_trace_test.dart b/tests/compiler/dart2js_extra/identical_trace_test.dart
new file mode 100644
index 0000000..8fc86cb
--- /dev/null
+++ b/tests/compiler/dart2js_extra/identical_trace_test.dart
@@ -0,0 +1,23 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:expect/expect.dart';
+
+main() {
+  var st1;
+  try {
+    try {
+      throw 'bad';
+    } catch (e, st) {
+      st1 = st;
+      rethrow;
+    }
+    Expect.fail('Exception expected');
+  } catch (e, st2) {
+    Expect.equals(st1, st2);
+    Expect.identical(st1, st2);
+    return;
+  }
+  Expect.fail('Exception expected');
+}
diff --git a/tests/compiler/dart2js_native/dart2js_native.status b/tests/compiler/dart2js_native/dart2js_native.status
index d078f3b..9798091 100644
--- a/tests/compiler/dart2js_native/dart2js_native.status
+++ b/tests/compiler/dart2js_native/dart2js_native.status
@@ -21,108 +21,26 @@
 compute_this_script_test: Skip # Issue 17458
 
 [ $compiler == dart2js && $cps_ir ]
-abstract_class_test: Crash # unsupported element kind: foo:function
-bound_closure_super_test: Crash # unsupported element kind: inscrutable:function
-bound_closure_test: Crash # unsupported element kind: inscrutable:function
-browser_compat_1_prepatched_test: Crash # unsupported element kind: getTagCallCount:function
-browser_compat_1_unpatched_test: Crash # unsupported element kind: getTagCallCount:function
-browser_compat_2_test: Crash # unsupported element kind: getTagCallCount:function
-catch_javascript_null_stack_trace_test: Crash # (JS('','(function () {throw null;})()')): handleStaticFunctionInvoke: foreign: function(JS)
-core_type_check_native_test: Crash # unsupported element kind: makeD:function
-downcast_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-event_loop_test: Crash # unsupported element kind: foo:function
-fake_thing_2_test: Crash # unsupported element kind: make3:function
-fake_thing_test: Crash # unsupported element kind: make2:function
-field_type2_test: Crash # unsupported element kind: makeNode:function
-field_type_test: Crash # unsupported element kind: makeNode:function
-fixup_get_tag_test: Crash # unsupported element kind: token:function
-foreign_test: Crash # (JS('bool','isNaN(#)',isNaN)): handleStaticFunctionInvoke: foreign: function(JS)
-hash_code_test: Crash # unsupported element kind: makeA:function
-inference_of_helper_methods_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-issue9182_test: Crash # unsupported element kind: makeA:function
-js_const_test: Crash # (JS('String',r'#.replace(#, #)',s1,re,fToUpper)): handleStaticFunctionInvoke: foreign: function(JS)
-jsobject_test: Crash # unsupported element kind: makeQ:function
-mirror_intercepted_field_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-native_call_arity1_frog_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-native_call_arity2_frog_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-native_call_arity3_frog_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-native_checked_arguments1_frog_test: Crash # unsupported element kind: cmp:function
-native_checked_fields_frog_test: Crash # unsupported element kind: makeB:function
-native_class_avoids_hidden_name_frog_test: Crash # unsupported element kind: makeB:function
-native_class_fields_2_test: Crash # unsupported element kind: makeA:function
-native_class_fields_3_test: Crash # unsupported element kind: makeA:function
-native_class_fields_test: Crash # unsupported element kind: makeA:function
-native_class_inheritance1_frog_test: Crash # unsupported element kind: makeB2:function
-native_class_inheritance2_frog_test: Crash # unsupported element kind: foo:function
-native_class_inheritance3_frog_test: Crash # unsupported element kind: foo:function
-native_class_inheritance4_frog_test: Crash # unsupported element kind: makeB:function
-native_class_is_check1_frog_test: Crash # unsupported element kind: makeA:function
-native_class_is_check3_frog_test: Crash # unsupported element kind: makeB:function
-native_class_with_dart_methods_frog_test: Crash # unsupported element kind: makeA:function
-native_closure_identity_frog_test: Crash # unsupported element kind: invoke:function
-native_constructor_name_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-native_equals_frog_test: Crash # unsupported element kind: makeA:function
-native_exception2_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-native_exception_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-native_exceptions1_frog_test: Crash # unsupported element kind: op:function
-native_field_invocation2_test: Crash # unsupported element kind: nativeId:function
-native_field_invocation3_test: Crash # unsupported element kind: makeCC:function
-native_field_invocation4_test: Crash # unsupported element kind: nativeId:function
-native_field_invocation5_test: Crash # unsupported element kind: nativeFirst:function
-native_field_invocation6_test: Crash # unsupported element kind: nativeFirst:function
-native_field_invocation_test: Crash # unsupported element kind: nativeId:function
-native_field_name_test: Crash # unsupported element kind: makeA:function
-native_field_optimization_test: Crash # unsupported element kind: makeFoo:function
-native_field_rename_1_frog_test: Crash # unsupported element kind: native_key_method:function
-native_field_rename_2_frog_test: Crash # unsupported element kind: native_key_method:function
-native_library_same_name_used_frog_test: Crash # (JS('creates:Impl; returns:I;','makeI()')): handleStaticFunctionInvoke: foreign: function(JS)
-native_method_inlining_test: Crash # unsupported element kind: makeA:function
-native_method_rename1_frog_test: Crash # unsupported element kind: baz:function
-native_method_rename2_frog_test: Crash # unsupported element kind: foo:function
-native_method_rename3_frog_test: Crash # unsupported element kind: foo:function
-native_method_with_keyword_name_test: Crash # unsupported element kind: makeA:function
-native_mirror_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-native_missing_method1_frog_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-native_missing_method2_frog_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-native_mixin_field_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-native_mixin_multiple2_test: Crash # unsupported element kind: makeB:function
-native_mixin_multiple3_test: Crash # unsupported element kind: makeC:function
-native_mixin_multiple_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-native_mixin_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-native_mixin_with_plain_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-native_named_constructors2_frog_test: Crash # unsupported element kind: foo:function
-native_named_constructors3_frog_test: Crash # unsupported element kind: foo:function
-native_no_such_method_exception2_frog_test: Crash # unsupported element kind: makeB:function
-native_no_such_method_exception3_frog_test: Crash # unsupported element kind: makeA:function
-native_no_such_method_exception4_frog_test: Crash # unsupported element kind: makeA:function
-native_no_such_method_exception5_frog_test: Crash # unsupported element kind: makeA:function
-native_no_such_method_exception_frog_test: Crash # unsupported element kind: makeA:function
-native_novel_html_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-native_null_closure_frog_test: Crash # unsupported element kind: invoke:function
-native_null_frog_test: Crash # unsupported element kind: returnZero:function
-native_property_frog_test: Crash # (JS('int','#._z',this)): handleStaticFunctionInvoke: foreign: function(JS)
-native_to_string_frog_test: Crash # unsupported element kind: makeA:function
-native_use_native_name_in_table_frog_test: Crash # unsupported element kind: makeB:function
-native_window1_frog_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-native_window2_frog_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-native_wrapping_function3_frog_test: Crash # unsupported element kind: foo2:function
-native_wrapping_function_frog_test: Crash # unsupported element kind: foo2:function
-oddly_named_fields_test: Crash # unsupported element kind: makeNativeClassWithOddNames:function
-optimization_hints_test: Crash # (JS('','String("in main function")')): handleStaticFunctionInvoke: foreign: function(JS)
-rti_only_native_test: Crash #  try/finally
-runtimetype_test: Crash # (JS('A','#',makeA())): handleStaticFunctionInvoke: foreign: function(JS)
-static_methods_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-subclassing_1_test: Crash # unsupported element kind: makeC:function
-subclassing_2_test: Crash # unsupported element kind: makeB:function
-subclassing_3_test: Crash # unsupported element kind: makeB:function
-subclassing_4_test: Crash # unsupported element kind: makeB:function
-subclassing_5_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-subclassing_constructor_1_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-subclassing_constructor_2_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-subclassing_super_call_test: Crash # (JS('','#(#)',constructor,b1)): handleStaticFunctionInvoke: foreign: function(JS)
-subclassing_super_field_1_test: Crash # (JS('','#(#)',constructor,b)): handleStaticFunctionInvoke: foreign: function(JS)
-subclassing_super_field_2_test: Crash # (JS('','#(#)',constructor,b)): handleStaticFunctionInvoke: foreign: function(JS)
-subclassing_type_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-super_call_test: Crash # unsupported element kind: makeD:function
-super_property_test: Crash # unsupported element kind: makeB:function
-undefined_bailout_test: Crash # (JS('','void 0')): handleStaticFunctionInvoke: foreign: function(JS)
+compute_this_script_test: RuntimeError # receiver.get$_collection$_nums is not a function
+event_loop_test: RuntimeError # receiver.get$_collection$_nums is not a function
+inference_of_helper_methods_test: RuntimeError # Please triage this failure.
+internal_library_test: RuntimeError # receiver.get$_collection$_nums is not a function
+mirror_intercepted_field_test: Crash # Internal Error: No default constructor available.
+native_closure_identity_frog_test: RuntimeError # invoke is not a function
+native_exception2_test: RuntimeError # Please triage this failure.
+native_exception_test: RuntimeError # J.getInterceptor(...).toString$0 is not a function
+native_method_inlining_test: RuntimeError # Please triage this failure.
+native_mirror_test: Crash # Internal Error: No default constructor available.
+native_mixin_field_test: RuntimeError # Please triage this failure.
+native_mixin_with_plain_test: RuntimeError # Please triage this failure.
+native_no_such_method_exception3_frog_test: RuntimeError # Please triage this failure.
+native_wrapping_function3_frog_test: RuntimeError # invoke is not a function
+native_wrapping_function_frog_test: RuntimeError # invoke is not a function
+optimization_hints_test: RuntimeError # Please triage this failure.
+static_methods_test: RuntimeError # invoke is not a function
+subclassing_constructor_1_test: RuntimeError # Please triage this failure.
+subclassing_constructor_2_test: RuntimeError # Please triage this failure.
+subclassing_super_call_test: RuntimeError # this.get$afield is not a function
+subclassing_super_field_1_test: RuntimeError # Please triage this failure.
+subclassing_super_field_2_test: RuntimeError # Please triage this failure.
+super_call_test: RuntimeError # this.bar$0 is not a function
diff --git a/tests/corelib/corelib.status b/tests/corelib/corelib.status
index f107d2c..b9428c1 100644
--- a/tests/corelib/corelib.status
+++ b/tests/corelib/corelib.status
@@ -205,128 +205,138 @@
 [ $mode == debug ]
 regexp/pcre_test: Pass, Slow # Timeout. Issue 22008
 
-[ $mode == debug && $runtime == vm]
-big_integer_arith_vm_test/gcd: Pass, Crash # Issue 23693
-big_integer_arith_vm_test/modInv: Pass, Crash # Issue 23693
-
 [ $runtime == vm && $arch == simarmv5te ]
 int_parse_radix_test/*: Pass, Slow
 big_integer_parsed_mul_div_vm_test: Pass, Slow
 
 [ $compiler == dart2js && $cps_ir ]
-apply2_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
+apply2_test: RuntimeError # Please triage this failure.
+apply3_test: RuntimeError # Please triage this failure.
+apply4_test: RuntimeError # Please triage this failure.
+apply_test: RuntimeError # Please triage this failure.
+collection_from_test: RuntimeError # Please triage this failure.
+collection_length_test: RuntimeError # Please triage this failure.
 collection_removes_test: RuntimeError # Please triage this failure.
-const_list_remove_range_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-const_list_set_range_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-core_runtime_types_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-date_time_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-double_ceil2_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-double_floor2_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-double_parse_test/01: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-double_parse_test/none: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-double_round2_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-double_truncate2_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-duration2_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-duration_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-error_stack_trace1_test: Pass # Please triage this failure.
-error_stack_trace_test: Crash # (switch (5){case 5:nested();default:Expect.fail("Should not reach");}): Unhandled node
-expando_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-growable_list_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-has_next_iterator_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-hash_map2_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-hash_set_test/01: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-hash_set_test/none: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-hash_set_type_check_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-hashcode_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-int_parse_radix_test/01: Crash # Please triage this failure.
-int_parse_radix_test/02: Crash # Please triage this failure.
-int_parse_radix_test/none: Crash # Please triage this failure.
-iterable_element_at_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-iterable_empty_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-iterable_expand_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-iterable_first_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-iterable_first_where_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-iterable_fold_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-iterable_last_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-iterable_last_where_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-iterable_reduce_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
+collection_test: RuntimeError # Please triage this failure.
+collection_to_string_test: RuntimeError # Please triage this failure.
+core_runtime_types_test: RuntimeError # Please triage this failure.
+date_time2_test: RuntimeError # Cannot read property 'prototype' of undefined
+date_time3_test: RuntimeError # Cannot read property 'prototype' of undefined
+date_time4_test: RuntimeError # Cannot read property 'prototype' of undefined
+date_time7_test: RuntimeError # Cannot read property 'prototype' of undefined
+date_time_parse_test: RuntimeError # Cannot read property 'prototype' of undefined
+error_stack_trace1_test: Pass # H.unwrapException(...).get$stackTrace is not a function
+for_in_test: RuntimeError # Please triage this failure.
+hash_set_test/none: RuntimeError # Please triage this failure.
+hashcode_test: RuntimeError # Please triage this failure.
+indexed_list_access_test: RuntimeError # Please triage this failure.
+int_parse_radix_test/01: Crash # Invalid argument(s)
+int_parse_radix_test/02: Crash # Invalid argument(s)
+int_parse_radix_test/none: Crash # Invalid argument(s)
+iterable_contains_test: RuntimeError # Please triage this failure.
+iterable_empty_test: RuntimeError # Please triage this failure.
+iterable_fold_test: RuntimeError # Please triage this failure.
+iterable_join_test: RuntimeError # Please triage this failure.
+iterable_mapping_test: RuntimeError # Please triage this failure.
+iterable_reduce_test: RuntimeError # Please triage this failure.
 iterable_return_type_test/none: RuntimeError # Please triage this failure.
-iterable_single_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-iterable_single_where_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-iterable_skip_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-iterable_take_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
+iterable_skip_test: RuntimeError # Please triage this failure.
+iterable_test: RuntimeError # Please triage this failure.
 iterable_to_list_test: RuntimeError # Please triage this failure.
 iterable_to_set_test: RuntimeError # Please triage this failure.
-linked_hash_map_from_iterables_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-list_as_map_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-list_fill_range_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-list_first_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-list_fixed_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-list_for_each_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-list_get_range_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-list_growable_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-list_insert_all_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-list_insert_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-list_iterators_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-list_last_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-list_remove_range_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-list_removeat_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-list_replace_range_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-list_set_all_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-list_set_range_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-list_sublist_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-list_test/01: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-list_test/none: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-list_to_string2_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-list_to_string_test: RuntimeError # Please triage this failure.
-map_from_iterables_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-map_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-map_to_string_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
+iterable_tostring_test: RuntimeError # Please triage this failure.
+json_map_test: Crash # Internal Error: No default constructor available.
+linked_hash_map_test: RuntimeError # Please triage this failure.
+list_as_map_test: RuntimeError # Please triage this failure.
+list_contains_argument_order_test: RuntimeError # Please triage this failure.
+list_fill_range_test: RuntimeError # Please triage this failure.
+list_for_each_test: RuntimeError # Please triage this failure.
+list_get_range_test: RuntimeError # Please triage this failure.
+list_growable_test: RuntimeError # Please triage this failure.
+list_index_of2_test: RuntimeError # Please triage this failure.
+list_index_of_test: RuntimeError # Please triage this failure.
+list_insert_all_test: RuntimeError # Please triage this failure.
+list_insert_test: RuntimeError # Please triage this failure.
+list_iterators_test: RuntimeError # Please triage this failure.
+list_literal_is_growable_test: RuntimeError # Please triage this failure.
+list_literal_test: RuntimeError # Please triage this failure.
+list_map_test: RuntimeError # Please triage this failure.
+list_remove_range_test: RuntimeError # Please triage this failure.
+list_removeat_test: RuntimeError # Please triage this failure.
+list_replace_range_test: RuntimeError # Please triage this failure.
+list_reversed_test: RuntimeError # Please triage this failure.
+list_set_all_test: RuntimeError # Please triage this failure.
+list_set_range_test: RuntimeError # Please triage this failure.
+list_sort_test: RuntimeError # Please triage this failure.
+list_test/01: RuntimeError # this.get$length is not a function
+list_test/none: RuntimeError # this.get$length is not a function
+list_to_string2_test: RuntimeError # Please triage this failure.
+list_unmodifiable_test: RuntimeError # Please triage this failure.
+main_test: RuntimeError # receiver.get$_collection$_nums is not a function
+map_test: Crash # Internal Error: No default constructor available.
 map_values2_test: RuntimeError # Please triage this failure.
 map_values3_test: RuntimeError # Please triage this failure.
 map_values4_test: RuntimeError # Please triage this failure.
-null_nosuchmethod_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-num_clamp_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-num_parse_test/01: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-num_parse_test/none: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-queue_first_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-queue_last_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-queue_single_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-queue_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-regexp/compile-crash_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-regexp/compile_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-regexp/early-acid3-86_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-regexp/invalid-range-in-class_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-regexp/multiline_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-regexp/no-extensions_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-regexp/pcre_test: Crash # Please triage this failure.
-regexp/range-out-of-order_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-regexp/regexp_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-set_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-set_to_string_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-splay_tree_from_iterables_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-splay_tree_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-string_buffer_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-string_codeunits_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-string_fromcharcode_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-string_fromcharcodes_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-string_operations_with_null_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-string_pattern_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-string_replace_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-string_runes_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-string_source_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-string_substring_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-string_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
+null_test: RuntimeError # Cannot read property 'prototype' of undefined
+queue_first_test: RuntimeError # Please triage this failure.
+queue_iterator_test: RuntimeError # Please triage this failure.
+queue_last_test: RuntimeError # Please triage this failure.
+queue_single_test: RuntimeError # Please triage this failure.
+queue_test: RuntimeError # Please triage this failure.
+range_error_test: RuntimeError # Please triage this failure.
+reg_exp_first_match_test: RuntimeError # Cannot read property 'prototype' of undefined
+reg_exp_group_test: RuntimeError # Cannot read property 'prototype' of undefined
+reg_exp_groups_test: RuntimeError # Please triage this failure.
+reg_exp_string_match_test: RuntimeError # Cannot read property 'prototype' of undefined
+regexp/capture-3_test: RuntimeError # Cannot read property 'prototype' of undefined
+regexp/capture_test: RuntimeError # Please triage this failure.
+regexp/extended-characters-match_test: RuntimeError # Cannot read property 'prototype' of undefined
+regexp/global_test: RuntimeError # Please triage this failure.
+regexp/many-brackets_test: RuntimeError # Please triage this failure.
+regexp/non-bmp_test: RuntimeError # Cannot read property 'prototype' of undefined
+regexp/non-capturing-groups_test: RuntimeError # Please triage this failure.
+regexp/pcre_test: Crash # Stack Overflow
+regexp/regexp_test: RuntimeError # Please triage this failure.
+regexp/regress-regexp-construct-result_test: RuntimeError # Cannot read property 'prototype' of undefined
+regexp/results-cache_test: RuntimeError # Cannot read property 'prototype' of undefined
+regexp/stack-overflow2_test: RuntimeError # Please triage this failure.
+regexp/stack-overflow_test: RuntimeError # Cannot read property 'prototype' of undefined
+regexp/unicode-handling_test: RuntimeError # Cannot read property 'prototype' of undefined
+regress_11099_test: RuntimeError # Please triage this failure.
+set_test: RuntimeError # Please triage this failure.
+set_to_string_test: RuntimeError # Please triage this failure.
+shuffle_test: RuntimeError # Please triage this failure.
+sort_test: RuntimeError # Please triage this failure.
+splay_tree_test: RuntimeError # Please triage this failure.
+stacktrace_fromstring_test: RuntimeError # receiver.get$_collection$_nums is not a function
+stopwatch2_test: RuntimeError # Cannot read property 'prototype' of undefined
+stopwatch_test: RuntimeError # Cannot read property 'prototype' of undefined
+string_codeunits_test: RuntimeError # Please triage this failure.
+string_from_list_test: RuntimeError # Please triage this failure.
+string_fromcharcodes_test: RuntimeError # Please triage this failure.
+string_pattern_test: RuntimeError # Please triage this failure.
+string_replace_all_test: RuntimeError # Cannot read property 'prototype' of undefined
+string_replace_test: RuntimeError # Please triage this failure.
+string_runes_test: RuntimeError # Please triage this failure.
+string_source_test: RuntimeError # Please triage this failure.
+string_split_test: RuntimeError # Please triage this failure.
+string_test: RuntimeError # Please triage this failure.
+string_to_lower_case_test: RuntimeError # Please triage this failure.
+strings_test: RuntimeError # Please triage this failure.
 symbol_operator_test/03: RuntimeError # Please triage this failure.
 symbol_reserved_word_test/03: Pass # Please triage this failure.
-symbol_reserved_word_test/06: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-symbol_reserved_word_test/09: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-symbol_reserved_word_test/12: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-symbol_test/none: Crash # Please triage this failure.
-uri_file_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-uri_ipv4_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-uri_ipv6_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-uri_path_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-uri_query_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-uri_scheme_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-uri_test: Crash # Please triage this failure.
+symbol_reserved_word_test/06: RuntimeError # Please triage this failure.
+symbol_reserved_word_test/09: RuntimeError # Please triage this failure.
+symbol_reserved_word_test/12: RuntimeError # Please triage this failure.
+symbol_test/none: Crash # The null object does not have a getter '_element'.
+uri_base_test: Crash # Invalid argument(s)
+uri_file_test: Crash # Invalid argument(s)
+uri_http_test: Crash # Invalid argument(s)
+uri_ipv4_test: RuntimeError # Please triage this failure.
+uri_ipv6_test: Crash # Invalid argument(s)
+uri_normalize_path_test: RuntimeError # Please triage this failure.
+uri_parse_test: Crash # Invalid argument(s)
+uri_path_test: Crash # Invalid argument(s)
+uri_query_test: Crash # Internal Error: No default constructor available.
+uri_scheme_test: Crash # Invalid argument(s)
+uri_test: Crash # Invalid argument(s)
diff --git a/tests/html/custom/created_callback_test.dart b/tests/html/custom/created_callback_test.dart
index 769b784..4ce85d2 100644
--- a/tests/html/custom/created_callback_test.dart
+++ b/tests/html/custom/created_callback_test.dart
@@ -86,7 +86,7 @@
 <x-b id="u"></x-b>
 <x-c id="v"></x-c>
 <x-b id="w"></x-b>
-""", treeSanitizer: new NullTreeSanitizer());
+""", treeSanitizer: NodeTreeSanitizer.trusted);
 
     upgradeCustomElements(div);
 
@@ -136,7 +136,7 @@
     var tag = ErrorConstructorElement.tag;
     expectGlobalError(() {
       dummy.setInnerHtml('<$tag></$tag>',
-          treeSanitizer: new NullTreeSanitizer());
+          treeSanitizer: NodeTreeSanitizer.trusted);
     });
 
     expect(ErrorConstructorElement.callCount, 1);
diff --git a/tests/html/html.status b/tests/html/html.status
index f7ff39d..8814b56 100644
--- a/tests/html/html.status
+++ b/tests/html/html.status
@@ -17,6 +17,7 @@
 element_animate_test/simple_timing: Fail # Not supported on Dartium
 element_animate_test/omit_timing: Fail # Not supported on Dartium
 element_animate_test/timing_dict: Fail # Not supported on Dartium
+trusted_html_tree_sanitizer_test/untrusted: Fail # We make adoptNode throw to verify it's not being called. That doesn't work on Dartium.
 
 [ $compiler == none && $mode == debug && ($runtime == drt || $runtime == dartium || $runtime == ContentShellOnAndroid) ]
 datalistelement_test: Skip # Issue 20540
@@ -413,148 +414,150 @@
 window_nosuchmethod_test: StaticWarning
 
 [ $compiler == dart2js && $cps_ir ]
-async_spawnuri_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-async_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-audiobuffersourcenode_test: Crash #  try/finally
-audiocontext_test: Crash #  try/finally
-audioelement_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-b_element_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-blob_constructor_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-cache_test: Crash #  try/finally
-callbacks_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-canvas_pixel_array_type_alias_test: Crash #  try/finally
-canvas_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-canvasrenderingcontext2d_test: Crash #  try/finally
-cdata_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-client_rect_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-cross_domain_iframe_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-crypto_test: Crash #  try/finally
-css_rule_list_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-css_test: Crash #  try/finally
-cssstyledeclaration_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-custom/attribute_changed_callback_test: Crash #  try/finally
-custom/constructor_calls_created_synchronously_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-custom/created_callback_test: Crash # (try {test();}catch (e){rethrow;}finally {js.context['testExpectsGlobalError']=false;}): try/finally
-custom/document_register_basic_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-custom/document_register_type_extensions_test: Crash #  try/finally
-custom/element_upgrade_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-custom/entered_left_view_test: Crash #  try/finally
-custom/js_custom_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-custom/mirrors_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-custom_element_method_clash_test: Crash #  try/finally
-custom_element_name_clash_test: Crash #  try/finally
-custom_elements_23127_test: Crash #  try/finally
-custom_elements_test: Crash #  try/finally
-custom_tags_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-dart_object_local_storage_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-datalistelement_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-document_test: Crash #  try/finally
-documentfragment_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-dom_constructors_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-domparser_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-element_add_test: Crash #  try/finally
-element_animate_test: Crash #  try/finally
-element_classes_svg_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-element_classes_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-element_constructor_1_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-element_dimensions_test: Crash #  try/finally
-element_offset_test: Crash #  try/finally
-element_test: Crash #  try/finally
-element_types_constructors1_test: Crash #  try/finally
-element_types_constructors2_test: Crash #  try/finally
-element_types_constructors3_test: Crash #  try/finally
-element_types_constructors4_test: Crash #  try/finally
-element_types_constructors5_test: Crash #  try/finally
-element_types_constructors6_test: Crash #  try/finally
-element_types_test: Crash #  try/finally
-event_customevent_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-event_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-events_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-exceptions_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-fileapi_test: Crash #  try/finally
-filereader_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-fontface_loaded_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-fontface_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-form_data_test: Crash #  try/finally
-form_element_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-geolocation_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-hidden_dom_1_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-hidden_dom_2_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-history_test: Crash #  try/finally
-htmlcollection_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-htmlelement_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-htmloptionscollection_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-indexeddb_1_test: Crash #  try/finally
-indexeddb_2_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-indexeddb_3_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-indexeddb_4_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-indexeddb_5_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-input_element_test: Crash #  try/finally
-instance_of_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-isolates_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-js_interop_1_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-js_test: Crash #  try/finally
-keyboard_event_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-localstorage_test: Crash # (try {fn();}finally {window.localStorage.clear();}): try/finally
-location_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-media_stream_test: Crash #  try/finally
-mediasource_test: Crash #  try/finally
-messageevent_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-mouse_event_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-mutationobserver_test: Crash #  try/finally
-native_gc_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-navigator_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-node_test: Crash #  try/finally
-node_validator_important_if_you_suppress_make_the_bug_critical_test: Crash #  try/finally
-non_instantiated_is_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-notification_test: Crash #  try/finally
-performance_api_test: Crash #  try/finally
-postmessage_structured_test: Crash #  try/finally
-query_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-queryall_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-range_test: Crash #  try/finally
-request_animation_frame_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-rtc_test: Crash #  try/finally
-selectelement_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-serialized_script_value_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-shadow_dom_test: Crash #  try/finally
-shadowroot_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-speechrecognition_test: Crash #  try/finally
-storage_quota_test/missingenumcheck: Crash # Instance of 'TypeOperator': type casts not implemented.
-storage_quota_test/none: Crash # Instance of 'TypeOperator': type casts not implemented.
-storage_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-streams_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-svg_test: Crash #  try/finally
-svgelement_test: Crash #  try/finally
-table_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-text_event_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-touchevent_test: Crash #  try/finally
-track_element_constructor_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-transferables_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-transition_event_test: Crash #  try/finally
-typed_arrays_1_test: Crash #  try/finally
-typed_arrays_2_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-typed_arrays_3_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-typed_arrays_4_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-typed_arrays_5_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-typed_arrays_arraybuffer_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-typed_arrays_dataview_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-typed_arrays_range_checks_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-typed_arrays_simd_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-typing_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-unknownelement_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-uri_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-url_test: Crash #  try/finally
-webgl_1_test: Crash #  try/finally
-websocket_test: Crash #  try/finally
-websql_test: Crash #  try/finally
-wheelevent_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-window_eq_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-window_mangling_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-window_nosuchmethod_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-window_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-worker_api_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-worker_test: Crash #  try/finally
-xhr_cross_origin_test: Crash #  try/finally
-xhr_test: Crash #  try/finally
-xsltprocessor_test: Crash #  try/finally
+async_spawnuri_test: Crash # Invalid argument(s)
+async_test: Crash # Invalid argument(s)
+audiobuffersourcenode_test: Crash # Invalid argument(s)
+audiocontext_test: Crash # Invalid argument(s)
+audioelement_test: Crash # Invalid argument(s)
+b_element_test: Crash # Invalid argument(s)
+blob_constructor_test: Crash # Invalid argument(s)
+cache_test: Crash # Invalid argument(s)
+callbacks_test: Crash # Invalid argument(s)
+canvas_pixel_array_type_alias_test: Crash # Invalid argument(s)
+canvas_test: Crash # Invalid argument(s)
+canvasrenderingcontext2d_test: Crash # Invalid argument(s)
+cdata_test: Crash # Invalid argument(s)
+client_rect_test: Crash # Invalid argument(s)
+cross_domain_iframe_test: Crash # Invalid argument(s)
+crypto_test: Crash # Invalid argument(s)
+css_rule_list_test: Crash # Invalid argument(s)
+css_test: Crash # Invalid argument(s)
+cssstyledeclaration_test: Crash # Invalid argument(s)
+custom/attribute_changed_callback_test: Crash # Invalid argument(s)
+custom/constructor_calls_created_synchronously_test: Crash # Invalid argument(s)
+custom/created_callback_test: Crash # Invalid argument(s)
+custom/document_register_basic_test: Crash # Invalid argument(s)
+custom/document_register_type_extensions_test: Crash # Invalid argument(s)
+custom/element_upgrade_test: Crash # Invalid argument(s)
+custom/entered_left_view_test: Crash # Invalid argument(s)
+custom/js_custom_test: Crash # Invalid argument(s)
+custom/mirrors_test: Crash # Invalid argument(s)
+custom/regress_194523002_test: Crash # Internal Error: No default constructor available.
+custom_element_method_clash_test: Crash # Invalid argument(s)
+custom_element_name_clash_test: Crash # Invalid argument(s)
+custom_elements_23127_test: Crash # Invalid argument(s)
+custom_elements_test: Crash # Invalid argument(s)
+custom_tags_test: Crash # Invalid argument(s)
+dart_object_local_storage_test: Crash # Invalid argument(s)
+datalistelement_test: Crash # Invalid argument(s)
+document_test: Crash # Invalid argument(s)
+documentfragment_test: Crash # Invalid argument(s)
+dom_constructors_test: Crash # Invalid argument(s)
+domparser_test: Crash # Invalid argument(s)
+element_add_test: Crash # Invalid argument(s)
+element_animate_test: Crash # Invalid argument(s)
+element_classes_svg_test: Crash # Invalid argument(s)
+element_classes_test: Crash # Invalid argument(s)
+element_constructor_1_test: Crash # Invalid argument(s)
+element_dimensions_test: Crash # Invalid argument(s)
+element_offset_test: Crash # Invalid argument(s)
+element_test: Crash # Invalid argument(s)
+element_types_constructors1_test: Crash # Invalid argument(s)
+element_types_constructors2_test: Crash # Invalid argument(s)
+element_types_constructors3_test: Crash # Invalid argument(s)
+element_types_constructors4_test: Crash # Invalid argument(s)
+element_types_constructors5_test: Crash # Invalid argument(s)
+element_types_constructors6_test: Crash # Invalid argument(s)
+element_types_test: Crash # Invalid argument(s)
+event_customevent_test: Crash # Invalid argument(s)
+event_test: Crash # Invalid argument(s)
+events_test: Crash # Invalid argument(s)
+exceptions_test: Crash # Invalid argument(s)
+fileapi_test: Crash # Invalid argument(s)
+filereader_test: Crash # Invalid argument(s)
+fontface_loaded_test: Crash # Invalid argument(s)
+fontface_test: Crash # Invalid argument(s)
+form_data_test: Crash # Invalid argument(s)
+form_element_test: Crash # Invalid argument(s)
+geolocation_test: Crash # Invalid argument(s)
+hidden_dom_1_test: Crash # Invalid argument(s)
+hidden_dom_2_test: Crash # Invalid argument(s)
+history_test: Crash # Invalid argument(s)
+htmlcollection_test: Crash # Invalid argument(s)
+htmlelement_test: Crash # Invalid argument(s)
+htmloptionscollection_test: Crash # Invalid argument(s)
+indexeddb_1_test: Crash # Invalid argument(s)
+indexeddb_2_test: Crash # Invalid argument(s)
+indexeddb_3_test: Crash # Invalid argument(s)
+indexeddb_4_test: Crash # Invalid argument(s)
+indexeddb_5_test: Crash # Invalid argument(s)
+input_element_test: Crash # Invalid argument(s)
+instance_of_test: Crash # Invalid argument(s)
+isolates_test: Crash # Invalid argument(s)
+js_interop_1_test: Crash # Invalid argument(s)
+js_test: Crash # Invalid argument(s)
+keyboard_event_test: Crash # Invalid argument(s)
+localstorage_test: Crash # Invalid argument(s)
+location_test: Crash # Invalid argument(s)
+media_stream_test: Crash # Invalid argument(s)
+mediasource_test: Crash # Invalid argument(s)
+messageevent_test: Crash # Invalid argument(s)
+mouse_event_test: Crash # Invalid argument(s)
+mutationobserver_test: Crash # Invalid argument(s)
+native_gc_test: Crash # Invalid argument(s)
+navigator_test: Crash # Invalid argument(s)
+node_test: Crash # Invalid argument(s)
+node_validator_important_if_you_suppress_make_the_bug_critical_test: Crash # Invalid argument(s)
+non_instantiated_is_test: Crash # Invalid argument(s)
+notification_test: Crash # Invalid argument(s)
+performance_api_test: Crash # Invalid argument(s)
+postmessage_structured_test: Crash # Invalid argument(s)
+query_test: Crash # Invalid argument(s)
+queryall_test: Crash # Invalid argument(s)
+range_test: Crash # Invalid argument(s)
+request_animation_frame_test: Crash # Invalid argument(s)
+rtc_test: Crash # Invalid argument(s)
+selectelement_test: Crash # Invalid argument(s)
+serialized_script_value_test: Crash # Invalid argument(s)
+shadow_dom_test: Crash # Invalid argument(s)
+shadowroot_test: Crash # Invalid argument(s)
+speechrecognition_test: Crash # Invalid argument(s)
+storage_quota_test/missingenumcheck: Crash # Invalid argument(s)
+storage_quota_test/none: Crash # Invalid argument(s)
+storage_test: Crash # Invalid argument(s)
+streams_test: Crash # Invalid argument(s)
+svg_test: Crash # Invalid argument(s)
+svgelement_test: Crash # Invalid argument(s)
+table_test: Crash # Invalid argument(s)
+text_event_test: Crash # Invalid argument(s)
+touchevent_test: Crash # Invalid argument(s)
+track_element_constructor_test: Crash # Invalid argument(s)
+transferables_test: Crash # Invalid argument(s)
+transition_event_test: Crash # Invalid argument(s)
+trusted_html_tree_sanitizer_test: Crash # Invalid argument(s)
+typed_arrays_1_test: Crash # Invalid argument(s)
+typed_arrays_2_test: Crash # Invalid argument(s)
+typed_arrays_3_test: Crash # Invalid argument(s)
+typed_arrays_4_test: Crash # Invalid argument(s)
+typed_arrays_5_test: Crash # Invalid argument(s)
+typed_arrays_arraybuffer_test: Crash # Invalid argument(s)
+typed_arrays_dataview_test: Crash # Invalid argument(s)
+typed_arrays_range_checks_test: Crash # Invalid argument(s)
+typed_arrays_simd_test: Crash # Invalid argument(s)
+typing_test: Crash # Invalid argument(s)
+unknownelement_test: Crash # Invalid argument(s)
+uri_test: Crash # Invalid argument(s)
+url_test: Crash # Invalid argument(s)
+webgl_1_test: Crash # Invalid argument(s)
+websocket_test: Crash # Invalid argument(s)
+websql_test: Crash # Invalid argument(s)
+wheelevent_test: Crash # Invalid argument(s)
+window_eq_test: Crash # Invalid argument(s)
+window_mangling_test: Crash # Invalid argument(s)
+window_nosuchmethod_test: Crash # Invalid argument(s)
+window_test: Crash # Invalid argument(s)
+worker_api_test: Crash # Invalid argument(s)
+worker_test: Crash # Invalid argument(s)
+xhr_cross_origin_test: Crash # Invalid argument(s)
+xhr_test: Crash # Invalid argument(s)
+xsltprocessor_test: Crash # Invalid argument(s)
diff --git a/tests/html/node_validator_important_if_you_suppress_make_the_bug_critical_test.dart b/tests/html/node_validator_important_if_you_suppress_make_the_bug_critical_test.dart
index a2a23c6..dfdcbdb 100644
--- a/tests/html/node_validator_important_if_you_suppress_make_the_bug_critical_test.dart
+++ b/tests/html/node_validator_important_if_you_suppress_make_the_bug_critical_test.dart
@@ -14,13 +14,10 @@
 import 'package:unittest/html_individual_config.dart';
 import 'utils.dart';
 
-
-var nullSanitizer = new NullTreeSanitizer();
-
 void validateHtml(String html, String reference, NodeValidator validator) {
   var a = document.body.createFragment(html, validator: validator);
   var b = document.body.createFragment(reference,
-      treeSanitizer: nullSanitizer);
+      treeSanitizer: NodeTreeSanitizer.trusted);
 
   // Prevent a false pass when both the html and the reference both get entirely
   // deleted, which is technically a match, but unlikely to be what we meant.
diff --git a/tests/html/trusted_html_tree_sanitizer_test.dart b/tests/html/trusted_html_tree_sanitizer_test.dart
new file mode 100644
index 0000000..c03e39d
--- /dev/null
+++ b/tests/html/trusted_html_tree_sanitizer_test.dart
@@ -0,0 +1,64 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// This tests HTML validation and sanitization, which is very important
+/// for prevent XSS or other attacks. If you suppress this, or parts of it
+/// please make it a critical bug and bring it to the attention of the
+/// dart:html maintainers.
+library trusted_html_tree_sanitizer_test;
+
+import 'dart:html';
+import 'dart:svg' as svg;
+import 'package:unittest/unittest.dart';
+import 'package:unittest/html_individual_config.dart';
+import 'utils.dart';
+import 'dart:js' as js;
+
+var oldAdoptNode;
+var jsDocument;
+
+/// We want to verify that with the trusted sanitizer we are not
+/// creating a document fragment. So make DocumentFragment operation
+/// throw.
+makeDocumentFragmentAdoptionThrow() {
+  var document = js.context['document'];
+  jsDocument = new js.JsObject.fromBrowserObject(document);
+  oldAdoptNode = jsDocument['adoptNode'];
+  jsDocument['adoptNode'] = null;
+}
+
+restoreOldAdoptNode() {
+  jsDocument['adoptNode'] = oldAdoptNode;
+}
+
+main() {
+  useHtmlIndividualConfiguration();
+
+  group('not_create_document_fragment', () {
+    setUp(makeDocumentFragmentAdoptionThrow);
+    tearDown(restoreOldAdoptNode);
+
+    test('setInnerHtml', () {
+      document.body.setInnerHtml('<div foo="baz">something</div>',
+          treeSanitizer: NodeTreeSanitizer.trusted);
+      expect(document.body.innerHtml, '<div foo="baz">something</div>');
+    });
+
+    test("appendHtml", () {
+      var oldStuff = document.body.innerHtml;
+      var newStuff = '<div rumplestiltskin="value">content</div>';
+      document.body.appendHtml(newStuff,
+          treeSanitizer: NodeTreeSanitizer.trusted);
+      expect(document.body.innerHtml, oldStuff + newStuff);
+    });
+  });
+
+  group('untrusted', () {
+    setUp(makeDocumentFragmentAdoptionThrow);
+    tearDown(restoreOldAdoptNode);
+    test('untrusted', () {
+      expect(() => document.body.innerHtml = "<p>anything</p>", throws);
+    });
+  });
+}
diff --git a/tests/isolate/isolate.status b/tests/isolate/isolate.status
index 5c2a946..58a420a 100644
--- a/tests/isolate/isolate.status
+++ b/tests/isolate/isolate.status
@@ -126,38 +126,58 @@
 package_root_test: SkipByDesign # Uses dart:io.
 
 [ $compiler == dart2js && $cps_ir ]
-count_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-cross_isolate_message_test: Crash #  Unhandled node
-deferred_in_isolate2_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-function_send_test: Crash # (try {p.send(func);}finally {p.send(0);}): try/finally
-handle_error2_test: Crash #  Unhandled node
-handle_error3_test: Crash #  Unhandled node
-handle_error_test: Crash #  Unhandled node
-illegal_msg_function_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-illegal_msg_mirror_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-isolate_complex_messages_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-isolate_current_test: Crash #  Unhandled node
-mandel_isolate_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-message2_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-message3_test/byteBuffer: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-message3_test/constInstance: Crash # Please triage this failure.
-message3_test/constList: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-message3_test/constList_identical: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-message3_test/constMap: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-message3_test/fun: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-message3_test/int32x4: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-message3_test/none: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-message_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-mint_maker_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-nested_spawn2_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-nested_spawn_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-raw_port_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-request_reply_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-spawn_function_custom_class_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-spawn_function_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-spawn_uri_multi_test/01: Crash # Instance of 'TypeOperator': type casts not implemented.
-spawn_uri_multi_test/none: Crash # Instance of 'TypeOperator': type casts not implemented.
-stacktrace_message_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-static_function_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-timer_isolate_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-unresolved_ports_test: Crash # Instance of 'TypeOperator': type casts not implemented.
+bool_from_environment_default_value_test: RuntimeError # receiver.get$_collection$_nums is not a function
+capability_test: RuntimeError # receiver.get$_collection$_nums is not a function
+compile_time_error_test/none: RuntimeError # receiver.get$_collection$_nums is not a function
+count_test: Crash # Invalid argument(s)
+cross_isolate_message_test: Crash # Invalid argument(s)
+deferred_in_isolate2_test: Crash # Invalid argument(s)
+deferred_in_isolate_test: RuntimeError # receiver.get$_collection$_nums is not a function
+function_send_test: RuntimeError # receiver.get$_nums is not a function
+handle_error2_test: RuntimeError # receiver.get$_collection$_nums is not a function
+handle_error3_test: RuntimeError # receiver.get$_collection$_nums is not a function
+handle_error_test: RuntimeError # receiver.get$_collection$_nums is not a function
+illegal_msg_function_test: Crash # Invalid argument(s)
+illegal_msg_mirror_test: Crash # Invalid argument(s)
+int_from_environment_default_value_test: RuntimeError # receiver.get$_collection$_nums is not a function
+isolate_complex_messages_test: Crash # Invalid argument(s)
+isolate_current_test: RuntimeError # receiver.get$_nums is not a function
+isolate_import_test/none: RuntimeError # receiver.get$_collection$_nums is not a function
+issue_22778_test: RuntimeError # receiver.get$_collection$_nums is not a function
+kill2_test: RuntimeError # receiver.get$_collection$_nums is not a function
+kill_self_test: RuntimeError # receiver.get$_collection$_nums is not a function
+kill_test: RuntimeError # receiver.get$_collection$_nums is not a function
+mandel_isolate_test: Crash # Invalid argument(s)
+message2_test: Crash # Invalid argument(s)
+message3_test/byteBuffer: RuntimeError # receiver.get$_collection$_nums is not a function
+message3_test/constInstance: Crash # Invalid argument(s)
+message3_test/fun: RuntimeError # receiver.get$_collection$_nums is not a function
+message3_test/int32x4: RuntimeError # receiver.get$_collection$_nums is not a function
+message3_test/none: RuntimeError # receiver.get$_collection$_nums is not a function
+message_enum_test: RuntimeError # receiver.get$_collection$_nums is not a function
+message_test: Crash # Invalid argument(s)
+mint_maker_test: Crash # Invalid argument(s)
+nested_spawn2_test: Crash # Invalid argument(s)
+nested_spawn_test: Crash # Invalid argument(s)
+object_leak_test: RuntimeError # receiver.get$_collection$_nums is not a function
+ondone_test: RuntimeError # receiver.get$_nums is not a function
+pause_test: RuntimeError # receiver.get$_nums is not a function
+ping_pause_test: RuntimeError # receiver.get$_collection$_nums is not a function
+ping_test: RuntimeError # receiver.get$_collection$_nums is not a function
+port_test: RuntimeError # receiver.get$_collection$_nums is not a function
+raw_port_test: Crash # Invalid argument(s)
+request_reply_test: Crash # Invalid argument(s)
+simple_message_test/none: RuntimeError # receiver.get$_collection$_nums is not a function
+spawn_function_custom_class_test: Crash # Invalid argument(s)
+spawn_function_test: Crash # Invalid argument(s)
+spawn_uri_missing_from_isolate_test: Crash # Invalid argument(s)
+spawn_uri_missing_test: Crash # Invalid argument(s)
+spawn_uri_multi_test/01: Crash # Invalid argument(s)
+spawn_uri_multi_test/none: Crash # Invalid argument(s)
+stacktrace_message_test: Crash # Invalid argument(s)
+start_paused_test: RuntimeError # receiver.get$_nums is not a function
+static_function_test: Crash # Invalid argument(s)
+string_from_environment_default_value_test: RuntimeError # receiver.get$_collection$_nums is not a function
+timer_isolate_test: Crash # Invalid argument(s)
+typed_message_test: RuntimeError # receiver.get$_nums is not a function
+unresolved_ports_test: Crash # Invalid argument(s)
diff --git a/tests/language/conditional_method_invocation_test.dart b/tests/language/conditional_method_invocation_test.dart
index 4bd6f1f..f6844a1 100644
--- a/tests/language/conditional_method_invocation_test.dart
+++ b/tests/language/conditional_method_invocation_test.dart
@@ -53,7 +53,7 @@
 
   // Nor can it be used to access toplevel functions in libraries imported via
   // prefix.
-  Expect.throws(() => h?.topLevelFunction(), noMethod); /// 11: static type warning
+  h?.topLevelFunction(); /// 11: compile-time error
 
   // However, '?.' can be used to access the toString method on the class Type.
   Expect.equals(C?.toString(), (C).toString()); /// 12: ok
diff --git a/tests/language/conditional_property_access_test.dart b/tests/language/conditional_property_access_test.dart
index e821865..0a58a53 100644
--- a/tests/language/conditional_property_access_test.dart
+++ b/tests/language/conditional_property_access_test.dart
@@ -47,7 +47,7 @@
 
   // Nor can it be used to access toplevel properties in libraries imported via
   // prefix.
-  Expect.throws(() => h?.topLevelVar, noMethod); /// 09: static type warning
+  var x = h?.topLevelVar; /// 09: compile-time error
 
   // However, '?.' can be used to access the hashCode getter on the class Type.
   Expect.equals(C?.hashCode, (C).hashCode); /// 10: ok
diff --git a/tests/language/conditional_property_assignment_test.dart b/tests/language/conditional_property_assignment_test.dart
index bf77842..6b34821 100644
--- a/tests/language/conditional_property_assignment_test.dart
+++ b/tests/language/conditional_property_assignment_test.dart
@@ -87,7 +87,7 @@
 
   // Nor can it be used to assign to toplevel properties in libraries imported
   // via prefix.
-  Expect.throws(() => h?.topLevelVar = null, noMethod); /// 20: static type warning
-  Expect.throws(() => h?.topLevelVar += null, noMethod); /// 21: static type warning
-  Expect.throws(() => h?.topLevelVar ??= null, noMethod); /// 22: static type warning
+  h?.topLevelVar = null; /// 20: compile-time error
+  h?.topLevelVar += null; /// 21: compile-time error
+  h?.topLevelVar ??= null; /// 22: compile-time error
 }
diff --git a/tests/language/conditional_property_increment_decrement_test.dart b/tests/language/conditional_property_increment_decrement_test.dart
new file mode 100644
index 0000000..03b48f8
--- /dev/null
+++ b/tests/language/conditional_property_increment_decrement_test.dart
@@ -0,0 +1,74 @@
+// 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.
+
+// Verify semantics of the ?. operator when it appears in a postincrement or
+// preincrement expression (or a postdecrement or predecrement expression).
+
+// SharedOptions=--enable-null-aware-operators
+
+import "package:expect/expect.dart";
+
+class C {
+  int v;
+  C(this.v);
+  static var staticField;
+}
+
+class D {
+  E v;
+  D(this.v);
+}
+
+class E {
+  G operator+(int i) => new I();
+  G operator-(int i) => new I();
+}
+
+class F {}
+
+class G extends E implements F {}
+
+class H {}
+
+class I extends G implements H {}
+
+C nullC() => null;
+
+main() {
+  // Make sure the "none" test fails if assignment to "?." is not implemented.
+  // This makes status files easier to maintain.
+  nullC()?.v = 1;
+
+  // e1?.v++ is equivalent to ((x) => x == null ? null : x.v++)(e1).
+  Expect.equals(null, nullC()?.v++); /// 01: ok
+  { C c = new C(1); Expect.equals(1, c?.v++); Expect.equals(2, c.v); } /// 02: ok
+
+  // The static type of e1?.v++ is the same as the static type of e1.v.
+  { E e1 = new E(); D d = new D(e1); E e2 = d?.v++; Expect.identical(e1, e2); } /// 03: ok
+  { G g = new G(); D d = new D(g); F f = d?.v++; Expect.identical(f, g); } /// 04: static type warning
+
+  // e1?.v-- is equivalent to ((x) => x == null ? null : x.v--)(e1).
+  Expect.equals(null, nullC()?.v--); /// 05: ok
+  { C c = new C(1); Expect.equals(1, c?.v--); Expect.equals(0, c.v); } /// 06: ok
+
+  // The static type of e1?.v-- is the same as the static type of e1.v.
+  { E e1 = new E(); D d = new D(e1); E e2 = d?.v--; Expect.identical(e1, e2); } /// 07: ok
+  { G g = new G(); D d = new D(g); F f = d?.v--; Expect.identical(f, g); } /// 08: static type warning
+
+  // ++e1?.v is equivalent to e1?.v += 1.
+  Expect.equals(null, ++nullC()?.v); /// 09: ok
+  { C c = new C(1); Expect.equals(2, ++c?.v); Expect.equals(2, c.v); } /// 10: ok
+
+  // The static type of ++e1?.v is the same as the static type of e1.v + 1.
+  { D d = new D(new E()); F f = ++d?.v; Expect.identical(d.v, f); } /// 11: ok
+  { D d = new D(new E()); H h = ++d?.v; Expect.identical(d.v, h); } /// 12: static type warning
+
+  // --e1?.v is equivalent to e1?.v += 1.
+  Expect.equals(null, --nullC()?.v); /// 13: ok
+  { C c = new C(1); Expect.equals(0, --c?.v); Expect.equals(0, c.v); } /// 14: ok
+
+  // The static type of --e1?.v is the same as the static type of e1.v - 1.
+  { D d = new D(new E()); F f = --d?.v; Expect.identical(d.v, f); } /// 15: ok
+  { D d = new D(new E()); H h = --d?.v; Expect.identical(d.v, h); } /// 16: static type warning
+}
diff --git a/tests/language/conditional_rewrite_test.dart b/tests/language/conditional_rewrite_test.dart
new file mode 100644
index 0000000..69a6398
--- /dev/null
+++ b/tests/language/conditional_rewrite_test.dart
@@ -0,0 +1,51 @@
+// 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";
+
+// Test that dart2js does not rewrite conditional into logical operators
+// in cases where it changes which falsy value is returned.
+
+posFalse(x, y) => x != null ? y : false;
+negFalse(x, y) => x != null ? !y : false;
+posNull(x, y) => x != null ? y : null;
+negNull(x, y) => x != null ? !y : null;
+
+main() {
+  bool isCheckedMode = false;
+  assert((isCheckedMode = true));
+
+  Expect.equals(false, posFalse(null, false));
+  Expect.equals(false, negFalse(null, false));
+  Expect.equals(null, posNull(null, false));
+  Expect.equals(null, negNull(null, false));
+
+  Expect.equals(false, posFalse(null, true));
+  Expect.equals(false, negFalse(null, true));
+  Expect.equals(null, posNull(null, true));
+  Expect.equals(null, negNull(null, true));
+
+  Expect.equals(false, posFalse([], false));
+  Expect.equals(true, negFalse([], false));
+  Expect.equals(false, posNull([], false));
+  Expect.equals(true, negNull([], false));
+
+  Expect.equals(true, posFalse([], true));
+  Expect.equals(false, negFalse([], true));
+  Expect.equals(true, posNull([], true));
+  Expect.equals(false, negNull([], true));
+
+  if (!isCheckedMode) {
+    Expect.equals(null, posFalse([], null));
+    Expect.equals(true, negFalse([], null));
+    Expect.equals(null, posNull([], null));
+    Expect.equals(true, negNull([], null));
+
+    var y = {};
+    Expect.identical(y, posFalse([], y));
+    Expect.equals(true, negFalse([], y));
+    Expect.identical(y, posNull([], y));
+    Expect.equals(true, negNull([], y));
+  }
+}
diff --git a/tests/language/const_error_multiply_initialized_test.dart b/tests/language/const_error_multiply_initialized_test.dart
new file mode 100644
index 0000000..896b1a3
--- /dev/null
+++ b/tests/language/const_error_multiply_initialized_test.dart
@@ -0,0 +1,28 @@
+// 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.
+
+// If a constant constructor contains an initializer, or an initializing
+// formal, for a final field which itself has an initializer at its
+// declaration, then a runtime error should occur if that constructor is
+// invoked using "new", but there should be no compile-time error.  However, if
+// the constructor is invoked using "const", there should be a compile-time
+// error, since it is a compile-time error for evaluation of a constant object
+// to result in an uncaught exception.
+
+import "package:expect/expect.dart";
+
+class C {
+  final x = 1;
+  const C() : x = 2; /// 01: compile-time error
+  const C() : x = 2; /// 02: static type warning
+  const C(this.x); /// 03: compile-time error
+  const C(this.x); /// 04: static type warning
+}
+
+main() {
+  const C(); /// 01: continued
+  Expect.throws(() => new C()); /// 02: continued
+  const C(2); /// 03: continued
+  Expect.throws(() => new C(2)); /// 04: continued
+}
diff --git a/tests/language/dead_field_access_test.dart b/tests/language/dead_field_access_test.dart
new file mode 100644
index 0000000..e3fc11b
--- /dev/null
+++ b/tests/language/dead_field_access_test.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.
+
+import 'package:expect/expect.dart';
+
+class Foo {
+  var field = 10;
+}
+
+@NoInline()
+getField(x) {
+  x.field;
+  return 34;
+}
+
+main() {
+  Expect.equals(34, getField(new Foo()));
+  Expect.throws(() => getField(null));
+}
diff --git a/tests/language/empty_library.dart b/tests/language/empty_library.dart
new file mode 100644
index 0000000..fe101dc
--- /dev/null
+++ b/tests/language/empty_library.dart
@@ -0,0 +1,5 @@
+// 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 empty_library;
diff --git a/tests/language/export_private_test.dart b/tests/language/export_private_test.dart
new file mode 100644
index 0000000..52b3f02
--- /dev/null
+++ b/tests/language/export_private_test.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.
+// Check that private dart:_ libraries cannot be imported.
+
+export "dart:_internal";  /// 01: compile-time error
+
+main() {
+  print("Done.");
+}
diff --git a/tests/language/function_subtype3_test.dart b/tests/language/function_subtype3_test.dart
new file mode 100644
index 0000000..7b2acc3
--- /dev/null
+++ b/tests/language/function_subtype3_test.dart
@@ -0,0 +1,30 @@
+// 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';
+
+class FunctionLike<T> {
+  call(T arg) {
+    return arg;
+  }
+}
+
+class Foo<T> {
+  testString() => new FunctionLike<String>() is T;
+  testInt() => new FunctionLike<int>() is T;
+}
+
+typedef TakeString(String arg);
+typedef TakeInt(int arg);
+
+main() {
+  Foo<TakeString> stringFoo = new Foo<TakeString>();
+  Foo<TakeInt> intFoo = new Foo<TakeInt>();
+
+  Expect.isTrue(stringFoo.testString());
+  Expect.isFalse(stringFoo.testInt());
+
+  Expect.isFalse(intFoo.testString());
+  Expect.isTrue(intFoo.testInt());
+}
diff --git a/tests/language/if_null_assignment_behavior_test.dart b/tests/language/if_null_assignment_behavior_test.dart
index 548d94a..ca2ce93 100644
--- a/tests/language/if_null_assignment_behavior_test.dart
+++ b/tests/language/if_null_assignment_behavior_test.dart
@@ -170,6 +170,8 @@
   { final l = 1; check(1, () => l ??= bad(), []); } /// 13: static type warning
   { final l = null; yGetValue = 1; checkThrows(noMethod, () => l ??= y, ['y']); } /// 14: static type warning
   check(C, () => C ??= bad(), []); /// 15: static type warning
+  h ??= null; /// 29: compile-time error
+  h[0] ??= null; /// 30: compile-time error
 
   // C.v ??= e is equivalent to ((x) => x == null ? C.v = e : x)(C.v)
   C.xGetValue = 1; check(1, () => C.x ??= bad(), ['C.x']); /// 16: ok
diff --git a/tests/language/illegal_invocation_test.dart b/tests/language/illegal_invocation_test.dart
index 3908a99..e0329ce 100644
--- a/tests/language/illegal_invocation_test.dart
+++ b/tests/language/illegal_invocation_test.dart
@@ -6,7 +6,7 @@
 // Test for issue 1393.  Invoking a library prefix name caused an internal error
 // in dartc.
 
-import "illegal_invocation_lib.dart" as foo;  /// 01: runtime error
+import "illegal_invocation_lib.dart" as foo;  /// 01: compile-time error
 
 main() {
   // probably what the user meant was foo.foo(), but the qualifier refers
diff --git a/tests/language/language.status b/tests/language/language.status
index c85375e..6898b8c 100644
--- a/tests/language/language.status
+++ b/tests/language/language.status
@@ -18,20 +18,12 @@
 duplicate_export_negative_test: Fail # Issue 6134
 
 [ $compiler == none ]
-# Null-aware operators aren't implemented in the VM yet.
-if_null_evaluation_order_test: Fail
-if_null_precedence_test: Fail
-if_null_behavior_test: Fail
-if_null_assignment_behavior_test: Fail
-if_null_assignment_static_test: Fail
-conditional_property_assignment_test: Fail
-conditional_property_access_test: Fail
-conditional_method_invocation_test: Fail
-this_conditional_operator_test/none: Fail
 
 deferred_redirecting_factory_test: Fail # Issue 23408
 redirecting_constructor_initializer_test: RuntimeError # Issue 23488
 
+[ $compiler == none && $runtime != dartium && $runtime != drt ]
+
 [ $compiler == none ]
 # Non-contractive types are not supported in the vm.
 cyclic_type_test/02: Fail, OK
@@ -47,6 +39,7 @@
 class_keyword_test/02: MissingCompileTimeError # Issue 13627
 unicode_bom_test: Fail # Issue 16067
 vm/debug_break_enabled_vm_test/01: Crash, OK # Expected to hit breakpoint.
+try_catch_optimized1_test: Skip # Srdjan investigating
 
 [ $compiler == none && $checked ]
 type_variable_bounds4_test/01: Fail # Issue 14006
diff --git a/tests/language/language_analyzer2.status b/tests/language/language_analyzer2.status
index eb24cf8..b35f11c 100644
--- a/tests/language/language_analyzer2.status
+++ b/tests/language/language_analyzer2.status
@@ -28,7 +28,6 @@
 external_test/25: Fail
 constructor_duplicate_final_test/03: Fail
 reify_typevar_static_test/00: MissingCompileTimeError # Issue 21565
-conditional_method_invocation_test/11: MissingStaticWarning # Issue 23461
 
 # Please add new failing tests before this line.
 # Section below is for invalid tests.
@@ -232,7 +231,6 @@
 getter_declaration_negative_test: CompileTimeError
 getter_no_setter2_test/01: StaticWarning
 getter_no_setter_test/01: StaticWarning
-illegal_invocation_test/01: StaticWarning
 implicit_this_test/02: StaticWarning
 implied_interface_test: StaticWarning
 import_combinators_test: StaticWarning
diff --git a/tests/language/language_dart2js.status b/tests/language/language_dart2js.status
index 81ff460..7209ad5 100644
--- a/tests/language/language_dart2js.status
+++ b/tests/language/language_dart2js.status
@@ -62,6 +62,26 @@
 
 if_null_assignment_behavior_test/13: Crash # Issue 23491
 if_null_assignment_behavior_test/14: Crash # Issue 23491
+nullaware_opt_test: Fail # Fails at e?.f ??= 200;
+
+conditional_method_invocation_test/11: MissingCompileTimeError # Issue 23611
+conditional_property_access_test/09: MissingCompileTimeError # Issue 23611
+conditional_property_assignment_test/20: MissingCompileTimeError # Issue 23611
+conditional_property_assignment_test/21: MissingCompileTimeError # Issue 23611
+conditional_property_assignment_test/22: MissingCompileTimeError # Issue 23611
+if_null_assignment_behavior_test/29: Crash # Issue 23611
+if_null_assignment_behavior_test/30: Crash # Issue 23611
+prefix_assignment_test/01: Crash # Issue 23611
+prefix_assignment_test/02: Crash # Issue 23611
+prefix_identifier_reference_test/01: MissingCompileTimeError # Issue 23611
+prefix_identifier_reference_test/02: MissingCompileTimeError # Issue 23611
+prefix_identifier_reference_test/03: MissingCompileTimeError # Issue 23611
+prefix_identifier_reference_test/04: Crash # Issue 23611
+prefix_identifier_reference_test/05: Crash # Issue 23611
+prefix_unqualified_invocation_test/01: RuntimeError # Issue 23611
+
+const_error_multiply_initialized_test/02: CompileTimeError # Issue 23618
+const_error_multiply_initialized_test/04: CompileTimeError # Issue 23618
 
 # VM specific tests that should not be run by dart2js.
 vm/*: Skip # Issue 12699
@@ -155,6 +175,7 @@
 infinity_test: RuntimeError # Issue 4984
 mixin_mixin2_test: RuntimeError # Issue 13109.
 mixin_mixin3_test: RuntimeError # Issue 13109.
+mixin_mixin7_test: RuntimeError # Issue 13109.
 mixin_regress_13688_test: RuntimeError # Issue 13109.
 modulo_test: RuntimeError # Issue 15246
 truncdiv_test: RuntimeError # Issue 15246
@@ -181,6 +202,10 @@
 bit_operations_test: RuntimeError, OK # Issue 1533
 expect_test: RuntimeError, OK # Issue 13080
 
+illegal_invocation_test/01: MissingCompileTimeError # Issue 23611
+prefix_unqualified_invocation_test/01: MissingCompileTimeError # Issue 23611
+prefix_unqualified_invocation_test/02: MissingCompileTimeError # Issue 23611
+
 [ $compiler == dart2js && $runtime == none ]
 *: Fail, Pass # TODO(ahe): Triage these tests.
 
@@ -218,21 +243,14 @@
 [ $compiler == dart2js && $cps_ir == false ]
 generic_field_mixin4_test: Crash # Issue 18651
 generic_field_mixin5_test: Crash # Issue 18651
-mixin_mixin7_test: RuntimeError # Issue 13109.
 
 [ $compiler == dart2js && $cps_ir ]
-aborting_switch_case_test: Crash # (switch (42){case 42:foo();foo();break;}): Unhandled node
-abstract_getter_test/01: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-abstract_runtime_error_test/01: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-abstract_runtime_error_test/02: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-arithmetic_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-assign_to_type_test/01: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-assign_to_type_test/02: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-assign_to_type_test/03: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-assign_to_type_test/04: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-assign_top_method_test/01: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
+abstract_object_method_test: RuntimeError # Please triage this failure.
+assert_assignable_type_test: RuntimeError # Please triage this failure.
+assign_op_test: RuntimeError # Please triage this failure.
+assignable_expression_test/none: RuntimeError # Please triage this failure.
 async_and_or_test: Crash # (test()async{await test1();await test2();}): cannot handle async/sync*/async* functions
-async_await_catch_regression_test: Crash #  cannot handle async/sync*/async* functions
+async_await_catch_regression_test: Crash # (test()async{var exc...  cannot handle async/sync*/async* functions
 async_await_syntax_test/a01a: Crash # (a01a()async=>null;): cannot handle async/sync*/async* functions
 async_await_syntax_test/a02a: Crash # (a02a()async{}): cannot handle async/sync*/async* functions
 async_await_syntax_test/a03a: Crash # (a03a()async*{}): cannot handle async/sync*/async* functions
@@ -246,7 +264,6 @@
 async_await_syntax_test/a08a: Crash # (a08a()sync*{yield* [] ;}): cannot handle async/sync*/async* functions
 async_await_syntax_test/a09a: Crash # (a09a()async*{yield 0;}): cannot handle async/sync*/async* functions
 async_await_syntax_test/a10a: Crash # (a10a()async*{yield* [] ;}): cannot handle async/sync*/async* functions
-async_await_syntax_test/a11a: Crash # Please triage this failure.
 async_await_syntax_test/a11b: Crash # (get sync sync*{}): cannot handle async/sync*/async* functions
 async_await_syntax_test/a11c: Crash # (get async async{}): cannot handle async/sync*/async* functions
 async_await_syntax_test/a11d: Crash # (get async async*{}): cannot handle async/sync*/async* functions
@@ -289,692 +306,410 @@
 async_await_test/02: Crash # (f()async{return id(42);}): cannot handle async/sync*/async* functions
 async_await_test/03: Crash # (f()async{return id(42);}): cannot handle async/sync*/async* functions
 async_await_test/none: Crash # (f()async{return id(42);}): cannot handle async/sync*/async* functions
-async_break_in_finally_test: Crash #  cannot handle async/sync*/async* functions
-async_continue_label_test/await_in_body: Crash #  cannot handle async/sync*/async* functions
-async_continue_label_test/await_in_condition: Crash #  cannot handle async/sync*/async* functions
-async_continue_label_test/await_in_init: Crash #  cannot handle async/sync*/async* functions
-async_continue_label_test/await_in_update: Crash #  cannot handle async/sync*/async* functions
-async_continue_label_test/none: Crash #  cannot handle async/sync*/async* functions
-async_control_structures_test: Crash #  cannot handle async/sync*/async* functions
-async_finally_rethrow_test: Crash #  cannot handle async/sync*/async* functions
+async_break_in_finally_test: Crash # (test()async{Expect....  cannot handle async/sync*/async* functions
+async_continue_label_test/await_in_body: Crash # (test()async{await t...  cannot handle async/sync*/async* functions
+async_continue_label_test/await_in_condition: Crash # (test()async{await t...  cannot handle async/sync*/async* functions
+async_continue_label_test/await_in_init: Crash # (test()async{await t...  cannot handle async/sync*/async* functions
+async_continue_label_test/await_in_update: Crash # (test()async{await t...  cannot handle async/sync*/async* functions
+async_continue_label_test/none: Crash # (test()async{await t...  cannot handle async/sync*/async* functions
+async_control_structures_test: Crash # (asyncImplicitReturn...  cannot handle async/sync*/async* functions
+async_finally_rethrow_test: Crash # (main()async{var err...  cannot handle async/sync*/async* functions
 async_or_generator_return_type_stacktrace_test/01: Crash # (void badReturnTypeAsync()async{}): cannot handle async/sync*/async* functions
 async_or_generator_return_type_stacktrace_test/02: Crash # (void badReturnTypeAsyncStar()async*{}): cannot handle async/sync*/async* functions
 async_or_generator_return_type_stacktrace_test/03: Crash # (void badReturnTypeSyncStar()sync*{}): cannot handle async/sync*/async* functions
 async_regression_23058_test: Crash # (foo()async{return x.foo==2?42:x.foo;}): cannot handle async/sync*/async* functions
-async_rethrow_test: Crash #  cannot handle async/sync*/async* functions
-async_return_types_test/nestedFuture: Crash #  cannot handle async/sync*/async* functions
-async_return_types_test/none: Crash #  cannot handle async/sync*/async* functions
-async_return_types_test/tooManyTypeParameters: Crash #  cannot handle async/sync*/async* functions
-async_return_types_test/wrongReturnType: Crash #  cannot handle async/sync*/async* functions
-async_return_types_test/wrongTypeParameter: Crash #  cannot handle async/sync*/async* functions
-async_star_cancel_and_throw_in_finally_test: Crash #  cannot handle async/sync*/async* functions
-async_star_regression_23116_test: Crash #  cannot handle async/sync*/async* functions
+async_rethrow_test: Crash # (rethrowString()asyn...  cannot handle async/sync*/async* functions
+async_return_types_test/nestedFuture: Crash # (test()async{Expect....  cannot handle async/sync*/async* functions
+async_return_types_test/none: Crash # (test()async{Expect....  cannot handle async/sync*/async* functions
+async_return_types_test/tooManyTypeParameters: Crash # (test()async{Expect....  cannot handle async/sync*/async* functions
+async_return_types_test/wrongReturnType: Crash # (test()async{Expect....  cannot handle async/sync*/async* functions
+async_return_types_test/wrongTypeParameter: Crash # (test()async{Expect....  cannot handle async/sync*/async* functions
+async_star_cancel_and_throw_in_finally_test: Crash # (test()async{var com...  cannot handle async/sync*/async* functions
+async_star_regression_23116_test: Crash # (test()async{Complet...  cannot handle async/sync*/async* functions
 async_star_test/01: Crash # (f()async*{}): cannot handle async/sync*/async* functions
 async_star_test/02: Crash # (f()async*{}): cannot handle async/sync*/async* functions
 async_star_test/03: Crash # (f()async*{}): cannot handle async/sync*/async* functions
 async_star_test/04: Crash # (f()async*{}): cannot handle async/sync*/async* functions
 async_star_test/05: Crash # (f()async*{}): cannot handle async/sync*/async* functions
 async_star_test/none: Crash # (f()async*{}): cannot handle async/sync*/async* functions
-async_switch_test/none: Crash #  cannot handle async/sync*/async* functions
-async_switch_test/withDefault: Crash #  cannot handle async/sync*/async* functions
-async_test/constructor2: Crash # (bar(int p1,p2)async{var z=8;return p2+z+foo;}): cannot handle async/sync*/async* functions
-async_test/constructor3: Crash # (bar(int p1,p2)async{var z=8;return p2+z+foo;}): cannot handle async/sync*/async* functions
-async_test/constructor4: Crash # (bar(int p1,p2)async{var z=8;return p2+z+foo;}): cannot handle async/sync*/async* functions
+async_switch_test/none: Crash # (test()async{Expect....  cannot handle async/sync*/async* functions
+async_switch_test/withDefault: Crash # (test()async{Expect....  cannot handle async/sync*/async* functions
 async_test/none: Crash # (bar(int p1,p2)async{var z=8;return p2+z+foo;}): cannot handle async/sync*/async* functions
-async_test/setter1: Crash # (bar(int p1,p2)async{var z=8;return p2+z+foo;}): cannot handle async/sync*/async* functions
 async_test/type-mismatch1: Crash # (bar(int p1,p2)async{var z=8;return p2+z+foo;}): cannot handle async/sync*/async* functions
 async_test/type-mismatch2: Crash # (bar(int p1,p2)async{var z=8;return p2+z+foo;}): cannot handle async/sync*/async* functions
 async_test/type-mismatch3: Crash # (bar(int p1,p2)async{var z=8;return p2+z+foo;}): cannot handle async/sync*/async* functions
 async_test/type-mismatch4: Crash # (bar(int p1,p2)async{var z=8;return p2+z+foo;}): cannot handle async/sync*/async* functions
 async_this_bound_test: Crash # (test()async{await testA();await testB();}): cannot handle async/sync*/async* functions
-async_throw_in_catch_test/forceAwait: Crash #  cannot handle async/sync*/async* functions
-async_throw_in_catch_test/none: Crash #  cannot handle async/sync*/async* functions
-asyncstar_concat_test: Crash #  cannot handle async/sync*/async* functions
-asyncstar_throw_in_catch_test: Crash #  cannot handle async/sync*/async* functions
-asyncstar_yield_test: Crash #  cannot handle async/sync*/async* functions
-asyncstar_yieldstar_test: Crash #  cannot handle async/sync*/async* functions
-await_backwards_compatibility_test/await1: Crash # (test1()async{var x=await 9;Expect.equals(9,x);}): cannot handle async/sync*/async* functions
-await_backwards_compatibility_test/await2: Crash # (test0()async{var x=await 7;Expect.equals(7,x);}): cannot handle async/sync*/async* functions
-await_backwards_compatibility_test/await3: Crash # (test1()async{var x=await 9;Expect.equals(9,x);}): cannot handle async/sync*/async* functions
-await_backwards_compatibility_test/await4: Crash # (test1()async{var x=await 9;Expect.equals(9,x);}): cannot handle async/sync*/async* functions
+async_throw_in_catch_test/forceAwait: Crash # (test()async{await r...  cannot handle async/sync*/async* functions
+async_throw_in_catch_test/none: Crash # (test()async{await r...  cannot handle async/sync*/async* functions
+asyncstar_concat_test: Crash # (test()async{Expect....  cannot handle async/sync*/async* functions
+asyncstar_throw_in_catch_test: Crash # (test()async{await r...  cannot handle async/sync*/async* functions
+asyncstar_yield_test: Crash # (test()async{Expect....  cannot handle async/sync*/async* functions
+asyncstar_yieldstar_test: Crash # (test()async{Expect....  cannot handle async/sync*/async* functions
 await_backwards_compatibility_test/none: Crash # (test1()async{var x=await 9;Expect.equals(9,x);}): cannot handle async/sync*/async* functions
 await_exceptions_test: Crash # (awaitFoo()async{await foo();}): cannot handle async/sync*/async* functions
 await_for_cancel_test: Crash # (test()async{await test1();await test2();}): cannot handle async/sync*/async* functions
-await_for_test: Crash #  cannot handle async/sync*/async* functions
-await_for_use_local_test: Crash #  cannot handle async/sync*/async* functions
-await_future_test: Crash #  cannot handle async/sync*/async* functions
+await_for_test: Crash # (consumeSomeOfInfini...  cannot handle async/sync*/async* functions
+await_for_use_local_test: Crash # (test()async{var cou...  cannot handle async/sync*/async* functions
+await_future_test: Crash # (test()async{var res...  cannot handle async/sync*/async* functions
 await_nonfuture_test: Crash # (foo()async{Expect.equals(X,10);return await 5;}): cannot handle async/sync*/async* functions
 await_not_started_immediately_test: Crash # (foo()async{x++ ;await 1;x++ ;}): cannot handle async/sync*/async* functions
-await_postfix_expr_test: Crash #  cannot handle async/sync*/async* functions
-await_regression_test: Crash #  cannot handle async/sync*/async* functions
-await_test: Crash #  cannot handle async/sync*/async* functions
-bool_check_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-call_closurization_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-call_nonexistent_static_test/01: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-call_nonexistent_static_test/02: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-call_nonexistent_static_test/03: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-call_nonexistent_static_test/04: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-call_nonexistent_static_test/05: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-call_nonexistent_static_test/06: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-call_nonexistent_static_test/07: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-call_nonexistent_static_test/08: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-call_nonexistent_static_test/09: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-call_nonexistent_static_test/10: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-call_nonexistent_static_test/none: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-call_property_test: Crash # Instance of 'TypeOperator': type check unimplemented for F.
-call_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-call_through_null_getter_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-call_type_literal_test/01: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-cascade2_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-cast2_test/01: Crash # Instance of 'TypeOperator': type casts not implemented.
-cast2_test/none: Crash # Instance of 'TypeOperator': type casts not implemented.
-cast_test/01: Crash # Instance of 'TypeOperator': type casts not implemented.
-cast_test/02: Crash # Instance of 'TypeOperator': type casts not implemented.
-cast_test/03: Crash # Instance of 'TypeOperator': type casts not implemented.
-cast_test/04: Crash # Instance of 'TypeOperator': type casts not implemented.
-cast_test/05: Crash # Instance of 'TypeOperator': type casts not implemented.
-cast_test/07: Crash # Instance of 'TypeOperator': type casts not implemented.
-cast_test/08: Crash # Instance of 'TypeOperator': type casts not implemented.
-cast_test/10: Crash # Instance of 'TypeOperator': type casts not implemented.
-cast_test/12: Crash # Instance of 'TypeOperator': type casts not implemented.
-cast_test/13: Crash # Instance of 'TypeOperator': type casts not implemented.
-cast_test/14: Crash # Instance of 'TypeOperator': type casts not implemented.
-cast_test/15: Crash # Instance of 'TypeOperator': type casts not implemented.
-cast_test/none: Crash # Instance of 'TypeOperator': type casts not implemented.
-cha_deopt1_test: RuntimeError # Please triage this failure.
-cha_deopt2_test: RuntimeError # Please triage this failure.
-cha_deopt3_test: RuntimeError # Please triage this failure.
-checked_null_test/01: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-checked_setter2_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-checked_setter3_test/01: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-checked_setter3_test/02: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-checked_setter3_test/none: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-checked_setter_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-class_literal_test/01: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-class_literal_test/02: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-class_literal_test/03: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-class_literal_test/04: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-class_literal_test/05: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-class_literal_test/06: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-class_literal_test/07: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-class_literal_test/08: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-class_literal_test/09: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-class_literal_test/10: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-class_literal_test/11: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-class_literal_test/12: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-class_literal_test/13: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-class_literal_test/14: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-class_literal_test/15: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-class_literal_test/16: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-class_literal_test/17: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-class_literal_test/18: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-class_literal_test/19: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-class_literal_test/20: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-class_literal_test/21: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-class_literal_test/22: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-class_literal_test/23: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-class_literal_test/24: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-class_literal_test/25: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-class_override_test/00: Crash # (try {instance.foo();}on NoSuchMethodError catch (error){}finally {}): try/finally
-class_override_test/none: Crash # (try {instance.foo();}finally {}): try/finally
-closure3_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-closure_in_constructor_test: Crash # Please triage this failure.
-closure_internals_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-closure_self_reference_test: Crash # (try {return inner(value-1);}finally {counter++ ;}): try/finally
-closure_type_variables_test: Crash # Please triage this failure.
-compile_time_constant_a_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-compile_time_constant_b_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-conditional_method_invocation_test/09: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-conditional_method_invocation_test/10: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-conditional_method_invocation_test/11: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-conditional_property_access_test/07: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-conditional_property_access_test/08: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-conditional_property_access_test/09: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-conditional_property_assignment_test/06: Crash # Instance of 'TypeOperator': type casts not implemented.
-conditional_property_assignment_test/11: Crash # Instance of 'TypeOperator': type casts not implemented.
-conditional_property_assignment_test/14: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-conditional_property_assignment_test/15: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-conditional_property_assignment_test/16: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-conditional_property_assignment_test/17: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-conditional_property_assignment_test/18: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-conditional_property_assignment_test/19: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-conditional_property_assignment_test/20: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-conditional_property_assignment_test/21: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-conditional_property_assignment_test/22: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-const_evaluation_test/01: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-const_nested_test: Crash # Please triage this failure.
-const_objects_are_immutable_test/01: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-const_objects_are_immutable_test/none: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-const_switch2_test/none: Crash # (switch (a){case 1:print("OK");}): Unhandled node
-const_switch_test/01: Crash #  Unhandled node
-const_switch_test/02: Crash #  Unhandled node
-const_switch_test/03: Crash #  Unhandled node
-const_switch_test/04: Crash #  Unhandled node
-constructor10_test/01: Crash # Please triage this failure.
-constructor10_test/02: Crash # Please triage this failure.
-constructor11_test: Crash # Please triage this failure.
+await_postfix_expr_test: Crash # (test()async{Expect....  cannot handle async/sync*/async* functions
+await_regression_test: Crash # (main()async{testNes...  cannot handle async/sync*/async* functions
+await_test: Crash # (others()async{var a...  cannot handle async/sync*/async* functions
+bind_test: RuntimeError # Cannot read property 'prototype' of undefined
+bound_closure_primitives_test: RuntimeError # Please triage this failure.
+call_with_no_such_method_test: RuntimeError # Please triage this failure.
+canonical_const3_test: RuntimeError # Cannot read property 'prototype' of undefined
+cascade2_test: RuntimeError # Please triage this failure.
+cascade_2_test: RuntimeError # Please triage this failure.
+cascade_test/none: RuntimeError # Cannot read property 'prototype' of undefined
+cast_test/04: RuntimeError # Please triage this failure.
+cast_test/05: RuntimeError # Please triage this failure.
+cast_test/none: RuntimeError # Please triage this failure.
+cha_deopt1_test: RuntimeError # receiver.get$_collection$_nums is not a function
+cha_deopt2_test: RuntimeError # receiver.get$_collection$_nums is not a function
+cha_deopt3_test: RuntimeError # receiver.get$_collection$_nums is not a function
+char_escape_test: RuntimeError # Please triage this failure.
+closure7_test: RuntimeError # Cannot read property 'prototype' of undefined
+closure8_test: RuntimeError # Cannot read property 'prototype' of undefined
+closure_cycles_test: RuntimeError # receiver.get$_collection$_nums is not a function
+closure_in_constructor_test: Crash # Invalid argument(s)
+closure_shared_state_test: RuntimeError # Cannot read property 'prototype' of undefined
+closure_type_variables_test: Crash # Invalid argument(s)
+closures_initializer2_test: RuntimeError # Cannot read property 'prototype' of undefined
+compile_time_constant_a_test: RuntimeError # Please triage this failure.
+compile_time_constant_b_test: RuntimeError # Please triage this failure.
+compound_assignment_operator_test: RuntimeError # Please triage this failure.
+const_evaluation_test/01: Crash # Internal Error: No default constructor available.
+const_list_test: RuntimeError # Please triage this failure.
+const_map_test: RuntimeError # Please triage this failure.
+const_nested_test: Crash # Invalid argument(s)
 constructor12_test: RuntimeError # Please triage this failure.
-constructor5_test: Crash # Please triage this failure.
-constructor_initializer_test/01: Crash # Please triage this failure.
-constructor_with_mixin_test: Crash # Please triage this failure.
-continue_test: Crash # (switch (0){case 0:i=22;continue;default:i=25;break;}): Unhandled node
-crash_12118_test: Crash # Please triage this failure.
-crash_6725_test/01: Crash # Please triage this failure.
-custom_await_stack_trace_test: Crash #  cannot handle async/sync*/async* functions
-deferred_call_empty_before_load_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-deferred_closurize_load_library_test: RuntimeError # Please triage this failure.
-deferred_constant_list_test: RuntimeError # Please triage this failure.
-deferred_constraints_constants_test/constructor1: Crash # (const lib.Const()): Unexpected constant kind null: null
-deferred_constraints_constants_test/constructor2: Crash # (const lib.Const.namedConstructor()): Unexpected constant kind null: null
-deferred_constraints_constants_test/default_argument1: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-deferred_constraints_constants_test/default_argument2: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-deferred_constraints_constants_test/metadata1: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-deferred_constraints_constants_test/metadata2: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-deferred_constraints_constants_test/metadata3: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-deferred_constraints_constants_test/none: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-deferred_constraints_constants_test/reference1: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-deferred_constraints_constants_test/reference2: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-deferred_constraints_constants_test/reference_after_load: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-deferred_constraints_type_annotation_test/as_operation: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-deferred_constraints_type_annotation_test/catch_check: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-deferred_constraints_type_annotation_test/is_check: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-deferred_constraints_type_annotation_test/new: RuntimeError # Please triage this failure.
-deferred_constraints_type_annotation_test/new_before_load: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-deferred_constraints_type_annotation_test/new_generic1: RuntimeError # Please triage this failure.
-deferred_constraints_type_annotation_test/new_generic2: RuntimeError # Please triage this failure.
-deferred_constraints_type_annotation_test/new_generic3: RuntimeError # Please triage this failure.
-deferred_constraints_type_annotation_test/none: RuntimeError # Please triage this failure.
-deferred_constraints_type_annotation_test/static_method: RuntimeError # Please triage this failure.
-deferred_constraints_type_annotation_test/type_annotation1: RuntimeError # Please triage this failure.
-deferred_constraints_type_annotation_test/type_annotation_generic1: RuntimeError # Please triage this failure.
-deferred_constraints_type_annotation_test/type_annotation_generic2: RuntimeError # Please triage this failure.
-deferred_constraints_type_annotation_test/type_annotation_generic3: RuntimeError # Please triage this failure.
-deferred_constraints_type_annotation_test/type_annotation_generic4: RuntimeError # Please triage this failure.
-deferred_constraints_type_annotation_test/type_annotation_non_deferred: RuntimeError # Please triage this failure.
-deferred_constraints_type_annotation_test/type_annotation_null: RuntimeError # Please triage this failure.
-deferred_constraints_type_annotation_test/type_annotation_top_level: RuntimeError # Please triage this failure.
-deferred_function_type_test: Crash # Instance of 'TypeOperator': type check unimplemented for F.
-deferred_global_test: RuntimeError # Please triage this failure.
-deferred_inheritance_constraints_test/redirecting_constructor: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-deferred_inlined_test: RuntimeError # Please triage this failure.
-deferred_load_constants_test/01: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-deferred_load_constants_test/02: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-deferred_load_constants_test/03: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-deferred_load_constants_test/04: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-deferred_load_constants_test/05: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-deferred_load_constants_test/none: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-deferred_load_inval_code_test: RuntimeError # Please triage this failure.
-deferred_load_library_wrong_args_test/none: RuntimeError # Please triage this failure.
-deferred_mixin_test: RuntimeError # Please triage this failure.
-deferred_no_such_method_test: RuntimeError # Please triage this failure.
-deferred_not_loaded_check_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-deferred_only_constant_test: RuntimeError # Please triage this failure.
-deferred_optimized_test: RuntimeError # Please triage this failure.
-deferred_redirecting_factory_test: Crash #  cannot handle async/sync*/async* functions
-deferred_regression_22995_test: Crash # Instance of 'TypeOperator': type check unimplemented for Ti.
-deferred_shadow_load_library_test: RuntimeError # Please triage this failure.
-deferred_shared_and_unshared_classes_test: RuntimeError # Please triage this failure.
-deferred_static_seperate_test: RuntimeError # Please triage this failure.
-deopt_inlined_function_lazy_test: Crash # (try {return x+12342353257893275483274832;}finally {}): try/finally
-div_with_power_of_two2_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-double_to_string_as_exponential2_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-double_to_string_as_fixed2_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-double_to_string_as_precision2_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-dynamic_prefix_core_test/01: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-dynamic_test: Crash # Instance of 'TypeOperator': type check unimplemented for F1<int>.
-empty_block_case_test: Crash # (switch (1){case 1:{}case 2:Expect.equals(true,false);}): Unhandled node
-enum_mirror_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-enum_private_test/02: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-enum_test: Crash #  Unhandled node
-equality_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-execute_finally10_test: Crash #  try/finally
-execute_finally11_test: Crash #  try/finally
-execute_finally12_test: Crash # (try {try {}finally {a=8;break;}}finally {return a==8;}): try/finally
-execute_finally1_test: Crash # (try {int j;j=func();i=1;return i;}finally {i=i+800;}): try/finally
-execute_finally2_test: Crash #  try/finally
-execute_finally3_test: Crash #  try/finally
-execute_finally4_test: Crash # (try {int j;j=func();i=1;}finally {i=i+10;}): try/finally
-execute_finally5_test: Crash #  try/finally
-execute_finally6_test: Crash #  try/finally
-execute_finally7_test: Crash #  try/finally
-execute_finally8_test: Crash # (try {sum+= 1;return 'hi';}finally {sum+= 1;throw 'ball';sum+= 1;}): try/finally
-execute_finally9_test: Crash #  try/finally
-factory_redirection3_cyclic_test/01: Crash # Please triage this failure.
-factory_redirection_test/04: Crash # Please triage this failure.
-factory_return_type_checked_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-factory_type_parameter2_test: Crash # Please triage this failure.
-factory_type_parameter_test: Crash # Please triage this failure.
+constructor_with_mixin_test: Crash # Internal Error: No default constructor available.
+crash_6725_test/01: Crash # The null object does not have a getter '_element'.
+custom_await_stack_trace_test: Crash # (main()async{try {va...  cannot handle async/sync*/async* functions
+cyclic_type_test/00: RuntimeError # Cannot read property 'prototype' of undefined
+cyclic_type_test/01: RuntimeError # Cannot read property 'prototype' of undefined
+cyclic_type_test/02: RuntimeError # Cannot read property 'prototype' of undefined
+cyclic_type_test/03: RuntimeError # Cannot read property 'prototype' of undefined
+cyclic_type_test/04: RuntimeError # Cannot read property 'prototype' of undefined
+deferred_closurize_load_library_test: RuntimeError # receiver.get$_collection$_nums is not a function
+deferred_constant_list_test: RuntimeError # receiver.get$_collection$_nums is not a function
+deferred_constraints_constants_test/none: Crash # Internal Error: No default constructor available.
+deferred_constraints_constants_test/reference_after_load: Crash # Internal Error: No default constructor available.
+deferred_constraints_type_annotation_test/as_operation: RuntimeError # receiver.get$_collection$_nums is not a function
+deferred_constraints_type_annotation_test/catch_check: Crash # The null object does not have a getter '_element'.
+deferred_constraints_type_annotation_test/is_check: RuntimeError # receiver.get$_collection$_nums is not a function
+deferred_constraints_type_annotation_test/new: RuntimeError # receiver.get$_collection$_nums is not a function
+deferred_constraints_type_annotation_test/new_before_load: RuntimeError # receiver.get$_collection$_nums is not a function
+deferred_constraints_type_annotation_test/new_generic1: RuntimeError # receiver.get$_collection$_nums is not a function
+deferred_constraints_type_annotation_test/new_generic2: RuntimeError # receiver.get$_collection$_nums is not a function
+deferred_constraints_type_annotation_test/new_generic3: RuntimeError # receiver.get$_collection$_nums is not a function
+deferred_constraints_type_annotation_test/none: RuntimeError # receiver.get$_collection$_nums is not a function
+deferred_constraints_type_annotation_test/static_method: RuntimeError # receiver.get$_collection$_nums is not a function
+deferred_constraints_type_annotation_test/type_annotation1: RuntimeError # receiver.get$_collection$_nums is not a function
+deferred_constraints_type_annotation_test/type_annotation_generic1: RuntimeError # receiver.get$_collection$_nums is not a function
+deferred_constraints_type_annotation_test/type_annotation_generic2: RuntimeError # receiver.get$_collection$_nums is not a function
+deferred_constraints_type_annotation_test/type_annotation_generic3: RuntimeError # receiver.get$_collection$_nums is not a function
+deferred_constraints_type_annotation_test/type_annotation_generic4: RuntimeError # receiver.get$_collection$_nums is not a function
+deferred_constraints_type_annotation_test/type_annotation_non_deferred: RuntimeError # receiver.get$_collection$_nums is not a function
+deferred_constraints_type_annotation_test/type_annotation_null: RuntimeError # receiver.get$_collection$_nums is not a function
+deferred_constraints_type_annotation_test/type_annotation_top_level: RuntimeError # receiver.get$_collection$_nums is not a function
+deferred_function_type_test: RuntimeError # receiver.get$_collection$_nums is not a function
+deferred_global_test: RuntimeError # receiver.get$_collection$_nums is not a function
+deferred_inlined_test: RuntimeError # receiver.get$_collection$_nums is not a function
+deferred_load_constants_test/none: RuntimeError # receiver.get$_collection$_nums is not a function
+deferred_load_inval_code_test: RuntimeError # receiver.get$_collection$_nums is not a function
+deferred_load_library_wrong_args_test/none: RuntimeError # receiver.get$_collection$_nums is not a function
+deferred_mixin_test: RuntimeError # receiver.get$_collection$_nums is not a function
+deferred_no_such_method_test: RuntimeError # receiver.get$_collection$_nums is not a function
+deferred_not_loaded_check_test: RuntimeError # Please triage this failure.
+deferred_only_constant_test: RuntimeError # receiver.get$_collection$_nums is not a function
+deferred_optimized_test: RuntimeError # receiver.get$_collection$_nums is not a function
+deferred_redirecting_factory_test: Crash # (test()async{await t...  cannot handle async/sync*/async* functions
+deferred_regression_22995_test: RuntimeError # receiver.get$_collection$_nums is not a function
+deferred_shadow_load_library_test: RuntimeError # receiver.get$_collection$_nums is not a function
+deferred_shared_and_unshared_classes_test: RuntimeError # receiver.get$_collection$_nums is not a function
+deferred_static_seperate_test: RuntimeError # receiver.get$_collection$_nums is not a function
+deopt_no_feedback_test: RuntimeError # Please triage this failure.
+enum_duplicate_test/01: RuntimeError # Please triage this failure.
+enum_duplicate_test/02: RuntimeError # Please triage this failure.
+enum_duplicate_test/none: RuntimeError # Please triage this failure.
+enum_mirror_test: Crash # Internal Error: No default constructor available.
+enum_private_test/01: RuntimeError # Please triage this failure.
+enum_private_test/02: RuntimeError # Please triage this failure.
+enum_private_test/none: RuntimeError # Please triage this failure.
+execute_finally7_test: RuntimeError # Cannot read property 'call$0' of null
+f_bounded_equality_test: RuntimeError # Cannot read property 'prototype' of undefined
+fannkuch_test: RuntimeError # Please triage this failure.
+field_increment_bailout_test: RuntimeError # Please triage this failure.
 final_super_field_set_test/01: RuntimeError # Please triage this failure.
-finally_test: Crash # (try {i=12;}finally {Expect.equals(12,i);executedFinally=true;}): try/finally
-first_class_types_literals_test/03: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-first_class_types_literals_test/04: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-first_class_types_literals_test/05: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-first_class_types_literals_test/06: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-first_class_types_literals_test/07: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-first_class_types_literals_test/08: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-first_class_types_literals_test/09: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-first_class_types_literals_test/10: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-first_class_types_literals_test/11: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-first_class_types_literals_test/12: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
+fixed_length_test: RuntimeError # Please triage this failure.
+fixed_type_variable_test/02: RuntimeError # Cannot read property 'prototype' of undefined
+fixed_type_variable_test/04: RuntimeError # Cannot read property 'prototype' of undefined
+fixed_type_variable_test/06: RuntimeError # Cannot read property 'prototype' of undefined
 flatten_test/01: Crash # (test()async{int x=await new Derived<int>();}): cannot handle async/sync*/async* functions
 flatten_test/02: Crash # (test()async{Future<int> f()async=>new Derived<int>();}): cannot handle async/sync*/async* functions
-flatten_test/03: Crash #  cannot handle async/sync*/async* functions
-flatten_test/04: Crash #  cannot handle async/sync*/async* functions
-flatten_test/05: Crash #  cannot handle async/sync*/async* functions
-flatten_test/06: Crash #  cannot handle async/sync*/async* functions
-flatten_test/07: Crash #  cannot handle async/sync*/async* functions
-flatten_test/08: Crash #  cannot handle async/sync*/async* functions
-flatten_test/09: Crash #  cannot handle async/sync*/async* functions
-flatten_test/10: Crash #  cannot handle async/sync*/async* functions
-flatten_test/11: Crash #  cannot handle async/sync*/async* functions
-flatten_test/12: Crash #  cannot handle async/sync*/async* functions
+flatten_test/03: Crash # (test()async{Future<...  cannot handle async/sync*/async* functions
+flatten_test/04: Crash # (test()async{Future<...  cannot handle async/sync*/async* functions
+flatten_test/05: Crash # (test()async{FixedPo...  cannot handle async/sync*/async* functions
+flatten_test/06: Crash # (test()async{Future<...  cannot handle async/sync*/async* functions
+flatten_test/07: Crash # (test()async{Future<...  cannot handle async/sync*/async* functions
+flatten_test/08: Crash # (test()async{Future<...  cannot handle async/sync*/async* functions
+flatten_test/09: Crash # (test()async{Diverge...  cannot handle async/sync*/async* functions
+flatten_test/10: Crash # (test()async{Future<...  cannot handle async/sync*/async* functions
+flatten_test/11: Crash # (test()async{Future<...  cannot handle async/sync*/async* functions
+flatten_test/12: Crash # (test()async{Future<...  cannot handle async/sync*/async* functions
 flatten_test/none: Crash # (test()async{}): cannot handle async/sync*/async* functions
-for2_test: Crash # Please triage this failure.
+for2_test: Crash # The null object does not have a getter 'field'.
 for_variable_capture_test: Crash # (i=0): For-loop variable captured in loop header
-function_propagation_test: Crash # Instance of 'TypeOperator': type check unimplemented for F.
-function_subtype0_test: Crash # Instance of 'TypeOperator': type check unimplemented for t__.
-function_subtype1_test: Crash # type expression int_ (typedef)
-function_subtype2_test: Crash # Instance of 'TypeOperator': type check unimplemented for T1.
-function_subtype_bound_closure0_test: Crash # Instance of 'TypeOperator': type check unimplemented for Foo.
-function_subtype_bound_closure1_test: Crash # Instance of 'TypeOperator': type check unimplemented for Foo<bool>.
-function_subtype_bound_closure2_test: Crash # Instance of 'TypeOperator': type check unimplemented for Foo<T>.
-function_subtype_bound_closure3_test: Crash # Instance of 'TypeOperator': type check unimplemented for Foo.
-function_subtype_bound_closure4_test: Crash # Instance of 'TypeOperator': type check unimplemented for Foo.
-function_subtype_bound_closure5_test: Crash # Instance of 'TypeOperator': type check unimplemented for Foo<T>.
-function_subtype_bound_closure5a_test: Crash # Instance of 'TypeOperator': type check unimplemented for Foo<T>.
-function_subtype_bound_closure6_test: Crash # Instance of 'TypeOperator': type check unimplemented for Foo<T>.
-function_subtype_bound_closure7_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-function_subtype_call0_test: Crash # Instance of 'TypeOperator': type check unimplemented for Foo.
-function_subtype_call1_test: Crash # Instance of 'TypeOperator': type check unimplemented for Foo.
-function_subtype_call2_test: Crash # Instance of 'TypeOperator': type check unimplemented for Foo.
-function_subtype_cast0_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-function_subtype_cast1_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-function_subtype_cast2_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-function_subtype_cast3_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-function_subtype_checked0_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-function_subtype_closure0_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-function_subtype_closure1_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-function_subtype_factory0_test: Crash # Please triage this failure.
-function_subtype_inline0_test: Crash # Instance of 'TypeOperator': type check unimplemented for Foo.
-function_subtype_local0_test: Crash # Instance of 'TypeOperator': type check unimplemented for Foo.
-function_subtype_local1_test: Crash # Instance of 'TypeOperator': type check unimplemented for Foo<bool>.
-function_subtype_local2_test: Crash # Instance of 'TypeOperator': type check unimplemented for Foo<T>.
-function_subtype_local3_test: Crash # Instance of 'TypeOperator': type check unimplemented for Foo.
-function_subtype_local4_test: Crash # Instance of 'TypeOperator': type check unimplemented for Foo.
-function_subtype_local5_test: Crash # Instance of 'TypeOperator': type check unimplemented for Foo<T>.
-function_subtype_named1_test: Crash # Instance of 'TypeOperator': type check unimplemented for t_void_.
-function_subtype_named2_test: Crash # type expression void___a_int (typedef)
-function_subtype_not0_test: Crash # Instance of 'TypeOperator': type check unimplemented for Foo.
-function_subtype_not1_test: Crash # Instance of 'TypeOperator': type check unimplemented for Foo.
-function_subtype_not2_test: Crash # Instance of 'TypeOperator': type check unimplemented for Foo<T>.
-function_subtype_not3_test: Crash # Instance of 'TypeOperator': type check unimplemented for Foo<T>.
-function_subtype_optional1_test: Crash # Instance of 'TypeOperator': type check unimplemented for t_void_.
-function_subtype_optional2_test: Crash # type expression void___int (typedef)
-function_subtype_setter0_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-function_subtype_simple0_test: Crash # Instance of 'TypeOperator': type check unimplemented for Args0.
-function_subtype_simple1_test: Crash # Instance of 'TypeOperator': type check unimplemented for Args0.
-function_subtype_simple2_test: Crash # Instance of 'TypeOperator': type check unimplemented for Args0.
-function_subtype_top_level0_test: Crash # Instance of 'TypeOperator': type check unimplemented for Foo.
-function_subtype_top_level1_test: Crash # Instance of 'TypeOperator': type check unimplemented for Foo<T>.
-function_subtype_typearg0_test: Crash # type expression Foo (typedef)
-function_subtype_typearg1_test: Crash # type expression f2 (typedef)
-function_subtype_typearg2_test: Crash # type expression f1 (typedef)
-function_subtype_typearg3_test: Crash # type expression f1 (typedef)
-function_subtype_typearg4_test: Crash # type expression f1 (typedef)
-function_type3_test: Crash # Instance of 'TypeOperator': type check unimplemented for F.
-function_type_alias2_test: Crash # Instance of 'TypeOperator': type check unimplemented for f1.
-function_type_alias3_test: Crash # Instance of 'TypeOperator': type check unimplemented for F.
-function_type_alias4_test: Crash # Instance of 'TypeOperator': type check unimplemented for F.
-function_type_alias6_test/none: Crash # Instance of 'TypeOperator': type check unimplemented for F.
-function_type_alias_test: Crash # Instance of 'TypeOperator': type check unimplemented for Fun.
-function_type_call_getter_test: Crash # Instance of 'TypeOperator': type check unimplemented for F.
-generic_closure_test: Crash # Instance of 'TypeOperator': type check unimplemented for F.
-generic_constructor_mixin2_test: Crash # Please triage this failure.
-generic_constructor_mixin3_test: Crash # Please triage this failure.
-generic_constructor_mixin_test: Crash # Please triage this failure.
+function_getter_test: RuntimeError # Cannot read property 'prototype' of undefined
+function_literals_test: RuntimeError # Cannot read property 'prototype' of undefined
+function_subtype0_test: RuntimeError # Cannot read property 'prototype' of undefined
+function_subtype_bound_closure0_test: RuntimeError # Cannot read property 'prototype' of undefined
+function_subtype_bound_closure1_test: RuntimeError # Cannot read property 'prototype' of undefined
+function_subtype_call0_test: RuntimeError # Cannot read property 'prototype' of undefined
+function_subtype_factory1_test: RuntimeError # Cannot read property 'prototype' of undefined
+function_subtype_local0_test: RuntimeError # Cannot read property 'prototype' of undefined
+function_subtype_local1_test: RuntimeError # Cannot read property 'prototype' of undefined
+function_subtype_named1_test: RuntimeError # Cannot read property 'prototype' of undefined
+function_subtype_not0_test: RuntimeError # Cannot read property 'prototype' of undefined
+function_subtype_optional1_test: RuntimeError # Cannot read property 'prototype' of undefined
+function_subtype_simple0_test: RuntimeError # Cannot read property 'prototype' of undefined
+function_subtype_simple1_test: RuntimeError # Cannot read property 'prototype' of undefined
+function_subtype_simple2_test: RuntimeError # Cannot read property 'prototype' of undefined
+function_subtype_top_level0_test: RuntimeError # Cannot read property 'prototype' of undefined
+function_syntax_test/none: RuntimeError # Please triage this failure.
+function_test: RuntimeError # Please triage this failure.
+function_type_alias6_test/none: RuntimeError # Cannot read property 'prototype' of undefined
+gc_test: RuntimeError # Please triage this failure.
+generic_constructor_mixin2_test: Crash # Internal Error: No default constructor available.
+generic_constructor_mixin3_test: Crash # Internal Error: No default constructor available.
+generic_constructor_mixin_test: Crash # Internal Error: No default constructor available.
+generic_creation_test: RuntimeError # Cannot read property 'prototype' of undefined
 generic_field_mixin3_test: RuntimeError # Please triage this failure.
-generic_instanceof2_test: Crash # Please triage this failure.
-generic_list_checked_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-if_null_assignment_behavior_test/04: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-if_null_assignment_static_test/01: RuntimeError # A.a incorrectly tree-shaken (issue 23548)
-if_null_assignment_static_test/02: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-if_null_assignment_static_test/03: RuntimeError # A.a incorrectly tree-shaken (issue 23548)
-if_null_assignment_static_test/04: RuntimeError # B.b incorrectly tree-shaken (issue 23548)
-if_null_assignment_static_test/05: RuntimeError # A.a incorrectly tree-shaken (issue 23548)
-if_null_assignment_static_test/06: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-if_null_assignment_static_test/08: RuntimeError # A.a incorrectly tree-shaken (issue 23548)
-if_null_assignment_static_test/09: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-if_null_assignment_static_test/10: RuntimeError # A.a incorrectly tree-shaken (issue 23548)
-if_null_assignment_static_test/11: RuntimeError # B.b incorrectly tree-shaken (issue 23548)
-if_null_assignment_static_test/12: RuntimeError # A.a incorrectly tree-shaken (issue 23548)
-if_null_assignment_static_test/13: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-if_null_assignment_static_test/15: RuntimeError # A.a incorrectly tree-shaken (issue 23548)
-if_null_assignment_static_test/16: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-if_null_assignment_static_test/17: RuntimeError # A.a incorrectly tree-shaken (issue 23548)
-if_null_assignment_static_test/18: RuntimeError # B.b incorrectly tree-shaken (issue 23548)
-if_null_assignment_static_test/19: RuntimeError # A.a incorrectly tree-shaken (issue 23548)
-if_null_assignment_static_test/20: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-if_null_assignment_static_test/22: RuntimeError # A.a incorrectly tree-shaken (issue 23548)
-if_null_assignment_static_test/23: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-if_null_assignment_static_test/24: RuntimeError # A.a incorrectly tree-shaken (issue 23548)
-if_null_assignment_static_test/25: RuntimeError # B.b incorrectly tree-shaken (issue 23548)
-if_null_assignment_static_test/26: RuntimeError # A.a incorrectly tree-shaken (issue 23548)
-if_null_assignment_static_test/27: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-if_null_assignment_static_test/29: RuntimeError # A.a incorrectly tree-shaken (issue 23548)
-if_null_assignment_static_test/30: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-if_null_assignment_static_test/31: RuntimeError # A.a incorrectly tree-shaken (issue 23548)
-if_null_assignment_static_test/32: RuntimeError # B.b incorrectly tree-shaken (issue 23548)
-if_null_assignment_static_test/33: RuntimeError # A.a incorrectly tree-shaken (issue 23548)
-if_null_assignment_static_test/34: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-if_null_assignment_static_test/36: RuntimeError # A.a incorrectly tree-shaken (issue 23548)
-if_null_assignment_static_test/37: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-if_null_assignment_static_test/38: RuntimeError # A.a incorrectly tree-shaken (issue 23548)
-if_null_assignment_static_test/39: RuntimeError # B.b incorrectly tree-shaken (issue 23548)
-if_null_assignment_static_test/40: RuntimeError # A.a incorrectly tree-shaken (issue 23548)
-if_null_assignment_static_test/41: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-if_null_behavior_test/07: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-if_null_behavior_test/10: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-if_null_behavior_test/12: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-if_null_behavior_test/14: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-if_null_behavior_test/15: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-if_null_behavior_test/16: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-if_null_precedence_test/07: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-if_null_precedence_test/08: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-implicit_super_constructor_call_test: Crash # Please triage this failure.
-import_self_test/01: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-inference_captured_variable2_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-inference_captured_variable_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-inference_list_or_null_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-inference_mixin_field_test: Crash # Please triage this failure.
-inference_super_constructor_call_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-inferrer_constructor2_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-inferrer_constructor3_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-inferrer_constructor4_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-inferrer_constructor5_test/01: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-inferrer_constructor_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-inferrer_synthesized_constructor_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-inferrer_synthesized_super_constructor_test: Crash # Please triage this failure.
-inferrer_this_access_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-infinite_switch_label_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-inlined_throw_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-instance_creation_in_function_annotation_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
+getter_setter_interceptor_test: RuntimeError # Please triage this failure.
+getter_setter_order_test: RuntimeError # Please triage this failure.
+gvn_interceptor_test: RuntimeError # Please triage this failure.
+identical_closure_test: RuntimeError # Cannot read property 'prototype' of undefined
+if_null_assignment_behavior_test/01: RuntimeError # Please triage this failure.
+if_null_assignment_behavior_test/02: RuntimeError # Please triage this failure.
+if_null_assignment_behavior_test/04: RuntimeError # Please triage this failure.
+if_null_assignment_behavior_test/05: RuntimeError # Please triage this failure.
+if_null_assignment_behavior_test/06: RuntimeError # Please triage this failure.
+if_null_assignment_behavior_test/07: RuntimeError # Please triage this failure.
+if_null_assignment_behavior_test/08: RuntimeError # Please triage this failure.
+if_null_assignment_behavior_test/09: RuntimeError # Please triage this failure.
+if_null_assignment_behavior_test/10: RuntimeError # Please triage this failure.
+if_null_assignment_behavior_test/12: RuntimeError # Please triage this failure.
+if_null_assignment_behavior_test/16: RuntimeError # Please triage this failure.
+if_null_assignment_behavior_test/17: RuntimeError # Please triage this failure.
+if_null_assignment_behavior_test/18: RuntimeError # Please triage this failure.
+if_null_assignment_behavior_test/19: RuntimeError # Please triage this failure.
+if_null_assignment_behavior_test/20: RuntimeError # Please triage this failure.
+if_null_assignment_behavior_test/21: RuntimeError # Please triage this failure.
+if_null_assignment_behavior_test/22: RuntimeError # Please triage this failure.
+if_null_assignment_behavior_test/23: RuntimeError # Please triage this failure.
+if_null_assignment_behavior_test/24: RuntimeError # Please triage this failure.
+if_null_assignment_behavior_test/25: RuntimeError # Please triage this failure.
+if_null_assignment_behavior_test/26: RuntimeError # Please triage this failure.
+if_null_assignment_behavior_test/27: RuntimeError # Please triage this failure.
+if_null_assignment_behavior_test/28: RuntimeError # Please triage this failure.
+if_null_assignment_static_test/01: RuntimeError # Issue 23669
+if_null_assignment_static_test/03: RuntimeError # Issue 23669
+if_null_assignment_static_test/04: RuntimeError # Issue 23669
+if_null_assignment_static_test/05: RuntimeError # Issue 23669
+if_null_assignment_static_test/29: RuntimeError # Issue 23669
+if_null_assignment_static_test/30: RuntimeError # Please triage this failure.
+if_null_assignment_static_test/31: RuntimeError # Issue 23669
+if_null_assignment_static_test/32: RuntimeError # Issue 23669
+if_null_assignment_static_test/33: RuntimeError # Issue 23669
+if_null_assignment_static_test/34: RuntimeError # Please triage this failure.
+if_null_assignment_static_test/35: RuntimeError # Please triage this failure.
+if_null_assignment_static_test/36: RuntimeError # Issue 23669
+if_null_assignment_static_test/38: RuntimeError # Issue 23669
+if_null_assignment_static_test/39: RuntimeError # Issue 23669
+if_null_assignment_static_test/40: RuntimeError # Issue 23669
+implicit_closure1_test: RuntimeError # Cannot read property 'prototype' of undefined
+implicit_closure2_test: RuntimeError # Cannot read property 'prototype' of undefined
+implicit_closure_test: RuntimeError # Cannot read property 'prototype' of undefined
+incr_op_test: RuntimeError # Please triage this failure.
+index_test: RuntimeError # Please triage this failure.
+inference_mixin_field_test: Crash # Internal Error: No default constructor available.
+infinite_switch_label_test: Crash # (switch (target){l0:...  continue to a labeled switch case
+inlined_conditional_test: RuntimeError # Cannot read property 'prototype' of undefined
+instance_creation_in_function_annotation_test: Crash # Internal Error: No default constructor available.
 instanceof4_test/01: RuntimeError # Please triage this failure.
-integer_division_by_zero_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-interceptor6_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-interceptor_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-internal_library_test/01: Crash # (JS('int','0')): handleStaticFunctionInvoke: foreign: function(JS)
-invocation_mirror_invoke_on2_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
+interceptor7_test: RuntimeError # Please triage this failure.
+invocation_mirror_invoke_on2_test: RuntimeError # Please triage this failure.
 invocation_mirror_invoke_on_test: RuntimeError # Please triage this failure.
-invocation_mirror_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-is_nan_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-is_not_class2_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-isnot_malformed_type_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-issue10581_test: Crash #  Unhandled node
-issue10721_test: RuntimeError # Please triage this failure.
-issue10747_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-issue10783_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-issue11724_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-issue12023_test: Crash #  Unhandled node
-issue12284_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-issue12336_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-issue13474_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-issue14014_3_test: Crash # Instance of 'TypeOperator': type check unimplemented for foo<T>.
-issue20476_test: Crash # (try {try {return 1;}catch (e1){}finally {return 3;}}catch (e2){}finally {return 5;}): try/finally
-issue7525_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-issue_1751477_test: RuntimeError # Please triage this failure.
-label_test: Crash # (switch (i){case 111:while(doAgain()){break L;}default:i-- ;}): Unhandled node
-large_class_declaration_test: Crash # Please triage this failure.
-lazy_static3_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-licm2_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-licm3_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-list_double_index_in_loop2_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-list_double_index_in_loop_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-list_length_tracer_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-list_literal3_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-list_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-malbounded_type_cast2_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-malbounded_type_cast_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-malbounded_type_test2_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-malformed2_test/00: Crash # Instance of 'TypeOperator': type casts not implemented.
-malformed_inheritance_test/03: Crash # Please triage this failure.
-malformed_inheritance_test/09: Crash # Please triage this failure.
-malformed_inheritance_test/10: Crash # Please triage this failure.
-malformed_test/06: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-malformed_test/none: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
+invocation_mirror_test: Crash # (super[37]=42): visitUnresolvedSuperIndexSet
+is_function_test: RuntimeError # Cannot read property 'prototype' of undefined
+issue12288_test: RuntimeError # Please triage this failure.
+issue13179_test: RuntimeError # Cannot read property 'prototype' of undefined
+issue7513_test: RuntimeError # Please triage this failure.
+issue_1751477_test: RuntimeError # receiver.get$_collection$_nums is not a function
+large_class_declaration_test: Crash # Stack Overflow
+list_literal3_test: RuntimeError # Please triage this failure.
+list_test: RuntimeError # Please triage this failure.
+list_tracer_closure_test: RuntimeError # Please triage this failure.
+list_tracer_in_list_test: RuntimeError # Please triage this failure.
+list_tracer_in_map_test: RuntimeError # Please triage this failure.
+list_tracer_return_from_tearoff_closure_test: RuntimeError # Please triage this failure.
+local_function_test: RuntimeError # Please triage this failure.
+logical_expression_test: RuntimeError # Please triage this failure.
+main_test/01: RuntimeError # receiver.get$_collection$_nums is not a function
+main_test/02: RuntimeError # receiver.get$_collection$_nums is not a function
+main_test/04: RuntimeError # receiver.get$_collection$_nums is not a function
+main_test/05: RuntimeError # receiver.get$_collection$_nums is not a function
+main_test/20: RuntimeError # receiver.get$_collection$_nums is not a function
+main_test/21: RuntimeError # receiver.get$_collection$_nums is not a function
+main_test/22: RuntimeError # receiver.get$_collection$_nums is not a function
+main_test/41: RuntimeError # receiver.get$_collection$_nums is not a function
+main_test/42: RuntimeError # receiver.get$_collection$_nums is not a function
+main_test/43: RuntimeError # receiver.get$_collection$_nums is not a function
+main_test/44: RuntimeError # receiver.get$_collection$_nums is not a function
+main_test/45: RuntimeError # receiver.get$_collection$_nums is not a function
+many_calls_test: RuntimeError # Please triage this failure.
+many_named_arguments_test: RuntimeError # Please triage this failure.
 many_overridden_no_such_method_test: RuntimeError # Please triage this failure.
-megamorphic_no_such_method_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-method_override4_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-method_override5_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-method_override_test: Crash # Instance of 'TypeOperator': type check unimplemented for RemoveFunctionType<String, String>.
-mint_arithmetic_test: Crash #  try/finally
-mixin_bound_test: Crash # Please triage this failure.
-mixin_cyclic_test/01: Crash # Please triage this failure.
-mixin_extends_field_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mixin_extends_method_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mixin_field_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mixin_forwarding_constructor1_test: Crash # Please triage this failure.
-mixin_forwarding_constructor3_test: Crash # Please triage this failure.
-mixin_illegal_cycles_test/02: Crash # Please triage this failure.
-mixin_illegal_cycles_test/03: Crash # Please triage this failure.
-mixin_illegal_cycles_test/04: Crash # Please triage this failure.
-mixin_illegal_cycles_test/06: Crash # Please triage this failure.
-mixin_illegal_static_access_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mixin_invalid_inheritance1_test/01: Crash # Please triage this failure.
-mixin_invalid_inheritance1_test/02: Crash # Please triage this failure.
-mixin_invalid_inheritance1_test/03: Crash # Please triage this failure.
-mixin_issue10216_2_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-mixin_issue10216_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-mixin_lib_extends_field_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mixin_lib_extends_method_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mixin_method_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mixin_super_constructor2_test: Crash # Please triage this failure.
-mixin_super_constructor_default_test: Crash # Please triage this failure.
-mixin_super_constructor_multiple_test: Crash # Please triage this failure.
-mixin_super_constructor_named_test/01: Crash # Please triage this failure.
-mixin_super_constructor_named_test/none: Crash # Please triage this failure.
-mixin_super_constructor_positionals_test/01: Crash # Please triage this failure.
-mixin_super_constructor_positionals_test/none: Crash # Please triage this failure.
-mixin_super_constructor_test: Crash # Please triage this failure.
-mixin_type_parameter2_test: Crash # Please triage this failure.
-mixin_type_parameter3_test: Crash # Please triage this failure.
-mixin_type_parameters_mixin_extends_test: Crash # Please triage this failure.
-mixin_type_parameters_mixin_test: Crash # Please triage this failure.
-mixin_type_parameters_super_extends_test: Crash # Please triage this failure.
-mixin_type_parameters_super_test: Crash # Please triage this failure.
-mixin_typedef_constructor_test: Crash # Please triage this failure.
-mixin_with_two_implicit_constructors_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-modulo_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-multiple_field_assignment_constructor_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-named_parameter_clash_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-named_parameters_aggregated_test/05: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-naming_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-nested_switch_label_test: Crash #  Unhandled node
-no_such_constructor2_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-no_such_method_dispatcher_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-no_such_method_empty_selector_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
+mega_load_test: RuntimeError # Please triage this failure.
+method_binding_test: RuntimeError # Cannot read property 'prototype' of undefined
+methods_as_constants2_test: RuntimeError # Cannot read property 'prototype' of undefined
+minify_closure_variable_collision_test: RuntimeError # Please triage this failure.
+mint_compares_test: RuntimeError # Cannot read property 'prototype' of undefined
+mixin_bound_test: Crash # Internal Error: No default constructor available.
+mixin_forwarding_constructor1_test: Crash # Internal Error: No default constructor available.
+mixin_forwarding_constructor3_test: Crash # Internal Error: No default constructor available.
+mixin_prefix_test: Crash # Internal Error: No default constructor available.
+mixin_super_constructor2_test: Crash # Internal Error: No default constructor available.
+mixin_super_constructor_default_test: Crash # Internal Error: No default constructor available.
+mixin_super_constructor_multiple_test: Crash # Internal Error: No default constructor available.
+mixin_super_constructor_named_test/01: Crash # Internal Error: No default constructor available.
+mixin_super_constructor_named_test/none: Crash # Internal Error: No default constructor available.
+mixin_super_constructor_positionals_test/01: Crash # Internal Error: No default constructor available.
+mixin_super_constructor_positionals_test/none: Crash # Internal Error: No default constructor available.
+mixin_super_constructor_test: Crash # Internal Error: No default constructor available.
+mixin_type_parameter2_test: Crash # Internal Error: No default constructor available.
+mixin_type_parameter3_test: Crash # Internal Error: No default constructor available.
+mixin_type_parameters_mixin_extends_test: Crash # The null object does not have a getter '_element'.
+mixin_type_parameters_mixin_test: Crash # The null object does not have a getter '_element'.
+mixin_type_parameters_super_extends_test: Crash # The null object does not have a getter '_element'.
+mixin_type_parameters_super_test: Crash # The null object does not have a getter '_element'.
+mixin_typedef_constructor_test: Crash # Internal Error: No default constructor available.
+named_parameters_with_conversions_test: RuntimeError # Cannot read property 'prototype' of undefined
+named_parameters_with_dollars_test: RuntimeError # Please triage this failure.
+nested_if_test: RuntimeError # Please triage this failure.
+nested_switch_label_test: Crash # (switch (target){out...  continue to a labeled switch case
+no_such_method_dispatcher_test: RuntimeError # Please triage this failure.
+no_such_method_empty_selector_test: RuntimeError # Please triage this failure.
 no_such_method_test: RuntimeError # Please triage this failure.
-null_inline_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-null_no_such_method_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-null_test/01: Crash # Instance of 'TypeOperator': type casts not implemented.
-null_test/02: Crash # Instance of 'TypeOperator': type casts not implemented.
-null_test/03: Crash # Instance of 'TypeOperator': type casts not implemented.
-null_test/none: Crash # Instance of 'TypeOperator': type casts not implemented.
-number_identifier_test/05: Crash # Instance of 'TypeOperator': type casts not implemented.
-number_identifier_test/08: Crash # Instance of 'TypeOperator': type casts not implemented.
-number_identifier_test/09: Crash # Instance of 'TypeOperator': type casts not implemented.
-number_identifier_test/none: Crash # Instance of 'TypeOperator': type casts not implemented.
-on_catch_malformed_type_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-operator_equals_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-optimized_constant_array_string_access_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-optimized_string_charat_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-optimized_string_charcodeat_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
+null_test/none: Crash # Internal Error: No default constructor available.
+null_to_string2_test: RuntimeError # Cannot read property 'prototype' of undefined
+null_to_string_test: RuntimeError # Cannot read property 'prototype' of undefined
+operator_index_evaluation_order_test: RuntimeError # Please triage this failure.
+optimize_redundant_array_load_test: RuntimeError # Please triage this failure.
+optimized_lists_test: RuntimeError # Please triage this failure.
+osr_test: RuntimeError # Please triage this failure.
 overridden_no_such_method_test: RuntimeError # Please triage this failure.
-phi_merge_test: Crash # (switch (value){case 42:break;case 43:break;}): Unhandled node
-prefix16_test: Crash # Instance of 'TypeOperator': type check unimplemented for myFunc.
-private4_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-private_access_test/01: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-private_access_test/02: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-private_access_test/03: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-private_access_test/04: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-private_access_test/05: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-private_access_test/06: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-private_mixin2_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-range_analysis2_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-redirecting_factory_incompatible_signature_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-ref_before_declaration_test/00: Crash # (switch (x){case 0:var x='Does fuzzy logic tickle?';}): Unhandled node
-ref_before_declaration_test/01: Crash # (switch (x){case 0:var x='Does fuzzy logic tickle?';}): Unhandled node
-ref_before_declaration_test/02: Crash # (switch (x){case 0:var x='Does fuzzy logic tickle?';}): Unhandled node
-ref_before_declaration_test/03: Crash # (switch (x){case 0:var x='Does fuzzy logic tickle?';}): Unhandled node
-ref_before_declaration_test/04: Crash # (switch (x){case 0:var x='Does fuzzy logic tickle?';}): Unhandled node
-ref_before_declaration_test/05: Crash # (switch (x){case 0:var x='Does fuzzy logic tickle?';}): Unhandled node
-ref_before_declaration_test/06: Crash # (switch (x){case 0:var x='Does fuzzy logic tickle?';}): Unhandled node
-ref_before_declaration_test/07: Crash # (switch (x){case 0:var x='Does fuzzy logic tickle?';}): Unhandled node
-ref_before_declaration_test/none: Crash # (switch (x){case 0:var x='Does fuzzy logic tickle?';}): Unhandled node
-refine_receiver_null_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-reg_exp_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-regress_12561_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-regress_18435_test: Crash # Please triage this failure.
-regress_18535_test: Crash # Please triage this failure.
-regress_21795_test: Crash # (try {foo(t);}finally {if(t==0){try {}catch (err,st){}}}): try/finally
-regress_22438_test: Crash #  cannot handle async/sync*/async* functions
-regress_22443_test: RuntimeError # Please triage this failure.
-regress_22445_test: Crash #  cannot handle async/sync*/async* functions
-regress_22579_test: Crash #  cannot handle async/sync*/async* functions
-regress_22700_test: Crash # Please triage this failure.
-regress_22728_test: Crash #  cannot handle async/sync*/async* functions
-regress_22777_test: Crash #  cannot handle async/sync*/async* functions
-regress_22822_test: Crash # (try {for(int i=0;i<10;i++ ){return ()=>i+b;}}finally {b=10;}): try/finally
-regress_22936_test/01: Crash # Please triage this failure.
-regress_22936_test/none: Crash # Please triage this failure.
-regress_23498_test: Crash #  cannot handle async/sync*/async* functions
-regress_23500_test/01: Crash #  cannot handle async/sync*/async* functions
-regress_23500_test/02: Crash #  cannot handle async/sync*/async* functions
-regress_23500_test/none: Crash #  cannot handle async/sync*/async* functions
-regress_23537_test: Crash # try/finally
-reify_typevar_static_test/01: Crash # Please triage this failure.
-return_type_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-side_effect_throw_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-stack_trace_test: Crash #  try/finally
-statement_test: Crash #  try/finally
-static_postfix_operator_test: Crash # (try {if(a++ ==0){inIt=true;}}finally {}): try/finally
-static_setter_get_test/01: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-string_charcode_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-string_optimizations_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-super_all_named_constructor_test: Crash # Please triage this failure.
-super_bound_closure_test/01: RuntimeError # Please triage this failure.
-super_bound_closure_test/none: RuntimeError # Please triage this failure.
+override_method_with_field_test/02: RuntimeError # Cannot read property 'prototype' of undefined
+override_method_with_field_test/none: RuntimeError # Cannot read property 'prototype' of undefined
+param2_test: RuntimeError # Please triage this failure.
+prefix14_test: RuntimeError # Cannot read property 'prototype' of undefined
+prefix15_test: RuntimeError # Cannot read property 'prototype' of undefined
+prefix21_test: RuntimeError # Cannot read property 'prototype' of undefined
+pure_function2_test: RuntimeError # Please triage this failure.
+pure_function_test: RuntimeError # Please triage this failure.
+range_analysis_test: RuntimeError # Cannot read property 'prototype' of undefined
+recursive_calls_test: RuntimeError # Cannot read property 'prototype' of undefined
+reg_ex2_test: RuntimeError # Cannot read property 'prototype' of undefined
+reg_exp2_test: RuntimeError # Cannot read property 'prototype' of undefined
+reg_exp_test: RuntimeError # Please triage this failure.
+regress_11800_test: RuntimeError # Please triage this failure.
+regress_18435_test: Crash # Invalid argument(s)
+regress_18535_test: Crash # Internal Error: No default constructor available.
+regress_21016_test: RuntimeError # Please triage this failure.
+regress_22438_test: Crash # (main()async{var err...  cannot handle async/sync*/async* functions
+regress_22443_test: RuntimeError # receiver.get$_collection$_nums is not a function
+regress_22445_test: Crash # (main()async{var err...  cannot handle async/sync*/async* functions
+regress_22579_test: Crash # (main()async{var err...  cannot handle async/sync*/async* functions
+regress_22728_test: Crash # (main()async{bool fa...  cannot handle async/sync*/async* functions
+regress_22777_test: Crash # (test()async{try {te...  cannot handle async/sync*/async* functions
+regress_22936_test/01: Crash # The null object does not have a getter '_element'.
+regress_22936_test/none: Crash # The null object does not have a getter '_element'.
+regress_23498_test: Crash # (main()async{var err...  cannot handle async/sync*/async* functions
+regress_23500_test/01: Crash # (main()async{var err...  cannot handle async/sync*/async* functions
+regress_23500_test/02: Crash # (main()async{var err...  cannot handle async/sync*/async* functions
+regress_23500_test/none: Crash # (main()async{var err...  cannot handle async/sync*/async* functions
+static_closure_identical_test: RuntimeError # Cannot read property 'prototype' of undefined
+static_field_test/none: RuntimeError # Cannot read property 'prototype' of undefined
+static_implicit_closure_test: RuntimeError # Cannot read property 'prototype' of undefined
+string_interpolation_test/01: RuntimeError # Cannot read property 'prototype' of undefined
+string_interpolation_test/none: RuntimeError # Cannot read property 'prototype' of undefined
+string_join_test: RuntimeError # Please triage this failure.
+string_test: RuntimeError # Please triage this failure.
+super_bound_closure_test/01: RuntimeError # Cannot read property 'call' of undefined
+super_bound_closure_test/none: RuntimeError # Cannot read property 'call' of undefined
 super_call4_test: RuntimeError # Please triage this failure.
-super_getter_setter_test: Crash # Please triage this failure.
-super_implicit_closure_test: RuntimeError # Please triage this failure.
-super_inferrer_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-super_operator_index2_test: RuntimeError # Please triage this failure.
+super_getter_setter_test: Crash # Class 'PartialMethodElement' has no instance getter 'initializer'.
+super_implicit_closure_test: RuntimeError # Cannot read property 'prototype' of undefined
+super_operator_index2_test: RuntimeError # this.get$map is not a function
+super_operator_index3_test: RuntimeError # Please triage this failure.
+super_operator_index4_test: RuntimeError # Please triage this failure.
 super_operator_index5_test: Crash # (super[0]=42): visitUnresolvedSuperIndexSet
+super_operator_index6_test: RuntimeError # Please triage this failure.
 super_operator_index7_test: Crash # (super[0]=42): visitUnresolvedSuperIndexSet
 super_operator_index8_test: Crash # (super[f()]=g()): visitUnresolvedSuperIndexSet
-super_operator_index_test/01: Crash # Please triage this failure.
 super_operator_index_test/03: Crash # (super[4]=42): visitUnresolvedSuperIndexSet
-super_operator_index_test/04: Crash # Please triage this failure.
 super_operator_index_test/05: Crash # (super[4]=42): visitUnresolvedSuperIndexSet
-super_operator_index_test/06: Crash # Please triage this failure.
-super_operator_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-switch6_test: Crash # (switch (a){case 0:{x=0;break;}case 1:x=1;break;}): Unhandled node
-switch8_test: Crash # (switch (new List(1)[0]){case const A():throw 'Test failed';}): Unhandled node
-switch_bad_case_test/02: Crash # (switch (n){case 1:return "I";case 4:return "IV";}): Unhandled node
-switch_bad_case_test/none: Crash # (switch (n){case 1:return "I";case 4:return "IV";}): Unhandled node
-switch_case_static_const_test: Crash # (switch (p){case S:break;case A.S:break;case 'abc':break;}): Unhandled node
-switch_case_test/none: Crash # (switch (new B()){}): Unhandled node
-switch_fallthru_test: Crash # (switch (n){case 0:result="zero";break;case 1:result="one";case 9:result="nine";}): Unhandled node
-switch_label2_test: Crash #  Unhandled node
-switch_label_test: Crash #  Unhandled node
-switch_scope_test: Crash #  Unhandled node
-switch_test: Crash # (switch (input){case true:result=12;break;case false:result=22;}): Unhandled node
-switch_try_catch_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-sync_generator1_test/01: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-sync_generator1_test/none: Crash #  cannot handle async/sync*/async* functions
-sync_generator2_test/01: Crash # (sync()sync*{yield sync;}): cannot handle async/sync*/async* functions
-sync_generator2_test/02: Crash # (sync()sync*{yield sync;}): cannot handle async/sync*/async* functions
-sync_generator2_test/03: Crash # (sync()sync*{yield sync;}): cannot handle async/sync*/async* functions
-sync_generator2_test/04: Crash # (sync()sync*{yield sync;}): cannot handle async/sync*/async* functions
-sync_generator2_test/05: Crash # (sync()sync*{yield sync;}): cannot handle async/sync*/async* functions
-sync_generator2_test/06: Crash # (sync()sync*{yield sync;}): cannot handle async/sync*/async* functions
+super_operator_index_test/06: Crash # The null object does not have a getter 'isParameter'.
+super_operator_test: RuntimeError # Please triage this failure.
+switch_label2_test: Crash # (switch (target){cas...  continue to a labeled switch case
+switch_label_test: Crash # (switch (animal){cas...  continue to a labeled switch case
+switch_try_catch_test: Crash # (switch (0){_0:case ...  continue to a labeled switch case
+sync_generator1_test/01: Crash # (dreiVier()sync*{yield* 3;}): cannot handle async/sync*/async* functions
+sync_generator1_test/none: Crash # (einsZwei()sync*{yie...  cannot handle async/sync*/async* functions
 sync_generator2_test/07: Crash # (sync()sync*{yield sync;}): cannot handle async/sync*/async* functions
 sync_generator2_test/08: Crash # (sync()sync*{yield sync;}): cannot handle async/sync*/async* functions
-sync_generator2_test/09: Crash # (sync()sync*{yield sync;}): cannot handle async/sync*/async* functions
 sync_generator2_test/10: Crash # (sync()sync*{yield sync;}): cannot handle async/sync*/async* functions
-sync_generator2_test/11: Crash # (sync()sync*{yield sync;}): cannot handle async/sync*/async* functions
-sync_generator2_test/20: Crash # (sync()sync*{yield sync;}): cannot handle async/sync*/async* functions
-sync_generator2_test/30: Crash # (sync()sync*{yield sync;}): cannot handle async/sync*/async* functions
-sync_generator2_test/40: Crash # (sync()sync*{yield sync;}): cannot handle async/sync*/async* functions
-sync_generator2_test/41: Crash # (sync()sync*{yield sync;}): cannot handle async/sync*/async* functions
-sync_generator2_test/50: Crash # (test02()sync*{yield 12321;}): cannot handle async/sync*/async* functions
-sync_generator2_test/51: Crash # (sync()sync*{yield sync;}): cannot handle async/sync*/async* functions
-sync_generator2_test/52: Crash # (sync()sync*{yield sync;}): cannot handle async/sync*/async* functions
 sync_generator2_test/none: Crash # (sync()sync*{yield sync;}): cannot handle async/sync*/async* functions
-sync_generator3_test/test1: Crash #  cannot handle async/sync*/async* functions
-sync_generator3_test/test2: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-syncstar_yield_test/copyParameters: Crash #  cannot handle async/sync*/async* functions
-syncstar_yield_test/none: Crash #  cannot handle async/sync*/async* functions
-syncstar_yieldstar_test: Crash #  cannot handle async/sync*/async* functions
-throw1_test: Crash #  try/finally
-throw2_test: Crash #  try/finally
-throw3_test: Crash #  try/finally
-throw4_test: Crash #  try/finally
-throw5_test: Crash #  try/finally
-throw6_test: Crash #  try/finally
-throw8_test: Crash #  try/finally
-throw_expr_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-throw_test: Crash #  try/finally
-truncdiv_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-try_catch3_test: Crash #  try/finally
-try_catch4_test: Crash #  try/finally
-try_catch5_test: Crash # (try {try {a=8;return;}finally {b=8==a;entered=true;continue;}}finally {continue;}): try/finally
-try_catch_optimized2_test: Crash # (try {bar();}finally {}): try/finally
-try_catch_osr_test: Crash # (try {if(x==null)throw 42;return 99;}finally {}): try/finally
-try_catch_test/01: Crash # Please triage this failure.
-try_catch_test/none: Crash # Please triage this failure.
-type_argument_in_super_type_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-type_check_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-type_error_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-type_literal_prefix_call_test/00: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-type_parameter_test/01: Crash # Please triage this failure.
-type_parameter_test/02: Crash # Please triage this failure.
-type_parameter_test/03: Crash # Please triage this failure.
-type_parameter_test/04: Crash # Please triage this failure.
-type_parameter_test/05: Crash # Please triage this failure.
-type_parameter_test/06: Crash # Please triage this failure.
-type_parameter_test/none: Crash # Please triage this failure.
-type_promotion_functions_test/01: Crash # Instance of 'TypeOperator': type check unimplemented for FuncDynToDyn.
-type_promotion_functions_test/02: Crash # Instance of 'TypeOperator': type check unimplemented for FuncDynToDyn.
-type_promotion_functions_test/03: Crash # Instance of 'TypeOperator': type check unimplemented for FuncDynToDyn.
-type_promotion_functions_test/04: Crash # Instance of 'TypeOperator': type check unimplemented for FuncDynToDyn.
-type_promotion_functions_test/05: Crash # Instance of 'TypeOperator': type check unimplemented for FuncDynToDyn.
-type_promotion_functions_test/06: Crash # Instance of 'TypeOperator': type check unimplemented for FuncDynToDyn.
-type_promotion_functions_test/07: Crash # Instance of 'TypeOperator': type check unimplemented for FuncDynToDyn.
-type_promotion_functions_test/08: Crash # Instance of 'TypeOperator': type check unimplemented for FuncDynToDyn.
-type_promotion_functions_test/09: Crash # Instance of 'TypeOperator': type check unimplemented for FuncDynToDyn.
-type_promotion_functions_test/10: Crash # Instance of 'TypeOperator': type check unimplemented for FuncDynToDyn.
-type_promotion_functions_test/11: Crash # Instance of 'TypeOperator': type check unimplemented for FuncDynToDyn.
-type_promotion_functions_test/12: Crash # Instance of 'TypeOperator': type check unimplemented for FuncDynToDyn.
-type_promotion_functions_test/13: Crash # Instance of 'TypeOperator': type check unimplemented for FuncDynToDyn.
-type_promotion_functions_test/14: Crash # Instance of 'TypeOperator': type check unimplemented for FuncDynToDyn.
-type_promotion_functions_test/none: Crash # Instance of 'TypeOperator': type check unimplemented for FuncDynToDyn.
-type_propagation_in_for_update_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
+sync_generator3_test/test1: Crash # (f()sync*{try {yield...  cannot handle async/sync*/async* functions
+sync_generator3_test/test2: Crash # (g()sync*{try {yield...  cannot handle async/sync*/async* functions
+syncstar_yield_test/copyParameters: Crash # (Iterable<int> foo3(...  cannot handle async/sync*/async* functions
+syncstar_yield_test/none: Crash # (Iterable<int> foo3(...  cannot handle async/sync*/async* functions
+syncstar_yieldstar_test: Crash # (main()async{Expect....  cannot handle async/sync*/async* functions
+top_level_in_initializer_test: RuntimeError # Cannot read property 'prototype' of undefined
+try_catch_test/none: Crash # The null object does not have a getter '_element'.
+type_check_const_function_typedef2_test/00: RuntimeError # Cannot read property 'prototype' of undefined
+type_check_const_function_typedef2_test/none: RuntimeError # Cannot read property 'prototype' of undefined
+type_check_const_function_typedef_test: RuntimeError # Cannot read property 'prototype' of undefined
+type_parameter_test/01: Crash # Invalid argument(s)
+type_parameter_test/02: Crash # Invalid argument(s)
+type_parameter_test/03: Crash # Invalid argument(s)
+type_parameter_test/04: Crash # Invalid argument(s)
+type_parameter_test/05: Crash # Invalid argument(s)
+type_parameter_test/06: Crash # Invalid argument(s)
+type_parameter_test/none: Crash # Invalid argument(s)
+type_promotion_functions_test/01: RuntimeError # Cannot read property 'prototype' of undefined
+type_promotion_functions_test/02: RuntimeError # Cannot read property 'prototype' of undefined
+type_promotion_functions_test/03: RuntimeError # Cannot read property 'prototype' of undefined
+type_promotion_functions_test/04: RuntimeError # Cannot read property 'prototype' of undefined
+type_promotion_functions_test/05: RuntimeError # Cannot read property 'prototype' of undefined
+type_promotion_functions_test/06: RuntimeError # Cannot read property 'prototype' of undefined
+type_promotion_functions_test/07: RuntimeError # Cannot read property 'prototype' of undefined
+type_promotion_functions_test/08: RuntimeError # Cannot read property 'prototype' of undefined
+type_promotion_functions_test/09: RuntimeError # Cannot read property 'prototype' of undefined
+type_promotion_functions_test/10: RuntimeError # Cannot read property 'prototype' of undefined
+type_promotion_functions_test/11: RuntimeError # Cannot read property 'prototype' of undefined
+type_promotion_functions_test/12: RuntimeError # Cannot read property 'prototype' of undefined
+type_promotion_functions_test/13: RuntimeError # Cannot read property 'prototype' of undefined
+type_promotion_functions_test/14: RuntimeError # Cannot read property 'prototype' of undefined
+type_promotion_functions_test/none: RuntimeError # Cannot read property 'prototype' of undefined
 type_variable_closure2_test: RuntimeError # Please triage this failure.
-type_variable_closure_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-type_variable_conflict2_test/03: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-type_variable_conflict2_test/04: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-type_variable_conflict2_test/05: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-type_variable_conflict2_test/07: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-type_variable_conflict2_test/09: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-type_variable_function_type_test: Crash # Instance of 'TypeOperator': type check unimplemented for Func<S>.
-type_variable_typedef_test: Crash # type expression Foo<T> (typedef)
-typed_equality_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-typedef_is_test: Crash # Instance of 'TypeOperator': type check unimplemented for Func1.
-typevariable_substitution2_test/01: Crash # Please triage this failure.
-typevariable_substitution2_test/02: Crash # Please triage this failure.
-typevariable_substitution2_test/none: Crash # Please triage this failure.
-unresolved_default_constructor_test/01: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-value_range2_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-value_range3_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-value_range_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-void_type_test: Crash #  Unhandled node
+type_variable_closure_test: Crash # Invalid argument(s)
+type_variable_conflict2_test/07: RuntimeError # Please triage this failure.
+typedef_is_test: RuntimeError # Cannot read property 'prototype' of undefined
+typevariable_substitution2_test/01: Crash # Internal Error: No default constructor available.
+typevariable_substitution2_test/02: Crash # Internal Error: No default constructor available.
+typevariable_substitution2_test/none: Crash # Internal Error: No default constructor available.
diff --git a/tests/language/nullaware_opt_test.dart b/tests/language/nullaware_opt_test.dart
new file mode 100644
index 0000000..aafb7ac
--- /dev/null
+++ b/tests/language/nullaware_opt_test.dart
@@ -0,0 +1,72 @@
+// 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-null-aware-operators
+// VMOptions=--optimization_counter_threshold=5
+//
+// Basic null-aware operator test that invokes the optimizing compiler.
+
+import "package:expect/expect.dart";
+
+class C {
+  C(this.f);
+  var f;
+  m(a) => a;
+}
+
+bomb() {
+  Expect.fail('Should not be executed');
+  return 100;
+}
+
+getNull() => null;
+
+test() {
+  var c;
+  var d = new C(5);
+  Expect.equals(null, c?.m(bomb()));
+  Expect.equals(null, getNull()?.anything(bomb()));
+  Expect.equals(1, d?.m(1));
+  Expect.equals("C", C?.toString());
+
+  Expect.equals(1, new C(1)?.f);
+  Expect.equals(null, c?.v);
+  Expect.equals(10, c ?? 10);
+  Expect.equals(d, d ?? bomb());
+
+  var e;
+  // The assginment to e is not executed since d != null.
+  d ??= e ??= new C(100);
+  Expect.equals(null, e);
+  e ??= new C(100);
+  Expect.equals(100, e?.f);
+  e?.f ??= 200;
+  Expect.equals(100, e?.f);
+
+  e.f = null;
+  e?.f ??= 200;
+  Expect.equals(200, e?.f);
+
+  c?.f ??= 400;
+  Expect.equals(null, c?.f);
+  Expect.equals(null, c?.f++);
+  e?.f++;
+  Expect.equals(201, e.f);
+
+  var x = 5 ?? bomb();
+}
+
+// Check that instructions without result do not crash.
+test2() {
+  var c;
+  c?.v;
+  c?.m(bomb());
+}
+
+main() {
+  for (int i = 0; i < 10; i++) {
+    test();
+    test2();
+  }
+}
\ No newline at end of file
diff --git a/tests/language/prefix_assignment_test.dart b/tests/language/prefix_assignment_test.dart
new file mode 100644
index 0000000..b473fc2
--- /dev/null
+++ b/tests/language/prefix_assignment_test.dart
@@ -0,0 +1,26 @@
+// 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.
+
+// Validate that assignment to a prefix is handled consistently with the
+// following spec text from section 16.19 (Assignment):
+//     Evaluation of an assignment a of the form v = e proceeds as follows:
+//     Let d be the innermost declaration whose name is v or v=, if it exists.
+//     It is a compile-time error if d denotes a prefix object.
+
+import "empty_library.dart" as p;
+
+class Base {
+  var p;
+}
+
+class Derived extends Base {
+  void f() {
+    p = 1; /// 01: compile-time error
+  }
+}
+
+main() {
+  new Derived().f();
+  p = 1; /// 02: compile-time error
+}
diff --git a/tests/language/prefix_identifier_reference_test.dart b/tests/language/prefix_identifier_reference_test.dart
new file mode 100644
index 0000000..a45d3bd
--- /dev/null
+++ b/tests/language/prefix_identifier_reference_test.dart
@@ -0,0 +1,25 @@
+// 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.
+
+// Validate the following spec text from section 16.32 (Identifier Reference):
+//     Evaluation of an identifier expression e of the form id proceeds as
+//   follows:
+//     Let d be the innermost declaration in the enclosing lexical scope whose
+//   name is id or id=.  If no such declaration exists in the lexical scope,
+//   d be the declaration of the inherited member named id if it exists.
+//     - If d is a prefix p, a compile-time error occurs unless the token
+//       immediately following d is '.'.
+
+import "package:expect/expect.dart";
+import "empty_library.dart" as p;
+
+void f(x) {}
+
+main() {
+  f(p);         /// 01: compile-time error
+  var x = p;    /// 02: compile-time error
+  var x = p[0]; /// 03: compile-time error
+  p[0] = null;  /// 04: compile-time error
+  p += 0;       /// 05: compile-time error
+}
diff --git a/tests/language/prefix_unqualified_invocation_test.dart b/tests/language/prefix_unqualified_invocation_test.dart
new file mode 100644
index 0000000..020ca3e
--- /dev/null
+++ b/tests/language/prefix_unqualified_invocation_test.dart
@@ -0,0 +1,29 @@
+// 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.
+
+// Validate the following spec text from section 16.14.3 (Unqualified
+// invocation):
+//     An unqualifiedfunction invocation i has the form
+//     id(a1, ..., an, xn+1 : an+1, ..., xn+k : an+k),
+//     where id is an identifier.
+//     If there exists a lexically visible declaration named id, let fid be the
+//   innermost such declaration.  Then:
+//     - If fid is a prefix object, a compile-time error occurs.
+
+import "empty_library.dart" as p;
+
+class Base {
+  void p() {}
+}
+
+class Derived extends Base {
+  void f() {
+    p(); /// 01: compile-time error
+  }
+}
+
+main() {
+  new Derived().f();
+  p(); /// 02: compile-time error
+}
diff --git a/tests/language/regress_23650_test.dart b/tests/language/regress_23650_test.dart
new file mode 100644
index 0000000..2beb67b
--- /dev/null
+++ b/tests/language/regress_23650_test.dart
@@ -0,0 +1,23 @@
+// 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 that type variables in try-catch work.
+
+import "package:expect/expect.dart";
+
+class C<T> {
+  C.foo();
+  factory C() {
+    try {
+      return new C<T>.foo();
+    } finally {
+    }
+  }
+}
+
+main() {
+  var c = new C<int>();
+  Expect.isTrue(c is C<int>);
+  Expect.isFalse(c is C<String>);
+}
diff --git a/tests/lib/async/future_test.dart b/tests/lib/async/future_test.dart
index 900eea6..030340d 100644
--- a/tests/lib/async/future_test.dart
+++ b/tests/lib/async/future_test.dart
@@ -882,7 +882,7 @@
   asyncStart();
   Completer completer = new Completer();
   completer.complete(bad);
-  completer.future.then((_) { fail("unreachable"); },
+  completer.future.then((_) { Expect.fail("unreachable"); },
                         onError: (e, s) {
                           Expect.isTrue(completer.isCompleted);
                           asyncEnd();
@@ -890,12 +890,42 @@
 
   asyncStart();
   var f = new Future.value().then((_) => bad);
-  f.then((_) { fail("unreachable"); },
+  f.then((_) { Expect.fail("unreachable"); },
          onError: (e, s) {
            asyncEnd();
          });
 }
 
+void testTypes() {
+  // Test that future is a Future<int> and not something less precise.
+  testType(name, future, [depth = 2]) {
+    var desc = "$name${".whenComplete"*(2-depth)}";
+    Expect.isTrue(future is Future<int>, "$desc is Future<int>");
+    Expect.isFalse(future is Future<String>, "$desc is! Future<String>");
+    var stream = future.asStream();
+    Expect.isTrue(stream is Stream<int>, "$desc.asStream() is Stream<int>");
+    Expect.isFalse(stream is Stream<String>,
+                   "$desc.asStream() is! Stream<String>");
+    if (depth > 0) {
+      testType(name, future.whenComplete((){}), depth - 1);
+    }
+  }
+  for (var value in [42, null]) {
+    testType("Future($value)",
+             new Future<int>(() => value));
+    testType("Future.delayed($value)",
+             new Future<int>.delayed(Duration.ZERO, () => value));
+    testType("Future.microtask($value)",
+             new Future<int>.microtask(() => value));
+    testType("Future.sync($value)", new Future<int>.sync(() => value));  /// 01: ok
+    testType("Future.sync(future($value))",                              /// 01: continued
+             new Future<int>.sync(() async => new Future.value(value))); /// 01: continued
+    testType("Future.value($value)", new Future<int>.value(value));
+  }
+  testType("Completer.future", new Completer<int>().future);
+  testType("Future.error", new Future<int>.error("ERR")..catchError((_){}));
+}
+
 main() {
   asyncStart();
 
@@ -957,6 +987,8 @@
 
   testBadFuture();
 
+  testTypes();
+
   asyncEnd();
 }
 
@@ -977,13 +1009,19 @@
 }
 
 class BadFuture<T> implements Future<T> {
-  Future then(action(result)) {
+  Future then(action(T result), {Function onError}) {
     throw "then GOTCHA!";
   }
-  Future catchError(Function onError) {
+  Future catchError(Function onError, {bool test(e)}) {
     throw "catch GOTCHA!";
   }
   Future whenComplete(action()) {
     throw "finally GOTCHA!";
   }
+  Stream<T> asStream() {
+    throw "asStream GOTCHA!";
+  }
+  Future timeout(Duration duration, {onTimeout()}) {
+    throw "timeout GOTCHA!";
+  }
 }
diff --git a/tests/lib/async/stream_empty_test.dart b/tests/lib/async/stream_empty_test.dart
new file mode 100644
index 0000000..c1d4b7b
--- /dev/null
+++ b/tests/lib/async/stream_empty_test.dart
@@ -0,0 +1,63 @@
+// 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 empty stream.
+import "package:expect/expect.dart";
+import "dart:async";
+import 'package:async_helper/async_helper.dart';
+
+main() {
+  asyncStart();
+  runTest().whenComplete(asyncEnd);
+}
+
+Future runTest() async {
+  unreachable([a,b]) { throw "UNREACHABLE"; }
+  int tick = 0;
+  ticker() { tick++; }
+
+  asyncStart();
+
+  Stream<int> s = const Stream<int>.empty();  // Is const constructor.
+  Expect.isFalse(s is Stream<String>);  // Respects type parameter.
+  StreamSubscription<int> sub =
+     s.listen(unreachable, onError: unreachable, onDone: ticker);
+  Expect.isFalse(sub is StreamSubscription<String>);  // Type parameter in sub.
+
+  // Doesn't do callback in response to listen.
+  Expect.equals(tick, 0);
+  await flushMicrotasks();
+  // Completes eventually.
+  Expect.equals(tick, 1);
+
+  // It's a broadcast stream - can listen twice.
+  Expect.isTrue(s.isBroadcast);
+  StreamSubscription<int> sub2 =
+     s.listen(unreachable, onError: unreachable, onDone: unreachable);
+  // respects pause.
+  sub2.pause();
+  await flushMicrotasks();
+  // respects cancel.
+  sub2.cancel();
+  await flushMicrotasks();
+  Expect.equals(tick, 1);
+  // Still not complete.
+
+  StreamSubscription<int> sub3 =
+     s.listen(unreachable, onError: unreachable, onDone: ticker);
+  // respects pause.
+  sub3.pause();
+  Expect.equals(tick, 1);
+  await flushMicrotasks();
+  // Doesn't complete while paused.
+  Expect.equals(tick, 1);
+  sub3.resume();
+  await flushMicrotasks();
+  // Now completed.
+  Expect.equals(tick, 2);
+
+  asyncEnd();
+}
+
+Future flushMicrotasks() => new Future.delayed(Duration.ZERO);
diff --git a/tests/lib/lib.status b/tests/lib/lib.status
index 006ecc0..184c01d 100644
--- a/tests/lib/lib.status
+++ b/tests/lib/lib.status
@@ -76,6 +76,7 @@
 mirrors/method_mirror_location_test: RuntimeError # Issue 6490
 mirrors/mirrors_test: RuntimeError # TODO(ahe): I'm working on fixing this. When removing this line please change the "endsWith" to "/mirrors_test.dart".
 mirrors/mirrors_nsm_test/dart2js: RuntimeError # Issue 19353
+mirrors/mirrors_nsm_mismatch_test: RuntimeError # Issue 19353
 mirrors/mixin_test: RuntimeError # Issue 12464
 mirrors/mixin_application_test: RuntimeError # Issue 12464
 mirrors/other_declarations_location_test: CompileTimeError # Issue 10905
@@ -277,6 +278,7 @@
 mirrors/immutable_collections_test: StaticWarning, OK # Expect failure for any type of Iterable.
 mirrors/inference_and_no_such_method_test: StaticWarning, OK # Expect to trigger noSuchMethod.
 mirrors/mirrors_nsm_test: StaticWarning, OK # Expect to trigger noSuchMethod.
+mirrors/mirrors_nsm_mismatch_test: StaticWarning, OK # Expect to trigger noSuchMethod.
 
 mirrors/repeated_private_anon_mixin_app_test: StaticWarning, OK # Intentional library name conflict.
 mirrors/removed_api_test: StaticWarning, OK # Deliberately refers to undeclared members.
@@ -289,8 +291,6 @@
 profiler/metrics_test: Fail # Issue 20309
 profiler/metrics_num_test: Fail # Issue 20309
 
-async/future_test: StaticWarning, OK # Deliberately broken implementation.
-
 [ ($compiler == dartanalyzer || $compiler == dart2analyzer) && $checked ]
 mirrors/regress_16321_test/01: MissingCompileTimeError # Issue 16391
 
@@ -328,315 +328,430 @@
 convert/streamed_conversion_json_utf8_decode_test: Skip  # Timeout.
 
 [ $compiler == dart2js && $cps_ir ]
-async/first_regression_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-async/future_timeout_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-async/future_value_chain4_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-async/multiple_timer_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-async/schedule_microtask2_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-async/schedule_microtask3_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-async/schedule_microtask5_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-async/schedule_microtask_test: Crash # Please triage this failure.
-async/stream_controller_async_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-async/stream_controller_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-async/stream_first_where_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-async/stream_from_iterable_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-async/stream_iterator_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-async/stream_join_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-async/stream_last_where_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-async/stream_listen_zone_test: Crash #  Unhandled node
-async/stream_periodic2_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-async/stream_periodic3_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-async/stream_periodic4_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-async/stream_periodic5_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-async/stream_periodic_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-async/stream_single_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-async/stream_single_to_multi_subscriber_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-async/stream_state_nonzero_timer_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-async/stream_state_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-async/stream_subscription_as_future_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-async/stream_subscription_cancel_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-async/stream_timeout_test: Crash # Please triage this failure.
-async/stream_transform_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-async/stream_transformation_broadcast_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-async/timer_cancel1_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-async/timer_cancel2_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-async/timer_cancel_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-async/timer_isActive_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-async/timer_repeat_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-async/timer_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-collection/linked_list_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-convert/ascii_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
+async/catch_errors11_test: RuntimeError # receiver.get$_nums is not a function
+async/catch_errors12_test: RuntimeError # receiver.get$_nums is not a function
+async/catch_errors13_test: RuntimeError # receiver.get$_nums is not a function
+async/catch_errors14_test: RuntimeError # receiver.get$_nums is not a function
+async/catch_errors15_test: RuntimeError # receiver.get$_nums is not a function
+async/catch_errors16_test: RuntimeError # receiver.get$_nums is not a function
+async/catch_errors17_test: RuntimeError # receiver.get$_nums is not a function
+async/catch_errors18_test: RuntimeError # receiver.get$_nums is not a function
+async/catch_errors19_test: RuntimeError # receiver.get$_nums is not a function
+async/catch_errors20_test: RuntimeError # receiver.get$_nums is not a function
+async/catch_errors21_test: RuntimeError # receiver.get$_nums is not a function
+async/catch_errors22_test: RuntimeError # receiver.get$_nums is not a function
+async/catch_errors23_test: RuntimeError # receiver.get$_nums is not a function
+async/catch_errors24_test: RuntimeError # receiver.get$_nums is not a function
+async/catch_errors25_test: RuntimeError # receiver.get$_nums is not a function
+async/catch_errors26_test: RuntimeError # receiver.get$_nums is not a function
+async/catch_errors27_test: RuntimeError # receiver.get$_nums is not a function
+async/catch_errors28_test: RuntimeError # receiver.get$_nums is not a function
+async/catch_errors2_test: RuntimeError # receiver.get$_nums is not a function
+async/catch_errors3_test: RuntimeError # receiver.get$_nums is not a function
+async/catch_errors4_test: RuntimeError # receiver.get$_nums is not a function
+async/catch_errors5_test: RuntimeError # receiver.get$_nums is not a function
+async/catch_errors6_test: RuntimeError # receiver.get$_nums is not a function
+async/catch_errors7_test: RuntimeError # receiver.get$_nums is not a function
+async/catch_errors8_test: RuntimeError # receiver.get$_nums is not a function
+async/catch_errors_test: RuntimeError # receiver.get$_nums is not a function
+async/first_regression_test: Crash # Invalid argument(s)
+async/future_constructor_test: RuntimeError # receiver.get$_collection$_nums is not a function
+async/future_delayed_error_test: RuntimeError # receiver.get$_collection$_nums is not a function
+async/future_microtask_test: RuntimeError # receiver.get$_collection$_nums is not a function
+async/future_test/01: Crash # (()async=>new Future.value(value)): cannot handle async/sync*/async* functions
+async/future_test/none: RuntimeError # receiver.get$_nums is not a function
+async/future_timeout_test: Crash # Invalid argument(s)
+async/future_value_chain2_test: RuntimeError # receiver.get$_collection$_nums is not a function
+async/future_value_chain3_test: RuntimeError # receiver.get$_collection$_nums is not a function
+async/future_value_chain4_test: RuntimeError # receiver.get$_collection$_nums is not a function
+async/future_value_chain_test: RuntimeError # receiver.get$_collection$_nums is not a function
+async/futures_test: RuntimeError # receiver.get$_collection$_nums is not a function
+async/intercept_print1_test: RuntimeError # receiver.get$_collection$_nums is not a function
+async/intercept_schedule_microtask1_test: RuntimeError # receiver.get$_nums is not a function
+async/intercept_schedule_microtask2_test: RuntimeError # receiver.get$_nums is not a function
+async/intercept_schedule_microtask3_test: RuntimeError # receiver.get$_nums is not a function
+async/intercept_schedule_microtask4_test: RuntimeError # receiver.get$_nums is not a function
+async/intercept_schedule_microtask5_test: RuntimeError # receiver.get$_nums is not a function
+async/intercept_schedule_microtask6_test: RuntimeError # receiver.get$_nums is not a function
+async/multiple_timer_test: Crash # Invalid argument(s)
+async/print_test/none: RuntimeError # receiver.get$_nums is not a function
+async/run_zoned1_test: RuntimeError # receiver.get$_nums is not a function
+async/run_zoned4_test: RuntimeError # receiver.get$_nums is not a function
+async/run_zoned5_test: RuntimeError # receiver.get$_nums is not a function
+async/run_zoned6_test/none: RuntimeError # receiver.get$_nums is not a function
+async/run_zoned7_test: RuntimeError # receiver.get$_nums is not a function
+async/run_zoned8_test: RuntimeError # receiver.get$_nums is not a function
+async/run_zoned9_test/none: RuntimeError # receiver.get$_nums is not a function
+async/schedule_microtask2_test: Crash # Invalid argument(s)
+async/schedule_microtask3_test: Crash # Invalid argument(s)
+async/schedule_microtask5_test: Crash # Invalid argument(s)
+async/schedule_microtask_test: Crash # Invalid argument(s)
+async/slow_consumer2_test: RuntimeError # receiver.get$_collection$_nums is not a function
+async/slow_consumer3_test: RuntimeError # receiver.get$_collection$_nums is not a function
+async/slow_consumer_test: RuntimeError # receiver.get$_collection$_nums is not a function
+async/stack_trace01_test: RuntimeError # receiver.get$_collection$_nums is not a function
+async/stack_trace02_test: RuntimeError # receiver.get$_collection$_nums is not a function
+async/stack_trace03_test: RuntimeError # receiver.get$_collection$_nums is not a function
+async/stack_trace04_test: RuntimeError # receiver.get$_collection$_nums is not a function
+async/stack_trace05_test: RuntimeError # receiver.get$_collection$_nums is not a function
+async/stack_trace06_test: RuntimeError # receiver.get$_collection$_nums is not a function
+async/stack_trace07_test: RuntimeError # receiver.get$_collection$_nums is not a function
+async/stack_trace08_test: RuntimeError # receiver.get$_collection$_nums is not a function
+async/stack_trace09_test: RuntimeError # receiver.get$_collection$_nums is not a function
+async/stack_trace10_test: RuntimeError # receiver.get$_collection$_nums is not a function
+async/stack_trace11_test: RuntimeError # receiver.get$_collection$_nums is not a function
+async/stack_trace12_test: RuntimeError # receiver.get$_collection$_nums is not a function
+async/stack_trace13_test: RuntimeError # receiver.get$_collection$_nums is not a function
+async/stack_trace14_test: RuntimeError # receiver.get$_collection$_nums is not a function
+async/stack_trace15_test: RuntimeError # receiver.get$_collection$_nums is not a function
+async/stack_trace16_test: RuntimeError # receiver.get$_collection$_nums is not a function
+async/stack_trace17_test: RuntimeError # receiver.get$_collection$_nums is not a function
+async/stack_trace18_test: RuntimeError # receiver.get$_collection$_nums is not a function
+async/stack_trace19_test: RuntimeError # receiver.get$_collection$_nums is not a function
+async/stack_trace20_test: RuntimeError # receiver.get$_collection$_nums is not a function
+async/stack_trace21_test: RuntimeError # receiver.get$_collection$_nums is not a function
+async/stack_trace22_test: RuntimeError # receiver.get$_collection$_nums is not a function
+async/stack_trace23_test: RuntimeError # receiver.get$_collection$_nums is not a function
+async/stack_trace24_test: RuntimeError # receiver.get$_collection$_nums is not a function
+async/stack_trace25_test: RuntimeError # receiver.get$_collection$_nums is not a function
+async/stream_controller_async_test: Crash # Invalid argument(s)
+async/stream_controller_test: RuntimeError # receiver.get$_collection$_nums is not a function
+async/stream_empty_test: Crash # (Future runTest()asy...  cannot handle async/sync*/async* functions
+async/stream_event_transformed_test: RuntimeError # receiver.get$_nums is not a function
+async/stream_first_where_test: Crash # Invalid argument(s)
+async/stream_from_iterable_test: Crash # Invalid argument(s)
+async/stream_iterator_double_cancel_test: RuntimeError # receiver.get$_collection$_nums is not a function
+async/stream_iterator_test: Crash # Invalid argument(s)
+async/stream_join_test: Crash # Invalid argument(s)
+async/stream_last_where_test: Crash # Invalid argument(s)
+async/stream_listen_zone_test: RuntimeError # receiver.get$_nums is not a function
+async/stream_periodic2_test: Crash # Invalid argument(s)
+async/stream_periodic3_test: Crash # Invalid argument(s)
+async/stream_periodic4_test: Crash # Invalid argument(s)
+async/stream_periodic5_test: Crash # Invalid argument(s)
+async/stream_periodic_test: Crash # Invalid argument(s)
+async/stream_single_test: Crash # Invalid argument(s)
+async/stream_single_to_multi_subscriber_test: Crash # Invalid argument(s)
+async/stream_state_nonzero_timer_test: Crash # Invalid argument(s)
+async/stream_state_test: Crash # Invalid argument(s)
+async/stream_subscription_as_future_test: Crash # Invalid argument(s)
+async/stream_subscription_cancel_test: Crash # Invalid argument(s)
+async/stream_timeout_test: Crash # Invalid argument(s)
+async/stream_transform_test: Crash # Invalid argument(s)
+async/stream_transformation_broadcast_test: Crash # Invalid argument(s)
+async/stream_transformer_from_handlers_test: RuntimeError # receiver.get$_collection$_nums is not a function
+async/stream_transformer_test: RuntimeError # receiver.get$_collection$_nums is not a function
+async/stream_zones_test: RuntimeError # receiver.get$_nums is not a function
+async/timer_cancel1_test: Crash # Invalid argument(s)
+async/timer_cancel2_test: Crash # Invalid argument(s)
+async/timer_cancel_test: Crash # Invalid argument(s)
+async/timer_isActive_test: Crash # Invalid argument(s)
+async/timer_regress22626_test: RuntimeError # receiver.get$_collection$_nums is not a function
+async/timer_repeat_test: Crash # Invalid argument(s)
+async/timer_test: Crash # Invalid argument(s)
+async/zone_bind_callback_test: RuntimeError # receiver.get$_nums is not a function
+async/zone_bind_callback_unary_test: RuntimeError # receiver.get$_nums is not a function
+async/zone_bind_test: RuntimeError # receiver.get$_nums is not a function
+async/zone_create_periodic_timer_test: RuntimeError # receiver.get$_nums is not a function
+async/zone_create_timer2_test: RuntimeError # receiver.get$_nums is not a function
+async/zone_create_timer_test: RuntimeError # receiver.get$_nums is not a function
+async/zone_debug_test: RuntimeError # receiver.get$_nums is not a function
+async/zone_empty_description2_test: RuntimeError # receiver.get$_nums is not a function
+async/zone_empty_description_test: RuntimeError # receiver.get$_nums is not a function
+async/zone_error_callback_test: RuntimeError # receiver.get$_nums is not a function
+async/zone_fork_test: RuntimeError # receiver.get$_nums is not a function
+async/zone_future_schedule_microtask_test: RuntimeError # receiver.get$_nums is not a function
+async/zone_register_callback_test: RuntimeError # receiver.get$_nums is not a function
+async/zone_register_callback_unary_test: RuntimeError # receiver.get$_nums is not a function
+async/zone_root_bind_test: RuntimeError # receiver.get$_nums is not a function
+async/zone_run_guarded_test: RuntimeError # receiver.get$_nums is not a function
+async/zone_run_test: RuntimeError # receiver.get$_nums is not a function
+async/zone_run_unary_test: RuntimeError # receiver.get$_nums is not a function
+async/zone_value_test: RuntimeError # receiver.get$_collection$_nums is not a function
+convert/ascii_test: RuntimeError # Please triage this failure.
+convert/chunked_conversion1_test: RuntimeError # Please triage this failure.
 convert/chunked_conversion2_test: RuntimeError # Please triage this failure.
-convert/chunked_conversion_utf82_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-convert/chunked_conversion_utf86_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-convert/chunked_conversion_utf87_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-convert/json_chunk_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-convert/json_lib_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-convert/json_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-convert/json_toEncodable_reviver_test: RuntimeError # Please triage this failure.
-convert/json_utf8_chunk_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-convert/json_util_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-convert/latin1_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-convert/line_splitter_test: Crash # Please triage this failure.
-convert/utf82_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-convert/utf8_encode_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-convert/utf8_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-js/null_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-math/math_parse_double_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-math/min_max_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-math/point_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-math/random_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-math/rectangle_test: Crash # Please triage this failure.
-mirrors/abstract_class_test/00: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/abstract_class_test/none: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/abstract_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/accessor_cache_overflow_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/basic_types_in_dart_core_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/circular_factory_redirection_test/01: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/circular_factory_redirection_test/02: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/circular_factory_redirection_test/none: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/class_declarations_test/01: Crash # (=Superclass.inheritedNormalFactory;): Unhandled node
-mirrors/class_declarations_test/none: Crash # (=Superclass.inheritedNormalFactory;): Unhandled node
-mirrors/class_mirror_location_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-mirrors/class_mirror_type_variables_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/closures_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/closurization_equivalence_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-mirrors/constructor_kinds_test/01: Crash # (=Class.factoryConstructor;): Unhandled node
-mirrors/constructor_kinds_test/none: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/constructor_private_name_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/constructors_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/dart2js_mirrors_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/declarations_type_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-mirrors/deferred_mirrors_metadata_test: RuntimeError # Please triage this failure.
-mirrors/deferred_mirrors_metatarget_test: RuntimeError # Please triage this failure.
-mirrors/deferred_mirrors_update_test: RuntimeError # Please triage this failure.
-mirrors/deferred_type_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-mirrors/delegate_call_through_getter_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
+convert/chunked_conversion_json_decode1_test: RuntimeError # Please triage this failure.
+convert/chunked_conversion_json_encode1_test: Crash # Internal Error: No default constructor available.
+convert/chunked_conversion_utf82_test: RuntimeError # Please triage this failure.
+convert/chunked_conversion_utf83_test: RuntimeError # Please triage this failure.
+convert/chunked_conversion_utf84_test: RuntimeError # Please triage this failure.
+convert/chunked_conversion_utf85_test: RuntimeError # Please triage this failure.
+convert/chunked_conversion_utf86_test: RuntimeError # Please triage this failure.
+convert/chunked_conversion_utf87_test: RuntimeError # Please triage this failure.
+convert/chunked_conversion_utf88_test: RuntimeError # Please triage this failure.
+convert/chunked_conversion_utf89_test: RuntimeError # Please triage this failure.
+convert/chunked_conversion_utf8_test: RuntimeError # Please triage this failure.
+convert/codec1_test: RuntimeError # Cannot read property 'prototype' of undefined
+convert/codec2_test: Crash # Internal Error: No default constructor available.
+convert/encoding_test: RuntimeError # receiver.get$_collection$_nums is not a function
+convert/html_escape_test: RuntimeError # receiver.get$_collection$_nums is not a function
+convert/json_chunk_test: RuntimeError # Please triage this failure.
+convert/json_lib_test: Crash # Invalid argument(s)
+convert/json_pretty_test: Crash # Internal Error: No default constructor available.
+convert/json_test: Crash # Internal Error: No default constructor available.
+convert/json_toEncodable_reviver_test: Crash # Internal Error: No default constructor available.
+convert/json_utf8_chunk_test: RuntimeError # Please triage this failure.
+convert/json_util_test: Crash # Internal Error: No default constructor available.
+convert/latin1_test: RuntimeError # Please triage this failure.
+convert/line_splitter_test: Crash # Invalid argument(s)
+convert/streamed_conversion_json_decode1_test: RuntimeError # receiver.get$_collection$_nums is not a function
+convert/streamed_conversion_json_encode1_test: Crash # Internal Error: No default constructor available.
+convert/streamed_conversion_json_utf8_decode_test: RuntimeError # receiver.get$_collection$_nums is not a function
+convert/streamed_conversion_json_utf8_encode_test: Crash # Internal Error: No default constructor available.
+convert/streamed_conversion_utf8_decode_test: RuntimeError # receiver.get$_collection$_nums is not a function
+convert/streamed_conversion_utf8_encode_test: RuntimeError # receiver.get$_collection$_nums is not a function
+convert/utf82_test: RuntimeError # Please triage this failure.
+convert/utf84_test: RuntimeError # Please triage this failure.
+convert/utf8_encode_test: RuntimeError # Please triage this failure.
+convert/utf8_test: RuntimeError # Please triage this failure.
+js/datetime_roundtrip_test: Crash # Internal Error: No default constructor available.
+js/null_test: Crash # Invalid argument(s)
+math/pi_test: RuntimeError # receiver.get$_collection$_nums is not a function
+math/point_test: Crash # Invalid argument(s)
+math/rectangle_test: Crash # Invalid argument(s)
+mirrors/abstract_class_test/00: Crash # Internal Error: No default constructor available.
+mirrors/abstract_class_test/none: Crash # Internal Error: No default constructor available.
+mirrors/abstract_test: Crash # Internal Error: No default constructor available.
+mirrors/accessor_cache_overflow_test: Crash # Internal Error: No default constructor available.
+mirrors/array_tracing2_test: Crash # Internal Error: No default constructor available.
+mirrors/array_tracing3_test: Crash # Internal Error: No default constructor available.
+mirrors/array_tracing_test: Crash # Internal Error: No default constructor available.
+mirrors/basic_types_in_dart_core_test: Crash # Internal Error: No default constructor available.
+mirrors/circular_factory_redirection_test/none: Crash # Internal Error: No default constructor available.
+mirrors/class_declarations_test/01: Crash # Internal Error: No default constructor available.
+mirrors/class_declarations_test/none: Crash # Internal Error: No default constructor available.
+mirrors/class_mirror_location_test: Crash # Internal Error: No default constructor available.
+mirrors/class_mirror_type_variables_test: Crash # Internal Error: No default constructor available.
+mirrors/closures_test: Crash # Internal Error: No default constructor available.
+mirrors/closurization_equivalence_test: Crash # Internal Error: No default constructor available.
+mirrors/constructor_kinds_test/01: Crash # Internal Error: No default constructor available.
+mirrors/constructor_kinds_test/none: Crash # Internal Error: No default constructor available.
+mirrors/constructors_test: Crash # Internal Error: No default constructor available.
+mirrors/dart2js_mirrors_test: Crash # Internal Error: No default constructor available.
+mirrors/declarations_type_test: Crash # Internal Error: No default constructor available.
+mirrors/deferred_mirrors_metadata_test: Crash # Internal Error: No default constructor available.
+mirrors/deferred_mirrors_metatarget_test: Crash # Internal Error: No default constructor available.
+mirrors/deferred_mirrors_update_test: Crash # Internal Error: No default constructor available.
+mirrors/deferred_type_test: Crash # Internal Error: No default constructor available.
+mirrors/delegate_call_through_getter_test: RuntimeError # Please triage this failure.
 mirrors/delegate_test: RuntimeError # Please triage this failure.
-mirrors/enum_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-mirrors/equality_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-mirrors/fake_function_with_call_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/fake_function_without_call_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/field_type_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/function_type_mirror_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/generic_bounded_by_type_parameter_test/01: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/generic_bounded_by_type_parameter_test/02: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/generic_bounded_by_type_parameter_test/none: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/generic_bounded_test/01: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/generic_bounded_test/02: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/generic_bounded_test/none: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/generic_class_declaration_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/generic_f_bounded_mixin_application_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/generic_f_bounded_test/01: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/generic_f_bounded_test/none: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/generic_function_typedef_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-mirrors/generic_interface_test/01: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/generic_interface_test/none: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/generic_list_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/generic_local_function_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/generic_mixin_applications_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/generic_mixin_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/generic_superclass_test/01: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/generic_superclass_test/none: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/generic_type_mirror_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/generics_double_substitution_test/01: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/generics_double_substitution_test/none: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/generics_dynamic_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/generics_special_types_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/generics_substitution_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-mirrors/generics_test/01: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/generics_test/none: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/globalized_closures2_test/00: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/globalized_closures2_test/none: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/globalized_closures_test/00: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/globalized_closures_test/none: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/hierarchy_invariants_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/hot_get_field_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/hot_set_field_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/immutable_collections_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/inference_and_no_such_method_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/inherit_field_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/inherited_metadata_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-mirrors/initializing_formals_test/01: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/initializing_formals_test/03: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/initializing_formals_test/none: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/instance_members_easier_test: Crash # (=Superclass.inheritedNormalFactory;): Unhandled node
-mirrors/instance_members_test: Crash # (=Superclass.inheritedNormalFactory;): Unhandled node
-mirrors/instance_members_unimplemented_interface_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/instance_members_with_override_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/instantiate_abstract_class_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/intercepted_cache_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/intercepted_class_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/intercepted_object_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/intercepted_superclass_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/invoke_call_on_closure_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/invoke_call_through_getter_previously_accessed_test/named: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/invoke_call_through_getter_previously_accessed_test/none: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/invoke_call_through_getter_test/named: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/invoke_call_through_getter_test/none: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/invoke_call_through_implicit_getter_previously_accessed_test/named: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/invoke_call_through_implicit_getter_previously_accessed_test/none: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/invoke_call_through_implicit_getter_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/invoke_closurization2_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/invoke_closurization_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/invoke_import_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/invoke_named_test/01: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/invoke_named_test/none: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/invoke_natives_malicious_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/invoke_private_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/invoke_private_wrong_library_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/invoke_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/invoke_throws_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/is_odd_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/lazy_static_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/libraries_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/library_declarations_test/01: Crash # (=Superclass.inheritedNormalFactory;): Unhandled node
-mirrors/library_declarations_test/none: Crash # (=Superclass.inheritedNormalFactory;): Unhandled node
-mirrors/library_enumeration_deferred_loading_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/library_exports_hidden_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/library_exports_shown_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/library_import_deferred_loading_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/library_imports_bad_metadata_test/01: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/library_imports_bad_metadata_test/none: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/library_imports_deferred_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/library_imports_hidden_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/library_imports_metadata_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/library_imports_prefixed_show_hide_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/library_imports_prefixed_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/library_imports_shown_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/library_uri_package_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-mirrors/list_constructor_test/01: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/list_constructor_test/none: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/load_library_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/local_function_is_static_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-mirrors/local_isolate_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/metadata_allowed_values_test/01: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/metadata_allowed_values_test/02: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/metadata_allowed_values_test/03: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/metadata_allowed_values_test/04: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/metadata_allowed_values_test/05: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/metadata_allowed_values_test/06: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/metadata_allowed_values_test/07: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/metadata_allowed_values_test/08: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/metadata_allowed_values_test/09: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/metadata_allowed_values_test/10: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/metadata_allowed_values_test/11: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/metadata_allowed_values_test/13: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/metadata_allowed_values_test/14: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/metadata_allowed_values_test/15: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/metadata_allowed_values_test/16: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/metadata_allowed_values_test/23: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/metadata_allowed_values_test/24: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/metadata_allowed_values_test/25: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/metadata_allowed_values_test/26: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/metadata_allowed_values_test/27: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/metadata_allowed_values_test/none: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/metadata_constructed_constant_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/metadata_constructor_arguments_test/01: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/metadata_constructor_arguments_test/02: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/metadata_constructor_arguments_test/03: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/metadata_constructor_arguments_test/04: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/metadata_constructor_arguments_test/05: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/metadata_constructor_arguments_test/06: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/metadata_constructor_arguments_test/07: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/metadata_constructor_arguments_test/none: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/metadata_nested_constructor_call_test/01: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/metadata_nested_constructor_call_test/02: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/metadata_nested_constructor_call_test/03: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/metadata_nested_constructor_call_test/04: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/metadata_nested_constructor_call_test/05: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/metadata_nested_constructor_call_test/06: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/metadata_nested_constructor_call_test/07: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/metadata_nested_constructor_call_test/08: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/metadata_nested_constructor_call_test/09: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/metadata_nested_constructor_call_test/none: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/method_mirror_location_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-mirrors/method_mirror_name_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/method_mirror_properties_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/method_mirror_returntype_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-mirrors/method_mirror_source_line_ending_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-mirrors/method_mirror_source_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-mirrors/mirrors_nsm_test/dart2js: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/mirrors_nsm_test/none: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/mirrors_reader_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/mirrors_resolve_fields_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/mirrors_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/mirrors_used_inheritance_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/mixin_application_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/mixin_members_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/mixin_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/model_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/native_class_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/new_instance_with_type_arguments_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/no_metadata_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/null2_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/null_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/operator_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/parameter_is_const_test/01: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/parameter_is_const_test/none: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/parameter_of_mixin_app_constructor_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/private_symbol_mangling_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/private_symbol_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/private_types_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-mirrors/proxy_type_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/raw_type_test/01: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/raw_type_test/none: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/redirecting_factory_test/01: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/redirecting_factory_test/02: Crash # Please triage this failure.
-mirrors/redirecting_factory_test/none: Crash # Please triage this failure.
-mirrors/reflect_class_test/01: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/reflect_class_test/02: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/reflect_class_test/none: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/reflect_model_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/reflected_type_classes_test/01: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/reflected_type_classes_test/02: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/reflected_type_classes_test/03: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/reflected_type_classes_test/none: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/reflected_type_function_type_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-mirrors/reflected_type_special_types_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/reflected_type_test/01: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/reflected_type_test/02: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/reflected_type_test/03: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/reflected_type_test/none: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/reflected_type_typedefs_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/reflected_type_typevars_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/regress_14304_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/regress_19731_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/relation_assignable_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-mirrors/relation_subclass_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-mirrors/relation_subtype_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-mirrors/removed_api_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/repeated_private_anon_mixin_app_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/set_field_with_final_inheritance_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/set_field_with_final_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/spawn_function_root_library_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/static_members_easier_test: Crash # (=Superclass.inheritedNormalFactory;): Unhandled node
-mirrors/static_members_test: Crash # (=Superclass.inheritedNormalFactory;): Unhandled node
-mirrors/static_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/superclass2_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/superclass_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/symbol_validation_test/01: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/symbol_validation_test/none: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/synthetic_accessor_properties_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/to_string_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/top_level_accessors_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/type_argument_is_type_variable_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/type_variable_is_static_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/type_variable_owner_test/01: Crash # Instance of 'TypeOperator': type casts not implemented.
-mirrors/type_variable_owner_test/none: Crash # Instance of 'TypeOperator': type casts not implemented.
-mirrors/typearguments_mirror_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/typedef_deferred_library_test: RuntimeError # Please triage this failure.
-mirrors/typedef_reflected_type_test/01: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/typedef_reflected_type_test/none: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/unnamed_library_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-mirrors/variable_is_const_test/01: Crash # Instance of 'TypeOperator': type casts not implemented.
-mirrors/variable_is_const_test/none: Crash # Instance of 'TypeOperator': type casts not implemented.
-profiler/metrics_num_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-profiler/metrics_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-profiler/user_tags_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-typed_data/constructor_checks_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-typed_data/float32x4_shuffle_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-typed_data/float32x4_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-typed_data/int32x4_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-typed_data/typed_data_list_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-typed_data/typed_list_iterable_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
+mirrors/disable_tree_shaking_test: Crash # Internal Error: No default constructor available.
+mirrors/empty_test: Crash # Internal Error: No default constructor available.
+mirrors/enum_test: Crash # Internal Error: No default constructor available.
+mirrors/equality_test: Crash # Internal Error: No default constructor available.
+mirrors/fake_function_with_call_test: Crash # Internal Error: No default constructor available.
+mirrors/fake_function_without_call_test: Crash # Internal Error: No default constructor available.
+mirrors/field_type_test: Crash # Internal Error: No default constructor available.
+mirrors/function_type_mirror_test: Crash # Internal Error: No default constructor available.
+mirrors/generic_bounded_by_type_parameter_test/01: Crash # Internal Error: No default constructor available.
+mirrors/generic_bounded_by_type_parameter_test/02: Crash # Internal Error: No default constructor available.
+mirrors/generic_bounded_by_type_parameter_test/none: Crash # Internal Error: No default constructor available.
+mirrors/generic_bounded_test/01: Crash # Internal Error: No default constructor available.
+mirrors/generic_bounded_test/02: Crash # Internal Error: No default constructor available.
+mirrors/generic_bounded_test/none: Crash # Internal Error: No default constructor available.
+mirrors/generic_class_declaration_test: Crash # Internal Error: No default constructor available.
+mirrors/generic_f_bounded_mixin_application_test: Crash # Internal Error: No default constructor available.
+mirrors/generic_f_bounded_test/01: Crash # Internal Error: No default constructor available.
+mirrors/generic_f_bounded_test/none: Crash # Internal Error: No default constructor available.
+mirrors/generic_function_typedef_test: Crash # Internal Error: No default constructor available.
+mirrors/generic_interface_test/01: Crash # Internal Error: No default constructor available.
+mirrors/generic_interface_test/none: Crash # Internal Error: No default constructor available.
+mirrors/generic_list_test: Crash # Internal Error: No default constructor available.
+mirrors/generic_local_function_test: Crash # Internal Error: No default constructor available.
+mirrors/generic_mixin_applications_test: Crash # Internal Error: No default constructor available.
+mirrors/generic_mixin_test: Crash # Internal Error: No default constructor available.
+mirrors/generic_superclass_test/01: Crash # Internal Error: No default constructor available.
+mirrors/generic_superclass_test/none: Crash # Internal Error: No default constructor available.
+mirrors/generic_type_mirror_test: Crash # Internal Error: No default constructor available.
+mirrors/generics_double_substitution_test/01: Crash # Internal Error: No default constructor available.
+mirrors/generics_double_substitution_test/none: Crash # Internal Error: No default constructor available.
+mirrors/generics_dynamic_test: Crash # Internal Error: No default constructor available.
+mirrors/generics_special_types_test: Crash # Internal Error: No default constructor available.
+mirrors/generics_substitution_test: Crash # Internal Error: No default constructor available.
+mirrors/generics_test/01: Crash # Internal Error: No default constructor available.
+mirrors/generics_test/none: Crash # Internal Error: No default constructor available.
+mirrors/get_field_cache_test: RuntimeError # Please triage this failure.
+mirrors/get_field_static_test/00: Crash # Internal Error: No default constructor available.
+mirrors/get_field_static_test/none: Crash # Internal Error: No default constructor available.
+mirrors/globalized_closures2_test/00: Crash # Internal Error: No default constructor available.
+mirrors/globalized_closures2_test/none: Crash # Internal Error: No default constructor available.
+mirrors/globalized_closures_test/00: Crash # Internal Error: No default constructor available.
+mirrors/globalized_closures_test/none: Crash # Internal Error: No default constructor available.
+mirrors/hierarchy_invariants_test: Crash # Internal Error: No default constructor available.
+mirrors/immutable_collections_test: Crash # Internal Error: No default constructor available.
+mirrors/inherit_field_test: Crash # Internal Error: No default constructor available.
+mirrors/inherited_metadata_test: Crash # Internal Error: No default constructor available.
+mirrors/initializing_formals_test/01: Crash # Internal Error: No default constructor available.
+mirrors/initializing_formals_test/none: Crash # Internal Error: No default constructor available.
+mirrors/instance_members_easier_test: Crash # Internal Error: No default constructor available.
+mirrors/instance_members_test: Crash # Internal Error: No default constructor available.
+mirrors/instance_members_unimplemented_interface_test: Crash # Internal Error: No default constructor available.
+mirrors/instance_members_with_override_test: Crash # Internal Error: No default constructor available.
+mirrors/instantiate_abstract_class_test: Crash # Internal Error: No default constructor available.
+mirrors/intercepted_cache_test: Crash # Internal Error: No default constructor available.
+mirrors/intercepted_class_test: Crash # Internal Error: No default constructor available.
+mirrors/intercepted_object_test: Crash # Internal Error: No default constructor available.
+mirrors/intercepted_superclass_test: Crash # Internal Error: No default constructor available.
+mirrors/invocation_cache_test: RuntimeError # Please triage this failure.
+mirrors/invocation_fuzz_test/emptyarray: Crash # Internal Error: No default constructor available.
+mirrors/invocation_fuzz_test/false: Crash # Internal Error: No default constructor available.
+mirrors/invocation_fuzz_test/none: Crash # Internal Error: No default constructor available.
+mirrors/invocation_fuzz_test/smi: Crash # Internal Error: No default constructor available.
+mirrors/invocation_fuzz_test/string: Crash # Internal Error: No default constructor available.
+mirrors/invoke_call_on_closure_test: Crash # Internal Error: No default constructor available.
+mirrors/invoke_call_through_getter_previously_accessed_test/named: Crash # Internal Error: No default constructor available.
+mirrors/invoke_call_through_getter_previously_accessed_test/none: Crash # Internal Error: No default constructor available.
+mirrors/invoke_call_through_getter_test/named: Crash # Internal Error: No default constructor available.
+mirrors/invoke_call_through_getter_test/none: Crash # Internal Error: No default constructor available.
+mirrors/invoke_call_through_implicit_getter_previously_accessed_test/named: Crash # Internal Error: No default constructor available.
+mirrors/invoke_call_through_implicit_getter_previously_accessed_test/none: Crash # Internal Error: No default constructor available.
+mirrors/invoke_call_through_implicit_getter_test: Crash # Internal Error: No default constructor available.
+mirrors/invoke_closurization2_test: Crash # Internal Error: No default constructor available.
+mirrors/invoke_closurization_test: Crash # Internal Error: No default constructor available.
+mirrors/invoke_import_test: Crash # Internal Error: No default constructor available.
+mirrors/invoke_named_test/01: Crash # Internal Error: No default constructor available.
+mirrors/invoke_named_test/none: Crash # Internal Error: No default constructor available.
+mirrors/invoke_natives_malicious_test: Crash # Internal Error: No default constructor available.
+mirrors/invoke_test: Crash # Internal Error: No default constructor available.
+mirrors/invoke_throws_test: Crash # Internal Error: No default constructor available.
+mirrors/is_odd_test: Crash # Internal Error: No default constructor available.
+mirrors/lazy_static_test: Crash # Internal Error: No default constructor available.
+mirrors/libraries_test: Crash # Internal Error: No default constructor available.
+mirrors/library_declarations_test/01: Crash # Internal Error: No default constructor available.
+mirrors/library_declarations_test/none: Crash # Internal Error: No default constructor available.
+mirrors/library_enumeration_deferred_loading_test: Crash # Internal Error: No default constructor available.
+mirrors/library_exports_hidden_test: Crash # Internal Error: No default constructor available.
+mirrors/library_exports_shown_test: Crash # Internal Error: No default constructor available.
+mirrors/library_import_deferred_loading_test: Crash # Internal Error: No default constructor available.
+mirrors/library_imports_bad_metadata_test/none: Crash # Internal Error: No default constructor available.
+mirrors/library_imports_deferred_test: Crash # Internal Error: No default constructor available.
+mirrors/library_imports_hidden_test: Crash # Internal Error: No default constructor available.
+mirrors/library_imports_metadata_test: Crash # Internal Error: No default constructor available.
+mirrors/library_imports_prefixed_show_hide_test: Crash # Internal Error: No default constructor available.
+mirrors/library_imports_prefixed_test: Crash # Internal Error: No default constructor available.
+mirrors/library_imports_shown_test: Crash # Internal Error: No default constructor available.
+mirrors/library_metadata2_test/none: Crash # Internal Error: No default constructor available.
+mirrors/library_metadata_test: Crash # Internal Error: No default constructor available.
+mirrors/library_uri_package_test: Crash # Invalid argument(s)
+mirrors/list_constructor_test/01: Crash # Internal Error: No default constructor available.
+mirrors/list_constructor_test/none: Crash # Internal Error: No default constructor available.
+mirrors/load_library_test: Crash # Internal Error: No default constructor available.
+mirrors/local_function_is_static_test: Crash # Internal Error: No default constructor available.
+mirrors/local_isolate_test: Crash # Internal Error: No default constructor available.
+mirrors/metadata_allowed_values_test/01: Crash # Internal Error: No default constructor available.
+mirrors/metadata_allowed_values_test/05: Crash # Internal Error: No default constructor available.
+mirrors/metadata_allowed_values_test/10: Crash # Internal Error: No default constructor available.
+mirrors/metadata_allowed_values_test/11: Crash # Internal Error: No default constructor available.
+mirrors/metadata_allowed_values_test/13: Crash # Internal Error: No default constructor available.
+mirrors/metadata_allowed_values_test/14: Crash # Internal Error: No default constructor available.
+mirrors/metadata_allowed_values_test/none: Crash # Internal Error: No default constructor available.
+mirrors/metadata_class_mirror_test: Crash # Internal Error: No default constructor available.
+mirrors/metadata_const_map_test: Crash # Internal Error: No default constructor available.
+mirrors/metadata_constructed_constant_test: Crash # Internal Error: No default constructor available.
+mirrors/metadata_constructor_arguments_test/none: Crash # Internal Error: No default constructor available.
+mirrors/metadata_nested_constructor_call_test/none: Crash # Internal Error: No default constructor available.
+mirrors/metadata_test: Crash # Internal Error: No default constructor available.
+mirrors/method_mirror_location_test: Crash # Internal Error: No default constructor available.
+mirrors/method_mirror_name_test: Crash # Internal Error: No default constructor available.
+mirrors/method_mirror_properties_test: Crash # Internal Error: No default constructor available.
+mirrors/method_mirror_returntype_test: Crash # Internal Error: No default constructor available.
+mirrors/method_mirror_source_line_ending_test: Crash # Internal Error: No default constructor available.
+mirrors/method_mirror_source_test: Crash # Internal Error: No default constructor available.
+mirrors/mirror_in_static_init_test/none: Crash # Internal Error: No default constructor available.
+mirrors/mirrors_nsm_mismatch_test: Crash # Internal Error: No default constructor available.
+mirrors/mirrors_nsm_test/dart2js: Crash # Internal Error: No default constructor available.
+mirrors/mirrors_nsm_test/none: Crash # Internal Error: No default constructor available.
+mirrors/mirrors_reader_test: Crash # Internal Error: No default constructor available.
+mirrors/mirrors_resolve_fields_test: Crash # Internal Error: No default constructor available.
+mirrors/mirrors_test: Crash # Internal Error: No default constructor available.
+mirrors/mirrors_used_typedef_declaration_test/01: Crash # Internal Error: No default constructor available.
+mirrors/mirrors_used_typedef_declaration_test/none: Crash # Internal Error: No default constructor available.
+mirrors/mixin_application_test: Crash # Internal Error: No default constructor available.
+mirrors/mixin_members_test: Crash # Internal Error: No default constructor available.
+mirrors/mixin_test: Crash # Internal Error: No default constructor available.
+mirrors/native_class_test: Crash # Internal Error: No default constructor available.
+mirrors/new_instance_optional_arguments_test: Crash # Internal Error: No default constructor available.
+mirrors/new_instance_with_type_arguments_test: Crash # Internal Error: No default constructor available.
+mirrors/no_metadata_test: Crash # Internal Error: No default constructor available.
+mirrors/null2_test: Crash # Internal Error: No default constructor available.
+mirrors/null_test: Crash # Invalid argument(s)
+mirrors/operator_test: Crash # Internal Error: No default constructor available.
+mirrors/parameter_annotation_mirror_test: Crash # Internal Error: No default constructor available.
+mirrors/parameter_is_const_test/none: Crash # Internal Error: No default constructor available.
+mirrors/parameter_metadata_test: Crash # Internal Error: No default constructor available.
+mirrors/parameter_of_mixin_app_constructor_test: Crash # Internal Error: No default constructor available.
+mirrors/parameter_test/01: Crash # Internal Error: No default constructor available.
+mirrors/parameter_test/none: Crash # Internal Error: No default constructor available.
+mirrors/private_symbol_mangling_test: Crash # Internal Error: No default constructor available.
+mirrors/private_types_test: Crash # Internal Error: No default constructor available.
+mirrors/proxy_type_test: Crash # Internal Error: No default constructor available.
+mirrors/raw_type_test/01: Crash # Internal Error: No default constructor available.
+mirrors/raw_type_test/none: Crash # Internal Error: No default constructor available.
+mirrors/redirecting_factory_test/01: Crash # Internal Error: No default constructor available.
+mirrors/redirecting_factory_test/02: Crash # Internal Error: No default constructor available.
+mirrors/redirecting_factory_test/none: Crash # Internal Error: No default constructor available.
+mirrors/reflect_class_test/01: Crash # Internal Error: No default constructor available.
+mirrors/reflect_class_test/02: Crash # Internal Error: No default constructor available.
+mirrors/reflect_class_test/none: Crash # Internal Error: No default constructor available.
+mirrors/reflect_model_test: Crash # Internal Error: No default constructor available.
+mirrors/reflect_runtime_type_test: Crash # Internal Error: No default constructor available.
+mirrors/reflect_uninstantiated_class_test: Crash # Internal Error: No default constructor available.
+mirrors/reflected_type_classes_test/01: Crash # Internal Error: No default constructor available.
+mirrors/reflected_type_classes_test/02: Crash # Internal Error: No default constructor available.
+mirrors/reflected_type_classes_test/03: Crash # Internal Error: No default constructor available.
+mirrors/reflected_type_classes_test/none: Crash # Internal Error: No default constructor available.
+mirrors/reflected_type_function_type_test: Crash # Internal Error: No default constructor available.
+mirrors/reflected_type_special_types_test: Crash # Internal Error: No default constructor available.
+mirrors/reflected_type_test/01: Crash # Internal Error: No default constructor available.
+mirrors/reflected_type_test/02: Crash # Internal Error: No default constructor available.
+mirrors/reflected_type_test/03: Crash # Internal Error: No default constructor available.
+mirrors/reflected_type_test/none: Crash # Internal Error: No default constructor available.
+mirrors/reflected_type_typedefs_test: Crash # Internal Error: No default constructor available.
+mirrors/reflected_type_typevars_test: Crash # Internal Error: No default constructor available.
+mirrors/reflectively_instantiate_uninstantiated_class_test: Crash # Internal Error: No default constructor available.
+mirrors/regress_14304_test: Crash # Internal Error: No default constructor available.
+mirrors/regress_16321_test/01: Crash # Internal Error: No default constructor available.
+mirrors/regress_16321_test/none: Crash # Internal Error: No default constructor available.
+mirrors/regress_19731_test: Crash # Internal Error: No default constructor available.
+mirrors/relation_assignable_test: Crash # Internal Error: No default constructor available.
+mirrors/relation_subclass_test: Crash # Internal Error: No default constructor available.
+mirrors/relation_subtype_test: Crash # Internal Error: No default constructor available.
+mirrors/removed_api_test: Crash # Internal Error: No default constructor available.
+mirrors/repeated_private_anon_mixin_app_test: Crash # Internal Error: No default constructor available.
+mirrors/return_type_test: Crash # Internal Error: No default constructor available.
+mirrors/runtime_type_test: Crash # Internal Error: No default constructor available.
+mirrors/set_field_with_final_inheritance_test: Crash # Internal Error: No default constructor available.
+mirrors/set_field_with_final_test: Crash # Internal Error: No default constructor available.
+mirrors/spawn_function_root_library_test: Crash # Internal Error: No default constructor available.
+mirrors/static_members_easier_test: Crash # Internal Error: No default constructor available.
+mirrors/static_members_test: Crash # Internal Error: No default constructor available.
+mirrors/static_test: Crash # Internal Error: No default constructor available.
+mirrors/superclass2_test: Crash # Internal Error: No default constructor available.
+mirrors/superclass_test: Crash # Internal Error: No default constructor available.
+mirrors/symbol_validation_test/01: Crash # Internal Error: No default constructor available.
+mirrors/symbol_validation_test/none: RuntimeError # Please triage this failure.
+mirrors/syntax_error_test/none: Crash # Internal Error: No default constructor available.
+mirrors/synthetic_accessor_properties_test: Crash # Internal Error: No default constructor available.
+mirrors/to_string_test: Crash # Internal Error: No default constructor available.
+mirrors/top_level_accessors_test: Crash # Internal Error: No default constructor available.
+mirrors/type_argument_is_type_variable_test: Crash # Internal Error: No default constructor available.
+mirrors/type_mirror_for_type_test: Crash # Internal Error: No default constructor available.
+mirrors/type_variable_is_static_test: Crash # Internal Error: No default constructor available.
+mirrors/type_variable_owner_test/01: Crash # Internal Error: No default constructor available.
+mirrors/type_variable_owner_test/none: Crash # Internal Error: No default constructor available.
+mirrors/typearguments_mirror_test: Crash # Internal Error: No default constructor available.
+mirrors/typedef_deferred_library_test: Crash # Internal Error: No default constructor available.
+mirrors/typedef_in_signature_test: Crash # Internal Error: No default constructor available.
+mirrors/typedef_library_test: Crash # Internal Error: No default constructor available.
+mirrors/typedef_metadata_test: Crash # Internal Error: No default constructor available.
+mirrors/typedef_reflected_type_test/01: Crash # Internal Error: No default constructor available.
+mirrors/typedef_reflected_type_test/none: Crash # Internal Error: No default constructor available.
+mirrors/typedef_test: Crash # Internal Error: No default constructor available.
+mirrors/unnamed_library_test: Crash # Internal Error: No default constructor available.
+mirrors/unused_mirrors_used_test: RuntimeError # Please triage this failure.
+mirrors/variable_is_const_test/none: Crash # Internal Error: No default constructor available.
+typed_data/int32x4_test: RuntimeError # Please triage this failure.
+typed_data/typed_data_from_list_test: RuntimeError # Please triage this failure.
+typed_data/typed_data_list_test: RuntimeError # Please triage this failure.
+typed_data/typed_list_iterable_test: RuntimeError # Please triage this failure.
diff --git a/tests/lib/mirrors/mirrors_nsm_mismatch_test.dart b/tests/lib/mirrors/mirrors_nsm_mismatch_test.dart
new file mode 100644
index 0000000..5c63ca1
--- /dev/null
+++ b/tests/lib/mirrors/mirrors_nsm_mismatch_test.dart
@@ -0,0 +1,54 @@
+// 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.mirrors_nsm_mistatch;
+
+import 'dart:mirrors';
+import 'mirrors_nsm_test.dart';
+
+topLevelMethod({missing}) {}
+class C {
+  C.constructor({missing});
+  factory C.redirecting({missing}) = C.constructor;
+  static staticMethod({missing}) {}
+  instanceMethod({missing}) {}
+}
+
+main() {
+  var mirrors = currentMirrorSystem();
+  var libMirror = mirrors.findLibrary(#test.mirrors_nsm_mistatch);
+  expectMatchingErrors(() => libMirror.invoke(#topLevelMethod, [], {#extra: 1}),
+                       () => topLevelMethod(extra: 1));
+  expectMatchingErrors(() => libMirror.invoke(#topLevelMethod, ['positional']),
+                       () => topLevelMethod('positional'));
+
+  var classMirror = reflectClass(C);
+  expectMatchingErrors(() => classMirror.newInstance(#constructor, [],
+                                                     {#extra: 1}),
+                       () => new C.constructor(extra: 1));
+  expectMatchingErrors(() => classMirror.newInstance(#redirecting, [],
+                                                     {#extra: 1}),
+                       () => new C.redirecting(extra: 1));
+  expectMatchingErrors(() => classMirror.invoke(#staticMethod, [],
+                                                {#extra: 1}),
+                       () => C.staticMethod(extra: 1));
+  expectMatchingErrors(() => classMirror.newInstance(#constructor,
+                                                     ['positional']),
+                       () => new C.constructor('positional'));
+  expectMatchingErrors(() => classMirror.newInstance(#redirecting,
+                                                     ['positional']),
+                       () => new C.redirecting('positional'));
+  expectMatchingErrors(() => classMirror.invoke(#staticMethod,
+                                                ['positional']),
+                       () => C.staticMethod('positional'));
+
+  var instanceMirror = reflect(new C.constructor());
+  expectMatchingErrors(() => instanceMirror.invoke(#instanceMethod, [],
+                                                   {#extra: 1}),
+                       () => instanceMirror.reflectee.instanceMethod(extra: 1));
+  expectMatchingErrors(() => instanceMirror.invoke(#instanceMethod,
+                                                   ['positional']),
+                       () => instanceMirror.reflectee
+                                 .instanceMethod('positional'));
+}
diff --git a/tests/lib/mirrors/mirrors_nsm_test.dart b/tests/lib/mirrors/mirrors_nsm_test.dart
index f1abaa7..2364f92 100644
--- a/tests/lib/mirrors/mirrors_nsm_test.dart
+++ b/tests/lib/mirrors/mirrors_nsm_test.dart
@@ -20,6 +20,10 @@
   final finalInstance = 0;
   static final finalStatic = 0;
 }
+class B {
+  B(a, b);
+  factory B.fac(a, b) => new B(a, b);
+}
 
 testMessageContents() {
   var mirrors = currentMirrorSystem();
@@ -61,14 +65,18 @@
   } catch(e) {
     reflectiveError = e;
   }
+
   try {
     baseAction();
   } catch(e) {
     baseError = e;
   }
-  print("\n==Base==\n $baseError");
-  print("\n==Reflective==\n $reflectiveError");
-  Expect.stringEquals(baseError.toString(), reflectiveError.toString());
+
+  if (baseError.toString() != reflectiveError.toString()) {
+    print("\n==Base==\n $baseError");
+    print("\n==Reflective==\n $reflectiveError");
+    throw "Expected matching errors";
+  }
 }
 
 testMatchingMessages() {
@@ -92,6 +100,8 @@
                        () => A.foo= null);
   expectMatchingErrors(() => classMirror.setField(#finalStatic, null),
                        () => A.finalStatic= null);
+  expectMatchingErrors(() => classMirror.newInstance(#constructor, [1, 2, 3]),
+                       () => new A.constructor(1, 2, 3));
 
   var instanceMirror = reflect(new A());
   expectMatchingErrors(() => instanceMirror.invoke(#foo, []),
diff --git a/tests/lib/typed_data/typed_data_list_test.dart b/tests/lib/typed_data/typed_data_list_test.dart
index 728416c..f4f5ad4 100644
--- a/tests/lib/typed_data/typed_data_list_test.dart
+++ b/tests/lib/typed_data/typed_data_list_test.dart
@@ -5,6 +5,10 @@
 import 'dart:typed_data';
 import 'package:expect/expect.dart';
 
+@AssumeDynamic()
+@NoInline()
+confuse(x) => x;
+
 void testListFunctions(list, first, last, toElementType) {
   assert(list.length > 0);
 
@@ -106,6 +110,17 @@
                     list.sublist(1, list.length - 1));
   Expect.listEquals(list.getRange(1, list.length).toList(), list.sublist(1));
   Expect.listEquals(list, list.sublist(0));
+
+  Expect.listEquals([], list.sublist(0, 0));
+  Expect.listEquals([], list.sublist(list.length));
+  Expect.listEquals([], list.sublist(list.length, list.length));
+
+  Expect.throws(() => list.sublist(list.length + 1),
+      (e) => e is RangeError);
+  Expect.throws(() => list.sublist(0, list.length + 1),
+      (e) => e is RangeError);
+  Expect.throws(() => list.sublist(1, 0),
+      (e) => e is RangeError);
 }
 
 void emptyChecks(list) {
diff --git a/tests/standalone/io/file_write_only_test.dart b/tests/standalone/io/file_write_only_test.dart
new file mode 100644
index 0000000..f541910
--- /dev/null
+++ b/tests/standalone/io/file_write_only_test.dart
@@ -0,0 +1,85 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+//
+// Dart test program for testing file I/O.
+
+import 'dart:async';
+import 'dart:io';
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+Future withTempDir(String prefix, void test(Directory dir)) async {
+  var tempDir = Directory.systemTemp.createTempSync(prefix);
+  try {
+    await test(tempDir);
+  } finally {
+    tempDir.deleteSync(recursive: true);
+  }
+}
+
+void withTempDirSync(String prefix, void test(Directory dir)) {
+  var tempDir = Directory.systemTemp.createTempSync(prefix);
+  try {
+    test(tempDir);
+  } finally {
+    tempDir.deleteSync(recursive: true);
+  }
+}
+
+Future expectThrowsAsync(Future future, String message) {
+  return future.then((r) => Expect.fail(message))
+               .catchError((e) {});
+}
+
+
+Future write(Directory dir) async {
+  var f = new File("${dir.path}${Platform.pathSeparator}write");
+  var raf = await f.open(mode: WRITE_ONLY);
+  await raf.writeString('Hello');
+  await raf.setPosition(0);
+  await raf.writeString('Hello');
+  await raf.setPosition(0);
+  await expectThrowsAsync(
+      raf.readByte(), 'Read from write only file succeeded');
+  await raf.close();
+  raf = await f.open(mode: WRITE_ONLY_APPEND);
+  await raf.writeString('Hello');
+  await expectThrowsAsync(
+      raf.readByte(), 'Read from write only file succeeded');
+  await raf.setPosition(0);
+  await raf.writeString('Hello');
+  await raf.close();
+  Expect.equals(f.lengthSync(), 10);
+}
+
+void writeSync(Directory dir) {
+  var f = new File("${dir.path}${Platform.pathSeparator}write_sync");
+  var raf = f.openSync(mode: WRITE_ONLY);
+  raf.writeStringSync('Hello');
+  raf.setPositionSync(0);
+  raf.writeStringSync('Hello');
+  raf.setPositionSync(0);
+  Expect.throws(() => raf.readByteSync());
+  raf.closeSync();
+}
+
+Future openWrite(Directory dir) async {
+  var f = new File("${dir.path}${Platform.pathSeparator}open_write");
+  var sink = f.openWrite(mode: WRITE_ONLY);
+  sink.write('Hello');
+  await sink.close();
+  sink = await f.openWrite(mode: WRITE_ONLY_APPEND);
+  sink.write('Hello');
+  await sink.close();
+  Expect.equals(f.lengthSync(), 10);
+}
+
+main() async {
+  asyncStart();
+  await withTempDir('file_write_only_test_1_', write);
+  withTempDirSync('file_write_only_test_2_', writeSync);
+  await withTempDir('file_write_only_test_3_', openWrite);
+  asyncEnd();
+}
diff --git a/tests/standalone/io/system_encoding_test.dart b/tests/standalone/io/system_encoding_test.dart
new file mode 100644
index 0000000..1a36331
--- /dev/null
+++ b/tests/standalone/io/system_encoding_test.dart
@@ -0,0 +1,52 @@
+// 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:io';
+import 'dart:convert';
+
+import "package:expect/expect.dart";
+
+// This only works reliabily for "ASCII" cross platform as that is the only
+// well known part of the default Windows code page.
+void testEncodeDecode(String str) {
+  Expect.equals(
+      SYSTEM_ENCODING.decode(SYSTEM_ENCODING.encode(str)), str);
+}
+
+// This only works reliabily for "ASCII" cross platform as that is the only
+// common set of bytes between UTF-8 Windows code pages that convert back
+// and forth.
+void testDecodeEncode(List<int> bytes) {
+  Expect.listEquals(
+      SYSTEM_ENCODING.encode(SYSTEM_ENCODING.decode(bytes)), bytes);
+}
+
+void test(List<int> bytes) {
+  var str = new String.fromCharCodes(bytes);
+  Expect.equals(SYSTEM_ENCODING.decode(bytes), str);
+  Expect.listEquals(SYSTEM_ENCODING.encode(str), bytes);
+  testDecodeEncode(bytes);
+  testEncodeDecode(str);
+}
+
+main() {
+  test([65, 66, 67]);
+  test([65, 0, 67]);
+  test([0, 65, 0, 67, 0]);
+  test([0, 0, 0]);
+  test(new Iterable.generate(128, (i) => i).toList());
+  if (Platform.isWindows) {
+    // On Windows the default Windows code page cannot encode these
+    // Unicode characters and the ? character is used.
+    Expect.listEquals(
+        SYSTEM_ENCODING.encode('\u1234\u5678\u9abc'),
+        '???'.codeUnits);
+  } else {
+    // On all systems except for Windows UTF-8 is used as the system
+    // encoding.
+    Expect.listEquals(
+        SYSTEM_ENCODING.encode('\u1234\u5678\u9abc'),
+        UTF8.encode('\u1234\u5678\u9abc'));
+  }
+}
diff --git a/tests/standalone/standalone.status b/tests/standalone/standalone.status
index 68f560a..7036123 100644
--- a/tests/standalone/standalone.status
+++ b/tests/standalone/standalone.status
@@ -170,84 +170,120 @@
 io/http_client_stays_alive_test: Skip  # Timeout.
 
 [ $compiler == dart2js && $cps_ir ]
-array_bounds_check_generalization_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-constant_left_shift_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-io/addlatexhash_test: Crash # (try {test(tempDir.path);}finally {tempDir.delete(recursive:true);}): try/finally
-io/create_recursive_test: Crash #  try/finally
-io/directory_chdir_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-io/directory_error_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-io/directory_fuzz_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-io/directory_invalid_arguments_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-io/directory_list_nonexistent_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-io/directory_list_pause_test: Crash # Please triage this failure.
-io/directory_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-io/directory_uri_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-io/file_copy_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-io/file_error_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-io/file_invalid_arguments_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-io/file_read_encoded_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-io/file_system_delete_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-io/file_system_links_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-io/file_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-io/file_typed_data_test: Crash # Please triage this failure.
-io/file_uri_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-io/http_bind_test: Crash #  cannot handle async/sync*/async* functions
-io/http_client_exception_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-io/http_content_length_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-io/http_cookie_date_test: Crash # Please triage this failure.
-io/http_date_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-io/http_detach_socket_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-io/http_headers_state_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-io/http_headers_test: Crash #  Unhandled node
-io/http_parser_test: Crash #  Unhandled node
-io/http_proxy_test: Crash # Please triage this failure.
-io/http_server_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-io/https_bad_certificate_test: Crash #  cannot handle async/sync*/async* functions
-io/https_server_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-io/internet_address_invalid_arguments_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-io/internet_address_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-io/issue_22636_test: Crash #  cannot handle async/sync*/async* functions
-io/issue_22637_test: Crash #  cannot handle async/sync*/async* functions
-io/link_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-io/link_uri_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-io/observatory_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-io/platform_resolved_executable_test/01: Crash # (try {test(tempDir);}finally {tempDir.deleteSync(recursive:true);}): try/finally
-io/platform_resolved_executable_test/02: Crash # (try {test(tempDir);}finally {tempDir.deleteSync(recursive:true);}): try/finally
-io/platform_resolved_executable_test/04: Crash # (try {test(tempDir);}finally {tempDir.deleteSync(recursive:true);}): try/finally
-io/platform_resolved_executable_test/05: Crash # (try {test(tempDir);}finally {tempDir.deleteSync(recursive:true);}): try/finally
-io/platform_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-io/process_invalid_arguments_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-io/raw_datagram_socket_test: Crash #  Unhandled node
-io/raw_secure_server_closing_test: Crash # Please triage this failure.
-io/raw_secure_server_socket_argument_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-io/raw_secure_server_socket_test: Crash # Please triage this failure.
-io/raw_secure_socket_pause_test: Crash #  Unhandled node
-io/raw_secure_socket_test: Crash #  Unhandled node
-io/raw_server_socket_cancel_test: Crash #  Unhandled node
-io/raw_socket_cross_process_test: Crash #  Unhandled node
-io/raw_socket_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-io/raw_socket_typed_data_test: Crash # Please triage this failure.
-io/regress_21160_test: Crash #  Unhandled node
-io/secure_client_raw_server_test: Crash #  Unhandled node
-io/secure_server_closing_test: Crash # Please triage this failure.
-io/secure_server_socket_test: Crash # Please triage this failure.
-io/secure_socket_alpn_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-io/secure_socket_argument_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-io/secure_socket_bad_data_test: Crash #  Unhandled node
-io/skipping_dart2js_compilations_test: Crash #  Unhandled node
-io/sleep_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-io/socket_bind_test: Crash #  cannot handle async/sync*/async* functions
-io/socket_close_test: Crash #  Unhandled node
-io/socket_exception_test: Crash # Please triage this failure.
-io/socket_source_address_test: Crash #  cannot handle async/sync*/async* functions
-io/socket_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-io/socket_upgrade_to_secure_test: Crash # Please triage this failure.
-io/stdout_stderr_terminal_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-io/test_extension_fail_test: Crash #  Unhandled node
-io/test_extension_test: Crash #  Unhandled node
-io/test_runner_test: Crash #  Unhandled node
-io/uri_platform_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-io/web_socket_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-io/windows_file_system_links_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-io/zlib_test: Crash # Instance of 'TypeOperator': type check unimplemented for _Nullary.
-priority_queue_stress_test: RuntimeError # Please triage this failure.
+array_bounds_check_generalization_test: RuntimeError # Please triage this failure.
+coverage_test: Crash # Invalid argument(s)
+io/addlatexhash_test: Crash # Invalid argument(s)
+io/create_recursive_test: Crash # Invalid argument(s)
+io/directory_list_pause_test: Crash # Invalid argument(s)
+io/directory_uri_test: Crash # Invalid argument(s)
+io/file_lock_test: Crash # Invalid argument(s)
+io/file_stat_test: Crash # Invalid argument(s)
+io/file_test: Crash # Invalid argument(s)
+io/file_typed_data_test: Crash # Invalid argument(s)
+io/file_uri_test: Crash # Invalid argument(s)
+io/file_write_only_test: Crash # (main()async{asyncSt...  cannot handle async/sync*/async* functions
+io/http_10_test: Crash # Internal Error: No default constructor available.
+io/http_advanced_test: Crash # Internal Error: No default constructor available.
+io/http_auth_digest_test: Crash # Invalid argument(s)
+io/http_auth_test: Crash # Invalid argument(s)
+io/http_basic_test: Crash # Internal Error: No default constructor available.
+io/http_bind_test: Crash # (testBindShared(Stri...  cannot handle async/sync*/async* functions
+io/http_client_connect_test: Crash # Internal Error: No default constructor available.
+io/http_client_exception_test: Crash # Internal Error: No default constructor available.
+io/http_client_request_test: Crash # Internal Error: No default constructor available.
+io/http_client_stays_alive_test: Crash # Internal Error: No default constructor available.
+io/http_close_test: Crash # Internal Error: No default constructor available.
+io/http_compression_test: Crash # Internal Error: No default constructor available.
+io/http_connection_close_test: Crash # Invalid argument(s)
+io/http_connection_header_test: Crash # Internal Error: No default constructor available.
+io/http_connection_info_test: Crash # Internal Error: No default constructor available.
+io/http_content_length_test: Crash # Internal Error: No default constructor available.
+io/http_cookie_date_test: Crash # Invalid argument(s)
+io/http_cookie_test: Crash # Internal Error: No default constructor available.
+io/http_cross_process_test: Crash # Internal Error: No default constructor available.
+io/http_date_test: Crash # Invalid argument(s)
+io/http_detach_socket_test: Crash # Internal Error: No default constructor available.
+io/http_head_test: Crash # Internal Error: No default constructor available.
+io/http_headers_state_test: Crash # Internal Error: No default constructor available.
+io/http_headers_test: Crash # Internal Error: No default constructor available.
+io/http_ipv6_test: Crash # Invalid argument(s)
+io/http_keep_alive_test: Crash # Internal Error: No default constructor available.
+io/http_no_reason_phrase_test: Crash # Invalid argument(s)
+io/http_outgoing_size_test: Crash # Internal Error: No default constructor available.
+io/http_parser_test: Crash # Invalid argument(s)
+io/http_proxy_configuration_test: Crash # Internal Error: No default constructor available.
+io/http_proxy_test: Crash # Invalid argument(s)
+io/http_read_test: Crash # Internal Error: No default constructor available.
+io/http_redirect_test: Crash # Invalid argument(s)
+io/http_request_pipeling_test: Crash # Internal Error: No default constructor available.
+io/http_requested_uri_test: Crash # Internal Error: No default constructor available.
+io/http_response_deadline_test: Crash # Internal Error: No default constructor available.
+io/http_reuse_server_port_test: Crash # Internal Error: No default constructor available.
+io/http_server_close_response_after_error_test: Crash # Internal Error: No default constructor available.
+io/http_server_early_client_close2_test: Crash # Internal Error: No default constructor available.
+io/http_server_early_client_close_test: Crash # Internal Error: No default constructor available.
+io/http_server_idle_timeout_test: Crash # Internal Error: No default constructor available.
+io/http_server_response_test: Crash # Internal Error: No default constructor available.
+io/http_server_test: Crash # Internal Error: No default constructor available.
+io/http_session_test: Crash # Internal Error: No default constructor available.
+io/http_shutdown_test: Crash # Internal Error: No default constructor available.
+io/http_stream_close_test: Crash # Invalid argument(s)
+io/https_bad_certificate_test: Crash # (main()async{var cli...  cannot handle async/sync*/async* functions
+io/https_client_certificate_test: Crash # Invalid argument(s)
+io/https_client_exception_test: Crash # Invalid argument(s)
+io/https_server_test: Crash # Internal Error: No default constructor available.
+io/https_unauthorized_test: Crash # Internal Error: No default constructor available.
+io/issue_22636_test: Crash # (test()async{server=...  cannot handle async/sync*/async* functions
+io/issue_22637_test: Crash # (test()async{server=...  cannot handle async/sync*/async* functions
+io/link_async_test: Crash # Invalid argument(s)
+io/link_test: Crash # Invalid argument(s)
+io/link_uri_test: Crash # Invalid argument(s)
+io/observatory_test: Crash # Invalid argument(s)
+io/parent_test: Crash # Invalid argument(s)
+io/platform_resolved_executable_test/00: Crash # Internal Error: No default constructor available.
+io/platform_resolved_executable_test/01: Crash # Invalid argument(s)
+io/platform_resolved_executable_test/02: Crash # Invalid argument(s)
+io/platform_resolved_executable_test/03: Crash # Internal Error: No default constructor available.
+io/platform_resolved_executable_test/04: Crash # Invalid argument(s)
+io/platform_resolved_executable_test/05: Crash # Invalid argument(s)
+io/platform_resolved_executable_test/06: Crash # Internal Error: No default constructor available.
+io/platform_resolved_executable_test/none: Crash # Internal Error: No default constructor available.
+io/platform_test: Crash # Internal Error: No default constructor available.
+io/process_environment_test: Crash # Internal Error: No default constructor available.
+io/process_path_environment_test: Crash # Internal Error: No default constructor available.
+io/raw_secure_server_closing_test: Crash # Invalid argument(s)
+io/raw_secure_server_socket_test: Crash # Invalid argument(s)
+io/raw_secure_socket_pause_test: Crash # Internal Error: No default constructor available.
+io/raw_secure_socket_test: Crash # Internal Error: No default constructor available.
+io/raw_socket_test: Crash # Invalid argument(s)
+io/raw_socket_typed_data_test: Crash # Invalid argument(s)
+io/regress_8828_test: Crash # Internal Error: No default constructor available.
+io/regress_9194_test: Crash # Internal Error: No default constructor available.
+io/resolve_symbolic_links_test: Crash # Invalid argument(s)
+io/secure_builtin_roots_test: Crash # Invalid argument(s)
+io/secure_server_closing_test: Crash # Invalid argument(s)
+io/secure_server_socket_test: Crash # Invalid argument(s)
+io/secure_socket_test: Crash # Internal Error: No default constructor available.
+io/skipping_dart2js_compilations_test: Crash # Invalid argument(s)
+io/socket_bind_test: Crash # (testListenCloseList...  cannot handle async/sync*/async* functions
+io/socket_exception_test: Crash # Invalid argument(s)
+io/socket_source_address_test: Crash # (Future testConnect(...  cannot handle async/sync*/async* functions
+io/socket_upgrade_to_secure_test: Crash # Invalid argument(s)
+io/stdin_sync_test: Crash # Internal Error: No default constructor available.
+io/test_extension_fail_test: Crash # Invalid argument(s)
+io/test_extension_test: Crash # Invalid argument(s)
+io/test_runner_test: Crash # Internal Error: No default constructor available.
+io/uri_platform_test: Crash # Invalid argument(s)
+io/web_socket_error_test: Crash # Internal Error: No default constructor available.
+io/web_socket_ping_test: Crash # Internal Error: No default constructor available.
+io/web_socket_pipe_test: Crash # Internal Error: No default constructor available.
+io/web_socket_protocol_test: Crash # Internal Error: No default constructor available.
+io/web_socket_test: Crash # Internal Error: No default constructor available.
+io/web_socket_typed_data_test: Crash # Internal Error: No default constructor available.
+io/windows_environment_test: Crash # Invalid argument(s)
+priority_queue_stress_test: RuntimeError # receiver.get$_collection$_nums is not a function
+slowpath_safepoints_test: RuntimeError # Cannot read property 'prototype' of undefined
+status_expression_test: RuntimeError # Please triage this failure.
+typed_array_test: RuntimeError # receiver.get$_collection$_nums is not a function
+verbose_gc_to_bmu_test: Crash # Invalid argument(s)
+verified_mem_test: RuntimeError # Please triage this failure.
diff --git a/tests/utils/utils.status b/tests/utils/utils.status
index af2c954..5bb2a3a 100644
--- a/tests/utils/utils.status
+++ b/tests/utils/utils.status
@@ -29,6 +29,6 @@
 source_mirrors_test: Pass, RuntimeError # Issue 17662
 
 [ $compiler == dart2js && $cps_ir ]
-dummy_compiler_test: Crash #  Unhandled node
-recursive_import_test: Crash #  Unhandled node
-source_mirrors_test: Crash # Please triage this failure.
+dummy_compiler_test: Crash # Internal Error: No default constructor available.
+recursive_import_test: Crash # Internal Error: No default constructor available.
+source_mirrors_test: Crash # Internal Error: No default constructor available.
diff --git a/third_party/.gitignore b/third_party/.gitignore
index 530a17c..cbe3480 100644
--- a/third_party/.gitignore
+++ b/third_party/.gitignore
@@ -4,3 +4,4 @@
 !.gitignore
 !pkg
 !pkg_tested
+!d8
diff --git a/third_party/d8/.gitignore b/third_party/d8/.gitignore
new file mode 100644
index 0000000..e5e7e0a
--- /dev/null
+++ b/third_party/d8/.gitignore
@@ -0,0 +1,3 @@
+/macos/d8
+/windows/d8.exe
+/linux/d8
diff --git a/third_party/d8/README.google b/third_party/d8/README.google
new file mode 100644
index 0000000..f5e801c
--- /dev/null
+++ b/third_party/d8/README.google
@@ -0,0 +1,14 @@
+Name: V8 command line javascript shell.
+Short Name: d8
+URL: https://chromium.googlesource.com/v8/v8/+/4.4.63.5
+Version: 4.4.63.5
+Revision: 288da5c7788134004a4b34a4ba0cb4814428cf7c
+Date: September 2nd 2014
+License: BSD
+
+
+Description:
+This directory contains the d8 binaries for Windows, Mac and Linux.
+The files were fetched from the v8 builders on the DartFYI waterfall:
+http://build.chromium.org/p/client.dart.fyi/console
+The binaries are used for testing dart code compiled to javascript.
diff --git a/third_party/d8/linux/d8-arm.sha1 b/third_party/d8/linux/d8-arm.sha1
new file mode 100644
index 0000000..2dafdac
--- /dev/null
+++ b/third_party/d8/linux/d8-arm.sha1
@@ -0,0 +1 @@
+560998fba34d0243b396ca5b63b86e4479cabb86
\ No newline at end of file
diff --git a/third_party/d8/linux/d8.sha1 b/third_party/d8/linux/d8.sha1
new file mode 100644
index 0000000..5f0b753
--- /dev/null
+++ b/third_party/d8/linux/d8.sha1
@@ -0,0 +1 @@
+3ce7314d80c9591de6681bbc68f9702406ad3ece
\ No newline at end of file
diff --git a/third_party/d8/macos/d8.sha1 b/third_party/d8/macos/d8.sha1
new file mode 100644
index 0000000..3a0f213
--- /dev/null
+++ b/third_party/d8/macos/d8.sha1
@@ -0,0 +1 @@
+9fd5757eac16ebfe1ec9b45778c5394dab0c36cc
\ No newline at end of file
diff --git a/third_party/d8/windows/d8.exe.sha1 b/third_party/d8/windows/d8.exe.sha1
new file mode 100644
index 0000000..7a7f50b
--- /dev/null
+++ b/third_party/d8/windows/d8.exe.sha1
@@ -0,0 +1 @@
+04e58ecd97cd9ee4186fbbce99a079d7d2cb2f68
\ No newline at end of file
diff --git a/third_party/pkg_tested/pkg_tested.status b/third_party/pkg_tested/pkg_tested.status
index e25c931..031b82b 100644
--- a/third_party/pkg_tested/pkg_tested.status
+++ b/third_party/pkg_tested/pkg_tested.status
@@ -27,463 +27,3 @@
 dart_style/test/command_line_test: Skip # The test controller does not take into account that tests take much longer in debug mode or on simulators/mips.
 dart_style/test/formatter_test: Skip # The test controller does not take into account that tests take much longer in debug mode or on simulators/mips.
 
-[ $compiler == dart2js && $cps_ir ]
-dart_style/test/command_line_test: Crash #  try/finally
-dart_style/test/formatter_test: Crash #  try/finally
-dart_style/test/io_test: Crash #  try/finally
-dart_style/test/source_code_test: Crash #  try/finally
-pub/test/ascii_tree_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-pub/test/barback/all_includes_all_default_directories_test: Crash #  try/finally
-pub/test/barback/directory_args_test: Crash #  try/finally
-pub/test/barback/fails_if_args_with_all_test: Crash #  try/finally
-pub/test/barback/fails_if_dir_arg_does_not_exist_test: Crash #  try/finally
-pub/test/barback/fails_if_dir_outside_package_test: Crash #  try/finally
-pub/test/barback/fails_if_no_default_dirs_test: Crash #  try/finally
-pub/test/barback/fails_on_all_with_no_buildable_directories_test: Crash #  try/finally
-pub/test/barback/fails_on_disallowed_directories_test: Crash #  try/finally
-pub/test/barback/fails_on_overlapping_directories_test: Crash #  try/finally
-pub/test/barback/subdirectories_test: Crash #  try/finally
-pub/test/build/allows_arbitrary_modes_test: Crash #  try/finally
-pub/test/build/can_specify_output_directory_test: Crash #  try/finally
-pub/test/build/cleans_entire_build_directory_test: Crash #  try/finally
-pub/test/build/copies_browser_js_next_to_entrypoints_test: Crash #  try/finally
-pub/test/build/copies_browser_js_with_dependency_override_test: Crash #  try/finally
-pub/test/build/copies_browser_js_with_dev_dependency_test: Crash #  try/finally
-pub/test/build/copies_non_dart_files_to_build_test: Crash #  try/finally
-pub/test/build/defaults_to_release_mode_test: Crash #  try/finally
-pub/test/build/handles_long_paths_test: Crash #  try/finally
-pub/test/build/includes_assets_from_dependencies_test: Crash #  try/finally
-pub/test/build/includes_dart_files_from_dependencies_in_debug_test: Crash #  try/finally
-pub/test/build/includes_dart_files_in_debug_mode_test: Crash #  try/finally
-pub/test/build/outputs_error_to_json_test: Crash #  try/finally
-pub/test/build/outputs_results_to_json_test: Crash #  try/finally
-pub/test/build/preserves_htaccess_test: Crash #  try/finally
-pub/test/cache/add/adds_latest_matching_version_test: Crash #  try/finally
-pub/test/cache/add/adds_latest_version_test: Crash #  try/finally
-pub/test/cache/add/all_adds_all_matching_versions_test: Crash #  try/finally
-pub/test/cache/add/all_with_some_versions_present_test: Crash #  try/finally
-pub/test/cache/add/already_cached_test: Crash #  try/finally
-pub/test/cache/add/bad_version_test: Crash #  try/finally
-pub/test/cache/add/missing_package_arg_test: Crash #  try/finally
-pub/test/cache/add/no_matching_version_test: Crash #  try/finally
-pub/test/cache/add/package_not_found_test: Crash #  try/finally
-pub/test/cache/add/unexpected_arguments_test: Crash #  try/finally
-pub/test/cache/list_test: Crash #  try/finally
-pub/test/cache/repair/empty_cache_test: Crash #  try/finally
-pub/test/cache/repair/handles_corrupted_binstub_test: Crash #  try/finally
-pub/test/cache/repair/handles_corrupted_global_lockfile_test: Crash #  try/finally
-pub/test/cache/repair/handles_failure_test: Crash #  try/finally
-pub/test/cache/repair/handles_orphaned_binstub_test: Crash #  try/finally
-pub/test/cache/repair/recompiles_snapshots_test: Crash #  try/finally
-pub/test/cache/repair/reinstalls_git_packages_test: Crash #  try/finally
-pub/test/cache/repair/reinstalls_hosted_packages_test: Crash #  try/finally
-pub/test/cache/repair/updates_binstubs_test: Crash #  try/finally
-pub/test/dart2js/allows_import_in_dart_code_test: Crash #  try/finally
-pub/test/dart2js/compiles_entrypoints_in_root_package_test: Crash #  try/finally
-pub/test/dart2js/compiles_generated_dart_file_test: Crash #  try/finally
-pub/test/dart2js/compiles_generated_file_from_dependency_outside_web_test: Crash #  try/finally
-pub/test/dart2js/compiles_generated_file_from_dependency_test: Crash #  try/finally
-pub/test/dart2js/compiles_imported_generated_file_test: Crash #  try/finally
-pub/test/dart2js/converts_isolate_entrypoint_in_web_test: Crash #  try/finally
-pub/test/dart2js/does_not_compile_if_disabled_test: Crash #  try/finally
-pub/test/dart2js/does_not_compile_until_its_output_is_requested_test: Crash #  try/finally
-pub/test/dart2js/does_not_support_invalid_command_line_options_type_test: Crash #  try/finally
-pub/test/dart2js/does_not_support_invalid_environment_type_test: Crash #  try/finally
-pub/test/dart2js/does_not_support_invalid_option_test: Crash #  try/finally
-pub/test/dart2js/doesnt_support_invalid_type_for_boolean_option_test: Crash #  try/finally
-pub/test/dart2js/environment_constant_test: Crash #  try/finally
-pub/test/dart2js/ignores_entrypoint_in_dependency_test: Crash #  try/finally
-pub/test/dart2js/ignores_entrypoints_in_lib_test: Crash #  try/finally
-pub/test/dart2js/ignores_non_entrypoint_dart_files_test: Crash #  try/finally
-pub/test/dart2js/includes_source_maps_if_sourceMaps_true_test: Crash #  try/finally
-pub/test/dart2js/includes_source_maps_in_debug_test: Crash #  try/finally
-pub/test/dart2js/minifies_in_release_mode_test: Crash #  try/finally
-pub/test/dart2js/minify_configuration_overrides_mode_test: Crash #  try/finally
-pub/test/dart2js/omits_source_map_if_sourceMaps_false_test: Crash #  try/finally
-pub/test/dart2js/omits_source_map_in_release_test: Crash #  try/finally
-pub/test/dart2js/outputs_deferred_libraries_test: Crash #  try/finally
-pub/test/dart2js/passes_along_environment_constants_test: Crash #  try/finally
-pub/test/dart2js/reports_dart_parse_errors_test: Crash #  try/finally
-pub/test/dart2js/source_maps_include_core_libs_in_subdirectory_test: Crash #  try/finally
-pub/test/dart2js/source_maps_include_core_libs_test: Crash #  try/finally
-pub/test/dart2js/supports_configuration_with_build_test: Crash #  try/finally
-pub/test/dart2js/supports_valid_options_test: Crash #  try/finally
-pub/test/dart2js/unminified_in_nonrelease_mode_test: Crash #  try/finally
-pub/test/dependency_computer/conservative_dependencies_test: Crash #  try/finally
-pub/test/dependency_computer/cycle_test: Crash #  try/finally
-pub/test/dependency_computer/dev_transformers_test: Crash #  try/finally
-pub/test/dependency_computer/error_test: Crash #  try/finally
-pub/test/dependency_computer/import_dependencies_test: Crash #  try/finally
-pub/test/dependency_computer/no_dependencies_test: Crash #  try/finally
-pub/test/dependency_computer/transformers_needed_by_library_test: Crash #  try/finally
-pub/test/dependency_override_test: Crash #  try/finally
-pub/test/deps_test: Crash #  try/finally
-pub/test/dev_dependency_test: Crash #  try/finally
-pub/test/downgrade/does_not_show_other_versions_test: Crash #  try/finally
-pub/test/downgrade/doesnt_change_git_dependencies_test: Crash #  try/finally
-pub/test/downgrade/dry_run_does_not_apply_changes_test: Crash #  try/finally
-pub/test/downgrade/unlock_dependers_test: Crash #  try/finally
-pub/test/downgrade/unlock_if_necessary_test: Crash #  try/finally
-pub/test/error_group_test: Crash #  try/finally
-pub/test/get/broken_symlink_test: Crash #  try/finally
-pub/test/get/cache_transformed_dependency_test: Crash #  try/finally
-pub/test/get/dry_run_does_not_apply_changes_test: Crash #  try/finally
-pub/test/get/git/check_out_and_upgrade_test: Crash #  try/finally
-pub/test/get/git/check_out_branch_test: Crash #  try/finally
-pub/test/get/git/check_out_revision_test: Crash #  try/finally
-pub/test/get/git/check_out_test: Crash #  try/finally
-pub/test/get/git/check_out_transitive_test: Crash #  try/finally
-pub/test/get/git/check_out_twice_test: Crash #  try/finally
-pub/test/get/git/check_out_unfetched_revision_of_cached_repo_test: Crash #  try/finally
-pub/test/get/git/check_out_with_trailing_slash_test: Crash #  try/finally
-pub/test/get/git/dependency_name_match_pubspec_test: Crash #  try/finally
-pub/test/get/git/different_repo_name_test: Crash #  try/finally
-pub/test/get/git/doesnt_fetch_if_nothing_changes_test: Crash #  try/finally
-pub/test/get/git/lock_version_test: Crash #  try/finally
-pub/test/get/git/locked_revision_without_repo_test: Crash #  try/finally
-pub/test/get/git/require_pubspec_name_test: Crash #  try/finally
-pub/test/get/git/require_pubspec_test: Crash #  try/finally
-pub/test/get/git/stay_locked_if_compatible_test: Crash #  try/finally
-pub/test/get/git/unlock_if_incompatible_test: Crash #  try/finally
-pub/test/get/hosted/avoid_network_requests_test: Crash #  try/finally
-pub/test/get/hosted/cached_pubspec_test: Crash #  try/finally
-pub/test/get/hosted/do_not_upgrade_on_removed_constraints_test: Crash #  try/finally
-pub/test/get/hosted/does_no_network_requests_when_possible_test: Crash #  try/finally
-pub/test/get/hosted/get_test: Crash #  try/finally
-pub/test/get/hosted/get_transitive_test: Crash #  try/finally
-pub/test/get/hosted/gets_a_package_with_busted_dev_dependencies_test: Crash #  try/finally
-pub/test/get/hosted/resolve_constraints_test: Crash #  try/finally
-pub/test/get/hosted/stay_locked_if_compatible_test: Crash #  try/finally
-pub/test/get/hosted/stay_locked_if_new_is_satisfied_test: Crash #  try/finally
-pub/test/get/hosted/stay_locked_test: Crash #  try/finally
-pub/test/get/hosted/unlock_if_incompatible_test: Crash #  try/finally
-pub/test/get/hosted/unlock_if_new_is_unsatisfied_test: Crash #  try/finally
-pub/test/get/hosted/unlock_if_version_doesnt_exist_test: Crash #  try/finally
-pub/test/get/path/absolute_path_test: Crash #  try/finally
-pub/test/get/path/absolute_symlink_test: Crash #  try/finally
-pub/test/get/path/empty_pubspec_test: Crash #  try/finally
-pub/test/get/path/no_pubspec_test: Crash #  try/finally
-pub/test/get/path/nonexistent_dir_test: Crash #  try/finally
-pub/test/get/path/path_is_file_test: Crash #  try/finally
-pub/test/get/path/relative_path_test: Crash #  try/finally
-pub/test/get/path/relative_symlink_test: Crash #  try/finally
-pub/test/get/path/shared_dependency_symlink_test: Crash #  try/finally
-pub/test/get/path/shared_dependency_test: Crash #  try/finally
-pub/test/get/relative_symlink_test: Crash #  try/finally
-pub/test/get/switch_source_test: Crash #  try/finally
-pub/test/global/activate/activate_git_after_hosted_test: Crash #  try/finally
-pub/test/global/activate/activate_hosted_after_git_test: Crash #  try/finally
-pub/test/global/activate/activate_hosted_after_path_test: Crash #  try/finally
-pub/test/global/activate/activate_path_after_hosted_test: Crash #  try/finally
-pub/test/global/activate/bad_version_test: Crash #  try/finally
-pub/test/global/activate/cached_package_test: Crash #  try/finally
-pub/test/global/activate/constraint_test: Crash #  try/finally
-pub/test/global/activate/constraint_with_path_test: Crash #  try/finally
-pub/test/global/activate/different_version_test: Crash #  try/finally
-pub/test/global/activate/doesnt_snapshot_path_executables_test: Crash #  try/finally
-pub/test/global/activate/empty_constraint_test: Crash #  try/finally
-pub/test/global/activate/git_package_test: Crash #  try/finally
-pub/test/global/activate/ignores_active_version_test: Crash #  try/finally
-pub/test/global/activate/installs_dependencies_for_git_test: Crash #  try/finally
-pub/test/global/activate/installs_dependencies_for_path_test: Crash #  try/finally
-pub/test/global/activate/installs_dependencies_test: Crash #  try/finally
-pub/test/global/activate/missing_git_repo_test: Crash #  try/finally
-pub/test/global/activate/missing_package_arg_test: Crash #  try/finally
-pub/test/global/activate/outdated_binstub_test: Crash #  try/finally
-pub/test/global/activate/path_package_test: Crash #  try/finally
-pub/test/global/activate/reactivating_git_upgrades_test: Crash #  try/finally
-pub/test/global/activate/removes_old_lockfile_test: Crash #  try/finally
-pub/test/global/activate/snapshots_git_executables_test: Crash #  try/finally
-pub/test/global/activate/snapshots_hosted_executables_test: Crash #  try/finally
-pub/test/global/activate/supports_version_solver_backtracking_test: Crash #  try/finally
-pub/test/global/activate/uncached_package_test: Crash #  try/finally
-pub/test/global/activate/unexpected_arguments_test: Crash #  try/finally
-pub/test/global/activate/unknown_package_test: Crash #  try/finally
-pub/test/global/binstubs/binstub_runs_executable_test: Crash #  try/finally
-pub/test/global/binstubs/binstub_runs_global_run_if_no_snapshot_test: Crash #  try/finally
-pub/test/global/binstubs/binstub_runs_precompiled_snapshot_test: Crash #  try/finally
-pub/test/global/binstubs/creates_executables_in_pubspec_test: Crash #  try/finally
-pub/test/global/binstubs/does_not_warn_if_no_executables_test: Crash #  try/finally
-pub/test/global/binstubs/does_not_warn_if_on_path_test: Crash #  try/finally
-pub/test/global/binstubs/explicit_and_no_executables_options_test: Crash #  try/finally
-pub/test/global/binstubs/explicit_executables_test: Crash #  try/finally
-pub/test/global/binstubs/missing_script_test: Crash #  try/finally
-pub/test/global/binstubs/name_collision_test: Crash #  try/finally
-pub/test/global/binstubs/name_collision_with_overwrite_test: Crash #  try/finally
-pub/test/global/binstubs/no_executables_flag_test: Crash #  try/finally
-pub/test/global/binstubs/outdated_binstub_runs_pub_global_test: Crash #  try/finally
-pub/test/global/binstubs/outdated_snapshot_test: Crash #  try/finally
-pub/test/global/binstubs/path_package_test: Crash #  try/finally
-pub/test/global/binstubs/reactivate_removes_old_executables_test: Crash #  try/finally
-pub/test/global/binstubs/removes_even_if_not_in_pubspec_test: Crash #  try/finally
-pub/test/global/binstubs/removes_when_deactivated_test: Crash #  try/finally
-pub/test/global/binstubs/unknown_explicit_executable_test: Crash #  try/finally
-pub/test/global/binstubs/warns_if_not_on_path_test: Crash #  try/finally
-pub/test/global/deactivate/deactivate_and_reactivate_package_test: Crash #  try/finally
-pub/test/global/deactivate/git_package_test: Crash #  try/finally
-pub/test/global/deactivate/hosted_package_test: Crash #  try/finally
-pub/test/global/deactivate/missing_package_arg_test: Crash #  try/finally
-pub/test/global/deactivate/path_package_test: Crash #  try/finally
-pub/test/global/deactivate/removes_precompiled_snapshots_test: Crash #  try/finally
-pub/test/global/deactivate/unexpected_arguments_test: Crash #  try/finally
-pub/test/global/deactivate/unknown_package_test: Crash #  try/finally
-pub/test/global/list_test: Crash #  try/finally
-pub/test/global/run/errors_if_outside_bin_test: Crash #  try/finally
-pub/test/global/run/implicit_executable_name_test: Crash #  try/finally
-pub/test/global/run/missing_executable_arg_test: Crash #  try/finally
-pub/test/global/run/missing_path_package_test: Crash #  try/finally
-pub/test/global/run/mode_test: Crash #  try/finally
-pub/test/global/run/nonexistent_script_test: Crash #  try/finally
-pub/test/global/run/recompiles_if_sdk_is_out_of_date_test: Crash #  try/finally
-pub/test/global/run/reflects_changes_to_local_package_test: Crash #  try/finally
-pub/test/global/run/runs_git_script_test: Crash #  try/finally
-pub/test/global/run/runs_path_script_test: Crash #  try/finally
-pub/test/global/run/runs_script_test: Crash #  try/finally
-pub/test/global/run/runs_transformer_test: Crash #  try/finally
-pub/test/global/run/unknown_package_test: Crash #  try/finally
-pub/test/global/run/uses_old_lockfile_test: Crash #  try/finally
-pub/test/hosted/fail_gracefully_on_missing_package_test: Crash #  try/finally
-pub/test/hosted/fail_gracefully_on_url_resolve_test: Crash #  try/finally
-pub/test/hosted/offline_test: Crash #  try/finally
-pub/test/hosted/remove_removed_dependency_test: Crash #  try/finally
-pub/test/hosted/remove_removed_transitive_dependency_test: Crash #  try/finally
-pub/test/hosted/version_negotiation_test: Crash #  try/finally
-pub/test/implicit_barback_dependency_test: Crash #  try/finally
-pub/test/implicit_dependency_test: Crash #  try/finally
-pub/test/io_test: Crash #  try/finally
-pub/test/lish/archives_and_uploads_a_package_test: Crash #  try/finally
-pub/test/lish/cloud_storage_upload_doesnt_redirect_test: Crash #  try/finally
-pub/test/lish/cloud_storage_upload_provides_an_error_test: Crash #  try/finally
-pub/test/lish/does_not_publish_if_private_test: Crash #  try/finally
-pub/test/lish/does_not_publish_if_private_with_server_arg_test: Crash #  try/finally
-pub/test/lish/force_cannot_be_combined_with_dry_run_test: Crash #  try/finally
-pub/test/lish/force_does_not_publish_if_private_test: Crash #  try/finally
-pub/test/lish/force_does_not_publish_if_there_are_errors_test: Crash #  try/finally
-pub/test/lish/force_publishes_if_tests_are_no_warnings_or_errors_test: Crash #  try/finally
-pub/test/lish/force_publishes_if_there_are_warnings_test: Crash #  try/finally
-pub/test/lish/many_files_test: Crash #  try/finally
-pub/test/lish/package_creation_provides_a_malformed_error_test: Crash #  try/finally
-pub/test/lish/package_creation_provides_a_malformed_success_test: Crash #  try/finally
-pub/test/lish/package_creation_provides_an_error_test: Crash #  try/finally
-pub/test/lish/package_creation_provides_invalid_json_test: Crash #  try/finally
-pub/test/lish/package_validation_has_a_warning_and_continues_test: Crash #  try/finally
-pub/test/lish/package_validation_has_a_warning_and_is_canceled_test: Crash #  try/finally
-pub/test/lish/package_validation_has_an_error_test: Crash #  try/finally
-pub/test/lish/preview_errors_if_private_test: Crash #  try/finally
-pub/test/lish/preview_package_validation_has_a_warning_test: Crash #  try/finally
-pub/test/lish/preview_package_validation_has_no_warnings_test: Crash #  try/finally
-pub/test/lish/server_arg_does_not_override_private_test: Crash #  try/finally
-pub/test/lish/server_arg_overrides_publish_to_url_test: Crash #  try/finally
-pub/test/lish/upload_form_fields_has_a_non_string_value_test: Crash #  try/finally
-pub/test/lish/upload_form_fields_is_not_a_map_test: Crash #  try/finally
-pub/test/lish/upload_form_is_missing_fields_test: Crash #  try/finally
-pub/test/lish/upload_form_is_missing_url_test: Crash #  try/finally
-pub/test/lish/upload_form_provides_an_error_test: Crash #  try/finally
-pub/test/lish/upload_form_provides_invalid_json_test: Crash #  try/finally
-pub/test/lish/upload_form_url_is_not_a_string_test: Crash #  try/finally
-pub/test/lish/uses_publish_to_url_test: Crash #  try/finally
-pub/test/list_package_dirs/ignores_updated_pubspec_test: Crash #  try/finally
-pub/test/list_package_dirs/includes_dev_dependencies_test: Crash #  try/finally
-pub/test/list_package_dirs/lists_dependency_directories_test: Crash #  try/finally
-pub/test/list_package_dirs/lockfile_error_test: Crash #  try/finally
-pub/test/list_package_dirs/missing_pubspec_test: Crash #  try/finally
-pub/test/list_package_dirs/no_lockfile_test: Crash #  try/finally
-pub/test/list_package_dirs/pubspec_error_test: Crash #  try/finally
-pub/test/lock_file_test: Crash #  try/finally
-pub/test/no_package_symlinks_test: Crash #  try/finally
-pub/test/oauth2/with_a_malformed_credentials_authenticates_again_test: Crash #  try/finally
-pub/test/oauth2/with_a_pre_existing_credentials_does_not_authenticate_test: Crash #  try/finally
-pub/test/oauth2/with_a_server_rejected_refresh_token_authenticates_again_test: Crash #  try/finally
-pub/test/oauth2/with_an_expired_credentials_refreshes_and_saves_test: Crash #  try/finally
-pub/test/oauth2/with_an_expired_credentials_without_a_refresh_token_authenticates_again_test: Crash #  try/finally
-pub/test/oauth2/with_no_credentials_authenticates_and_saves_credentials_test: Crash #  try/finally
-pub/test/oauth2/with_server_rejected_credentials_authenticates_again_test: Crash #  try/finally
-pub/test/package_list_files_test: Crash #  try/finally
-pub/test/preprocess_test: Crash #  try/finally
-pub/test/pub_get_and_upgrade_test: Crash #  try/finally
-pub/test/pub_test: Crash #  try/finally
-pub/test/pub_uploader_test: Crash #  try/finally
-pub/test/pubspec_test: Crash #  try/finally
-pub/test/real_version_test: Crash #  try/finally
-pub/test/run/allows_dart_extension_test: Crash #  try/finally
-pub/test/run/app_can_read_from_stdin_test: Crash #  try/finally
-pub/test/run/displays_transformer_logs_test: Crash #  try/finally
-pub/test/run/does_not_run_on_transformer_error_test: Crash #  try/finally
-pub/test/run/doesnt_load_an_unnecessary_transformer_test: Crash #  try/finally
-pub/test/run/errors_if_no_executable_is_given_test: Crash #  try/finally
-pub/test/run/errors_if_only_transitive_dependency_test: Crash #  try/finally
-pub/test/run/errors_if_path_in_dependency_test: Crash #  try/finally
-pub/test/run/forwards_signal_posix_test: Crash #  try/finally
-pub/test/run/ignores_explicit_dart2js_transformer_test: Crash #  try/finally
-pub/test/run/includes_parent_directories_of_entrypoint_test: Crash #  try/finally
-pub/test/run/mode_test: Crash #  try/finally
-pub/test/run/nonexistent_dependency_test: Crash #  try/finally
-pub/test/run/nonexistent_script_in_dependency_test: Crash #  try/finally
-pub/test/run/nonexistent_script_test: Crash #  try/finally
-pub/test/run/passes_along_arguments_test: Crash #  try/finally
-pub/test/run/runs_a_generated_script_test: Crash #  try/finally
-pub/test/run/runs_app_in_directory_in_entrypoint_test: Crash #  try/finally
-pub/test/run/runs_app_in_entrypoint_test: Crash #  try/finally
-pub/test/run/runs_app_in_entrypoint_with_warning_test: Crash #  try/finally
-pub/test/run/runs_from_a_dependency_override_after_dependency_test: Crash #  try/finally
-pub/test/run/runs_named_app_in_dependency_test: Crash #  try/finally
-pub/test/run/runs_named_app_in_dev_dependency_test: Crash #  try/finally
-pub/test/run/runs_shorthand_app_in_dependency_test: Crash #  try/finally
-pub/test/run/runs_the_script_in_checked_mode_test: Crash #  try/finally
-pub/test/run/runs_transformer_in_entrypoint_test: Crash #  try/finally
-pub/test/serve/404_page_test: Crash #  try/finally
-pub/test/serve/allows_arbitrary_modes_test: Crash #  try/finally
-pub/test/serve/defaults_to_debug_mode_test: Crash #  try/finally
-pub/test/serve/does_not_crash_if_an_unused_dart_file_has_a_syntax_error_test: Crash #  try/finally
-pub/test/serve/does_not_get_first_if_a_dependency_is_removed_test: Crash #  try/finally
-pub/test/serve/does_not_get_first_if_git_url_did_not_change_test: Crash #  try/finally
-pub/test/serve/does_not_get_first_if_locked_matches_override_test: Crash #  try/finally
-pub/test/serve/does_not_get_first_if_locked_version_matches_test: Crash #  try/finally
-pub/test/serve/does_not_serve_dart_in_release_test: Crash #  try/finally
-pub/test/serve/does_not_serve_hidden_assets_test: Crash #  try/finally
-pub/test/serve/does_not_watch_compiled_js_files_test: Crash #  try/finally
-pub/test/serve/gets_first_if_dependency_added_test: Crash #  try/finally
-pub/test/serve/gets_first_if_dependency_is_not_installed_test: Crash #  try/finally
-pub/test/serve/gets_first_if_dependency_version_changed_test: Crash #  try/finally
-pub/test/serve/gets_first_if_dev_dependency_changed_test: Crash #  try/finally
-pub/test/serve/gets_first_if_git_ref_changed_test: Crash #  try/finally
-pub/test/serve/gets_first_if_git_url_changed_test: Crash #  try/finally
-pub/test/serve/gets_first_if_no_lockfile_test: Crash #  try/finally
-pub/test/serve/gets_first_if_path_dependency_changed_test: Crash #  try/finally
-pub/test/serve/gets_first_if_source_changed_test: Crash #  try/finally
-pub/test/serve/gets_first_if_transitive_dependency_is_not_installed_test: Crash #  try/finally
-pub/test/serve/invalid_method_test: Crash #  try/finally
-pub/test/serve/invalid_urls_test: Crash #  try/finally
-pub/test/serve/missing_asset_test: Crash #  try/finally
-pub/test/serve/missing_dependency_file_test: Crash #  try/finally
-pub/test/serve/missing_file_test: Crash #  try/finally
-pub/test/serve/native_watch_added_file_test: Crash #  try/finally
-pub/test/serve/native_watch_modified_file_test: Crash #  try/finally
-pub/test/serve/native_watch_removed_file_test: Crash #  try/finally
-pub/test/serve/native_watch_replaced_file_test: Crash #  try/finally
-pub/test/serve/serve_from_app_lib_test: Crash #  try/finally
-pub/test/serve/serve_from_app_web_test: Crash #  try/finally
-pub/test/serve/serve_from_dependency_lib_test: Crash #  try/finally
-pub/test/serve/serves_file_with_space_test: Crash #  try/finally
-pub/test/serve/serves_index_html_for_directories_test: Crash #  try/finally
-pub/test/serve/serves_web_and_test_dirs_by_default_test: Crash #  try/finally
-pub/test/serve/supports_cross_origin_header_test: Crash #  try/finally
-pub/test/serve/supports_user_defined_declaring_transformers_test: Crash #  try/finally
-pub/test/serve/supports_user_defined_lazy_transformers_test: Crash #  try/finally
-pub/test/serve/unknown_dependency_test: Crash #  try/finally
-pub/test/serve/uses_appropriate_mime_types_test: Crash #  try/finally
-pub/test/serve/watch_added_file_test: Crash #  try/finally
-pub/test/serve/watch_modified_file_test: Crash #  try/finally
-pub/test/serve/watch_removed_file_test: Crash #  try/finally
-pub/test/serve/web_socket/exit_on_close_test: Crash #  try/finally
-pub/test/serve/web_socket/path_to_urls_errors_test: Crash #  try/finally
-pub/test/serve/web_socket/path_to_urls_test: Crash #  try/finally
-pub/test/serve/web_socket/path_to_urls_with_line_test: Crash #  try/finally
-pub/test/serve/web_socket/serve_directory_already_served_test: Crash #  try/finally
-pub/test/serve/web_socket/serve_directory_and_immediately_request_asset_test: Crash #  try/finally
-pub/test/serve/web_socket/serve_directory_and_immediately_serve_again_test: Crash #  try/finally
-pub/test/serve/web_socket/serve_directory_and_immediately_unserve_test: Crash #  try/finally
-pub/test/serve/web_socket/serve_directory_arg_errors_test: Crash #  try/finally
-pub/test/serve/web_socket/serve_directory_overlapping_test: Crash #  try/finally
-pub/test/serve/web_socket/serve_directory_test: Crash #  try/finally
-pub/test/serve/web_socket/unserve_directory_arg_errors_test: Crash #  try/finally
-pub/test/serve/web_socket/unserve_directory_not_served_test: Crash #  try/finally
-pub/test/serve/web_socket/unserve_directory_test: Crash #  try/finally
-pub/test/serve/web_socket/url_to_asset_id_errors_test: Crash #  try/finally
-pub/test/serve/web_socket/url_to_asset_id_test: Crash #  try/finally
-pub/test/serve/web_socket/url_to_asset_id_with_line_test: Crash #  try/finally
-pub/test/snapshot/creates_a_snapshot_for_immediate_and_transitive_dep_test: Crash #  try/finally
-pub/test/snapshot/creates_a_snapshot_test: Crash #  try/finally
-pub/test/snapshot/doesnt_load_irrelevant_transformers_test: Crash #  try/finally
-pub/test/snapshot/doesnt_resnapshot_when_a_dependency_is_unchanged_test: Crash #  try/finally
-pub/test/snapshot/doesnt_snapshot_an_entrypoint_dependency_test: Crash #  try/finally
-pub/test/snapshot/doesnt_snapshot_path_dependency_test: Crash #  try/finally
-pub/test/snapshot/doesnt_snapshot_transitive_dependencies_test: Crash #  try/finally
-pub/test/snapshot/prints_errors_for_broken_snapshots_test: Crash #  try/finally
-pub/test/snapshot/recompiles_if_the_sdk_is_out_of_date_test: Crash #  try/finally
-pub/test/snapshot/snapshots_transformed_code_test: Crash #  try/finally
-pub/test/snapshot/updates_snapshot_for_git_dependency_test: Crash #  try/finally
-pub/test/snapshot/upgrades_snapshot_for_dependency_test: Crash #  try/finally
-pub/test/snapshot/upgrades_snapshot_test: Crash #  try/finally
-pub/test/transcript_test: Crash # Instance of 'TypeOperator': type casts not implemented.
-pub/test/transformer/a_transformer_rejects_its_config_test: Crash #  try/finally
-pub/test/transformer/asset_not_found_exceptions_are_detectable_test: Crash #  try/finally
-pub/test/transformer/cache_test: Crash #  try/finally
-pub/test/transformer/can_log_messages_test: Crash #  try/finally
-pub/test/transformer/can_use_consume_primary_test: Crash #  try/finally
-pub/test/transformer/can_use_has_input_test: Crash #  try/finally
-pub/test/transformer/can_use_read_input_as_string_test: Crash #  try/finally
-pub/test/transformer/can_use_read_input_test: Crash #  try/finally
-pub/test/transformer/configuration/configuration_defaults_to_empty_map_test: Crash #  try/finally
-pub/test/transformer/configuration/passes_configuration_to_a_transformer_test: Crash #  try/finally
-pub/test/transformer/configuration/with_configuration_only_instantiates_configurable_transformers_test: Crash #  try/finally
-pub/test/transformer/dart2js_transformer_before_another_transformer_test: Crash #  try/finally
-pub/test/transformer/does_not_run_a_transform_on_an_input_in_another_package_test: Crash #  try/finally
-pub/test/transformer/exclusion/exclude_asset_glob_test: Crash #  try/finally
-pub/test/transformer/exclusion/exclude_asset_list_test: Crash #  try/finally
-pub/test/transformer/exclusion/exclude_asset_prefix_test: Crash #  try/finally
-pub/test/transformer/exclusion/exclude_asset_string_test: Crash #  try/finally
-pub/test/transformer/exclusion/include_asset_glob_test: Crash #  try/finally
-pub/test/transformer/exclusion/include_asset_list_test: Crash #  try/finally
-pub/test/transformer/exclusion/include_asset_prefix_test: Crash #  try/finally
-pub/test/transformer/exclusion/include_asset_string_test: Crash #  try/finally
-pub/test/transformer/exclusion/includes_before_excludes_test: Crash #  try/finally
-pub/test/transformer/exclusion/works_on_aggregate_transformer_test: Crash #  try/finally
-pub/test/transformer/exclusion/works_on_dart2js_test: Crash #  try/finally
-pub/test/transformer/exclusion/works_on_lazy_transformer_test: Crash #  try/finally
-pub/test/transformer/exclusion/works_on_transformer_group_test: Crash #  try/finally
-pub/test/transformer/fails_to_load_a_file_that_defines_no_transforms_test: Crash #  try/finally
-pub/test/transformer/fails_to_load_a_non_existent_transform_test: Crash #  try/finally
-pub/test/transformer/fails_to_load_a_pubspec_with_reserved_transformer_test: Crash #  try/finally
-pub/test/transformer/fails_to_load_a_transform_from_a_deps_dev_dependency_test: Crash #  try/finally
-pub/test/transformer/fails_to_load_a_transform_from_a_non_dependency_test: Crash #  try/finally
-pub/test/transformer/fails_to_load_a_transform_with_a_syntax_error_test: Crash #  try/finally
-pub/test/transformer/fails_to_load_a_transform_with_an_import_error_test: Crash #  try/finally
-pub/test/transformer/fails_to_load_an_unconfigurable_transformer_when_config_is_passed_test: Crash #  try/finally
-pub/test/transformer/ignores_a_transformer_on_test_files_in_a_dependency_test: Crash #  try/finally
-pub/test/transformer/loads_a_declaring_aggregate_transformer_test: Crash #  try/finally
-pub/test/transformer/loads_a_diamond_transformer_dependency_graph_test: Crash #  try/finally
-pub/test/transformer/loads_a_lazy_aggregate_transformer_test: Crash #  try/finally
-pub/test/transformer/loads_a_transformer_defined_in_an_exported_library_test: Crash #  try/finally
-pub/test/transformer/loads_an_aggregate_transformer_test: Crash #  try/finally
-pub/test/transformer/loads_different_configurations_from_the_same_isolate_test: Crash #  try/finally
-pub/test/transformer/multiple_transformers_reject_their_config_test: Crash #  try/finally
-pub/test/transformer/prefers_transformer_to_library_name_test: Crash #  try/finally
-pub/test/transformer/prints_a_transform_error_in_apply_test: Crash #  try/finally
-pub/test/transformer/prints_a_transform_interface_error_test: Crash #  try/finally
-pub/test/transformer/runs_a_local_transform_on_the_application_package_test: Crash #  try/finally
-pub/test/transformer/runs_a_third_party_transform_on_the_application_package_test: Crash #  try/finally
-pub/test/transformer/runs_a_third_party_transformer_on_a_local_transformer_test: Crash #  try/finally
-pub/test/transformer/runs_a_transformer_group_test: Crash #  try/finally
-pub/test/transformer/runs_a_transformer_on_a_dependency_test: Crash #  try/finally
-pub/test/transformer/runs_one_third_party_transformer_on_another_test: Crash #  try/finally
-pub/test/transformer/supports_a_transformer_that_doesnt_return_futures_test: Crash #  try/finally
-pub/test/unknown_source_test: Crash #  try/finally
-pub/test/upgrade/dry_run_does_not_apply_changes_test: Crash #  try/finally
-pub/test/upgrade/git/do_not_upgrade_if_unneeded_test: Crash #  try/finally
-pub/test/upgrade/git/upgrade_locked_test: Crash #  try/finally
-pub/test/upgrade/git/upgrade_one_locked_test: Crash #  try/finally
-pub/test/upgrade/git/upgrade_to_incompatible_pubspec_test: Crash #  try/finally
-pub/test/upgrade/git/upgrade_to_nonexistent_pubspec_test: Crash #  try/finally
-pub/test/upgrade/hosted/unlock_dependers_test: Crash #  try/finally
-pub/test/upgrade/hosted/unlock_if_necessary_test: Crash #  try/finally
-pub/test/upgrade/hosted/upgrade_removed_constraints_test: Crash #  try/finally
-pub/test/upgrade/report/describes_change_test: Crash #  try/finally
-pub/test/upgrade/report/does_not_show_newer_versions_for_locked_packages_test: Crash #  try/finally
-pub/test/upgrade/report/highlights_overrides_test: Crash #  try/finally
-pub/test/upgrade/report/leading_character_shows_change_test: Crash #  try/finally
-pub/test/upgrade/report/shows_newer_available_versions_test: Crash #  try/finally
-pub/test/upgrade/report/shows_number_of_changed_dependencies_test: Crash #  try/finally
-pub/test/utils_test: Crash #  try/finally
-pub/test/validator/compiled_dartdoc_test: Crash #  try/finally
-pub/test/validator/dependency_override_test: Crash #  try/finally
-pub/test/validator/dependency_test: Crash #  try/finally
-pub/test/validator/directory_test: Crash #  try/finally
-pub/test/validator/executable_test: Crash #  try/finally
-pub/test/validator/license_test: Crash #  try/finally
-pub/test/validator/name_test: Crash #  try/finally
-pub/test/validator/pubspec_field_test: Crash #  try/finally
-pub/test/validator/sdk_constraint_test: Crash #  try/finally
-pub/test/validator/size_test: Crash #  try/finally
-pub/test/validator/utf8_readme_test: Crash #  try/finally
-pub/test/version_solver_test: Crash #  try/finally
diff --git a/tools/FAKE_COMMITS b/tools/FAKE_COMMITS
index 2e1275c..59a3d33 100644
--- a/tools/FAKE_COMMITS
+++ b/tools/FAKE_COMMITS
@@ -13,3 +13,4 @@
 Trigger bots after github outage
 Trigger bots on github pull
 Trigger bots 
+Purple is the new green.
diff --git a/tools/VERSION b/tools/VERSION
index 78758e0..d214ff1 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -25,7 +25,7 @@
 #
 CHANNEL dev
 MAJOR 1
-MINOR 11
+MINOR 12
 PATCH 0
-PRERELEASE 5
-PRERELEASE_PATCH 7
+PRERELEASE 0
+PRERELEASE_PATCH 0
diff --git a/tools/apps/update_homebrew/bin/update_homebrew.dart b/tools/apps/update_homebrew/bin/update_homebrew.dart
index 7e21db9..a1e4586 100644
--- a/tools/apps/update_homebrew/bin/update_homebrew.dart
+++ b/tools/apps/update_homebrew/bin/update_homebrew.dart
@@ -21,17 +21,13 @@
 
 const CHANNELS = const ['dev', 'stable'];
 
-const SDK_FILES = const [
-  'sdk/dartsdk-macos-x64-release.zip',
-  'sdk/dartsdk-macos-ia32-release.zip'
-];
+const FILES = const [x64File, ia32File, dartiumFile, contentShellFile];
 
-const DARTIUM_FILES = const [
-  'dartium/dartium-macos-ia32-release.zip',
-  'dartium/content_shell-macos-ia32-release.zip'
-];
-
-final FILES = []..addAll(SDK_FILES)..addAll(DARTIUM_FILES);
+const urlBase = 'https://storage.googleapis.com/dart-archive/channels';
+const x64File = 'sdk/dartsdk-macos-x64-release.zip';
+const ia32File = 'sdk/dartsdk-macos-ia32-release.zip';
+const dartiumFile = 'dartium/dartium-macos-ia32-release.zip';
+const contentShellFile = 'dartium/content_shell-macos-ia32-release.zip';
 
 Future<String> getHash256(
     String channel, String revision, String download) async {
@@ -65,7 +61,8 @@
   }
 }
 
-Future setCurrentRevisions(Map revisions) async {
+Future<Map> getCurrentRevisions() async {
+  var revisions = <String, String>{};
   var lines = await (new File('$repository/dart.rb')).readAsLines();
 
   for (var channel in CHANNELS) {
@@ -82,50 +79,44 @@
     revisions[channel] =
         regExp.firstMatch(lines.firstWhere(regExp.hasMatch)).group(1);
   }
+  return revisions;
 }
 
-Future setHashes(Map revisions, Map hashes) {
-  List waitOn = [];
+Future<Map> getHashes(Map revisions) async {
+  var hashes = <String, Map>{};
   for (var channel in CHANNELS) {
     hashes[channel] = {};
     for (var file in FILES) {
-      waitOn.add(getHash256(channel, revisions[channel], file).then((hash) {
-        hashes[channel][file] = hash;
-      }));
+      var hash = await getHash256(channel, revisions[channel], file);
+      hashes[channel][file] = hash;
     }
   }
-  return Future.wait(waitOn);
+  return hashes;
 }
 
 Future writeHomebrewInfo(String channel, String revision) async {
-  var revisions = {};
-  var hashes = {};
-
-  await setCurrentRevisions(revisions);
+  var revisions = await getCurrentRevisions();
 
   if (revisions[channel] == revision) {
     print("Channel $channel is already at revision $revision in homebrew.");
     exit(0);
   }
   revisions[channel] = revision;
-  await setHashes(revisions, hashes);
+  var hashes = await getHashes(revisions);
   var devVersion = await getVersion('dev', revisions['dev']);
 
   var stableVersion = await getVersion('stable', revisions['stable']);
 
-  await (new File('$repository/dartium.rb').openWrite()
-    ..write(DartiumFile(revisions, hashes, devVersion, stableVersion))).close();
-  await (new File('$repository/dart.rb').openWrite()
-    ..write(DartFile(revisions, hashes, devVersion, stableVersion))).close();
+  await new File('$repository/dartium.rb').writeAsString(
+      createDartiumFormula(revisions, hashes, devVersion, stableVersion),
+      flush: true);
+  await new File('$repository/dart.rb').writeAsString(
+      createDartFormula(revisions, hashes, devVersion, stableVersion),
+      flush: true);
 }
 
-String DartiumFile(
-    Map revisions, Map hashes, String devVersion, String stableVersion) {
-  final urlBase = 'https://storage.googleapis.com/dart-archive/channels';
-  final dartiumFile = 'dartium/dartium-macos-ia32-release.zip';
-  final contentShellFile = 'dartium/content_shell-macos-ia32-release.zip';
-
-  return '''
+String createDartiumFormula(
+    Map revisions, Map hashes, String devVersion, String stableVersion) => '''
 require 'formula'
 
 class Dartium < Formula
@@ -142,14 +133,12 @@
 
     resource 'content_shell' do
       url '$urlBase/dev/release/${revisions['dev']}/$contentShellFile'
-      version '$devVersion'
       sha256 '${hashes['dev'][contentShellFile]}'
     end
   end
 
   resource 'content_shell' do
     url '$urlBase/stable/release/${revisions['stable']}/$contentShellFile'
-    version '$stableVersion'
     sha256 '${hashes['stable'][contentShellFile]}'
   end
 
@@ -171,7 +160,11 @@
   end
 
   def caveats; <<-EOS.undent
-     To use with IntelliJ, set the Dartium execute home to:
+    DEPRECATED
+      In the future, use the `dart` formula using
+      `--with-dartium` and/or `--with-content-shell`
+
+    To use with IntelliJ, set the Dartium execute home to:
         #{prefix}/Chromium.app
     EOS
   end
@@ -181,15 +174,9 @@
   end
 end
 ''';
-}
 
-String DartFile(
-    Map revisions, Map hashes, String devVersion, String stableVersion) {
-  final urlBase = 'https://storage.googleapis.com/dart-archive/channels';
-  final x64File = 'sdk/dartsdk-macos-x64-release.zip';
-  final ia32File = 'sdk/dartsdk-macos-ia32-release.zip';
-
-  return '''
+String createDartFormula(
+    Map revisions, Map hashes, String devVersion, String stableVersion) => '''
 require 'formula'
 
 class Dart < Formula
@@ -204,6 +191,9 @@
     sha256 '${hashes['stable'][ia32File]}'
   end
 
+  option 'with-content-shell', 'Download and install content_shell -- headless Dartium for testing'
+  option 'with-dartium', 'Download and install Dartium -- Chromium with Dart'
+
   devel do
     version '$devVersion'
     if MacOS.prefer_64_bit?
@@ -213,17 +203,64 @@
       url '$urlBase/dev/release/${revisions['dev']}/$ia32File'
       sha256 '${hashes['dev'][ia32File]}'
     end
+
+    resource 'content_shell' do
+      version '$devVersion'
+      url '$urlBase/dev/release/${revisions['dev']}/$contentShellFile'
+      sha256 '${hashes['dev'][contentShellFile]}'
+    end
+
+    resource 'dartium' do
+      version '$devVersion'
+      url '$urlBase/dev/release/${revisions['dev']}/$dartiumFile'
+      sha256 '${hashes['dev'][dartiumFile]}'
+    end
+  end
+
+  resource 'content_shell' do
+    version '$stableVersion'
+    url '$urlBase/stable/release/${revisions['stable']}/$contentShellFile'
+    sha256 '${hashes['stable'][contentShellFile]}'
+  end
+
+  resource 'dartium' do
+    version '$stableVersion'
+    url '$urlBase/stable/release/${revisions['stable']}/$dartiumFile'
+    sha256 '${hashes['stable'][dartiumFile]}'
   end
 
   def install
     libexec.install Dir['*']
     bin.install_symlink "#{libexec}/bin/dart"
     bin.write_exec_script Dir["#{libexec}/bin/{pub,docgen,dart?*}"]
+
+    if build.with? 'content-shell'
+      dartium_binary = 'Chromium.app/Contents/MacOS/Chromium'
+      prefix.install resource('dartium')
+      (bin+"dartium").write shim_script dartium_binary
+    end
+
+    if build.with? 'content-shell'
+      content_shell_binary = 'Content Shell.app/Contents/MacOS/Content Shell'
+      prefix.install resource('content_shell')
+      (bin+"content_shell").write shim_script content_shell_binary
+    end
+  end
+
+  def shim_script target
+    <<-EOS.undent
+      #!/bin/bash
+      exec "#{prefix}/#{target}" "\$@"
+    EOS
   end
 
   def caveats; <<-EOS.undent
     Please note the path to the Dart SDK:
       #{opt_libexec}
+
+    --with-dartium:
+      To use with IntelliJ, set the Dartium execute home to:
+        #{prefix}/Chromium.app
     EOS
   end
 
@@ -238,7 +275,6 @@
   end
 end
 ''';
-}
 
 Future runGit(List<String> args) async {
   print("git ${args.join(' ')}");
@@ -258,14 +294,17 @@
   final options = parser.parse(args);
   final revision = options['revision'];
   final channel = options['channel'];
-  final key = options['key'];
-  if ([revision, channel, key].contains(null)) {
-    print("Usage: update_homebrew.dart -r revision -c channel -k ssh_key\n"
+  if ([revision, channel].contains(null)) {
+    print("Usage: update_homebrew.dart -r revision -c channel [-k ssh_key]\n"
         "  ssh_key should allow pushes to ${GITHUB_REPO} on github");
     return;
   }
-  final sshWrapper = Platform.script.resolve('ssh_with_key').toFilePath();
-  gitEnvironment = {'GIT_SSH': sshWrapper, 'SSH_KEY_PATH': key};
+
+  final key = options['key'];
+  if (key != null) {
+    final sshWrapper = Platform.script.resolve('ssh_with_key').toFilePath();
+    gitEnvironment = {'GIT_SSH': sshWrapper, 'SSH_KEY_PATH': key};
+  }
 
   Chain.capture(() async {
     var tempDir = await Directory.systemTemp.createTemp('update_homebrew');
diff --git a/tools/bots/bot_utils.py b/tools/bots/bot_utils.py
index 565ee5a..3646724 100644
--- a/tools/bots/bot_utils.py
+++ b/tools/bots/bot_utils.py
@@ -169,6 +169,9 @@
   def apidocs_zipfilename(self):
     return 'dart-api-docs.zip'
 
+  def dartdocs_zipfilename(self):
+    return 'dartdocs-gen-api.zip'
+
   def editor_zipfilename(self, system, arch):
     return 'darteditor-%s-%s.zip' % (
         SYSTEM_RENAMES[system], ARCH_RENAMES[arch])
@@ -203,6 +206,11 @@
     assert len('%s' % revision) > 0
     return '%s/channels/%s/%s' % (self.bucket, self.channel, revision)
 
+  def dartdocs_dirpath(self, revision):
+    assert len('%s' % revision) > 0
+    return '%s/channels/%s/gen-dartdocs/%s' % (self.bucket, 
+                                               self.channel, revision)
+
   def docs_latestpath(self, revision):
     assert len('%s' % revision) > 0
     return '%s/channels/%s/latest.txt' % (self.bucket, self.channel)
@@ -278,10 +286,14 @@
                shell=(GSUtil.GSUTIL_IS_SHELL_SCRIPT and
                       sys.platform == 'win32'))
 
-  def upload(self, local_path, remote_path, recursive=False, public=False):
+  def upload(self, local_path, remote_path, recursive=False, 
+             public=False, multithread=False):
     assert remote_path.startswith('gs://')
 
-    args = ['cp']
+    if multithread:
+      args = ['-m', 'cp']
+    else:
+      args = ['cp']
     if public:
       args += ['-a', 'public-read']
     if recursive:
diff --git a/tools/bots/cross-vm.py b/tools/bots/cross-vm.py
index f11777e..1296fe9 100644
--- a/tools/bots/cross-vm.py
+++ b/tools/bots/cross-vm.py
@@ -16,7 +16,7 @@
 import utils
 
 CROSS_VM = r'cross-(arm)-vm-linux-(release)'
-TARGET_VM = r'target-(arm)-vm-linux-(release)'
+TARGET_VM = r'target-(arm)-vm-linux-(([0-9]+)-([0-9]+))?(release)'
 GSUTIL = utils.GetBuildbotGSUtilPath()
 
 def run(args):
@@ -65,12 +65,15 @@
       if os.path.exists(path):
         os.remove(path)
 
-def target_builder(arch, mode):
+def target_builder(arch, mode, total_shards, shard_index):
   test_py = os.path.join('tools', 'test.py')
   test_args = [sys.executable, test_py, '--progress=line', '--report',
                '--time', '--compiler=none', '--runtime=vm', '--write-debug-log',
                '--write-test-outcome-log', '--mode=' + mode, '--arch=' + arch,
                '--exclude-suite=pkg']
+  if total_shards and shard_index:
+    test_args.append('--shards=%s' % total_shards)
+    test_args.append('--shard=%s' % shard_index)
 
   revision = os.environ['BUILDBOT_GOT_REVISION']
   tarball = tarball_name(arch, mode, revision)
@@ -106,8 +109,10 @@
     cross_compiling_builder(arch, mode)
   elif target_vm_pattern_match:
     arch = target_vm_pattern_match.group(1)
-    mode = target_vm_pattern_match.group(2)
-    target_builder(arch, mode)
+    mode = target_vm_pattern_match.group(5)
+    shard_index = target_vm_pattern_match.group(3)
+    total_shards = target_vm_pattern_match.group(4)
+    target_builder(arch, mode, total_shards, shard_index)
   else:
     raise Exception("Unknown builder name %s" % name)
 
diff --git a/tools/bots/dart_sdk.py b/tools/bots/dart_sdk.py
index c124c5d..bb7b2f4 100644
--- a/tools/bots/dart_sdk.py
+++ b/tools/bots/dart_sdk.py
@@ -7,6 +7,7 @@
 import os.path
 import shutil
 import sys
+import subprocess
 
 import bot
 import bot_utils
@@ -30,6 +31,23 @@
     Run([sys.executable, './tools/build.py', '--mode=release',
          '--arch=ia32', 'dartdocgen'])
 
+def BuildDartdocAPIDocs(dirname):
+  dart_sdk = os.path.join(bot_utils.DART_DIR,
+                          utils.GetBuildRoot(BUILD_OS, 'release', 'ia32'),
+                          'dart-sdk')
+  dart_exe =  os.path.join(dart_sdk, 'bin', 'dart')
+  dartdoc_dart = os.path.join(bot_utils.DART_DIR,
+                              'third_party', 'pkg' , 'dartdoc' , 'bin' , 
+                              'dartdoc.dart')
+  packages_dir = os.path.join(bot_utils.DART_DIR,
+                              utils.GetBuildRoot(BUILD_OS, 'release', 'ia32'),
+                              'packages')
+  with bot.BuildStep('Build API docs by dartdoc'):
+    subprocess.call([dart_exe, '--package-root=' + packages_dir, dartdoc_dart, 
+                     '--sdk-docs','--output', dirname, '--dart-sdk', dart_sdk, 
+                     '--package-root=%s' % packages_dir], 
+                     stdout=open(os.devnull, 'wb'))
+
 def CreateUploadVersionFile():
   file_path = os.path.join(bot_utils.DART_DIR,
                            utils.GetBuildRoot(BUILD_OS, 'release', 'ia32'),
@@ -40,7 +58,7 @@
 
 def DartArchiveUploadVersionFile(version_file):
   namer = bot_utils.GCSNamer(CHANNEL, bot_utils.ReleaseType.RAW)
-  revision = utils.GetSVNRevision()
+  revision = utils.GetArchiveVersion()
   for revision in [revision, 'latest']:
     destination = namer.version_filepath(revision)
     DartArchiveFile(version_file, destination, checksum_files=False)
@@ -68,7 +86,7 @@
 
 def DartArchiveUploadSDKs(system, sdk32_zip, sdk64_zip):
   namer = bot_utils.GCSNamer(CHANNEL, bot_utils.ReleaseType.RAW)
-  revision = utils.GetSVNRevision()
+  revision = utils.GetArchiveVersion()
   for revision in [revision, 'latest']:
     path32 = namer.sdk_zipfilepath(revision, system, 'ia32', 'release')
     path64 = namer.sdk_zipfilepath(revision, system, 'x64', 'release')
@@ -86,16 +104,27 @@
   api_zip = os.path.join(bot_utils.DART_DIR,
                          utils.GetBuildRoot(BUILD_OS, 'release', 'ia32'),
                          'dart-api-docs.zip')
+  dartdoc_dir =  os.path.join(bot_utils.DART_DIR,
+                              utils.GetBuildRoot(BUILD_OS, 'release', 'ia32'),
+                              'gen-dartdocs')
+  dartdoc_zip =  os.path.join(bot_utils.DART_DIR,
+                              utils.GetBuildRoot(BUILD_OS, 'release', 'ia32'),
+                              'dartdocs-api.zip')
   shutil.rmtree(api_path, ignore_errors=True)
   FileDelete(api_zip)
   BuildAPIDocs()
   UploadApiDocs(api_path)
+  UploadApiLatestFile()
   CreateZip(api_path, api_zip)
   DartArchiveUploadAPIDocs(api_zip)
+  BuildDartdocAPIDocs(dartdoc_dir) 
+  UploadDartdocApiDocs(dartdoc_dir)  
+  CreateZip(dartdoc_dir, dartdoc_zip)  
+  DartArchiveUploadDartdocAPIDocs(dartdoc_zip)
 
 def DartArchiveUploadAPIDocs(api_zip):
   namer = bot_utils.GCSNamer(CHANNEL, bot_utils.ReleaseType.RAW)
-  revision = utils.GetSVNRevision()
+  revision = utils.GetArchiveVersion()
   for revision in [revision, 'latest']:
     destination = (namer.apidocs_directory(revision) + '/' +
         namer.apidocs_zipfilename())
@@ -103,7 +132,7 @@
 
 def UploadApiDocs(dir_name):
   apidocs_namer = bot_utils.GCSNamerApiDocs(CHANNEL)
-  revision = utils.GetSVNRevision()
+  revision = utils.GetArchiveVersion()
   apidocs_destination_gcsdir = apidocs_namer.docs_dirpath(revision)
   apidocs_destination_latestfile = apidocs_namer.docs_latestpath(revision)
 
@@ -120,6 +149,36 @@
   gsutil.upload(dir_name, apidocs_destination_gcsdir, recursive=True,
                 public=True)
 
+def DartArchiveUploadDartdocAPIDocs(api_zip):
+  namer = bot_utils.GCSNamer(CHANNEL, bot_utils.ReleaseType.RAW)
+  revision = utils.GetArchiveVersion()
+  for revision in [revision, 'latest']:
+    destination = (namer.apidocs_directory(revision) + '/' +
+        namer.dartdocs_zipfilename())
+    DartArchiveFile(api_zip, destination, checksum_files=False)
+
+def UploadDartdocApiDocs(dir_name):
+  apidocs_namer = bot_utils.GCSNamerApiDocs(CHANNEL)
+  revision = utils.GetArchiveVersion()
+  dartdocs_destination_gcsdir = apidocs_namer.dartdocs_dirpath(revision)
+
+  # Return early if the documents have already been uploaded.
+  # This can happen if a build was forced, or a commit had no changes in the
+  # dart repository (e.g. DEPS file update).
+  if GsutilExists(dartdocs_destination_gcsdir):
+    print ("Not uploading api docs, since %s is already present."
+           % dartdocs_destination_gcsdir)
+    return
+
+  # Upload everything inside the built apidocs directory.
+  gsutil = bot_utils.GSUtil()
+  gsutil.upload(dir_name, dartdocs_destination_gcsdir, recursive=True,
+                public=True, multithread=True)
+
+def UploadApiLatestFile():
+  apidocs_namer = bot_utils.GCSNamerApiDocs(CHANNEL)
+  revision = utils.GetArchiveVersion()
+  apidocs_destination_latestfile = apidocs_namer.docs_latestpath(revision)
   # Update latest.txt to contain the newest revision.
   with utils.TempDir('latest_file') as temp_dir:
     latest_file = os.path.join(temp_dir, 'latest.txt')
@@ -187,9 +246,9 @@
   return bot.RunProcess(command)
 
 if __name__ == '__main__':
-  if CHANNEL != bot_utils.Channel.BLEEDING_EDGE:
-    # We always clobber the bot, to make sure releases are build from scratch
-    bot.Clobber(force=True)
+  # We always clobber the bot, to make sure releases are build from scratch
+  force = CHANNEL != bot_utils.Channel.BLEEDING_EDGE
+  bot.Clobber(force=force)
 
   CreateUploadSDK()
   if BUILD_OS == 'linux':
diff --git a/tools/bots/dartium_android.py b/tools/bots/dartium_android.py
index 8f740bf..29623e5 100644
--- a/tools/bots/dartium_android.py
+++ b/tools/bots/dartium_android.py
@@ -52,7 +52,7 @@
     # Archive content shell
     local = os.path.join(options.build_products_dir, CS_LOCATION)
 
-    for revision in [utils.GetSVNRevision(), 'latest']:
+    for revision in [utils.GetArchiveVersion(), 'latest']:
       # TODO(whesse): pass in arch and mode from reciepe
       remote = namer.dartium_android_apk_filepath(revision,
                                                   'content_shell-android',
diff --git a/tools/bots/linux_distribution_support.py b/tools/bots/linux_distribution_support.py
index 6717b95..6b8b2e8 100644
--- a/tools/bots/linux_distribution_support.py
+++ b/tools/bots/linux_distribution_support.py
@@ -39,7 +39,7 @@
 def ArchiveArtifacts(tarfile, builddir, channel, linux_system):
   namer = bot_utils.GCSNamer(channel=channel)
   gsutil = bot_utils.GSUtil()
-  revision = utils.GetSVNRevision()
+  revision = utils.GetArchiveVersion()
   # Archive the src tar to the src dir
   remote_tarfile = '/'.join([namer.src_directory(revision),
                              os.path.basename(tarfile)])
diff --git a/tools/bots/pkg.py b/tools/bots/pkg.py
new file mode 100644
index 0000000..1ba85bb
--- /dev/null
+++ b/tools/bots/pkg.py
@@ -0,0 +1,83 @@
+#!/usr/bin/python
+
+# Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+
+"""
+Pkg buildbot steps.
+
+Runs tests for packages that are hosted in the main Dart repo and in
+third_party/pkg_tested.
+"""
+
+import re
+import sys
+
+import bot
+
+PKG_BUILDER = r'pkg-(linux|mac|win)(-(russian))?(-(debug))?'
+
+def PkgConfig(name, is_buildbot):
+  """Returns info for the current buildbot based on the name of the builder.
+
+  Currently, this is just:
+  - mode: "debug", "release"
+  - system: "linux", "mac", or "win"
+  """
+  pkg_pattern = re.match(PKG_BUILDER, name)
+  if not pkg_pattern:
+    return None
+
+  system = pkg_pattern.group(1)
+  locale = pkg_pattern.group(3)
+  mode = pkg_pattern.group(5) or 'release'
+  if system == 'win': system = 'windows'
+
+  return bot.BuildInfo('none', 'vm', mode, system, checked=True,
+                       builder_tag=locale)
+
+def PkgSteps(build_info):
+  with bot.BuildStep('Build package-root'):
+    args = [sys.executable, './tools/build.py', '--mode=' + build_info.mode,
+            'packages']
+    print 'Building package-root: %s' % (' '.join(args))
+    bot.RunProcess(args)
+
+  common_args = ['--write-test-outcome-log']
+  if build_info.builder_tag:
+    common_args.append('--builder-tag=%s' % build_info.builder_tag)
+
+  # There are a number of big/integration tests in pkg, run with bigger timeout
+  common_args.append('--timeout=120')
+  # We have some unreproducible vm crashes on these bots
+  common_args.append('--copy-coredumps')
+
+  # We are seeing issues with pub get calls on the windows bots.
+  # Experiment with not running concurrent calls.
+  if build_info.system == 'windows':
+    common_args.append('-j1')
+  if build_info.mode == 'release':
+    bot.RunTest('pkg ', build_info,
+                common_args + ['pkg', 'docs', 'pkg_tested'],
+                swallow_error=True)
+  else:
+    # Pkg tests currently have a lot of timeouts when run in debug mode.
+    # See issue 18479
+    bot.RunTest('pkg', build_info, common_args + ['pkg', 'docs'],
+                swallow_error=True)
+
+  if build_info.mode == 'release':
+    pkgbuild_build_info = bot.BuildInfo('none', 'vm', build_info.mode,
+                                        build_info.system, checked=False)
+    bot.RunTest('pkgbuild_repo_pkgs', pkgbuild_build_info,
+                common_args + ['--append_logs', '--use-repository-packages',
+                               'pkgbuild'],
+                swallow_error=True)
+
+    public_args = (common_args +
+                   ['--append_logs', '--use-public-packages', 'pkgbuild'])
+    bot.RunTest('pkgbuild_public_pkgs', pkgbuild_build_info, public_args)
+
+if __name__ == '__main__':
+  bot.RunBot(PkgConfig, PkgSteps)
diff --git a/tools/bots/pub.py b/tools/bots/pub.py
index 98ae672..ee3cd1e 100755
--- a/tools/bots/pub.py
+++ b/tools/bots/pub.py
@@ -10,73 +10,66 @@
 Runs tests for pub and the pub packages that are hosted in the main Dart repo.
 """
 
+import os
 import re
+import shutil
 import sys
 
 import bot
+import bot_utils
 
-PUB_BUILDER = r'pub-(linux|mac|win)(-(russian))?(-(debug))?'
+utils = bot_utils.GetUtils()
+
+BUILD_OS = utils.GuessOS()
+
+PUB_BUILDER = r'pub-(linux|mac|win)'
 
 def PubConfig(name, is_buildbot):
   """Returns info for the current buildbot based on the name of the builder.
 
   Currently, this is just:
-  - mode: "debug", "release"
+  - mode: always release, we don't run pub in debug mode
   - system: "linux", "mac", or "win"
+  - checked: always true
   """
   pub_pattern = re.match(PUB_BUILDER, name)
   if not pub_pattern:
     return None
 
   system = pub_pattern.group(1)
-  locale = pub_pattern.group(3)
-  mode = pub_pattern.group(5) or 'release'
+  mode = 'release'
   if system == 'win': system = 'windows'
 
-  return bot.BuildInfo('none', 'vm', mode, system, checked=True,
-                       builder_tag=locale)
+  return bot.BuildInfo('none', 'vm', mode, system, checked=True)
+
+def Run(command):
+  print "Running %s" % ' '.join(command)
+  return bot.RunProcess(command)
 
 def PubSteps(build_info):
-  with bot.BuildStep('Build package-root'):
-    args = [sys.executable, './tools/build.py', '--mode=' + build_info.mode,
-            'packages']
-    print 'Building package-root: %s' % (' '.join(args))
-    bot.RunProcess(args)
+  sdk_bin = os.path.join(
+      bot_utils.DART_DIR,
+      utils.GetBuildSdkBin(BUILD_OS, build_info.mode, build_info.arch))
+  pub_script_name = 'pub.bat' if build_info.system == 'windows' else 'pub'
+  pub_bin = os.path.join(sdk_bin, pub_script_name)
 
-  common_args = ['--write-test-outcome-log']
-  if build_info.builder_tag:
-    common_args.append('--builder-tag=%s' % build_info.builder_tag)
+  pub_copy = os.path.join(utils.GetBuildRoot(BUILD_OS), 'pub_copy')
+  pub_location = os.path.join('third_party', 'pkg', 'pub')
 
-  # There are a number of big/integration tests in pkg, run with bigger timeout
-  common_args.append('--timeout=120')
-  # We have some unreproducible vm crashes on these bots
-  common_args.append('--copy-coredumps')
+  with bot.BuildStep('Make copy of pub for testing'):
+    print 'Removing old copy %s' % pub_copy
+    shutil.rmtree(pub_copy, ignore_errors=True)
+    print 'Copying %s to %s' % (pub_location, pub_copy)
+    shutil.copytree(pub_location, pub_copy)
 
-  if build_info.system == 'windows':
-    common_args.append('-j1')
-  if build_info.mode == 'release':
-    bot.RunTest('pub and pkg ', build_info,
-                common_args + ['pub', 'pkg', 'docs', 'pkg_tested'],
-                swallow_error=True)
-  else:
-    # Pub tests currently have a lot of timeouts when run in debug mode.
-    # See issue 18479
-    bot.RunTest('pub and pkg', build_info, common_args + ['pkg', 'docs'],
-                swallow_error=True)
+  # TODO(nweiz): add logic for testing pub.
+  with bot.BuildStep('Doing the magic ls'):
+    with utils.ChangedWorkingDirectory(pub_copy):
+      Run(['ls', '-l'])
 
-  if build_info.mode == 'release':
-    pkgbuild_build_info = bot.BuildInfo('none', 'vm', build_info.mode,
-                                        build_info.system, checked=False)
-    bot.RunTest('pkgbuild_repo_pkgs', pkgbuild_build_info,
-                common_args + ['--append_logs', '--use-repository-packages',
-                               'pkgbuild'],
-                swallow_error=True)
+  with bot.BuildStep('Running pub'):
+    Run([pub_bin, '--version'])
 
-    # We are seeing issues with pub get calls on the windows bots.
-    # Experiment with not running concurrent calls.
-    public_args = (common_args +
-                   ['--append_logs', '--use-public-packages', 'pkgbuild'])
-    bot.RunTest('pkgbuild_public_pkgs', pkgbuild_build_info, public_args)
 
 if __name__ == '__main__':
   bot.RunBot(PubConfig, PubSteps)
diff --git a/tools/clean_output_directory.py b/tools/clean_output_directory.py
index deee240..f94259b 100755
--- a/tools/clean_output_directory.py
+++ b/tools/clean_output_directory.py
@@ -11,6 +11,7 @@
 
 def Main():
   build_root = utils.GetBuildRoot(utils.GuessOS())
+  print 'Deleting %s' % build_root
   shutil.rmtree(build_root, ignore_errors=True)
   return 0
 
diff --git a/tools/create_sdk.py b/tools/create_sdk.py
index 9ec9371..3a2b541 100755
--- a/tools/create_sdk.py
+++ b/tools/create_sdk.py
@@ -28,9 +28,9 @@
 # ........utils_wrapper.dart.snapshot
 # ....include/
 # ......dart_api.h
-# ......dart_debugger_api.h
 # ......dart_mirrors_api.h
 # ......dart_native_api.h
+# ......dart_tools_api.h
 # ....lib/
 # ......_internal/
 # ......async/
@@ -182,12 +182,12 @@
   os.makedirs(INCLUDE)
   copyfile(join(HOME, 'runtime', 'include', 'dart_api.h'),
            join(INCLUDE, 'dart_api.h'))
-  copyfile(join(HOME, 'runtime', 'include', 'dart_debugger_api.h'),
-           join(INCLUDE, 'dart_debugger_api.h'))
   copyfile(join(HOME, 'runtime', 'include', 'dart_mirrors_api.h'),
            join(INCLUDE, 'dart_mirrors_api.h'))
   copyfile(join(HOME, 'runtime', 'include', 'dart_native_api.h'),
            join(INCLUDE, 'dart_native_api.h'))
+  copyfile(join(HOME, 'runtime', 'include', 'dart_tools_api.h'),
+           join(INCLUDE, 'dart_tools_api.h'))
 
   #
   # Create and populate sdk/lib.
@@ -229,7 +229,7 @@
 
   RESOURCE = join(SDK_tmp, 'lib', '_internal', 'pub', 'asset')
   os.makedirs(os.path.dirname(RESOURCE))
-  copytree(join(HOME, 'third_party', 'pkg_tested', 'pub', 'lib', 'src',
+  copytree(join(HOME, 'third_party', 'pkg', 'pub', 'lib', 'src',
                 'asset'),
            join(RESOURCE),
            ignore=ignore_patterns('.svn'))
@@ -251,7 +251,7 @@
   versionFile.close()
 
   # Write the 'revision' file
-  revision = utils.GetSVNRevision()
+  revision = utils.GetGitRevision()
 
   if revision is not None:
     with open(os.path.join(SDK_tmp, 'revision'), 'w') as f:
diff --git a/tools/create_tarball.py b/tools/create_tarball.py
index 73d8bb8..f51e4bb 100755
--- a/tools/create_tarball.py
+++ b/tools/create_tarball.py
@@ -102,9 +102,9 @@
     f.write(' -- Dart Team <misc@dartlang.org>  %s\n' %
             datetime.datetime.utcnow().strftime('%a, %d %b %Y %X +0000'))
 
-def GenerateSvnRevision(filename, svn_revision):
+def GenerateGitRevision(filename, git_revision):
   with open(filename, 'w') as f:
-    f.write(str(svn_revision))
+    f.write(str(git_revision))
 
 
 def CreateTarball(tarfilename):
@@ -138,11 +138,11 @@
       GenerateChangeLog(change_log, version)
       tar.add(change_log, arcname='%s/debian/changelog' % versiondir)
 
-      # For bleeding_edge add the SVN_REVISION file.
+      # For bleeding_edge add the GIT_REVISION file.
       if utils.GetChannel() == 'be':
-        svn_revision = join(temp_dir, 'SVN_REVISION')
-        GenerateSvnRevision(svn_revision, utils.GetSVNRevision())
-        tar.add(svn_revision, arcname='%s/dart/tools/SVN_REVISION' % versiondir)
+        git_revision = join(temp_dir, 'GIT_REVISION')
+        GenerateGitRevision(git_revision, utils.GetGitRevision())
+        tar.add(git_revision, arcname='%s/dart/tools/GIT_REVISION' % versiondir)
 
 def Main():
   if HOST_OS != 'linux':
diff --git a/tools/dart2js/angular2_testing_deps/CURRENT_ANGULAR_DEPS b/tools/dart2js/angular2_testing_deps/CURRENT_ANGULAR_DEPS
index c6d0509..8886d26 100644
--- a/tools/dart2js/angular2_testing_deps/CURRENT_ANGULAR_DEPS
+++ b/tools/dart2js/angular2_testing_deps/CURRENT_ANGULAR_DEPS
@@ -1 +1 @@
-390cfb793b2cd351d2db609d088a8fdda3df4f24
+0c282e826a3e35e6b6aa2dd430f899d159eaf458
diff --git a/tools/dart2js/class_generator/class_generator.dart b/tools/dart2js/class_generator/class_generator.dart
new file mode 100644
index 0000000..59bf22e
--- /dev/null
+++ b/tools/dart2js/class_generator/class_generator.dart
@@ -0,0 +1,785 @@
+// 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.
+
+// Script that generates different approaches to initialize classes in
+// JavaScript.
+// Also benchmarks the approaches.
+
+import 'dart:io';
+import 'dart:async';
+
+class Config {
+  /// Number of classes that should be generated.
+  final int nbClasses;
+
+  /// Number of methods per class.
+  final int nbMethodsPerClass;
+
+  /// Should the JavaScript classes share a common super class?
+  ///
+  /// Currently unused for Dart, since it always has a common super class
+  /// anyways.
+  // TODO(floitsch): also create a common super class in Dart?
+  final bool shareCommonSuperclass;
+
+  /// Assign unique names to the methods or let them share the same one?
+  ///
+  /// Independent of this flag, the `callAll` and `instantiatePrevious` method
+  /// names are the same for all classes.
+  final bool sameMethodNames;
+
+  /// Adds a `print` statement to the method.
+  final bool shouldPrintInMethod;
+
+  /// Adds while loops to the method body.
+  ///
+  /// This has the effect that dart2js won't be able to inline the method and
+  /// controls the size of the method bodies.
+  final int nbWhileLoopsInBody;
+
+  /// Should the JavaScript output be wrapped into an anonymous function?
+  ///
+  /// When enabled wraps the program with the following pattern:
+  /// `(function() { <program> })()`.
+  final bool shouldWrapProgram;
+
+  /// Adds a `callAll` method that invokes all other methods of the class.
+  ///
+  /// This is necessary for dart2js to avoid tree-shaking.
+  /// Should probably always be on (except for presentations to demonstrate that
+  /// dart2js knows how to tree-shake).
+  ///
+  /// This method counts towards the [nbMethodsPerClass] limit.
+  final bool shouldEmitCallAllMethods;
+
+  /// Adds an `instantiatePrevious` method that instantiates the previous class.
+  ///
+  /// A "previous" class is the class that was generated before the current
+  /// class. The first class returns `null`.
+  final bool shouldEmitInstantiatePreviousMethod;
+
+  /// Makes sure that the dart2js tree-shaker doesn't remove classes.
+  ///
+  /// When set to `-1`, all classes are kept alive.
+  final int fakeInstantiateClass;
+
+  /// Defines the percent of classes that are dynamically instantiated.
+  final int instantiateClassesPercent;
+
+  Config({this.nbClasses, this.nbMethodsPerClass,
+          this.shareCommonSuperclass, this.sameMethodNames,
+          this.shouldPrintInMethod, this.nbWhileLoopsInBody,
+          this.shouldWrapProgram, this.shouldEmitCallAllMethods,
+          this.shouldEmitInstantiatePreviousMethod,
+          this.fakeInstantiateClass, this.instantiateClassesPercent});
+}
+
+String get d8Path {
+  Uri scriptPath = Platform.script;
+  String d8Executable = "../../../third_party/d8/";
+  if (Platform.isWindows) {
+    d8Executable += "windows/d8.exe";
+  } else if (Platform.isMacOS) {
+    d8Executable += "macos/d8";
+  } else if (Platform.isLinux) {
+    d8Executable += "linux/d8";
+  } else {
+    return null;
+  }
+  return scriptPath.resolve(d8Executable).path;
+}
+
+String get jsShellPath {
+  Uri scriptPath = Platform.script;
+  if (!Platform.isLinux) {
+    return null;
+  }
+  return scriptPath.resolve("../../../tools/testing/bin/jsshell").path;
+}
+
+String get dart2jsPath {
+  Uri scriptPath = Platform.script;
+  return scriptPath.resolve("../../../sdk/bin/dart2js").path;
+}
+
+abstract class ClassGenerator {
+  final StringBuffer buffer = new StringBuffer();
+  // By convention all methods should take one argument with this name.
+  final String argumentName = "x";
+  final String callOtherMethodsName = "callAll";
+  final String instantiatePreviousMethodName = "instantiatePrevious";
+
+  final Config config;
+
+  ClassGenerator(this.config);
+
+  int get nbClasses => config.nbClasses;
+  int get nbMethodsPerClass => config.nbMethodsPerClass;
+  bool get shouldPrintInMethod => config.shouldPrintInMethod;
+  bool get sameMethodNames => config.sameMethodNames;
+  int get nbWhileLoopsInMethod => config.nbWhileLoopsInBody;
+  bool get shareCommonSuperclass => config.shareCommonSuperclass;
+  bool get shouldEmitCallAllMethods => config.shouldEmitCallAllMethods;
+  bool get shouldEmitInstantiatePreviousMethod =>
+      config.shouldEmitInstantiatePreviousMethod;
+  int get fakeInstantiateClass => config.fakeInstantiateClass;
+  int get instantiateClassesPercent => config.instantiateClassesPercent;
+
+  Future measure(String filePrefix) async {
+    String fileName = await generateRawJs(filePrefix);
+    if (fileName == null) return;
+    Directory dir = Directory.systemTemp.createTempSync('classes');
+    try {
+      File measuring = new File("${dir.path}/measuring.js");
+      IOSink sink = measuring.openWrite();
+      sink.writeln("var start = new Date();");
+      await sink.addStream(new File(fileName).openRead());
+      sink.writeln("print(new Date() - start)");
+      String command;
+      List<String> args;
+      bool runJsShell = false;
+      if (runJsShell) {
+        command = jsShellPath;
+        print("Running $command");
+        args = [measuring.path];
+      } else {
+        command = d8Path;
+        print("Running $command");
+        args = ["--harmony-sloppy", measuring.path];
+      }
+      print("Running: $fileName");
+      int nbRuns = 10;
+      int sum = 0;
+      int sumSw = 0;
+      Stopwatch watch = new Stopwatch();
+      for (int i = 0; i < nbRuns; i++) {
+        watch.reset();
+        watch.start();
+        ProcessResult result = await Process.run(command, args);
+        if (result.exitCode != 0) {
+          print("run failed");
+          print(result.stdout);
+          print(result.stderr);
+        }
+        int elapsed = watch.elapsedMilliseconds;
+        print("  output: ${result.stdout.trim()} ($elapsed)");
+        sum += int.parse(result.stdout, onError: (str) => 0);
+        sumSw += elapsed;
+      }
+      int mean = sum == 0 ? 0 : sum ~/ nbRuns;
+      int meanSw = sumSw == 0 ? 0 : sumSw ~/ nbRuns;
+      print("  mean: $mean ($meanSw)");
+    } finally {
+      dir.deleteSync(recursive: true);
+    }
+  }
+
+  Future<String> generateRawJs(String filePrefix);
+
+  String buildFileName(String filePrefix, String extension) {
+    // TODO(floitsch): store other config info in the file name.
+    return "$filePrefix.$nbClasses.$nbMethodsPerClass."
+           "$instantiateClassesPercent.$description.$extension";
+  }
+
+  String writeFile(String filePrefix) {
+    buffer.clear();
+    emitClasses();  // Output is stored in `buffer`.
+
+    String fileName = buildFileName(filePrefix, fileExtension);
+    new File(fileName).writeAsStringSync(buffer.toString());
+    print("wrote: $fileName");
+    return fileName;
+  }
+
+  void writeln(x) => buffer.writeln(x);
+
+  String classIdToName(int id) {
+    if (id < 0) id = nbClasses + id;
+    return "Class$id";
+  }
+
+  /// [id] is per class.
+  String methodIdToName(int id, int classId) {
+    if (sameMethodNames) return "method$id";
+    return "method${classId}_$id";
+  }
+
+  // Must work for Dart and JS.
+  void emitMethodBody(int methodId, int classId) {
+    writeln("{");
+    if (shouldPrintInMethod) {
+      writeln("print('class: $classId, method: $methodId');");
+    }
+    if (nbWhileLoopsInMethod > 0) {
+      writeln("var sum = 0;");
+      for (int i = 0; i < nbWhileLoopsInMethod; i++) {
+        writeln("for (var i = 0; i < $argumentName; i++) {");
+        writeln("  sum++;");
+        writeln("}");
+      }
+      writeln("return sum;");
+    }
+    writeln("}");
+  }
+
+  // Must work for Dart and JS.
+  void emitCallOtherMethodsBody(List<int> methodIds, int classId) {
+    writeln("{");
+    writeln("var sum = 0;");
+    for (int methodId in methodIds) {
+      String methodName = methodIdToName(methodId, classId);
+      writeln("sum += this.$methodName($argumentName);");
+    }
+    writeln("return sum;");
+    writeln("}");
+  }
+
+  // Must work for Dart and JS.
+  void emitInstantiatePrevious(int classId) {
+    writeln("{");
+    if (classId == 0) {
+      writeln("return null;");
+    } else {
+      String previousClass = classIdToName(classId - 1);
+      writeln("return new $previousClass();");
+    }
+    writeln("}");
+  }
+
+  /// Should write the class using [writeln].
+  void emitClasses();
+
+  String get description;
+  String get fileExtension;
+}
+
+abstract class JavaScriptClassGenerator extends ClassGenerator {
+  bool get wrapProgram => config.shouldWrapProgram;
+  final String methodsObjectName = "methods";
+
+  JavaScriptClassGenerator(Config config) : super(config);
+
+  Future<String> generateRawJs(String filePrefix) =>
+      new Future.value(writeFile(filePrefix));
+
+  void emitUtilityFunctions();
+  void emitClass(int classId, int superclassId);
+
+  void emitClasses() {
+    if (wrapProgram) writeln("(function() {");
+    writeln("var $methodsObjectName;");
+    emitUtilityFunctions();
+    for (int i = 0; i < nbClasses; i++) {
+      int superclassId = shareCommonSuperclass && i != 0 ? 0 : null;
+      emitClass(i, superclassId);
+    }
+
+    if (fakeInstantiateClass != null) {
+      String className = classIdToName(fakeInstantiateClass);
+      writeln("""
+        if (new Date() == 42) {
+          var o = new $className();
+          do {
+            o.$callOtherMethodsName(99);
+            o = o.$instantiatePreviousMethodName();
+          } while(o != null);
+        }""");
+    }
+    if (instantiateClassesPercent != null) {
+      int targetClassId = ((nbClasses - 1) * instantiateClassesPercent) ~/ 100;
+      String targetClassName = classIdToName(targetClassId);
+      writeln("""
+        var o = new $targetClassName();
+        do {
+          o = o.$instantiatePreviousMethodName();
+        } while(o != null);
+      """);
+    }
+    if (wrapProgram) writeln("})();");
+  }
+
+  String get fileExtension => "js";
+}
+
+enum PrototypeApproach {
+  tmpFunction,
+  internalProto,
+  objectCreate
+}
+class PlainJavaScriptClassGenerator extends JavaScriptClassGenerator {
+  final PrototypeApproach prototypeApproach;
+  final bool shouldInlineInherit;
+  final bool useMethodsObject;
+
+  PlainJavaScriptClassGenerator(Config config,
+                                {this.prototypeApproach,
+                                 this.shouldInlineInherit,
+                                 this.useMethodsObject})
+      : super(config) {
+    if (prototypeApproach == null) {
+      throw "Must provide prototype approach";
+    }
+    if (shouldInlineInherit == null) {
+      throw "Must provide inlining approach";
+    }
+    if (useMethodsObject == null) {
+      throw "Must provide object-proto approach";
+    }
+    if (shouldInlineInherit &&
+        prototypeApproach == PrototypeApproach.tmpFunction) {
+      throw "Can't inline tmp-function approach";
+    }
+  }
+
+  void emitInherit(cls, superclassId) {
+    if (superclassId == null && !useMethodsObject) return;
+    String sup = (superclassId == null) ? "null" : classIdToName(superclassId);
+    if (!shouldInlineInherit) {
+      if (useMethodsObject) {
+        writeln("inherit($cls, $sup, $methodsObjectName);");
+      } else {
+        writeln("inherit($cls, $sup);");
+      }
+      return;
+    }
+    switch (prototypeApproach) {
+      case PrototypeApproach.tmpFunction:
+        throw "Should not happen";
+        break;
+      case PrototypeApproach.internalProto:
+        if (useMethodsObject) {
+          writeln("$cls.prototype = $methodsObjectName;");
+        }
+        if (superclassId != null) {
+          writeln("$cls.prototype.__proto__ = $sup.prototype;");
+        }
+        break;
+      case PrototypeApproach.objectCreate:
+        if (useMethodsObject) {
+          if (superclassId == null) {
+            writeln("$cls.prototype = $methodsObjectName;");
+          } else {
+            writeln("$cls.prototype = Object.create($sup.prototype);");
+            writeln("copyProperties($methodsObjectName, $cls.prototype);");
+          }
+        } else {
+          writeln("$cls.prototype = Object.create($sup.prototype);");
+        }
+        break;
+    }
+  }
+
+  void emitUtilityFunctions() {
+    switch (prototypeApproach) {
+      case PrototypeApproach.internalProto:
+        if (useMethodsObject) {
+          writeln('''
+            function inherit(cls, sup, methods) {
+              cls.prototype = methods;
+              if (sup != null) {
+                cls.prototype.__proto__ = sup.prototype;
+              }
+            }
+            ''');
+
+        } else {
+          writeln('''
+            function inherit(cls, sup) {
+              cls.prototype.__proto__ = sup.prototype;
+            }
+            ''');
+        }
+        break;
+      case PrototypeApproach.tmpFunction:
+        if (useMethodsObject) {
+          writeln('''
+            function inherit(cls, sup, methods) {
+              if (sup != null) {
+                function tmp() {}
+                tmp.prototype = sup.prototype;
+                var proto = new tmp();
+                proto.constructor = cls;
+                cls.prototype = proto;
+              }
+              copyProperties(methods, cls.prototype);
+            }''');
+        } else {
+          writeln('''
+            function inherit(cls, sup) {
+              function tmp() {}
+              tmp.prototype = sup.prototype;
+              var proto = new tmp();
+              proto.constructor = cls;
+              cls.prototype = proto;
+            }''');
+        }
+        break;
+      case PrototypeApproach.objectCreate:
+        if (useMethodsObject) {
+          writeln('''
+            function inherit(cls, sup, methods) {
+              if (sup == null) {
+                cls.prototype = methods;
+              } else {
+                cls.prototype = Object.create(sup.prototype);
+                copyProperties(methods, cls.prototype);
+              }
+            }
+            ''');
+        } else {
+          writeln('''
+            function inherit(cls, sup) {
+              cls.prototype = Object.create(sup.prototype);
+            }
+            ''');
+        }
+        break;
+    }
+    writeln("""
+    function copyProperties(from, to) {
+      var props = Object.keys(from);
+      for (var i = 0; i < props.length; i++) {
+        var p = props[i];
+        to[p] = from[p];
+      }
+    }""");
+  }
+
+  void emitMethod(int classId, String methodName, Function bodyEmitter,
+                  {bool emitArgument: true}) {
+    String argumentString = emitArgument ? argumentName : "";
+    if (useMethodsObject) {
+      writeln("$methodName: function($argumentString)");
+      bodyEmitter();
+      writeln(",");
+    } else {
+      String className = classIdToName(classId);
+      String proto = "$className.prototype";
+      writeln("$proto.$methodName = function($argumentString)");
+      bodyEmitter();
+    }
+  }
+
+  /// Returns the methods object, if we use an object.
+  void emitMethods(int classId) {
+    List<int> methodIds = [];
+    int nbGenericMethods = nbMethodsPerClass;
+    if (useMethodsObject) {
+      writeln("$methodsObjectName = {");
+    }
+    if (shouldEmitCallAllMethods) nbGenericMethods--;
+    for (int j = 0; j < nbGenericMethods; j++) {
+      String methodName = methodIdToName(j, classId);
+      emitMethod(classId, methodName, () => emitMethodBody(j, classId));
+      methodIds.add(j);
+    }
+    if (shouldEmitCallAllMethods) {
+      emitMethod(classId,
+      callOtherMethodsName,
+          () => emitCallOtherMethodsBody(methodIds, classId));
+    }
+    if (shouldEmitInstantiatePreviousMethod) {
+      emitMethod(classId,
+      instantiatePreviousMethodName,
+          () => emitInstantiatePrevious(classId),
+      emitArgument: false);
+    }
+    if (useMethodsObject) {
+      writeln("};");
+    }
+  }
+
+  void emitClass(int classId, int superclassId) {
+    String className = classIdToName(classId);
+    writeln("function $className() {}");
+    switch (prototypeApproach) {
+      case PrototypeApproach.objectCreate:
+        if (useMethodsObject) {
+          emitMethods(classId);
+          emitInherit(className, superclassId);
+        } else {
+          emitInherit(className, superclassId);
+          emitMethods(classId);
+        }
+        break;
+      case PrototypeApproach.tmpFunction:
+        if (useMethodsObject) {
+          emitMethods(classId);
+          emitInherit(className, superclassId);
+        } else {
+          emitInherit(className, superclassId);
+          emitMethods(classId);
+        }
+        break;
+      case PrototypeApproach.internalProto:
+        emitMethods(classId);
+        emitInherit(className, superclassId);
+        break;
+    }
+  }
+
+  String get description {
+    String protoApproachDescription;
+    switch (prototypeApproach) {
+      case PrototypeApproach.objectCreate:
+        protoApproachDescription = "objectCreate";
+        break;
+      case PrototypeApproach.tmpFunction:
+        protoApproachDescription = "tmpFunction";
+        break;
+      case PrototypeApproach.internalProto:
+        protoApproachDescription = "internalProto";
+        break;
+    }
+    String inline = shouldInlineInherit ? "inl" : "noInl";
+    String objectProto = useMethodsObject ? "obj" : "noObj";
+    return "plain_${protoApproachDescription}_${inline}_$objectProto";
+  }
+}
+
+class Es6ClassGenerator extends JavaScriptClassGenerator {
+  Es6ClassGenerator(Config config) : super(config);
+
+  void emitUtilityFunctions() {}
+
+  void emitClass(int classId, int superclassId) {
+    String className = classIdToName(classId);
+    if (superclassId != null) {
+      String superclassName = classIdToName(superclassId);
+      buffer.writeln("class $className extends $superclassName {");
+    } else {
+      buffer.writeln("class $className {");
+    }
+    List<int> methodIds = [];
+    int nbGenericMethods = nbMethodsPerClass;
+    if (shouldEmitCallAllMethods) nbGenericMethods--;
+    for (int j = 0; j < nbGenericMethods; j++) {
+      String methodName = methodIdToName(j, classId);
+      writeln("$methodName($argumentName) ");
+      emitMethodBody(j, classId);
+      methodIds.add(j);
+    }
+    if (shouldEmitCallAllMethods) {
+      writeln("$callOtherMethodsName($argumentName)");
+      emitCallOtherMethodsBody(methodIds, classId);
+    }
+    if (shouldEmitInstantiatePreviousMethod) {
+      writeln("$instantiatePreviousMethodName()");
+      emitInstantiatePrevious(classId);
+    }
+    writeln("}");
+  }
+
+  String get description => "es6";
+}
+
+class DartClassGenerator extends ClassGenerator {
+  final bool shouldUseNewEmitter;
+
+  DartClassGenerator(Config config, {this.shouldUseNewEmitter: false})
+      : super(config);
+
+  void emitClasses() {
+    // TODO(flo): instantiateAndCallPrevious
+    for (int i = 0; i < nbClasses; i++) {
+      String className = classIdToName(i);
+      writeln("class $className {");
+      List<int> methodIds = [];
+      int nbGenericMethods = nbMethodsPerClass;
+      if (shouldEmitCallAllMethods) nbGenericMethods--;
+      for (int j = 0; j < nbGenericMethods; j++) {
+        String methodName = methodIdToName(j, i);
+        writeln("$methodName($argumentName)");
+        emitMethodBody(j, i);
+        methodIds.add(j);
+      }
+      if (shouldEmitCallAllMethods) {
+        writeln("$callOtherMethodsName($argumentName)");
+        emitCallOtherMethodsBody(methodIds, i);
+      }
+      if (shouldEmitInstantiatePreviousMethod) {
+        writeln("$instantiatePreviousMethodName()");
+        emitInstantiatePrevious(i);
+      }
+      writeln("}");
+    }
+    writeln("main() {");
+    if (fakeInstantiateClass != null) {
+      String className = classIdToName(fakeInstantiateClass);
+      writeln("""
+        if (new DateTime.now().millisecondsSinceEpoch == 42) {
+          var o = new $className();
+          do {
+            o.$callOtherMethodsName(99);
+            o = o.$instantiatePreviousMethodName();
+          } while(o != null);
+        }""");
+    }
+    if (instantiateClassesPercent != null) {
+      int targetClassId = ((nbClasses - 1) * instantiateClassesPercent) ~/ 100;
+      String targetClassName = classIdToName(targetClassId);
+      writeln("""
+        var o = new $targetClassName();
+        do {
+          o = o.$instantiatePreviousMethodName();
+        } while(o != null);
+      """);
+    }
+    writeln("}");
+  }
+
+  Future<String> generateRawJs(String filePrefix) async {
+    String dartFile = writeFile(filePrefix);
+    String outFile = buildFileName(filePrefix, "js");
+    Map<String, String> env = {};
+    if (shouldUseNewEmitter) {
+      env["DART_VM_OPTIONS"] = '-Ddart2js.use.new.emitter=true';
+    }
+    print("compiling");
+    print("dart2jsPath: $dart2jsPath");
+    ProcessResult result =
+        await Process.run(dart2jsPath, [dartFile, "--out=$outFile"],
+                          environment: env);
+    if (result.exitCode != 0) {
+      print("compilation failed");
+      print(result.stdout);
+      print(result.stderr);
+      return null;
+    }
+    print("compilation done");
+    return outFile;
+  }
+
+  Future measureDart(String filePrefix, { bool useSnapshot: false }) async {
+    String dartFile = writeFile(filePrefix);
+    String command = Platform.executable;
+    Stopwatch watch = new Stopwatch();
+    Directory dir = Directory.systemTemp.createTempSync('snapshot');
+    try {
+      String measuring = dartFile;
+      if (useSnapshot) {
+        print("creating snapshot");
+        measuring = new File("${dir.path}/measuring.snapshot").path;
+        ProcessResult result =
+        await Process.run(command, ["--snapshot=$measuring", dartFile]);
+        if (result.exitCode != 0) {
+          print("snapshot creation failed");
+          print(result.stdout);
+          print(result.stderr);
+          return;
+        }
+      }
+      List<String> args = [measuring];
+      print("Running: $command ${args.join(' ')}");
+      int nbRuns = 10;
+      int sum = 0;
+      for (int i = 0; i < nbRuns; i++) {
+        watch.reset();
+        watch.start();
+        ProcessResult result = await Process.run(command, args);
+        int elapsedMilliseconds = watch.elapsedMilliseconds;
+        if (result.exitCode != 0) {
+          print("run failed");
+          print(result.stdout);
+          print(result.stderr);
+          return;
+        }
+        print("  measured time (including VM startup): $elapsedMilliseconds");
+        sum += elapsedMilliseconds;
+      }
+      if (sum != 0) {
+        print("  mean: ${sum ~/ nbRuns}");
+      }
+    } finally {
+      dir.deleteSync(recursive: true);
+    }
+  }
+
+  String get fileExtension => "dart";
+  String get description {
+    if (shouldUseNewEmitter) return "dartNew";
+    return "dart";
+  }
+}
+
+main(List<String> arguments) async {
+  String filePrefix = arguments.length > 0
+      ? arguments.first
+      : Directory.systemTemp.uri.resolve("classes").path;
+
+  Config config = new Config(
+      nbClasses: 2000,
+      nbMethodsPerClass: 20,
+      fakeInstantiateClass: -1,
+      instantiateClassesPercent: 20,
+      shareCommonSuperclass: true,
+      sameMethodNames: true,
+      shouldPrintInMethod: true,
+      nbWhileLoopsInBody: 1,
+      shouldWrapProgram: true,
+      shouldEmitCallAllMethods: true,
+      shouldEmitInstantiatePreviousMethod: true
+  );
+
+  var plain = new PlainJavaScriptClassGenerator(config,
+      prototypeApproach: PrototypeApproach.tmpFunction,
+      useMethodsObject: false,
+      shouldInlineInherit: false);
+  var plainProto = new PlainJavaScriptClassGenerator(config,
+      prototypeApproach: PrototypeApproach.internalProto,
+      useMethodsObject: false,
+      shouldInlineInherit: false);
+  var plainObjectCreate = new PlainJavaScriptClassGenerator(config,
+      prototypeApproach: PrototypeApproach.objectCreate,
+      useMethodsObject: false,
+      shouldInlineInherit: false);
+  var plainProtoInline = new PlainJavaScriptClassGenerator(config,
+      prototypeApproach: PrototypeApproach.internalProto,
+      useMethodsObject: false,
+      shouldInlineInherit: true);
+  var plainObjectCreateInline = new PlainJavaScriptClassGenerator(config,
+      prototypeApproach: PrototypeApproach.objectCreate,
+      useMethodsObject: false,
+      shouldInlineInherit: true);
+  var plainObj = new PlainJavaScriptClassGenerator(config,
+      prototypeApproach: PrototypeApproach.tmpFunction,
+      useMethodsObject: true,
+      shouldInlineInherit: false);
+  var plainProtoObj = new PlainJavaScriptClassGenerator(config,
+      prototypeApproach: PrototypeApproach.internalProto,
+      useMethodsObject: true,
+      shouldInlineInherit: false);
+  var plainObjectCreateObj = new PlainJavaScriptClassGenerator(config,
+      prototypeApproach: PrototypeApproach.objectCreate,
+      useMethodsObject: true,
+      shouldInlineInherit: false);
+  var plainProtoInlineObj = new PlainJavaScriptClassGenerator(config,
+      prototypeApproach: PrototypeApproach.internalProto,
+      useMethodsObject: true,
+      shouldInlineInherit: true);
+  var plainObjectCreateInlineObj = new PlainJavaScriptClassGenerator(config,
+      prototypeApproach: PrototypeApproach.objectCreate,
+      useMethodsObject: true,
+      shouldInlineInherit: true);
+  var es6 = new Es6ClassGenerator(config);
+  var dart = new DartClassGenerator(config);
+  var dartNew = new DartClassGenerator(config, shouldUseNewEmitter: true);
+
+  await plain.measure(filePrefix);
+  await plainProto.measure(filePrefix);
+  await plainObjectCreate.measure(filePrefix);
+  await plainProtoInline.measure(filePrefix);
+  await plainObjectCreateInline.measure(filePrefix);
+  await plainObj.measure(filePrefix);
+  await plainProtoObj.measure(filePrefix);
+  await plainObjectCreateObj.measure(filePrefix);
+  await plainProtoInlineObj.measure(filePrefix);
+  await plainObjectCreateInlineObj.measure(filePrefix);
+  await es6.measure(filePrefix);
+  await dartNew.measure(filePrefix);
+  await dart.measure(filePrefix);
+  await dart.measureDart(filePrefix);
+  await dart.measureDart(filePrefix, useSnapshot: true);
+}
diff --git a/tools/dartium/buildbot_annotated_steps.py b/tools/dartium/buildbot_annotated_steps.py
index 26c993c..a4d7fc3 100755
--- a/tools/dartium/buildbot_annotated_steps.py
+++ b/tools/dartium/buildbot_annotated_steps.py
@@ -79,7 +79,7 @@
   with utils.ChangedWorkingDirectory(DART_PATH):
     dart_tools_utils = imp.load_source('dart_tools_utils',
                                        os.path.join('tools', 'utils.py'))
-    dart_revision = dart_tools_utils.GetSVNRevision()
+    dart_revision = dart_tools_utils.GetArchiveVersion()
 
   version = '%s.0' % dart_revision
   info = upload_steps.BuildInfo(dart_revision, version)
diff --git a/tools/dartium/deploy_aar.py b/tools/dartium/deploy_aar.py
deleted file mode 100755
index ac8205b..0000000
--- a/tools/dartium/deploy_aar.py
+++ /dev/null
@@ -1,142 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (c) 2014 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import glob
-import optparse
-import os.path
-import re
-import subprocess
-import sys
-import utils
-
-# FIXME: integrate this helper script into the build instead of hardcoding
-# these paths.
-RESOURCE_AAR_PATTERN = 'content_shell_apk/resource_aar/*.aar'
-CONTENT_SHELL_APK_AAR = 'content_shell_apk/content_shell_apk.aar'
-
-SRC_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)),
-                        "..", "..", "..")
-
-DART_DIR = os.path.join(SRC_PATH, 'dart')
-CHROME_VERSION_PATH = os.path.join(SRC_PATH, 'chrome', 'VERSION')
-
-def main():
-  parser = optparse.OptionParser()
-  parser.add_option('--mode', dest='mode',
-                    action='store', type='string',
-                    help='Build mode (Debug or Release)')
-  parser.add_option('--repo', action='store', type='string',
-                    help='Local Maven repository (defaults to ~/.m2)')
-  (options, args) = parser.parse_args()
-  mode = options.mode
-  version = GetVersion()
-  if not (mode in ['debug', 'release']):
-    raise Exception('Invalid build mode')
-
-  mode = 'Debug' if mode == 'debug' else 'Release'
-
-  build_root = os.path.join('out', mode)
-
-  aars = glob.glob(os.path.join(build_root, RESOURCE_AAR_PATTERN))
-  aars.append(os.path.join(build_root, CONTENT_SHELL_APK_AAR))
-
-  flags = [
-    '-DgroupId=org.dartlang',
-    '-Dversion=%s' % version,
-    '-Dpackaging=aar'
-  ]
-  if options.repo:
-    flags.append('-DlocalRepositoryPath=%s' % options.repo)
-
-  for aar_file in aars:
-    artifact_id = os.path.splitext(os.path.basename(aar_file))[0]
-    cmd = [
-      'mvn',
-      'install:install-file',
-      '-Dfile=%s' % aar_file,
-      '-DartifactId=%s' % artifact_id,
-    ]
-    cmd.extend(flags)
-    utils.runCommand(cmd)
-
-def GetVersion():
-  version = GetChromeVersion()
-  return '%d.%d.%d-%05d-%06d' % (
-      version[0],
-      version[1],
-      version[2],
-      version[3],
-      GetDartSVNRevision())
-
-def GetChromeVersion():
-  version = []
-  for line in file(CHROME_VERSION_PATH).readlines():
-    version.append(int(line.strip().split('=')[1]))
-
-  return version
-
-def GetDartSVNRevision():
-  # When building from tarball use tools/SVN_REVISION
-  svn_revision_file = os.path.join(DART_DIR, 'tools', 'SVN_REVISION')
-  try:
-    with open(svn_revision_file) as fd:
-      return int(fd.read())
-  except:
-    pass
-
-  custom_env = dict(os.environ)
-  custom_env['LC_MESSAGES'] = 'en_GB'
-  p = subprocess.Popen(['svn', 'info'], stdout = subprocess.PIPE,
-                       stderr = subprocess.STDOUT, shell = IsWindows(),
-                       env = custom_env,
-                       cwd = DART_DIR)
-  output, _ = p.communicate()
-  revision = ParseSvnInfoOutput(output)
-  if revision:
-    return int(revision)
-
-  # Check for revision using git (Note: we can't use git-svn because in a
-  # pure-git checkout, "git-svn anyCommand" just hangs!). We look an arbitrary
-  # number of commits backwards (100) to get past any local commits.
-  p = subprocess.Popen(['git', 'log', '-100'], stdout = subprocess.PIPE,
-      stderr = subprocess.STDOUT, shell=IsWindows(), cwd = DART_DIR)
-  output, _ = p.communicate()
-  revision = ParseGitInfoOutput(output)
-  if revision:
-    return int(revision)
-
-  # In the rare off-chance that git log -100 doesn't have a svn repo number,
-  # attempt to use "git svn info."
-  p = subprocess.Popen(['git', 'svn', 'info'], stdout = subprocess.PIPE,
-      stderr = subprocess.STDOUT, shell=IsWindows(), cwd = DART_DIR)
-  output, _ = p.communicate()
-  revision = ParseSvnInfoOutput(output)
-  if revision:
-    return int(revision)
-
-  # Only fail on the buildbot in case of a SVN client version mismatch.
-  user = GetUserName()
-  return '0'
-
-def ParseGitInfoOutput(output):
-  """Given a git log, determine the latest corresponding svn revision."""
-  for line in output.split('\n'):
-    tokens = line.split()
-    if len(tokens) > 0 and tokens[0] == 'git-svn-id:':
-      return tokens[1].split('@')[1]
-  return None
-
-def ParseSvnInfoOutput(output):
-  revision_match = re.search('Last Changed Rev: (\d+)', output)
-  if revision_match:
-    return revision_match.group(1)
-  return None
-
-def IsWindows():
-  return (sys.platform=='win32')
-
-if __name__ == '__main__':
-  main()
diff --git a/tools/deps/dartium.deps/DEPS b/tools/deps/dartium.deps/DEPS
index f618ff8..191a94c 100644
--- a/tools/deps/dartium.deps/DEPS
+++ b/tools/deps/dartium.deps/DEPS
@@ -13,14 +13,16 @@
   "dartium_chromium_commit": "62a7524d4f71c9e0858d24b0aa1bbff3a2d09bff",
   "chromium_base_revision": "297060",
   "dartium_webkit_branch": "/blink/branches/dart/dartium",
-  "dartium_webkit_revision": "196634",
+  "dartium_webkit_revision": "197293",
 
   "args_tag": "@0.13.0",
   "barback_rev" : "@29ee90dbcf77cfd64632fa2797a4c8a4f29a4b51",
   "charcode_tag": "@1.1.0",
   "collection_rev": "@1da9a07f32efa2ba0c391b289e2037391e31da0e",
   "crypto_rev" : "@2df57a1e26dd88e8d0614207d4b062c73209917d",
+  "csslib_tag" : "@0.12.0",
   "glob_rev": "@704cf75e4f26b417505c5c611bdaacd8808467dd",
+  "html_tag" : "@0.12.1+1",
   "http_rev" : "@9b93e1542c753090c50b46ef1592d44bc858bfe7",
   "http_multi_server_tag" : "@1.3.2",
   "http_parser_rev" : "@8b179e36aba985208e4c5fb15cfddd386b6370a4",
@@ -32,11 +34,11 @@
   "metatest_rev": "@e5aa8e4e19fc4188ac2f6d38368a47d8f07c3df1",
   "oauth2_rev": "@1bff41f4d54505c36f2d1a001b83b8b745c452f5",
   "observatory_pub_packages_rev": "@45565",
-  "package_config_tag": "@0.0.3+1",
+  "package_config_tag": "@0.1.1",
   "path_rev": "@b657c0854d1cf41c014986fa9d2321f1173df805",
   "plugin_tag": "@0.1.0",
   "pool_rev": "@22e12aeb16ad0b626900dbe79e4a25391ddfb28c",
-  "pub_rev": "@6f2a1b90b8210a85a38aab1af479c047681c29e6",
+  "pub_rev": "@9d707158fedc86fc2b02f62cdfe804902b098d9d",
   "pub_semver_tag": "@1.2.0",
   "shelf_rev": "@1e87b79b21ac5e6fa2f93576d6c06eaa65285ef4",
   "shelf_web_socket_rev": "@ff170cec2c0e4e5722cdf47c557be63b5035a602",
@@ -45,6 +47,7 @@
   "string_scanner_rev": "@3e7617d6f74ba382e9b6130b1cc12091d89a9bc5",
   "test_tag": "@0.12.1",
   "unittest_tag": "@0.11.6",
+  "utf_rev": "@1f55027068759e2d52f2c12de6a57cce5f3c5ee6",
   "watcher_tag": "@0.9.5",
   "yaml_rev": "@563a5ffd4a800a2897b8f4dd6b19f2a370df2f2b",
   "zlib_rev": "@c3d0a6190f2f8c924a05ab6cc97b8f975bddd33f",
@@ -88,10 +91,14 @@
       "https://github.com/dart-lang/barback.git" + Var("barback_rev"),
   "src/dart/third_party/pkg/crypto":
       "https://github.com/dart-lang/crypto.git" + Var("crypto_rev"),
+  "src/dart/third_party/pkg/csslib":
+      "https://github.com/dart-lang/csslib.git" + Var("csslib_tag"),
   "src/dart/third_party/pkg/collection":
       "https://github.com/dart-lang/collection.git" + Var("collection_rev"),
   "src/dart/third_party/pkg/glob":
       "https://github.com/dart-lang/glob.git" + Var("glob_rev"),
+  "src/dart/third_party/pkg/html":
+      "https://github.com/dart-lang/html.git" + Var("html_tag"),
   "src/dart/third_party/pkg/json_rpc_2":
       "https://github.com/dart-lang/json_rpc_2.git" + Var("json_rpc_2_rev"),
   "src/dart/third_party/pkg/http":
@@ -103,6 +110,8 @@
       "https://github.com/dart-lang/http_parser.git" + Var("http_parser_rev"),
   "src/dart/third_party/pkg/http_throttle":
       "https://github.com/dart-lang/http_throttle.git" + Var("http_throttle_rev"),
+  "src/dart/third_party/pkg/logging":
+      "https://github.com/dart-lang/logging.git" + Var("logging_rev"),
   "src/dart/third_party/pkg/mime":
       "https://github.com/dart-lang/mime.git" + Var("mime_rev"),
   "src/dart/third_party/pkg/oauth2":
@@ -111,7 +120,7 @@
       "https://github.com/dart-lang/plugin.git" + Var("plugin_tag"),
   "src/dart/third_party/pkg/pool":
       "https://github.com/dart-lang/pool.git" + Var("pool_rev"),
-  "src/dart/third_party/pkg_tested/pub":
+  "src/dart/third_party/pkg/pub":
       "https://github.com/dart-lang/pub.git" + Var("pub_rev"),
   "src/dart/third_party/pkg/pub_semver":
       "https://github.com/dart-lang/pub_semver.git" + Var("pub_semver_tag"),
@@ -120,6 +129,8 @@
   "src/dart/third_party/pkg/shelf_web_socket":
       "https://github.com/dart-lang/shelf_web_socket.git" +
       Var("shelf_web_socket_rev"),
+  "src/dart/third_party/pkg/utf":
+      "https://github.com/dart-lang/utf.git" + Var("utf_rev"),
   "src/dart/third_party/pkg/watcher":
       "https://github.com/dart-lang/watcher.git" + Var("watcher_tag"),
   "src/dart/third_party/pkg/yaml":
diff --git a/tools/dom/src/Validators.dart b/tools/dom/src/Validators.dart
index 5724770..809f8e5 100644
--- a/tools/dom/src/Validators.dart
+++ b/tools/dom/src/Validators.dart
@@ -68,9 +68,27 @@
    * will mark the entire tree as unsafe.
    */
   void sanitizeTree(Node node);
+
+  /**
+   * A sanitizer for trees that we trust. It does no validation and allows
+   * any elements. It is also more efficient, since it can pass the text
+   * directly through to the underlying APIs without creating a document 
+   * fragment to be sanitized.
+   */
+  static const trusted = const _TrustedHtmlTreeSanitizer();
 }
 
 /**
+ * A sanitizer for trees that we trust. It does no validation and allows
+ * any elements.
+ */
+class _TrustedHtmlTreeSanitizer implements NodeTreeSanitizer {
+  const _TrustedHtmlTreeSanitizer();
+
+  sanitizeTree(Node node) {}
+}
+  
+/**
  * Defines the policy for what types of uris are allowed for particular
  * attribute values.
  *
diff --git a/tools/dom/templates/html/impl/impl_Element.darttemplate b/tools/dom/templates/html/impl/impl_Element.darttemplate
index f5b165b..fcf3c0c 100644
--- a/tools/dom/templates/html/impl/impl_Element.darttemplate
+++ b/tools/dom/templates/html/impl/impl_Element.darttemplate
@@ -1014,8 +1014,12 @@
    */
   void insertAdjacentHtml(String where, String html, {NodeValidator validator,
       NodeTreeSanitizer treeSanitizer}) {
-      _insertAdjacentNode(where, new DocumentFragment.html(html,
-          validator: validator, treeSanitizer: treeSanitizer));
+      if (treeSanitizer is _TrustedHtmlTreeSanitizer) {
+        _insertAdjacentHtml(where, html);
+      } else {
+        _insertAdjacentNode(where, new DocumentFragment.html(html,
+            validator: validator, treeSanitizer: treeSanitizer));
+      }
   }
 
 $if DART2JS
@@ -1374,8 +1378,12 @@
   void setInnerHtml(String html,
     {NodeValidator validator, NodeTreeSanitizer treeSanitizer}) {
     text = null;
-    append(createFragment(
-        html, validator: validator, treeSanitizer: treeSanitizer));
+    if (treeSanitizer is _TrustedHtmlTreeSanitizer) {
+      _innerHtml = html;
+    } else {
+      append(createFragment(
+          html, validator: validator, treeSanitizer: treeSanitizer));
+    }
   }
   String get innerHtml => _innerHtml;
 
diff --git a/tools/gyp/configurations_make.gypi b/tools/gyp/configurations_make.gypi
index 15eee37..d8f7965 100644
--- a/tools/gyp/configurations_make.gypi
+++ b/tools/gyp/configurations_make.gypi
@@ -171,10 +171,14 @@
         'target_conditions': [
           ['_toolset=="target"', {
             'cflags': [
+              '-EL',
               '-march=mips32',
               '-mhard-float',
               '-fno-strict-overflow',
             ],
+            'ldflags': [
+              '-EL',
+            ],
           }],
           ['_toolset=="host"',{
             'cflags': [ '-O3', '-m32', '-msse2' ],
diff --git a/tools/promote.py b/tools/promote.py
index ea420b4..81ab402 100644
--- a/tools/promote.py
+++ b/tools/promote.py
@@ -61,12 +61,6 @@
     if options.revision is None:
       die('You must specify a --revision to specify which revision to promote')
 
-    # Make sure revision is a valid integer
-    try:
-      _ = int(options.revision)
-    except:
-      die('You must supply a valid integer argument to --revision to promote')
-
     # Make sure options.channel is a valid
     if not options.channel:
       die('Specify --channel=be/dev/stable')
diff --git a/tools/run_pub.py b/tools/run_pub.py
index 37b6772..f54a411 100755
--- a/tools/run_pub.py
+++ b/tools/run_pub.py
@@ -12,7 +12,7 @@
 
 SCRIPT_DIR = os.path.dirname(sys.argv[0])
 DART_ROOT = os.path.realpath(os.path.join(SCRIPT_DIR, '..'))
-PUB_PATH = os.path.join(DART_ROOT, 'third_party/pkg_tested/pub/bin/pub.dart')
+PUB_PATH = os.path.join(DART_ROOT, 'third_party/pkg/pub/bin/pub.dart')
 CANARY_PATH = os.path.join(DART_ROOT, 'tools', 'canary.dart')
 
 usage = """run_pub.py --package-root=<package root>"""
diff --git a/tools/testing/dart/test_suite.dart b/tools/testing/dart/test_suite.dart
index e6c6778..3c3116a 100644
--- a/tools/testing/dart/test_suite.dart
+++ b/tools/testing/dart/test_suite.dart
@@ -2199,7 +2199,7 @@
     }
     String compiler = configuration["compiler"];
     if (compiler == "dart2js") {
-      args = [];
+      args = ['--generate-code-with-compile-time-errors', '--test-mode'];
       if (configuration["checked"]) {
         args.add('--enable-checked-mode');
       }
diff --git a/tools/utils.py b/tools/utils.py
index ec6312e..cc37f6a 100644
--- a/tools/utils.py
+++ b/tools/utils.py
@@ -294,7 +294,7 @@
     return None
 
   if version.channel == 'be':
-    postfix = '-edge' if ignore_svn_revision else '-edge.%s' % GetSVNRevision()
+    postfix = '-edge' if ignore_svn_revision else '-edge.%s' % GetGitRevision()
   elif version.channel == 'dev':
     postfix = '-dev.%s.%s' % (version.prerelease, version.prerelease_patch)
   else:
@@ -303,24 +303,9 @@
 
   return '%s.%s.%s%s' % (version.major, version.minor, version.patch, postfix)
 
-def GetEclipseVersionQualifier():
-  def pad(number, num_digits):
-    number_str = str(number)
-    return '0' * max(0, num_digits - len(number_str)) + number_str
-
-  version = ReadVersionFile()
-  if version.channel == 'be':
-    return 'edge_%s' % pad(GetSVNRevision(), 6)
-  elif version.channel == 'dev':
-    return 'dev_%s_%s' % (pad(version.prerelease, 2),
-                          pad(version.prerelease_patch, 2))
-  else:
-    return 'release'
-
 def GetVersion():
   return GetSemanticSDKVersion()
 
-
 # The editor used to produce the VERSION file put on gcs. We now produce this
 # in the bots archiving the sdk.
 # The content looks like this:
@@ -375,18 +360,6 @@
     print "Warning: VERSION file (%s) has wrong format" % version_file
     return None
 
-def GetSVNRevision():
-  # When building from tarball use tools/SVN_REVISION
-  svn_revision_file = os.path.join(DART_DIR, 'tools', 'SVN_REVISION')
-  try:
-    with open(svn_revision_file) as fd:
-      return fd.read()
-  except:
-    pass
-
-  # TODO(ricow): Remove all calls to GetSVNRevision.
-  # For now, simply forward call to GetArchiveVersion
-  return GetArchiveVersion();
 
 # Our schema for releases and archiving is based on an increasing
 # sequence of numbers. In the svn world this was simply the revision of a
@@ -407,6 +380,14 @@
 
 
 def GetGitRevision():
+  # When building from tarball use tools/GIT_REVISION
+  git_revision_file = os.path.join(DART_DIR, 'tools', 'GIT_REVISION')
+  try:
+    with open(git_revision_file) as fd:
+      return fd.read()
+  except:
+    pass
+
   p = subprocess.Popen(['git', 'log', '-n', '1', '--pretty=format:%H'],
                        stdout = subprocess.PIPE,
                        stderr = subprocess.STDOUT, shell=IsWindows(),
@@ -418,7 +399,7 @@
     return None
   return output
 
-# To eliminate clashing with older archived builds on bleding edge we add
+# To eliminate clashing with older archived builds on bleeding edge we add
 # a base number bigger the largest svn revision (this also gives us an easy
 # way of seeing if an archive comes from git based or svn based commits).
 GIT_NUMBER_BASE = 100000
diff --git a/utils/pub/pub.gyp b/utils/pub/pub.gyp
index 252a255..81dcec7 100644
--- a/utils/pub/pub.gyp
+++ b/utils/pub/pub.gyp
@@ -30,7 +30,7 @@
             '<(PRODUCT_DIR)/<(EXECUTABLE_PREFIX)dart<(EXECUTABLE_SUFFIX)',
             '--package-root=<(PRODUCT_DIR)/packages/',
             '--snapshot=<(SHARED_INTERMEDIATE_DIR)/pub.dart.snapshot',
-            '../../third_party/pkg_tested/pub/bin/pub.dart',
+            '../../third_party/pkg/pub/bin/pub.dart',
           ]
         },
       ],